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

Commit 773ccdfd authored by Wei WANG's avatar Wei WANG Committed by Samuel Ortiz
Browse files

mfd: rtsx: Read vendor setting from config space



Normally OEMs will set vendor setting to the config space of Realtek
card reader in BIOS stage. This patch reads the setting at the first,
and configure the internal registers according to it, to improve card
reader's compatibility condition.

Signed-off-by: default avatarWei WANG <wei_wang@realsil.com.cn>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 74d85e47
Loading
Loading
Loading
Loading
+71 −6
Original line number Original line Diff line number Diff line
@@ -47,19 +47,70 @@ static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr)
		return 0;
		return 0;
}
}


static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
{
	u32 reg1;
	u8 reg3;

	rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg1);
	dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1);

	if (!rtsx_vendor_setting_valid(reg1))
		return;

	pcr->aspm_en = rtsx_reg_to_aspm(reg1);
	pcr->sd30_drive_sel_1v8 =
		map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg1));
	pcr->card_drive_sel &= 0x3F;
	pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg1);

	rtsx_pci_read_config_byte(pcr, PCR_SETTING_REG3, &reg3);
	dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3);
	pcr->sd30_drive_sel_3v3 = rtl8411_reg_to_sd30_drive_sel_3v3(reg3);
}

static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr)
{
	u32 reg;

	rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
	dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);

	if (!rtsx_vendor_setting_valid(reg))
		return;

	pcr->aspm_en = rtsx_reg_to_aspm(reg);
	pcr->sd30_drive_sel_1v8 =
		map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg));
	pcr->sd30_drive_sel_3v3 =
		map_sd_drive(rtl8411b_reg_to_sd30_drive_sel_3v3(reg));
}

static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr)
static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr)
{
{
	return rtsx_pci_write_register(pcr, CD_PAD_CTL,
	rtsx_pci_init_cmd(pcr);

	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
			0xFF, pcr->sd30_drive_sel_3v3);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL,
			CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
			CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);

	return rtsx_pci_send_cmd(pcr, 100);
}
}


static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr)
static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr)
{
{
	if (rtl8411b_is_qfn48(pcr))
	rtsx_pci_init_cmd(pcr);
		rtsx_pci_write_register(pcr, CARD_PULL_CTL3, 0xFF, 0xF5);


	return rtsx_pci_write_register(pcr, CD_PAD_CTL,
	if (rtl8411b_is_qfn48(pcr))
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
				CARD_PULL_CTL3, 0xFF, 0xF5);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
			0xFF, pcr->sd30_drive_sel_3v3);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL,
			CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
			CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);

	return rtsx_pci_send_cmd(pcr, 100);
}
}


static int rtl8411_turn_on_led(struct rtsx_pcr *pcr)
static int rtl8411_turn_on_led(struct rtsx_pcr *pcr)
@@ -141,13 +192,13 @@ static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
	mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK;
	mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK;
	if (voltage == OUTPUT_3V3) {
	if (voltage == OUTPUT_3V3) {
		err = rtsx_pci_write_register(pcr,
		err = rtsx_pci_write_register(pcr,
				SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D);
				SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3;
		val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3;
	} else if (voltage == OUTPUT_1V8) {
	} else if (voltage == OUTPUT_1V8) {
		err = rtsx_pci_write_register(pcr,
		err = rtsx_pci_write_register(pcr,
				SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B);
				SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8;
		val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8;
@@ -222,6 +273,7 @@ static int rtl8411_conv_clk_and_div_n(int input, int dir)
}
}


static const struct pcr_ops rtl8411_pcr_ops = {
static const struct pcr_ops rtl8411_pcr_ops = {
	.fetch_vendor_settings = rtl8411_fetch_vendor_settings,
	.extra_init_hw = rtl8411_extra_init_hw,
	.extra_init_hw = rtl8411_extra_init_hw,
	.optimize_phy = NULL,
	.optimize_phy = NULL,
	.turn_on_led = rtl8411_turn_on_led,
	.turn_on_led = rtl8411_turn_on_led,
@@ -236,6 +288,7 @@ static const struct pcr_ops rtl8411_pcr_ops = {
};
};


static const struct pcr_ops rtl8411b_pcr_ops = {
static const struct pcr_ops rtl8411b_pcr_ops = {
	.fetch_vendor_settings = rtl8411b_fetch_vendor_settings,
	.extra_init_hw = rtl8411b_extra_init_hw,
	.extra_init_hw = rtl8411b_extra_init_hw,
	.optimize_phy = NULL,
	.optimize_phy = NULL,
	.turn_on_led = rtl8411_turn_on_led,
	.turn_on_led = rtl8411_turn_on_led,
@@ -385,6 +438,12 @@ void rtl8411_init_params(struct rtsx_pcr *pcr)
	pcr->num_slots = 2;
	pcr->num_slots = 2;
	pcr->ops = &rtl8411_pcr_ops;
	pcr->ops = &rtl8411_pcr_ops;


	pcr->flags = 0;
	pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT;
	pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
	pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
	pcr->aspm_en = ASPM_L1_EN;

	pcr->ic_version = rtl8411_get_ic_version(pcr);
	pcr->ic_version = rtl8411_get_ic_version(pcr);
	pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl;
	pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl;
	pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl;
	pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl;
@@ -398,6 +457,12 @@ void rtl8411b_init_params(struct rtsx_pcr *pcr)
	pcr->num_slots = 2;
	pcr->num_slots = 2;
	pcr->ops = &rtl8411b_pcr_ops;
	pcr->ops = &rtl8411b_pcr_ops;


	pcr->flags = 0;
	pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT;
	pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
	pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
	pcr->aspm_en = ASPM_L1_EN;

	pcr->ic_version = rtl8411_get_ic_version(pcr);
	pcr->ic_version = rtl8411_get_ic_version(pcr);


	if (rtl8411b_is_qfn48(pcr)) {
	if (rtl8411b_is_qfn48(pcr)) {
+33 −15
Original line number Original line Diff line number Diff line
@@ -34,18 +34,28 @@ static u8 rts5209_get_ic_version(struct rtsx_pcr *pcr)
	return val & 0x0F;
	return val & 0x0F;
}
}


static void rts5209_init_vendor_cfg(struct rtsx_pcr *pcr)
static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr)
{
{
	u32 val;
	u32 reg;


	rtsx_pci_read_config_dword(pcr, 0x724, &val);
	rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
	dev_dbg(&(pcr->pci->dev), "Cfg 0x724: 0x%x\n", val);
	dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);


	if (!(val & 0x80)) {
	if (rts5209_vendor_setting1_valid(reg)) {
		if (val & 0x08)
		if (rts5209_reg_check_ms_pmos(reg))
			pcr->ms_pmos = false;
			pcr->flags |= PCR_MS_PMOS;
		else
		pcr->aspm_en = rts5209_reg_to_aspm(reg);
			pcr->ms_pmos = true;
	}

	rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
	dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);

	if (rts5209_vendor_setting2_valid(reg)) {
		pcr->sd30_drive_sel_1v8 =
			rts5209_reg_to_sd30_drive_sel_1v8(reg);
		pcr->sd30_drive_sel_3v3 =
			rts5209_reg_to_sd30_drive_sel_3v3(reg);
		pcr->card_drive_sel = rts5209_reg_to_card_drive_sel(reg);
	}
	}
}
}


@@ -57,6 +67,9 @@ static int rts5209_extra_init_hw(struct rtsx_pcr *pcr)
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO, 0xFF, 0x03);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO, 0xFF, 0x03);
	/* Configure GPIO as output */
	/* Configure GPIO as output */
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO_DIR, 0xFF, 0x03);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO_DIR, 0xFF, 0x03);
	/* Configure driving */
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
			0xFF, pcr->sd30_drive_sel_3v3);


	return rtsx_pci_send_cmd(pcr, 100);
	return rtsx_pci_send_cmd(pcr, 100);
}
}
@@ -95,7 +108,7 @@ static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card)
	partial_pwr_on = SD_PARTIAL_POWER_ON;
	partial_pwr_on = SD_PARTIAL_POWER_ON;
	pwr_on = SD_POWER_ON;
	pwr_on = SD_POWER_ON;


	if (pcr->ms_pmos && (card == RTSX_MS_CARD)) {
	if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) {
		pwr_mask = MS_POWER_MASK;
		pwr_mask = MS_POWER_MASK;
		partial_pwr_on = MS_PARTIAL_POWER_ON;
		partial_pwr_on = MS_PARTIAL_POWER_ON;
		pwr_on = MS_POWER_ON;
		pwr_on = MS_POWER_ON;
@@ -131,7 +144,7 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
	pwr_mask = SD_POWER_MASK;
	pwr_mask = SD_POWER_MASK;
	pwr_off = SD_POWER_OFF;
	pwr_off = SD_POWER_OFF;


	if (pcr->ms_pmos && (card == RTSX_MS_CARD)) {
	if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) {
		pwr_mask = MS_POWER_MASK;
		pwr_mask = MS_POWER_MASK;
		pwr_off = MS_POWER_OFF;
		pwr_off = MS_POWER_OFF;
	}
	}
@@ -140,7 +153,7 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
			pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA);
			pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
			LDO3318_PWR_MASK, 0X06);
			LDO3318_PWR_MASK, 0x06);
	return rtsx_pci_send_cmd(pcr, 100);
	return rtsx_pci_send_cmd(pcr, 100);
}
}


@@ -150,7 +163,7 @@ static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)


	if (voltage == OUTPUT_3V3) {
	if (voltage == OUTPUT_3V3) {
		err = rtsx_pci_write_register(pcr,
		err = rtsx_pci_write_register(pcr,
				SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D);
				SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
@@ -158,7 +171,7 @@ static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
			return err;
			return err;
	} else if (voltage == OUTPUT_1V8) {
	} else if (voltage == OUTPUT_1V8) {
		err = rtsx_pci_write_register(pcr,
		err = rtsx_pci_write_register(pcr,
				SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B);
				SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
@@ -172,6 +185,7 @@ static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
}
}


static const struct pcr_ops rts5209_pcr_ops = {
static const struct pcr_ops rts5209_pcr_ops = {
	.fetch_vendor_settings = rts5209_fetch_vendor_settings,
	.extra_init_hw = rts5209_extra_init_hw,
	.extra_init_hw = rts5209_extra_init_hw,
	.optimize_phy = rts5209_optimize_phy,
	.optimize_phy = rts5209_optimize_phy,
	.turn_on_led = rts5209_turn_on_led,
	.turn_on_led = rts5209_turn_on_led,
@@ -242,7 +256,11 @@ void rts5209_init_params(struct rtsx_pcr *pcr)
	pcr->num_slots = 2;
	pcr->num_slots = 2;
	pcr->ops = &rts5209_pcr_ops;
	pcr->ops = &rts5209_pcr_ops;


	rts5209_init_vendor_cfg(pcr);
	pcr->flags = 0;
	pcr->card_drive_sel = RTS5209_CARD_DRIVE_DEFAULT;
	pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
	pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
	pcr->aspm_en = ASPM_L1_EN;


	pcr->ic_version = rts5209_get_ic_version(pcr);
	pcr->ic_version = rts5209_get_ic_version(pcr);
	pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl;
	pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl;
+71 −20
Original line number Original line Diff line number Diff line
@@ -29,6 +29,60 @@


#include "rtsx_pcr.h"
#include "rtsx_pcr.h"


static void rts5227_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
{
	u8 driving_3v3[4][3] = {
		{0x13, 0x13, 0x13},
		{0x96, 0x96, 0x96},
		{0x7F, 0x7F, 0x7F},
		{0x96, 0x96, 0x96},
	};
	u8 driving_1v8[4][3] = {
		{0x99, 0x99, 0x99},
		{0xAA, 0xAA, 0xAA},
		{0xFE, 0xFE, 0xFE},
		{0xB3, 0xB3, 0xB3},
	};
	u8 (*driving)[3], drive_sel;

	if (voltage == OUTPUT_3V3) {
		driving = driving_3v3;
		drive_sel = pcr->sd30_drive_sel_3v3;
	} else {
		driving = driving_1v8;
		drive_sel = pcr->sd30_drive_sel_1v8;
	}

	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
			0xFF, driving[drive_sel][0]);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
			0xFF, driving[drive_sel][1]);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
			0xFF, driving[drive_sel][2]);
}

static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr)
{
	u32 reg;

	rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
	dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);

	if (!rtsx_vendor_setting_valid(reg))
		return;

	pcr->aspm_en = rtsx_reg_to_aspm(reg);
	pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg);
	pcr->card_drive_sel &= 0x3F;
	pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);

	rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
	dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
	pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
	if (rtsx_reg_check_reverse_socket(reg))
		pcr->flags |= PCR_REVERSE_SOCKET;
}

static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
{
{
	u16 cap;
	u16 cap;
@@ -48,17 +102,15 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3);
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3);
	/* Configure OBFF */
	/* Configure OBFF */
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03);
	/* Configure force_clock_req
	/* Configure driving */
	 * Maybe We should define 0xFF03 as some name
	rts5227_fill_driving(pcr, OUTPUT_3V3);
	 */
	/* Configure force_clock_req */
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 0xFF03, 0x08, 0x08);
	if (pcr->flags & PCR_REVERSE_SOCKET)
	/* Correct driving */
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
			SD30_CLK_DRIVE_SEL, 0xFF, 0x96);
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
			SD30_CMD_DRIVE_SEL, 0xFF, 0x96);
				AUTOLOAD_CFG_BASE + 3, 0xB8, 0xB8);
	else
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
			SD30_DAT_DRIVE_SEL, 0xFF, 0x96);
				AUTOLOAD_CFG_BASE + 3, 0xB8, 0x88);


	return rtsx_pci_send_cmd(pcr, 100);
	return rtsx_pci_send_cmd(pcr, 100);
}
}
@@ -131,13 +183,11 @@ static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card)
static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
{
{
	int err;
	int err;
	u8 drive_sel;


	if (voltage == OUTPUT_3V3) {
	if (voltage == OUTPUT_3V3) {
		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		drive_sel = 0x96;
	} else if (voltage == OUTPUT_1V8) {
	} else if (voltage == OUTPUT_1V8) {
		err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02);
		err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02);
		if (err < 0)
		if (err < 0)
@@ -145,23 +195,18 @@ static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24);
		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		drive_sel = 0xB3;
	} else {
	} else {
		return -EINVAL;
		return -EINVAL;
	}
	}


	/* set pad drive */
	/* set pad drive */
	rtsx_pci_init_cmd(pcr);
	rtsx_pci_init_cmd(pcr);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
	rts5227_fill_driving(pcr, voltage);
			0xFF, drive_sel);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
			0xFF, drive_sel);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
			0xFF, drive_sel);
	return rtsx_pci_send_cmd(pcr, 100);
	return rtsx_pci_send_cmd(pcr, 100);
}
}


static const struct pcr_ops rts5227_pcr_ops = {
static const struct pcr_ops rts5227_pcr_ops = {
	.fetch_vendor_settings = rts5227_fetch_vendor_settings,
	.extra_init_hw = rts5227_extra_init_hw,
	.extra_init_hw = rts5227_extra_init_hw,
	.optimize_phy = rts5227_optimize_phy,
	.optimize_phy = rts5227_optimize_phy,
	.turn_on_led = rts5227_turn_on_led,
	.turn_on_led = rts5227_turn_on_led,
@@ -227,6 +272,12 @@ void rts5227_init_params(struct rtsx_pcr *pcr)
	pcr->num_slots = 2;
	pcr->num_slots = 2;
	pcr->ops = &rts5227_pcr_ops;
	pcr->ops = &rts5227_pcr_ops;


	pcr->flags = 0;
	pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
	pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
	pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
	pcr->aspm_en = ASPM_L1_EN;

	pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl;
	pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl;
	pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl;
	pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl;
	pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl;
	pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl;
+35 −3
Original line number Original line Diff line number Diff line
@@ -34,6 +34,28 @@ static u8 rts5229_get_ic_version(struct rtsx_pcr *pcr)
	return val & 0x0F;
	return val & 0x0F;
}
}


static void rts5229_fetch_vendor_settings(struct rtsx_pcr *pcr)
{
	u32 reg;

	rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
	dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);

	if (!rtsx_vendor_setting_valid(reg))
		return;

	pcr->aspm_en = rtsx_reg_to_aspm(reg);
	pcr->sd30_drive_sel_1v8 =
		map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg));
	pcr->card_drive_sel &= 0x3F;
	pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);

	rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
	dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
	pcr->sd30_drive_sel_3v3 =
		map_sd_drive(rtsx_reg_to_sd30_drive_sel_3v3(reg));
}

static int rts5229_extra_init_hw(struct rtsx_pcr *pcr)
static int rts5229_extra_init_hw(struct rtsx_pcr *pcr)
{
{
	rtsx_pci_init_cmd(pcr);
	rtsx_pci_init_cmd(pcr);
@@ -45,6 +67,9 @@ static int rts5229_extra_init_hw(struct rtsx_pcr *pcr)
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
	/* LED shine disabled, set initial shine cycle period */
	/* LED shine disabled, set initial shine cycle period */
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
	/* Configure driving */
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
			0xFF, pcr->sd30_drive_sel_3v3);


	return rtsx_pci_send_cmd(pcr, 100);
	return rtsx_pci_send_cmd(pcr, 100);
}
}
@@ -110,7 +135,7 @@ static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
			SD_POWER_MASK | PMOS_STRG_MASK,
			SD_POWER_MASK | PMOS_STRG_MASK,
			SD_POWER_OFF | PMOS_STRG_400mA);
			SD_POWER_OFF | PMOS_STRG_400mA);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
			LDO3318_PWR_MASK, 0X00);
			LDO3318_PWR_MASK, 0x00);
	return rtsx_pci_send_cmd(pcr, 100);
	return rtsx_pci_send_cmd(pcr, 100);
}
}


@@ -120,7 +145,7 @@ static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)


	if (voltage == OUTPUT_3V3) {
	if (voltage == OUTPUT_3V3) {
		err = rtsx_pci_write_register(pcr,
		err = rtsx_pci_write_register(pcr,
				SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D);
				SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
@@ -128,7 +153,7 @@ static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
			return err;
			return err;
	} else if (voltage == OUTPUT_1V8) {
	} else if (voltage == OUTPUT_1V8) {
		err = rtsx_pci_write_register(pcr,
		err = rtsx_pci_write_register(pcr,
				SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B);
				SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
@@ -142,6 +167,7 @@ static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
}
}


static const struct pcr_ops rts5229_pcr_ops = {
static const struct pcr_ops rts5229_pcr_ops = {
	.fetch_vendor_settings = rts5229_fetch_vendor_settings,
	.extra_init_hw = rts5229_extra_init_hw,
	.extra_init_hw = rts5229_extra_init_hw,
	.optimize_phy = rts5229_optimize_phy,
	.optimize_phy = rts5229_optimize_phy,
	.turn_on_led = rts5229_turn_on_led,
	.turn_on_led = rts5229_turn_on_led,
@@ -221,6 +247,12 @@ void rts5229_init_params(struct rtsx_pcr *pcr)
	pcr->num_slots = 2;
	pcr->num_slots = 2;
	pcr->ops = &rts5229_pcr_ops;
	pcr->ops = &rts5229_pcr_ops;


	pcr->flags = 0;
	pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
	pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
	pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
	pcr->aspm_en = ASPM_L1_EN;

	pcr->ic_version = rts5229_get_ic_version(pcr);
	pcr->ic_version = rts5229_get_ic_version(pcr);
	if (pcr->ic_version == IC_VER_C) {
	if (pcr->ic_version == IC_VER_C) {
		pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl2;
		pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl2;
+70 −20
Original line number Original line Diff line number Diff line
@@ -34,6 +34,60 @@ static u8 rts5249_get_ic_version(struct rtsx_pcr *pcr)
	return val & 0x0F;
	return val & 0x0F;
}
}


static void rts5249_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
{
	u8 driving_3v3[4][3] = {
		{0x11, 0x11, 0x11},
		{0x55, 0x55, 0x5C},
		{0x99, 0x99, 0x92},
		{0x99, 0x99, 0x92},
	};
	u8 driving_1v8[4][3] = {
		{0x3C, 0x3C, 0x3C},
		{0xB3, 0xB3, 0xB3},
		{0xFE, 0xFE, 0xFE},
		{0xC4, 0xC4, 0xC4},
	};
	u8 (*driving)[3], drive_sel;

	if (voltage == OUTPUT_3V3) {
		driving = driving_3v3;
		drive_sel = pcr->sd30_drive_sel_3v3;
	} else {
		driving = driving_1v8;
		drive_sel = pcr->sd30_drive_sel_1v8;
	}

	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
			0xFF, driving[drive_sel][0]);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
			0xFF, driving[drive_sel][1]);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
			0xFF, driving[drive_sel][2]);
}

static void rts5249_fetch_vendor_settings(struct rtsx_pcr *pcr)
{
	u32 reg;

	rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
	dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);

	if (!rtsx_vendor_setting_valid(reg))
		return;

	pcr->aspm_en = rtsx_reg_to_aspm(reg);
	pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg);
	pcr->card_drive_sel &= 0x3F;
	pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);

	rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
	dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
	pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
	if (rtsx_reg_check_reverse_socket(reg))
		pcr->flags |= PCR_REVERSE_SOCKET;
}

static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
{
{
	rtsx_pci_init_cmd(pcr);
	rtsx_pci_init_cmd(pcr);
@@ -45,13 +99,14 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
	/* LED shine disabled, set initial shine cycle period */
	/* LED shine disabled, set initial shine cycle period */
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
	/* Correct driving */
	/* Configure driving */
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
	rts5249_fill_driving(pcr, OUTPUT_3V3);
			SD30_CLK_DRIVE_SEL, 0xFF, 0x99);
	if (pcr->flags & PCR_REVERSE_SOCKET)
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
			SD30_CMD_DRIVE_SEL, 0xFF, 0x99);
				AUTOLOAD_CFG_BASE + 3, 0xB0, 0xB0);
	else
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
		rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
			SD30_DAT_DRIVE_SEL, 0xFF, 0x92);
				AUTOLOAD_CFG_BASE + 3, 0xB0, 0x80);


	return rtsx_pci_send_cmd(pcr, 100);
	return rtsx_pci_send_cmd(pcr, 100);
}
}
@@ -129,15 +184,11 @@ static int rts5249_card_power_off(struct rtsx_pcr *pcr, int card)
static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
{
{
	int err;
	int err;
	u8 clk_drive, cmd_drive, dat_drive;


	if (voltage == OUTPUT_3V3) {
	if (voltage == OUTPUT_3V3) {
		err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24);
		err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		clk_drive = 0x99;
		cmd_drive = 0x99;
		dat_drive = 0x92;
	} else if (voltage == OUTPUT_1V8) {
	} else if (voltage == OUTPUT_1V8) {
		err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02);
		err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02);
		if (err < 0)
		if (err < 0)
@@ -145,25 +196,18 @@ static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
		err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24);
		err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
		clk_drive = 0xb3;
		cmd_drive = 0xb3;
		dat_drive = 0xb3;
	} else {
	} else {
		return -EINVAL;
		return -EINVAL;
	}
	}


	/* set pad drive */
	/* set pad drive */
	rtsx_pci_init_cmd(pcr);
	rtsx_pci_init_cmd(pcr);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
	rts5249_fill_driving(pcr, voltage);
			0xFF, clk_drive);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
			0xFF, cmd_drive);
	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
			0xFF, dat_drive);
	return rtsx_pci_send_cmd(pcr, 100);
	return rtsx_pci_send_cmd(pcr, 100);
}
}


static const struct pcr_ops rts5249_pcr_ops = {
static const struct pcr_ops rts5249_pcr_ops = {
	.fetch_vendor_settings = rts5249_fetch_vendor_settings,
	.extra_init_hw = rts5249_extra_init_hw,
	.extra_init_hw = rts5249_extra_init_hw,
	.optimize_phy = rts5249_optimize_phy,
	.optimize_phy = rts5249_optimize_phy,
	.turn_on_led = rts5249_turn_on_led,
	.turn_on_led = rts5249_turn_on_led,
@@ -233,6 +277,12 @@ void rts5249_init_params(struct rtsx_pcr *pcr)
	pcr->num_slots = 2;
	pcr->num_slots = 2;
	pcr->ops = &rts5249_pcr_ops;
	pcr->ops = &rts5249_pcr_ops;


	pcr->flags = 0;
	pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
	pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_C;
	pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
	pcr->aspm_en = ASPM_L1_EN;

	pcr->ic_version = rts5249_get_ic_version(pcr);
	pcr->ic_version = rts5249_get_ic_version(pcr);
	pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl;
	pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl;
	pcr->sd_pull_ctl_disable_tbl = rts5249_sd_pull_ctl_disable_tbl;
	pcr->sd_pull_ctl_disable_tbl = rts5249_sd_pull_ctl_disable_tbl;
Loading