From patchwork Fri Jan 21 14:00:55 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vishwanath BS X-Patchwork-Id: 12 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:39:13 -0000 Delivered-To: patches@linaro.org Received: by 10.147.124.10 with SMTP id b10cs148470yan; Fri, 21 Jan 2011 05:57:45 -0800 (PST) Received: by 10.91.121.18 with SMTP id y18mr786338agm.208.1295618264305; Fri, 21 Jan 2011 05:57:44 -0800 (PST) Received: from comal.ext.ti.com (comal.ext.ti.com [198.47.26.152]) by mx.google.com with ESMTPS id i10si21521533ane.125.2011.01.21.05.57.44 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 21 Jan 2011 05:57:44 -0800 (PST) Received-SPF: pass (google.com: domain of vishwanath.bs@ti.com designates 198.47.26.152 as permitted sender) client-ip=198.47.26.152; Authentication-Results: mx.google.com; spf=pass (google.com: domain of vishwanath.bs@ti.com designates 198.47.26.152 as permitted sender) smtp.mail=vishwanath.bs@ti.com Received: from dbdp31.itg.ti.com ([172.24.170.98]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id p0LDvea8000503 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 21 Jan 2011 07:57:43 -0600 Received: from localhost.localdomain (localhost [127.0.0.1]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with ESMTP id p0LDvSPT010507; Fri, 21 Jan 2011 19:27:40 +0530 (IST) From: Vishwanath BS To: linux-omap@vger.kernel.org Cc: patches@linaro.org, Vishwanath BS , Thara Gopinath Subject: [PATCH 03/13] OMAP: Implement Basic DVFS Date: Fri, 21 Jan 2011 19:30:55 +0530 Message-Id: <1295618465-15234-4-git-send-email-vishwanath.bs@ti.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1295618465-15234-1-git-send-email-vishwanath.bs@ti.com> References: <1295618465-15234-1-git-send-email-vishwanath.bs@ti.com> This patch introduces an API to perform DVFS for a given voltage domain. It takes omap_vdd_dvfs_info pointer as input parameter, computes the highest requested voltage for that vdd and scales all the devices in that vdd to the requested frequency along with voltage scaling. Based on original patch from Thara. Signed-off-by: Vishwanath BS Cc: Thara Gopinath --- arch/arm/mach-omap2/dvfs.c | 87 +++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 86 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/dvfs.c b/arch/arm/mach-omap2/dvfs.c index 8832e4a..cefc2be 100755 --- a/arch/arm/mach-omap2/dvfs.c +++ b/arch/arm/mach-omap2/dvfs.c @@ -21,7 +21,7 @@ #include /** - * struct omap_dev_user_list - Structure maitain userlist per devide + * struct omap_dev_user_list - Structure maitain userlist per device * * @dev: The device requesting for a particular frequency * @node: The list head entry @@ -413,6 +413,91 @@ static int omap_dvfs_remove_freq_request(struct omap_vdd_dvfs_info *dvfs_info, } /** + * omap_dvfs_voltage_scale() : API to scale the devices associated with a + * voltage domain vdd voltage. + * + * @dvfs_info: omap_vdd_dvfs_info pointer for the required vdd + * + * This API runs through the list of devices associated with the + * voltage domain and scales the device rates to the one requested + * by the user or those corresponding to the new voltage of the + * voltage domain. Target voltage is the highest voltage in the vdd_user_list. + * + * Returns 0 on success + * else the error value. + */ +static int omap_dvfs_voltage_scale(struct omap_vdd_dvfs_info *dvfs_info) +{ + unsigned long curr_volt; + int is_volt_scaled = 0; + struct omap_vdd_dev_list *temp_dev; + struct plist_node *node; + int ret = 0; + struct voltagedomain *voltdm; + unsigned long volt; + + if (!dvfs_info || IS_ERR(dvfs_info)) { + pr_warning("%s: VDD specified does not exist!\n", __func__); + return -EINVAL; + } + + voltdm = dvfs_info->voltdm; + + mutex_lock(&dvfs_info->scaling_mutex); + + /* Find the highest voltage being requested */ + node = plist_last(&dvfs_info->user_list); + volt = node->prio; + + curr_volt = omap_voltage_get_nom_volt(voltdm); + + if (curr_volt == volt) { + is_volt_scaled = 1; + } else if (curr_volt < volt) { + ret = omap_voltage_scale_vdd(voltdm, volt); + if (ret) { + pr_warning("%s: Unable to scale the %s to %ld volt\n", + __func__, voltdm->name, volt); + mutex_unlock(&dvfs_info->scaling_mutex); + return ret; + } + is_volt_scaled = 1; + } + + list_for_each_entry(temp_dev, &dvfs_info->dev_list, node) { + struct device *dev; + struct opp *opp; + unsigned long freq; + + dev = temp_dev->dev; + if (!plist_head_empty(&temp_dev->user_list)) { + node = plist_last(&temp_dev->user_list); + freq = node->prio; + } else { + opp = omap_dvfs_find_voltage(dev, volt); + if (IS_ERR(opp)) + continue; + freq = opp_get_freq(opp); + } + + if (freq == omap_device_get_rate(dev)) { + dev_dbg(dev, "%s: Already at the requested" + "rate %ld\n", __func__, freq); + continue; + } + + ret |= omap_device_set_rate(dev, freq); + } + + if (!is_volt_scaled && !ret) + omap_voltage_scale_vdd(voltdm, volt); + + mutex_unlock(&dvfs_info->scaling_mutex); + + return 0; +} + +/** * omap_dvfs_init() - Initialize omap dvfs layer * * Initalizes omap dvfs layer. It basically allocates memory for