Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e45e706 authored by Subhash Jadavani's avatar Subhash Jadavani Committed by Kyle Yan
Browse files

scsi: ufs: add support to limit the gear speed



Max. supported gear (for both HS and PWM modes) is negotiated between
host and device during link startup. We would switch to this max.
supported gear during UFS initialization. But on some platforms
(especially emulation platforms), this negotiated max. gear may not
work reliably. Hence this change adds options to limit the max. gear
(for both HS and PWM mode) for both directions (TX and RX).

Change-Id: I30b88ec9ac8fd35ab5ee48e06e727739fb9cd6b5
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
parent c04fcdd8
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -52,6 +52,12 @@ Optional properties:
- 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.
- limit-tx-hs-gear	: Specify the max. limit on the TX HS gear.
			  Valid range: 1-3. 1 => HS-G1, 2 => HS-G2, 3 => HS-G3
- limit-rx-hs-gear	: Specify the max. limit on the RX HS gear. Refer "limit-tx-hs-gear" for expected values.
- limit-tx-pwm-gear	: Specify the max. limit on the TX PWM gear
			  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.

Note: If above properties are not defined it can be assumed that the supply
regulators or clocks are always on.
+31 −0
Original line number Diff line number Diff line
@@ -234,6 +234,36 @@ static void ufshcd_parse_pm_levels(struct ufs_hba *hba)
	}
}

static void ufshcd_parse_gear_limits(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, "limit-tx-hs-gear",
		&hba->limit_tx_hs_gear);
	if (ret)
		hba->limit_tx_hs_gear = -1;

	ret = of_property_read_u32(np, "limit-rx-hs-gear",
		&hba->limit_rx_hs_gear);
	if (ret)
		hba->limit_rx_hs_gear = -1;

	ret = of_property_read_u32(np, "limit-tx-pwm-gear",
		&hba->limit_tx_pwm_gear);
	if (ret)
		hba->limit_tx_pwm_gear = -1;

	ret = of_property_read_u32(np, "limit-rx-pwm-gear",
		&hba->limit_rx_pwm_gear);
	if (ret)
		hba->limit_rx_pwm_gear = -1;
}

#ifdef CONFIG_SMP
/**
 * ufshcd_pltfrm_suspend - suspend power management function
@@ -339,6 +369,7 @@ int ufshcd_pltfrm_init(struct platform_device *pdev,
	}

	ufshcd_parse_pm_levels(hba);
	ufshcd_parse_gear_limits(hba);

	if (!dev->dma_mask)
		dev->dma_mask = &dev->coherent_dma_mask;
+16 −0
Original line number Diff line number Diff line
@@ -4164,8 +4164,16 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba)
			dev_err(hba->dev, "%s: invalid max pwm rx gear read = %d\n",
				__func__, pwr_info->gear_rx);
			return -EINVAL;
		} else {
			if (hba->limit_rx_pwm_gear > 0 &&
			    (hba->limit_rx_pwm_gear < pwr_info->gear_rx))
				pwr_info->gear_rx = hba->limit_rx_pwm_gear;
		}
		pwr_info->pwr_rx = SLOW_MODE;
	} else {
		if (hba->limit_rx_hs_gear > 0 &&
		    (hba->limit_rx_hs_gear < pwr_info->gear_rx))
			pwr_info->gear_rx = hba->limit_rx_hs_gear;
	}

	ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR),
@@ -4177,8 +4185,16 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba)
			dev_err(hba->dev, "%s: invalid max pwm tx gear read = %d\n",
				__func__, pwr_info->gear_tx);
			return -EINVAL;
		} else {
			if (hba->limit_tx_pwm_gear > 0 &&
			    (hba->limit_tx_pwm_gear < pwr_info->gear_tx))
				pwr_info->gear_tx = hba->limit_tx_pwm_gear;
		}
		pwr_info->pwr_tx = SLOW_MODE;
	} else {
		if (hba->limit_tx_hs_gear > 0 &&
		    (hba->limit_tx_hs_gear < pwr_info->gear_tx))
			pwr_info->gear_tx = hba->limit_tx_hs_gear;
	}

	hba->max_pwr_info.is_valid = true;
+6 −0
Original line number Diff line number Diff line
@@ -840,6 +840,12 @@ struct ufs_hba {
	/* Number of lanes available (1 or 2) for Rx/Tx */
	u32 lanes_per_direction;

	/* Gear limits */
	u32 limit_tx_hs_gear;
	u32 limit_rx_hs_gear;
	u32 limit_tx_pwm_gear;
	u32 limit_rx_pwm_gear;

	/* Bitmask for enabling debug prints */
	u32 ufshcd_dbg_print;