.. | .. |
---|
8 | 8 | |
---|
9 | 9 | #include <common.h> |
---|
10 | 10 | #include <bouncebuf.h> |
---|
| 11 | +#include <div64.h> |
---|
11 | 12 | #include <errno.h> |
---|
12 | 13 | #include <malloc.h> |
---|
13 | 14 | #include <memalign.h> |
---|
.. | .. |
---|
19 | 20 | #endif |
---|
20 | 21 | |
---|
21 | 22 | #define PAGE_SIZE 4096 |
---|
| 23 | +#define MSEC_PER_SEC 1000ULL |
---|
22 | 24 | |
---|
23 | 25 | /* |
---|
24 | 26 | * Currently it supports read/write up to 8*8*4 Bytes per |
---|
.. | .. |
---|
159 | 161 | dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks); |
---|
160 | 162 | } |
---|
161 | 163 | |
---|
162 | | -static unsigned int dwmci_get_timeout(struct mmc *mmc, const unsigned int size) |
---|
| 164 | +#ifdef CONFIG_SPL_BUILD |
---|
| 165 | +static unsigned int dwmci_get_drto(struct dwmci_host *host, |
---|
| 166 | + const unsigned int size) |
---|
| 167 | +{ |
---|
| 168 | + unsigned int drto_clks; |
---|
| 169 | + unsigned int drto_div; |
---|
| 170 | + unsigned int drto_ms; |
---|
| 171 | + |
---|
| 172 | + drto_clks = dwmci_readl(host, DWMCI_TMOUT) >> 8; |
---|
| 173 | + drto_div = (dwmci_readl(host, DWMCI_CLKDIV) & 0xff) * 2; |
---|
| 174 | + if (drto_div == 0) |
---|
| 175 | + drto_div = 1; |
---|
| 176 | + |
---|
| 177 | + drto_ms = DIV_ROUND_UP_ULL((u64)MSEC_PER_SEC * drto_clks * drto_div, |
---|
| 178 | + host->mmc->clock); |
---|
| 179 | + |
---|
| 180 | + /* add a bit spare time */ |
---|
| 181 | + drto_ms += 10; |
---|
| 182 | + |
---|
| 183 | + return drto_ms; |
---|
| 184 | +} |
---|
| 185 | +#else |
---|
| 186 | +static unsigned int dwmci_get_drto(struct dwmci_host *host, |
---|
| 187 | + const unsigned int size) |
---|
163 | 188 | { |
---|
164 | 189 | unsigned int timeout; |
---|
165 | 190 | |
---|
166 | 191 | timeout = size * 8; /* counting in bits */ |
---|
167 | 192 | timeout *= 10; /* wait 10 times as long */ |
---|
168 | | - timeout /= mmc->clock; |
---|
169 | | - timeout /= mmc->bus_width; |
---|
| 193 | + timeout /= host->mmc->clock; |
---|
| 194 | + timeout /= host->mmc->bus_width; |
---|
170 | 195 | timeout *= 1000; /* counting in msec */ |
---|
171 | 196 | timeout = (timeout < 10000) ? 10000 : timeout; |
---|
172 | 197 | |
---|
173 | 198 | return timeout; |
---|
| 199 | +} |
---|
| 200 | +#endif |
---|
| 201 | + |
---|
| 202 | +static unsigned int dwmci_get_cto(struct dwmci_host *host) |
---|
| 203 | +{ |
---|
| 204 | + unsigned int cto_clks; |
---|
| 205 | + unsigned int cto_div; |
---|
| 206 | + unsigned int cto_ms; |
---|
| 207 | + |
---|
| 208 | + cto_clks = dwmci_readl(host, DWMCI_TMOUT) & 0xff; |
---|
| 209 | + cto_div = (dwmci_readl(host, DWMCI_CLKDIV) & 0xff) * 2; |
---|
| 210 | + if (cto_div == 0) |
---|
| 211 | + cto_div = 1; |
---|
| 212 | + |
---|
| 213 | + cto_ms = DIV_ROUND_UP_ULL((u64)MSEC_PER_SEC * cto_clks * cto_div, |
---|
| 214 | + host->mmc->clock); |
---|
| 215 | + |
---|
| 216 | + /* add a bit spare time */ |
---|
| 217 | + cto_ms += 10; |
---|
| 218 | + |
---|
| 219 | + return cto_ms; |
---|
174 | 220 | } |
---|
175 | 221 | |
---|
176 | 222 | static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data) |
---|
.. | .. |
---|
192 | 238 | else |
---|
193 | 239 | buf = (unsigned int *)data->src; |
---|
194 | 240 | |
---|
195 | | - timeout = dwmci_get_timeout(host->mmc, size); |
---|
| 241 | + timeout = dwmci_get_drto(host, size); |
---|
196 | 242 | size /= 4; |
---|
197 | 243 | |
---|
198 | 244 | for (;;) { |
---|
.. | .. |
---|
252 | 298 | } |
---|
253 | 299 | dwmci_writel(host, DWMCI_RINTSTS, |
---|
254 | 300 | DWMCI_INTMSK_RXDR); |
---|
| 301 | + start = get_timer(0); |
---|
255 | 302 | } else if (data->flags == MMC_DATA_WRITE && |
---|
256 | 303 | (mask & DWMCI_INTMSK_TXDR)) { |
---|
257 | 304 | while (size) { |
---|
.. | .. |
---|
281 | 328 | } |
---|
282 | 329 | dwmci_writel(host, DWMCI_RINTSTS, |
---|
283 | 330 | DWMCI_INTMSK_TXDR); |
---|
| 331 | + start = get_timer(0); |
---|
284 | 332 | } |
---|
285 | 333 | } |
---|
286 | 334 | |
---|
.. | .. |
---|
329 | 377 | struct dwmci_host *host = mmc->priv; |
---|
330 | 378 | ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, |
---|
331 | 379 | data ? DIV_ROUND_UP(data->blocks, 8) : 0); |
---|
332 | | - int ret = 0, flags = 0, i; |
---|
| 380 | + int ret = 0, flags = 0; |
---|
333 | 381 | unsigned int timeout = 500; |
---|
334 | | - u32 retry = 100000; |
---|
335 | 382 | u32 mask, ctrl; |
---|
336 | 383 | ulong start = get_timer(0); |
---|
337 | 384 | struct bounce_buffer bbstate; |
---|
.. | .. |
---|
400 | 447 | |
---|
401 | 448 | dwmci_writel(host, DWMCI_CMD, flags); |
---|
402 | 449 | |
---|
403 | | - for (i = 0; i < retry; i++) { |
---|
| 450 | + timeout = dwmci_get_cto(host); |
---|
| 451 | + start = get_timer(0); |
---|
| 452 | + do { |
---|
404 | 453 | mask = dwmci_readl(host, DWMCI_RINTSTS); |
---|
405 | 454 | if (mask & DWMCI_INTMSK_CDONE) { |
---|
406 | 455 | if (!data) |
---|
407 | 456 | dwmci_writel(host, DWMCI_RINTSTS, mask); |
---|
408 | 457 | break; |
---|
409 | 458 | } |
---|
410 | | - } |
---|
| 459 | + } while (!(get_timer(start) > timeout)); |
---|
411 | 460 | |
---|
412 | | - if (i == retry) { |
---|
| 461 | + if (get_timer(start) > timeout) { |
---|
413 | 462 | debug("%s: Timeout.\n", __func__); |
---|
414 | 463 | return -ETIMEDOUT; |
---|
415 | 464 | } |
---|
.. | .. |
---|
470 | 519 | #endif |
---|
471 | 520 | struct dwmci_host *host = mmc->priv; |
---|
472 | 521 | struct dwmci_idmac *cur_idmac; |
---|
473 | | - int ret = 0, flags = 0, i; |
---|
| 522 | + int ret = 0, flags = 0; |
---|
474 | 523 | unsigned int timeout = 500; |
---|
475 | | - u32 retry = 100000; |
---|
476 | 524 | u32 mask; |
---|
477 | 525 | ulong start = get_timer(0); |
---|
478 | 526 | struct bounce_buffer bbstate; |
---|
.. | .. |
---|
541 | 589 | |
---|
542 | 590 | dwmci_writel(host, DWMCI_CMD, flags); |
---|
543 | 591 | |
---|
544 | | - for (i = 0; i < retry; i++) { |
---|
| 592 | + timeout = dwmci_get_cto(host); |
---|
| 593 | + start = get_timer(0); |
---|
| 594 | + do { |
---|
545 | 595 | mask = dwmci_readl(host, DWMCI_RINTSTS); |
---|
546 | 596 | if (mask & DWMCI_INTMSK_CDONE) { |
---|
547 | 597 | if (!data) |
---|
548 | 598 | dwmci_writel(host, DWMCI_RINTSTS, mask); |
---|
549 | 599 | break; |
---|
550 | 600 | } |
---|
551 | | - } |
---|
| 601 | + } while (!(get_timer(start) > timeout)); |
---|
552 | 602 | |
---|
553 | | - if (i == retry) { |
---|
| 603 | + if (get_timer(start) > timeout) { |
---|
554 | 604 | debug("%s: Timeout.\n", __func__); |
---|
555 | 605 | return -ETIMEDOUT; |
---|
556 | 606 | } |
---|