From patchwork Wed Aug 2 10:12:32 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 109207 Delivered-To: patch@linaro.org Received: by 10.140.101.6 with SMTP id t6csp2591669qge; Wed, 2 Aug 2017 03:14:07 -0700 (PDT) X-Received: by 10.99.149.79 with SMTP id t15mr21490589pgn.247.1501668847890; Wed, 02 Aug 2017 03:14:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1501668847; cv=none; d=google.com; s=arc-20160816; b=vgmE6QAfVE1SgGXlfNADTkSXaK1uWd0gW+KsI9ntuERoBLYmCqmDocF1FtAqkXQqd4 dac2BM7gzfBOen/OjLpS0inLlcFdF1FpmLvvArhWz3iHFE+uOmqi27IxePjXQVv3fGCJ laiM73/nHFbNSbHrvP6h6trdmfVMw0A0PehdKXlRb95suiXZgkyHa8EvDSmzSq1HafNJ fxtwWVgrxRhYLTZarfCWXlgeZ3P3AYaHX/+yg7++M86RMXximdm1EqN342cHDNHcoGe1 JP96akOH2Alke3+KPuMTLIDvFjSS2AFUfqlTVxFKOH5T/RCeFj5/9+Z5gEWRUnSZ01TU 2PPg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=Ta8TAGbVzRXpECYS4RGQXLFm8dWiD+awa1MwThILKxY=; b=FbFHYWy7F8v2dxkvFFso72YkcymdnH/sr19JUHdif0PhegTm9/+78vMcPM7JI1C1E/ PjNW5coMKQZ/i7IZU+Sw89Ue+hIo1++T/0t6UBR+n+/toy2gYXgGhxSULJZqRaEWRsL2 nI3kgP5XId2VO/YxJzHRCbZ4p8PWJ9AcP2cOcscNbEdtuaDUXy1w5WrE1Vt9d5kXbtcY SEjgHEpSHi1r9K9qLbhgR/kk0JpRiBN8Ank/6sYZE27M+oxwXHIOredpiGNZJQAUMZJC xZIR8F7ZjPHpFkN2h3OZXZsh0ftE2w8qrYMh6TCkVu6mGPjfI4DkinY6iIsmXLbs9JGB LVRg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=B0yWQc15; 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 x13si13790243pfj.353.2017.08.02.03.14.07; Wed, 02 Aug 2017 03:14:07 -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=B0yWQc15; 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 S1752743AbdHBKMz (ORCPT + 25 others); Wed, 2 Aug 2017 06:12:55 -0400 Received: from mail-pf0-f177.google.com ([209.85.192.177]:36012 "EHLO mail-pf0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751191AbdHBKMs (ORCPT ); Wed, 2 Aug 2017 06:12:48 -0400 Received: by mail-pf0-f177.google.com with SMTP id z129so19284120pfb.3 for ; Wed, 02 Aug 2017 03:12:48 -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:in-reply-to:references :in-reply-to:references; bh=Ta8TAGbVzRXpECYS4RGQXLFm8dWiD+awa1MwThILKxY=; b=B0yWQc156dNXKuONkVyhS3yQ9UjvFBBJUqbp0VrnDLlllhKkGdPCQlwxuKt7xCwiCy TZzUa9c1uOZiBbxzCVD1E5lG6QstauEl5QSyAVCsndyD/Hwzkzu01+F/F45/duIlUQhA SEo9LWGeYEL61P6+Qqsgib5eKhRrF42IggCOM= 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:in-reply-to :references:in-reply-to:references; bh=Ta8TAGbVzRXpECYS4RGQXLFm8dWiD+awa1MwThILKxY=; b=YKc2P6opQ2tptcr/HyU6o0F7CSqLlbrncR6DbD04orxRqiAEhHMLx4UjTmQ5wdXDqU PIbSKYMzxcv6Zo3ta5QX2O/icFOwfhREYgSIQR1JYo8b7k7IMSuThORAnn5tCKxveiV+ QCZroQBfuoohSZbvFiLxPMAUHpLUB4DL8nX9aXi/nEkiEb4FLBWkLsZD8GpgQKot0ahu Xek+fWNlJjensNN1XAHK01GZpCo8926cy81rPTE3mn7lSh0vOPd2ka99hoRPsJmUnToe FbU5pJF+renOi+fxSeHepjk9WJVvXxLcftrZ3gnrbbjJiKKLl+vyShFw0zS9/4FAlOtm aDcw== X-Gm-Message-State: AIVw113QT1Pb4m0YVQJLjEz8VzjjaYslmrxMAM30xaezLAZqiQQE2ccP v3xPbFuMfGFthfAy X-Received: by 10.99.173.6 with SMTP id g6mr22138540pgf.1.1501668768133; Wed, 02 Aug 2017 03:12:48 -0700 (PDT) Received: from localhost ([122.171.108.183]) by smtp.gmail.com with ESMTPSA id m3sm57048103pfm.175.2017.08.02.03.12.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 02 Aug 2017 03:12:47 -0700 (PDT) From: Viresh Kumar To: Rafael Wysocki , ulf.hansson@linaro.org, Kevin Hilman Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Stephen Boyd , Nishanth Menon , robh+dt@kernel.org, lina.iyer@linaro.org, rnayak@codeaurora.org, sudeep.holla@arm.com, linux-kernel@vger.kernel.org, Len Brown , Pavel Machek , Andy Gross , David Brown Subject: [PATCH V9 1/7] PM / Domains: Add support to select performance-state of domains Date: Wed, 2 Aug 2017 15:42:32 +0530 Message-Id: X-Mailer: git-send-email 2.13.0.71.gd7076ec9c9cb In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Some platforms have the capability to configure the performance state of PM domains and this patch updates the genpd core to support them. The performance levels (within the genpd core) are identified by positive integer values, a lower value represents lower performance state. This patch adds two new genpd APIs: - int dev_pm_genpd_has_performance_state(struct device *dev) This can be called (only once) by the device drivers to make sure all dependencies are met and the PM domain of the device supports performance states. - int dev_pm_genpd_update_performance_state(struct device *dev, unsigned long rate); This can be called (any number of times) by the device drivers after they have called dev_pm_genpd_has_performance_state() once and it returned "true". This call will update the performance state of the PM domain of the device (for which this routine is called) and propagate it to the masters of the PM domain. This requires certain callbacks to be available for the genpd of the device, which are internally called by this routine in the order in which they are described below. - dev_get_performance_state() This shall return the performance state (integer value) corresponding to a target frequency for the device. This state is used by the genpd core as device's requested performance state and would be used while aggregating the requested states of all the devices and subdomains for a PM domain. Note that the same state value will be used by the device's PM domain and its masters hierarchy. We may want to implement master specific states later on once we have more complex cases available. Providing this callback is mandatory for any genpd which needs to manage performance states and is registered as master of one or more devices. Domains which only have sub domains and no devices, should not implement this callback. - genpd_set_performance_state() The aggregate of the performance states of the devices and subdomains of a PM genpd is then passed to this callback, which must change the performance state of the genpd. This callback of the masters of the genpd are also called to propagate the change. The power domains can avoid supplying these callbacks, if they don't support setting performance-states. Tested-by: Rajendra Nayak Signed-off-by: Viresh Kumar --- drivers/base/power/domain.c | 284 +++++++++++++++++++++++++++++++++++++++++++- include/linux/pm_domain.h | 23 ++++ 2 files changed, 305 insertions(+), 2 deletions(-) -- 2.13.0.71.gd7076ec9c9cb diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 43fd08e50ae9..5f50d5295cd4 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -237,6 +237,274 @@ static void genpd_update_accounting(struct generic_pm_domain *genpd) static inline void genpd_update_accounting(struct generic_pm_domain *genpd) {} #endif +/** + * dev_pm_genpd_has_performance_state - Checks if power domain does performance + * state management. + * + * @dev: Device whose power domain is getting inquired. + * + * This can be called by the user drivers, before they start calling + * dev_pm_genpd_update_performance_state(), to guarantee that all dependencies + * are met and the device's genpd supports performance states. + * + * It is assumed that the user driver guarantees that the genpd wouldn't be + * detached while this routine is getting called. + * + * Returns "true" if device's genpd supports performance states, "false" + * otherwise. + */ +bool dev_pm_genpd_has_performance_state(struct device *dev) +{ + struct generic_pm_domain *genpd = genpd_lookup_dev(dev); + + return !IS_ERR(genpd) && genpd->dev_get_performance_state; +} +EXPORT_SYMBOL_GPL(dev_pm_genpd_has_performance_state); + +static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd, + int state, int depth); + +/* Returns -ve errors or 0 on success */ +static int _genpd_set_performance_state(struct generic_pm_domain *genpd, + int state, int depth) +{ + struct generic_pm_domain *master; + struct gpd_link *link; + int prev = genpd->performance_state, ret; + + if (genpd->genpd_set_performance_state) { + ret = genpd->genpd_set_performance_state(genpd, state); + if (ret) + return ret; + } + + /* Propagate to masters of genpd */ + list_for_each_entry(link, &genpd->slave_links, slave_node) { + master = link->master; + + genpd_lock_nested(master, depth + 1); + + link->performance_state = state; + ret = _genpd_reeval_performance_state(master, state, depth + 1); + if (ret) + link->performance_state = prev; + + genpd_unlock(master); + + if (ret) + goto err; + } + + /* + * The masters are updated now, lets get genpd performance_state in sync + * with those. + */ + genpd->performance_state = state; + return 0; + +err: + /* Encountered an error, lets rollback */ + list_for_each_entry_continue_reverse(link, &genpd->slave_links, + slave_node) { + master = link->master; + + genpd_lock_nested(master, depth + 1); + link->performance_state = prev; + if (_genpd_reeval_performance_state(master, prev, depth + 1)) { + pr_err("%s: Failed to roll back to %d performance state\n", + master->name, prev); + } + genpd_unlock(master); + } + + if (genpd->genpd_set_performance_state) { + if (genpd->genpd_set_performance_state(genpd, prev)) { + pr_err("%s: Failed to roll back to %d performance state\n", + genpd->name, prev); + } + } + + return ret; +} + +/* + * Re-evaluate performance state of a genpd. Finds the highest requested + * performance state by the devices and subdomains within the genpd and then + * change genpd's performance state (if required). The request is then + * propagated to the masters of the genpd. + * + * @genpd: PM domain whose state needs to be reevaluated. + * @state: Newly requested performance state of the device or subdomain for + * which this routine is called. + * @depth: nesting count for lockdep. + * + * Locking rules followed are: + * + * - Device's state (pd_data->performance_state) should be accessed from within + * its master's lock protected section. + * + * - Subdomains have a separate state field (link->performance_state) per master + * domain and is accessed only from within master's lock protected section. + * + * - Subdomain's state (genpd->performance_state) should be accessed from within + * its own lock protected section. + * + * - The locks are always taken in bottom->up order, i.e. subdomain first, + * followed by its masters. + * + * Returns -ve errors or 0 on success. + */ +static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd, + int state, int depth) +{ + struct generic_pm_domain_data *pd_data; + struct pm_domain_data *pdd; + struct gpd_link *link; + + /* New requested state is same as Max requested state */ + if (state == genpd->performance_state) + return 0; + + /* New requested state is higher than Max requested state */ + if (state > genpd->performance_state) + goto update_state; + + /* Traverse all devices within the domain */ + list_for_each_entry(pdd, &genpd->dev_list, list_node) { + pd_data = to_gpd_data(pdd); + + if (pd_data->performance_state > state) + state = pd_data->performance_state; + } + + /* + * Traverse all subdomains within the domain. This can be done without + * any additional locks as all link->performance_state fields are + * protected by genpd->lock, which is already taken. + */ + list_for_each_entry(link, &genpd->master_links, master_node) { + if (link->performance_state > state) + state = link->performance_state; + } + +update_state: + return _genpd_set_performance_state(genpd, state, depth); +} + +static void __genpd_dev_update_performance_state(struct device *dev, int state) +{ + struct generic_pm_domain_data *gpd_data; + + spin_lock_irq(&dev->power.lock); + + if (!dev->power.subsys_data || !dev->power.subsys_data->domain_data) { + WARN_ON(1); + goto unlock; + } + + gpd_data = to_gpd_data(dev->power.subsys_data->domain_data); + gpd_data->performance_state = state; + +unlock: + spin_unlock_irq(&dev->power.lock); +} + +/** + * dev_pm_genpd_update_performance_state - Update performance state of device's + * power domain for the target frequency for the device. + * + * @dev: Device for which the performance-state needs to be adjusted. + * @rate: Device's next frequency. This can be set as 0 when the device doesn't + * have any performance state constraints left (And so the device wouldn't + * participate anymore to find the target performance state of the genpd). + * + * The user drivers may want to call dev_pm_genpd_has_performance_state() (only + * once) before calling this routine (any number of times) to guarantee that all + * dependencies are met. + * + * It is assumed that the user driver guarantees that the genpd wouldn't be + * detached while this routine is getting called. + * + * Returns 0 on success and negative error values on failures. + */ +int dev_pm_genpd_update_performance_state(struct device *dev, + unsigned long rate) +{ + struct generic_pm_domain *genpd; + int ret, state; + + genpd = dev_to_genpd(dev); + if (IS_ERR(genpd)) + return -ENODEV; + + genpd_lock(genpd); + + if (!genpd_status_on(genpd)) { + ret = -EBUSY; + goto unlock; + } + + state = genpd->dev_get_performance_state(dev, rate); + if (state < 0) { + ret = state; + goto unlock; + } + + ret = _genpd_reeval_performance_state(genpd, state, 0); + if (!ret) { + /* + * Since we are passing "state" to + * _genpd_reeval_performance_state() as well, we don't need to + * call __genpd_dev_update_performance_state() before updating + * genpd's state with the above call. Update it only after the + * state of master domain is updated. + */ + __genpd_dev_update_performance_state(dev, state); + } + +unlock: + genpd_unlock(genpd); + + return ret; +} +EXPORT_SYMBOL_GPL(dev_pm_genpd_update_performance_state); + +static int _genpd_on_update_performance_state(struct generic_pm_domain *genpd, + int depth) +{ + int ret, prev = genpd->prev_performance_state; + + if (likely(!prev)) + return 0; + + ret = _genpd_set_performance_state(genpd, prev, depth); + if (ret) { + pr_err("%s: Failed to restore performance state to %d (%d)\n", + genpd->name, prev, ret); + } else { + genpd->prev_performance_state = 0; + } + + return ret; +} + +static void _genpd_off_update_performance_state(struct generic_pm_domain *genpd, + int depth) +{ + int ret, state = genpd->performance_state; + + if (likely(!state)) + return; + + ret = _genpd_set_performance_state(genpd, 0, depth); + if (ret) { + pr_err("%s: Failed to set performance state to 0 (%d)\n", + genpd->name, ret); + } else { + genpd->prev_performance_state = state; + } +} + static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed) { unsigned int state_idx = genpd->state_idx; @@ -388,6 +656,8 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on, return ret; } + _genpd_off_update_performance_state(genpd, depth); + genpd->status = GPD_STATE_POWER_OFF; genpd_update_accounting(genpd); @@ -437,15 +707,21 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth) } } - ret = _genpd_power_on(genpd, true); + ret = _genpd_on_update_performance_state(genpd, depth); if (ret) goto err; + ret = _genpd_power_on(genpd, true); + if (ret) + goto err_power_on; + genpd->status = GPD_STATE_ACTIVE; genpd_update_accounting(genpd); return 0; + err_power_on: + _genpd_off_update_performance_state(genpd, depth); err: list_for_each_entry_continue_reverse(link, &genpd->slave_links, @@ -807,6 +1083,8 @@ static void genpd_sync_power_off(struct generic_pm_domain *genpd, bool use_lock, if (_genpd_power_off(genpd, false)) return; + _genpd_off_update_performance_state(genpd, depth); + genpd->status = GPD_STATE_POWER_OFF; list_for_each_entry(link, &genpd->slave_links, slave_node) { @@ -852,7 +1130,9 @@ static void genpd_sync_power_on(struct generic_pm_domain *genpd, bool use_lock, genpd_unlock(link->master); } - _genpd_power_on(genpd, false); + if (!_genpd_on_update_performance_state(genpd, depth)) + if (_genpd_power_on(genpd, false)) + _genpd_off_update_performance_state(genpd, depth); genpd->status = GPD_STATE_ACTIVE; } diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 84f423d5633e..715cca7ac399 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -64,8 +64,13 @@ struct generic_pm_domain { unsigned int device_count; /* Number of devices */ unsigned int suspended_count; /* System suspend device counter */ unsigned int prepared_count; /* Suspend counter of prepared devices */ + unsigned int performance_state; /* Max requested performance state */ + unsigned int prev_performance_state; /* Performance state before power off */ int (*power_off)(struct generic_pm_domain *domain); int (*power_on)(struct generic_pm_domain *domain); + int (*dev_get_performance_state)(struct device *dev, unsigned long rate); + int (*genpd_set_performance_state)(struct generic_pm_domain *genpd, + unsigned int state); struct gpd_dev_ops dev_ops; s64 max_off_time_ns; /* Maximum allowed "suspended" time. */ bool max_off_time_changed; @@ -102,6 +107,9 @@ struct gpd_link { struct list_head master_node; struct generic_pm_domain *slave; struct list_head slave_node; + + /* Sub-domain's per-master domain performance state */ + unsigned int performance_state; }; struct gpd_timing_data { @@ -121,6 +129,7 @@ struct generic_pm_domain_data { struct pm_domain_data base; struct gpd_timing_data td; struct notifier_block nb; + unsigned int performance_state; void *data; }; @@ -148,6 +157,9 @@ extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, extern int pm_genpd_init(struct generic_pm_domain *genpd, struct dev_power_governor *gov, bool is_off); extern int pm_genpd_remove(struct generic_pm_domain *genpd); +extern bool dev_pm_genpd_has_performance_state(struct device *dev); +extern int dev_pm_genpd_update_performance_state(struct device *dev, + unsigned long rate); extern struct dev_power_governor simple_qos_governor; extern struct dev_power_governor pm_domain_always_on_gov; @@ -188,6 +200,17 @@ static inline int pm_genpd_remove(struct generic_pm_domain *genpd) return -ENOTSUPP; } +static inline bool dev_pm_genpd_has_performance_state(struct device *dev) +{ + return false; +} + +static inline int dev_pm_genpd_update_performance_state(struct device *dev, + unsigned long rate) +{ + return -ENOTSUPP; +} + #define simple_qos_governor (*(struct dev_power_governor *)(NULL)) #define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL)) #endif From patchwork Wed Aug 2 10:12:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 109202 Delivered-To: patch@linaro.org Received: by 10.140.101.6 with SMTP id t6csp2590590qge; Wed, 2 Aug 2017 03:13:00 -0700 (PDT) X-Received: by 10.84.139.195 with SMTP id 61mr3104518plr.445.1501668780715; Wed, 02 Aug 2017 03:13:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1501668780; cv=none; d=google.com; s=arc-20160816; b=u2DYk2YBWWW1oLxemptq5TPL19Hw/heO/HWx/yCLHnJtl/1JiUh9FE9CmBzFHH7Mnp tFJsW7jEsNjmIT3WpLNdaHt7prPlfA7IgUf05H3SYk+UvXfxC6igSfNVXEeoBBmT+E+l Qaah+539VdZvjLeo6SDQ/E7Udxg23VBcrnJLb2fwx4fmDweNiXyUDnFT5PMwfiwTsfCm z9VMGrDzc5+ky34Dh9xIs9c09WVLub+NIXMFt2Gh/q2r9JnsanTPwmps1jjJ3W3U5bp3 AnvpHTH8ebU05wWAQ0UhEfaSBbU67rKUyH32x9wtqgPtDgW3s3cloyWF4i7DRTuZQGuA Zh0g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=WBUWgEGGVTFYaONG0MiR/7EKcbkcCHMjIM/+DeFBQAM=; b=ZZKlIqhxq/bAIHx9Hed0/o1PmVxfESAsYfH3BatMPr4VHWRdRn7gJOjw1bnIZQNUsQ VE3YqgQqOQPYfLPljHcDhoXEd5/0XzpdPBl48zd5BOkmgUwLTy0WXao/WIxg7hCJeRXL okF/m38bP1FfVyZchUefWp+4V+g/n8vBiRCuH+wIeDtAi6eLWE2rGfB1Vg/+TRMmrx1p Z0icWcjau/hWTjz/HBeff0oykktnztWD/0dJpG+TP7mH8p0zz/zqiLhVZsXxD/V7z+wA 6/aucKRD3fnWw9DjgegZLrVjVP5NLnxK/5Z/LB946a/3PXgFzmnaOPSCbgMuaZx92Jjz D54A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=kQSVLLo6; 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 x11si21418147plm.792.2017.08.02.03.13.00; Wed, 02 Aug 2017 03:13:00 -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=kQSVLLo6; 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 S1752832AbdHBKM4 (ORCPT + 25 others); Wed, 2 Aug 2017 06:12:56 -0400 Received: from mail-pg0-f48.google.com ([74.125.83.48]:36185 "EHLO mail-pg0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751991AbdHBKMv (ORCPT ); Wed, 2 Aug 2017 06:12:51 -0400 Received: by mail-pg0-f48.google.com with SMTP id v77so13742488pgb.3 for ; Wed, 02 Aug 2017 03:12:51 -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:in-reply-to:references :in-reply-to:references; bh=WBUWgEGGVTFYaONG0MiR/7EKcbkcCHMjIM/+DeFBQAM=; b=kQSVLLo60hXIxt9Tr2yPz82R3myHORX0Fu0lNzRYQFquBVQBrt7+skzqPZoE5lt2KT FdLJgEwoz4brrsWkH0b7Nk9JZmO+LC0ABn7NvYelpE4o84BH8Z/taQ7jvYfGVyky12kh vs2bh0LU8ydATdZN+7/RrbR5bCy34BxCAmJPM= 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:in-reply-to :references:in-reply-to:references; bh=WBUWgEGGVTFYaONG0MiR/7EKcbkcCHMjIM/+DeFBQAM=; b=Y2lBqlMeGPIg1hCXCwXfFRv0UvuyhPTiZ11K1j18k2ljk1XpBzakeJIJrYI82trE+u WjKvrFTbFbMPlM6c7dnHypLDEE/ESyYyB2S5dPKl7ASErt1hqHwK1MNw+tfEBCsn1EAG pg7gd44otFKsBnOAg1RhNVVRND2DD0cNYQRP6Vq2gkVNCMeF5+uOWjw/TcmZjWcoDIsC pd+weJKGIl6ZyoE/9NwlB9CCvsuO/cw7E4lqiuSjz/pai9JhhVMSF011Xm9MWHUsx+En w+5yLdB7jAUtV1tjo9XtOdwhMgkzHAg64kXv29GRfwAIZv+ARzMgc+EoE8gE7p4Pg/ae yi3w== X-Gm-Message-State: AIVw1139bgDGDSMnxCUxuv8D+0vD9L8rQt4Tj0JEnmEHBHt7nEa9k0D/ 8ym4M5C9K3K7lq3w X-Received: by 10.99.117.94 with SMTP id f30mr22863858pgn.366.1501668770756; Wed, 02 Aug 2017 03:12:50 -0700 (PDT) Received: from localhost ([122.171.108.183]) by smtp.gmail.com with ESMTPSA id s4sm4892202pfk.71.2017.08.02.03.12.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 02 Aug 2017 03:12:50 -0700 (PDT) From: Viresh Kumar To: Rafael Wysocki , ulf.hansson@linaro.org, Kevin Hilman Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Stephen Boyd , Nishanth Menon , robh+dt@kernel.org, lina.iyer@linaro.org, rnayak@codeaurora.org, sudeep.holla@arm.com, linux-kernel@vger.kernel.org, Len Brown , Pavel Machek , Andy Gross , David Brown Subject: [PATCH V9 2/7] PM / Domains: Catch missing genpd_set_performance_state() in masters Date: Wed, 2 Aug 2017 15:42:33 +0530 Message-Id: <565fee348107f84f643c8f1a37a90a41654ea707.1501668354.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.13.0.71.gd7076ec9c9cb In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch catches the cases where dev_get_performance_state() callback is implemented for a genpd, but none of its masters or their masters (and so on) have implemented genpd_set_performance_state() callback. The internal performance state routines don't return 0 anymore for success, rather they return count of the domains whose performance state is updated and the top level routine checks for that. A zero value there would indicate that the genpd_set_performance_state() callbacks are missing in the master hierarchy of the device. This adds very little burden on the API and can be pretty useful. Tested-by: Rajendra Nayak Signed-off-by: Viresh Kumar --- drivers/base/power/domain.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) -- 2.13.0.71.gd7076ec9c9cb diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 5f50d5295cd4..0922679c1d43 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -264,18 +264,20 @@ EXPORT_SYMBOL_GPL(dev_pm_genpd_has_performance_state); static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd, int state, int depth); -/* Returns -ve errors or 0 on success */ +/* Returns -ve errors or number of domains whose performance is set */ static int _genpd_set_performance_state(struct generic_pm_domain *genpd, int state, int depth) { struct generic_pm_domain *master; struct gpd_link *link; - int prev = genpd->performance_state, ret; + int prev = genpd->performance_state, ret, count = 0; if (genpd->genpd_set_performance_state) { ret = genpd->genpd_set_performance_state(genpd, state); if (ret) return ret; + + count = 1; } /* Propagate to masters of genpd */ @@ -286,13 +288,15 @@ static int _genpd_set_performance_state(struct generic_pm_domain *genpd, link->performance_state = state; ret = _genpd_reeval_performance_state(master, state, depth + 1); - if (ret) + if (ret < 0) link->performance_state = prev; genpd_unlock(master); - if (ret) + if (ret < 0) goto err; + + count += ret; } /* @@ -300,7 +304,7 @@ static int _genpd_set_performance_state(struct generic_pm_domain *genpd, * with those. */ genpd->performance_state = state; - return 0; + return count; err: /* Encountered an error, lets rollback */ @@ -310,7 +314,7 @@ static int _genpd_set_performance_state(struct generic_pm_domain *genpd, genpd_lock_nested(master, depth + 1); link->performance_state = prev; - if (_genpd_reeval_performance_state(master, prev, depth + 1)) { + if (_genpd_reeval_performance_state(master, prev, depth + 1) < 0) { pr_err("%s: Failed to roll back to %d performance state\n", master->name, prev); } @@ -352,7 +356,7 @@ static int _genpd_set_performance_state(struct generic_pm_domain *genpd, * - The locks are always taken in bottom->up order, i.e. subdomain first, * followed by its masters. * - * Returns -ve errors or 0 on success. + * Returns -ve errors or number of domains whose performance is set. */ static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd, int state, int depth) @@ -361,9 +365,14 @@ static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd, struct pm_domain_data *pdd; struct gpd_link *link; - /* New requested state is same as Max requested state */ - if (state == genpd->performance_state) - return 0; + if (state == genpd->performance_state) { + /* + * New requested state is same as Max requested state, return 1 + * to distinguish from the case where none of the masters have + * set their genpd_set_performance_state() callback. + */ + return 1; + } /* New requested state is higher than Max requested state */ if (state > genpd->performance_state) @@ -451,7 +460,7 @@ int dev_pm_genpd_update_performance_state(struct device *dev, } ret = _genpd_reeval_performance_state(genpd, state, 0); - if (!ret) { + if (ret > 0) { /* * Since we are passing "state" to * _genpd_reeval_performance_state() as well, we don't need to @@ -460,6 +469,11 @@ int dev_pm_genpd_update_performance_state(struct device *dev, * state of master domain is updated. */ __genpd_dev_update_performance_state(dev, state); + ret = 0; + } else { + WARN(!ret, "%s: None of %s and its masters have provided genpd_set_performance_state()\n", + __func__, genpd->name); + ret = -ENODEV; } unlock: @@ -478,7 +492,7 @@ static int _genpd_on_update_performance_state(struct generic_pm_domain *genpd, return 0; ret = _genpd_set_performance_state(genpd, prev, depth); - if (ret) { + if (ret < 0) { pr_err("%s: Failed to restore performance state to %d (%d)\n", genpd->name, prev, ret); } else { @@ -497,7 +511,7 @@ static void _genpd_off_update_performance_state(struct generic_pm_domain *genpd, return; ret = _genpd_set_performance_state(genpd, 0, depth); - if (ret) { + if (ret < 0) { pr_err("%s: Failed to set performance state to 0 (%d)\n", genpd->name, ret); } else { From patchwork Wed Aug 2 10:12:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 109203 Delivered-To: patch@linaro.org Received: by 10.140.101.6 with SMTP id t6csp2590631qge; Wed, 2 Aug 2017 03:13:04 -0700 (PDT) X-Received: by 10.84.229.1 with SMTP id b1mr25216567plk.273.1501668784180; Wed, 02 Aug 2017 03:13:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1501668784; cv=none; d=google.com; s=arc-20160816; b=HZfBzGsjFHLafE3/zzaqqhB4NJdVRAigU3P51WI1ta2GYbFuOFArJnMo2ukY2x/QjK a9zTU2iWXfTFC7S4BQL5ArUs9qc18q/X1nXRYU9WJnlzAF+QKGfw6ubLLoBreZnflIPX ln+0Kinb7t2wS6V+djj9OQ6nei5YejAc19cr5OYTEdyGzsfgym0bRVevLE9jHrFQoLqD 5ZoXSdqxMbzr9//P+TIJpQ/HIgHTn1zXO1T4GJ4fEqrTRLWawkZAKxxmftSM0lfn6xCw ZU52lHUe80wu6m/jfjGnFsNSrTSGwRlw+JWQX9mQA5kCdYzpSM4Yb/5I7ydXZ0zapd1w J9lQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=EhWBq9fcTg0cVmqOO3xYhUelkN5ezozYqIyR+ZDxbEg=; b=hKlAghZoPb+tpM2KhetX2AQ9D/skO9lA3ANps7Zc8cw1DbxFWIOzBZa5W/iiEHqHbU zmVhxzQ6xZXV0cY4F7dkPF8pj5acTQnnpcwNKRepQ/Ajo3/qvdcxjqARw0rPi6RnyZqW YM2yXzUKPCdFT5aZn4RsMiYyHCTiOsz2BjaaBrcEm642r3kMdTSX5um0Z++8l8iipmUI FJV9Jsz16XIiOlCUE3hFCU3UhpJRPZcvfVZwOICq8rI7jpPIzjPT/XaXNViT3XIOcZu9 7NM2vmfj2o0FW3O2/azCgtqjgbSsVVVDaIt/EEymDDvplYnHIqzeAlViXN9HBlAE3+44 5gnQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=U/ZUdu3X; 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 t124si17038144pgt.629.2017.08.02.03.13.03; Wed, 02 Aug 2017 03:13: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=U/ZUdu3X; 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 S1752870AbdHBKNA (ORCPT + 25 others); Wed, 2 Aug 2017 06:13:00 -0400 Received: from mail-pf0-f172.google.com ([209.85.192.172]:36039 "EHLO mail-pf0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752820AbdHBKM5 (ORCPT ); Wed, 2 Aug 2017 06:12:57 -0400 Received: by mail-pf0-f172.google.com with SMTP id z129so19285297pfb.3 for ; Wed, 02 Aug 2017 03:12:56 -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:in-reply-to:references :in-reply-to:references; bh=EhWBq9fcTg0cVmqOO3xYhUelkN5ezozYqIyR+ZDxbEg=; b=U/ZUdu3XU1+sOmZ60iqYN2fymZCE6lQNscvS66R/jCWv2j7a6raZvMtZDiZtS4IoGp DdgSMN4CQYmraQ+QrFghNCNTAZbV3PapzvgXkeqhzEiHeNh371MrBDM+qcHFO3sWExKZ P9Ha6Ujz9SPTVrjWLiyhBJrVI3pyalYisDzIw= 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:in-reply-to :references:in-reply-to:references; bh=EhWBq9fcTg0cVmqOO3xYhUelkN5ezozYqIyR+ZDxbEg=; b=cdisXjBZJ1oxfA+7YL8x1gZ9/kwLQeg30/04wkHeItcxe54EEvYs3RrCUzvCt4TU+Y r/LG1UHooAB0OUnRNYg/wDqYyKgD+lFklAvbdZXntOZgZLKSUS3jqCNW+oEgPBP/aOky iuctcYpdXY2n1SV2km8t7UP2ILtjHkAJIthZGawOJrGIvzPVo8G4ap8J88Cby9O8xggb SE9GezyWLnKkGM27Toewqsmu0iC6w/84WAJtOAqaNtE3NzfwoORvLsHitW6PJB/v3Kft 9zmUiBqk6VhrByLH429jY62BCHUHlP7ZCM9QTvQO/3KXRj4EleJZXtUusoGxYi7NhiF8 CdFg== X-Gm-Message-State: AIVw110oheNNvAuPc696Bp+ptm5koQtkps9/QLh6qOiR1y4xQN1hBFFz HQJG779DT4idtm4k X-Received: by 10.98.153.72 with SMTP id d69mr21968278pfe.42.1501668776285; Wed, 02 Aug 2017 03:12:56 -0700 (PDT) Received: from localhost ([122.171.108.183]) by smtp.gmail.com with ESMTPSA id d4sm38706920pfj.59.2017.08.02.03.12.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 02 Aug 2017 03:12:55 -0700 (PDT) From: Viresh Kumar To: Rafael Wysocki , ulf.hansson@linaro.org, Kevin Hilman Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Stephen Boyd , Nishanth Menon , robh+dt@kernel.org, lina.iyer@linaro.org, rnayak@codeaurora.org, sudeep.holla@arm.com, linux-kernel@vger.kernel.org, Len Brown , Pavel Machek , Andy Gross , David Brown Subject: [PATCH V9 4/7] soc: qcom: rpmpd: Add a powerdomain driver to model cx/mx powerdomains Date: Wed, 2 Aug 2017 15:42:35 +0530 Message-Id: X-Mailer: git-send-email 2.13.0.71.gd7076ec9c9cb In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Rajendra Nayak THIS IS TEST CODE, SHOULDN'T BE MERGED. The cx/mx powerdomains just pass the performance state set by the consumers to the RPM (Remote Power manager) which then takes care of setting the appropriate voltage on the corresponding rails to meet the performance needs. Add data for all powerdomains on msm8996. NOT-signed-off-by: Rajendra Nayak NOT-signed-off-by: Viresh Kumar --- .../devicetree/bindings/power/qcom,rpmpd.txt | 10 + arch/arm64/boot/dts/qcom/msm8996.dtsi | 5 + drivers/soc/qcom/Kconfig | 9 + drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/rpmpd.c | 307 +++++++++++++++++++++ 5 files changed, 332 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/qcom,rpmpd.txt create mode 100644 drivers/soc/qcom/rpmpd.c -- 2.13.0.71.gd7076ec9c9cb diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt new file mode 100644 index 000000000000..8b48ce57a563 --- /dev/null +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt @@ -0,0 +1,10 @@ +Qualcomm RPM Powerdomains + +* For RPM powerdomains, we communicate a performance state to RPM +which then translates it into a corresponding voltage on a rail + +Required Properties: + - compatible: Should be one of the following + * qcom,rpmpd-msm8996: RPM Powerdomain for the msm8996 family of SoC + - power-domain-cells: number of cells in power domain specifier + must be 1. diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index 8f085716e258..0ce9ea514cd1 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -418,6 +418,11 @@ status = "disabled"; }; + rpmpd: qcom,rpmpd { + compatible = "qcom,rpmpd-msm8996", "qcom,rpmpd"; + #power-domain-cells = <1>; + }; + sdhc2: sdhci@74a4900 { status = "disabled"; compatible = "qcom,sdhci-msm-v4"; diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 9fca977ef18d..3892148be3c3 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -24,6 +24,15 @@ config QCOM_PM modes. It interface with various system drivers to put the cores in low power modes. +config QCOM_RPMPD + tristate "Qualcomm RPM Powerdomain driver" + depends on MFD_QCOM_RPM && QCOM_SMD_RPM + help + QCOM RPM powerdomain driver to support powerdomain with + performance states. The driver communicates a performance state + value to RPM which then translates it into corresponding voltage + for the voltage rail. + config QCOM_SMEM tristate "Qualcomm Shared Memory Manager (SMEM)" depends on ARCH_QCOM diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 414f0de274fa..f7c3edfa6de8 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o obj-$(CONFIG_QCOM_SMP2P) += smp2p.o obj-$(CONFIG_QCOM_SMSM) += smsm.o obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o +obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c new file mode 100644 index 000000000000..d34d9c363815 --- /dev/null +++ b/drivers/soc/qcom/rpmpd.c @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd) + +/* Resource types */ +#define RPMPD_SMPA 0x61706d73 +#define RPMPD_LDOA 0x616f646c + +/* Operation Keys */ +#define KEY_CORNER 0x6e726f63 /* corn */ +#define KEY_ENABLE 0x6e657773 /* swen */ +#define KEY_FLOOR_CORNER 0x636676 /* vfc */ + +#define DEFINE_RPMPD_CORN_SMPA(_platform, _name, _active, r_id) \ + static struct rpmpd _platform##_##_active; \ + static struct rpmpd _platform##_##_name = { \ + .pd = { .name = #_name, }, \ + .peer = &_platform##_##_active, \ + .res_type = RPMPD_SMPA, \ + .res_id = r_id, \ + .key = KEY_CORNER, \ + }; \ + static struct rpmpd _platform##_##_active = { \ + .pd = { .name = #_active, }, \ + .peer = &_platform##_##_name, \ + .active_only = true, \ + .res_type = RPMPD_SMPA, \ + .res_id = r_id, \ + .key = KEY_CORNER, \ + } + +#define DEFINE_RPMPD_CORN_LDOA(_platform, _name, r_id) \ + static struct rpmpd _platform##_##_name = { \ + .pd = { .name = #_name, }, \ + .res_type = RPMPD_LDOA, \ + .res_id = r_id, \ + .key = KEY_CORNER, \ + } + +#define DEFINE_RPMPD_VFC(_platform, _name, r_id, r_type) \ + static struct rpmpd _platform##_##_name = { \ + .pd = { .name = #_name, }, \ + .res_type = r_type, \ + .res_id = r_id, \ + .key = KEY_FLOOR_CORNER, \ + } + +#define DEFINE_RPMPD_VFC_SMPA(_platform, _name, r_id) \ + DEFINE_RPMPD_VFC(_platform, _name, r_id, RPMPD_SMPA) + +#define DEFINE_RPMPD_VFC_LDOA(_platform, _name, r_id) \ + DEFINE_RPMPD_VFC(_platform, _name, r_id, RPMPD_LDOA) + +struct rpmpd_req { + __le32 key; + __le32 nbytes; + __le32 value; +}; + +struct rpmpd { + struct generic_pm_domain pd; + struct rpmpd *peer; + const bool active_only; + unsigned long corner; + bool enabled; + const char *res_name; + const int res_type; + const int res_id; + struct qcom_smd_rpm *rpm; + __le32 key; +}; + +struct rpmpd_desc { + struct rpmpd **rpmpds; + size_t num_pds; +}; + +static DEFINE_MUTEX(rpmpd_lock); + +/* msm8996 RPM powerdomains */ +DEFINE_RPMPD_CORN_SMPA(msm8996, vddcx, vddcx_ao, 1); +DEFINE_RPMPD_CORN_SMPA(msm8996, vddmx, vddmx_ao, 2); +DEFINE_RPMPD_CORN_LDOA(msm8996, vddsscx, 26); + +DEFINE_RPMPD_VFC_SMPA(msm8996, vddcx_vfc, 1); +DEFINE_RPMPD_VFC_LDOA(msm8996, vddsscx_vfc, 26); + +static struct rpmpd *msm8996_rpmpds[] = { + [0] = &msm8996_vddcx, + [1] = &msm8996_vddcx_ao, + [2] = &msm8996_vddcx_vfc, + [3] = &msm8996_vddmx, + [4] = &msm8996_vddmx_ao, + [5] = &msm8996_vddsscx, + [6] = &msm8996_vddsscx_vfc, +}; + +static const struct rpmpd_desc msm8996_desc = { + .rpmpds = msm8996_rpmpds, + .num_pds = ARRAY_SIZE(msm8996_rpmpds), +}; + +static const struct of_device_id rpmpd_match_table[] = { + { .compatible = "qcom,rpmpd-msm8996", .data = &msm8996_desc }, + { } +}; +MODULE_DEVICE_TABLE(of, rpmpd_match_table); + +static int rpmpd_send_enable(struct rpmpd *pd, bool enable) +{ + struct rpmpd_req req = { + .key = KEY_ENABLE, + .nbytes = cpu_to_le32(sizeof(u32)), + .value = cpu_to_le32(enable), + }; + + return qcom_rpm_smd_write(pd->rpm, QCOM_RPM_ACTIVE_STATE, pd->res_type, + pd->res_id, &req, sizeof(req)); +} + +static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner) +{ + struct rpmpd_req req = { + .key = pd->key, + .nbytes = cpu_to_le32(sizeof(u32)), + .value = cpu_to_le32(corner), + }; + + return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id, + &req, sizeof(req)); +}; + +static void to_active_sleep(struct rpmpd *pd, unsigned long corner, + unsigned long *active, unsigned long *sleep) +{ + *active = corner; + + if (pd->active_only) + *sleep = 0; + else + *sleep = *active; +} + +static int rpmpd_aggregate_corner(struct rpmpd *pd) +{ + int ret; + struct rpmpd *peer = pd->peer; + unsigned long active_corner, sleep_corner; + unsigned long this_corner = 0, this_sleep_corner = 0; + unsigned long peer_corner = 0, peer_sleep_corner = 0; + + to_active_sleep(pd, pd->corner, &this_corner, &this_sleep_corner); + + if (peer && peer->enabled) + to_active_sleep(peer, peer->corner, &peer_corner, + &peer_sleep_corner); + + active_corner = max(this_corner, peer_corner); + + ret = rpmpd_send_corner(pd, QCOM_RPM_ACTIVE_STATE, active_corner); + if (ret) + return ret; + + sleep_corner = max(this_sleep_corner, peer_sleep_corner); + + return rpmpd_send_corner(pd, QCOM_RPM_SLEEP_STATE, sleep_corner); +} + +static int rpmpd_power_on(struct generic_pm_domain *domain) +{ + int ret; + struct rpmpd *pd = domain_to_rpmpd(domain); + + mutex_lock(&rpmpd_lock); + + ret = rpmpd_send_enable(pd, true); + if (ret) + goto out; + + pd->enabled = true; + + if (pd->corner) + ret = rpmpd_aggregate_corner(pd); + +out: + mutex_unlock(&rpmpd_lock); + + return ret; +} + +static int rpmpd_power_off(struct generic_pm_domain *domain) +{ + int ret; + struct rpmpd *pd = domain_to_rpmpd(domain); + + mutex_lock(&rpmpd_lock); + + ret = rpmpd_send_enable(pd, false); + if (!ret) + pd->enabled = false; + + mutex_unlock(&rpmpd_lock); + + return ret; +} + +static int rpmpd_probe(struct platform_device *pdev) +{ + int i; + size_t num; + struct genpd_onecell_data *data; + struct qcom_smd_rpm *rpm; + struct rpmpd **rpmpds; + const struct rpmpd_desc *desc; + + rpm = dev_get_drvdata(pdev->dev.parent); + if (!rpm) { + dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n"); + return -ENODEV; + } + + desc = of_device_get_match_data(&pdev->dev); + if (!desc) + return -EINVAL; + + rpmpds = desc->rpmpds; + num = desc->num_pds; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains), + GFP_KERNEL); + data->num_domains = num; + + for (i = 0; i < num; i++) { + if (!rpmpds[i]) + continue; + + rpmpds[i]->rpm = rpm; + rpmpds[i]->pd.power_off = rpmpd_power_off; + rpmpds[i]->pd.power_on = rpmpd_power_on; + pm_genpd_init(&rpmpds[i]->pd, NULL, true); + + data->domains[i] = &rpmpds[i]->pd; + } + + return of_genpd_add_provider_onecell(pdev->dev.of_node, data); +} + +static int rpmpd_remove(struct platform_device *pdev) +{ + of_genpd_del_provider(pdev->dev.of_node); + return 0; +} + +static struct platform_driver rpmpd_driver = { + .driver = { + .name = "qcom-rpmpd", + .of_match_table = rpmpd_match_table, + }, + .probe = rpmpd_probe, + .remove = rpmpd_remove, +}; + +static int __init rpmpd_init(void) +{ + return platform_driver_register(&rpmpd_driver); +} +core_initcall(rpmpd_init); + +static void __exit rpmpd_exit(void) +{ + platform_driver_unregister(&rpmpd_driver); +} +module_exit(rpmpd_exit); + +MODULE_DESCRIPTION("Qualcomm RPM Power Domain Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:qcom-rpmpd"); From patchwork Wed Aug 2 10:12:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 109206 Delivered-To: patch@linaro.org Received: by 10.140.101.6 with SMTP id t6csp2591184qge; Wed, 2 Aug 2017 03:13:37 -0700 (PDT) X-Received: by 10.98.144.135 with SMTP id q7mr7547727pfk.229.1501668817715; Wed, 02 Aug 2017 03:13:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1501668817; cv=none; d=google.com; s=arc-20160816; b=DxIe+rxo/uhjhrpXpBfNNKs+q+GAsE5jnBukGkqDLxP4Jj9cS3czrpeKYO1wYCVQ/k mDrizE2b7kJ//Djo/TT964vRvy/q1jYa4IlxLR5Ok6ag67DhH1tB4FTdhogAXede2p+t hBWz91fQ8xSMyEJr5QZ5PJaGmLl9VeFFyh+NZ27/MrHj6mrFVgN8+fCycf0B4d0WDZfD Go53DeikyeaNxkRPhAJZ9Igj6+xrSZfNRvHWisTxhz1wvArtj+lKQeYsaKwW4EpLkIsm a7kaSJUkfuEOgoZ8Tf2ljb6bxyECQ3Mus8OiB30FvEDHtX1Tfq7HeoEy2awTva5FtpcP /Xnw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=7WVHJW/q7IWlyzxQF0UA+Z7F29XuErZmWFY/9A/KKBo=; b=jAvb4SNICaQmaBoZejQfo6DtYMGzAylUUUX2YJB/WmZVq2P+hnj/Y6oyv7tyr8YxIN u96hEyN8fbxeEIpgFn2fbIHMBQH0px+WYAbRq5hG0AHp5JXdhDnit23uFBWiO1E3bQCI pVVBtzlbqeEVj8Slydz8vVHiL4yP2SkbFp1N2RYg0kSPWGLp69tdlq2f+7mx6UpwCrNP VD7KA3JKeLqiSY/8od+h38eaJSfHvmt4XHo75y0MLGRJwQgQktKB+P6g6uopqqAAbwFc UmABX/0k2GDWYMesmNVMTURaXZ6e9kXHwVeTMbMabrYbirQ40rEHdcs60msTh5MKHRFS +6Og== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=DGUonGfU; 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 p190si11634707pga.102.2017.08.02.03.13.37; Wed, 02 Aug 2017 03:13:37 -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=DGUonGfU; 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 S1752991AbdHBKNf (ORCPT + 25 others); Wed, 2 Aug 2017 06:13:35 -0400 Received: from mail-pf0-f174.google.com ([209.85.192.174]:34203 "EHLO mail-pf0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752846AbdHBKM7 (ORCPT ); Wed, 2 Aug 2017 06:12:59 -0400 Received: by mail-pf0-f174.google.com with SMTP id o86so15897389pfj.1 for ; Wed, 02 Aug 2017 03:12: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:in-reply-to:references :in-reply-to:references; bh=7WVHJW/q7IWlyzxQF0UA+Z7F29XuErZmWFY/9A/KKBo=; b=DGUonGfUTdtHht4JG749JDZb1zh2Wwr++Q/kP6RS5b3RsSuUdMkyXgsgvSoCgNf6be 6gf4NLSLP2Q3I7oFvP43KkXm3AXE6yVMQ9eLYLH6un1kiZ4woN+DExKnjkDRQ0cn6i8S wm1DKBefJwRBK5V8F4hNc9Ir0aIHSekkQpjdg= 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:in-reply-to :references:in-reply-to:references; bh=7WVHJW/q7IWlyzxQF0UA+Z7F29XuErZmWFY/9A/KKBo=; b=TwVe1DCN4aM86voVUEyPkTF0uGfQi/L3YjBPfNR4IO+OlWQmRITo+G8Hdulq7L7tTs CM5rq+KGIlq8sOFk+GBofPOw+wIMPgChjDqCMoUNtIpXFMON1j093Wu3EK/wFFnT7p5S nykwwfkYE82xLiXo2be+041JY+6MFRJC8lehL0hOuZDdUw4OW1Lf2GDPvmMOBo3RrvGP a4EoVMZMusJnUkVq2ENCdbUdH2IDXSix1QIPfcbHBotdAoXd2tZ4S952lzZ0lcvdFCir rKtQUWO0+pn5qOsuCGhA+WPW2JOQ/NpN0KLTf+IHJp9sbsIH6GH4unfvwuYuIF4o0Nxw bLMw== X-Gm-Message-State: AIVw111dSFW/w6vLb165RZuJjIJD+k9dEp5pWwbelzj7jcQ/32DZOwv2 7/vwBomzzPfdljb+ X-Received: by 10.99.166.17 with SMTP id t17mr22214988pge.60.1501668779018; Wed, 02 Aug 2017 03:12:59 -0700 (PDT) Received: from localhost ([122.171.108.183]) by smtp.gmail.com with ESMTPSA id t24sm5852913pfe.45.2017.08.02.03.12.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 02 Aug 2017 03:12:58 -0700 (PDT) From: Viresh Kumar To: Rafael Wysocki , ulf.hansson@linaro.org, Kevin Hilman Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Stephen Boyd , Nishanth Menon , robh+dt@kernel.org, lina.iyer@linaro.org, rnayak@codeaurora.org, sudeep.holla@arm.com, linux-kernel@vger.kernel.org, Len Brown , Pavel Machek , Andy Gross , David Brown Subject: [PATCH V9 5/7] soc: qcom: rpmpd: Add support for get/set performance state Date: Wed, 2 Aug 2017 15:42:36 +0530 Message-Id: <2cc3c8fecf9bc135b136b176ae4ce73221ee4fb6.1501668354.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.13.0.71.gd7076ec9c9cb In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Rajendra Nayak THIS IS TEST CODE, SHOULDN'T BE MERGED. With genpd now expecting powerdomain drivers supporting performance state to support get/set performance state callbacks, add support for it in the rpmpd driver. NOT-signed-off-by: Rajendra Nayak NOT-signed-off-by: Viresh Kumar --- drivers/soc/qcom/rpmpd.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) -- 2.13.0.71.gd7076ec9c9cb diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index d34d9c363815..4e4f5cda9ce2 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -101,6 +101,20 @@ struct rpmpd_desc { size_t num_pds; }; +enum rpmpd_levels { + NONE, + LOWER, /* SVS2 */ + LOW, /* SVS */ + NOMINAL, /* NOMINAL */ + HIGH, /* Turbo */ + MAX_LEVEL, +}; + +struct rpmpd_freq_map { + struct rpmpd *pd; + unsigned long freq[MAX_LEVEL]; +}; + static DEFINE_MUTEX(rpmpd_lock); /* msm8996 RPM powerdomains */ @@ -126,6 +140,47 @@ static const struct rpmpd_desc msm8996_desc = { .num_pds = ARRAY_SIZE(msm8996_rpmpds), }; +enum msm8996_devices { + SDHCI, + UFS, + PCIE, + USB3, +}; + +static struct rpmpd_freq_map msm8996_rpmpd_freq_map[] = { + [SDHCI] = { + .pd = &msm8996_vddcx, + .freq[LOWER] = 19200000, + .freq[LOW] = 200000000, + .freq[NOMINAL] = 400000000, + }, + [UFS] = { + .pd = &msm8996_vddcx, + .freq[LOWER] = 19200000, + .freq[LOW] = 100000000, + .freq[NOMINAL] = 200000000, + .freq[HIGH] = 240000000, + }, + [PCIE] = { + .pd = &msm8996_vddcx, + .freq[LOWER] = 1011000, + }, + [USB3] = { + .pd = &msm8996_vddcx, + .freq[LOWER] = 60000000, + .freq[LOW] = 120000000, + .freq[NOMINAL] = 150000000, + }, +}; + +static const struct of_device_id rpmpd_performance_table[] = { + { .compatible = "qcom,sdhci-msm-v4", .data = (void *)SDHCI }, + { .compatible = "qcom,ufshc", .data = (void *)UFS }, + { .compatible = "qcom,pcie-msm8996", .data = (void *)PCIE }, + { .compatible = "qcom,dwc3", .data = (void *)USB3 }, + { } +}; + static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,rpmpd-msm8996", .data = &msm8996_desc }, { } @@ -230,6 +285,49 @@ static int rpmpd_power_off(struct generic_pm_domain *domain) return ret; } +static int rpmpd_set_performance(struct generic_pm_domain *domain, + unsigned int state) +{ + int ret = 0; + struct rpmpd *pd = domain_to_rpmpd(domain); + + mutex_lock(&rpmpd_lock); + + pd->corner = state; + + if (!pd->enabled && (pd->key != KEY_FLOOR_CORNER)) + goto out; + + ret = rpmpd_aggregate_corner(pd); + +out: + mutex_unlock(&rpmpd_lock); + + return ret; +} + + +static int rpmpd_get_performance(struct device *dev, unsigned long rate) +{ + int i; + unsigned long index; + const struct of_device_id *id; + + if (!rate) + return 0; + + id = of_match_device(rpmpd_performance_table, dev); + if (!id) + return -EINVAL; + + index = (unsigned long)id->data; + for (i = 0; i < MAX_LEVEL; i++) + if (msm8996_rpmpd_freq_map[index].freq[i] >= rate) + return i; + + return MAX_LEVEL; +} + static int rpmpd_probe(struct platform_device *pdev) { int i; @@ -267,6 +365,8 @@ static int rpmpd_probe(struct platform_device *pdev) rpmpds[i]->rpm = rpm; rpmpds[i]->pd.power_off = rpmpd_power_off; rpmpds[i]->pd.power_on = rpmpd_power_on; + rpmpds[i]->pd.genpd_set_performance_state = rpmpd_set_performance; + rpmpds[i]->pd.dev_get_performance_state = rpmpd_get_performance; pm_genpd_init(&rpmpds[i]->pd, NULL, true); data->domains[i] = &rpmpds[i]->pd; From patchwork Wed Aug 2 10:12:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 109204 Delivered-To: patch@linaro.org Received: by 10.140.101.6 with SMTP id t6csp2590707qge; Wed, 2 Aug 2017 03:13:09 -0700 (PDT) X-Received: by 10.99.185.20 with SMTP id z20mr21561940pge.308.1501668789391; Wed, 02 Aug 2017 03:13:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1501668789; cv=none; d=google.com; s=arc-20160816; b=Ck2cAbw16zSwfrUFvYmbzbtARwCHbl8yMWrW+HP5Q1+3DS1s832IT1cvXQFXujl2IW mlm9dCySyZ1R6cmGrcyh9jq4VgjEbDolLqQBn5LqP4LfV23N5xkO/P3bO/vC1wkLsZs6 F0SnLLSgL2zFB7TvZSPq1CFNVWgW/P8aFraOHjSmgDdGIvM1PW/tdnTtAezpFexK3rvx azU2c85aInV5DmwVSczuwbORqRXlHiakJ6X0xdIlCQiFURahp9shRGMM3+AHlJ+X9vP4 1gEQIvKv4uDOEGBCh9503x+7Fztl9qhyNfIq8KR9WMdaZWSZ7wabszqRpz3gxZOjE5pA B00Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=wHC4cdUP0vtDhe0cPCB6R3R+9d2DE2vnnZYak5Oc7pU=; b=sQsleuBCAOQlTezXchAVtrL4maqhMjPvYNLWhSW4qQMn3bGoEi9idKwTDgAZXyTf5f 2A7SYhoeUWGs/2VyKzo+zWO8rKTRfz760DqG2OQPVeYMe9OVVe7EC0+TeakHyYxy89Af gB6WF2JLMrR9Y8rE0M+9bvz7PXPE7bOFONTMmCT5l3uQD8BfQXs1wkR1+Qyh2YIlX5Io LO7MepD3Aa5KTzi2cPseYCFmZz+4OJJKBel5zysRlpKq3WQvszED8JPeVt0V60gb+5Wn /1Ol121C0jNkEGORzZJYKK3OULvaEYFd//toqSvOommMemS+x98g1R6cf7diGGwuGUkt RAFw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=Ux9XwmH5; 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 t124si17038144pgt.629.2017.08.02.03.13.09; Wed, 02 Aug 2017 03:13:09 -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=Ux9XwmH5; 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 S1752904AbdHBKNG (ORCPT + 25 others); Wed, 2 Aug 2017 06:13:06 -0400 Received: from mail-pg0-f46.google.com ([74.125.83.46]:35679 "EHLO mail-pg0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752820AbdHBKNC (ORCPT ); Wed, 2 Aug 2017 06:13:02 -0400 Received: by mail-pg0-f46.google.com with SMTP id v189so19398297pgd.2 for ; Wed, 02 Aug 2017 03:13:02 -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:in-reply-to:references :in-reply-to:references; bh=wHC4cdUP0vtDhe0cPCB6R3R+9d2DE2vnnZYak5Oc7pU=; b=Ux9XwmH578qTuANaVyQhARNUv/UaeQ7cvafDeA/Mc3JQpVIMoVEz1xHgbS9kHVauJo Xtp6l2hayII5LaXIh8ELAqcy9AlC2h7rXRU+DvFb6DKEF+r2uITxujuzbqLsQcU23B2i EwbYlUZPi1u1V7fekxcSr49eGMuneSA5DZ8lE= 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:in-reply-to :references:in-reply-to:references; bh=wHC4cdUP0vtDhe0cPCB6R3R+9d2DE2vnnZYak5Oc7pU=; b=ORbWXwCjYwrgpNRtOvcwOenTyP6wOoPjq7Rf8Pw6Cy2Ok2X5Q4msJOztzm4OXiO/LH G7im2JEclq5Xr0e4fkil0EWtWyvAUMww/IWFVERXUwPSmFjIQ7OmiZitNr/c1j9gBgWn kXN1G84x68CqjCPRmDxqhcUT/b4MsvQ637z+deIFBtwVjURG7WtnAFH7u59Cp4RJwmq2 hbYzgzzIuoiFK53h+0ntWuFB4UaNoWmSGXlsQ1jTW/a82FirCmgdLawKotgnA8o92KUX 9djXWPy0ShMKr2waYFPkfl6m1gf+UK90woGS9r3aldWpLqF44K9DSLIqksfdzt/YgwnH ECAQ== X-Gm-Message-State: AIVw1106Y1drtUcRnAc3izqBHIar4g2hB4Lg7+ZqpBzgvcR4rC2tFoNz 9ARn8BnT00FZ0oK+ X-Received: by 10.84.140.129 with SMTP id 1mr24167997plt.379.1501668782149; Wed, 02 Aug 2017 03:13:02 -0700 (PDT) Received: from localhost ([122.171.108.183]) by smtp.gmail.com with ESMTPSA id 184sm32893176pfg.16.2017.08.02.03.13.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 02 Aug 2017 03:13:01 -0700 (PDT) From: Viresh Kumar To: Rafael Wysocki , ulf.hansson@linaro.org, Kevin Hilman Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Stephen Boyd , Nishanth Menon , robh+dt@kernel.org, lina.iyer@linaro.org, rnayak@codeaurora.org, sudeep.holla@arm.com, linux-kernel@vger.kernel.org, Len Brown , Pavel Machek , Andy Gross , David Brown Subject: [PATCH V9 6/7] mmc: sdhci-msm: Adapt the driver to use OPPs to set clocks/performance state Date: Wed, 2 Aug 2017 15:42:37 +0530 Message-Id: <9e8bdfb809f1b17212625da121f53be750131893.1501668354.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.13.0.71.gd7076ec9c9cb In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Rajendra Nayak THIS IS TEST CODE, SHOULDN'T BE MERGED. SDHCI driver needs to set a performance state along with scaling its clocks. Modify the driver to use the newly introducded powerdomain performance state based OPPs to scale clocks as well as set an appropriate powerdomain performance state. The patch also adds OPPs for sdhci device on msm8996. The changes have to be validated by populating similar OPP tables on all other devices which use the sdhci driver. This is for now validated only on msm8996 and with missing OPP tables for other devices is known to break those platforms. NOT-signed-off-by: Rajendra Nayak NOT-signed-off-by: Viresh Kumar --- arch/arm64/boot/dts/qcom/msm8996.dtsi | 34 ++++++++++++++++++++++++++++++ drivers/clk/qcom/gcc-msm8996.c | 8 +++---- drivers/mmc/host/sdhci-msm.c | 39 ++++++++++++++++++++++++++--------- 3 files changed, 67 insertions(+), 14 deletions(-) -- 2.13.0.71.gd7076ec9c9cb diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi index 0ce9ea514cd1..00f514f53571 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -437,8 +437,42 @@ <&gcc GCC_SDCC2_APPS_CLK>, <&xo_board>; bus-width = <4>; + power-domains = <&rpmpd 0>; + operating-points-v2 = <&sdhc_opp_table>; }; + sdhc_opp_table: opp_table { + compatible = "operating-points-v2"; + + opp@400000 { + opp-hz = /bits/ 64 <400000>; + }; + + opp@20000000 { + opp-hz = /bits/ 64 <20000000>; + }; + + opp@25000000 { + opp-hz = /bits/ 64 <25000000>; + }; + + opp@50000000 { + opp-hz = /bits/ 64 <50000000>; + }; + + opp@96000000 { + opp-hz = /bits/ 64 <96000000>; + }; + + opp@192000000 { + opp-hz = /bits/ 64 <192000000>; + }; + + opp@384000000 { + opp-hz = /bits/ 64 <384000000>; + }; + }; + msmgpio: pinctrl@1010000 { compatible = "qcom,msm8996-pinctrl"; reg = <0x01010000 0x300000>; diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c index 8abc200d4fd3..9eb23063e78f 100644 --- a/drivers/clk/qcom/gcc-msm8996.c +++ b/drivers/clk/qcom/gcc-msm8996.c @@ -460,7 +460,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = { .name = "sdcc1_apps_clk_src", .parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div, .num_parents = 4, - .ops = &clk_rcg2_floor_ops, + .ops = &clk_rcg2_ops, }, }; @@ -505,7 +505,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = { .name = "sdcc2_apps_clk_src", .parent_names = gcc_xo_gpll0_gpll4, .num_parents = 3, - .ops = &clk_rcg2_floor_ops, + .ops = &clk_rcg2_ops, }, }; @@ -519,7 +519,7 @@ static struct clk_rcg2 sdcc3_apps_clk_src = { .name = "sdcc3_apps_clk_src", .parent_names = gcc_xo_gpll0_gpll4, .num_parents = 3, - .ops = &clk_rcg2_floor_ops, + .ops = &clk_rcg2_ops, }, }; @@ -543,7 +543,7 @@ static struct clk_rcg2 sdcc4_apps_clk_src = { .name = "sdcc4_apps_clk_src", .parent_names = gcc_xo_gpll0, .num_parents = 2, - .ops = &clk_rcg2_floor_ops, + .ops = &clk_rcg2_ops, }, }; diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 9d601dc0d646..2dfa4d58e113 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "sdhci-pltfm.h" @@ -131,6 +132,7 @@ struct sdhci_msm_host { struct clk *pclk; /* SDHC peripheral bus clock */ struct clk *bus_clk; /* SDHC bus voter clock */ struct clk *xo_clk; /* TCXO clk needed for FLL feature of cm_dll*/ + struct opp_table *opp_table; unsigned long clk_rate; struct mmc_host *mmc; bool use_14lpp_dll_reset; @@ -140,7 +142,7 @@ struct sdhci_msm_host { bool use_cdclp533; }; -static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host, +static long unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host, unsigned int clock) { struct mmc_ios ios = host->mmc->ios; @@ -165,16 +167,22 @@ static void msm_set_clock_rate_for_bus_mode(struct sdhci_host *host, struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); struct mmc_ios curr_ios = host->mmc->ios; int rc; + struct device *dev = &msm_host->pdev->dev; + struct dev_pm_opp *opp; + long unsigned int freq; + + freq = msm_get_clock_rate_for_bus_mode(host, clock); + opp = dev_pm_opp_find_freq_floor(dev, &freq); + if (IS_ERR(opp)) + pr_err("%s: failed to find OPP for %u at timing %d\n", + mmc_hostname(host->mmc), clock, curr_ios.timing); + + rc = dev_pm_opp_set_rate(dev, freq); + if (rc) + pr_err("%s: error in setting opp\n", __func__); + + msm_host->clk_rate = freq; - clock = msm_get_clock_rate_for_bus_mode(host, clock); - rc = clk_set_rate(msm_host->clk, clock); - if (rc) { - pr_err("%s: Failed to set clock at rate %u at timing %d\n", - mmc_hostname(host->mmc), clock, - curr_ios.timing); - return; - } - msm_host->clk_rate = clock; pr_debug("%s: Setting clock at rate %lu at timing %d\n", mmc_hostname(host->mmc), clk_get_rate(msm_host->clk), curr_ios.timing); @@ -1267,6 +1275,13 @@ static int sdhci_msm_probe(struct platform_device *pdev) goto clk_disable; } + /* Set up the OPP table */ + msm_host->opp_table = dev_pm_opp_set_clkname(&pdev->dev, "core"); + + ret = dev_pm_opp_of_add_table(&pdev->dev); + if (ret) + dev_warn(&pdev->dev, "%s: No OPP table specified\n", __func__); + pm_runtime_get_noresume(&pdev->dev); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); @@ -1288,6 +1303,8 @@ static int sdhci_msm_probe(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); + dev_pm_opp_of_remove_table(&pdev->dev); + dev_pm_opp_put_clkname(msm_host->opp_table); clk_disable: clk_disable_unprepare(msm_host->clk); pclk_disable: @@ -1313,6 +1330,8 @@ static int sdhci_msm_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); + dev_pm_opp_of_remove_table(&pdev->dev); + dev_pm_opp_put_clkname(msm_host->opp_table); clk_disable_unprepare(msm_host->clk); clk_disable_unprepare(msm_host->pclk); From patchwork Wed Aug 2 10:12:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 109205 Delivered-To: patch@linaro.org Received: by 10.140.101.6 with SMTP id t6csp2590806qge; Wed, 2 Aug 2017 03:13:15 -0700 (PDT) X-Received: by 10.98.102.149 with SMTP id s21mr22682161pfj.331.1501668795335; Wed, 02 Aug 2017 03:13:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1501668795; cv=none; d=google.com; s=arc-20160816; b=zMIytacDOX68HAMi6Lul106KvFcuhLGl5XP9m66hKBB8Wxf5skCIUsJOc69pJs/hB1 8W0JB6V4Fk6LKvYf1E32csqc1O4Dgx0aLlJVn7Wt1IKlMRz8epoeDfnnNVWIfqszHm2C ZVePMRUvyngJSwH6plMDykPPkLHJCUZ1/cDx8LW9VN8nFVZihG37/+dibOKRVYF6vqR1 MbzZMIpPMayS3G7lulc9SBDZRXupRwvmSa9Us/dNAVGEFKE+9lDxy55+m/hrOfras8fL gwafOLVENeYLfO137jA6hr9SYox/VlaVBDUVXL2WtF/Ops71n96nlkPEYqvUu1L364ac Fp0g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=JNNwhuEdfBzQXGQfzTSMrKgozOgWmiF/fw1fFUkDXB4=; b=dMX3be7W43Gx5QgvfSPIgG6ScOaOYNorlypWFvMn9uq4qIADRc05buMLNsh0vKw0Ar UR2bnnCk+YHs4bWTpeKiZ0HU56WRZr/CoQU+rsmFjzxP0CiKOTRRgeX+dGwMEFQC66EO gP37X8O4oxjXU7s/kJgf0mx5BdYCJqQe163wVtEy4vIElpnu7XbNDkPzT9O8AnzCcj3p i7dBCOaaWHJwXMpx8HpK/DX31s8LQHdoacbLF9WxovsGDsVEgxyw9EXTgAxY4ims/kOU eBJaGBp6FqYjTuNH4yv8BU9S8QI4jpOYiWKQ0urSHuLx26AMX0BQYkT8ibL9ziX8f1mK 9kEg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=hwc4JX09; 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 g25si1641480plj.140.2017.08.02.03.13.14; Wed, 02 Aug 2017 03:13:15 -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=hwc4JX09; 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 S1752935AbdHBKNN (ORCPT + 25 others); Wed, 2 Aug 2017 06:13:13 -0400 Received: from mail-pg0-f46.google.com ([74.125.83.46]:35690 "EHLO mail-pg0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752883AbdHBKNF (ORCPT ); Wed, 2 Aug 2017 06:13:05 -0400 Received: by mail-pg0-f46.google.com with SMTP id v189so19398702pgd.2 for ; Wed, 02 Aug 2017 03:13:05 -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:in-reply-to:references :in-reply-to:references; bh=JNNwhuEdfBzQXGQfzTSMrKgozOgWmiF/fw1fFUkDXB4=; b=hwc4JX09IM6dQ2lAn+f9rIXMokslyQ8Q6v5pYO/euXEqdOU4rdTMeGqFRvWWvbTcjM Lh9f42oCcMdaXuIBxF216JnmPLwwMTiAJzoYgbJA1blRhe02qLeoKrakz7OECERhXD71 /tEv25J0X0FzwuBoYfNXJwjqWkCLxYASkIdUY= 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:in-reply-to :references:in-reply-to:references; bh=JNNwhuEdfBzQXGQfzTSMrKgozOgWmiF/fw1fFUkDXB4=; b=ozgVuixKJF4haGuuACk7EAhmTf0cEl7LPlHCJrfSz04ctaNuCBzXQ7WB+loIKXJc5w VVhvmEUyu4G8FTcJcEJp8JY76a8zMirhcE/ZdG+1zR7dVnDJ1qugam4xYOKzFJL9Ev1r IE2TkpJdZOtwaA1pHGwP4M//MGgM5ZlfrM8qtwMO0VmdZ2/CYakvJyD9/SY3u+YgoLuu XWz6fX5+wrn/qkhQYiqPJT/Mo9C0pTD0DsmEUXkoO9ZwePXC2fKQ5nPLgW4pWKqY+VXH kJJ3E4xzCl1Q33V5v5oc8wDpBDU6DAE/SV/rA16FW4FZ3yATufgIu8ZoKTM9Bq9L37yz nwrQ== X-Gm-Message-State: AIVw1132h4d3REUONsRHHlMCSZVqQUEgtd2/NjeWTFyTyOytPNZoz/zn 2Z5D49+VIL/Y02af X-Received: by 10.99.240.69 with SMTP id s5mr21471530pgj.23.1501668784990; Wed, 02 Aug 2017 03:13:04 -0700 (PDT) Received: from localhost ([122.171.108.183]) by smtp.gmail.com with ESMTPSA id 86sm2096203pfm.105.2017.08.02.03.13.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 02 Aug 2017 03:13:04 -0700 (PDT) From: Viresh Kumar To: Rafael Wysocki , ulf.hansson@linaro.org, Kevin Hilman Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , Stephen Boyd , Nishanth Menon , robh+dt@kernel.org, lina.iyer@linaro.org, rnayak@codeaurora.org, sudeep.holla@arm.com, linux-kernel@vger.kernel.org, Len Brown , Pavel Machek , Andy Gross , David Brown Subject: [PATCH V9 7/7] remoteproc: qcom: q6v5: Vote for proxy powerdomain performance state Date: Wed, 2 Aug 2017 15:42:38 +0530 Message-Id: <632eb4c9568177dd7a3f3c29ba88698616f6e4ad.1501668354.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 2.13.0.71.gd7076ec9c9cb In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Rajendra Nayak THIS IS TEST CODE, SHOULDN'T BE MERGED. This patch just demonstrates the usage of pm_genpd_update_performance_state() api in cases where users need to set performance state of a powerdomain without having to do it via the OPP framework. q6v5 remoteproc driver needs to proxy vote for performance states of multiple powerdomains (but we currently only demonstate how it can be done for one powerdomain, as there is no way to associate multiple powerdomains to a device at this time) while it loads the firmware, and then releases the vote, once the firmware is up and can vote for itself. This is not a functional patch since rpmpd driver only supports msm8996 and there is no msm8996 support in the q6v5 remoteproc driver at this point in mainline. This patch is not tested as well. NOT-signed-off-by: Rajendra Nayak NOT-signed-off-by: Viresh Kumar --- drivers/remoteproc/qcom_q6v5_pil.c | 20 +++++++++++++------- drivers/soc/qcom/rpmpd.c | 5 +++++ 2 files changed, 18 insertions(+), 7 deletions(-) -- 2.13.0.71.gd7076ec9c9cb diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 8fd697a3cf8f..586f74ddd909 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -152,6 +153,8 @@ struct q6v5 { void *mpss_region; size_t mpss_size; + bool has_perf_state; + struct qcom_rproc_subdev smd_subdev; }; @@ -603,11 +606,12 @@ static int q6v5_start(struct rproc *rproc) struct q6v5 *qproc = (struct q6v5 *)rproc->priv; int ret; - ret = q6v5_regulator_enable(qproc, qproc->proxy_regs, - qproc->proxy_reg_count); - if (ret) { - dev_err(qproc->dev, "failed to enable proxy supplies\n"); - return ret; + if (qproc->has_perf_state) { + ret = dev_pm_genpd_update_performance_state(qproc->dev, INT_MAX); + if (ret) { + dev_err(qproc->dev, "Failed to set performance state.\n"); + return ret; + } } ret = q6v5_clk_enable(qproc->dev, qproc->proxy_clks, @@ -671,8 +675,8 @@ static int q6v5_start(struct rproc *rproc) q6v5_clk_disable(qproc->dev, qproc->proxy_clks, qproc->proxy_clk_count); - q6v5_regulator_disable(qproc, qproc->proxy_regs, - qproc->proxy_reg_count); + if (qproc->has_perf_state) + dev_pm_genpd_update_performance_state(qproc->dev, 0); return 0; @@ -1043,6 +1047,8 @@ static int q6v5_probe(struct platform_device *pdev) if (ret) goto free_rproc; + qproc->has_perf_state = pm_genpd_has_performance_state(&qproc->dev); + return 0; free_rproc: diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index 4e4f5cda9ce2..c1733da8a7c8 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -145,6 +145,7 @@ enum msm8996_devices { UFS, PCIE, USB3, + Q6V5_PIL, }; static struct rpmpd_freq_map msm8996_rpmpd_freq_map[] = { @@ -171,6 +172,10 @@ static struct rpmpd_freq_map msm8996_rpmpd_freq_map[] = { .freq[LOW] = 120000000, .freq[NOMINAL] = 150000000, }, + [Q6V5_PIL] = { + .pd = &msm8996_vddcx, + .freq[HIGH] = INT_MAX, + }, }; static const struct of_device_id rpmpd_performance_table[] = {