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