Added gpio and led drivers for 2.6.25.10 kernel
[10.03/openwrt.git] / target / linux / at91 / patches-2.6.21 / 012-at91-mmcfix.patch
1 Index: linux-2.6.21.7/drivers/mmc/at91_mci.c
2 ===================================================================
3 --- linux-2.6.21.7.orig/drivers/mmc/at91_mci.c
4 +++ linux-2.6.21.7/drivers/mmc/at91_mci.c
5 @@ -79,7 +79,8 @@
6  
7  #define DRIVER_NAME "at91_mci"
8  
9 -#undef SUPPORT_4WIRE
10 +//#undef       SUPPORT_4WIRE
11 +#define        SUPPORT_4WIRE
12  
13  #define FL_SENT_COMMAND        (1 << 0)
14  #define FL_SENT_STOP   (1 << 1)
15 @@ -132,7 +133,7 @@ struct at91mci_host
16  /*
17   * Copy from sg to a dma block - used for transfers
18   */
19 -static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
20 +static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
21  {
22         unsigned int len, i, size;
23         unsigned *dmabuf = host->buffer;
24 @@ -181,7 +182,7 @@ static inline void at91mci_sg_to_dma(str
25  /*
26   * Prepare a dma read
27   */
28 -static void at91mci_pre_dma_read(struct at91mci_host *host)
29 +static void at91_mci_pre_dma_read(struct at91mci_host *host)
30  {
31         int i;
32         struct scatterlist *sg;
33 @@ -249,23 +250,24 @@ static void at91mci_pre_dma_read(struct 
34  /*
35   * Handle after a dma read
36   */
37 -static void at91mci_post_dma_read(struct at91mci_host *host)
38 +static int at91_mci_post_dma_read(struct at91mci_host *host)
39  {
40         struct mmc_command *cmd;
41         struct mmc_data *data;
42 +       int completed = 0;
43  
44         pr_debug("post dma read\n");
45  
46         cmd = host->cmd;
47         if (!cmd) {
48                 pr_debug("no command\n");
49 -               return;
50 +               return 1;
51         }
52  
53         data = cmd->data;
54         if (!data) {
55                 pr_debug("no data\n");
56 -               return;
57 +               return 1;
58         }
59  
60         while (host->in_use_index < host->transfer_index) {
61 @@ -300,39 +302,14 @@ static void at91mci_post_dma_read(struct
62  
63         /* Is there another transfer to trigger? */
64         if (host->transfer_index < data->sg_len)
65 -               at91mci_pre_dma_read(host);
66 +               at91_mci_pre_dma_read(host);
67         else {
68 +               at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
69                 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
70 -               at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
71         }
72  
73         pr_debug("post dma read done\n");
74 -}
75 -
76 -/*
77 - * Handle transmitted data
78 - */
79 -static void at91_mci_handle_transmitted(struct at91mci_host *host)
80 -{
81 -       struct mmc_command *cmd;
82 -       struct mmc_data *data;
83 -
84 -       pr_debug("Handling the transmit\n");
85 -
86 -       /* Disable the transfer */
87 -       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
88 -
89 -       /* Now wait for cmd ready */
90 -       at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
91 -       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
92 -
93 -       cmd = host->cmd;
94 -       if (!cmd) return;
95 -
96 -       data = cmd->data;
97 -       if (!data) return;
98 -
99 -       data->bytes_xfered = host->total_length;
100 +       return completed;
101  }
102  
103  /*
104 @@ -340,10 +317,17 @@ static void at91_mci_handle_transmitted(
105   */
106  static void at91_mci_enable(struct at91mci_host *host)
107  {
108 +       unsigned int mr;
109 +
110         at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
111         at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
112         at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
113 -       at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a);
114 +       mr = AT91_MCI_PDCMODE | 0x34a;
115 +
116 +       if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
117 +               mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
118 +
119 +       at91_mci_write(host, AT91_MCI_MR, mr);
120  
121         /* use Slot A or B (only one at same time) */
122         at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
123 @@ -359,9 +343,8 @@ static void at91_mci_disable(struct at91
124  
125  /*
126   * Send a command
127 - * return the interrupts to enable
128   */
129 -static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
130 +static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
131  {
132         unsigned int cmdr, mr;
133         unsigned int block_length;
134 @@ -372,8 +355,7 @@ static unsigned int at91_mci_send_comman
135  
136         host->cmd = cmd;
137  
138 -       /* Not sure if this is needed */
139 -#if 0
140 +       /* Needed for leaving busy state before CMD1 */
141         if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
142                 pr_debug("Clearing timeout\n");
143                 at91_mci_write(host, AT91_MCI_ARGR, 0);
144 @@ -383,7 +365,7 @@ static unsigned int at91_mci_send_comman
145                         pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
146                 }
147         }
148 -#endif
149 +
150         cmdr = cmd->opcode;
151  
152         if (mmc_resp_type(cmd) == MMC_RSP_NONE)
153 @@ -440,50 +422,48 @@ static unsigned int at91_mci_send_comman
154                 at91_mci_write(host, ATMEL_PDC_TCR, 0);
155                 at91_mci_write(host, ATMEL_PDC_TNPR, 0);
156                 at91_mci_write(host, ATMEL_PDC_TNCR, 0);
157 +               ier = AT91_MCI_CMDRDY;
158 +       } else {
159 +               /* zero block length in PDC mode */
160 +               mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
161 +               at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
162 +
163 +               /*
164 +                * Disable the PDC controller
165 +                */
166 +               at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
167  
168 -               at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
169 -               at91_mci_write(host, AT91_MCI_CMDR, cmdr);
170 -               return AT91_MCI_CMDRDY;
171 -       }
172 -
173 -       mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */
174 -       at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
175 -
176 -       /*
177 -        * Disable the PDC controller
178 -        */
179 -       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
180 -
181 -       if (cmdr & AT91_MCI_TRCMD_START) {
182 -               data->bytes_xfered = 0;
183 -               host->transfer_index = 0;
184 -               host->in_use_index = 0;
185 -               if (cmdr & AT91_MCI_TRDIR) {
186 -                       /*
187 -                        * Handle a read
188 -                        */
189 -                       host->buffer = NULL;
190 -                       host->total_length = 0;
191 +               if (cmdr & AT91_MCI_TRCMD_START) {
192 +                       data->bytes_xfered = 0;
193 +                       host->transfer_index = 0;
194 +                       host->in_use_index = 0;
195 +                       if (cmdr & AT91_MCI_TRDIR) {
196 +                               /*
197 +                                * Handle a read
198 +                                */
199 +                               host->buffer = NULL;
200 +                               host->total_length = 0;
201  
202 -                       at91mci_pre_dma_read(host);
203 -                       ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
204 -               }
205 -               else {
206 -                       /*
207 -                        * Handle a write
208 -                        */
209 -                       host->total_length = block_length * blocks;
210 -                       host->buffer = dma_alloc_coherent(NULL,
211 -                                                 host->total_length,
212 -                                                 &host->physical_address, GFP_KERNEL);
213 -
214 -                       at91mci_sg_to_dma(host, data);
215 -
216 -                       pr_debug("Transmitting %d bytes\n", host->total_length);
217 -
218 -                       at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
219 -                       at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
220 -                       ier = AT91_MCI_TXBUFE;
221 +                               at91_mci_pre_dma_read(host);
222 +                               ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
223 +                       }
224 +                       else {
225 +                               /*
226 +                               * Handle a write
227 +                               */
228 +                               host->total_length = block_length * blocks;
229 +                               host->buffer = dma_alloc_coherent(NULL,
230 +                                                       host->total_length,
231 +                                                       &host->physical_address, GFP_KERNEL);
232 +
233 +                               at91_mci_sg_to_dma(host, data);
234 +
235 +                               pr_debug("Transmitting %d bytes\n", host->total_length);
236 +
237 +                               at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
238 +                               at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
239 +                               ier = AT91_MCI_CMDRDY;
240 +                       }
241                 }
242         }
243  
244 @@ -498,39 +478,24 @@ static unsigned int at91_mci_send_comman
245         if (cmdr & AT91_MCI_TRCMD_START) {
246                 if (cmdr & AT91_MCI_TRDIR)
247                         at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
248 -               else
249 -                       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
250         }
251 -       return ier;
252 -}
253  
254 -/*
255 - * Wait for a command to complete
256 - */
257 -static void at91mci_process_command(struct at91mci_host *host, struct mmc_command *cmd)
258 -{
259 -       unsigned int ier;
260 -
261 -       ier = at91_mci_send_command(host, cmd);
262 -
263 -       pr_debug("setting ier to %08X\n", ier);
264 -
265 -       /* Stop on errors or the required value */
266 +       /* Enable selected interrupts */
267         at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
268  }
269  
270  /*
271   * Process the next step in the request
272   */
273 -static void at91mci_process_next(struct at91mci_host *host)
274 +static void at91_mci_process_next(struct at91mci_host *host)
275  {
276         if (!(host->flags & FL_SENT_COMMAND)) {
277                 host->flags |= FL_SENT_COMMAND;
278 -               at91mci_process_command(host, host->request->cmd);
279 +               at91_mci_send_command(host, host->request->cmd);
280         }
281         else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
282                 host->flags |= FL_SENT_STOP;
283 -               at91mci_process_command(host, host->request->stop);
284 +               at91_mci_send_command(host, host->request->stop);
285         }
286         else
287                 mmc_request_done(host->mmc, host->request);
288 @@ -539,7 +504,7 @@ static void at91mci_process_next(struct 
289  /*
290   * Handle a command that has been completed
291   */
292 -static void at91mci_completed_command(struct at91mci_host *host)
293 +static void at91_mci_completed_command(struct at91mci_host *host)
294  {
295         struct mmc_command *cmd = host->cmd;
296         unsigned int status;
297 @@ -583,7 +548,7 @@ static void at91mci_completed_command(st
298         else
299                 cmd->error = MMC_ERR_NONE;
300  
301 -       at91mci_process_next(host);
302 +       at91_mci_process_next(host);
303  }
304  
305  /*
306 @@ -595,7 +560,60 @@ static void at91_mci_request(struct mmc_
307         host->request = mrq;
308         host->flags = 0;
309  
310 -       at91mci_process_next(host);
311 +       at91_mci_process_next(host);
312 +}
313 +
314 +/*
315 + * Handle transmitted data
316 + */
317 +static void at91_mci_handle_transmitted(struct at91mci_host *host)
318 +{
319 +       struct mmc_command *cmd;
320 +       struct mmc_data *data;
321 +
322 +       pr_debug("Handling the transmit\n");
323 +
324 +       /* Disable the transfer */
325 +       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
326 +
327 +       /* Now wait for cmd ready */
328 +       at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
329 +
330 +       cmd = host->cmd;
331 +       if (!cmd) return;
332 +
333 +       data = cmd->data;
334 +       if (!data) return;
335 +
336 +       if (cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) {
337 +               pr_debug("multiple write : wait for BLKE...\n");
338 +               at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
339 +       } else
340 +               at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
341 +
342 +       data->bytes_xfered = host->total_length;
343 +}
344 +
345 +
346 +/*Handle after command sent ready*/
347 +static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
348 +{
349 +       if (!host->cmd)
350 +               return 1;
351 +       else if (!host->cmd->data) {
352 +               if (host->flags & FL_SENT_STOP) {
353 +                       /*After multi block write, we mus wait for NOTBUSY*/
354 +                       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
355 +               } else return 1;
356 +       } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
357 +               /*After sending multi-block-write command, start DMA transfer*/
358 +               at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE);
359 +               at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
360 +               at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
361 +       }
362 +
363 +       /* command not completed, have to wait */
364 +       return 0;
365  }
366  
367  /*
368 @@ -698,29 +716,33 @@ static irqreturn_t at91_mci_irq(int irq,
369                         at91_mci_handle_transmitted(host);
370                 }
371  
372 +               if (int_status & AT91_MCI_ENDRX) {
373 +                       pr_debug("ENDRX\n");
374 +                       at91_mci_post_dma_read(host);
375 +               }
376 +
377                 if (int_status & AT91_MCI_RXBUFF) {
378                         pr_debug("RX buffer full\n");
379 -                       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
380 +                       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
381 +                       at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
382 +                       completed = 1;
383                 }
384  
385                 if (int_status & AT91_MCI_ENDTX)
386                         pr_debug("Transmit has ended\n");
387  
388 -               if (int_status & AT91_MCI_ENDRX) {
389 -                       pr_debug("Receive has ended\n");
390 -                       at91mci_post_dma_read(host);
391 -               }
392 -
393                 if (int_status & AT91_MCI_NOTBUSY) {
394                         pr_debug("Card is ready\n");
395 -                       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
396 +                       completed = 1;
397                 }
398  
399                 if (int_status & AT91_MCI_DTIP)
400                         pr_debug("Data transfer in progress\n");
401  
402 -               if (int_status & AT91_MCI_BLKE)
403 +               if (int_status & AT91_MCI_BLKE) {
404                         pr_debug("Block transfer has ended\n");
405 +                       completed = 1;
406 +               }
407  
408                 if (int_status & AT91_MCI_TXRDY)
409                         pr_debug("Ready to transmit\n");
410 @@ -730,14 +752,14 @@ static irqreturn_t at91_mci_irq(int irq,
411  
412                 if (int_status & AT91_MCI_CMDRDY) {
413                         pr_debug("Command ready\n");
414 -                       completed = 1;
415 +                       completed = at91_mci_handle_cmdrdy(host);
416                 }
417         }
418  
419         if (completed) {
420                 pr_debug("Completed command\n");
421                 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
422 -               at91mci_completed_command(host);
423 +               at91_mci_completed_command(host);
424         } else
425                 at91_mci_write(host, AT91_MCI_IDR, int_status);
426