0234-bcm2835-sdhost-Reset-the-clock-in-task-context.patch 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. From c63af7f27233c7e7c6f0e4ee7d040e9545190df8 Mon Sep 17 00:00:00 2001
  2. From: Phil Elwell <phil@raspberrypi.org>
  3. Date: Mon, 11 Apr 2016 12:50:58 +0100
  4. Subject: [PATCH] bcm2835-sdhost: Reset the clock in task context
  5. Since reprogramming the clock can now involve a round-trip to the
  6. firmware it must not be done at atomic context, and a tasklet
  7. is not a task.
  8. Signed-off-by: Phil Elwell <phil@raspberrypi.org>
  9. ---
  10. drivers/mmc/host/bcm2835-sdhost.c | 25 ++++++++++++++++++-------
  11. 1 file changed, 18 insertions(+), 7 deletions(-)
  12. --- a/drivers/mmc/host/bcm2835-sdhost.c
  13. +++ b/drivers/mmc/host/bcm2835-sdhost.c
  14. @@ -185,6 +185,7 @@ struct bcm2835_host {
  15. unsigned int debug:1; /* Enable debug output */
  16. unsigned int firmware_sets_cdiv:1; /* Let the firmware manage the clock */
  17. + unsigned int reset_clock:1; /* Reset the clock fore the next request */
  18. /*DMA part*/
  19. struct dma_chan *dma_chan_rxtx; /* DMA channel for reads and writes */
  20. @@ -1505,6 +1506,7 @@ void bcm2835_sdhost_set_clock(struct bcm
  21. {
  22. int div = 0; /* Initialized for compiler warning */
  23. unsigned int input_clock = clock;
  24. + unsigned long flags;
  25. if (host->debug)
  26. pr_info("%s: set_clock(%d)\n", mmc_hostname(host->mmc), clock);
  27. @@ -1544,13 +1546,17 @@ void bcm2835_sdhost_set_clock(struct bcm
  28. &msg, sizeof(msg));
  29. clock = max(msg[1], msg[2]);
  30. + spin_lock_irqsave(&host->lock, flags);
  31. } else {
  32. + spin_lock_irqsave(&host->lock, flags);
  33. if (clock < 100000) {
  34. /* Can't stop the clock, but make it as slow as
  35. * possible to show willing
  36. */
  37. host->cdiv = SDCDIV_MAX_CDIV;
  38. bcm2835_sdhost_write(host, host->cdiv, SDCDIV);
  39. + mmiowb();
  40. + spin_unlock_irqrestore(&host->lock, flags);
  41. return;
  42. }
  43. @@ -1605,6 +1611,11 @@ void bcm2835_sdhost_set_clock(struct bcm
  44. bcm2835_sdhost_write(host, clock/2, SDTOUT);
  45. host->mmc->actual_clock = clock;
  46. + host->clock = input_clock;
  47. + host->reset_clock = 0;
  48. +
  49. + mmiowb();
  50. + spin_unlock_irqrestore(&host->lock, flags);
  51. }
  52. static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq)
  53. @@ -1653,6 +1664,9 @@ static void bcm2835_sdhost_request(struc
  54. (mrq->data->blocks > host->pio_limit))
  55. bcm2835_sdhost_prepare_dma(host, mrq->data);
  56. + if (host->reset_clock)
  57. + bcm2835_sdhost_set_clock(host, host->clock);
  58. +
  59. spin_lock_irqsave(&host->lock, flags);
  60. WARN_ON(host->mrq != NULL);
  61. @@ -1731,14 +1745,12 @@ static void bcm2835_sdhost_set_ios(struc
  62. bcm2835_sdhost_write(host, host->hcfg, SDHCFG);
  63. - if (!ios->clock || ios->clock != host->clock) {
  64. - bcm2835_sdhost_set_clock(host, ios->clock);
  65. - host->clock = ios->clock;
  66. - }
  67. -
  68. mmiowb();
  69. spin_unlock_irqrestore(&host->lock, flags);
  70. +
  71. + if (!ios->clock || ios->clock != host->clock)
  72. + bcm2835_sdhost_set_clock(host, ios->clock);
  73. }
  74. static struct mmc_host_ops bcm2835_sdhost_ops = {
  75. @@ -1810,7 +1822,7 @@ static void bcm2835_sdhost_tasklet_finis
  76. host->overclock_50--;
  77. pr_warn("%s: reducing overclock due to errors\n",
  78. mmc_hostname(host->mmc));
  79. - bcm2835_sdhost_set_clock(host,50*MHZ);
  80. + host->reset_clock = 1;
  81. mrq->cmd->error = -EILSEQ;
  82. mrq->cmd->retries = 1;
  83. }
  84. @@ -1979,7 +1991,6 @@ static int bcm2835_sdhost_probe(struct p
  85. mmc->ops = &bcm2835_sdhost_ops;
  86. host = mmc_priv(mmc);
  87. host->mmc = mmc;
  88. - host->cmd_quick_poll_retries = 0;
  89. host->pio_timeout = msecs_to_jiffies(500);
  90. host->pio_limit = 1;
  91. host->max_delay = 1; /* Warn if over 1ms */