Commit d817ac4e authored by Wei WANG's avatar Wei WANG Committed by Samuel Ortiz

mfd: rtsx: Add output voltage switch hook

Different card reader has different method to switch output voltage,
add this callback to let the card reader implement its individual switch
function.
This is needed as rtl8411 has a specific switch output voltage procedure.
Signed-off-by: default avatarWei WANG <wei_wang@realsil.com.cn>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 00441b5e
...@@ -112,6 +112,21 @@ static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card) ...@@ -112,6 +112,21 @@ static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card)
BPP_LDO_POWB, BPP_LDO_SUSPEND); 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) static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
{ {
unsigned int card_exist; unsigned int card_exist;
...@@ -172,6 +187,7 @@ static const struct pcr_ops rtl8411_pcr_ops = { ...@@ -172,6 +187,7 @@ static const struct pcr_ops rtl8411_pcr_ops = {
.disable_auto_blink = rtl8411_disable_auto_blink, .disable_auto_blink = rtl8411_disable_auto_blink,
.card_power_on = rtl8411_card_power_on, .card_power_on = rtl8411_card_power_on,
.card_power_off = rtl8411_card_power_off, .card_power_off = rtl8411_card_power_off,
.switch_output_voltage = rtl8411_switch_output_voltage,
.cd_deglitch = rtl8411_cd_deglitch, .cd_deglitch = rtl8411_cd_deglitch,
}; };
......
...@@ -144,6 +144,25 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card) ...@@ -144,6 +144,25 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
return rtsx_pci_send_cmd(pcr, 100); 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 = { static const struct pcr_ops rts5209_pcr_ops = {
.extra_init_hw = rts5209_extra_init_hw, .extra_init_hw = rts5209_extra_init_hw,
.optimize_phy = rts5209_optimize_phy, .optimize_phy = rts5209_optimize_phy,
...@@ -153,6 +172,7 @@ static const struct pcr_ops rts5209_pcr_ops = { ...@@ -153,6 +172,7 @@ static const struct pcr_ops rts5209_pcr_ops = {
.disable_auto_blink = rts5209_disable_auto_blink, .disable_auto_blink = rts5209_disable_auto_blink,
.card_power_on = rts5209_card_power_on, .card_power_on = rts5209_card_power_on,
.card_power_off = rts5209_card_power_off, .card_power_off = rts5209_card_power_off,
.switch_output_voltage = rts5209_switch_output_voltage,
.cd_deglitch = NULL, .cd_deglitch = NULL,
}; };
......
...@@ -114,6 +114,25 @@ static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card) ...@@ -114,6 +114,25 @@ static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
return rtsx_pci_send_cmd(pcr, 100); 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 = { static const struct pcr_ops rts5229_pcr_ops = {
.extra_init_hw = rts5229_extra_init_hw, .extra_init_hw = rts5229_extra_init_hw,
.optimize_phy = rts5229_optimize_phy, .optimize_phy = rts5229_optimize_phy,
...@@ -123,6 +142,7 @@ static const struct pcr_ops rts5229_pcr_ops = { ...@@ -123,6 +142,7 @@ static const struct pcr_ops rts5229_pcr_ops = {
.disable_auto_blink = rts5229_disable_auto_blink, .disable_auto_blink = rts5229_disable_auto_blink,
.card_power_on = rts5229_card_power_on, .card_power_on = rts5229_card_power_on,
.card_power_off = rts5229_card_power_off, .card_power_off = rts5229_card_power_off,
.switch_output_voltage = rts5229_switch_output_voltage,
.cd_deglitch = NULL, .cd_deglitch = NULL,
}; };
......
...@@ -703,6 +703,15 @@ int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card) ...@@ -703,6 +703,15 @@ int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card)
} }
EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off); 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 rtsx_pci_card_exist(struct rtsx_pcr *pcr)
{ {
unsigned int val; unsigned int val;
......
...@@ -158,10 +158,9 @@ ...@@ -158,10 +158,9 @@
#define SG_TRANS_DATA (0x02 << 4) #define SG_TRANS_DATA (0x02 << 4)
#define SG_LINK_DESC (0x03 << 4) #define SG_LINK_DESC (0x03 << 4)
/* SD bank voltage */ /* Output voltage */
#define SD_IO_3V3 0 #define OUTPUT_3V3 0
#define SD_IO_1V8 1 #define OUTPUT_1V8 1
/* Card Clock Enable Register */ /* Card Clock Enable Register */
#define SD_CLK_EN 0x04 #define SD_CLK_EN 0x04
...@@ -201,6 +200,20 @@ ...@@ -201,6 +200,20 @@
#define CHANGE_CLK 0x01 #define CHANGE_CLK 0x01
/* LDO_CTL */ /* 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_POWB 0x03
#define BPP_LDO_ON 0x00 #define BPP_LDO_ON 0x00
#define BPP_LDO_SUSPEND 0x02 #define BPP_LDO_SUSPEND 0x02
...@@ -688,6 +701,8 @@ struct pcr_ops { ...@@ -688,6 +701,8 @@ struct pcr_ops {
int (*disable_auto_blink)(struct rtsx_pcr *pcr); int (*disable_auto_blink)(struct rtsx_pcr *pcr);
int (*card_power_on)(struct rtsx_pcr *pcr, int card); int (*card_power_on)(struct rtsx_pcr *pcr, int card);
int (*card_power_off)(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); 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, ...@@ -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); 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_on(struct rtsx_pcr *pcr, int card);
int rtsx_pci_card_power_off(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); unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr);
void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr); void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment