* [PATCH v2 01/17] scsi: ufs-qcom: add number of lanes per direction [not found] <1445874072-25909-1-git-send-email-ygardi@codeaurora.org> @ 2015-10-26 15:40 ` Yaniv Gardi [not found] ` <1445874072-25909-1-git-send-email-ygardi-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> 1 sibling, 0 replies; 3+ messages in thread From: Yaniv Gardi @ 2015-10-26 15:40 UTC (permalink / raw) To: robherring2, James.Bottomley, pebolle, hch Cc: linux-kernel, linux-scsi, linux-arm-msm, santoshsy, linux-scsi-owner, subhashj, ygardi, gbroner, draviv, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Vinayak Holikatti, James E.J. Bottomley, open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS Different platform may have different number of lanes for the UFS link. Add parameter to device tree specifying how many lanes should be configured for the UFS link. Signed-off-by: Gilad Broner <gbroner@codeaurora.org> Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org> --- .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 3 ++ drivers/scsi/ufs/ufs-qcom.c | 38 ++++++++++++---------- drivers/scsi/ufs/ufshcd-pltfrm.c | 19 +++++++++++ drivers/scsi/ufs/ufshcd.c | 1 + drivers/scsi/ufs/ufshcd.h | 2 ++ 5 files changed, 46 insertions(+), 17 deletions(-) diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt index 03c0e98..9fea0de 100644 --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt @@ -38,6 +38,9 @@ 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. +- 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. Note: If above properties are not defined it can be assumed that the supply regulators or clocks are always on. diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 4f38d00..c470c40 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -132,21 +132,23 @@ static int ufs_qcom_enable_lane_clks(struct ufs_qcom_host *host) if (err) goto disable_rx_l0; - err = ufs_qcom_host_clk_enable(dev, "rx_lane1_sync_clk", - host->rx_l1_sync_clk); - if (err) - goto disable_tx_l0; - - err = ufs_qcom_host_clk_enable(dev, "tx_lane1_sync_clk", - host->tx_l1_sync_clk); - if (err) - goto disable_rx_l1; + if (host->hba->lanes_per_direction > 1) { + err = ufs_qcom_host_clk_enable(dev, "rx_lane1_sync_clk", + host->rx_l1_sync_clk); + if (err) + goto disable_tx_l0; + err = ufs_qcom_host_clk_enable(dev, "tx_lane1_sync_clk", + host->tx_l1_sync_clk); + if (err) + goto disable_rx_l1; + } host->is_lane_clks_enabled = true; goto out; disable_rx_l1: - clk_disable_unprepare(host->rx_l1_sync_clk); + if (host->hba->lanes_per_direction > 1) + clk_disable_unprepare(host->rx_l1_sync_clk); disable_tx_l0: clk_disable_unprepare(host->tx_l0_sync_clk); disable_rx_l0: @@ -170,14 +172,16 @@ static int ufs_qcom_init_lane_clks(struct ufs_qcom_host *host) if (err) goto out; - err = ufs_qcom_host_clk_get(dev, "rx_lane1_sync_clk", - &host->rx_l1_sync_clk); - if (err) - goto out; - - err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk", - &host->tx_l1_sync_clk); + /* In case of single lane per direction, don't read lane1 clocks */ + if (host->hba->lanes_per_direction > 1) { + err = ufs_qcom_host_clk_get(dev, "rx_lane1_sync_clk", + &host->rx_l1_sync_clk); + if (err) + goto out; + err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk", + &host->tx_l1_sync_clk); + } out: return err; } diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index 9714f2a..5be0c91 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -40,6 +40,8 @@ #include "ufshcd.h" #include "ufshcd-pltfrm.h" +#define UFSHCD_DEFAULT_LANES_PER_DIRECTION 2 + static int ufshcd_parse_clock_info(struct ufs_hba *hba) { int ret = 0; @@ -277,6 +279,21 @@ void ufshcd_pltfrm_shutdown(struct platform_device *pdev) } EXPORT_SYMBOL_GPL(ufshcd_pltfrm_shutdown); +static void ufshcd_init_lanes_per_dir(struct ufs_hba *hba) +{ + struct device *dev = hba->dev; + int ret; + + ret = of_property_read_u32(dev->of_node, "lanes-per-direction", + &hba->lanes_per_direction); + if (ret) { + dev_dbg(hba->dev, + "%s: failed to read lanes-per-direction, ret=%d\n", + __func__, ret); + hba->lanes_per_direction = UFSHCD_DEFAULT_LANES_PER_DIRECTION; + } +} + /** * ufshcd_pltfrm_init - probe routine of the driver * @pdev: pointer to Platform device handle @@ -331,6 +348,8 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); + ufshcd_init_lanes_per_dir(hba); + err = ufshcd_init(hba, mmio_base, irq); if (err) { dev_err(dev, "Intialization failed\n"); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 98607e4..8d16aca 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -40,6 +40,7 @@ #include <linux/async.h> #include <linux/devfreq.h> +#include <linux/of.h> #include "ufshcd.h" #include "unipro.h" diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index f8ce680..e7bcf65 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -509,6 +509,8 @@ struct ufs_hba { bool wlun_dev_clr_ua; + /* Number of lanes available (1 or 2) for Rx/Tx */ + u32 lanes_per_direction; struct ufs_pa_layer_attr pwr_info; struct ufs_pwr_mode_info max_pwr_info; -- 1.8.5.2 -- QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation ^ permalink raw reply related [flat|nested] 3+ messages in thread
[parent not found: <1445874072-25909-1-git-send-email-ygardi-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>]
* [PATCH v2 02/17] scsi: ufs: add option to change default UFS power management level [not found] ` <1445874072-25909-1-git-send-email-ygardi-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> @ 2015-10-26 15:40 ` Yaniv Gardi 2015-11-12 17:39 ` Rob Herring 0 siblings, 1 reply; 3+ messages in thread From: Yaniv Gardi @ 2015-10-26 15:40 UTC (permalink / raw) To: robherring2-Re5JQEeQqe8AvxtiuMwx3w, James.Bottomley-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk, pebolle-IWqWACnzNjzz+pZb47iToQ, hch-wEGCiKHe2LqWVfeAwA7xHQ Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA, linux-scsi-u79uwXL29TY76Z2rM5mHXA, linux-arm-msm-u79uwXL29TY76Z2rM5mHXA, santoshsy-Re5JQEeQqe8AvxtiuMwx3w, linux-scsi-owner-u79uwXL29TY76Z2rM5mHXA, subhashj-sgV2jX0FEOL9JmXXK+q4OQ, ygardi-sgV2jX0FEOL9JmXXK+q4OQ, gbroner-sgV2jX0FEOL9JmXXK+q4OQ, draviv-sgV2jX0FEOL9JmXXK+q4OQ, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Vinayak Holikatti, James E.J. Bottomley, open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS 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 <subhashj-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> Signed-off-by: Yaniv Gardi <ygardi-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> --- .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 8 +++++ drivers/scsi/ufs/ufshcd-pltfrm.c | 17 +++++++++- drivers/scsi/ufs/ufshcd.c | 39 ++++++++++++++++++++++ drivers/scsi/ufs/ufshcd.h | 4 +-- 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt index 9fea0de..b7db1c9 100644 --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt @@ -38,6 +38,14 @@ 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. diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index 5be0c91..1130dd9 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -226,7 +226,20 @@ out: return err; } -#ifdef CONFIG_PM +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_SMP /** * ufshcd_pltfrm_suspend - suspend power management function * @dev: pointer to device handle @@ -345,6 +358,8 @@ 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 8d16aca..20c5b5d 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -187,6 +187,30 @@ ufs_get_pm_lvl_to_link_pwr_state(enum ufs_pm_level lvl) return ufs_pm_lvl_states[lvl].link_state; } +static inline enum ufs_pm_level +ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state, + enum uic_link_state link_state) +{ + enum ufs_pm_level lvl; + + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) { + if ((ufs_pm_lvl_states[lvl].dev_state == dev_state) && + (ufs_pm_lvl_states[lvl].link_state == link_state)) + return lvl; + } + + /* if no match found, return the level 0 */ + 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 void ufshcd_tmc_handler(struct ufs_hba *hba); static void ufshcd_async_scan(void *data, async_cookie_t cookie); static int ufshcd_reset_and_restore(struct ufs_hba *hba); @@ -5885,6 +5909,21 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) hba->clk_scaling.window_start_t = 0; } + /* + * 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. + */ + 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); + /* Hold auto suspend until async scan completes */ pm_runtime_get_sync(dev); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index e7bcf65..889335a 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -408,9 +408,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; int pm_op_in_progress; struct ufshcd_lrb *lrb; -- 1.8.5.2 -- QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2 02/17] scsi: ufs: add option to change default UFS power management level 2015-10-26 15:40 ` [PATCH v2 02/17] scsi: ufs: add option to change default UFS power management level Yaniv Gardi @ 2015-11-12 17:39 ` Rob Herring 0 siblings, 0 replies; 3+ messages in thread From: Rob Herring @ 2015-11-12 17:39 UTC (permalink / raw) To: Yaniv Gardi Cc: robherring2, James.Bottomley, pebolle, hch, linux-kernel, linux-scsi, linux-arm-msm, santoshsy, linux-scsi-owner, subhashj, gbroner, draviv, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Vinayak Holikatti, James E.J. Bottomley, open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS On Mon, Oct 26, 2015 at 05:40:57PM +0200, Yaniv Gardi wrote: > 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 <subhashj@codeaurora.org> > Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org> > > --- > .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 8 +++++ > drivers/scsi/ufs/ufshcd-pltfrm.c | 17 +++++++++- > drivers/scsi/ufs/ufshcd.c | 39 ++++++++++++++++++++++ > drivers/scsi/ufs/ufshcd.h | 4 +-- > 4 files changed, 65 insertions(+), 3 deletions(-) > > diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt > index 9fea0de..b7db1c9 100644 > --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt > +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt > @@ -38,6 +38,14 @@ 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. These seem too Linux specific. What would make them different for runtime-PM vs. system suspend? Power mgmt capabilities in the kernel change over time (and vary by OS), so you don't want to encode them into DT. I would probably define separately what modes the phy supports and the device supports. Isn't hibern8 required by the MPHY or UniPro spec? If so, that should be assumed to be supported and then have a quirk property to flag it as broken. Rob ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2015-11-12 17:39 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- [not found] <1445874072-25909-1-git-send-email-ygardi@codeaurora.org> 2015-10-26 15:40 ` [PATCH v2 01/17] scsi: ufs-qcom: add number of lanes per direction Yaniv Gardi [not found] ` <1445874072-25909-1-git-send-email-ygardi-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> 2015-10-26 15:40 ` [PATCH v2 02/17] scsi: ufs: add option to change default UFS power management level Yaniv Gardi 2015-11-12 17:39 ` Rob Herring
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).