1 // SPDX-License-Identifier: GPL-2.0+
4 * Dong Aisheng <aisheng.dong@nxp.com>
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/of_platform.h>
12 #include <linux/platform_device.h>
13 #include <linux/pm_domain.h>
14 #include <linux/pm_runtime.h>
15 #include <linux/slab.h>
19 #define IMX_SIP_CPUFREQ 0xC2000001
20 #define IMX_SIP_SET_CPUFREQ 0x00
22 static struct imx_sc_ipc
*ccm_ipc_handle
;
23 static struct device_node
*pd_np
;
24 static struct platform_driver imx_clk_scu_driver
;
26 struct imx_scu_clk_node
{
30 const char * const *parents
;
34 struct list_head node
;
37 struct list_head imx_scu_clks
[IMX_SC_R_LAST
];
40 * struct clk_scu - Description of one SCU clock
41 * @hw: the common clk_hw
42 * @rsrc_id: resource ID of this SCU clock
43 * @clk_type: type of this clock resource
50 /* for state save&restore */
56 * struct imx_sc_msg_req_set_clock_rate - clock set rate protocol
57 * @hdr: SCU protocol header
59 * @resource: clock resource to set rate
60 * @clk: clk type of this resource
62 * This structure describes the SCU protocol of clock rate set
64 struct imx_sc_msg_req_set_clock_rate
{
65 struct imx_sc_rpc_msg hdr
;
69 } __packed
__aligned(4);
71 struct req_get_clock_rate
{
74 } __packed
__aligned(4);
76 struct resp_get_clock_rate
{
81 * struct imx_sc_msg_get_clock_rate - clock get rate protocol
82 * @hdr: SCU protocol header
83 * @req: get rate request protocol
84 * @resp: get rate response protocol
86 * This structure describes the SCU protocol of clock rate get
88 struct imx_sc_msg_get_clock_rate
{
89 struct imx_sc_rpc_msg hdr
;
91 struct req_get_clock_rate req
;
92 struct resp_get_clock_rate resp
;
97 * struct imx_sc_msg_get_clock_parent - clock get parent protocol
98 * @hdr: SCU protocol header
99 * @req: get parent request protocol
100 * @resp: get parent response protocol
102 * This structure describes the SCU protocol of clock get parent
104 struct imx_sc_msg_get_clock_parent
{
105 struct imx_sc_rpc_msg hdr
;
107 struct req_get_clock_parent
{
110 } __packed
__aligned(4) req
;
111 struct resp_get_clock_parent
{
118 * struct imx_sc_msg_set_clock_parent - clock set parent protocol
119 * @hdr: SCU protocol header
120 * @req: set parent request protocol
122 * This structure describes the SCU protocol of clock set parent
124 struct imx_sc_msg_set_clock_parent
{
125 struct imx_sc_rpc_msg hdr
;
132 * struct imx_sc_msg_req_clock_enable - clock gate protocol
133 * @hdr: SCU protocol header
134 * @resource: clock resource to gate
135 * @clk: clk type of this resource
136 * @enable: whether gate off the clock
137 * @autog: HW auto gate enable
139 * This structure describes the SCU protocol of clock gate
141 struct imx_sc_msg_req_clock_enable
{
142 struct imx_sc_rpc_msg hdr
;
147 } __packed
__aligned(4);
149 static inline struct clk_scu
*to_clk_scu(struct clk_hw
*hw
)
151 return container_of(hw
, struct clk_scu
, hw
);
154 int imx_clk_scu_init(struct device_node
*np
)
159 ret
= imx_scu_get_handle(&ccm_ipc_handle
);
163 of_property_read_u32(np
, "#clock-cells", &clk_cells
);
165 if (clk_cells
== 2) {
166 for (i
= 0; i
< IMX_SC_R_LAST
; i
++)
167 INIT_LIST_HEAD(&imx_scu_clks
[i
]);
169 /* pd_np will be used to attach power domains later */
170 pd_np
= of_find_compatible_node(NULL
, NULL
, "fsl,scu-pd");
175 return platform_driver_register(&imx_clk_scu_driver
);
179 * clk_scu_recalc_rate - Get clock rate for a SCU clock
180 * @hw: clock to get rate for
181 * @parent_rate: parent rate provided by common clock framework, not used
183 * Gets the current clock rate of a SCU clock. Returns the current
184 * clock rate, or zero in failure.
186 static unsigned long clk_scu_recalc_rate(struct clk_hw
*hw
,
187 unsigned long parent_rate
)
189 struct clk_scu
*clk
= to_clk_scu(hw
);
190 struct imx_sc_msg_get_clock_rate msg
;
191 struct imx_sc_rpc_msg
*hdr
= &msg
.hdr
;
194 hdr
->ver
= IMX_SC_RPC_VERSION
;
195 hdr
->svc
= IMX_SC_RPC_SVC_PM
;
196 hdr
->func
= IMX_SC_PM_FUNC_GET_CLOCK_RATE
;
199 msg
.data
.req
.resource
= cpu_to_le16(clk
->rsrc_id
);
200 msg
.data
.req
.clk
= clk
->clk_type
;
202 ret
= imx_scu_call_rpc(ccm_ipc_handle
, &msg
, true);
204 pr_err("%s: failed to get clock rate %d\n",
205 clk_hw_get_name(hw
), ret
);
209 return le32_to_cpu(msg
.data
.resp
.rate
);
213 * clk_scu_round_rate - Round clock rate for a SCU clock
214 * @hw: clock to round rate for
215 * @rate: rate to round
216 * @parent_rate: parent rate provided by common clock framework, not used
218 * Returns the current clock rate, or zero in failure.
220 static long clk_scu_round_rate(struct clk_hw
*hw
, unsigned long rate
,
221 unsigned long *parent_rate
)
224 * Assume we support all the requested rate and let the SCU firmware
225 * to handle the left work
230 static int clk_scu_atf_set_cpu_rate(struct clk_hw
*hw
, unsigned long rate
,
231 unsigned long parent_rate
)
233 struct clk_scu
*clk
= to_clk_scu(hw
);
234 struct arm_smccc_res res
;
235 unsigned long cluster_id
;
237 if (clk
->rsrc_id
== IMX_SC_R_A35
)
242 /* CPU frequency scaling can ONLY be done by ARM-Trusted-Firmware */
243 arm_smccc_smc(IMX_SIP_CPUFREQ
, IMX_SIP_SET_CPUFREQ
,
244 cluster_id
, rate
, 0, 0, 0, 0, &res
);
250 * clk_scu_set_rate - Set rate for a SCU clock
251 * @hw: clock to change rate for
252 * @rate: target rate for the clock
253 * @parent_rate: rate of the clock parent, not used for SCU clocks
255 * Sets a clock frequency for a SCU clock. Returns the SCU
258 static int clk_scu_set_rate(struct clk_hw
*hw
, unsigned long rate
,
259 unsigned long parent_rate
)
261 struct clk_scu
*clk
= to_clk_scu(hw
);
262 struct imx_sc_msg_req_set_clock_rate msg
;
263 struct imx_sc_rpc_msg
*hdr
= &msg
.hdr
;
265 hdr
->ver
= IMX_SC_RPC_VERSION
;
266 hdr
->svc
= IMX_SC_RPC_SVC_PM
;
267 hdr
->func
= IMX_SC_PM_FUNC_SET_CLOCK_RATE
;
270 msg
.rate
= cpu_to_le32(rate
);
271 msg
.resource
= cpu_to_le16(clk
->rsrc_id
);
272 msg
.clk
= clk
->clk_type
;
274 return imx_scu_call_rpc(ccm_ipc_handle
, &msg
, true);
277 static u8
clk_scu_get_parent(struct clk_hw
*hw
)
279 struct clk_scu
*clk
= to_clk_scu(hw
);
280 struct imx_sc_msg_get_clock_parent msg
;
281 struct imx_sc_rpc_msg
*hdr
= &msg
.hdr
;
284 hdr
->ver
= IMX_SC_RPC_VERSION
;
285 hdr
->svc
= IMX_SC_RPC_SVC_PM
;
286 hdr
->func
= IMX_SC_PM_FUNC_GET_CLOCK_PARENT
;
289 msg
.data
.req
.resource
= cpu_to_le16(clk
->rsrc_id
);
290 msg
.data
.req
.clk
= clk
->clk_type
;
292 ret
= imx_scu_call_rpc(ccm_ipc_handle
, &msg
, true);
294 pr_err("%s: failed to get clock parent %d\n",
295 clk_hw_get_name(hw
), ret
);
299 return msg
.data
.resp
.parent
;
302 static int clk_scu_set_parent(struct clk_hw
*hw
, u8 index
)
304 struct clk_scu
*clk
= to_clk_scu(hw
);
305 struct imx_sc_msg_set_clock_parent msg
;
306 struct imx_sc_rpc_msg
*hdr
= &msg
.hdr
;
308 hdr
->ver
= IMX_SC_RPC_VERSION
;
309 hdr
->svc
= IMX_SC_RPC_SVC_PM
;
310 hdr
->func
= IMX_SC_PM_FUNC_SET_CLOCK_PARENT
;
313 msg
.resource
= cpu_to_le16(clk
->rsrc_id
);
314 msg
.clk
= clk
->clk_type
;
317 return imx_scu_call_rpc(ccm_ipc_handle
, &msg
, true);
320 static int sc_pm_clock_enable(struct imx_sc_ipc
*ipc
, u16 resource
,
321 u8 clk
, bool enable
, bool autog
)
323 struct imx_sc_msg_req_clock_enable msg
;
324 struct imx_sc_rpc_msg
*hdr
= &msg
.hdr
;
326 hdr
->ver
= IMX_SC_RPC_VERSION
;
327 hdr
->svc
= IMX_SC_RPC_SVC_PM
;
328 hdr
->func
= IMX_SC_PM_FUNC_CLOCK_ENABLE
;
331 msg
.resource
= cpu_to_le16(resource
);
336 return imx_scu_call_rpc(ccm_ipc_handle
, &msg
, true);
340 * clk_scu_prepare - Enable a SCU clock
341 * @hw: clock to enable
343 * Enable the clock at the DSC slice level
345 static int clk_scu_prepare(struct clk_hw
*hw
)
347 struct clk_scu
*clk
= to_clk_scu(hw
);
349 return sc_pm_clock_enable(ccm_ipc_handle
, clk
->rsrc_id
,
350 clk
->clk_type
, true, false);
354 * clk_scu_unprepare - Disable a SCU clock
355 * @hw: clock to enable
357 * Disable the clock at the DSC slice level
359 static void clk_scu_unprepare(struct clk_hw
*hw
)
361 struct clk_scu
*clk
= to_clk_scu(hw
);
364 ret
= sc_pm_clock_enable(ccm_ipc_handle
, clk
->rsrc_id
,
365 clk
->clk_type
, false, false);
367 pr_warn("%s: clk unprepare failed %d\n", clk_hw_get_name(hw
),
371 static const struct clk_ops clk_scu_ops
= {
372 .recalc_rate
= clk_scu_recalc_rate
,
373 .round_rate
= clk_scu_round_rate
,
374 .set_rate
= clk_scu_set_rate
,
375 .get_parent
= clk_scu_get_parent
,
376 .set_parent
= clk_scu_set_parent
,
377 .prepare
= clk_scu_prepare
,
378 .unprepare
= clk_scu_unprepare
,
381 static const struct clk_ops clk_scu_cpu_ops
= {
382 .recalc_rate
= clk_scu_recalc_rate
,
383 .round_rate
= clk_scu_round_rate
,
384 .set_rate
= clk_scu_atf_set_cpu_rate
,
385 .prepare
= clk_scu_prepare
,
386 .unprepare
= clk_scu_unprepare
,
389 struct clk_hw
*__imx_clk_scu(struct device
*dev
, const char *name
,
390 const char * const *parents
, int num_parents
,
391 u32 rsrc_id
, u8 clk_type
)
393 struct clk_init_data init
;
398 clk
= kzalloc(sizeof(*clk
), GFP_KERNEL
);
400 return ERR_PTR(-ENOMEM
);
402 clk
->rsrc_id
= rsrc_id
;
403 clk
->clk_type
= clk_type
;
406 init
.ops
= &clk_scu_ops
;
407 if (rsrc_id
== IMX_SC_R_A35
)
408 init
.ops
= &clk_scu_cpu_ops
;
410 init
.ops
= &clk_scu_ops
;
411 init
.parent_names
= parents
;
412 init
.num_parents
= num_parents
;
415 * Note on MX8, the clocks are tightly coupled with power domain
416 * that once the power domain is off, the clock status may be
417 * lost. So we make it NOCACHE to let user to retrieve the real
418 * clock status from HW instead of using the possible invalid
421 init
.flags
= CLK_GET_RATE_NOCACHE
;
422 clk
->hw
.init
= &init
;
425 ret
= clk_hw_register(dev
, hw
);
432 dev_set_drvdata(dev
, clk
);
437 struct clk_hw
*imx_scu_of_clk_src_get(struct of_phandle_args
*clkspec
,
440 unsigned int rsrc
= clkspec
->args
[0];
441 unsigned int idx
= clkspec
->args
[1];
442 struct list_head
*scu_clks
= data
;
443 struct imx_scu_clk_node
*clk
;
445 list_for_each_entry(clk
, &scu_clks
[rsrc
], node
) {
446 if (clk
->clk_type
== idx
)
450 return ERR_PTR(-ENODEV
);
453 static int imx_clk_scu_probe(struct platform_device
*pdev
)
455 struct device
*dev
= &pdev
->dev
;
456 struct imx_scu_clk_node
*clk
= dev_get_platdata(dev
);
460 pm_runtime_set_suspended(dev
);
461 pm_runtime_set_autosuspend_delay(dev
, 50);
462 pm_runtime_use_autosuspend(&pdev
->dev
);
463 pm_runtime_enable(dev
);
465 ret
= pm_runtime_get_sync(dev
);
467 pm_runtime_disable(dev
);
471 hw
= __imx_clk_scu(dev
, clk
->name
, clk
->parents
, clk
->num_parents
,
472 clk
->rsrc
, clk
->clk_type
);
474 pm_runtime_disable(dev
);
479 list_add_tail(&clk
->node
, &imx_scu_clks
[clk
->rsrc
]);
481 pm_runtime_mark_last_busy(&pdev
->dev
);
482 pm_runtime_put_autosuspend(&pdev
->dev
);
484 dev_dbg(dev
, "register SCU clock rsrc:%d type:%d\n", clk
->rsrc
,
490 static int __maybe_unused
imx_clk_scu_suspend(struct device
*dev
)
492 struct clk_scu
*clk
= dev_get_drvdata(dev
);
494 clk
->rate
= clk_hw_get_rate(&clk
->hw
);
495 clk
->is_enabled
= clk_hw_is_enabled(&clk
->hw
);
498 dev_dbg(dev
, "save rate %d\n", clk
->rate
);
501 dev_dbg(dev
, "save enabled state\n");
506 static int __maybe_unused
imx_clk_scu_resume(struct device
*dev
)
508 struct clk_scu
*clk
= dev_get_drvdata(dev
);
512 ret
= clk_scu_set_rate(&clk
->hw
, clk
->rate
, 0);
513 dev_dbg(dev
, "restore rate %d %s\n", clk
->rate
,
514 !ret
? "success" : "failed");
517 if (clk
->is_enabled
) {
518 ret
= clk_scu_prepare(&clk
->hw
);
519 dev_dbg(dev
, "restore enabled state %s\n",
520 !ret
? "success" : "failed");
526 static const struct dev_pm_ops imx_clk_scu_pm_ops
= {
527 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_scu_suspend
,
531 static struct platform_driver imx_clk_scu_driver
= {
533 .name
= "imx-scu-clk",
534 .suppress_bind_attrs
= true,
535 .pm
= &imx_clk_scu_pm_ops
,
537 .probe
= imx_clk_scu_probe
,
540 static int imx_clk_scu_attach_pd(struct device
*dev
, u32 rsrc_id
)
542 struct of_phandle_args genpdspec
= {
548 if (rsrc_id
== IMX_SC_R_A35
|| rsrc_id
== IMX_SC_R_A53
||
549 rsrc_id
== IMX_SC_R_A72
)
552 return of_genpd_add_device(&genpdspec
, dev
);
555 struct clk_hw
*imx_clk_scu_alloc_dev(const char *name
,
556 const char * const *parents
,
557 int num_parents
, u32 rsrc_id
, u8 clk_type
)
559 struct imx_scu_clk_node clk
= {
562 .clk_type
= clk_type
,
564 .num_parents
= num_parents
,
566 struct platform_device
*pdev
;
569 pdev
= platform_device_alloc(name
, PLATFORM_DEVID_NONE
);
571 pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n",
572 name
, rsrc_id
, clk_type
);
573 return ERR_PTR(-ENOMEM
);
576 ret
= platform_device_add_data(pdev
, &clk
, sizeof(clk
));
578 platform_device_put(pdev
);
582 pdev
->driver_override
= "imx-scu-clk";
584 ret
= imx_clk_scu_attach_pd(&pdev
->dev
, rsrc_id
);
586 pr_warn("%s: failed to attached the power domain %d\n",
589 platform_device_add(pdev
);
591 /* For API backwards compatiblilty, simply return NULL for success */
595 void imx_clk_scu_unregister(void)
597 struct imx_scu_clk_node
*clk
;
600 for (i
= 0; i
< IMX_SC_R_LAST
; i
++) {
601 list_for_each_entry(clk
, &imx_scu_clks
[i
], node
) {
602 clk_hw_unregister(clk
->hw
);