brcm2708: add linux 4.1 support
[openwrt.git] / target / linux / brcm2708 / patches-4.1 / 0092-bcm2835-sdhost-Further-improve-overclock-back-off.patch
1 From d645d31525be338b1baa22916217f3ac0c3705f9 Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.org>
3 Date: Thu, 25 Jun 2015 08:47:09 +0100
4 Subject: [PATCH 092/121] bcm2835-sdhost: Further improve overclock back-off
5
6 ---
7  drivers/mmc/host/bcm2835-sdhost.c | 144 +++++++++++++++++++++-----------------
8  1 file changed, 78 insertions(+), 66 deletions(-)
9
10 --- a/drivers/mmc/host/bcm2835-sdhost.c
11 +++ b/drivers/mmc/host/bcm2835-sdhost.c
12 @@ -161,8 +161,6 @@ struct bcm2835_host {
13  
14         unsigned int                    use_busy:1;             /* Wait for busy interrupt */
15  
16 -       unsigned int                    reduce_overclock:1;     /* ...at the next opportunity */
17 -
18         unsigned int                    debug:1;                /* Enable debug output */
19  
20         u32                             thread_isr;
21 @@ -466,36 +464,25 @@ static void bcm2835_sdhost_dma_complete(
22         spin_unlock_irqrestore(&host->lock, flags);
23  }
24  
25 -static bool data_transfer_wait(struct bcm2835_host *host, const char *caller)
26 +static bool data_transfer_wait(struct bcm2835_host *host)
27  {
28         unsigned long timeout = 1000000;
29 -       u32 hsts;
30         while (timeout)
31         {
32 -               hsts = bcm2835_sdhost_read(host, SDHSTS);
33 -               if (hsts & (SDHSTS_TRANSFER_ERROR_MASK |
34 -                           SDHSTS_DATA_FLAG)) {
35 -                       bcm2835_sdhost_write(host, SDHSTS_TRANSFER_ERROR_MASK,
36 -                                            SDHSTS);
37 +               u32 sdhsts = bcm2835_sdhost_read(host, SDHSTS);
38 +               if (sdhsts & SDHSTS_DATA_FLAG) {
39 +                       bcm2835_sdhost_write(host, SDHSTS_DATA_FLAG, SDHSTS);
40                         break;
41                 }
42                 timeout--;
43         }
44 -
45 -       if (hsts & (SDHSTS_CRC16_ERROR |
46 -                   SDHSTS_CRC7_ERROR |
47 -                   SDHSTS_FIFO_ERROR)) {
48 -               pr_err("%s: data error in %s - HSTS %x\n",
49 -                      mmc_hostname(host->mmc), caller, hsts);
50 -               host->data->error = -EILSEQ;
51 -               return false;
52 -       } else if ((timeout == 0) ||
53 -                  (hsts & (SDHSTS_CMD_TIME_OUT |
54 -                           SDHSTS_REW_TIME_OUT))) {
55 -               pr_err("%s: timeout in %s - HSTS %x\n",
56 -                      mmc_hostname(host->mmc), caller, hsts);
57 -               host->data->error = -ETIMEDOUT;
58 -               return false;
59 +       if (timeout == 0) {
60 +           pr_err("%s: Data %s timeout\n",
61 +                  mmc_hostname(host->mmc),
62 +                  (host->data->flags & MMC_DATA_READ) ? "read" : "write");
63 +           bcm2835_sdhost_dumpregs(host);
64 +           host->data->error = -ETIMEDOUT;
65 +           return false;
66         }
67         return true;
68  }
69 @@ -523,7 +510,7 @@ static void bcm2835_sdhost_read_block_pi
70                 buf = (u32 *)host->sg_miter.addr;
71  
72                 while (len) {
73 -                       if (!data_transfer_wait(host, "read_block_pio"))
74 +                       if (!data_transfer_wait(host))
75                                 break;
76  
77                         *(buf++) = bcm2835_sdhost_read(host, SDDATA);
78 @@ -562,7 +549,7 @@ static void bcm2835_sdhost_write_block_p
79                 buf = host->sg_miter.addr;
80  
81                 while (len) {
82 -                       if (!data_transfer_wait(host, "write_block_pio"))
83 +                       if (!data_transfer_wait(host))
84                                 break;
85  
86                         bcm2835_sdhost_write(host, *(buf++), SDDATA);
87 @@ -581,13 +568,33 @@ static void bcm2835_sdhost_write_block_p
88  
89  static void bcm2835_sdhost_transfer_pio(struct bcm2835_host *host)
90  {
91 +       u32 sdhsts;
92 +       bool is_read;
93         BUG_ON(!host->data);
94  
95 -       if (host->data->flags & MMC_DATA_READ) {
96 +       is_read = (host->data->flags & MMC_DATA_READ) != 0;
97 +       if (is_read)
98                 bcm2835_sdhost_read_block_pio(host);
99 -       } else {
100 +       else
101                 bcm2835_sdhost_write_block_pio(host);
102  
103 +       sdhsts = bcm2835_sdhost_read(host, SDHSTS);
104 +       if (sdhsts & (SDHSTS_CRC16_ERROR |
105 +                     SDHSTS_CRC7_ERROR |
106 +                     SDHSTS_FIFO_ERROR)) {
107 +               pr_err("%s: %s transfer error - HSTS %x\n",
108 +                      mmc_hostname(host->mmc),
109 +                      is_read ? "read" : "write",
110 +                      sdhsts);
111 +               host->data->error = -EILSEQ;
112 +       } else if ((sdhsts & (SDHSTS_CMD_TIME_OUT |
113 +                             SDHSTS_REW_TIME_OUT))) {
114 +               pr_err("%s: %s timeout error - HSTS %x\n",
115 +                      mmc_hostname(host->mmc),
116 +                      is_read ? "read" : "write",
117 +                      sdhsts);
118 +               host->data->error = -ETIMEDOUT;
119 +       } else if (!is_read && !host->data->error) {
120                 /* Start a timer in case a transfer error occurs because
121                    there is no error interrupt */
122                 mod_timer(&host->pio_timer, jiffies + host->pio_timeout);
123 @@ -701,8 +708,9 @@ static void bcm2835_sdhost_prepare_data(
124  
125  void bcm2835_sdhost_send_command(struct bcm2835_host *host, struct mmc_command *cmd)
126  {
127 -       u32 sdcmd;
128 +       u32 sdcmd, sdhsts;
129         unsigned long timeout;
130 +       int delay;
131  
132         WARN_ON(host->cmd);
133  
134 @@ -719,8 +727,8 @@ void bcm2835_sdhost_send_command(struct
135                          mmc_hostname(host->mmc),
136                          cmd->opcode, cmd->arg, cmd->flags);
137  
138 -       /* Wait max 10 ms */
139 -       timeout = 1000;
140 +       /* Wait max 100 ms */
141 +       timeout = 10000;
142  
143         while (bcm2835_sdhost_read(host, SDCMD) & SDCMD_NEW_FLAG) {
144                 if (timeout == 0) {
145 @@ -735,8 +743,9 @@ void bcm2835_sdhost_send_command(struct
146                 udelay(10);
147         }
148  
149 -       if ((1000-timeout)/100 > 1 && (1000-timeout)/100 > host->max_delay) {
150 -               host->max_delay = (1000-timeout)/100;
151 +       delay = (10000 - timeout)/100;
152 +       if (delay > host->max_delay) {
153 +               host->max_delay = delay;
154                 pr_warning("%s: controller hung for %d ms\n",
155                            mmc_hostname(host->mmc),
156                            host->max_delay);
157 @@ -751,6 +760,11 @@ void bcm2835_sdhost_send_command(struct
158  
159         host->cmd = cmd;
160  
161 +       /* Clear any error flags */
162 +       sdhsts = bcm2835_sdhost_read(host, SDHSTS);
163 +       if (sdhsts & SDHSTS_ERROR_MASK)
164 +               bcm2835_sdhost_write(host, sdhsts, SDHSTS);
165 +
166         bcm2835_sdhost_prepare_data(host, cmd);
167  
168         bcm2835_sdhost_write(host, cmd->arg, SDARG);
169 @@ -876,7 +890,7 @@ static void bcm2835_sdhost_transfer_comp
170  static void bcm2835_sdhost_finish_command(struct bcm2835_host *host)
171  {
172         u32 sdcmd;
173 -       int timeout = 1000;
174 +       unsigned long timeout;
175  #ifdef DEBUG
176         struct timeval before, after;
177         int timediff = 0;
178 @@ -889,6 +903,8 @@ static void bcm2835_sdhost_finish_comman
179  #ifdef DEBUG
180         do_gettimeofday(&before);
181  #endif
182 +       /* Wait max 100 ms */
183 +       timeout = 10000;
184         for (sdcmd = bcm2835_sdhost_read(host, SDCMD);
185              (sdcmd & SDCMD_NEW_FLAG) && timeout;
186              timeout--) {
187 @@ -1049,9 +1065,9 @@ static void bcm2835_sdhost_pio_timeout(u
188         spin_lock_irqsave(&host->lock, flags);
189  
190         if (host->data) {
191 -               u32 hsts = bcm2835_sdhost_read(host, SDHSTS);
192 +               u32 sdhsts = bcm2835_sdhost_read(host, SDHSTS);
193  
194 -               if (hsts & SDHSTS_REW_TIME_OUT) {
195 +               if (sdhsts & SDHSTS_REW_TIME_OUT) {
196                         pr_err("%s: transfer timeout\n",
197                                mmc_hostname(host->mmc));
198                         if (host->debug)
199 @@ -1380,19 +1396,10 @@ void bcm2835_sdhost_set_clock(struct bcm
200         if (host->debug)
201                 pr_info("%s: set_clock(%d)\n", mmc_hostname(host->mmc), clock);
202  
203 -       if ((clock == 0) && host->reduce_overclock) {
204 -               /* This is a reset following data corruption - reduce any
205 -                  overclock */
206 -               host->reduce_overclock = 0;
207 -               if (host->overclock_50 > 50) {
208 -                       pr_warn("%s: reducing overclock due to errors\n",
209 -                               mmc_hostname(host->mmc));
210 -                       host->overclock_50--;
211 -               }
212 -       }
213 -
214 -       if (host->overclock_50 && (clock == 50*MHZ))
215 +       if ((host->overclock_50 > 50) &&
216 +           (clock == 50*MHZ)) {
217                 clock = host->overclock_50 * MHZ + (MHZ - 1);
218 +       }
219  
220         /* The SDCDIV register has 11 bits, and holds (div - 2).
221            But in data mode the max is 50MHz wihout a minimum, and only the
222 @@ -1450,11 +1457,12 @@ void bcm2835_sdhost_set_clock(struct bcm
223                         host->overclock = clock;
224                 }
225         }
226 -       else if ((clock == 50 * MHZ) && host->overclock)
227 +       else if (host->overclock)
228         {
229 -               pr_warn("%s: cancelling overclock\n",
230 -                       mmc_hostname(host->mmc));
231                 host->overclock = 0;
232 +               if (clock == 50 * MHZ)
233 +                       pr_warn("%s: cancelling overclock\n",
234 +                               mmc_hostname(host->mmc));
235         }
236  
237         host->cdiv = div;
238 @@ -1492,6 +1500,14 @@ static void bcm2835_sdhost_request(struc
239                                 cmd->opcode, cmd->arg, cmd->flags);
240         }
241  
242 +       /* Reset the error statuses in case this is a retry */
243 +       if (mrq->cmd)
244 +               mrq->cmd->error = 0;
245 +       if (mrq->data)
246 +               mrq->data->error = 0;
247 +       if (mrq->stop)
248 +               mrq->stop->error = 0;
249 +
250         if (mrq->data && !is_power_of_2(mrq->data->blksz)) {
251                 pr_err("%s: unsupported block size (%d bytes)\n",
252                        mmc_hostname(mmc), mrq->data->blksz);
253 @@ -1613,21 +1629,16 @@ static void bcm2835_sdhost_tasklet_finis
254  
255         /* Drop the overclock after any data corruption, or after any
256            error overclocked */
257 -       if (mrq->data && (mrq->data->error == -EILSEQ))
258 -               host->reduce_overclock = 1;
259 -       else if (host->overclock) {
260 -               /* Convert timeout errors while overclocked to data errors,
261 -                  because the system recovers better. */
262 -               if (mrq->cmd && mrq->cmd->error) {
263 -                       host->reduce_overclock = 1;
264 -                       if (mrq->cmd->error == -ETIMEDOUT)
265 -                               mrq->cmd->error = -EILSEQ;
266 -               }
267 -
268 -               if (mrq->data && mrq->data->error) {
269 -                       host->reduce_overclock = 1;
270 -                       if (mrq->data->error == -ETIMEDOUT)
271 -                               mrq->data->error = -EILSEQ;
272 +       if (host->overclock) {
273 +               if ((mrq->cmd && mrq->cmd->error) ||
274 +                   (mrq->data && mrq->data->error) ||
275 +                   (mrq->stop && mrq->stop->error)) {
276 +                       host->overclock_50--;
277 +                       pr_warn("%s: reducing overclock due to errors\n",
278 +                               mmc_hostname(host->mmc));
279 +                       bcm2835_sdhost_set_clock(host,50*MHZ);
280 +                       mrq->cmd->error = -EILSEQ;
281 +                       mrq->cmd->retries = 1;
282                 }
283         }
284  
285 @@ -1769,6 +1780,7 @@ static int bcm2835_sdhost_probe(struct p
286         host = mmc_priv(mmc);
287         host->mmc = mmc;
288         host->pio_timeout = msecs_to_jiffies(500);
289 +       host->max_delay = 1; /* Warn if over 1ms */
290         spin_lock_init(&host->lock);
291  
292         iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);