Commit 86f4c65f authored by Ricky WU's avatar Ricky WU Committed by Greg Kroah-Hartman
Browse files

misc: rtsx: rts522a rts5228 rts5261 support Runtime PM



rts522a, rts5228, rts5261
add extra init flow for rtd3
add more power_down setting for avoid being woken up
by plugging or unplugging card when system in S3

Tested-by: default avatarKai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: default avatarRicky Wu <ricky_wu@realtek.com>
Link: https://lore.kernel.org/r/dace32f573a445908fec0a10482c394c@realtek.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f4e335f3
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -72,6 +72,8 @@ static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr)

	pci_read_config_dword(pdev, PCR_SETTING_REG2, &reg);
	pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
	if (CHK_PCI_PID(pcr, 0x522A))
		pcr->rtd3_en = rtsx_reg_to_rtd3(reg);
	if (rtsx_check_mmc_support(reg))
		pcr->extra_caps |= EXTRA_CAPS_NO_MMC;
	pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
@@ -171,6 +173,28 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
	else
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x30, 0x00);

	if (CHK_PCI_PID(pcr, 0x522A))
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RTS522A_AUTOLOAD_CFG1,
			CD_RESUME_EN_MASK, CD_RESUME_EN_MASK);

	if (pcr->rtd3_en) {
		if (CHK_PCI_PID(pcr, 0x522A)) {
			rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RTS522A_PM_CTRL3, 0x01, 0x01);
			rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RTS522A_PME_FORCE_CTL, 0x30, 0x30);
		} else {
			rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x01, 0x01);
			rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PME_FORCE_CTL, 0xFF, 0x33);
		}
	} else {
		if (CHK_PCI_PID(pcr, 0x522A)) {
			rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RTS522A_PM_CTRL3, 0x01, 0x00);
			rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RTS522A_PME_FORCE_CTL, 0x30, 0x20);
		} else {
			rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PME_FORCE_CTL, 0xFF, 0x30);
			rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x01, 0x00);
		}
	}

	if (option->force_clkreq_0)
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,
				FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
@@ -438,6 +462,28 @@ static int rts522a_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
	return rtsx_pci_send_cmd(pcr, 100);
}

static void rts522a_force_power_down(struct rtsx_pcr *pcr, u8 pm_state, bool runtime)
{
	/* Set relink_time to 0 */
	rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, MASK_8_BIT_DEF, 0);
	rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, MASK_8_BIT_DEF, 0);
	rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3,
				RELINK_TIME_MASK, 0);

	rtsx_pci_write_register(pcr, RTS522A_PM_CTRL3,
			D3_DELINK_MODE_EN, D3_DELINK_MODE_EN);

	if (!runtime) {
		rtsx_pci_write_register(pcr, RTS522A_AUTOLOAD_CFG1,
				CD_RESUME_EN_MASK, 0);
		rtsx_pci_write_register(pcr, RTS522A_PM_CTRL3, 0x01, 0x00);
		rtsx_pci_write_register(pcr, RTS522A_PME_FORCE_CTL, 0x30, 0x20);
	}

	rtsx_pci_write_register(pcr, FPDCTL, ALL_POWER_DOWN, ALL_POWER_DOWN);
}


static void rts522a_set_l1off_cfg_sub_d0(struct rtsx_pcr *pcr, int active)
{
	struct rtsx_cr_option *option = &pcr->option;
@@ -473,6 +519,7 @@ static const struct pcr_ops rts522a_pcr_ops = {
	.card_power_on = rts5227_card_power_on,
	.card_power_off = rts5227_card_power_off,
	.switch_output_voltage = rts522a_switch_output_voltage,
	.force_power_down = rts522a_force_power_down,
	.cd_deglitch = NULL,
	.conv_clk_and_div_n = NULL,
	.set_l1off_cfg_sub_d0 = rts522a_set_l1off_cfg_sub_d0,
+19 −2
Original line number Diff line number Diff line
@@ -102,6 +102,14 @@ static void rts5228_force_power_down(struct rtsx_pcr *pcr, u8 pm_state, bool run
	rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3,
			D3_DELINK_MODE_EN, D3_DELINK_MODE_EN);

	if (!runtime) {
		rtsx_pci_write_register(pcr, RTS5228_AUTOLOAD_CFG1,
				CD_RESUME_EN_MASK, 0);
		rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x01, 0x00);
		rtsx_pci_write_register(pcr, RTS5228_REG_PME_FORCE_CTL,
				FORCE_PM_CONTROL | FORCE_PM_VALUE, FORCE_PM_CONTROL);
	}

	rtsx_pci_write_register(pcr, FPDCTL,
		SSC_POWER_DOWN, SSC_POWER_DOWN);
}
@@ -480,9 +488,18 @@ static int rts5228_extra_init_hw(struct rtsx_pcr *pcr)
				 FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);

	rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB);
	rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00);

	if (pcr->rtd3_en) {
		rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x01, 0x01);
	rtsx_pci_write_register(pcr, RTS5228_REG_PME_FORCE_CTL,
				FORCE_PM_CONTROL | FORCE_PM_VALUE,
				FORCE_PM_CONTROL | FORCE_PM_VALUE);
	} else {
		rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x01, 0x00);
		rtsx_pci_write_register(pcr, RTS5228_REG_PME_FORCE_CTL,
				FORCE_PM_CONTROL | FORCE_PM_VALUE, FORCE_PM_CONTROL);
	}
	rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, D3_DELINK_MODE_EN, 0x00);

	return 0;
}
+30 −3
Original line number Diff line number Diff line
@@ -103,6 +103,24 @@ static void rts5261_force_power_down(struct rtsx_pcr *pcr, u8 pm_state, bool run
		rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3,
					D3_DELINK_MODE_EN, D3_DELINK_MODE_EN);

	if (!runtime) {
		rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG1,
				CD_RESUME_EN_MASK, 0);
		rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x01, 0x00);
		rtsx_pci_write_register(pcr, RTS5261_REG_PME_FORCE_CTL,
				FORCE_PM_CONTROL | FORCE_PM_VALUE, FORCE_PM_CONTROL);

	} else {
		rtsx_pci_write_register(pcr, RTS5261_REG_PME_FORCE_CTL,
				FORCE_PM_CONTROL | FORCE_PM_VALUE, 0);

		rtsx_pci_write_register(pcr, RTS5261_FW_CTL,
				RTS5261_INFORM_RTD3_COLD, RTS5261_INFORM_RTD3_COLD);
		rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG4,
				RTS5261_FORCE_PRSNT_LOW, RTS5261_FORCE_PRSNT_LOW);

	}

	rtsx_pci_write_register(pcr, RTS5261_REG_FPDCTL,
		SSC_POWER_DOWN, SSC_POWER_DOWN);
}
@@ -536,9 +554,18 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
				 FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);

	rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB);
	rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00);

	if (pcr->rtd3_en) {
		rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x01, 0x01);
		rtsx_pci_write_register(pcr, RTS5261_REG_PME_FORCE_CTL,
				FORCE_PM_CONTROL | FORCE_PM_VALUE,
				FORCE_PM_CONTROL | FORCE_PM_VALUE);
	} else {
		rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x01, 0x00);
		rtsx_pci_write_register(pcr, RTS5261_REG_PME_FORCE_CTL,
				FORCE_PM_CONTROL | FORCE_PM_VALUE, FORCE_PM_CONTROL);
	}
	rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, D3_DELINK_MODE_EN, 0x00);

	/* Clear Enter RTD3_cold Information*/
	rtsx_pci_write_register(pcr, RTS5261_FW_CTL,
+2 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
#define MIN_DIV_N_PCR		80
#define MAX_DIV_N_PCR		208

#define RTS522A_PME_FORCE_CTL	0xFF78
#define RTS522A_AUTOLOAD_CFG1	0xFF7C
#define RTS522A_PM_CTRL3		0xFF7E

#define RTS524A_PME_FORCE_CTL		0xFF78