1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2014 MediaTek Inc.
4 * Author: James Liao <jamesjj.liao@mediatek.com>
7 #include <linux/bitops.h>
8 #include <linux/clk-provider.h>
11 #include <linux/mfd/syscon.h>
12 #include <linux/module.h>
14 #include <linux/of_address.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/slab.h>
23 const struct mtk_gate_regs cg_regs_dummy
= { 0, 0, 0 };
24 EXPORT_SYMBOL_GPL(cg_regs_dummy
);
26 static int mtk_clk_dummy_enable(struct clk_hw
*hw
)
31 static void mtk_clk_dummy_disable(struct clk_hw
*hw
) { }
33 const struct clk_ops mtk_clk_dummy_ops
= {
34 .enable
= mtk_clk_dummy_enable
,
35 .disable
= mtk_clk_dummy_disable
,
37 EXPORT_SYMBOL_GPL(mtk_clk_dummy_ops
);
39 static void mtk_init_clk_data(struct clk_hw_onecell_data
*clk_data
,
44 clk_data
->num
= clk_num
;
46 for (i
= 0; i
< clk_num
; i
++)
47 clk_data
->hws
[i
] = ERR_PTR(-ENOENT
);
50 struct clk_hw_onecell_data
*mtk_devm_alloc_clk_data(struct device
*dev
,
53 struct clk_hw_onecell_data
*clk_data
;
55 clk_data
= devm_kzalloc(dev
, struct_size(clk_data
, hws
, clk_num
),
60 mtk_init_clk_data(clk_data
, clk_num
);
64 EXPORT_SYMBOL_GPL(mtk_devm_alloc_clk_data
);
66 struct clk_hw_onecell_data
*mtk_alloc_clk_data(unsigned int clk_num
)
68 struct clk_hw_onecell_data
*clk_data
;
70 clk_data
= kzalloc(struct_size(clk_data
, hws
, clk_num
), GFP_KERNEL
);
74 mtk_init_clk_data(clk_data
, clk_num
);
78 EXPORT_SYMBOL_GPL(mtk_alloc_clk_data
);
80 void mtk_free_clk_data(struct clk_hw_onecell_data
*clk_data
)
84 EXPORT_SYMBOL_GPL(mtk_free_clk_data
);
86 int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk
*clks
, int num
,
87 struct clk_hw_onecell_data
*clk_data
)
95 for (i
= 0; i
< num
; i
++) {
96 const struct mtk_fixed_clk
*rc
= &clks
[i
];
98 if (!IS_ERR_OR_NULL(clk_data
->hws
[rc
->id
])) {
99 pr_warn("Trying to register duplicate clock ID: %d\n", rc
->id
);
103 hw
= clk_hw_register_fixed_rate(NULL
, rc
->name
, rc
->parent
, 0,
107 pr_err("Failed to register clk %s: %pe\n", rc
->name
,
112 clk_data
->hws
[rc
->id
] = hw
;
119 const struct mtk_fixed_clk
*rc
= &clks
[i
];
121 if (IS_ERR_OR_NULL(clk_data
->hws
[rc
->id
]))
124 clk_hw_unregister_fixed_rate(clk_data
->hws
[rc
->id
]);
125 clk_data
->hws
[rc
->id
] = ERR_PTR(-ENOENT
);
130 EXPORT_SYMBOL_GPL(mtk_clk_register_fixed_clks
);
132 void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk
*clks
, int num
,
133 struct clk_hw_onecell_data
*clk_data
)
140 for (i
= num
; i
> 0; i
--) {
141 const struct mtk_fixed_clk
*rc
= &clks
[i
- 1];
143 if (IS_ERR_OR_NULL(clk_data
->hws
[rc
->id
]))
146 clk_hw_unregister_fixed_rate(clk_data
->hws
[rc
->id
]);
147 clk_data
->hws
[rc
->id
] = ERR_PTR(-ENOENT
);
150 EXPORT_SYMBOL_GPL(mtk_clk_unregister_fixed_clks
);
152 int mtk_clk_register_factors(const struct mtk_fixed_factor
*clks
, int num
,
153 struct clk_hw_onecell_data
*clk_data
)
161 for (i
= 0; i
< num
; i
++) {
162 const struct mtk_fixed_factor
*ff
= &clks
[i
];
164 if (!IS_ERR_OR_NULL(clk_data
->hws
[ff
->id
])) {
165 pr_warn("Trying to register duplicate clock ID: %d\n", ff
->id
);
169 hw
= clk_hw_register_fixed_factor(NULL
, ff
->name
, ff
->parent_name
,
170 ff
->flags
, ff
->mult
, ff
->div
);
173 pr_err("Failed to register clk %s: %pe\n", ff
->name
,
178 clk_data
->hws
[ff
->id
] = hw
;
185 const struct mtk_fixed_factor
*ff
= &clks
[i
];
187 if (IS_ERR_OR_NULL(clk_data
->hws
[ff
->id
]))
190 clk_hw_unregister_fixed_factor(clk_data
->hws
[ff
->id
]);
191 clk_data
->hws
[ff
->id
] = ERR_PTR(-ENOENT
);
196 EXPORT_SYMBOL_GPL(mtk_clk_register_factors
);
198 void mtk_clk_unregister_factors(const struct mtk_fixed_factor
*clks
, int num
,
199 struct clk_hw_onecell_data
*clk_data
)
206 for (i
= num
; i
> 0; i
--) {
207 const struct mtk_fixed_factor
*ff
= &clks
[i
- 1];
209 if (IS_ERR_OR_NULL(clk_data
->hws
[ff
->id
]))
212 clk_hw_unregister_fixed_factor(clk_data
->hws
[ff
->id
]);
213 clk_data
->hws
[ff
->id
] = ERR_PTR(-ENOENT
);
216 EXPORT_SYMBOL_GPL(mtk_clk_unregister_factors
);
218 static struct clk_hw
*mtk_clk_register_composite(struct device
*dev
,
219 const struct mtk_composite
*mc
, void __iomem
*base
, spinlock_t
*lock
)
222 struct clk_mux
*mux
= NULL
;
223 struct clk_gate
*gate
= NULL
;
224 struct clk_divider
*div
= NULL
;
225 struct clk_hw
*mux_hw
= NULL
, *gate_hw
= NULL
, *div_hw
= NULL
;
226 const struct clk_ops
*mux_ops
= NULL
, *gate_ops
= NULL
, *div_ops
= NULL
;
227 const char * const *parent_names
;
232 if (mc
->mux_shift
>= 0) {
233 mux
= kzalloc(sizeof(*mux
), GFP_KERNEL
);
235 return ERR_PTR(-ENOMEM
);
237 mux
->reg
= base
+ mc
->mux_reg
;
238 mux
->mask
= BIT(mc
->mux_width
) - 1;
239 mux
->shift
= mc
->mux_shift
;
241 mux
->flags
= mc
->mux_flags
;
243 mux_ops
= &clk_mux_ops
;
245 parent_names
= mc
->parent_names
;
246 num_parents
= mc
->num_parents
;
249 parent_names
= &parent
;
253 if (mc
->gate_shift
>= 0) {
254 gate
= kzalloc(sizeof(*gate
), GFP_KERNEL
);
260 gate
->reg
= base
+ mc
->gate_reg
;
261 gate
->bit_idx
= mc
->gate_shift
;
262 gate
->flags
= CLK_GATE_SET_TO_DISABLE
;
266 gate_ops
= &clk_gate_ops
;
269 if (mc
->divider_shift
>= 0) {
270 div
= kzalloc(sizeof(*div
), GFP_KERNEL
);
276 div
->reg
= base
+ mc
->divider_reg
;
277 div
->shift
= mc
->divider_shift
;
278 div
->width
= mc
->divider_width
;
282 div_ops
= &clk_divider_ops
;
285 hw
= clk_hw_register_composite(dev
, mc
->name
, parent_names
, num_parents
,
305 static void mtk_clk_unregister_composite(struct clk_hw
*hw
)
307 struct clk_composite
*composite
;
308 struct clk_mux
*mux
= NULL
;
309 struct clk_gate
*gate
= NULL
;
310 struct clk_divider
*div
= NULL
;
315 composite
= to_clk_composite(hw
);
316 if (composite
->mux_hw
)
317 mux
= to_clk_mux(composite
->mux_hw
);
318 if (composite
->gate_hw
)
319 gate
= to_clk_gate(composite
->gate_hw
);
320 if (composite
->rate_hw
)
321 div
= to_clk_divider(composite
->rate_hw
);
323 clk_hw_unregister_composite(hw
);
329 int mtk_clk_register_composites(struct device
*dev
,
330 const struct mtk_composite
*mcs
, int num
,
331 void __iomem
*base
, spinlock_t
*lock
,
332 struct clk_hw_onecell_data
*clk_data
)
340 for (i
= 0; i
< num
; i
++) {
341 const struct mtk_composite
*mc
= &mcs
[i
];
343 if (!IS_ERR_OR_NULL(clk_data
->hws
[mc
->id
])) {
344 pr_warn("Trying to register duplicate clock ID: %d\n",
349 hw
= mtk_clk_register_composite(dev
, mc
, base
, lock
);
352 pr_err("Failed to register clk %s: %pe\n", mc
->name
,
357 clk_data
->hws
[mc
->id
] = hw
;
364 const struct mtk_composite
*mc
= &mcs
[i
];
366 if (IS_ERR_OR_NULL(clk_data
->hws
[mcs
->id
]))
369 mtk_clk_unregister_composite(clk_data
->hws
[mc
->id
]);
370 clk_data
->hws
[mc
->id
] = ERR_PTR(-ENOENT
);
375 EXPORT_SYMBOL_GPL(mtk_clk_register_composites
);
377 void mtk_clk_unregister_composites(const struct mtk_composite
*mcs
, int num
,
378 struct clk_hw_onecell_data
*clk_data
)
385 for (i
= num
; i
> 0; i
--) {
386 const struct mtk_composite
*mc
= &mcs
[i
- 1];
388 if (IS_ERR_OR_NULL(clk_data
->hws
[mc
->id
]))
391 mtk_clk_unregister_composite(clk_data
->hws
[mc
->id
]);
392 clk_data
->hws
[mc
->id
] = ERR_PTR(-ENOENT
);
395 EXPORT_SYMBOL_GPL(mtk_clk_unregister_composites
);
397 int mtk_clk_register_dividers(struct device
*dev
,
398 const struct mtk_clk_divider
*mcds
, int num
,
399 void __iomem
*base
, spinlock_t
*lock
,
400 struct clk_hw_onecell_data
*clk_data
)
408 for (i
= 0; i
< num
; i
++) {
409 const struct mtk_clk_divider
*mcd
= &mcds
[i
];
411 if (!IS_ERR_OR_NULL(clk_data
->hws
[mcd
->id
])) {
412 pr_warn("Trying to register duplicate clock ID: %d\n",
417 hw
= clk_hw_register_divider(dev
, mcd
->name
, mcd
->parent_name
,
418 mcd
->flags
, base
+ mcd
->div_reg
, mcd
->div_shift
,
419 mcd
->div_width
, mcd
->clk_divider_flags
, lock
);
422 pr_err("Failed to register clk %s: %pe\n", mcd
->name
,
427 clk_data
->hws
[mcd
->id
] = hw
;
434 const struct mtk_clk_divider
*mcd
= &mcds
[i
];
436 if (IS_ERR_OR_NULL(clk_data
->hws
[mcd
->id
]))
439 clk_hw_unregister_divider(clk_data
->hws
[mcd
->id
]);
440 clk_data
->hws
[mcd
->id
] = ERR_PTR(-ENOENT
);
445 EXPORT_SYMBOL_GPL(mtk_clk_register_dividers
);
447 void mtk_clk_unregister_dividers(const struct mtk_clk_divider
*mcds
, int num
,
448 struct clk_hw_onecell_data
*clk_data
)
455 for (i
= num
; i
> 0; i
--) {
456 const struct mtk_clk_divider
*mcd
= &mcds
[i
- 1];
458 if (IS_ERR_OR_NULL(clk_data
->hws
[mcd
->id
]))
461 clk_hw_unregister_divider(clk_data
->hws
[mcd
->id
]);
462 clk_data
->hws
[mcd
->id
] = ERR_PTR(-ENOENT
);
465 EXPORT_SYMBOL_GPL(mtk_clk_unregister_dividers
);
467 static int __mtk_clk_simple_probe(struct platform_device
*pdev
,
468 struct device_node
*node
)
470 const struct platform_device_id
*id
;
471 const struct mtk_clk_desc
*mcd
;
472 struct clk_hw_onecell_data
*clk_data
;
473 void __iomem
*base
= NULL
;
476 mcd
= device_get_match_data(&pdev
->dev
);
478 /* Clock driver wasn't registered from devicetree */
479 id
= platform_get_device_id(pdev
);
481 mcd
= (const struct mtk_clk_desc
*)id
->driver_data
;
487 /* Composite and divider clocks needs us to pass iomem pointer */
488 if (mcd
->composite_clks
|| mcd
->divider_clks
) {
490 base
= devm_platform_ioremap_resource(pdev
, 0);
492 base
= of_iomap(node
, 0);
494 if (IS_ERR_OR_NULL(base
))
495 return IS_ERR(base
) ? PTR_ERR(base
) : -ENOMEM
;
499 if (mcd
->need_runtime_pm
) {
500 devm_pm_runtime_enable(&pdev
->dev
);
502 * Do a pm_runtime_resume_and_get() to workaround a possible
503 * deadlock between clk_register() and the genpd framework.
505 r
= pm_runtime_resume_and_get(&pdev
->dev
);
510 /* Calculate how many clk_hw_onecell_data entries to allocate */
511 num_clks
= mcd
->num_clks
+ mcd
->num_composite_clks
;
512 num_clks
+= mcd
->num_fixed_clks
+ mcd
->num_factor_clks
;
513 num_clks
+= mcd
->num_mux_clks
+ mcd
->num_divider_clks
;
515 clk_data
= mtk_alloc_clk_data(num_clks
);
521 if (mcd
->fixed_clks
) {
522 r
= mtk_clk_register_fixed_clks(mcd
->fixed_clks
,
523 mcd
->num_fixed_clks
, clk_data
);
528 if (mcd
->factor_clks
) {
529 r
= mtk_clk_register_factors(mcd
->factor_clks
,
530 mcd
->num_factor_clks
, clk_data
);
532 goto unregister_fixed_clks
;
536 r
= mtk_clk_register_muxes(&pdev
->dev
, mcd
->mux_clks
,
537 mcd
->num_mux_clks
, node
,
538 mcd
->clk_lock
, clk_data
);
540 goto unregister_factors
;
543 if (mcd
->composite_clks
) {
544 /* We don't check composite_lock because it's optional */
545 r
= mtk_clk_register_composites(&pdev
->dev
,
547 mcd
->num_composite_clks
,
548 base
, mcd
->clk_lock
, clk_data
);
550 goto unregister_muxes
;
553 if (mcd
->divider_clks
) {
554 r
= mtk_clk_register_dividers(&pdev
->dev
,
556 mcd
->num_divider_clks
,
557 base
, mcd
->clk_lock
, clk_data
);
559 goto unregister_composites
;
563 r
= mtk_clk_register_gates(&pdev
->dev
, node
, mcd
->clks
,
564 mcd
->num_clks
, clk_data
);
566 goto unregister_dividers
;
569 if (mcd
->clk_notifier_func
) {
570 struct clk
*mfg_mux
= clk_data
->hws
[mcd
->mfg_clk_idx
]->clk
;
572 r
= mcd
->clk_notifier_func(&pdev
->dev
, mfg_mux
);
574 goto unregister_clks
;
577 r
= of_clk_add_hw_provider(node
, of_clk_hw_onecell_get
, clk_data
);
579 goto unregister_clks
;
581 platform_set_drvdata(pdev
, clk_data
);
584 r
= mtk_register_reset_controller_with_dev(&pdev
->dev
,
587 goto unregister_clks
;
590 if (mcd
->need_runtime_pm
)
591 pm_runtime_put(&pdev
->dev
);
597 mtk_clk_unregister_gates(mcd
->clks
, mcd
->num_clks
, clk_data
);
599 if (mcd
->divider_clks
)
600 mtk_clk_unregister_dividers(mcd
->divider_clks
,
601 mcd
->num_divider_clks
, clk_data
);
602 unregister_composites
:
603 if (mcd
->composite_clks
)
604 mtk_clk_unregister_composites(mcd
->composite_clks
,
605 mcd
->num_composite_clks
, clk_data
);
608 mtk_clk_unregister_muxes(mcd
->mux_clks
,
609 mcd
->num_mux_clks
, clk_data
);
611 if (mcd
->factor_clks
)
612 mtk_clk_unregister_factors(mcd
->factor_clks
,
613 mcd
->num_factor_clks
, clk_data
);
614 unregister_fixed_clks
:
616 mtk_clk_unregister_fixed_clks(mcd
->fixed_clks
,
617 mcd
->num_fixed_clks
, clk_data
);
619 mtk_free_clk_data(clk_data
);
621 if (mcd
->shared_io
&& base
)
624 if (mcd
->need_runtime_pm
)
625 pm_runtime_put(&pdev
->dev
);
629 static void __mtk_clk_simple_remove(struct platform_device
*pdev
,
630 struct device_node
*node
)
632 struct clk_hw_onecell_data
*clk_data
= platform_get_drvdata(pdev
);
633 const struct mtk_clk_desc
*mcd
= device_get_match_data(&pdev
->dev
);
635 of_clk_del_provider(node
);
637 mtk_clk_unregister_gates(mcd
->clks
, mcd
->num_clks
, clk_data
);
638 if (mcd
->divider_clks
)
639 mtk_clk_unregister_dividers(mcd
->divider_clks
,
640 mcd
->num_divider_clks
, clk_data
);
641 if (mcd
->composite_clks
)
642 mtk_clk_unregister_composites(mcd
->composite_clks
,
643 mcd
->num_composite_clks
, clk_data
);
645 mtk_clk_unregister_muxes(mcd
->mux_clks
,
646 mcd
->num_mux_clks
, clk_data
);
647 if (mcd
->factor_clks
)
648 mtk_clk_unregister_factors(mcd
->factor_clks
,
649 mcd
->num_factor_clks
, clk_data
);
651 mtk_clk_unregister_fixed_clks(mcd
->fixed_clks
,
652 mcd
->num_fixed_clks
, clk_data
);
653 mtk_free_clk_data(clk_data
);
656 int mtk_clk_pdev_probe(struct platform_device
*pdev
)
658 struct device
*dev
= &pdev
->dev
;
659 struct device_node
*node
= dev
->parent
->of_node
;
661 return __mtk_clk_simple_probe(pdev
, node
);
663 EXPORT_SYMBOL_GPL(mtk_clk_pdev_probe
);
665 int mtk_clk_simple_probe(struct platform_device
*pdev
)
667 struct device_node
*node
= pdev
->dev
.of_node
;
669 return __mtk_clk_simple_probe(pdev
, node
);
671 EXPORT_SYMBOL_GPL(mtk_clk_simple_probe
);
673 void mtk_clk_pdev_remove(struct platform_device
*pdev
)
675 struct device
*dev
= &pdev
->dev
;
676 struct device_node
*node
= dev
->parent
->of_node
;
678 __mtk_clk_simple_remove(pdev
, node
);
680 EXPORT_SYMBOL_GPL(mtk_clk_pdev_remove
);
682 void mtk_clk_simple_remove(struct platform_device
*pdev
)
684 __mtk_clk_simple_remove(pdev
, pdev
->dev
.of_node
);
686 EXPORT_SYMBOL_GPL(mtk_clk_simple_remove
);
688 MODULE_LICENSE("GPL");