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