xref: /linux/drivers/clk/ux500/clk-prcmu.c (revision 0d456bad36d42d16022be045c8a53ddbb59ee478)
1 /*
2  * PRCMU clock implementation for ux500 platform.
3  *
4  * Copyright (C) 2012 ST-Ericsson SA
5  * Author: Ulf Hansson <ulf.hansson@linaro.org>
6  *
7  * License terms: GNU General Public License (GPL) version 2
8  */
9 
10 #include <linux/clk-provider.h>
11 #include <linux/clk-private.h>
12 #include <linux/mfd/dbx500-prcmu.h>
13 #include <linux/slab.h>
14 #include <linux/io.h>
15 #include <linux/err.h>
16 #include "clk.h"
17 
18 #define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw)
19 
20 struct clk_prcmu {
21 	struct clk_hw hw;
22 	u8 cg_sel;
23 	int is_enabled;
24 };
25 
26 /* PRCMU clock operations. */
27 
28 static int clk_prcmu_prepare(struct clk_hw *hw)
29 {
30 	struct clk_prcmu *clk = to_clk_prcmu(hw);
31 	return prcmu_request_clock(clk->cg_sel, true);
32 }
33 
34 static void clk_prcmu_unprepare(struct clk_hw *hw)
35 {
36 	struct clk_prcmu *clk = to_clk_prcmu(hw);
37 	if (prcmu_request_clock(clk->cg_sel, false))
38 		pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
39 			hw->init->name);
40 }
41 
42 static int clk_prcmu_enable(struct clk_hw *hw)
43 {
44 	struct clk_prcmu *clk = to_clk_prcmu(hw);
45 	clk->is_enabled = 1;
46 	return 0;
47 }
48 
49 static void clk_prcmu_disable(struct clk_hw *hw)
50 {
51 	struct clk_prcmu *clk = to_clk_prcmu(hw);
52 	clk->is_enabled = 0;
53 }
54 
55 static int clk_prcmu_is_enabled(struct clk_hw *hw)
56 {
57 	struct clk_prcmu *clk = to_clk_prcmu(hw);
58 	return clk->is_enabled;
59 }
60 
61 static unsigned long clk_prcmu_recalc_rate(struct clk_hw *hw,
62 					   unsigned long parent_rate)
63 {
64 	struct clk_prcmu *clk = to_clk_prcmu(hw);
65 	return prcmu_clock_rate(clk->cg_sel);
66 }
67 
68 static long clk_prcmu_round_rate(struct clk_hw *hw, unsigned long rate,
69 				 unsigned long *parent_rate)
70 {
71 	struct clk_prcmu *clk = to_clk_prcmu(hw);
72 	return prcmu_round_clock_rate(clk->cg_sel, rate);
73 }
74 
75 static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate,
76 			      unsigned long parent_rate)
77 {
78 	struct clk_prcmu *clk = to_clk_prcmu(hw);
79 	return prcmu_set_clock_rate(clk->cg_sel, rate);
80 }
81 
82 static int request_ape_opp100(bool enable)
83 {
84 	static int reqs;
85 	int err = 0;
86 
87 	if (enable) {
88 		if (!reqs)
89 			err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
90 							"clock", 100);
91 		if (!err)
92 			reqs++;
93 	} else {
94 		reqs--;
95 		if (!reqs)
96 			prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
97 						"clock");
98 	}
99 	return err;
100 }
101 
102 static int clk_prcmu_opp_prepare(struct clk_hw *hw)
103 {
104 	int err;
105 	struct clk_prcmu *clk = to_clk_prcmu(hw);
106 
107 	err = request_ape_opp100(true);
108 	if (err) {
109 		pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n",
110 			__func__, hw->init->name);
111 		return err;
112 	}
113 
114 	err = prcmu_request_clock(clk->cg_sel, true);
115 	if (err)
116 		request_ape_opp100(false);
117 
118 	return err;
119 }
120 
121 static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
122 {
123 	struct clk_prcmu *clk = to_clk_prcmu(hw);
124 
125 	if (prcmu_request_clock(clk->cg_sel, false))
126 		goto out_error;
127 	if (request_ape_opp100(false))
128 		goto out_error;
129 	return;
130 
131 out_error:
132 	pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
133 		hw->init->name);
134 }
135 
136 static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
137 {
138 	int err;
139 	struct clk_prcmu *clk = to_clk_prcmu(hw);
140 
141 	err = prcmu_request_ape_opp_100_voltage(true);
142 	if (err) {
143 		pr_err("clk_prcmu: %s failed to request APE OPP VOLT for %s.\n",
144 			__func__, hw->init->name);
145 		return err;
146 	}
147 
148 	err = prcmu_request_clock(clk->cg_sel, true);
149 	if (err)
150 		prcmu_request_ape_opp_100_voltage(false);
151 
152 	return err;
153 }
154 
155 static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
156 {
157 	struct clk_prcmu *clk = to_clk_prcmu(hw);
158 
159 	if (prcmu_request_clock(clk->cg_sel, false))
160 		goto out_error;
161 	if (prcmu_request_ape_opp_100_voltage(false))
162 		goto out_error;
163 	return;
164 
165 out_error:
166 	pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
167 		hw->init->name);
168 }
169 
170 static struct clk_ops clk_prcmu_scalable_ops = {
171 	.prepare = clk_prcmu_prepare,
172 	.unprepare = clk_prcmu_unprepare,
173 	.enable = clk_prcmu_enable,
174 	.disable = clk_prcmu_disable,
175 	.is_enabled = clk_prcmu_is_enabled,
176 	.recalc_rate = clk_prcmu_recalc_rate,
177 	.round_rate = clk_prcmu_round_rate,
178 	.set_rate = clk_prcmu_set_rate,
179 };
180 
181 static struct clk_ops clk_prcmu_gate_ops = {
182 	.prepare = clk_prcmu_prepare,
183 	.unprepare = clk_prcmu_unprepare,
184 	.enable = clk_prcmu_enable,
185 	.disable = clk_prcmu_disable,
186 	.is_enabled = clk_prcmu_is_enabled,
187 	.recalc_rate = clk_prcmu_recalc_rate,
188 };
189 
190 static struct clk_ops clk_prcmu_scalable_rate_ops = {
191 	.is_enabled = clk_prcmu_is_enabled,
192 	.recalc_rate = clk_prcmu_recalc_rate,
193 	.round_rate = clk_prcmu_round_rate,
194 	.set_rate = clk_prcmu_set_rate,
195 };
196 
197 static struct clk_ops clk_prcmu_rate_ops = {
198 	.is_enabled = clk_prcmu_is_enabled,
199 	.recalc_rate = clk_prcmu_recalc_rate,
200 };
201 
202 static struct clk_ops clk_prcmu_opp_gate_ops = {
203 	.prepare = clk_prcmu_opp_prepare,
204 	.unprepare = clk_prcmu_opp_unprepare,
205 	.enable = clk_prcmu_enable,
206 	.disable = clk_prcmu_disable,
207 	.is_enabled = clk_prcmu_is_enabled,
208 	.recalc_rate = clk_prcmu_recalc_rate,
209 };
210 
211 static struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
212 	.prepare = clk_prcmu_opp_volt_prepare,
213 	.unprepare = clk_prcmu_opp_volt_unprepare,
214 	.enable = clk_prcmu_enable,
215 	.disable = clk_prcmu_disable,
216 	.is_enabled = clk_prcmu_is_enabled,
217 	.recalc_rate = clk_prcmu_recalc_rate,
218 	.round_rate = clk_prcmu_round_rate,
219 	.set_rate = clk_prcmu_set_rate,
220 };
221 
222 static struct clk *clk_reg_prcmu(const char *name,
223 				 const char *parent_name,
224 				 u8 cg_sel,
225 				 unsigned long rate,
226 				 unsigned long flags,
227 				 struct clk_ops *clk_prcmu_ops)
228 {
229 	struct clk_prcmu *clk;
230 	struct clk_init_data clk_prcmu_init;
231 	struct clk *clk_reg;
232 
233 	if (!name) {
234 		pr_err("clk_prcmu: %s invalid arguments passed\n", __func__);
235 		return ERR_PTR(-EINVAL);
236 	}
237 
238 	clk = kzalloc(sizeof(struct clk_prcmu), GFP_KERNEL);
239 	if (!clk) {
240 		pr_err("clk_prcmu: %s could not allocate clk\n", __func__);
241 		return ERR_PTR(-ENOMEM);
242 	}
243 
244 	clk->cg_sel = cg_sel;
245 	clk->is_enabled = 1;
246 	/* "rate" can be used for changing the initial frequency */
247 	if (rate)
248 		prcmu_set_clock_rate(cg_sel, rate);
249 
250 	clk_prcmu_init.name = name;
251 	clk_prcmu_init.ops = clk_prcmu_ops;
252 	clk_prcmu_init.flags = flags;
253 	clk_prcmu_init.parent_names = (parent_name ? &parent_name : NULL);
254 	clk_prcmu_init.num_parents = (parent_name ? 1 : 0);
255 	clk->hw.init = &clk_prcmu_init;
256 
257 	clk_reg = clk_register(NULL, &clk->hw);
258 	if (IS_ERR_OR_NULL(clk_reg))
259 		goto free_clk;
260 
261 	return clk_reg;
262 
263 free_clk:
264 	kfree(clk);
265 	pr_err("clk_prcmu: %s failed to register clk\n", __func__);
266 	return ERR_PTR(-ENOMEM);
267 }
268 
269 struct clk *clk_reg_prcmu_scalable(const char *name,
270 				   const char *parent_name,
271 				   u8 cg_sel,
272 				   unsigned long rate,
273 				   unsigned long flags)
274 {
275 	return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
276 			&clk_prcmu_scalable_ops);
277 }
278 
279 struct clk *clk_reg_prcmu_gate(const char *name,
280 			       const char *parent_name,
281 			       u8 cg_sel,
282 			       unsigned long flags)
283 {
284 	return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
285 			&clk_prcmu_gate_ops);
286 }
287 
288 struct clk *clk_reg_prcmu_scalable_rate(const char *name,
289 					const char *parent_name,
290 					u8 cg_sel,
291 					unsigned long rate,
292 					unsigned long flags)
293 {
294 	return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
295 			&clk_prcmu_scalable_rate_ops);
296 }
297 
298 struct clk *clk_reg_prcmu_rate(const char *name,
299 			       const char *parent_name,
300 			       u8 cg_sel,
301 			       unsigned long flags)
302 {
303 	return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
304 			&clk_prcmu_rate_ops);
305 }
306 
307 struct clk *clk_reg_prcmu_opp_gate(const char *name,
308 				   const char *parent_name,
309 				   u8 cg_sel,
310 				   unsigned long flags)
311 {
312 	return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
313 			&clk_prcmu_opp_gate_ops);
314 }
315 
316 struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
317 					    const char *parent_name,
318 					    u8 cg_sel,
319 					    unsigned long rate,
320 					    unsigned long flags)
321 {
322 	return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
323 			&clk_prcmu_opp_volt_scalable_ops);
324 }
325