summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233/sd-imx233.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx233/sd-imx233.c')
-rw-r--r--firmware/target/arm/imx233/sd-imx233.c134
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
39static tCardInfo card_info; 43static tCardInfo card_info;
44static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
40static struct mutex sd_mutex; 45static struct mutex sd_mutex;
46static const char sd_thread_name[] = "sd";
47static struct event_queue sd_queue;
48static int sd_first_drive;
49static bool sd_initialized;
50static int last_disk_activity;
41 51
42static void sd_detect_callback(int ssp) 52static 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
56int sd_init(void) 66void 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
81static 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
109static void sd_thread(void) NORETURN_ATTR;
110static 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
178int 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
102int sd_num_drives(int first_drive) 222int 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