1
2
3
4
5
6#include <common.h>
7#include <clk-uclass.h>
8#include <dm.h>
9#include <errno.h>
10#include <malloc.h>
11#include <asm/clk.h>
12#include <linux/clk-provider.h>
13
14static ulong sandbox_clk_get_rate(struct clk *clk)
15{
16 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
17
18 if (!priv->probed)
19 return -ENODEV;
20
21 if (clk->id >= SANDBOX_CLK_ID_COUNT)
22 return -EINVAL;
23
24 return priv->rate[clk->id];
25}
26
27static ulong sandbox_clk_round_rate(struct clk *clk, ulong rate)
28{
29 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
30
31 if (!priv->probed)
32 return -ENODEV;
33
34 if (clk->id >= SANDBOX_CLK_ID_COUNT)
35 return -EINVAL;
36
37 if (!rate)
38 return -EINVAL;
39
40 return rate;
41}
42
43static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
44{
45 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
46 ulong old_rate;
47
48 if (!priv->probed)
49 return -ENODEV;
50
51 if (clk->id >= SANDBOX_CLK_ID_COUNT)
52 return -EINVAL;
53
54 if (!rate)
55 return -EINVAL;
56
57 old_rate = priv->rate[clk->id];
58 priv->rate[clk->id] = rate;
59
60 return old_rate;
61}
62
63static int sandbox_clk_enable(struct clk *clk)
64{
65 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
66
67 if (!priv->probed)
68 return -ENODEV;
69
70 if (clk->id >= SANDBOX_CLK_ID_COUNT)
71 return -EINVAL;
72
73 priv->enabled[clk->id] = true;
74
75 return 0;
76}
77
78static int sandbox_clk_disable(struct clk *clk)
79{
80 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
81
82 if (!priv->probed)
83 return -ENODEV;
84
85 if (clk->id >= SANDBOX_CLK_ID_COUNT)
86 return -EINVAL;
87
88 priv->enabled[clk->id] = false;
89
90 return 0;
91}
92
93static int sandbox_clk_request(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] = true;
101 return 0;
102}
103
104static void sandbox_clk_free(struct clk *clk)
105{
106 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
107
108 if (clk->id >= SANDBOX_CLK_ID_COUNT)
109 return;
110
111 priv->requested[clk->id] = false;
112 return;
113}
114
115static struct clk_ops sandbox_clk_ops = {
116 .round_rate = sandbox_clk_round_rate,
117 .get_rate = sandbox_clk_get_rate,
118 .set_rate = sandbox_clk_set_rate,
119 .enable = sandbox_clk_enable,
120 .disable = sandbox_clk_disable,
121 .request = sandbox_clk_request,
122 .rfree = sandbox_clk_free,
123};
124
125static int sandbox_clk_probe(struct udevice *dev)
126{
127 struct sandbox_clk_priv *priv = dev_get_priv(dev);
128
129 priv->probed = true;
130 return 0;
131}
132
133static const struct udevice_id sandbox_clk_ids[] = {
134 { .compatible = "sandbox,clk" },
135 { }
136};
137
138U_BOOT_DRIVER(sandbox_clk) = {
139 .name = "sandbox_clk",
140 .id = UCLASS_CLK,
141 .of_match = sandbox_clk_ids,
142 .ops = &sandbox_clk_ops,
143 .probe = sandbox_clk_probe,
144 .priv_auto = sizeof(struct sandbox_clk_priv),
145};
146
147ulong sandbox_clk_query_rate(struct udevice *dev, int id)
148{
149 struct sandbox_clk_priv *priv = dev_get_priv(dev);
150
151 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
152 return -EINVAL;
153
154 return priv->rate[id];
155}
156
157int sandbox_clk_query_enable(struct udevice *dev, int id)
158{
159 struct sandbox_clk_priv *priv = dev_get_priv(dev);
160
161 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
162 return -EINVAL;
163
164 return priv->enabled[id];
165}
166
167int sandbox_clk_query_requested(struct udevice *dev, int id)
168{
169 struct sandbox_clk_priv *priv = dev_get_priv(dev);
170
171 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
172 return -EINVAL;
173 return priv->requested[id];
174}
175
176int clk_fixed_rate_of_to_plat(struct udevice *dev)
177{
178 struct clk_fixed_rate *cplat;
179
180#if CONFIG_IS_ENABLED(OF_PLATDATA)
181 struct sandbox_clk_fixed_rate_plat *plat = dev_get_plat(dev);
182
183 cplat = &plat->fixed;
184 cplat->fixed_rate = plat->dtplat.clock_frequency;
185#else
186 cplat = to_clk_fixed_rate(dev);
187#endif
188 clk_fixed_rate_ofdata_to_plat_(dev, cplat);
189
190 return 0;
191}
192
193static const struct udevice_id sandbox_clk_fixed_rate_match[] = {
194 { .compatible = "sandbox,fixed-clock" },
195 { }
196};
197
198U_BOOT_DRIVER(sandbox_fixed_clock) = {
199 .name = "sandbox_fixed_clock",
200 .id = UCLASS_CLK,
201 .of_match = sandbox_clk_fixed_rate_match,
202 .of_to_plat = clk_fixed_rate_of_to_plat,
203 .plat_auto = sizeof(struct sandbox_clk_fixed_rate_plat),
204 .ops = &clk_fixed_rate_ops,
205 .flags = DM_FLAG_PRE_RELOC,
206};
207