Commit | Line | Data |
---|---|---|
7657c3a7 AH |
1 | /* |
2 | * Freescale eSDHC controller driver. | |
3 | * | |
f060bc9c | 4 | * Copyright (c) 2007, 2010, 2012 Freescale Semiconductor, Inc. |
7657c3a7 AH |
5 | * Copyright (c) 2009 MontaVista Software, Inc. |
6 | * | |
7 | * Authors: Xiaobo Xie <X.Xie@freescale.com> | |
8 | * Anton Vorontsov <avorontsov@ru.mvista.com> | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; either version 2 of the License, or (at | |
13 | * your option) any later version. | |
14 | */ | |
15 | ||
66b50a00 | 16 | #include <linux/err.h> |
7657c3a7 | 17 | #include <linux/io.h> |
f060bc9c | 18 | #include <linux/of.h> |
ea35645a | 19 | #include <linux/of_address.h> |
7657c3a7 | 20 | #include <linux/delay.h> |
88b47679 | 21 | #include <linux/module.h> |
151ede40 | 22 | #include <linux/sys_soc.h> |
19c3a0ef | 23 | #include <linux/clk.h> |
24 | #include <linux/ktime.h> | |
7657c3a7 | 25 | #include <linux/mmc/host.h> |
38576af1 | 26 | #include "sdhci-pltfm.h" |
80872e21 | 27 | #include "sdhci-esdhc.h" |
7657c3a7 | 28 | |
137ccd46 | 29 | #define VENDOR_V_22 0x12 |
a4071fbb | 30 | #define VENDOR_V_23 0x13 |
f4932cfd | 31 | |
32 | struct sdhci_esdhc { | |
33 | u8 vendor_ver; | |
34 | u8 spec_ver; | |
151ede40 | 35 | bool quirk_incorrect_hostver; |
19c3a0ef | 36 | unsigned int peripheral_clock; |
f4932cfd | 37 | }; |
38 | ||
39 | /** | |
40 | * esdhc_read*_fixup - Fixup the value read from incompatible eSDHC register | |
41 | * to make it compatible with SD spec. | |
42 | * | |
43 | * @host: pointer to sdhci_host | |
44 | * @spec_reg: SD spec register address | |
45 | * @value: 32bit eSDHC register value on spec_reg address | |
46 | * | |
47 | * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC | |
48 | * registers are 32 bits. There are differences in register size, register | |
49 | * address, register function, bit position and function between eSDHC spec | |
50 | * and SD spec. | |
51 | * | |
52 | * Return a fixed up register value | |
53 | */ | |
54 | static u32 esdhc_readl_fixup(struct sdhci_host *host, | |
55 | int spec_reg, u32 value) | |
137ccd46 | 56 | { |
f4932cfd | 57 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
8605e7ae | 58 | struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); |
137ccd46 JH |
59 | u32 ret; |
60 | ||
137ccd46 JH |
61 | /* |
62 | * The bit of ADMA flag in eSDHC is not compatible with standard | |
63 | * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is | |
64 | * supported by eSDHC. | |
65 | * And for many FSL eSDHC controller, the reset value of field | |
f4932cfd | 66 | * SDHCI_CAN_DO_ADMA1 is 1, but some of them can't support ADMA, |
137ccd46 | 67 | * only these vendor version is greater than 2.2/0x12 support ADMA. |
137ccd46 | 68 | */ |
f4932cfd | 69 | if ((spec_reg == SDHCI_CAPABILITIES) && (value & SDHCI_CAN_DO_ADMA1)) { |
70 | if (esdhc->vendor_ver > VENDOR_V_22) { | |
71 | ret = value | SDHCI_CAN_DO_ADMA2; | |
72 | return ret; | |
73 | } | |
137ccd46 | 74 | } |
b0921d5c MW |
75 | /* |
76 | * The DAT[3:0] line signal levels and the CMD line signal level are | |
77 | * not compatible with standard SDHC register. The line signal levels | |
78 | * DAT[7:0] are at bits 31:24 and the command line signal level is at | |
79 | * bit 23. All other bits are the same as in the standard SDHC | |
80 | * register. | |
81 | */ | |
82 | if (spec_reg == SDHCI_PRESENT_STATE) { | |
83 | ret = value & 0x000fffff; | |
84 | ret |= (value >> 4) & SDHCI_DATA_LVL_MASK; | |
85 | ret |= (value << 1) & SDHCI_CMD_LVL; | |
86 | return ret; | |
87 | } | |
88 | ||
f4932cfd | 89 | ret = value; |
137ccd46 JH |
90 | return ret; |
91 | } | |
92 | ||
f4932cfd | 93 | static u16 esdhc_readw_fixup(struct sdhci_host *host, |
94 | int spec_reg, u32 value) | |
7657c3a7 | 95 | { |
151ede40 | 96 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
97 | struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); | |
7657c3a7 | 98 | u16 ret; |
f4932cfd | 99 | int shift = (spec_reg & 0x2) * 8; |
7657c3a7 | 100 | |
f4932cfd | 101 | if (spec_reg == SDHCI_HOST_VERSION) |
102 | ret = value & 0xffff; | |
7657c3a7 | 103 | else |
f4932cfd | 104 | ret = (value >> shift) & 0xffff; |
151ede40 | 105 | /* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect |
106 | * vendor version and spec version information. | |
107 | */ | |
108 | if ((spec_reg == SDHCI_HOST_VERSION) && | |
109 | (esdhc->quirk_incorrect_hostver)) | |
110 | ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200; | |
e51cbc9e X |
111 | return ret; |
112 | } | |
113 | ||
f4932cfd | 114 | static u8 esdhc_readb_fixup(struct sdhci_host *host, |
115 | int spec_reg, u32 value) | |
e51cbc9e | 116 | { |
f4932cfd | 117 | u8 ret; |
118 | u8 dma_bits; | |
119 | int shift = (spec_reg & 0x3) * 8; | |
120 | ||
121 | ret = (value >> shift) & 0xff; | |
ba8c4dc9 RZ |
122 | |
123 | /* | |
124 | * "DMA select" locates at offset 0x28 in SD specification, but on | |
125 | * P5020 or P3041, it locates at 0x29. | |
126 | */ | |
f4932cfd | 127 | if (spec_reg == SDHCI_HOST_CONTROL) { |
ba8c4dc9 | 128 | /* DMA select is 22,23 bits in Protocol Control Register */ |
f4932cfd | 129 | dma_bits = (value >> 5) & SDHCI_CTRL_DMA_MASK; |
ba8c4dc9 RZ |
130 | /* fixup the result */ |
131 | ret &= ~SDHCI_CTRL_DMA_MASK; | |
132 | ret |= dma_bits; | |
133 | } | |
7657c3a7 AH |
134 | return ret; |
135 | } | |
136 | ||
f4932cfd | 137 | /** |
138 | * esdhc_write*_fixup - Fixup the SD spec register value so that it could be | |
139 | * written into eSDHC register. | |
140 | * | |
141 | * @host: pointer to sdhci_host | |
142 | * @spec_reg: SD spec register address | |
143 | * @value: 8/16/32bit SD spec register value that would be written | |
144 | * @old_value: 32bit eSDHC register value on spec_reg address | |
145 | * | |
146 | * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC | |
147 | * registers are 32 bits. There are differences in register size, register | |
148 | * address, register function, bit position and function between eSDHC spec | |
149 | * and SD spec. | |
150 | * | |
151 | * Return a fixed up register value | |
152 | */ | |
153 | static u32 esdhc_writel_fixup(struct sdhci_host *host, | |
154 | int spec_reg, u32 value, u32 old_value) | |
a4071fbb | 155 | { |
f4932cfd | 156 | u32 ret; |
157 | ||
a4071fbb | 158 | /* |
f4932cfd | 159 | * Enabling IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE] |
160 | * when SYSCTL[RSTD] is set for some special operations. | |
161 | * No any impact on other operation. | |
a4071fbb | 162 | */ |
f4932cfd | 163 | if (spec_reg == SDHCI_INT_ENABLE) |
164 | ret = value | SDHCI_INT_BLK_GAP; | |
165 | else | |
166 | ret = value; | |
167 | ||
168 | return ret; | |
a4071fbb HZ |
169 | } |
170 | ||
f4932cfd | 171 | static u32 esdhc_writew_fixup(struct sdhci_host *host, |
172 | int spec_reg, u16 value, u32 old_value) | |
7657c3a7 | 173 | { |
f4932cfd | 174 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
175 | int shift = (spec_reg & 0x2) * 8; | |
176 | u32 ret; | |
177 | ||
178 | switch (spec_reg) { | |
179 | case SDHCI_TRANSFER_MODE: | |
180 | /* | |
181 | * Postpone this write, we must do it together with a | |
182 | * command write that is down below. Return old value. | |
183 | */ | |
184 | pltfm_host->xfer_mode_shadow = value; | |
185 | return old_value; | |
186 | case SDHCI_COMMAND: | |
187 | ret = (value << 16) | pltfm_host->xfer_mode_shadow; | |
188 | return ret; | |
189 | } | |
190 | ||
191 | ret = old_value & (~(0xffff << shift)); | |
192 | ret |= (value << shift); | |
193 | ||
194 | if (spec_reg == SDHCI_BLOCK_SIZE) { | |
7657c3a7 AH |
195 | /* |
196 | * Two last DMA bits are reserved, and first one is used for | |
197 | * non-standard blksz of 4096 bytes that we don't support | |
198 | * yet. So clear the DMA boundary bits. | |
199 | */ | |
f4932cfd | 200 | ret &= (~SDHCI_MAKE_BLKSZ(0x7, 0)); |
7657c3a7 | 201 | } |
f4932cfd | 202 | return ret; |
7657c3a7 AH |
203 | } |
204 | ||
f4932cfd | 205 | static u32 esdhc_writeb_fixup(struct sdhci_host *host, |
206 | int spec_reg, u8 value, u32 old_value) | |
7657c3a7 | 207 | { |
f4932cfd | 208 | u32 ret; |
209 | u32 dma_bits; | |
210 | u8 tmp; | |
211 | int shift = (spec_reg & 0x3) * 8; | |
212 | ||
9e4703df | 213 | /* |
214 | * eSDHC doesn't have a standard power control register, so we do | |
215 | * nothing here to avoid incorrect operation. | |
216 | */ | |
217 | if (spec_reg == SDHCI_POWER_CONTROL) | |
218 | return old_value; | |
ba8c4dc9 RZ |
219 | /* |
220 | * "DMA select" location is offset 0x28 in SD specification, but on | |
221 | * P5020 or P3041, it's located at 0x29. | |
222 | */ | |
f4932cfd | 223 | if (spec_reg == SDHCI_HOST_CONTROL) { |
dcaff04d OG |
224 | /* |
225 | * If host control register is not standard, exit | |
226 | * this function | |
227 | */ | |
228 | if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) | |
f4932cfd | 229 | return old_value; |
dcaff04d | 230 | |
ba8c4dc9 | 231 | /* DMA select is 22,23 bits in Protocol Control Register */ |
f4932cfd | 232 | dma_bits = (value & SDHCI_CTRL_DMA_MASK) << 5; |
233 | ret = (old_value & (~(SDHCI_CTRL_DMA_MASK << 5))) | dma_bits; | |
234 | tmp = (value & (~SDHCI_CTRL_DMA_MASK)) | | |
235 | (old_value & SDHCI_CTRL_DMA_MASK); | |
236 | ret = (ret & (~0xff)) | tmp; | |
237 | ||
238 | /* Prevent SDHCI core from writing reserved bits (e.g. HISPD) */ | |
239 | ret &= ~ESDHC_HOST_CONTROL_RES; | |
240 | return ret; | |
ba8c4dc9 RZ |
241 | } |
242 | ||
f4932cfd | 243 | ret = (old_value & (~(0xff << shift))) | (value << shift); |
244 | return ret; | |
245 | } | |
246 | ||
247 | static u32 esdhc_be_readl(struct sdhci_host *host, int reg) | |
248 | { | |
249 | u32 ret; | |
250 | u32 value; | |
251 | ||
252 | value = ioread32be(host->ioaddr + reg); | |
253 | ret = esdhc_readl_fixup(host, reg, value); | |
254 | ||
255 | return ret; | |
256 | } | |
257 | ||
258 | static u32 esdhc_le_readl(struct sdhci_host *host, int reg) | |
259 | { | |
260 | u32 ret; | |
261 | u32 value; | |
262 | ||
263 | value = ioread32(host->ioaddr + reg); | |
264 | ret = esdhc_readl_fixup(host, reg, value); | |
265 | ||
266 | return ret; | |
267 | } | |
268 | ||
269 | static u16 esdhc_be_readw(struct sdhci_host *host, int reg) | |
270 | { | |
271 | u16 ret; | |
272 | u32 value; | |
273 | int base = reg & ~0x3; | |
274 | ||
275 | value = ioread32be(host->ioaddr + base); | |
276 | ret = esdhc_readw_fixup(host, reg, value); | |
277 | return ret; | |
278 | } | |
279 | ||
280 | static u16 esdhc_le_readw(struct sdhci_host *host, int reg) | |
281 | { | |
282 | u16 ret; | |
283 | u32 value; | |
284 | int base = reg & ~0x3; | |
285 | ||
286 | value = ioread32(host->ioaddr + base); | |
287 | ret = esdhc_readw_fixup(host, reg, value); | |
288 | return ret; | |
289 | } | |
290 | ||
291 | static u8 esdhc_be_readb(struct sdhci_host *host, int reg) | |
292 | { | |
293 | u8 ret; | |
294 | u32 value; | |
295 | int base = reg & ~0x3; | |
296 | ||
297 | value = ioread32be(host->ioaddr + base); | |
298 | ret = esdhc_readb_fixup(host, reg, value); | |
299 | return ret; | |
300 | } | |
301 | ||
302 | static u8 esdhc_le_readb(struct sdhci_host *host, int reg) | |
303 | { | |
304 | u8 ret; | |
305 | u32 value; | |
306 | int base = reg & ~0x3; | |
307 | ||
308 | value = ioread32(host->ioaddr + base); | |
309 | ret = esdhc_readb_fixup(host, reg, value); | |
310 | return ret; | |
311 | } | |
312 | ||
313 | static void esdhc_be_writel(struct sdhci_host *host, u32 val, int reg) | |
314 | { | |
315 | u32 value; | |
316 | ||
317 | value = esdhc_writel_fixup(host, reg, val, 0); | |
318 | iowrite32be(value, host->ioaddr + reg); | |
319 | } | |
320 | ||
321 | static void esdhc_le_writel(struct sdhci_host *host, u32 val, int reg) | |
322 | { | |
323 | u32 value; | |
324 | ||
325 | value = esdhc_writel_fixup(host, reg, val, 0); | |
326 | iowrite32(value, host->ioaddr + reg); | |
327 | } | |
328 | ||
329 | static void esdhc_be_writew(struct sdhci_host *host, u16 val, int reg) | |
330 | { | |
331 | int base = reg & ~0x3; | |
332 | u32 value; | |
333 | u32 ret; | |
334 | ||
335 | value = ioread32be(host->ioaddr + base); | |
336 | ret = esdhc_writew_fixup(host, reg, val, value); | |
337 | if (reg != SDHCI_TRANSFER_MODE) | |
338 | iowrite32be(ret, host->ioaddr + base); | |
339 | } | |
340 | ||
341 | static void esdhc_le_writew(struct sdhci_host *host, u16 val, int reg) | |
342 | { | |
343 | int base = reg & ~0x3; | |
344 | u32 value; | |
345 | u32 ret; | |
346 | ||
347 | value = ioread32(host->ioaddr + base); | |
348 | ret = esdhc_writew_fixup(host, reg, val, value); | |
349 | if (reg != SDHCI_TRANSFER_MODE) | |
350 | iowrite32(ret, host->ioaddr + base); | |
351 | } | |
352 | ||
353 | static void esdhc_be_writeb(struct sdhci_host *host, u8 val, int reg) | |
354 | { | |
355 | int base = reg & ~0x3; | |
356 | u32 value; | |
357 | u32 ret; | |
358 | ||
359 | value = ioread32be(host->ioaddr + base); | |
360 | ret = esdhc_writeb_fixup(host, reg, val, value); | |
361 | iowrite32be(ret, host->ioaddr + base); | |
362 | } | |
363 | ||
364 | static void esdhc_le_writeb(struct sdhci_host *host, u8 val, int reg) | |
365 | { | |
366 | int base = reg & ~0x3; | |
367 | u32 value; | |
368 | u32 ret; | |
369 | ||
370 | value = ioread32(host->ioaddr + base); | |
371 | ret = esdhc_writeb_fixup(host, reg, val, value); | |
372 | iowrite32(ret, host->ioaddr + base); | |
7657c3a7 AH |
373 | } |
374 | ||
a4071fbb HZ |
375 | /* |
376 | * For Abort or Suspend after Stop at Block Gap, ignore the ADMA | |
377 | * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC]) | |
378 | * and Block Gap Event(IRQSTAT[BGE]) are also set. | |
379 | * For Continue, apply soft reset for data(SYSCTL[RSTD]); | |
380 | * and re-issue the entire read transaction from beginning. | |
381 | */ | |
f4932cfd | 382 | static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask) |
a4071fbb | 383 | { |
f4932cfd | 384 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
8605e7ae | 385 | struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); |
a4071fbb HZ |
386 | bool applicable; |
387 | dma_addr_t dmastart; | |
388 | dma_addr_t dmanow; | |
389 | ||
a4071fbb | 390 | applicable = (intmask & SDHCI_INT_DATA_END) && |
f4932cfd | 391 | (intmask & SDHCI_INT_BLK_GAP) && |
392 | (esdhc->vendor_ver == VENDOR_V_23); | |
a4071fbb HZ |
393 | if (!applicable) |
394 | return; | |
395 | ||
396 | host->data->error = 0; | |
397 | dmastart = sg_dma_address(host->data->sg); | |
398 | dmanow = dmastart + host->data->bytes_xfered; | |
399 | /* | |
400 | * Force update to the next DMA block boundary. | |
401 | */ | |
402 | dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) + | |
403 | SDHCI_DEFAULT_BOUNDARY_SIZE; | |
404 | host->data->bytes_xfered = dmanow - dmastart; | |
405 | sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); | |
406 | } | |
407 | ||
80872e21 | 408 | static int esdhc_of_enable_dma(struct sdhci_host *host) |
7657c3a7 | 409 | { |
f4932cfd | 410 | u32 value; |
411 | ||
412 | value = sdhci_readl(host, ESDHC_DMA_SYSCTL); | |
413 | value |= ESDHC_DMA_SNOOP; | |
414 | sdhci_writel(host, value, ESDHC_DMA_SYSCTL); | |
7657c3a7 AH |
415 | return 0; |
416 | } | |
417 | ||
80872e21 | 418 | static unsigned int esdhc_of_get_max_clock(struct sdhci_host *host) |
7657c3a7 | 419 | { |
e307148f | 420 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
19c3a0ef | 421 | struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); |
7657c3a7 | 422 | |
19c3a0ef | 423 | if (esdhc->peripheral_clock) |
424 | return esdhc->peripheral_clock; | |
425 | else | |
426 | return pltfm_host->clock; | |
7657c3a7 AH |
427 | } |
428 | ||
80872e21 | 429 | static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host) |
7657c3a7 | 430 | { |
e307148f | 431 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
19c3a0ef | 432 | struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); |
433 | unsigned int clock; | |
7657c3a7 | 434 | |
19c3a0ef | 435 | if (esdhc->peripheral_clock) |
436 | clock = esdhc->peripheral_clock; | |
437 | else | |
438 | clock = pltfm_host->clock; | |
439 | return clock / 256 / 16; | |
7657c3a7 AH |
440 | } |
441 | ||
f060bc9c JH |
442 | static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) |
443 | { | |
f4932cfd | 444 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
8605e7ae | 445 | struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); |
bd455029 | 446 | int pre_div = 1; |
d31fc00a | 447 | int div = 1; |
e145ac45 | 448 | ktime_t timeout; |
d31fc00a DA |
449 | u32 temp; |
450 | ||
1650d0c7 RK |
451 | host->mmc->actual_clock = 0; |
452 | ||
d31fc00a | 453 | if (clock == 0) |
373073ef | 454 | return; |
d31fc00a | 455 | |
77bd2f6f | 456 | /* Workaround to start pre_div at 2 for VNN < VENDOR_V_23 */ |
f4932cfd | 457 | if (esdhc->vendor_ver < VENDOR_V_23) |
77bd2f6f YL |
458 | pre_div = 2; |
459 | ||
a627f025 | 460 | /* |
461 | * Limit SD clock to 167MHz for ls1046a according to its datasheet | |
462 | */ | |
463 | if (clock > 167000000 && | |
464 | of_find_compatible_node(NULL, NULL, "fsl,ls1046a-esdhc")) | |
465 | clock = 167000000; | |
466 | ||
467 | /* | |
468 | * Limit SD clock to 125MHz for ls1012a according to its datasheet | |
469 | */ | |
470 | if (clock > 125000000 && | |
471 | of_find_compatible_node(NULL, NULL, "fsl,ls1012a-esdhc")) | |
472 | clock = 125000000; | |
473 | ||
f060bc9c JH |
474 | /* Workaround to reduce the clock frequency for p1010 esdhc */ |
475 | if (of_find_compatible_node(NULL, NULL, "fsl,p1010-esdhc")) { | |
476 | if (clock > 20000000) | |
477 | clock -= 5000000; | |
478 | if (clock > 40000000) | |
479 | clock -= 5000000; | |
480 | } | |
481 | ||
d31fc00a | 482 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); |
e87d2db2 | 483 | temp &= ~(ESDHC_CLOCK_SDCLKEN | ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | |
484 | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK); | |
d31fc00a DA |
485 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); |
486 | ||
487 | while (host->max_clk / pre_div / 16 > clock && pre_div < 256) | |
488 | pre_div *= 2; | |
489 | ||
490 | while (host->max_clk / pre_div / div > clock && div < 16) | |
491 | div++; | |
492 | ||
493 | dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", | |
e76b8559 | 494 | clock, host->max_clk / pre_div / div); |
bd455029 | 495 | host->mmc->actual_clock = host->max_clk / pre_div / div; |
d31fc00a DA |
496 | pre_div >>= 1; |
497 | div--; | |
498 | ||
499 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | |
500 | temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | |
501 | | (div << ESDHC_DIVIDER_SHIFT) | |
502 | | (pre_div << ESDHC_PREDIV_SHIFT)); | |
503 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | |
e87d2db2 | 504 | |
505 | /* Wait max 20 ms */ | |
e145ac45 | 506 | timeout = ktime_add_ms(ktime_get(), 20); |
e87d2db2 | 507 | while (!(sdhci_readl(host, ESDHC_PRSSTAT) & ESDHC_CLOCK_STABLE)) { |
e145ac45 | 508 | if (ktime_after(ktime_get(), timeout)) { |
e87d2db2 | 509 | pr_err("%s: Internal clock never stabilised.\n", |
510 | mmc_hostname(host->mmc)); | |
511 | return; | |
512 | } | |
e145ac45 | 513 | udelay(10); |
e87d2db2 | 514 | } |
515 | ||
516 | temp |= ESDHC_CLOCK_SDCLKEN; | |
517 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | |
f060bc9c JH |
518 | } |
519 | ||
2317f56c | 520 | static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) |
66b50a00 OG |
521 | { |
522 | u32 ctrl; | |
523 | ||
f4932cfd | 524 | ctrl = sdhci_readl(host, ESDHC_PROCTL); |
525 | ctrl &= (~ESDHC_CTRL_BUSWIDTH_MASK); | |
66b50a00 OG |
526 | switch (width) { |
527 | case MMC_BUS_WIDTH_8: | |
f4932cfd | 528 | ctrl |= ESDHC_CTRL_8BITBUS; |
66b50a00 OG |
529 | break; |
530 | ||
531 | case MMC_BUS_WIDTH_4: | |
f4932cfd | 532 | ctrl |= ESDHC_CTRL_4BITBUS; |
66b50a00 OG |
533 | break; |
534 | ||
535 | default: | |
66b50a00 OG |
536 | break; |
537 | } | |
538 | ||
f4932cfd | 539 | sdhci_writel(host, ctrl, ESDHC_PROCTL); |
66b50a00 OG |
540 | } |
541 | ||
19c3a0ef | 542 | static void esdhc_clock_enable(struct sdhci_host *host, bool enable) |
543 | { | |
544 | u32 val; | |
545 | ktime_t timeout; | |
546 | ||
547 | val = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | |
548 | ||
549 | if (enable) | |
550 | val |= ESDHC_CLOCK_SDCLKEN; | |
551 | else | |
552 | val &= ~ESDHC_CLOCK_SDCLKEN; | |
553 | ||
554 | sdhci_writel(host, val, ESDHC_SYSTEM_CONTROL); | |
555 | ||
556 | /* Wait max 20 ms */ | |
557 | timeout = ktime_add_ms(ktime_get(), 20); | |
558 | val = ESDHC_CLOCK_STABLE; | |
559 | while (!(sdhci_readl(host, ESDHC_PRSSTAT) & val)) { | |
560 | if (ktime_after(ktime_get(), timeout)) { | |
561 | pr_err("%s: Internal clock never stabilised.\n", | |
562 | mmc_hostname(host->mmc)); | |
563 | break; | |
564 | } | |
565 | udelay(10); | |
566 | } | |
567 | } | |
568 | ||
304f0a98 AIB |
569 | static void esdhc_reset(struct sdhci_host *host, u8 mask) |
570 | { | |
571 | sdhci_reset(host, mask); | |
572 | ||
573 | sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); | |
574 | sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); | |
575 | } | |
576 | ||
ea35645a | 577 | /* The SCFG, Supplemental Configuration Unit, provides SoC specific |
578 | * configuration and status registers for the device. There is a | |
579 | * SDHC IO VSEL control register on SCFG for some platforms. It's | |
580 | * used to support SDHC IO voltage switching. | |
581 | */ | |
582 | static const struct of_device_id scfg_device_ids[] = { | |
583 | { .compatible = "fsl,t1040-scfg", }, | |
584 | { .compatible = "fsl,ls1012a-scfg", }, | |
585 | { .compatible = "fsl,ls1046a-scfg", }, | |
586 | {} | |
587 | }; | |
588 | ||
589 | /* SDHC IO VSEL control register definition */ | |
590 | #define SCFG_SDHCIOVSELCR 0x408 | |
591 | #define SDHCIOVSELCR_TGLEN 0x80000000 | |
592 | #define SDHCIOVSELCR_VSELVAL 0x60000000 | |
593 | #define SDHCIOVSELCR_SDHC_VS 0x00000001 | |
594 | ||
595 | static int esdhc_signal_voltage_switch(struct mmc_host *mmc, | |
596 | struct mmc_ios *ios) | |
597 | { | |
598 | struct sdhci_host *host = mmc_priv(mmc); | |
599 | struct device_node *scfg_node; | |
600 | void __iomem *scfg_base = NULL; | |
601 | u32 sdhciovselcr; | |
602 | u32 val; | |
603 | ||
604 | /* | |
605 | * Signal Voltage Switching is only applicable for Host Controllers | |
606 | * v3.00 and above. | |
607 | */ | |
608 | if (host->version < SDHCI_SPEC_300) | |
609 | return 0; | |
610 | ||
611 | val = sdhci_readl(host, ESDHC_PROCTL); | |
612 | ||
613 | switch (ios->signal_voltage) { | |
614 | case MMC_SIGNAL_VOLTAGE_330: | |
615 | val &= ~ESDHC_VOLT_SEL; | |
616 | sdhci_writel(host, val, ESDHC_PROCTL); | |
617 | return 0; | |
618 | case MMC_SIGNAL_VOLTAGE_180: | |
619 | scfg_node = of_find_matching_node(NULL, scfg_device_ids); | |
620 | if (scfg_node) | |
621 | scfg_base = of_iomap(scfg_node, 0); | |
622 | if (scfg_base) { | |
623 | sdhciovselcr = SDHCIOVSELCR_TGLEN | | |
624 | SDHCIOVSELCR_VSELVAL; | |
625 | iowrite32be(sdhciovselcr, | |
626 | scfg_base + SCFG_SDHCIOVSELCR); | |
627 | ||
628 | val |= ESDHC_VOLT_SEL; | |
629 | sdhci_writel(host, val, ESDHC_PROCTL); | |
630 | mdelay(5); | |
631 | ||
632 | sdhciovselcr = SDHCIOVSELCR_TGLEN | | |
633 | SDHCIOVSELCR_SDHC_VS; | |
634 | iowrite32be(sdhciovselcr, | |
635 | scfg_base + SCFG_SDHCIOVSELCR); | |
636 | iounmap(scfg_base); | |
637 | } else { | |
638 | val |= ESDHC_VOLT_SEL; | |
639 | sdhci_writel(host, val, ESDHC_PROCTL); | |
640 | } | |
641 | return 0; | |
642 | default: | |
643 | return 0; | |
644 | } | |
645 | } | |
646 | ||
ba49cbd0 | 647 | static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) |
648 | { | |
649 | struct sdhci_host *host = mmc_priv(mmc); | |
650 | u32 val; | |
651 | ||
652 | /* Use tuning block for tuning procedure */ | |
653 | esdhc_clock_enable(host, false); | |
654 | val = sdhci_readl(host, ESDHC_DMA_SYSCTL); | |
655 | val |= ESDHC_FLUSH_ASYNC_FIFO; | |
656 | sdhci_writel(host, val, ESDHC_DMA_SYSCTL); | |
657 | ||
658 | val = sdhci_readl(host, ESDHC_TBCTL); | |
659 | val |= ESDHC_TB_EN; | |
660 | sdhci_writel(host, val, ESDHC_TBCTL); | |
661 | esdhc_clock_enable(host, true); | |
662 | ||
663 | return sdhci_execute_tuning(mmc, opcode); | |
664 | } | |
665 | ||
9e48b336 | 666 | #ifdef CONFIG_PM_SLEEP |
723f7924 RK |
667 | static u32 esdhc_proctl; |
668 | static int esdhc_of_suspend(struct device *dev) | |
669 | { | |
670 | struct sdhci_host *host = dev_get_drvdata(dev); | |
671 | ||
f4932cfd | 672 | esdhc_proctl = sdhci_readl(host, SDHCI_HOST_CONTROL); |
723f7924 | 673 | |
d38dcad4 AH |
674 | if (host->tuning_mode != SDHCI_TUNING_MODE_3) |
675 | mmc_retune_needed(host->mmc); | |
676 | ||
723f7924 RK |
677 | return sdhci_suspend_host(host); |
678 | } | |
679 | ||
06732b84 | 680 | static int esdhc_of_resume(struct device *dev) |
723f7924 RK |
681 | { |
682 | struct sdhci_host *host = dev_get_drvdata(dev); | |
683 | int ret = sdhci_resume_host(host); | |
684 | ||
685 | if (ret == 0) { | |
686 | /* Isn't this already done by sdhci_resume_host() ? --rmk */ | |
687 | esdhc_of_enable_dma(host); | |
f4932cfd | 688 | sdhci_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL); |
723f7924 | 689 | } |
723f7924 RK |
690 | return ret; |
691 | } | |
723f7924 RK |
692 | #endif |
693 | ||
9e48b336 UH |
694 | static SIMPLE_DEV_PM_OPS(esdhc_of_dev_pm_ops, |
695 | esdhc_of_suspend, | |
696 | esdhc_of_resume); | |
697 | ||
f4932cfd | 698 | static const struct sdhci_ops sdhci_esdhc_be_ops = { |
699 | .read_l = esdhc_be_readl, | |
700 | .read_w = esdhc_be_readw, | |
701 | .read_b = esdhc_be_readb, | |
702 | .write_l = esdhc_be_writel, | |
703 | .write_w = esdhc_be_writew, | |
704 | .write_b = esdhc_be_writeb, | |
705 | .set_clock = esdhc_of_set_clock, | |
706 | .enable_dma = esdhc_of_enable_dma, | |
707 | .get_max_clock = esdhc_of_get_max_clock, | |
708 | .get_min_clock = esdhc_of_get_min_clock, | |
709 | .adma_workaround = esdhc_of_adma_workaround, | |
710 | .set_bus_width = esdhc_pltfm_set_bus_width, | |
711 | .reset = esdhc_reset, | |
712 | .set_uhs_signaling = sdhci_set_uhs_signaling, | |
713 | }; | |
714 | ||
715 | static const struct sdhci_ops sdhci_esdhc_le_ops = { | |
716 | .read_l = esdhc_le_readl, | |
717 | .read_w = esdhc_le_readw, | |
718 | .read_b = esdhc_le_readb, | |
719 | .write_l = esdhc_le_writel, | |
720 | .write_w = esdhc_le_writew, | |
721 | .write_b = esdhc_le_writeb, | |
722 | .set_clock = esdhc_of_set_clock, | |
723 | .enable_dma = esdhc_of_enable_dma, | |
724 | .get_max_clock = esdhc_of_get_max_clock, | |
725 | .get_min_clock = esdhc_of_get_min_clock, | |
726 | .adma_workaround = esdhc_of_adma_workaround, | |
727 | .set_bus_width = esdhc_pltfm_set_bus_width, | |
728 | .reset = esdhc_reset, | |
729 | .set_uhs_signaling = sdhci_set_uhs_signaling, | |
730 | }; | |
731 | ||
732 | static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = { | |
e9acc77d | 733 | .quirks = ESDHC_DEFAULT_QUIRKS | |
734 | #ifdef CONFIG_PPC | |
735 | SDHCI_QUIRK_BROKEN_CARD_DETECTION | | |
736 | #endif | |
737 | SDHCI_QUIRK_NO_CARD_NO_RESET | | |
738 | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | |
f4932cfd | 739 | .ops = &sdhci_esdhc_be_ops, |
740 | }; | |
741 | ||
742 | static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = { | |
e9acc77d | 743 | .quirks = ESDHC_DEFAULT_QUIRKS | |
744 | SDHCI_QUIRK_NO_CARD_NO_RESET | | |
745 | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | |
f4932cfd | 746 | .ops = &sdhci_esdhc_le_ops, |
7657c3a7 | 747 | }; |
38576af1 | 748 | |
151ede40 | 749 | static struct soc_device_attribute soc_incorrect_hostver[] = { |
750 | { .family = "QorIQ T4240", .revision = "1.0", }, | |
751 | { .family = "QorIQ T4240", .revision = "2.0", }, | |
752 | { }, | |
753 | }; | |
754 | ||
f4932cfd | 755 | static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) |
756 | { | |
757 | struct sdhci_pltfm_host *pltfm_host; | |
758 | struct sdhci_esdhc *esdhc; | |
19c3a0ef | 759 | struct device_node *np; |
760 | struct clk *clk; | |
761 | u32 val; | |
f4932cfd | 762 | u16 host_ver; |
763 | ||
764 | pltfm_host = sdhci_priv(host); | |
8605e7ae | 765 | esdhc = sdhci_pltfm_priv(pltfm_host); |
f4932cfd | 766 | |
767 | host_ver = sdhci_readw(host, SDHCI_HOST_VERSION); | |
768 | esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >> | |
769 | SDHCI_VENDOR_VER_SHIFT; | |
770 | esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK; | |
151ede40 | 771 | if (soc_device_match(soc_incorrect_hostver)) |
772 | esdhc->quirk_incorrect_hostver = true; | |
773 | else | |
774 | esdhc->quirk_incorrect_hostver = false; | |
19c3a0ef | 775 | |
776 | np = pdev->dev.of_node; | |
777 | clk = of_clk_get(np, 0); | |
778 | if (!IS_ERR(clk)) { | |
779 | /* | |
780 | * esdhc->peripheral_clock would be assigned with a value | |
781 | * which is eSDHC base clock when use periperal clock. | |
782 | * For ls1046a, the clock value got by common clk API is | |
783 | * peripheral clock while the eSDHC base clock is 1/2 | |
784 | * peripheral clock. | |
785 | */ | |
786 | if (of_device_is_compatible(np, "fsl,ls1046a-esdhc")) | |
787 | esdhc->peripheral_clock = clk_get_rate(clk) / 2; | |
788 | else | |
789 | esdhc->peripheral_clock = clk_get_rate(clk); | |
790 | ||
791 | clk_put(clk); | |
792 | } | |
793 | ||
794 | if (esdhc->peripheral_clock) { | |
795 | esdhc_clock_enable(host, false); | |
796 | val = sdhci_readl(host, ESDHC_DMA_SYSCTL); | |
797 | val |= ESDHC_PERIPHERAL_CLK_SEL; | |
798 | sdhci_writel(host, val, ESDHC_DMA_SYSCTL); | |
799 | esdhc_clock_enable(host, true); | |
800 | } | |
f4932cfd | 801 | } |
802 | ||
c3be1efd | 803 | static int sdhci_esdhc_probe(struct platform_device *pdev) |
38576af1 | 804 | { |
66b50a00 | 805 | struct sdhci_host *host; |
dcaff04d | 806 | struct device_node *np; |
1ef5e49e | 807 | struct sdhci_pltfm_host *pltfm_host; |
808 | struct sdhci_esdhc *esdhc; | |
66b50a00 OG |
809 | int ret; |
810 | ||
f4932cfd | 811 | np = pdev->dev.of_node; |
812 | ||
150d4240 | 813 | if (of_property_read_bool(np, "little-endian")) |
8605e7ae JZ |
814 | host = sdhci_pltfm_init(pdev, &sdhci_esdhc_le_pdata, |
815 | sizeof(struct sdhci_esdhc)); | |
f4932cfd | 816 | else |
8605e7ae JZ |
817 | host = sdhci_pltfm_init(pdev, &sdhci_esdhc_be_pdata, |
818 | sizeof(struct sdhci_esdhc)); | |
f4932cfd | 819 | |
66b50a00 OG |
820 | if (IS_ERR(host)) |
821 | return PTR_ERR(host); | |
822 | ||
ea35645a | 823 | host->mmc_host_ops.start_signal_voltage_switch = |
824 | esdhc_signal_voltage_switch; | |
ba49cbd0 | 825 | host->mmc_host_ops.execute_tuning = esdhc_execute_tuning; |
6b236f37 | 826 | host->tuning_delay = 1; |
ea35645a | 827 | |
f4932cfd | 828 | esdhc_init(pdev, host); |
829 | ||
66b50a00 OG |
830 | sdhci_get_of_property(pdev); |
831 | ||
1ef5e49e | 832 | pltfm_host = sdhci_priv(host); |
8605e7ae | 833 | esdhc = sdhci_pltfm_priv(pltfm_host); |
1ef5e49e | 834 | if (esdhc->vendor_ver == VENDOR_V_22) |
835 | host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; | |
836 | ||
837 | if (esdhc->vendor_ver > VENDOR_V_22) | |
838 | host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; | |
839 | ||
74fd5e30 YL |
840 | if (of_device_is_compatible(np, "fsl,p5040-esdhc") || |
841 | of_device_is_compatible(np, "fsl,p5020-esdhc") || | |
842 | of_device_is_compatible(np, "fsl,p4080-esdhc") || | |
843 | of_device_is_compatible(np, "fsl,p1020-esdhc") || | |
e9acc77d | 844 | of_device_is_compatible(np, "fsl,t1040-esdhc")) |
74fd5e30 YL |
845 | host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; |
846 | ||
a22950c8 | 847 | if (of_device_is_compatible(np, "fsl,ls1021a-esdhc")) |
848 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; | |
849 | ||
dcaff04d OG |
850 | if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { |
851 | /* | |
852 | * Freescale messed up with P2020 as it has a non-standard | |
853 | * host control register | |
854 | */ | |
855 | host->quirks2 |= SDHCI_QUIRK2_BROKEN_HOST_CONTROL; | |
856 | } | |
857 | ||
66b50a00 | 858 | /* call to generic mmc_of_parse to support additional capabilities */ |
f0991408 UH |
859 | ret = mmc_of_parse(host->mmc); |
860 | if (ret) | |
861 | goto err; | |
862 | ||
490104ac | 863 | mmc_of_parse_voltage(np, &host->ocr_mask); |
66b50a00 OG |
864 | |
865 | ret = sdhci_add_host(host); | |
866 | if (ret) | |
f0991408 | 867 | goto err; |
66b50a00 | 868 | |
f0991408 UH |
869 | return 0; |
870 | err: | |
871 | sdhci_pltfm_free(pdev); | |
66b50a00 | 872 | return ret; |
38576af1 SG |
873 | } |
874 | ||
38576af1 SG |
875 | static const struct of_device_id sdhci_esdhc_of_match[] = { |
876 | { .compatible = "fsl,mpc8379-esdhc" }, | |
877 | { .compatible = "fsl,mpc8536-esdhc" }, | |
878 | { .compatible = "fsl,esdhc" }, | |
879 | { } | |
880 | }; | |
881 | MODULE_DEVICE_TABLE(of, sdhci_esdhc_of_match); | |
882 | ||
883 | static struct platform_driver sdhci_esdhc_driver = { | |
884 | .driver = { | |
885 | .name = "sdhci-esdhc", | |
38576af1 | 886 | .of_match_table = sdhci_esdhc_of_match, |
9e48b336 | 887 | .pm = &esdhc_of_dev_pm_ops, |
38576af1 SG |
888 | }, |
889 | .probe = sdhci_esdhc_probe, | |
caebcae9 | 890 | .remove = sdhci_pltfm_unregister, |
38576af1 SG |
891 | }; |
892 | ||
d1f81a64 | 893 | module_platform_driver(sdhci_esdhc_driver); |
38576af1 SG |
894 | |
895 | MODULE_DESCRIPTION("SDHCI OF driver for Freescale MPC eSDHC"); | |
896 | MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, " | |
897 | "Anton Vorontsov <avorontsov@ru.mvista.com>"); | |
898 | MODULE_LICENSE("GPL v2"); |