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