xref: /openbmc/linux/drivers/clk/ux500/clk-prcmu.c (revision 05bcf503)
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 struct clk_ops clk_prcmu_scalable_ops = {
137 	.prepare = clk_prcmu_prepare,
138 	.unprepare = clk_prcmu_unprepare,
139 	.enable = clk_prcmu_enable,
140 	.disable = clk_prcmu_disable,
141 	.is_enabled = clk_prcmu_is_enabled,
142 	.recalc_rate = clk_prcmu_recalc_rate,
143 	.round_rate = clk_prcmu_round_rate,
144 	.set_rate = clk_prcmu_set_rate,
145 };
146 
147 static struct clk_ops clk_prcmu_gate_ops = {
148 	.prepare = clk_prcmu_prepare,
149 	.unprepare = clk_prcmu_unprepare,
150 	.enable = clk_prcmu_enable,
151 	.disable = clk_prcmu_disable,
152 	.is_enabled = clk_prcmu_is_enabled,
153 	.recalc_rate = clk_prcmu_recalc_rate,
154 };
155 
156 static struct clk_ops clk_prcmu_rate_ops = {
157 	.is_enabled = clk_prcmu_is_enabled,
158 	.recalc_rate = clk_prcmu_recalc_rate,
159 };
160 
161 static struct clk_ops clk_prcmu_opp_gate_ops = {
162 	.prepare = clk_prcmu_opp_prepare,
163 	.unprepare = clk_prcmu_opp_unprepare,
164 	.enable = clk_prcmu_enable,
165 	.disable = clk_prcmu_disable,
166 	.is_enabled = clk_prcmu_is_enabled,
167 	.recalc_rate = clk_prcmu_recalc_rate,
168 };
169 
170 static struct clk *clk_reg_prcmu(const char *name,
171 				 const char *parent_name,
172 				 u8 cg_sel,
173 				 unsigned long rate,
174 				 unsigned long flags,
175 				 struct clk_ops *clk_prcmu_ops)
176 {
177 	struct clk_prcmu *clk;
178 	struct clk_init_data clk_prcmu_init;
179 	struct clk *clk_reg;
180 
181 	if (!name) {
182 		pr_err("clk_prcmu: %s invalid arguments passed\n", __func__);
183 		return ERR_PTR(-EINVAL);
184 	}
185 
186 	clk = kzalloc(sizeof(struct clk_prcmu), GFP_KERNEL);
187 	if (!clk) {
188 		pr_err("clk_prcmu: %s could not allocate clk\n", __func__);
189 		return ERR_PTR(-ENOMEM);
190 	}
191 
192 	clk->cg_sel = cg_sel;
193 	clk->is_enabled = 1;
194 	/* "rate" can be used for changing the initial frequency */
195 	if (rate)
196 		prcmu_set_clock_rate(cg_sel, rate);
197 
198 	clk_prcmu_init.name = name;
199 	clk_prcmu_init.ops = clk_prcmu_ops;
200 	clk_prcmu_init.flags = flags;
201 	clk_prcmu_init.parent_names = (parent_name ? &parent_name : NULL);
202 	clk_prcmu_init.num_parents = (parent_name ? 1 : 0);
203 	clk->hw.init = &clk_prcmu_init;
204 
205 	clk_reg = clk_register(NULL, &clk->hw);
206 	if (IS_ERR_OR_NULL(clk_reg))
207 		goto free_clk;
208 
209 	return clk_reg;
210 
211 free_clk:
212 	kfree(clk);
213 	pr_err("clk_prcmu: %s failed to register clk\n", __func__);
214 	return ERR_PTR(-ENOMEM);
215 }
216 
217 struct clk *clk_reg_prcmu_scalable(const char *name,
218 				   const char *parent_name,
219 				   u8 cg_sel,
220 				   unsigned long rate,
221 				   unsigned long flags)
222 {
223 	return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
224 			&clk_prcmu_scalable_ops);
225 }
226 
227 struct clk *clk_reg_prcmu_gate(const char *name,
228 			       const char *parent_name,
229 			       u8 cg_sel,
230 			       unsigned long flags)
231 {
232 	return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
233 			&clk_prcmu_gate_ops);
234 }
235 
236 struct clk *clk_reg_prcmu_rate(const char *name,
237 			       const char *parent_name,
238 			       u8 cg_sel,
239 			       unsigned long flags)
240 {
241 	return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
242 			&clk_prcmu_rate_ops);
243 }
244 
245 struct clk *clk_reg_prcmu_opp_gate(const char *name,
246 				   const char *parent_name,
247 				   u8 cg_sel,
248 				   unsigned long flags)
249 {
250 	return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
251 			&clk_prcmu_opp_gate_ops);
252 }
253