1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2018-2021 NXP
4 * Dong Aisheng <aisheng.dong@nxp.com>
7 #include <dt-bindings/firmware/imx/rsrc.h>
8 #include <linux/arm-smccc.h>
9 #include <linux/bsearch.h>
10 #include <linux/clk-provider.h>
11 #include <linux/err.h>
13 #include <linux/firmware/imx/svc/rm.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_domain.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/slab.h>
22 #define IMX_SIP_CPUFREQ 0xC2000001
23 #define IMX_SIP_SET_CPUFREQ 0x00
25 static struct imx_sc_ipc
*ccm_ipc_handle
;
26 static struct device_node
*pd_np
;
27 static struct platform_driver imx_clk_scu_driver
;
28 static const struct imx_clk_scu_rsrc_table
*rsrc_table
;
30 struct imx_scu_clk_node
{
34 const char * const *parents
;
38 struct list_head node
;
41 struct list_head imx_scu_clks
[IMX_SC_R_LAST
];
44 * struct clk_scu - Description of one SCU clock
45 * @hw: the common clk_hw
46 * @rsrc_id: resource ID of this SCU clock
47 * @clk_type: type of this clock resource
54 /* for state save&restore */
55 struct clk_hw
*parent
;
62 * struct clk_gpr_scu - Description of one SCU GPR clock
63 * @hw: the common clk_hw
64 * @rsrc_id: resource ID of this SCU clock
65 * @gpr_id: GPR ID index to control the divider
75 #define to_clk_gpr_scu(_hw) container_of(_hw, struct clk_gpr_scu, hw)
78 * struct imx_sc_msg_req_set_clock_rate - clock set rate protocol
79 * @hdr: SCU protocol header
81 * @resource: clock resource to set rate
82 * @clk: clk type of this resource
84 * This structure describes the SCU protocol of clock rate set
86 struct imx_sc_msg_req_set_clock_rate
{
87 struct imx_sc_rpc_msg hdr
;
91 } __packed
__aligned(4);
93 struct req_get_clock_rate
{
96 } __packed
__aligned(4);
98 struct resp_get_clock_rate
{
103 * struct imx_sc_msg_get_clock_rate - clock get rate protocol
104 * @hdr: SCU protocol header
105 * @req: get rate request protocol
106 * @resp: get rate response protocol
108 * This structure describes the SCU protocol of clock rate get
110 struct imx_sc_msg_get_clock_rate
{
111 struct imx_sc_rpc_msg hdr
;
113 struct req_get_clock_rate req
;
114 struct resp_get_clock_rate resp
;
119 * struct imx_sc_msg_get_clock_parent - clock get parent protocol
120 * @hdr: SCU protocol header
121 * @req: get parent request protocol
122 * @resp: get parent response protocol
124 * This structure describes the SCU protocol of clock get parent
126 struct imx_sc_msg_get_clock_parent
{
127 struct imx_sc_rpc_msg hdr
;
129 struct req_get_clock_parent
{
132 } __packed
__aligned(4) req
;
133 struct resp_get_clock_parent
{
140 * struct imx_sc_msg_set_clock_parent - clock set parent protocol
141 * @hdr: SCU protocol header
142 * @req: set parent request protocol
144 * This structure describes the SCU protocol of clock set parent
146 struct imx_sc_msg_set_clock_parent
{
147 struct imx_sc_rpc_msg hdr
;
154 * struct imx_sc_msg_req_clock_enable - clock gate protocol
155 * @hdr: SCU protocol header
156 * @resource: clock resource to gate
157 * @clk: clk type of this resource
158 * @enable: whether gate off the clock
159 * @autog: HW auto gate enable
161 * This structure describes the SCU protocol of clock gate
163 struct imx_sc_msg_req_clock_enable
{
164 struct imx_sc_rpc_msg hdr
;
169 } __packed
__aligned(4);
171 static inline struct clk_scu
*to_clk_scu(struct clk_hw
*hw
)
173 return container_of(hw
, struct clk_scu
, hw
);
176 static inline int imx_scu_clk_search_cmp(const void *rsrc
, const void *rsrc_p
)
178 return *(u32
*)rsrc
- *(u32
*)rsrc_p
;
181 static bool imx_scu_clk_is_valid(u32 rsrc_id
)
188 p
= bsearch(&rsrc_id
, rsrc_table
->rsrc
, rsrc_table
->num
,
189 sizeof(rsrc_table
->rsrc
[0]), imx_scu_clk_search_cmp
);
194 int imx_clk_scu_init(struct device_node
*np
,
195 const struct imx_clk_scu_rsrc_table
*data
)
200 ret
= imx_scu_get_handle(&ccm_ipc_handle
);
204 of_property_read_u32(np
, "#clock-cells", &clk_cells
);
206 if (clk_cells
== 2) {
207 for (i
= 0; i
< IMX_SC_R_LAST
; i
++)
208 INIT_LIST_HEAD(&imx_scu_clks
[i
]);
210 /* pd_np will be used to attach power domains later */
211 pd_np
= of_find_compatible_node(NULL
, NULL
, "fsl,scu-pd");
218 return platform_driver_register(&imx_clk_scu_driver
);
222 * clk_scu_recalc_rate - Get clock rate for a SCU clock
223 * @hw: clock to get rate for
224 * @parent_rate: parent rate provided by common clock framework, not used
226 * Gets the current clock rate of a SCU clock. Returns the current
227 * clock rate, or zero in failure.
229 static unsigned long clk_scu_recalc_rate(struct clk_hw
*hw
,
230 unsigned long parent_rate
)
232 struct clk_scu
*clk
= to_clk_scu(hw
);
233 struct imx_sc_msg_get_clock_rate msg
;
234 struct imx_sc_rpc_msg
*hdr
= &msg
.hdr
;
237 hdr
->ver
= IMX_SC_RPC_VERSION
;
238 hdr
->svc
= IMX_SC_RPC_SVC_PM
;
239 hdr
->func
= IMX_SC_PM_FUNC_GET_CLOCK_RATE
;
242 msg
.data
.req
.resource
= cpu_to_le16(clk
->rsrc_id
);
243 msg
.data
.req
.clk
= clk
->clk_type
;
245 ret
= imx_scu_call_rpc(ccm_ipc_handle
, &msg
, true);
247 pr_err("%s: failed to get clock rate %d\n",
248 clk_hw_get_name(hw
), ret
);
252 return le32_to_cpu(msg
.data
.resp
.rate
);
256 * clk_scu_determine_rate - Returns the closest rate for a SCU clock
257 * @hw: clock to round rate for
258 * @req: clock rate request
260 * Returns 0 on success, a negative error on failure
262 static int clk_scu_determine_rate(struct clk_hw
*hw
,
263 struct clk_rate_request
*req
)
266 * Assume we support all the requested rate and let the SCU firmware
267 * to handle the left work
273 * clk_scu_round_rate - Round clock rate for a SCU clock
274 * @hw: clock to round rate for
275 * @rate: rate to round
276 * @parent_rate: parent rate provided by common clock framework, not used
278 * Returns the current clock rate, or zero in failure.
280 static long clk_scu_round_rate(struct clk_hw
*hw
, unsigned long rate
,
281 unsigned long *parent_rate
)
284 * Assume we support all the requested rate and let the SCU firmware
285 * to handle the left work
290 static int clk_scu_atf_set_cpu_rate(struct clk_hw
*hw
, unsigned long rate
,
291 unsigned long parent_rate
)
293 struct clk_scu
*clk
= to_clk_scu(hw
);
294 struct arm_smccc_res res
;
295 unsigned long cluster_id
;
297 if (clk
->rsrc_id
== IMX_SC_R_A35
|| clk
->rsrc_id
== IMX_SC_R_A53
)
299 else if (clk
->rsrc_id
== IMX_SC_R_A72
)
304 /* CPU frequency scaling can ONLY be done by ARM-Trusted-Firmware */
305 arm_smccc_smc(IMX_SIP_CPUFREQ
, IMX_SIP_SET_CPUFREQ
,
306 cluster_id
, rate
, 0, 0, 0, 0, &res
);
312 * clk_scu_set_rate - Set rate for a SCU clock
313 * @hw: clock to change rate for
314 * @rate: target rate for the clock
315 * @parent_rate: rate of the clock parent, not used for SCU clocks
317 * Sets a clock frequency for a SCU clock. Returns the SCU
320 static int clk_scu_set_rate(struct clk_hw
*hw
, unsigned long rate
,
321 unsigned long parent_rate
)
323 struct clk_scu
*clk
= to_clk_scu(hw
);
324 struct imx_sc_msg_req_set_clock_rate msg
;
325 struct imx_sc_rpc_msg
*hdr
= &msg
.hdr
;
327 hdr
->ver
= IMX_SC_RPC_VERSION
;
328 hdr
->svc
= IMX_SC_RPC_SVC_PM
;
329 hdr
->func
= IMX_SC_PM_FUNC_SET_CLOCK_RATE
;
332 msg
.rate
= cpu_to_le32(rate
);
333 msg
.resource
= cpu_to_le16(clk
->rsrc_id
);
334 msg
.clk
= clk
->clk_type
;
336 return imx_scu_call_rpc(ccm_ipc_handle
, &msg
, true);
339 static u8
clk_scu_get_parent(struct clk_hw
*hw
)
341 struct clk_scu
*clk
= to_clk_scu(hw
);
342 struct imx_sc_msg_get_clock_parent msg
;
343 struct imx_sc_rpc_msg
*hdr
= &msg
.hdr
;
346 hdr
->ver
= IMX_SC_RPC_VERSION
;
347 hdr
->svc
= IMX_SC_RPC_SVC_PM
;
348 hdr
->func
= IMX_SC_PM_FUNC_GET_CLOCK_PARENT
;
351 msg
.data
.req
.resource
= cpu_to_le16(clk
->rsrc_id
);
352 msg
.data
.req
.clk
= clk
->clk_type
;
354 ret
= imx_scu_call_rpc(ccm_ipc_handle
, &msg
, true);
356 pr_err("%s: failed to get clock parent %d\n",
357 clk_hw_get_name(hw
), ret
);
361 clk
->parent_index
= msg
.data
.resp
.parent
;
363 return msg
.data
.resp
.parent
;
366 static int clk_scu_set_parent(struct clk_hw
*hw
, u8 index
)
368 struct clk_scu
*clk
= to_clk_scu(hw
);
369 struct imx_sc_msg_set_clock_parent msg
;
370 struct imx_sc_rpc_msg
*hdr
= &msg
.hdr
;
373 hdr
->ver
= IMX_SC_RPC_VERSION
;
374 hdr
->svc
= IMX_SC_RPC_SVC_PM
;
375 hdr
->func
= IMX_SC_PM_FUNC_SET_CLOCK_PARENT
;
378 msg
.resource
= cpu_to_le16(clk
->rsrc_id
);
379 msg
.clk
= clk
->clk_type
;
382 ret
= imx_scu_call_rpc(ccm_ipc_handle
, &msg
, true);
384 pr_err("%s: failed to set clock parent %d\n",
385 clk_hw_get_name(hw
), ret
);
389 clk
->parent_index
= index
;
394 static int sc_pm_clock_enable(struct imx_sc_ipc
*ipc
, u16 resource
,
395 u8 clk
, bool enable
, bool autog
)
397 struct imx_sc_msg_req_clock_enable msg
;
398 struct imx_sc_rpc_msg
*hdr
= &msg
.hdr
;
400 hdr
->ver
= IMX_SC_RPC_VERSION
;
401 hdr
->svc
= IMX_SC_RPC_SVC_PM
;
402 hdr
->func
= IMX_SC_PM_FUNC_CLOCK_ENABLE
;
405 msg
.resource
= cpu_to_le16(resource
);
410 return imx_scu_call_rpc(ccm_ipc_handle
, &msg
, true);
414 * clk_scu_prepare - Enable a SCU clock
415 * @hw: clock to enable
417 * Enable the clock at the DSC slice level
419 static int clk_scu_prepare(struct clk_hw
*hw
)
421 struct clk_scu
*clk
= to_clk_scu(hw
);
423 return sc_pm_clock_enable(ccm_ipc_handle
, clk
->rsrc_id
,
424 clk
->clk_type
, true, false);
428 * clk_scu_unprepare - Disable a SCU clock
429 * @hw: clock to enable
431 * Disable the clock at the DSC slice level
433 static void clk_scu_unprepare(struct clk_hw
*hw
)
435 struct clk_scu
*clk
= to_clk_scu(hw
);
438 ret
= sc_pm_clock_enable(ccm_ipc_handle
, clk
->rsrc_id
,
439 clk
->clk_type
, false, false);
441 pr_warn("%s: clk unprepare failed %d\n", clk_hw_get_name(hw
),
445 static const struct clk_ops clk_scu_ops
= {
446 .recalc_rate
= clk_scu_recalc_rate
,
447 .determine_rate
= clk_scu_determine_rate
,
448 .set_rate
= clk_scu_set_rate
,
449 .get_parent
= clk_scu_get_parent
,
450 .set_parent
= clk_scu_set_parent
,
451 .prepare
= clk_scu_prepare
,
452 .unprepare
= clk_scu_unprepare
,
455 static const struct clk_ops clk_scu_cpu_ops
= {
456 .recalc_rate
= clk_scu_recalc_rate
,
457 .round_rate
= clk_scu_round_rate
,
458 .set_rate
= clk_scu_atf_set_cpu_rate
,
459 .prepare
= clk_scu_prepare
,
460 .unprepare
= clk_scu_unprepare
,
463 static const struct clk_ops clk_scu_pi_ops
= {
464 .recalc_rate
= clk_scu_recalc_rate
,
465 .round_rate
= clk_scu_round_rate
,
466 .set_rate
= clk_scu_set_rate
,
469 struct clk_hw
*__imx_clk_scu(struct device
*dev
, const char *name
,
470 const char * const *parents
, int num_parents
,
471 u32 rsrc_id
, u8 clk_type
)
473 struct clk_init_data init
;
478 clk
= kzalloc(sizeof(*clk
), GFP_KERNEL
);
480 return ERR_PTR(-ENOMEM
);
482 clk
->rsrc_id
= rsrc_id
;
483 clk
->clk_type
= clk_type
;
486 init
.ops
= &clk_scu_ops
;
487 if (rsrc_id
== IMX_SC_R_A35
|| rsrc_id
== IMX_SC_R_A53
|| rsrc_id
== IMX_SC_R_A72
)
488 init
.ops
= &clk_scu_cpu_ops
;
489 else if (rsrc_id
== IMX_SC_R_PI_0_PLL
)
490 init
.ops
= &clk_scu_pi_ops
;
492 init
.ops
= &clk_scu_ops
;
493 init
.parent_names
= parents
;
494 init
.num_parents
= num_parents
;
497 * Note on MX8, the clocks are tightly coupled with power domain
498 * that once the power domain is off, the clock status may be
499 * lost. So we make it NOCACHE to let user to retrieve the real
500 * clock status from HW instead of using the possible invalid
503 init
.flags
= CLK_GET_RATE_NOCACHE
;
504 clk
->hw
.init
= &init
;
507 ret
= clk_hw_register(dev
, hw
);
515 dev_set_drvdata(dev
, clk
);
520 struct clk_hw
*imx_scu_of_clk_src_get(struct of_phandle_args
*clkspec
,
523 unsigned int rsrc
= clkspec
->args
[0];
524 unsigned int idx
= clkspec
->args
[1];
525 struct list_head
*scu_clks
= data
;
526 struct imx_scu_clk_node
*clk
;
528 list_for_each_entry(clk
, &scu_clks
[rsrc
], node
) {
529 if (clk
->clk_type
== idx
)
533 return ERR_PTR(-ENODEV
);
536 static int imx_clk_scu_probe(struct platform_device
*pdev
)
538 struct device
*dev
= &pdev
->dev
;
539 struct imx_scu_clk_node
*clk
= dev_get_platdata(dev
);
543 if (!((clk
->rsrc
== IMX_SC_R_A35
) || (clk
->rsrc
== IMX_SC_R_A53
) ||
544 (clk
->rsrc
== IMX_SC_R_A72
))) {
545 pm_runtime_set_suspended(dev
);
546 pm_runtime_set_autosuspend_delay(dev
, 50);
547 pm_runtime_use_autosuspend(&pdev
->dev
);
548 pm_runtime_enable(dev
);
550 ret
= pm_runtime_resume_and_get(dev
);
552 pm_genpd_remove_device(dev
);
553 pm_runtime_disable(dev
);
558 hw
= __imx_clk_scu(dev
, clk
->name
, clk
->parents
, clk
->num_parents
,
559 clk
->rsrc
, clk
->clk_type
);
561 pm_runtime_disable(dev
);
566 list_add_tail(&clk
->node
, &imx_scu_clks
[clk
->rsrc
]);
568 if (!((clk
->rsrc
== IMX_SC_R_A35
) || (clk
->rsrc
== IMX_SC_R_A53
) ||
569 (clk
->rsrc
== IMX_SC_R_A72
))) {
570 pm_runtime_mark_last_busy(&pdev
->dev
);
571 pm_runtime_put_autosuspend(&pdev
->dev
);
574 dev_dbg(dev
, "register SCU clock rsrc:%d type:%d\n", clk
->rsrc
,
580 static int __maybe_unused
imx_clk_scu_suspend(struct device
*dev
)
582 struct clk_scu
*clk
= dev_get_drvdata(dev
);
583 u32 rsrc_id
= clk
->rsrc_id
;
585 if ((rsrc_id
== IMX_SC_R_A35
) || (rsrc_id
== IMX_SC_R_A53
) ||
586 (rsrc_id
== IMX_SC_R_A72
))
589 clk
->parent
= clk_hw_get_parent(&clk
->hw
);
591 /* DC SS needs to handle bypass clock using non-cached clock rate */
592 if (clk
->rsrc_id
== IMX_SC_R_DC_0_VIDEO0
||
593 clk
->rsrc_id
== IMX_SC_R_DC_0_VIDEO1
||
594 clk
->rsrc_id
== IMX_SC_R_DC_1_VIDEO0
||
595 clk
->rsrc_id
== IMX_SC_R_DC_1_VIDEO1
)
596 clk
->rate
= clk_scu_recalc_rate(&clk
->hw
, 0);
598 clk
->rate
= clk_hw_get_rate(&clk
->hw
);
599 clk
->is_enabled
= clk_hw_is_prepared(&clk
->hw
);
602 dev_dbg(dev
, "save parent %s idx %u\n", clk_hw_get_name(clk
->parent
),
606 dev_dbg(dev
, "save rate %d\n", clk
->rate
);
609 dev_dbg(dev
, "save enabled state\n");
614 static int __maybe_unused
imx_clk_scu_resume(struct device
*dev
)
616 struct clk_scu
*clk
= dev_get_drvdata(dev
);
617 u32 rsrc_id
= clk
->rsrc_id
;
620 if ((rsrc_id
== IMX_SC_R_A35
) || (rsrc_id
== IMX_SC_R_A53
) ||
621 (rsrc_id
== IMX_SC_R_A72
))
625 ret
= clk_scu_set_parent(&clk
->hw
, clk
->parent_index
);
626 dev_dbg(dev
, "restore parent %s idx %u %s\n",
627 clk_hw_get_name(clk
->parent
),
628 clk
->parent_index
, !ret
? "success" : "failed");
632 ret
= clk_scu_set_rate(&clk
->hw
, clk
->rate
, 0);
633 dev_dbg(dev
, "restore rate %d %s\n", clk
->rate
,
634 !ret
? "success" : "failed");
637 if (clk
->is_enabled
&& rsrc_id
!= IMX_SC_R_PI_0_PLL
) {
638 ret
= clk_scu_prepare(&clk
->hw
);
639 dev_dbg(dev
, "restore enabled state %s\n",
640 !ret
? "success" : "failed");
646 static const struct dev_pm_ops imx_clk_scu_pm_ops
= {
647 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_clk_scu_suspend
,
651 static struct platform_driver imx_clk_scu_driver
= {
653 .name
= "imx-scu-clk",
654 .suppress_bind_attrs
= true,
655 .pm
= &imx_clk_scu_pm_ops
,
657 .probe
= imx_clk_scu_probe
,
660 static int imx_clk_scu_attach_pd(struct device
*dev
, u32 rsrc_id
)
662 struct of_phandle_args genpdspec
= {
668 if (rsrc_id
== IMX_SC_R_A35
|| rsrc_id
== IMX_SC_R_A53
||
669 rsrc_id
== IMX_SC_R_A72
)
672 return of_genpd_add_device(&genpdspec
, dev
);
675 static bool imx_clk_is_resource_owned(u32 rsrc
)
678 * A-core resources are special. SCFW reports they are not "owned" by
679 * current partition but linux can still adjust them for cpufreq.
681 if (rsrc
== IMX_SC_R_A53
|| rsrc
== IMX_SC_R_A72
|| rsrc
== IMX_SC_R_A35
)
684 return imx_sc_rm_is_resource_owned(ccm_ipc_handle
, rsrc
);
687 struct clk_hw
*imx_clk_scu_alloc_dev(const char *name
,
688 const char * const *parents
,
689 int num_parents
, u32 rsrc_id
, u8 clk_type
)
691 struct imx_scu_clk_node clk
= {
694 .clk_type
= clk_type
,
696 .num_parents
= num_parents
,
698 struct platform_device
*pdev
;
701 if (!imx_scu_clk_is_valid(rsrc_id
))
702 return ERR_PTR(-EINVAL
);
704 if (!imx_clk_is_resource_owned(rsrc_id
))
707 pdev
= platform_device_alloc(name
, PLATFORM_DEVID_NONE
);
709 pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n",
710 name
, rsrc_id
, clk_type
);
711 return ERR_PTR(-ENOMEM
);
714 ret
= platform_device_add_data(pdev
, &clk
, sizeof(clk
));
718 ret
= driver_set_override(&pdev
->dev
, &pdev
->driver_override
,
719 "imx-scu-clk", strlen("imx-scu-clk"));
723 ret
= imx_clk_scu_attach_pd(&pdev
->dev
, rsrc_id
);
725 pr_warn("%s: failed to attached the power domain %d\n",
728 ret
= platform_device_add(pdev
);
732 /* For API backwards compatiblilty, simply return NULL for success */
736 platform_device_put(pdev
);
740 void imx_clk_scu_unregister(void)
742 struct imx_scu_clk_node
*clk
, *n
;
745 for (i
= 0; i
< IMX_SC_R_LAST
; i
++) {
746 list_for_each_entry_safe(clk
, n
, &imx_scu_clks
[i
], node
) {
747 clk_hw_unregister(clk
->hw
);
753 static unsigned long clk_gpr_div_scu_recalc_rate(struct clk_hw
*hw
,
754 unsigned long parent_rate
)
756 struct clk_gpr_scu
*clk
= to_clk_gpr_scu(hw
);
757 unsigned long rate
= 0;
761 err
= imx_sc_misc_get_control(ccm_ipc_handle
, clk
->rsrc_id
,
764 rate
= val
? parent_rate
/ 2 : parent_rate
;
766 return err
? 0 : rate
;
769 static long clk_gpr_div_scu_round_rate(struct clk_hw
*hw
, unsigned long rate
,
770 unsigned long *prate
)
780 static int clk_gpr_div_scu_set_rate(struct clk_hw
*hw
, unsigned long rate
,
781 unsigned long parent_rate
)
783 struct clk_gpr_scu
*clk
= to_clk_gpr_scu(hw
);
787 val
= (rate
< parent_rate
) ? 1 : 0;
788 err
= imx_sc_misc_set_control(ccm_ipc_handle
, clk
->rsrc_id
,
791 return err
? -EINVAL
: 0;
794 static const struct clk_ops clk_gpr_div_scu_ops
= {
795 .recalc_rate
= clk_gpr_div_scu_recalc_rate
,
796 .round_rate
= clk_gpr_div_scu_round_rate
,
797 .set_rate
= clk_gpr_div_scu_set_rate
,
800 static u8
clk_gpr_mux_scu_get_parent(struct clk_hw
*hw
)
802 struct clk_gpr_scu
*clk
= to_clk_gpr_scu(hw
);
805 imx_sc_misc_get_control(ccm_ipc_handle
, clk
->rsrc_id
,
811 static int clk_gpr_mux_scu_set_parent(struct clk_hw
*hw
, u8 index
)
813 struct clk_gpr_scu
*clk
= to_clk_gpr_scu(hw
);
815 return imx_sc_misc_set_control(ccm_ipc_handle
, clk
->rsrc_id
,
819 static const struct clk_ops clk_gpr_mux_scu_ops
= {
820 .determine_rate
= clk_hw_determine_rate_no_reparent
,
821 .get_parent
= clk_gpr_mux_scu_get_parent
,
822 .set_parent
= clk_gpr_mux_scu_set_parent
,
825 static int clk_gpr_gate_scu_prepare(struct clk_hw
*hw
)
827 struct clk_gpr_scu
*clk
= to_clk_gpr_scu(hw
);
829 return imx_sc_misc_set_control(ccm_ipc_handle
, clk
->rsrc_id
,
830 clk
->gpr_id
, !clk
->gate_invert
);
833 static void clk_gpr_gate_scu_unprepare(struct clk_hw
*hw
)
835 struct clk_gpr_scu
*clk
= to_clk_gpr_scu(hw
);
838 ret
= imx_sc_misc_set_control(ccm_ipc_handle
, clk
->rsrc_id
,
839 clk
->gpr_id
, clk
->gate_invert
);
841 pr_err("%s: clk unprepare failed %d\n", clk_hw_get_name(hw
),
845 static int clk_gpr_gate_scu_is_prepared(struct clk_hw
*hw
)
847 struct clk_gpr_scu
*clk
= to_clk_gpr_scu(hw
);
851 ret
= imx_sc_misc_get_control(ccm_ipc_handle
, clk
->rsrc_id
,
856 return clk
->gate_invert
? !val
: val
;
859 static const struct clk_ops clk_gpr_gate_scu_ops
= {
860 .prepare
= clk_gpr_gate_scu_prepare
,
861 .unprepare
= clk_gpr_gate_scu_unprepare
,
862 .is_prepared
= clk_gpr_gate_scu_is_prepared
,
865 struct clk_hw
*__imx_clk_gpr_scu(const char *name
, const char * const *parent_name
,
866 int num_parents
, u32 rsrc_id
, u8 gpr_id
, u8 flags
,
869 struct imx_scu_clk_node
*clk_node
;
870 struct clk_gpr_scu
*clk
;
872 struct clk_init_data init
;
875 if (rsrc_id
>= IMX_SC_R_LAST
|| gpr_id
>= IMX_SC_C_LAST
)
876 return ERR_PTR(-EINVAL
);
878 clk_node
= kzalloc(sizeof(*clk_node
), GFP_KERNEL
);
880 return ERR_PTR(-ENOMEM
);
882 if (!imx_scu_clk_is_valid(rsrc_id
)) {
884 return ERR_PTR(-EINVAL
);
887 if (!imx_clk_is_resource_owned(rsrc_id
)) {
892 clk
= kzalloc(sizeof(*clk
), GFP_KERNEL
);
895 return ERR_PTR(-ENOMEM
);
898 clk
->rsrc_id
= rsrc_id
;
899 clk
->gpr_id
= gpr_id
;
901 clk
->gate_invert
= invert
;
903 if (flags
& IMX_SCU_GPR_CLK_GATE
)
904 init
.ops
= &clk_gpr_gate_scu_ops
;
906 if (flags
& IMX_SCU_GPR_CLK_DIV
)
907 init
.ops
= &clk_gpr_div_scu_ops
;
909 if (flags
& IMX_SCU_GPR_CLK_MUX
)
910 init
.ops
= &clk_gpr_mux_scu_ops
;
914 init
.parent_names
= parent_name
;
915 init
.num_parents
= num_parents
;
917 clk
->hw
.init
= &init
;
920 ret
= clk_hw_register(NULL
, hw
);
927 clk_node
->clk_type
= gpr_id
;
928 list_add_tail(&clk_node
->node
, &imx_scu_clks
[rsrc_id
]);