aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorNicolas Ferre <nicolas.ferre@rfo.atmel.com>2007-07-09 08:58:16 -0400
committerPierre Ossman <drzeus@drzeus.cx>2007-07-09 15:29:07 -0400
commited99c541e0a15281c57530d54a4a5e3272f74fb9 (patch)
tree55c5a90415b6d793cd952e85982163b0511d3073 /drivers
parente8d04d3dba60bdc139644350fcc88f82e40129dc (diff)
mmc: at91_mci: fix hanging and rework to match flowcharts
Fixes hanging using multi block operations (seen during CMD25). Follows closely the datasheet flowcharts. This piece of code handles better big file writing. I had to take care of the notbusy signal during write (at91_mci_handle_cmdrdy function) and to rearrange the AT91_MCI_ENDRX and AT91_MCI_RXBUFF flag usage. Signed-off-by: Nicolas Ferre <nicolas.ferre@rfo.atmel.com> Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/at91_mci.c199
1 files changed, 108 insertions, 91 deletions
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index 647f29473cf9..28c881895ab7 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -78,8 +78,6 @@
78 78
79#define DRIVER_NAME "at91_mci" 79#define DRIVER_NAME "at91_mci"
80 80
81#undef SUPPORT_4WIRE
82
83#define FL_SENT_COMMAND (1 << 0) 81#define FL_SENT_COMMAND (1 << 0)
84#define FL_SENT_STOP (1 << 1) 82#define FL_SENT_STOP (1 << 1)
85 83
@@ -268,8 +266,6 @@ static void at91_mci_post_dma_read(struct at91mci_host *host)
268 } 266 }
269 267
270 while (host->in_use_index < host->transfer_index) { 268 while (host->in_use_index < host->transfer_index) {
271 unsigned int *buffer;
272
273 struct scatterlist *sg; 269 struct scatterlist *sg;
274 270
275 pr_debug("finishing index %d\n", host->in_use_index); 271 pr_debug("finishing index %d\n", host->in_use_index);
@@ -280,20 +276,22 @@ static void at91_mci_post_dma_read(struct at91mci_host *host)
280 276
281 dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE); 277 dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
282 278
283 /* Swap the contents of the buffer */
284 buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
285 pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
286
287 data->bytes_xfered += sg->length; 279 data->bytes_xfered += sg->length;
288 280
289 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ 281 if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
282 unsigned int *buffer;
290 int index; 283 int index;
291 284
285 /* Swap the contents of the buffer */
286 buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
287 pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
288
292 for (index = 0; index < (sg->length / 4); index++) 289 for (index = 0; index < (sg->length / 4); index++)
293 buffer[index] = swab32(buffer[index]); 290 buffer[index] = swab32(buffer[index]);
291
292 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
294 } 293 }
295 294
296 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
297 flush_dcache_page(sg->page); 295 flush_dcache_page(sg->page);
298 } 296 }
299 297
@@ -301,8 +299,8 @@ static void at91_mci_post_dma_read(struct at91mci_host *host)
301 if (host->transfer_index < data->sg_len) 299 if (host->transfer_index < data->sg_len)
302 at91_mci_pre_dma_read(host); 300 at91_mci_pre_dma_read(host);
303 else { 301 else {
302 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
304 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF); 303 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
305 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
306 } 304 }
307 305
308 pr_debug("post dma read done\n"); 306 pr_debug("post dma read done\n");
@@ -323,7 +321,6 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host)
323 321
324 /* Now wait for cmd ready */ 322 /* Now wait for cmd ready */
325 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE); 323 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
326 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
327 324
328 cmd = host->cmd; 325 cmd = host->cmd;
329 if (!cmd) return; 326 if (!cmd) return;
@@ -331,18 +328,53 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host)
331 data = cmd->data; 328 data = cmd->data;
332 if (!data) return; 329 if (!data) return;
333 330
331 if (cmd->data->flags & MMC_DATA_MULTI) {
332 pr_debug("multiple write : wait for BLKE...\n");
333 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
334 } else
335 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
336
334 data->bytes_xfered = host->total_length; 337 data->bytes_xfered = host->total_length;
335} 338}
336 339
340/*Handle after command sent ready*/
341static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
342{
343 if (!host->cmd)
344 return 1;
345 else if (!host->cmd->data) {
346 if (host->flags & FL_SENT_STOP) {
347 /*After multi block write, we must wait for NOTBUSY*/
348 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
349 } else return 1;
350 } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
351 /*After sendding multi-block-write command, start DMA transfer*/
352 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE);
353 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
354 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
355 }
356
357 /* command not completed, have to wait */
358 return 0;
359}
360
361
337/* 362/*
338 * Enable the controller 363 * Enable the controller
339 */ 364 */
340static void at91_mci_enable(struct at91mci_host *host) 365static void at91_mci_enable(struct at91mci_host *host)
341{ 366{
367 unsigned int mr;
368
342 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN); 369 at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
343 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff); 370 at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
344 at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC); 371 at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
345 at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a); 372 mr = AT91_MCI_PDCMODE | 0x34a;
373
374 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
375 mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
376
377 at91_mci_write(host, AT91_MCI_MR, mr);
346 378
347 /* use Slot A or B (only one at same time) */ 379 /* use Slot A or B (only one at same time) */
348 at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b); 380 at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
@@ -358,9 +390,8 @@ static void at91_mci_disable(struct at91mci_host *host)
358 390
359/* 391/*
360 * Send a command 392 * Send a command
361 * return the interrupts to enable
362 */ 393 */
363static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd) 394static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
364{ 395{
365 unsigned int cmdr, mr; 396 unsigned int cmdr, mr;
366 unsigned int block_length; 397 unsigned int block_length;
@@ -371,8 +402,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
371 402
372 host->cmd = cmd; 403 host->cmd = cmd;
373 404
374 /* Not sure if this is needed */ 405 /* Needed for leaving busy state before CMD1 */
375#if 0
376 if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) { 406 if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
377 pr_debug("Clearing timeout\n"); 407 pr_debug("Clearing timeout\n");
378 at91_mci_write(host, AT91_MCI_ARGR, 0); 408 at91_mci_write(host, AT91_MCI_ARGR, 0);
@@ -382,7 +412,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
382 pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR)); 412 pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
383 } 413 }
384 } 414 }
385#endif 415
386 cmdr = cmd->opcode; 416 cmdr = cmd->opcode;
387 417
388 if (mmc_resp_type(cmd) == MMC_RSP_NONE) 418 if (mmc_resp_type(cmd) == MMC_RSP_NONE)
@@ -439,50 +469,48 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
439 at91_mci_write(host, ATMEL_PDC_TCR, 0); 469 at91_mci_write(host, ATMEL_PDC_TCR, 0);
440 at91_mci_write(host, ATMEL_PDC_TNPR, 0); 470 at91_mci_write(host, ATMEL_PDC_TNPR, 0);
441 at91_mci_write(host, ATMEL_PDC_TNCR, 0); 471 at91_mci_write(host, ATMEL_PDC_TNCR, 0);
472 ier = AT91_MCI_CMDRDY;
473 } else {
474 /* zero block length and PDC mode */
475 mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
476 at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
442 477
443 at91_mci_write(host, AT91_MCI_ARGR, cmd->arg); 478 /*
444 at91_mci_write(host, AT91_MCI_CMDR, cmdr); 479 * Disable the PDC controller
445 return AT91_MCI_CMDRDY; 480 */
446 } 481 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
447
448 mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */
449 at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
450
451 /*
452 * Disable the PDC controller
453 */
454 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
455
456 if (cmdr & AT91_MCI_TRCMD_START) {
457 data->bytes_xfered = 0;
458 host->transfer_index = 0;
459 host->in_use_index = 0;
460 if (cmdr & AT91_MCI_TRDIR) {
461 /*
462 * Handle a read
463 */
464 host->buffer = NULL;
465 host->total_length = 0;
466
467 at91_mci_pre_dma_read(host);
468 ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
469 }
470 else {
471 /*
472 * Handle a write
473 */
474 host->total_length = block_length * blocks;
475 host->buffer = dma_alloc_coherent(NULL,
476 host->total_length,
477 &host->physical_address, GFP_KERNEL);
478
479 at91_mci_sg_to_dma(host, data);
480
481 pr_debug("Transmitting %d bytes\n", host->total_length);
482 482
483 at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address); 483 if (cmdr & AT91_MCI_TRCMD_START) {
484 at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4); 484 data->bytes_xfered = 0;
485 ier = AT91_MCI_TXBUFE; 485 host->transfer_index = 0;
486 host->in_use_index = 0;
487 if (cmdr & AT91_MCI_TRDIR) {
488 /*
489 * Handle a read
490 */
491 host->buffer = NULL;
492 host->total_length = 0;
493
494 at91_mci_pre_dma_read(host);
495 ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
496 }
497 else {
498 /*
499 * Handle a write
500 */
501 host->total_length = block_length * blocks;
502 host->buffer = dma_alloc_coherent(NULL,
503 host->total_length,
504 &host->physical_address, GFP_KERNEL);
505
506 at91_mci_sg_to_dma(host, data);
507
508 pr_debug("Transmitting %d bytes\n", host->total_length);
509
510 at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
511 at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
512 ier = AT91_MCI_CMDRDY;
513 }
486 } 514 }
487 } 515 }
488 516
@@ -497,24 +525,9 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
497 if (cmdr & AT91_MCI_TRCMD_START) { 525 if (cmdr & AT91_MCI_TRCMD_START) {
498 if (cmdr & AT91_MCI_TRDIR) 526 if (cmdr & AT91_MCI_TRDIR)
499 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN); 527 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
500 else
501 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
502 } 528 }
503 return ier;
504}
505 529
506/* 530 /* Enable selected interrupts */
507 * Wait for a command to complete
508 */
509static void at91_mci_process_command(struct at91mci_host *host, struct mmc_command *cmd)
510{
511 unsigned int ier;
512
513 ier = at91_mci_send_command(host, cmd);
514
515 pr_debug("setting ier to %08X\n", ier);
516
517 /* Stop on errors or the required value */
518 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier); 531 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
519} 532}
520 533
@@ -525,11 +538,11 @@ static void at91_mci_process_next(struct at91mci_host *host)
525{ 538{
526 if (!(host->flags & FL_SENT_COMMAND)) { 539 if (!(host->flags & FL_SENT_COMMAND)) {
527 host->flags |= FL_SENT_COMMAND; 540 host->flags |= FL_SENT_COMMAND;
528 at91_mci_process_command(host, host->request->cmd); 541 at91_mci_send_command(host, host->request->cmd);
529 } 542 }
530 else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) { 543 else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
531 host->flags |= FL_SENT_STOP; 544 host->flags |= FL_SENT_STOP;
532 at91_mci_process_command(host, host->request->stop); 545 at91_mci_send_command(host, host->request->stop);
533 } 546 }
534 else 547 else
535 mmc_request_done(host->mmc, host->request); 548 mmc_request_done(host->mmc, host->request);
@@ -698,29 +711,33 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
698 at91_mci_handle_transmitted(host); 711 at91_mci_handle_transmitted(host);
699 } 712 }
700 713
714 if (int_status & AT91_MCI_ENDRX) {
715 pr_debug("ENDRX\n");
716 at91_mci_post_dma_read(host);
717 }
718
701 if (int_status & AT91_MCI_RXBUFF) { 719 if (int_status & AT91_MCI_RXBUFF) {
702 pr_debug("RX buffer full\n"); 720 pr_debug("RX buffer full\n");
703 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY); 721 at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
722 at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
723 completed = 1;
704 } 724 }
705 725
706 if (int_status & AT91_MCI_ENDTX) 726 if (int_status & AT91_MCI_ENDTX)
707 pr_debug("Transmit has ended\n"); 727 pr_debug("Transmit has ended\n");
708 728
709 if (int_status & AT91_MCI_ENDRX) {
710 pr_debug("Receive has ended\n");
711 at91_mci_post_dma_read(host);
712 }
713
714 if (int_status & AT91_MCI_NOTBUSY) { 729 if (int_status & AT91_MCI_NOTBUSY) {
715 pr_debug("Card is ready\n"); 730 pr_debug("Card is ready\n");
716 at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY); 731 completed = 1;
717 } 732 }
718 733
719 if (int_status & AT91_MCI_DTIP) 734 if (int_status & AT91_MCI_DTIP)
720 pr_debug("Data transfer in progress\n"); 735 pr_debug("Data transfer in progress\n");
721 736
722 if (int_status & AT91_MCI_BLKE) 737 if (int_status & AT91_MCI_BLKE) {
723 pr_debug("Block transfer has ended\n"); 738 pr_debug("Block transfer has ended\n");
739 completed = 1;
740 }
724 741
725 if (int_status & AT91_MCI_TXRDY) 742 if (int_status & AT91_MCI_TXRDY)
726 pr_debug("Ready to transmit\n"); 743 pr_debug("Ready to transmit\n");
@@ -730,7 +747,7 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
730 747
731 if (int_status & AT91_MCI_CMDRDY) { 748 if (int_status & AT91_MCI_CMDRDY) {
732 pr_debug("Command ready\n"); 749 pr_debug("Command ready\n");
733 completed = 1; 750 completed = at91_mci_handle_cmdrdy(host);
734 } 751 }
735 } 752 }
736 753
@@ -830,11 +847,11 @@ static int __init at91_mci_probe(struct platform_device *pdev)
830 host->bus_mode = 0; 847 host->bus_mode = 0;
831 host->board = pdev->dev.platform_data; 848 host->board = pdev->dev.platform_data;
832 if (host->board->wire4) { 849 if (host->board->wire4) {
833#ifdef SUPPORT_4WIRE 850 if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
834 mmc->caps |= MMC_CAP_4_BIT_DATA; 851 mmc->caps |= MMC_CAP_4_BIT_DATA;
835#else 852 else
836 printk("AT91 MMC: 4 wire bus mode not supported by this driver - using 1 wire\n"); 853 printk("AT91 MMC: 4 wire bus mode not supported"
837#endif 854 " - using 1 wire\n");
838 } 855 }
839 856
840 /* 857 /*