blob: 8dd77f18d90170f30d1c6a6ff49ce2fdf561c51a [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
Stephen Warren135aa952016-06-17 09:44:00 -06006#include <clk-uclass.h>
Simon Glass6a1c7ce2015-07-06 12:54:24 -06007#include <dm.h>
8#include <errno.h>
Simon Glass336d4612020-02-03 07:36:16 -07009#include <malloc.h>
Stephen Warren135aa952016-06-17 09:44:00 -060010#include <asm/clk.h>
Simon Glass88139862021-03-15 17:25:24 +130011#include <linux/clk-provider.h>
Simon Glass6a1c7ce2015-07-06 12:54:24 -060012
Stephen Warren135aa952016-06-17 09:44:00 -060013static ulong sandbox_clk_get_rate(struct clk *clk)
Simon Glass6a1c7ce2015-07-06 12:54:24 -060014{
Stephen Warren135aa952016-06-17 09:44:00 -060015 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
Simon Glass6a1c7ce2015-07-06 12:54:24 -060016
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020017 if (!priv->probed)
18 return -ENODEV;
19
Stephen Warrendf8b0a02016-06-21 13:32:07 -060020 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060021 return -EINVAL;
22
23 return priv->rate[clk->id];
Simon Glass6a1c7ce2015-07-06 12:54:24 -060024}
25
Dario Binacchi2983ad52020-12-30 00:06:31 +010026static ulong sandbox_clk_round_rate(struct clk *clk, ulong rate)
27{
28 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
29
30 if (!priv->probed)
31 return -ENODEV;
32
33 if (clk->id >= SANDBOX_CLK_ID_COUNT)
34 return -EINVAL;
35
36 if (!rate)
37 return -EINVAL;
38
39 return rate;
40}
41
Stephen Warren135aa952016-06-17 09:44:00 -060042static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
Simon Glass6a1c7ce2015-07-06 12:54:24 -060043{
Stephen Warren135aa952016-06-17 09:44:00 -060044 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
45 ulong old_rate;
46
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020047 if (!priv->probed)
48 return -ENODEV;
49
Stephen Warrendf8b0a02016-06-21 13:32:07 -060050 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060051 return -EINVAL;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060052
53 if (!rate)
54 return -EINVAL;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060055
Stephen Warren135aa952016-06-17 09:44:00 -060056 old_rate = priv->rate[clk->id];
57 priv->rate[clk->id] = rate;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060058
59 return old_rate;
60}
61
Stephen Warren135aa952016-06-17 09:44:00 -060062static int sandbox_clk_enable(struct clk *clk)
Simon Glass6a1c7ce2015-07-06 12:54:24 -060063{
Stephen Warren135aa952016-06-17 09:44:00 -060064 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
Simon Glass6a1c7ce2015-07-06 12:54:24 -060065
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020066 if (!priv->probed)
67 return -ENODEV;
68
Stephen Warrendf8b0a02016-06-21 13:32:07 -060069 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060070 return -EINVAL;
71
72 priv->enabled[clk->id] = true;
73
74 return 0;
75}
76
77static int sandbox_clk_disable(struct clk *clk)
78{
79 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
80
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020081 if (!priv->probed)
82 return -ENODEV;
83
Stephen Warrendf8b0a02016-06-21 13:32:07 -060084 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060085 return -EINVAL;
86
87 priv->enabled[clk->id] = false;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060088
89 return 0;
90}
91
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +020092static int sandbox_clk_request(struct clk *clk)
93{
94 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
95
96 if (clk->id >= SANDBOX_CLK_ID_COUNT)
97 return -EINVAL;
98
99 priv->requested[clk->id] = true;
100 return 0;
101}
102
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600103static struct clk_ops sandbox_clk_ops = {
Dario Binacchi2983ad52020-12-30 00:06:31 +0100104 .round_rate = sandbox_clk_round_rate,
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600105 .get_rate = sandbox_clk_get_rate,
106 .set_rate = sandbox_clk_set_rate,
Stephen Warren135aa952016-06-17 09:44:00 -0600107 .enable = sandbox_clk_enable,
108 .disable = sandbox_clk_disable,
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +0200109 .request = sandbox_clk_request,
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600110};
111
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +0200112static int sandbox_clk_probe(struct udevice *dev)
113{
114 struct sandbox_clk_priv *priv = dev_get_priv(dev);
115
116 priv->probed = true;
117 return 0;
118}
119
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600120static const struct udevice_id sandbox_clk_ids[] = {
121 { .compatible = "sandbox,clk" },
122 { }
123};
124
Simon Glass88280522020-10-03 11:31:32 -0600125U_BOOT_DRIVER(sandbox_clk) = {
126 .name = "sandbox_clk",
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600127 .id = UCLASS_CLK,
128 .of_match = sandbox_clk_ids,
129 .ops = &sandbox_clk_ops,
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +0200130 .probe = sandbox_clk_probe,
Simon Glass41575d82020-12-03 16:55:17 -0700131 .priv_auto = sizeof(struct sandbox_clk_priv),
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600132};
Stephen Warren135aa952016-06-17 09:44:00 -0600133
134ulong sandbox_clk_query_rate(struct udevice *dev, int id)
135{
136 struct sandbox_clk_priv *priv = dev_get_priv(dev);
137
138 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
139 return -EINVAL;
140
141 return priv->rate[id];
142}
143
144int sandbox_clk_query_enable(struct udevice *dev, int id)
145{
146 struct sandbox_clk_priv *priv = dev_get_priv(dev);
147
148 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
149 return -EINVAL;
150
151 return priv->enabled[id];
152}
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +0200153
154int sandbox_clk_query_requested(struct udevice *dev, int id)
155{
156 struct sandbox_clk_priv *priv = dev_get_priv(dev);
157
158 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
159 return -EINVAL;
160 return priv->requested[id];
161}
Simon Glass88139862021-03-15 17:25:24 +1300162
163int clk_fixed_rate_of_to_plat(struct udevice *dev)
164{
165 struct clk_fixed_rate *cplat;
166
167#if CONFIG_IS_ENABLED(OF_PLATDATA)
168 struct sandbox_clk_fixed_rate_plat *plat = dev_get_plat(dev);
169
170 cplat = &plat->fixed;
171 cplat->fixed_rate = plat->dtplat.clock_frequency;
172#else
173 cplat = to_clk_fixed_rate(dev);
174#endif
175 clk_fixed_rate_ofdata_to_plat_(dev, cplat);
176
177 return 0;
178}
179
180static const struct udevice_id sandbox_clk_fixed_rate_match[] = {
181 { .compatible = "sandbox,fixed-clock" },
182 { /* sentinel */ }
183};
184
185U_BOOT_DRIVER(sandbox_fixed_clock) = {
186 .name = "sandbox_fixed_clock",
187 .id = UCLASS_CLK,
188 .of_match = sandbox_clk_fixed_rate_match,
189 .of_to_plat = clk_fixed_rate_of_to_plat,
190 .plat_auto = sizeof(struct sandbox_clk_fixed_rate_plat),
191 .ops = &clk_fixed_rate_ops,
192 .flags = DM_FLAG_PRE_RELOC,
193};