Commit d3e89bac authored by Seungwon Jeon's avatar Seungwon Jeon Committed by James Bottomley
Browse files

[SCSI] ufs: configure the attribute for power mode



UIC attributes can be set with using DME_SET command for
power mode change. For configuration the link capability
attributes are used, which is updated after successful
link startup.

Signed-off-by: default avatarSeungwon Jeon <tgih.jun@samsung.com>
Reviewed-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: default avatarSantosh Y <santoshsy@gmail.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 53b3d9c3
Loading
Loading
Loading
Loading
+66 −0
Original line number Diff line number Diff line
@@ -1531,6 +1531,70 @@ int ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode)
	return ret;
}

/**
 * ufshcd_config_max_pwr_mode - Set & Change power mode with
 *	maximum capability attribute information.
 * @hba: per adapter instance
 *
 * Returns 0 on success, non-zero value on failure
 */
static int ufshcd_config_max_pwr_mode(struct ufs_hba *hba)
{
	enum {RX = 0, TX = 1};
	u32 lanes[] = {1, 1};
	u32 gear[] = {1, 1};
	u8 pwr[] = {FASTAUTO_MODE, FASTAUTO_MODE};
	int ret;

	/* Get the connected lane count */
	ufshcd_dme_get(hba, UIC_ARG_MIB(PA_CONNECTEDRXDATALANES), &lanes[RX]);
	ufshcd_dme_get(hba, UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), &lanes[TX]);

	/*
	 * First, get the maximum gears of HS speed.
	 * If a zero value, it means there is no HSGEAR capability.
	 * Then, get the maximum gears of PWM speed.
	 */
	ufshcd_dme_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR), &gear[RX]);
	if (!gear[RX]) {
		ufshcd_dme_get(hba, UIC_ARG_MIB(PA_MAXRXPWMGEAR), &gear[RX]);
		pwr[RX] = SLOWAUTO_MODE;
	}

	ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR), &gear[TX]);
	if (!gear[TX]) {
		ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXPWMGEAR),
				    &gear[TX]);
		pwr[TX] = SLOWAUTO_MODE;
	}

	/*
	 * Configure attributes for power mode change with below.
	 * - PA_RXGEAR, PA_ACTIVERXDATALANES, PA_RXTERMINATION,
	 * - PA_TXGEAR, PA_ACTIVETXDATALANES, PA_TXTERMINATION,
	 * - PA_HSSERIES
	 */
	ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXGEAR), gear[RX]);
	ufshcd_dme_set(hba, UIC_ARG_MIB(PA_ACTIVERXDATALANES), lanes[RX]);
	if (pwr[RX] == FASTAUTO_MODE)
		ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXTERMINATION), TRUE);

	ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXGEAR), gear[TX]);
	ufshcd_dme_set(hba, UIC_ARG_MIB(PA_ACTIVETXDATALANES), lanes[TX]);
	if (pwr[TX] == FASTAUTO_MODE)
		ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXTERMINATION), TRUE);

	if (pwr[RX] == FASTAUTO_MODE || pwr[TX] == FASTAUTO_MODE)
		ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HSSERIES), PA_HS_MODE_B);

	ret = ufshcd_uic_change_pwr_mode(hba, pwr[RX] << 4 | pwr[TX]);
	if (ret)
		dev_err(hba->dev,
			"pwr_mode: power mode change failed %d\n", ret);

	return ret;
}

/**
 * ufshcd_complete_dev_init() - checks device readiness
 * hba: per-adapter instance
@@ -2662,6 +2726,8 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie)
	if (ret)
		goto out;

	ufshcd_config_max_pwr_mode(hba);

	ret = ufshcd_verify_dev_init(hba);
	if (ret)
		goto out;
+21 −0
Original line number Diff line number Diff line
@@ -72,6 +72,21 @@
#define PA_STALLNOCONFIGTIME	0x15A3
#define PA_SAVECONFIGTIME	0x15A4

/* PA power modes */
enum {
	FAST_MODE	= 1,
	SLOW_MODE	= 2,
	FASTAUTO_MODE	= 4,
	SLOWAUTO_MODE	= 5,
	UNCHANGED	= 7,
};

/* PA TX/RX Frequency Series */
enum {
	PA_HS_MODE_A	= 1,
	PA_HS_MODE_B	= 2,
};

/*
 * Data Link Layer Attributes
 */
@@ -127,4 +142,10 @@
#define T_TC0TXMAXSDUSIZE	0x4060
#define T_TC1TXMAXSDUSIZE	0x4061

/* Boolean attribute values */
enum {
	FALSE = 0,
	TRUE,
};

#endif /* _UNIPRO_H_ */