diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/export/config/sansaclipplus.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/as3525/sd-as3525v2.c | 129 |
2 files changed, 99 insertions, 34 deletions
diff --git a/firmware/export/config/sansaclipplus.h b/firmware/export/config/sansaclipplus.h index f54951f0ac..310df3a115 100644 --- a/firmware/export/config/sansaclipplus.h +++ b/firmware/export/config/sansaclipplus.h | |||
@@ -9,13 +9,13 @@ | |||
9 | #define FIRMWARE_OFFSET_FILE_DATA 8 | 9 | #define FIRMWARE_OFFSET_FILE_DATA 8 |
10 | #define FIRMWARE_OFFSET_FILE_CRC 0 | 10 | #define FIRMWARE_OFFSET_FILE_CRC 0 |
11 | 11 | ||
12 | #if 0 /* TODO */ | 12 | |
13 | #ifndef BOOTLOADER | 13 | #ifndef BOOTLOADER |
14 | #define HAVE_MULTIDRIVE | 14 | #define HAVE_MULTIDRIVE |
15 | #define NUM_DRIVES 2 | 15 | #define NUM_DRIVES 2 |
16 | #define HAVE_HOTSWAP | 16 | #define HAVE_HOTSWAP |
17 | #endif | 17 | #endif |
18 | #endif | 18 | |
19 | 19 | ||
20 | #if 0 /* disabled since there is no driver (yet) */ | 20 | #if 0 /* disabled since there is no driver (yet) */ |
21 | 21 | ||
diff --git a/firmware/target/arm/as3525/sd-as3525v2.c b/firmware/target/arm/as3525/sd-as3525v2.c index 37f3a70601..992db4d307 100644 --- a/firmware/target/arm/as3525/sd-as3525v2.c +++ b/firmware/target/arm/as3525/sd-as3525v2.c | |||
@@ -140,6 +140,7 @@ | |||
140 | #define CMD_WAIT_PRV_DAT_BIT (1<<13) | 140 | #define CMD_WAIT_PRV_DAT_BIT (1<<13) |
141 | #define CMD_ABRT_CMD_BIT (1<<14) | 141 | #define CMD_ABRT_CMD_BIT (1<<14) |
142 | #define CMD_SEND_INIT_BIT (1<<15) | 142 | #define CMD_SEND_INIT_BIT (1<<15) |
143 | #define CMD_CARD_NO(x) ((x)<<16) /* 5 bits wide */ | ||
143 | #define CMD_SEND_CLK_ONLY (1<<21) | 144 | #define CMD_SEND_CLK_ONLY (1<<21) |
144 | #define CMD_READ_CEATA (1<<22) | 145 | #define CMD_READ_CEATA (1<<22) |
145 | #define CMD_CCS_EXPECTED (1<<23) | 146 | #define CMD_CCS_EXPECTED (1<<23) |
@@ -326,14 +327,9 @@ static struct wakeup transfer_completion_signal; | |||
326 | static volatile bool retry; | 327 | static volatile bool retry; |
327 | static volatile bool data_transfer = false; | 328 | static volatile bool data_transfer = false; |
328 | 329 | ||
329 | static inline bool card_detect_target(void) | ||
330 | { | ||
331 | #if defined(HAVE_MULTIDRIVE) | 330 | #if defined(HAVE_MULTIDRIVE) |
332 | return !(GPIOA_PIN(2)); | 331 | int active_card = 0; |
333 | #else | ||
334 | return false; | ||
335 | #endif | 332 | #endif |
336 | } | ||
337 | 333 | ||
338 | static inline void mci_delay(void) { int i = 0xffff; while(i--) ; } | 334 | static inline void mci_delay(void) { int i = 0xffff; while(i--) ; } |
339 | 335 | ||
@@ -353,10 +349,32 @@ void INT_NAND(void) | |||
353 | MCI_CTRL |= INT_ENABLE; | 349 | MCI_CTRL |= INT_ENABLE; |
354 | } | 350 | } |
355 | 351 | ||
356 | static bool send_cmd(const int cmd, const int arg, const int flags, | 352 | static inline bool card_detect_target(void) |
353 | { | ||
354 | #if defined(HAVE_MULTIDRIVE) | ||
355 | return !(GPIOA_PIN(2)); | ||
356 | #else | ||
357 | return false; | ||
358 | #endif | ||
359 | } | ||
360 | |||
361 | static bool send_cmd(const int drive, const int cmd, const int arg, const int flags, | ||
357 | unsigned long *response) | 362 | unsigned long *response) |
358 | { | 363 | { |
364 | #if defined(HAVE_MULTIDRIVE) | ||
365 | /* Check to see if we need to switch cards */ | ||
366 | if(sd_present(SD_SLOT_AS3525)) | ||
367 | if(active_card != drive) | ||
368 | { | ||
369 | GPIOB_PIN(5) = (1-drive) << 5; | ||
370 | active_card = drive; | ||
371 | } | ||
372 | |||
373 | MCI_COMMAND = cmd | CMD_CARD_NO(drive); | ||
374 | #else | ||
375 | (void) drive; | ||
359 | MCI_COMMAND = cmd; | 376 | MCI_COMMAND = cmd; |
377 | #endif | ||
360 | 378 | ||
361 | if(flags & MCI_RESP) | 379 | if(flags & MCI_RESP) |
362 | { | 380 | { |
@@ -420,13 +438,13 @@ static int sd_init_card(const int drive) | |||
420 | /* Start of Card Identification Mode ************************************/ | 438 | /* Start of Card Identification Mode ************************************/ |
421 | 439 | ||
422 | /* CMD0 Go Idle */ | 440 | /* CMD0 Go Idle */ |
423 | if(!send_cmd(SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) | 441 | if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) |
424 | return -1; | 442 | return -1; |
425 | mci_delay(); | 443 | mci_delay(); |
426 | 444 | ||
427 | /* CMD8 Check for v2 sd card. Must be sent before using ACMD41 | 445 | /* CMD8 Check for v2 sd card. Must be sent before using ACMD41 |
428 | Non v2 cards will not respond to this command*/ | 446 | Non v2 cards will not respond to this command*/ |
429 | if(send_cmd(SD_SEND_IF_COND, 0x1AA, MCI_RESP, &response)) | 447 | if(send_cmd(drive, SD_SEND_IF_COND, 0x1AA, MCI_RESP, &response)) |
430 | if((response & 0xFFF) == 0x1AA) | 448 | if((response & 0xFFF) == 0x1AA) |
431 | sd_v2 = true; | 449 | sd_v2 = true; |
432 | 450 | ||
@@ -439,37 +457,45 @@ static int sd_init_card(const int drive) | |||
439 | return -2; | 457 | return -2; |
440 | 458 | ||
441 | /* app_cmd */ | 459 | /* app_cmd */ |
442 | send_cmd(SD_APP_CMD, 0, MCI_RESP, &response); | 460 | send_cmd(drive, SD_APP_CMD, 0, MCI_RESP, &response); |
443 | 461 | ||
444 | /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */ | 462 | /* ACMD41 For v2 cards set HCS bit[30] & send host voltage range to all */ |
445 | if(!send_cmd(SD_APP_OP_COND, (sd_v2 ? 0x40FF8000 : (1<<23)), | 463 | if(!send_cmd(drive, SD_APP_OP_COND, (sd_v2 ? 0x40FF8000 : (1<<23)), |
446 | MCI_RESP, &card_info[drive].ocr)) | 464 | MCI_RESP, &card_info[drive].ocr)) |
447 | return -3; | 465 | return -3; |
448 | } while(!(card_info[drive].ocr & (1<<31)) ); | 466 | } while(!(card_info[drive].ocr & (1<<31)) ); |
449 | 467 | ||
450 | /* CMD2 send CID */ | 468 | /* CMD2 send CID */ |
451 | if(!send_cmd(SD_ALL_SEND_CID, 0, MCI_RESP|MCI_LONG_RESP, card_info[drive].cid)) | 469 | if(!send_cmd(drive, SD_ALL_SEND_CID, 0, MCI_RESP|MCI_LONG_RESP, card_info[drive].cid)) |
452 | return -5; | 470 | return -4; |
453 | 471 | ||
454 | /* CMD3 send RCA */ | 472 | /* CMD3 send RCA */ |
455 | if(!send_cmd(SD_SEND_RELATIVE_ADDR, 0, MCI_RESP, &card_info[drive].rca)) | 473 | if(!send_cmd(drive, SD_SEND_RELATIVE_ADDR, 0, MCI_RESP, &card_info[drive].rca)) |
456 | return -4; | 474 | return -5; |
457 | 475 | ||
476 | #ifdef HAVE_MULTIDRIVE | ||
477 | /* Make sure we have 2 unique rca numbers */ | ||
478 | if(card_info[INTERNAL_AS3525].rca == card_info[SD_SLOT_AS3525].rca) | ||
479 | if(!send_cmd(drive, SD_SEND_RELATIVE_ADDR, 0, MCI_RESP, &card_info[drive].rca)) | ||
480 | return -6; | ||
481 | #endif | ||
458 | /* End of Card Identification Mode ************************************/ | 482 | /* End of Card Identification Mode ************************************/ |
459 | 483 | ||
460 | /* CMD9 send CSD */ | 484 | /* CMD9 send CSD */ |
461 | if(!send_cmd(SD_SEND_CSD, card_info[drive].rca, | 485 | if(!send_cmd(drive, SD_SEND_CSD, card_info[drive].rca, |
462 | MCI_RESP|MCI_LONG_RESP, card_info[drive].csd)) | 486 | MCI_RESP|MCI_LONG_RESP, card_info[drive].csd)) |
463 | return -5; | 487 | return -7; |
464 | 488 | ||
465 | sd_parse_csd(&card_info[drive]); | 489 | sd_parse_csd(&card_info[drive]); |
466 | 490 | ||
467 | /* Card back to full speed */ | 491 | /* Card back to full speed */ |
468 | MCI_CLKDIV &= ~(0xFF); /* CLK_DIV_0 : bits 7:0 = 0x00 */ | 492 | MCI_CLKDIV &= ~(0xFF); /* CLK_DIV_0 : bits 7:0 = 0x00 */ |
469 | 493 | ||
494 | #ifndef HAVE_MULTIDRIVE | ||
470 | /* CMD7 w/rca: Select card to put it in TRAN state */ | 495 | /* CMD7 w/rca: Select card to put it in TRAN state */ |
471 | if(!send_cmd(SD_SELECT_CARD, card_info[drive].rca, MCI_NO_RESP, NULL)) | 496 | if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_NO_RESP, NULL)) |
472 | return -6; | 497 | return -8; |
498 | #endif | ||
473 | 499 | ||
474 | card_info[drive].initialized = 1; | 500 | card_info[drive].initialized = 1; |
475 | 501 | ||
@@ -566,12 +592,15 @@ static void sd_thread(void) | |||
566 | 592 | ||
567 | static void init_controller(void) | 593 | static void init_controller(void) |
568 | { | 594 | { |
569 | MCI_PWREN = 0x0; /* power off all cards */ | 595 | int hcon_numcards = ((MCI_HCON>>1) & 0x1F) + 1; |
596 | int card_mask = (1 << hcon_numcards) - 1; | ||
597 | |||
598 | MCI_PWREN &= ~card_mask; /* power off all cards */ | ||
570 | 599 | ||
571 | MCI_CLKSRC = 0x00; /* All CLK_SRC_CRD set to 0*/ | 600 | MCI_CLKSRC = 0x00; /* All CLK_SRC_CRD set to 0*/ |
572 | MCI_CLKDIV = 0x00; /* CLK_DIV_0 : bits 7:0 */ | 601 | MCI_CLKDIV = 0x00; /* CLK_DIV_0 : bits 7:0 */ |
573 | 602 | ||
574 | MCI_PWREN = PWR_CRD_0; /* power up card 0 (internal) */ | 603 | MCI_PWREN |= card_mask; /* power up cards */ |
575 | mci_delay(); | 604 | mci_delay(); |
576 | 605 | ||
577 | MCI_CTRL |= CTRL_RESET; | 606 | MCI_CTRL |= CTRL_RESET; |
@@ -584,7 +613,7 @@ static void init_controller(void) | |||
584 | 613 | ||
585 | MCI_CTYPE = 0x0; /* all cards 1 bit bus for now */ | 614 | MCI_CTYPE = 0x0; /* all cards 1 bit bus for now */ |
586 | 615 | ||
587 | MCI_CLKENA = CCLK_ENA_CRD0; | 616 | MCI_CLKENA = card_mask; |
588 | 617 | ||
589 | MCI_ARGUMENT = 0; | 618 | MCI_ARGUMENT = 0; |
590 | MCI_COMMAND = CMD_DONE_BIT|CMD_SEND_CLK_ONLY|CMD_WAIT_PRV_DAT_BIT; | 619 | MCI_COMMAND = CMD_DONE_BIT|CMD_SEND_CLK_ONLY|CMD_WAIT_PRV_DAT_BIT; |
@@ -598,6 +627,8 @@ static void init_controller(void) | |||
598 | 627 | ||
599 | MCI_MASK = 0xffffffff & ~(MCI_INT_ACD|MCI_INT_CRDDET); | 628 | MCI_MASK = 0xffffffff & ~(MCI_INT_ACD|MCI_INT_CRDDET); |
600 | 629 | ||
630 | GPIOB_DIR |= (1<<5); /* Pin B5 output */ | ||
631 | |||
601 | MCI_CTRL |= INT_ENABLE; | 632 | MCI_CTRL |= INT_ENABLE; |
602 | } | 633 | } |
603 | 634 | ||
@@ -614,14 +645,23 @@ int sd_init(void) | |||
614 | CGU_MEMSTICK = (1<<8) | (1<<7) | | 645 | CGU_MEMSTICK = (1<<8) | (1<<7) | |
615 | ((CLK_DIV(AS3525_PLLA_FREQ, AS3525_MS_FREQ) -1) << 2) | 1; | 646 | ((CLK_DIV(AS3525_PLLA_FREQ, AS3525_MS_FREQ) -1) << 2) | 1; |
616 | 647 | ||
617 | /* FIXME: divider should be shifted by 2, but doing prevents card | ||
618 | * initialisation */ | ||
619 | *(volatile int*)(CGU_BASE+0x3C) = (1<<7) | | 648 | *(volatile int*)(CGU_BASE+0x3C) = (1<<7) | |
620 | (CLK_DIV(AS3525_PLLA_FREQ, 24000000) -1) | 1; | 649 | (CLK_DIV(AS3525_PLLA_FREQ, 24000000) -1)<<2 | 1; |
621 | 650 | ||
622 | wakeup_init(&transfer_completion_signal); | 651 | wakeup_init(&transfer_completion_signal); |
623 | 652 | ||
624 | VIC_INT_ENABLE |= INTERRUPT_NAND; | 653 | #ifdef HAVE_MULTIDRIVE |
654 | /* setup isr for microsd monitoring */ | ||
655 | VIC_INT_ENABLE = (INTERRUPT_GPIOA); | ||
656 | /* clear previous irq */ | ||
657 | GPIOA_IC = (1<<2); | ||
658 | /* enable edge detecting */ | ||
659 | GPIOA_IS &= ~(1<<2); | ||
660 | /* detect both raising and falling edges */ | ||
661 | GPIOA_IBE |= (1<<2); | ||
662 | #endif | ||
663 | |||
664 | VIC_INT_ENABLE = INTERRUPT_NAND; | ||
625 | 665 | ||
626 | init_controller(); | 666 | init_controller(); |
627 | ret = sd_init_card(INTERNAL_AS3525); | 667 | ret = sd_init_card(INTERNAL_AS3525); |
@@ -652,7 +692,7 @@ static int sd_wait_for_state(const int drive, unsigned int state) | |||
652 | { | 692 | { |
653 | long tick; | 693 | long tick; |
654 | 694 | ||
655 | if(!send_cmd(SD_SEND_STATUS, card_info[drive].rca, | 695 | if(!send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca, |
656 | MCI_RESP, &response)) | 696 | MCI_RESP, &response)) |
657 | return -1; | 697 | return -1; |
658 | 698 | ||
@@ -698,6 +738,12 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, | |||
698 | } | 738 | } |
699 | } | 739 | } |
700 | 740 | ||
741 | #ifdef HAVE_MULTIDRIVE | ||
742 | /* CMD7 w/rca: Select card to put it in TRAN state */ | ||
743 | if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_NO_RESP, NULL)) | ||
744 | return -6; | ||
745 | #endif | ||
746 | |||
701 | last_disk_activity = current_tick; | 747 | last_disk_activity = current_tick; |
702 | ret = sd_wait_for_state(drive, SD_TRAN); | 748 | ret = sd_wait_for_state(drive, SD_TRAN); |
703 | if (ret < 0) | 749 | if (ret < 0) |
@@ -706,7 +752,7 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, | |||
706 | "IDLE", "RDY", "IDENT", "STBY", "TRAN", "DATA", "RCV", "PRG", "DIS" | 752 | "IDLE", "RDY", "IDENT", "STBY", "TRAN", "DATA", "RCV", "PRG", "DIS" |
707 | }; | 753 | }; |
708 | if(ret <= -10) | 754 | if(ret <= -10) |
709 | panicf("wait for state failed (%s)", st[(-ret / 10) % 9]); | 755 | panicf("wait for state failed (%s) %d", st[(-ret / 10) % 9], drive); |
710 | else | 756 | else |
711 | panicf("wait for state failed"); | 757 | panicf("wait for state failed"); |
712 | goto sd_transfer_error; | 758 | goto sd_transfer_error; |
@@ -745,9 +791,9 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, | |||
745 | 791 | ||
746 | 792 | ||
747 | if(card_info[drive].ocr & (1<<30) ) /* SDHC */ | 793 | if(card_info[drive].ocr & (1<<30) ) /* SDHC */ |
748 | ret = send_cmd(cmd, start, MCI_NO_RESP, NULL); | 794 | ret = send_cmd(drive, cmd, start, MCI_NO_RESP, NULL); |
749 | else | 795 | else |
750 | ret = send_cmd(cmd, start * SD_BLOCK_SIZE, | 796 | ret = send_cmd(drive, cmd, start * SD_BLOCK_SIZE, |
751 | MCI_NO_RESP, NULL); | 797 | MCI_NO_RESP, NULL); |
752 | 798 | ||
753 | if (ret < 0) | 799 | if (ret < 0) |
@@ -766,7 +812,7 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, | |||
766 | 812 | ||
767 | last_disk_activity = current_tick; | 813 | last_disk_activity = current_tick; |
768 | 814 | ||
769 | if(!send_cmd(SD_STOP_TRANSMISSION, 0, MCI_NO_RESP, NULL)) | 815 | if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_NO_RESP, NULL)) |
770 | { | 816 | { |
771 | ret = -666; | 817 | ret = -666; |
772 | panicf("STOP TRANSMISSION failed"); | 818 | panicf("STOP TRANSMISSION failed"); |
@@ -792,6 +838,12 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start, | |||
792 | 838 | ||
793 | dma_release(); | 839 | dma_release(); |
794 | 840 | ||
841 | #ifdef HAVE_MULTIDRIVE | ||
842 | /* CMD7 w/rca =0 : deselect card to put it in STBY state */ | ||
843 | if(!send_cmd(drive, SD_SELECT_CARD, 0, MCI_NO_RESP, NULL)) | ||
844 | return -6; | ||
845 | #endif | ||
846 | |||
795 | #ifndef BOOTLOADER | 847 | #ifndef BOOTLOADER |
796 | sd_enable(false); | 848 | sd_enable(false); |
797 | #endif | 849 | #endif |
@@ -836,7 +888,10 @@ long sd_last_disk_activity(void) | |||
836 | void sd_enable(bool on) | 888 | void sd_enable(bool on) |
837 | { | 889 | { |
838 | /* TODO */ | 890 | /* TODO */ |
839 | (void)on; | 891 | if(on) |
892 | CCU_IO |= (1<<2); /* XPD is SD-MCI interface (b3:2 = 01) */ | ||
893 | else | ||
894 | CCU_IO &= ~(1<<2); /* XPD is general purpose IO (b3:2 = 00) */ | ||
840 | return; | 895 | return; |
841 | } | 896 | } |
842 | 897 | ||
@@ -889,3 +944,13 @@ void card_enable_monitoring_target(bool on) | |||
889 | GPIOA_IE &= ~(1<<2); | 944 | GPIOA_IE &= ~(1<<2); |
890 | } | 945 | } |
891 | #endif /* HAVE_HOTSWAP */ | 946 | #endif /* HAVE_HOTSWAP */ |
947 | |||
948 | #ifdef CONFIG_STORAGE_MULTI | ||
949 | int sd_num_drives(int first_drive) | ||
950 | { | ||
951 | /* We don't care which logical drive number(s) we have been assigned */ | ||
952 | (void)first_drive; | ||
953 | |||
954 | return NUM_DRIVES; | ||
955 | } | ||
956 | #endif /* CONFIG_STORAGE_MULTI */ | ||