summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2009-01-22 22:05:04 +0000
committerMichael Sevakis <jethead71@rockbox.org>2009-01-22 22:05:04 +0000
commitda76a3469437261bd8857c6eddeaafcc601f373e (patch)
tree33e6c461aeb03d28575166c5ed5002aaf8ea9741
parent81df953da55e75632b5efbe676f2b348e11b2c4b (diff)
downloadrockbox-da76a3469437261bd8857c6eddeaafcc601f373e.tar.gz
rockbox-da76a3469437261bd8857c6eddeaafcc601f373e.zip
Use bus reset detection for all ARC OTG devices. Remove conflict from LV24020LP driver with some GPIO-by-number macros for PP502x. Start monitoring for USB stack once all core threads and queues are created otherwise queues will likely be registered after USB acks. Putting PP502x system_reboot in IRAM (unmapped, uncached) memory seems to help it work more consistently. Hopefully I got all the PP USB connect handlers in the right spot in irq_handler. If device seems unresponsive to cable, check there first.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19819 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/main.c6
-rw-r--r--firmware/drivers/tuner/lv24020lp.c41
-rw-r--r--firmware/export/config-c200.h3
-rw-r--r--firmware/export/config-e200.h3
-rw-r--r--firmware/export/config.h13
-rw-r--r--firmware/export/pp5020.h36
-rw-r--r--firmware/export/usb.h3
-rw-r--r--firmware/target/arm/ata-sd-pp.c1
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/usb-imx31.c29
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/usb-target.h3
-rw-r--r--firmware/target/arm/powermgmt-ascodec.c8
-rw-r--r--firmware/target/arm/system-pp502x.c100
-rw-r--r--firmware/target/arm/usb-drv-arc.c11
-rw-r--r--firmware/target/arm/usb-fw-pp502x.c215
-rw-r--r--firmware/target/arm/usb-target.h9
-rw-r--r--firmware/usb.c36
16 files changed, 337 insertions, 180 deletions
diff --git a/apps/main.c b/apps/main.c
index 4e66a851f1..8a1f0a986c 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -141,6 +141,10 @@ static void app_main(void)
141 viewportmanager_set_statusbar(true); 141 viewportmanager_set_statusbar(true);
142 add_event(GUI_EVENT_STATUSBAR_TOGGLE, false, 142 add_event(GUI_EVENT_STATUSBAR_TOGGLE, false,
143 viewportmanager_statusbar_changed); 143 viewportmanager_statusbar_changed);
144#ifdef HAVE_USBSTACK
145 /* All threads should be created and public queues registered by now */
146 usb_start_monitoring();
147#endif
144 root_menu(); 148 root_menu();
145} 149}
146 150
@@ -454,8 +458,8 @@ static void init(void)
454 eeprom_settings_init(); 458 eeprom_settings_init();
455#endif 459#endif
456 460
457 usb_start_monitoring();
458#ifndef HAVE_USBSTACK 461#ifndef HAVE_USBSTACK
462 usb_start_monitoring();
459 while (usb_detect() == USB_INSERTED) 463 while (usb_detect() == USB_INSERTED)
460 { 464 {
461#ifdef HAVE_EEPROM_SETTINGS 465#ifdef HAVE_EEPROM_SETTINGS
diff --git a/firmware/drivers/tuner/lv24020lp.c b/firmware/drivers/tuner/lv24020lp.c
index 0f05d90ea2..9d6425b962 100644
--- a/firmware/drivers/tuner/lv24020lp.c
+++ b/firmware/drivers/tuner/lv24020lp.c
@@ -61,16 +61,17 @@ static int fd_log = -1;
61/** tuner register defines **/ 61/** tuner register defines **/
62 62
63#if defined(SANSA_E200) || defined(SANSA_C200) 63#if defined(SANSA_E200) || defined(SANSA_C200)
64#define GPIO_OUTPUT_EN GPIOH_OUTPUT_EN 64#define TUNER_GPIO_OUTPUT_EN GPIOH_OUTPUT_EN
65#define GPIO_OUTPUT_VAL GPIOH_OUTPUT_VAL 65#define TUNER_GPIO_OUTPUT_VAL GPIOH_OUTPUT_VAL
66#define GPIO_INPUT_VAL GPIOH_INPUT_VAL 66#define TUNER_GPIO_INPUT_VAL GPIOH_INPUT_VAL
67#define FM_NRW_PIN 3 67#define FM_NRW_PIN 3
68#define FM_CLOCK_PIN 4 68#define FM_CLOCK_PIN 4
69#define FM_DATA_PIN 5 69#define FM_DATA_PIN 5
70
70#elif defined(IAUDIO_7) 71#elif defined(IAUDIO_7)
71#define GPIO_OUTPUT_EN GPIOA_DIR 72#define TUNER_GPIO_OUTPUT_EN GPIOA_DIR
72#define GPIO_OUTPUT_VAL GPIOA 73#define TUNER_GPIO_OUTPUT_VAL GPIOA
73#define GPIO_INPUT_VAL GPIOA 74#define TUNER_GPIO_INPUT_VAL GPIOA
74#define FM_CLOCK_PIN 5 75#define FM_CLOCK_PIN 5
75#define FM_DATA_PIN 6 76#define FM_DATA_PIN 6
76#define FM_NRW_PIN 7 77#define FM_NRW_PIN 7
@@ -83,9 +84,9 @@ static void udelay(int usecs)
83} 84}
84 85
85#elif defined(COWON_D2) 86#elif defined(COWON_D2)
86#define GPIO_OUTPUT_EN GPIOC_DIR 87#define TUNER_GPIO_OUTPUT_EN GPIOC_DIR
87#define GPIO_OUTPUT_VAL GPIOC 88#define TUNER_GPIO_OUTPUT_VAL GPIOC
88#define GPIO_INPUT_VAL GPIOC 89#define TUNER_GPIO_INPUT_VAL GPIOC
89#define FM_NRW_PIN 31 90#define FM_NRW_PIN 31
90#define FM_CLOCK_PIN 29 91#define FM_CLOCK_PIN 29
91#define FM_DATA_PIN 30 92#define FM_DATA_PIN 30
@@ -292,16 +293,16 @@ static void lv24020lp_send_byte(unsigned int byte)
292 293
293 for (i = 0; i < 8; i++) 294 for (i = 0; i < 8; i++)
294 { 295 {
295 GPIO_OUTPUT_VAL &= ~(1 << FM_CLOCK_PIN); 296 TUNER_GPIO_OUTPUT_VAL &= ~(1 << FM_CLOCK_PIN);
296 297
297 if (byte & 1) 298 if (byte & 1)
298 GPIO_OUTPUT_VAL |= (1 << FM_DATA_PIN); 299 TUNER_GPIO_OUTPUT_VAL |= (1 << FM_DATA_PIN);
299 else 300 else
300 GPIO_OUTPUT_VAL &= ~(1 << FM_DATA_PIN); 301 TUNER_GPIO_OUTPUT_VAL &= ~(1 << FM_DATA_PIN);
301 302
302 udelay(FM_CLK_DELAY); 303 udelay(FM_CLK_DELAY);
303 304
304 GPIO_OUTPUT_VAL |= (1 << FM_CLOCK_PIN); 305 TUNER_GPIO_OUTPUT_VAL |= (1 << FM_CLOCK_PIN);
305 udelay(FM_CLK_DELAY); 306 udelay(FM_CLK_DELAY);
306 307
307 byte >>= 1; 308 byte >>= 1;
@@ -312,8 +313,8 @@ static void lv24020lp_send_byte(unsigned int byte)
312static void lv24020lp_end_write(void) 313static void lv24020lp_end_write(void)
313{ 314{
314 /* switch back to read mode */ 315 /* switch back to read mode */
315 GPIO_OUTPUT_EN &= ~(1 << FM_DATA_PIN); 316 TUNER_GPIO_OUTPUT_EN &= ~(1 << FM_DATA_PIN);
316 GPIO_OUTPUT_VAL &= ~(1 << FM_NRW_PIN); 317 TUNER_GPIO_OUTPUT_VAL &= ~(1 << FM_NRW_PIN);
317 udelay(FM_CLK_DELAY); 318 udelay(FM_CLK_DELAY);
318} 319}
319 320
@@ -327,8 +328,8 @@ static unsigned int lv24020lp_begin_write(unsigned int address)
327 for (;;) 328 for (;;)
328 { 329 {
329 /* Prepare 3-wire bus pins for write cycle */ 330 /* Prepare 3-wire bus pins for write cycle */
330 GPIO_OUTPUT_VAL |= (1 << FM_NRW_PIN); 331 TUNER_GPIO_OUTPUT_VAL |= (1 << FM_NRW_PIN);
331 GPIO_OUTPUT_EN |= (1 << FM_DATA_PIN); 332 TUNER_GPIO_OUTPUT_EN |= (1 << FM_DATA_PIN);
332 udelay(FM_CLK_DELAY); 333 udelay(FM_CLK_DELAY);
333 334
334 /* current block == register block? */ 335 /* current block == register block? */
@@ -419,13 +420,13 @@ static unsigned int lv24020lp_read(unsigned int address)
419 toread = 0; 420 toread = 0;
420 for (i = 0; i < 8; i++) 421 for (i = 0; i < 8; i++)
421 { 422 {
422 GPIO_OUTPUT_VAL &= ~(1 << FM_CLOCK_PIN); 423 TUNER_GPIO_OUTPUT_VAL &= ~(1 << FM_CLOCK_PIN);
423 udelay(FM_CLK_DELAY); 424 udelay(FM_CLK_DELAY);
424 425
425 if (GPIO_INPUT_VAL & (1 << FM_DATA_PIN)) 426 if (TUNER_GPIO_INPUT_VAL & (1 << FM_DATA_PIN))
426 toread |= (1 << i); 427 toread |= (1 << i);
427 428
428 GPIO_OUTPUT_VAL |= (1 << FM_CLOCK_PIN); 429 TUNER_GPIO_OUTPUT_VAL |= (1 << FM_CLOCK_PIN);
429 udelay(FM_CLK_DELAY); 430 udelay(FM_CLK_DELAY);
430 } 431 }
431 432
diff --git a/firmware/export/config-c200.h b/firmware/export/config-c200.h
index ff260dc956..d68d21455f 100644
--- a/firmware/export/config-c200.h
+++ b/firmware/export/config-c200.h
@@ -180,9 +180,6 @@
180 180
181/* enable these for the experimental usb stack */ 181/* enable these for the experimental usb stack */
182#define HAVE_USBSTACK 182#define HAVE_USBSTACK
183#ifndef BOOTLOADER
184#define USB_DETECT_BY_DRV
185#endif
186#define USB_VENDOR_ID 0x0781 183#define USB_VENDOR_ID 0x0781
187#define USB_PRODUCT_ID 0x7450 184#define USB_PRODUCT_ID 0x7450
188 185
diff --git a/firmware/export/config-e200.h b/firmware/export/config-e200.h
index 7b27391c64..2be64d95cc 100644
--- a/firmware/export/config-e200.h
+++ b/firmware/export/config-e200.h
@@ -177,9 +177,6 @@
177 177
178/* enable these for the experimental usb stack */ 178/* enable these for the experimental usb stack */
179#define HAVE_USBSTACK 179#define HAVE_USBSTACK
180#ifndef BOOTLOADER
181#define USB_DETECT_BY_DRV
182#endif
183#define USB_VENDOR_ID 0x0781 180#define USB_VENDOR_ID 0x0781
184#define USB_PRODUCT_ID 0x7421 181#define USB_PRODUCT_ID 0x7421
185 182
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 15b137588e..7fb41d8d83 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -439,6 +439,8 @@
439#if CONFIG_CPU == IMX31L 439#if CONFIG_CPU == IMX31L
440/* Priority in bootloader is wanted */ 440/* Priority in bootloader is wanted */
441#define HAVE_PRIORITY_SCHEDULING 441#define HAVE_PRIORITY_SCHEDULING
442#define USB_STATUS_BY_EVENT
443#define USB_DETECT_BY_DRV
442#endif 444#endif
443 445
444#else /* !BOOTLOADER */ 446#else /* !BOOTLOADER */
@@ -452,13 +454,18 @@
452 454
453#define HAVE_SEMAPHORE_OBJECTS 455#define HAVE_SEMAPHORE_OBJECTS
454 456
455#ifdef TOSHIBA_GIGABEAT_F 457#if defined(HAVE_USBSTACK) && CONFIG_USBOTG == USBOTG_ARC
456#define HAVE_WAKEUP_OBJECTS 458#define USB_STATUS_BY_EVENT
459#define USB_DETECT_BY_DRV
460#if CONFIG_CPU != IMX31L
461#define INCLUDE_TIMEOUT_API
457#endif 462#endif
463#endif /* HAVE_USBSTACK */
458 464
459#endif /* BOOTLOADER */ 465#endif /* BOOTLOADER */
460 466
461#if defined(HAVE_USBSTACK) || (CONFIG_CPU == JZ4732) || (CONFIG_CPU == AS3525) 467#if defined(HAVE_USBSTACK) || (CONFIG_CPU == JZ4732) \
468 || (CONFIG_CPU == AS3525) || (CONFIG_CPU == S3C2440)
462#define HAVE_WAKEUP_OBJECTS 469#define HAVE_WAKEUP_OBJECTS
463#endif 470#endif
464 471
diff --git a/firmware/export/pp5020.h b/firmware/export/pp5020.h
index 0f622a907d..36c88e00df 100644
--- a/firmware/export/pp5020.h
+++ b/firmware/export/pp5020.h
@@ -218,6 +218,7 @@
218#define CACHE_OP_INVALIDATE 0x0004 218#define CACHE_OP_INVALIDATE 0x0004
219 219
220/* GPIO Ports */ 220/* GPIO Ports */
221#define GPIO_BASE_ADDR 0x6000d000
221#define GPIOA_ENABLE (*(volatile unsigned long *)(0x6000d000)) 222#define GPIOA_ENABLE (*(volatile unsigned long *)(0x6000d000))
222#define GPIOB_ENABLE (*(volatile unsigned long *)(0x6000d004)) 223#define GPIOB_ENABLE (*(volatile unsigned long *)(0x6000d004))
223#define GPIOC_ENABLE (*(volatile unsigned long *)(0x6000d008)) 224#define GPIOC_ENABLE (*(volatile unsigned long *)(0x6000d008))
@@ -322,10 +323,41 @@
322 * define the value of those bits. */ 323 * define the value of those bits. */
323 324
324#define GPIO_SET_BITWISE(port, mask) \ 325#define GPIO_SET_BITWISE(port, mask) \
325 do { *(&port + (0x800/sizeof(long))) = (mask << 8) | mask; } while(0) 326 do { *(&(port) + (0x800/sizeof(long))) = ((mask) << 8) | (mask); } while(0)
326 327
327#define GPIO_CLEAR_BITWISE(port, mask) \ 328#define GPIO_CLEAR_BITWISE(port, mask) \
328 do { *(&port + (0x800/sizeof(long))) = mask << 8; } while(0) 329 do { *(&(port) + (0x800/sizeof(long))) = (mask) << 8; } while(0)
330
331#define GPIO_WRITE_BITWISE(port, val, mask) \
332 do { *(&(port) + (0x800/sizeof(long))) = ((mask) << 8) | (val); } while(0)
333
334/* GPIO Module 0 */
335#define GPIOA 0
336#define GPIOB 1
337#define GPIOC 2
338#define GPIOD 3
339/* GPIO Module 1 */
340#define GPIOE 4
341#define GPIOF 5
342#define GPIOG 6
343#define GPIOH 7
344/* GPIO Module 2 */
345#define GPIOI 8
346#define GPIOJ 9
347#define GPIOK 10
348#define GPIOL 11
349
350#define GPIO_MODULE_NUM(gpio) ((gpio)>>2)
351#define GPIO_MAP_ADDR(gpio) (GPIO_BASE_ADDR+(GPIO_MODULE_NUM(gpio)<<7)+(((gpio)&3)<<2))
352#define GPIO_ENABLE(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x00))
353#define GPIO_OUTPUT_EN(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x10))
354#define GPIO_OUTPUT_VAL(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x20))
355#define GPIO_INPUT_VAL(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x30))
356#define GPIO_INT_STAT(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x40))
357#define GPIO_INT_EN(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x50))
358#define GPIO_INT_LEV(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x60))
359#define GPIO_INT_CLR(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x70))
360#define GPIO_HI_INT_MASK(gpio) (1ul << GPIO_MODULE_NUM(gpio))
329 361
330/* Device initialization */ 362/* Device initialization */
331#define PP_VER1 (*(volatile unsigned long *)(0x70000000)) 363#define PP_VER1 (*(volatile unsigned long *)(0x70000000))
diff --git a/firmware/export/usb.h b/firmware/export/usb.h
index 0a0539a622..90713594a5 100644
--- a/firmware/export/usb.h
+++ b/firmware/export/usb.h
@@ -31,8 +31,8 @@
31 31
32/* Messages from usb_tick and thread states */ 32/* Messages from usb_tick and thread states */
33enum { 33enum {
34 USB_EXTRACTED = 0, /* Event+State */
34 USB_INSERTED, /* Event+State */ 35 USB_INSERTED, /* Event+State */
35 USB_EXTRACTED, /* Event+State */
36#if defined(HAVE_USB_POWER) || defined(USB_DETECT_BY_DRV) 36#if defined(HAVE_USB_POWER) || defined(USB_DETECT_BY_DRV)
37 USB_POWERED, /* Event+State */ 37 USB_POWERED, /* Event+State */
38#endif 38#endif
@@ -135,6 +135,7 @@ bool usb_exclusive_storage(void); /* storage is available for usb */
135 135
136#ifdef USB_FIREWIRE_HANDLING 136#ifdef USB_FIREWIRE_HANDLING
137bool firewire_detect(void); 137bool firewire_detect(void);
138void usb_firewire_connect_event(void);
138#endif 139#endif
139 140
140#endif 141#endif
diff --git a/firmware/target/arm/ata-sd-pp.c b/firmware/target/arm/ata-sd-pp.c
index eb94072ff8..3a095e1321 100644
--- a/firmware/target/arm/ata-sd-pp.c
+++ b/firmware/target/arm/ata-sd-pp.c
@@ -1247,7 +1247,6 @@ void microsd_int(void)
1247 GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); 1247 GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08);
1248#endif 1248#endif
1249 timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0); 1249 timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0);
1250
1251} 1250}
1252#endif /* HAVE_HOTSWAP */ 1251#endif /* HAVE_HOTSWAP */
1253 1252
diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c b/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c
index c0d7cb8d2a..99f3e072eb 100644
--- a/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c
@@ -53,14 +53,19 @@ static void enable_transceiver(bool enable)
53 } 53 }
54} 54}
55 55
56/* Read the immediate state of the cable from the PMIC */
57bool usb_plugged(void)
58{
59 return mc13783_read(MC13783_INTERRUPT_SENSE0) & MC13783_USB4V4S;
60}
61
56void usb_connect_event(void) 62void usb_connect_event(void)
57{ 63{
58 uint32_t status = mc13783_read(MC13783_INTERRUPT_SENSE0); 64 int status = usb_plugged() ? USB_INSERTED : USB_EXTRACTED;
59 usb_status = (status & MC13783_USB4V4S) ? 65 usb_status = status;
60 USB_INSERTED : USB_EXTRACTED;
61 /* Notify power that USB charging is potentially available */ 66 /* Notify power that USB charging is potentially available */
62 charger_usb_detect_event(usb_status); 67 charger_usb_detect_event(status);
63 usb_status_event(usb_status); 68 usb_status_event((status == USB_INSERTED) ? USB_POWERED : USB_UNPOWERED);
64} 69}
65 70
66int usb_detect(void) 71int usb_detect(void)
@@ -68,12 +73,6 @@ int usb_detect(void)
68 return usb_status; 73 return usb_status;
69} 74}
70 75
71/* Read the immediate state of the cable from the PMIC */
72bool usb_plugged(void)
73{
74 return mc13783_read(MC13783_INTERRUPT_SENSE0) & MC13783_USB4V4S;
75}
76
77void usb_init_device(void) 76void usb_init_device(void)
78{ 77{
79 /* Do one-time inits */ 78 /* Do one-time inits */
@@ -107,7 +106,7 @@ void usb_enable(bool on)
107 106
108void usb_attach(void) 107void usb_attach(void)
109{ 108{
110 usb_enable(true); 109 usb_drv_attach();
111} 110}
112 111
113static void __attribute__((interrupt("IRQ"))) USB_OTG_HANDLER(void) 112static void __attribute__((interrupt("IRQ"))) USB_OTG_HANDLER(void)
@@ -122,3 +121,9 @@ void usb_drv_int_enable(bool enable)
122 else 121 else
123 avic_disable_int(USB_OTG); 122 avic_disable_int(USB_OTG);
124} 123}
124
125/* Called during the bus reset interrupt when in detect mode */
126void usb_drv_usb_detect_event(void)
127{
128 usb_status_event(USB_INSERTED);
129}
diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-target.h b/firmware/target/arm/imx31/gigabeat-s/usb-target.h
index 31b8080b57..1f96a9a7eb 100644
--- a/firmware/target/arm/imx31/gigabeat-s/usb-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/usb-target.h
@@ -25,9 +25,6 @@
25#define USB_DRIVER_CLOSE 25#define USB_DRIVER_CLOSE
26#endif 26#endif
27 27
28/* Connect by events, not by tick polling */
29#define USB_STATUS_BY_EVENT
30
31void usb_connect_event(void); 28void usb_connect_event(void);
32void usb_init_device(void); 29void usb_init_device(void);
33int usb_detect(void); 30int usb_detect(void);
diff --git a/firmware/target/arm/powermgmt-ascodec.c b/firmware/target/arm/powermgmt-ascodec.c
index 6ee6209823..1eaaf6ab30 100644
--- a/firmware/target/arm/powermgmt-ascodec.c
+++ b/firmware/target/arm/powermgmt-ascodec.c
@@ -134,10 +134,6 @@ static inline void charger_plugged(void)
134{ 134{
135 batt_threshold = BATT_FULL_VOLTAGE; /* Start with topped value. */ 135 batt_threshold = BATT_FULL_VOLTAGE; /* Start with topped value. */
136 battery_voltage_sync(); 136 battery_voltage_sync();
137#if defined(USB_STATUS_BY_EVENT) && defined(USB_DETECT_BY_DRV)
138 /* Charger pin detect is USB pin detect */
139 usb_connect_event(true);
140#endif
141} 137}
142 138
143static inline void charger_control(void) 139static inline void charger_control(void)
@@ -192,10 +188,6 @@ static inline void charger_unplugged(void)
192 disable_charger(); 188 disable_charger();
193 if (charge_state >= CHARGE_STATE_ERROR) 189 if (charge_state >= CHARGE_STATE_ERROR)
194 charge_state = DISCHARGING; /* Reset error */ 190 charge_state = DISCHARGING; /* Reset error */
195#if defined(USB_STATUS_BY_EVENT) && defined(USB_DETECT_BY_DRV)
196 /* Charger pin detect is USB pin detect */
197 usb_connect_event(false);
198#endif
199} 191}
200 192
201/* Main charging algorithm - called from powermgmt.c */ 193/* Main charging algorithm - called from powermgmt.c */
diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c
index ed4c028ff4..d4c07f10eb 100644
--- a/firmware/target/arm/system-pp502x.c
+++ b/firmware/target/arm/system-pp502x.c
@@ -25,9 +25,8 @@
25#include "as3514.h" 25#include "as3514.h"
26#include "ata-sd-target.h" 26#include "ata-sd-target.h"
27#include "button-target.h" 27#include "button-target.h"
28#ifdef HAVE_USBSTACK 28#include "usb-target.h"
29#include "usb_drv.h" 29#include "usb_drv.h"
30#endif
31 30
32#ifndef BOOTLOADER 31#ifndef BOOTLOADER
33extern void TIMER1(void); 32extern void TIMER1(void);
@@ -42,51 +41,108 @@ void __attribute__((interrupt("IRQ"))) irq_handler(void)
42 { 41 {
43 if (CPU_INT_STAT & TIMER1_MASK) { 42 if (CPU_INT_STAT & TIMER1_MASK) {
44 TIMER1(); 43 TIMER1();
45 } else if (CPU_INT_STAT & TIMER2_MASK) 44 }
45 else if (CPU_INT_STAT & TIMER2_MASK) {
46 TIMER2(); 46 TIMER2();
47 }
48#ifdef HAVE_USBSTACK
49 /* Rather high priority - place near front */
50 else if (CPU_INT_STAT & USB_MASK) {
51 usb_drv_int();
52 }
53#endif
47#if defined(IPOD_MINI) /* Mini 1st gen only, mini 2nd gen uses iPod 4G code */ 54#if defined(IPOD_MINI) /* Mini 1st gen only, mini 2nd gen uses iPod 4G code */
48 else if (CPU_HI_INT_STAT & GPIO0_MASK) 55 else if (CPU_HI_INT_STAT & GPIO0_MASK) {
49 ipod_mini_button_int(); 56 if ((GPIOA_INT_STAT & 0x3f) || (GPIOB_INT_STAT & 0x30))
57 ipod_mini_button_int();
58 if (GPIOC_INT_STAT & 0x02)
59 firewire_insert_int();
60 if (GPIOD_INT_STAT & 0x08)
61 usb_insert_int();
62 }
63/* end IPOD_MINI */
50#elif CONFIG_KEYPAD == IPOD_4G_PAD /* except Mini 1st gen, handled above */ 64#elif CONFIG_KEYPAD == IPOD_4G_PAD /* except Mini 1st gen, handled above */
51 else if (CPU_HI_INT_STAT & I2C_MASK) 65 else if (CPU_HI_INT_STAT & I2C_MASK) {
52 ipod_4g_button_int(); 66 ipod_4g_button_int();
67 }
68#if defined(IPOD_COLOR) || defined(IPOD_MINI2G) || defined(IPOD_4G)
69 else if (CPU_HI_INT_STAT & GPIO0_MASK) {
70 if (GPIOC_INT_STAT & 0x02)
71 firewire_insert_int();
72 if (GPIOD_INT_STAT & 0x08)
73 usb_insert_int();
74 }
75#elif defined(IPOD_NANO) || defined(IPOD_VIDEO)
76 else if (CPU_HI_INT_STAT & GPIO2_MASK) {
77 if (GPIOL_INT_STAT & 0x10)
78 usb_insert_int();
79 }
80#endif
81/* end CONFIG_KEYPAD == IPOD_4G_PAD */
82#elif defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
83 else if (CPU_HI_INT_STAT & GPIO2_MASK) {
84 if (GPIOL_INT_STAT & 0x04)
85 usb_insert_int();
86 }
87/* end IRIVER_H10 || IRIVER_H10_5GB */
53#elif defined(SANSA_E200) 88#elif defined(SANSA_E200)
54#ifdef HAVE_HOTSWAP
55 else if (CPU_HI_INT_STAT & GPIO0_MASK) { 89 else if (CPU_HI_INT_STAT & GPIO0_MASK) {
90#ifdef HAVE_HOTSWAP
56 if (GPIOA_INT_STAT & 0x80) 91 if (GPIOA_INT_STAT & 0x80)
57 microsd_int(); 92 microsd_int();
58 }
59#endif 93#endif
94 if (GPIOB_INT_STAT & 0x10)
95 usb_insert_int();
96 }
60 else if (CPU_HI_INT_STAT & GPIO1_MASK) { 97 else if (CPU_HI_INT_STAT & GPIO1_MASK) {
61 if (GPIOF_INT_STAT & 0xff) 98 if (GPIOF_INT_STAT & 0xff)
62 button_int(); 99 button_int();
63 if (GPIOH_INT_STAT & 0xc0) 100 if (GPIOH_INT_STAT & 0xc0)
64 clickwheel_int(); 101 clickwheel_int();
65 } 102 }
66#elif defined(SANSA_C200) && defined(HAVE_HOTSWAP) 103/* end SANSA_E200 */
104#elif defined(SANSA_C200)
105 else if (CPU_HI_INT_STAT & GPIO1_MASK) {
106 if (GPIOH_INT_STAT & 0x02)
107 usb_insert_int();
108 }
109#ifdef HAVE_HOTSWAP
67 else if (CPU_HI_INT_STAT & GPIO2_MASK) { 110 else if (CPU_HI_INT_STAT & GPIO2_MASK) {
68 if (GPIOL_INT_STAT & 0x08) 111 if (GPIOL_INT_STAT & 0x08)
69 microsd_int(); 112 microsd_int();
70 } 113 }
114#endif
115/* end SANSA_C200 */
71#elif defined(MROBE_100) 116#elif defined(MROBE_100)
72 else if (CPU_HI_INT_STAT & GPIO0_MASK) { 117 else if (CPU_HI_INT_STAT & GPIO0_MASK) {
73 if (GPIOD_INT_STAT & 0x2) 118 if (GPIOD_INT_STAT & 0x02)
74 button_int(); 119 button_int();
75 } 120 }
121 else if (CPU_HI_INT_STAT & GPIO2_MASK) {
122 if (GPIOL_INT_STAT & 0x04)
123 usb_insert_int();
124 }
125/* end MROBE_100 */
126#elif defined(PHILIPS_SA9200)
127 else if (CPU_HI_INT_STAT & GPIO1_MASK) {
128 if (GPIOF_INT_STAT & 0x80)
129 usb_insert_int();
130 }
131/* end PHILIPS_SA9200 */
76#elif defined(PHILIPS_HDD1630) 132#elif defined(PHILIPS_HDD1630)
77 else if (CPU_HI_INT_STAT & GPIO0_MASK) { 133 else if (CPU_HI_INT_STAT & GPIO0_MASK) {
78 if (GPIOA_INT_STAT & 0x20) 134 if (GPIOA_INT_STAT & 0x20)
79 button_int(); 135 button_int();
80 } 136 }
137 else if (CPU_HI_INT_STAT & GPIO1_MASK) {
138 if (GPIOE_INT_STAT & 0x04)
139 usb_insert_int();
140 }
141/* end PHILIPS_HDD1630 */
81#endif 142#endif
82#ifdef IPOD_ACCESSORY_PROTOCOL 143#ifdef IPOD_ACCESSORY_PROTOCOL
83 else if (CPU_HI_INT_STAT & SER0_MASK) { 144 else if (CPU_HI_INT_STAT & SER0_MASK) {
84 SERIAL0(); 145 SERIAL0();
85 }
86#endif
87#ifdef HAVE_USBSTACK
88 else if (CPU_INT_STAT & USB_MASK) {
89 usb_drv_int();
90 } 146 }
91#endif 147#endif
92 } else { 148 } else {
@@ -437,8 +493,12 @@ void system_init(void)
437#endif /* BOOTLOADER */ 493#endif /* BOOTLOADER */
438} 494}
439 495
440void system_reboot(void) 496void ICODE_ATTR system_reboot(void)
441{ 497{
498 disable_interrupt(IRQ_FIQ_STATUS);
499 CPU_INT_DIS = -1;
500 COP_INT_DIS = -1;
501
442 /* Reboot */ 502 /* Reboot */
443#if defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200) 503#if defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200)
444 CACHE_CTL &= ~CACHE_CTL_VECT_REMAP; 504 CACHE_CTL &= ~CACHE_CTL_VECT_REMAP;
diff --git a/firmware/target/arm/usb-drv-arc.c b/firmware/target/arm/usb-drv-arc.c
index b6d6ff154d..15f3bf2c6c 100644
--- a/firmware/target/arm/usb-drv-arc.c
+++ b/firmware/target/arm/usb-drv-arc.c
@@ -419,13 +419,11 @@ static void _usb_drv_init(bool attach)
419 REG_ENDPOINTLISTADDR = (unsigned int)qh_array; 419 REG_ENDPOINTLISTADDR = (unsigned int)qh_array;
420 REG_DEVICEADDR = 0; 420 REG_DEVICEADDR = 0;
421 421
422#ifdef USB_DETECT_BY_DRV
423 if (!attach) { 422 if (!attach) {
424 /* enable RESET interrupt */ 423 /* enable RESET interrupt */
425 REG_USBINTR = USBINTR_RESET_EN; 424 REG_USBINTR = USBINTR_RESET_EN;
426 } 425 }
427 else 426 else
428#endif
429 { 427 {
430 /* enable USB interrupts */ 428 /* enable USB interrupts */
431 REG_USBINTR = 429 REG_USBINTR =
@@ -449,23 +447,17 @@ static void _usb_drv_init(bool attach)
449 (void)attach; 447 (void)attach;
450} 448}
451 449
452/** With USB_DETECT_BY_DRV, attach is distinct from init, otherwise eqivalent. **/
453
454/* USB_DETECT_BY_DRV - enable bus reset detection only
455 * else fully enable driver */
456void usb_drv_init(void) 450void usb_drv_init(void)
457{ 451{
458 _usb_drv_init(false); 452 _usb_drv_init(false);
459} 453}
460 454
461#ifdef USB_DETECT_BY_DRV
462/* fully enable driver */ 455/* fully enable driver */
463void usb_drv_attach(void) 456void usb_drv_attach(void)
464{ 457{
465 sleep(HZ/10); 458 sleep(HZ/10);
466 _usb_drv_init(true); 459 _usb_drv_init(true);
467} 460}
468#endif /* USB_DETECT_BY_DRV */
469 461
470void usb_drv_exit(void) 462void usb_drv_exit(void)
471{ 463{
@@ -513,7 +505,7 @@ void usb_drv_int(void)
513 /* reset interrupt */ 505 /* reset interrupt */
514 if (status & USBSTS_RESET) { 506 if (status & USBSTS_RESET) {
515 REG_USBSTS = USBSTS_RESET; 507 REG_USBSTS = USBSTS_RESET;
516#ifdef USB_DETECT_BY_DRV 508
517 if (UNLIKELY(usbintr == USBINTR_RESET_EN)) { 509 if (UNLIKELY(usbintr == USBINTR_RESET_EN)) {
518 /* USB detected - detach and inform */ 510 /* USB detected - detach and inform */
519 usb_drv_stop(); 511 usb_drv_stop();
@@ -523,7 +515,6 @@ void usb_drv_int(void)
523 usb_drv_usb_detect_event(); 515 usb_drv_usb_detect_event();
524 } 516 }
525 else 517 else
526#endif
527 { 518 {
528 bus_reset(); 519 bus_reset();
529 usb_core_bus_reset(); /* tell mom */ 520 usb_core_bus_reset(); /* tell mom */
diff --git a/firmware/target/arm/usb-fw-pp502x.c b/firmware/target/arm/usb-fw-pp502x.c
index 8a6d78675f..883ca1e8e2 100644
--- a/firmware/target/arm/usb-fw-pp502x.c
+++ b/firmware/target/arm/usb-fw-pp502x.c
@@ -33,6 +33,60 @@
33#include "usb_core.h" 33#include "usb_core.h"
34#include "usb_drv.h" 34#include "usb_drv.h"
35 35
36#if defined(IPOD_4G) || defined(IPOD_COLOR) \
37 || defined(IPOD_MINI) || defined(IPOD_MINI2G)
38 /* GPIO D bit 3 is usb detect */
39#define USB_GPIO GPIOD
40#define USB_GPIO_MASK 0x08
41#define USB_GPIO_VAL 0x08
42
43#elif defined(IPOD_NANO) || defined(IPOD_VIDEO)
44 /* GPIO L bit 4 is usb detect */
45#define USB_GPIO GPIOL
46#define USB_GPIO_MASK 0x10
47#define USB_GPIO_VAL 0x10
48
49#elif defined(SANSA_C200)
50 /* GPIO H bit 1 is usb/charger detect */
51#define USB_GPIO GPIOH
52#define USB_GPIO_MASK 0x02
53#define USB_GPIO_VAL 0x02
54
55#elif defined(SANSA_E200)
56 /* GPIO B bit 4 is usb/charger detect */
57#define USB_GPIO GPIOB
58#define USB_GPIO_MASK 0x10
59#define USB_GPIO_VAL 0x10
60
61#elif defined(IRIVER_H10) || defined(IRIVER_H10_5GB) || defined(MROBE_100)
62 /* GPIO L bit 2 is usb detect */
63#define USB_GPIO GPIOL
64#define USB_GPIO_MASK 0x04
65#define USB_GPIO_VAL 0x04
66
67#elif defined(PHILIPS_SA9200)
68 /* GPIO F bit 7 (low) is usb detect */
69#define USB_GPIO GPIOF
70#define USB_GPIO_MASK 0x80
71#define USB_GPIO_VAL 0x00
72
73#elif defined(PHILIPS_HDD1630)
74 /* GPIO E bit 2 is usb detect */
75#define USB_GPIO GPIOE
76#define USB_GPIO_MASK 0x04
77#define USB_GPIO_VAL 0x04
78#else
79#error No USB GPIO config specified
80#endif
81
82#define USB_GPIO_ENABLE GPIO_ENABLE(USB_GPIO)
83#define USB_GPIO_OUTPUT_EN GPIO_OUTPUT_EN(USB_GPIO)
84#define USB_GPIO_INPUT_VAL GPIO_INPUT_VAL(USB_GPIO)
85#define USB_GPIO_INT_EN GPIO_INT_EN(USB_GPIO)
86#define USB_GPIO_INT_LEV GPIO_INT_LEV(USB_GPIO)
87#define USB_GPIO_INT_CLR GPIO_INT_CLR(USB_GPIO)
88#define USB_GPIO_HI_INT_MASK GPIO_HI_INT_MASK(USB_GPIO)
89
36void usb_init_device(void) 90void usb_init_device(void)
37{ 91{
38 /* enable usb module */ 92 /* enable usb module */
@@ -52,7 +106,10 @@ void usb_init_device(void)
52 while ((inl(0x70000028) & 0x80) == 0); 106 while ((inl(0x70000028) & 0x80) == 0);
53 outl(inl(0x70000028) | 0x2, 0x70000028); 107 outl(inl(0x70000028) | 0x2, 0x70000028);
54 udelay(100000); 108 udelay(100000);
55 109
110 /* Do one-time inits */
111 usb_drv_startup();
112
56 /* disable USB-devices until USB is detected via GPIO */ 113 /* disable USB-devices until USB is detected via GPIO */
57#ifndef BOOTLOADER 114#ifndef BOOTLOADER
58 /* Disabling USB0 in the bootloader makes the OF not load, 115 /* Disabling USB0 in the bootloader makes the OF not load,
@@ -63,17 +120,38 @@ void usb_init_device(void)
63 DEV_INIT2 &= ~INIT_USB; 120 DEV_INIT2 &= ~INIT_USB;
64#endif 121#endif
65 122
66#if defined(IPOD_COLOR) || defined(IPOD_4G) \ 123 /* These set INV_LEV to the inserted level so it will fire if already
67 || defined(IPOD_MINI) || defined(IPOD_MINI2G) 124 * inserted at the time they are enabled. */
125#ifdef USB_STATUS_BY_EVENT
126 GPIO_CLEAR_BITWISE(USB_GPIO_INT_EN, USB_GPIO_MASK);
127 GPIO_CLEAR_BITWISE(USB_GPIO_OUTPUT_EN, USB_GPIO_MASK);
128 GPIO_SET_BITWISE(USB_GPIO_ENABLE, USB_GPIO_MASK);
129 GPIO_WRITE_BITWISE(USB_GPIO_INT_LEV, USB_GPIO_VAL, USB_GPIO_MASK);
130 USB_GPIO_INT_CLR = USB_GPIO_MASK;
131 GPIO_SET_BITWISE(USB_GPIO_INT_EN, USB_GPIO_MASK);
132 CPU_HI_INT_EN = USB_GPIO_HI_INT_MASK;
133
134#ifdef USB_FIREWIRE_HANDLING
68 /* GPIO C bit 1 is firewire detect */ 135 /* GPIO C bit 1 is firewire detect */
69 GPIOC_ENABLE |= 0x02; 136 GPIO_CLEAR_BITWISE(GPIOC_INT_EN, 0x02);
70 GPIOC_OUTPUT_EN &= ~0x02; 137 GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_EN, 0x02);
138 GPIO_SET_BITWISE(GPIOC_ENABLE, 0x02);
139 GPIO_WRITE_BITWISE(GPIOC_INT_LEV, 0x00, 0x02);
140 GPIOC_INT_CLR = 0x02;
141 GPIO_SET_BITWISE(GPIOC_INT_EN, 0x02);
142 CPU_HI_INT_EN = GPIO0_MASK;
71#endif 143#endif
72 144 CPU_INT_EN = HI_MASK;
73#ifdef HAVE_USBSTACK 145#else
74 /* Do one-time inits */ 146 /* No interrupt - setup pin read only (BOOTLOADER) */
75 usb_drv_startup(); 147 GPIO_CLEAR_BITWISE(USB_GPIO_OUTPUT_EN, USB_GPIO_MASK);
148 GPIO_SET_BITWISE(USB_GPIO_ENABLE, USB_GPIO_MASK);
149#ifdef USB_FIREWIRE_HANDLING
150 /* GPIO C bit 1 is firewire detect */
151 GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_EN, 0x02);
152 GPIO_SET_BITWISE(GPIOC_ENABLE, 0x02);
76#endif 153#endif
154#endif /* USB_STATUS_BY_EVENT */
77} 155}
78 156
79void usb_enable(bool on) 157void usb_enable(bool on)
@@ -96,21 +174,27 @@ void usb_enable(bool on)
96 174
97void usb_attach(void) 175void usb_attach(void)
98{ 176{
99#ifdef USB_DETECT_BY_DRV
100 usb_drv_attach(); 177 usb_drv_attach();
101#else
102 usb_enable(true);
103#endif
104} 178}
105 179
106#ifdef USB_DETECT_BY_DRV 180#ifdef USB_STATUS_BY_EVENT
107/* Cannot tell charger pin from USB pin */ 181/* Cannot always tell power pin from USB pin */
108static int usb_status = USB_EXTRACTED; 182static int usb_status = USB_EXTRACTED;
109 183
110void usb_connect_event(bool inserted) 184static int usb_timeout_event(struct timeout *tmo)
185{
186 usb_status_event(tmo->data == USB_GPIO_VAL ? USB_POWERED : USB_UNPOWERED);
187 return 0;
188}
189
190void usb_insert_int(void)
111{ 191{
112 usb_status = inserted ? USB_INSERTED : USB_EXTRACTED; 192 static struct timeout usb_oneshot;
113 usb_status_event(inserted ? USB_POWERED : USB_UNPOWERED); 193 unsigned long val = USB_GPIO_INPUT_VAL & USB_GPIO_MASK;
194 usb_status = (val == USB_GPIO_VAL) ? USB_INSERTED : USB_EXTRACTED;
195 GPIO_WRITE_BITWISE(USB_GPIO_INT_LEV, val ^ USB_GPIO_MASK, USB_GPIO_MASK);
196 USB_GPIO_INT_CLR = USB_GPIO_MASK;
197 timeout_register(&usb_oneshot, usb_timeout_event, HZ/5, val);
114} 198}
115 199
116/* Called during the bus reset interrupt when in detect mode */ 200/* Called during the bus reset interrupt when in detect mode */
@@ -118,51 +202,7 @@ void usb_drv_usb_detect_event(void)
118{ 202{
119 usb_status_event(USB_INSERTED); 203 usb_status_event(USB_INSERTED);
120} 204}
121#else /* !USB_DETECT_BY_DRV */ 205#endif /* USB_STATUS_BY_EVENT */
122static bool usb_pin_detect(void)
123{
124 bool retval = false;
125
126#if defined(IPOD_4G) || defined(IPOD_COLOR) \
127 || defined(IPOD_MINI) || defined(IPOD_MINI2G)
128 /* GPIO D bit 3 is usb detect */
129 if (GPIOD_INPUT_VAL & 0x08)
130 retval = true;
131
132#elif defined(IPOD_NANO) || defined(IPOD_VIDEO)
133 /* GPIO L bit 4 is usb detect */
134 if (GPIOL_INPUT_VAL & 0x10)
135 retval = true;
136
137#elif defined(SANSA_C200)
138 /* GPIO H bit 1 is usb/charger detect */
139 if (GPIOH_INPUT_VAL & 0x02)
140 retval = true;
141
142#elif defined(SANSA_E200)
143 /* GPIO B bit 4 is usb/charger detect */
144 if (GPIOB_INPUT_VAL & 0x10)
145 retval = true;
146
147#elif defined(IRIVER_H10) || defined(IRIVER_H10_5GB) || defined(MROBE_100)
148 /* GPIO L bit 2 is usb detect */
149 if (GPIOL_INPUT_VAL & 0x4)
150 retval = true;
151
152#elif defined(PHILIPS_SA9200)
153 /* GPIO F bit 7 is usb detect */
154 if (!(GPIOF_INPUT_VAL & 0x80))
155 retval = true;
156
157#elif defined(PHILIPS_HDD1630)
158 /* GPIO E bit 2 is usb detect */
159 if (GPIOE_INPUT_VAL & 0x4)
160 retval = true;
161#endif
162
163 return retval;
164}
165#endif /* USB_DETECT_BY_DRV */
166 206
167void usb_drv_int_enable(bool enable) 207void usb_drv_int_enable(bool enable)
168{ 208{
@@ -178,27 +218,46 @@ void usb_drv_int_enable(bool enable)
178/* detect host or charger (INSERTED or EXTRACTED) */ 218/* detect host or charger (INSERTED or EXTRACTED) */
179int usb_detect(void) 219int usb_detect(void)
180{ 220{
181#ifdef USB_DETECT_BY_DRV 221#ifdef USB_STATUS_BY_EVENT
182 return usb_status; 222 return usb_status;
183#else 223#else
184 if(usb_pin_detect()) { 224 return ((USB_GPIO_INPUT_VAL & USB_GPIO_MASK) == USB_GPIO_VAL) ?
185 return USB_INSERTED; 225 USB_INSERTED : USB_EXTRACTED;
186 }
187 else {
188 return USB_EXTRACTED;
189 }
190#endif 226#endif
191} 227}
192 228
193#if defined(IPOD_COLOR) || defined(IPOD_4G) \ 229#ifdef USB_FIREWIRE_HANDLING
194 || defined(IPOD_MINI) || defined(IPOD_MINI2G) 230#ifdef USB_STATUS_BY_EVENT
231static bool firewire_status = false;
232#endif
233
195bool firewire_detect(void) 234bool firewire_detect(void)
196{ 235{
236#ifdef USB_STATUS_BY_EVENT
237 return firewire_status;
238#else
197 /* GPIO C bit 1 is firewire detect */ 239 /* GPIO C bit 1 is firewire detect */
198 if (!(GPIOC_INPUT_VAL & 0x02)) 240 /* no charger detection needed for firewire */
199 /* no charger detection needed for firewire */ 241 return (GPIOC_INPUT_VAL & 0x02) == 0x00;
200 return true;
201 else
202 return false;
203}
204#endif 242#endif
243}
244
245#ifdef USB_STATUS_BY_EVENT
246static int firewire_timeout_event(struct timeout *tmo)
247{
248 if (tmo->data == 0x00)
249 usb_firewire_connect_event();
250 return 0;
251}
252
253void firewire_insert_int(void)
254{
255 static struct timeout firewire_oneshot;
256 unsigned long val = GPIOC_INPUT_VAL & 0x02;
257 firewire_status = val == 0x00;
258 GPIO_WRITE_BITWISE(GPIOC_INT_LEV, val ^ 0x02, 0x02);
259 GPIOC_INT_CLR = 0x02;
260 timeout_register(&firewire_oneshot, firewire_timeout_event, HZ/5, val);
261}
262#endif /* USB_STATUS_BY_EVENT */
263#endif /* USB_FIREWIRE_HANDLING */
diff --git a/firmware/target/arm/usb-target.h b/firmware/target/arm/usb-target.h
index 913ad805ce..8e159617d5 100644
--- a/firmware/target/arm/usb-target.h
+++ b/firmware/target/arm/usb-target.h
@@ -22,12 +22,7 @@
22#define USB_TARGET_H 22#define USB_TARGET_H
23 23
24void usb_init_device(void); 24void usb_init_device(void);
25 25void usb_insert_int(void);
26#ifndef BOOTLOADER 26void firewire_insert_int(void);
27#if defined(SANSA_C200) || defined(SANSA_E200)
28#define USB_STATUS_BY_EVENT /* No USB tick */
29void usb_connect_event(bool inserted);
30#endif
31#endif /* BOOTLOADER */
32 27
33#endif 28#endif
diff --git a/firmware/usb.c b/firmware/usb.c
index 10a7ae1bff..a1e552a321 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -416,9 +416,11 @@ static void usb_thread(void)
416#ifdef USB_STATUS_BY_EVENT 416#ifdef USB_STATUS_BY_EVENT
417void usb_status_event(int current_status) 417void usb_status_event(int current_status)
418{ 418{
419 /* Status should be USB_POWERED, USB_UNPOWERED, USB_INSERTED or 419 /* Caller isn't expected to filter for changes in status.
420 * USB_EXTRACTED. 420 * current_status:
421 * Caller isn't expected to filter for changes in status. */ 421 * USB_DETECT_BY_DRV: USB_POWERED, USB_UNPOWERED, USB_INSERTED (driver)
422 * else: USB_INSERTED, USB_EXTRACTED
423 */
422 if(usb_monitor_enabled) 424 if(usb_monitor_enabled)
423 { 425 {
424 int oldstatus = disable_irq_save(); /* Dual-use function */ 426 int oldstatus = disable_irq_save(); /* Dual-use function */
@@ -435,16 +437,30 @@ void usb_status_event(int current_status)
435 437
436void usb_start_monitoring(void) 438void usb_start_monitoring(void)
437{ 439{
440 int oldstatus = disable_irq_save(); /* Sync to event */
438 int status = usb_detect(); 441 int status = usb_detect();
442
443 usb_monitor_enabled = true;
444
439#ifdef USB_DETECT_BY_DRV 445#ifdef USB_DETECT_BY_DRV
440 /* USB detection begins by USB_POWERED, not USB_INSERTED. If it is 446 status = (status == USB_INSERTED) ? USB_POWERED : USB_UNPOWERED;
441 * USB_EXTRACTED, then nothing changes and post will be skipped. */
442 if(USB_INSERTED == status)
443 status = USB_POWERED;
444#endif 447#endif
445 usb_monitor_enabled = true;
446 usb_status_event(status); 448 usb_status_event(status);
449
450#ifdef USB_FIREWIRE_HANDLING
451 if (firewire_detect())
452 usb_firewire_connect_event();
453#endif
454
455 restore_irq(oldstatus);
447} 456}
457
458#ifdef USB_FIREWIRE_HANDLING
459void usb_firewire_connect_event(void)
460{
461 queue_post(&usb_queue, USB_REQUEST_REBOOT, 0);
462}
463#endif /* USB_FIREWIRE_HANDLING */
448#else /* !USB_STATUS_BY_EVENT */ 464#else /* !USB_STATUS_BY_EVENT */
449static void usb_tick(void) 465static void usb_tick(void)
450{ 466{
@@ -522,7 +538,11 @@ void usb_init(void)
522{ 538{
523 /* We assume that the USB cable is extracted */ 539 /* We assume that the USB cable is extracted */
524 usb_state = USB_EXTRACTED; 540 usb_state = USB_EXTRACTED;
541#ifdef USB_DETECT_BY_DRV
542 last_usb_status = USB_UNPOWERED;
543#else
525 last_usb_status = USB_EXTRACTED; 544 last_usb_status = USB_EXTRACTED;
545#endif
526 usb_monitor_enabled = false; 546 usb_monitor_enabled = false;
527 547
528#ifdef HAVE_USBSTACK 548#ifdef HAVE_USBSTACK