| .. | .. |
|---|
| 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 | } |
|---|