From da76a3469437261bd8857c6eddeaafcc601f373e Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Thu, 22 Jan 2009 22:05:04 +0000 Subject: 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 --- apps/main.c | 6 +- firmware/drivers/tuner/lv24020lp.c | 41 +++-- firmware/export/config-c200.h | 3 - firmware/export/config-e200.h | 3 - firmware/export/config.h | 13 +- firmware/export/pp5020.h | 36 +++- firmware/export/usb.h | 3 +- firmware/target/arm/ata-sd-pp.c | 1 - firmware/target/arm/imx31/gigabeat-s/usb-imx31.c | 29 +-- firmware/target/arm/imx31/gigabeat-s/usb-target.h | 3 - firmware/target/arm/powermgmt-ascodec.c | 8 - firmware/target/arm/system-pp502x.c | 100 ++++++++-- firmware/target/arm/usb-drv-arc.c | 11 +- firmware/target/arm/usb-fw-pp502x.c | 215 ++++++++++++++-------- firmware/target/arm/usb-target.h | 9 +- firmware/usb.c | 36 +++- 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) viewportmanager_set_statusbar(true); add_event(GUI_EVENT_STATUSBAR_TOGGLE, false, viewportmanager_statusbar_changed); +#ifdef HAVE_USBSTACK + /* All threads should be created and public queues registered by now */ + usb_start_monitoring(); +#endif root_menu(); } @@ -454,8 +458,8 @@ static void init(void) eeprom_settings_init(); #endif - usb_start_monitoring(); #ifndef HAVE_USBSTACK + usb_start_monitoring(); while (usb_detect() == USB_INSERTED) { #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; /** tuner register defines **/ #if defined(SANSA_E200) || defined(SANSA_C200) -#define GPIO_OUTPUT_EN GPIOH_OUTPUT_EN -#define GPIO_OUTPUT_VAL GPIOH_OUTPUT_VAL -#define GPIO_INPUT_VAL GPIOH_INPUT_VAL +#define TUNER_GPIO_OUTPUT_EN GPIOH_OUTPUT_EN +#define TUNER_GPIO_OUTPUT_VAL GPIOH_OUTPUT_VAL +#define TUNER_GPIO_INPUT_VAL GPIOH_INPUT_VAL #define FM_NRW_PIN 3 #define FM_CLOCK_PIN 4 #define FM_DATA_PIN 5 + #elif defined(IAUDIO_7) -#define GPIO_OUTPUT_EN GPIOA_DIR -#define GPIO_OUTPUT_VAL GPIOA -#define GPIO_INPUT_VAL GPIOA +#define TUNER_GPIO_OUTPUT_EN GPIOA_DIR +#define TUNER_GPIO_OUTPUT_VAL GPIOA +#define TUNER_GPIO_INPUT_VAL GPIOA #define FM_CLOCK_PIN 5 #define FM_DATA_PIN 6 #define FM_NRW_PIN 7 @@ -83,9 +84,9 @@ static void udelay(int usecs) } #elif defined(COWON_D2) -#define GPIO_OUTPUT_EN GPIOC_DIR -#define GPIO_OUTPUT_VAL GPIOC -#define GPIO_INPUT_VAL GPIOC +#define TUNER_GPIO_OUTPUT_EN GPIOC_DIR +#define TUNER_GPIO_OUTPUT_VAL GPIOC +#define TUNER_GPIO_INPUT_VAL GPIOC #define FM_NRW_PIN 31 #define FM_CLOCK_PIN 29 #define FM_DATA_PIN 30 @@ -292,16 +293,16 @@ static void lv24020lp_send_byte(unsigned int byte) for (i = 0; i < 8; i++) { - GPIO_OUTPUT_VAL &= ~(1 << FM_CLOCK_PIN); + TUNER_GPIO_OUTPUT_VAL &= ~(1 << FM_CLOCK_PIN); if (byte & 1) - GPIO_OUTPUT_VAL |= (1 << FM_DATA_PIN); + TUNER_GPIO_OUTPUT_VAL |= (1 << FM_DATA_PIN); else - GPIO_OUTPUT_VAL &= ~(1 << FM_DATA_PIN); + TUNER_GPIO_OUTPUT_VAL &= ~(1 << FM_DATA_PIN); udelay(FM_CLK_DELAY); - GPIO_OUTPUT_VAL |= (1 << FM_CLOCK_PIN); + TUNER_GPIO_OUTPUT_VAL |= (1 << FM_CLOCK_PIN); udelay(FM_CLK_DELAY); byte >>= 1; @@ -312,8 +313,8 @@ static void lv24020lp_send_byte(unsigned int byte) static void lv24020lp_end_write(void) { /* switch back to read mode */ - GPIO_OUTPUT_EN &= ~(1 << FM_DATA_PIN); - GPIO_OUTPUT_VAL &= ~(1 << FM_NRW_PIN); + TUNER_GPIO_OUTPUT_EN &= ~(1 << FM_DATA_PIN); + TUNER_GPIO_OUTPUT_VAL &= ~(1 << FM_NRW_PIN); udelay(FM_CLK_DELAY); } @@ -327,8 +328,8 @@ static unsigned int lv24020lp_begin_write(unsigned int address) for (;;) { /* Prepare 3-wire bus pins for write cycle */ - GPIO_OUTPUT_VAL |= (1 << FM_NRW_PIN); - GPIO_OUTPUT_EN |= (1 << FM_DATA_PIN); + TUNER_GPIO_OUTPUT_VAL |= (1 << FM_NRW_PIN); + TUNER_GPIO_OUTPUT_EN |= (1 << FM_DATA_PIN); udelay(FM_CLK_DELAY); /* current block == register block? */ @@ -419,13 +420,13 @@ static unsigned int lv24020lp_read(unsigned int address) toread = 0; for (i = 0; i < 8; i++) { - GPIO_OUTPUT_VAL &= ~(1 << FM_CLOCK_PIN); + TUNER_GPIO_OUTPUT_VAL &= ~(1 << FM_CLOCK_PIN); udelay(FM_CLK_DELAY); - if (GPIO_INPUT_VAL & (1 << FM_DATA_PIN)) + if (TUNER_GPIO_INPUT_VAL & (1 << FM_DATA_PIN)) toread |= (1 << i); - GPIO_OUTPUT_VAL |= (1 << FM_CLOCK_PIN); + TUNER_GPIO_OUTPUT_VAL |= (1 << FM_CLOCK_PIN); udelay(FM_CLK_DELAY); } 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 @@ /* enable these for the experimental usb stack */ #define HAVE_USBSTACK -#ifndef BOOTLOADER -#define USB_DETECT_BY_DRV -#endif #define USB_VENDOR_ID 0x0781 #define USB_PRODUCT_ID 0x7450 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 @@ /* enable these for the experimental usb stack */ #define HAVE_USBSTACK -#ifndef BOOTLOADER -#define USB_DETECT_BY_DRV -#endif #define USB_VENDOR_ID 0x0781 #define USB_PRODUCT_ID 0x7421 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 @@ #if CONFIG_CPU == IMX31L /* Priority in bootloader is wanted */ #define HAVE_PRIORITY_SCHEDULING +#define USB_STATUS_BY_EVENT +#define USB_DETECT_BY_DRV #endif #else /* !BOOTLOADER */ @@ -452,13 +454,18 @@ #define HAVE_SEMAPHORE_OBJECTS -#ifdef TOSHIBA_GIGABEAT_F -#define HAVE_WAKEUP_OBJECTS +#if defined(HAVE_USBSTACK) && CONFIG_USBOTG == USBOTG_ARC +#define USB_STATUS_BY_EVENT +#define USB_DETECT_BY_DRV +#if CONFIG_CPU != IMX31L +#define INCLUDE_TIMEOUT_API #endif +#endif /* HAVE_USBSTACK */ #endif /* BOOTLOADER */ -#if defined(HAVE_USBSTACK) || (CONFIG_CPU == JZ4732) || (CONFIG_CPU == AS3525) +#if defined(HAVE_USBSTACK) || (CONFIG_CPU == JZ4732) \ + || (CONFIG_CPU == AS3525) || (CONFIG_CPU == S3C2440) #define HAVE_WAKEUP_OBJECTS #endif 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 @@ #define CACHE_OP_INVALIDATE 0x0004 /* GPIO Ports */ +#define GPIO_BASE_ADDR 0x6000d000 #define GPIOA_ENABLE (*(volatile unsigned long *)(0x6000d000)) #define GPIOB_ENABLE (*(volatile unsigned long *)(0x6000d004)) #define GPIOC_ENABLE (*(volatile unsigned long *)(0x6000d008)) @@ -322,10 +323,41 @@ * define the value of those bits. */ #define GPIO_SET_BITWISE(port, mask) \ - do { *(&port + (0x800/sizeof(long))) = (mask << 8) | mask; } while(0) + do { *(&(port) + (0x800/sizeof(long))) = ((mask) << 8) | (mask); } while(0) #define GPIO_CLEAR_BITWISE(port, mask) \ - do { *(&port + (0x800/sizeof(long))) = mask << 8; } while(0) + do { *(&(port) + (0x800/sizeof(long))) = (mask) << 8; } while(0) + +#define GPIO_WRITE_BITWISE(port, val, mask) \ + do { *(&(port) + (0x800/sizeof(long))) = ((mask) << 8) | (val); } while(0) + +/* GPIO Module 0 */ +#define GPIOA 0 +#define GPIOB 1 +#define GPIOC 2 +#define GPIOD 3 +/* GPIO Module 1 */ +#define GPIOE 4 +#define GPIOF 5 +#define GPIOG 6 +#define GPIOH 7 +/* GPIO Module 2 */ +#define GPIOI 8 +#define GPIOJ 9 +#define GPIOK 10 +#define GPIOL 11 + +#define GPIO_MODULE_NUM(gpio) ((gpio)>>2) +#define GPIO_MAP_ADDR(gpio) (GPIO_BASE_ADDR+(GPIO_MODULE_NUM(gpio)<<7)+(((gpio)&3)<<2)) +#define GPIO_ENABLE(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x00)) +#define GPIO_OUTPUT_EN(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x10)) +#define GPIO_OUTPUT_VAL(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x20)) +#define GPIO_INPUT_VAL(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x30)) +#define GPIO_INT_STAT(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x40)) +#define GPIO_INT_EN(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x50)) +#define GPIO_INT_LEV(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x60)) +#define GPIO_INT_CLR(gpio) (*(volatile unsigned long *)(GPIO_MAP_ADDR(gpio)+0x70)) +#define GPIO_HI_INT_MASK(gpio) (1ul << GPIO_MODULE_NUM(gpio)) /* Device initialization */ #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 @@ /* Messages from usb_tick and thread states */ enum { + USB_EXTRACTED = 0, /* Event+State */ USB_INSERTED, /* Event+State */ - USB_EXTRACTED, /* Event+State */ #if defined(HAVE_USB_POWER) || defined(USB_DETECT_BY_DRV) USB_POWERED, /* Event+State */ #endif @@ -135,6 +135,7 @@ bool usb_exclusive_storage(void); /* storage is available for usb */ #ifdef USB_FIREWIRE_HANDLING bool firewire_detect(void); +void usb_firewire_connect_event(void); #endif #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) GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); #endif timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0); - } #endif /* HAVE_HOTSWAP */ 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) } } +/* Read the immediate state of the cable from the PMIC */ +bool usb_plugged(void) +{ + return mc13783_read(MC13783_INTERRUPT_SENSE0) & MC13783_USB4V4S; +} + void usb_connect_event(void) { - uint32_t status = mc13783_read(MC13783_INTERRUPT_SENSE0); - usb_status = (status & MC13783_USB4V4S) ? - USB_INSERTED : USB_EXTRACTED; + int status = usb_plugged() ? USB_INSERTED : USB_EXTRACTED; + usb_status = status; /* Notify power that USB charging is potentially available */ - charger_usb_detect_event(usb_status); - usb_status_event(usb_status); + charger_usb_detect_event(status); + usb_status_event((status == USB_INSERTED) ? USB_POWERED : USB_UNPOWERED); } int usb_detect(void) @@ -68,12 +73,6 @@ int usb_detect(void) return usb_status; } -/* Read the immediate state of the cable from the PMIC */ -bool usb_plugged(void) -{ - return mc13783_read(MC13783_INTERRUPT_SENSE0) & MC13783_USB4V4S; -} - void usb_init_device(void) { /* Do one-time inits */ @@ -107,7 +106,7 @@ void usb_enable(bool on) void usb_attach(void) { - usb_enable(true); + usb_drv_attach(); } static void __attribute__((interrupt("IRQ"))) USB_OTG_HANDLER(void) @@ -122,3 +121,9 @@ void usb_drv_int_enable(bool enable) else avic_disable_int(USB_OTG); } + +/* Called during the bus reset interrupt when in detect mode */ +void usb_drv_usb_detect_event(void) +{ + usb_status_event(USB_INSERTED); +} 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 @@ #define USB_DRIVER_CLOSE #endif -/* Connect by events, not by tick polling */ -#define USB_STATUS_BY_EVENT - void usb_connect_event(void); void usb_init_device(void); int 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) { batt_threshold = BATT_FULL_VOLTAGE; /* Start with topped value. */ battery_voltage_sync(); -#if defined(USB_STATUS_BY_EVENT) && defined(USB_DETECT_BY_DRV) - /* Charger pin detect is USB pin detect */ - usb_connect_event(true); -#endif } static inline void charger_control(void) @@ -192,10 +188,6 @@ static inline void charger_unplugged(void) disable_charger(); if (charge_state >= CHARGE_STATE_ERROR) charge_state = DISCHARGING; /* Reset error */ -#if defined(USB_STATUS_BY_EVENT) && defined(USB_DETECT_BY_DRV) - /* Charger pin detect is USB pin detect */ - usb_connect_event(false); -#endif } /* 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 @@ #include "as3514.h" #include "ata-sd-target.h" #include "button-target.h" -#ifdef HAVE_USBSTACK +#include "usb-target.h" #include "usb_drv.h" -#endif #ifndef BOOTLOADER extern void TIMER1(void); @@ -42,51 +41,108 @@ void __attribute__((interrupt("IRQ"))) irq_handler(void) { if (CPU_INT_STAT & TIMER1_MASK) { TIMER1(); - } else if (CPU_INT_STAT & TIMER2_MASK) + } + else if (CPU_INT_STAT & TIMER2_MASK) { TIMER2(); + } +#ifdef HAVE_USBSTACK + /* Rather high priority - place near front */ + else if (CPU_INT_STAT & USB_MASK) { + usb_drv_int(); + } +#endif #if defined(IPOD_MINI) /* Mini 1st gen only, mini 2nd gen uses iPod 4G code */ - else if (CPU_HI_INT_STAT & GPIO0_MASK) - ipod_mini_button_int(); + else if (CPU_HI_INT_STAT & GPIO0_MASK) { + if ((GPIOA_INT_STAT & 0x3f) || (GPIOB_INT_STAT & 0x30)) + ipod_mini_button_int(); + if (GPIOC_INT_STAT & 0x02) + firewire_insert_int(); + if (GPIOD_INT_STAT & 0x08) + usb_insert_int(); + } +/* end IPOD_MINI */ #elif CONFIG_KEYPAD == IPOD_4G_PAD /* except Mini 1st gen, handled above */ - else if (CPU_HI_INT_STAT & I2C_MASK) + else if (CPU_HI_INT_STAT & I2C_MASK) { ipod_4g_button_int(); + } +#if defined(IPOD_COLOR) || defined(IPOD_MINI2G) || defined(IPOD_4G) + else if (CPU_HI_INT_STAT & GPIO0_MASK) { + if (GPIOC_INT_STAT & 0x02) + firewire_insert_int(); + if (GPIOD_INT_STAT & 0x08) + usb_insert_int(); + } +#elif defined(IPOD_NANO) || defined(IPOD_VIDEO) + else if (CPU_HI_INT_STAT & GPIO2_MASK) { + if (GPIOL_INT_STAT & 0x10) + usb_insert_int(); + } +#endif +/* end CONFIG_KEYPAD == IPOD_4G_PAD */ +#elif defined(IRIVER_H10) || defined(IRIVER_H10_5GB) + else if (CPU_HI_INT_STAT & GPIO2_MASK) { + if (GPIOL_INT_STAT & 0x04) + usb_insert_int(); + } +/* end IRIVER_H10 || IRIVER_H10_5GB */ #elif defined(SANSA_E200) -#ifdef HAVE_HOTSWAP else if (CPU_HI_INT_STAT & GPIO0_MASK) { +#ifdef HAVE_HOTSWAP if (GPIOA_INT_STAT & 0x80) microsd_int(); - } #endif + if (GPIOB_INT_STAT & 0x10) + usb_insert_int(); + } else if (CPU_HI_INT_STAT & GPIO1_MASK) { if (GPIOF_INT_STAT & 0xff) button_int(); if (GPIOH_INT_STAT & 0xc0) clickwheel_int(); } -#elif defined(SANSA_C200) && defined(HAVE_HOTSWAP) +/* end SANSA_E200 */ +#elif defined(SANSA_C200) + else if (CPU_HI_INT_STAT & GPIO1_MASK) { + if (GPIOH_INT_STAT & 0x02) + usb_insert_int(); + } +#ifdef HAVE_HOTSWAP else if (CPU_HI_INT_STAT & GPIO2_MASK) { if (GPIOL_INT_STAT & 0x08) microsd_int(); } +#endif +/* end SANSA_C200 */ #elif defined(MROBE_100) else if (CPU_HI_INT_STAT & GPIO0_MASK) { - if (GPIOD_INT_STAT & 0x2) + if (GPIOD_INT_STAT & 0x02) button_int(); - } + } + else if (CPU_HI_INT_STAT & GPIO2_MASK) { + if (GPIOL_INT_STAT & 0x04) + usb_insert_int(); + } +/* end MROBE_100 */ +#elif defined(PHILIPS_SA9200) + else if (CPU_HI_INT_STAT & GPIO1_MASK) { + if (GPIOF_INT_STAT & 0x80) + usb_insert_int(); + } +/* end PHILIPS_SA9200 */ #elif defined(PHILIPS_HDD1630) else if (CPU_HI_INT_STAT & GPIO0_MASK) { if (GPIOA_INT_STAT & 0x20) button_int(); - } + } + else if (CPU_HI_INT_STAT & GPIO1_MASK) { + if (GPIOE_INT_STAT & 0x04) + usb_insert_int(); + } +/* end PHILIPS_HDD1630 */ #endif #ifdef IPOD_ACCESSORY_PROTOCOL - else if (CPU_HI_INT_STAT & SER0_MASK) { - SERIAL0(); - } -#endif -#ifdef HAVE_USBSTACK - else if (CPU_INT_STAT & USB_MASK) { - usb_drv_int(); + else if (CPU_HI_INT_STAT & SER0_MASK) { + SERIAL0(); } #endif } else { @@ -437,8 +493,12 @@ void system_init(void) #endif /* BOOTLOADER */ } -void system_reboot(void) +void ICODE_ATTR system_reboot(void) { + disable_interrupt(IRQ_FIQ_STATUS); + CPU_INT_DIS = -1; + COP_INT_DIS = -1; + /* Reboot */ #if defined(SANSA_E200) || defined(SANSA_C200) || defined(PHILIPS_SA9200) 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) REG_ENDPOINTLISTADDR = (unsigned int)qh_array; REG_DEVICEADDR = 0; -#ifdef USB_DETECT_BY_DRV if (!attach) { /* enable RESET interrupt */ REG_USBINTR = USBINTR_RESET_EN; } else -#endif { /* enable USB interrupts */ REG_USBINTR = @@ -449,23 +447,17 @@ static void _usb_drv_init(bool attach) (void)attach; } -/** With USB_DETECT_BY_DRV, attach is distinct from init, otherwise eqivalent. **/ - -/* USB_DETECT_BY_DRV - enable bus reset detection only - * else fully enable driver */ void usb_drv_init(void) { _usb_drv_init(false); } -#ifdef USB_DETECT_BY_DRV /* fully enable driver */ void usb_drv_attach(void) { sleep(HZ/10); _usb_drv_init(true); } -#endif /* USB_DETECT_BY_DRV */ void usb_drv_exit(void) { @@ -513,7 +505,7 @@ void usb_drv_int(void) /* reset interrupt */ if (status & USBSTS_RESET) { REG_USBSTS = USBSTS_RESET; -#ifdef USB_DETECT_BY_DRV + if (UNLIKELY(usbintr == USBINTR_RESET_EN)) { /* USB detected - detach and inform */ usb_drv_stop(); @@ -523,7 +515,6 @@ void usb_drv_int(void) usb_drv_usb_detect_event(); } else -#endif { bus_reset(); 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 @@ #include "usb_core.h" #include "usb_drv.h" +#if defined(IPOD_4G) || defined(IPOD_COLOR) \ + || defined(IPOD_MINI) || defined(IPOD_MINI2G) + /* GPIO D bit 3 is usb detect */ +#define USB_GPIO GPIOD +#define USB_GPIO_MASK 0x08 +#define USB_GPIO_VAL 0x08 + +#elif defined(IPOD_NANO) || defined(IPOD_VIDEO) + /* GPIO L bit 4 is usb detect */ +#define USB_GPIO GPIOL +#define USB_GPIO_MASK 0x10 +#define USB_GPIO_VAL 0x10 + +#elif defined(SANSA_C200) + /* GPIO H bit 1 is usb/charger detect */ +#define USB_GPIO GPIOH +#define USB_GPIO_MASK 0x02 +#define USB_GPIO_VAL 0x02 + +#elif defined(SANSA_E200) + /* GPIO B bit 4 is usb/charger detect */ +#define USB_GPIO GPIOB +#define USB_GPIO_MASK 0x10 +#define USB_GPIO_VAL 0x10 + +#elif defined(IRIVER_H10) || defined(IRIVER_H10_5GB) || defined(MROBE_100) + /* GPIO L bit 2 is usb detect */ +#define USB_GPIO GPIOL +#define USB_GPIO_MASK 0x04 +#define USB_GPIO_VAL 0x04 + +#elif defined(PHILIPS_SA9200) + /* GPIO F bit 7 (low) is usb detect */ +#define USB_GPIO GPIOF +#define USB_GPIO_MASK 0x80 +#define USB_GPIO_VAL 0x00 + +#elif defined(PHILIPS_HDD1630) + /* GPIO E bit 2 is usb detect */ +#define USB_GPIO GPIOE +#define USB_GPIO_MASK 0x04 +#define USB_GPIO_VAL 0x04 +#else +#error No USB GPIO config specified +#endif + +#define USB_GPIO_ENABLE GPIO_ENABLE(USB_GPIO) +#define USB_GPIO_OUTPUT_EN GPIO_OUTPUT_EN(USB_GPIO) +#define USB_GPIO_INPUT_VAL GPIO_INPUT_VAL(USB_GPIO) +#define USB_GPIO_INT_EN GPIO_INT_EN(USB_GPIO) +#define USB_GPIO_INT_LEV GPIO_INT_LEV(USB_GPIO) +#define USB_GPIO_INT_CLR GPIO_INT_CLR(USB_GPIO) +#define USB_GPIO_HI_INT_MASK GPIO_HI_INT_MASK(USB_GPIO) + void usb_init_device(void) { /* enable usb module */ @@ -52,7 +106,10 @@ void usb_init_device(void) while ((inl(0x70000028) & 0x80) == 0); outl(inl(0x70000028) | 0x2, 0x70000028); udelay(100000); - + + /* Do one-time inits */ + usb_drv_startup(); + /* disable USB-devices until USB is detected via GPIO */ #ifndef BOOTLOADER /* Disabling USB0 in the bootloader makes the OF not load, @@ -63,17 +120,38 @@ void usb_init_device(void) DEV_INIT2 &= ~INIT_USB; #endif -#if defined(IPOD_COLOR) || defined(IPOD_4G) \ - || defined(IPOD_MINI) || defined(IPOD_MINI2G) + /* These set INV_LEV to the inserted level so it will fire if already + * inserted at the time they are enabled. */ +#ifdef USB_STATUS_BY_EVENT + GPIO_CLEAR_BITWISE(USB_GPIO_INT_EN, USB_GPIO_MASK); + GPIO_CLEAR_BITWISE(USB_GPIO_OUTPUT_EN, USB_GPIO_MASK); + GPIO_SET_BITWISE(USB_GPIO_ENABLE, USB_GPIO_MASK); + GPIO_WRITE_BITWISE(USB_GPIO_INT_LEV, USB_GPIO_VAL, USB_GPIO_MASK); + USB_GPIO_INT_CLR = USB_GPIO_MASK; + GPIO_SET_BITWISE(USB_GPIO_INT_EN, USB_GPIO_MASK); + CPU_HI_INT_EN = USB_GPIO_HI_INT_MASK; + +#ifdef USB_FIREWIRE_HANDLING /* GPIO C bit 1 is firewire detect */ - GPIOC_ENABLE |= 0x02; - GPIOC_OUTPUT_EN &= ~0x02; + GPIO_CLEAR_BITWISE(GPIOC_INT_EN, 0x02); + GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_EN, 0x02); + GPIO_SET_BITWISE(GPIOC_ENABLE, 0x02); + GPIO_WRITE_BITWISE(GPIOC_INT_LEV, 0x00, 0x02); + GPIOC_INT_CLR = 0x02; + GPIO_SET_BITWISE(GPIOC_INT_EN, 0x02); + CPU_HI_INT_EN = GPIO0_MASK; #endif - -#ifdef HAVE_USBSTACK - /* Do one-time inits */ - usb_drv_startup(); + CPU_INT_EN = HI_MASK; +#else + /* No interrupt - setup pin read only (BOOTLOADER) */ + GPIO_CLEAR_BITWISE(USB_GPIO_OUTPUT_EN, USB_GPIO_MASK); + GPIO_SET_BITWISE(USB_GPIO_ENABLE, USB_GPIO_MASK); +#ifdef USB_FIREWIRE_HANDLING + /* GPIO C bit 1 is firewire detect */ + GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_EN, 0x02); + GPIO_SET_BITWISE(GPIOC_ENABLE, 0x02); #endif +#endif /* USB_STATUS_BY_EVENT */ } void usb_enable(bool on) @@ -96,21 +174,27 @@ void usb_enable(bool on) void usb_attach(void) { -#ifdef USB_DETECT_BY_DRV usb_drv_attach(); -#else - usb_enable(true); -#endif } -#ifdef USB_DETECT_BY_DRV -/* Cannot tell charger pin from USB pin */ +#ifdef USB_STATUS_BY_EVENT +/* Cannot always tell power pin from USB pin */ static int usb_status = USB_EXTRACTED; -void usb_connect_event(bool inserted) +static int usb_timeout_event(struct timeout *tmo) +{ + usb_status_event(tmo->data == USB_GPIO_VAL ? USB_POWERED : USB_UNPOWERED); + return 0; +} + +void usb_insert_int(void) { - usb_status = inserted ? USB_INSERTED : USB_EXTRACTED; - usb_status_event(inserted ? USB_POWERED : USB_UNPOWERED); + static struct timeout usb_oneshot; + unsigned long val = USB_GPIO_INPUT_VAL & USB_GPIO_MASK; + usb_status = (val == USB_GPIO_VAL) ? USB_INSERTED : USB_EXTRACTED; + GPIO_WRITE_BITWISE(USB_GPIO_INT_LEV, val ^ USB_GPIO_MASK, USB_GPIO_MASK); + USB_GPIO_INT_CLR = USB_GPIO_MASK; + timeout_register(&usb_oneshot, usb_timeout_event, HZ/5, val); } /* Called during the bus reset interrupt when in detect mode */ @@ -118,51 +202,7 @@ void usb_drv_usb_detect_event(void) { usb_status_event(USB_INSERTED); } -#else /* !USB_DETECT_BY_DRV */ -static bool usb_pin_detect(void) -{ - bool retval = false; - -#if defined(IPOD_4G) || defined(IPOD_COLOR) \ - || defined(IPOD_MINI) || defined(IPOD_MINI2G) - /* GPIO D bit 3 is usb detect */ - if (GPIOD_INPUT_VAL & 0x08) - retval = true; - -#elif defined(IPOD_NANO) || defined(IPOD_VIDEO) - /* GPIO L bit 4 is usb detect */ - if (GPIOL_INPUT_VAL & 0x10) - retval = true; - -#elif defined(SANSA_C200) - /* GPIO H bit 1 is usb/charger detect */ - if (GPIOH_INPUT_VAL & 0x02) - retval = true; - -#elif defined(SANSA_E200) - /* GPIO B bit 4 is usb/charger detect */ - if (GPIOB_INPUT_VAL & 0x10) - retval = true; - -#elif defined(IRIVER_H10) || defined(IRIVER_H10_5GB) || defined(MROBE_100) - /* GPIO L bit 2 is usb detect */ - if (GPIOL_INPUT_VAL & 0x4) - retval = true; - -#elif defined(PHILIPS_SA9200) - /* GPIO F bit 7 is usb detect */ - if (!(GPIOF_INPUT_VAL & 0x80)) - retval = true; - -#elif defined(PHILIPS_HDD1630) - /* GPIO E bit 2 is usb detect */ - if (GPIOE_INPUT_VAL & 0x4) - retval = true; -#endif - - return retval; -} -#endif /* USB_DETECT_BY_DRV */ +#endif /* USB_STATUS_BY_EVENT */ void usb_drv_int_enable(bool enable) { @@ -178,27 +218,46 @@ void usb_drv_int_enable(bool enable) /* detect host or charger (INSERTED or EXTRACTED) */ int usb_detect(void) { -#ifdef USB_DETECT_BY_DRV +#ifdef USB_STATUS_BY_EVENT return usb_status; #else - if(usb_pin_detect()) { - return USB_INSERTED; - } - else { - return USB_EXTRACTED; - } + return ((USB_GPIO_INPUT_VAL & USB_GPIO_MASK) == USB_GPIO_VAL) ? + USB_INSERTED : USB_EXTRACTED; #endif } -#if defined(IPOD_COLOR) || defined(IPOD_4G) \ - || defined(IPOD_MINI) || defined(IPOD_MINI2G) +#ifdef USB_FIREWIRE_HANDLING +#ifdef USB_STATUS_BY_EVENT +static bool firewire_status = false; +#endif + bool firewire_detect(void) { +#ifdef USB_STATUS_BY_EVENT + return firewire_status; +#else /* GPIO C bit 1 is firewire detect */ - if (!(GPIOC_INPUT_VAL & 0x02)) - /* no charger detection needed for firewire */ - return true; - else - return false; -} + /* no charger detection needed for firewire */ + return (GPIOC_INPUT_VAL & 0x02) == 0x00; #endif +} + +#ifdef USB_STATUS_BY_EVENT +static int firewire_timeout_event(struct timeout *tmo) +{ + if (tmo->data == 0x00) + usb_firewire_connect_event(); + return 0; +} + +void firewire_insert_int(void) +{ + static struct timeout firewire_oneshot; + unsigned long val = GPIOC_INPUT_VAL & 0x02; + firewire_status = val == 0x00; + GPIO_WRITE_BITWISE(GPIOC_INT_LEV, val ^ 0x02, 0x02); + GPIOC_INT_CLR = 0x02; + timeout_register(&firewire_oneshot, firewire_timeout_event, HZ/5, val); +} +#endif /* USB_STATUS_BY_EVENT */ +#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 @@ #define USB_TARGET_H void usb_init_device(void); - -#ifndef BOOTLOADER -#if defined(SANSA_C200) || defined(SANSA_E200) -#define USB_STATUS_BY_EVENT /* No USB tick */ -void usb_connect_event(bool inserted); -#endif -#endif /* BOOTLOADER */ +void usb_insert_int(void); +void firewire_insert_int(void); #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) #ifdef USB_STATUS_BY_EVENT void usb_status_event(int current_status) { - /* Status should be USB_POWERED, USB_UNPOWERED, USB_INSERTED or - * USB_EXTRACTED. - * Caller isn't expected to filter for changes in status. */ + /* Caller isn't expected to filter for changes in status. + * current_status: + * USB_DETECT_BY_DRV: USB_POWERED, USB_UNPOWERED, USB_INSERTED (driver) + * else: USB_INSERTED, USB_EXTRACTED + */ if(usb_monitor_enabled) { int oldstatus = disable_irq_save(); /* Dual-use function */ @@ -435,16 +437,30 @@ void usb_status_event(int current_status) void usb_start_monitoring(void) { + int oldstatus = disable_irq_save(); /* Sync to event */ int status = usb_detect(); + + usb_monitor_enabled = true; + #ifdef USB_DETECT_BY_DRV - /* USB detection begins by USB_POWERED, not USB_INSERTED. If it is - * USB_EXTRACTED, then nothing changes and post will be skipped. */ - if(USB_INSERTED == status) - status = USB_POWERED; + status = (status == USB_INSERTED) ? USB_POWERED : USB_UNPOWERED; #endif - usb_monitor_enabled = true; usb_status_event(status); + +#ifdef USB_FIREWIRE_HANDLING + if (firewire_detect()) + usb_firewire_connect_event(); +#endif + + restore_irq(oldstatus); } + +#ifdef USB_FIREWIRE_HANDLING +void usb_firewire_connect_event(void) +{ + queue_post(&usb_queue, USB_REQUEST_REBOOT, 0); +} +#endif /* USB_FIREWIRE_HANDLING */ #else /* !USB_STATUS_BY_EVENT */ static void usb_tick(void) { @@ -522,7 +538,11 @@ void usb_init(void) { /* We assume that the USB cable is extracted */ usb_state = USB_EXTRACTED; +#ifdef USB_DETECT_BY_DRV + last_usb_status = USB_UNPOWERED; +#else last_usb_status = USB_EXTRACTED; +#endif usb_monitor_enabled = false; #ifdef HAVE_USBSTACK -- cgit v1.2.3