diff options
Diffstat (limited to 'firmware/target/arm/as3525/sd-as3525.c')
-rw-r--r-- | firmware/target/arm/as3525/sd-as3525.c | 276 |
1 files changed, 113 insertions, 163 deletions
diff --git a/firmware/target/arm/as3525/sd-as3525.c b/firmware/target/arm/as3525/sd-as3525.c index e65a7525b6..d6c6654319 100644 --- a/firmware/target/arm/as3525/sd-as3525.c +++ b/firmware/target/arm/as3525/sd-as3525.c | |||
@@ -24,7 +24,6 @@ | |||
24 | 24 | ||
25 | #include "config.h" /* for HAVE_MULTIDRIVE & AMS_OF_SIZE */ | 25 | #include "config.h" /* for HAVE_MULTIDRIVE & AMS_OF_SIZE */ |
26 | #include "fs_defines.h" | 26 | #include "fs_defines.h" |
27 | #include "thread.h" | ||
28 | #include "led.h" | 27 | #include "led.h" |
29 | #include "sdmmc.h" | 28 | #include "sdmmc.h" |
30 | #include "system.h" | 29 | #include "system.h" |
@@ -39,20 +38,15 @@ | |||
39 | #include "dma-target.h" /* DMA request lines */ | 38 | #include "dma-target.h" /* DMA request lines */ |
40 | #include "clock-target.h" | 39 | #include "clock-target.h" |
41 | #include "panic.h" | 40 | #include "panic.h" |
41 | #include "storage.h" | ||
42 | |||
42 | #ifdef HAVE_BUTTON_LIGHT | 43 | #ifdef HAVE_BUTTON_LIGHT |
43 | #include "backlight-target.h" | 44 | #include "backlight-target.h" |
44 | #endif | 45 | #endif |
45 | #include "stdbool.h" | 46 | |
46 | #include "ata_idle_notify.h" | ||
47 | #include "sd.h" | ||
48 | #include "usb.h" | ||
49 | /*#define LOGF_ENABLE*/ | 47 | /*#define LOGF_ENABLE*/ |
50 | #include "logf.h" | 48 | #include "logf.h" |
51 | 49 | ||
52 | #ifdef HAVE_HOTSWAP | ||
53 | #include "disk.h" | ||
54 | #endif | ||
55 | |||
56 | //#define VERIFY_WRITE 1 | 50 | //#define VERIFY_WRITE 1 |
57 | 51 | ||
58 | /* command flags */ | 52 | /* command flags */ |
@@ -119,16 +113,19 @@ static tCardInfo card_info[NUM_DRIVES]; | |||
119 | #define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */ | 113 | #define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */ |
120 | #define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */ | 114 | #define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */ |
121 | 115 | ||
116 | #ifdef CONFIG_STORAGE_MULTI | ||
117 | static int sd_first_drive = 0; | ||
118 | #else | ||
119 | #define sd_first_drive 0 | ||
120 | #endif | ||
121 | |||
122 | /* for compatibility */ | 122 | /* for compatibility */ |
123 | static long last_disk_activity = -1; | 123 | static long last_disk_activity = -1; |
124 | 124 | ||
125 | #define MIN_YIELD_PERIOD 5 /* ticks */ | 125 | #define MIN_YIELD_PERIOD 5 /* ticks */ |
126 | static long next_yield = 0; | 126 | static long next_yield = 0; |
127 | 127 | ||
128 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | 128 | static struct mutex sd_mtx; |
129 | static const char sd_thread_name[] = "ata/sd"; | ||
130 | static struct mutex sd_mtx; | ||
131 | static struct event_queue sd_queue; | ||
132 | bool sd_enabled = false; | 129 | bool sd_enabled = false; |
133 | 130 | ||
134 | #if defined(HAVE_MULTIDRIVE) | 131 | #if defined(HAVE_MULTIDRIVE) |
@@ -147,6 +144,59 @@ static unsigned char *uncached_buffer = AS3525_UNCACHED_ADDR(&aligned_buffer[0]) | |||
147 | 144 | ||
148 | static inline void mci_delay(void) { udelay(1000) ; } | 145 | static inline void mci_delay(void) { udelay(1000) ; } |
149 | 146 | ||
147 | static void enable_controller(bool on) | ||
148 | { | ||
149 | |||
150 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | ||
151 | extern int buttonlight_is_on; | ||
152 | #endif | ||
153 | |||
154 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
155 | static bool cpu_boosted = false; | ||
156 | #endif | ||
157 | |||
158 | if (sd_enabled == on) | ||
159 | return; /* nothing to do */ | ||
160 | |||
161 | sd_enabled = on; | ||
162 | |||
163 | if(on) | ||
164 | { | ||
165 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | ||
166 | /* buttonlight AMSes need a bit of special handling for the buttonlight | ||
167 | * here due to the dual mapping of GPIOD and XPD */ | ||
168 | bitmod32(&CCU_IO, 1<<2, 3<<2); /* XPD is SD-MCI interface (b3:2 = 01) */ | ||
169 | if (buttonlight_is_on) | ||
170 | GPIOD_DIR &= ~(1<<7); | ||
171 | else | ||
172 | buttonlight_hw_off(); | ||
173 | #endif | ||
174 | |||
175 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
176 | if(card_detect_target()) /* If SD card present Boost cpu for voltage */ | ||
177 | { | ||
178 | cpu_boosted = true; | ||
179 | cpu_boost(true); | ||
180 | } | ||
181 | #endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */ | ||
182 | } | ||
183 | else | ||
184 | { | ||
185 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
186 | if(cpu_boosted) | ||
187 | { | ||
188 | cpu_boost(false); | ||
189 | cpu_boosted = false; | ||
190 | } | ||
191 | #endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */ | ||
192 | |||
193 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | ||
194 | bitmod32(&CCU_IO, 0<<2, 3<<2); /* XPD is general purpose IO (b3:2 = 00) */ | ||
195 | if (buttonlight_is_on) | ||
196 | buttonlight_hw_on(); | ||
197 | #endif | ||
198 | } | ||
199 | } | ||
150 | 200 | ||
151 | static inline bool card_detect_target(void) | 201 | static inline bool card_detect_target(void) |
152 | { | 202 | { |
@@ -161,18 +211,13 @@ static inline bool card_detect_target(void) | |||
161 | #ifdef HAVE_HOTSWAP | 211 | #ifdef HAVE_HOTSWAP |
162 | static int sd1_oneshot_callback(struct timeout *tmo) | 212 | static int sd1_oneshot_callback(struct timeout *tmo) |
163 | { | 213 | { |
164 | (void)tmo; | ||
165 | |||
166 | /* This is called only if the state was stable for 300ms - check state | 214 | /* This is called only if the state was stable for 300ms - check state |
167 | * and post appropriate event. */ | 215 | * and post appropriate event. */ |
168 | if (card_detect_target()) | 216 | queue_broadcast(card_detect_target() ? SYS_HOTSWAP_INSERTED : |
169 | { | 217 | SYS_HOTSWAP_EXTRACTED, |
170 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 218 | sd_first_drive + SD_SLOT_AS3525); |
171 | } | ||
172 | else | ||
173 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
174 | |||
175 | return 0; | 219 | return 0; |
220 | (void)tmo; | ||
176 | } | 221 | } |
177 | 222 | ||
178 | void sd_gpioa_isr(void) | 223 | void sd_gpioa_isr(void) |
@@ -435,87 +480,6 @@ static int sd_init_card(const int drive) | |||
435 | return 0; | 480 | return 0; |
436 | } | 481 | } |
437 | 482 | ||
438 | static void sd_thread(void) NORETURN_ATTR; | ||
439 | static void sd_thread(void) | ||
440 | { | ||
441 | struct queue_event ev; | ||
442 | bool idle_notified = false; | ||
443 | |||
444 | while (1) | ||
445 | { | ||
446 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
447 | |||
448 | switch ( ev.id ) | ||
449 | { | ||
450 | #ifdef HAVE_HOTSWAP | ||
451 | case SYS_HOTSWAP_INSERTED: | ||
452 | case SYS_HOTSWAP_EXTRACTED:; | ||
453 | int success = 1; | ||
454 | |||
455 | disk_unmount(SD_SLOT_AS3525); /* release "by force" */ | ||
456 | |||
457 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
458 | |||
459 | /* Force card init for new card, re-init for re-inserted one or | ||
460 | * clear if the last attempt to init failed with an error. */ | ||
461 | card_info[SD_SLOT_AS3525].initialized = 0; | ||
462 | |||
463 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
464 | { | ||
465 | success = 0; | ||
466 | sd_enable(true); | ||
467 | init_pl180_controller(SD_SLOT_AS3525); | ||
468 | int rc = sd_init_card(SD_SLOT_AS3525); | ||
469 | sd_enable(false); | ||
470 | if (rc >= 0) | ||
471 | success = 2; | ||
472 | else /* initialisation failed */ | ||
473 | panicf("microSD init failed : %d", rc); | ||
474 | } | ||
475 | |||
476 | mutex_unlock(&sd_mtx); | ||
477 | |||
478 | if (success > 1) | ||
479 | success = disk_mount(SD_SLOT_AS3525); /* 0 if fail */ | ||
480 | |||
481 | /* | ||
482 | * Mount succeeded, or this was an EXTRACTED event, | ||
483 | * in both cases notify the system about the changed filesystems | ||
484 | */ | ||
485 | if (success) | ||
486 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
487 | |||
488 | break; | ||
489 | #endif /* HAVE_HOTSWAP */ | ||
490 | |||
491 | case SYS_TIMEOUT: | ||
492 | if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
493 | { | ||
494 | idle_notified = false; | ||
495 | } | ||
496 | else | ||
497 | { | ||
498 | /* never let a timer wrap confuse us */ | ||
499 | next_yield = current_tick; | ||
500 | |||
501 | if (!idle_notified) | ||
502 | { | ||
503 | call_storage_idle_notifys(false); | ||
504 | idle_notified = true; | ||
505 | } | ||
506 | } | ||
507 | break; | ||
508 | |||
509 | case SYS_USB_CONNECTED: | ||
510 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
511 | /* Wait until the USB cable is extracted again */ | ||
512 | usb_wait_for_disconnect(&sd_queue); | ||
513 | |||
514 | break; | ||
515 | } | ||
516 | } | ||
517 | } | ||
518 | |||
519 | static void init_pl180_controller(const int drive) | 483 | static void init_pl180_controller(const int drive) |
520 | { | 484 | { |
521 | MCI_COMMAND(drive) = MCI_DATA_CTRL(drive) = 0; | 485 | MCI_COMMAND(drive) = MCI_DATA_CTRL(drive) = 0; |
@@ -576,12 +540,8 @@ int sd_init(void) | |||
576 | /* init mutex */ | 540 | /* init mutex */ |
577 | mutex_init(&sd_mtx); | 541 | mutex_init(&sd_mtx); |
578 | 542 | ||
579 | queue_init(&sd_queue, true); | 543 | sd_enabled = true; /* force action on next call */ |
580 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | 544 | enable_controller(false); |
581 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | ||
582 | |||
583 | sd_enabled = true; | ||
584 | sd_enable(false); | ||
585 | 545 | ||
586 | return 0; | 546 | return 0; |
587 | } | 547 | } |
@@ -698,7 +658,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, | |||
698 | unsigned long response; | 658 | unsigned long response; |
699 | bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); | 659 | bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); |
700 | 660 | ||
701 | sd_enable(true); | 661 | enable_controller(true); |
702 | led(true); | 662 | led(true); |
703 | 663 | ||
704 | if (card_info[drive].initialized <= 0) | 664 | if (card_info[drive].initialized <= 0) |
@@ -873,7 +833,7 @@ sd_transfer_error: | |||
873 | sd_transfer_error_nodma: | 833 | sd_transfer_error_nodma: |
874 | 834 | ||
875 | led(false); | 835 | led(false); |
876 | sd_enable(false); | 836 | enable_controller(false); |
877 | 837 | ||
878 | if (ret) /* error */ | 838 | if (ret) /* error */ |
879 | card_info[drive].initialized = 0; | 839 | card_info[drive].initialized = 0; |
@@ -947,55 +907,9 @@ long sd_last_disk_activity(void) | |||
947 | 907 | ||
948 | void sd_enable(bool on) | 908 | void sd_enable(bool on) |
949 | { | 909 | { |
950 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | 910 | mutex_lock(&sd_mtx); |
951 | extern int buttonlight_is_on; | 911 | enable_controller(on); |
952 | #endif | 912 | mutex_unlock(&sd_mtx); |
953 | |||
954 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
955 | static bool cpu_boosted = false; | ||
956 | #endif | ||
957 | |||
958 | if (sd_enabled == on) | ||
959 | return; /* nothing to do */ | ||
960 | |||
961 | sd_enabled = on; | ||
962 | |||
963 | if(on) | ||
964 | { | ||
965 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | ||
966 | /* buttonlight AMSes need a bit of special handling for the buttonlight | ||
967 | * here due to the dual mapping of GPIOD and XPD */ | ||
968 | bitmod32(&CCU_IO, 1<<2, 3<<2); /* XPD is SD-MCI interface (b3:2 = 01) */ | ||
969 | if (buttonlight_is_on) | ||
970 | GPIOD_DIR &= ~(1<<7); | ||
971 | else | ||
972 | buttonlight_hw_off(); | ||
973 | #endif | ||
974 | |||
975 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
976 | if(card_detect_target()) /* If SD card present Boost cpu for voltage */ | ||
977 | { | ||
978 | cpu_boosted = true; | ||
979 | cpu_boost(true); | ||
980 | } | ||
981 | #endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */ | ||
982 | } | ||
983 | else | ||
984 | { | ||
985 | #if defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) | ||
986 | if(cpu_boosted) | ||
987 | { | ||
988 | cpu_boost(false); | ||
989 | cpu_boosted = false; | ||
990 | } | ||
991 | #endif /* defined(HAVE_HOTSWAP) && defined (HAVE_ADJUSTABLE_CPU_VOLTAGE) */ | ||
992 | |||
993 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | ||
994 | bitmod32(&CCU_IO, 0<<2, 3<<2); /* XPD is general purpose IO (b3:2 = 00) */ | ||
995 | if (buttonlight_is_on) | ||
996 | buttonlight_hw_on(); | ||
997 | #endif | ||
998 | } | ||
999 | } | 913 | } |
1000 | 914 | ||
1001 | tCardInfo *card_get_info_target(int card_no) | 915 | tCardInfo *card_get_info_target(int card_no) |
@@ -1006,9 +920,45 @@ tCardInfo *card_get_info_target(int card_no) | |||
1006 | #ifdef CONFIG_STORAGE_MULTI | 920 | #ifdef CONFIG_STORAGE_MULTI |
1007 | int sd_num_drives(int first_drive) | 921 | int sd_num_drives(int first_drive) |
1008 | { | 922 | { |
1009 | /* We don't care which logical drive number(s) we have been assigned */ | 923 | sd_first_drive = first_drive; |
1010 | (void)first_drive; | ||
1011 | |||
1012 | return NUM_DRIVES; | 924 | return NUM_DRIVES; |
1013 | } | 925 | } |
1014 | #endif /* CONFIG_STORAGE_MULTI */ | 926 | #endif /* CONFIG_STORAGE_MULTI */ |
927 | |||
928 | int sd_event(long id, intptr_t data) | ||
929 | { | ||
930 | int rc = 0; | ||
931 | |||
932 | switch (id) | ||
933 | { | ||
934 | #ifdef HAVE_HOTSWAP | ||
935 | case SYS_HOTSWAP_INSERTED: | ||
936 | case SYS_HOTSWAP_EXTRACTED: | ||
937 | mutex_lock(&sd_mtx); /* lock-out card activity */ | ||
938 | |||
939 | /* Force card init for new card, re-init for re-inserted one or | ||
940 | * clear if the last attempt to init failed with an error. */ | ||
941 | card_info[data].initialized = 0; | ||
942 | |||
943 | if (id == SYS_HOTSWAP_INSERTED) | ||
944 | { | ||
945 | enable_controller(true); | ||
946 | init_pl180_controller(data); | ||
947 | rc = sd_init_card(data); | ||
948 | enable_controller(false); | ||
949 | } | ||
950 | |||
951 | mutex_unlock(&sd_mtx); | ||
952 | break; | ||
953 | #endif /* HAVE_HOTSWAP */ | ||
954 | case Q_STORAGE_TICK: | ||
955 | /* never let a timer wrap confuse us */ | ||
956 | next_yield = current_tick; | ||
957 | default: | ||
958 | rc = storage_event_default_handler(id, data, last_disk_activity, | ||
959 | STORAGE_SD); | ||
960 | break; | ||
961 | } | ||
962 | |||
963 | return rc; | ||
964 | } | ||