diff options
Diffstat (limited to 'firmware/target/arm/imx233/sd-imx233.c')
-rw-r--r-- | firmware/target/arm/imx233/sd-imx233.c | 134 |
1 files changed, 127 insertions, 7 deletions
diff --git a/firmware/target/arm/imx233/sd-imx233.c b/firmware/target/arm/imx233/sd-imx233.c index 5e9f2cf030..b9114ae130 100644 --- a/firmware/target/arm/imx233/sd-imx233.c +++ b/firmware/target/arm/imx233/sd-imx233.c | |||
@@ -25,6 +25,10 @@ | |||
25 | #include "ssp-imx233.h" | 25 | #include "ssp-imx233.h" |
26 | #include "pinctrl-imx233.h" | 26 | #include "pinctrl-imx233.h" |
27 | #include "button-target.h" | 27 | #include "button-target.h" |
28 | #include "fat.h" | ||
29 | #include "disk.h" | ||
30 | #include "usb.h" | ||
31 | #include "debug.h" | ||
28 | 32 | ||
29 | /** | 33 | /** |
30 | * This code assumes a single SD card slot | 34 | * This code assumes a single SD card slot |
@@ -37,7 +41,13 @@ | |||
37 | #endif | 41 | #endif |
38 | 42 | ||
39 | static tCardInfo card_info; | 43 | static tCardInfo card_info; |
44 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | ||
40 | static struct mutex sd_mutex; | 45 | static struct mutex sd_mutex; |
46 | static const char sd_thread_name[] = "sd"; | ||
47 | static struct event_queue sd_queue; | ||
48 | static int sd_first_drive; | ||
49 | static bool sd_initialized; | ||
50 | static int last_disk_activity; | ||
41 | 51 | ||
42 | static void sd_detect_callback(int ssp) | 52 | static void sd_detect_callback(int ssp) |
43 | { | 53 | { |
@@ -53,22 +63,132 @@ static void sd_detect_callback(int ssp) | |||
53 | imx233_ssp_sdmmc_setup_detect(SD_SSP, true, sd_detect_callback); | 63 | imx233_ssp_sdmmc_setup_detect(SD_SSP, true, sd_detect_callback); |
54 | } | 64 | } |
55 | 65 | ||
56 | int sd_init(void) | 66 | void sd_enable(bool on) |
57 | { | 67 | { |
58 | mutex_init(&sd_mutex); | 68 | static bool sd_enable = false; |
69 | if(sd_enable == on) | ||
70 | return; | ||
59 | 71 | ||
72 | mutex_lock(&sd_mutex); | ||
73 | if(on) | ||
74 | imx233_ssp_start(SD_SSP); | ||
75 | else | ||
76 | imx233_ssp_stop(SD_SSP); | ||
77 | mutex_unlock(&sd_mutex); | ||
78 | sd_enable = on; | ||
79 | } | ||
80 | |||
81 | static int sd_init_card(void) | ||
82 | { | ||
83 | printf("sd_init_card"); | ||
60 | imx233_ssp_start(SD_SSP); | 84 | imx233_ssp_start(SD_SSP); |
61 | imx233_ssp_softreset(SD_SSP); | 85 | imx233_ssp_softreset(SD_SSP); |
62 | imx233_ssp_set_mode(SD_SSP, HW_SSP_CTRL1__SSP_MODE__SD_MMC); | 86 | imx233_ssp_set_mode(SD_SSP, HW_SSP_CTRL1__SSP_MODE__SD_MMC); |
63 | #ifdef SANSA_FUZEPLUS | ||
64 | imx233_ssp_setup_ssp1_sd_mmc_pins(true, 4, PINCTRL_DRIVE_8mA, false); | ||
65 | #endif | ||
66 | imx233_ssp_sdmmc_setup_detect(SD_SSP, true, sd_detect_callback); | ||
67 | /* SSPCLK @ 96MHz | 87 | /* SSPCLK @ 96MHz |
68 | * gives bitrate of 96000 / 240 / 1 = 400kHz */ | 88 | * gives bitrate of 96000 / 240 / 1 = 400kHz */ |
69 | imx233_ssp_set_timings(SD_SSP, 240, 0, 0xffff); | 89 | imx233_ssp_set_timings(SD_SSP, 240, 0, 0xffff); |
70 | imx233_ssp_set_bus_width(SD_SSP, 1); | 90 | imx233_ssp_set_bus_width(SD_SSP, 1); |
71 | imx233_ssp_set_block_size(SD_SSP, 9); | 91 | imx233_ssp_set_block_size(SD_SSP, 9); |
92 | |||
93 | card_info.rca = 0; | ||
94 | bool is_v2 = false; | ||
95 | uint32_t resp; | ||
96 | /* go to idle state */ | ||
97 | int ret = imx233_ssp_sd_mmc_transfer(SD_SSP, SD_GO_IDLE_STATE, 0, SSP_NO_RESP, NULL, 0, false, false, NULL); | ||
98 | if(ret != 0) | ||
99 | return -1; | ||
100 | /* CMD8 Check for v2 sd card. Must be sent before using ACMD41 | ||
101 | Non v2 cards will not respond to this command*/ | ||
102 | ret = imx233_ssp_sd_mmc_transfer(SD_SSP, SD_SEND_IF_COND, 0x1AA, SSP_SHORT_RESP, NULL, 0, false, false, &resp); | ||
103 | if(ret == 0 && (resp & 0xFFF) == 0x1AA) | ||
104 | is_v2 = true; | ||
105 | |||
106 | return -10; | ||
107 | } | ||
108 | |||
109 | static void sd_thread(void) NORETURN_ATTR; | ||
110 | static void sd_thread(void) | ||
111 | { | ||
112 | struct queue_event ev; | ||
113 | |||
114 | while (1) | ||
115 | { | ||
116 | queue_wait_w_tmo(&sd_queue, &ev, HZ); | ||
117 | |||
118 | switch(ev.id) | ||
119 | { | ||
120 | case SYS_HOTSWAP_INSERTED: | ||
121 | case SYS_HOTSWAP_EXTRACTED: | ||
122 | { | ||
123 | int microsd_init = 1; | ||
124 | fat_lock(); /* lock-out FAT activity first - | ||
125 | prevent deadlocking via disk_mount that | ||
126 | would cause a reverse-order attempt with | ||
127 | another thread */ | ||
128 | mutex_lock(&sd_mutex); /* lock-out card activity - direct calls | ||
129 | into driver that bypass the fat cache */ | ||
130 | |||
131 | /* We now have exclusive control of fat cache and sd */ | ||
132 | |||
133 | disk_unmount(sd_first_drive); /* release "by force", ensure file | ||
134 | descriptors aren't leaked and any busy | ||
135 | ones are invalid if mounting */ | ||
136 | /* Force card init for new card, re-init for re-inserted one or | ||
137 | * clear if the last attempt to init failed with an error. */ | ||
138 | card_info.initialized = 0; | ||
139 | |||
140 | if(ev.id == SYS_HOTSWAP_INSERTED) | ||
141 | { | ||
142 | int ret = sd_init_card(); | ||
143 | if(ret == 0) | ||
144 | { | ||
145 | ret = disk_mount(sd_first_drive); /* 0 if fail */ | ||
146 | if(ret < 0) | ||
147 | DEBUGF("disk_mount failed: %d", ret); | ||
148 | } | ||
149 | else | ||
150 | DEBUGF("sd_init_card failed: %d", ret); | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * Mount succeeded, or this was an EXTRACTED event, | ||
155 | * in both cases notify the system about the changed filesystems | ||
156 | */ | ||
157 | if(card_info.initialized) | ||
158 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
159 | |||
160 | /* Access is now safe */ | ||
161 | mutex_unlock(&sd_mutex); | ||
162 | fat_unlock(); | ||
163 | } | ||
164 | break; | ||
165 | case SYS_TIMEOUT: | ||
166 | if(!TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) | ||
167 | sd_enable(false); | ||
168 | break; | ||
169 | case SYS_USB_CONNECTED: | ||
170 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
171 | /* Wait until the USB cable is extracted again */ | ||
172 | usb_wait_for_disconnect(&sd_queue); | ||
173 | break; | ||
174 | } | ||
175 | } | ||
176 | } | ||
177 | |||
178 | int sd_init(void) | ||
179 | { | ||
180 | mutex_init(&sd_mutex); | ||
181 | queue_init(&sd_queue, true); | ||
182 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0, | ||
183 | sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | ||
184 | |||
185 | #ifdef SANSA_FUZEPLUS | ||
186 | imx233_ssp_setup_ssp1_sd_mmc_pins(true, 4, PINCTRL_DRIVE_8mA, false); | ||
187 | #endif | ||
188 | imx233_ssp_sdmmc_setup_detect(SD_SSP, true, sd_detect_callback); | ||
189 | |||
190 | if(imx233_ssp_sdmmc_detect(SD_SSP)) | ||
191 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | ||
72 | 192 | ||
73 | return 0; | 193 | return 0; |
74 | } | 194 | } |
@@ -101,7 +221,7 @@ tCardInfo *card_get_info_target(int card_no) | |||
101 | 221 | ||
102 | int sd_num_drives(int first_drive) | 222 | int sd_num_drives(int first_drive) |
103 | { | 223 | { |
104 | (void) first_drive; | 224 | sd_first_drive = first_drive; |
105 | return 1; | 225 | return 1; |
106 | } | 226 | } |
107 | 227 | ||