Commit f8cba9a7 authored by Manish Pandey's avatar Manish Pandey Committed by Martin K. Petersen
Browse files

scsi: ufs: qcom: Add quirks for Samsung UFS devices



Introduce quirks for Samsung UFS devices to adjust PA TX HSG1 sync
length and TX_HS_EQUALIZER settings on the Qualcomm UFS Host
controller. This ensures proper functionality of Samsung UFS devices
with the Qualcomm UFS Host controller.

Signed-off-by: default avatarManish Pandey <quic_mapa@quicinc.com>
Link: https://lore.kernel.org/r/20250411121630.21330-2-quic_mapa@quicinc.com


Reviewed-by: default avatarBean Huo <beanhuo@micron.com>
Reviewed-by: default avatarManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 7f533cc5
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -33,6 +33,10 @@
	((((c) >> 16) & MCQ_QCFGPTR_MASK) * MCQ_QCFGPTR_UNIT)
#define MCQ_QCFG_SIZE	0x40

/* De-emphasis for gear-5 */
#define DEEMPHASIS_3_5_dB	0x04
#define NO_DEEMPHASIS		0x0

enum {
	TSTBUS_UAWM,
	TSTBUS_UARM,
@@ -795,6 +799,23 @@ static int ufs_qcom_icc_update_bw(struct ufs_qcom_host *host)
	return ufs_qcom_icc_set_bw(host, bw_table.mem_bw, bw_table.cfg_bw);
}

static void ufs_qcom_set_tx_hs_equalizer(struct ufs_hba *hba, u32 gear, u32 tx_lanes)
{
	u32 equalizer_val;
	int ret, i;

	/* Determine the equalizer value based on the gear */
	equalizer_val = (gear == 5) ? DEEMPHASIS_3_5_dB : NO_DEEMPHASIS;

	for (i = 0; i < tx_lanes; i++) {
		ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(TX_HS_EQUALIZER, i),
				     equalizer_val);
		if (ret)
			dev_err(hba->dev, "%s: failed equalizer lane %d\n",
				__func__, i);
	}
}

static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
				enum ufs_notify_change_status status,
				const struct ufs_pa_layer_attr *dev_max_params,
@@ -846,6 +867,11 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
						dev_req_params->gear_tx,
						PA_INITIAL_ADAPT);
		}

		if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TX_DEEMPHASIS_TUNING)
			ufs_qcom_set_tx_hs_equalizer(hba,
					dev_req_params->gear_tx, dev_req_params->lane_tx);

		break;
	case POST_CHANGE:
		if (ufs_qcom_cfg_timers(hba, false)) {
@@ -893,6 +919,16 @@ static int ufs_qcom_quirk_host_pa_saveconfigtime(struct ufs_hba *hba)
			    (pa_vs_config_reg1 | (1 << 12)));
}

static void ufs_qcom_override_pa_tx_hsg1_sync_len(struct ufs_hba *hba)
{
	int err;

	err = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(PA_TX_HSG1_SYNC_LENGTH),
				  PA_TX_HSG1_SYNC_LENGTH_VAL);
	if (err)
		dev_err(hba->dev, "Failed (%d) set PA_TX_HSG1_SYNC_LENGTH\n", err);
}

static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba)
{
	int err = 0;
@@ -900,6 +936,9 @@ static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba)
	if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME)
		err = ufs_qcom_quirk_host_pa_saveconfigtime(hba);

	if (hba->dev_quirks & UFS_DEVICE_QUIRK_PA_TX_HSG1_SYNC_LENGTH)
		ufs_qcom_override_pa_tx_hsg1_sync_len(hba);

	return err;
}

@@ -914,6 +953,10 @@ static struct ufs_dev_quirk ufs_qcom_dev_fixups[] = {
	{ .wmanufacturerid = UFS_VENDOR_WDC,
	  .model = UFS_ANY_MODEL,
	  .quirk = UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE },
	{ .wmanufacturerid = UFS_VENDOR_SAMSUNG,
	  .model = UFS_ANY_MODEL,
	  .quirk = UFS_DEVICE_QUIRK_PA_TX_HSG1_SYNC_LENGTH |
		   UFS_DEVICE_QUIRK_PA_TX_DEEMPHASIS_TUNING },
	{}
};

+18 −0
Original line number Diff line number Diff line
@@ -122,8 +122,11 @@ enum {
				 TMRLUT_HW_CGC_EN | OCSC_HW_CGC_EN)

/* QUniPro Vendor specific attributes */
#define PA_TX_HSG1_SYNC_LENGTH	0x1552
#define PA_VS_CONFIG_REG1	0x9000
#define DME_VS_CORE_CLK_CTRL	0xD002
#define TX_HS_EQUALIZER		0x0037

/* bit and mask definitions for DME_VS_CORE_CLK_CTRL attribute */
#define CLK_1US_CYCLES_MASK_V4				GENMASK(27, 16)
#define CLK_1US_CYCLES_MASK				GENMASK(7, 0)
@@ -141,6 +144,21 @@ enum {
#define UNIPRO_CORE_CLK_FREQ_201_5_MHZ         202
#define UNIPRO_CORE_CLK_FREQ_403_MHZ           403

/* TX_HSG1_SYNC_LENGTH attr value */
#define PA_TX_HSG1_SYNC_LENGTH_VAL	0x4A

/*
 * Some ufs device vendors need a different TSync length.
 * Enable this quirk to give an additional TX_HS_SYNC_LENGTH.
 */
#define UFS_DEVICE_QUIRK_PA_TX_HSG1_SYNC_LENGTH		BIT(16)

/*
 * Some ufs device vendors need a different Deemphasis setting.
 * Enable this quirk to tune TX Deemphasis parameters.
 */
#define UFS_DEVICE_QUIRK_PA_TX_DEEMPHASIS_TUNING	BIT(17)

/* ICE allocator type to share AES engines among TX stream and RX stream */
#define ICE_ALLOCATOR_TYPE 2