Commit | Line | Data |
---|---|---|
9c92ab61 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
01acf691 AL |
2 | /* |
3 | * Copyright (C) 2013 BayHub Technology Ltd. | |
4 | * | |
5 | * Authors: Peter Guo <peter.guo@bayhubtech.com> | |
6 | * Adam Lee <adam.lee@canonical.com> | |
57322d54 | 7 | * Ernest Zhang <ernest.zhang@bayhubtech.com> |
01acf691 AL |
8 | */ |
9 | ||
10 | #include <linux/pci.h> | |
0086fc21 | 11 | #include <linux/mmc/host.h> |
12 | #include <linux/mmc/mmc.h> | |
13 | #include <linux/delay.h> | |
7d440617 | 14 | #include <linux/iopoll.h> |
4be33cf1 | 15 | #include <linux/bitfield.h> |
01acf691 AL |
16 | |
17 | #include "sdhci.h" | |
18 | #include "sdhci-pci.h" | |
361eeda0 AH |
19 | |
20 | /* | |
21 | * O2Micro device registers | |
22 | */ | |
23 | ||
da2a69cf | 24 | #define O2_SD_PCIE_SWITCH 0x54 |
361eeda0 AH |
25 | #define O2_SD_MISC_REG5 0x64 |
26 | #define O2_SD_LD0_CTRL 0x68 | |
27 | #define O2_SD_DEV_CTRL 0x88 | |
28 | #define O2_SD_LOCK_WP 0xD3 | |
29 | #define O2_SD_TEST_REG 0xD4 | |
30 | #define O2_SD_FUNC_REG0 0xDC | |
31 | #define O2_SD_MULTI_VCC3V 0xEE | |
32 | #define O2_SD_CLKREQ 0xEC | |
33 | #define O2_SD_CAPS 0xE0 | |
34 | #define O2_SD_ADMA1 0xE2 | |
35 | #define O2_SD_ADMA2 0xE7 | |
096cc0cd | 36 | #define O2_SD_MISC_CTRL2 0xF0 |
361eeda0 AH |
37 | #define O2_SD_INF_MOD 0xF1 |
38 | #define O2_SD_MISC_CTRL4 0xFC | |
1ad9f880 | 39 | #define O2_SD_MISC_CTRL 0x1C0 |
3d757ddb | 40 | #define O2_SD_EXP_INT_REG 0x1E0 |
1ad9f880 | 41 | #define O2_SD_PWR_FORCE_L0 0x0002 |
361eeda0 AH |
42 | #define O2_SD_TUNING_CTRL 0x300 |
43 | #define O2_SD_PLL_SETTING 0x304 | |
57322d54 | 44 | #define O2_SD_MISC_SETTING 0x308 |
361eeda0 AH |
45 | #define O2_SD_CLK_SETTING 0x328 |
46 | #define O2_SD_CAP_REG2 0x330 | |
47 | #define O2_SD_CAP_REG0 0x334 | |
48 | #define O2_SD_UHS1_CAP_SETTING 0x33C | |
49 | #define O2_SD_DELAY_CTRL 0x350 | |
4be33cf1 | 50 | #define O2_SD_OUTPUT_CLK_SOURCE_SWITCH 0x354 |
361eeda0 AH |
51 | #define O2_SD_UHS2_L1_CTRL 0x35C |
52 | #define O2_SD_FUNC_REG3 0x3E0 | |
53 | #define O2_SD_FUNC_REG4 0x3E4 | |
3d757ddb CL |
54 | #define O2_SD_PARA_SET_REG1 0x444 |
55 | #define O2_SD_VDDX_CTRL_REG 0x508 | |
56 | #define O2_SD_GPIO_CTRL_REG1 0x510 | |
361eeda0 AH |
57 | #define O2_SD_LED_ENABLE BIT(6) |
58 | #define O2_SD_FREG0_LEDOFF BIT(13) | |
4be33cf1 | 59 | #define O2_SD_SEL_DLL BIT(16) |
361eeda0 | 60 | #define O2_SD_FREG4_ENABLE_CLK_SET BIT(22) |
4be33cf1 FA |
61 | #define O2_SD_PHASE_MASK GENMASK(23, 20) |
62 | #define O2_SD_FIX_PHASE FIELD_PREP(O2_SD_PHASE_MASK, 0x9) | |
361eeda0 AH |
63 | |
64 | #define O2_SD_VENDOR_SETTING 0x110 | |
65 | #define O2_SD_VENDOR_SETTING2 0x1C8 | |
0086fc21 | 66 | #define O2_SD_HW_TUNING_DISABLE BIT(4) |
67 | ||
9674bab4 | 68 | #define O2_PLL_DLL_WDT_CONTROL1 0x1CC |
69d91ed1 EZW |
69 | #define O2_PLL_FORCE_ACTIVE BIT(18) |
70 | #define O2_PLL_LOCK_STATUS BIT(14) | |
71 | #define O2_PLL_SOFT_RESET BIT(12) | |
7d440617 | 72 | #define O2_DLL_LOCK_STATUS BIT(11) |
69d91ed1 EZW |
73 | |
74 | #define O2_SD_DETECT_SETTING 0x324 | |
75 | ||
7d440617 SHS |
76 | static const u32 dmdn_table[] = {0x2B1C0000, |
77 | 0x2C1A0000, 0x371B0000, 0x35100000}; | |
78 | #define DMDN_SZ ARRAY_SIZE(dmdn_table) | |
79 | ||
80 | struct o2_host { | |
81 | u8 dll_adjust_count; | |
82 | }; | |
83 | ||
908fd508 SHS |
84 | static void sdhci_o2_wait_card_detect_stable(struct sdhci_host *host) |
85 | { | |
86 | ktime_t timeout; | |
87 | u32 scratch32; | |
88 | ||
89 | /* Wait max 50 ms */ | |
90 | timeout = ktime_add_ms(ktime_get(), 50); | |
91 | while (1) { | |
92 | bool timedout = ktime_after(ktime_get(), timeout); | |
93 | ||
94 | scratch32 = sdhci_readl(host, SDHCI_PRESENT_STATE); | |
95 | if ((scratch32 & SDHCI_CARD_PRESENT) >> SDHCI_CARD_PRES_SHIFT | |
96 | == (scratch32 & SDHCI_CD_LVL) >> SDHCI_CD_LVL_SHIFT) | |
97 | break; | |
98 | ||
99 | if (timedout) { | |
100 | pr_err("%s: Card Detect debounce never finished.\n", | |
101 | mmc_hostname(host->mmc)); | |
102 | sdhci_dumpregs(host); | |
103 | return; | |
104 | } | |
105 | udelay(10); | |
106 | } | |
107 | } | |
108 | ||
109 | static void sdhci_o2_enable_internal_clock(struct sdhci_host *host) | |
110 | { | |
111 | ktime_t timeout; | |
112 | u16 scratch; | |
113 | u32 scratch32; | |
114 | ||
115 | /* PLL software reset */ | |
116 | scratch32 = sdhci_readl(host, O2_PLL_DLL_WDT_CONTROL1); | |
117 | scratch32 |= O2_PLL_SOFT_RESET; | |
118 | sdhci_writel(host, scratch32, O2_PLL_DLL_WDT_CONTROL1); | |
119 | udelay(1); | |
120 | scratch32 &= ~(O2_PLL_SOFT_RESET); | |
121 | sdhci_writel(host, scratch32, O2_PLL_DLL_WDT_CONTROL1); | |
122 | ||
123 | /* PLL force active */ | |
124 | scratch32 |= O2_PLL_FORCE_ACTIVE; | |
125 | sdhci_writel(host, scratch32, O2_PLL_DLL_WDT_CONTROL1); | |
126 | ||
127 | /* Wait max 20 ms */ | |
128 | timeout = ktime_add_ms(ktime_get(), 20); | |
129 | while (1) { | |
130 | bool timedout = ktime_after(ktime_get(), timeout); | |
131 | ||
132 | scratch = sdhci_readw(host, O2_PLL_DLL_WDT_CONTROL1); | |
133 | if (scratch & O2_PLL_LOCK_STATUS) | |
134 | break; | |
135 | if (timedout) { | |
136 | pr_err("%s: Internal clock never stabilised.\n", | |
137 | mmc_hostname(host->mmc)); | |
138 | sdhci_dumpregs(host); | |
139 | goto out; | |
140 | } | |
141 | udelay(10); | |
142 | } | |
143 | ||
144 | /* Wait for card detect finish */ | |
145 | udelay(1); | |
146 | sdhci_o2_wait_card_detect_stable(host); | |
147 | ||
148 | out: | |
149 | /* Cancel PLL force active */ | |
150 | scratch32 = sdhci_readl(host, O2_PLL_DLL_WDT_CONTROL1); | |
151 | scratch32 &= ~O2_PLL_FORCE_ACTIVE; | |
152 | sdhci_writel(host, scratch32, O2_PLL_DLL_WDT_CONTROL1); | |
153 | } | |
154 | ||
155 | static int sdhci_o2_get_cd(struct mmc_host *mmc) | |
156 | { | |
157 | struct sdhci_host *host = mmc_priv(mmc); | |
158 | ||
7d440617 SHS |
159 | if (!(sdhci_readw(host, O2_PLL_DLL_WDT_CONTROL1) & O2_PLL_LOCK_STATUS)) |
160 | sdhci_o2_enable_internal_clock(host); | |
e591fcf6 CL |
161 | else |
162 | sdhci_o2_wait_card_detect_stable(host); | |
908fd508 SHS |
163 | |
164 | return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT); | |
165 | } | |
166 | ||
167 | static void o2_pci_set_baseclk(struct sdhci_pci_chip *chip, u32 value) | |
168 | { | |
169 | u32 scratch_32; | |
170 | ||
171 | pci_read_config_dword(chip->pdev, | |
172 | O2_SD_PLL_SETTING, &scratch_32); | |
173 | ||
174 | scratch_32 &= 0x0000FFFF; | |
175 | scratch_32 |= value; | |
176 | ||
177 | pci_write_config_dword(chip->pdev, | |
178 | O2_SD_PLL_SETTING, scratch_32); | |
179 | } | |
180 | ||
7d440617 SHS |
181 | static u32 sdhci_o2_pll_dll_wdt_control(struct sdhci_host *host) |
182 | { | |
183 | return sdhci_readl(host, O2_PLL_DLL_WDT_CONTROL1); | |
184 | } | |
185 | ||
186 | /* | |
187 | * This function is used to detect dll lock status. | |
188 | * Since the dll lock status bit will toggle randomly | |
189 | * with very short interval which needs to be polled | |
190 | * as fast as possible. Set sleep_us as 1 microsecond. | |
191 | */ | |
192 | static int sdhci_o2_wait_dll_detect_lock(struct sdhci_host *host) | |
193 | { | |
194 | u32 scratch32 = 0; | |
195 | ||
196 | return readx_poll_timeout(sdhci_o2_pll_dll_wdt_control, host, | |
197 | scratch32, !(scratch32 & O2_DLL_LOCK_STATUS), 1, 1000000); | |
198 | } | |
199 | ||
0086fc21 | 200 | static void sdhci_o2_set_tuning_mode(struct sdhci_host *host) |
201 | { | |
202 | u16 reg; | |
203 | ||
204 | /* enable hardware tuning */ | |
205 | reg = sdhci_readw(host, O2_SD_VENDOR_SETTING); | |
206 | reg &= ~O2_SD_HW_TUNING_DISABLE; | |
207 | sdhci_writew(host, reg, O2_SD_VENDOR_SETTING); | |
208 | } | |
209 | ||
210 | static void __sdhci_o2_execute_tuning(struct sdhci_host *host, u32 opcode) | |
211 | { | |
212 | int i; | |
213 | ||
7b7d897e | 214 | sdhci_send_tuning(host, opcode); |
0086fc21 | 215 | |
216 | for (i = 0; i < 150; i++) { | |
217 | u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | |
218 | ||
219 | if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { | |
220 | if (ctrl & SDHCI_CTRL_TUNED_CLK) { | |
221 | host->tuning_done = true; | |
222 | return; | |
223 | } | |
224 | pr_warn("%s: HW tuning failed !\n", | |
225 | mmc_hostname(host->mmc)); | |
226 | break; | |
227 | } | |
228 | ||
229 | mdelay(1); | |
230 | } | |
231 | ||
232 | pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", | |
233 | mmc_hostname(host->mmc)); | |
234 | sdhci_reset_tuning(host); | |
235 | } | |
236 | ||
7d440617 SHS |
237 | /* |
238 | * This function is used to fix o2 dll shift issue. | |
239 | * It isn't necessary to detect card present before recovery. | |
240 | * Firstly, it is used by bht emmc card, which is embedded. | |
241 | * Second, before call recovery card present will be detected | |
242 | * outside of the execute tuning function. | |
243 | */ | |
244 | static int sdhci_o2_dll_recovery(struct sdhci_host *host) | |
245 | { | |
246 | int ret = 0; | |
247 | u8 scratch_8 = 0; | |
248 | u32 scratch_32 = 0; | |
249 | struct sdhci_pci_slot *slot = sdhci_priv(host); | |
250 | struct sdhci_pci_chip *chip = slot->chip; | |
251 | struct o2_host *o2_host = sdhci_pci_priv(slot); | |
252 | ||
253 | /* UnLock WP */ | |
254 | pci_read_config_byte(chip->pdev, | |
255 | O2_SD_LOCK_WP, &scratch_8); | |
256 | scratch_8 &= 0x7f; | |
257 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); | |
258 | while (o2_host->dll_adjust_count < DMDN_SZ && !ret) { | |
259 | /* Disable clock */ | |
260 | sdhci_writeb(host, 0, SDHCI_CLOCK_CONTROL); | |
261 | ||
262 | /* PLL software reset */ | |
263 | scratch_32 = sdhci_readl(host, O2_PLL_DLL_WDT_CONTROL1); | |
264 | scratch_32 |= O2_PLL_SOFT_RESET; | |
265 | sdhci_writel(host, scratch_32, O2_PLL_DLL_WDT_CONTROL1); | |
266 | ||
267 | pci_read_config_dword(chip->pdev, | |
268 | O2_SD_FUNC_REG4, | |
269 | &scratch_32); | |
270 | /* Enable Base Clk setting change */ | |
271 | scratch_32 |= O2_SD_FREG4_ENABLE_CLK_SET; | |
272 | pci_write_config_dword(chip->pdev, O2_SD_FUNC_REG4, scratch_32); | |
273 | o2_pci_set_baseclk(chip, dmdn_table[o2_host->dll_adjust_count]); | |
274 | ||
275 | /* Enable internal clock */ | |
276 | scratch_8 = SDHCI_CLOCK_INT_EN; | |
277 | sdhci_writeb(host, scratch_8, SDHCI_CLOCK_CONTROL); | |
278 | ||
279 | if (sdhci_o2_get_cd(host->mmc)) { | |
280 | /* | |
281 | * need wait at least 5ms for dll status stable, | |
282 | * after enable internal clock | |
283 | */ | |
284 | usleep_range(5000, 6000); | |
285 | if (sdhci_o2_wait_dll_detect_lock(host)) { | |
286 | scratch_8 |= SDHCI_CLOCK_CARD_EN; | |
287 | sdhci_writeb(host, scratch_8, | |
288 | SDHCI_CLOCK_CONTROL); | |
289 | ret = 1; | |
290 | } else { | |
291 | pr_warn("%s: DLL unlocked when dll_adjust_count is %d.\n", | |
292 | mmc_hostname(host->mmc), | |
293 | o2_host->dll_adjust_count); | |
294 | } | |
295 | } else { | |
296 | pr_err("%s: card present detect failed.\n", | |
297 | mmc_hostname(host->mmc)); | |
298 | break; | |
299 | } | |
300 | ||
301 | o2_host->dll_adjust_count++; | |
302 | } | |
303 | if (!ret && o2_host->dll_adjust_count == DMDN_SZ) | |
304 | pr_err("%s: DLL adjust over max times\n", | |
305 | mmc_hostname(host->mmc)); | |
306 | /* Lock WP */ | |
307 | pci_read_config_byte(chip->pdev, | |
308 | O2_SD_LOCK_WP, &scratch_8); | |
309 | scratch_8 |= 0x80; | |
310 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); | |
311 | return ret; | |
312 | } | |
313 | ||
0086fc21 | 314 | static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode) |
315 | { | |
316 | struct sdhci_host *host = mmc_priv(mmc); | |
4be33cf1 FA |
317 | struct sdhci_pci_slot *slot = sdhci_priv(host); |
318 | struct sdhci_pci_chip *chip = slot->chip; | |
0086fc21 | 319 | int current_bus_width = 0; |
1ad9f880 SH |
320 | u32 scratch32 = 0; |
321 | u16 scratch = 0; | |
4be33cf1 FA |
322 | u8 scratch_8 = 0; |
323 | u32 reg_val; | |
0086fc21 | 324 | |
325 | /* | |
50aecccc | 326 | * This handler implements the hardware tuning that is specific to |
0086fc21 | 327 | * this controller. Fall back to the standard method for other TIMING. |
328 | */ | |
7b7d897e | 329 | if ((host->timing != MMC_TIMING_MMC_HS200) && |
50aecccc CL |
330 | (host->timing != MMC_TIMING_UHS_SDR104) && |
331 | (host->timing != MMC_TIMING_UHS_SDR50)) | |
0086fc21 | 332 | return sdhci_execute_tuning(mmc, opcode); |
333 | ||
b98e7e8d | 334 | if (WARN_ON(!mmc_op_tuning(opcode))) |
0086fc21 | 335 | return -EINVAL; |
1ad9f880 SH |
336 | |
337 | /* Force power mode enter L0 */ | |
338 | scratch = sdhci_readw(host, O2_SD_MISC_CTRL); | |
339 | scratch |= O2_SD_PWR_FORCE_L0; | |
340 | sdhci_writew(host, scratch, O2_SD_MISC_CTRL); | |
341 | ||
3d757ddb CL |
342 | /* Update output phase */ |
343 | switch (chip->pdev->device) { | |
344 | case PCI_DEVICE_ID_O2_SDS0: | |
345 | case PCI_DEVICE_ID_O2_SEABIRD0: | |
346 | case PCI_DEVICE_ID_O2_SEABIRD1: | |
347 | case PCI_DEVICE_ID_O2_SDS1: | |
348 | case PCI_DEVICE_ID_O2_FUJIN2: | |
349 | /* Stop clk */ | |
350 | reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | |
351 | reg_val &= ~SDHCI_CLOCK_CARD_EN; | |
352 | sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL); | |
353 | ||
354 | if (host->timing == MMC_TIMING_MMC_HS200 || | |
355 | host->timing == MMC_TIMING_UHS_SDR104) { | |
356 | /* UnLock WP */ | |
357 | pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); | |
358 | scratch_8 &= 0x7f; | |
359 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); | |
360 | ||
361 | /* Set pcr 0x354[16] to choose dll clock, and set the default phase */ | |
362 | pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, ®_val); | |
363 | reg_val &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK); | |
364 | reg_val |= (O2_SD_SEL_DLL | O2_SD_FIX_PHASE); | |
365 | pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, reg_val); | |
366 | ||
367 | /* Lock WP */ | |
368 | pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); | |
369 | scratch_8 |= 0x80; | |
370 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); | |
371 | } | |
51dfc614 | 372 | |
3d757ddb CL |
373 | /* Start clk */ |
374 | reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | |
375 | reg_val |= SDHCI_CLOCK_CARD_EN; | |
376 | sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL); | |
377 | break; | |
378 | default: | |
379 | break; | |
51dfc614 | 380 | } |
4be33cf1 | 381 | |
1ad9f880 SH |
382 | /* wait DLL lock, timeout value 5ms */ |
383 | if (readx_poll_timeout(sdhci_o2_pll_dll_wdt_control, host, | |
384 | scratch32, (scratch32 & O2_DLL_LOCK_STATUS), 1, 5000)) | |
385 | pr_warn("%s: DLL can't lock in 5ms after force L0 during tuning.\n", | |
386 | mmc_hostname(host->mmc)); | |
7d440617 SHS |
387 | /* |
388 | * Judge the tuning reason, whether caused by dll shift | |
389 | * If cause by dll shift, should call sdhci_o2_dll_recovery | |
390 | */ | |
391 | if (!sdhci_o2_wait_dll_detect_lock(host)) | |
392 | if (!sdhci_o2_dll_recovery(host)) { | |
393 | pr_err("%s: o2 dll recovery failed\n", | |
394 | mmc_hostname(host->mmc)); | |
395 | return -EINVAL; | |
396 | } | |
0086fc21 | 397 | /* |
398 | * o2 sdhci host didn't support 8bit emmc tuning | |
399 | */ | |
400 | if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) { | |
401 | current_bus_width = mmc->ios.bus_width; | |
0f7b79a4 | 402 | mmc->ios.bus_width = MMC_BUS_WIDTH_4; |
0086fc21 | 403 | sdhci_set_bus_width(host, MMC_BUS_WIDTH_4); |
404 | } | |
405 | ||
406 | sdhci_o2_set_tuning_mode(host); | |
407 | ||
408 | sdhci_start_tuning(host); | |
409 | ||
410 | __sdhci_o2_execute_tuning(host, opcode); | |
411 | ||
412 | sdhci_end_tuning(host); | |
413 | ||
0f7b79a4 RR |
414 | if (current_bus_width == MMC_BUS_WIDTH_8) { |
415 | mmc->ios.bus_width = MMC_BUS_WIDTH_8; | |
0086fc21 | 416 | sdhci_set_bus_width(host, current_bus_width); |
0f7b79a4 | 417 | } |
0086fc21 | 418 | |
1ad9f880 SH |
419 | /* Cancel force power mode enter L0 */ |
420 | scratch = sdhci_readw(host, O2_SD_MISC_CTRL); | |
421 | scratch &= ~(O2_SD_PWR_FORCE_L0); | |
422 | sdhci_writew(host, scratch, O2_SD_MISC_CTRL); | |
423 | ||
7b7d897e | 424 | sdhci_reset(host, SDHCI_RESET_CMD); |
425 | sdhci_reset(host, SDHCI_RESET_DATA); | |
426 | ||
0086fc21 | 427 | host->flags &= ~SDHCI_HS400_TUNING; |
428 | return 0; | |
429 | } | |
01acf691 | 430 | |
706adf6b PG |
431 | static void o2_pci_led_enable(struct sdhci_pci_chip *chip) |
432 | { | |
433 | int ret; | |
434 | u32 scratch_32; | |
435 | ||
436 | /* Set led of SD host function enable */ | |
437 | ret = pci_read_config_dword(chip->pdev, | |
438 | O2_SD_FUNC_REG0, &scratch_32); | |
439 | if (ret) | |
440 | return; | |
441 | ||
442 | scratch_32 &= ~O2_SD_FREG0_LEDOFF; | |
443 | pci_write_config_dword(chip->pdev, | |
444 | O2_SD_FUNC_REG0, scratch_32); | |
445 | ||
446 | ret = pci_read_config_dword(chip->pdev, | |
447 | O2_SD_TEST_REG, &scratch_32); | |
448 | if (ret) | |
449 | return; | |
450 | ||
451 | scratch_32 |= O2_SD_LED_ENABLE; | |
452 | pci_write_config_dword(chip->pdev, | |
453 | O2_SD_TEST_REG, scratch_32); | |
706adf6b PG |
454 | } |
455 | ||
f0cbd780 | 456 | static void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip) |
01acf691 AL |
457 | { |
458 | u32 scratch_32; | |
459 | int ret; | |
460 | /* Improve write performance for SD3.0 */ | |
461 | ret = pci_read_config_dword(chip->pdev, O2_SD_DEV_CTRL, &scratch_32); | |
462 | if (ret) | |
463 | return; | |
464 | scratch_32 &= ~((1 << 12) | (1 << 13) | (1 << 14)); | |
465 | pci_write_config_dword(chip->pdev, O2_SD_DEV_CTRL, scratch_32); | |
466 | ||
467 | /* Enable Link abnormal reset generating Reset */ | |
468 | ret = pci_read_config_dword(chip->pdev, O2_SD_MISC_REG5, &scratch_32); | |
469 | if (ret) | |
470 | return; | |
471 | scratch_32 &= ~((1 << 19) | (1 << 11)); | |
472 | scratch_32 |= (1 << 10); | |
473 | pci_write_config_dword(chip->pdev, O2_SD_MISC_REG5, scratch_32); | |
474 | ||
475 | /* set card power over current protection */ | |
476 | ret = pci_read_config_dword(chip->pdev, O2_SD_TEST_REG, &scratch_32); | |
477 | if (ret) | |
478 | return; | |
479 | scratch_32 |= (1 << 4); | |
480 | pci_write_config_dword(chip->pdev, O2_SD_TEST_REG, scratch_32); | |
481 | ||
482 | /* adjust the output delay for SD mode */ | |
483 | pci_write_config_dword(chip->pdev, O2_SD_DELAY_CTRL, 0x00002492); | |
484 | ||
485 | /* Set the output voltage setting of Aux 1.2v LDO */ | |
486 | ret = pci_read_config_dword(chip->pdev, O2_SD_LD0_CTRL, &scratch_32); | |
487 | if (ret) | |
488 | return; | |
489 | scratch_32 &= ~(3 << 12); | |
490 | pci_write_config_dword(chip->pdev, O2_SD_LD0_CTRL, scratch_32); | |
491 | ||
492 | /* Set Max power supply capability of SD host */ | |
493 | ret = pci_read_config_dword(chip->pdev, O2_SD_CAP_REG0, &scratch_32); | |
494 | if (ret) | |
495 | return; | |
496 | scratch_32 &= ~(0x01FE); | |
497 | scratch_32 |= 0x00CC; | |
498 | pci_write_config_dword(chip->pdev, O2_SD_CAP_REG0, scratch_32); | |
499 | /* Set DLL Tuning Window */ | |
500 | ret = pci_read_config_dword(chip->pdev, | |
501 | O2_SD_TUNING_CTRL, &scratch_32); | |
502 | if (ret) | |
503 | return; | |
504 | scratch_32 &= ~(0x000000FF); | |
505 | scratch_32 |= 0x00000066; | |
506 | pci_write_config_dword(chip->pdev, O2_SD_TUNING_CTRL, scratch_32); | |
507 | ||
508 | /* Set UHS2 T_EIDLE */ | |
509 | ret = pci_read_config_dword(chip->pdev, | |
510 | O2_SD_UHS2_L1_CTRL, &scratch_32); | |
511 | if (ret) | |
512 | return; | |
513 | scratch_32 &= ~(0x000000FC); | |
514 | scratch_32 |= 0x00000084; | |
515 | pci_write_config_dword(chip->pdev, O2_SD_UHS2_L1_CTRL, scratch_32); | |
516 | ||
517 | /* Set UHS2 Termination */ | |
518 | ret = pci_read_config_dword(chip->pdev, O2_SD_FUNC_REG3, &scratch_32); | |
519 | if (ret) | |
520 | return; | |
521 | scratch_32 &= ~((1 << 21) | (1 << 30)); | |
522 | ||
01acf691 AL |
523 | pci_write_config_dword(chip->pdev, O2_SD_FUNC_REG3, scratch_32); |
524 | ||
525 | /* Set L1 Entrance Timer */ | |
526 | ret = pci_read_config_dword(chip->pdev, O2_SD_CAPS, &scratch_32); | |
527 | if (ret) | |
528 | return; | |
529 | scratch_32 &= ~(0xf0000000); | |
530 | scratch_32 |= 0x30000000; | |
531 | pci_write_config_dword(chip->pdev, O2_SD_CAPS, scratch_32); | |
532 | ||
533 | ret = pci_read_config_dword(chip->pdev, | |
534 | O2_SD_MISC_CTRL4, &scratch_32); | |
535 | if (ret) | |
536 | return; | |
537 | scratch_32 &= ~(0x000f0000); | |
538 | scratch_32 |= 0x00080000; | |
539 | pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL4, scratch_32); | |
540 | } | |
01acf691 | 541 | |
02a3c0bd | 542 | static void sdhci_pci_o2_enable_msi(struct sdhci_pci_chip *chip, |
543 | struct sdhci_host *host) | |
544 | { | |
545 | int ret; | |
546 | ||
547 | ret = pci_find_capability(chip->pdev, PCI_CAP_ID_MSI); | |
548 | if (!ret) { | |
0818d197 | 549 | pr_info("%s: unsupported MSI, use INTx irq\n", |
02a3c0bd | 550 | mmc_hostname(host->mmc)); |
551 | return; | |
552 | } | |
553 | ||
554 | ret = pci_alloc_irq_vectors(chip->pdev, 1, 1, | |
555 | PCI_IRQ_MSI | PCI_IRQ_MSIX); | |
556 | if (ret < 0) { | |
557 | pr_err("%s: enable PCI MSI failed, err=%d\n", | |
558 | mmc_hostname(host->mmc), ret); | |
559 | return; | |
560 | } | |
561 | ||
562 | host->irq = pci_irq_vector(chip->pdev, 0); | |
563 | } | |
564 | ||
69d91ed1 EZW |
565 | static void sdhci_o2_enable_clk(struct sdhci_host *host, u16 clk) |
566 | { | |
567 | /* Enable internal clock */ | |
568 | clk |= SDHCI_CLOCK_INT_EN; | |
569 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | |
570 | ||
7d440617 | 571 | sdhci_o2_enable_internal_clock(host); |
69d91ed1 EZW |
572 | if (sdhci_o2_get_cd(host->mmc)) { |
573 | clk |= SDHCI_CLOCK_CARD_EN; | |
574 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | |
575 | } | |
576 | } | |
577 | ||
580b946e | 578 | static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock) |
69d91ed1 EZW |
579 | { |
580 | u16 clk; | |
7b7d897e | 581 | u8 scratch; |
582 | u32 scratch_32; | |
3d757ddb | 583 | u32 dmdn_208m, dmdn_200m; |
7b7d897e | 584 | struct sdhci_pci_slot *slot = sdhci_priv(host); |
585 | struct sdhci_pci_chip *chip = slot->chip; | |
69d91ed1 EZW |
586 | |
587 | host->mmc->actual_clock = 0; | |
588 | ||
589 | sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); | |
590 | ||
591 | if (clock == 0) | |
592 | return; | |
593 | ||
4be33cf1 FA |
594 | /* UnLock WP */ |
595 | pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); | |
596 | scratch &= 0x7f; | |
597 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | |
7b7d897e | 598 | |
3d757ddb CL |
599 | if (chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9860 || |
600 | chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9861 || | |
601 | chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9862 || | |
602 | chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9863) { | |
603 | dmdn_208m = 0x2c500000; | |
604 | dmdn_200m = 0x25200000; | |
605 | } else { | |
606 | dmdn_208m = 0x2c280000; | |
607 | dmdn_200m = 0x25100000; | |
608 | } | |
609 | ||
4be33cf1 | 610 | if ((host->timing == MMC_TIMING_UHS_SDR104) && (clock == 200000000)) { |
7b7d897e | 611 | pci_read_config_dword(chip->pdev, O2_SD_PLL_SETTING, &scratch_32); |
612 | ||
3d757ddb CL |
613 | if ((scratch_32 & 0xFFFF0000) != dmdn_208m) |
614 | o2_pci_set_baseclk(chip, dmdn_208m); | |
a7c18e5c FA |
615 | } else { |
616 | pci_read_config_dword(chip->pdev, O2_SD_PLL_SETTING, &scratch_32); | |
617 | ||
3d757ddb CL |
618 | if ((scratch_32 & 0xFFFF0000) != dmdn_200m) |
619 | o2_pci_set_baseclk(chip, dmdn_200m); | |
4be33cf1 | 620 | } |
7b7d897e | 621 | |
4be33cf1 FA |
622 | pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32); |
623 | scratch_32 &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK); | |
624 | pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, scratch_32); | |
7b7d897e | 625 | |
4be33cf1 FA |
626 | /* Lock WP */ |
627 | pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); | |
628 | scratch |= 0x80; | |
629 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | |
7b7d897e | 630 | |
69d91ed1 EZW |
631 | clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); |
632 | sdhci_o2_enable_clk(host, clk); | |
633 | } | |
634 | ||
da2a69cf CL |
635 | static int sdhci_pci_o2_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios) |
636 | { | |
637 | struct sdhci_host *host = mmc_priv(mmc); | |
638 | struct sdhci_pci_slot *slot = sdhci_priv(host); | |
639 | struct sdhci_pci_chip *chip = slot->chip; | |
640 | u8 scratch8; | |
641 | u16 scratch16; | |
642 | int ret; | |
643 | ||
644 | /* Disable clock */ | |
645 | sdhci_writeb(host, 0, SDHCI_CLOCK_CONTROL); | |
646 | ||
647 | /* Set VDD2 voltage*/ | |
648 | scratch8 = sdhci_readb(host, SDHCI_POWER_CONTROL); | |
649 | scratch8 &= 0x0F; | |
650 | if (host->mmc->ios.timing == MMC_TIMING_SD_EXP_1_2V && | |
651 | host->mmc->caps2 & MMC_CAP2_SD_EXP_1_2V) { | |
652 | scratch8 |= SDHCI_VDD2_POWER_ON | SDHCI_VDD2_POWER_120; | |
653 | } else { | |
654 | scratch8 |= SDHCI_VDD2_POWER_ON | SDHCI_VDD2_POWER_180; | |
655 | } | |
656 | ||
657 | sdhci_writeb(host, scratch8, SDHCI_POWER_CONTROL); | |
658 | ||
659 | /* UnLock WP */ | |
660 | pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch8); | |
661 | scratch8 &= 0x7f; | |
662 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch8); | |
663 | ||
664 | /* Wait for express card clkreqn assert */ | |
665 | ret = read_poll_timeout(sdhci_readb, scratch8, !(scratch8 & BIT(0)), | |
666 | 1, 30000, false, host, O2_SD_EXP_INT_REG); | |
667 | ||
668 | if (!ret) { | |
669 | /* Switch to PCIe mode */ | |
670 | scratch16 = sdhci_readw(host, O2_SD_PCIE_SWITCH); | |
671 | scratch16 |= BIT(8); | |
672 | sdhci_writew(host, scratch16, O2_SD_PCIE_SWITCH); | |
673 | } else { | |
674 | /* Power off VDD2 voltage*/ | |
675 | scratch8 = sdhci_readb(host, SDHCI_POWER_CONTROL); | |
676 | scratch8 &= 0x0F; | |
677 | sdhci_writeb(host, scratch8, SDHCI_POWER_CONTROL); | |
678 | ||
679 | /* Keep mode as UHSI */ | |
680 | pci_read_config_word(chip->pdev, O2_SD_PARA_SET_REG1, &scratch16); | |
681 | scratch16 &= ~BIT(11); | |
682 | pci_write_config_word(chip->pdev, O2_SD_PARA_SET_REG1, scratch16); | |
683 | ||
684 | host->mmc->ios.timing = MMC_TIMING_LEGACY; | |
685 | pr_info("%s: Express card initialization failed, falling back to Legacy\n", | |
686 | mmc_hostname(host->mmc)); | |
687 | } | |
688 | /* Lock WP */ | |
689 | pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch8); | |
690 | scratch8 |= 0x80; | |
691 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch8); | |
692 | ||
693 | return 0; | |
694 | } | |
695 | ||
58aeb562 FA |
696 | static void sdhci_pci_o2_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd) |
697 | { | |
698 | struct sdhci_pci_chip *chip; | |
699 | struct sdhci_pci_slot *slot = sdhci_priv(host); | |
700 | u32 scratch_32 = 0; | |
701 | u8 scratch_8 = 0; | |
702 | ||
703 | chip = slot->chip; | |
704 | ||
705 | if (mode == MMC_POWER_OFF) { | |
706 | /* UnLock WP */ | |
707 | pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); | |
708 | scratch_8 &= 0x7f; | |
709 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); | |
710 | ||
711 | /* Set PCR 0x354[16] to switch Clock Source back to OPE Clock */ | |
712 | pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32); | |
713 | scratch_32 &= ~(O2_SD_SEL_DLL); | |
714 | pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, scratch_32); | |
715 | ||
716 | /* Lock WP */ | |
717 | pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); | |
718 | scratch_8 |= 0x80; | |
719 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); | |
720 | } | |
721 | ||
722 | sdhci_set_power(host, mode, vdd); | |
723 | } | |
724 | ||
580b946e | 725 | static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) |
01acf691 AL |
726 | { |
727 | struct sdhci_pci_chip *chip; | |
728 | struct sdhci_host *host; | |
7d440617 | 729 | struct o2_host *o2_host = sdhci_pci_priv(slot); |
de23f0b7 | 730 | u32 reg, caps; |
57322d54 | 731 | int ret; |
01acf691 AL |
732 | |
733 | chip = slot->chip; | |
734 | host = slot->host; | |
de23f0b7 | 735 | |
7d440617 | 736 | o2_host->dll_adjust_count = 0; |
de23f0b7 RR |
737 | caps = sdhci_readl(host, SDHCI_CAPABILITIES); |
738 | ||
739 | /* | |
740 | * mmc_select_bus_width() will test the bus to determine the actual bus | |
741 | * width. | |
742 | */ | |
743 | if (caps & SDHCI_CAN_DO_8BIT) | |
744 | host->mmc->caps |= MMC_CAP_8_BIT_DATA; | |
745 | ||
3d757ddb CL |
746 | host->quirks2 |= SDHCI_QUIRK2_BROKEN_DDR50; |
747 | ||
748 | sdhci_pci_o2_enable_msi(chip, host); | |
749 | ||
750 | host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning; | |
01acf691 AL |
751 | switch (chip->pdev->device) { |
752 | case PCI_DEVICE_ID_O2_SDS0: | |
753 | case PCI_DEVICE_ID_O2_SEABIRD0: | |
754 | case PCI_DEVICE_ID_O2_SEABIRD1: | |
755 | case PCI_DEVICE_ID_O2_SDS1: | |
756 | case PCI_DEVICE_ID_O2_FUJIN2: | |
757 | reg = sdhci_readl(host, O2_SD_VENDOR_SETTING); | |
758 | if (reg & 0x1) | |
759 | host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; | |
760 | ||
57322d54 | 761 | if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) { |
762 | ret = pci_read_config_dword(chip->pdev, | |
763 | O2_SD_MISC_SETTING, ®); | |
764 | if (ret) | |
765 | return -EIO; | |
766 | if (reg & (1 << 4)) { | |
767 | pr_info("%s: emmc 1.8v flag is set, force 1.8v signaling voltage\n", | |
768 | mmc_hostname(host->mmc)); | |
769 | host->flags &= ~SDHCI_SIGNALING_330; | |
770 | host->flags |= SDHCI_SIGNALING_180; | |
771 | host->mmc->caps2 |= MMC_CAP2_NO_SD; | |
772 | host->mmc->caps2 |= MMC_CAP2_NO_SDIO; | |
69d91ed1 EZW |
773 | pci_write_config_dword(chip->pdev, |
774 | O2_SD_DETECT_SETTING, 3); | |
57322d54 | 775 | } |
69d91ed1 EZW |
776 | |
777 | slot->host->mmc_host_ops.get_cd = sdhci_o2_get_cd; | |
57322d54 | 778 | } |
779 | ||
cdd2b769 | 780 | if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD1) { |
781 | slot->host->mmc_host_ops.get_cd = sdhci_o2_get_cd; | |
782 | host->mmc->caps2 |= MMC_CAP2_NO_SDIO; | |
783 | host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; | |
784 | } | |
785 | ||
01acf691 AL |
786 | if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2) |
787 | break; | |
788 | /* set dll watch dog timer */ | |
789 | reg = sdhci_readl(host, O2_SD_VENDOR_SETTING2); | |
790 | reg |= (1 << 12); | |
791 | sdhci_writel(host, reg, O2_SD_VENDOR_SETTING2); | |
3d757ddb CL |
792 | break; |
793 | case PCI_DEVICE_ID_O2_GG8_9860: | |
794 | case PCI_DEVICE_ID_O2_GG8_9861: | |
795 | case PCI_DEVICE_ID_O2_GG8_9862: | |
796 | case PCI_DEVICE_ID_O2_GG8_9863: | |
da2a69cf | 797 | host->mmc->caps2 |= MMC_CAP2_NO_SDIO | MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V; |
3d757ddb CL |
798 | host->mmc->caps |= MMC_CAP_HW_RESET; |
799 | host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; | |
800 | slot->host->mmc_host_ops.get_cd = sdhci_o2_get_cd; | |
da2a69cf | 801 | host->mmc_host_ops.init_sd_express = sdhci_pci_o2_init_sd_express; |
01acf691 AL |
802 | break; |
803 | default: | |
804 | break; | |
805 | } | |
806 | ||
807 | return 0; | |
808 | } | |
01acf691 | 809 | |
580b946e | 810 | static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) |
01acf691 AL |
811 | { |
812 | int ret; | |
813 | u8 scratch; | |
3d757ddb | 814 | u16 scratch16; |
01acf691 AL |
815 | u32 scratch_32; |
816 | ||
817 | switch (chip->pdev->device) { | |
818 | case PCI_DEVICE_ID_O2_8220: | |
819 | case PCI_DEVICE_ID_O2_8221: | |
820 | case PCI_DEVICE_ID_O2_8320: | |
821 | case PCI_DEVICE_ID_O2_8321: | |
822 | /* This extra setup is required due to broken ADMA. */ | |
823 | ret = pci_read_config_byte(chip->pdev, | |
824 | O2_SD_LOCK_WP, &scratch); | |
825 | if (ret) | |
a91bf3b3 | 826 | goto read_fail; |
01acf691 AL |
827 | scratch &= 0x7f; |
828 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | |
829 | ||
830 | /* Set Multi 3 to VCC3V# */ | |
831 | pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08); | |
832 | ||
833 | /* Disable CLK_REQ# support after media DET */ | |
834 | ret = pci_read_config_byte(chip->pdev, | |
835 | O2_SD_CLKREQ, &scratch); | |
836 | if (ret) | |
a91bf3b3 | 837 | goto read_fail; |
01acf691 AL |
838 | scratch |= 0x20; |
839 | pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch); | |
840 | ||
841 | /* Choose capabilities, enable SDMA. We have to write 0x01 | |
842 | * to the capabilities register first to unlock it. | |
843 | */ | |
844 | ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch); | |
845 | if (ret) | |
a91bf3b3 | 846 | goto read_fail; |
01acf691 AL |
847 | scratch |= 0x01; |
848 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch); | |
849 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73); | |
850 | ||
851 | /* Disable ADMA1/2 */ | |
852 | pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39); | |
853 | pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08); | |
854 | ||
855 | /* Disable the infinite transfer mode */ | |
856 | ret = pci_read_config_byte(chip->pdev, | |
857 | O2_SD_INF_MOD, &scratch); | |
858 | if (ret) | |
a91bf3b3 | 859 | goto read_fail; |
01acf691 AL |
860 | scratch |= 0x08; |
861 | pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch); | |
862 | ||
863 | /* Lock WP */ | |
864 | ret = pci_read_config_byte(chip->pdev, | |
865 | O2_SD_LOCK_WP, &scratch); | |
866 | if (ret) | |
a91bf3b3 | 867 | goto read_fail; |
01acf691 AL |
868 | scratch |= 0x80; |
869 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | |
870 | break; | |
871 | case PCI_DEVICE_ID_O2_SDS0: | |
872 | case PCI_DEVICE_ID_O2_SDS1: | |
873 | case PCI_DEVICE_ID_O2_FUJIN2: | |
874 | /* UnLock WP */ | |
875 | ret = pci_read_config_byte(chip->pdev, | |
876 | O2_SD_LOCK_WP, &scratch); | |
877 | if (ret) | |
a91bf3b3 | 878 | goto read_fail; |
01acf691 AL |
879 | |
880 | scratch &= 0x7f; | |
881 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | |
882 | ||
706adf6b PG |
883 | /* DevId=8520 subId= 0x11 or 0x12 Type Chip support */ |
884 | if (chip->pdev->device == PCI_DEVICE_ID_O2_FUJIN2) { | |
885 | ret = pci_read_config_dword(chip->pdev, | |
886 | O2_SD_FUNC_REG0, | |
887 | &scratch_32); | |
d599005a | 888 | if (ret) |
a91bf3b3 | 889 | goto read_fail; |
706adf6b PG |
890 | scratch_32 = ((scratch_32 & 0xFF000000) >> 24); |
891 | ||
892 | /* Check Whether subId is 0x11 or 0x12 */ | |
893 | if ((scratch_32 == 0x11) || (scratch_32 == 0x12)) { | |
3665ff03 | 894 | scratch_32 = 0x25100000; |
706adf6b | 895 | |
706adf6b PG |
896 | o2_pci_set_baseclk(chip, scratch_32); |
897 | ret = pci_read_config_dword(chip->pdev, | |
898 | O2_SD_FUNC_REG4, | |
899 | &scratch_32); | |
d599005a | 900 | if (ret) |
a91bf3b3 | 901 | goto read_fail; |
706adf6b PG |
902 | |
903 | /* Enable Base Clk setting change */ | |
904 | scratch_32 |= O2_SD_FREG4_ENABLE_CLK_SET; | |
905 | pci_write_config_dword(chip->pdev, | |
906 | O2_SD_FUNC_REG4, | |
907 | scratch_32); | |
908 | ||
909 | /* Set Tuning Window to 4 */ | |
910 | pci_write_config_byte(chip->pdev, | |
911 | O2_SD_TUNING_CTRL, 0x44); | |
912 | ||
913 | break; | |
914 | } | |
915 | } | |
916 | ||
917 | /* Enable 8520 led function */ | |
918 | o2_pci_led_enable(chip); | |
919 | ||
01acf691 AL |
920 | /* Set timeout CLK */ |
921 | ret = pci_read_config_dword(chip->pdev, | |
922 | O2_SD_CLK_SETTING, &scratch_32); | |
923 | if (ret) | |
a91bf3b3 | 924 | goto read_fail; |
01acf691 AL |
925 | |
926 | scratch_32 &= ~(0xFF00); | |
927 | scratch_32 |= 0x07E0C800; | |
928 | pci_write_config_dword(chip->pdev, | |
929 | O2_SD_CLK_SETTING, scratch_32); | |
930 | ||
931 | ret = pci_read_config_dword(chip->pdev, | |
932 | O2_SD_CLKREQ, &scratch_32); | |
933 | if (ret) | |
a91bf3b3 | 934 | goto read_fail; |
01acf691 AL |
935 | scratch_32 |= 0x3; |
936 | pci_write_config_dword(chip->pdev, O2_SD_CLKREQ, scratch_32); | |
937 | ||
938 | ret = pci_read_config_dword(chip->pdev, | |
939 | O2_SD_PLL_SETTING, &scratch_32); | |
940 | if (ret) | |
a91bf3b3 | 941 | goto read_fail; |
01acf691 AL |
942 | |
943 | scratch_32 &= ~(0x1F3F070E); | |
944 | scratch_32 |= 0x18270106; | |
945 | pci_write_config_dword(chip->pdev, | |
946 | O2_SD_PLL_SETTING, scratch_32); | |
947 | ||
948 | /* Disable UHS1 funciton */ | |
949 | ret = pci_read_config_dword(chip->pdev, | |
950 | O2_SD_CAP_REG2, &scratch_32); | |
951 | if (ret) | |
a91bf3b3 | 952 | goto read_fail; |
01acf691 AL |
953 | scratch_32 &= ~(0xE0); |
954 | pci_write_config_dword(chip->pdev, | |
955 | O2_SD_CAP_REG2, scratch_32); | |
956 | ||
957 | if (chip->pdev->device == PCI_DEVICE_ID_O2_FUJIN2) | |
958 | sdhci_pci_o2_fujin2_pci_init(chip); | |
959 | ||
960 | /* Lock WP */ | |
961 | ret = pci_read_config_byte(chip->pdev, | |
962 | O2_SD_LOCK_WP, &scratch); | |
963 | if (ret) | |
a91bf3b3 | 964 | goto read_fail; |
01acf691 AL |
965 | scratch |= 0x80; |
966 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | |
967 | break; | |
968 | case PCI_DEVICE_ID_O2_SEABIRD0: | |
969 | case PCI_DEVICE_ID_O2_SEABIRD1: | |
970 | /* UnLock WP */ | |
971 | ret = pci_read_config_byte(chip->pdev, | |
972 | O2_SD_LOCK_WP, &scratch); | |
973 | if (ret) | |
a91bf3b3 | 974 | goto read_fail; |
01acf691 AL |
975 | |
976 | scratch &= 0x7f; | |
977 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | |
978 | ||
979 | ret = pci_read_config_dword(chip->pdev, | |
706adf6b | 980 | O2_SD_PLL_SETTING, &scratch_32); |
d599005a | 981 | if (ret) |
a91bf3b3 | 982 | goto read_fail; |
01acf691 AL |
983 | |
984 | if ((scratch_32 & 0xff000000) == 0x01000000) { | |
985 | scratch_32 &= 0x0000FFFF; | |
986 | scratch_32 |= 0x1F340000; | |
987 | ||
988 | pci_write_config_dword(chip->pdev, | |
989 | O2_SD_PLL_SETTING, scratch_32); | |
990 | } else { | |
991 | scratch_32 &= 0x0000FFFF; | |
3665ff03 | 992 | scratch_32 |= 0x25100000; |
01acf691 AL |
993 | |
994 | pci_write_config_dword(chip->pdev, | |
995 | O2_SD_PLL_SETTING, scratch_32); | |
996 | ||
997 | ret = pci_read_config_dword(chip->pdev, | |
998 | O2_SD_FUNC_REG4, | |
999 | &scratch_32); | |
d599005a | 1000 | if (ret) |
a91bf3b3 | 1001 | goto read_fail; |
01acf691 AL |
1002 | scratch_32 |= (1 << 22); |
1003 | pci_write_config_dword(chip->pdev, | |
1004 | O2_SD_FUNC_REG4, scratch_32); | |
1005 | } | |
1006 | ||
706adf6b PG |
1007 | /* Set Tuning Windows to 5 */ |
1008 | pci_write_config_byte(chip->pdev, | |
1009 | O2_SD_TUNING_CTRL, 0x55); | |
096cc0cd CL |
1010 | //Adjust 1st and 2nd CD debounce time |
1011 | pci_read_config_dword(chip->pdev, O2_SD_MISC_CTRL2, &scratch_32); | |
1012 | scratch_32 &= 0xFFE7FFFF; | |
1013 | scratch_32 |= 0x00180000; | |
1014 | pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL2, scratch_32); | |
1015 | pci_write_config_dword(chip->pdev, O2_SD_DETECT_SETTING, 1); | |
01acf691 AL |
1016 | /* Lock WP */ |
1017 | ret = pci_read_config_byte(chip->pdev, | |
1018 | O2_SD_LOCK_WP, &scratch); | |
1019 | if (ret) | |
a91bf3b3 | 1020 | goto read_fail; |
01acf691 AL |
1021 | scratch |= 0x80; |
1022 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | |
1023 | break; | |
3d757ddb CL |
1024 | case PCI_DEVICE_ID_O2_GG8_9860: |
1025 | case PCI_DEVICE_ID_O2_GG8_9861: | |
1026 | case PCI_DEVICE_ID_O2_GG8_9862: | |
1027 | case PCI_DEVICE_ID_O2_GG8_9863: | |
1028 | /* UnLock WP */ | |
1029 | ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); | |
1030 | if (ret) | |
a91bf3b3 | 1031 | goto read_fail; |
3d757ddb CL |
1032 | scratch &= 0x7f; |
1033 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | |
1034 | ||
1035 | /* Select mode switch source as software control */ | |
1036 | pci_read_config_word(chip->pdev, O2_SD_PARA_SET_REG1, &scratch16); | |
1037 | scratch16 &= 0xF8FF; | |
1038 | scratch16 |= BIT(9); | |
1039 | pci_write_config_word(chip->pdev, O2_SD_PARA_SET_REG1, scratch16); | |
1040 | ||
1041 | /* set VDD1 supply source */ | |
1042 | pci_read_config_word(chip->pdev, O2_SD_VDDX_CTRL_REG, &scratch16); | |
1043 | scratch16 &= 0xFFE3; | |
1044 | scratch16 |= BIT(3); | |
1045 | pci_write_config_word(chip->pdev, O2_SD_VDDX_CTRL_REG, scratch16); | |
1046 | ||
1047 | /* Set host drive strength*/ | |
1048 | scratch16 = 0x0025; | |
1049 | pci_write_config_word(chip->pdev, O2_SD_PLL_SETTING, scratch16); | |
1050 | ||
1051 | /* Set output delay*/ | |
1052 | pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32); | |
1053 | scratch_32 &= 0xFF0FFF00; | |
1054 | scratch_32 |= 0x00B0003B; | |
1055 | pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, scratch_32); | |
1056 | ||
1057 | /* Lock WP */ | |
1058 | ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); | |
1059 | if (ret) | |
a91bf3b3 | 1060 | goto read_fail; |
3d757ddb CL |
1061 | scratch |= 0x80; |
1062 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | |
1063 | break; | |
01acf691 AL |
1064 | } |
1065 | ||
1066 | return 0; | |
a91bf3b3 IJ |
1067 | |
1068 | read_fail: | |
1069 | return pcibios_err_to_errno(ret); | |
01acf691 | 1070 | } |
01acf691 | 1071 | |
b7813f0f | 1072 | #ifdef CONFIG_PM_SLEEP |
580b946e | 1073 | static int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip) |
01acf691 AL |
1074 | { |
1075 | sdhci_pci_o2_probe(chip); | |
30cf2803 | 1076 | return sdhci_pci_resume_host(chip); |
01acf691 | 1077 | } |
b7813f0f | 1078 | #endif |
328be8be | 1079 | |
69d91ed1 EZW |
1080 | static const struct sdhci_ops sdhci_pci_o2_ops = { |
1081 | .set_clock = sdhci_pci_o2_set_clock, | |
1082 | .enable_dma = sdhci_pci_enable_dma, | |
1083 | .set_bus_width = sdhci_set_bus_width, | |
1084 | .reset = sdhci_reset, | |
1085 | .set_uhs_signaling = sdhci_set_uhs_signaling, | |
58aeb562 | 1086 | .set_power = sdhci_pci_o2_set_power, |
69d91ed1 EZW |
1087 | }; |
1088 | ||
328be8be EZW |
1089 | const struct sdhci_pci_fixes sdhci_o2 = { |
1090 | .probe = sdhci_pci_o2_probe, | |
1091 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | |
49baa01c | 1092 | .quirks2 = SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD, |
328be8be EZW |
1093 | .probe_slot = sdhci_pci_o2_probe_slot, |
1094 | #ifdef CONFIG_PM_SLEEP | |
1095 | .resume = sdhci_pci_o2_resume, | |
1096 | #endif | |
69d91ed1 | 1097 | .ops = &sdhci_pci_o2_ops, |
7d440617 | 1098 | .priv_size = sizeof(struct o2_host), |
328be8be | 1099 | }; |