From patchwork Tue Jun 20 10:05:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 105994 Delivered-To: patch@linaro.org Received: by 10.140.91.2 with SMTP id y2csp1284455qgd; Tue, 20 Jun 2017 03:06:04 -0700 (PDT) X-Received: by 10.99.167.78 with SMTP id w14mr31023844pgo.228.1497953164241; Tue, 20 Jun 2017 03:06:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1497953164; cv=none; d=google.com; s=arc-20160816; b=NoH5ffdaUfTgfe2EVEooZ0NFyr9CYjeblnzpX6VGbZJL91Dbi+phdMqHzUyHRii48N 7d657K46SUoyeBOPTGnmDDasvGLwJ7tsh5pUn5uFo7Dp3R8KuurqI65KuPvavCyWiqwg T9OFt7ZShsxeJCUu2kPLdImoBrjw+l+e2cmql7JwdZP531XiNO1U2kvvvd2271rIPHxC BWZ6E1RcAL7o0UM3o7bUXvLtBXYJmfbWnRAwfjMeRU5q6KdU0aN4oDZaHZEHejbzth+x 8rp6E/IjBdH+/fEznrsyfYE2oKSJ1hk7ZQrb8fKKL/nE5eObuFni3+rGpn3aVxv8UnW9 kuhA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=/zDREp0npR76Q59m6jAn2Hz+qHye4/r3OrHWsXswjkY=; b=O8v2yG7VAPPZLdSqZuq5VXMBOXZJv9pQYZPRHUGw9zaE4CQZ4FQZ82cOO5BL2CHRbS N2FIsUkrrrdfVQEAmABK5zoaeg5WzkPmY+EXuZydgReM2E5jmyVVjrgsU3ndHJhpfMWb sgzQJ9SRd3k+Ay3ZIs8i2pmzSCg9lAQflM3vD7yJWEQ1xla0+jRORhxEjVZgo+19YdnX fGXBuQ/CGcURNBbZBvWCD99HvfSJCUX7lIwZFEvzOEv0ZGdoaEUQxXvf08wtf2xkv99e DxuyxV7YE0bGKHrBvo54dtiAmGvx6wgNvmh3dc2hnW/xyfRo03asiQGtaivn8ER/GlcB SyvQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=GBVaroQh; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w5si10229264pgo.148.2017.06.20.03.06.03; Tue, 20 Jun 2017 03:06:04 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.b=GBVaroQh; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751106AbdFTKGB (ORCPT + 25 others); Tue, 20 Jun 2017 06:06:01 -0400 Received: from mail-pg0-f47.google.com ([74.125.83.47]:34246 "EHLO mail-pg0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750955AbdFTKF7 (ORCPT ); Tue, 20 Jun 2017 06:05:59 -0400 Received: by mail-pg0-f47.google.com with SMTP id e187so8183480pgc.1 for ; Tue, 20 Jun 2017 03:05:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=/zDREp0npR76Q59m6jAn2Hz+qHye4/r3OrHWsXswjkY=; b=GBVaroQhAGrEalHlnEU4Ed7VH+gFFgrnM0HDBR7jVIBEv8pxoQFXySi8VORmZraV66 /x5BVDLNFa41NsKUazbwBrR6jDY8+9IjJ59MK3fzOcRIQi2gIMFzv8udnrC0da6UMqmt uCLW5rFgjt6ItDjPexEdNzWqgR7Fn81YO/DfY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=/zDREp0npR76Q59m6jAn2Hz+qHye4/r3OrHWsXswjkY=; b=jChww0PEgtIRIUboEJb6YIU5QcFbRN3Pq4DzXbvuWUTk5oa7cL9UtxkM9DOd5xJ8fN L2n+iNOC2UhNNWm56okDkE2HUplDt5Lv7l5kBexr7iX+vr38gNN3zwTnSSUYtmASDZqy kTU6qBGW6Kpwy2MjBLvIiQJM62+eMqt6w+13bqlSFkfGRjr9Z7mPRsjf4w1oKRN2I8KF jVkBHSb/drYsndfPkQZZe7V/lplwL3ad6sD+Nl6c1qWuLiOJBB56SjH6pkceX7BxpJ1N my6TaVNRuuQMf7+3f/vl7sd9fiKPlSjlqqT1dPOx6/6UpMerzRCzNWZ8tmhf117oAq8e FAqQ== X-Gm-Message-State: AKS2vOxmNKWFM89d/NGy6iWneF0j141npi6NzNePzELc7TDCtjKkEwlu oYSLjYS5JnIPvHlT X-Received: by 10.84.191.164 with SMTP id a33mr319053pld.119.1497953158716; Tue, 20 Jun 2017 03:05:58 -0700 (PDT) Received: from localhost ([122.167.168.61]) by smtp.gmail.com with ESMTPSA id i2sm26965497pfe.89.2017.06.20.03.05.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 20 Jun 2017 03:05:58 -0700 (PDT) From: Viresh Kumar To: Rafael Wysocki , Viresh Kumar , Nishanth Menon , Stephen Boyd Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Rajendra Nayak , linux-kernel@vger.kernel.org Subject: [PATCH] PM / OPP: Add dev_pm_opp_{set|put}_clkname() Date: Tue, 20 Jun 2017 15:35:22 +0530 Message-Id: X-Mailer: git-send-email 2.13.0.71.gd7076ec9c9cb Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In order to support OPP switching, OPP layer needs to get pointer to the clock for the device. Simple cases work fine without using the routines added by this patch (i.e. by passing connection-id as NULL), but for a device with multiple clocks available, the OPP core needs to know the exact name of the clk to use. Add a new set of APIs to get that done. Tested-by: Rajendra Nayak Signed-off-by: Viresh Kumar --- drivers/base/power/opp/core.c | 90 +++++++++++++++++++++++++++++++++++++++++++ drivers/base/power/opp/opp.h | 2 + include/linux/pm_opp.h | 9 +++++ 3 files changed, 101 insertions(+) -- 2.13.0.71.gd7076ec9c9cb diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index 5ee7aadf0abf..f675b83ba721 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -1363,6 +1363,96 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table) EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulators); /** + * dev_pm_opp_set_clkname() - Set clk name for the device + * @dev: Device for which clk name is being set. + * @name: Clk name. + * + * In order to support OPP switching, OPP layer needs to get pointer to the + * clock for the device. Simple cases work fine without using this routine (i.e. + * by passing connection-id as NULL), but for a device with multiple clocks + * available, the OPP core needs to know the exact name of the clk to use. + * + * This must be called before any OPPs are initialized for the device. + */ +struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char *name) +{ + struct opp_table *opp_table; + int ret; + + opp_table = dev_pm_opp_get_opp_table(dev); + if (!opp_table) + return ERR_PTR(-ENOMEM); + + /* This should be called before OPPs are initialized */ + if (WARN_ON(!list_empty(&opp_table->opp_list))) { + ret = -EBUSY; + goto err; + } + + /* Already have clkname set */ + if (opp_table->clk_name) { + ret = -EBUSY; + goto err; + } + + opp_table->clk_name = kstrdup(name, GFP_KERNEL); + if (!opp_table->clk_name) { + ret = -ENOMEM; + goto err; + } + + /* Already have default clk set, free it */ + if (!IS_ERR(opp_table->clk)) + clk_put(opp_table->clk); + + /* Find clk for the device */ + opp_table->clk = clk_get(dev, name); + if (IS_ERR(opp_table->clk)) { + ret = PTR_ERR(opp_table->clk); + if (ret != -EPROBE_DEFER) { + dev_err(dev, "%s: Couldn't find clock: %d\n", __func__, + ret); + } + goto free_clk_name; + } + + return opp_table; + +free_clk_name: + kfree(opp_table->clk_name); + opp_table->clk_name = NULL; + +err: + dev_pm_opp_put_opp_table(opp_table); + + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(dev_pm_opp_set_clkname); + +/** + * dev_pm_opp_put_clkname() - Releases resources blocked for clk. + * @opp_table: OPP table returned from dev_pm_opp_set_clkname(). + */ +void dev_pm_opp_put_clkname(struct opp_table *opp_table) +{ + if (!opp_table->clk_name) { + pr_err("%s: Doesn't have clk set\n", __func__); + return; + } + + /* Make sure there are no concurrent readers while updating opp_table */ + WARN_ON(!list_empty(&opp_table->opp_list)); + + clk_put(opp_table->clk); + opp_table->clk = ERR_PTR(-EINVAL); + kfree(opp_table->clk_name); + opp_table->clk_name = NULL; + + dev_pm_opp_put_opp_table(opp_table); +} +EXPORT_SYMBOL_GPL(dev_pm_opp_put_clkname); + +/** * dev_pm_opp_register_set_opp_helper() - Register custom set OPP helper * @dev: Device for which the helper is getting registered. * @set_opp: Custom set OPP helper. diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h index 166eef990599..0443ea4452b4 100644 --- a/drivers/base/power/opp/opp.h +++ b/drivers/base/power/opp/opp.h @@ -132,6 +132,7 @@ enum opp_table_access { * @supported_hw: Array of version number to support. * @supported_hw_count: Number of elements in supported_hw array. * @prop_name: A name to postfix to many DT properties, while parsing them. + * @clkname: Clock's name. * @clk: Device's clock handle * @regulators: Supply regulators * @regulator_count: Number of power supply regulators @@ -167,6 +168,7 @@ struct opp_table { unsigned int *supported_hw; unsigned int supported_hw_count; const char *prop_name; + const char *clk_name; struct clk *clk; struct regulator **regulators; unsigned int regulator_count; diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index a6685b3dde26..51ec727b4824 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -121,6 +121,8 @@ struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name) void dev_pm_opp_put_prop_name(struct opp_table *opp_table); struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count); void dev_pm_opp_put_regulators(struct opp_table *opp_table); +struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char * name); +void dev_pm_opp_put_clkname(struct opp_table *opp_table); struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data)); void dev_pm_opp_register_put_opp_helper(struct opp_table *opp_table); int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq); @@ -257,6 +259,13 @@ static inline struct opp_table *dev_pm_opp_set_regulators(struct device *dev, co static inline void dev_pm_opp_put_regulators(struct opp_table *opp_table) {} +static inline struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char * name) +{ + return ERR_PTR(-ENOTSUPP); +} + +static inline void dev_pm_opp_put_clkname(struct opp_table *opp_table) {} + static inline int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) { return -ENOTSUPP;