blob: b28b67b44860020c287182d9afb50ceb37132993 [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 Glass6a1c7ce2015-07-06 12:54:24 -060012
13struct sandbox_clk_priv {
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020014 bool probed;
Stephen Warren135aa952016-06-17 09:44:00 -060015 ulong rate[SANDBOX_CLK_ID_COUNT];
16 bool enabled[SANDBOX_CLK_ID_COUNT];
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +020017 bool requested[SANDBOX_CLK_ID_COUNT];
Simon Glass6a1c7ce2015-07-06 12:54:24 -060018};
19
Stephen Warren135aa952016-06-17 09:44:00 -060020static ulong sandbox_clk_get_rate(struct clk *clk)
Simon Glass6a1c7ce2015-07-06 12:54:24 -060021{
Stephen Warren135aa952016-06-17 09:44:00 -060022 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
Simon Glass6a1c7ce2015-07-06 12:54:24 -060023
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020024 if (!priv->probed)
25 return -ENODEV;
26
Stephen Warrendf8b0a02016-06-21 13:32:07 -060027 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060028 return -EINVAL;
29
30 return priv->rate[clk->id];
Simon Glass6a1c7ce2015-07-06 12:54:24 -060031}
32
Dario Binacchi2983ad52020-12-30 00:06:31 +010033static 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
Stephen Warren135aa952016-06-17 09:44:00 -060049static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
Simon Glass6a1c7ce2015-07-06 12:54:24 -060050{
Stephen Warren135aa952016-06-17 09:44:00 -060051 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
52 ulong old_rate;
53
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020054 if (!priv->probed)
55 return -ENODEV;
56
Stephen Warrendf8b0a02016-06-21 13:32:07 -060057 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060058 return -EINVAL;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060059
60 if (!rate)
61 return -EINVAL;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060062
Stephen Warren135aa952016-06-17 09:44:00 -060063 old_rate = priv->rate[clk->id];
64 priv->rate[clk->id] = rate;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060065
66 return old_rate;
67}
68
Stephen Warren135aa952016-06-17 09:44:00 -060069static int sandbox_clk_enable(struct clk *clk)
Simon Glass6a1c7ce2015-07-06 12:54:24 -060070{
Stephen Warren135aa952016-06-17 09:44:00 -060071 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
Simon Glass6a1c7ce2015-07-06 12:54:24 -060072
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020073 if (!priv->probed)
74 return -ENODEV;
75
Stephen Warrendf8b0a02016-06-21 13:32:07 -060076 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060077 return -EINVAL;
78
79 priv->enabled[clk->id] = true;
80
81 return 0;
82}
83
84static int sandbox_clk_disable(struct clk *clk)
85{
86 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
87
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020088 if (!priv->probed)
89 return -ENODEV;
90
Stephen Warrendf8b0a02016-06-21 13:32:07 -060091 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060092 return -EINVAL;
93
94 priv->enabled[clk->id] = false;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060095
96 return 0;
97}
98
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +020099static 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
110static 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
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600121static struct clk_ops sandbox_clk_ops = {
Dario Binacchi2983ad52020-12-30 00:06:31 +0100122 .round_rate = sandbox_clk_round_rate,
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600123 .get_rate = sandbox_clk_get_rate,
124 .set_rate = sandbox_clk_set_rate,
Stephen Warren135aa952016-06-17 09:44:00 -0600125 .enable = sandbox_clk_enable,
126 .disable = sandbox_clk_disable,
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +0200127 .request = sandbox_clk_request,
Simon Glassfb8c0d52020-02-03 07:35:54 -0700128 .rfree = sandbox_clk_free,
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600129};
130
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +0200131static 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
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600139static const struct udevice_id sandbox_clk_ids[] = {
140 { .compatible = "sandbox,clk" },
141 { }
142};
143
Simon Glass88280522020-10-03 11:31:32 -0600144U_BOOT_DRIVER(sandbox_clk) = {
145 .name = "sandbox_clk",
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600146 .id = UCLASS_CLK,
147 .of_match = sandbox_clk_ids,
148 .ops = &sandbox_clk_ops,
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +0200149 .probe = sandbox_clk_probe,
Simon Glass41575d82020-12-03 16:55:17 -0700150 .priv_auto = sizeof(struct sandbox_clk_priv),
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600151};
Stephen Warren135aa952016-06-17 09:44:00 -0600152
153ulong 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
163int 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}
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +0200172
173int 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}