summaryrefslogtreecommitdiffstats
path: root/drivers/clk/clk-bulk.c
diff options
context:
space:
mode:
authorDong Aisheng <aisheng.dong@nxp.com>2018-08-31 12:45:54 +0800
committerStephen Boyd <sboyd@kernel.org>2018-10-16 15:42:48 -0700
commit616e45df7c4aa71279c07cc803a1d51f43f89f37 (patch)
tree4bd2daac3b7fcc1ec51419d6ad0e78b586d1701a /drivers/clk/clk-bulk.c
parentcfdc0411cf01aff7bb44a4edcbaa578ad363ab77 (diff)
downloadlinux-616e45df7c4aa71279c07cc803a1d51f43f89f37.tar.bz2
clk: add new APIs to operate on all available clocks
This patch introduces of_clk_bulk_get_all and clk_bulk_x_all APIs to users who just want to handle all available clocks from device tree without need to know the detailed clock information likes clock numbers and names. This is useful in writing some generic drivers to handle clock part. Cc: Stephen Boyd <sboyd@codeaurora.org> Cc: Masahiro Yamada <yamada.masahiro@socionext.com> Tested-by: Thor Thayer <thor.thayer@linux.intel.com> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Diffstat (limited to 'drivers/clk/clk-bulk.c')
-rw-r--r--drivers/clk/clk-bulk.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/clk/clk-bulk.c b/drivers/clk/clk-bulk.c
index 4460ac52199f..6a7118d4250a 100644
--- a/drivers/clk/clk-bulk.c
+++ b/drivers/clk/clk-bulk.c
@@ -17,9 +17,11 @@
*/
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/export.h>
#include <linux/of.h>
+#include <linux/slab.h>
static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks,
struct clk_bulk_data *clks)
@@ -49,6 +51,32 @@ err:
return ret;
}
+static int __must_check of_clk_bulk_get_all(struct device_node *np,
+ struct clk_bulk_data **clks)
+{
+ struct clk_bulk_data *clk_bulk;
+ int num_clks;
+ int ret;
+
+ num_clks = of_clk_get_parent_count(np);
+ if (!num_clks)
+ return 0;
+
+ clk_bulk = kmalloc_array(num_clks, sizeof(*clk_bulk), GFP_KERNEL);
+ if (!clk_bulk)
+ return -ENOMEM;
+
+ ret = of_clk_bulk_get(np, num_clks, clk_bulk);
+ if (ret) {
+ kfree(clk_bulk);
+ return ret;
+ }
+
+ *clks = clk_bulk;
+
+ return num_clks;
+}
+
void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
{
while (--num_clks >= 0) {
@@ -88,6 +116,29 @@ err:
}
EXPORT_SYMBOL(clk_bulk_get);
+void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks)
+{
+ if (IS_ERR_OR_NULL(clks))
+ return;
+
+ clk_bulk_put(num_clks, clks);
+
+ kfree(clks);
+}
+EXPORT_SYMBOL(clk_bulk_put_all);
+
+int __must_check clk_bulk_get_all(struct device *dev,
+ struct clk_bulk_data **clks)
+{
+ struct device_node *np = dev_of_node(dev);
+
+ if (!np)
+ return 0;
+
+ return of_clk_bulk_get_all(np, clks);
+}
+EXPORT_SYMBOL(clk_bulk_get_all);
+
#ifdef CONFIG_HAVE_CLK_PREPARE
/**