Skip to content

Commit

Permalink
mfd: rtsx: Read vendor setting from config space
Browse files Browse the repository at this point in the history
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: Wei WANG <wei_wang@realsil.com.cn>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
  • Loading branch information
Wei WANG authored and Samuel Ortiz committed Aug 20, 2013
1 parent 74d85e4 commit 773ccdf
Show file tree
Hide file tree
Showing 8 changed files with 365 additions and 68 deletions.
77 changes: 71 additions & 6 deletions drivers/mfd/rtl8411.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,70 @@ static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr)
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)
{
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);

return rtsx_pci_send_cmd(pcr, 100);
}

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

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);

return rtsx_pci_send_cmd(pcr, 100);
}

static int rtl8411_turn_on_led(struct rtsx_pcr *pcr)
Expand Down Expand Up @@ -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;
if (voltage == OUTPUT_3V3) {
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)
return err;
val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3;
} else if (voltage == OUTPUT_1V8) {
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)
return err;
val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8;
Expand Down Expand Up @@ -222,6 +273,7 @@ static int rtl8411_conv_clk_and_div_n(int input, int dir)
}

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

static const struct pcr_ops rtl8411b_pcr_ops = {
.fetch_vendor_settings = rtl8411b_fetch_vendor_settings,
.extra_init_hw = rtl8411b_extra_init_hw,
.optimize_phy = NULL,
.turn_on_led = rtl8411_turn_on_led,
Expand Down Expand Up @@ -385,6 +438,12 @@ void rtl8411_init_params(struct rtsx_pcr *pcr)
pcr->num_slots = 2;
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->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl;
pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl;
Expand All @@ -398,6 +457,12 @@ void rtl8411b_init_params(struct rtsx_pcr *pcr)
pcr->num_slots = 2;
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);

if (rtl8411b_is_qfn48(pcr)) {
Expand Down
48 changes: 33 additions & 15 deletions drivers/mfd/rts5209.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,28 @@ static u8 rts5209_get_ic_version(struct rtsx_pcr *pcr)
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);
dev_dbg(&(pcr->pci->dev), "Cfg 0x724: 0x%x\n", val);
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 (!(val & 0x80)) {
if (val & 0x08)
pcr->ms_pmos = false;
else
pcr->ms_pmos = true;
if (rts5209_vendor_setting1_valid(reg)) {
if (rts5209_reg_check_ms_pmos(reg))
pcr->flags |= PCR_MS_PMOS;
pcr->aspm_en = rts5209_reg_to_aspm(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);

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);
}
}

Expand All @@ -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);
/* Configure GPIO as output */
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);
}
Expand Down Expand Up @@ -95,7 +108,7 @@ static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card)
partial_pwr_on = SD_PARTIAL_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;
partial_pwr_on = MS_PARTIAL_POWER_ON;
pwr_on = MS_POWER_ON;
Expand Down Expand Up @@ -131,7 +144,7 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
pwr_mask = SD_POWER_MASK;
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_off = MS_POWER_OFF;
}
Expand All @@ -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,
pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA);
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);
}

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

if (voltage == OUTPUT_3V3) {
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)
return err;
err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
if (err < 0)
return err;
} else if (voltage == OUTPUT_1V8) {
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)
return err;
err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
Expand All @@ -172,6 +185,7 @@ static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
}

static const struct pcr_ops rts5209_pcr_ops = {
.fetch_vendor_settings = rts5209_fetch_vendor_settings,
.extra_init_hw = rts5209_extra_init_hw,
.optimize_phy = rts5209_optimize_phy,
.turn_on_led = rts5209_turn_on_led,
Expand Down Expand Up @@ -242,7 +256,11 @@ void rts5209_init_params(struct rtsx_pcr *pcr)
pcr->num_slots = 2;
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->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl;
Expand Down
91 changes: 71 additions & 20 deletions drivers/mfd/rts5227.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,60 @@

#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)
{
u16 cap;
Expand All @@ -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);
/* Configure OBFF */
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03);
/* Configure force_clock_req
* Maybe We should define 0xFF03 as some name
*/
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 0xFF03, 0x08, 0x08);
/* Correct driving */
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
SD30_CLK_DRIVE_SEL, 0xFF, 0x96);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
SD30_CMD_DRIVE_SEL, 0xFF, 0x96);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
SD30_DAT_DRIVE_SEL, 0xFF, 0x96);
/* Configure driving */
rts5227_fill_driving(pcr, OUTPUT_3V3);
/* Configure force_clock_req */
if (pcr->flags & PCR_REVERSE_SOCKET)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
AUTOLOAD_CFG_BASE + 3, 0xB8, 0xB8);
else
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
AUTOLOAD_CFG_BASE + 3, 0xB8, 0x88);

return rtsx_pci_send_cmd(pcr, 100);
}
Expand Down Expand Up @@ -131,37 +183,30 @@ static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card)
static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
{
int err;
u8 drive_sel;

if (voltage == OUTPUT_3V3) {
err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
if (err < 0)
return err;
drive_sel = 0x96;
} else if (voltage == OUTPUT_1V8) {
err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02);
if (err < 0)
return err;
err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24);
if (err < 0)
return err;
drive_sel = 0xB3;
} else {
return -EINVAL;
}

/* set pad drive */
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
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);
rts5227_fill_driving(pcr, voltage);
return rtsx_pci_send_cmd(pcr, 100);
}

static const struct pcr_ops rts5227_pcr_ops = {
.fetch_vendor_settings = rts5227_fetch_vendor_settings,
.extra_init_hw = rts5227_extra_init_hw,
.optimize_phy = rts5227_optimize_phy,
.turn_on_led = rts5227_turn_on_led,
Expand Down Expand Up @@ -227,6 +272,12 @@ void rts5227_init_params(struct rtsx_pcr *pcr)
pcr->num_slots = 2;
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_disable_tbl = rts5227_sd_pull_ctl_disable_tbl;
pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl;
Expand Down
Loading

0 comments on commit 773ccdf

Please sign in to comment.