1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) Copyright 2015 Google, Inc
4  */
5 
6 #include <common.h>
7 #include <clk-uclass.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <malloc.h>
11 #include <asm/clk.h>
12 
13 struct sandbox_clk_priv {
14 	bool probed;
15 	ulong rate[SANDBOX_CLK_ID_COUNT];
16 	bool enabled[SANDBOX_CLK_ID_COUNT];
17 	bool requested[SANDBOX_CLK_ID_COUNT];
18 };
19 
sandbox_clk_get_rate(struct clk * clk)20 static ulong sandbox_clk_get_rate(struct clk *clk)
21 {
22 	struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
23 
24 	if (!priv->probed)
25 		return -ENODEV;
26 
27 	if (clk->id >= SANDBOX_CLK_ID_COUNT)
28 		return -EINVAL;
29 
30 	return priv->rate[clk->id];
31 }
32 
sandbox_clk_round_rate(struct clk * clk,ulong rate)33 static 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 
sandbox_clk_set_rate(struct clk * clk,ulong rate)49 static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
50 {
51 	struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
52 	ulong old_rate;
53 
54 	if (!priv->probed)
55 		return -ENODEV;
56 
57 	if (clk->id >= SANDBOX_CLK_ID_COUNT)
58 		return -EINVAL;
59 
60 	if (!rate)
61 		return -EINVAL;
62 
63 	old_rate = priv->rate[clk->id];
64 	priv->rate[clk->id] = rate;
65 
66 	return old_rate;
67 }
68 
sandbox_clk_enable(struct clk * clk)69 static int sandbox_clk_enable(struct clk *clk)
70 {
71 	struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
72 
73 	if (!priv->probed)
74 		return -ENODEV;
75 
76 	if (clk->id >= SANDBOX_CLK_ID_COUNT)
77 		return -EINVAL;
78 
79 	priv->enabled[clk->id] = true;
80 
81 	return 0;
82 }
83 
sandbox_clk_disable(struct clk * clk)84 static int sandbox_clk_disable(struct clk *clk)
85 {
86 	struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
87 
88 	if (!priv->probed)
89 		return -ENODEV;
90 
91 	if (clk->id >= SANDBOX_CLK_ID_COUNT)
92 		return -EINVAL;
93 
94 	priv->enabled[clk->id] = false;
95 
96 	return 0;
97 }
98 
sandbox_clk_request(struct clk * clk)99 static 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 
sandbox_clk_free(struct clk * clk)110 static 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 
121 static struct clk_ops sandbox_clk_ops = {
122 	.round_rate	= sandbox_clk_round_rate,
123 	.get_rate	= sandbox_clk_get_rate,
124 	.set_rate	= sandbox_clk_set_rate,
125 	.enable		= sandbox_clk_enable,
126 	.disable	= sandbox_clk_disable,
127 	.request	= sandbox_clk_request,
128 	.rfree		= sandbox_clk_free,
129 };
130 
sandbox_clk_probe(struct udevice * dev)131 static 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 
139 static const struct udevice_id sandbox_clk_ids[] = {
140 	{ .compatible = "sandbox,clk" },
141 	{ }
142 };
143 
144 U_BOOT_DRIVER(sandbox_clk) = {
145 	.name		= "sandbox_clk",
146 	.id		= UCLASS_CLK,
147 	.of_match	= sandbox_clk_ids,
148 	.ops		= &sandbox_clk_ops,
149 	.probe		= sandbox_clk_probe,
150 	.priv_auto	= sizeof(struct sandbox_clk_priv),
151 };
152 
sandbox_clk_query_rate(struct udevice * dev,int id)153 ulong 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 
sandbox_clk_query_enable(struct udevice * dev,int id)163 int 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 }
172 
sandbox_clk_query_requested(struct udevice * dev,int id)173 int 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 }
181