0223-Revert-bcm2835-sdhost-Precalc-divisors-and-overclock.patch 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. From 28d6ecd622da2efdb7a7c6c07ab8a92c82dded6b Mon Sep 17 00:00:00 2001
  2. From: Phil Elwell <phil@raspberrypi.org>
  3. Date: Mon, 4 Apr 2016 12:35:32 +0100
  4. Subject: [PATCH 223/381] Revert "bcm2835-sdhost: Precalc divisors and
  5. overclocks"
  6. This reverts commit 20260462773366a5734e5268dae0a4c179a21a2d.
  7. ---
  8. drivers/mmc/host/bcm2835-sdhost.c | 152 ++++++++++++++++----------------------
  9. 1 file changed, 64 insertions(+), 88 deletions(-)
  10. --- a/drivers/mmc/host/bcm2835-sdhost.c
  11. +++ b/drivers/mmc/host/bcm2835-sdhost.c
  12. @@ -154,15 +154,12 @@ struct bcm2835_host {
  13. u32 pio_timeout; /* In jiffies */
  14. int clock; /* Current clock speed */
  15. - int clocks[2];
  16. bool slow_card; /* Force 11-bit divisor */
  17. unsigned int max_clk; /* Max src clock freq */
  18. - unsigned int src_clks[2]; /* Min/max src clock freqs */
  19. - unsigned int cur_clk_idx; /* Index of current clock */
  20. - unsigned int next_clk_idx; /* Next clock index */
  21. - unsigned int cdivs[2];
  22. + unsigned int min_clk; /* Min src clock freq */
  23. + unsigned int cur_clk; /* Current src clock freq */
  24. struct tasklet_struct finish_tasklet; /* Tasklet structures */
  25. @@ -216,7 +213,7 @@ struct bcm2835_host {
  26. u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */
  27. u32 delay_after_this_stop; /* minimum time between this stop and subsequent data transfer */
  28. u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */
  29. - u32 prev_overclock_50;
  30. + u32 overclock; /* Current frequency if overclocked, else zero */
  31. u32 pio_limit; /* Maximum block count for PIO (0 = always DMA) */
  32. u32 sectors; /* Cached card size in sectors */
  33. @@ -1512,35 +1509,10 @@ static irqreturn_t bcm2835_sdhost_irq(in
  34. return result;
  35. }
  36. -static void bcm2835_sdhost_select_clock(struct bcm2835_host *host, int idx)
  37. -{
  38. - unsigned int clock = host->clocks[idx];
  39. - unsigned int cdiv = host->cdivs[idx];
  40. -
  41. - host->mmc->actual_clock = clock;
  42. - host->ns_per_fifo_word = (1000000000/clock) *
  43. - ((host->mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32);
  44. -
  45. - host->cdiv = cdiv;
  46. - bcm2835_sdhost_write(host, host->cdiv, SDCDIV);
  47. -
  48. - /* Set the timeout to 500ms */
  49. - bcm2835_sdhost_write(host, clock/2, SDTOUT);
  50. -
  51. - host->cur_clk_idx = host->next_clk_idx = idx;
  52. -
  53. - if (host->debug)
  54. - pr_info("%s: clock=%d -> src_clk=%d, cdiv=%x (actual %d)\n",
  55. - mmc_hostname(host->mmc), host->clock,
  56. - host->src_clks[idx], host->cdiv,
  57. - host->mmc->actual_clock);
  58. -}
  59. -
  60. void bcm2835_sdhost_set_clock(struct bcm2835_host *host)
  61. {
  62. int div = 0; /* Initialized for compiler warning */
  63. unsigned int clock = host->clock;
  64. - int clk_idx;
  65. if (host->debug)
  66. pr_info("%s: set_clock(%d)\n", mmc_hostname(host->mmc), clock);
  67. @@ -1581,45 +1553,53 @@ void bcm2835_sdhost_set_clock(struct bcm
  68. return;
  69. }
  70. - /* Calculate the clock divisors */
  71. - for (clk_idx = 0; clk_idx <= host->variable_clock; clk_idx++)
  72. - {
  73. - unsigned int cur_clk = host->src_clks[clk_idx];
  74. - unsigned int actual_clock;
  75. + div = host->cur_clk / clock;
  76. + if (div < 2)
  77. + div = 2;
  78. + if ((host->cur_clk / div) > clock)
  79. + div++;
  80. + div -= 2;
  81. +
  82. + if (div > SDCDIV_MAX_CDIV)
  83. + div = SDCDIV_MAX_CDIV;
  84. +
  85. + clock = host->cur_clk / (div + 2);
  86. + host->mmc->actual_clock = clock;
  87. +
  88. + /* Calibrate some delays */
  89. +
  90. + host->ns_per_fifo_word = (1000000000/clock) *
  91. + ((host->mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32);
  92. - div = cur_clk / clock;
  93. - if (div < 2)
  94. - div = 2;
  95. - if ((cur_clk / div) > clock)
  96. - div++;
  97. - div -= 2;
  98. -
  99. - if (div > SDCDIV_MAX_CDIV)
  100. - div = SDCDIV_MAX_CDIV;
  101. - actual_clock = cur_clk / (div + 2);
  102. -
  103. - host->cdivs[clk_idx] = div;
  104. - host->clocks[clk_idx] = actual_clock;
  105. -
  106. - if (host->overclock_50 != host->prev_overclock_50) {
  107. - const char *clk_name = "";
  108. - if (host->variable_clock)
  109. - clk_name = clk_idx ? " (turbo)" : " (normal)";
  110. - if (actual_clock > host->clock)
  111. - pr_info("%s: overclocking to %dHz%s\n",
  112. - mmc_hostname(host->mmc),
  113. - actual_clock, clk_name);
  114. - else if ((host->overclock_50 < 50) && (clk_idx == 0))
  115. - pr_info("%s: cancelling overclock%s\n",
  116. - mmc_hostname(host->mmc),
  117. - host->variable_clock ? "s" : "");
  118. + if (clock > host->clock) {
  119. + /* Save the closest value, to make it easier
  120. + to reduce in the event of error */
  121. + host->overclock_50 = (clock/MHZ);
  122. +
  123. + if (clock != host->overclock) {
  124. + pr_warn("%s: overclocking to %dHz\n",
  125. + mmc_hostname(host->mmc), clock);
  126. + host->overclock = clock;
  127. }
  128. }
  129. + else if (host->overclock)
  130. + {
  131. + host->overclock = 0;
  132. + if (clock == 50 * MHZ)
  133. + pr_warn("%s: cancelling overclock\n",
  134. + mmc_hostname(host->mmc));
  135. + }
  136. - if (host->clock == 50*MHZ)
  137. - host->prev_overclock_50 = host->overclock_50;
  138. + host->cdiv = div;
  139. + bcm2835_sdhost_write(host, host->cdiv, SDCDIV);
  140. - bcm2835_sdhost_select_clock(host, host->cur_clk_idx);
  141. + /* Set the timeout to 500ms */
  142. + bcm2835_sdhost_write(host, host->mmc->actual_clock/2, SDTOUT);
  143. +
  144. + if (host->debug)
  145. + pr_info("%s: clock=%d -> cur_clk=%d, cdiv=%x (actual clock %d)\n",
  146. + mmc_hostname(host->mmc), host->clock,
  147. + host->cur_clk, host->cdiv, host->mmc->actual_clock);
  148. }
  149. static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq)
  150. @@ -1677,9 +1657,6 @@ static void bcm2835_sdhost_request(struc
  151. spin_lock_irqsave(&host->lock, flags);
  152. - if (host->next_clk_idx != host->cur_clk_idx)
  153. - bcm2835_sdhost_select_clock(host, host->next_clk_idx);
  154. -
  155. WARN_ON(host->mrq != NULL);
  156. host->mrq = mrq;
  157. @@ -1742,7 +1719,11 @@ static int bcm2835_sdhost_cpufreq_callba
  158. return NOTIFY_BAD;
  159. break;
  160. case CPUFREQ_POSTCHANGE:
  161. - host->next_clk_idx = (freq->new > freq->old);
  162. + if (freq->new > freq->old)
  163. + host->cur_clk = host->max_clk;
  164. + else
  165. + host->cur_clk = host->min_clk;
  166. + bcm2835_sdhost_set_clock(host);
  167. up(&host->cpufreq_semaphore);
  168. break;
  169. default:
  170. @@ -1782,11 +1763,8 @@ static void bcm2835_sdhost_set_ios(struc
  171. ios->clock, ios->power_mode, ios->bus_width,
  172. ios->timing, ios->signal_voltage, ios->drv_type);
  173. - if (ios->clock && (host->cur_clk_idx == -1)) {
  174. - unsigned int cur_clk =
  175. - get_core_clock(RPI_FIRMWARE_GET_CLOCK_RATE);
  176. - host->cur_clk_idx = (cur_clk == host->src_clks[0]) ? 0 : 1;
  177. - }
  178. + if (ios->clock && !host->cur_clk)
  179. + host->cur_clk = get_core_clock(RPI_FIRMWARE_GET_CLOCK_RATE);
  180. spin_lock_irqsave(&host->lock, flags);
  181. @@ -1876,12 +1854,11 @@ static void bcm2835_sdhost_tasklet_finis
  182. /* Drop the overclock after any data corruption, or after any
  183. error overclocked */
  184. - if (host->clock > 50*MHZ) {
  185. + if (host->overclock) {
  186. if ((mrq->cmd && mrq->cmd->error) ||
  187. (mrq->data && mrq->data->error) ||
  188. (mrq->stop && mrq->stop->error)) {
  189. - host->overclock_50 = (host->clock/MHZ) - 1;
  190. -
  191. + host->overclock_50--;
  192. pr_warn("%s: reducing overclock due to errors\n",
  193. mmc_hostname(host->mmc));
  194. bcm2835_sdhost_set_clock(host);
  195. @@ -2045,7 +2022,7 @@ static int bcm2835_sdhost_probe(struct p
  196. struct bcm2835_host *host;
  197. struct mmc_host *mmc;
  198. const __be32 *addr;
  199. - unsigned int max_clk, min_clk;
  200. + unsigned int max_clk;
  201. int ret;
  202. pr_debug("bcm2835_sdhost_probe\n");
  203. @@ -2151,8 +2128,12 @@ static int bcm2835_sdhost_probe(struct p
  204. else
  205. mmc->caps |= MMC_CAP_4_BIT_DATA;
  206. + ret = bcm2835_sdhost_add_host(host);
  207. + if (ret)
  208. + goto err;
  209. +
  210. /* Query the core clock frequencies */
  211. - min_clk = get_core_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE);
  212. + host->min_clk = get_core_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE);
  213. max_clk = get_core_clock(RPI_FIRMWARE_GET_MAX_CLOCK_RATE);
  214. if (max_clk != host->max_clk) {
  215. pr_warn("%s: Expected max clock %d, found %d\n",
  216. @@ -2160,24 +2141,19 @@ static int bcm2835_sdhost_probe(struct p
  217. host->max_clk = max_clk;
  218. }
  219. - host->src_clks[0] = min_clk;
  220. - host->cur_clk_idx = -1;
  221. - if (max_clk != min_clk) {
  222. - host->src_clks[1] = max_clk;
  223. + if (host->min_clk != host->max_clk) {
  224. host->cpufreq_nb.notifier_call =
  225. bcm2835_sdhost_cpufreq_callback;
  226. sema_init(&host->cpufreq_semaphore, 1);
  227. cpufreq_register_notifier(&host->cpufreq_nb,
  228. CPUFREQ_TRANSITION_NOTIFIER);
  229. host->variable_clock = 1;
  230. + host->cur_clk = 0; /* Get this later */
  231. } else {
  232. host->variable_clock = 0;
  233. + host->cur_clk = host->max_clk;
  234. }
  235. - ret = bcm2835_sdhost_add_host(host);
  236. - if (ret)
  237. - goto err;
  238. -
  239. platform_set_drvdata(pdev, host);
  240. pr_debug("bcm2835_sdhost_probe -> OK\n");