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, ®1);
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, ®3);
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, ®);
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