diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2009-01-19 13:41:25 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2009-01-19 13:41:25 +0000 |
commit | 616c98b38f6ddac0ac3dde8ec0fa248f835717e2 (patch) | |
tree | 5eeeabb85fbefa162a438edca88611c1bc688269 /firmware | |
parent | cef6399c4c3bcaa35733bdab8b9016b66b71a6f0 (diff) | |
download | rockbox-616c98b38f6ddac0ac3dde8ec0fa248f835717e2.tar.gz rockbox-616c98b38f6ddac0ac3dde8ec0fa248f835717e2.zip |
USB detection changes. c200/e200: Consider USB to be powered when charger is plugged but detect USB connection by bus reset. When received, disconnect and restart the driver fully enabled. imx31: Fix hack used to make initial connect succeeded-- set PHY type before initial reset. General: Move some target code out of usb-drv-arc.c and implement it in respective usb sources and CPU headers so things stay clean.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19797 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/export/config-c200.h | 3 | ||||
-rw-r--r-- | firmware/export/config-e200.h | 3 | ||||
-rw-r--r-- | firmware/export/config-gigabeat-s.h | 6 | ||||
-rwxr-xr-x | firmware/export/imx31l.h | 8 | ||||
-rw-r--r-- | firmware/export/pp5020.h | 7 | ||||
-rw-r--r-- | firmware/export/usb.h | 8 | ||||
-rw-r--r-- | firmware/export/usb_core.h | 10 | ||||
-rw-r--r-- | firmware/export/usb_drv.h | 6 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/system-target.h | 8 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/usb-imx31.c | 35 | ||||
-rw-r--r-- | firmware/target/arm/powermgmt-ascodec.c | 10 | ||||
-rw-r--r-- | firmware/target/arm/usb-drv-arc.c | 186 | ||||
-rw-r--r-- | firmware/target/arm/usb-fw-pp502x.c | 49 | ||||
-rw-r--r-- | firmware/target/arm/usb-target.h | 7 | ||||
-rw-r--r-- | firmware/usb.c | 65 | ||||
-rw-r--r-- | firmware/usbstack/usb_core.c | 6 | ||||
-rw-r--r-- | firmware/usbstack/usb_storage.c | 2 |
17 files changed, 276 insertions, 143 deletions
diff --git a/firmware/export/config-c200.h b/firmware/export/config-c200.h index d68d21455f..ff260dc956 100644 --- a/firmware/export/config-c200.h +++ b/firmware/export/config-c200.h | |||
@@ -180,6 +180,9 @@ | |||
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 | ||
183 | #define USB_VENDOR_ID 0x0781 | 186 | #define USB_VENDOR_ID 0x0781 |
184 | #define USB_PRODUCT_ID 0x7450 | 187 | #define USB_PRODUCT_ID 0x7450 |
185 | 188 | ||
diff --git a/firmware/export/config-e200.h b/firmware/export/config-e200.h index 2be64d95cc..7b27391c64 100644 --- a/firmware/export/config-e200.h +++ b/firmware/export/config-e200.h | |||
@@ -177,6 +177,9 @@ | |||
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 | ||
180 | #define USB_VENDOR_ID 0x0781 | 183 | #define USB_VENDOR_ID 0x0781 |
181 | #define USB_PRODUCT_ID 0x7421 | 184 | #define USB_PRODUCT_ID 0x7421 |
182 | 185 | ||
diff --git a/firmware/export/config-gigabeat-s.h b/firmware/export/config-gigabeat-s.h index 64f351c1ce..9e6029f00b 100644 --- a/firmware/export/config-gigabeat-s.h +++ b/firmware/export/config-gigabeat-s.h | |||
@@ -176,10 +176,12 @@ | |||
176 | /* USB On-the-go */ | 176 | /* USB On-the-go */ |
177 | #define CONFIG_USBOTG USBOTG_ARC | 177 | #define CONFIG_USBOTG USBOTG_ARC |
178 | 178 | ||
179 | /* enable these for the experimental usb stack */ | 179 | /* enable these for the usb stack */ |
180 | #define USE_ROCKBOX_USB | 180 | #define USE_ROCKBOX_USB |
181 | #define HAVE_USBSTACK | 181 | #define HAVE_USBSTACK |
182 | #define USB_STORAGE | 182 | #define USB_STORAGE |
183 | /* usb stack and driver settings */ | ||
184 | #define USB_PORTSCX_PHY_TYPE PORTSCX_PTS_ULPI | ||
183 | #define USB_VENDOR_ID 0x0930 | 185 | #define USB_VENDOR_ID 0x0930 |
184 | #define USB_PRODUCT_ID 0x0010 | 186 | #define USB_PRODUCT_ID 0x0010 |
185 | 187 | ||
@@ -201,7 +203,7 @@ | |||
201 | /* Offset ( in the firmware file's header ) to the real data */ | 203 | /* Offset ( in the firmware file's header ) to the real data */ |
202 | #define FIRMWARE_OFFSET_FILE_DATA 8 | 204 | #define FIRMWARE_OFFSET_FILE_DATA 8 |
203 | 205 | ||
204 | #define HAVE_SERIAL | 206 | //#define HAVE_SERIAL |
205 | #define HAVE_VOLUME_IN_LIST | 207 | #define HAVE_VOLUME_IN_LIST |
206 | 208 | ||
207 | /*Remove Comments from UART_INT to enable the UART interrupts,*/ | 209 | /*Remove Comments from UART_INT to enable the UART interrupts,*/ |
diff --git a/firmware/export/imx31l.h b/firmware/export/imx31l.h index b572c788a9..b55a56b105 100755 --- a/firmware/export/imx31l.h +++ b/firmware/export/imx31l.h | |||
@@ -36,7 +36,11 @@ | |||
36 | #define FRAME_SIZE (240*320*2) | 36 | #define FRAME_SIZE (240*320*2) |
37 | 37 | ||
38 | #define DEVBSS_ATTR __attribute__((section(".devbss"),nocommon)) | 38 | #define DEVBSS_ATTR __attribute__((section(".devbss"),nocommon)) |
39 | #define QHARRAY_ATTR __attribute__((section(".qharray"),nocommon)) | 39 | /* USBOTG */ |
40 | #define USB_QHARRAY_ATTR __attribute__((section(".qharray"),nocommon,aligned(2048))) | ||
41 | #define USB_NUM_ENDPOINTS 8 | ||
42 | #define USB_DEVBSS_ATTR DEVBSS_ATTR | ||
43 | #define USB_BASE OTG_BASE_ADDR | ||
40 | 44 | ||
41 | /* | 45 | /* |
42 | * AIPS 1 | 46 | * AIPS 1 |
@@ -1580,6 +1584,4 @@ | |||
1580 | #define UART_FIFO_CTRL 0x881 | 1584 | #define UART_FIFO_CTRL 0x881 |
1581 | #define TIMEOUT 1000 | 1585 | #define TIMEOUT 1000 |
1582 | 1586 | ||
1583 | #define USB_BASE OTG_BASE_ADDR | ||
1584 | |||
1585 | #endif /* __IMX31L_H__ */ | 1587 | #endif /* __IMX31L_H__ */ |
diff --git a/firmware/export/pp5020.h b/firmware/export/pp5020.h index b4919a219e..0f622a907d 100644 --- a/firmware/export/pp5020.h +++ b/firmware/export/pp5020.h | |||
@@ -23,7 +23,12 @@ | |||
23 | 23 | ||
24 | /* All info gleaned and/or copied from the iPodLinux project. */ | 24 | /* All info gleaned and/or copied from the iPodLinux project. */ |
25 | 25 | ||
26 | #define QHARRAY_ATTR __attribute__((section(".qharray"),nocommon)) | 26 | /* USBOTG */ |
27 | #define USB_NUM_ENDPOINTS 3 | ||
28 | /* This needs to be 2048 byte aligned, but USB_QHARRAY_ATTR should take care | ||
29 | * of that */ | ||
30 | #define USB_QHARRAY_ATTR __attribute__((section(".qharray"),nocommon,aligned(4))) | ||
31 | #define USB_DEVBSS_ATTR IBSS_ATTR | ||
27 | 32 | ||
28 | /* DRAM starts at 0x10000000, but in Rockbox we remap it to 0x00000000 */ | 33 | /* DRAM starts at 0x10000000, but in Rockbox we remap it to 0x00000000 */ |
29 | #define DRAM_START 0x10000000 | 34 | #define DRAM_START 0x10000000 |
diff --git a/firmware/export/usb.h b/firmware/export/usb.h index a6cfad5889..0a0539a622 100644 --- a/firmware/export/usb.h +++ b/firmware/export/usb.h | |||
@@ -33,8 +33,11 @@ | |||
33 | enum { | 33 | enum { |
34 | USB_INSERTED, /* Event+State */ | 34 | USB_INSERTED, /* Event+State */ |
35 | USB_EXTRACTED, /* Event+State */ | 35 | USB_EXTRACTED, /* Event+State */ |
36 | #ifdef HAVE_USB_POWER | 36 | #if defined(HAVE_USB_POWER) || defined(USB_DETECT_BY_DRV) |
37 | USB_POWERED, /* State */ | 37 | USB_POWERED, /* Event+State */ |
38 | #endif | ||
39 | #ifdef USB_DETECT_BY_DRV | ||
40 | USB_UNPOWERED, /* Event */ | ||
38 | #endif | 41 | #endif |
39 | #ifdef HAVE_LCD_BITMAP | 42 | #ifdef HAVE_LCD_BITMAP |
40 | USB_SCREENDUMP, /* State */ | 43 | USB_SCREENDUMP, /* State */ |
@@ -107,6 +110,7 @@ struct usb_transfer_completion_event_data | |||
107 | 110 | ||
108 | void usb_init(void); | 111 | void usb_init(void); |
109 | void usb_enable(bool on); | 112 | void usb_enable(bool on); |
113 | void usb_attach(void); | ||
110 | void usb_start_monitoring(void); | 114 | void usb_start_monitoring(void); |
111 | void usb_close(void); | 115 | void usb_close(void); |
112 | void usb_acknowledge(long id); | 116 | void usb_acknowledge(long id); |
diff --git a/firmware/export/usb_core.h b/firmware/export/usb_core.h index 7af8e43c8d..d0c8270d93 100644 --- a/firmware/export/usb_core.h +++ b/firmware/export/usb_core.h | |||
@@ -7,7 +7,7 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2007 by Bjรถrn Stenberg | 10 | * Copyright (C) 2007 by Bj๖rn Stenberg |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 13 | * modify it under the terms of the GNU General Public License |
@@ -35,14 +35,6 @@ | |||
35 | 35 | ||
36 | /* endpoints */ | 36 | /* endpoints */ |
37 | #define EP_CONTROL 0 | 37 | #define EP_CONTROL 0 |
38 | #if CONFIG_CPU == IMX31L | ||
39 | #define NUM_ENDPOINTS 8 | ||
40 | #define USBDEVBSS_ATTR DEVBSS_ATTR | ||
41 | #else | ||
42 | #define USBDEVBSS_ATTR IBSS_ATTR | ||
43 | #define NUM_ENDPOINTS 3 | ||
44 | #endif | ||
45 | |||
46 | extern int usb_max_pkt_size; | 38 | extern int usb_max_pkt_size; |
47 | 39 | ||
48 | struct usb_class_driver; | 40 | struct usb_class_driver; |
diff --git a/firmware/export/usb_drv.h b/firmware/export/usb_drv.h index 3d2e689050..23f6f4ce2a 100644 --- a/firmware/export/usb_drv.h +++ b/firmware/export/usb_drv.h | |||
@@ -24,9 +24,13 @@ | |||
24 | #include "kernel.h" | 24 | #include "kernel.h" |
25 | 25 | ||
26 | void usb_drv_startup(void); | 26 | void usb_drv_startup(void); |
27 | void usb_drv_usb_detect_event(void); /* Target implemented */ | ||
28 | void usb_drv_int_enable(bool enable); /* Target implemented */ | ||
29 | void usb_drv_reset(void); | ||
27 | void usb_drv_init(void); | 30 | void usb_drv_init(void); |
28 | void usb_drv_exit(void); | 31 | void usb_drv_exit(void); |
29 | void usb_drv_int(void); | 32 | void usb_drv_attach(void); |
33 | void usb_drv_int(void); /* Call from target INT handler */ | ||
30 | void usb_drv_stall(int endpoint, bool stall,bool in); | 34 | void usb_drv_stall(int endpoint, bool stall,bool in); |
31 | bool usb_drv_stalled(int endpoint,bool in); | 35 | bool usb_drv_stalled(int endpoint,bool in); |
32 | int usb_drv_send(int endpoint, void* ptr, int length); | 36 | int usb_drv_send(int endpoint, void* ptr, int length); |
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-target.h b/firmware/target/arm/imx31/gigabeat-s/system-target.h index 847e6cfc51..b99b31d1b4 100644 --- a/firmware/target/arm/imx31/gigabeat-s/system-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/system-target.h | |||
@@ -31,6 +31,14 @@ | |||
31 | #define CPUFREQ_MAX CPU_FREQ | 31 | #define CPUFREQ_MAX CPU_FREQ |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | /* For USB driver - no accuracy assurance */ | ||
35 | static inline void udelay(unsigned int usecs) | ||
36 | { | ||
37 | unsigned int x; | ||
38 | for (x = 0; x < 300*usecs; x++) | ||
39 | asm volatile (""); | ||
40 | } | ||
41 | |||
34 | #if 0 | 42 | #if 0 |
35 | static inline void udelay(unsigned int usecs) | 43 | static inline void udelay(unsigned int usecs) |
36 | { | 44 | { |
diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c b/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c index cd8b513ecd..c0d7cb8d2a 100644 --- a/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "usb-target.h" | 29 | #include "usb-target.h" |
30 | #include "clkctl-imx31.h" | 30 | #include "clkctl-imx31.h" |
31 | #include "power-imx31.h" | 31 | #include "power-imx31.h" |
32 | #include "avic-imx31.h" | ||
32 | #include "mc13783.h" | 33 | #include "mc13783.h" |
33 | 34 | ||
34 | static int usb_status = USB_EXTRACTED; | 35 | static int usb_status = USB_EXTRACTED; |
@@ -75,11 +76,7 @@ bool usb_plugged(void) | |||
75 | 76 | ||
76 | void usb_init_device(void) | 77 | void usb_init_device(void) |
77 | { | 78 | { |
78 | imx31_clkctl_module_clock_gating(CG_USBOTG, CGM_ON_ALL); | 79 | /* Do one-time inits */ |
79 | |||
80 | enable_transceiver(true); | ||
81 | |||
82 | /* Module will be turned off later after firmware init */ | ||
83 | usb_drv_startup(); | 80 | usb_drv_startup(); |
84 | 81 | ||
85 | /* Initially poll */ | 82 | /* Initially poll */ |
@@ -91,19 +88,37 @@ void usb_init_device(void) | |||
91 | 88 | ||
92 | void usb_enable(bool on) | 89 | void usb_enable(bool on) |
93 | { | 90 | { |
91 | /* Module clock should be on since since this could be called with | ||
92 | * OFF initially and writing module registers would hardlock otherwise. */ | ||
93 | imx31_clkctl_module_clock_gating(CG_USBOTG, CGM_ON_ALL); | ||
94 | enable_transceiver(true); | ||
95 | |||
94 | if (on) | 96 | if (on) |
95 | { | 97 | { |
96 | imx31_clkctl_module_clock_gating(CG_USBOTG, CGM_ON_ALL); | ||
97 | enable_transceiver(true); | ||
98 | usb_core_init(); | 98 | usb_core_init(); |
99 | } | 99 | } |
100 | else | 100 | else |
101 | { | 101 | { |
102 | /* Module clock should be on since this could be called first */ | ||
103 | imx31_clkctl_module_clock_gating(CG_USBOTG, CGM_ON_ALL); | ||
104 | enable_transceiver(true); | ||
105 | usb_core_exit(); | 102 | usb_core_exit(); |
106 | enable_transceiver(false); | 103 | enable_transceiver(false); |
107 | imx31_clkctl_module_clock_gating(CG_USBOTG, CGM_OFF); | 104 | imx31_clkctl_module_clock_gating(CG_USBOTG, CGM_OFF); |
108 | } | 105 | } |
109 | } | 106 | } |
107 | |||
108 | void usb_attach(void) | ||
109 | { | ||
110 | usb_enable(true); | ||
111 | } | ||
112 | |||
113 | static void __attribute__((interrupt("IRQ"))) USB_OTG_HANDLER(void) | ||
114 | { | ||
115 | usb_drv_int(); /* Call driver handler */ | ||
116 | } | ||
117 | |||
118 | void usb_drv_int_enable(bool enable) | ||
119 | { | ||
120 | if (enable) | ||
121 | avic_enable_int(USB_OTG, IRQ, 7, USB_OTG_HANDLER); | ||
122 | else | ||
123 | avic_disable_int(USB_OTG); | ||
124 | } | ||
diff --git a/firmware/target/arm/powermgmt-ascodec.c b/firmware/target/arm/powermgmt-ascodec.c index ab9fd7b490..6ee6209823 100644 --- a/firmware/target/arm/powermgmt-ascodec.c +++ b/firmware/target/arm/powermgmt-ascodec.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include "adc.h" | 27 | #include "adc.h" |
28 | #include "powermgmt.h" | 28 | #include "powermgmt.h" |
29 | #include "power.h" | 29 | #include "power.h" |
30 | #include "usb-target.h" | ||
31 | #include "usb.h" | ||
30 | 32 | ||
31 | /*=========================================================================== | 33 | /*=========================================================================== |
32 | * These parameters may be defined per target: | 34 | * These parameters may be defined per target: |
@@ -132,6 +134,10 @@ static inline void charger_plugged(void) | |||
132 | { | 134 | { |
133 | batt_threshold = BATT_FULL_VOLTAGE; /* Start with topped value. */ | 135 | batt_threshold = BATT_FULL_VOLTAGE; /* Start with topped value. */ |
134 | 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 | ||
135 | } | 141 | } |
136 | 142 | ||
137 | static inline void charger_control(void) | 143 | static inline void charger_control(void) |
@@ -186,6 +192,10 @@ static inline void charger_unplugged(void) | |||
186 | disable_charger(); | 192 | disable_charger(); |
187 | if (charge_state >= CHARGE_STATE_ERROR) | 193 | if (charge_state >= CHARGE_STATE_ERROR) |
188 | charge_state = DISCHARGING; /* Reset error */ | 194 | 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 | ||
189 | } | 199 | } |
190 | 200 | ||
191 | /* Main charging algorithm - called from powermgmt.c */ | 201 | /* Main charging algorithm - called from powermgmt.c */ |
diff --git a/firmware/target/arm/usb-drv-arc.c b/firmware/target/arm/usb-drv-arc.c index 1cdc0f9e90..99845c2a49 100644 --- a/firmware/target/arm/usb-drv-arc.c +++ b/firmware/target/arm/usb-drv-arc.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * | 9 | * |
10 | * Driver for ARC USBOTG Device Controller | 10 | * Driver for ARC USBOTG Device Controller |
11 | * | 11 | * |
12 | * Copyright (C) 2007 by Bjรถrn Stenberg | 12 | * Copyright (C) 2007 by Bj๖rn Stenberg |
13 | * | 13 | * |
14 | * This program is free software; you can redistribute it and/or | 14 | * This program is free software; you can redistribute it and/or |
15 | * modify it under the terms of the GNU General Public License | 15 | * modify it under the terms of the GNU General Public License |
@@ -33,11 +33,6 @@ | |||
33 | //#define LOGF_ENABLE | 33 | //#define LOGF_ENABLE |
34 | #include "logf.h" | 34 | #include "logf.h" |
35 | 35 | ||
36 | #if CONFIG_CPU == IMX31L | ||
37 | #include "avic-imx31.h" | ||
38 | static void __attribute__((interrupt("IRQ"))) USB_OTG_HANDLER(void); | ||
39 | #endif | ||
40 | |||
41 | /* USB device mode registers (Little Endian) */ | 36 | /* USB device mode registers (Little Endian) */ |
42 | 37 | ||
43 | #define REG_ID (*(volatile unsigned int *)(USB_BASE+0x000)) | 38 | #define REG_ID (*(volatile unsigned int *)(USB_BASE+0x000)) |
@@ -326,8 +321,8 @@ struct transfer_descriptor { | |||
326 | unsigned int reserved; | 321 | unsigned int reserved; |
327 | } __attribute__ ((packed)); | 322 | } __attribute__ ((packed)); |
328 | 323 | ||
329 | static struct transfer_descriptor td_array[NUM_ENDPOINTS*2] | 324 | static struct transfer_descriptor td_array[USB_NUM_ENDPOINTS*2] |
330 | USBDEVBSS_ATTR __attribute__((aligned(32))); | 325 | USB_DEVBSS_ATTR __attribute__((aligned(32))); |
331 | 326 | ||
332 | /* manual: 32.13.1 Endpoint Queue Head (dQH) */ | 327 | /* manual: 32.13.1 Endpoint Queue Head (dQH) */ |
333 | struct queue_head { | 328 | struct queue_head { |
@@ -342,17 +337,10 @@ struct queue_head { | |||
342 | unsigned int wait; /* for softwate use, indicates if the transfer is blocking */ | 337 | unsigned int wait; /* for softwate use, indicates if the transfer is blocking */ |
343 | } __attribute__((packed)); | 338 | } __attribute__((packed)); |
344 | 339 | ||
345 | #if CONFIG_CPU == IMX31L | 340 | static struct queue_head qh_array[USB_NUM_ENDPOINTS*2] |
346 | static struct queue_head qh_array[NUM_ENDPOINTS*2] | 341 | USB_QHARRAY_ATTR; |
347 | QHARRAY_ATTR __attribute__((aligned (2048))); | ||
348 | #else | ||
349 | /* This still needs to be 2048 byte aligned, but QHARRAY_ATTR should take | ||
350 | care of that */ | ||
351 | static struct queue_head qh_array[NUM_ENDPOINTS*2] | ||
352 | QHARRAY_ATTR __attribute__((aligned (4))); | ||
353 | #endif | ||
354 | 342 | ||
355 | static struct wakeup transfer_completion_signal[NUM_ENDPOINTS*2] | 343 | static struct wakeup transfer_completion_signal[USB_NUM_ENDPOINTS*2] |
356 | SHAREDBSS_ATTR; | 344 | SHAREDBSS_ATTR; |
357 | 345 | ||
358 | static const unsigned int pipe2mask[] = { | 346 | static const unsigned int pipe2mask[] = { |
@@ -363,7 +351,7 @@ static const unsigned int pipe2mask[] = { | |||
363 | 0x10, 0x100000, | 351 | 0x10, 0x100000, |
364 | }; | 352 | }; |
365 | 353 | ||
366 | static char ep_allocation[NUM_ENDPOINTS]; | 354 | static char ep_allocation[USB_NUM_ENDPOINTS]; |
367 | 355 | ||
368 | /*-------------------------------------------------------------------------*/ | 356 | /*-------------------------------------------------------------------------*/ |
369 | static void transfer_completed(void); | 357 | static void transfer_completed(void); |
@@ -378,52 +366,46 @@ static void init_control_queue_heads(void); | |||
378 | static void init_bulk_queue_heads(void); | 366 | static void init_bulk_queue_heads(void); |
379 | static void init_endpoints(void); | 367 | static void init_endpoints(void); |
380 | /*-------------------------------------------------------------------------*/ | 368 | /*-------------------------------------------------------------------------*/ |
381 | 369 | static void usb_drv_stop(void) | |
382 | bool usb_drv_powered(void) | ||
383 | { | 370 | { |
384 | return (REG_OTGSC & OTGSC_B_SESSION_VALID) ? true : false; | 371 | /* disable interrupts */ |
372 | REG_USBINTR = 0; | ||
373 | /* stop usb controller (disconnect) */ | ||
374 | REG_USBCMD &= ~USBCMD_RUN; | ||
385 | } | 375 | } |
386 | 376 | ||
387 | /* One-time driver startup init */ | 377 | void usb_drv_reset(void) |
388 | void usb_drv_startup(void) | ||
389 | { | 378 | { |
390 | #if CONFIG_CPU == IMX31L && defined(BOOTLOADER) | 379 | int oldlevel = disable_irq_save(); |
391 | /* This is the bootloader - activate the OTG controller or cold | ||
392 | * connect later could/will fail */ | ||
393 | REG_USBCMD &= ~USBCMD_RUN; | 380 | REG_USBCMD &= ~USBCMD_RUN; |
381 | restore_irq(oldlevel); | ||
394 | 382 | ||
383 | #ifdef USB_PORTSCX_PHY_TYPE | ||
384 | /* If a PHY type is specified, set it now */ | ||
385 | REG_PORTSC1 = (REG_PORTSC1 & ~PORTSCX_PHY_TYPE_SEL) | USB_PORTSCX_PHY_TYPE; | ||
386 | #endif | ||
395 | sleep(HZ/20); | 387 | sleep(HZ/20); |
396 | REG_USBCMD |= USBCMD_CTRL_RESET; | 388 | REG_USBCMD |= USBCMD_CTRL_RESET; |
397 | while (REG_USBCMD & USBCMD_CTRL_RESET); | 389 | while (REG_USBCMD & USBCMD_CTRL_RESET); |
390 | } | ||
398 | 391 | ||
399 | /* Set to ULPI */ | 392 | /* One-time driver startup init */ |
400 | REG_PORTSC1 = (REG_PORTSC1 & ~PORTSCX_PHY_TYPE_SEL) | PORTSCX_PTS_ULPI; | 393 | void usb_drv_startup(void) |
401 | sleep(HZ/10); | 394 | { |
402 | #endif | ||
403 | |||
404 | /* Initialize all the signal objects once */ | 395 | /* Initialize all the signal objects once */ |
405 | int i; | 396 | int i; |
406 | for(i=0;i<NUM_ENDPOINTS*2;i++) { | 397 | for(i=0;i<USB_NUM_ENDPOINTS*2;i++) { |
407 | wakeup_init(&transfer_completion_signal[i]); | 398 | wakeup_init(&transfer_completion_signal[i]); |
408 | } | 399 | } |
409 | } | 400 | } |
410 | 401 | ||
411 | /* manual: 32.14.1 Device Controller Initialization */ | 402 | /* manual: 32.14.1 Device Controller Initialization */ |
412 | void usb_drv_init(void) | 403 | static void _usb_drv_init(bool attach) |
413 | { | 404 | { |
414 | REG_USBCMD &= ~USBCMD_RUN; | 405 | usb_drv_reset(); |
415 | sleep(HZ/20); | ||
416 | REG_USBCMD |= USBCMD_CTRL_RESET; | ||
417 | while (REG_USBCMD & USBCMD_CTRL_RESET); | ||
418 | |||
419 | 406 | ||
420 | REG_USBMODE = USBMODE_CTRL_MODE_DEVICE; | 407 | REG_USBMODE = USBMODE_CTRL_MODE_DEVICE; |
421 | 408 | ||
422 | #if CONFIG_CPU == IMX31L | ||
423 | /* Set to ULPI */ | ||
424 | REG_PORTSC1 = (REG_PORTSC1 & ~PORTSCX_PHY_TYPE_SEL) | PORTSCX_PTS_ULPI; | ||
425 | #endif | ||
426 | |||
427 | #ifdef USB_NO_HIGH_SPEED | 409 | #ifdef USB_NO_HIGH_SPEED |
428 | /* Force device to full speed */ | 410 | /* Force device to full speed */ |
429 | /* See 32.9.5.9.2 */ | 411 | /* See 32.9.5.9.2 */ |
@@ -436,69 +418,76 @@ void usb_drv_init(void) | |||
436 | REG_ENDPOINTLISTADDR = (unsigned int)qh_array; | 418 | REG_ENDPOINTLISTADDR = (unsigned int)qh_array; |
437 | REG_DEVICEADDR = 0; | 419 | REG_DEVICEADDR = 0; |
438 | 420 | ||
439 | /* enable USB interrupts */ | 421 | #ifdef USB_DETECT_BY_DRV |
440 | REG_USBINTR = | 422 | if (!attach) { |
441 | USBINTR_INT_EN | | 423 | /* enable RESET interrupt */ |
442 | USBINTR_ERR_INT_EN | | 424 | REG_USBINTR = USBINTR_RESET_EN; |
443 | USBINTR_PTC_DETECT_EN | | 425 | } |
444 | USBINTR_RESET_EN | | 426 | else |
445 | USBINTR_SYS_ERR_EN; | ||
446 | |||
447 | #if CONFIG_CPU == IMX31L | ||
448 | avic_enable_int(USB_OTG, IRQ, 7, USB_OTG_HANDLER); | ||
449 | #else | ||
450 | /* enable USB IRQ in CPU */ | ||
451 | CPU_INT_EN = USB_MASK; | ||
452 | #endif | 427 | #endif |
428 | { | ||
429 | /* enable USB interrupts */ | ||
430 | REG_USBINTR = | ||
431 | USBINTR_INT_EN | | ||
432 | USBINTR_ERR_INT_EN | | ||
433 | USBINTR_PTC_DETECT_EN | | ||
434 | USBINTR_RESET_EN; | ||
435 | } | ||
436 | |||
437 | usb_drv_int_enable(true); | ||
453 | 438 | ||
454 | /* go go go */ | 439 | /* go go go */ |
455 | REG_USBCMD |= USBCMD_RUN; | 440 | REG_USBCMD |= USBCMD_RUN; |
456 | 441 | ||
457 | |||
458 | logf("usb_drv_init() finished"); | 442 | logf("usb_drv_init() finished"); |
459 | logf("usb id %x", REG_ID); | 443 | logf("usb id %x", REG_ID); |
460 | logf("usb dciversion %x", REG_DCIVERSION); | 444 | logf("usb dciversion %x", REG_DCIVERSION); |
461 | logf("usb dccparams %x", REG_DCCPARAMS); | 445 | logf("usb dccparams %x", REG_DCCPARAMS); |
462 | 446 | ||
463 | /* now a bus reset will occur. see bus_reset() */ | 447 | /* now a bus reset will occur. see bus_reset() */ |
448 | (void)attach; | ||
464 | } | 449 | } |
465 | 450 | ||
466 | void usb_drv_exit(void) | 451 | /** With USB_DETECT_BY_DRV, attach is distinct from init, otherwise eqivalent. **/ |
452 | |||
453 | /* USB_DETECT_BY_DRV - enable bus reset detection only | ||
454 | * else fully enable driver */ | ||
455 | void usb_drv_init(void) | ||
467 | { | 456 | { |
468 | /* disable interrupts */ | 457 | _usb_drv_init(false); |
469 | REG_USBINTR = 0; | 458 | } |
470 | 459 | ||
471 | /* stop usb controller */ | 460 | #ifdef USB_DETECT_BY_DRV |
472 | REG_USBCMD &= ~USBCMD_RUN; | 461 | /* fully enable driver */ |
462 | void usb_drv_attach(void) | ||
463 | { | ||
464 | sleep(HZ/10); | ||
465 | _usb_drv_init(true); | ||
466 | } | ||
467 | #endif /* USB_DETECT_BY_DRV */ | ||
468 | |||
469 | void usb_drv_exit(void) | ||
470 | { | ||
471 | usb_drv_stop(); | ||
473 | 472 | ||
474 | /* TODO : is one of these needed to save power ? | 473 | /* TODO : is one of these needed to save power ? |
475 | REG_PORTSC1 |= PORTSCX_PHY_LOW_POWER_SPD; | 474 | REG_PORTSC1 |= PORTSCX_PHY_LOW_POWER_SPD; |
476 | REG_USBCMD |= USBCMD_CTRL_RESET; | 475 | REG_USBCMD |= USBCMD_CTRL_RESET; |
477 | */ | 476 | */ |
478 | 477 | ||
479 | #if CONFIG_CPU == IMX31L | 478 | usb_drv_int_enable(false); |
480 | avic_disable_int(USB_OTG); | ||
481 | #else | ||
482 | CPU_INT_DIS = USB_MASK; | ||
483 | #endif | ||
484 | |||
485 | cancel_cpu_boost(); | ||
486 | } | 479 | } |
487 | 480 | ||
488 | #if CONFIG_CPU == IMX31L | ||
489 | static void __attribute__((interrupt("IRQ"))) USB_OTG_HANDLER(void) | ||
490 | #else | ||
491 | void usb_drv_int(void) | 481 | void usb_drv_int(void) |
492 | #endif | ||
493 | { | 482 | { |
494 | unsigned int status = REG_USBSTS; | 483 | unsigned int usbintr = REG_USBINTR; /* Only watch enabled ints */ |
484 | unsigned int status = REG_USBSTS & usbintr; | ||
495 | 485 | ||
496 | #if 0 | 486 | #if 0 |
497 | if (status & USBSTS_INT) logf("int: usb ioc"); | 487 | if (status & USBSTS_INT) logf("int: usb ioc"); |
498 | if (status & USBSTS_ERR) logf("int: usb err"); | 488 | if (status & USBSTS_ERR) logf("int: usb err"); |
499 | if (status & USBSTS_PORT_CHANGE) logf("int: portchange"); | 489 | if (status & USBSTS_PORT_CHANGE) logf("int: portchange"); |
500 | if (status & USBSTS_RESET) logf("int: reset"); | 490 | if (status & USBSTS_RESET) logf("int: reset"); |
501 | if (status & USBSTS_SYS_ERR) logf("int: syserr"); | ||
502 | #endif | 491 | #endif |
503 | 492 | ||
504 | /* usb transaction interrupt */ | 493 | /* usb transaction interrupt */ |
@@ -523,8 +512,18 @@ void usb_drv_int(void) | |||
523 | /* reset interrupt */ | 512 | /* reset interrupt */ |
524 | if (status & USBSTS_RESET) { | 513 | if (status & USBSTS_RESET) { |
525 | REG_USBSTS = USBSTS_RESET; | 514 | REG_USBSTS = USBSTS_RESET; |
526 | bus_reset(); | 515 | #ifdef USB_DETECT_BY_DRV |
527 | usb_core_bus_reset(); /* tell mom */ | 516 | if (UNLIKELY(usbintr == USBINTR_RESET_EN)) { |
517 | /* USB detected - detach and inform */ | ||
518 | usb_drv_stop(); | ||
519 | usb_drv_usb_detect_event(); | ||
520 | } | ||
521 | else | ||
522 | #endif | ||
523 | { | ||
524 | bus_reset(); | ||
525 | usb_core_bus_reset(); /* tell mom */ | ||
526 | } | ||
528 | } | 527 | } |
529 | 528 | ||
530 | /* port change */ | 529 | /* port change */ |
@@ -588,7 +587,14 @@ int usb_drv_port_speed(void) | |||
588 | 587 | ||
589 | bool usb_drv_connected(void) | 588 | bool usb_drv_connected(void) |
590 | { | 589 | { |
591 | return ((REG_PORTSC1 & PORTSCX_CURRENT_CONNECT_STATUS) !=0); | 590 | return (REG_PORTSC1 & |
591 | (PORTSCX_PORT_SUSPEND | PORTSCX_CURRENT_CONNECT_STATUS)) | ||
592 | == PORTSCX_CURRENT_CONNECT_STATUS; | ||
593 | } | ||
594 | |||
595 | bool usb_drv_powered(void) | ||
596 | { | ||
597 | return (REG_OTGSC & OTGSC_B_SESSION_VALID) ? true : false; | ||
592 | } | 598 | } |
593 | 599 | ||
594 | void usb_drv_set_address(int address) | 600 | void usb_drv_set_address(int address) |
@@ -628,10 +634,7 @@ void usb_drv_set_test_mode(int mode) | |||
628 | REG_PORTSC1 |= PORTSCX_PTC_FORCE_EN; | 634 | REG_PORTSC1 |= PORTSCX_PTC_FORCE_EN; |
629 | break; | 635 | break; |
630 | } | 636 | } |
631 | REG_USBCMD &= ~USBCMD_RUN; | 637 | usb_drv_reset(); |
632 | sleep(HZ/20); | ||
633 | REG_USBCMD |= USBCMD_CTRL_RESET; | ||
634 | while (REG_USBCMD & USBCMD_CTRL_RESET); | ||
635 | REG_USBCMD |= USBCMD_RUN; | 638 | REG_USBCMD |= USBCMD_RUN; |
636 | } | 639 | } |
637 | 640 | ||
@@ -735,7 +738,7 @@ void usb_drv_cancel_all_transfers(void) | |||
735 | while (REG_ENDPTFLUSH); | 738 | while (REG_ENDPTFLUSH); |
736 | 739 | ||
737 | memset(td_array, 0, sizeof td_array); | 740 | memset(td_array, 0, sizeof td_array); |
738 | for(i=0;i<NUM_ENDPOINTS*2;i++) { | 741 | for(i=0;i<USB_NUM_ENDPOINTS*2;i++) { |
739 | if(qh_array[i].wait) { | 742 | if(qh_array[i].wait) { |
740 | qh_array[i].wait=0; | 743 | qh_array[i].wait=0; |
741 | qh_array[i].status=DTD_STATUS_HALTED; | 744 | qh_array[i].status=DTD_STATUS_HALTED; |
@@ -750,7 +753,7 @@ int usb_drv_request_endpoint(int dir) | |||
750 | 753 | ||
751 | bit=(dir & USB_DIR_IN)? 2:1; | 754 | bit=(dir & USB_DIR_IN)? 2:1; |
752 | 755 | ||
753 | for (i=1; i < NUM_ENDPOINTS; i++) { | 756 | for (i=1; i < USB_NUM_ENDPOINTS; i++) { |
754 | if((ep_allocation[i] & bit)!=0) | 757 | if((ep_allocation[i] & bit)!=0) |
755 | continue; | 758 | continue; |
756 | ep_allocation[i] |= bit; | 759 | ep_allocation[i] |= bit; |
@@ -819,7 +822,7 @@ static void transfer_completed(void) | |||
819 | unsigned int mask = REG_ENDPTCOMPLETE; | 822 | unsigned int mask = REG_ENDPTCOMPLETE; |
820 | REG_ENDPTCOMPLETE = mask; | 823 | REG_ENDPTCOMPLETE = mask; |
821 | 824 | ||
822 | for (ep=0; ep<NUM_ENDPOINTS; ep++) { | 825 | for (ep=0; ep<USB_NUM_ENDPOINTS; ep++) { |
823 | int dir; | 826 | int dir; |
824 | for (dir=0; dir<2; dir++) { | 827 | for (dir=0; dir<2; dir++) { |
825 | int pipe = ep * 2 + dir; | 828 | int pipe = ep * 2 + dir; |
@@ -869,13 +872,8 @@ static void bus_reset(void) | |||
869 | logf("usb: double reset"); | 872 | logf("usb: double reset"); |
870 | return; | 873 | return; |
871 | } | 874 | } |
872 | #if CONFIG_CPU == IMX31L | 875 | |
873 | int x; | ||
874 | for (x = 0; x < 30000; x++) | ||
875 | asm volatile (""); | ||
876 | #else | ||
877 | udelay(100); | 876 | udelay(100); |
878 | #endif | ||
879 | } | 877 | } |
880 | if (REG_ENDPTPRIME) { | 878 | if (REG_ENDPTPRIME) { |
881 | logf("usb: short reset timeout"); | 879 | logf("usb: short reset timeout"); |
@@ -917,7 +915,7 @@ static void init_bulk_queue_heads(void) | |||
917 | /* TODO: this should take ep_allocation into account */ | 915 | /* TODO: this should take ep_allocation into account */ |
918 | 916 | ||
919 | /*** bulk ***/ | 917 | /*** bulk ***/ |
920 | for(i=1;i<NUM_ENDPOINTS;i++) { | 918 | for(i=1;i<USB_NUM_ENDPOINTS;i++) { |
921 | qh_array[i*2].max_pkt_length = rx_packetsize << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL; | 919 | qh_array[i*2].max_pkt_length = rx_packetsize << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL; |
922 | qh_array[i*2].dtd.next_td_ptr = QH_NEXT_TERMINATE; | 920 | qh_array[i*2].dtd.next_td_ptr = QH_NEXT_TERMINATE; |
923 | qh_array[i*2+1].max_pkt_length = tx_packetsize << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL; | 921 | qh_array[i*2+1].max_pkt_length = tx_packetsize << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL; |
@@ -930,7 +928,7 @@ static void init_endpoints(void) | |||
930 | int i; | 928 | int i; |
931 | /* TODO: this should take ep_allocation into account */ | 929 | /* TODO: this should take ep_allocation into account */ |
932 | /* bulk */ | 930 | /* bulk */ |
933 | for(i=1;i<NUM_ENDPOINTS;i++) { | 931 | for(i=1;i<USB_NUM_ENDPOINTS;i++) { |
934 | REG_ENDPTCTRL(i) = | 932 | REG_ENDPTCTRL(i) = |
935 | EPCTRL_RX_DATA_TOGGLE_RST | EPCTRL_RX_ENABLE | | 933 | EPCTRL_RX_DATA_TOGGLE_RST | EPCTRL_RX_ENABLE | |
936 | EPCTRL_TX_DATA_TOGGLE_RST | EPCTRL_TX_ENABLE | | 934 | EPCTRL_TX_DATA_TOGGLE_RST | EPCTRL_TX_ENABLE | |
diff --git a/firmware/target/arm/usb-fw-pp502x.c b/firmware/target/arm/usb-fw-pp502x.c index a41ef9a598..8a6d78675f 100644 --- a/firmware/target/arm/usb-fw-pp502x.c +++ b/firmware/target/arm/usb-fw-pp502x.c | |||
@@ -25,13 +25,13 @@ | |||
25 | ****************************************************************************/ | 25 | ****************************************************************************/ |
26 | #include "config.h" | 26 | #include "config.h" |
27 | #include "system.h" | 27 | #include "system.h" |
28 | #include "usb-target.h" | ||
28 | #include "usb.h" | 29 | #include "usb.h" |
29 | #include "button.h" | 30 | #include "button.h" |
30 | #include "ata.h" | 31 | #include "ata.h" |
31 | #include "string.h" | 32 | #include "string.h" |
32 | #include "usb_core.h" | 33 | #include "usb_core.h" |
33 | #include "usb_drv.h" | 34 | #include "usb_drv.h" |
34 | #include "usb-target.h" | ||
35 | 35 | ||
36 | void usb_init_device(void) | 36 | void usb_init_device(void) |
37 | { | 37 | { |
@@ -94,6 +94,31 @@ void usb_enable(bool on) | |||
94 | } | 94 | } |
95 | } | 95 | } |
96 | 96 | ||
97 | void usb_attach(void) | ||
98 | { | ||
99 | #ifdef USB_DETECT_BY_DRV | ||
100 | usb_drv_attach(); | ||
101 | #else | ||
102 | usb_enable(true); | ||
103 | #endif | ||
104 | } | ||
105 | |||
106 | #ifdef USB_DETECT_BY_DRV | ||
107 | /* Cannot tell charger pin from USB pin */ | ||
108 | static int usb_status = USB_EXTRACTED; | ||
109 | |||
110 | void usb_connect_event(bool inserted) | ||
111 | { | ||
112 | usb_status = inserted ? USB_INSERTED : USB_EXTRACTED; | ||
113 | usb_status_event(inserted ? USB_POWERED : USB_UNPOWERED); | ||
114 | } | ||
115 | |||
116 | /* Called during the bus reset interrupt when in detect mode */ | ||
117 | void usb_drv_usb_detect_event(void) | ||
118 | { | ||
119 | usb_status_event(USB_INSERTED); | ||
120 | } | ||
121 | #else /* !USB_DETECT_BY_DRV */ | ||
97 | static bool usb_pin_detect(void) | 122 | static bool usb_pin_detect(void) |
98 | { | 123 | { |
99 | bool retval = false; | 124 | bool retval = false; |
@@ -110,12 +135,12 @@ static bool usb_pin_detect(void) | |||
110 | retval = true; | 135 | retval = true; |
111 | 136 | ||
112 | #elif defined(SANSA_C200) | 137 | #elif defined(SANSA_C200) |
113 | /* GPIO H bit 1 is usb detect */ | 138 | /* GPIO H bit 1 is usb/charger detect */ |
114 | if (GPIOH_INPUT_VAL & 0x02) | 139 | if (GPIOH_INPUT_VAL & 0x02) |
115 | retval = true; | 140 | retval = true; |
116 | 141 | ||
117 | #elif defined(SANSA_E200) | 142 | #elif defined(SANSA_E200) |
118 | /* GPIO B bit 4 is usb detect */ | 143 | /* GPIO B bit 4 is usb/charger detect */ |
119 | if (GPIOB_INPUT_VAL & 0x10) | 144 | if (GPIOB_INPUT_VAL & 0x10) |
120 | retval = true; | 145 | retval = true; |
121 | 146 | ||
@@ -137,16 +162,32 @@ static bool usb_pin_detect(void) | |||
137 | 162 | ||
138 | return retval; | 163 | return retval; |
139 | } | 164 | } |
165 | #endif /* USB_DETECT_BY_DRV */ | ||
140 | 166 | ||
141 | /* detect host or charger (INSERTED or POWERED) */ | 167 | void usb_drv_int_enable(bool enable) |
168 | { | ||
169 | /* enable/disable USB IRQ in CPU */ | ||
170 | if(enable) { | ||
171 | CPU_INT_EN = USB_MASK; | ||
172 | } | ||
173 | else { | ||
174 | CPU_INT_DIS = USB_MASK; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /* detect host or charger (INSERTED or EXTRACTED) */ | ||
142 | int usb_detect(void) | 179 | int usb_detect(void) |
143 | { | 180 | { |
181 | #ifdef USB_DETECT_BY_DRV | ||
182 | return usb_status; | ||
183 | #else | ||
144 | if(usb_pin_detect()) { | 184 | if(usb_pin_detect()) { |
145 | return USB_INSERTED; | 185 | return USB_INSERTED; |
146 | } | 186 | } |
147 | else { | 187 | else { |
148 | return USB_EXTRACTED; | 188 | return USB_EXTRACTED; |
149 | } | 189 | } |
190 | #endif | ||
150 | } | 191 | } |
151 | 192 | ||
152 | #if defined(IPOD_COLOR) || defined(IPOD_4G) \ | 193 | #if defined(IPOD_COLOR) || defined(IPOD_4G) \ |
diff --git a/firmware/target/arm/usb-target.h b/firmware/target/arm/usb-target.h index cdf6776cc1..913ad805ce 100644 --- a/firmware/target/arm/usb-target.h +++ b/firmware/target/arm/usb-target.h | |||
@@ -23,4 +23,11 @@ | |||
23 | 23 | ||
24 | void usb_init_device(void); | 24 | void usb_init_device(void); |
25 | 25 | ||
26 | #ifndef BOOTLOADER | ||
27 | #if defined(SANSA_C200) || defined(SANSA_E200) | ||
28 | #define USB_STATUS_BY_EVENT /* No USB tick */ | ||
29 | void usb_connect_event(bool inserted); | ||
30 | #endif | ||
31 | #endif /* BOOTLOADER */ | ||
32 | |||
26 | #endif | 33 | #endif |
diff --git a/firmware/usb.c b/firmware/usb.c index 918d9802a3..10a7ae1bff 100644 --- a/firmware/usb.c +++ b/firmware/usb.c | |||
@@ -34,11 +34,11 @@ | |||
34 | #include "disk.h" | 34 | #include "disk.h" |
35 | #include "panic.h" | 35 | #include "panic.h" |
36 | #include "lcd.h" | 36 | #include "lcd.h" |
37 | #include "usb-target.h" | ||
37 | #include "usb.h" | 38 | #include "usb.h" |
38 | #include "button.h" | 39 | #include "button.h" |
39 | #include "sprintf.h" | 40 | #include "sprintf.h" |
40 | #include "string.h" | 41 | #include "string.h" |
41 | #include "usb-target.h" | ||
42 | #ifdef HAVE_USBSTACK | 42 | #ifdef HAVE_USBSTACK |
43 | #include "usb_core.h" | 43 | #include "usb_core.h" |
44 | #endif | 44 | #endif |
@@ -129,11 +129,13 @@ static inline void usb_slave_mode(bool on) | |||
129 | #ifdef HAVE_PRIORITY_SCHEDULING | 129 | #ifdef HAVE_PRIORITY_SCHEDULING |
130 | thread_set_priority(THREAD_ID_CURRENT, PRIORITY_REALTIME); | 130 | thread_set_priority(THREAD_ID_CURRENT, PRIORITY_REALTIME); |
131 | #endif | 131 | #endif |
132 | usb_enable(true); | 132 | usb_attach(); |
133 | } | 133 | } |
134 | else /* usb_state == USB_INSERTED (only!) */ | 134 | else /* usb_state == USB_INSERTED (only!) */ |
135 | { | 135 | { |
136 | #ifndef USB_DETECT_BY_DRV | ||
136 | usb_enable(false); | 137 | usb_enable(false); |
138 | #endif | ||
137 | #ifdef HAVE_PRIORITY_SCHEDULING | 139 | #ifdef HAVE_PRIORITY_SCHEDULING |
138 | thread_set_priority(THREAD_ID_CURRENT, PRIORITY_SYSTEM); | 140 | thread_set_priority(THREAD_ID_CURRENT, PRIORITY_SYSTEM); |
139 | #endif | 141 | #endif |
@@ -234,6 +236,26 @@ static void usb_thread(void) | |||
234 | (struct usb_transfer_completion_event_data*)ev.data); | 236 | (struct usb_transfer_completion_event_data*)ev.data); |
235 | break; | 237 | break; |
236 | #endif | 238 | #endif |
239 | #ifdef USB_DETECT_BY_DRV | ||
240 | /* In this case, these events the handle cable insertion USB | ||
241 | * driver determines INSERTED/EXTRACTED state. */ | ||
242 | case USB_POWERED: | ||
243 | /* Set the state to USB_POWERED for now and enable the driver | ||
244 | * to detect a bus reset only. If a bus reset is detected, | ||
245 | * USB_INSERTED will be received. */ | ||
246 | usb_state = USB_POWERED; | ||
247 | usb_enable(true); | ||
248 | break; | ||
249 | |||
250 | case USB_UNPOWERED: | ||
251 | usb_enable(false); | ||
252 | /* This part shouldn't be obligatory for anything that can | ||
253 | * reliably detect removal of the data lines. USB_EXTRACTED | ||
254 | * could be posted on that event while bus power remains | ||
255 | * available. */ | ||
256 | queue_post(&usb_queue, USB_EXTRACTED, 0); | ||
257 | break; | ||
258 | #endif /* USB_DETECT_BY_DRV */ | ||
237 | case USB_INSERTED: | 259 | case USB_INSERTED: |
238 | #ifdef HAVE_LCD_BITMAP | 260 | #ifdef HAVE_LCD_BITMAP |
239 | if(do_screendump_instead_of_usb) | 261 | if(do_screendump_instead_of_usb) |
@@ -244,14 +266,14 @@ static void usb_thread(void) | |||
244 | } | 266 | } |
245 | #endif | 267 | #endif |
246 | #ifdef HAVE_USB_POWER | 268 | #ifdef HAVE_USB_POWER |
247 | if (usb_power_button()) | 269 | if(usb_power_button()) |
248 | { | 270 | { |
249 | /* Only charging is desired */ | 271 | /* Only charging is desired */ |
250 | usb_state = USB_POWERED; | 272 | usb_state = USB_POWERED; |
251 | #ifdef HAVE_USBSTACK | 273 | #ifdef HAVE_USBSTACK |
252 | usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, false); | 274 | usb_core_enable_driver(USB_DRIVER_MASS_STORAGE, false); |
253 | usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, true); | 275 | usb_core_enable_driver(USB_DRIVER_CHARGING_ONLY, true); |
254 | usb_enable(true); | 276 | usb_attach(); |
255 | #endif | 277 | #endif |
256 | break; | 278 | break; |
257 | } | 279 | } |
@@ -272,7 +294,7 @@ static void usb_thread(void) | |||
272 | 294 | ||
273 | if(!exclusive_storage_access) | 295 | if(!exclusive_storage_access) |
274 | { | 296 | { |
275 | usb_enable(true); | 297 | usb_attach(); |
276 | break; | 298 | break; |
277 | } | 299 | } |
278 | #endif /* HAVE_USBSTACK */ | 300 | #endif /* HAVE_USBSTACK */ |
@@ -304,7 +326,7 @@ static void usb_thread(void) | |||
304 | usb_state = USB_EXTRACTED; | 326 | usb_state = USB_EXTRACTED; |
305 | break; /* Connected for screendump only */ | 327 | break; /* Connected for screendump only */ |
306 | } | 328 | } |
307 | #endif /* HAVE_LCD_BITMAP */ | 329 | #endif |
308 | #ifndef HAVE_USBSTACK /* Stack must undo this if POWERED state was transitional */ | 330 | #ifndef HAVE_USBSTACK /* Stack must undo this if POWERED state was transitional */ |
309 | #ifdef HAVE_USB_POWER | 331 | #ifdef HAVE_USB_POWER |
310 | if(usb_state == USB_POWERED) | 332 | if(usb_state == USB_POWERED) |
@@ -312,7 +334,7 @@ static void usb_thread(void) | |||
312 | usb_state = USB_EXTRACTED; | 334 | usb_state = USB_EXTRACTED; |
313 | break; | 335 | break; |
314 | } | 336 | } |
315 | #endif /* HAVE_USB_POWER */ | 337 | #endif |
316 | #endif /* HAVE_USBSTACK */ | 338 | #endif /* HAVE_USBSTACK */ |
317 | if(usb_state == USB_INSERTED) | 339 | if(usb_state == USB_INSERTED) |
318 | { | 340 | { |
@@ -324,9 +346,11 @@ static void usb_thread(void) | |||
324 | 346 | ||
325 | usb_state = USB_EXTRACTED; | 347 | usb_state = USB_EXTRACTED; |
326 | #ifdef HAVE_USBSTACK | 348 | #ifdef HAVE_USBSTACK |
327 | if (!exclusive_storage_access) | 349 | if(!exclusive_storage_access) |
328 | { | 350 | { |
351 | #ifndef USB_DETECT_BY_DRV /* Disabled handling USB_UNPOWERED */ | ||
329 | usb_enable(false); | 352 | usb_enable(false); |
353 | #endif | ||
330 | break; | 354 | break; |
331 | } | 355 | } |
332 | 356 | ||
@@ -392,19 +416,34 @@ static void usb_thread(void) | |||
392 | #ifdef USB_STATUS_BY_EVENT | 416 | #ifdef USB_STATUS_BY_EVENT |
393 | void usb_status_event(int current_status) | 417 | void usb_status_event(int current_status) |
394 | { | 418 | { |
395 | /* Status should be USB_INSERTED or USB_EXTRACTED. | 419 | /* Status should be USB_POWERED, USB_UNPOWERED, USB_INSERTED or |
420 | * USB_EXTRACTED. | ||
396 | * Caller isn't expected to filter for changes in status. */ | 421 | * Caller isn't expected to filter for changes in status. */ |
397 | if (usb_monitor_enabled && last_usb_status != current_status) | 422 | if(usb_monitor_enabled) |
398 | { | 423 | { |
399 | last_usb_status = current_status; | 424 | int oldstatus = disable_irq_save(); /* Dual-use function */ |
400 | queue_post(&usb_queue, current_status, 0); | 425 | |
426 | if(last_usb_status != current_status) | ||
427 | { | ||
428 | last_usb_status = current_status; | ||
429 | queue_post(&usb_queue, current_status, 0); | ||
430 | } | ||
431 | |||
432 | restore_irq(oldstatus); | ||
401 | } | 433 | } |
402 | } | 434 | } |
403 | 435 | ||
404 | void usb_start_monitoring(void) | 436 | void usb_start_monitoring(void) |
405 | { | 437 | { |
438 | int status = usb_detect(); | ||
439 | #ifdef USB_DETECT_BY_DRV | ||
440 | /* USB detection begins by USB_POWERED, not USB_INSERTED. If it is | ||
441 | * USB_EXTRACTED, then nothing changes and post will be skipped. */ | ||
442 | if(USB_INSERTED == status) | ||
443 | status = USB_POWERED; | ||
444 | #endif | ||
406 | usb_monitor_enabled = true; | 445 | usb_monitor_enabled = true; |
407 | usb_status_event(usb_detect()); | 446 | usb_status_event(status); |
408 | } | 447 | } |
409 | #else /* !USB_STATUS_BY_EVENT */ | 448 | #else /* !USB_STATUS_BY_EVENT */ |
410 | static void usb_tick(void) | 449 | static void usb_tick(void) |
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index 50c9d8589c..5fac5d3815 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c | |||
@@ -175,7 +175,7 @@ static struct | |||
175 | completion_handler_t completion_handler[2]; | 175 | completion_handler_t completion_handler[2]; |
176 | control_handler_t control_handler[2]; | 176 | control_handler_t control_handler[2]; |
177 | struct usb_transfer_completion_event_data completion_event; | 177 | struct usb_transfer_completion_event_data completion_event; |
178 | } ep_data[NUM_ENDPOINTS]; | 178 | } ep_data[USB_NUM_ENDPOINTS]; |
179 | 179 | ||
180 | static struct usb_class_driver drivers[USB_NUM_DRIVERS] = | 180 | static struct usb_class_driver drivers[USB_NUM_DRIVERS] = |
181 | { | 181 | { |
@@ -240,7 +240,7 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] = | |||
240 | 240 | ||
241 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req); | 241 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req); |
242 | 242 | ||
243 | static unsigned char response_data[256] USBDEVBSS_ATTR; | 243 | static unsigned char response_data[256] USB_DEVBSS_ATTR; |
244 | 244 | ||
245 | 245 | ||
246 | static short hex[16] = {'0','1','2','3','4','5','6','7', | 246 | static short hex[16] = {'0','1','2','3','4','5','6','7', |
@@ -476,7 +476,7 @@ static void allocate_interfaces_and_endpoints(void) | |||
476 | 476 | ||
477 | memset(ep_data,0,sizeof(ep_data)); | 477 | memset(ep_data,0,sizeof(ep_data)); |
478 | 478 | ||
479 | for (i = 0; i < NUM_ENDPOINTS; i++) { | 479 | for (i = 0; i < USB_NUM_ENDPOINTS; i++) { |
480 | usb_drv_release_endpoint(i | USB_DIR_OUT); | 480 | usb_drv_release_endpoint(i | USB_DIR_OUT); |
481 | usb_drv_release_endpoint(i | USB_DIR_IN); | 481 | usb_drv_release_endpoint(i | USB_DIR_IN); |
482 | } | 482 | } |
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c index a70681d3e0..e2d58cf0a9 100644 --- a/firmware/usbstack/usb_storage.c +++ b/firmware/usbstack/usb_storage.c | |||
@@ -401,7 +401,7 @@ void usb_storage_init_connection(void) | |||
401 | #if CONFIG_CPU == IMX31L || CONFIG_USBOTG == USBOTG_ISP1583 || \ | 401 | #if CONFIG_CPU == IMX31L || CONFIG_USBOTG == USBOTG_ISP1583 || \ |
402 | defined(CPU_TCC77X) || defined(CPU_TCC780X) | 402 | defined(CPU_TCC77X) || defined(CPU_TCC780X) |
403 | static unsigned char _transfer_buffer[BUFFER_SIZE*2] | 403 | static unsigned char _transfer_buffer[BUFFER_SIZE*2] |
404 | USBDEVBSS_ATTR __attribute__((aligned(32))); | 404 | USB_DEVBSS_ATTR __attribute__((aligned(32))); |
405 | tb.transfer_buffer = (void *)_transfer_buffer; | 405 | tb.transfer_buffer = (void *)_transfer_buffer; |
406 | #else | 406 | #else |
407 | /* TODO : check if bufsize is at least 32K ? */ | 407 | /* TODO : check if bufsize is at least 32K ? */ |