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