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 <malloc.h>
11 #include <asm/clk.h>
12
13 struct sandbox_clk_priv {
14 bool probed;
15 ulong rate[SANDBOX_CLK_ID_COUNT];
16 bool enabled[SANDBOX_CLK_ID_COUNT];
17 bool requested[SANDBOX_CLK_ID_COUNT];
18 };
19
sandbox_clk_get_rate(struct clk * clk)20 static ulong sandbox_clk_get_rate(struct clk *clk)
21 {
22 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
23
24 if (!priv->probed)
25 return -ENODEV;
26
27 if (clk->id >= SANDBOX_CLK_ID_COUNT)
28 return -EINVAL;
29
30 return priv->rate[clk->id];
31 }
32
sandbox_clk_round_rate(struct clk * clk,ulong rate)33 static ulong sandbox_clk_round_rate(struct clk *clk, ulong rate)
34 {
35 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
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 return rate;
47 }
48
sandbox_clk_set_rate(struct clk * clk,ulong rate)49 static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
50 {
51 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
52 ulong old_rate;
53
54 if (!priv->probed)
55 return -ENODEV;
56
57 if (clk->id >= SANDBOX_CLK_ID_COUNT)
58 return -EINVAL;
59
60 if (!rate)
61 return -EINVAL;
62
63 old_rate = priv->rate[clk->id];
64 priv->rate[clk->id] = rate;
65
66 return old_rate;
67 }
68
sandbox_clk_enable(struct clk * clk)69 static int sandbox_clk_enable(struct clk *clk)
70 {
71 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
72
73 if (!priv->probed)
74 return -ENODEV;
75
76 if (clk->id >= SANDBOX_CLK_ID_COUNT)
77 return -EINVAL;
78
79 priv->enabled[clk->id] = true;
80
81 return 0;
82 }
83
sandbox_clk_disable(struct clk * clk)84 static int sandbox_clk_disable(struct clk *clk)
85 {
86 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
87
88 if (!priv->probed)
89 return -ENODEV;
90
91 if (clk->id >= SANDBOX_CLK_ID_COUNT)
92 return -EINVAL;
93
94 priv->enabled[clk->id] = false;
95
96 return 0;
97 }
98
sandbox_clk_request(struct clk * clk)99 static int sandbox_clk_request(struct clk *clk)
100 {
101 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
102
103 if (clk->id >= SANDBOX_CLK_ID_COUNT)
104 return -EINVAL;
105
106 priv->requested[clk->id] = true;
107 return 0;
108 }
109
sandbox_clk_free(struct clk * clk)110 static int sandbox_clk_free(struct clk *clk)
111 {
112 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
113
114 if (clk->id >= SANDBOX_CLK_ID_COUNT)
115 return -EINVAL;
116
117 priv->requested[clk->id] = false;
118 return 0;
119 }
120
121 static struct clk_ops sandbox_clk_ops = {
122 .round_rate = sandbox_clk_round_rate,
123 .get_rate = sandbox_clk_get_rate,
124 .set_rate = sandbox_clk_set_rate,
125 .enable = sandbox_clk_enable,
126 .disable = sandbox_clk_disable,
127 .request = sandbox_clk_request,
128 .rfree = sandbox_clk_free,
129 };
130
sandbox_clk_probe(struct udevice * dev)131 static int sandbox_clk_probe(struct udevice *dev)
132 {
133 struct sandbox_clk_priv *priv = dev_get_priv(dev);
134
135 priv->probed = true;
136 return 0;
137 }
138
139 static const struct udevice_id sandbox_clk_ids[] = {
140 { .compatible = "sandbox,clk" },
141 { }
142 };
143
144 U_BOOT_DRIVER(sandbox_clk) = {
145 .name = "sandbox_clk",
146 .id = UCLASS_CLK,
147 .of_match = sandbox_clk_ids,
148 .ops = &sandbox_clk_ops,
149 .probe = sandbox_clk_probe,
150 .priv_auto = sizeof(struct sandbox_clk_priv),
151 };
152
sandbox_clk_query_rate(struct udevice * dev,int id)153 ulong sandbox_clk_query_rate(struct udevice *dev, int id)
154 {
155 struct sandbox_clk_priv *priv = dev_get_priv(dev);
156
157 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
158 return -EINVAL;
159
160 return priv->rate[id];
161 }
162
sandbox_clk_query_enable(struct udevice * dev,int id)163 int sandbox_clk_query_enable(struct udevice *dev, int id)
164 {
165 struct sandbox_clk_priv *priv = dev_get_priv(dev);
166
167 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
168 return -EINVAL;
169
170 return priv->enabled[id];
171 }
172
sandbox_clk_query_requested(struct udevice * dev,int id)173 int sandbox_clk_query_requested(struct udevice *dev, int id)
174 {
175 struct sandbox_clk_priv *priv = dev_get_priv(dev);
176
177 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
178 return -EINVAL;
179 return priv->requested[id];
180 }
181