14c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG/* Driver for Realtek PCI-Express card reader 24c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * 34c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. 44c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * 54c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * This program is free software; you can redistribute it and/or modify it 64c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * under the terms of the GNU General Public License as published by the 74c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * Free Software Foundation; either version 2, or (at your option) any 84c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * later version. 94c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * 104c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * This program is distributed in the hope that it will be useful, but 114c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * WITHOUT ANY WARRANTY; without even the implied warranty of 124c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 134c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * General Public License for more details. 144c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * 154c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * You should have received a copy of the GNU General Public License along 164c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * with this program; if not, see <http://www.gnu.org/licenses/>. 174c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * 184c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * Author: 194c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * Wei WANG <wei_wang@realsil.com.cn> 204c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG */ 214c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 224c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG#include <linux/module.h> 234c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG#include <linux/delay.h> 244c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG#include <linux/mfd/rtsx_pci.h> 254c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 264c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG#include "rtsx_pcr.h" 274c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 284c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic u8 rts5249_get_ic_version(struct rtsx_pcr *pcr) 294c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG{ 304c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG u8 val; 314c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 324c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val); 334c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return val & 0x0F; 344c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG} 354c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 36773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANGstatic void rts5249_fill_driving(struct rtsx_pcr *pcr, u8 voltage) 37773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG{ 38773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG u8 driving_3v3[4][3] = { 39773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG {0x11, 0x11, 0x11}, 40773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG {0x55, 0x55, 0x5C}, 41773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG {0x99, 0x99, 0x92}, 42773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG {0x99, 0x99, 0x92}, 43773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG }; 44773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG u8 driving_1v8[4][3] = { 45773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG {0x3C, 0x3C, 0x3C}, 46773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG {0xB3, 0xB3, 0xB3}, 47773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG {0xFE, 0xFE, 0xFE}, 48773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG {0xC4, 0xC4, 0xC4}, 49773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG }; 50773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG u8 (*driving)[3], drive_sel; 51773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG 52773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG if (voltage == OUTPUT_3V3) { 53773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG driving = driving_3v3; 54773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG drive_sel = pcr->sd30_drive_sel_3v3; 55773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG } else { 56773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG driving = driving_1v8; 57773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG drive_sel = pcr->sd30_drive_sel_1v8; 58773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG } 59773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG 60773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL, 61773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG 0xFF, driving[drive_sel][0]); 62773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL, 63773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG 0xFF, driving[drive_sel][1]); 64773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL, 65773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG 0xFF, driving[drive_sel][2]); 66773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG} 67773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG 68773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANGstatic void rts5249_fetch_vendor_settings(struct rtsx_pcr *pcr) 69773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG{ 70773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG u32 reg; 71773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG 72773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); 73773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); 74773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG 75773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG if (!rtsx_vendor_setting_valid(reg)) 76773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG return; 77773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG 78773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG pcr->aspm_en = rtsx_reg_to_aspm(reg); 79773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg); 80773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG pcr->card_drive_sel &= 0x3F; 81773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg); 82773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG 83773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®); 84773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg); 85773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg); 86773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG if (rtsx_reg_check_reverse_socket(reg)) 87773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG pcr->flags |= PCR_REVERSE_SOCKET; 88773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG} 89773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG 90eb891c65c9c87e55f728d95bcc514dea337aed12Wei WANGstatic void rts5249_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) 915947c167d145f32d4475d647a87e2af2699efe45Wei WANG{ 925947c167d145f32d4475d647a87e2af2699efe45Wei WANG /* Set relink_time to 0 */ 935947c167d145f32d4475d647a87e2af2699efe45Wei WANG rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0); 945947c167d145f32d4475d647a87e2af2699efe45Wei WANG rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0); 955947c167d145f32d4475d647a87e2af2699efe45Wei WANG rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0); 965947c167d145f32d4475d647a87e2af2699efe45Wei WANG 97eb891c65c9c87e55f728d95bcc514dea337aed12Wei WANG if (pm_state == HOST_ENTER_S3) 98eb891c65c9c87e55f728d95bcc514dea337aed12Wei WANG rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10); 99eb891c65c9c87e55f728d95bcc514dea337aed12Wei WANG 1005947c167d145f32d4475d647a87e2af2699efe45Wei WANG rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03); 1015947c167d145f32d4475d647a87e2af2699efe45Wei WANG} 1025947c167d145f32d4475d647a87e2af2699efe45Wei WANG 1034c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic int rts5249_extra_init_hw(struct rtsx_pcr *pcr) 1044c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG{ 1054c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_init_cmd(pcr); 1064c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 1074c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG /* Configure GPIO as output */ 1084c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02); 1097140812c4a3676e834bc2ed587be441afba04e18Wei WANG /* Reset ASPM state to default value */ 1107140812c4a3676e834bc2ed587be441afba04e18Wei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0); 1114c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG /* Switch LDO3318 source from DV33 to card_3v3 */ 1124c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00); 1134c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01); 1144c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG /* LED shine disabled, set initial shine cycle period */ 1154c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02); 116773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG /* Configure driving */ 117773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG rts5249_fill_driving(pcr, OUTPUT_3V3); 118773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG if (pcr->flags & PCR_REVERSE_SOCKET) 119773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 120773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG AUTOLOAD_CFG_BASE + 3, 0xB0, 0xB0); 121773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG else 122773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, 123773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG AUTOLOAD_CFG_BASE + 3, 0xB0, 0x80); 124eb891c65c9c87e55f728d95bcc514dea337aed12Wei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00); 1254c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 1264c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return rtsx_pci_send_cmd(pcr, 100); 1274c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG} 1284c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 1294c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic int rts5249_optimize_phy(struct rtsx_pcr *pcr) 1304c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG{ 1314c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG int err; 1324c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 13326b818511c6562ce372566c219a2ef1afea35fe6Wei WANG err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV, 13426b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_REG_REV_RESV | PHY_REG_REV_RXIDLE_LATCHED | 13526b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_REG_REV_P1_EN | PHY_REG_REV_RXIDLE_EN | 13626b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_REG_REV_RX_PWST | PHY_REG_REV_CLKREQ_DLY_TIMER_1_0 | 13726b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_REG_REV_STOP_CLKRD | PHY_REG_REV_STOP_CLKWR); 1384c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG if (err < 0) 1394c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return err; 1404c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 1414c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG msleep(1); 1424c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 14326b818511c6562ce372566c219a2ef1afea35fe6Wei WANG err = rtsx_pci_write_phy_register(pcr, PHY_BPCR, 14426b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_BPCR_IBRXSEL | PHY_BPCR_IBTXSEL | 14526b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_BPCR_IB_FILTER | PHY_BPCR_CMIRROR_EN); 14626b818511c6562ce372566c219a2ef1afea35fe6Wei WANG if (err < 0) 14726b818511c6562ce372566c219a2ef1afea35fe6Wei WANG return err; 14826b818511c6562ce372566c219a2ef1afea35fe6Wei WANG err = rtsx_pci_write_phy_register(pcr, PHY_PCR, 14926b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_PCR_FORCE_CODE | PHY_PCR_OOBS_CALI_50 | 15026b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_PCR_OOBS_VCM_08 | PHY_PCR_OOBS_SEN_90 | 15126b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_PCR_RSSI_EN); 15226b818511c6562ce372566c219a2ef1afea35fe6Wei WANG if (err < 0) 15326b818511c6562ce372566c219a2ef1afea35fe6Wei WANG return err; 15426b818511c6562ce372566c219a2ef1afea35fe6Wei WANG err = rtsx_pci_write_phy_register(pcr, PHY_RCR2, 15526b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_RCR2_EMPHASE_EN | PHY_RCR2_NADJR | 15626b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_RCR2_CDR_CP_10 | PHY_RCR2_CDR_SR_2 | 15726b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_RCR2_FREQSEL_12 | PHY_RCR2_CPADJEN | 15826b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_RCR2_CDR_SC_8 | PHY_RCR2_CALIB_LATE); 15926b818511c6562ce372566c219a2ef1afea35fe6Wei WANG if (err < 0) 16026b818511c6562ce372566c219a2ef1afea35fe6Wei WANG return err; 16126b818511c6562ce372566c219a2ef1afea35fe6Wei WANG err = rtsx_pci_write_phy_register(pcr, PHY_FLD4, 16226b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_FLD4_FLDEN_SEL | PHY_FLD4_REQ_REF | 16326b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_FLD4_RXAMP_OFF | PHY_FLD4_REQ_ADDA | 16426b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_FLD4_BER_COUNT | PHY_FLD4_BER_TIMER | 16526b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_FLD4_BER_CHK_EN); 16626b818511c6562ce372566c219a2ef1afea35fe6Wei WANG if (err < 0) 16726b818511c6562ce372566c219a2ef1afea35fe6Wei WANG return err; 16826b818511c6562ce372566c219a2ef1afea35fe6Wei WANG err = rtsx_pci_write_phy_register(pcr, PHY_RDR, PHY_RDR_RXDSEL_1_9); 16926b818511c6562ce372566c219a2ef1afea35fe6Wei WANG if (err < 0) 17026b818511c6562ce372566c219a2ef1afea35fe6Wei WANG return err; 17126b818511c6562ce372566c219a2ef1afea35fe6Wei WANG err = rtsx_pci_write_phy_register(pcr, PHY_RCR1, 17226b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_RCR1_ADP_TIME | PHY_RCR1_VCO_COARSE); 17326b818511c6562ce372566c219a2ef1afea35fe6Wei WANG if (err < 0) 17426b818511c6562ce372566c219a2ef1afea35fe6Wei WANG return err; 17526b818511c6562ce372566c219a2ef1afea35fe6Wei WANG err = rtsx_pci_write_phy_register(pcr, PHY_FLD3, 17626b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_FLD3_TIMER_4 | PHY_FLD3_TIMER_6 | 17726b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_FLD3_RXDELINK); 17826b818511c6562ce372566c219a2ef1afea35fe6Wei WANG if (err < 0) 17926b818511c6562ce372566c219a2ef1afea35fe6Wei WANG return err; 18026b818511c6562ce372566c219a2ef1afea35fe6Wei WANG return rtsx_pci_write_phy_register(pcr, PHY_TUNE, 18126b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_TUNE_TUNEREF_1_0 | PHY_TUNE_VBGSEL_1252 | 18226b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_TUNE_SDBUS_33 | PHY_TUNE_TUNED18 | 18326b818511c6562ce372566c219a2ef1afea35fe6Wei WANG PHY_TUNE_TUNED12); 1844c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG} 1854c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 1864c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic int rts5249_turn_on_led(struct rtsx_pcr *pcr) 1874c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG{ 1884c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02); 1894c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG} 1904c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 1914c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic int rts5249_turn_off_led(struct rtsx_pcr *pcr) 1924c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG{ 1934c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00); 1944c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG} 1954c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 1964c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic int rts5249_enable_auto_blink(struct rtsx_pcr *pcr) 1974c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG{ 1984c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08); 1994c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG} 2004c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2014c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic int rts5249_disable_auto_blink(struct rtsx_pcr *pcr) 2024c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG{ 2034c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00); 2044c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG} 2054c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2064c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic int rts5249_card_power_on(struct rtsx_pcr *pcr, int card) 2074c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG{ 2084c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG int err; 2094c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2104c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_init_cmd(pcr); 2114c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, 2124c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG SD_POWER_MASK, SD_VCC_PARTIAL_POWER_ON); 2134c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, 2144c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG LDO3318_PWR_MASK, 0x02); 2154c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG err = rtsx_pci_send_cmd(pcr, 100); 2164c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG if (err < 0) 2174c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return err; 2184c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2194c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG msleep(5); 2204c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2214c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_init_cmd(pcr); 2224c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, 2234c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG SD_POWER_MASK, SD_VCC_POWER_ON); 2244c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, 2254c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG LDO3318_PWR_MASK, 0x06); 2264c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG err = rtsx_pci_send_cmd(pcr, 100); 2274c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG if (err < 0) 2284c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return err; 2294c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2304c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return 0; 2314c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG} 2324c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2334c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic int rts5249_card_power_off(struct rtsx_pcr *pcr, int card) 2344c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG{ 2354c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_init_cmd(pcr); 2364c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, 2374c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG SD_POWER_MASK, SD_POWER_OFF); 2384c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, 2394c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG LDO3318_PWR_MASK, 0x00); 2404c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return rtsx_pci_send_cmd(pcr, 100); 2414c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG} 2424c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2434c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) 2444c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG{ 2454c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG int err; 2464c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2474c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG if (voltage == OUTPUT_3V3) { 2484c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24); 2494c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG if (err < 0) 2504c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return err; 2514c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG } else if (voltage == OUTPUT_1V8) { 2524c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02); 2534c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG if (err < 0) 2544c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return err; 2554c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24); 2564c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG if (err < 0) 2574c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return err; 2584c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG } else { 2594c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return -EINVAL; 2604c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG } 2614c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2624c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG /* set pad drive */ 2634c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG rtsx_pci_init_cmd(pcr); 264773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG rts5249_fill_driving(pcr, voltage); 2654c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG return rtsx_pci_send_cmd(pcr, 100); 2664c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG} 2674c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2684c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic const struct pcr_ops rts5249_pcr_ops = { 269773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG .fetch_vendor_settings = rts5249_fetch_vendor_settings, 2704c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG .extra_init_hw = rts5249_extra_init_hw, 2714c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG .optimize_phy = rts5249_optimize_phy, 2724c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG .turn_on_led = rts5249_turn_on_led, 2734c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG .turn_off_led = rts5249_turn_off_led, 2744c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG .enable_auto_blink = rts5249_enable_auto_blink, 2754c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG .disable_auto_blink = rts5249_disable_auto_blink, 2764c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG .card_power_on = rts5249_card_power_on, 2774c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG .card_power_off = rts5249_card_power_off, 2784c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG .switch_output_voltage = rts5249_switch_output_voltage, 2795947c167d145f32d4475d647a87e2af2699efe45Wei WANG .force_power_down = rts5249_force_power_down, 2804c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG}; 2814c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2824c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG/* SD Pull Control Enable: 2834c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * SD_DAT[3:0] ==> pull up 2844c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * SD_CD ==> pull up 2854c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * SD_WP ==> pull up 2864c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * SD_CMD ==> pull up 2874c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * SD_CLK ==> pull down 2884c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG */ 2894c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic const u32 rts5249_sd_pull_ctl_enable_tbl[] = { 2904c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66), 2914c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), 2924c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9), 2934c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL4, 0xAA), 2944c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 0, 2954c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG}; 2964c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 2974c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG/* SD Pull Control Disable: 2984c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * SD_DAT[3:0] ==> pull down 2994c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * SD_CD ==> pull up 3004c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * SD_WP ==> pull down 3014c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * SD_CMD ==> pull down 3024c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * SD_CLK ==> pull down 3034c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG */ 3044c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic const u32 rts5249_sd_pull_ctl_disable_tbl[] = { 3054c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66), 3064c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 3074c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5), 3084c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55), 3094c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 0, 3104c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG}; 3114c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 3124c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG/* MS Pull Control Enable: 3134c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * MS CD ==> pull up 3144c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * others ==> pull down 3154c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG */ 3164c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic const u32 rts5249_ms_pull_ctl_enable_tbl[] = { 3174c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55), 3184c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55), 3194c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15), 3204c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 0, 3214c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG}; 3224c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 3234c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG/* MS Pull Control Disable: 3244c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * MS CD ==> pull up 3254c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG * others ==> pull down 3264c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG */ 3274c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGstatic const u32 rts5249_ms_pull_ctl_disable_tbl[] = { 3284c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55), 3294c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55), 3304c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15), 3314c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 0, 3324c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG}; 3334c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 3344c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANGvoid rts5249_init_params(struct rtsx_pcr *pcr) 3354c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG{ 3364c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; 3374c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG pcr->num_slots = 2; 3384c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG pcr->ops = &rts5249_pcr_ops; 3394c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG 340773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG pcr->flags = 0; 341773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT; 342773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_C; 343773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B; 344773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG pcr->aspm_en = ASPM_L1_EN; 34584d72f9cc21d6e41c620dd34b8248734cd02d995Wei WANG pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16); 34684d72f9cc21d6e41c620dd34b8248734cd02d995Wei WANG pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5); 347773ccdfd9cc6f9bf8ec75a59fa742d7a663a5903Wei WANG 3484c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG pcr->ic_version = rts5249_get_ic_version(pcr); 3494c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl; 3504c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG pcr->sd_pull_ctl_disable_tbl = rts5249_sd_pull_ctl_disable_tbl; 3514c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG pcr->ms_pull_ctl_enable_tbl = rts5249_ms_pull_ctl_enable_tbl; 3524c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG pcr->ms_pull_ctl_disable_tbl = rts5249_ms_pull_ctl_disable_tbl; 3534c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbbWei WANG} 354