From patchwork Wed Jun 21 07:10:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 106048 Delivered-To: patch@linaro.org Received: by 10.140.91.2 with SMTP id y2csp1786066qgd; Wed, 21 Jun 2017 00:11:11 -0700 (PDT) X-Received: by 10.99.122.3 with SMTP id v3mr12858124pgc.98.1498029070998; Wed, 21 Jun 2017 00:11:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1498029070; cv=none; d=google.com; s=arc-20160816; b=Ukdg0ARCZddYoSQfkPm4tuz2Vc75ePvb04esYHKxZhfPi6igIKA3SFs0WwA38ZyJXb YP7RHq4lglUQOZBVK1xOBENJK92MBxk2YhwUYipbopLIZ8V+ViXpV2CCTVMok7xSzaib afp1ojS6qncS4Gf14TpwSR5A+pktd+GKHFgI03nSOSw/s8ym5fUDGdcT1YslRyzLYhnt rUpIX9o7+KN4Rh++doGkEka5ZqOe+akTBOw9Hr6V1yWzksGgDub4/COTiWbbKT2MtD/M pwN5F1pRj++e1odyj5+0O+eVtn5JqGLWfxJAf6wjqoIytAnWOXR22xp6ryvZyE/fLUQA 57Rw== 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=zn3MOY+pJXsMvmSqNjH37cmv5R2KWY7X/J0KSyC+e/k=; b=IjnSKwxtjBrfAQhZEibd1jLDtdWjjF0bpt3bkBJJnbyAStZK+hJO9dfZ/Ek3C4EAB4 GRuCYaJd7ENywzu2wzlIrUGulyos0XFKPx6g5EoA4y6yndSNp5tTR5W+XNrYQ/JJwWLE mt1XDn4ANuNOyiXQcgTLyYOT7N3IcZe5kByuDgNn+HYA+YOHHug/KXT0BqjThBkyWUWv Q3XzGkVGkbcgK/gFXdhGqWoTJE0u6xmB5u0RU3SBLUw9lHljxzHTK6Fjg1d9pt0r8DwK c9Qk4hxjK4WMkDyZ3Vqt56qU1qVnL8Uff4AaRnetO2b1ig2A2nckn79Bh5DQt7jdb5Ac 1g2g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=OKRSwMDH; 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 d5si12427990pgk.320.2017.06.21.00.11.10; Wed, 21 Jun 2017 00:11:10 -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=OKRSwMDH; 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 S1752393AbdFUHLH (ORCPT + 25 others); Wed, 21 Jun 2017 03:11:07 -0400 Received: from mail-pf0-f180.google.com ([209.85.192.180]:34984 "EHLO mail-pf0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752002AbdFUHLD (ORCPT ); Wed, 21 Jun 2017 03:11:03 -0400 Received: by mail-pf0-f180.google.com with SMTP id c73so20819831pfk.2 for ; Wed, 21 Jun 2017 00:11:03 -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=zn3MOY+pJXsMvmSqNjH37cmv5R2KWY7X/J0KSyC+e/k=; b=OKRSwMDHX/XdnL4sH3YQ+CRd/8i7mPkZkMDS9m7e7Z3QpXYB8eNwPreKnsG/mWWzX/ px0JDXZf1DeHungdw8rRkEx7Pfih/3FFZjCmdp6w4YMJQIICBoO3votSaeAaQ5wnA69V 2u9hNo00LWNqMKepgSU08XKII7fBOSPkYWtVw= 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=zn3MOY+pJXsMvmSqNjH37cmv5R2KWY7X/J0KSyC+e/k=; b=DAJxozPdA+LCoyz/d5D40aFCZegLrIPhKrSGcLDWNysvwavM9uGASkuxindSvMi4Vr nyamJKrFZPtB5x6nWLZg+m9ZF0Uu7T9rScfN+FWU4yuXD8pAtIUX1/H4EpMA+04mIj2A 83ZCGQ3nArZQZSyYgmmMwj5IGXX0pTBxuOfXVCz1UES7vTW7EKEy8dnilfFvPCncpb8H lSSJgm8zYak3h0umE2UAwsI8VkrmNZdz8BQ5+rjjh76fXEOjOY3gFo85kv7zQTEhneni ibEiXnC6hmobdfPYeG0HGIe6NFzUyGvOiiWPFhpt7//SElYZrx/8nFN0cHkZDg97YxHs BPdA== X-Gm-Message-State: AKS2vOyGAG7XayPWc0gGv3cFWCH1nPqLfzQx9NxRAjw30h+8xsV0rBIY 2GzlSOwV6JgN2GyM X-Received: by 10.98.159.19 with SMTP id g19mr17203558pfe.21.1498029062474; Wed, 21 Jun 2017 00:11:02 -0700 (PDT) Received: from localhost ([122.172.59.234]) by smtp.gmail.com with ESMTPSA id l85sm31066999pfj.130.2017.06.21.00.11.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Jun 2017 00:11: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 V8 1/6] PM / Domains: Add support to select performance-state of domains Date: Wed, 21 Jun 2017 12:40:48 +0530 Message-Id: <52daf22d2c9d92b0e61c8c5c5a88516d7a08a31a.1498026827.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 Some platforms have the capability to configure the performance state of their Power Domains. The performance levels are identified by positive integer values, a lower value represents lower performance state. This patch adds a new genpd API: pm_genpd_update_performance_state(). The caller passes the affected device and the frequency representing its next DVFS state. The power domains get two new callbacks: - get_performance_state(): This is called by the genpd core to retrieve the performance state (integer value) corresponding to a target frequency for the device. This state is used by the genpd core to find the highest requested state by all the devices powered by a domain. - set_performance_state(): The highest state retrieved from above interface is then passed to this callback to finally program the performance state of the power domain. The power domains can avoid supplying these callbacks, if they don't support setting performance-states. A power domain may have only get_performance_state() callback, if it doesn't have the capability of changing the performance state itself but someone in its parent hierarchy has. A power domain may have only set_performance_state(), if it doesn't have any direct devices below it but subdomains. And so the get_performance_state() will never get called from the core. The more common case would be to have both the callbacks set. Another API, pm_genpd_has_performance_state(), is also added to let other parts of the kernel check if the power domain of a device supports performance-states or not. This could have been done from pm_genpd_update_performance_state() as well, but that routine gets called every time we do DVFS for the device and it wouldn't be optimal in that case. Note that, the performance level as returned by ->get_performance_state() for the parent domain of a device is used for all domains in parent hierarchy. Tested-by: Rajendra Nayak Signed-off-by: Viresh Kumar --- drivers/base/power/domain.c | 223 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/pm_domain.h | 22 +++++ 2 files changed, 245 insertions(+) -- 2.13.0.71.gd7076ec9c9cb diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 71c95ad808d5..d506be9ff1f7 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -466,6 +466,229 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb, return NOTIFY_DONE; } +/* + * Returns true if anyone in genpd's parent hierarchy has + * set_performance_state() set. + */ +static bool genpd_has_set_performance_state(struct generic_pm_domain *genpd) +{ + struct gpd_link *link; + + if (genpd->set_performance_state) + return true; + + list_for_each_entry(link, &genpd->slave_links, slave_node) { + if (genpd_has_set_performance_state(link->master)) + return true; + } + + return false; +} + +/** + * pm_genpd_has_performance_state - Checks if power domain does performance + * state management. + * + * @dev: Device whose power domain is getting inquired. + * + * This must be called by the user drivers, before they start calling + * 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 pm_genpd_has_performance_state(struct device *dev) +{ + struct generic_pm_domain *genpd = genpd_lookup_dev(dev); + + /* The parent domain must have set get_performance_state() */ + if (!IS_ERR(genpd) && genpd->get_performance_state) { + if (genpd_has_set_performance_state(genpd)) + return true; + + /* + * A genpd with ->get_performance_state() callback must also + * allow setting performance state. + */ + dev_err(dev, "genpd doesn't support setting performance state\n"); + } + + return false; +} +EXPORT_SYMBOL_GPL(pm_genpd_has_performance_state); + +/* + * Re-evaluate performance state of a power domain. Finds the highest requested + * performance state by the devices and subdomains within the power domain and + * then tries to change its performance state. If the power domain doesn't have + * a set_performance_state() callback, then we move the request to its parent + * power domain. + * + * Locking: Access (or update) to device's "pd_data->performance_state" field + * happens only with parent domain's lock held. Subdomains have their + * "genpd->performance_state" protected with their own lock (and they are the + * only user of this field) and their per-parent-domain + * "link->performance_state" field is protected with individual parent power + * domain's lock and is only accessed/updated with that lock held. + */ +static int genpd_update_performance_state(struct generic_pm_domain *genpd, + int depth) +{ + struct generic_pm_domain_data *pd_data; + struct generic_pm_domain *master; + struct pm_domain_data *pdd; + unsigned int state = 0, prev; + struct gpd_link *link; + int ret; + + /* 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 */ + list_for_each_entry(link, &genpd->master_links, master_node) { + if (link->performance_state > state) + state = link->performance_state; + } + + if (genpd->performance_state == state) + return 0; + + if (genpd->set_performance_state) { + ret = genpd->set_performance_state(genpd, state); + if (!ret) + genpd->performance_state = state; + + return ret; + } + + /* + * Not all domains support updating performance state. Move on to their + * parent domains in that case. + */ + prev = genpd->performance_state; + + 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_update_performance_state(master, depth + 1); + if (ret) + link->performance_state = prev; + + genpd_unlock(master); + + if (ret) + goto err; + } + + /* + * The parent domains are updated now, lets get genpd performance_state + * in sync with those. + */ + genpd->performance_state = state; + return 0; + +err: + 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_update_performance_state(master, depth + 1)) + pr_err("%s: Failed to roll back to %d performance state\n", + genpd->name, prev); + genpd_unlock(master); + } + + return ret; +} + +static int __dev_update_performance_state(struct device *dev, int state) +{ + struct generic_pm_domain_data *gpd_data; + int ret; + + spin_lock_irq(&dev->power.lock); + + if (!dev->power.subsys_data || !dev->power.subsys_data->domain_data) { + ret = -ENODEV; + goto unlock; + } + + gpd_data = to_gpd_data(dev->power.subsys_data->domain_data); + + ret = gpd_data->performance_state; + gpd_data->performance_state = state; + +unlock: + spin_unlock_irq(&dev->power.lock); + + return ret; +} + +/** + * pm_genpd_update_performance_state - Update performance state of device's + * parent 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). + * + * This must be called by the user drivers (as many times as they want) only + * after pm_genpd_has_performance_state() is called (only once) and that + * returned "true". + * + * 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 pm_genpd_update_performance_state(struct device *dev, unsigned long rate) +{ + struct generic_pm_domain *genpd = dev_to_genpd(dev); + int ret, state; + + if (IS_ERR(genpd)) + return -ENODEV; + + genpd_lock(genpd); + + state = genpd->get_performance_state(dev, rate); + if (state < 0) { + ret = state; + goto unlock; + } + + state = __dev_update_performance_state(dev, state); + if (state < 0) { + ret = state; + goto unlock; + } + + ret = genpd_update_performance_state(genpd, 0); + if (ret) + __dev_update_performance_state(dev, state); + +unlock: + genpd_unlock(genpd); + + return ret; +} +EXPORT_SYMBOL_GPL(pm_genpd_update_performance_state); + /** * genpd_power_off_work_fn - Power off PM domain whose subdomain count is 0. * @work: Work structure used for scheduling the execution of this function. diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index b7803a251044..bf90177208a2 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -63,8 +63,12 @@ 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 */ int (*power_off)(struct generic_pm_domain *domain); int (*power_on)(struct generic_pm_domain *domain); + int (*get_performance_state)(struct device *dev, unsigned long rate); + int (*set_performance_state)(struct generic_pm_domain *domain, + unsigned int state); struct gpd_dev_ops dev_ops; s64 max_off_time_ns; /* Maximum allowed "suspended" time. */ bool max_off_time_changed; @@ -99,6 +103,9 @@ struct gpd_link { struct list_head master_node; struct generic_pm_domain *slave; struct list_head slave_node; + + /* Sub-domain's per-parent domain performance state */ + unsigned int performance_state; }; struct gpd_timing_data { @@ -118,6 +125,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 +156,9 @@ extern int pm_genpd_remove(struct generic_pm_domain *genpd); extern struct dev_power_governor simple_qos_governor; extern struct dev_power_governor pm_domain_always_on_gov; +extern bool pm_genpd_has_performance_state(struct device *dev); +extern int pm_genpd_update_performance_state(struct device *dev, + unsigned long rate); #else static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev) @@ -185,6 +196,17 @@ static inline int pm_genpd_remove(struct generic_pm_domain *genpd) return -ENOTSUPP; } +static inline bool pm_genpd_has_performance_state(struct device *dev) +{ + return false; +} + +static inline int 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 Jun 21 07:10:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 106050 Delivered-To: patch@linaro.org Received: by 10.140.91.2 with SMTP id y2csp1786211qgd; Wed, 21 Jun 2017 00:11:35 -0700 (PDT) X-Received: by 10.98.38.129 with SMTP id m123mr4262459pfm.183.1498029095568; Wed, 21 Jun 2017 00:11:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1498029095; cv=none; d=google.com; s=arc-20160816; b=VxJMmxGtHIGVu8Hmry3Yl9b79g2c0EkiThm2r2KmdlNZ/0Xkr39G/D2Drtp6w+8Kip 8L2MxJ1LGYmicrgj1BemXaChtagba0sJ9L2x8yKFOConK8POGZDDTXQRKiAXAg2Mj6xd JBUjxBOwgwGxk8QFxzJciyyRtVp/ObH8jDLSbOBs1+eUoRmIJtk+nUmWbOzZ9XKoREDA VrwDT/YZpR8xSxlpBkBX4ghFERLmc1eU2txmnqgpmdJaUNFs6utVU5STENVcHAJhCKIv 4MWXmqEm637KjN+H676iRPyzyS6gHsToPFOkHHLY3lgMYQvZ7Oym4lehDUwrKkGGtPLx dOug== 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=m+s6JsuMHct+vF461rcRxRWYhdMYL9+QiNWQa9d104E=; b=Ik9VgdU7ywz6tNyGepKNw9aLZlZAHh9LrixxuQc1ioNcNSA20nUVDpyyiBykem2ojd rGRkdeO7jvb5DFsGrz/NAPa9yhftXZQGBYteDzBLpSq9bYVuS1/mxRbO78QlYBdlgY2F mXad2tGjUoIw8wja+i7KGtq2W9mAa8oKsVwfcbo+tVPpFfp55jTDcW5m+KPtOLbXMvZT YQ0NRz1JBfzIFAO0uAxUU3O9ME4jRuA51QT01qz/+gPcz4M9A4ZW88oTYDu11pUPXKGZ QRvkrzQzuSXVoY9BN1U47cZ57d9IPH1EK3UaZIbSi0qeMEXqgk20MUMx59JPkC1XLgw9 O0Qw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=imbSJWeX; 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 h66si12330513pfa.285.2017.06.21.00.11.35; Wed, 21 Jun 2017 00:11:35 -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=imbSJWeX; 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 S1752493AbdFUHLP (ORCPT + 25 others); Wed, 21 Jun 2017 03:11:15 -0400 Received: from mail-pg0-f49.google.com ([74.125.83.49]:36706 "EHLO mail-pg0-f49.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751969AbdFUHLL (ORCPT ); Wed, 21 Jun 2017 03:11:11 -0400 Received: by mail-pg0-f49.google.com with SMTP id u62so54183043pgb.3 for ; Wed, 21 Jun 2017 00:11:11 -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=m+s6JsuMHct+vF461rcRxRWYhdMYL9+QiNWQa9d104E=; b=imbSJWeXXpOrDSL7/7sd7EAQelf/G2atOEpkMczUMu7IGt6SFD8xoOYDiOmr0+7rJ7 +9O99r5F9ad1odfbDRKMwe9dv29bGVVAvD1uhkLJUSgXg9JbhAgUT27OIGMKVkdC2Sxv ZeMsLUzwI1ub0/J3lEJ6vgN6SJOyWz+7Rcbnk= 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=m+s6JsuMHct+vF461rcRxRWYhdMYL9+QiNWQa9d104E=; b=iO85f1yIwaPTEbOGMECfK0i200PoyRXqfbmPWuiPKcj1NSqK7huFNhoH3XQFr/x0Xw m4+xKD5CriCy7HiKOheMCvknCNjtsfYL7ILQFvKYZDiPFYfYJrfDGYnku6N5g0wFju1d kZ53cv/1Jq9PUYWxV7TtN2kQ9LLQiO7sVtwjLJp2MNyH3c0dTKQ3jNBaviCm/gX1IjYH NtXwE7UAs8ZosEHTx3DomOgHULvaAFsXR+TIPTReiwFhiOrPnW0X14XUTWg1cTH/NL67 kP6xguYIkh1l6+3+tcNTHi1Jk5Em2aVo7zmV9wFhN48/Z34LxMooRPzTTB3BrfoJY/ZN 1g+A== X-Gm-Message-State: AKS2vOxvy1/WvM8y6evnN4xgP7cAWMGwnxNM0oMiLxpWtB3JnR1UveHX RRyzomIyS+cr/vGI X-Received: by 10.84.128.107 with SMTP id 98mr36006840pla.285.1498029065395; Wed, 21 Jun 2017 00:11:05 -0700 (PDT) Received: from localhost ([122.172.59.234]) by smtp.gmail.com with ESMTPSA id q14sm19259895pgr.11.2017.06.21.00.11.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Jun 2017 00:11: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 V8 2/6] PM / OPP: Support updating performance state of device's power domains Date: Wed, 21 Jun 2017 12:40:49 +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 The genpd framework now provides an API to request device's power domain to update its performance state based on a particular target frequency for the device. Use that interface from the OPP core for devices whose power domains support performance states. Note that the current implementation is restricted to the case where the device doesn't have separate regulators for itself. We shouldn't over engineer the code before we have real use case for them. We can always come back and add more code to support such cases later on. Tested-by: Rajendra Nayak Signed-off-by: Viresh Kumar --- drivers/base/power/opp/core.c | 48 ++++++++++++++++++++++++++++++++++++++++++- drivers/base/power/opp/opp.h | 2 ++ 2 files changed, 49 insertions(+), 1 deletion(-) -- 2.13.0.71.gd7076ec9c9cb diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index a8cc14fd8ae4..ef623afcc5fd 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "opp.h" @@ -535,6 +536,42 @@ _generic_set_opp_clk_only(struct device *dev, struct clk *clk, return ret; } +static inline int +_generic_set_opp_domain(struct device *dev, struct clk *clk, + unsigned long old_freq, unsigned long freq) +{ + int ret; + + /* Scaling up? Scale domain performance state before frequency */ + if (freq > old_freq) { + ret = pm_genpd_update_performance_state(dev, freq); + if (ret) + return ret; + } + + ret = _generic_set_opp_clk_only(dev, clk, old_freq, freq); + if (ret) + goto restore_domain_state; + + /* Scaling down? Scale domain performance state after frequency */ + if (freq < old_freq) { + ret = pm_genpd_update_performance_state(dev, freq); + if (ret) + goto restore_freq; + } + + return 0; + +restore_freq: + if (_generic_set_opp_clk_only(dev, clk, freq, old_freq)) + dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n", + __func__, old_freq); +restore_domain_state: + pm_genpd_update_performance_state(dev, old_freq); + + return ret; +} + static int _generic_set_opp_regulator(const struct opp_table *opp_table, struct device *dev, unsigned long old_freq, @@ -653,7 +690,14 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) /* Only frequency scaling */ if (!opp_table->regulators) { - ret = _generic_set_opp_clk_only(dev, clk, old_freq, freq); + /* + * We don't support devices with both regulator and + * domain performance-state for now. + */ + if (opp_table->genpd_performance_state) + ret = _generic_set_opp_domain(dev, clk, old_freq, freq); + else + ret = _generic_set_opp_clk_only(dev, clk, old_freq, freq); } else if (!opp_table->set_opp) { ret = _generic_set_opp_regulator(opp_table, dev, old_freq, freq, IS_ERR(old_opp) ? NULL : old_opp->supplies, @@ -755,6 +799,8 @@ static struct opp_table *_allocate_opp_table(struct device *dev) ret); } + opp_table->genpd_performance_state = pm_genpd_has_performance_state(dev); + BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head); INIT_LIST_HEAD(&opp_table->opp_list); mutex_init(&opp_table->lock); diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h index 166eef990599..1efa253e1934 100644 --- a/drivers/base/power/opp/opp.h +++ b/drivers/base/power/opp/opp.h @@ -135,6 +135,7 @@ enum opp_table_access { * @clk: Device's clock handle * @regulators: Supply regulators * @regulator_count: Number of power supply regulators + * @genpd_performance_state: Device's power domain support performance state. * @set_opp: Platform specific set_opp callback * @set_opp_data: Data to be passed to set_opp callback * @dentry: debugfs dentry pointer of the real device directory (not links). @@ -170,6 +171,7 @@ struct opp_table { struct clk *clk; struct regulator **regulators; unsigned int regulator_count; + bool genpd_performance_state; int (*set_opp)(struct dev_pm_set_opp_data *data); struct dev_pm_set_opp_data *set_opp_data; From patchwork Wed Jun 21 07:10:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 106051 Delivered-To: patch@linaro.org Received: by 10.140.91.2 with SMTP id y2csp1786215qgd; Wed, 21 Jun 2017 00:11:36 -0700 (PDT) X-Received: by 10.99.185.28 with SMTP id z28mr25294146pge.123.1498029096066; Wed, 21 Jun 2017 00:11:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1498029096; cv=none; d=google.com; s=arc-20160816; b=MX9n5XxNGJzCusvOr3zX6r3G6g1Phc2F92726ieILACgsZHeFuO/jPaI21XrMAZsAN FrcJatRPmscdookN2dtvjTQswmxw4PV4eYVZax//68+GeOtj9Am4JllklK13u9bf3RpX 3bommemvuklB+YwaarDV5E5/onVQWxzk9hIOYDfDSoNBUpFAtSO1IcsezxLOEgcXy2aA 0rZ4RNg6aAO/XpfYJCrwA5mToSvY7aGVJpquN4CIa4SfScGs0vsqP/o2Zf8kwencKmBx AYBXJ1MYpjhoh+WybaJVBaJ60jNmpz0zy7IBCxlMG8dXCxXMoVYSjGz7jqI+ByPb2YgD yZTQ== 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=5dPXUkCU6keoNlN2wcycWhovbeBXa8Zqf6Rw7KvqOvQ=; b=x76uYtpB1AZ2pZsgLHSGjm/zQNle1vaPLH2gUep1gitkX6Ia5eD9jz+ze+NwWMNhWM TKd5fyt6VToT2U/eTeiaXyhm8FpVw7W+iZ698nULgm0gq5xhLJGGOdtUFaAxEwGrc3v3 AoTYL0mqpqw4lkC48bpo8OmxHg4wAs5JhBDHSRxpppQpnFuu+fX0WZ/gAeZ3w0teHonJ BQpZBYWruBU8GE1EEIdtAaUQd7+RvtRLlsn5DfnTrqkxwSZnuksgLwCPYiWryKMRCypc DABaFzy1/bBXxRxAXh/FOqZKjtUIZOvTVOG9++Rkt45sHzwvflFGS3lMsTMPmn/B0kG6 Clxg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=IIH4Pl35; 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 h66si12330513pfa.285.2017.06.21.00.11.35; Wed, 21 Jun 2017 00:11:36 -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=IIH4Pl35; 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 S1752554AbdFUHLS (ORCPT + 25 others); Wed, 21 Jun 2017 03:11:18 -0400 Received: from mail-pg0-f46.google.com ([74.125.83.46]:32866 "EHLO mail-pg0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751969AbdFUHLQ (ORCPT ); Wed, 21 Jun 2017 03:11:16 -0400 Received: by mail-pg0-f46.google.com with SMTP id f185so73495711pgc.0 for ; Wed, 21 Jun 2017 00:11:16 -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=5dPXUkCU6keoNlN2wcycWhovbeBXa8Zqf6Rw7KvqOvQ=; b=IIH4Pl355fueY/3ad7OGahBwF+/+e3SsuL+SJaony0oZqNI2zKNRR8ILxkqqc7sXKm B4duBl8Mn4fMNLRlLJOF614Lf7/yhc1rUpiaVNJGYiR8qyOTM6fLego3SH/06iZgrJ+b QqVWY+MJePz1lBvUGfS5rtLgTPtJjt9pBfx6g= 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=5dPXUkCU6keoNlN2wcycWhovbeBXa8Zqf6Rw7KvqOvQ=; b=KlesILxhK6D5pOUipxgYQjBlAWH1N+eOHueL07O+rJ28w7rl+Osmf0mAiThfjltMYM /su8i0zbZsz8OCb0e19LHiFQfU9Z0CZ5okEzojVkFqvMCP5bA2Vswi26x4aF1+Ur4Ei+ I+pA6Ni+9eAublnXz89AMHbhN9HUDcRs5O1wv2nwav3YuZM5muxshvvK35TYxUd84b99 BrBD+5StWSENZq6xkoHhoHhixD/wtyjqwxKaBfndTlhOr4MiU+JYoWImUvso38cKd+9w qMMCEFGYLWsddPtWznIl+SiBRrkGKfX8LyXZI+cRoYuRziX0UpsKX6W2o5Sa3smVDKeq hHkQ== X-Gm-Message-State: AKS2vOxVV7Oo4hR62FhFD20A4sTqVYHimmHj/R70t/0BoOx9iw5peVNh z7e9mmV1ZdDnIKdS X-Received: by 10.101.76.136 with SMTP id m8mr34994836pgt.159.1498029070926; Wed, 21 Jun 2017 00:11:10 -0700 (PDT) Received: from localhost ([122.172.59.234]) by smtp.gmail.com with ESMTPSA id r81sm9575350pfi.61.2017.06.21.00.11.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Jun 2017 00:11:10 -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: [NOT-FOR-MERGE V8 4/6] soc: qcom: rpmpd: Add support for get/set performance state Date: Wed, 21 Jun 2017 12:40:51 +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. 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..7ef81429c5c5 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.set_performance_state = rpmpd_set_performance; + rpmpds[i]->pd.get_performance_state = rpmpd_get_performance; pm_genpd_init(&rpmpds[i]->pd, NULL, true); data->domains[i] = &rpmpds[i]->pd; From patchwork Wed Jun 21 07:10:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 106053 Delivered-To: patch@linaro.org Received: by 10.140.91.2 with SMTP id y2csp1786535qgd; Wed, 21 Jun 2017 00:12:34 -0700 (PDT) X-Received: by 10.84.224.134 with SMTP id s6mr7323499plj.263.1498029154898; Wed, 21 Jun 2017 00:12:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1498029154; cv=none; d=google.com; s=arc-20160816; b=FndA+u4YPwWxXEHq/ILC6Sz4RThq1yqO9Yd1ye+vDkHQENzmsYlaiOgnh4Ggigziq6 FHP7+XYGYMdaK3aB+zUwZdlUnuD+B2Q5Ow7nxbV5FZKno60C5m0fc4YhFXNZcVN2yclO RhlR2Y04EIdLcoTJ/Kf2aF9/fxeMGyY5k1Dd7OLID4uHD/x2PMnb7FwuyhHmq30kEjr1 6SsOgsHhd7bCK1lKrH4n9cS6bks36D/mMklmfBznu5O007DgDrv528HwXV//wfKJOVYi vyaW9pOFA4Ruc+Ph+xEhhiV9MCPcjXq7Bs5WbDRxw3nX+/lfGK4+X7NKMwZ7RusKe510 7EIg== 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=ZTX0Pi34XLsGzoqQyf+h/V1gN+kFopSppadv049CvSk=; b=bd09IG9GBICE16uMbW9XxdJpXZs3PiNFVABxezZsT/eHLeQD+6f14xUixvyUM9+/3P Xwf5u2UW0ke8Pnm3zromuFGOZlVwLjn6NECKvfQW3LxMFUf4ECr5lskRv6CyXMkApUtr T0JOTFbzm6Rrl0svCQZ/7U6AHT4UiZO4hvcCGq3Xe2KgbH/vzgURbdZwfyJ5Z1oCyR0I 9qoOiz697yW02l4Ci3tnoP/5r2fkQRgO/S0c1iRE6hcsUqaR+P4ZHj61Twl9F88LhYWj 3JJ26vb0WyRUlXCYOjt6J8yrntmkn1e40m568mQLJki/m8EnJzRXNQbO0BxSYrM86VDv bB/A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=QALQxjKI; 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 d32si10837027pld.390.2017.06.21.00.12.34; Wed, 21 Jun 2017 00:12:34 -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=QALQxjKI; 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 S1752642AbdFUHMV (ORCPT + 25 others); Wed, 21 Jun 2017 03:12:21 -0400 Received: from mail-pg0-f51.google.com ([74.125.83.51]:36733 "EHLO mail-pg0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752320AbdFUHLO (ORCPT ); Wed, 21 Jun 2017 03:11:14 -0400 Received: by mail-pg0-f51.google.com with SMTP id u62so54184311pgb.3 for ; Wed, 21 Jun 2017 00:11:14 -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=ZTX0Pi34XLsGzoqQyf+h/V1gN+kFopSppadv049CvSk=; b=QALQxjKIkwcbR7WHfldzaT+7pRTknW0eTDC7YDnKqBo+7C0WRwE5+z0kSxgToDqt5o vVSCuyGfteYL0d/2aKI3IEEY/g1BxH5b6HLkldTIenjQOYkxMr9pKpEETWDEg0gfIf5M xTZUd9ZRCFtd4voTe7CVoEiIrFEoA8Z0gqR6o= 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=ZTX0Pi34XLsGzoqQyf+h/V1gN+kFopSppadv049CvSk=; b=htRjEPPax1JcO/vAuwQkOD/ZjvO2Ba8gB4+7IYBK5hW5tqdcBzqMBezFV11VufSVcF fSxzHvTA7lK4MZrUWp45IikjkVgJCOUMKq58kiSHYdd3VjTnai/1fPfH+QJrN5b7J6t3 UQ4HzlwghpDKZ6VSlQAOIkYn1SuMDSqQcMWvebQdteOH4DZSSYC1f9Wcqes4/h4RnHce Qx/o+D+5I+SnDWHgJ2c3jLUHpFhZDpk5KEcGL7bklS+gLAjt3C5tGZmzOzm87HHIlLgY 2Iiix1VPIHhVnRDUC56FmXTuX0+S/TtLaAXkoj8MywpGbdMqODRgvQ9Xn4BKOVo7y0gC hwlQ== X-Gm-Message-State: AKS2vOxRj9poywpk4hsdzxG5VM4KlDeNFBnxeqHc6lLf4c1j929lRx/g SmG+rvXYptBMAmlS X-Received: by 10.84.230.137 with SMTP id e9mr40815184plk.100.1498029073945; Wed, 21 Jun 2017 00:11:13 -0700 (PDT) Received: from localhost ([122.172.59.234]) by smtp.gmail.com with ESMTPSA id p186sm28086059pga.32.2017.06.21.00.11.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Jun 2017 00:11:13 -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: [NOT-FOR-MERGE V8 5/6] mmc: sdhci-msm: Adapt the driver to use OPPs to set clocks/performance state Date: Wed, 21 Jun 2017 12:40:52 +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. 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 1fec06285f38..2cabdba93e0e 100644 --- a/arch/arm64/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi @@ -431,8 +431,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);