513 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* Driver for Realtek PCI-Express card reader3 *4 * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.5 *6 * Author:7 * Wei WANG <wei_wang@realsil.com.cn>8 * Roger Tseng <rogerable@realtek.com>9 */10 11#include <linux/module.h>12#include <linux/delay.h>13#include <linux/rtsx_pci.h>14 15#include "rtsx_pcr.h"16 17static u8 rts5227_get_ic_version(struct rtsx_pcr *pcr)18{19 u8 val;20 21 rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);22 return val & 0x0F;23}24 25static void rts5227_fill_driving(struct rtsx_pcr *pcr, u8 voltage)26{27 u8 driving_3v3[4][3] = {28 {0x13, 0x13, 0x13},29 {0x96, 0x96, 0x96},30 {0x7F, 0x7F, 0x7F},31 {0x96, 0x96, 0x96},32 };33 u8 driving_1v8[4][3] = {34 {0x99, 0x99, 0x99},35 {0xAA, 0xAA, 0xAA},36 {0xFE, 0xFE, 0xFE},37 {0xB3, 0xB3, 0xB3},38 };39 u8 (*driving)[3], drive_sel;40 41 if (voltage == OUTPUT_3V3) {42 driving = driving_3v3;43 drive_sel = pcr->sd30_drive_sel_3v3;44 } else {45 driving = driving_1v8;46 drive_sel = pcr->sd30_drive_sel_1v8;47 }48 49 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,50 0xFF, driving[drive_sel][0]);51 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,52 0xFF, driving[drive_sel][1]);53 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,54 0xFF, driving[drive_sel][2]);55}56 57static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr)58{59 struct pci_dev *pdev = pcr->pci;60 u32 reg;61 62 pci_read_config_dword(pdev, PCR_SETTING_REG1, ®);63 pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);64 65 if (!rtsx_vendor_setting_valid(reg))66 return;67 68 pcr->aspm_en = rtsx_reg_to_aspm(reg);69 pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg);70 pcr->card_drive_sel &= 0x3F;71 pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);72 73 pci_read_config_dword(pdev, PCR_SETTING_REG2, ®);74 pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);75 if (CHK_PCI_PID(pcr, 0x522A))76 pcr->rtd3_en = rtsx_reg_to_rtd3(reg);77 if (rtsx_check_mmc_support(reg))78 pcr->extra_caps |= EXTRA_CAPS_NO_MMC;79 pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);80 if (rtsx_reg_check_reverse_socket(reg))81 pcr->flags |= PCR_REVERSE_SOCKET;82}83 84static void rts5227_init_from_cfg(struct rtsx_pcr *pcr)85{86 struct rtsx_cr_option *option = &pcr->option;87 88 if (CHK_PCI_PID(pcr, 0x522A)) {89 if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN90 | PM_L1_1_EN | PM_L1_2_EN))91 rtsx_pci_disable_oobs_polling(pcr);92 else93 rtsx_pci_enable_oobs_polling(pcr);94 }95 96 if (option->ltr_en) {97 if (option->ltr_enabled)98 rtsx_set_ltr_latency(pcr, option->ltr_active_latency);99 }100}101 102static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)103{104 u16 cap;105 struct rtsx_cr_option *option = &pcr->option;106 107 rts5227_init_from_cfg(pcr);108 rtsx_pci_init_cmd(pcr);109 110 /* Configure GPIO as output */111 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);112 /* Reset ASPM state to default value */113 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);114 /* Switch LDO3318 source from DV33 to card_3v3 */115 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);116 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);117 /* LED shine disabled, set initial shine cycle period */118 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);119 /* Configure LTR */120 pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &cap);121 if (cap & PCI_EXP_DEVCTL2_LTR_EN)122 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3);123 /* Configure OBFF */124 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03);125 /* Configure driving */126 rts5227_fill_driving(pcr, OUTPUT_3V3);127 /* Configure force_clock_req */128 if (pcr->flags & PCR_REVERSE_SOCKET)129 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x30, 0x30);130 else131 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x30, 0x00);132 133 if (CHK_PCI_PID(pcr, 0x522A))134 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RTS522A_AUTOLOAD_CFG1,135 CD_RESUME_EN_MASK, CD_RESUME_EN_MASK);136 137 if (pcr->rtd3_en) {138 if (CHK_PCI_PID(pcr, 0x522A)) {139 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RTS522A_PM_CTRL3, 0x01, 0x01);140 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RTS522A_PME_FORCE_CTL, 0x30, 0x30);141 } else {142 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x01, 0x01);143 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PME_FORCE_CTL, 0xFF, 0x33);144 }145 } else {146 if (CHK_PCI_PID(pcr, 0x522A)) {147 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RTS522A_PM_CTRL3, 0x01, 0x00);148 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RTS522A_PME_FORCE_CTL, 0x30, 0x20);149 } else {150 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PME_FORCE_CTL, 0xFF, 0x30);151 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x01, 0x00);152 }153 }154 155 if (option->force_clkreq_0)156 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,157 FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);158 else159 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,160 FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);161 162 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, pcr->reg_pm_ctrl3, 0x10, 0x00);163 164 return rtsx_pci_send_cmd(pcr, 100);165}166 167static int rts5227_optimize_phy(struct rtsx_pcr *pcr)168{169 int err;170 171 err = rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);172 if (err < 0)173 return err;174 175 /* Optimize RX sensitivity */176 return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);177}178 179static int rts5227_turn_on_led(struct rtsx_pcr *pcr)180{181 return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);182}183 184static int rts5227_turn_off_led(struct rtsx_pcr *pcr)185{186 return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);187}188 189static int rts5227_enable_auto_blink(struct rtsx_pcr *pcr)190{191 return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);192}193 194static int rts5227_disable_auto_blink(struct rtsx_pcr *pcr)195{196 return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);197}198 199static int rts5227_card_power_on(struct rtsx_pcr *pcr, int card)200{201 int err;202 203 if (pcr->option.ocp_en)204 rtsx_pci_enable_ocp(pcr);205 206 rtsx_pci_init_cmd(pcr);207 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,208 SD_POWER_MASK, SD_PARTIAL_POWER_ON);209 210 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,211 LDO3318_PWR_MASK, 0x02);212 213 err = rtsx_pci_send_cmd(pcr, 100);214 if (err < 0)215 return err;216 217 /* To avoid too large in-rush current */218 msleep(20);219 rtsx_pci_init_cmd(pcr);220 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,221 SD_POWER_MASK, SD_POWER_ON);222 223 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,224 LDO3318_PWR_MASK, 0x06);225 226 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE,227 SD_OUTPUT_EN, SD_OUTPUT_EN);228 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_OE,229 MS_OUTPUT_EN, MS_OUTPUT_EN);230 return rtsx_pci_send_cmd(pcr, 100);231}232 233static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card)234{235 if (pcr->option.ocp_en)236 rtsx_pci_disable_ocp(pcr);237 238 rtsx_pci_write_register(pcr, CARD_PWR_CTL, SD_POWER_MASK |239 PMOS_STRG_MASK, SD_POWER_OFF | PMOS_STRG_400mA);240 rtsx_pci_write_register(pcr, PWR_GATE_CTRL, LDO3318_PWR_MASK, 0X00);241 242 return 0;243}244 245static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)246{247 int err;248 249 if (voltage == OUTPUT_3V3) {250 err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);251 if (err < 0)252 return err;253 } else if (voltage == OUTPUT_1V8) {254 err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02);255 if (err < 0)256 return err;257 err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24);258 if (err < 0)259 return err;260 } else {261 return -EINVAL;262 }263 264 /* set pad drive */265 rtsx_pci_init_cmd(pcr);266 rts5227_fill_driving(pcr, voltage);267 return rtsx_pci_send_cmd(pcr, 100);268}269 270static const struct pcr_ops rts5227_pcr_ops = {271 .fetch_vendor_settings = rts5227_fetch_vendor_settings,272 .extra_init_hw = rts5227_extra_init_hw,273 .optimize_phy = rts5227_optimize_phy,274 .turn_on_led = rts5227_turn_on_led,275 .turn_off_led = rts5227_turn_off_led,276 .enable_auto_blink = rts5227_enable_auto_blink,277 .disable_auto_blink = rts5227_disable_auto_blink,278 .card_power_on = rts5227_card_power_on,279 .card_power_off = rts5227_card_power_off,280 .switch_output_voltage = rts5227_switch_output_voltage,281 .cd_deglitch = NULL,282 .conv_clk_and_div_n = NULL,283};284 285/* SD Pull Control Enable:286 * SD_DAT[3:0] ==> pull up287 * SD_CD ==> pull up288 * SD_WP ==> pull up289 * SD_CMD ==> pull up290 * SD_CLK ==> pull down291 */292static const u32 rts5227_sd_pull_ctl_enable_tbl[] = {293 RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),294 RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),295 0,296};297 298/* SD Pull Control Disable:299 * SD_DAT[3:0] ==> pull down300 * SD_CD ==> pull up301 * SD_WP ==> pull down302 * SD_CMD ==> pull down303 * SD_CLK ==> pull down304 */305static const u32 rts5227_sd_pull_ctl_disable_tbl[] = {306 RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),307 RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),308 0,309};310 311/* MS Pull Control Enable:312 * MS CD ==> pull up313 * others ==> pull down314 */315static const u32 rts5227_ms_pull_ctl_enable_tbl[] = {316 RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),317 RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),318 0,319};320 321/* MS Pull Control Disable:322 * MS CD ==> pull up323 * others ==> pull down324 */325static const u32 rts5227_ms_pull_ctl_disable_tbl[] = {326 RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),327 RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),328 0,329};330 331void rts5227_init_params(struct rtsx_pcr *pcr)332{333 pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;334 pcr->num_slots = 2;335 pcr->ops = &rts5227_pcr_ops;336 337 pcr->flags = 0;338 pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;339 pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;340 pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;341 pcr->aspm_en = ASPM_L1_EN;342 pcr->aspm_mode = ASPM_MODE_CFG;343 pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15);344 pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 7, 7);345 346 pcr->ic_version = rts5227_get_ic_version(pcr);347 pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl;348 pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl;349 pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl;350 pcr->ms_pull_ctl_disable_tbl = rts5227_ms_pull_ctl_disable_tbl;351 352 pcr->reg_pm_ctrl3 = PM_CTRL3;353}354 355static int rts522a_optimize_phy(struct rtsx_pcr *pcr)356{357 int err;358 359 err = rtsx_pci_write_register(pcr, RTS522A_PM_CTRL3, D3_DELINK_MODE_EN,360 0x00);361 if (err < 0)362 return err;363 364 if (is_version(pcr, 0x522A, IC_VER_A)) {365 err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,366 PHY_RCR2_INIT_27S);367 if (err)368 return err;369 370 rtsx_pci_write_phy_register(pcr, PHY_RCR1, PHY_RCR1_INIT_27S);371 rtsx_pci_write_phy_register(pcr, PHY_FLD0, PHY_FLD0_INIT_27S);372 rtsx_pci_write_phy_register(pcr, PHY_FLD3, PHY_FLD3_INIT_27S);373 rtsx_pci_write_phy_register(pcr, PHY_FLD4, PHY_FLD4_INIT_27S);374 }375 376 return 0;377}378 379static int rts522a_extra_init_hw(struct rtsx_pcr *pcr)380{381 rts5227_extra_init_hw(pcr);382 383 /* Power down OCP for power consumption */384 if (!pcr->card_exist)385 rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN,386 OC_POWER_DOWN);387 388 rtsx_pci_write_register(pcr, FUNC_FORCE_CTL, FUNC_FORCE_UPME_XMT_DBG,389 FUNC_FORCE_UPME_XMT_DBG);390 rtsx_pci_write_register(pcr, PCLK_CTL, 0x04, 0x04);391 rtsx_pci_write_register(pcr, PM_EVENT_DEBUG, PME_DEBUG_0, PME_DEBUG_0);392 rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 0xFF, 0x11);393 394 return 0;395}396 397static int rts522a_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)398{399 int err;400 401 if (voltage == OUTPUT_3V3) {402 err = rtsx_pci_write_phy_register(pcr, 0x08, 0x57E4);403 if (err < 0)404 return err;405 } else if (voltage == OUTPUT_1V8) {406 err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02);407 if (err < 0)408 return err;409 err = rtsx_pci_write_phy_register(pcr, 0x08, 0x54A4);410 if (err < 0)411 return err;412 } else {413 return -EINVAL;414 }415 416 /* set pad drive */417 rtsx_pci_init_cmd(pcr);418 rts5227_fill_driving(pcr, voltage);419 return rtsx_pci_send_cmd(pcr, 100);420}421 422static void rts522a_force_power_down(struct rtsx_pcr *pcr, u8 pm_state, bool runtime)423{424 /* Set relink_time to 0 */425 rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, MASK_8_BIT_DEF, 0);426 rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, MASK_8_BIT_DEF, 0);427 rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3,428 RELINK_TIME_MASK, 0);429 430 rtsx_pci_write_register(pcr, RTS522A_PM_CTRL3,431 D3_DELINK_MODE_EN, D3_DELINK_MODE_EN);432 433 if (!runtime) {434 rtsx_pci_write_register(pcr, RTS522A_AUTOLOAD_CFG1,435 CD_RESUME_EN_MASK, 0);436 rtsx_pci_write_register(pcr, RTS522A_PM_CTRL3, 0x01, 0x00);437 rtsx_pci_write_register(pcr, RTS522A_PME_FORCE_CTL, 0x30, 0x20);438 }439 440 rtsx_pci_write_register(pcr, FPDCTL, ALL_POWER_DOWN, ALL_POWER_DOWN);441}442 443 444static void rts522a_set_l1off_cfg_sub_d0(struct rtsx_pcr *pcr, int active)445{446 struct rtsx_cr_option *option = &pcr->option;447 int aspm_L1_1, aspm_L1_2;448 u8 val = 0;449 450 aspm_L1_1 = rtsx_check_dev_flag(pcr, ASPM_L1_1_EN);451 aspm_L1_2 = rtsx_check_dev_flag(pcr, ASPM_L1_2_EN);452 453 if (active) {454 /* run, latency: 60us */455 if (aspm_L1_1)456 val = option->ltr_l1off_snooze_sspwrgate;457 } else {458 /* l1off, latency: 300us */459 if (aspm_L1_2)460 val = option->ltr_l1off_sspwrgate;461 }462 463 rtsx_set_l1off_sub(pcr, val);464}465 466/* rts522a operations mainly derived from rts5227, except phy/hw init setting.467 */468static const struct pcr_ops rts522a_pcr_ops = {469 .fetch_vendor_settings = rts5227_fetch_vendor_settings,470 .extra_init_hw = rts522a_extra_init_hw,471 .optimize_phy = rts522a_optimize_phy,472 .turn_on_led = rts5227_turn_on_led,473 .turn_off_led = rts5227_turn_off_led,474 .enable_auto_blink = rts5227_enable_auto_blink,475 .disable_auto_blink = rts5227_disable_auto_blink,476 .card_power_on = rts5227_card_power_on,477 .card_power_off = rts5227_card_power_off,478 .switch_output_voltage = rts522a_switch_output_voltage,479 .force_power_down = rts522a_force_power_down,480 .cd_deglitch = NULL,481 .conv_clk_and_div_n = NULL,482 .set_l1off_cfg_sub_d0 = rts522a_set_l1off_cfg_sub_d0,483};484 485void rts522a_init_params(struct rtsx_pcr *pcr)486{487 struct rtsx_cr_option *option = &pcr->option;488 489 rts5227_init_params(pcr);490 pcr->ops = &rts522a_pcr_ops;491 pcr->aspm_mode = ASPM_MODE_REG;492 pcr->tx_initial_phase = SET_CLOCK_PHASE(20, 20, 11);493 pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3;494 495 option->dev_flags = LTR_L1SS_PWR_GATE_EN;496 option->ltr_en = true;497 498 /* init latency of active, idle, L1OFF to 60us, 300us, 3ms */499 option->ltr_active_latency = LTR_ACTIVE_LATENCY_DEF;500 option->ltr_idle_latency = LTR_IDLE_LATENCY_DEF;501 option->ltr_l1off_latency = LTR_L1OFF_LATENCY_DEF;502 option->l1_snooze_delay = L1_SNOOZE_DELAY_DEF;503 option->ltr_l1off_sspwrgate = 0x7F;504 option->ltr_l1off_snooze_sspwrgate = 0x78;505 506 pcr->option.ocp_en = 1;507 if (pcr->option.ocp_en)508 pcr->hw_param.interrupt_en |= SD_OC_INT_EN;509 pcr->hw_param.ocp_glitch = SD_OCP_GLITCH_10M;510 pcr->option.sd_800mA_ocp_thd = RTS522A_OCP_THD_800;511 512}513