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, &reg);
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, &reg);
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