[PATCH v2 6/7] ufs: host: ufs-exynos: add support for fsd ufs hci

Chanho Park chanho61.park at samsung.com
Tue Jun 7 19:17:07 PDT 2022


> Subject: [PATCH v2 6/7] ufs: host: ufs-exynos: add support for fsd ufs hci
> 
> Adds support of UFS HCI which is found in Tesla Full Self-Driving (FSD)
> SoC.
> 
> Signed-off-by: Bharat Uppal <bharat.uppal at samsung.com>
> Signed-off-by: Alim Akhtar <alim.akhtar at samsung.com>
> ---
>  drivers/ufs/host/ufs-exynos.c | 138 ++++++++++++++++++++++++++++++++++
>  1 file changed, 138 insertions(+)
> 
> diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
> index cc128aff8871..7e0ab8a8662e 100644
> --- a/drivers/ufs/host/ufs-exynos.c
> +++ b/drivers/ufs/host/ufs-exynos.c
> @@ -1474,6 +1474,102 @@ static int exynosauto_ufs_vh_init(struct ufs_hba
> *hba)
>  	return 0;
>  }
> 
> +static int fsd_ufs_pre_link(struct exynos_ufs *ufs) {
> +	int i;
> +	struct ufs_hba *hba = ufs->hba;
> +
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(0x9514), 1000000000L / ufs-
> >mclk_rate);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(0x201), 0x12);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(0x200), 0x40);
> +
> +	for_each_ufs_tx_lane(ufs, i) {
> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xAA, i), 1000000000L /
> ufs->mclk_rate);

Use NSEC_PER_SEC and DIV_ROUND_UP as well.

> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x8F, i), 0x3F);
> +	}
> +
> +	for_each_ufs_rx_lane(ufs, i) {
> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x12, i), 1000000000L /
> ufs->mclk_rate);
> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x5C, i), 0x38);
> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x0F, i), 0x0);
> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x65, i), 0x1);
> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x69, i), 0x1);
> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x21, i), 0x0);
> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x22, i), 0x0);
> +	}
> +
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(0x200), 0x0);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(0x9536), 0x4E20);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(0x9564), 0x2e820183);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0x0);
> +
> +	exynos_ufs_establish_connt(ufs);
> +
> +	return 0;
> +}
> +
> +static int fsd_ufs_post_link(struct exynos_ufs *ufs) {
> +	int i;
> +	struct ufs_hba *hba = ufs->hba;
> +	u32 hw_cap_min_tactivate;
> +	u32 peer_rx_min_actv_time_cap;
> +	u32 max_rx_hibern8_time_cap;
> +
> +	ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(0x8F, 4),
> +			&hw_cap_min_tactivate); /* HW Capability of
> MIN_TACTIVATE */
> +	ufshcd_dme_get(hba, UIC_ARG_MIB(0x15A8),
> +			&peer_rx_min_actv_time_cap);    /* PA_TActivate */
> +	ufshcd_dme_get(hba, UIC_ARG_MIB(0x15A7),
> +			&max_rx_hibern8_time_cap);      /* PA_Hibern8Time */
> +
> +	if (peer_rx_min_actv_time_cap >= hw_cap_min_tactivate)
> +		ufshcd_dme_peer_set(hba, UIC_ARG_MIB(0x15A8),
> +					peer_rx_min_actv_time_cap + 1);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(0x15A7), max_rx_hibern8_time_cap +
> 1);
> +
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(0x9529), 0x01);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(0x15A4), 0xFA);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(0x9529), 0x00);
> +
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(0x200), 0x40);
> +
> +	for_each_ufs_rx_lane(ufs, i) {
> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x35, i), 0x05);
> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x73, i), 0x01);
> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x41, i), 0x02);
> +		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x42, i), 0xAC);
> +	}
> +
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(0x200), 0x0);
> +
> +	return 0;
> +}
> +
> +static int fsd_ufs_pre_pwr_change(struct exynos_ufs *ufs,
> +					struct ufs_pa_layer_attr *pwr)
> +{
> +	struct ufs_hba *hba = ufs->hba;
> +
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXTERMINATION), 0x1);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXTERMINATION), 0x1);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(DL_FC0PROTTIMEOUTVAL), 8064);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(DL_TC0REPLAYTIMEOUTVAL), 28224);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(DL_AFC0REQTIMEOUTVAL), 20160);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA0), 12000);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA1), 32000);
> +	ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA2), 16000);

If you set custom pwrmode setting, you'll need to set UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING.

> +
> +	unipro_writel(ufs, 8064, 0x7888);
> +	unipro_writel(ufs, 28224, 0x788C);
> +	unipro_writel(ufs, 20160, 0x7890);

Duplicated setting with above dme_set calls. (DL_FC0PROTTIMEOUTVAL / DL_TC0REPLAYTIMEOUTVAL / DL_AFC0REQTIMEOUTVAL)
Unipro registers are mirrored and you can use unipro_* APIs but need to choose one of them.

> +	unipro_writel(ufs, 12000, 0x78B8);
> +	unipro_writel(ufs, 32000, 0x78BC);
> +	unipro_writel(ufs, 16000, 0x78C0);

Put some documents the register as DME_POWERMODE_REQ_REMOTEL2TIMER0/1/2 or use macro for them.

Best Regards,
Chanho Park




More information about the linux-arm-kernel mailing list