From patchwork Fri Jul 6 12:30:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Asutosh Das (asd)" X-Patchwork-Id: 10511547 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7A9D460325 for ; Fri, 6 Jul 2018 12:39:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6BF812860A for ; Fri, 6 Jul 2018 12:39:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5F7DD28617; Fri, 6 Jul 2018 12:39:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D4D3A2860A for ; Fri, 6 Jul 2018 12:39:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933206AbeGFMis (ORCPT ); Fri, 6 Jul 2018 08:38:48 -0400 Received: from alexa-out-blr-02.qualcomm.com ([103.229.18.198]:32534 "EHLO alexa-out-blr.qualcomm.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S933155AbeGFMiq (ORCPT ); Fri, 6 Jul 2018 08:38:46 -0400 X-Greylist: delayed 439 seconds by postgrey-1.27 at vger.kernel.org; Fri, 06 Jul 2018 08:38:44 EDT X-IronPort-AV: E=Sophos;i="5.51,316,1526322600"; d="scan'208";a="98693" Received: from ironmsg03-blr.qualcomm.com ([10.86.208.132]) by alexa-out-blr.qualcomm.com with ESMTP/TLS/AES256-SHA; 06 Jul 2018 18:00:53 +0530 X-IronPort-AV: E=McAfee;i="5900,7806,8945"; a="470257" Received: from asutoshd-linux.qualcomm.com ([10.206.24.163]) by ironmsg03-blr.qualcomm.com with ESMTP; 06 Jul 2018 18:00:52 +0530 Received: by asutoshd-linux.qualcomm.com (Postfix, from userid 92687) id D68A42FA3; Fri, 6 Jul 2018 18:00:51 +0530 (IST) From: Asutosh Das To: subhashj@codeaurora.org, cang@codeaurora.org, vivek.gautam@codeaurora.org, rnayak@codeaurora.org, vinholikatti@gmail.com, jejb@linux.vnet.ibm.com, martin.petersen@oracle.com, linux-scsi@vger.kernel.org Cc: linux-arm-msm@vger.kernel.org, Venkat Gopalakrishnan , Asutosh Das , Rob Herring , Mark Rutland , Mathieu Malaterre , devicetree@vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS), linux-kernel@vger.kernel.org (open list) Subject: [PATCH v1 4/9] scsi: ufs: add option to change default UFS power management level Date: Fri, 6 Jul 2018 18:00:31 +0530 Message-Id: X-Mailer: git-send-email 1.9.1 In-Reply-To: References: In-Reply-To: References: Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Subhash Jadavani UFS device and link can be put in multiple different low power modes hence UFS driver supports multiple different low power modes. By default UFS driver selects the default (optimal) low power mode (which gives moderate power savings and have relatively less enter and exit latencies) but we might have to tune this default power mode for different chipset platforms to meet the low power requirements/goals. Hence this patch adds option to change default UFS low power mode (level). Signed-off-by: Subhash Jadavani Signed-off-by: Venkat Gopalakrishnan Signed-off-by: Can Guo Signed-off-by: Asutosh Das --- .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 11 ++++++++ drivers/scsi/ufs/ufshcd-pltfrm.c | 14 +++++++++++ drivers/scsi/ufs/ufshcd.c | 29 +++++++++++++++------- drivers/scsi/ufs/ufshcd.h | 4 +-- 4 files changed, 47 insertions(+), 11 deletions(-) diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt index c39dfef..f564d9a 100644 --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt @@ -38,6 +38,15 @@ Optional properties: defined or a value in the array is "0" then it is assumed that the frequency is set by the parent clock or a fixed rate clock source. +- rpm-level : UFS Runtime power management level. Following PM levels are supported: + 0 - Both UFS device and Link in active state (Highest power consumption) + 1 - UFS device in active state but Link in Hibern8 state + 2 - UFS device in Sleep state but Link in active state + 3 - UFS device in Sleep state and Link in hibern8 state (default PM level) + 4 - UFS device in Power-down state and Link in Hibern8 state + 5 - UFS device in Power-down state and Link in OFF state (Lowest power consumption) +- spm-level : UFS System power management level. Allowed PM levels are same as rpm-level. + -lanes-per-direction : number of lanes available per direction - either 1 or 2. Note that it is assume same number of lanes is used both directions at once. If not specified, default is 2 lanes per direction. @@ -66,4 +75,6 @@ Example: freq-table-hz = <100000000 200000000>, <0 0>, <0 0>; phys = <&ufsphy1>; phy-names = "ufsphy"; + rpm-level = <3>; + spm-level = <5>; }; diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index e82bde0..7dba799 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -221,6 +221,19 @@ static int ufshcd_parse_regulator_info(struct ufs_hba *hba) return err; } +static void ufshcd_parse_pm_levels(struct ufs_hba *hba) +{ + struct device *dev = hba->dev; + struct device_node *np = dev->of_node; + + if (np) { + if (of_property_read_u32(np, "rpm-level", &hba->rpm_lvl)) + hba->rpm_lvl = -1; + if (of_property_read_u32(np, "spm-level", &hba->spm_lvl)) + hba->spm_lvl = -1; + } +} + #ifdef CONFIG_PM /** * ufshcd_pltfrm_suspend - suspend power management function @@ -340,6 +353,7 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, goto dealloc_host; } + ufshcd_parse_pm_levels(hba); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index b03f3ea..e950204 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -192,6 +192,14 @@ struct ufs_pm_lvl_states ufs_pm_lvl_states[] = { return UFS_PM_LVL_0; } +static inline bool ufshcd_is_valid_pm_lvl(int lvl) +{ + if (lvl >= 0 && lvl < ARRAY_SIZE(ufs_pm_lvl_states)) + return true; + else + return false; +} + static struct ufs_dev_fix ufs_fixups[] = { /* UFS cards deviations table */ UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, @@ -8051,16 +8059,19 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) } /* - * Set the default power management level for runtime and system PM. - * Default power saving mode is to keep UFS link in Hibern8 state - * and UFS device in sleep state. + * If rpm_lvl and and spm_lvl are not already set to valid levels, + * set the default power management level for UFS runtime and system + * suspend. Default power saving mode selected is keeping UFS link in + * Hibern8 state and UFS device in sleep state. */ - hba->rpm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( - UFS_SLEEP_PWR_MODE, - UIC_LINK_HIBERN8_STATE); - hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( - UFS_SLEEP_PWR_MODE, - UIC_LINK_HIBERN8_STATE); + if (!ufshcd_is_valid_pm_lvl(hba->rpm_lvl)) + hba->rpm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( + UFS_SLEEP_PWR_MODE, + UIC_LINK_HIBERN8_STATE); + if (!ufshcd_is_valid_pm_lvl(hba->spm_lvl)) + hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( + UFS_SLEEP_PWR_MODE, + UIC_LINK_HIBERN8_STATE); /* Set the default auto-hiberate idle timer value to 150 ms */ if (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT) { diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index e996a08..a2e1d5c 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -526,9 +526,9 @@ struct ufs_hba { enum ufs_dev_pwr_mode curr_dev_pwr_mode; enum uic_link_state uic_link_state; /* Desired UFS power management level during runtime PM */ - enum ufs_pm_level rpm_lvl; + int rpm_lvl; /* Desired UFS power management level during system PM */ - enum ufs_pm_level spm_lvl; + int spm_lvl; struct device_attribute rpm_lvl_attr; struct device_attribute spm_lvl_attr; int pm_op_in_progress;