misc: rtsx_pci: Add separate CD/WP pin polarity reversal support

Previously, the Card Detect (CD) and Write Protect (WP) pins shared the
same reverse polarity setting in the configuration space. This meant both
signals were reversed together, without the ability to configure them
individually.

This patch introduces two new parameters:
sd_cd_reverse_en – enable reverse polarity for the CD pin.
sd_wp_reverse_en – enable reverse polarity for the WP pin.

With this change, the controller can now support:
1.Reversing both CD and WP pins together (original behavior).
2.Reversing CD and WP pins separately (newly added behavior), if
supported by the configuration space.

This provides greater flexibility when dealing with devices that have
independent polarity requirements for CD and WP pins.

Signed-off-by: Ricky Wu <ricky_wu@realtek.com>
Link: https://lore.kernel.org/r/20250812063521.2427696-1-ricky_wu@realtek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Ricky Wu authored and Greg Kroah-Hartman committed 2025-08-19 12:37:10 +02:00
1 parent 6e6fe5a990
commit 807221d3c5
7 files changed
+54 -12

No files matched your search

+10 -3
View File
@@ -79,6 +79,10 @@ static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr)
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;
if (rtsx_reg_check_cd_reverse(reg))
pcr->option.sd_cd_reverse_en = 1;
if (rtsx_reg_check_wp_reverse(reg))
pcr->option.sd_wp_reverse_en = 1;
}
static void rts5227_init_from_cfg(struct rtsx_pcr *pcr)
@@ -127,8 +131,10 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
/* Configure force_clock_req */
if (pcr->flags & PCR_REVERSE_SOCKET)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x30, 0x30);
else
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x30, 0x00);
else {
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x20, option->sd_cd_reverse_en << 5);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x10, option->sd_wp_reverse_en << 4);
}
if (CHK_PCI_PID(pcr, 0x522A))
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RTS522A_AUTOLOAD_CFG1,
@@ -350,6 +356,8 @@ void rts5227_init_params(struct rtsx_pcr *pcr)
pcr->ms_pull_ctl_disable_tbl = rts5227_ms_pull_ctl_disable_tbl;
pcr->reg_pm_ctrl3 = PM_CTRL3;
pcr->option.sd_cd_reverse_en = 0;
pcr->option.sd_wp_reverse_en = 0;
}
static int rts522a_optimize_phy(struct rtsx_pcr *pcr)
@@ -508,5 +516,4 @@ void rts522a_init_params(struct rtsx_pcr *pcr)
pcr->hw_param.interrupt_en |= SD_OC_INT_EN;
pcr->hw_param.ocp_glitch = SD_OCP_GLITCH_10M;
pcr->option.sd_800mA_ocp_thd = RTS522A_OCP_THD_800;
}
+10 -2
View File
@@ -84,6 +84,10 @@ static void rtsx5228_fetch_vendor_settings(struct rtsx_pcr *pcr)
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;
if (rtsx_reg_check_cd_reverse(reg))
pcr->option.sd_cd_reverse_en = 1;
if (rtsx_reg_check_wp_reverse(reg))
pcr->option.sd_wp_reverse_en = 1;
}
static int rts5228_optimize_phy(struct rtsx_pcr *pcr)
@@ -432,8 +436,10 @@ static int rts5228_extra_init_hw(struct rtsx_pcr *pcr)
if (pcr->flags & PCR_REVERSE_SOCKET)
rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x30);
else
rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00);
else {
rtsx_pci_write_register(pcr, PETXCFG, 0x20, option->sd_cd_reverse_en << 5);
rtsx_pci_write_register(pcr, PETXCFG, 0x10, option->sd_wp_reverse_en << 4);
}
/*
* If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
@@ -720,4 +726,6 @@ void rts5228_init_params(struct rtsx_pcr *pcr)
hw_param->interrupt_en |= SD_OC_INT_EN;
hw_param->ocp_glitch = SD_OCP_GLITCH_800U;
option->sd_800mA_ocp_thd = RTS5228_LDO1_OCP_THD_930;
option->sd_cd_reverse_en = 0;
option->sd_wp_reverse_en = 0;
}
+13 -3
View File
@@ -60,6 +60,7 @@ static void rtsx_base_fetch_vendor_settings(struct rtsx_pcr *pcr)
pci_read_config_dword(pdev, PCR_SETTING_REG1, &reg);
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
pci_write_config_dword(pdev, 0x718, 0x0007C000);
if (!rtsx_vendor_setting_valid(reg)) {
pcr_dbg(pcr, "skip fetch vendor setting\n");
@@ -82,6 +83,10 @@ static void rtsx_base_fetch_vendor_settings(struct rtsx_pcr *pcr)
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;
if (rtsx_reg_check_cd_reverse(reg))
pcr->option.sd_cd_reverse_en = 1;
if (rtsx_reg_check_wp_reverse(reg))
pcr->option.sd_wp_reverse_en = 1;
}
static void rts5249_init_from_cfg(struct rtsx_pcr *pcr)
@@ -254,9 +259,11 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
/* Configure driving */
rts5249_fill_driving(pcr, OUTPUT_3V3);
if (pcr->flags & PCR_REVERSE_SOCKET)
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0xB0);
else
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0x80);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x30, 0x30);
else {
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x20, option->sd_cd_reverse_en << 5);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x10, option->sd_wp_reverse_en << 4);
}
rtsx_pci_send_cmd(pcr, CMD_TIMEOUT_DEF);
@@ -572,6 +579,9 @@ void rts5249_init_params(struct rtsx_pcr *pcr)
option->ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5249_DEF;
option->ltr_l1off_snooze_sspwrgate =
LTR_L1OFF_SNOOZE_SSPWRGATE_5249_DEF;
option->sd_cd_reverse_en = 0;
option->sd_wp_reverse_en = 0;
}
static int rts524a_write_phy(struct rtsx_pcr *pcr, u8 addr, u16 val)
+16 -4
View File
@@ -527,8 +527,16 @@ static void rts5264_init_from_hw(struct rtsx_pcr *pcr)
pcr->rtd3_en = rts5264_reg_to_rtd3(lval2);
if (rts5264_reg_check_reverse_socket(lval2))
pcr->flags |= PCR_REVERSE_SOCKET;
if (rts5264_reg_check_reverse_socket(lval2)) {
if (is_version_higher_than(pcr, PID_5264, RTS5264_IC_VER_B))
pcr->option.sd_cd_reverse_en = 1;
else
pcr->flags |= PCR_REVERSE_SOCKET;
}
if (rts5264_reg_check_wp_reverse(lval2) &&
is_version_higher_than(pcr, PID_5264, RTS5264_IC_VER_B))
pcr->option.sd_wp_reverse_en = 1;
pci_read_config_dword(pdev, setting_reg1, &lval1);
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", setting_reg1, lval1);
@@ -622,8 +630,10 @@ static int rts5264_extra_init_hw(struct rtsx_pcr *pcr)
if (pcr->flags & PCR_REVERSE_SOCKET)
rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x30);
else
rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00);
else {
rtsx_pci_write_register(pcr, PETXCFG, 0x20, option->sd_cd_reverse_en << 5);
rtsx_pci_write_register(pcr, PETXCFG, 0x10, option->sd_wp_reverse_en << 4);
}
/*
* If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
@@ -957,4 +967,6 @@ void rts5264_init_params(struct rtsx_pcr *pcr)
hw_param->interrupt_en |= (SD_OC_INT_EN | SD_OVP_INT_EN);
hw_param->ocp_glitch = SD_OCP_GLITCH_800U | SDVIO_OCP_GLITCH_800U;
option->sd_800mA_ocp_thd = RTS5264_LDO1_OCP_THD_1150;
option->sd_cd_reverse_en = 0;
option->sd_wp_reverse_en = 0;
}
+1
View File
@@ -14,6 +14,7 @@
#define rts5264_reg_to_aspm(reg) \
(((~(reg) >> 28) & 0x02) | (((reg) >> 28) & 0x01))
#define rts5264_reg_check_reverse_socket(reg) ((reg) & 0x04)
#define rts5264_reg_check_wp_reverse(reg) ((reg) & 0x8000)
#define rts5264_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 22) & 0x03)
#define rts5264_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 16) & 0x03)
#define rts5264_reg_to_rtd3(reg) ((reg) & 0x08)
+2
View File
@@ -100,6 +100,8 @@ static inline u8 map_sd_drive(int idx)
#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 rtsx_reg_check_cd_reverse(reg) ((reg) & 0x800000)
#define rtsx_reg_check_wp_reverse(reg) ((reg) & 0x400000)
#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)
+2
View File
@@ -1160,6 +1160,8 @@ struct rtsx_cr_option {
bool ocp_en;
u8 sd_400mA_ocp_thd;
u8 sd_800mA_ocp_thd;
u8 sd_cd_reverse_en;
u8 sd_wp_reverse_en;
};
/*