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