]>
Commit | Line | Data |
---|---|---|
50586ef2 | 1 | /* |
d621da00 | 2 | * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc |
50586ef2 AF |
3 | * Andy Fleming |
4 | * | |
5 | * Based vaguely on the pxa mmc code: | |
6 | * (C) Copyright 2003 | |
7 | * Kyle Harris, Nexus Technologies, Inc. [email protected] | |
8 | * | |
1a459660 | 9 | * SPDX-License-Identifier: GPL-2.0+ |
50586ef2 AF |
10 | */ |
11 | ||
12 | #include <config.h> | |
13 | #include <common.h> | |
14 | #include <command.h> | |
b33433a6 | 15 | #include <hwconfig.h> |
50586ef2 AF |
16 | #include <mmc.h> |
17 | #include <part.h> | |
18 | #include <malloc.h> | |
19 | #include <mmc.h> | |
20 | #include <fsl_esdhc.h> | |
b33433a6 | 21 | #include <fdt_support.h> |
50586ef2 AF |
22 | #include <asm/io.h> |
23 | ||
50586ef2 AF |
24 | DECLARE_GLOBAL_DATA_PTR; |
25 | ||
a3d6e386 YL |
26 | #define SDHCI_IRQ_EN_BITS (IRQSTATEN_CC | IRQSTATEN_TC | \ |
27 | IRQSTATEN_CINT | \ | |
28 | IRQSTATEN_CTOE | IRQSTATEN_CCE | IRQSTATEN_CEBE | \ | |
29 | IRQSTATEN_CIE | IRQSTATEN_DTOE | IRQSTATEN_DCE | \ | |
30 | IRQSTATEN_DEBE | IRQSTATEN_BRR | IRQSTATEN_BWR | \ | |
31 | IRQSTATEN_DINT) | |
32 | ||
50586ef2 | 33 | struct fsl_esdhc { |
511948b2 HZ |
34 | uint dsaddr; /* SDMA system address register */ |
35 | uint blkattr; /* Block attributes register */ | |
36 | uint cmdarg; /* Command argument register */ | |
37 | uint xfertyp; /* Transfer type register */ | |
38 | uint cmdrsp0; /* Command response 0 register */ | |
39 | uint cmdrsp1; /* Command response 1 register */ | |
40 | uint cmdrsp2; /* Command response 2 register */ | |
41 | uint cmdrsp3; /* Command response 3 register */ | |
42 | uint datport; /* Buffer data port register */ | |
43 | uint prsstat; /* Present state register */ | |
44 | uint proctl; /* Protocol control register */ | |
45 | uint sysctl; /* System Control Register */ | |
46 | uint irqstat; /* Interrupt status register */ | |
47 | uint irqstaten; /* Interrupt status enable register */ | |
48 | uint irqsigen; /* Interrupt signal enable register */ | |
49 | uint autoc12err; /* Auto CMD error status register */ | |
50 | uint hostcapblt; /* Host controller capabilities register */ | |
51 | uint wml; /* Watermark level register */ | |
52 | uint mixctrl; /* For USDHC */ | |
53 | char reserved1[4]; /* reserved */ | |
54 | uint fevt; /* Force event register */ | |
55 | uint admaes; /* ADMA error status register */ | |
56 | uint adsaddr; /* ADMA system address register */ | |
f022d36e OS |
57 | char reserved2[100]; /* reserved */ |
58 | uint vendorspec; /* Vendor Specific register */ | |
323aaaa1 | 59 | char reserved3[56]; /* reserved */ |
511948b2 | 60 | uint hostver; /* Host controller version register */ |
511948b2 | 61 | char reserved4[4]; /* reserved */ |
f022d36e | 62 | uint dmaerraddr; /* DMA error address register */ |
511948b2 | 63 | char reserved5[4]; /* reserved */ |
f022d36e OS |
64 | uint dmaerrattr; /* DMA error attribute register */ |
65 | char reserved6[4]; /* reserved */ | |
511948b2 | 66 | uint hostcapblt2; /* Host controller capabilities register 2 */ |
f022d36e | 67 | char reserved7[8]; /* reserved */ |
511948b2 | 68 | uint tcr; /* Tuning control register */ |
f022d36e | 69 | char reserved8[28]; /* reserved */ |
511948b2 | 70 | uint sddirctl; /* SD direction control register */ |
f022d36e | 71 | char reserved9[712]; /* reserved */ |
511948b2 | 72 | uint scr; /* eSDHC control register */ |
50586ef2 AF |
73 | }; |
74 | ||
75 | /* Return the XFERTYP flags for a given command and data packet */ | |
eafa90a1 | 76 | static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) |
50586ef2 AF |
77 | { |
78 | uint xfertyp = 0; | |
79 | ||
80 | if (data) { | |
77c1458d DD |
81 | xfertyp |= XFERTYP_DPSEL; |
82 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO | |
83 | xfertyp |= XFERTYP_DMAEN; | |
84 | #endif | |
50586ef2 AF |
85 | if (data->blocks > 1) { |
86 | xfertyp |= XFERTYP_MSBSEL; | |
87 | xfertyp |= XFERTYP_BCEN; | |
d621da00 JH |
88 | #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111 |
89 | xfertyp |= XFERTYP_AC12EN; | |
90 | #endif | |
50586ef2 AF |
91 | } |
92 | ||
93 | if (data->flags & MMC_DATA_READ) | |
94 | xfertyp |= XFERTYP_DTDSEL; | |
95 | } | |
96 | ||
97 | if (cmd->resp_type & MMC_RSP_CRC) | |
98 | xfertyp |= XFERTYP_CCCEN; | |
99 | if (cmd->resp_type & MMC_RSP_OPCODE) | |
100 | xfertyp |= XFERTYP_CICEN; | |
101 | if (cmd->resp_type & MMC_RSP_136) | |
102 | xfertyp |= XFERTYP_RSPTYP_136; | |
103 | else if (cmd->resp_type & MMC_RSP_BUSY) | |
104 | xfertyp |= XFERTYP_RSPTYP_48_BUSY; | |
105 | else if (cmd->resp_type & MMC_RSP_PRESENT) | |
106 | xfertyp |= XFERTYP_RSPTYP_48; | |
107 | ||
8b06460e YL |
108 | #if defined(CONFIG_MX53) || defined(CONFIG_PPC_T4240) || \ |
109 | defined(CONFIG_LS102XA) || defined(CONFIG_LS2085A) | |
4571de33 JL |
110 | if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) |
111 | xfertyp |= XFERTYP_CMDTYP_ABORT; | |
112 | #endif | |
50586ef2 AF |
113 | return XFERTYP_CMD(cmd->cmdidx) | xfertyp; |
114 | } | |
115 | ||
77c1458d DD |
116 | #ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO |
117 | /* | |
118 | * PIO Read/Write Mode reduce the performace as DMA is not used in this mode. | |
119 | */ | |
7b43db92 | 120 | static void |
77c1458d DD |
121 | esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data) |
122 | { | |
8eee2bd7 IS |
123 | struct fsl_esdhc_cfg *cfg = mmc->priv; |
124 | struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; | |
77c1458d DD |
125 | uint blocks; |
126 | char *buffer; | |
127 | uint databuf; | |
128 | uint size; | |
129 | uint irqstat; | |
130 | uint timeout; | |
131 | ||
132 | if (data->flags & MMC_DATA_READ) { | |
133 | blocks = data->blocks; | |
134 | buffer = data->dest; | |
135 | while (blocks) { | |
136 | timeout = PIO_TIMEOUT; | |
137 | size = data->blocksize; | |
138 | irqstat = esdhc_read32(®s->irqstat); | |
139 | while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BREN) | |
140 | && --timeout); | |
141 | if (timeout <= 0) { | |
142 | printf("\nData Read Failed in PIO Mode."); | |
7b43db92 | 143 | return; |
77c1458d DD |
144 | } |
145 | while (size && (!(irqstat & IRQSTAT_TC))) { | |
146 | udelay(100); /* Wait before last byte transfer complete */ | |
147 | irqstat = esdhc_read32(®s->irqstat); | |
148 | databuf = in_le32(®s->datport); | |
149 | *((uint *)buffer) = databuf; | |
150 | buffer += 4; | |
151 | size -= 4; | |
152 | } | |
153 | blocks--; | |
154 | } | |
155 | } else { | |
156 | blocks = data->blocks; | |
7b43db92 | 157 | buffer = (char *)data->src; |
77c1458d DD |
158 | while (blocks) { |
159 | timeout = PIO_TIMEOUT; | |
160 | size = data->blocksize; | |
161 | irqstat = esdhc_read32(®s->irqstat); | |
162 | while (!(esdhc_read32(®s->prsstat) & PRSSTAT_BWEN) | |
163 | && --timeout); | |
164 | if (timeout <= 0) { | |
165 | printf("\nData Write Failed in PIO Mode."); | |
7b43db92 | 166 | return; |
77c1458d DD |
167 | } |
168 | while (size && (!(irqstat & IRQSTAT_TC))) { | |
169 | udelay(100); /* Wait before last byte transfer complete */ | |
170 | databuf = *((uint *)buffer); | |
171 | buffer += 4; | |
172 | size -= 4; | |
173 | irqstat = esdhc_read32(®s->irqstat); | |
174 | out_le32(®s->datport, databuf); | |
175 | } | |
176 | blocks--; | |
177 | } | |
178 | } | |
179 | } | |
180 | #endif | |
181 | ||
50586ef2 AF |
182 | static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) |
183 | { | |
50586ef2 | 184 | int timeout; |
93bfd616 | 185 | struct fsl_esdhc_cfg *cfg = mmc->priv; |
c67bee14 | 186 | struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; |
8b06460e YL |
187 | #ifdef CONFIG_LS2085A |
188 | dma_addr_t addr; | |
189 | #endif | |
7b43db92 | 190 | uint wml_value; |
50586ef2 AF |
191 | |
192 | wml_value = data->blocksize/4; | |
193 | ||
194 | if (data->flags & MMC_DATA_READ) { | |
32c8cfb2 PJ |
195 | if (wml_value > WML_RD_WML_MAX) |
196 | wml_value = WML_RD_WML_MAX_VAL; | |
50586ef2 | 197 | |
ab467c51 | 198 | esdhc_clrsetbits32(®s->wml, WML_RD_WML_MASK, wml_value); |
71689776 | 199 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO |
8b06460e YL |
200 | #ifdef CONFIG_LS2085A |
201 | addr = virt_to_phys((void *)(data->dest)); | |
202 | if (upper_32_bits(addr)) | |
203 | printf("Error found for upper 32 bits\n"); | |
204 | else | |
205 | esdhc_write32(®s->dsaddr, lower_32_bits(addr)); | |
206 | #else | |
c67bee14 | 207 | esdhc_write32(®s->dsaddr, (u32)data->dest); |
8b06460e | 208 | #endif |
71689776 | 209 | #endif |
50586ef2 | 210 | } else { |
71689776 | 211 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO |
e576bd90 EN |
212 | flush_dcache_range((ulong)data->src, |
213 | (ulong)data->src+data->blocks | |
214 | *data->blocksize); | |
71689776 | 215 | #endif |
32c8cfb2 PJ |
216 | if (wml_value > WML_WR_WML_MAX) |
217 | wml_value = WML_WR_WML_MAX_VAL; | |
c67bee14 | 218 | if ((esdhc_read32(®s->prsstat) & PRSSTAT_WPSPL) == 0) { |
50586ef2 AF |
219 | printf("\nThe SD card is locked. Can not write to a locked card.\n\n"); |
220 | return TIMEOUT; | |
221 | } | |
ab467c51 RZ |
222 | |
223 | esdhc_clrsetbits32(®s->wml, WML_WR_WML_MASK, | |
224 | wml_value << 16); | |
71689776 | 225 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO |
8b06460e YL |
226 | #ifdef CONFIG_LS2085A |
227 | addr = virt_to_phys((void *)(data->src)); | |
228 | if (upper_32_bits(addr)) | |
229 | printf("Error found for upper 32 bits\n"); | |
230 | else | |
231 | esdhc_write32(®s->dsaddr, lower_32_bits(addr)); | |
232 | #else | |
c67bee14 | 233 | esdhc_write32(®s->dsaddr, (u32)data->src); |
8b06460e | 234 | #endif |
71689776 | 235 | #endif |
50586ef2 AF |
236 | } |
237 | ||
c67bee14 | 238 | esdhc_write32(®s->blkattr, data->blocks << 16 | data->blocksize); |
50586ef2 AF |
239 | |
240 | /* Calculate the timeout period for data transactions */ | |
b71ea336 PJ |
241 | /* |
242 | * 1)Timeout period = (2^(timeout+13)) SD Clock cycles | |
243 | * 2)Timeout period should be minimum 0.250sec as per SD Card spec | |
244 | * So, Number of SD Clock cycles for 0.25sec should be minimum | |
245 | * (SD Clock/sec * 0.25 sec) SD Clock cycles | |
fb823981 | 246 | * = (mmc->clock * 1/4) SD Clock cycles |
b71ea336 | 247 | * As 1) >= 2) |
fb823981 | 248 | * => (2^(timeout+13)) >= mmc->clock * 1/4 |
b71ea336 | 249 | * Taking log2 both the sides |
fb823981 | 250 | * => timeout + 13 >= log2(mmc->clock/4) |
b71ea336 | 251 | * Rounding up to next power of 2 |
fb823981 AG |
252 | * => timeout + 13 = log2(mmc->clock/4) + 1 |
253 | * => timeout + 13 = fls(mmc->clock/4) | |
b71ea336 | 254 | */ |
fb823981 | 255 | timeout = fls(mmc->clock/4); |
50586ef2 AF |
256 | timeout -= 13; |
257 | ||
258 | if (timeout > 14) | |
259 | timeout = 14; | |
260 | ||
261 | if (timeout < 0) | |
262 | timeout = 0; | |
263 | ||
5103a03a KG |
264 | #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC_A001 |
265 | if ((timeout == 4) || (timeout == 8) || (timeout == 12)) | |
266 | timeout++; | |
267 | #endif | |
268 | ||
1336e2d3 HZ |
269 | #ifdef ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE |
270 | timeout = 0xE; | |
271 | #endif | |
c67bee14 | 272 | esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16); |
50586ef2 AF |
273 | |
274 | return 0; | |
275 | } | |
276 | ||
10dc7771 | 277 | #ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO |
e576bd90 EN |
278 | static void check_and_invalidate_dcache_range |
279 | (struct mmc_cmd *cmd, | |
280 | struct mmc_data *data) { | |
8b06460e YL |
281 | #ifdef CONFIG_LS2085A |
282 | unsigned start = 0; | |
283 | #else | |
e576bd90 | 284 | unsigned start = (unsigned)data->dest ; |
8b06460e | 285 | #endif |
e576bd90 EN |
286 | unsigned size = roundup(ARCH_DMA_MINALIGN, |
287 | data->blocks*data->blocksize); | |
288 | unsigned end = start+size ; | |
8b06460e YL |
289 | #ifdef CONFIG_LS2085A |
290 | dma_addr_t addr; | |
291 | ||
292 | addr = virt_to_phys((void *)(data->dest)); | |
293 | if (upper_32_bits(addr)) | |
294 | printf("Error found for upper 32 bits\n"); | |
295 | else | |
296 | start = lower_32_bits(addr); | |
297 | #endif | |
e576bd90 EN |
298 | invalidate_dcache_range(start, end); |
299 | } | |
10dc7771 TR |
300 | #endif |
301 | ||
50586ef2 AF |
302 | /* |
303 | * Sends a command out on the bus. Takes the mmc pointer, | |
304 | * a command pointer, and an optional data pointer. | |
305 | */ | |
306 | static int | |
307 | esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) | |
308 | { | |
8a573022 | 309 | int err = 0; |
50586ef2 AF |
310 | uint xfertyp; |
311 | uint irqstat; | |
93bfd616 | 312 | struct fsl_esdhc_cfg *cfg = mmc->priv; |
c67bee14 | 313 | volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; |
50586ef2 | 314 | |
d621da00 JH |
315 | #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111 |
316 | if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) | |
317 | return 0; | |
318 | #endif | |
319 | ||
c67bee14 | 320 | esdhc_write32(®s->irqstat, -1); |
50586ef2 AF |
321 | |
322 | sync(); | |
323 | ||
324 | /* Wait for the bus to be idle */ | |
c67bee14 SB |
325 | while ((esdhc_read32(®s->prsstat) & PRSSTAT_CICHB) || |
326 | (esdhc_read32(®s->prsstat) & PRSSTAT_CIDHB)) | |
327 | ; | |
50586ef2 | 328 | |
c67bee14 SB |
329 | while (esdhc_read32(®s->prsstat) & PRSSTAT_DLA) |
330 | ; | |
50586ef2 AF |
331 | |
332 | /* Wait at least 8 SD clock cycles before the next command */ | |
333 | /* | |
334 | * Note: This is way more than 8 cycles, but 1ms seems to | |
335 | * resolve timing issues with some cards | |
336 | */ | |
337 | udelay(1000); | |
338 | ||
339 | /* Set up for a data transfer if we have one */ | |
340 | if (data) { | |
50586ef2 AF |
341 | err = esdhc_setup_data(mmc, data); |
342 | if(err) | |
343 | return err; | |
344 | } | |
345 | ||
346 | /* Figure out the transfer arguments */ | |
347 | xfertyp = esdhc_xfertyp(cmd, data); | |
348 | ||
01b77353 AG |
349 | /* Mask all irqs */ |
350 | esdhc_write32(®s->irqsigen, 0); | |
351 | ||
50586ef2 | 352 | /* Send the command */ |
c67bee14 | 353 | esdhc_write32(®s->cmdarg, cmd->cmdarg); |
4692708d JL |
354 | #if defined(CONFIG_FSL_USDHC) |
355 | esdhc_write32(®s->mixctrl, | |
0e1bf614 VR |
356 | (esdhc_read32(®s->mixctrl) & 0xFFFFFF80) | (xfertyp & 0x7F) |
357 | | (mmc->ddr_mode ? XFERTYP_DDREN : 0)); | |
4692708d JL |
358 | esdhc_write32(®s->xfertyp, xfertyp & 0xFFFF0000); |
359 | #else | |
c67bee14 | 360 | esdhc_write32(®s->xfertyp, xfertyp); |
4692708d | 361 | #endif |
7a5b8029 | 362 | |
50586ef2 | 363 | /* Wait for the command to complete */ |
7a5b8029 | 364 | while (!(esdhc_read32(®s->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE))) |
c67bee14 | 365 | ; |
50586ef2 | 366 | |
c67bee14 | 367 | irqstat = esdhc_read32(®s->irqstat); |
50586ef2 | 368 | |
8a573022 AG |
369 | if (irqstat & CMD_ERR) { |
370 | err = COMM_ERR; | |
371 | goto out; | |
7a5b8029 DB |
372 | } |
373 | ||
8a573022 AG |
374 | if (irqstat & IRQSTAT_CTOE) { |
375 | err = TIMEOUT; | |
376 | goto out; | |
377 | } | |
50586ef2 | 378 | |
f022d36e OS |
379 | /* Switch voltage to 1.8V if CMD11 succeeded */ |
380 | if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) { | |
381 | esdhc_setbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); | |
382 | ||
383 | printf("Run CMD11 1.8V switch\n"); | |
384 | /* Sleep for 5 ms - max time for card to switch to 1.8V */ | |
385 | udelay(5000); | |
386 | } | |
387 | ||
7a5b8029 DB |
388 | /* Workaround for ESDHC errata ENGcm03648 */ |
389 | if (!data && (cmd->resp_type & MMC_RSP_BUSY)) { | |
390 | int timeout = 2500; | |
391 | ||
392 | /* Poll on DATA0 line for cmd with busy signal for 250 ms */ | |
393 | while (timeout > 0 && !(esdhc_read32(®s->prsstat) & | |
394 | PRSSTAT_DAT0)) { | |
395 | udelay(100); | |
396 | timeout--; | |
397 | } | |
398 | ||
399 | if (timeout <= 0) { | |
400 | printf("Timeout waiting for DAT0 to go high!\n"); | |
8a573022 AG |
401 | err = TIMEOUT; |
402 | goto out; | |
7a5b8029 DB |
403 | } |
404 | } | |
405 | ||
50586ef2 AF |
406 | /* Copy the response to the response buffer */ |
407 | if (cmd->resp_type & MMC_RSP_136) { | |
408 | u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; | |
409 | ||
c67bee14 SB |
410 | cmdrsp3 = esdhc_read32(®s->cmdrsp3); |
411 | cmdrsp2 = esdhc_read32(®s->cmdrsp2); | |
412 | cmdrsp1 = esdhc_read32(®s->cmdrsp1); | |
413 | cmdrsp0 = esdhc_read32(®s->cmdrsp0); | |
998be3dd RV |
414 | cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); |
415 | cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); | |
416 | cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); | |
417 | cmd->response[3] = (cmdrsp0 << 8); | |
50586ef2 | 418 | } else |
c67bee14 | 419 | cmd->response[0] = esdhc_read32(®s->cmdrsp0); |
50586ef2 AF |
420 | |
421 | /* Wait until all of the blocks are transferred */ | |
422 | if (data) { | |
77c1458d DD |
423 | #ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO |
424 | esdhc_pio_read_write(mmc, data); | |
425 | #else | |
50586ef2 | 426 | do { |
c67bee14 | 427 | irqstat = esdhc_read32(®s->irqstat); |
50586ef2 | 428 | |
8a573022 AG |
429 | if (irqstat & IRQSTAT_DTOE) { |
430 | err = TIMEOUT; | |
431 | goto out; | |
432 | } | |
63fb5a7e | 433 | |
8a573022 AG |
434 | if (irqstat & DATA_ERR) { |
435 | err = COMM_ERR; | |
436 | goto out; | |
437 | } | |
9b74dc56 | 438 | } while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE); |
71689776 | 439 | |
54899fc8 EN |
440 | if (data->flags & MMC_DATA_READ) |
441 | check_and_invalidate_dcache_range(cmd, data); | |
71689776 | 442 | #endif |
50586ef2 AF |
443 | } |
444 | ||
8a573022 AG |
445 | out: |
446 | /* Reset CMD and DATA portions on error */ | |
447 | if (err) { | |
448 | esdhc_write32(®s->sysctl, esdhc_read32(®s->sysctl) | | |
449 | SYSCTL_RSTC); | |
450 | while (esdhc_read32(®s->sysctl) & SYSCTL_RSTC) | |
451 | ; | |
452 | ||
453 | if (data) { | |
454 | esdhc_write32(®s->sysctl, | |
455 | esdhc_read32(®s->sysctl) | | |
456 | SYSCTL_RSTD); | |
457 | while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTD)) | |
458 | ; | |
459 | } | |
f022d36e OS |
460 | |
461 | /* If this was CMD11, then notify that power cycle is needed */ | |
462 | if (cmd->cmdidx == SD_CMD_SWITCH_UHS18V) | |
463 | printf("CMD11 to switch to 1.8V mode failed, card requires power cycle.\n"); | |
8a573022 AG |
464 | } |
465 | ||
c67bee14 | 466 | esdhc_write32(®s->irqstat, -1); |
50586ef2 | 467 | |
8a573022 | 468 | return err; |
50586ef2 AF |
469 | } |
470 | ||
eafa90a1 | 471 | static void set_sysctl(struct mmc *mmc, uint clock) |
50586ef2 | 472 | { |
50586ef2 | 473 | int div, pre_div; |
93bfd616 | 474 | struct fsl_esdhc_cfg *cfg = mmc->priv; |
c67bee14 | 475 | volatile struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; |
a2ac1b3a | 476 | int sdhc_clk = cfg->sdhc_clk; |
50586ef2 AF |
477 | uint clk; |
478 | ||
93bfd616 PA |
479 | if (clock < mmc->cfg->f_min) |
480 | clock = mmc->cfg->f_min; | |
c67bee14 | 481 | |
50586ef2 AF |
482 | if (sdhc_clk / 16 > clock) { |
483 | for (pre_div = 2; pre_div < 256; pre_div *= 2) | |
484 | if ((sdhc_clk / pre_div) <= (clock * 16)) | |
485 | break; | |
486 | } else | |
487 | pre_div = 2; | |
488 | ||
489 | for (div = 1; div <= 16; div++) | |
490 | if ((sdhc_clk / (div * pre_div)) <= clock) | |
491 | break; | |
492 | ||
0e1bf614 | 493 | pre_div >>= mmc->ddr_mode ? 2 : 1; |
50586ef2 AF |
494 | div -= 1; |
495 | ||
496 | clk = (pre_div << 8) | (div << 4); | |
497 | ||
cc4d1226 | 498 | esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); |
c67bee14 SB |
499 | |
500 | esdhc_clrsetbits32(®s->sysctl, SYSCTL_CLOCK_MASK, clk); | |
50586ef2 AF |
501 | |
502 | udelay(10000); | |
503 | ||
cc4d1226 | 504 | clk = SYSCTL_PEREN | SYSCTL_CKEN; |
c67bee14 SB |
505 | |
506 | esdhc_setbits32(®s->sysctl, clk); | |
50586ef2 AF |
507 | } |
508 | ||
509 | static void esdhc_set_ios(struct mmc *mmc) | |
510 | { | |
93bfd616 | 511 | struct fsl_esdhc_cfg *cfg = mmc->priv; |
c67bee14 | 512 | struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; |
50586ef2 AF |
513 | |
514 | /* Set the clock speed */ | |
515 | set_sysctl(mmc, mmc->clock); | |
516 | ||
517 | /* Set the bus width */ | |
c67bee14 | 518 | esdhc_clrbits32(®s->proctl, PROCTL_DTW_4 | PROCTL_DTW_8); |
50586ef2 AF |
519 | |
520 | if (mmc->bus_width == 4) | |
c67bee14 | 521 | esdhc_setbits32(®s->proctl, PROCTL_DTW_4); |
50586ef2 | 522 | else if (mmc->bus_width == 8) |
c67bee14 SB |
523 | esdhc_setbits32(®s->proctl, PROCTL_DTW_8); |
524 | ||
50586ef2 AF |
525 | } |
526 | ||
527 | static int esdhc_init(struct mmc *mmc) | |
528 | { | |
93bfd616 | 529 | struct fsl_esdhc_cfg *cfg = mmc->priv; |
c67bee14 | 530 | struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; |
50586ef2 AF |
531 | int timeout = 1000; |
532 | ||
c67bee14 | 533 | /* Reset the entire host controller */ |
a61da72b | 534 | esdhc_setbits32(®s->sysctl, SYSCTL_RSTA); |
c67bee14 SB |
535 | |
536 | /* Wait until the controller is available */ | |
537 | while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA) && --timeout) | |
538 | udelay(1000); | |
50586ef2 | 539 | |
16e43f35 | 540 | #ifndef ARCH_MXC |
2c1764ef | 541 | /* Enable cache snooping */ |
16e43f35 BT |
542 | esdhc_write32(®s->scr, 0x00000040); |
543 | #endif | |
2c1764ef | 544 | |
a61da72b | 545 | esdhc_setbits32(®s->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN); |
50586ef2 AF |
546 | |
547 | /* Set the initial clock speed */ | |
4a6ee172 | 548 | mmc_set_clock(mmc, 400000); |
50586ef2 AF |
549 | |
550 | /* Disable the BRR and BWR bits in IRQSTAT */ | |
c67bee14 | 551 | esdhc_clrbits32(®s->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR); |
50586ef2 AF |
552 | |
553 | /* Put the PROCTL reg back to the default */ | |
c67bee14 | 554 | esdhc_write32(®s->proctl, PROCTL_INIT); |
50586ef2 | 555 | |
c67bee14 SB |
556 | /* Set timout to the maximum value */ |
557 | esdhc_clrsetbits32(®s->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16); | |
50586ef2 | 558 | |
ee0c5389 OS |
559 | #ifdef CONFIG_SYS_FSL_ESDHC_FORCE_VSELECT |
560 | esdhc_setbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); | |
561 | #endif | |
562 | ||
d48d2e21 TR |
563 | return 0; |
564 | } | |
50586ef2 | 565 | |
d48d2e21 TR |
566 | static int esdhc_getcd(struct mmc *mmc) |
567 | { | |
93bfd616 | 568 | struct fsl_esdhc_cfg *cfg = mmc->priv; |
d48d2e21 TR |
569 | struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; |
570 | int timeout = 1000; | |
571 | ||
f7e27cc5 HZ |
572 | #ifdef CONFIG_ESDHC_DETECT_QUIRK |
573 | if (CONFIG_ESDHC_DETECT_QUIRK) | |
574 | return 1; | |
575 | #endif | |
d48d2e21 TR |
576 | while (!(esdhc_read32(®s->prsstat) & PRSSTAT_CINS) && --timeout) |
577 | udelay(1000); | |
c67bee14 | 578 | |
d48d2e21 | 579 | return timeout > 0; |
50586ef2 AF |
580 | } |
581 | ||
48bb3bb5 JH |
582 | static void esdhc_reset(struct fsl_esdhc *regs) |
583 | { | |
584 | unsigned long timeout = 100; /* wait max 100 ms */ | |
585 | ||
586 | /* reset the controller */ | |
a61da72b | 587 | esdhc_setbits32(®s->sysctl, SYSCTL_RSTA); |
48bb3bb5 JH |
588 | |
589 | /* hardware clears the bit when it is done */ | |
590 | while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA) && --timeout) | |
591 | udelay(1000); | |
592 | if (!timeout) | |
593 | printf("MMC/SD: Reset never completed.\n"); | |
594 | } | |
595 | ||
ab769f22 PA |
596 | static const struct mmc_ops esdhc_ops = { |
597 | .send_cmd = esdhc_send_cmd, | |
598 | .set_ios = esdhc_set_ios, | |
599 | .init = esdhc_init, | |
600 | .getcd = esdhc_getcd, | |
601 | }; | |
602 | ||
c67bee14 | 603 | int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) |
50586ef2 | 604 | { |
c67bee14 | 605 | struct fsl_esdhc *regs; |
50586ef2 | 606 | struct mmc *mmc; |
030955c2 | 607 | u32 caps, voltage_caps; |
50586ef2 | 608 | |
c67bee14 SB |
609 | if (!cfg) |
610 | return -1; | |
611 | ||
c67bee14 SB |
612 | regs = (struct fsl_esdhc *)cfg->esdhc_base; |
613 | ||
48bb3bb5 JH |
614 | /* First reset the eSDHC controller */ |
615 | esdhc_reset(regs); | |
616 | ||
975324a7 JH |
617 | esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN |
618 | | SYSCTL_IPGEN | SYSCTL_CKEN); | |
619 | ||
a3d6e386 | 620 | writel(SDHCI_IRQ_EN_BITS, ®s->irqstaten); |
93bfd616 PA |
621 | memset(&cfg->cfg, 0, sizeof(cfg->cfg)); |
622 | ||
030955c2 | 623 | voltage_caps = 0; |
19060bd8 | 624 | caps = esdhc_read32(®s->hostcapblt); |
3b4456ec RZ |
625 | |
626 | #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135 | |
627 | caps = caps & ~(ESDHC_HOSTCAPBLT_SRS | | |
628 | ESDHC_HOSTCAPBLT_VS18 | ESDHC_HOSTCAPBLT_VS30); | |
629 | #endif | |
ef38f3ff HZ |
630 | |
631 | /* T4240 host controller capabilities register should have VS33 bit */ | |
632 | #ifdef CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33 | |
633 | caps = caps | ESDHC_HOSTCAPBLT_VS33; | |
634 | #endif | |
635 | ||
50586ef2 | 636 | if (caps & ESDHC_HOSTCAPBLT_VS18) |
030955c2 | 637 | voltage_caps |= MMC_VDD_165_195; |
50586ef2 | 638 | if (caps & ESDHC_HOSTCAPBLT_VS30) |
030955c2 | 639 | voltage_caps |= MMC_VDD_29_30 | MMC_VDD_30_31; |
50586ef2 | 640 | if (caps & ESDHC_HOSTCAPBLT_VS33) |
030955c2 LY |
641 | voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34; |
642 | ||
93bfd616 PA |
643 | cfg->cfg.name = "FSL_SDHC"; |
644 | cfg->cfg.ops = &esdhc_ops; | |
030955c2 | 645 | #ifdef CONFIG_SYS_SD_VOLTAGE |
93bfd616 | 646 | cfg->cfg.voltages = CONFIG_SYS_SD_VOLTAGE; |
030955c2 | 647 | #else |
93bfd616 | 648 | cfg->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; |
030955c2 | 649 | #endif |
93bfd616 | 650 | if ((cfg->cfg.voltages & voltage_caps) == 0) { |
030955c2 LY |
651 | printf("voltage not supported by controller\n"); |
652 | return -1; | |
653 | } | |
50586ef2 | 654 | |
93bfd616 | 655 | cfg->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_HC; |
0e1bf614 VR |
656 | #ifdef CONFIG_SYS_FSL_ESDHC_HAS_DDR_MODE |
657 | cfg->cfg.host_caps |= MMC_MODE_DDR_52MHz; | |
658 | #endif | |
50586ef2 | 659 | |
aad4659a AR |
660 | if (cfg->max_bus_width > 0) { |
661 | if (cfg->max_bus_width < 8) | |
93bfd616 | 662 | cfg->cfg.host_caps &= ~MMC_MODE_8BIT; |
aad4659a | 663 | if (cfg->max_bus_width < 4) |
93bfd616 | 664 | cfg->cfg.host_caps &= ~MMC_MODE_4BIT; |
aad4659a AR |
665 | } |
666 | ||
50586ef2 | 667 | if (caps & ESDHC_HOSTCAPBLT_HSS) |
93bfd616 | 668 | cfg->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; |
50586ef2 | 669 | |
d47e3d27 HZ |
670 | #ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK |
671 | if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK) | |
93bfd616 | 672 | cfg->cfg.host_caps &= ~MMC_MODE_8BIT; |
d47e3d27 HZ |
673 | #endif |
674 | ||
93bfd616 | 675 | cfg->cfg.f_min = 400000; |
21008ad6 | 676 | cfg->cfg.f_max = min(cfg->sdhc_clk, (u32)52000000); |
50586ef2 | 677 | |
93bfd616 PA |
678 | cfg->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; |
679 | ||
680 | mmc = mmc_create(&cfg->cfg, cfg); | |
681 | if (mmc == NULL) | |
682 | return -1; | |
50586ef2 AF |
683 | |
684 | return 0; | |
685 | } | |
686 | ||
687 | int fsl_esdhc_mmc_init(bd_t *bis) | |
688 | { | |
c67bee14 SB |
689 | struct fsl_esdhc_cfg *cfg; |
690 | ||
88227a1d | 691 | cfg = calloc(sizeof(struct fsl_esdhc_cfg), 1); |
c67bee14 | 692 | cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR; |
e9adeca3 | 693 | cfg->sdhc_clk = gd->arch.sdhc_clk; |
c67bee14 | 694 | return fsl_esdhc_initialize(bis, cfg); |
50586ef2 | 695 | } |
b33433a6 | 696 | |
c67bee14 | 697 | #ifdef CONFIG_OF_LIBFDT |
b33433a6 AV |
698 | void fdt_fixup_esdhc(void *blob, bd_t *bd) |
699 | { | |
700 | const char *compat = "fsl,esdhc"; | |
b33433a6 | 701 | |
a6da8b81 | 702 | #ifdef CONFIG_FSL_ESDHC_PIN_MUX |
b33433a6 | 703 | if (!hwconfig("esdhc")) { |
a6da8b81 CZ |
704 | do_fixup_by_compat(blob, compat, "status", "disabled", |
705 | 8 + 1, 1); | |
706 | return; | |
b33433a6 | 707 | } |
a6da8b81 | 708 | #endif |
b33433a6 AV |
709 | |
710 | do_fixup_by_compat_u32(blob, compat, "clock-frequency", | |
e9adeca3 | 711 | gd->arch.sdhc_clk, 1); |
a6da8b81 CZ |
712 | |
713 | do_fixup_by_compat(blob, compat, "status", "okay", | |
714 | 4 + 1, 1); | |
b33433a6 | 715 | } |
c67bee14 | 716 | #endif |