diff options
Diffstat (limited to 'firmware/target/arm/as3525/sd-as3525v2.c')
-rw-r--r-- | firmware/target/arm/as3525/sd-as3525v2.c | 188 |
1 files changed, 69 insertions, 119 deletions
diff --git a/firmware/target/arm/as3525/sd-as3525v2.c b/firmware/target/arm/as3525/sd-as3525v2.c index 3f39629e0b..f78345577c 100644 --- a/firmware/target/arm/as3525/sd-as3525v2.c +++ b/firmware/target/arm/as3525/sd-as3525v2.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include "config.h" /* for HAVE_MULTIVOLUME */ | 23 | #include "config.h" /* for HAVE_MULTIVOLUME */ |
24 | #include "fs_defines.h" | 24 | #include "fs_defines.h" |
25 | #include "thread.h" | ||
26 | #include "gcc_extensions.h" | 25 | #include "gcc_extensions.h" |
27 | #include "led.h" | 26 | #include "led.h" |
28 | #include "sdmmc.h" | 27 | #include "sdmmc.h" |
@@ -36,19 +35,7 @@ | |||
36 | #include "pl081.h" /* DMA controller */ | 35 | #include "pl081.h" /* DMA controller */ |
37 | #include "dma-target.h" /* DMA request lines */ | 36 | #include "dma-target.h" /* DMA request lines */ |
38 | #include "clock-target.h" | 37 | #include "clock-target.h" |
39 | #include "panic.h" | 38 | #include "storage.h" |
40 | #include "stdbool.h" | ||
41 | #include "ata_idle_notify.h" | ||
42 | #include "sd.h" | ||
43 | #include "usb.h" | ||
44 | |||
45 | #ifdef HAVE_HOTSWAP | ||
46 | #include "disk.h" | ||
47 | #endif | ||
48 | |||
49 | #include "lcd.h" | ||
50 | #include <stdarg.h> | ||
51 | #include "sysfont.h" | ||
52 | 39 | ||
53 | #define INTERNAL_AS3525 0 /* embedded SD card */ | 40 | #define INTERNAL_AS3525 0 /* embedded SD card */ |
54 | #define SD_SLOT_AS3525 1 /* SD slot if present */ | 41 | #define SD_SLOT_AS3525 1 /* SD slot if present */ |
@@ -327,13 +314,15 @@ static unsigned char *uncached_buffer = AS3525_UNCACHED_ADDR(&aligned_buffer[0]) | |||
327 | 314 | ||
328 | static tCardInfo card_info[NUM_DRIVES]; | 315 | static tCardInfo card_info[NUM_DRIVES]; |
329 | 316 | ||
317 | #ifdef CONFIG_STORAGE_MULTI | ||
318 | static int sd_first_drive = 0; | ||
319 | #else | ||
320 | #define sd_first_drive 0 | ||
321 | #endif | ||
322 | |||
330 | /* for compatibility */ | 323 | /* for compatibility */ |
331 | static long last_disk_activity = -1; | 324 | static long last_disk_activity = -1; |
332 | |||
333 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | ||
334 | static const char sd_thread_name[] = "ata/sd"; | ||
335 | static struct mutex sd_mtx SHAREDBSS_ATTR; | 325 | static struct mutex sd_mtx SHAREDBSS_ATTR; |
336 | static struct event_queue sd_queue; | ||
337 | #ifndef BOOTLOADER | 326 | #ifndef BOOTLOADER |
338 | bool sd_enabled = false; | 327 | bool sd_enabled = false; |
339 | #endif | 328 | #endif |
@@ -371,6 +360,22 @@ void INT_NAND(void) | |||
371 | MCI_CTRL |= INT_ENABLE; | 360 | MCI_CTRL |= INT_ENABLE; |
372 | } | 361 | } |
373 | 362 | ||
363 | #ifndef BOOTLOADER | ||
364 | static void enable_controller(bool on) | ||
365 | { | ||
366 | if (on) | ||
367 | { | ||
368 | bitset32(&CGU_PERI, CGU_MCI_CLOCK_ENABLE); | ||
369 | CGU_SDSLOT |= (1<<7); /* interface enable */ | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | CGU_SDSLOT &= ~(1<<7); /* interface enable */ | ||
374 | bitclr32(&CGU_PERI, CGU_MCI_CLOCK_ENABLE); | ||
375 | } | ||
376 | } | ||
377 | #endif /* BOOTLOADER */ | ||
378 | |||
374 | static inline bool card_detect_target(void) | 379 | static inline bool card_detect_target(void) |
375 | { | 380 | { |
376 | #if defined(HAVE_MULTIDRIVE) | 381 | #if defined(HAVE_MULTIDRIVE) |
@@ -577,75 +582,6 @@ static int sd_init_card(const int drive) | |||
577 | return 0; | 582 | return 0; |
578 | } | 583 | } |
579 | 584 | ||
580 | static void sd_thread(void) NORETURN_ATTR; | ||
581 | static void sd_thread(void) | ||
582 | { | ||
583 | struct queue_event ev; | ||
584 | bool idle_notified = false; | ||
585 | |||
586 | while (1) | ||
587 | { | ||
588 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
589 | |||
590 | switch ( ev.id ) | ||
591 | { | ||
592 | #ifdef HAVE_HOTSWAP | ||
593 | case SYS_HOTSWAP_INSERTED: | ||
594 | case SYS_HOTSWAP_EXTRACTED:; | ||
595 | int success = 1; | ||
596 | |||
597 | disk_unmount(SD_SLOT_AS3525); /* release "by force" */ | ||
598 | |||
599 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
600 | |||
601 | /* Force card init for new card, re-init for re-inserted one or | ||
602 | * clear if the last attempt to init failed with an error. */ | ||
603 | card_info[SD_SLOT_AS3525].initialized = 0; | ||
604 | |||
605 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
606 | { | ||
607 | sd_enable(true); | ||
608 | success = sd_init_card(SD_SLOT_AS3525) == 0 ? 2 : 0; | ||
609 | sd_enable(false); | ||
610 | } | ||
611 | |||
612 | mutex_unlock(&sd_mtx); | ||
613 | |||
614 | if (success > 1) | ||
615 | success = disk_mount(SD_SLOT_AS3525); /* 0 if fail */ | ||
616 | |||
617 | /* | ||
618 | * Mount succeeded, or this was an EXTRACTED event, | ||
619 | * in both cases notify the system about the changed filesystems | ||
620 | */ | ||
621 | if (success) | ||
622 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
623 | |||
624 | break; | ||
625 | #endif /* HAVE_HOTSWAP */ | ||
626 | |||
627 | case SYS_TIMEOUT: | ||
628 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
629 | { | ||
630 | idle_notified = false; | ||
631 | } | ||
632 | else if (!idle_notified) | ||
633 | { | ||
634 | call_storage_idle_notifys(false); | ||
635 | idle_notified = true; | ||
636 | } | ||
637 | break; | ||
638 | |||
639 | case SYS_USB_CONNECTED: | ||
640 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
641 | /* Wait until the USB cable is extracted again */ | ||
642 | usb_wait_for_disconnect(&sd_queue); | ||
643 | |||
644 | break; | ||
645 | } | ||
646 | } | ||
647 | } | ||
648 | |||
649 | static void init_controller(void) | 585 | static void init_controller(void) |
650 | { | 586 | { |
651 | int hcon_numcards = ((MCI_HCON>>1) & 0x1F) + 1; | 587 | int hcon_numcards = ((MCI_HCON>>1) & 0x1F) + 1; |
@@ -706,6 +642,7 @@ int sd_init(void) | |||
706 | | (AS3525_SDSLOT_DIV << 2) | 642 | | (AS3525_SDSLOT_DIV << 2) |
707 | | 1; /* clock source = PLLA */ | 643 | | 1; /* clock source = PLLA */ |
708 | 644 | ||
645 | mutex_init(&sd_mtx); | ||
709 | semaphore_init(&transfer_completion_signal, 1, 0); | 646 | semaphore_init(&transfer_completion_signal, 1, 0); |
710 | semaphore_init(&command_completion_signal, 1, 0); | 647 | semaphore_init(&command_completion_signal, 1, 0); |
711 | 648 | ||
@@ -737,16 +674,9 @@ int sd_init(void) | |||
737 | if(ret < 0) | 674 | if(ret < 0) |
738 | return ret; | 675 | return ret; |
739 | 676 | ||
740 | /* init mutex */ | ||
741 | mutex_init(&sd_mtx); | ||
742 | |||
743 | queue_init(&sd_queue, true); | ||
744 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | ||
745 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | ||
746 | |||
747 | #ifndef BOOTLOADER | 677 | #ifndef BOOTLOADER |
748 | sd_enabled = true; | 678 | sd_enabled = true; |
749 | sd_enable(false); | 679 | enable_controller(false); |
750 | #endif | 680 | #endif |
751 | return 0; | 681 | return 0; |
752 | } | 682 | } |
@@ -767,7 +697,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, | |||
767 | 697 | ||
768 | mutex_lock(&sd_mtx); | 698 | mutex_lock(&sd_mtx); |
769 | #ifndef BOOTLOADER | 699 | #ifndef BOOTLOADER |
770 | sd_enable(true); | 700 | enable_controller(true); |
771 | led(true); | 701 | led(true); |
772 | #endif | 702 | #endif |
773 | 703 | ||
@@ -925,7 +855,7 @@ retry_with_reinit: | |||
925 | 855 | ||
926 | exit: | 856 | exit: |
927 | #ifndef BOOTLOADER | 857 | #ifndef BOOTLOADER |
928 | sd_enable(false); | 858 | enable_controller(false); |
929 | led(false); | 859 | led(false); |
930 | #endif | 860 | #endif |
931 | mutex_unlock(&sd_mtx); | 861 | mutex_unlock(&sd_mtx); |
@@ -952,16 +882,9 @@ long sd_last_disk_activity(void) | |||
952 | 882 | ||
953 | void sd_enable(bool on) | 883 | void sd_enable(bool on) |
954 | { | 884 | { |
955 | if (on) | 885 | mutex_lock(&sd_mtx); |
956 | { | 886 | enable_controller(on); |
957 | bitset32(&CGU_PERI, CGU_MCI_CLOCK_ENABLE); | 887 | mutex_unlock(&sd_mtx); |
958 | CGU_SDSLOT |= (1<<7); /* interface enable */ | ||
959 | } | ||
960 | else | ||
961 | { | ||
962 | CGU_SDSLOT &= ~(1<<7); /* interface enable */ | ||
963 | bitclr32(&CGU_PERI, CGU_MCI_CLOCK_ENABLE); | ||
964 | } | ||
965 | } | 888 | } |
966 | #endif /* BOOTLOADER */ | 889 | #endif /* BOOTLOADER */ |
967 | 890 | ||
@@ -983,18 +906,13 @@ bool sd_present(IF_MD_NONVOID(int drive)) | |||
983 | 906 | ||
984 | static int sd1_oneshot_callback(struct timeout *tmo) | 907 | static int sd1_oneshot_callback(struct timeout *tmo) |
985 | { | 908 | { |
986 | (void)tmo; | ||
987 | |||
988 | /* This is called only if the state was stable for 300ms - check state | 909 | /* This is called only if the state was stable for 300ms - check state |
989 | * and post appropriate event. */ | 910 | * and post appropriate event. */ |
990 | if (card_detect_target()) | 911 | queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED : |
991 | { | 912 | SYS_HOTSWAP_EXTRACTED, |
992 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 913 | sd_first_drive + SD_SLOT_AS3525); |
993 | } | ||
994 | else | ||
995 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
996 | |||
997 | return 0; | 914 | return 0; |
915 | (void)tmo; | ||
998 | } | 916 | } |
999 | 917 | ||
1000 | void sd_gpioa_isr(void) | 918 | void sd_gpioa_isr(void) |
@@ -1012,9 +930,41 @@ void sd_gpioa_isr(void) | |||
1012 | #ifdef CONFIG_STORAGE_MULTI | 930 | #ifdef CONFIG_STORAGE_MULTI |
1013 | int sd_num_drives(int first_drive) | 931 | int sd_num_drives(int first_drive) |
1014 | { | 932 | { |
1015 | /* We don't care which logical drive number(s) we have been assigned */ | 933 | sd_first_drive = first_drive; |
1016 | (void)first_drive; | ||
1017 | |||
1018 | return NUM_DRIVES; | 934 | return NUM_DRIVES; |
1019 | } | 935 | } |
1020 | #endif /* CONFIG_STORAGE_MULTI */ | 936 | #endif /* CONFIG_STORAGE_MULTI */ |
937 | |||
938 | int sd_event(long id, intptr_t data) | ||
939 | { | ||
940 | int rc = 0; | ||
941 | |||
942 | switch (id) | ||
943 | { | ||
944 | #ifdef HAVE_HOTSWAP | ||
945 | case SYS_HOTSWAP_INSERTED: | ||
946 | case SYS_HOTSWAP_EXTRACTED: | ||
947 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
948 | |||
949 | /* Force card init for new card, re-init for re-inserted one or | ||
950 | * clear if the last attempt to init failed with an error. */ | ||
951 | card_info[data].initialized = 0; | ||
952 | |||
953 | if (id == SYS_HOTSWAP_INSERTED) | ||
954 | { | ||
955 | enable_controller(true); | ||
956 | rc = sd_init_card(data); | ||
957 | enable_controller(false); | ||
958 | } | ||
959 | |||
960 | mutex_unlock(&sd_mtx); | ||
961 | break; | ||
962 | #endif /* HAVE_HOTSWAP */ | ||
963 | default: | ||
964 | rc = storage_event_default_handler(id, data, last_disk_activity, | ||
965 | STORAGE_SD); | ||
966 | break; | ||
967 | } | ||
968 | |||
969 | return rc; | ||
970 | } | ||