aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/clk-bulk.c80
-rw-r--r--drivers/clk/clk-devres.c24
-rw-r--r--drivers/clk/tegra/clk-dfll.c8
-rw-r--r--drivers/clk/tegra/clk-tegra210.c7
-rw-r--r--include/linux/clk.h65
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
26static 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
48err:
49 clk_bulk_put(i, clks);
50
51 return ret;
52}
53
54static 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
23void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) 80void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
24{ 81{
@@ -59,6 +116,29 @@ err:
59} 116}
60EXPORT_SYMBOL(clk_bulk_get); 117EXPORT_SYMBOL(clk_bulk_get);
61 118
119void 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}
128EXPORT_SYMBOL(clk_bulk_put_all);
129
130int __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}
140EXPORT_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}
71EXPORT_SYMBOL_GPL(devm_clk_bulk_get); 71EXPORT_SYMBOL_GPL(devm_clk_bulk_get);
72 72
73int __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}
95EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all);
96
73static int devm_clk_match(struct device *dev, void *res, void *data) 97static 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 */
313int __must_check clk_bulk_get(struct device *dev, int num_clks, 313int __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 */
333int __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 */
328int __must_check devm_clk_bulk_get(struct device *dev, int num_clks, 347int __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
363int __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);
488void clk_bulk_put(int num_clks, struct clk_bulk_data *clks); 523void 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 */
536void 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
710static inline int __must_check clk_bulk_get_all(struct device *dev,
711 struct clk_bulk_data **clks)
712{
713 return 0;
714}
715
662static inline struct clk *devm_clk_get(struct device *dev, const char *id) 716static 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
727static 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
673static inline struct clk *devm_get_clk_from_child(struct device *dev, 734static 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
681static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {} 742static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {}
682 743
744static inline void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) {}
745
683static inline void devm_clk_put(struct device *dev, struct clk *clk) {} 746static inline void devm_clk_put(struct device *dev, struct clk *clk) {}
684 747
685 748