Loading Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt +7 −0 Original line number Original line Diff line number Diff line Loading @@ -59,6 +59,12 @@ Optional properties: Valid range: 1-4. 1 => PWM-G1, 2 => PWM-G2, 3 => PWM-G3, 4 => PWM-G4 Valid range: 1-4. 1 => PWM-G1, 2 => PWM-G2, 3 => PWM-G3, 4 => PWM-G4 - limit-rx-pwm-gear : Specify the max. limit on the RX PWM gear. Refer "limit-tx-pwm-gear" for expected values. - limit-rx-pwm-gear : Specify the max. limit on the RX PWM gear. Refer "limit-tx-pwm-gear" for expected values. - scsi-cmd-timeout : Specify the command timeout (in seconds) for scsi commands - scsi-cmd-timeout : Specify the command timeout (in seconds) for scsi commands - dev-ref-clk-freq : Specify the device reference clock frequency, must be one of the following: 0: 19.2 MHz 1: 26 MHz 2: 38.4 MHz 3: 52 MHz Defaults to 26 MHz if not specified. Note: If above properties are not defined it can be assumed that the supply Note: If above properties are not defined it can be assumed that the supply regulators or clocks are always on. regulators or clocks are always on. Loading Loading @@ -87,6 +93,7 @@ Example: phy-names = "ufsphy"; phy-names = "ufsphy"; rpm-level = <3>; rpm-level = <3>; spm-level = <5>; spm-level = <5>; dev-ref-clk-freq = <0>; /* reference clock freq: 19.2 MHz */ }; }; ==== MSM UFS platform driver properties ===== ==== MSM UFS platform driver properties ===== Loading drivers/scsi/ufs/ufs.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -261,6 +261,15 @@ enum bkops_status { BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL, BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL, }; }; /* bRefClkFreq attribute values */ enum ref_clk_freq { REF_CLK_FREQ_19_2_MHZ = 0x0, REF_CLK_FREQ_26_MHZ = 0x1, REF_CLK_FREQ_38_4_MHZ = 0x2, REF_CLK_FREQ_52_MHZ = 0x3, REF_CLK_FREQ_MAX = REF_CLK_FREQ_52_MHZ, }; /* Query response result code */ /* Query response result code */ enum { enum { QUERY_RESULT_SUCCESS = 0x00, QUERY_RESULT_SUCCESS = 0x00, Loading drivers/scsi/ufs/ufshcd-pltfrm.c +19 −0 Original line number Original line Diff line number Diff line Loading @@ -279,6 +279,24 @@ static void ufshcd_parse_cmd_timeout(struct ufs_hba *hba) hba->scsi_cmd_timeout = 0; hba->scsi_cmd_timeout = 0; } } static void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba) { struct device *dev = hba->dev; struct device_node *np = dev->of_node; int ret; if (!np) return; ret = of_property_read_u32(np, "dev-ref-clk-freq", &hba->dev_ref_clk_freq); if (ret || (hba->dev_ref_clk_freq < 0) || (hba->dev_ref_clk_freq > REF_CLK_FREQ_52_MHZ)) /* default setting */ hba->dev_ref_clk_freq = REF_CLK_FREQ_26_MHZ; } #ifdef CONFIG_SMP #ifdef CONFIG_SMP /** /** * ufshcd_pltfrm_suspend - suspend power management function * ufshcd_pltfrm_suspend - suspend power management function Loading Loading @@ -383,6 +401,7 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, goto dealloc_host; goto dealloc_host; } } ufshcd_parse_dev_ref_clk_freq(hba); ufshcd_parse_pm_levels(hba); ufshcd_parse_pm_levels(hba); ufshcd_parse_gear_limits(hba); ufshcd_parse_gear_limits(hba); ufshcd_parse_cmd_timeout(hba); ufshcd_parse_cmd_timeout(hba); Loading drivers/scsi/ufs/ufshcd.c +60 −0 Original line number Original line Diff line number Diff line Loading @@ -6840,6 +6840,61 @@ static void ufshcd_apply_pm_quirks(struct ufs_hba *hba) } } } } /** * ufshcd_set_dev_ref_clk - set the device bRefClkFreq * @hba: per-adapter instance * * Read the current value of the bRefClkFreq attribute from device and update it * if host is supplying different reference clock frequency than one mentioned * in bRefClkFreq attribute. * * Returns zero on success, non-zero error value on failure. */ static int ufshcd_set_dev_ref_clk(struct ufs_hba *hba) { int err = 0; int ref_clk = -1; static const char * const ref_clk_freqs[] = {"19.2 MHz", "26 MHz", "38.4 MHz", "52 MHz"}; err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, QUERY_ATTR_IDN_REF_CLK_FREQ, 0, 0, &ref_clk); if (err) { dev_err(hba->dev, "%s: failed reading bRefClkFreq. err = %d\n", __func__, err); goto out; } if ((ref_clk < 0) || (ref_clk > REF_CLK_FREQ_52_MHZ)) { dev_err(hba->dev, "%s: invalid ref_clk setting = %d\n", __func__, ref_clk); err = -EINVAL; goto out; } if (ref_clk == hba->dev_ref_clk_freq) goto out; /* nothing to update */ err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, QUERY_ATTR_IDN_REF_CLK_FREQ, 0, 0, &hba->dev_ref_clk_freq); if (err) dev_err(hba->dev, "%s: bRefClkFreq setting to %s failed\n", __func__, ref_clk_freqs[hba->dev_ref_clk_freq]); else /* * It is good to print this out here to debug any later failures * related to gear switch. */ dev_info(hba->dev, "%s: bRefClkFreq setting to %s succeeded\n", __func__, ref_clk_freqs[hba->dev_ref_clk_freq]); out: return err; } /** /** * ufshcd_probe_hba - probe hba to detect device and initialize * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance * @hba: per-adapter instance Loading Loading @@ -6896,6 +6951,11 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) "%s: Failed getting max supported power mode\n", "%s: Failed getting max supported power mode\n", __func__); __func__); } else { } else { /* * Set the right value to bRefClkFreq before attempting to * switch to HS gears. */ ufshcd_set_dev_ref_clk(hba); ret = ufshcd_config_pwr_mode(hba, &hba->max_pwr_info.info); ret = ufshcd_config_pwr_mode(hba, &hba->max_pwr_info.info); if (ret) { if (ret) { dev_err(hba->dev, "%s: Failed setting power mode, err = %d\n", dev_err(hba->dev, "%s: Failed setting power mode, err = %d\n", Loading drivers/scsi/ufs/ufshcd.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -727,6 +727,8 @@ struct ufs_hba { unsigned int irq; unsigned int irq; bool is_irq_enabled; bool is_irq_enabled; u32 dev_ref_clk_freq; /* Interrupt aggregation support is broken */ /* Interrupt aggregation support is broken */ #define UFSHCD_QUIRK_BROKEN_INTR_AGGR UFS_BIT(0) #define UFSHCD_QUIRK_BROKEN_INTR_AGGR UFS_BIT(0) Loading Loading
Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt +7 −0 Original line number Original line Diff line number Diff line Loading @@ -59,6 +59,12 @@ Optional properties: Valid range: 1-4. 1 => PWM-G1, 2 => PWM-G2, 3 => PWM-G3, 4 => PWM-G4 Valid range: 1-4. 1 => PWM-G1, 2 => PWM-G2, 3 => PWM-G3, 4 => PWM-G4 - limit-rx-pwm-gear : Specify the max. limit on the RX PWM gear. Refer "limit-tx-pwm-gear" for expected values. - limit-rx-pwm-gear : Specify the max. limit on the RX PWM gear. Refer "limit-tx-pwm-gear" for expected values. - scsi-cmd-timeout : Specify the command timeout (in seconds) for scsi commands - scsi-cmd-timeout : Specify the command timeout (in seconds) for scsi commands - dev-ref-clk-freq : Specify the device reference clock frequency, must be one of the following: 0: 19.2 MHz 1: 26 MHz 2: 38.4 MHz 3: 52 MHz Defaults to 26 MHz if not specified. Note: If above properties are not defined it can be assumed that the supply Note: If above properties are not defined it can be assumed that the supply regulators or clocks are always on. regulators or clocks are always on. Loading Loading @@ -87,6 +93,7 @@ Example: phy-names = "ufsphy"; phy-names = "ufsphy"; rpm-level = <3>; rpm-level = <3>; spm-level = <5>; spm-level = <5>; dev-ref-clk-freq = <0>; /* reference clock freq: 19.2 MHz */ }; }; ==== MSM UFS platform driver properties ===== ==== MSM UFS platform driver properties ===== Loading
drivers/scsi/ufs/ufs.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -261,6 +261,15 @@ enum bkops_status { BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL, BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL, }; }; /* bRefClkFreq attribute values */ enum ref_clk_freq { REF_CLK_FREQ_19_2_MHZ = 0x0, REF_CLK_FREQ_26_MHZ = 0x1, REF_CLK_FREQ_38_4_MHZ = 0x2, REF_CLK_FREQ_52_MHZ = 0x3, REF_CLK_FREQ_MAX = REF_CLK_FREQ_52_MHZ, }; /* Query response result code */ /* Query response result code */ enum { enum { QUERY_RESULT_SUCCESS = 0x00, QUERY_RESULT_SUCCESS = 0x00, Loading
drivers/scsi/ufs/ufshcd-pltfrm.c +19 −0 Original line number Original line Diff line number Diff line Loading @@ -279,6 +279,24 @@ static void ufshcd_parse_cmd_timeout(struct ufs_hba *hba) hba->scsi_cmd_timeout = 0; hba->scsi_cmd_timeout = 0; } } static void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba) { struct device *dev = hba->dev; struct device_node *np = dev->of_node; int ret; if (!np) return; ret = of_property_read_u32(np, "dev-ref-clk-freq", &hba->dev_ref_clk_freq); if (ret || (hba->dev_ref_clk_freq < 0) || (hba->dev_ref_clk_freq > REF_CLK_FREQ_52_MHZ)) /* default setting */ hba->dev_ref_clk_freq = REF_CLK_FREQ_26_MHZ; } #ifdef CONFIG_SMP #ifdef CONFIG_SMP /** /** * ufshcd_pltfrm_suspend - suspend power management function * ufshcd_pltfrm_suspend - suspend power management function Loading Loading @@ -383,6 +401,7 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, goto dealloc_host; goto dealloc_host; } } ufshcd_parse_dev_ref_clk_freq(hba); ufshcd_parse_pm_levels(hba); ufshcd_parse_pm_levels(hba); ufshcd_parse_gear_limits(hba); ufshcd_parse_gear_limits(hba); ufshcd_parse_cmd_timeout(hba); ufshcd_parse_cmd_timeout(hba); Loading
drivers/scsi/ufs/ufshcd.c +60 −0 Original line number Original line Diff line number Diff line Loading @@ -6840,6 +6840,61 @@ static void ufshcd_apply_pm_quirks(struct ufs_hba *hba) } } } } /** * ufshcd_set_dev_ref_clk - set the device bRefClkFreq * @hba: per-adapter instance * * Read the current value of the bRefClkFreq attribute from device and update it * if host is supplying different reference clock frequency than one mentioned * in bRefClkFreq attribute. * * Returns zero on success, non-zero error value on failure. */ static int ufshcd_set_dev_ref_clk(struct ufs_hba *hba) { int err = 0; int ref_clk = -1; static const char * const ref_clk_freqs[] = {"19.2 MHz", "26 MHz", "38.4 MHz", "52 MHz"}; err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, QUERY_ATTR_IDN_REF_CLK_FREQ, 0, 0, &ref_clk); if (err) { dev_err(hba->dev, "%s: failed reading bRefClkFreq. err = %d\n", __func__, err); goto out; } if ((ref_clk < 0) || (ref_clk > REF_CLK_FREQ_52_MHZ)) { dev_err(hba->dev, "%s: invalid ref_clk setting = %d\n", __func__, ref_clk); err = -EINVAL; goto out; } if (ref_clk == hba->dev_ref_clk_freq) goto out; /* nothing to update */ err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, QUERY_ATTR_IDN_REF_CLK_FREQ, 0, 0, &hba->dev_ref_clk_freq); if (err) dev_err(hba->dev, "%s: bRefClkFreq setting to %s failed\n", __func__, ref_clk_freqs[hba->dev_ref_clk_freq]); else /* * It is good to print this out here to debug any later failures * related to gear switch. */ dev_info(hba->dev, "%s: bRefClkFreq setting to %s succeeded\n", __func__, ref_clk_freqs[hba->dev_ref_clk_freq]); out: return err; } /** /** * ufshcd_probe_hba - probe hba to detect device and initialize * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance * @hba: per-adapter instance Loading Loading @@ -6896,6 +6951,11 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) "%s: Failed getting max supported power mode\n", "%s: Failed getting max supported power mode\n", __func__); __func__); } else { } else { /* * Set the right value to bRefClkFreq before attempting to * switch to HS gears. */ ufshcd_set_dev_ref_clk(hba); ret = ufshcd_config_pwr_mode(hba, &hba->max_pwr_info.info); ret = ufshcd_config_pwr_mode(hba, &hba->max_pwr_info.info); if (ret) { if (ret) { dev_err(hba->dev, "%s: Failed setting power mode, err = %d\n", dev_err(hba->dev, "%s: Failed setting power mode, err = %d\n", Loading
drivers/scsi/ufs/ufshcd.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -727,6 +727,8 @@ struct ufs_hba { unsigned int irq; unsigned int irq; bool is_irq_enabled; bool is_irq_enabled; u32 dev_ref_clk_freq; /* Interrupt aggregation support is broken */ /* Interrupt aggregation support is broken */ #define UFSHCD_QUIRK_BROKEN_INTR_AGGR UFS_BIT(0) #define UFSHCD_QUIRK_BROKEN_INTR_AGGR UFS_BIT(0) Loading