diff options
author | Rafaël Carré <rafael.carre@gmail.com> | 2010-05-03 22:15:56 +0000 |
---|---|---|
committer | Rafaël Carré <rafael.carre@gmail.com> | 2010-05-03 22:15:56 +0000 |
commit | 7480afb3c59f4aebff262e1ce47395a3924ca994 (patch) | |
tree | f035d1430d2d416f1522024a1aab70caab9c2f80 /firmware | |
parent | 1bc59454d5aab440da2018eb95e8a835db3ebc22 (diff) | |
download | rockbox-7480afb3c59f4aebff262e1ce47395a3924ca994.tar.gz rockbox-7480afb3c59f4aebff262e1ce47395a3924ca994.zip |
as3525v2: Use CD Interrupt vs. CD polling in send_cmd()
Also enable write support, test_disk passes on all targets
Flyspray: FS#11140
Authors: Jack Halpin and myself
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25799 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/arm/as3525/sd-as3525v2.c | 63 |
1 files changed, 34 insertions, 29 deletions
diff --git a/firmware/target/arm/as3525/sd-as3525v2.c b/firmware/target/arm/as3525/sd-as3525v2.c index d42f7b46f0..fe4d60925a 100644 --- a/firmware/target/arm/as3525/sd-as3525v2.c +++ b/firmware/target/arm/as3525/sd-as3525v2.c | |||
@@ -338,7 +338,9 @@ bool sd_enabled = false; | |||
338 | #endif | 338 | #endif |
339 | 339 | ||
340 | static struct wakeup transfer_completion_signal; | 340 | static struct wakeup transfer_completion_signal; |
341 | static struct wakeup command_completion_signal; | ||
341 | static volatile bool retry; | 342 | static volatile bool retry; |
343 | static volatile int cmd_error; | ||
342 | 344 | ||
343 | #if defined(HAVE_MULTIDRIVE) | 345 | #if defined(HAVE_MULTIDRIVE) |
344 | int active_card = 0; | 346 | int active_card = 0; |
@@ -350,7 +352,8 @@ static inline void mci_delay(void) { udelay(1000); } | |||
350 | void INT_NAND(void) | 352 | void INT_NAND(void) |
351 | { | 353 | { |
352 | MCI_CTRL &= ~INT_ENABLE; | 354 | MCI_CTRL &= ~INT_ENABLE; |
353 | const int status = MCI_MASK_STATUS; | 355 | /* use raw status here as we need to check some Ints that are masked */ |
356 | const int status = MCI_RAW_STATUS; | ||
354 | 357 | ||
355 | MCI_RAW_STATUS = status; /* clear status */ | 358 | MCI_RAW_STATUS = status; /* clear status */ |
356 | 359 | ||
@@ -360,6 +363,11 @@ void INT_NAND(void) | |||
360 | if( status & (MCI_INT_DTO|MCI_DATA_ERROR)) | 363 | if( status & (MCI_INT_DTO|MCI_DATA_ERROR)) |
361 | wakeup_signal(&transfer_completion_signal); | 364 | wakeup_signal(&transfer_completion_signal); |
362 | 365 | ||
366 | cmd_error = status & MCI_CMD_ERROR; | ||
367 | |||
368 | if(status & MCI_INT_CD) | ||
369 | wakeup_signal(&command_completion_signal); | ||
370 | |||
363 | MCI_CTRL |= INT_ENABLE; | 371 | MCI_CTRL |= INT_ENABLE; |
364 | } | 372 | } |
365 | 373 | ||
@@ -394,6 +402,12 @@ static bool send_cmd(const int drive, const int cmd, const int arg, const int fl | |||
394 | #define TRANSFER_CMD (cmd == SD_READ_MULTIPLE_BLOCK || \ | 402 | #define TRANSFER_CMD (cmd == SD_READ_MULTIPLE_BLOCK || \ |
395 | cmd == SD_WRITE_MULTIPLE_BLOCK) | 403 | cmd == SD_WRITE_MULTIPLE_BLOCK) |
396 | 404 | ||
405 | /* RCRC & RTO interrupts should be set together with the CD interrupt but | ||
406 | * in practice sometimes incorrectly precede the CD interrupt. If we leave | ||
407 | * them masked for now we can check them in the isr by reading raw status when | ||
408 | * the CD int is triggered. | ||
409 | */ | ||
410 | MCI_MASK |= MCI_INT_CD; | ||
397 | MCI_ARGUMENT = arg; | 411 | MCI_ARGUMENT = arg; |
398 | 412 | ||
399 | /* Construct MCI_COMMAND */ | 413 | /* Construct MCI_COMMAND */ |
@@ -415,19 +429,17 @@ static bool send_cmd(const int drive, const int cmd, const int arg, const int fl | |||
415 | /*b23 | CMD_CCS_EXPECTED unused */ | 429 | /*b23 | CMD_CCS_EXPECTED unused */ |
416 | /*b31 */ | CMD_DONE_BIT; | 430 | /*b31 */ | CMD_DONE_BIT; |
417 | 431 | ||
418 | int max = 0x40000; | 432 | wakeup_wait(&command_completion_signal, TIMEOUT_BLOCK); |
419 | while(MCI_COMMAND & CMD_DONE_BIT) | 433 | |
420 | { | 434 | MCI_MASK &= ~MCI_INT_CD; |
421 | if(--max == 0) /* timeout */ | 435 | |
422 | return false; | 436 | /* Handle command responses */ |
423 | } | ||
424 | 437 | ||
425 | /* TODO Check crc values to determine if the response was valid */ | 438 | /* TODO Check crc values to determine if the response was valid */ |
426 | if(flags & MCI_RESP) | 439 | if(flags & MCI_RESP) |
427 | { | 440 | { |
428 | int i = 0xff; while(i--) ; | 441 | if(cmd_error & MCI_INT_RCRC) /* skipping timeout for now */ |
429 | /* if we read the response too fast we might read the response | 442 | return false; |
430 | * of the previous command instead */ | ||
431 | 443 | ||
432 | if(flags & MCI_LONG_RESP) | 444 | if(flags & MCI_LONG_RESP) |
433 | { | 445 | { |
@@ -498,6 +510,9 @@ static int sd_init_card(const int drive) | |||
498 | #endif | 510 | #endif |
499 | /* End of Card Identification Mode ************************************/ | 511 | /* End of Card Identification Mode ************************************/ |
500 | 512 | ||
513 | /* Card back to full speed */ | ||
514 | MCI_CLKDIV &= ~(0xFF); /* CLK_DIV_0 : bits 7:0 = 0x00 */ | ||
515 | |||
501 | /* Attempt to switch cards to HS timings, non HS cards just ignore this */ | 516 | /* Attempt to switch cards to HS timings, non HS cards just ignore this */ |
502 | /* CMD7 w/rca: Select card to put it in TRAN state */ | 517 | /* CMD7 w/rca: Select card to put it in TRAN state */ |
503 | if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_RESP, &response)) | 518 | if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_RESP, &response)) |
@@ -509,7 +524,6 @@ static int sd_init_card(const int drive) | |||
509 | /* CMD6 */ | 524 | /* CMD6 */ |
510 | if(!send_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL)) | 525 | if(!send_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL)) |
511 | return -9; | 526 | return -9; |
512 | mci_delay(); | ||
513 | 527 | ||
514 | /* We need to go back to STBY state now so we can read csd */ | 528 | /* We need to go back to STBY state now so we can read csd */ |
515 | /* CMD7 w/rca=0: Deselect card to put it in STBY state */ | 529 | /* CMD7 w/rca=0: Deselect card to put it in STBY state */ |
@@ -523,8 +537,6 @@ static int sd_init_card(const int drive) | |||
523 | 537 | ||
524 | sd_parse_csd(&card_info[drive]); | 538 | sd_parse_csd(&card_info[drive]); |
525 | 539 | ||
526 | /* Card back to full speed */ | ||
527 | MCI_CLKDIV &= ~(0xFF); /* CLK_DIV_0 : bits 7:0 = 0x00 */ | ||
528 | 540 | ||
529 | #ifndef HAVE_MULTIDRIVE | 541 | #ifndef HAVE_MULTIDRIVE |
530 | /* CMD7 w/rca: Select card to put it in TRAN state */ | 542 | /* CMD7 w/rca: Select card to put it in TRAN state */ |
@@ -686,7 +698,7 @@ int sd_init(void) | |||
686 | | 1; /* clock source = PLLA */ | 698 | | 1; /* clock source = PLLA */ |
687 | 699 | ||
688 | wakeup_init(&transfer_completion_signal); | 700 | wakeup_init(&transfer_completion_signal); |
689 | 701 | wakeup_init(&command_completion_signal); | |
690 | #ifdef HAVE_MULTIDRIVE | 702 | #ifdef HAVE_MULTIDRIVE |
691 | /* clear previous irq */ | 703 | /* clear previous irq */ |
692 | GPIOA_IC = EXT_SD_BITS; | 704 | GPIOA_IC = EXT_SD_BITS; |
@@ -729,9 +741,7 @@ static int sd_wait_for_state(const int drive, unsigned int state) | |||
729 | { | 741 | { |
730 | long tick; | 742 | long tick; |
731 | 743 | ||
732 | if(!send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca, | 744 | while(!(send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca, MCI_RESP, &response))); |
733 | MCI_RESP, &response)) | ||
734 | return -1; | ||
735 | 745 | ||
736 | if (((response >> 9) & 0xf) == state) | 746 | if (((response >> 9) & 0xf) == state) |
737 | return 0; | 747 | return 0; |
@@ -818,15 +828,11 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, | |||
818 | } | 828 | } |
819 | 829 | ||
820 | MCI_MASK |= (MCI_DATA_ERROR | MCI_INT_DTO); | 830 | MCI_MASK |= (MCI_DATA_ERROR | MCI_INT_DTO); |
821 | MCI_CTRL |= DMA_ENABLE; | ||
822 | 831 | ||
823 | int arg = start; | 832 | int arg = start; |
824 | if(!(card_info[drive].ocr & (1<<30))) /* not SDHC */ | 833 | if(!(card_info[drive].ocr & (1<<30))) /* not SDHC */ |
825 | arg *= SD_BLOCK_SIZE; | 834 | arg *= SD_BLOCK_SIZE; |
826 | 835 | ||
827 | if(!send_cmd(drive, cmd, arg, MCI_NO_RESP, NULL)) | ||
828 | panicf("%s multiple blocks failed", write ? "write" : "read"); | ||
829 | |||
830 | if(write) | 836 | if(write) |
831 | dma_enable_channel(0, dma_buf, MCI_FIFO, DMA_PERI_SD, | 837 | dma_enable_channel(0, dma_buf, MCI_FIFO, DMA_PERI_SD, |
832 | DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL); | 838 | DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL); |
@@ -834,6 +840,12 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, | |||
834 | dma_enable_channel(0, MCI_FIFO, dma_buf, DMA_PERI_SD, | 840 | dma_enable_channel(0, MCI_FIFO, dma_buf, DMA_PERI_SD, |
835 | DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL); | 841 | DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL); |
836 | 842 | ||
843 | MCI_CTRL |= DMA_ENABLE; | ||
844 | |||
845 | unsigned long dummy; /* if we don't ask for a response, writing fails */ | ||
846 | if(!send_cmd(drive, cmd, arg, MCI_RESP, &dummy)) | ||
847 | panicf("%s multiple blocks failed", write ? "write" : "read"); | ||
848 | |||
837 | wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK); | 849 | wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK); |
838 | 850 | ||
839 | MCI_MASK &= ~(MCI_DATA_ERROR | MCI_INT_DTO); | 851 | MCI_MASK &= ~(MCI_DATA_ERROR | MCI_INT_DTO); |
@@ -904,14 +916,7 @@ int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count, | |||
904 | (void) buf; | 916 | (void) buf; |
905 | return -1; | 917 | return -1; |
906 | #else | 918 | #else |
907 | //return sd_transfer_sectors(IF_MD2(drive,) start, count, (void*)buf, true); | 919 | return sd_transfer_sectors(IF_MD2(drive,) start, count, (void*)buf, true); |
908 | #ifdef HAVE_MULTIDRIVE | ||
909 | (void)drive; | ||
910 | #endif | ||
911 | (void)start; | ||
912 | (void)count; | ||
913 | (void)buf; | ||
914 | return -1; /* not working, seems to cause FIFO overruns */ | ||
915 | #endif /* defined(BOOTLOADER) */ | 920 | #endif /* defined(BOOTLOADER) */ |
916 | } | 921 | } |
917 | 922 | ||