blob: 73d943f9e092313576e3a45018358c5564a8519e [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Simon Glass8cc4d822015-07-06 12:54:24 -06002/*
3 * (C) Copyright 2015 Google, Inc
Simon Glass8cc4d822015-07-06 12:54:24 -06004 */
5
6#include <common.h>
Stephen Warrena9622432016-06-17 09:44:00 -06007#include <clk-uclass.h>
Simon Glass8cc4d822015-07-06 12:54:24 -06008#include <dm.h>
9#include <errno.h>
Simon Glass9bc15642020-02-03 07:36:16 -070010#include <malloc.h>
Stephen Warrena9622432016-06-17 09:44:00 -060011#include <asm/clk.h>
Simon Glass9bb88fb2021-03-15 17:25:24 +130012#include <linux/clk-provider.h>
Simon Glass8cc4d822015-07-06 12:54:24 -060013
Stephen Warrena9622432016-06-17 09:44:00 -060014static ulong sandbox_clk_get_rate(struct clk *clk)
Simon Glass8cc4d822015-07-06 12:54:24 -060015{
Stephen Warrena9622432016-06-17 09:44:00 -060016 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
17
Jean-Jacques Hiblotc1e9c942019-10-22 14:00:07 +020018 if (!priv->probed)
19 return -ENODEV;
20
Stephen Warrendaec47b2016-06-21 13:32:07 -060021 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warrena9622432016-06-17 09:44:00 -060022 return -EINVAL;
Simon Glass8cc4d822015-07-06 12:54:24 -060023
Stephen Warrena9622432016-06-17 09:44:00 -060024 return priv->rate[clk->id];
Simon Glass8cc4d822015-07-06 12:54:24 -060025}
26
Dario Binacchib7f85892020-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 Warrena9622432016-06-17 09:44:00 -060043static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
Simon Glass8cc4d822015-07-06 12:54:24 -060044{
Stephen Warrena9622432016-06-17 09:44:00 -060045 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
46 ulong old_rate;
47
Jean-Jacques Hiblotc1e9c942019-10-22 14:00:07 +020048 if (!priv->probed)
49 return -ENODEV;
50
Stephen Warrendaec47b2016-06-21 13:32:07 -060051 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warrena9622432016-06-17 09:44:00 -060052 return -EINVAL;
Simon Glass8cc4d822015-07-06 12:54:24 -060053
54 if (!rate)
55 return -EINVAL;
Simon Glass8cc4d822015-07-06 12:54:24 -060056
Stephen Warrena9622432016-06-17 09:44:00 -060057 old_rate = priv->rate[clk->id];
58 priv->rate[clk->id] = rate;
Simon Glass8cc4d822015-07-06 12:54:24 -060059
Stephen Warrena9622432016-06-17 09:44:00 -060060 return old_rate;
Simon Glass8cc4d822015-07-06 12:54:24 -060061}
62
Stephen Warrena9622432016-06-17 09:44:00 -060063static int sandbox_clk_enable(struct clk *clk)
Simon Glass8cc4d822015-07-06 12:54:24 -060064{
Stephen Warrena9622432016-06-17 09:44:00 -060065 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
Simon Glass8cc4d822015-07-06 12:54:24 -060066
Jean-Jacques Hiblotc1e9c942019-10-22 14:00:07 +020067 if (!priv->probed)
68 return -ENODEV;
69
Stephen Warrendaec47b2016-06-21 13:32:07 -060070 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Simon Glass8cc4d822015-07-06 12:54:24 -060071 return -EINVAL;
Simon Glass8cc4d822015-07-06 12:54:24 -060072
Stephen Warrena9622432016-06-17 09:44:00 -060073 priv->enabled[clk->id] = true;
74
75 return 0;
Simon Glass8cc4d822015-07-06 12:54:24 -060076}
77
Stephen Warrena9622432016-06-17 09:44:00 -060078static int sandbox_clk_disable(struct clk *clk)
Simon Glass8cc4d822015-07-06 12:54:24 -060079{
Stephen Warrena9622432016-06-17 09:44:00 -060080 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
81
Jean-Jacques Hiblotc1e9c942019-10-22 14:00:07 +020082 if (!priv->probed)
83 return -ENODEV;
84
Stephen Warrendaec47b2016-06-21 13:32:07 -060085 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warrena9622432016-06-17 09:44:00 -060086 return -EINVAL;
Simon Glass8cc4d822015-07-06 12:54:24 -060087
Stephen Warrena9622432016-06-17 09:44:00 -060088 priv->enabled[clk->id] = false;
Simon Glass8cc4d822015-07-06 12:54:24 -060089
90 return 0;
91}
92
Jean-Jacques Hiblot98e84182019-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
Simon Glass8cc4d822015-07-06 12:54:24 -0600104static struct clk_ops sandbox_clk_ops = {
Dario Binacchib7f85892020-12-30 00:06:31 +0100105 .round_rate = sandbox_clk_round_rate,
Simon Glass8cc4d822015-07-06 12:54:24 -0600106 .get_rate = sandbox_clk_get_rate,
107 .set_rate = sandbox_clk_set_rate,
Stephen Warrena9622432016-06-17 09:44:00 -0600108 .enable = sandbox_clk_enable,
109 .disable = sandbox_clk_disable,
Jean-Jacques Hiblot98e84182019-10-22 14:00:05 +0200110 .request = sandbox_clk_request,
Simon Glass8cc4d822015-07-06 12:54:24 -0600111};
112
Jean-Jacques Hiblotc1e9c942019-10-22 14:00:07 +0200113static 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
Simon Glass8cc4d822015-07-06 12:54:24 -0600121static const struct udevice_id sandbox_clk_ids[] = {
122 { .compatible = "sandbox,clk" },
123 { }
124};
125
Simon Glass6b927b12020-10-03 11:31:32 -0600126U_BOOT_DRIVER(sandbox_clk) = {
127 .name = "sandbox_clk",
Simon Glass8cc4d822015-07-06 12:54:24 -0600128 .id = UCLASS_CLK,
129 .of_match = sandbox_clk_ids,
130 .ops = &sandbox_clk_ops,
Jean-Jacques Hiblotc1e9c942019-10-22 14:00:07 +0200131 .probe = sandbox_clk_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700132 .priv_auto = sizeof(struct sandbox_clk_priv),
Simon Glass8cc4d822015-07-06 12:54:24 -0600133};
Stephen Warrena9622432016-06-17 09:44:00 -0600134
135ulong 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
145int 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}
Jean-Jacques Hiblot98e84182019-10-22 14:00:05 +0200154
155int 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}
Simon Glass9bb88fb2021-03-15 17:25:24 +1300163
164int clk_fixed_rate_of_to_plat(struct udevice *dev)
165{
166 struct clk_fixed_rate *cplat;
167
168#if CONFIG_IS_ENABLED(OF_PLATDATA)
169 struct sandbox_clk_fixed_rate_plat *plat = dev_get_plat(dev);
170
171 cplat = &plat->fixed;
172 cplat->fixed_rate = plat->dtplat.clock_frequency;
173#else
174 cplat = to_clk_fixed_rate(dev);
175#endif
176 clk_fixed_rate_ofdata_to_plat_(dev, cplat);
177
178 return 0;
179}
180
181static const struct udevice_id sandbox_clk_fixed_rate_match[] = {
182 { .compatible = "sandbox,fixed-clock" },
183 { /* sentinel */ }
184};
185
186U_BOOT_DRIVER(sandbox_fixed_clock) = {
187 .name = "sandbox_fixed_clock",
188 .id = UCLASS_CLK,
189 .of_match = sandbox_clk_fixed_rate_match,
190 .of_to_plat = clk_fixed_rate_of_to_plat,
191 .plat_auto = sizeof(struct sandbox_clk_fixed_rate_plat),
192 .ops = &clk_fixed_rate_ops,
193 .flags = DM_FLAG_PRE_RELOC,
194};