From: Stephen Boyd <sboyd@codeaurora.org> To: Michael Turquette <mturquette@baylibre.com>, Stephen Boyd <sboyd@codeaurora.org> Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 02/13] clk: Add {devm_}clk_hw_{register,unregister}() APIs Date: Thu, 21 Apr 2016 15:21:53 -0700 [thread overview] Message-ID: <1461277324-27185-3-git-send-email-sboyd@codeaurora.org> (raw) In-Reply-To: <1461277324-27185-1-git-send-email-sboyd@codeaurora.org> We've largely split the clk consumer and provider APIs along struct clk and struct clk_hw, but clk_register() still returns a struct clk pointer for each struct clk_hw that's registered. Eventually we'd like to only allocate struct clks when there's a user, because struct clk is per-user now, so clk_register() needs to change. Let's add new APIs to register struct clk_hws, but this time we'll hide the struct clk from the caller by returning an int error code. Also add an unregistration API that takes the clk_hw structure that was passed to the registration API. This way provider drivers never have to deal with a struct clk pointer unless they're using the clk consumer APIs. Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> --- Documentation/driver-model/devres.txt | 1 + drivers/clk/clk.c | 86 +++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 6 +++ 3 files changed, 93 insertions(+) diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 73b98dfbcea4..108d45553e1b 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -236,6 +236,7 @@ certainly invest a bit more effort into libata core layer). CLOCK devm_clk_get() devm_clk_put() + devm_clk_hw_register() DMA dmam_alloc_coherent() diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fb74dc1f7520..0ef919666827 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2536,6 +2536,22 @@ fail_out: } EXPORT_SYMBOL_GPL(clk_register); +/** + * clk_hw_register - register a clk_hw and return an error code + * @dev: device that is registering this clock + * @hw: link to hardware-specific clock data + * + * clk_hw_register is the primary interface for populating the clock tree with + * new clock nodes. It returns an integer equal to zero indicating success or + * less than zero indicating failure. Drivers must test for an error code after + * calling clk_hw_register(). + */ +int clk_hw_register(struct device *dev, struct clk_hw *hw) +{ + return PTR_ERR_OR_ZERO(clk_register(dev, hw)); +} +EXPORT_SYMBOL_GPL(clk_hw_register); + /* Free memory allocated for a clock. */ static void __clk_release(struct kref *ref) { @@ -2637,11 +2653,26 @@ unlock: } EXPORT_SYMBOL_GPL(clk_unregister); +/** + * clk_hw_unregister - unregister a currently registered clk_hw + * @hw: hardware-specific clock data to unregister + */ +void clk_hw_unregister(struct clk_hw *hw) +{ + clk_unregister(hw->clk); +} +EXPORT_SYMBOL_GPL(clk_hw_unregister); + static void devm_clk_release(struct device *dev, void *res) { clk_unregister(*(struct clk **)res); } +static void devm_clk_hw_release(struct device *dev, void *res) +{ + clk_hw_unregister(*(struct clk_hw **)res); +} + /** * devm_clk_register - resource managed clk_register() * @dev: device that is registering this clock @@ -2672,6 +2703,36 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw) } EXPORT_SYMBOL_GPL(devm_clk_register); +/** + * devm_clk_hw_register - resource managed clk_hw_register() + * @dev: device that is registering this clock + * @hw: link to hardware-specific clock data + * + * Managed clk_hw_register(). Clocks returned from this function are + * automatically clk_hw_unregister()ed on driver detach. See clk_hw_register() + * for more information. + */ +int devm_clk_hw_register(struct device *dev, struct clk_hw *hw) +{ + struct clk_hw **hwp; + int ret; + + hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL); + if (!hwp) + return -ENOMEM; + + ret = clk_hw_register(dev, hw); + if (!ret) { + *hwp = hw; + devres_add(dev, hwp); + } else { + devres_free(hwp); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_clk_hw_register); + static int devm_clk_match(struct device *dev, void *res, void *data) { struct clk *c = res; @@ -2680,6 +2741,15 @@ static int devm_clk_match(struct device *dev, void *res, void *data) return c == data; } +static int devm_clk_hw_match(struct device *dev, void *res, void *data) +{ + struct clk_hw *hw = res; + + if (WARN_ON(!hw)) + return 0; + return hw == data; +} + /** * devm_clk_unregister - resource managed clk_unregister() * @clk: clock to unregister @@ -2694,6 +2764,22 @@ void devm_clk_unregister(struct device *dev, struct clk *clk) } EXPORT_SYMBOL_GPL(devm_clk_unregister); +/** + * devm_clk_hw_unregister - resource managed clk_hw_unregister() + * @dev: device that is unregistering the hardware-specific clock data + * @hw: link to hardware-specific clock data + * + * Unregister a clk_hw registered with devm_clk_hw_register(). Normally + * this function will not need to be called and the resource management + * code will ensure that the resource is freed. + */ +void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw) +{ + WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match, + hw)); +} +EXPORT_SYMBOL_GPL(devm_clk_hw_unregister); + /* * clkdev helpers */ diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index da95258127aa..bc6c8de1fac1 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -655,9 +655,15 @@ struct clk *clk_register_gpio_mux(struct device *dev, const char *name, struct clk *clk_register(struct device *dev, struct clk_hw *hw); struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw); +int __must_check clk_hw_register(struct device *dev, struct clk_hw *hw); +int __must_check devm_clk_hw_register(struct device *dev, struct clk_hw *hw); + void clk_unregister(struct clk *clk); void devm_clk_unregister(struct device *dev, struct clk *clk); +void clk_hw_unregister(struct clk_hw *hw); +void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw); + /* helper functions */ const char *__clk_get_name(const struct clk *clk); const char *clk_hw_get_name(const struct clk_hw *hw); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
WARNING: multiple messages have this Message-ID (diff)
From: sboyd@codeaurora.org (Stephen Boyd) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 02/13] clk: Add {devm_}clk_hw_{register,unregister}() APIs Date: Thu, 21 Apr 2016 15:21:53 -0700 [thread overview] Message-ID: <1461277324-27185-3-git-send-email-sboyd@codeaurora.org> (raw) In-Reply-To: <1461277324-27185-1-git-send-email-sboyd@codeaurora.org> We've largely split the clk consumer and provider APIs along struct clk and struct clk_hw, but clk_register() still returns a struct clk pointer for each struct clk_hw that's registered. Eventually we'd like to only allocate struct clks when there's a user, because struct clk is per-user now, so clk_register() needs to change. Let's add new APIs to register struct clk_hws, but this time we'll hide the struct clk from the caller by returning an int error code. Also add an unregistration API that takes the clk_hw structure that was passed to the registration API. This way provider drivers never have to deal with a struct clk pointer unless they're using the clk consumer APIs. Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> --- Documentation/driver-model/devres.txt | 1 + drivers/clk/clk.c | 86 +++++++++++++++++++++++++++++++++++ include/linux/clk-provider.h | 6 +++ 3 files changed, 93 insertions(+) diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 73b98dfbcea4..108d45553e1b 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -236,6 +236,7 @@ certainly invest a bit more effort into libata core layer). CLOCK devm_clk_get() devm_clk_put() + devm_clk_hw_register() DMA dmam_alloc_coherent() diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fb74dc1f7520..0ef919666827 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2536,6 +2536,22 @@ fail_out: } EXPORT_SYMBOL_GPL(clk_register); +/** + * clk_hw_register - register a clk_hw and return an error code + * @dev: device that is registering this clock + * @hw: link to hardware-specific clock data + * + * clk_hw_register is the primary interface for populating the clock tree with + * new clock nodes. It returns an integer equal to zero indicating success or + * less than zero indicating failure. Drivers must test for an error code after + * calling clk_hw_register(). + */ +int clk_hw_register(struct device *dev, struct clk_hw *hw) +{ + return PTR_ERR_OR_ZERO(clk_register(dev, hw)); +} +EXPORT_SYMBOL_GPL(clk_hw_register); + /* Free memory allocated for a clock. */ static void __clk_release(struct kref *ref) { @@ -2637,11 +2653,26 @@ unlock: } EXPORT_SYMBOL_GPL(clk_unregister); +/** + * clk_hw_unregister - unregister a currently registered clk_hw + * @hw: hardware-specific clock data to unregister + */ +void clk_hw_unregister(struct clk_hw *hw) +{ + clk_unregister(hw->clk); +} +EXPORT_SYMBOL_GPL(clk_hw_unregister); + static void devm_clk_release(struct device *dev, void *res) { clk_unregister(*(struct clk **)res); } +static void devm_clk_hw_release(struct device *dev, void *res) +{ + clk_hw_unregister(*(struct clk_hw **)res); +} + /** * devm_clk_register - resource managed clk_register() * @dev: device that is registering this clock @@ -2672,6 +2703,36 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw) } EXPORT_SYMBOL_GPL(devm_clk_register); +/** + * devm_clk_hw_register - resource managed clk_hw_register() + * @dev: device that is registering this clock + * @hw: link to hardware-specific clock data + * + * Managed clk_hw_register(). Clocks returned from this function are + * automatically clk_hw_unregister()ed on driver detach. See clk_hw_register() + * for more information. + */ +int devm_clk_hw_register(struct device *dev, struct clk_hw *hw) +{ + struct clk_hw **hwp; + int ret; + + hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL); + if (!hwp) + return -ENOMEM; + + ret = clk_hw_register(dev, hw); + if (!ret) { + *hwp = hw; + devres_add(dev, hwp); + } else { + devres_free(hwp); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_clk_hw_register); + static int devm_clk_match(struct device *dev, void *res, void *data) { struct clk *c = res; @@ -2680,6 +2741,15 @@ static int devm_clk_match(struct device *dev, void *res, void *data) return c == data; } +static int devm_clk_hw_match(struct device *dev, void *res, void *data) +{ + struct clk_hw *hw = res; + + if (WARN_ON(!hw)) + return 0; + return hw == data; +} + /** * devm_clk_unregister - resource managed clk_unregister() * @clk: clock to unregister @@ -2694,6 +2764,22 @@ void devm_clk_unregister(struct device *dev, struct clk *clk) } EXPORT_SYMBOL_GPL(devm_clk_unregister); +/** + * devm_clk_hw_unregister - resource managed clk_hw_unregister() + * @dev: device that is unregistering the hardware-specific clock data + * @hw: link to hardware-specific clock data + * + * Unregister a clk_hw registered with devm_clk_hw_register(). Normally + * this function will not need to be called and the resource management + * code will ensure that the resource is freed. + */ +void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw) +{ + WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match, + hw)); +} +EXPORT_SYMBOL_GPL(devm_clk_hw_unregister); + /* * clkdev helpers */ diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index da95258127aa..bc6c8de1fac1 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -655,9 +655,15 @@ struct clk *clk_register_gpio_mux(struct device *dev, const char *name, struct clk *clk_register(struct device *dev, struct clk_hw *hw); struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw); +int __must_check clk_hw_register(struct device *dev, struct clk_hw *hw); +int __must_check devm_clk_hw_register(struct device *dev, struct clk_hw *hw); + void clk_unregister(struct clk *clk); void devm_clk_unregister(struct device *dev, struct clk *clk); +void clk_hw_unregister(struct clk_hw *hw); +void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw); + /* helper functions */ const char *__clk_get_name(const struct clk *clk); const char *clk_hw_get_name(const struct clk_hw *hw); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
next prev parent reply other threads:[~2016-04-21 22:22 UTC|newest] Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-04-21 22:21 [PATCH v2 00/13] clk_hw based clkdev/DT providers Stephen Boyd 2016-04-21 22:21 ` Stephen Boyd 2016-04-21 22:21 ` [PATCH v2 01/13] clkdev: Remove clk_register_clkdevs() Stephen Boyd 2016-04-21 22:21 ` Stephen Boyd 2016-05-03 0:37 ` Stephen Boyd 2016-05-03 0:37 ` Stephen Boyd 2016-04-21 22:21 ` Stephen Boyd [this message] 2016-04-21 22:21 ` [PATCH v2 02/13] clk: Add {devm_}clk_hw_{register,unregister}() APIs Stephen Boyd 2016-04-22 21:44 ` Stephen Boyd 2016-04-22 21:44 ` Stephen Boyd 2016-04-21 22:21 ` [PATCH v2 03/13] clk: Add clk_hw OF clk providers Stephen Boyd 2016-04-21 22:21 ` Stephen Boyd 2016-04-22 21:45 ` Stephen Boyd 2016-04-22 21:45 ` Stephen Boyd 2016-04-21 22:21 ` [PATCH v2 04/13] clkdev: Add clk_hw based registration APIs Stephen Boyd 2016-04-21 22:21 ` Stephen Boyd 2016-05-03 0:37 ` Stephen Boyd 2016-05-03 0:37 ` Stephen Boyd 2016-05-03 10:36 ` Russell King - ARM Linux 2016-05-03 10:36 ` Russell King - ARM Linux 2016-04-21 22:21 ` [PATCH v2 05/13] clk: divider: Add hw " Stephen Boyd 2016-04-21 22:21 ` Stephen Boyd 2016-04-22 21:49 ` Stephen Boyd 2016-04-22 21:49 ` Stephen Boyd 2016-04-21 22:21 ` [PATCH v2 06/13] clk: gate: " Stephen Boyd 2016-04-21 22:21 ` Stephen Boyd 2016-04-22 21:49 ` Stephen Boyd 2016-04-22 21:49 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-21 22:21 ` [PATCH v2 07/13] clk: mux: " Stephen Boyd 2016-04-21 22:21 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-21 22:21 ` [PATCH v2 08/13] clk: fixed-factor: " Stephen Boyd 2016-04-21 22:21 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-21 22:22 ` [PATCH v2 09/13] clk: fractional-divider: " Stephen Boyd 2016-04-21 22:22 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-21 22:22 ` [PATCH v2 10/13] clk: composite: " Stephen Boyd 2016-04-21 22:22 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-21 22:22 ` [PATCH v2 11/13] clk: gpio: " Stephen Boyd 2016-04-21 22:22 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-21 22:22 ` [PATCH v2 12/13] clk: fixed-rate: " Stephen Boyd 2016-04-21 22:22 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-22 22:58 ` Stephen Boyd 2016-04-21 22:22 ` [PATCH v2 13/13] clk: qcom: Migrate to clk_hw based registration and OF APIs Stephen Boyd 2016-04-21 22:22 ` Stephen Boyd
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1461277324-27185-3-git-send-email-sboyd@codeaurora.org \ --to=sboyd@codeaurora.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-clk@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=mturquette@baylibre.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.