Fix two bugs in rtl8411
Subsystems (2)
cover Fix two bugs in rtl8411
From: Wei WANG <[email protected]>
1. The method to switch output voltage is different in rtl8411
2. Fix the formula to calculate N from SD clock if clock divider is more than 1
Wei WANG (3):
MFD:rtsx: Add callback function switch_output_voltage MMC:rtsx: Using callback function to switch output voltage MFD:rtsx: Add callback function conv_clk_and_div_n
drivers/mfd/rtl8411.c | 29 +++++++++++++++++++++++++++++ drivers/mfd/rts5209.c | 21 +++++++++++++++++++++ drivers/mfd/rts5229.c | 21 +++++++++++++++++++++ drivers/mfd/rtsx_pcr.c | 23 +++++++++++++++++++++-- drivers/mmc/host/rtsx_pci_sdmmc.c | 30 +++++------------------------- include/linux/mfd/rtsx_common.h | 3 +++ include/linux/mfd/rtsx_pci.h | 25 +++++++++++++++++++++---- 7 files changed, 121 insertions(+), 31 deletions(-)
Signature · 1 line
1.7.9.5
PATCH 1/3 MFD:rtsx: Add callback function switch_output_voltage
From: Wei WANG <[email protected]>
Different card reader has different method to switch output voltage, add this callback to let the card reader implement its individual switch function.
--- drivers/mfd/rtl8411.c | 16 ++++++++++++++++ drivers/mfd/rts5209.c | 20 ++++++++++++++++++++ drivers/mfd/rts5229.c | 20 ++++++++++++++++++++ drivers/mfd/rtsx_pcr.c | 9 +++++++++ include/linux/mfd/rtsx_pci.h | 24 ++++++++++++++++++++---- 5 files changed, 85 insertions(+), 4 deletions(-)
drivers/mfd/rtl8411.c +16 -0
@@ -112,6 +112,21 @@ static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card) BPP_LDO_POWB, BPP_LDO_SUSPEND); } +static int rtl8411_switch_output_voltage (struct rtsx_pcr *pcr,u8 voltage) +{ +u8 mask, val; + + mask = (BPP_REG_TUNED18 <<BPP_TUNED18_SHIFT_8411 ) |BPP_PAD_MASK ; +if (voltage ==OUTPUT_3V3 ) + val = (BPP_ASIC_3V3 <<BPP_TUNED18_SHIFT_8411 ) |BPP_PAD_3V3 ; +else if (voltage ==OUTPUT_1V8 ) + val = (BPP_ASIC_1V8 <<BPP_TUNED18_SHIFT_8411 ) |BPP_PAD_1V8 ; +else +return -EINVAL ; + +return rtsx_pci_write_register (pcr,LDO_CTL , mask, val); +} +static unsigned int rtl8411_cd_deglitch (struct rtsx_pcr *pcr) {unsigned int card_exist;
@@ -172,6 +187,7 @@ static const struct pcr_ops rtl8411_pcr_ops = { .disable_auto_blink = rtl8411_disable_auto_blink, .card_power_on = rtl8411_card_power_on, .card_power_off = rtl8411_card_power_off, + .switch_output_voltage = rtl8411_switch_output_voltage, .cd_deglitch = rtl8411_cd_deglitch, };
drivers/mfd/rts5209.c +20 -0
@@ -144,6 +144,25 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)return rtsx_pci_send_cmd (pcr,100 ); } +static int rts5209_switch_output_voltage (struct rtsx_pcr *pcr,u8 voltage) +{ +int err; + +if (voltage ==OUTPUT_3V3 ) { + err =rtsx_pci_write_phy_register (pcr,0x08 ,0x4FC0 |0x24 ); +if (err <0 ) +return err; + }else if (voltage ==OUTPUT_1V8 ) { + err =rtsx_pci_write_phy_register (pcr,0x08 ,0x4C40 |0x24 ); +if (err <0 ) +return err; + }else { +return -EINVAL ; + } + +return 0 ; +} +static const struct pcr_ops rts5209_pcr_ops = { .extra_init_hw = rts5209_extra_init_hw, .optimize_phy = rts5209_optimize_phy,
@@ -153,6 +172,7 @@ static const struct pcr_ops rts5209_pcr_ops = { .disable_auto_blink = rts5209_disable_auto_blink, .card_power_on = rts5209_card_power_on, .card_power_off = rts5209_card_power_off, + .switch_output_voltage = rts5209_switch_output_voltage, .cd_deglitch = NULL, };
drivers/mfd/rts5229.c +20 -0
@@ -114,6 +114,25 @@ static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)return rtsx_pci_send_cmd (pcr,100 ); } +static int rts5229_switch_output_voltage (struct rtsx_pcr *pcr,u8 voltage) +{ +int err; + +if (voltage ==OUTPUT_3V3 ) { + err =rtsx_pci_write_phy_register (pcr,0x08 ,0x4FC0 |0x24 ); +if (err <0 ) +return err; + }else if (voltage ==OUTPUT_1V8 ) { + err =rtsx_pci_write_phy_register (pcr,0x08 ,0x4C40 |0x24 ); +if (err <0 ) +return err; + }else { +return -EINVAL ; + } + +return 0 ; +} +static const struct pcr_ops rts5229_pcr_ops = { .extra_init_hw = rts5229_extra_init_hw, .optimize_phy = rts5229_optimize_phy,
@@ -123,6 +142,7 @@ static const struct pcr_ops rts5229_pcr_ops = { .disable_auto_blink = rts5229_disable_auto_blink, .card_power_on = rts5229_card_power_on, .card_power_off = rts5229_card_power_off, + .switch_output_voltage = rts5229_switch_output_voltage, .cd_deglitch = NULL, };
drivers/mfd/rtsx_pcr.c +9 -0
@@ -703,6 +703,15 @@ int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card) }EXPORT_SYMBOL_GPL (rtsx_pci_card_power_off); +int rtsx_pci_switch_output_voltage (struct rtsx_pcr *pcr,u8 voltage) +{ +if (pcr->ops->switch_output_voltage) +return pcr->ops->switch_output_voltage (pcr, voltage); + +return 0 ; +} +EXPORT_SYMBOL_GPL (rtsx_pci_switch_output_voltage); +unsigned int rtsx_pci_card_exist (struct rtsx_pcr *pcr) {unsigned int val;
include/linux/mfd/rtsx_pci.h +20 -4
@@ -158,10 +158,9 @@#define SG_TRANS_DATA (0x02 << 4)#define SG_LINK_DESC (0x03 << 4) -/* SD bank voltage */ -#define SD_IO_3V3 0 -#define SD_IO_1V8 1 - +/* Output voltage */ +#define OUTPUT_3V3 0 +#define OUTPUT_1V8 1/* Card Clock Enable Register */ #define SD_CLK_EN 0x04
@@ -201,6 +200,20 @@#define CHANGE_CLK 0x01/* LDO_CTL */ +#define BPP_ASIC_1V7 0x00 +#define BPP_ASIC_1V8 0x01 +#define BPP_ASIC_1V9 0x02 +#define BPP_ASIC_2V0 0x03 +#define BPP_ASIC_2V7 0x04 +#define BPP_ASIC_2V8 0x05 +#define BPP_ASIC_3V2 0x06 +#define BPP_ASIC_3V3 0x07 +#define BPP_REG_TUNED18 0x07 +#define BPP_TUNED18_SHIFT_8402 5 +#define BPP_TUNED18_SHIFT_8411 4 +#define BPP_PAD_MASK 0x04 +#define BPP_PAD_3V3 0x04 +#define BPP_PAD_1V8 0x00#define BPP_LDO_POWB 0x03#define BPP_LDO_ON 0x00#define BPP_LDO_SUSPEND 0x02
@@ -688,6 +701,8 @@ struct pcr_ops {int (*disable_auto_blink)(struct rtsx_pcr *pcr);int (*card_power_on)(struct rtsx_pcr *pcr,int card);int (*card_power_off)(struct rtsx_pcr *pcr,int card); +int (*switch_output_voltage)(struct rtsx_pcr *pcr, +u8 voltage);unsigned int (*cd_deglitch)(struct rtsx_pcr *pcr); };
@@ -783,6 +798,7 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk);int rtsx_pci_card_power_on (struct rtsx_pcr *pcr,int card);int rtsx_pci_card_power_off (struct rtsx_pcr *pcr,int card); +int rtsx_pci_switch_output_voltage (struct rtsx_pcr *pcr,u8 voltage);unsigned int rtsx_pci_card_exist (struct rtsx_pcr *pcr);void rtsx_pci_complete_unfinished_transfer (struct rtsx_pcr *pcr);
Signature · 1 line
1.7.9.5
PATCH 2/3 MMC:rtsx: Using callback function to switch output voltage
In reply to [email protected]From: Wei WANG <[email protected]>
Different card reader has different method to switch output voltage, so we have to use the callback function provided by MFD driver to switch output pad voltage.
--- drivers/mmc/host/rtsx_pci_sdmmc.c | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-)
drivers/mmc/host/rtsx_pci_sdmmc.c +5 -25
@@ -1060,26 +1060,6 @@ static int sd_wait_voltage_stable_2(struct realtek_pci_sdmmc *host)return 0 ; } -static int sd_change_bank_voltage (struct realtek_pci_sdmmc *host,u8 voltage) -{ -struct rtsx_pcr *pcr = host->pcr; -int err; - -if (voltage ==SD_IO_3V3 ) { - err =rtsx_pci_write_phy_register (pcr,0x08 ,0x4FC0 |0x24 ); -if (err <0 ) -return err; - }else if (voltage ==SD_IO_1V8 ) { - err =rtsx_pci_write_phy_register (pcr,0x08 ,0x4C40 |0x24 ); -if (err <0 ) -return err; - }else { -return -EINVAL ; - } - -return 0 ; -} -static int sdmmc_switch_voltage (struct mmc_host *mmc,struct mmc_ios *ios) {struct realtek_pci_sdmmc *host =mmc_priv (mmc);
@@ -1098,11 +1078,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)rtsx_pci_start_run (pcr);if (ios->signal_voltage ==MMC_SIGNAL_VOLTAGE_330 ) - voltage =SD_IO_3V3 ; + voltage =OUTPUT_3V3 ;else - voltage =SD_IO_1V8 ; + voltage =OUTPUT_1V8 ; -if (voltage ==SD_IO_1V8 ) { +if (voltage ==OUTPUT_1V8 ) { err =rtsx_pci_write_register (pcr,SD30_DRIVE_SEL ,0x07 ,DRIVER_TYPE_B );if (err <0 )
@@ -1113,11 +1093,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) goto out; } - err =sd_change_bank_voltage (host, voltage); + err =rtsx_pci_switch_output_voltage (pcr, voltage);if (err <0 ) goto out; -if (voltage ==SD_IO_1V8 ) { +if (voltage ==OUTPUT_1V8 ) { err =sd_wait_voltage_stable_2 (host);if (err <0 ) goto out;
Signature · 1 line
1.7.9.5
PATCH 3/3 MFD:rtsx: Add callback function conv_clk_and_div_n
In reply to [email protected]From: Wei WANG <[email protected]>
Add callback function conv_clk_and_div_n to convert between SSC clock and its divider N.
For rtl8411, the formula to calculate SSC clock divider N is different with the other card reader models.
--- drivers/mfd/rtl8411.c | 13 +++++++++++++ drivers/mfd/rts5209.c | 1 + drivers/mfd/rts5229.c | 1 + drivers/mfd/rtsx_pcr.c | 14 ++++++++++++-- include/linux/mfd/rtsx_common.h | 3 +++ include/linux/mfd/rtsx_pci.h | 1 + 6 files changed, 31 insertions(+), 2 deletions(-)
drivers/mfd/rtl8411.c +13 -0
@@ -178,6 +178,18 @@ static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)return card_exist; } +static int rtl8411_conv_clk_and_div_n (int input,int dir) +{ +int output; + +if (dir ==CLK_TO_DIV_N ) + output = input *4 /5 -2 ; +else + output = (input +2 ) *5 /4 ; + +return output; +} +static const struct pcr_ops rtl8411_pcr_ops = { .extra_init_hw = rtl8411_extra_init_hw, .optimize_phy =NULL ,
@@ -189,6 +201,7 @@ static const struct pcr_ops rtl8411_pcr_ops = { .card_power_off = rtl8411_card_power_off, .switch_output_voltage = rtl8411_switch_output_voltage, .cd_deglitch = rtl8411_cd_deglitch, + .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, };/* SD Pull Control Enable:
drivers/mfd/rts5209.c +1 -0
@@ -174,6 +174,7 @@ static const struct pcr_ops rts5209_pcr_ops = { .card_power_off = rts5209_card_power_off, .switch_output_voltage = rts5209_switch_output_voltage, .cd_deglitch = NULL, + .conv_clk_and_div_n = NULL, };/* SD Pull Control Enable:
drivers/mfd/rts5229.c +1 -0
@@ -144,6 +144,7 @@ static const struct pcr_ops rts5229_pcr_ops = { .card_power_off = rts5229_card_power_off, .switch_output_voltage = rts5229_switch_output_voltage, .cd_deglitch = NULL, + .conv_clk_and_div_n = NULL, };/* SD Pull Control Enable:
drivers/mfd/rtsx_pcr.c +12 -2
@@ -630,7 +630,10 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,if (clk == pcr->cur_clock)return 0 ; -N = (u8)(clk -2 ); +if (pcr->ops->conv_clk_and_div_n) +N = (u8 )pcr->ops->conv_clk_and_div_n (clk,CLK_TO_DIV_N ); +else +N = (u8)(clk -2 );if ((clk <=2 ) || (N > max_N))return -EINVAL ;
@@ -641,7 +644,14 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,/* Make sure that the SSC clock div_n is equal or greater than min_N */ div =CLK_DIV_1 ;while ((N < min_N) && (div < max_div)) { -N = (N +2 ) *2 -2 ; +if (pcr->ops->conv_clk_and_div_n) { +int dbl_clk = pcr->ops->conv_clk_and_div_n (N , +DIV_N_TO_CLK ) *2 ; +N = (u8 )pcr->ops->conv_clk_and_div_n (dbl_clk, +CLK_TO_DIV_N ); + }else { +N = (N +2 ) *2 -2 ; + } div++; }dev_dbg (&(pcr->pci->dev),"N = %d, div = %d\n" ,N , div);
include/linux/mfd/rtsx_common.h +3 -0
@@ -38,6 +38,9 @@#define RTSX_SD_CARD 0#define RTSX_MS_CARD 1 +#define CLK_TO_DIV_N 0 +#define DIV_N_TO_CLK 1 +struct platform_device ;struct rtsx_slot {
include/linux/mfd/rtsx_pci.h +1 -0
@@ -704,6 +704,7 @@ struct pcr_ops {int (*switch_output_voltage)(struct rtsx_pcr *pcr,u8 voltage);unsigned int (*cd_deglitch)(struct rtsx_pcr *pcr); +int (*conv_clk_and_div_n)(int clk,int dir); };enum PDEV_STAT {PDEV_STAT_IDLE ,PDEV_STAT_RUN };
Signature · 1 line
1.7.9.5
Hi Wei,
Quoted 9 lines · On Wed, Jan 23, 2013 at 09:51:03AM +0800, [email protected] wrote:
From: Wei WANG <[email protected]>
1. The method to switch output voltage is different in rtl8411
2. Fix the formula to calculate N from SD clock if clock divider is more than 1Wei WANG (3):
MFD:rtsx: Add callback functionswitch_output_voltageMMC:rtsx: Using callback function to switch output voltage MFD:rtsx: Add callback functionconv_clk_and_div_n
All 3 patches applied to my for-linus branch. I rephrased the changelog slightly, to make it clearer that this is a bug fix.
Cheers,
Samuel.
Signature · 2 lines
Intel Open Source Technology Centre http://oss.intel.com/