Home Home > GIT Browse > SLE12-SP4
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMian Yousaf Kaukab <yousaf.kaukab@suse.com>2019-08-08 12:22:02 +0200
committerMian Yousaf Kaukab <yousaf.kaukab@suse.com>2019-08-08 12:22:10 +0200
commitc57dfa50685f3fc3485d640e9d4d4321d6931578 (patch)
treeff445123c7c38ee9d897de9b396edeb99ad3909f
parent93f1b1edc2ac2cbf1323032719dea71862d97710 (diff)
clk: add clk_bulk_get accessories (bsc#1144813).
-rw-r--r--patches.drivers/0001-clk-add-clk_bulk_get-accessories.patch415
-rw-r--r--series.conf1
2 files changed, 416 insertions, 0 deletions
diff --git a/patches.drivers/0001-clk-add-clk_bulk_get-accessories.patch b/patches.drivers/0001-clk-add-clk_bulk_get-accessories.patch
new file mode 100644
index 0000000000..eee51d7bba
--- /dev/null
+++ b/patches.drivers/0001-clk-add-clk_bulk_get-accessories.patch
@@ -0,0 +1,415 @@
+From: Dong Aisheng <aisheng.dong@nxp.com>
+Date: Fri, 19 May 2017 21:49:04 +0800
+Subject: clk: add clk_bulk_get accessories
+
+Git-commit: 266e4e9d9150e98141b85c7400f8aa3cd57a7f9b
+Patch-mainline: v4.13-rc1
+References: bsc#1144813
+
+These helper function allows drivers to get several clk consumers in
+one operation. If any of the clk cannot be acquired then any clks
+that were got will be put before returning to the caller.
+
+This can relieve the driver owners' life who needs to handle many clocks,
+as well as each clock error reporting.
+
+Cc: Michael Turquette <mturquette@baylibre.com>
+Cc: Stephen Boyd <sboyd@codeaurora.org>
+Cc: Russell King <linux@arm.linux.org.uk>
+Cc: Geert Uytterhoeven <geert@linux-m68k.org>
+Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
+Cc: Viresh Kumar <viresh.kumar@linaro.org>
+Cc: Mark Brown <broonie@kernel.org>
+Cc: Shawn Guo <shawnguo@kernel.org>
+Cc: Fabio Estevam <fabio.estevam@nxp.com>
+Cc: Sascha Hauer <kernel@pengutronix.de>
+Cc: Anson Huang <anson.huang@nxp.com>
+Cc: Robin Gong <yibin.gong@nxp.com>
+Cc: Bai Ping <ping.bai@nxp.com>
+Cc: Leonard Crestez <leonard.crestez@nxp.com>
+Cc: Octavian Purdila <octavian.purdila@nxp.com>
+Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@suse.com>
+---
+ drivers/clk/Makefile | 2 +-
+ drivers/clk/clk-bulk.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/clk.h | 111 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 269 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/clk/clk-bulk.c
+
+diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
+index c19983afcb81..ed1e99f19ec3 100644
+--- a/drivers/clk/Makefile
++++ b/drivers/clk/Makefile
+@@ -1,5 +1,5 @@
+ # common clock types
+-obj-$(CONFIG_HAVE_CLK) += clk-devres.o
++obj-$(CONFIG_HAVE_CLK) += clk-devres.o clk-bulk.o
+ obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o
+ obj-$(CONFIG_COMMON_CLK) += clk.o
+ obj-$(CONFIG_COMMON_CLK) += clk-divider.o
+diff --git a/drivers/clk/clk-bulk.c b/drivers/clk/clk-bulk.c
+new file mode 100644
+index 000000000000..c834f5abfc49
+--- /dev/null
++++ b/drivers/clk/clk-bulk.c
+@@ -0,0 +1,157 @@
++/*
++ * Copyright 2017 NXP
++ *
++ * Dong Aisheng <aisheng.dong@nxp.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <linux/clk.h>
++#include <linux/device.h>
++#include <linux/export.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 *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);
++ 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);
++
++#ifdef CONFIG_HAVE_CLK_PREPARE
++
++/**
++ * clk_bulk_unprepare - undo preparation of a set of clock sources
++ * @num_clks: the number of clk_bulk_data
++ * @clks: the clk_bulk_data table being unprepared
++ *
++ * clk_bulk_unprepare may sleep, which differentiates it from clk_bulk_disable.
++ * Returns 0 on success, -EERROR otherwise.
++ */
++void clk_bulk_unprepare(int num_clks, const struct clk_bulk_data *clks)
++{
++ while (--num_clks >= 0)
++ clk_unprepare(clks[num_clks].clk);
++}
++EXPORT_SYMBOL_GPL(clk_bulk_unprepare);
++
++/**
++ * clk_bulk_prepare - prepare a set of clocks
++ * @num_clks: the number of clk_bulk_data
++ * @clks: the clk_bulk_data table being prepared
++ *
++ * clk_bulk_prepare may sleep, which differentiates it from clk_bulk_enable.
++ * Returns 0 on success, -EERROR otherwise.
++ */
++int __must_check clk_bulk_prepare(int num_clks,
++ const struct clk_bulk_data *clks)
++{
++ int ret;
++ int i;
++
++ for (i = 0; i < num_clks; i++) {
++ ret = clk_prepare(clks[i].clk);
++ if (ret) {
++ pr_err("Failed to prepare clk '%s': %d\n",
++ clks[i].id, ret);
++ goto err;
++ }
++ }
++
++ return 0;
++
++err:
++ clk_bulk_unprepare(i, clks);
++
++ return ret;
++}
++
++#endif /* CONFIG_HAVE_CLK_PREPARE */
++
++/**
++ * 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);
+diff --git a/include/linux/clk.h b/include/linux/clk.h
+index 024cd07870d0..72b0cfce9165 100644
+--- a/include/linux/clk.h
++++ b/include/linux/clk.h
+@@ -77,6 +77,21 @@ struct clk_notifier_data {
+ unsigned long new_rate;
+ };
+
++/**
++ * struct clk_bulk_data - Data used for bulk clk operations.
++ *
++ * @id: clock consumer ID
++ * @clk: struct clk * to store the associated clock
++ *
++ * The CLK APIs provide a series of clk_bulk_() API calls as
++ * a convenience to consumers which require multiple clks. This
++ * structure is used to manage data for these calls.
++ */
++struct clk_bulk_data {
++ const char *id;
++ struct clk *clk;
++};
++
+ #ifdef CONFIG_COMMON_CLK
+
+ /**
+@@ -185,12 +200,20 @@ static inline bool clk_is_match(const struct clk *p, const struct clk *q)
+ */
+ #ifdef CONFIG_HAVE_CLK_PREPARE
+ int clk_prepare(struct clk *clk);
++int __must_check clk_bulk_prepare(int num_clks,
++ const struct clk_bulk_data *clks);
+ #else
+ static inline int clk_prepare(struct clk *clk)
+ {
+ might_sleep();
+ return 0;
+ }
++
++static inline int clk_bulk_prepare(int num_clks, struct clk_bulk_data *clks)
++{
++ might_sleep();
++ return 0;
++}
+ #endif
+
+ /**
+@@ -204,11 +227,16 @@ static inline int clk_prepare(struct clk *clk)
+ */
+ #ifdef CONFIG_HAVE_CLK_PREPARE
+ void clk_unprepare(struct clk *clk);
++void clk_bulk_unprepare(int num_clks, const struct clk_bulk_data *clks);
+ #else
+ static inline void clk_unprepare(struct clk *clk)
+ {
+ might_sleep();
+ }
++static inline void clk_bulk_unprepare(int num_clks, struct clk_bulk_data *clks)
++{
++ might_sleep();
++}
+ #endif
+
+ #ifdef CONFIG_HAVE_CLK
+@@ -230,6 +258,29 @@ static inline void clk_unprepare(struct clk *clk)
+ struct clk *clk_get(struct device *dev, const char *id);
+
+ /**
++ * clk_bulk_get - lookup and obtain a number of references to clock producer.
++ * @dev: device for clock "consumer"
++ * @num_clks: the number of clk_bulk_data
++ * @clks: the clk_bulk_data table of consumer
++ *
++ * This helper function allows drivers to get several clk consumers in one
++ * operation. If any of the clk cannot be acquired then any clks
++ * that were obtained will be freed before returning to the caller.
++ *
++ * Returns 0 if all clocks specified in clk_bulk_data table are obtained
++ * successfully, or valid IS_ERR() condition containing errno.
++ * The implementation uses @dev and @clk_bulk_data.id to determine the
++ * clock consumer, and thereby the clock producer.
++ * The clock returned is stored in each @clk_bulk_data.clk field.
++ *
++ * Drivers must assume that the clock source is not enabled.
++ *
++ * clk_bulk_get should not be called from within interrupt context.
++ */
++int __must_check clk_bulk_get(struct device *dev, int num_clks,
++ struct clk_bulk_data *clks);
++
++/**
+ * devm_clk_get - lookup and obtain a managed reference to a clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+@@ -279,6 +330,18 @@ struct clk *devm_get_clk_from_child(struct device *dev,
+ int clk_enable(struct clk *clk);
+
+ /**
++ * clk_bulk_enable - inform the system when the set of clks should be running.
++ * @num_clks: the number of clk_bulk_data
++ * @clks: the clk_bulk_data table of consumer
++ *
++ * May be called from atomic contexts.
++ *
++ * Returns success (0) or negative errno.
++ */
++int __must_check clk_bulk_enable(int num_clks,
++ const struct clk_bulk_data *clks);
++
++/**
+ * clk_disable - inform the system when the clock source is no longer required.
+ * @clk: clock source
+ *
+@@ -295,6 +358,24 @@ int clk_enable(struct clk *clk);
+ void clk_disable(struct clk *clk);
+
+ /**
++ * clk_bulk_disable - inform the system when the set of clks is no
++ * longer required.
++ * @num_clks: the number of clk_bulk_data
++ * @clks: the clk_bulk_data table of consumer
++ *
++ * Inform the system that a set of clks is no longer required by
++ * a driver and may be shut down.
++ *
++ * May be called from atomic contexts.
++ *
++ * Implementation detail: if the set of clks is shared between
++ * multiple drivers, clk_bulk_enable() calls must be balanced by the
++ * same number of clk_bulk_disable() calls for the clock source to be
++ * disabled.
++ */
++void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks);
++
++/**
+ * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
+ * This is only valid once the clock source has been enabled.
+ * @clk: clock source
+@@ -314,6 +395,19 @@ unsigned long clk_get_rate(struct clk *clk);
+ void clk_put(struct clk *clk);
+
+ /**
++ * clk_bulk_put - "free" the clock source
++ * @num_clks: the number of clk_bulk_data
++ * @clks: the clk_bulk_data table of consumer
++ *
++ * Note: drivers must ensure that all clk_bulk_enable calls made on this
++ * clock source are balanced by clk_bulk_disable calls prior to calling
++ * this function.
++ *
++ * clk_bulk_put should not be called from within interrupt context.
++ */
++void clk_bulk_put(int num_clks, struct clk_bulk_data *clks);
++
++/**
+ * devm_clk_put - "free" a managed clock source
+ * @dev: device used to acquire the clock
+ * @clk: clock source acquired with devm_clk_get()
+@@ -445,6 +539,12 @@ static inline struct clk *clk_get(struct device *dev, const char *id)
+ return NULL;
+ }
+
++static inline int clk_bulk_get(struct device *dev, int num_clks,
++ struct clk_bulk_data *clks)
++{
++ return 0;
++}
++
+ static inline struct clk *devm_clk_get(struct device *dev, const char *id)
+ {
+ return NULL;
+@@ -458,6 +558,8 @@ static inline struct clk *devm_get_clk_from_child(struct device *dev,
+
+ static inline void clk_put(struct clk *clk) {}
+
++static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {}
++
+ static inline void devm_clk_put(struct device *dev, struct clk *clk) {}
+
+ static inline int clk_enable(struct clk *clk)
+@@ -465,8 +567,17 @@ static inline int clk_enable(struct clk *clk)
+ return 0;
+ }
+
++static inline int clk_bulk_enable(int num_clks, struct clk_bulk_data *clks)
++{
++ return 0;
++}
++
+ static inline void clk_disable(struct clk *clk) {}
+
++
++static inline void clk_bulk_disable(int num_clks,
++ struct clk_bulk_data *clks) {}
++
+ static inline unsigned long clk_get_rate(struct clk *clk)
+ {
+ return 0;
+--
+2.11.0
+
diff --git a/series.conf b/series.conf
index ca36066a59..bcd538376a 100644
--- a/series.conf
+++ b/series.conf
@@ -2915,6 +2915,7 @@
patches.drivers/clk-renesas-r8a7745-Remove-nonexisting-scu-src-0789-
patches.drivers/clk-renesas-r8a7745-Remove-PLL-configs-for-MD19-0
patches.drivers/clk-renesas-r8a7795-Correct-pwm-gpio-and-i2c-parent-
+ patches.drivers/0001-clk-add-clk_bulk_get-accessories.patch
patches.drivers/clk-at91-fix-clk-generated-compilation
patches.drivers/0023-clk-rockchip-add-dt-binding-header-for-rk3128.patch
patches.drivers/0024-clk-rockchip-add-ids-for-rk3399-testclks-used-for-ca.patch