diff options
-rw-r--r-- | drivers/clk/clk-bulk.c | 80 | ||||
-rw-r--r-- | drivers/clk/clk-devres.c | 24 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-dfll.c | 8 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra210.c | 7 | ||||
-rw-r--r-- | include/linux/clk.h | 65 |
5 files changed, 178 insertions, 6 deletions
diff --git a/drivers/clk/clk-bulk.c b/drivers/clk/clk-bulk.c index 6904ed6da504..6a7118d4250a 100644 --- a/drivers/clk/clk-bulk.c +++ b/drivers/clk/clk-bulk.c | |||
@@ -17,8 +17,65 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
20 | #include <linux/clk-provider.h> | ||
20 | #include <linux/device.h> | 21 | #include <linux/device.h> |
21 | #include <linux/export.h> | 22 | #include <linux/export.h> |
23 | #include <linux/of.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks, | ||
27 | struct clk_bulk_data *clks) | ||
28 | { | ||
29 | int ret; | ||
30 | int i; | ||
31 | |||
32 | for (i = 0; i < num_clks; i++) | ||
33 | clks[i].clk = NULL; | ||
34 | |||
35 | for (i = 0; i < num_clks; i++) { | ||
36 | clks[i].clk = of_clk_get(np, i); | ||
37 | if (IS_ERR(clks[i].clk)) { | ||
38 | ret = PTR_ERR(clks[i].clk); | ||
39 | pr_err("%pOF: Failed to get clk index: %d ret: %d\n", | ||
40 | np, i, ret); | ||
41 | clks[i].clk = NULL; | ||
42 | goto err; | ||
43 | } | ||
44 | } | ||
45 | |||
46 | return 0; | ||
47 | |||
48 | err: | ||
49 | clk_bulk_put(i, clks); | ||
50 | |||
51 | return ret; | ||
52 | } | ||
53 | |||
54 | static int __must_check of_clk_bulk_get_all(struct device_node *np, | ||
55 | struct clk_bulk_data **clks) | ||
56 | { | ||
57 | struct clk_bulk_data *clk_bulk; | ||
58 | int num_clks; | ||
59 | int ret; | ||
60 | |||
61 | num_clks = of_clk_get_parent_count(np); | ||
62 | if (!num_clks) | ||
63 | return 0; | ||
64 | |||
65 | clk_bulk = kmalloc_array(num_clks, sizeof(*clk_bulk), GFP_KERNEL); | ||
66 | if (!clk_bulk) | ||
67 | return -ENOMEM; | ||
68 | |||
69 | ret = of_clk_bulk_get(np, num_clks, clk_bulk); | ||
70 | if (ret) { | ||
71 | kfree(clk_bulk); | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | *clks = clk_bulk; | ||
76 | |||
77 | return num_clks; | ||
78 | } | ||
22 | 79 | ||
23 | void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) | 80 | void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) |
24 | { | 81 | { |
@@ -59,6 +116,29 @@ err: | |||
59 | } | 116 | } |
60 | EXPORT_SYMBOL(clk_bulk_get); | 117 | EXPORT_SYMBOL(clk_bulk_get); |
61 | 118 | ||
119 | void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) | ||
120 | { | ||
121 | if (IS_ERR_OR_NULL(clks)) | ||
122 | return; | ||
123 | |||
124 | clk_bulk_put(num_clks, clks); | ||
125 | |||
126 | kfree(clks); | ||
127 | } | ||
128 | EXPORT_SYMBOL(clk_bulk_put_all); | ||
129 | |||
130 | int __must_check clk_bulk_get_all(struct device *dev, | ||
131 | struct clk_bulk_data **clks) | ||
132 | { | ||
133 | struct device_node *np = dev_of_node(dev); | ||
134 | |||
135 | if (!np) | ||
136 | return 0; | ||
137 | |||
138 | return of_clk_bulk_get_all(np, clks); | ||
139 | } | ||
140 | EXPORT_SYMBOL(clk_bulk_get_all); | ||
141 | |||
62 | #ifdef CONFIG_HAVE_CLK_PREPARE | 142 | #ifdef CONFIG_HAVE_CLK_PREPARE |
63 | 143 | ||
64 | /** | 144 | /** |
diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c index d854e26a8ddb..12c87457eca1 100644 --- a/drivers/clk/clk-devres.c +++ b/drivers/clk/clk-devres.c | |||
@@ -70,6 +70,30 @@ int __must_check devm_clk_bulk_get(struct device *dev, int num_clks, | |||
70 | } | 70 | } |
71 | EXPORT_SYMBOL_GPL(devm_clk_bulk_get); | 71 | EXPORT_SYMBOL_GPL(devm_clk_bulk_get); |
72 | 72 | ||
73 | int __must_check devm_clk_bulk_get_all(struct device *dev, | ||
74 | struct clk_bulk_data **clks) | ||
75 | { | ||
76 | struct clk_bulk_devres *devres; | ||
77 | int ret; | ||
78 | |||
79 | devres = devres_alloc(devm_clk_bulk_release, | ||
80 | sizeof(*devres), GFP_KERNEL); | ||
81 | if (!devres) | ||
82 | return -ENOMEM; | ||
83 | |||
84 | ret = clk_bulk_get_all(dev, &devres->clks); | ||
85 | if (ret > 0) { | ||
86 | *clks = devres->clks; | ||
87 | devres->num_clks = ret; | ||
88 | devres_add(dev, devres); | ||
89 | } else { | ||
90 | devres_free(devres); | ||
91 | } | ||
92 | |||
93 | return ret; | ||
94 | } | ||
95 | EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all); | ||
96 | |||
73 | static int devm_clk_match(struct device *dev, void *res, void *data) | 97 | static int devm_clk_match(struct device *dev, void *res, void *data) |
74 | { | 98 | { |
75 | struct clk **c = res; | 99 | struct clk **c = res; |
diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c index 48ee43734e05..ebb0e1b6bf01 100644 --- a/drivers/clk/tegra/clk-dfll.c +++ b/drivers/clk/tegra/clk-dfll.c | |||
@@ -1609,8 +1609,12 @@ int tegra_dfll_register(struct platform_device *pdev, | |||
1609 | 1609 | ||
1610 | td->vdd_reg = devm_regulator_get(td->dev, "vdd-cpu"); | 1610 | td->vdd_reg = devm_regulator_get(td->dev, "vdd-cpu"); |
1611 | if (IS_ERR(td->vdd_reg)) { | 1611 | if (IS_ERR(td->vdd_reg)) { |
1612 | dev_err(td->dev, "couldn't get vdd_cpu regulator\n"); | 1612 | ret = PTR_ERR(td->vdd_reg); |
1613 | return PTR_ERR(td->vdd_reg); | 1613 | if (ret != -EPROBE_DEFER) |
1614 | dev_err(td->dev, "couldn't get vdd_cpu regulator: %d\n", | ||
1615 | ret); | ||
1616 | |||
1617 | return ret; | ||
1614 | } | 1618 | } |
1615 | 1619 | ||
1616 | td->dvco_rst = devm_reset_control_get(td->dev, "dvco"); | 1620 | td->dvco_rst = devm_reset_control_get(td->dev, "dvco"); |
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 9eb1cb14fce1..88f1943bd2b5 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <dt-bindings/clock/tegra210-car.h> | 27 | #include <dt-bindings/clock/tegra210-car.h> |
28 | #include <dt-bindings/reset/tegra210-car.h> | 28 | #include <dt-bindings/reset/tegra210-car.h> |
29 | #include <linux/iopoll.h> | 29 | #include <linux/iopoll.h> |
30 | #include <linux/sizes.h> | ||
30 | #include <soc/tegra/pmc.h> | 31 | #include <soc/tegra/pmc.h> |
31 | 32 | ||
32 | #include "clk.h" | 33 | #include "clk.h" |
@@ -2603,7 +2604,7 @@ static struct tegra210_domain_mbist_war tegra210_pg_mbist_war[] = { | |||
2603 | [TEGRA_POWERGATE_MPE] = { | 2604 | [TEGRA_POWERGATE_MPE] = { |
2604 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | 2605 | .handle_lvl2_ovr = tegra210_generic_mbist_war, |
2605 | .lvl2_offset = LVL2_CLK_GATE_OVRE, | 2606 | .lvl2_offset = LVL2_CLK_GATE_OVRE, |
2606 | .lvl2_mask = BIT(2), | 2607 | .lvl2_mask = BIT(29), |
2607 | }, | 2608 | }, |
2608 | [TEGRA_POWERGATE_SOR] = { | 2609 | [TEGRA_POWERGATE_SOR] = { |
2609 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | 2610 | .handle_lvl2_ovr = tegra210_generic_mbist_war, |
@@ -2654,14 +2655,14 @@ static struct tegra210_domain_mbist_war tegra210_pg_mbist_war[] = { | |||
2654 | .num_clks = ARRAY_SIZE(nvdec_slcg_clkids), | 2655 | .num_clks = ARRAY_SIZE(nvdec_slcg_clkids), |
2655 | .clk_init_data = nvdec_slcg_clkids, | 2656 | .clk_init_data = nvdec_slcg_clkids, |
2656 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | 2657 | .handle_lvl2_ovr = tegra210_generic_mbist_war, |
2657 | .lvl2_offset = LVL2_CLK_GATE_OVRC, | 2658 | .lvl2_offset = LVL2_CLK_GATE_OVRE, |
2658 | .lvl2_mask = BIT(9) | BIT(31), | 2659 | .lvl2_mask = BIT(9) | BIT(31), |
2659 | }, | 2660 | }, |
2660 | [TEGRA_POWERGATE_NVJPG] = { | 2661 | [TEGRA_POWERGATE_NVJPG] = { |
2661 | .num_clks = ARRAY_SIZE(nvjpg_slcg_clkids), | 2662 | .num_clks = ARRAY_SIZE(nvjpg_slcg_clkids), |
2662 | .clk_init_data = nvjpg_slcg_clkids, | 2663 | .clk_init_data = nvjpg_slcg_clkids, |
2663 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | 2664 | .handle_lvl2_ovr = tegra210_generic_mbist_war, |
2664 | .lvl2_offset = LVL2_CLK_GATE_OVRC, | 2665 | .lvl2_offset = LVL2_CLK_GATE_OVRE, |
2665 | .lvl2_mask = BIT(9) | BIT(31), | 2666 | .lvl2_mask = BIT(9) | BIT(31), |
2666 | }, | 2667 | }, |
2667 | [TEGRA_POWERGATE_AUD] = { | 2668 | [TEGRA_POWERGATE_AUD] = { |
diff --git a/include/linux/clk.h b/include/linux/clk.h index 7da754d79f9d..a7773b5c0b9f 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h | |||
@@ -312,7 +312,26 @@ struct clk *clk_get(struct device *dev, const char *id); | |||
312 | */ | 312 | */ |
313 | int __must_check clk_bulk_get(struct device *dev, int num_clks, | 313 | int __must_check clk_bulk_get(struct device *dev, int num_clks, |
314 | struct clk_bulk_data *clks); | 314 | struct clk_bulk_data *clks); |
315 | 315 | /** | |
316 | * clk_bulk_get_all - lookup and obtain all available references to clock | ||
317 | * producer. | ||
318 | * @dev: device for clock "consumer" | ||
319 | * @clks: pointer to the clk_bulk_data table of consumer | ||
320 | * | ||
321 | * This helper function allows drivers to get all clk consumers in one | ||
322 | * operation. If any of the clk cannot be acquired then any clks | ||
323 | * that were obtained will be freed before returning to the caller. | ||
324 | * | ||
325 | * Returns a positive value for the number of clocks obtained while the | ||
326 | * clock references are stored in the clk_bulk_data table in @clks field. | ||
327 | * Returns 0 if there're none and a negative value if something failed. | ||
328 | * | ||
329 | * Drivers must assume that the clock source is not enabled. | ||
330 | * | ||
331 | * clk_bulk_get should not be called from within interrupt context. | ||
332 | */ | ||
333 | int __must_check clk_bulk_get_all(struct device *dev, | ||
334 | struct clk_bulk_data **clks); | ||
316 | /** | 335 | /** |
317 | * devm_clk_bulk_get - managed get multiple clk consumers | 336 | * devm_clk_bulk_get - managed get multiple clk consumers |
318 | * @dev: device for clock "consumer" | 337 | * @dev: device for clock "consumer" |
@@ -327,6 +346,22 @@ int __must_check clk_bulk_get(struct device *dev, int num_clks, | |||
327 | */ | 346 | */ |
328 | int __must_check devm_clk_bulk_get(struct device *dev, int num_clks, | 347 | int __must_check devm_clk_bulk_get(struct device *dev, int num_clks, |
329 | struct clk_bulk_data *clks); | 348 | struct clk_bulk_data *clks); |
349 | /** | ||
350 | * devm_clk_bulk_get_all - managed get multiple clk consumers | ||
351 | * @dev: device for clock "consumer" | ||
352 | * @clks: pointer to the clk_bulk_data table of consumer | ||
353 | * | ||
354 | * Returns a positive value for the number of clocks obtained while the | ||
355 | * clock references are stored in the clk_bulk_data table in @clks field. | ||
356 | * Returns 0 if there're none and a negative value if something failed. | ||
357 | * | ||
358 | * This helper function allows drivers to get several clk | ||
359 | * consumers in one operation with management, the clks will | ||
360 | * automatically be freed when the device is unbound. | ||
361 | */ | ||
362 | |||
363 | int __must_check devm_clk_bulk_get_all(struct device *dev, | ||
364 | struct clk_bulk_data **clks); | ||
330 | 365 | ||
331 | /** | 366 | /** |
332 | * devm_clk_get - lookup and obtain a managed reference to a clock producer. | 367 | * devm_clk_get - lookup and obtain a managed reference to a clock producer. |
@@ -488,6 +523,19 @@ void clk_put(struct clk *clk); | |||
488 | void clk_bulk_put(int num_clks, struct clk_bulk_data *clks); | 523 | void clk_bulk_put(int num_clks, struct clk_bulk_data *clks); |
489 | 524 | ||
490 | /** | 525 | /** |
526 | * clk_bulk_put_all - "free" all the clock source | ||
527 | * @num_clks: the number of clk_bulk_data | ||
528 | * @clks: the clk_bulk_data table of consumer | ||
529 | * | ||
530 | * Note: drivers must ensure that all clk_bulk_enable calls made on this | ||
531 | * clock source are balanced by clk_bulk_disable calls prior to calling | ||
532 | * this function. | ||
533 | * | ||
534 | * clk_bulk_put_all should not be called from within interrupt context. | ||
535 | */ | ||
536 | void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks); | ||
537 | |||
538 | /** | ||
491 | * devm_clk_put - "free" a managed clock source | 539 | * devm_clk_put - "free" a managed clock source |
492 | * @dev: device used to acquire the clock | 540 | * @dev: device used to acquire the clock |
493 | * @clk: clock source acquired with devm_clk_get() | 541 | * @clk: clock source acquired with devm_clk_get() |
@@ -659,6 +707,12 @@ static inline int __must_check clk_bulk_get(struct device *dev, int num_clks, | |||
659 | return 0; | 707 | return 0; |
660 | } | 708 | } |
661 | 709 | ||
710 | static inline int __must_check clk_bulk_get_all(struct device *dev, | ||
711 | struct clk_bulk_data **clks) | ||
712 | { | ||
713 | return 0; | ||
714 | } | ||
715 | |||
662 | static inline struct clk *devm_clk_get(struct device *dev, const char *id) | 716 | static inline struct clk *devm_clk_get(struct device *dev, const char *id) |
663 | { | 717 | { |
664 | return NULL; | 718 | return NULL; |
@@ -670,6 +724,13 @@ static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clk | |||
670 | return 0; | 724 | return 0; |
671 | } | 725 | } |
672 | 726 | ||
727 | static inline int __must_check devm_clk_bulk_get_all(struct device *dev, | ||
728 | struct clk_bulk_data **clks) | ||
729 | { | ||
730 | |||
731 | return 0; | ||
732 | } | ||
733 | |||
673 | static inline struct clk *devm_get_clk_from_child(struct device *dev, | 734 | static inline struct clk *devm_get_clk_from_child(struct device *dev, |
674 | struct device_node *np, const char *con_id) | 735 | struct device_node *np, const char *con_id) |
675 | { | 736 | { |
@@ -680,6 +741,8 @@ static inline void clk_put(struct clk *clk) {} | |||
680 | 741 | ||
681 | static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {} | 742 | static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {} |
682 | 743 | ||
744 | static inline void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) {} | ||
745 | |||
683 | static inline void devm_clk_put(struct device *dev, struct clk *clk) {} | 746 | static inline void devm_clk_put(struct device *dev, struct clk *clk) {} |
684 | 747 | ||
685 | 748 | ||