From patchwork Tue Jan 31 00:57:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 9546289 X-Patchwork-Delegate: sboyd@codeaurora.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 14B7160425 for ; Tue, 31 Jan 2017 00:57:19 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0338227FE4 for ; Tue, 31 Jan 2017 00:57:19 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EC00028285; Tue, 31 Jan 2017 00:57:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 30BD827FE4 for ; Tue, 31 Jan 2017 00:57:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754619AbdAaA5R (ORCPT ); Mon, 30 Jan 2017 19:57:17 -0500 Received: from mail-pf0-f193.google.com ([209.85.192.193]:34164 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754598AbdAaA5Q (ORCPT ); Mon, 30 Jan 2017 19:57:16 -0500 Received: by mail-pf0-f193.google.com with SMTP id y143so24946143pfb.1; Mon, 30 Jan 2017 16:57:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=g/+4LXTvSwn2g7HaBCOhYYCjVeVFD5vXoqsm+Bi7Vrs=; b=hhrHY5VPSMZ9kMd03HlmfFrbHwCoiFgMycSH8kBQlJz7LGknecB4UXWi0AO0vaLQbL ilQ54d0tZJlm0iy306wgcNjc9D3nDwsjn2DX99KFrvuhTFXIHOIA2qbx0hhcDVchDw/K afyvgnTIW1bElXKX78HoCiSqnrVF+leogLwWvsXqDJGftTiZv3zAG/1PRlZHrqIk4+U9 pmXekGNiAf6W3RFLe/Ww5lXd8agkTQpnODJyw2mfpD1r3hneYTTxuNa8v02EjVMHrJ3X DkbGJXLS94E5YRhjtgnXGPgs8IR3eGptaOw/LgZprKhDUx0HYY4CA1Dtxa4bXs1mAZex mbhg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=g/+4LXTvSwn2g7HaBCOhYYCjVeVFD5vXoqsm+Bi7Vrs=; b=Qusp5ETQS02viDMhpOFA3OGSFbciDLV++wmBAElCNvFIiZuBuZj+YcINF32f/iXcyn 8cVUJiEPhcWNaUNNH+N0OKOD0iw7rc/wxEboLfAEvVcVmeFr6NNvd7HHuR4MeXTTwRAu pZkXuhoaepwKvGZ9DRk5UagCV0tGwGGRxvkV4nIpiiJtPRpNKkP2S1/zpqrR6Jl3AxDC YbIkOgWEwN2ps4Z1wQAZM0jg1pxDaFCdJJz4gv7Q5QQk0VyIK6oAoBiNBfAarmUvi0Zm Z9pVHQJnmXGB+rKt6M0qkMWANHRpdByu2FqMuQ3V9/tU5fTC5cRkYYvaRa8xOuBMMUS4 cykw== X-Gm-Message-State: AIkVDXIDwp9zeo9fid7vNQ1lndM5AOX+nS6h/VR2urpfSQixeabBUOtjnVGMzSdT3ex15Q== X-Received: by 10.84.134.169 with SMTP id 38mr35411961plh.67.1485824236107; Mon, 30 Jan 2017 16:57:16 -0800 (PST) Received: from dtor-ws ([2620:0:1000:1311:c0b7:99da:f3c5:7745]) by smtp.gmail.com with ESMTPSA id 184sm35691883pgj.5.2017.01.30.16.57.15 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Mon, 30 Jan 2017 16:57:15 -0800 (PST) Date: Mon, 30 Jan 2017 16:57:13 -0800 From: Dmitry Torokhov To: Stephen Boyd Cc: Russell King - ARM Linux , Guenter Roeck , Michael Turquette , Viresh Kumar , Andy Shevchenko , linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3] clk: add more managed APIs Message-ID: <20170131005713.GA35974@dtor-ws> References: <20170128184047.GA24957@dtor-ws> <20170128190309.GN27312@n2100.armlinux.org.uk> <20170128192207.GA38136@dtor-ws> <64ed0890-14f6-42ff-66b1-60f7b3d7d02f@roeck-us.net> <20170128233911.GO27312@n2100.armlinux.org.uk> <20170129180743.GA10917@dtor-ws> <20170130185551.GM8801@codeaurora.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20170130185551.GM8801@codeaurora.org> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When converting a driver to managed resources it is desirable to be able to manage all resources in the same fashion. This change allows managing clock prepared and enabled state in the same way we manage many other resources. This adds the following managed APIs: - devm_clk_prepare()/devm_clk_unprepare(); - devm_clk_prepare_enable()/devm_clk_disable_unprepare(). Reviewed-by: Guenter Roeck Signed-off-by: Dmitry Torokhov --- v3: adjusted commit message, added Guenter's reviewed-by v2: dropped devm_clk_enable() and devm_clk_disable() drivers/clk/clk-devres.c | 98 +++++++++++++++++++++++++++++++--------------- include/linux/clk.h | 68 ++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 32 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-clk" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c index 3a218c3a06ae..2ff94ffe11d3 100644 --- a/drivers/clk/clk-devres.c +++ b/drivers/clk/clk-devres.c @@ -9,30 +9,20 @@ #include #include -static void devm_clk_release(struct device *dev, void *res) +static int devm_clk_create_devres(struct device *dev, struct clk *clk, + void (*release)(struct device *, void *)) { - clk_put(*(struct clk **)res); -} + struct clk **ptr; -struct clk *devm_clk_get(struct device *dev, const char *id) -{ - struct clk **ptr, *clk; - - ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); + ptr = devres_alloc(release, sizeof(*ptr), GFP_KERNEL); if (!ptr) - return ERR_PTR(-ENOMEM); + return -ENOMEM; - clk = clk_get(dev, id); - if (!IS_ERR(clk)) { - *ptr = clk; - devres_add(dev, ptr); - } else { - devres_free(ptr); - } + *ptr = clk; + devres_add(dev, ptr); - return clk; + return 0; } -EXPORT_SYMBOL(devm_clk_get); static int devm_clk_match(struct device *dev, void *res, void *data) { @@ -44,31 +34,75 @@ static int devm_clk_match(struct device *dev, void *res, void *data) return *c == data; } -void devm_clk_put(struct device *dev, struct clk *clk) +#define DEFINE_DEVM_CLK_DESTROY_OP(destroy_op) \ +static void devm_##destroy_op##_release(struct device *dev, void *res) \ +{ \ + destroy_op(*(struct clk **)res); \ +} \ + \ +void devm_##destroy_op(struct device *dev, struct clk *clk) \ +{ \ + WARN_ON(devres_release(dev, devm_##destroy_op##_release, \ + devm_clk_match, clk)); \ +} \ +EXPORT_SYMBOL(devm_##destroy_op) + +#define DEFINE_DEVM_CLK_OP(create_op, destroy_op) \ +DEFINE_DEVM_CLK_DESTROY_OP(destroy_op); \ +int devm_##create_op(struct device *dev, struct clk *clk) \ +{ \ + int error; \ + \ + error = create_op(clk); \ + if (error) \ + return error; \ + \ + error = devm_clk_create_devres(dev, clk, \ + devm_##destroy_op##_release); \ + if (error) { \ + destroy_op(clk); \ + return error; \ + } \ + \ + return 0; \ +} \ +EXPORT_SYMBOL(devm_##create_op) + +DEFINE_DEVM_CLK_DESTROY_OP(clk_put); +DEFINE_DEVM_CLK_OP(clk_prepare, clk_unprepare); +DEFINE_DEVM_CLK_OP(clk_prepare_enable, clk_disable_unprepare); + +struct clk *devm_clk_get(struct device *dev, const char *id) { - int ret; + struct clk *clk; + int error; - ret = devres_release(dev, devm_clk_release, devm_clk_match, clk); + clk = clk_get(dev, id); + if (!IS_ERR(clk)) { + error = devm_clk_create_devres(dev, clk, devm_clk_put_release); + if (error) { + clk_put(clk); + return ERR_PTR(error); + } + } - WARN_ON(ret); + return clk; } -EXPORT_SYMBOL(devm_clk_put); +EXPORT_SYMBOL(devm_clk_get); struct clk *devm_get_clk_from_child(struct device *dev, struct device_node *np, const char *con_id) { - struct clk **ptr, *clk; - - ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return ERR_PTR(-ENOMEM); + struct clk *clk; + int error; clk = of_clk_get_by_name(np, con_id); if (!IS_ERR(clk)) { - *ptr = clk; - devres_add(dev, ptr); - } else { - devres_free(ptr); + error = devm_clk_create_devres(dev, clk, devm_clk_put_release); + if (error) { + clk_put(clk); + return ERR_PTR(error); + } } return clk; diff --git a/include/linux/clk.h b/include/linux/clk.h index e9d36b3e49de..413dc8f636bd 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -267,6 +267,29 @@ struct clk *devm_get_clk_from_child(struct device *dev, struct device_node *np, const char *con_id); /** + * devm_clk_prepare - prepare clock source as a managed resource + * @dev: device owning the resource + * @clk: clock source + * + * This prepares the clock source for use. + * + * Must not be called from within atomic context. + */ +int devm_clk_prepare(struct device *dev, struct clk *clk); + +/** + * devm_clk_unprepare - undo preparation of a managed clock source + * @dev: device used to prepare the clock + * @clk: clock source + * + * This undoes preparation of a clock, previously prepared with a call + * to devm_clk_pepare(). + * + * Must not be called from within atomic context. + */ +void devm_clk_unprepare(struct device *dev, struct clk *clk); + +/** * clk_enable - inform the system when the clock source should be running. * @clk: clock source * @@ -295,6 +318,28 @@ int clk_enable(struct clk *clk); void clk_disable(struct clk *clk); /** + * devm_clk_prepare_enable - prepare and enable a managed clock source + * @dev: device owning the clock source + * @clk: clock source + * + * This prepares the clock source for use and enables it. + * + * Must not be called from within atomic context. + */ +int devm_clk_prepare_enable(struct device *dev, struct clk *clk); + +/** + * devm_clk_disable_unprepare - disable and undo preparation of a managed clock + * @dev: device used to prepare and enable the clock + * @clk: clock source + * + * This disables and undoes a previously prepared clock. + * + * Must not be called from within atomic context. + */ +void devm_clk_disable_unprepare(struct device *dev, struct clk *clk); + +/** * 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 @@ -460,6 +505,17 @@ static inline void clk_put(struct clk *clk) {} static inline void devm_clk_put(struct device *dev, struct clk *clk) {} +static inline int devm_clk_prepare(struct device *dev, struct clk *clk) +{ + might_sleep(); + return 0; +} + +static inline void devm_clk_unprepare(struct device *dev, struct clk *clk) +{ + might_sleep(); +} + static inline int clk_enable(struct clk *clk) { return 0; @@ -467,6 +523,18 @@ static inline int clk_enable(struct clk *clk) static inline void clk_disable(struct clk *clk) {} +static inline int devm_clk_prepare_enable(struct device *dev, struct clk *clk) +{ + might_sleep(); + return 0; +} + +static inline void devm_clk_disable_unprepare(struct device *dev, + struct clk *clk) +{ + might_sleep(); +} + static inline unsigned long clk_get_rate(struct clk *clk) { return 0;