1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * (C) Copyright 2015 Google, Inc
4 */
5
6 #include <common.h>
7 #include <clk-uclass.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <asm/clk.h>
11
12 struct sandbox_clk_priv {
13 bool probed;
14 ulong rate[SANDBOX_CLK_ID_COUNT];
15 bool enabled[SANDBOX_CLK_ID_COUNT];
16 bool requested[SANDBOX_CLK_ID_COUNT];
17 };
18
sandbox_clk_get_rate(struct clk * clk)19 static ulong sandbox_clk_get_rate(struct clk *clk)
20 {
21 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
22
23 if (!priv->probed)
24 return -ENODEV;
25
26 if (clk->id >= SANDBOX_CLK_ID_COUNT)
27 return -EINVAL;
28
29 return priv->rate[clk->id];
30 }
31
sandbox_clk_set_rate(struct clk * clk,ulong rate)32 static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
33 {
34 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
35 ulong old_rate;
36
37 if (!priv->probed)
38 return -ENODEV;
39
40 if (clk->id >= SANDBOX_CLK_ID_COUNT)
41 return -EINVAL;
42
43 if (!rate)
44 return -EINVAL;
45
46 old_rate = priv->rate[clk->id];
47 priv->rate[clk->id] = rate;
48
49 return old_rate;
50 }
51
sandbox_clk_enable(struct clk * clk)52 static int sandbox_clk_enable(struct clk *clk)
53 {
54 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
55
56 if (!priv->probed)
57 return -ENODEV;
58
59 if (clk->id >= SANDBOX_CLK_ID_COUNT)
60 return -EINVAL;
61
62 priv->enabled[clk->id] = true;
63
64 return 0;
65 }
66
sandbox_clk_disable(struct clk * clk)67 static int sandbox_clk_disable(struct clk *clk)
68 {
69 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
70
71 if (!priv->probed)
72 return -ENODEV;
73
74 if (clk->id >= SANDBOX_CLK_ID_COUNT)
75 return -EINVAL;
76
77 priv->enabled[clk->id] = false;
78
79 return 0;
80 }
81
sandbox_clk_request(struct clk * clk)82 static int sandbox_clk_request(struct clk *clk)
83 {
84 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
85
86 if (clk->id >= SANDBOX_CLK_ID_COUNT)
87 return -EINVAL;
88
89 priv->requested[clk->id] = true;
90 return 0;
91 }
92
sandbox_clk_free(struct clk * clk)93 static int sandbox_clk_free(struct clk *clk)
94 {
95 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
96
97 if (clk->id >= SANDBOX_CLK_ID_COUNT)
98 return -EINVAL;
99
100 priv->requested[clk->id] = false;
101 return 0;
102 }
103
104 static struct clk_ops sandbox_clk_ops = {
105 .get_rate = sandbox_clk_get_rate,
106 .set_rate = sandbox_clk_set_rate,
107 .enable = sandbox_clk_enable,
108 .disable = sandbox_clk_disable,
109 .request = sandbox_clk_request,
110 .free = sandbox_clk_free,
111 };
112
sandbox_clk_probe(struct udevice * dev)113 static int sandbox_clk_probe(struct udevice *dev)
114 {
115 struct sandbox_clk_priv *priv = dev_get_priv(dev);
116
117 priv->probed = true;
118 return 0;
119 }
120
121 static const struct udevice_id sandbox_clk_ids[] = {
122 { .compatible = "sandbox,clk" },
123 { }
124 };
125
126 U_BOOT_DRIVER(clk_sandbox) = {
127 .name = "clk_sandbox",
128 .id = UCLASS_CLK,
129 .of_match = sandbox_clk_ids,
130 .ops = &sandbox_clk_ops,
131 .probe = sandbox_clk_probe,
132 .priv_auto_alloc_size = sizeof(struct sandbox_clk_priv),
133 };
134
sandbox_clk_query_rate(struct udevice * dev,int id)135 ulong sandbox_clk_query_rate(struct udevice *dev, int id)
136 {
137 struct sandbox_clk_priv *priv = dev_get_priv(dev);
138
139 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
140 return -EINVAL;
141
142 return priv->rate[id];
143 }
144
sandbox_clk_query_enable(struct udevice * dev,int id)145 int sandbox_clk_query_enable(struct udevice *dev, int id)
146 {
147 struct sandbox_clk_priv *priv = dev_get_priv(dev);
148
149 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
150 return -EINVAL;
151
152 return priv->enabled[id];
153 }
154
sandbox_clk_query_requested(struct udevice * dev,int id)155 int sandbox_clk_query_requested(struct udevice *dev, int id)
156 {
157 struct sandbox_clk_priv *priv = dev_get_priv(dev);
158
159 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
160 return -EINVAL;
161 return priv->requested[id];
162 }
163