summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootloader/gigabeat-s.c329
-rw-r--r--firmware/backlight.c49
-rw-r--r--firmware/drivers/ata.c28
-rw-r--r--firmware/drivers/button.c7
-rw-r--r--firmware/export/ata.h1
-rw-r--r--firmware/export/backlight.h1
-rw-r--r--firmware/export/button.h1
-rw-r--r--firmware/export/config-gigabeat-s.h22
-rw-r--r--firmware/export/usb.h5
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/ata-target.h4
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c4
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/backlight-target.h8
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/button-imx31.c38
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/button-target.h7
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c48
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/system-imx31.c1
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/usb-target.h4
-rw-r--r--firmware/usb.c19
18 files changed, 423 insertions, 153 deletions
diff --git a/bootloader/gigabeat-s.c b/bootloader/gigabeat-s.c
index 30c2955c19..dfe13e4540 100644
--- a/bootloader/gigabeat-s.c
+++ b/bootloader/gigabeat-s.c
@@ -21,11 +21,15 @@
21#include <sprintf.h> 21#include <sprintf.h>
22#include "kernel.h" 22#include "kernel.h"
23#include "string.h" 23#include "string.h"
24#include "adc.h"
25#include "powermgmt.h"
24#include "ata.h" 26#include "ata.h"
25#include "dir.h" 27#include "dir.h"
26#include "disk.h" 28#include "disk.h"
27#include "common.h" 29#include "common.h"
30#include "backlight.h"
28#include "usb.h" 31#include "usb.h"
32#include "button.h"
29#include "font.h" 33#include "font.h"
30#include "lcd.h" 34#include "lcd.h"
31#include "usb-target.h" 35#include "usb-target.h"
@@ -39,11 +43,15 @@ static const char basedir[] = "/Content/0b00/00/";
39/* Can use memory after vector table up to 0x01f00000 */ 43/* Can use memory after vector table up to 0x01f00000 */
40static char * const tarbuf = (char *)0x00000040; 44static char * const tarbuf = (char *)0x00000040;
41static const size_t tarbuf_size = 0x01f00000 - 0x00000040; 45static const size_t tarbuf_size = 0x01f00000 - 0x00000040;
42/* Queue to get notifications when in USB mode */ 46/* Firmware data */
43static struct event_queue usb_wait_queue; 47static void * const load_buf = 0x00000000;
48static const size_t load_buf_size = 0x20000000 - 0x100000;
49static const void * const start_addr = 0x00000000;
44 50
45static void show_splash(int timeout, const char *msg) 51static void show_splash(int timeout, const char *msg)
46{ 52{
53 backlight_on();
54 reset_screen();
47 lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2, 55 lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2,
48 (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg); 56 (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg);
49 lcd_update(); 57 lcd_update();
@@ -51,6 +59,95 @@ static void show_splash(int timeout, const char *msg)
51 sleep(timeout); 59 sleep(timeout);
52} 60}
53 61
62static bool pause_if_button_pressed(bool pre_usb)
63{
64 while (1)
65 {
66 int button = button_read_device();
67
68 if (pre_usb && !usb_plugged())
69 return false;
70
71 /* Exit if no button or only the menu (settings reset) button */
72 switch (button)
73 {
74 case BUTTON_MENU:
75 case BUTTON_NONE:
76 return true;
77 }
78
79 sleep(HZ/5);
80
81 /* If the disk powers off, the firmware will lock at startup */
82 ata_spin();
83 }
84}
85
86/* TODO: Handle charging while connected */
87static void handle_usb(void)
88{
89 int button;
90
91 /* Check if plugged and pause to look at messages. If the cable was pulled
92 * while waiting, proceed as if it never was plugged. */
93 if (!usb_plugged() || !pause_if_button_pressed(true))
94 {
95 /* Bang on the controller */
96 usb_init_device();
97 return;
98 }
99
100 /** Enter USB mode **/
101
102 /* We need full button and backlight handling now */
103 backlight_init();
104 button_init();
105
106 /* Start the USB driver */
107 usb_init();
108 usb_start_monitoring();
109
110 /* Wait for threads to connect or cable is pulled */
111 show_splash(HZ/2, "Waiting for USB");
112
113 while (1)
114 {
115 button = button_get_w_tmo(HZ/2);
116
117 if (button == SYS_USB_CONNECTED)
118 break; /* Hit */
119
120 if (!usb_plugged())
121 break; /* Cable pulled */
122 }
123
124 if (button == SYS_USB_CONNECTED)
125 {
126 /* Got the message - wait for disconnect */
127 show_splash(0, "Bootloader USB mode");
128
129 usb_acknowledge(SYS_USB_CONNECTED_ACK);
130
131 while (1)
132 {
133 button = button_get(true);
134 if (button == SYS_USB_DISCONNECTED)
135 {
136 usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
137 break;
138 }
139 }
140 }
141
142 /* Put drivers initialized for USB connection into a known state */
143 backlight_on();
144 usb_close();
145 button_close();
146 backlight_close();
147
148 reset_screen();
149}
150
54static void untar(int tar_fd) 151static void untar(int tar_fd)
55{ 152{
56 char header[TAR_HEADER_SIZE]; 153 char header[TAR_HEADER_SIZE];
@@ -60,13 +157,15 @@ static void untar(int tar_fd)
60 int ret; 157 int ret;
61 size_t size = filesize(tar_fd); 158 size_t size = filesize(tar_fd);
62 159
63 if (size > tarbuf_size) { 160 if (size > tarbuf_size)
161 {
64 printf("tar file too large"); /* Paranoid but proper */ 162 printf("tar file too large"); /* Paranoid but proper */
65 return; 163 return;
66 } 164 }
67 165
68 ret = read(tar_fd, tarbuf, filesize(tar_fd)); 166 ret = read(tar_fd, tarbuf, filesize(tar_fd));
69 if (ret < 0) { 167 if (ret < 0)
168 {
70 printf("couldn't read tar file (%d)", ret); 169 printf("couldn't read tar file (%d)", ret);
71 return; 170 return;
72 } 171 }
@@ -131,153 +230,91 @@ static void untar(int tar_fd)
131 } 230 }
132} 231}
133 232
134void main(void) 233/* Look for a tar file or rockbox binary in the MTP directory */
234static void handle_untar(void)
135{ 235{
136 char buf[MAX_PATH]; 236 char buf[MAX_PATH];
137 char tarstring[6]; 237 char tarstring[6];
138 char model[5]; 238 char model[5];
139 239 struct dirent_uncached* entry;
140 /* Flush and invalidate all caches (because vectors were written) */ 240 DIR_UNCACHED* dir;
141 invalidate_icache(); 241 int fd;
142
143 lcd_clear_display();
144 printf("Gigabeat S Rockbox Bootloader v.00000013");
145 system_init();
146 kernel_init();
147 printf("kernel init done");
148 int rc; 242 int rc;
149 243
150 enable_interrupt(IRQ_FIQ_STATUS); 244 dir = opendir_uncached(basedir);
151 245
152 rc = ata_init(); 246 while ((entry = readdir_uncached(dir)))
153 if(rc)
154 { 247 {
155 reset_screen(); 248 if (*entry->d_name == '.')
156 error(EATA, rc); 249 continue;
157 }
158 printf("ata init done");
159 250
160 disk_init(); 251 snprintf(buf, sizeof(buf), "%s%s", basedir, entry->d_name);
161 printf("disk init done"); 252 fd = open(buf, O_RDONLY);
162 253
163 rc = disk_mount_all(); 254 if (fd < 0)
164 if (rc<=0) 255 continue;
165 {
166 error(EDISK,rc);
167 }
168 256
169 /* Look for a tar file */ 257 /* Check whether the file is a rockbox binary. */
170 struct dirent_uncached* entry; 258 lseek(fd, 4, SEEK_SET);
171 DIR_UNCACHED* dir; 259 rc = read(fd, model, 4);
172 int fd; 260 if (rc == 4)
173 dir = opendir_uncached(basedir);
174 while ((entry = readdir_uncached(dir)))
175 {
176 if (*entry->d_name != '.')
177 { 261 {
178 snprintf(buf, sizeof(buf), "%s%s", basedir, entry->d_name); 262 model[4] = 0;
179 fd = open(buf, O_RDONLY); 263 if (strcmp(model, "gigs") == 0)
180 if (fd >= 0)
181 { 264 {
182 /* Check whether the file is a rockbox binary. */ 265 printf("Found rockbox binary. Moving...");
183 lseek(fd, 4, SEEK_SET);
184 rc = read(fd, model, 4);
185 if (rc == 4)
186 {
187 model[4] = 0;
188 if (strcmp(model, "gigs") == 0)
189 {
190 printf("Found rockbox binary. Moving...");
191 close(fd);
192 remove("/.rockbox/rockbox.gigabeat");
193 int ret = rename(buf, "/.rockbox/rockbox.gigabeat");
194 printf("returned %d", ret);
195 sleep(HZ);
196 break;
197 }
198 }
199
200 /* Check whether the file is a tar file. */
201 lseek(fd, 257, SEEK_SET);
202 rc = read(fd, tarstring, 5);
203 if (rc == 5)
204 {
205 tarstring[5] = 0;
206 if (strcmp(tarstring, "ustar") == 0)
207 {
208 printf("Found tar file. Unarchiving...");
209 lseek(fd, 0, SEEK_SET);
210 untar(fd);
211 close(fd);
212 printf("Removing tar file");
213 remove(buf);
214 break;
215 }
216 }
217 close(fd); 266 close(fd);
267 remove("/.rockbox/rockbox.gigabeat");
268 int ret = rename(buf, "/.rockbox/rockbox.gigabeat");
269 printf("returned %d", ret);
270 sleep(HZ);
271 break;
218 } 272 }
219 } 273 }
220 }
221
222 if (usb_plugged())
223 {
224 /* Enter USB mode */
225 struct queue_event ev;
226 queue_init(&usb_wait_queue, true);
227
228 /* Start the USB driver */
229 usb_init();
230 usb_start_monitoring();
231
232 /* Wait for threads to connect or cable is pulled */
233 reset_screen();
234 show_splash(0, "Waiting for USB");
235
236 while (1)
237 {
238 queue_wait_w_tmo(&usb_wait_queue, &ev, HZ/2);
239
240 if (ev.id == SYS_USB_CONNECTED)
241 break; /* Hit */
242
243 if (!usb_plugged())
244 break; /* Cable pulled */
245 }
246 274
247 if (ev.id == SYS_USB_CONNECTED) 275 /* Check whether the file is a tar file. */
276 lseek(fd, 257, SEEK_SET);
277 rc = read(fd, tarstring, 5);
278 if (rc == 5)
248 { 279 {
249 /* Got the message - wait for disconnect */ 280 tarstring[5] = 0;
250 reset_screen(); 281 if (strcmp(tarstring, "ustar") == 0)
251 show_splash(0, "Bootloader USB mode"); 282 {
252 283 printf("Found tar file. Unarchiving...");
253 usb_acknowledge(SYS_USB_CONNECTED_ACK); 284 lseek(fd, 0, SEEK_SET);
254 usb_wait_for_disconnect(&usb_wait_queue); 285 untar(fd);
286 close(fd);
287 printf("Removing tar file");
288 remove(buf);
289 break;
290 }
255 } 291 }
256 292
257 /* No more monitoring */ 293 close(fd);
258 usb_stop_monitoring();
259
260 reset_screen();
261 }
262 else
263 {
264 /* Bang on the controller */
265 usb_init_device();
266 } 294 }
295}
267 296
268 unsigned char *loadbuffer = (unsigned char *)0x0; 297/* Try to load the firmware and run it */
269 int buffer_size = 31*1024*1024; 298static void __attribute__((noreturn)) handle_firmware_load(void)
299{
300 int rc = load_firmware(load_buf, "/.rockbox/rockbox.gigabeat",
301 load_buf_size);
270 302
271 rc = load_firmware(loadbuffer, "/.rockbox/rockbox.gigabeat", buffer_size);
272 if(rc < 0) 303 if(rc < 0)
273 error(EBOOTFILE, rc); 304 error(EBOOTFILE, rc);
274 305
306 /* Pause to look at messages */
307 pause_if_button_pressed(false);
308
309 /* Put drivers into a known state */
310 button_close_device();
311 ata_close();
275 system_prepare_fw_start(); 312 system_prepare_fw_start();
276 313
277 if (rc == EOK) 314 if (rc == EOK)
278 { 315 {
279 invalidate_icache(); 316 invalidate_icache();
280 asm volatile ("bx %0": : "r"(loadbuffer)); 317 asm volatile ("bx %0": : "r"(start_addr));
281 } 318 }
282 319
283 /* Halt */ 320 /* Halt */
@@ -285,3 +322,55 @@ void main(void)
285 core_idle(); 322 core_idle();
286} 323}
287 324
325static void check_battery(void)
326{
327 int batt = battery_adc_voltage();
328 printf("Battery: %d.%03d V", batt / 1000, batt % 1000);
329 /* TODO: warn on low battery or shut down */
330}
331
332void main(void)
333{
334 int rc;
335
336 /* Flush and invalidate all caches (because vectors were written) */
337 invalidate_icache();
338
339 lcd_clear_display();
340 printf("Gigabeat S Rockbox Bootloader");
341 printf("Version %s", version);
342 system_init();
343 kernel_init();
344
345 enable_interrupt(IRQ_FIQ_STATUS);
346
347 /* Initialize KPP so we can poll the button states */
348 button_init_device();
349
350 adc_init();
351
352 check_battery();
353
354 rc = ata_init();
355 if(rc)
356 {
357 reset_screen();
358 error(EATA, rc);
359 }
360
361 disk_init();
362
363 rc = disk_mount_all();
364 if (rc<=0)
365 {
366 error(EDISK,rc);
367 }
368
369 printf("Init complete");
370
371 /* Do USB first since a tar or binary could be added to the MTP directory
372 * at the time and we can untar or move after unplugging. */
373 handle_usb();
374 handle_untar();
375 handle_firmware_load(); /* No return */
376}
diff --git a/firmware/backlight.c b/firmware/backlight.c
index 4a00f86f39..74cdee1205 100644
--- a/firmware/backlight.c
+++ b/firmware/backlight.c
@@ -39,6 +39,11 @@
39#include "backlight-target.h" 39#include "backlight-target.h"
40#endif 40#endif
41 41
42#if !defined(BOOTLOADER)
43/* The whole driver should be built */
44#define BACKLIGHT_FULL_INIT
45#endif
46
42#ifdef SIMULATOR 47#ifdef SIMULATOR
43/* TODO: find a better way to do it but we need a kernel thread somewhere to 48/* TODO: find a better way to do it but we need a kernel thread somewhere to
44 handle this */ 49 handle this */
@@ -85,7 +90,7 @@ static inline void _remote_backlight_off(void)
85 90
86#endif /* SIMULATOR */ 91#endif /* SIMULATOR */
87 92
88#if defined(HAVE_BACKLIGHT) && !defined(BOOTLOADER) 93#if defined(HAVE_BACKLIGHT) && defined(BACKLIGHT_FULL_INIT)
89 94
90enum { 95enum {
91 BACKLIGHT_ON, 96 BACKLIGHT_ON,
@@ -104,12 +109,18 @@ enum {
104 BUTTON_LIGHT_ON, 109 BUTTON_LIGHT_ON,
105 BUTTON_LIGHT_OFF, 110 BUTTON_LIGHT_OFF,
106#endif 111#endif
112#ifdef BACKLIGHT_DRIVER_CLOSE
113 BACKLIGHT_QUIT,
114#endif
107}; 115};
108 116
109static void backlight_thread(void); 117static void backlight_thread(void);
110static long backlight_stack[DEFAULT_STACK_SIZE/sizeof(long)]; 118static long backlight_stack[DEFAULT_STACK_SIZE/sizeof(long)];
111static const char backlight_thread_name[] = "backlight"; 119static const char backlight_thread_name[] = "backlight";
112static struct event_queue backlight_queue; 120static struct event_queue backlight_queue;
121#ifdef BACKLIGHT_DRIVER_CLOSE
122static struct thread_entry *backlight_thread_p = NULL;
123#endif
113 124
114static int backlight_timer SHAREDBSS_ATTR; 125static int backlight_timer SHAREDBSS_ATTR;
115static int backlight_timeout SHAREDBSS_ATTR; 126static int backlight_timeout SHAREDBSS_ATTR;
@@ -158,7 +169,7 @@ void buttonlight_set_timeout(int value)
158 buttonlight_update_state(); 169 buttonlight_update_state();
159} 170}
160 171
161#endif 172#endif /* HAVE_BUTTON_LIGHT */
162 173
163#ifdef HAVE_REMOTE_LCD 174#ifdef HAVE_REMOTE_LCD
164static int remote_backlight_timer; 175static int remote_backlight_timer;
@@ -170,7 +181,7 @@ static int remote_backlight_timeout_plugged = 5*HZ;
170#ifdef HAS_REMOTE_BUTTON_HOLD 181#ifdef HAS_REMOTE_BUTTON_HOLD
171static int remote_backlight_on_button_hold = 0; 182static int remote_backlight_on_button_hold = 0;
172#endif 183#endif
173#endif 184#endif /* HAVE_REMOTE_LCD */
174 185
175#ifdef HAVE_LCD_SLEEP 186#ifdef HAVE_LCD_SLEEP
176const signed char lcd_sleep_timeout_value[10] = 187const signed char lcd_sleep_timeout_value[10] =
@@ -494,6 +505,12 @@ void backlight_thread(void)
494 case SYS_USB_DISCONNECTED: 505 case SYS_USB_DISCONNECTED:
495 usb_acknowledge(SYS_USB_DISCONNECTED_ACK); 506 usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
496 break; 507 break;
508
509#ifdef BACKLIGHT_DRIVER_CLOSE
510 /* Get out of here */
511 case BACKLIGHT_QUIT:
512 return;
513#endif
497 } 514 }
498 if (locked) 515 if (locked)
499 continue; 516 continue;
@@ -613,7 +630,9 @@ void backlight_init(void)
613 /* Leave all lights as set by the bootloader here. The settings load will 630 /* Leave all lights as set by the bootloader here. The settings load will
614 * call the appropriate backlight_set_*() functions, only changing light 631 * call the appropriate backlight_set_*() functions, only changing light
615 * status if necessary. */ 632 * status if necessary. */
616 633#ifdef BACKLIGHT_DRIVER_CLOSE
634 backlight_thread_p =
635#endif
617 create_thread(backlight_thread, backlight_stack, 636 create_thread(backlight_thread, backlight_stack,
618 sizeof(backlight_stack), 0, backlight_thread_name 637 sizeof(backlight_stack), 0, backlight_thread_name
619 IF_PRIO(, PRIORITY_USER_INTERFACE) 638 IF_PRIO(, PRIORITY_USER_INTERFACE)
@@ -621,6 +640,22 @@ void backlight_init(void)
621 tick_add_task(backlight_tick); 640 tick_add_task(backlight_tick);
622} 641}
623 642
643#ifdef BACKLIGHT_DRIVER_CLOSE
644void backlight_close(void)
645{
646 struct thread_entry *thread = backlight_thread_p;
647
648 /* Wait for thread to exit */
649 if (thread == NULL)
650 return;
651
652 backlight_thread_p = NULL;
653
654 queue_post(&backlight_queue, BACKLIGHT_QUIT, 0);
655 thread_wait(thread);
656}
657#endif /* BACKLIGHT_DRIVER_CLOSE */
658
624void backlight_on(void) 659void backlight_on(void)
625{ 660{
626 queue_remove_from_head(&backlight_queue, BACKLIGHT_ON); 661 queue_remove_from_head(&backlight_queue, BACKLIGHT_ON);
@@ -788,10 +823,10 @@ void buttonlight_set_brightness(int val)
788} 823}
789#endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */ 824#endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */
790 825
791#else /* !defined(HAVE_BACKLIGHT) || defined(BOOTLOADER) 826#else /* !defined(HAVE_BACKLIGHT) || !defined(BACKLIGHT_FULL_INIT)
792 -- no backlight, empty dummy functions */ 827 -- no backlight, empty dummy functions */
793 828
794#if defined(BOOTLOADER) && defined(HAVE_BACKLIGHT) 829#if defined(HAVE_BACKLIGHT) && !defined(BACKLIGHT_FULL_INIT)
795void backlight_init(void) 830void backlight_init(void)
796{ 831{
797 (void)_backlight_init(); 832 (void)_backlight_init();
@@ -826,4 +861,4 @@ void backlight_set_brightness(int val) { (void)val; }
826#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS 861#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
827void buttonlight_set_brightness(int val) { (void)val; } 862void buttonlight_set_brightness(int val) { (void)val; }
828#endif 863#endif
829#endif /* defined(HAVE_BACKLIGHT) && !defined(BOOTLOADER) */ 864#endif /* defined(HAVE_BACKLIGHT) && defined(BACKLIGHT_FULL_INIT) */
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 2dca17512e..87dacc3ed0 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -59,6 +59,7 @@
59#define CMD_SECURITY_FREEZE_LOCK 0xF5 59#define CMD_SECURITY_FREEZE_LOCK 0xF5
60 60
61#define Q_SLEEP 0 61#define Q_SLEEP 0
62#define Q_CLOSE 1
62 63
63#define READ_TIMEOUT 5*HZ 64#define READ_TIMEOUT 5*HZ
64 65
@@ -66,6 +67,10 @@
66#define ATA_POWER_OFF_TIMEOUT 2*HZ 67#define ATA_POWER_OFF_TIMEOUT 2*HZ
67#endif 68#endif
68 69
70#ifdef ATA_DRIVER_CLOSE
71static struct thread_entry *ata_thread_p = NULL;
72#endif
73
69#if defined(MAX_PHYS_SECTOR_SIZE) && MEM == 64 74#if defined(MAX_PHYS_SECTOR_SIZE) && MEM == 64
70/* Hack - what's the deal with 5g? */ 75/* Hack - what's the deal with 5g? */
71struct ata_lock 76struct ata_lock
@@ -941,6 +946,11 @@ static void ata_thread(void)
941 call_ata_idle_notifys(false); 946 call_ata_idle_notifys(false);
942 last_disk_activity = current_tick - sleep_timeout + (HZ/2); 947 last_disk_activity = current_tick - sleep_timeout + (HZ/2);
943 break; 948 break;
949
950#ifdef ATA_DRIVER_CLOSE
951 case Q_CLOSE:
952 return;
953#endif
944 } 954 }
945 } 955 }
946} 956}
@@ -1307,6 +1317,9 @@ int ata_init(void)
1307 mutex_lock(&ata_mtx); /* Balance unlock below */ 1317 mutex_lock(&ata_mtx); /* Balance unlock below */
1308 1318
1309 last_disk_activity = current_tick; 1319 last_disk_activity = current_tick;
1320#ifdef ATA_DRIVER_CLOSE
1321 ata_thread_p =
1322#endif
1310 create_thread(ata_thread, ata_stack, 1323 create_thread(ata_thread, ata_stack,
1311 sizeof(ata_stack), 0, ata_thread_name 1324 sizeof(ata_stack), 0, ata_thread_name
1312 IF_PRIO(, PRIORITY_USER_INTERFACE) 1325 IF_PRIO(, PRIORITY_USER_INTERFACE)
@@ -1322,6 +1335,21 @@ int ata_init(void)
1322 return rc; 1335 return rc;
1323} 1336}
1324 1337
1338#ifdef ATA_DRIVER_CLOSE
1339void ata_close(void)
1340{
1341 struct thread_entry *thread = ata_thread_p;
1342
1343 if (thread == NULL)
1344 return;
1345
1346 ata_thread_p = NULL;
1347
1348 queue_post(&ata_queue, Q_CLOSE, 0);
1349 thread_wait(thread);
1350}
1351#endif /* ATA_DRIVER_CLOSE */
1352
1325#if (CONFIG_LED == LED_REAL) 1353#if (CONFIG_LED == LED_REAL)
1326void ata_set_led_enabled(bool enabled) 1354void ata_set_led_enabled(bool enabled)
1327{ 1355{
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c
index 90ff800c88..74c5a97167 100644
--- a/firmware/drivers/button.c
+++ b/firmware/drivers/button.c
@@ -410,6 +410,13 @@ void button_init(void)
410 tick_add_task(button_tick); 410 tick_add_task(button_tick);
411} 411}
412 412
413#ifdef BUTTON_DRIVER_CLOSE
414void button_close(void)
415{
416 tick_remove_task(button_tick);
417}
418#endif /* BUTTON_DRIVER_CLOSE */
419
413#ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */ 420#ifdef HAVE_LCD_BITMAP /* only bitmap displays can be flipped */
414/* 421/*
415 * helper function to swap LEFT/RIGHT, UP/DOWN (if present), and F1/F3 (Recorder) 422 * helper function to swap LEFT/RIGHT, UP/DOWN (if present), and F1/F3 (Recorder)
diff --git a/firmware/export/ata.h b/firmware/export/ata.h
index 35538f6354..9b5bd36a5b 100644
--- a/firmware/export/ata.h
+++ b/firmware/export/ata.h
@@ -48,6 +48,7 @@ extern bool ata_disk_is_active(void);
48extern int ata_hard_reset(void); 48extern int ata_hard_reset(void);
49extern int ata_soft_reset(void); 49extern int ata_soft_reset(void);
50extern int ata_init(void); 50extern int ata_init(void);
51extern void ata_close(void);
51extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf); 52extern int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf);
52extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf); 53extern int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf);
53extern void ata_spin(void); 54extern void ata_spin(void);
diff --git a/firmware/export/backlight.h b/firmware/export/backlight.h
index 35c0f86178..895328d98e 100644
--- a/firmware/export/backlight.h
+++ b/firmware/export/backlight.h
@@ -28,6 +28,7 @@ void backlight_set_timeout(int value);
28 28
29#ifdef HAVE_BACKLIGHT 29#ifdef HAVE_BACKLIGHT
30void backlight_init(void); 30void backlight_init(void);
31void backlight_close(void);
31 32
32int backlight_get_current_timeout(void); 33int backlight_get_current_timeout(void);
33 34
diff --git a/firmware/export/button.h b/firmware/export/button.h
index 6decf6ec69..82ea81ffab 100644
--- a/firmware/export/button.h
+++ b/firmware/export/button.h
@@ -29,6 +29,7 @@
29extern struct event_queue button_queue; 29extern struct event_queue button_queue;
30 30
31void button_init (void); 31void button_init (void);
32void button_close(void);
32int button_queue_count(void); 33int button_queue_count(void);
33long button_get (bool block); 34long button_get (bool block);
34long button_get_w_tmo(int ticks); 35long button_get_w_tmo(int ticks);
diff --git a/firmware/export/config-gigabeat-s.h b/firmware/export/config-gigabeat-s.h
index d74f05ce9c..a0c05dad45 100644
--- a/firmware/export/config-gigabeat-s.h
+++ b/firmware/export/config-gigabeat-s.h
@@ -54,15 +54,6 @@
54/* Define this for LCD backlight available */ 54/* Define this for LCD backlight available */
55#define HAVE_BACKLIGHT 55#define HAVE_BACKLIGHT
56 56
57#define HAVE_LCD_ENABLE
58
59#define HAVE_BACKLIGHT_BRIGHTNESS
60
61/* Main LCD backlight brightness range and defaults */
62#define MIN_BRIGHTNESS_SETTING 0
63#define MAX_BRIGHTNESS_SETTING 24
64#define DEFAULT_BRIGHTNESS_SETTING 12
65
66/* Define this if you have a software controlled poweroff */ 57/* Define this if you have a software controlled poweroff */
67#define HAVE_SW_POWEROFF 58#define HAVE_SW_POWEROFF
68 59
@@ -78,7 +69,20 @@
78#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \ 69#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | \
79 SAMPR_CAP_11) 70 SAMPR_CAP_11)
80 71
72#ifndef BOOTLOADER
73/* Not for bootloader */
74#define HAVE_LCD_ENABLE
75
76#define HAVE_BACKLIGHT_BRIGHTNESS
77
78/* Main LCD backlight brightness range and defaults */
79#define MIN_BRIGHTNESS_SETTING 0
80#define MAX_BRIGHTNESS_SETTING 24
81#define DEFAULT_BRIGHTNESS_SETTING 12
82
83
81#define HAVE_HEADPHONE_DETECTION 84#define HAVE_HEADPHONE_DETECTION
85#endif /* BOOTLOADER */
82 86
83#ifndef SIMULATOR 87#ifndef SIMULATOR
84 88
diff --git a/firmware/export/usb.h b/firmware/export/usb.h
index 4500cb2cde..ff1f55cd35 100644
--- a/firmware/export/usb.h
+++ b/firmware/export/usb.h
@@ -31,7 +31,8 @@ enum {
31 USB_TRANSFER_COMPLETION, 31 USB_TRANSFER_COMPLETION,
32 USB_REQUEST_DISK, 32 USB_REQUEST_DISK,
33 USB_RELEASE_DISK, 33 USB_RELEASE_DISK,
34 USB_REQUEST_REBOOT 34 USB_REQUEST_REBOOT,
35 USB_QUIT,
35}; 36};
36 37
37 38
@@ -89,7 +90,7 @@ struct usb_transfer_completion_event_data
89void usb_init(void); 90void usb_init(void);
90void usb_enable(bool on); 91void usb_enable(bool on);
91void usb_start_monitoring(void); 92void usb_start_monitoring(void);
92void usb_stop_monitoring(void); 93void usb_close(void);
93void usb_acknowledge(long id); 94void usb_acknowledge(long id);
94void usb_wait_for_disconnect(struct event_queue *q); 95void usb_wait_for_disconnect(struct event_queue *q);
95int usb_wait_for_disconnect_w_tmo(struct event_queue *q, int ticks); 96int usb_wait_for_disconnect_w_tmo(struct event_queue *q, int ticks);
diff --git a/firmware/target/arm/imx31/gigabeat-s/ata-target.h b/firmware/target/arm/imx31/gigabeat-s/ata-target.h
index 6428e9f41f..8f8083dc8d 100644
--- a/firmware/target/arm/imx31/gigabeat-s/ata-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/ata-target.h
@@ -19,6 +19,10 @@
19#ifndef ATA_TARGET_H 19#ifndef ATA_TARGET_H
20#define ATA_TARGET_H 20#define ATA_TARGET_H
21 21
22#ifdef BOOTLOADER
23#define ATA_DRIVER_CLOSE
24#endif
25
22/* Plain C read & write loops */ 26/* Plain C read & write loops */
23#define PREFER_C_READING 27#define PREFER_C_READING
24#define PREFER_C_WRITING 28#define PREFER_C_WRITING
diff --git a/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c b/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c
index 4df9be843c..b35e3c1ad0 100644
--- a/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c
@@ -22,6 +22,7 @@
22#include "mc13783.h" 22#include "mc13783.h"
23#include "backlight-target.h" 23#include "backlight-target.h"
24 24
25#ifdef HAVE_BACKLIGHT_BRIGHTNESS
25/* Table that uses combinations of current level and pwm fraction to get 26/* Table that uses combinations of current level and pwm fraction to get
26 * as many uniquely-visible brightness levels as possible. The lowest current 27 * as many uniquely-visible brightness levels as possible. The lowest current
27 * level for any average current is used even though many combinations give 28 * level for any average current is used even though many combinations give
@@ -60,6 +61,7 @@ static const struct
60 { 3, 12 }, /* 9 12 7.2 */ 61 { 3, 12 }, /* 9 12 7.2 */
61 /* Anything higher is just too much */ 62 /* Anything higher is just too much */
62}; 63};
64#endif /* HAVE_BACKLIGHT_BRIGHTNESS */
63 65
64bool _backlight_init(void) 66bool _backlight_init(void)
65{ 67{
@@ -85,6 +87,7 @@ void _backlight_off(void)
85 mc13783_clear(MC13783_LED_CONTROL0, MC13783_LEDEN); 87 mc13783_clear(MC13783_LED_CONTROL0, MC13783_LEDEN);
86} 88}
87 89
90#ifdef HAVE_BACKLIGHT_BRIGHTNESS
88/* Assumes that the backlight has been initialized */ 91/* Assumes that the backlight has been initialized */
89void _backlight_set_brightness(int brightness) 92void _backlight_set_brightness(int brightness)
90{ 93{
@@ -106,3 +109,4 @@ void _backlight_set_brightness(int brightness)
106 109
107 mc13783_write(MC13783_LED_CONTROL2, data); 110 mc13783_write(MC13783_LED_CONTROL2, data);
108} 111}
112#endif /* HAVE_BACKLIGHT_BRIGHTNESS */
diff --git a/firmware/target/arm/imx31/gigabeat-s/backlight-target.h b/firmware/target/arm/imx31/gigabeat-s/backlight-target.h
index 7c4b2fa0fd..145df0d930 100644
--- a/firmware/target/arm/imx31/gigabeat-s/backlight-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/backlight-target.h
@@ -19,11 +19,15 @@
19#ifndef BACKLIGHT_TARGET_H 19#ifndef BACKLIGHT_TARGET_H
20#define BACKLIGHT_TARGET_H 20#define BACKLIGHT_TARGET_H
21 21
22#ifdef BOOTLOADER
23#define BACKLIGHT_DRIVER_CLOSE
24/* Force the whole driver to be built */
25#define BACKLIGHT_FULL_INIT
26#endif
27
22bool _backlight_init(void); 28bool _backlight_init(void);
23void _backlight_on(void); 29void _backlight_on(void);
24void _backlight_off(void); 30void _backlight_off(void);
25void _backlight_set_brightness(int brightness); 31void _backlight_set_brightness(int brightness);
26 32
27/* true: backlight fades off - false: backlight fades on */
28void __backlight_dim(bool dim);
29#endif 33#endif
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
index e80166bca7..746883d010 100644
--- a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
@@ -29,11 +29,16 @@
29 29
30/* Most code in here is taken from the Linux BSP provided by Freescale 30/* Most code in here is taken from the Linux BSP provided by Freescale
31 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */ 31 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */
32 32#ifdef HAVE_HEADPHONE_DETECTION
33static bool headphones_detect = false; 33static bool headphones_detect = false;
34#endif
34static uint32_t int_btn = BUTTON_NONE; 35static uint32_t int_btn = BUTTON_NONE;
35static bool hold_button = false; 36static bool hold_button = false;
37#ifdef BOOTLOADER
38static bool initialized = false;
39#else
36static bool hold_button_old = false; 40static bool hold_button_old = false;
41#endif
37#define _button_hold() (GPIO3_DR & 0x10) 42#define _button_hold() (GPIO3_DR & 0x10)
38 43
39static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void) 44static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
@@ -116,6 +121,14 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
116 121
117void button_init_device(void) 122void button_init_device(void)
118{ 123{
124#ifdef BOOTLOADER
125 /* Can be called more than once in the bootloader */
126 if (initialized)
127 return;
128
129 initialized = true;
130#endif
131
119 /* Enable keypad clock */ 132 /* Enable keypad clock */
120 imx31_clkctl_module_clock_gating(CG_KPP, CGM_ON_ALL); 133 imx31_clkctl_module_clock_gating(CG_KPP, CGM_ON_ALL);
121 134
@@ -136,15 +149,26 @@ void button_init_device(void)
136 KPP_KDDR = (KPP_KDDR | (0x7 << 8)) & ~0x1f; 149 KPP_KDDR = (KPP_KDDR | (0x7 << 8)) & ~0x1f;
137 150
138 /* 5. Clear the KPKD Status Flag and Synchronizer chain. 151 /* 5. Clear the KPKD Status Flag and Synchronizer chain.
139 * 6. Set the KDIE control bit, and set the KRIE control 152 * 6. Set the KDIE control bit bit. */
140 * bit (to force immediate scan). */ 153 KPP_KPSR = KPP_KPSR_KDIE | KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKD;
141 KPP_KPSR = KPP_KPSR_KRIE | KPP_KPSR_KDIE | KPP_KPSR_KRSS |
142 KPP_KPSR_KDSC | KPP_KPSR_KPKR | KPP_KPSR_KPKD;
143 154
144 /* KPP IRQ at priority 3 */ 155 /* KPP IRQ at priority 3 */
145 avic_enable_int(KPP, IRQ, 3, KPP_HANDLER); 156 avic_enable_int(KPP, IRQ, 3, KPP_HANDLER);
146} 157}
147 158
159#ifdef BUTTON_DRIVER_CLOSE
160void button_close_device(void)
161{
162 int oldlevel = disable_irq_save();
163
164 avic_disable_int(KPP);
165 KPP_KPSR &= ~(KPP_KPSR_KRIE | KPP_KPSR_KDIE);
166 int_btn = BUTTON_NONE;
167
168 restore_irq(oldlevel);
169}
170#endif /* BUTTON_DRIVER_CLOSE */
171
148bool button_hold(void) 172bool button_hold(void)
149{ 173{
150 return _button_hold(); 174 return _button_hold();
@@ -155,12 +179,14 @@ int button_read_device(void)
155 /* Simple poll of GPIO status */ 179 /* Simple poll of GPIO status */
156 hold_button = _button_hold(); 180 hold_button = _button_hold();
157 181
182#ifndef BOOTLOADER
158 /* Backlight hold handling */ 183 /* Backlight hold handling */
159 if (hold_button != hold_button_old) 184 if (hold_button != hold_button_old)
160 { 185 {
161 hold_button_old = hold_button; 186 hold_button_old = hold_button;
162 backlight_hold_changed(hold_button); 187 backlight_hold_changed(hold_button);
163 } 188 }
189#endif
164 190
165 /* Enable the keypad interrupt to cause it to fire if a key is down. 191 /* Enable the keypad interrupt to cause it to fire if a key is down.
166 * KPP_HANDLER will clear and disable it after the scan. If no key 192 * KPP_HANDLER will clear and disable it after the scan. If no key
@@ -190,6 +216,7 @@ void button_power_set_state(bool pressed)
190 restore_irq(oldlevel); 216 restore_irq(oldlevel);
191} 217}
192 218
219#ifdef HAVE_HEADPHONE_DETECTION
193/* This is called from the mc13783 interrupt thread */ 220/* This is called from the mc13783 interrupt thread */
194void set_headphones_inserted(bool inserted) 221void set_headphones_inserted(bool inserted)
195{ 222{
@@ -203,3 +230,4 @@ bool headphones_inserted(void)
203{ 230{
204 return headphones_detect; 231 return headphones_detect;
205} 232}
233#endif /* HAVE_HEADPHONE_DETECTION */
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-target.h b/firmware/target/arm/imx31/gigabeat-s/button-target.h
index e2f68162f7..61d33f8e70 100644
--- a/firmware/target/arm/imx31/gigabeat-s/button-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/button-target.h
@@ -24,8 +24,13 @@
24 24
25#define HAS_BUTTON_HOLD 25#define HAS_BUTTON_HOLD
26 26
27#ifdef BOOTLOADER
28#define BUTTON_DRIVER_CLOSE
29#endif
30
27bool button_hold(void); 31bool button_hold(void);
28void button_init_device(void); 32void button_init_device(void);
33void button_close_device(void);
29int button_read_device(void); 34int button_read_device(void);
30void button_power_set_state(bool pressed); 35void button_power_set_state(bool pressed);
31void set_headphones_inserted(bool inserted); 36void set_headphones_inserted(bool inserted);
@@ -48,6 +53,8 @@ bool headphones_inserted(void);
48#define BUTTON_NEXT (1 << 11) 53#define BUTTON_NEXT (1 << 11)
49#define BUTTON_POWER (1 << 12) /* Read from PMIC */ 54#define BUTTON_POWER (1 << 12) /* Read from PMIC */
50 55
56#define BUTTON_MAIN (0x1fff)
57
51#define BUTTON_REMOTE 0 58#define BUTTON_REMOTE 0
52 59
53#define POWEROFF_BUTTON BUTTON_POWER 60#define POWEROFF_BUTTON BUTTON_POWER
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
index 3af4b48b66..ddf8d1360f 100644
--- a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
@@ -29,6 +29,10 @@
29#include "adc-target.h" 29#include "adc-target.h"
30#include "usb-target.h" 30#include "usb-target.h"
31 31
32#ifdef BOOTLOADER
33#define PMIC_DRIVER_CLOSE
34#endif
35
32/* This is all based on communicating with the MC13783 PMU which is on 36/* This is all based on communicating with the MC13783 PMU which is on
33 * CSPI2 with the chip select at 0. The LCD controller resides on 37 * CSPI2 with the chip select at 0. The LCD controller resides on
34 * CSPI3 cs1, but we have no idea how to communicate to it */ 38 * CSPI3 cs1, but we have no idea how to communicate to it */
@@ -48,10 +52,14 @@ static struct spi_node mc13783_spi =
48static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)]; 52static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)];
49static const char *mc13783_thread_name = "pmic"; 53static const char *mc13783_thread_name = "pmic";
50static struct wakeup mc13783_wake; 54static struct wakeup mc13783_wake;
55#ifdef PMIC_DRIVER_CLOSE
56static bool pmic_close = false;
57static struct thread_entry *mc13783_thread_p = NULL;
58#endif
51 59
52/* The next two functions are rather target-specific but they'll just be left 60/* The next two functions are rather target-specific but they'll just be left
53 * here for the moment */ 61 * here for the moment */
54static __attribute__((noreturn)) void mc13783_interrupt_thread(void) 62static void mc13783_interrupt_thread(void)
55{ 63{
56 const unsigned char status_regs[2] = 64 const unsigned char status_regs[2] =
57 { 65 {
@@ -76,7 +84,9 @@ static __attribute__((noreturn)) void mc13783_interrupt_thread(void)
76 84
77 value = mc13783_read(MC13783_INTERRUPT_SENSE1); 85 value = mc13783_read(MC13783_INTERRUPT_SENSE1);
78 button_power_set_state((value & MC13783_ONOFD1) == 0); 86 button_power_set_state((value & MC13783_ONOFD1) == 0);
87#ifdef HAVE_HEADPHONE_DETECTION
79 set_headphones_inserted((value & MC13783_ONOFD2) == 0); 88 set_headphones_inserted((value & MC13783_ONOFD2) == 0);
89#endif
80 90
81 pending[0] = pending[1] = 0xffffff; 91 pending[0] = pending[1] = 0xffffff;
82 mc13783_write_regset(status_regs, pending, 2); 92 mc13783_write_regset(status_regs, pending, 2);
@@ -90,6 +100,14 @@ static __attribute__((noreturn)) void mc13783_interrupt_thread(void)
90 { 100 {
91 wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK); 101 wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK);
92 102
103#ifdef PMIC_DRIVER_CLOSE
104 if (pmic_close)
105 {
106 gpio_disable_event(MC13783_GPIO_NUM, MC13783_EVENT_ID);
107 return;
108 }
109#endif
110
93 mc13783_read_regset(status_regs, pending, 2); 111 mc13783_read_regset(status_regs, pending, 2);
94 mc13783_write_regset(status_regs, pending, 2); 112 mc13783_write_regset(status_regs, pending, 2);
95 113
@@ -130,9 +148,10 @@ static __attribute__((noreturn)) void mc13783_interrupt_thread(void)
130 148
131 if (pending[1] & MC13783_ONOFD1) 149 if (pending[1] & MC13783_ONOFD1)
132 button_power_set_state((value & MC13783_ONOFD1) == 0); 150 button_power_set_state((value & MC13783_ONOFD1) == 0);
133 151#ifdef HAVE_HEADPHONE_DETECTION
134 if (pending[1] & MC13783_ONOFD2) 152 if (pending[1] & MC13783_ONOFD2)
135 set_headphones_inserted((value & MC13783_ONOFD2) == 0); 153 set_headphones_inserted((value & MC13783_ONOFD2) == 0);
154#endif
136 } 155 }
137 } 156 }
138 } 157 }
@@ -161,10 +180,29 @@ void mc13783_init(void)
161 180
162 MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE); 181 MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE);
163 182
164 create_thread(mc13783_interrupt_thread, mc13783_thread_stack, 183#ifdef PMIC_DRIVER_CLOSE
165 sizeof(mc13783_thread_stack), 0, mc13783_thread_name 184 mc13783_thread_p =
166 IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU)); 185#endif
186 create_thread(mc13783_interrupt_thread,
187 mc13783_thread_stack, sizeof(mc13783_thread_stack), 0,
188 mc13783_thread_name IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU));
189}
190
191#ifdef PMIC_DRIVER_CLOSE
192void mc13783_close(void)
193{
194 struct thread_entry *thread = mc13783_thread_p;
195
196 if (thread == NULL)
197 return;
198
199 mc13783_thread_p = NULL;
200
201 pmic_close = true;
202 wakeup_signal(&mc13783_wake);
203 thread_wait(thread);
167} 204}
205#endif
168 206
169uint32_t mc13783_set(unsigned address, uint32_t bits) 207uint32_t mc13783_set(unsigned address, uint32_t bits)
170{ 208{
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c
index 3ec46bae67..1c3abc64fc 100644
--- a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c
@@ -117,6 +117,7 @@ void system_prepare_fw_start(void)
117{ 117{
118 disable_interrupt(IRQ_FIQ_STATUS); 118 disable_interrupt(IRQ_FIQ_STATUS);
119 avic_disable_int(ALL); 119 avic_disable_int(ALL);
120 mc13783_close();
120 tick_stop(); 121 tick_stop();
121} 122}
122#endif 123#endif
diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-target.h b/firmware/target/arm/imx31/gigabeat-s/usb-target.h
index 8c9dcfc65f..7ecd9a7d49 100644
--- a/firmware/target/arm/imx31/gigabeat-s/usb-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/usb-target.h
@@ -19,6 +19,10 @@
19#ifndef USB_TARGET_H 19#ifndef USB_TARGET_H
20#define USB_TARGET_H 20#define USB_TARGET_H
21 21
22#ifdef BOOTLOADER
23#define USB_DRIVER_CLOSE
24#endif
25
22void usb_set_status(bool plugged); 26void usb_set_status(bool plugged);
23bool usb_init_device(void); 27bool usb_init_device(void);
24int usb_detect(void); 28int usb_detect(void);
diff --git a/firmware/usb.c b/firmware/usb.c
index 3867bfb496..90991e25fd 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -172,6 +172,10 @@ static void usb_thread(void)
172 queue_wait(&usb_queue, &ev); 172 queue_wait(&usb_queue, &ev);
173 switch(ev.id) 173 switch(ev.id)
174 { 174 {
175#ifdef USB_DRIVER_CLOSE
176 case USB_QUIT:
177 return;
178#endif
175#ifdef HAVE_USBSTACK 179#ifdef HAVE_USBSTACK
176 case USB_TRANSFER_COMPLETION: 180 case USB_TRANSFER_COMPLETION:
177 usb_core_handle_transfer_completion((struct usb_transfer_completion_event_data*)ev.data); 181 usb_core_handle_transfer_completion((struct usb_transfer_completion_event_data*)ev.data);
@@ -531,13 +535,22 @@ void usb_start_monitoring(void)
531 usb_monitor_enabled = true; 535 usb_monitor_enabled = true;
532} 536}
533 537
534#ifdef TOSHIBA_GIGABEAT_S 538#ifdef USB_DRIVER_CLOSE
535void usb_stop_monitoring(void) 539void usb_close(void)
536{ 540{
541 struct thread_entry *thread = usb_thread_entry;
542 usb_thread_entry = NULL;
543
544 if (thread == NULL)
545 return;
546
537 tick_remove_task(usb_tick); 547 tick_remove_task(usb_tick);
538 usb_monitor_enabled = false; 548 usb_monitor_enabled = false;
549
550 queue_post(&usb_queue, USB_QUIT, 0);
551 thread_wait(thread);
539} 552}
540#endif 553#endif /* USB_DRIVER_CLOSE */
541 554
542bool usb_inserted(void) 555bool usb_inserted(void)
543{ 556{