Ack to all: [Quantal][PATCH] mfd: rtsx: Read vendor setting from config space
Brad Figg
brad.figg at canonical.com
Mon Sep 9 15:43:13 UTC 2013
On 09/09/2013 01:44 AM, Adam Lee wrote:
> From: Wei WANG <wei_wang at realsil.com.cn>
>
> BugLink: http://bugs.launchpad.net/bugs/1201698
>
> 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 at realsil.com.cn>
> Signed-off-by: Samuel Ortiz <sameo at linux.intel.com>
> (backported from commit 773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903)
>
> Conflicts:
>
> drivers/mfd/rts5249.c
> include/linux/mfd/rtsx_pci.h
> Signed-off-by: Adam Lee <adam.lee at canonical.com>
> ---
> drivers/mfd/rtl8411.c | 77 ++++++++++++++++++++++++++++++++---
> drivers/mfd/rts5209.c | 48 +++++++++++++++-------
> drivers/mfd/rts5227.c | 91 ++++++++++++++++++++++++++++++++----------
> drivers/mfd/rts5229.c | 38 ++++++++++++++++--
> drivers/mfd/rtsx_pcr.c | 26 ++++++++++--
> drivers/mfd/rtsx_pcr.h | 29 ++++++++++++++
> include/linux/mfd/rtsx_pci.h | 68 ++++++++++++++++++++++++++++++-
> 7 files changed, 329 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c
> index c436bf2..5a68c9b 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)) {
> diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c
> index ec78d9f..2170449 100644
> --- a/drivers/mfd/rts5209.c
> +++ b/drivers/mfd/rts5209.c
> @@ -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, ®);
> + 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, ®);
> + 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);
> /* 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);
> }
> @@ -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;
> @@ -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;
> }
> @@ -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);
> }
>
> @@ -150,7 +163,7 @@ 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);
> @@ -158,7 +171,7 @@ static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
> 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);
> @@ -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,
> @@ -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;
> diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c
> index 1863aee..28f66f0a 100644
> --- a/drivers/mfd/rts5227.c
> +++ b/drivers/mfd/rts5227.c
> @@ -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, ®);
> + 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, ®);
> + 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;
> @@ -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);
> }
> @@ -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)
> {
> 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)
> @@ -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);
> 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,
> @@ -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;
> diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c
> index 58af4db..7a1ad6d 100644
> --- a/drivers/mfd/rts5229.c
> +++ b/drivers/mfd/rts5229.c
> @@ -34,6 +34,28 @@ static u8 rts5229_get_ic_version(struct rtsx_pcr *pcr)
> return val & 0x0F;
> }
>
> +static void rts5229_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->card_drive_sel &= 0x3F;
> + pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
> +
> + rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®);
> + 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)
> {
> 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);
> /* LED shine disabled, set initial shine cycle period */
> 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);
> }
> @@ -110,7 +135,7 @@ static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
> SD_POWER_MASK | PMOS_STRG_MASK,
> SD_POWER_OFF | PMOS_STRG_400mA);
> 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);
> }
>
> @@ -120,7 +145,7 @@ static int rts5229_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);
> @@ -128,7 +153,7 @@ static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
> 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);
> @@ -142,6 +167,7 @@ static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
> }
>
> static const struct pcr_ops rts5229_pcr_ops = {
> + .fetch_vendor_settings = rts5229_fetch_vendor_settings,
> .extra_init_hw = rts5229_extra_init_hw,
> .optimize_phy = rts5229_optimize_phy,
> .turn_on_led = rts5229_turn_on_led,
> @@ -221,6 +247,12 @@ void rts5229_init_params(struct rtsx_pcr *pcr)
> pcr->num_slots = 2;
> 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);
> if (pcr->ic_version == IC_VER_C) {
> pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl2;
> diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
> index 8c38aff..0fa07b6 100644
> --- a/drivers/mfd/rtsx_pcr.c
> +++ b/drivers/mfd/rtsx_pcr.c
> @@ -71,6 +71,9 @@ void rtsx_pci_start_run(struct rtsx_pcr *pcr)
> pcr->state = PDEV_STAT_RUN;
> if (pcr->ops->enable_auto_blink)
> pcr->ops->enable_auto_blink(pcr);
> +
> + if (pcr->aspm_en)
> + rtsx_pci_write_config_byte(pcr, LCTLR, 0);
> }
>
> cancel_delayed_work(&pcr->idle_work);
> @@ -722,7 +725,7 @@ int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card)
> [RTSX_MS_CARD] = MS_EXIST
> };
>
> - if (!pcr->ms_pmos) {
> + if (!(pcr->flags & PCR_MS_PMOS)) {
> /* When using single PMOS, accessing card is not permitted
> * if the existing card is not the designated one.
> */
> @@ -923,6 +926,9 @@ static void rtsx_pci_idle_work(struct work_struct *work)
> if (pcr->ops->turn_off_led)
> pcr->ops->turn_off_led(pcr);
>
> + if (pcr->aspm_en)
> + rtsx_pci_write_config_byte(pcr, LCTLR, pcr->aspm_en);
> +
> mutex_unlock(&pcr->pcr_mutex);
> }
>
> @@ -961,8 +967,8 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
> /* Reset delink mode */
> rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x0A, 0);
> /* Card driving select */
> - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
> - 0x07, DRIVER_TYPE_D);
> + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DRIVE_SEL,
> + 0xFF, pcr->card_drive_sel);
> /* Enable SSC Clock */
> rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1,
> 0xFF, SSC_8X_EN | SSC_SEL_4M);
> @@ -994,6 +1000,8 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
> if (err < 0)
> return err;
>
> + rtsx_pci_write_config_byte(pcr, LCTLR, 0);
> +
> /* Enable clk_request_n to enable clock power management */
> rtsx_pci_write_config_byte(pcr, 0x81, 1);
> /* Enter L1 when host tx idle */
> @@ -1054,6 +1062,18 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
> if (!pcr->slots)
> return -ENOMEM;
>
> + if (pcr->ops->fetch_vendor_settings)
> + pcr->ops->fetch_vendor_settings(pcr);
> +
> + dev_dbg(&(pcr->pci->dev), "pcr->aspm_en = 0x%x\n", pcr->aspm_en);
> + dev_dbg(&(pcr->pci->dev), "pcr->sd30_drive_sel_1v8 = 0x%x\n",
> + pcr->sd30_drive_sel_1v8);
> + dev_dbg(&(pcr->pci->dev), "pcr->sd30_drive_sel_3v3 = 0x%x\n",
> + pcr->sd30_drive_sel_3v3);
> + dev_dbg(&(pcr->pci->dev), "pcr->card_drive_sel = 0x%x\n",
> + pcr->card_drive_sel);
> + dev_dbg(&(pcr->pci->dev), "pcr->flags = 0x%x\n", pcr->flags);
> +
> pcr->state = PDEV_STAT_IDLE;
> err = rtsx_pci_init_hw(pcr);
> if (err < 0) {
> diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h
> index 445303d..19f2311 100644
> --- a/drivers/mfd/rtsx_pcr.h
> +++ b/drivers/mfd/rtsx_pcr.h
> @@ -34,4 +34,33 @@ void rtl8411_init_params(struct rtsx_pcr *pcr);
> void rts5227_init_params(struct rtsx_pcr *pcr);
> void rtl8411b_init_params(struct rtsx_pcr *pcr);
>
> +static inline u8 map_sd_drive(int idx)
> +{
> + u8 sd_drive[4] = {
> + 0x01, /* Type D */
> + 0x02, /* Type C */
> + 0x05, /* Type A */
> + 0x03 /* Type B */
> + };
> +
> + return sd_drive[idx];
> +}
> +
> +#define rtsx_vendor_setting_valid(reg) (!((reg) & 0x1000000))
> +#define rts5209_vendor_setting1_valid(reg) (!((reg) & 0x80))
> +#define rts5209_vendor_setting2_valid(reg) ((reg) & 0x80)
> +
> +#define rtsx_reg_to_aspm(reg) (((reg) >> 28) & 0x03)
> +#define rtsx_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 26) & 0x03)
> +#define rtsx_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 5) & 0x03)
> +#define rtsx_reg_to_card_drive_sel(reg) ((((reg) >> 25) & 0x01) << 6)
> +#define rtsx_reg_check_reverse_socket(reg) ((reg) & 0x4000)
> +#define rts5209_reg_to_aspm(reg) (((reg) >> 5) & 0x03)
> +#define rts5209_reg_check_ms_pmos(reg) (!((reg) & 0x08))
> +#define rts5209_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 3) & 0x07)
> +#define rts5209_reg_to_sd30_drive_sel_3v3(reg) ((reg) & 0x07)
> +#define rts5209_reg_to_card_drive_sel(reg) ((reg) >> 8)
> +#define rtl8411_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 5) & 0x07)
> +#define rtl8411b_reg_to_sd30_drive_sel_3v3(reg) ((reg) & 0x03)
> +
> #endif
> diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h
> index 8effb7a..ef44738 100644
> --- a/include/linux/mfd/rtsx_pci.h
> +++ b/include/linux/mfd/rtsx_pci.h
> @@ -184,11 +184,26 @@
> #define CARD_SHARE_BAROSSA_SD 0x01
> #define CARD_SHARE_BAROSSA_MS 0x02
>
> +/* CARD_DRIVE_SEL */
> +#define MS_DRIVE_8mA (0x01 << 6)
> +#define MMC_DRIVE_8mA (0x01 << 4)
> +#define XD_DRIVE_8mA (0x01 << 2)
> +#define GPIO_DRIVE_8mA 0x01
> +#define RTS5209_CARD_DRIVE_DEFAULT (MS_DRIVE_8mA | MMC_DRIVE_8mA |\
> + XD_DRIVE_8mA | GPIO_DRIVE_8mA)
> +#define RTL8411_CARD_DRIVE_DEFAULT (MS_DRIVE_8mA | MMC_DRIVE_8mA |\
> + XD_DRIVE_8mA)
> +#define RTSX_CARD_DRIVE_DEFAULT (MS_DRIVE_8mA | GPIO_DRIVE_8mA)
> +
> /* SD30_DRIVE_SEL */
> #define DRIVER_TYPE_A 0x05
> #define DRIVER_TYPE_B 0x03
> #define DRIVER_TYPE_C 0x02
> #define DRIVER_TYPE_D 0x01
> +#define CFG_DRIVER_TYPE_A 0x02
> +#define CFG_DRIVER_TYPE_B 0x03
> +#define CFG_DRIVER_TYPE_C 0x01
> +#define CFG_DRIVER_TYPE_D 0x00
>
> /* FPDCTL */
> #define SSC_POWER_DOWN 0x01
> @@ -682,6 +697,8 @@
>
> #define DUMMY_REG_RESET_0 0xFE90
>
> +#define AUTOLOAD_CFG_BASE 0xFF00
> +
> /* Memory mapping */
> #define SRAM_BASE 0xE600
> #define RBUF_BASE 0xF400
> @@ -690,6 +707,45 @@
> #define IMAGE_FLAG_ADDR0 0xCE80
> #define IMAGE_FLAG_ADDR1 0xCE81
>
> +/* Phy register */
> +#define PHY_PCR 0x00
> +#define PHY_RCR0 0x01
> +#define PHY_RCR1 0x02
> +#define PHY_RCR2 0x03
> +#define PHY_RTCR 0x04
> +#define PHY_RDR 0x05
> +#define PHY_TCR0 0x06
> +#define PHY_TCR1 0x07
> +#define PHY_TUNE 0x08
> +#define PHY_IMR 0x09
> +#define PHY_BPCR 0x0A
> +#define PHY_BIST 0x0B
> +#define PHY_RAW_L 0x0C
> +#define PHY_RAW_H 0x0D
> +#define PHY_RAW_DATA 0x0E
> +#define PHY_HOST_CLK_CTRL 0x0F
> +#define PHY_DMR 0x10
> +#define PHY_BACR 0x11
> +#define PHY_IER 0x12
> +#define PHY_BCSR 0x13
> +#define PHY_BPR 0x14
> +#define PHY_BPNR2 0x15
> +#define PHY_BPNR 0x16
> +#define PHY_BRNR2 0x17
> +#define PHY_BENR 0x18
> +#define PHY_REG_REV 0x19
> +#define PHY_FLD0 0x1A
> +#define PHY_FLD1 0x1B
> +#define PHY_FLD2 0x1C
> +#define PHY_FLD3 0x1D
> +#define PHY_FLD4 0x1E
> +#define PHY_DUM_REG 0x1F
> +
> +#define LCTLR 0x80
> +#define PCR_SETTING_REG1 0x724
> +#define PCR_SETTING_REG2 0x814
> +#define PCR_SETTING_REG3 0x747
> +
> #define rtsx_pci_init_cmd(pcr) ((pcr)->ci = 0)
>
> struct rtsx_pcr;
> @@ -711,6 +767,7 @@ struct pcr_ops {
> u8 voltage);
> unsigned int (*cd_deglitch)(struct rtsx_pcr *pcr);
> int (*conv_clk_and_div_n)(int clk, int dir);
> + void (*fetch_vendor_settings)(struct rtsx_pcr *pcr);
> };
>
> enum PDEV_STAT {PDEV_STAT_IDLE, PDEV_STAT_RUN};
> @@ -752,7 +809,6 @@ struct rtsx_pcr {
> struct completion *finish_me;
>
> unsigned int cur_clock;
> - bool ms_pmos;
> bool remove_pci;
> bool msi_en;
>
> @@ -770,6 +826,16 @@ struct rtsx_pcr {
> #define IC_VER_D 3
> u8 ic_version;
>
> + u8 sd30_drive_sel_1v8;
> + u8 sd30_drive_sel_3v3;
> + u8 card_drive_sel;
> +#define ASPM_L1_EN 0x02
> + u8 aspm_en;
> +
> +#define PCR_MS_PMOS (1 << 0)
> +#define PCR_REVERSE_SOCKET (1 << 1)
> + u32 flags;
> +
> const u32 *sd_pull_ctl_enable_tbl;
> const u32 *sd_pull_ctl_disable_tbl;
> const u32 *ms_pull_ctl_enable_tbl;
>
--
Brad Figg brad.figg at canonical.com http://www.canonical.com
More information about the kernel-team
mailing list