1*aaf4989bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2e455b69dSRui Feng /* Driver for Realtek PCI-Express card reader 3e455b69dSRui Feng * 4e455b69dSRui Feng * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. 5e455b69dSRui Feng * 6e455b69dSRui Feng * Author: 7e455b69dSRui Feng * Wei WANG <wei_wang@realsil.com.cn> 8e455b69dSRui Feng * Roger Tseng <rogerable@realtek.com> 9e455b69dSRui Feng */ 10e455b69dSRui Feng 11e455b69dSRui Feng #include <linux/module.h> 12e455b69dSRui Feng #include <linux/bitops.h> 13e455b69dSRui Feng #include <linux/delay.h> 14e455b69dSRui Feng #include <linux/rtsx_pci.h> 15e455b69dSRui Feng 16e455b69dSRui Feng #include "rtsx_pcr.h" 17e455b69dSRui Feng 18e455b69dSRui Feng static u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr) 19e455b69dSRui Feng { 20e455b69dSRui Feng u8 val; 21e455b69dSRui Feng 22e455b69dSRui Feng rtsx_pci_read_register(pcr, SYS_VER, &val); 23e455b69dSRui Feng return val & 0x0F; 24e455b69dSRui Feng } 25e455b69dSRui Feng 26e455b69dSRui Feng static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr) 27e455b69dSRui Feng { 28e455b69dSRui Feng u8 val = 0; 29e455b69dSRui Feng 30e455b69dSRui Feng rtsx_pci_read_register(pcr, RTL8411B_PACKAGE_MODE, &val); 31e455b69dSRui Feng 32e455b69dSRui Feng if (val & 0x2) 33e455b69dSRui Feng return 1; 34e455b69dSRui Feng else 35e455b69dSRui Feng return 0; 36e455b69dSRui Feng } 37e455b69dSRui Feng 38e455b69dSRui Feng static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr) 39e455b69dSRui Feng { 40e455b69dSRui Feng u32 reg1 = 0; 41e455b69dSRui Feng u8 reg3 = 0; 42e455b69dSRui Feng 43e455b69dSRui Feng rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®1); 44e455b69dSRui Feng pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1); 45e455b69dSRui Feng 46e455b69dSRui Feng if (!rtsx_vendor_setting_valid(reg1)) 47e455b69dSRui Feng return; 48e455b69dSRui Feng 49e455b69dSRui Feng pcr->aspm_en = rtsx_reg_to_aspm(reg1); 50e455b69dSRui Feng pcr->sd30_drive_sel_1v8 = 51e455b69dSRui Feng map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg1)); 52e455b69dSRui Feng pcr->card_drive_sel &= 0x3F; 53e455b69dSRui Feng pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg1); 54e455b69dSRui Feng 55e455b69dSRui Feng rtsx_pci_read_config_byte(pcr, PCR_SETTING_REG3, ®3); 56e455b69dSRui Feng pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3); 57e455b69dSRui Feng pcr->sd30_drive_sel_3v3 = rtl8411_reg_to_sd30_drive_sel_3v3(reg3); 58e455b69dSRui Feng } 59e455b69dSRui Feng 60e455b69dSRui Feng static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr) 61e455b69dSRui Feng { 62e455b69dSRui Feng u32 reg = 0; 63e455b69dSRui Feng 64e455b69dSRui Feng rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); 65e455b69dSRui Feng pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); 66e455b69dSRui Feng 67e455b69dSRui Feng if (!rtsx_vendor_setting_valid(reg)) 68e455b69dSRui Feng return; 69e455b69dSRui Feng 70e455b69dSRui Feng pcr->aspm_en = rtsx_reg_to_aspm(reg); 71e455b69dSRui Feng pcr->sd30_drive_sel_1v8 = 72e455b69dSRui Feng map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg)); 73e455b69dSRui Feng pcr->sd30_drive_sel_3v3 = 74e455b69dSRui Feng map_sd_drive(rtl8411b_reg_to_sd30_drive_sel_3v3(reg)); 75e455b69dSRui Feng } 76e455b69dSRui Feng 77e455b69dSRui Feng static void rtl8411_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) 78e455b69dSRui Feng { 79e455b69dSRui Feng rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07); 80e455b69dSRui Feng } 81e455b69dSRui Feng 82e455b69dSRui Feng static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr) 83e455b69dSRui Feng { 84e455b69dSRui Feng rtsx_pci_init_cmd(pcr); 85e455b69dSRui Feng 86e455b69dSRui Feng rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, 87e455b69dSRui Feng 0xFF, pcr->sd30_drive_sel_3v3); 88e455b69dSRui Feng rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL, 89e455b69dSRui Feng CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); 90e455b69dSRui Feng 91e455b69dSRui Feng return rtsx_pci_send_cmd(pcr, 100); 92e455b69dSRui Feng } 93e455b69dSRui Feng 94e455b69dSRui Feng static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr) 95e455b69dSRui Feng { 96e455b69dSRui Feng rtsx_pci_init_cmd(pcr); 97e455b69dSRui Feng 98e455b69dSRui Feng if (rtl8411b_is_qfn48(pcr)) 99e455b69dSRui Feng rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 100e455b69dSRui Feng CARD_PULL_CTL3, 0xFF, 0xF5); 101e455b69dSRui Feng rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL, 102e455b69dSRui Feng 0xFF, pcr->sd30_drive_sel_3v3); 103e455b69dSRui Feng rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL, 104e455b69dSRui Feng CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); 105e455b69dSRui Feng rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, FUNC_FORCE_CTL, 106e455b69dSRui Feng 0x06, 0x00); 107e455b69dSRui Feng 108e455b69dSRui Feng return rtsx_pci_send_cmd(pcr, 100); 109e455b69dSRui Feng } 110e455b69dSRui Feng 111e455b69dSRui Feng static int rtl8411_turn_on_led(struct rtsx_pcr *pcr) 112e455b69dSRui Feng { 113e455b69dSRui Feng return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00); 114e455b69dSRui Feng } 115e455b69dSRui Feng 116e455b69dSRui Feng static int rtl8411_turn_off_led(struct rtsx_pcr *pcr) 117e455b69dSRui Feng { 118e455b69dSRui Feng return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01); 119e455b69dSRui Feng } 120e455b69dSRui Feng 121e455b69dSRui Feng static int rtl8411_enable_auto_blink(struct rtsx_pcr *pcr) 122e455b69dSRui Feng { 123e455b69dSRui Feng return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D); 124e455b69dSRui Feng } 125e455b69dSRui Feng 126e455b69dSRui Feng static int rtl8411_disable_auto_blink(struct rtsx_pcr *pcr) 127e455b69dSRui Feng { 128e455b69dSRui Feng return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00); 129e455b69dSRui Feng } 130e455b69dSRui Feng 131e455b69dSRui Feng static int rtl8411_card_power_on(struct rtsx_pcr *pcr, int card) 132e455b69dSRui Feng { 133e455b69dSRui Feng int err; 134e455b69dSRui Feng 135e455b69dSRui Feng rtsx_pci_init_cmd(pcr); 136e455b69dSRui Feng rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, 137e455b69dSRui Feng BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON); 138e455b69dSRui Feng rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CTL, 139e455b69dSRui Feng BPP_LDO_POWB, BPP_LDO_SUSPEND); 140e455b69dSRui Feng err = rtsx_pci_send_cmd(pcr, 100); 141e455b69dSRui Feng if (err < 0) 142e455b69dSRui Feng return err; 143e455b69dSRui Feng 144e455b69dSRui Feng /* To avoid too large in-rush current */ 145e455b69dSRui Feng udelay(150); 146e455b69dSRui Feng 147e455b69dSRui Feng err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, 148e455b69dSRui Feng BPP_POWER_MASK, BPP_POWER_10_PERCENT_ON); 149e455b69dSRui Feng if (err < 0) 150e455b69dSRui Feng return err; 151e455b69dSRui Feng 152e455b69dSRui Feng udelay(150); 153e455b69dSRui Feng 154e455b69dSRui Feng err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, 155e455b69dSRui Feng BPP_POWER_MASK, BPP_POWER_15_PERCENT_ON); 156e455b69dSRui Feng if (err < 0) 157e455b69dSRui Feng return err; 158e455b69dSRui Feng 159e455b69dSRui Feng udelay(150); 160e455b69dSRui Feng 161e455b69dSRui Feng err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, 162e455b69dSRui Feng BPP_POWER_MASK, BPP_POWER_ON); 163e455b69dSRui Feng if (err < 0) 164e455b69dSRui Feng return err; 165e455b69dSRui Feng 166e455b69dSRui Feng return rtsx_pci_write_register(pcr, LDO_CTL, BPP_LDO_POWB, BPP_LDO_ON); 167e455b69dSRui Feng } 168e455b69dSRui Feng 169e455b69dSRui Feng static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card) 170e455b69dSRui Feng { 171e455b69dSRui Feng int err; 172e455b69dSRui Feng 173e455b69dSRui Feng err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, 174e455b69dSRui Feng BPP_POWER_MASK, BPP_POWER_OFF); 175e455b69dSRui Feng if (err < 0) 176e455b69dSRui Feng return err; 177e455b69dSRui Feng 178e455b69dSRui Feng return rtsx_pci_write_register(pcr, LDO_CTL, 179e455b69dSRui Feng BPP_LDO_POWB, BPP_LDO_SUSPEND); 180e455b69dSRui Feng } 181e455b69dSRui Feng 182e455b69dSRui Feng static int rtl8411_do_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage, 183e455b69dSRui Feng int bpp_tuned18_shift, int bpp_asic_1v8) 184e455b69dSRui Feng { 185e455b69dSRui Feng u8 mask, val; 186e455b69dSRui Feng int err; 187e455b69dSRui Feng 188e455b69dSRui Feng mask = (BPP_REG_TUNED18 << bpp_tuned18_shift) | BPP_PAD_MASK; 189e455b69dSRui Feng if (voltage == OUTPUT_3V3) { 190e455b69dSRui Feng err = rtsx_pci_write_register(pcr, 191e455b69dSRui Feng SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3); 192e455b69dSRui Feng if (err < 0) 193e455b69dSRui Feng return err; 194e455b69dSRui Feng val = (BPP_ASIC_3V3 << bpp_tuned18_shift) | BPP_PAD_3V3; 195e455b69dSRui Feng } else if (voltage == OUTPUT_1V8) { 196e455b69dSRui Feng err = rtsx_pci_write_register(pcr, 197e455b69dSRui Feng SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8); 198e455b69dSRui Feng if (err < 0) 199e455b69dSRui Feng return err; 200e455b69dSRui Feng val = (bpp_asic_1v8 << bpp_tuned18_shift) | BPP_PAD_1V8; 201e455b69dSRui Feng } else { 202e455b69dSRui Feng return -EINVAL; 203e455b69dSRui Feng } 204e455b69dSRui Feng 205e455b69dSRui Feng return rtsx_pci_write_register(pcr, LDO_CTL, mask, val); 206e455b69dSRui Feng } 207e455b69dSRui Feng 208e455b69dSRui Feng static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) 209e455b69dSRui Feng { 210e455b69dSRui Feng return rtl8411_do_switch_output_voltage(pcr, voltage, 211e455b69dSRui Feng BPP_TUNED18_SHIFT_8411, BPP_ASIC_1V8); 212e455b69dSRui Feng } 213e455b69dSRui Feng 214e455b69dSRui Feng static int rtl8402_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) 215e455b69dSRui Feng { 216e455b69dSRui Feng return rtl8411_do_switch_output_voltage(pcr, voltage, 217e455b69dSRui Feng BPP_TUNED18_SHIFT_8402, BPP_ASIC_2V0); 218e455b69dSRui Feng } 219e455b69dSRui Feng 220e455b69dSRui Feng static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr) 221e455b69dSRui Feng { 222e455b69dSRui Feng unsigned int card_exist; 223e455b69dSRui Feng 224e455b69dSRui Feng card_exist = rtsx_pci_readl(pcr, RTSX_BIPR); 225e455b69dSRui Feng card_exist &= CARD_EXIST; 226e455b69dSRui Feng if (!card_exist) { 227e455b69dSRui Feng /* Enable card CD */ 228e455b69dSRui Feng rtsx_pci_write_register(pcr, CD_PAD_CTL, 229e455b69dSRui Feng CD_DISABLE_MASK, CD_ENABLE); 230e455b69dSRui Feng /* Enable card interrupt */ 231e455b69dSRui Feng rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x00); 232e455b69dSRui Feng return 0; 233e455b69dSRui Feng } 234e455b69dSRui Feng 235e455b69dSRui Feng if (hweight32(card_exist) > 1) { 236e455b69dSRui Feng rtsx_pci_write_register(pcr, CARD_PWR_CTL, 237e455b69dSRui Feng BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON); 238e455b69dSRui Feng msleep(100); 239e455b69dSRui Feng 240e455b69dSRui Feng card_exist = rtsx_pci_readl(pcr, RTSX_BIPR); 241e455b69dSRui Feng if (card_exist & MS_EXIST) 242e455b69dSRui Feng card_exist = MS_EXIST; 243e455b69dSRui Feng else if (card_exist & SD_EXIST) 244e455b69dSRui Feng card_exist = SD_EXIST; 245e455b69dSRui Feng else 246e455b69dSRui Feng card_exist = 0; 247e455b69dSRui Feng 248e455b69dSRui Feng rtsx_pci_write_register(pcr, CARD_PWR_CTL, 249e455b69dSRui Feng BPP_POWER_MASK, BPP_POWER_OFF); 250e455b69dSRui Feng 251e455b69dSRui Feng pcr_dbg(pcr, "After CD deglitch, card_exist = 0x%x\n", 252e455b69dSRui Feng card_exist); 253e455b69dSRui Feng } 254e455b69dSRui Feng 255e455b69dSRui Feng if (card_exist & MS_EXIST) { 256e455b69dSRui Feng /* Disable SD interrupt */ 257e455b69dSRui Feng rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x40); 258e455b69dSRui Feng rtsx_pci_write_register(pcr, CD_PAD_CTL, 259e455b69dSRui Feng CD_DISABLE_MASK, MS_CD_EN_ONLY); 260e455b69dSRui Feng } else if (card_exist & SD_EXIST) { 261e455b69dSRui Feng /* Disable MS interrupt */ 262e455b69dSRui Feng rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x80); 263e455b69dSRui Feng rtsx_pci_write_register(pcr, CD_PAD_CTL, 264e455b69dSRui Feng CD_DISABLE_MASK, SD_CD_EN_ONLY); 265e455b69dSRui Feng } 266e455b69dSRui Feng 267e455b69dSRui Feng return card_exist; 268e455b69dSRui Feng } 269e455b69dSRui Feng 270e455b69dSRui Feng static int rtl8411_conv_clk_and_div_n(int input, int dir) 271e455b69dSRui Feng { 272e455b69dSRui Feng int output; 273e455b69dSRui Feng 274e455b69dSRui Feng if (dir == CLK_TO_DIV_N) 275e455b69dSRui Feng output = input * 4 / 5 - 2; 276e455b69dSRui Feng else 277e455b69dSRui Feng output = (input + 2) * 5 / 4; 278e455b69dSRui Feng 279e455b69dSRui Feng return output; 280e455b69dSRui Feng } 281e455b69dSRui Feng 282e455b69dSRui Feng static const struct pcr_ops rtl8411_pcr_ops = { 283e455b69dSRui Feng .fetch_vendor_settings = rtl8411_fetch_vendor_settings, 284e455b69dSRui Feng .extra_init_hw = rtl8411_extra_init_hw, 285e455b69dSRui Feng .optimize_phy = NULL, 286e455b69dSRui Feng .turn_on_led = rtl8411_turn_on_led, 287e455b69dSRui Feng .turn_off_led = rtl8411_turn_off_led, 288e455b69dSRui Feng .enable_auto_blink = rtl8411_enable_auto_blink, 289e455b69dSRui Feng .disable_auto_blink = rtl8411_disable_auto_blink, 290e455b69dSRui Feng .card_power_on = rtl8411_card_power_on, 291e455b69dSRui Feng .card_power_off = rtl8411_card_power_off, 292e455b69dSRui Feng .switch_output_voltage = rtl8411_switch_output_voltage, 293e455b69dSRui Feng .cd_deglitch = rtl8411_cd_deglitch, 294e455b69dSRui Feng .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, 295e455b69dSRui Feng .force_power_down = rtl8411_force_power_down, 296e455b69dSRui Feng }; 297e455b69dSRui Feng 298e455b69dSRui Feng static const struct pcr_ops rtl8402_pcr_ops = { 299e455b69dSRui Feng .fetch_vendor_settings = rtl8411_fetch_vendor_settings, 300e455b69dSRui Feng .extra_init_hw = rtl8411_extra_init_hw, 301e455b69dSRui Feng .optimize_phy = NULL, 302e455b69dSRui Feng .turn_on_led = rtl8411_turn_on_led, 303e455b69dSRui Feng .turn_off_led = rtl8411_turn_off_led, 304e455b69dSRui Feng .enable_auto_blink = rtl8411_enable_auto_blink, 305e455b69dSRui Feng .disable_auto_blink = rtl8411_disable_auto_blink, 306e455b69dSRui Feng .card_power_on = rtl8411_card_power_on, 307e455b69dSRui Feng .card_power_off = rtl8411_card_power_off, 308e455b69dSRui Feng .switch_output_voltage = rtl8402_switch_output_voltage, 309e455b69dSRui Feng .cd_deglitch = rtl8411_cd_deglitch, 310e455b69dSRui Feng .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, 311e455b69dSRui Feng .force_power_down = rtl8411_force_power_down, 312e455b69dSRui Feng }; 313e455b69dSRui Feng 314e455b69dSRui Feng static const struct pcr_ops rtl8411b_pcr_ops = { 315e455b69dSRui Feng .fetch_vendor_settings = rtl8411b_fetch_vendor_settings, 316e455b69dSRui Feng .extra_init_hw = rtl8411b_extra_init_hw, 317e455b69dSRui Feng .optimize_phy = NULL, 318e455b69dSRui Feng .turn_on_led = rtl8411_turn_on_led, 319e455b69dSRui Feng .turn_off_led = rtl8411_turn_off_led, 320e455b69dSRui Feng .enable_auto_blink = rtl8411_enable_auto_blink, 321e455b69dSRui Feng .disable_auto_blink = rtl8411_disable_auto_blink, 322e455b69dSRui Feng .card_power_on = rtl8411_card_power_on, 323e455b69dSRui Feng .card_power_off = rtl8411_card_power_off, 324e455b69dSRui Feng .switch_output_voltage = rtl8411_switch_output_voltage, 325e455b69dSRui Feng .cd_deglitch = rtl8411_cd_deglitch, 326e455b69dSRui Feng .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, 327e455b69dSRui Feng .force_power_down = rtl8411_force_power_down, 328e455b69dSRui Feng }; 329e455b69dSRui Feng 330e455b69dSRui Feng /* SD Pull Control Enable: 331e455b69dSRui Feng * SD_DAT[3:0] ==> pull up 332e455b69dSRui Feng * SD_CD ==> pull up 333e455b69dSRui Feng * SD_WP ==> pull up 334e455b69dSRui Feng * SD_CMD ==> pull up 335e455b69dSRui Feng * SD_CLK ==> pull down 336e455b69dSRui Feng */ 337e455b69dSRui Feng static const u32 rtl8411_sd_pull_ctl_enable_tbl[] = { 338e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA), 339e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), 340e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL3, 0xA9), 341e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09), 342e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL5, 0x09), 343e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04), 344e455b69dSRui Feng 0, 345e455b69dSRui Feng }; 346e455b69dSRui Feng 347e455b69dSRui Feng /* SD Pull Control Disable: 348e455b69dSRui Feng * SD_DAT[3:0] ==> pull down 349e455b69dSRui Feng * SD_CD ==> pull up 350e455b69dSRui Feng * SD_WP ==> pull down 351e455b69dSRui Feng * SD_CMD ==> pull down 352e455b69dSRui Feng * SD_CLK ==> pull down 353e455b69dSRui Feng */ 354e455b69dSRui Feng static const u32 rtl8411_sd_pull_ctl_disable_tbl[] = { 355e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 356e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 357e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95), 358e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09), 359e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05), 360e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04), 361e455b69dSRui Feng 0, 362e455b69dSRui Feng }; 363e455b69dSRui Feng 364e455b69dSRui Feng /* MS Pull Control Enable: 365e455b69dSRui Feng * MS CD ==> pull up 366e455b69dSRui Feng * others ==> pull down 367e455b69dSRui Feng */ 368e455b69dSRui Feng static const u32 rtl8411_ms_pull_ctl_enable_tbl[] = { 369e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 370e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 371e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95), 372e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05), 373e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05), 374e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04), 375e455b69dSRui Feng 0, 376e455b69dSRui Feng }; 377e455b69dSRui Feng 378e455b69dSRui Feng /* MS Pull Control Disable: 379e455b69dSRui Feng * MS CD ==> pull up 380e455b69dSRui Feng * others ==> pull down 381e455b69dSRui Feng */ 382e455b69dSRui Feng static const u32 rtl8411_ms_pull_ctl_disable_tbl[] = { 383e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 384e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 385e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95), 386e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09), 387e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05), 388e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04), 389e455b69dSRui Feng 0, 390e455b69dSRui Feng }; 391e455b69dSRui Feng 392e455b69dSRui Feng static const u32 rtl8411b_qfn64_sd_pull_ctl_enable_tbl[] = { 393e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA), 394e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), 395e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL3, 0x09 | 0xD0), 396e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50), 397e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), 398e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 399e455b69dSRui Feng 0, 400e455b69dSRui Feng }; 401e455b69dSRui Feng 402e455b69dSRui Feng static const u32 rtl8411b_qfn48_sd_pull_ctl_enable_tbl[] = { 403e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), 404e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL3, 0x69 | 0x90), 405e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL6, 0x08 | 0x11), 406e455b69dSRui Feng 0, 407e455b69dSRui Feng }; 408e455b69dSRui Feng 409e455b69dSRui Feng static const u32 rtl8411b_qfn64_sd_pull_ctl_disable_tbl[] = { 410e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 411e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 412e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0), 413e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50), 414e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), 415e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 416e455b69dSRui Feng 0, 417e455b69dSRui Feng }; 418e455b69dSRui Feng 419e455b69dSRui Feng static const u32 rtl8411b_qfn48_sd_pull_ctl_disable_tbl[] = { 420e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 421e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90), 422e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 423e455b69dSRui Feng 0, 424e455b69dSRui Feng }; 425e455b69dSRui Feng 426e455b69dSRui Feng static const u32 rtl8411b_qfn64_ms_pull_ctl_enable_tbl[] = { 427e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 428e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 429e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0), 430e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05 | 0x50), 431e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), 432e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 433e455b69dSRui Feng 0, 434e455b69dSRui Feng }; 435e455b69dSRui Feng 436e455b69dSRui Feng static const u32 rtl8411b_qfn48_ms_pull_ctl_enable_tbl[] = { 437e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 438e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90), 439e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 440e455b69dSRui Feng 0, 441e455b69dSRui Feng }; 442e455b69dSRui Feng 443e455b69dSRui Feng static const u32 rtl8411b_qfn64_ms_pull_ctl_disable_tbl[] = { 444e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 445e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 446e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0), 447e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50), 448e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50), 449e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 450e455b69dSRui Feng 0, 451e455b69dSRui Feng }; 452e455b69dSRui Feng 453e455b69dSRui Feng static const u32 rtl8411b_qfn48_ms_pull_ctl_disable_tbl[] = { 454e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 455e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90), 456e455b69dSRui Feng RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11), 457e455b69dSRui Feng 0, 458e455b69dSRui Feng }; 459e455b69dSRui Feng 460e455b69dSRui Feng static void rtl8411_init_common_params(struct rtsx_pcr *pcr) 461e455b69dSRui Feng { 462e455b69dSRui Feng pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; 463e455b69dSRui Feng pcr->num_slots = 2; 464e455b69dSRui Feng pcr->flags = 0; 465e455b69dSRui Feng pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT; 466e455b69dSRui Feng pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B; 467e455b69dSRui Feng pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D; 468e455b69dSRui Feng pcr->aspm_en = ASPM_L1_EN; 469e455b69dSRui Feng pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14); 470e455b69dSRui Feng pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10); 471e455b69dSRui Feng pcr->ic_version = rtl8411_get_ic_version(pcr); 472e455b69dSRui Feng } 473e455b69dSRui Feng 474e455b69dSRui Feng void rtl8411_init_params(struct rtsx_pcr *pcr) 475e455b69dSRui Feng { 476e455b69dSRui Feng rtl8411_init_common_params(pcr); 477e455b69dSRui Feng pcr->ops = &rtl8411_pcr_ops; 478e455b69dSRui Feng set_pull_ctrl_tables(pcr, rtl8411); 479e455b69dSRui Feng } 480e455b69dSRui Feng 481e455b69dSRui Feng void rtl8411b_init_params(struct rtsx_pcr *pcr) 482e455b69dSRui Feng { 483e455b69dSRui Feng rtl8411_init_common_params(pcr); 484e455b69dSRui Feng pcr->ops = &rtl8411b_pcr_ops; 485e455b69dSRui Feng if (rtl8411b_is_qfn48(pcr)) 486e455b69dSRui Feng set_pull_ctrl_tables(pcr, rtl8411b_qfn48); 487e455b69dSRui Feng else 488e455b69dSRui Feng set_pull_ctrl_tables(pcr, rtl8411b_qfn64); 489e455b69dSRui Feng } 490e455b69dSRui Feng 491e455b69dSRui Feng void rtl8402_init_params(struct rtsx_pcr *pcr) 492e455b69dSRui Feng { 493e455b69dSRui Feng rtl8411_init_common_params(pcr); 494e455b69dSRui Feng pcr->ops = &rtl8402_pcr_ops; 495e455b69dSRui Feng set_pull_ctrl_tables(pcr, rtl8411); 496e455b69dSRui Feng } 497