Commit | Line | Data |
---|---|---|
5da4e04a RF |
1 | /* Driver for Realtek PCI-Express card reader |
2 | * | |
3 | * Copyright(c) 2016-2017 Realtek Semiconductor Corp. All rights reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the | |
7 | * Free Software Foundation; either version 2, or (at your option) any | |
8 | * later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License along | |
16 | * with this program; if not, see <http://www.gnu.org/licenses/>. | |
17 | * | |
18 | * Author: | |
19 | * Steven FENG <steven_feng@realsil.com.cn> | |
20 | * Rui FENG <rui_feng@realsil.com.cn> | |
21 | * Wei WANG <wei_wang@realsil.com.cn> | |
22 | */ | |
23 | ||
24 | #include <linux/module.h> | |
25 | #include <linux/delay.h> | |
26 | #include <linux/rtsx_pci.h> | |
27 | ||
28 | #include "rts5260.h" | |
29 | #include "rtsx_pcr.h" | |
30 | ||
31 | static u8 rts5260_get_ic_version(struct rtsx_pcr *pcr) | |
32 | { | |
33 | u8 val; | |
34 | ||
35 | rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val); | |
36 | return val & IC_VERSION_MASK; | |
37 | } | |
38 | ||
39 | static void rts5260_fill_driving(struct rtsx_pcr *pcr, u8 voltage) | |
40 | { | |
41 | u8 driving_3v3[6][3] = { | |
42 | {0x94, 0x94, 0x94}, | |
43 | {0x11, 0x11, 0x18}, | |
44 | {0x55, 0x55, 0x5C}, | |
45 | {0x94, 0x94, 0x94}, | |
46 | {0x94, 0x94, 0x94}, | |
47 | {0xFF, 0xFF, 0xFF}, | |
48 | }; | |
49 | u8 driving_1v8[6][3] = { | |
50 | {0x9A, 0x89, 0x89}, | |
51 | {0xC4, 0xC4, 0xC4}, | |
52 | {0x3C, 0x3C, 0x3C}, | |
53 | {0x9B, 0x99, 0x99}, | |
54 | {0x9A, 0x89, 0x89}, | |
55 | {0xFE, 0xFE, 0xFE}, | |
56 | }; | |
57 | u8 (*driving)[3], drive_sel; | |
58 | ||
59 | if (voltage == OUTPUT_3V3) { | |
60 | driving = driving_3v3; | |
61 | drive_sel = pcr->sd30_drive_sel_3v3; | |
62 | } else { | |
63 | driving = driving_1v8; | |
64 | drive_sel = pcr->sd30_drive_sel_1v8; | |
65 | } | |
66 | ||
bede03a5 | 67 | rtsx_pci_write_register(pcr, SD30_CLK_DRIVE_SEL, |
5da4e04a | 68 | 0xFF, driving[drive_sel][0]); |
bede03a5 R |
69 | |
70 | rtsx_pci_write_register(pcr, SD30_CMD_DRIVE_SEL, | |
5da4e04a | 71 | 0xFF, driving[drive_sel][1]); |
bede03a5 R |
72 | |
73 | rtsx_pci_write_register(pcr, SD30_CMD_DRIVE_SEL, | |
5da4e04a RF |
74 | 0xFF, driving[drive_sel][2]); |
75 | } | |
76 | ||
77 | static void rtsx_base_fetch_vendor_settings(struct rtsx_pcr *pcr) | |
78 | { | |
79 | u32 reg; | |
80 | ||
81 | rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, ®); | |
82 | pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg); | |
83 | ||
84 | if (!rtsx_vendor_setting_valid(reg)) { | |
85 | pcr_dbg(pcr, "skip fetch vendor setting\n"); | |
86 | return; | |
87 | } | |
88 | ||
89 | pcr->aspm_en = rtsx_reg_to_aspm(reg); | |
90 | pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg); | |
91 | pcr->card_drive_sel &= 0x3F; | |
92 | pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg); | |
93 | ||
94 | rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, ®); | |
95 | pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg); | |
96 | pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg); | |
97 | if (rtsx_reg_check_reverse_socket(reg)) | |
98 | pcr->flags |= PCR_REVERSE_SOCKET; | |
99 | } | |
100 | ||
101 | static void rtsx_base_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) | |
102 | { | |
103 | /* Set relink_time to 0 */ | |
104 | rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, MASK_8_BIT_DEF, 0); | |
105 | rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, MASK_8_BIT_DEF, 0); | |
106 | rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, | |
107 | RELINK_TIME_MASK, 0); | |
108 | ||
109 | if (pm_state == HOST_ENTER_S3) | |
110 | rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, | |
111 | D3_DELINK_MODE_EN, D3_DELINK_MODE_EN); | |
112 | ||
113 | rtsx_pci_write_register(pcr, FPDCTL, ALL_POWER_DOWN, ALL_POWER_DOWN); | |
114 | } | |
115 | ||
116 | static int rtsx_base_enable_auto_blink(struct rtsx_pcr *pcr) | |
117 | { | |
118 | return rtsx_pci_write_register(pcr, OLT_LED_CTL, | |
119 | LED_SHINE_MASK, LED_SHINE_EN); | |
120 | } | |
121 | ||
122 | static int rtsx_base_disable_auto_blink(struct rtsx_pcr *pcr) | |
123 | { | |
124 | return rtsx_pci_write_register(pcr, OLT_LED_CTL, | |
125 | LED_SHINE_MASK, LED_SHINE_DISABLE); | |
126 | } | |
127 | ||
128 | static int rts5260_turn_on_led(struct rtsx_pcr *pcr) | |
129 | { | |
130 | return rtsx_pci_write_register(pcr, RTS5260_REG_GPIO_CTL0, | |
131 | RTS5260_REG_GPIO_MASK, RTS5260_REG_GPIO_ON); | |
132 | } | |
133 | ||
134 | static int rts5260_turn_off_led(struct rtsx_pcr *pcr) | |
135 | { | |
136 | return rtsx_pci_write_register(pcr, RTS5260_REG_GPIO_CTL0, | |
137 | RTS5260_REG_GPIO_MASK, RTS5260_REG_GPIO_OFF); | |
138 | } | |
139 | ||
140 | /* SD Pull Control Enable: | |
141 | * SD_DAT[3:0] ==> pull up | |
142 | * SD_CD ==> pull up | |
143 | * SD_WP ==> pull up | |
144 | * SD_CMD ==> pull up | |
145 | * SD_CLK ==> pull down | |
146 | */ | |
147 | static const u32 rts5260_sd_pull_ctl_enable_tbl[] = { | |
148 | RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66), | |
149 | RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), | |
150 | RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9), | |
151 | RTSX_REG_PAIR(CARD_PULL_CTL4, 0xAA), | |
152 | 0, | |
153 | }; | |
154 | ||
155 | /* SD Pull Control Disable: | |
156 | * SD_DAT[3:0] ==> pull down | |
157 | * SD_CD ==> pull up | |
158 | * SD_WP ==> pull down | |
159 | * SD_CMD ==> pull down | |
160 | * SD_CLK ==> pull down | |
161 | */ | |
162 | static const u32 rts5260_sd_pull_ctl_disable_tbl[] = { | |
163 | RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66), | |
164 | RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), | |
165 | RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5), | |
166 | RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55), | |
167 | 0, | |
168 | }; | |
169 | ||
170 | /* MS Pull Control Enable: | |
171 | * MS CD ==> pull up | |
172 | * others ==> pull down | |
173 | */ | |
174 | static const u32 rts5260_ms_pull_ctl_enable_tbl[] = { | |
175 | RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55), | |
176 | RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55), | |
177 | RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15), | |
178 | 0, | |
179 | }; | |
180 | ||
181 | /* MS Pull Control Disable: | |
182 | * MS CD ==> pull up | |
183 | * others ==> pull down | |
184 | */ | |
185 | static const u32 rts5260_ms_pull_ctl_disable_tbl[] = { | |
186 | RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55), | |
187 | RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55), | |
188 | RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15), | |
189 | 0, | |
190 | }; | |
191 | ||
192 | static int sd_set_sample_push_timing_sd30(struct rtsx_pcr *pcr) | |
193 | { | |
194 | rtsx_pci_write_register(pcr, SD_CFG1, SD_MODE_SELECT_MASK | |
195 | | SD_ASYNC_FIFO_NOT_RST, SD_30_MODE | SD_ASYNC_FIFO_NOT_RST); | |
196 | rtsx_pci_write_register(pcr, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ); | |
197 | rtsx_pci_write_register(pcr, CARD_CLK_SOURCE, 0xFF, | |
bede03a5 | 198 | CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1); |
5da4e04a RF |
199 | rtsx_pci_write_register(pcr, CLK_CTL, CLK_LOW_FREQ, 0); |
200 | ||
201 | return 0; | |
202 | } | |
203 | ||
204 | static int rts5260_card_power_on(struct rtsx_pcr *pcr, int card) | |
205 | { | |
206 | int err = 0; | |
207 | struct rtsx_cr_option *option = &pcr->option; | |
208 | ||
209 | if (option->ocp_en) | |
210 | rtsx_pci_enable_ocp(pcr); | |
211 | ||
5da4e04a | 212 | |
bede03a5 R |
213 | rtsx_pci_write_register(pcr, LDO_CONFIG2, DV331812_VDD1, DV331812_VDD1); |
214 | rtsx_pci_write_register(pcr, LDO_VCC_CFG0, | |
5da4e04a | 215 | RTS5260_DVCC_TUNE_MASK, RTS5260_DVCC_33); |
5da4e04a | 216 | |
bede03a5 R |
217 | rtsx_pci_write_register(pcr, LDO_VCC_CFG1, LDO_POW_SDVDD1_MASK, |
218 | LDO_POW_SDVDD1_ON); | |
219 | ||
220 | rtsx_pci_write_register(pcr, LDO_CONFIG2, | |
221 | DV331812_POWERON, DV331812_POWERON); | |
5da4e04a RF |
222 | msleep(20); |
223 | ||
224 | if (pcr->extra_caps & EXTRA_CAPS_SD_SDR50 || | |
225 | pcr->extra_caps & EXTRA_CAPS_SD_SDR104) | |
226 | sd_set_sample_push_timing_sd30(pcr); | |
227 | ||
228 | /* Initialize SD_CFG1 register */ | |
229 | rtsx_pci_write_register(pcr, SD_CFG1, 0xFF, | |
230 | SD_CLK_DIVIDE_128 | SD_20_MODE); | |
231 | ||
232 | rtsx_pci_write_register(pcr, SD_SAMPLE_POINT_CTL, | |
233 | 0xFF, SD20_RX_POS_EDGE); | |
234 | rtsx_pci_write_register(pcr, SD_PUSH_POINT_CTL, 0xFF, 0); | |
235 | rtsx_pci_write_register(pcr, CARD_STOP, SD_STOP | SD_CLR_ERR, | |
236 | SD_STOP | SD_CLR_ERR); | |
237 | ||
238 | /* Reset SD_CFG3 register */ | |
239 | rtsx_pci_write_register(pcr, SD_CFG3, SD30_CLK_END_EN, 0); | |
240 | rtsx_pci_write_register(pcr, REG_SD_STOP_SDCLK_CFG, | |
bede03a5 R |
241 | SD30_CLK_STOP_CFG_EN | SD30_CLK_STOP_CFG1 | |
242 | SD30_CLK_STOP_CFG0, 0); | |
5da4e04a RF |
243 | |
244 | rtsx_pci_write_register(pcr, REG_PRE_RW_MODE, EN_INFINITE_MODE, 0); | |
245 | ||
246 | return err; | |
247 | } | |
248 | ||
249 | static int rts5260_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | |
250 | { | |
251 | switch (voltage) { | |
252 | case OUTPUT_3V3: | |
253 | rtsx_pci_write_register(pcr, LDO_CONFIG2, | |
254 | DV331812_VDD1, DV331812_VDD1); | |
255 | rtsx_pci_write_register(pcr, LDO_DV18_CFG, | |
256 | DV331812_MASK, DV331812_33); | |
257 | rtsx_pci_write_register(pcr, SD_PAD_CTL, SD_IO_USING_1V8, 0); | |
258 | break; | |
259 | case OUTPUT_1V8: | |
260 | rtsx_pci_write_register(pcr, LDO_CONFIG2, | |
261 | DV331812_VDD1, DV331812_VDD1); | |
262 | rtsx_pci_write_register(pcr, LDO_DV18_CFG, | |
263 | DV331812_MASK, DV331812_17); | |
264 | rtsx_pci_write_register(pcr, SD_PAD_CTL, SD_IO_USING_1V8, | |
265 | SD_IO_USING_1V8); | |
266 | break; | |
267 | default: | |
268 | return -EINVAL; | |
269 | } | |
270 | ||
271 | /* set pad drive */ | |
5da4e04a | 272 | rts5260_fill_driving(pcr, voltage); |
bede03a5 R |
273 | |
274 | return 0; | |
5da4e04a RF |
275 | } |
276 | ||
277 | static void rts5260_stop_cmd(struct rtsx_pcr *pcr) | |
278 | { | |
279 | rtsx_pci_writel(pcr, RTSX_HCBCTLR, STOP_CMD); | |
280 | rtsx_pci_writel(pcr, RTSX_HDBCTLR, STOP_DMA); | |
281 | rtsx_pci_write_register(pcr, RTS5260_DMA_RST_CTL_0, | |
282 | RTS5260_DMA_RST | RTS5260_ADMA3_RST, | |
283 | RTS5260_DMA_RST | RTS5260_ADMA3_RST); | |
284 | rtsx_pci_write_register(pcr, RBCTL, RB_FLUSH, RB_FLUSH); | |
285 | } | |
286 | ||
287 | static void rts5260_card_before_power_off(struct rtsx_pcr *pcr) | |
288 | { | |
5da4e04a RF |
289 | rts5260_stop_cmd(pcr); |
290 | rts5260_switch_output_voltage(pcr, OUTPUT_3V3); | |
291 | ||
5da4e04a RF |
292 | } |
293 | ||
294 | static int rts5260_card_power_off(struct rtsx_pcr *pcr, int card) | |
295 | { | |
296 | int err = 0; | |
297 | ||
298 | rts5260_card_before_power_off(pcr); | |
bede03a5 | 299 | err = rtsx_pci_write_register(pcr, LDO_VCC_CFG1, |
5da4e04a | 300 | LDO_POW_SDVDD1_MASK, LDO_POW_SDVDD1_OFF); |
bede03a5 | 301 | err = rtsx_pci_write_register(pcr, LDO_CONFIG2, |
5da4e04a | 302 | DV331812_POWERON, DV331812_POWEROFF); |
bede03a5 R |
303 | if (pcr->option.ocp_en) |
304 | rtsx_pci_disable_ocp(pcr); | |
5da4e04a RF |
305 | |
306 | return err; | |
307 | } | |
308 | ||
309 | static void rts5260_init_ocp(struct rtsx_pcr *pcr) | |
310 | { | |
311 | struct rtsx_cr_option *option = &pcr->option; | |
312 | ||
313 | if (option->ocp_en) { | |
314 | u8 mask, val; | |
315 | ||
5da4e04a RF |
316 | |
317 | rtsx_pci_write_register(pcr, RTS5260_DVCC_CTRL, | |
bede03a5 R |
318 | RTS5260_DVCC_OCP_THD_MASK, |
319 | option->sd_800mA_ocp_thd); | |
5da4e04a RF |
320 | |
321 | rtsx_pci_write_register(pcr, RTS5260_DV331812_CFG, | |
bede03a5 R |
322 | RTS5260_DV331812_OCP_THD_MASK, |
323 | RTS5260_DV331812_OCP_THD_270); | |
5da4e04a | 324 | |
bede03a5 | 325 | mask = SD_OCP_GLITCH_MASK; |
5da4e04a RF |
326 | val = pcr->hw_param.ocp_glitch; |
327 | rtsx_pci_write_register(pcr, REG_OCPGLITCH, mask, val); | |
bede03a5 R |
328 | rtsx_pci_write_register(pcr, RTS5260_DVCC_CTRL, |
329 | RTS5260_DVCC_OCP_EN | | |
330 | RTS5260_DVCC_OCP_CL_EN, | |
331 | RTS5260_DVCC_OCP_EN | | |
332 | RTS5260_DVCC_OCP_CL_EN); | |
5da4e04a RF |
333 | |
334 | rtsx_pci_enable_ocp(pcr); | |
335 | } else { | |
336 | rtsx_pci_write_register(pcr, RTS5260_DVCC_CTRL, | |
337 | RTS5260_DVCC_OCP_EN | | |
338 | RTS5260_DVCC_OCP_CL_EN, 0); | |
5da4e04a RF |
339 | } |
340 | } | |
341 | ||
342 | static void rts5260_enable_ocp(struct rtsx_pcr *pcr) | |
343 | { | |
344 | u8 val = 0; | |
345 | ||
5da4e04a | 346 | val = SD_OCP_INT_EN | SD_DETECT_EN; |
5da4e04a | 347 | rtsx_pci_write_register(pcr, REG_OCPCTL, 0xFF, val); |
bede03a5 | 348 | |
5da4e04a RF |
349 | } |
350 | ||
351 | static void rts5260_disable_ocp(struct rtsx_pcr *pcr) | |
352 | { | |
353 | u8 mask = 0; | |
354 | ||
355 | mask = SD_OCP_INT_EN | SD_DETECT_EN; | |
5da4e04a | 356 | rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0); |
5da4e04a | 357 | |
5da4e04a RF |
358 | } |
359 | ||
bede03a5 | 360 | |
75a89805 | 361 | static int rts5260_get_ocpstat(struct rtsx_pcr *pcr, u8 *val) |
5da4e04a RF |
362 | { |
363 | return rtsx_pci_read_register(pcr, REG_OCPSTAT, val); | |
364 | } | |
365 | ||
75a89805 | 366 | static int rts5260_get_ocpstat2(struct rtsx_pcr *pcr, u8 *val) |
5da4e04a RF |
367 | { |
368 | return rtsx_pci_read_register(pcr, REG_DV3318_OCPSTAT, val); | |
369 | } | |
370 | ||
75a89805 | 371 | static void rts5260_clear_ocpstat(struct rtsx_pcr *pcr) |
5da4e04a RF |
372 | { |
373 | u8 mask = 0; | |
374 | u8 val = 0; | |
375 | ||
376 | mask = SD_OCP_INT_CLR | SD_OC_CLR; | |
5da4e04a | 377 | val = SD_OCP_INT_CLR | SD_OC_CLR; |
5da4e04a RF |
378 | |
379 | rtsx_pci_write_register(pcr, REG_OCPCTL, mask, val); | |
380 | rtsx_pci_write_register(pcr, REG_DV3318_OCPCTL, | |
381 | DV3318_OCP_INT_CLR | DV3318_OCP_CLR, | |
382 | DV3318_OCP_INT_CLR | DV3318_OCP_CLR); | |
383 | udelay(10); | |
384 | rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0); | |
385 | rtsx_pci_write_register(pcr, REG_DV3318_OCPCTL, | |
386 | DV3318_OCP_INT_CLR | DV3318_OCP_CLR, 0); | |
387 | } | |
388 | ||
75a89805 | 389 | static void rts5260_process_ocp(struct rtsx_pcr *pcr) |
5da4e04a RF |
390 | { |
391 | if (!pcr->option.ocp_en) | |
392 | return; | |
393 | ||
394 | rtsx_pci_get_ocpstat(pcr, &pcr->ocp_stat); | |
395 | rts5260_get_ocpstat2(pcr, &pcr->ocp_stat2); | |
bede03a5 R |
396 | |
397 | if ((pcr->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) || | |
398 | (pcr->ocp_stat2 & (DV3318_OCP_NOW | DV3318_OCP_EVER))) { | |
399 | rtsx_pci_card_power_off(pcr, RTSX_SD_CARD); | |
400 | rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0); | |
401 | rtsx_pci_clear_ocpstat(pcr); | |
5da4e04a RF |
402 | pcr->ocp_stat = 0; |
403 | pcr->ocp_stat2 = 0; | |
404 | } | |
405 | ||
5da4e04a RF |
406 | } |
407 | ||
75a89805 | 408 | static int rts5260_init_hw(struct rtsx_pcr *pcr) |
5da4e04a RF |
409 | { |
410 | int err; | |
411 | ||
5da4e04a RF |
412 | rtsx_pci_init_cmd(pcr); |
413 | ||
414 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, L1SUB_CONFIG1, | |
415 | AUX_CLK_ACTIVE_SEL_MASK, MAC_CKSW_DONE); | |
416 | /* Rest L1SUB Config */ | |
417 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, L1SUB_CONFIG3, 0xFF, 0x00); | |
418 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CLK_FORCE_CTL, | |
419 | CLK_PM_EN, CLK_PM_EN); | |
420 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWD_SUSPEND_EN, 0xFF, 0xFF); | |
421 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, | |
422 | PWR_GATE_EN, PWR_GATE_EN); | |
423 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, REG_VREF, | |
424 | PWD_SUSPND_EN, PWD_SUSPND_EN); | |
425 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RBCTL, | |
426 | U_AUTO_DMA_EN_MASK, U_AUTO_DMA_DISABLE); | |
427 | ||
428 | if (pcr->flags & PCR_REVERSE_SOCKET) | |
429 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0xB0); | |
430 | else | |
431 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0x80); | |
432 | ||
433 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, | |
434 | OBFF_EN_MASK, OBFF_DISABLE); | |
435 | ||
436 | err = rtsx_pci_send_cmd(pcr, CMD_TIMEOUT_DEF); | |
437 | if (err < 0) | |
438 | return err; | |
439 | ||
bede03a5 R |
440 | rtsx_pci_init_ocp(pcr); |
441 | ||
5da4e04a RF |
442 | return 0; |
443 | } | |
444 | ||
445 | static void rts5260_pwr_saving_setting(struct rtsx_pcr *pcr) | |
446 | { | |
447 | int lss_l1_1, lss_l1_2; | |
448 | ||
449 | lss_l1_1 = rtsx_check_dev_flag(pcr, ASPM_L1_1_EN) | |
450 | | rtsx_check_dev_flag(pcr, PM_L1_1_EN); | |
451 | lss_l1_2 = rtsx_check_dev_flag(pcr, ASPM_L1_2_EN) | |
452 | | rtsx_check_dev_flag(pcr, PM_L1_2_EN); | |
453 | ||
454 | if (lss_l1_2) { | |
455 | pcr_dbg(pcr, "Set parameters for L1.2."); | |
456 | rtsx_pci_write_register(pcr, PWR_GLOBAL_CTRL, | |
457 | 0xFF, PCIE_L1_2_EN); | |
bede03a5 R |
458 | rtsx_pci_write_register(pcr, RTS5260_DVCC_CTRL, |
459 | RTS5260_DVCC_OCP_EN | | |
460 | RTS5260_DVCC_OCP_CL_EN, | |
461 | RTS5260_DVCC_OCP_EN | | |
462 | RTS5260_DVCC_OCP_CL_EN); | |
463 | ||
464 | rtsx_pci_write_register(pcr, PWR_FE_CTL, | |
5da4e04a RF |
465 | 0xFF, PCIE_L1_2_PD_FE_EN); |
466 | } else if (lss_l1_1) { | |
467 | pcr_dbg(pcr, "Set parameters for L1.1."); | |
468 | rtsx_pci_write_register(pcr, PWR_GLOBAL_CTRL, | |
469 | 0xFF, PCIE_L1_1_EN); | |
470 | rtsx_pci_write_register(pcr, PWR_FE_CTL, | |
471 | 0xFF, PCIE_L1_1_PD_FE_EN); | |
472 | } else { | |
473 | pcr_dbg(pcr, "Set parameters for L1."); | |
474 | rtsx_pci_write_register(pcr, PWR_GLOBAL_CTRL, | |
475 | 0xFF, PCIE_L1_0_EN); | |
476 | rtsx_pci_write_register(pcr, PWR_FE_CTL, | |
477 | 0xFF, PCIE_L1_0_PD_FE_EN); | |
478 | } | |
479 | ||
480 | rtsx_pci_write_register(pcr, CFG_L1_0_PCIE_DPHY_RET_VALUE, | |
481 | 0xFF, CFG_L1_0_RET_VALUE_DEFAULT); | |
482 | rtsx_pci_write_register(pcr, CFG_L1_0_PCIE_MAC_RET_VALUE, | |
483 | 0xFF, CFG_L1_0_RET_VALUE_DEFAULT); | |
484 | rtsx_pci_write_register(pcr, CFG_L1_0_CRC_SD30_RET_VALUE, | |
485 | 0xFF, CFG_L1_0_RET_VALUE_DEFAULT); | |
486 | rtsx_pci_write_register(pcr, CFG_L1_0_CRC_SD40_RET_VALUE, | |
487 | 0xFF, CFG_L1_0_RET_VALUE_DEFAULT); | |
488 | rtsx_pci_write_register(pcr, CFG_L1_0_SYS_RET_VALUE, | |
489 | 0xFF, CFG_L1_0_RET_VALUE_DEFAULT); | |
490 | /*Option cut APHY*/ | |
491 | rtsx_pci_write_register(pcr, CFG_PCIE_APHY_OFF_0, | |
492 | 0xFF, CFG_PCIE_APHY_OFF_0_DEFAULT); | |
493 | rtsx_pci_write_register(pcr, CFG_PCIE_APHY_OFF_1, | |
494 | 0xFF, CFG_PCIE_APHY_OFF_1_DEFAULT); | |
495 | rtsx_pci_write_register(pcr, CFG_PCIE_APHY_OFF_2, | |
496 | 0xFF, CFG_PCIE_APHY_OFF_2_DEFAULT); | |
497 | rtsx_pci_write_register(pcr, CFG_PCIE_APHY_OFF_3, | |
498 | 0xFF, CFG_PCIE_APHY_OFF_3_DEFAULT); | |
499 | /*CDR DEC*/ | |
500 | rtsx_pci_write_register(pcr, PWC_CDR, 0xFF, PWC_CDR_DEFAULT); | |
501 | /*PWMPFM*/ | |
502 | rtsx_pci_write_register(pcr, CFG_LP_FPWM_VALUE, | |
503 | 0xFF, CFG_LP_FPWM_VALUE_DEFAULT); | |
504 | /*No Power Saving WA*/ | |
505 | rtsx_pci_write_register(pcr, CFG_L1_0_CRC_MISC_RET_VALUE, | |
506 | 0xFF, CFG_L1_0_CRC_MISC_RET_VALUE_DEFAULT); | |
507 | } | |
508 | ||
509 | static void rts5260_init_from_cfg(struct rtsx_pcr *pcr) | |
510 | { | |
511 | struct rtsx_cr_option *option = &pcr->option; | |
512 | u32 lval; | |
513 | ||
514 | rtsx_pci_read_config_dword(pcr, PCR_ASPM_SETTING_5260, &lval); | |
515 | ||
516 | if (lval & ASPM_L1_1_EN_MASK) | |
517 | rtsx_set_dev_flag(pcr, ASPM_L1_1_EN); | |
518 | ||
519 | if (lval & ASPM_L1_2_EN_MASK) | |
520 | rtsx_set_dev_flag(pcr, ASPM_L1_2_EN); | |
521 | ||
522 | if (lval & PM_L1_1_EN_MASK) | |
523 | rtsx_set_dev_flag(pcr, PM_L1_1_EN); | |
524 | ||
525 | if (lval & PM_L1_2_EN_MASK) | |
526 | rtsx_set_dev_flag(pcr, PM_L1_2_EN); | |
527 | ||
528 | rts5260_pwr_saving_setting(pcr); | |
529 | ||
530 | if (option->ltr_en) { | |
531 | u16 val; | |
532 | ||
533 | pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &val); | |
534 | if (val & PCI_EXP_DEVCTL2_LTR_EN) { | |
535 | option->ltr_enabled = true; | |
536 | option->ltr_active = true; | |
537 | rtsx_set_ltr_latency(pcr, option->ltr_active_latency); | |
538 | } else { | |
539 | option->ltr_enabled = false; | |
540 | } | |
541 | } | |
542 | ||
543 | if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN | |
544 | | PM_L1_1_EN | PM_L1_2_EN)) | |
545 | option->force_clkreq_0 = false; | |
546 | else | |
547 | option->force_clkreq_0 = true; | |
548 | } | |
549 | ||
550 | static int rts5260_extra_init_hw(struct rtsx_pcr *pcr) | |
551 | { | |
552 | struct rtsx_cr_option *option = &pcr->option; | |
553 | ||
554 | /* Set mcu_cnt to 7 to ensure data can be sampled properly */ | |
555 | rtsx_pci_write_register(pcr, 0xFC03, 0x7F, 0x07); | |
556 | rtsx_pci_write_register(pcr, SSC_DIV_N_0, 0xFF, 0x5D); | |
557 | ||
558 | rts5260_init_from_cfg(pcr); | |
559 | ||
560 | /* force no MDIO*/ | |
561 | rtsx_pci_write_register(pcr, RTS5260_AUTOLOAD_CFG4, | |
562 | 0xFF, RTS5260_MIMO_DISABLE); | |
563 | /*Modify SDVCC Tune Default Parameters!*/ | |
564 | rtsx_pci_write_register(pcr, LDO_VCC_CFG0, | |
565 | RTS5260_DVCC_TUNE_MASK, RTS5260_DVCC_33); | |
566 | ||
567 | rtsx_pci_write_register(pcr, PCLK_CTL, PCLK_MODE_SEL, PCLK_MODE_SEL); | |
568 | ||
569 | rts5260_init_hw(pcr); | |
570 | ||
571 | /* | |
572 | * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced | |
573 | * to drive low, and we forcibly request clock. | |
574 | */ | |
575 | if (option->force_clkreq_0) | |
576 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, | |
577 | FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); | |
578 | else | |
579 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, | |
580 | FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); | |
581 | ||
582 | return 0; | |
583 | } | |
584 | ||
75a89805 | 585 | static void rts5260_set_aspm(struct rtsx_pcr *pcr, bool enable) |
5da4e04a RF |
586 | { |
587 | struct rtsx_cr_option *option = &pcr->option; | |
588 | u8 val = 0; | |
589 | ||
590 | if (pcr->aspm_enabled == enable) | |
591 | return; | |
592 | ||
593 | if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) { | |
594 | if (enable) | |
595 | val = pcr->aspm_en; | |
596 | rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL, | |
597 | ASPM_MASK_NEG, val); | |
598 | } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) { | |
599 | u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0; | |
600 | ||
601 | if (!enable) | |
602 | val = FORCE_ASPM_CTL0; | |
603 | rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val); | |
604 | } | |
605 | ||
606 | pcr->aspm_enabled = enable; | |
607 | } | |
608 | ||
609 | static void rts5260_set_l1off_cfg_sub_d0(struct rtsx_pcr *pcr, int active) | |
610 | { | |
611 | struct rtsx_cr_option *option = &pcr->option; | |
612 | u32 interrupt = rtsx_pci_readl(pcr, RTSX_BIPR); | |
613 | int card_exist = (interrupt & SD_EXIST) | (interrupt & MS_EXIST); | |
614 | int aspm_L1_1, aspm_L1_2; | |
615 | u8 val = 0; | |
616 | ||
617 | aspm_L1_1 = rtsx_check_dev_flag(pcr, ASPM_L1_1_EN); | |
618 | aspm_L1_2 = rtsx_check_dev_flag(pcr, ASPM_L1_2_EN); | |
619 | ||
620 | if (active) { | |
621 | /* run, latency: 60us */ | |
622 | if (aspm_L1_1) | |
623 | val = option->ltr_l1off_snooze_sspwrgate; | |
624 | } else { | |
625 | /* l1off, latency: 300us */ | |
626 | if (aspm_L1_2) | |
627 | val = option->ltr_l1off_sspwrgate; | |
628 | } | |
629 | ||
630 | if (aspm_L1_1 || aspm_L1_2) { | |
631 | if (rtsx_check_dev_flag(pcr, | |
632 | LTR_L1SS_PWR_GATE_CHECK_CARD_EN)) { | |
633 | if (card_exist) | |
634 | val &= ~L1OFF_MBIAS2_EN_5250; | |
635 | else | |
636 | val |= L1OFF_MBIAS2_EN_5250; | |
637 | } | |
638 | } | |
639 | rtsx_set_l1off_sub(pcr, val); | |
640 | } | |
641 | ||
642 | static const struct pcr_ops rts5260_pcr_ops = { | |
643 | .fetch_vendor_settings = rtsx_base_fetch_vendor_settings, | |
644 | .turn_on_led = rts5260_turn_on_led, | |
645 | .turn_off_led = rts5260_turn_off_led, | |
646 | .extra_init_hw = rts5260_extra_init_hw, | |
647 | .enable_auto_blink = rtsx_base_enable_auto_blink, | |
648 | .disable_auto_blink = rtsx_base_disable_auto_blink, | |
649 | .card_power_on = rts5260_card_power_on, | |
650 | .card_power_off = rts5260_card_power_off, | |
651 | .switch_output_voltage = rts5260_switch_output_voltage, | |
652 | .force_power_down = rtsx_base_force_power_down, | |
653 | .stop_cmd = rts5260_stop_cmd, | |
654 | .set_aspm = rts5260_set_aspm, | |
655 | .set_l1off_cfg_sub_d0 = rts5260_set_l1off_cfg_sub_d0, | |
656 | .enable_ocp = rts5260_enable_ocp, | |
657 | .disable_ocp = rts5260_disable_ocp, | |
658 | .init_ocp = rts5260_init_ocp, | |
659 | .process_ocp = rts5260_process_ocp, | |
660 | .get_ocpstat = rts5260_get_ocpstat, | |
661 | .clear_ocpstat = rts5260_clear_ocpstat, | |
662 | }; | |
663 | ||
664 | void rts5260_init_params(struct rtsx_pcr *pcr) | |
665 | { | |
666 | struct rtsx_cr_option *option = &pcr->option; | |
667 | struct rtsx_hw_param *hw_param = &pcr->hw_param; | |
668 | ||
669 | pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; | |
670 | pcr->num_slots = 2; | |
671 | ||
672 | pcr->flags = 0; | |
673 | pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT; | |
674 | pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B; | |
675 | pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B; | |
676 | pcr->aspm_en = ASPM_L1_EN; | |
677 | pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16); | |
678 | pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5); | |
679 | ||
680 | pcr->ic_version = rts5260_get_ic_version(pcr); | |
681 | pcr->sd_pull_ctl_enable_tbl = rts5260_sd_pull_ctl_enable_tbl; | |
682 | pcr->sd_pull_ctl_disable_tbl = rts5260_sd_pull_ctl_disable_tbl; | |
683 | pcr->ms_pull_ctl_enable_tbl = rts5260_ms_pull_ctl_enable_tbl; | |
684 | pcr->ms_pull_ctl_disable_tbl = rts5260_ms_pull_ctl_disable_tbl; | |
685 | ||
686 | pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3; | |
687 | ||
688 | pcr->ops = &rts5260_pcr_ops; | |
689 | ||
690 | option->dev_flags = (LTR_L1SS_PWR_GATE_CHECK_CARD_EN | |
691 | | LTR_L1SS_PWR_GATE_EN); | |
692 | option->ltr_en = true; | |
693 | ||
694 | /* init latency of active, idle, L1OFF to 60us, 300us, 3ms */ | |
695 | option->ltr_active_latency = LTR_ACTIVE_LATENCY_DEF; | |
696 | option->ltr_idle_latency = LTR_IDLE_LATENCY_DEF; | |
697 | option->ltr_l1off_latency = LTR_L1OFF_LATENCY_DEF; | |
698 | option->dev_aspm_mode = DEV_ASPM_DYNAMIC; | |
699 | option->l1_snooze_delay = L1_SNOOZE_DELAY_DEF; | |
700 | option->ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF; | |
701 | option->ltr_l1off_snooze_sspwrgate = | |
702 | LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF; | |
703 | ||
704 | option->ocp_en = 1; | |
705 | if (option->ocp_en) | |
706 | hw_param->interrupt_en |= SD_OC_INT_EN; | |
bede03a5 | 707 | hw_param->ocp_glitch = SDVIO_OCP_GLITCH_800U | SDVIO_OCP_GLITCH_800U; |
5da4e04a RF |
708 | option->sd_400mA_ocp_thd = RTS5260_DVCC_OCP_THD_550; |
709 | option->sd_800mA_ocp_thd = RTS5260_DVCC_OCP_THD_970; | |
710 | } |