diff options
author | Wei WANG <wei_wang@realsil.com.cn> | 2013-08-20 14:18:51 +0800 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2013-08-20 10:22:00 +0200 |
commit | 773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903 (patch) | |
tree | 3e9ac1a210e718aaeb459dc8950666e928ca68b1 /drivers/mfd/rtl8411.c | |
parent | 74d85e47ab8a7cdeffde6373cf1550bfbd2feaa6 (diff) | |
download | lwn-773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903.tar.gz lwn-773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903.zip |
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: Wei WANG <wei_wang@realsil.com.cn>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/rtl8411.c')
-rw-r--r-- | drivers/mfd/rtl8411.c | 77 |
1 files changed, 71 insertions, 6 deletions
diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index c436bf27e78d..5a68c9bdeddf 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c @@ -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, ®1); + 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, ®3); + 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, ®); + 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) @@ -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; @@ -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, @@ -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, @@ -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; @@ -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)) { |