0185-bcm2835-sdhost-Workaround-for-slow-sectors.patch 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. From 95ca033cb9ac492b060c0cc44093180871e8d63b Mon Sep 17 00:00:00 2001
  2. From: Phil Elwell <phil@raspberrypi.org>
  3. Date: Tue, 15 Mar 2016 14:10:29 +0000
  4. Subject: [PATCH] bcm2835-sdhost: Workaround for "slow" sectors
  5. Some cards have been seen to cause timeouts after certain sectors are
  6. read. This workaround enforces a minimum delay between the stop after
  7. reading one of those sectors and a subsequent data command.
  8. Using CMD23 (SET_BLOCK_COUNT) avoids this problem, so good cards will
  9. not be penalised by this workaround.
  10. Signed-off-by: Phil Elwell <phil@raspberrypi.org>
  11. ---
  12. drivers/mmc/host/bcm2835-sdhost.c | 50 +++++++++++++++++++++++++++++++++++----
  13. 1 file changed, 46 insertions(+), 4 deletions(-)
  14. --- a/drivers/mmc/host/bcm2835-sdhost.c
  15. +++ b/drivers/mmc/host/bcm2835-sdhost.c
  16. @@ -202,9 +202,12 @@ struct bcm2835_host {
  17. int max_delay; /* maximum length of time spent waiting */
  18. struct timeval stop_time; /* when the last stop was issued */
  19. u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */
  20. + u32 delay_after_this_stop; /* minimum time between this stop and subsequent data transfer */
  21. u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */
  22. u32 overclock; /* Current frequency if overclocked, else zero */
  23. u32 pio_limit; /* Maximum block count for PIO (0 = always DMA) */
  24. +
  25. + u32 sectors; /* Cached card size in sectors */
  26. };
  27. #if ENABLE_LOG
  28. @@ -425,6 +428,7 @@ static void bcm2835_sdhost_reset_interna
  29. bcm2835_sdhost_set_power(host, true);
  30. mdelay(10);
  31. host->clock = 0;
  32. + host->sectors = 0;
  33. bcm2835_sdhost_write(host, host->hcfg, SDHCFG);
  34. bcm2835_sdhost_write(host, host->cdiv, SDCDIV);
  35. mmiowb();
  36. @@ -880,6 +884,24 @@ static void bcm2835_sdhost_prepare_data(
  37. host->flush_fifo = 0;
  38. host->data->bytes_xfered = 0;
  39. + if (!host->sectors && host->mmc->card) {
  40. + struct mmc_card *card = host->mmc->card;
  41. + if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
  42. + /*
  43. + * The EXT_CSD sector count is in number of 512 byte
  44. + * sectors.
  45. + */
  46. + host->sectors = card->ext_csd.sectors;
  47. + } else {
  48. + /*
  49. + * The CSD capacity field is in units of read_blkbits.
  50. + * set_capacity takes units of 512 bytes.
  51. + */
  52. + host->sectors = card->csd.capacity <<
  53. + (card->csd.read_blkbits - 9);
  54. + }
  55. + }
  56. +
  57. if (!host->dma_desc) {
  58. /* Use PIO */
  59. int flags = SG_MITER_ATOMIC;
  60. @@ -989,7 +1011,7 @@ bool bcm2835_sdhost_send_command(struct
  61. if (cmd->data) {
  62. log_event("CMDD", cmd->data->blocks, cmd->data->blksz);
  63. - if (host->delay_after_stop) {
  64. + if (host->delay_after_this_stop) {
  65. struct timeval now;
  66. int time_since_stop;
  67. do_gettimeofday(&now);
  68. @@ -998,12 +1020,32 @@ bool bcm2835_sdhost_send_command(struct
  69. /* Possibly less than one second */
  70. time_since_stop = time_since_stop * 1000000 +
  71. (now.tv_usec - host->stop_time.tv_usec);
  72. - if (time_since_stop < host->delay_after_stop)
  73. - udelay(host->delay_after_stop -
  74. + if (time_since_stop <
  75. + host->delay_after_this_stop)
  76. + udelay(host->delay_after_this_stop -
  77. time_since_stop);
  78. }
  79. }
  80. + host->delay_after_this_stop = host->delay_after_stop;
  81. + if ((cmd->data->flags & MMC_DATA_READ) && !host->use_sbc) {
  82. + /* See if read crosses one of the hazardous sectors */
  83. + u32 first_blk, last_blk;
  84. +
  85. + /* Intentionally include the following sector because
  86. + without CMD23/SBC the read may run on. */
  87. + first_blk = host->mrq->cmd->arg;
  88. + last_blk = first_blk + cmd->data->blocks;
  89. +
  90. + if (((last_blk >= (host->sectors - 64)) &&
  91. + (first_blk <= (host->sectors - 64))) ||
  92. + ((last_blk >= (host->sectors - 32)) &&
  93. + (first_blk <= (host->sectors - 32)))) {
  94. + host->delay_after_this_stop =
  95. + max(250u, host->delay_after_stop);
  96. + }
  97. + }
  98. +
  99. if (cmd->data->flags & MMC_DATA_WRITE)
  100. sdcmd |= SDCMD_WRITE_CMD;
  101. if (cmd->data->flags & MMC_DATA_READ)
  102. @@ -1078,7 +1120,7 @@ static void bcm2835_sdhost_transfer_comp
  103. if (!host->use_busy)
  104. bcm2835_sdhost_finish_command(host, NULL);
  105. - if (host->delay_after_stop)
  106. + if (host->delay_after_this_stop)
  107. do_gettimeofday(&host->stop_time);
  108. }
  109. } else {