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