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