summaryrefslogtreecommitdiff
path: root/firmware/target/arm/as3525
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/as3525')
-rw-r--r--firmware/target/arm/as3525/sd-as3525v2.c63
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
340static struct wakeup transfer_completion_signal; 340static struct wakeup transfer_completion_signal;
341static struct wakeup command_completion_signal;
341static volatile bool retry; 342static volatile bool retry;
343static volatile int cmd_error;
342 344
343#if defined(HAVE_MULTIDRIVE) 345#if defined(HAVE_MULTIDRIVE)
344int active_card = 0; 346int active_card = 0;
@@ -350,7 +352,8 @@ static inline void mci_delay(void) { udelay(1000); }
350void INT_NAND(void) 352void 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