xref: /openbmc/linux/drivers/clk/imx/clk-scu.c (revision b830f94f)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2018 NXP
4  *   Dong Aisheng <aisheng.dong@nxp.com>
5  */
6 
7 #include <dt-bindings/firmware/imx/rsrc.h>
8 #include <linux/arm-smccc.h>
9 #include <linux/clk-provider.h>
10 #include <linux/err.h>
11 #include <linux/slab.h>
12 
13 #include "clk-scu.h"
14 
15 #define IMX_SIP_CPUFREQ			0xC2000001
16 #define IMX_SIP_SET_CPUFREQ		0x00
17 
18 static struct imx_sc_ipc *ccm_ipc_handle;
19 
20 /*
21  * struct clk_scu - Description of one SCU clock
22  * @hw: the common clk_hw
23  * @rsrc_id: resource ID of this SCU clock
24  * @clk_type: type of this clock resource
25  */
26 struct clk_scu {
27 	struct clk_hw hw;
28 	u16 rsrc_id;
29 	u8 clk_type;
30 };
31 
32 /*
33  * struct imx_sc_msg_req_set_clock_rate - clock set rate protocol
34  * @hdr: SCU protocol header
35  * @rate: rate to set
36  * @resource: clock resource to set rate
37  * @clk: clk type of this resource
38  *
39  * This structure describes the SCU protocol of clock rate set
40  */
41 struct imx_sc_msg_req_set_clock_rate {
42 	struct imx_sc_rpc_msg hdr;
43 	__le32 rate;
44 	__le16 resource;
45 	u8 clk;
46 } __packed;
47 
48 struct req_get_clock_rate {
49 	__le16 resource;
50 	u8 clk;
51 } __packed;
52 
53 struct resp_get_clock_rate {
54 	__le32 rate;
55 };
56 
57 /*
58  * struct imx_sc_msg_get_clock_rate - clock get rate protocol
59  * @hdr: SCU protocol header
60  * @req: get rate request protocol
61  * @resp: get rate response protocol
62  *
63  * This structure describes the SCU protocol of clock rate get
64  */
65 struct imx_sc_msg_get_clock_rate {
66 	struct imx_sc_rpc_msg hdr;
67 	union {
68 		struct req_get_clock_rate req;
69 		struct resp_get_clock_rate resp;
70 	} data;
71 };
72 
73 /*
74  * struct imx_sc_msg_get_clock_parent - clock get parent protocol
75  * @hdr: SCU protocol header
76  * @req: get parent request protocol
77  * @resp: get parent response protocol
78  *
79  * This structure describes the SCU protocol of clock get parent
80  */
81 struct imx_sc_msg_get_clock_parent {
82 	struct imx_sc_rpc_msg hdr;
83 	union {
84 		struct req_get_clock_parent {
85 			__le16 resource;
86 			u8 clk;
87 		} __packed req;
88 		struct resp_get_clock_parent {
89 			u8 parent;
90 		} resp;
91 	} data;
92 };
93 
94 /*
95  * struct imx_sc_msg_set_clock_parent - clock set parent protocol
96  * @hdr: SCU protocol header
97  * @req: set parent request protocol
98  *
99  * This structure describes the SCU protocol of clock set parent
100  */
101 struct imx_sc_msg_set_clock_parent {
102 	struct imx_sc_rpc_msg hdr;
103 	__le16 resource;
104 	u8 clk;
105 	u8 parent;
106 } __packed;
107 
108 /*
109  * struct imx_sc_msg_req_clock_enable - clock gate protocol
110  * @hdr: SCU protocol header
111  * @resource: clock resource to gate
112  * @clk: clk type of this resource
113  * @enable: whether gate off the clock
114  * @autog: HW auto gate enable
115  *
116  * This structure describes the SCU protocol of clock gate
117  */
118 struct imx_sc_msg_req_clock_enable {
119 	struct imx_sc_rpc_msg hdr;
120 	__le16 resource;
121 	u8 clk;
122 	u8 enable;
123 	u8 autog;
124 } __packed;
125 
126 static inline struct clk_scu *to_clk_scu(struct clk_hw *hw)
127 {
128 	return container_of(hw, struct clk_scu, hw);
129 }
130 
131 int imx_clk_scu_init(void)
132 {
133 	return imx_scu_get_handle(&ccm_ipc_handle);
134 }
135 
136 /*
137  * clk_scu_recalc_rate - Get clock rate for a SCU clock
138  * @hw: clock to get rate for
139  * @parent_rate: parent rate provided by common clock framework, not used
140  *
141  * Gets the current clock rate of a SCU clock. Returns the current
142  * clock rate, or zero in failure.
143  */
144 static unsigned long clk_scu_recalc_rate(struct clk_hw *hw,
145 					 unsigned long parent_rate)
146 {
147 	struct clk_scu *clk = to_clk_scu(hw);
148 	struct imx_sc_msg_get_clock_rate msg;
149 	struct imx_sc_rpc_msg *hdr = &msg.hdr;
150 	int ret;
151 
152 	hdr->ver = IMX_SC_RPC_VERSION;
153 	hdr->svc = IMX_SC_RPC_SVC_PM;
154 	hdr->func = IMX_SC_PM_FUNC_GET_CLOCK_RATE;
155 	hdr->size = 2;
156 
157 	msg.data.req.resource = cpu_to_le16(clk->rsrc_id);
158 	msg.data.req.clk = clk->clk_type;
159 
160 	ret = imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
161 	if (ret) {
162 		pr_err("%s: failed to get clock rate %d\n",
163 		       clk_hw_get_name(hw), ret);
164 		return 0;
165 	}
166 
167 	return le32_to_cpu(msg.data.resp.rate);
168 }
169 
170 /*
171  * clk_scu_round_rate - Round clock rate for a SCU clock
172  * @hw: clock to round rate for
173  * @rate: rate to round
174  * @parent_rate: parent rate provided by common clock framework, not used
175  *
176  * Returns the current clock rate, or zero in failure.
177  */
178 static long clk_scu_round_rate(struct clk_hw *hw, unsigned long rate,
179 			       unsigned long *parent_rate)
180 {
181 	/*
182 	 * Assume we support all the requested rate and let the SCU firmware
183 	 * to handle the left work
184 	 */
185 	return rate;
186 }
187 
188 static int clk_scu_atf_set_cpu_rate(struct clk_hw *hw, unsigned long rate,
189 				    unsigned long parent_rate)
190 {
191 	struct clk_scu *clk = to_clk_scu(hw);
192 	struct arm_smccc_res res;
193 	unsigned long cluster_id;
194 
195 	if (clk->rsrc_id == IMX_SC_R_A35)
196 		cluster_id = 0;
197 	else
198 		return -EINVAL;
199 
200 	/* CPU frequency scaling can ONLY be done by ARM-Trusted-Firmware */
201 	arm_smccc_smc(IMX_SIP_CPUFREQ, IMX_SIP_SET_CPUFREQ,
202 		      cluster_id, rate, 0, 0, 0, 0, &res);
203 
204 	return 0;
205 }
206 
207 /*
208  * clk_scu_set_rate - Set rate for a SCU clock
209  * @hw: clock to change rate for
210  * @rate: target rate for the clock
211  * @parent_rate: rate of the clock parent, not used for SCU clocks
212  *
213  * Sets a clock frequency for a SCU clock. Returns the SCU
214  * protocol status.
215  */
216 static int clk_scu_set_rate(struct clk_hw *hw, unsigned long rate,
217 			    unsigned long parent_rate)
218 {
219 	struct clk_scu *clk = to_clk_scu(hw);
220 	struct imx_sc_msg_req_set_clock_rate msg;
221 	struct imx_sc_rpc_msg *hdr = &msg.hdr;
222 
223 	hdr->ver = IMX_SC_RPC_VERSION;
224 	hdr->svc = IMX_SC_RPC_SVC_PM;
225 	hdr->func = IMX_SC_PM_FUNC_SET_CLOCK_RATE;
226 	hdr->size = 3;
227 
228 	msg.rate = cpu_to_le32(rate);
229 	msg.resource = cpu_to_le16(clk->rsrc_id);
230 	msg.clk = clk->clk_type;
231 
232 	return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
233 }
234 
235 static u8 clk_scu_get_parent(struct clk_hw *hw)
236 {
237 	struct clk_scu *clk = to_clk_scu(hw);
238 	struct imx_sc_msg_get_clock_parent msg;
239 	struct imx_sc_rpc_msg *hdr = &msg.hdr;
240 	int ret;
241 
242 	hdr->ver = IMX_SC_RPC_VERSION;
243 	hdr->svc = IMX_SC_RPC_SVC_PM;
244 	hdr->func = IMX_SC_PM_FUNC_GET_CLOCK_PARENT;
245 	hdr->size = 2;
246 
247 	msg.data.req.resource = cpu_to_le16(clk->rsrc_id);
248 	msg.data.req.clk = clk->clk_type;
249 
250 	ret = imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
251 	if (ret) {
252 		pr_err("%s: failed to get clock parent %d\n",
253 		       clk_hw_get_name(hw), ret);
254 		return 0;
255 	}
256 
257 	return msg.data.resp.parent;
258 }
259 
260 static int clk_scu_set_parent(struct clk_hw *hw, u8 index)
261 {
262 	struct clk_scu *clk = to_clk_scu(hw);
263 	struct imx_sc_msg_set_clock_parent msg;
264 	struct imx_sc_rpc_msg *hdr = &msg.hdr;
265 
266 	hdr->ver = IMX_SC_RPC_VERSION;
267 	hdr->svc = IMX_SC_RPC_SVC_PM;
268 	hdr->func = IMX_SC_PM_FUNC_SET_CLOCK_PARENT;
269 	hdr->size = 2;
270 
271 	msg.resource = cpu_to_le16(clk->rsrc_id);
272 	msg.clk = clk->clk_type;
273 	msg.parent = index;
274 
275 	return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
276 }
277 
278 static int sc_pm_clock_enable(struct imx_sc_ipc *ipc, u16 resource,
279 			      u8 clk, bool enable, bool autog)
280 {
281 	struct imx_sc_msg_req_clock_enable msg;
282 	struct imx_sc_rpc_msg *hdr = &msg.hdr;
283 
284 	hdr->ver = IMX_SC_RPC_VERSION;
285 	hdr->svc = IMX_SC_RPC_SVC_PM;
286 	hdr->func = IMX_SC_PM_FUNC_CLOCK_ENABLE;
287 	hdr->size = 3;
288 
289 	msg.resource = cpu_to_le16(resource);
290 	msg.clk = clk;
291 	msg.enable = enable;
292 	msg.autog = autog;
293 
294 	return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
295 }
296 
297 /*
298  * clk_scu_prepare - Enable a SCU clock
299  * @hw: clock to enable
300  *
301  * Enable the clock at the DSC slice level
302  */
303 static int clk_scu_prepare(struct clk_hw *hw)
304 {
305 	struct clk_scu *clk = to_clk_scu(hw);
306 
307 	return sc_pm_clock_enable(ccm_ipc_handle, clk->rsrc_id,
308 				  clk->clk_type, true, false);
309 }
310 
311 /*
312  * clk_scu_unprepare - Disable a SCU clock
313  * @hw: clock to enable
314  *
315  * Disable the clock at the DSC slice level
316  */
317 static void clk_scu_unprepare(struct clk_hw *hw)
318 {
319 	struct clk_scu *clk = to_clk_scu(hw);
320 	int ret;
321 
322 	ret = sc_pm_clock_enable(ccm_ipc_handle, clk->rsrc_id,
323 				 clk->clk_type, false, false);
324 	if (ret)
325 		pr_warn("%s: clk unprepare failed %d\n", clk_hw_get_name(hw),
326 			ret);
327 }
328 
329 static const struct clk_ops clk_scu_ops = {
330 	.recalc_rate = clk_scu_recalc_rate,
331 	.round_rate = clk_scu_round_rate,
332 	.set_rate = clk_scu_set_rate,
333 	.get_parent = clk_scu_get_parent,
334 	.set_parent = clk_scu_set_parent,
335 	.prepare = clk_scu_prepare,
336 	.unprepare = clk_scu_unprepare,
337 };
338 
339 static const struct clk_ops clk_scu_cpu_ops = {
340 	.recalc_rate = clk_scu_recalc_rate,
341 	.round_rate = clk_scu_round_rate,
342 	.set_rate = clk_scu_atf_set_cpu_rate,
343 	.prepare = clk_scu_prepare,
344 	.unprepare = clk_scu_unprepare,
345 };
346 
347 struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
348 			     int num_parents, u32 rsrc_id, u8 clk_type)
349 {
350 	struct clk_init_data init;
351 	struct clk_scu *clk;
352 	struct clk_hw *hw;
353 	int ret;
354 
355 	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
356 	if (!clk)
357 		return ERR_PTR(-ENOMEM);
358 
359 	clk->rsrc_id = rsrc_id;
360 	clk->clk_type = clk_type;
361 
362 	init.name = name;
363 	init.ops = &clk_scu_ops;
364 	if (rsrc_id == IMX_SC_R_A35)
365 		init.ops = &clk_scu_cpu_ops;
366 	else
367 		init.ops = &clk_scu_ops;
368 	init.parent_names = parents;
369 	init.num_parents = num_parents;
370 
371 	/*
372 	 * Note on MX8, the clocks are tightly coupled with power domain
373 	 * that once the power domain is off, the clock status may be
374 	 * lost. So we make it NOCACHE to let user to retrieve the real
375 	 * clock status from HW instead of using the possible invalid
376 	 * cached rate.
377 	 */
378 	init.flags = CLK_GET_RATE_NOCACHE;
379 	clk->hw.init = &init;
380 
381 	hw = &clk->hw;
382 	ret = clk_hw_register(NULL, hw);
383 	if (ret) {
384 		kfree(clk);
385 		hw = ERR_PTR(ret);
386 	}
387 
388 	return hw;
389 }
390