diff options
author | Andrey Smirnov <andrew.smirnov@gmail.com> | 2019-02-19 23:29:26 -0800 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-02-22 08:11:18 +0100 |
commit | 7817ca90abcc7807152cb4339065cfd8db565d68 (patch) | |
tree | 459b28aadba1b556d968298d91d41c17fffcdfe9 /drivers/clk | |
parent | 2916bfffbdee5f1ba1a74d65b548635c4fe5e174 (diff) | |
download | barebox-7817ca90abcc7807152cb4339065cfd8db565d68.tar.gz barebox-7817ca90abcc7807152cb4339065cfd8db565d68.tar.xz |
clk: Import a subset of clk_bulk API from Linux
Import a subset of clk_bulk API from Linux to support porting kernel
code that uses it.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/Makefile | 3 | ||||
-rw-r--r-- | drivers/clk/clk-bulk.c | 102 |
2 files changed, 104 insertions, 1 deletions
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index cd4026c944..34c44fff9b 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -1,7 +1,8 @@ obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed.o clk-divider.o clk-fixed-factor.o \ clk-mux.o clk-gate.o clk-composite.o \ clk-fractional-divider.o clk-conf.o \ - clk-gate-shared.o clk-gpio.o + clk-gate-shared.o clk-gpio.o \ + clk-bulk.o obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o obj-$(CONFIG_ARCH_MVEBU) += mvebu/ diff --git a/drivers/clk/clk-bulk.c b/drivers/clk/clk-bulk.c new file mode 100644 index 0000000000..ddbe32f9c2 --- /dev/null +++ b/drivers/clk/clk-bulk.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2017 NXP + * + * Dong Aisheng <aisheng.dong@nxp.com> + */ + +#include <common.h> +#include <errno.h> +#include <malloc.h> +#include <stringlist.h> +#include <complete.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/clk/clk-conf.h> + +void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) +{ + while (--num_clks >= 0) { + clk_put(clks[num_clks].clk); + clks[num_clks].clk = NULL; + } +} +EXPORT_SYMBOL_GPL(clk_bulk_put); + +int __must_check clk_bulk_get(struct device_d *dev, int num_clks, + struct clk_bulk_data *clks) +{ + int ret; + int i; + + for (i = 0; i < num_clks; i++) + clks[i].clk = NULL; + + for (i = 0; i < num_clks; i++) { + clks[i].clk = clk_get(dev, clks[i].id); + if (IS_ERR(clks[i].clk)) { + ret = PTR_ERR(clks[i].clk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get clk '%s': %d\n", + clks[i].id, ret); + clks[i].clk = NULL; + goto err; + } + } + + return 0; + +err: + clk_bulk_put(i, clks); + + return ret; +} +EXPORT_SYMBOL(clk_bulk_get); + +/** + * clk_bulk_disable - gate a set of clocks + * @num_clks: the number of clk_bulk_data + * @clks: the clk_bulk_data table being gated + * + * clk_bulk_disable must not sleep, which differentiates it from + * clk_bulk_unprepare. clk_bulk_disable must be called before + * clk_bulk_unprepare. + */ +void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks) +{ + + while (--num_clks >= 0) + clk_disable(clks[num_clks].clk); +} +EXPORT_SYMBOL_GPL(clk_bulk_disable); + +/** + * clk_bulk_enable - ungate a set of clocks + * @num_clks: the number of clk_bulk_data + * @clks: the clk_bulk_data table being ungated + * + * clk_bulk_enable must not sleep + * Returns 0 on success, -EERROR otherwise. + */ +int __must_check clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks) +{ + int ret; + int i; + + for (i = 0; i < num_clks; i++) { + ret = clk_enable(clks[i].clk); + if (ret) { + pr_err("Failed to enable clk '%s': %d\n", + clks[i].id, ret); + goto err; + } + } + + return 0; + +err: + clk_bulk_disable(i, clks); + + return ret; +} +EXPORT_SYMBOL_GPL(clk_bulk_enable); |