summaryrefslogtreecommitdiff
path: root/firmware/target/arm/as3525/sd-as3525.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2017-03-15 01:51:54 -0400
committerMichael Sevakis <jethead71@rockbox.org>2017-10-26 14:35:41 -0400
commit1654efc31339972d0e6bd41a499fcffc0a45822e (patch)
tree5fb7f59ab918a3694608bb1138c2c52fb47698c3 /firmware/target/arm/as3525/sd-as3525.c
parent7807934a271e9eb7b045cdcd89ba70fb59a91d69 (diff)
downloadrockbox-1654efc31339972d0e6bd41a499fcffc0a45822e.tar.gz
rockbox-1654efc31339972d0e6bd41a499fcffc0a45822e.zip
Unify storage threads into one
* Editing a bunch of drivers' thread routines in order to implement a new feature is tedious. * No matter the number of storage drivers, they share one thread. No extra threads needed for CONFIG_STORAGE_MULTI. * Each has an event callback called by the storage thread. * A default callback is provided to fake sleeping in order to trigger idle callbacks. It could also do other default processing. Changes to it will be part of driver code without editing each one. * Drivers may sleep and wake as they please as long as they give a low pulse on their storage bit to ask to go into sleep mode. Idle callback is called on its behalf and driver immediately put into sleep mode. * Drivers may indicate they are to continue receiving events in USB mode, otherwise they receve nothing until disconnect (they do receive SYS_USB_DISCONNECTED no matter what). * Rework a few things to keep the callback implementation sane and maintainable. ata.c was dreadful with all those bools; make it a state machine and easier to follow. Remove last_user_activity; it has no purpose that isn't served by keeping the disk active through last_disk_activity instead. * Even-out stack sizes partly because of a lack of a decent place to define them by driver or SoC or whatever; it doesn't seem too critical to do that anyway. Many are simply too large while at least one isn't really adequate. They may be individually overridden if necessary (figure out where). The thread uses the greatest size demanded. Newer file code is much more frugal with stack space. I barely see use crack 50% after idle callbacks (usually mid-40s). Card insert/eject doesn't demand much. * No forcing of idle callbacks. If it isn't necessary for one or more non-disk storage types, it really isn't any more necessary for disk storage. Besides, it makes the whole thing easier to implement. Change-Id: Id30c284d82a8af66e47f2cfe104c52cbd8aa7215
Diffstat (limited to 'firmware/target/arm/as3525/sd-as3525.c')
-rw-r--r--firmware/target/arm/as3525/sd-as3525.c276
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
117static int sd_first_drive = 0;
118#else
119#define sd_first_drive 0
120#endif
121
122/* for compatibility */ 122/* for compatibility */
123static long last_disk_activity = -1; 123static long last_disk_activity = -1;
124 124
125#define MIN_YIELD_PERIOD 5 /* ticks */ 125#define MIN_YIELD_PERIOD 5 /* ticks */
126static long next_yield = 0; 126static long next_yield = 0;
127 127
128static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; 128static struct mutex sd_mtx;
129static const char sd_thread_name[] = "ata/sd";
130static struct mutex sd_mtx;
131static struct event_queue sd_queue;
132bool sd_enabled = false; 129bool 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
148static inline void mci_delay(void) { udelay(1000) ; } 145static inline void mci_delay(void) { udelay(1000) ; }
149 146
147static 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
151static inline bool card_detect_target(void) 201static 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
162static int sd1_oneshot_callback(struct timeout *tmo) 212static 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
178void sd_gpioa_isr(void) 223void 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
438static void sd_thread(void) NORETURN_ATTR;
439static 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
519static void init_pl180_controller(const int drive) 483static 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:
873sd_transfer_error_nodma: 833sd_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
948void sd_enable(bool on) 908void 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
1001tCardInfo *card_get_info_target(int card_no) 915tCardInfo *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
1007int sd_num_drives(int first_drive) 921int 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
928int 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}