blob: 636914db8ca20ed1b42ea82222aa1221ef8952ab [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Simon Glass6a1c7ce2015-07-06 12:54:24 -06002/*
3 * (C) Copyright 2015 Google, Inc
Simon Glass6a1c7ce2015-07-06 12:54:24 -06004 */
5
6#include <common.h>
Stephen Warren135aa952016-06-17 09:44:00 -06007#include <clk-uclass.h>
Simon Glass6a1c7ce2015-07-06 12:54:24 -06008#include <dm.h>
9#include <errno.h>
Simon Glass336d4612020-02-03 07:36:16 -070010#include <malloc.h>
Stephen Warren135aa952016-06-17 09:44:00 -060011#include <asm/clk.h>
Simon Glass88139862021-03-15 17:25:24 +130012#include <linux/clk-provider.h>
Simon Glass6a1c7ce2015-07-06 12:54:24 -060013
Stephen Warren135aa952016-06-17 09:44:00 -060014static ulong sandbox_clk_get_rate(struct clk *clk)
Simon Glass6a1c7ce2015-07-06 12:54:24 -060015{
Stephen Warren135aa952016-06-17 09:44:00 -060016 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
Simon Glass6a1c7ce2015-07-06 12:54:24 -060017
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020018 if (!priv->probed)
19 return -ENODEV;
20
Stephen Warrendf8b0a02016-06-21 13:32:07 -060021 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060022 return -EINVAL;
23
24 return priv->rate[clk->id];
Simon Glass6a1c7ce2015-07-06 12:54:24 -060025}
26
Dario Binacchi2983ad52020-12-30 00:06:31 +010027static 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
Stephen Warren135aa952016-06-17 09:44:00 -060043static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
Simon Glass6a1c7ce2015-07-06 12:54:24 -060044{
Stephen Warren135aa952016-06-17 09:44:00 -060045 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
46 ulong old_rate;
47
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020048 if (!priv->probed)
49 return -ENODEV;
50
Stephen Warrendf8b0a02016-06-21 13:32:07 -060051 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060052 return -EINVAL;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060053
54 if (!rate)
55 return -EINVAL;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060056
Stephen Warren135aa952016-06-17 09:44:00 -060057 old_rate = priv->rate[clk->id];
58 priv->rate[clk->id] = rate;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060059
60 return old_rate;
61}
62
Stephen Warren135aa952016-06-17 09:44:00 -060063static int sandbox_clk_enable(struct clk *clk)
Simon Glass6a1c7ce2015-07-06 12:54:24 -060064{
Stephen Warren135aa952016-06-17 09:44:00 -060065 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
Simon Glass6a1c7ce2015-07-06 12:54:24 -060066
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020067 if (!priv->probed)
68 return -ENODEV;
69
Stephen Warrendf8b0a02016-06-21 13:32:07 -060070 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060071 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
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020082 if (!priv->probed)
83 return -ENODEV;
84
Stephen Warrendf8b0a02016-06-21 13:32:07 -060085 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060086 return -EINVAL;
87
88 priv->enabled[clk->id] = false;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060089
90 return 0;
91}
92
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +020093static 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
Sean Anderson276d4462022-01-15 17:24:58 -0500104static void sandbox_clk_free(struct clk *clk)
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +0200105{
106 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
107
108 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Sean Anderson276d4462022-01-15 17:24:58 -0500109 return;
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +0200110
111 priv->requested[clk->id] = false;
Sean Anderson276d4462022-01-15 17:24:58 -0500112 return;
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +0200113}
114
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600115static struct clk_ops sandbox_clk_ops = {
Dario Binacchi2983ad52020-12-30 00:06:31 +0100116 .round_rate = sandbox_clk_round_rate,
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600117 .get_rate = sandbox_clk_get_rate,
118 .set_rate = sandbox_clk_set_rate,
Stephen Warren135aa952016-06-17 09:44:00 -0600119 .enable = sandbox_clk_enable,
120 .disable = sandbox_clk_disable,
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +0200121 .request = sandbox_clk_request,
Simon Glassfb8c0d52020-02-03 07:35:54 -0700122 .rfree = sandbox_clk_free,
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600123};
124
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +0200125static 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
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600133static const struct udevice_id sandbox_clk_ids[] = {
134 { .compatible = "sandbox,clk" },
135 { }
136};
137
Simon Glass88280522020-10-03 11:31:32 -0600138U_BOOT_DRIVER(sandbox_clk) = {
139 .name = "sandbox_clk",
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600140 .id = UCLASS_CLK,
141 .of_match = sandbox_clk_ids,
142 .ops = &sandbox_clk_ops,
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +0200143 .probe = sandbox_clk_probe,
Simon Glass41575d82020-12-03 16:55:17 -0700144 .priv_auto = sizeof(struct sandbox_clk_priv),
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600145};
Stephen Warren135aa952016-06-17 09:44:00 -0600146
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}
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +0200166
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}
Simon Glass88139862021-03-15 17:25:24 +1300175
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 { /* sentinel */ }
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};