blob: 768fbb7c52030f58e8c996ef464bdb7af03d46e6 [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
Stephen Warren135aa952016-06-17 09:44:00 -060033static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
Simon Glass6a1c7ce2015-07-06 12:54:24 -060034{
Stephen Warren135aa952016-06-17 09:44:00 -060035 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
36 ulong old_rate;
37
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020038 if (!priv->probed)
39 return -ENODEV;
40
Stephen Warrendf8b0a02016-06-21 13:32:07 -060041 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060042 return -EINVAL;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060043
44 if (!rate)
45 return -EINVAL;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060046
Stephen Warren135aa952016-06-17 09:44:00 -060047 old_rate = priv->rate[clk->id];
48 priv->rate[clk->id] = rate;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060049
50 return old_rate;
51}
52
Stephen Warren135aa952016-06-17 09:44:00 -060053static int sandbox_clk_enable(struct clk *clk)
Simon Glass6a1c7ce2015-07-06 12:54:24 -060054{
Stephen Warren135aa952016-06-17 09:44:00 -060055 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
Simon Glass6a1c7ce2015-07-06 12:54:24 -060056
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020057 if (!priv->probed)
58 return -ENODEV;
59
Stephen Warrendf8b0a02016-06-21 13:32:07 -060060 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060061 return -EINVAL;
62
63 priv->enabled[clk->id] = true;
64
65 return 0;
66}
67
68static int sandbox_clk_disable(struct clk *clk)
69{
70 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
71
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +020072 if (!priv->probed)
73 return -ENODEV;
74
Stephen Warrendf8b0a02016-06-21 13:32:07 -060075 if (clk->id >= SANDBOX_CLK_ID_COUNT)
Stephen Warren135aa952016-06-17 09:44:00 -060076 return -EINVAL;
77
78 priv->enabled[clk->id] = false;
Simon Glass6a1c7ce2015-07-06 12:54:24 -060079
80 return 0;
81}
82
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +020083static int sandbox_clk_request(struct clk *clk)
84{
85 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
86
87 if (clk->id >= SANDBOX_CLK_ID_COUNT)
88 return -EINVAL;
89
90 priv->requested[clk->id] = true;
91 return 0;
92}
93
94static int sandbox_clk_free(struct clk *clk)
95{
96 struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
97
98 if (clk->id >= SANDBOX_CLK_ID_COUNT)
99 return -EINVAL;
100
101 priv->requested[clk->id] = false;
102 return 0;
103}
104
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600105static struct clk_ops sandbox_clk_ops = {
106 .get_rate = sandbox_clk_get_rate,
107 .set_rate = sandbox_clk_set_rate,
Stephen Warren135aa952016-06-17 09:44:00 -0600108 .enable = sandbox_clk_enable,
109 .disable = sandbox_clk_disable,
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +0200110 .request = sandbox_clk_request,
Simon Glassfb8c0d52020-02-03 07:35:54 -0700111 .rfree = sandbox_clk_free,
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600112};
113
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +0200114static int sandbox_clk_probe(struct udevice *dev)
115{
116 struct sandbox_clk_priv *priv = dev_get_priv(dev);
117
118 priv->probed = true;
119 return 0;
120}
121
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600122static const struct udevice_id sandbox_clk_ids[] = {
123 { .compatible = "sandbox,clk" },
124 { }
125};
126
127U_BOOT_DRIVER(clk_sandbox) = {
128 .name = "clk_sandbox",
129 .id = UCLASS_CLK,
130 .of_match = sandbox_clk_ids,
131 .ops = &sandbox_clk_ops,
Jean-Jacques Hiblot9a52be12019-10-22 14:00:07 +0200132 .probe = sandbox_clk_probe,
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600133 .priv_auto_alloc_size = sizeof(struct sandbox_clk_priv),
Simon Glass6a1c7ce2015-07-06 12:54:24 -0600134};
Stephen Warren135aa952016-06-17 09:44:00 -0600135
136ulong sandbox_clk_query_rate(struct udevice *dev, int id)
137{
138 struct sandbox_clk_priv *priv = dev_get_priv(dev);
139
140 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
141 return -EINVAL;
142
143 return priv->rate[id];
144}
145
146int sandbox_clk_query_enable(struct udevice *dev, int id)
147{
148 struct sandbox_clk_priv *priv = dev_get_priv(dev);
149
150 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
151 return -EINVAL;
152
153 return priv->enabled[id];
154}
Jean-Jacques Hiblotdd2e0ce2019-10-22 14:00:05 +0200155
156int sandbox_clk_query_requested(struct udevice *dev, int id)
157{
158 struct sandbox_clk_priv *priv = dev_get_priv(dev);
159
160 if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
161 return -EINVAL;
162 return priv->requested[id];
163}