diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2013-08-11 19:21:24 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2013-08-11 19:21:24 +0200 |
commit | 737dafe7dfbc6c1e3dc54d8685bc5dffbcf13342 (patch) | |
tree | 39f60d0aa4a9fe315ce96ea93066c91b1b794991 /firmware/target/arm | |
parent | 1b1692ff06a563db90e812a4edf8c1434bc4976d (diff) | |
download | rockbox-737dafe7dfbc6c1e3dc54d8685bc5dffbcf13342.tar.gz rockbox-737dafe7dfbc6c1e3dc54d8685bc5dffbcf13342.zip |
Revert "rk27xx: implement usb driver"
This reverts commit 310f9e068d58d3113358e86d6dd239500cdd11c4.
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/rk27xx/usb-drv-rk27xx.c | 714 | ||||
-rw-r--r-- | firmware/target/arm/rk27xx/usb-rk27xx.c | 14 |
2 files changed, 285 insertions, 443 deletions
diff --git a/firmware/target/arm/rk27xx/usb-drv-rk27xx.c b/firmware/target/arm/rk27xx/usb-drv-rk27xx.c index af613e7024..9380f54193 100644 --- a/firmware/target/arm/rk27xx/usb-drv-rk27xx.c +++ b/firmware/target/arm/rk27xx/usb-drv-rk27xx.c | |||
@@ -5,9 +5,9 @@ | |||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | ||
8 | * | 9 | * |
9 | * Copyright (C) 2011 by Marcin Bukat | 10 | * Copyright (C) 2011 by Marcin Bukat |
10 | * Copyright (C) 2012 by Amaury Pouly | ||
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 |
@@ -28,12 +28,13 @@ | |||
28 | #include "kernel.h" | 28 | #include "kernel.h" |
29 | #include "panic.h" | 29 | #include "panic.h" |
30 | 30 | ||
31 | //#include "usb-s3c6400x.h" | ||
32 | |||
31 | #include "usb_ch9.h" | 33 | #include "usb_ch9.h" |
32 | #include "usb_core.h" | 34 | #include "usb_core.h" |
33 | #include <inttypes.h> | 35 | #include <inttypes.h> |
34 | #include "power.h" | 36 | #include "power.h" |
35 | 37 | ||
36 | /*#define LOGF_ENABLE*/ | ||
37 | #include "logf.h" | 38 | #include "logf.h" |
38 | 39 | ||
39 | typedef volatile uint32_t reg32; | 40 | typedef volatile uint32_t reg32; |
@@ -58,16 +59,6 @@ typedef volatile uint32_t reg32; | |||
58 | #define IIN_DMAINCTL(ep_num) (*(reg32*)(AHB0_UDC+0x84+0x38*((ep_num/3)-1))) | 59 | #define IIN_DMAINCTL(ep_num) (*(reg32*)(AHB0_UDC+0x84+0x38*((ep_num/3)-1))) |
59 | #define IIN_DMAINLMADDR(ep_num) (*(reg32*)(AHB0_UDC+0x88+0x38*((ep_num/3)-1))) | 60 | #define IIN_DMAINLMADDR(ep_num) (*(reg32*)(AHB0_UDC+0x88+0x38*((ep_num/3)-1))) |
60 | 61 | ||
61 | #define USB_FULL_SPEED 0 | ||
62 | #define USB_HIGH_SPEED 1 | ||
63 | |||
64 | /* max allowed packet size definitions */ | ||
65 | #define CTL_MAX_SIZE 64 | ||
66 | #define BLK_HS_MAX_SIZE 512 | ||
67 | #define BLK_FS_MAX_SIZE 64 | ||
68 | #define INT_HS_MAX_SIZE 1024 | ||
69 | #define INT_FS_MAX_SIZE 64 | ||
70 | |||
71 | #ifdef LOGF_ENABLE | 62 | #ifdef LOGF_ENABLE |
72 | #define XFER_DIR_STR(dir) ((dir) ? "IN" : "OUT") | 63 | #define XFER_DIR_STR(dir) ((dir) ? "IN" : "OUT") |
73 | #define XFER_TYPE_STR(type) \ | 64 | #define XFER_TYPE_STR(type) \ |
@@ -80,7 +71,6 @@ typedef volatile uint32_t reg32; | |||
80 | struct endpoint_t { | 71 | struct endpoint_t { |
81 | const int type; /* EP type */ | 72 | const int type; /* EP type */ |
82 | const int dir; /* DIR_IN/DIR_OUT */ | 73 | const int dir; /* DIR_IN/DIR_OUT */ |
83 | const unsigned int intr_mask; | ||
84 | bool allocated; /* flag to mark EPs taken */ | 74 | bool allocated; /* flag to mark EPs taken */ |
85 | volatile void *buf; /* tx/rx buffer address */ | 75 | volatile void *buf; /* tx/rx buffer address */ |
86 | volatile int len; /* size of the transfer (bytes) */ | 76 | volatile int len; /* size of the transfer (bytes) */ |
@@ -90,33 +80,30 @@ struct endpoint_t { | |||
90 | }; | 80 | }; |
91 | 81 | ||
92 | static struct endpoint_t ctrlep[2] = { | 82 | static struct endpoint_t ctrlep[2] = { |
93 | {USB_ENDPOINT_XFER_CONTROL, DIR_OUT, 0, true, NULL, 0, 0, true, {0, 0, 0}}, | 83 | {USB_ENDPOINT_XFER_CONTROL, DIR_OUT, true, NULL, 0, 0, true, {0, 0, 0}}, |
94 | {USB_ENDPOINT_XFER_CONTROL, DIR_IN, 0, true, NULL, 0, 0, true, {0, 0, 0}} | 84 | {USB_ENDPOINT_XFER_CONTROL, DIR_IN, true, NULL, 0, 0, true, {0, 0, 0}} |
95 | }; | 85 | }; |
96 | 86 | ||
97 | static struct endpoint_t endpoints[16] = { | 87 | static struct endpoint_t endpoints[16] = { |
98 | {USB_ENDPOINT_XFER_CONTROL, 3, 0, true, NULL, 0, 0, true, {0, 0, 0}}, /* stub */ | 88 | {USB_ENDPOINT_XFER_CONTROL, 3, true, NULL, 0, 0, true, {0, 0, 0}}, /* stub */ |
99 | {USB_ENDPOINT_XFER_BULK, DIR_OUT, BOUT1_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT1 */ | 89 | {USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT1 */ |
100 | {USB_ENDPOINT_XFER_BULK, DIR_IN, BIN2_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN2 */ | 90 | {USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN2 */ |
101 | {USB_ENDPOINT_XFER_INT, DIR_IN, IIN3_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN3 */ | 91 | {USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN3 */ |
102 | {USB_ENDPOINT_XFER_BULK, DIR_OUT, BOUT4_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT4 */ | 92 | {USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT4 */ |
103 | {USB_ENDPOINT_XFER_BULK, DIR_IN, BIN5_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN5 */ | 93 | {USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN5 */ |
104 | {USB_ENDPOINT_XFER_INT, DIR_IN, IIN6_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN6 */ | 94 | {USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN6 */ |
105 | {USB_ENDPOINT_XFER_BULK, DIR_OUT, BOUT7_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT7 */ | 95 | {USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT7 */ |
106 | {USB_ENDPOINT_XFER_BULK, DIR_IN, BIN8_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN8 */ | 96 | {USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN8 */ |
107 | {USB_ENDPOINT_XFER_INT, DIR_IN, IIN9_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN9 */ | 97 | {USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN9 */ |
108 | {USB_ENDPOINT_XFER_BULK, DIR_OUT, BOUT10_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT10 */ | 98 | {USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT10 */ |
109 | {USB_ENDPOINT_XFER_BULK, DIR_IN, BIN11_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN11 */ | 99 | {USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN11 */ |
110 | {USB_ENDPOINT_XFER_INT, DIR_IN, IIN12_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN12 */ | 100 | {USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN12 */ |
111 | {USB_ENDPOINT_XFER_BULK, DIR_OUT, BOUT13_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT13 */ | 101 | {USB_ENDPOINT_XFER_BULK, DIR_OUT, false, NULL, 0, 0, false, {0, 0, 0}}, /* BOUT13 */ |
112 | {USB_ENDPOINT_XFER_BULK, DIR_IN, BIN14_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN14 */ | 102 | {USB_ENDPOINT_XFER_BULK, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* BIN14 */ |
113 | {USB_ENDPOINT_XFER_INT, DIR_IN, IIN15_INTR, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN15 */ | 103 | {USB_ENDPOINT_XFER_INT, DIR_IN, false, NULL, 0, 0, false, {0, 0, 0}}, /* IIN15 */ |
114 | }; | 104 | }; |
115 | 105 | ||
116 | static volatile bool set_address = false; | 106 | static void setup_received(void) |
117 | static volatile bool set_configuration = false; | ||
118 | |||
119 | static void setup_irq_handler(void) | ||
120 | { | 107 | { |
121 | static uint32_t setup_data[2]; | 108 | static uint32_t setup_data[2]; |
122 | 109 | ||
@@ -124,6 +111,10 @@ static void setup_irq_handler(void) | |||
124 | setup_data[0] = SETUP1; | 111 | setup_data[0] = SETUP1; |
125 | setup_data[1] = SETUP2; | 112 | setup_data[1] = SETUP2; |
126 | 113 | ||
114 | /* clear all pending control transfers | ||
115 | * do we need this here? | ||
116 | */ | ||
117 | |||
127 | /* pass setup data to the upper layer */ | 118 | /* pass setup data to the upper layer */ |
128 | usb_core_control_request((struct usb_ctrlrequest*)setup_data); | 119 | usb_core_control_request((struct usb_ctrlrequest*)setup_data); |
129 | } | 120 | } |
@@ -131,12 +122,12 @@ static void setup_irq_handler(void) | |||
131 | /* service ep0 IN transaction */ | 122 | /* service ep0 IN transaction */ |
132 | static void ctr_write(void) | 123 | static void ctr_write(void) |
133 | { | 124 | { |
134 | int xfer_size = MIN(ctrlep[DIR_IN].cnt, CTL_MAX_SIZE); | 125 | int xfer_size = (ctrlep[DIR_IN].cnt > 64) ? 64 : ctrlep[DIR_IN].cnt; |
135 | unsigned int timeout = current_tick + HZ/10; | 126 | unsigned int timeout = current_tick + HZ/10; |
136 | 127 | ||
137 | while (TX0BUF & TXFULL) /* TX0FULL flag */ | 128 | while (TX0BUF & TXFULL) /* TX0FULL flag */ |
138 | { | 129 | { |
139 | if (TIME_AFTER(current_tick, timeout)) | 130 | if(TIME_AFTER(current_tick, timeout)) |
140 | break; | 131 | break; |
141 | } | 132 | } |
142 | 133 | ||
@@ -152,7 +143,7 @@ static void ctr_write(void) | |||
152 | * get zero len after transfer which indicates we need to send | 143 | * get zero len after transfer which indicates we need to send |
153 | * zero length packet to signal host end of the transfer. | 144 | * zero length packet to signal host end of the transfer. |
154 | */ | 145 | */ |
155 | ctrlep[DIR_IN].cnt -= CTL_MAX_SIZE; | 146 | ctrlep[DIR_IN].cnt -= 64; |
156 | ctrlep[DIR_IN].buf += xfer_size; | 147 | ctrlep[DIR_IN].buf += xfer_size; |
157 | } | 148 | } |
158 | 149 | ||
@@ -170,147 +161,60 @@ static void ctr_read(void) | |||
170 | RX0DMACTLO = DMA_START; /* start DMA */ | 161 | RX0DMACTLO = DMA_START; /* start DMA */ |
171 | } | 162 | } |
172 | 163 | ||
173 | static void blk_write(int ep_num) | 164 | static void blk_write(int ep) |
174 | { | 165 | { |
166 | int ep_num = EP_NUM(ep); | ||
167 | int max = usb_drv_port_speed() ? 512 : 64; | ||
168 | int xfer_size = (endpoints[ep_num].cnt > max) ? max : endpoints[ep_num].cnt; | ||
175 | unsigned int timeout = current_tick + HZ/10; | 169 | unsigned int timeout = current_tick + HZ/10; |
176 | int max = usb_drv_port_speed() ? BLK_HS_MAX_SIZE : BLK_FS_MAX_SIZE; | 170 | |
177 | int xfer_size = MIN(endpoints[ep_num].cnt, max); | ||
178 | |||
179 | while (BIN_TXBUF(ep_num) & TXFULL) /* TXFULL flag */ | 171 | while (BIN_TXBUF(ep_num) & TXFULL) /* TXFULL flag */ |
180 | { | 172 | { |
181 | if (TIME_AFTER(current_tick, timeout)) | 173 | if(TIME_AFTER(current_tick, timeout)) |
182 | break; | 174 | break; |
183 | } | 175 | } |
184 | 176 | ||
185 | BIN_TXSTAT(ep_num) = xfer_size; /* size */ | 177 | BIN_TXSTAT(ep_num) = xfer_size; /* size */ |
186 | BIN_DMAINLMADDR(ep_num) = (uint32_t)endpoints[ep_num].buf; /* buf address */ | 178 | BIN_DMAINLMADDR(ep_num) = (uint32_t)endpoints[ep_num].buf; /* buf address */ |
187 | BIN_DMAINCTL(ep_num) = DMA_START; /* start DMA */ | 179 | BIN_DMAINCTL(ep_num) = DMA_START; /* start DMA */ |
188 | BIN_TXCON(ep_num) &= ~TXNAK; /* clear NAK */ | 180 | BIN_TXCON(ep_num) &= ~TXNAK; /* clear NAK */ |
189 | 181 | ||
190 | /* Decrement by max packet size is intentional. | 182 | /* Decrement by max packet size is intentional. |
191 | * This way if we have final packet short one we will get negative len | 183 | * This way if we have final packet short one we will get negative len |
192 | * after transfer, which in turn indicates we *don't* need to send | 184 | * after transfer, which in turn indicates we *don't* need to send |
193 | * zero length packet. If the final packet is max sized packet we will | 185 | * zero length packet. If the final packet is max sized packet we will |
194 | * get zero len after transfer which indicates we need to send | 186 | * get zero len after transfer which indicates we need to send |
195 | * zero length packet to signal host end of the transfer. | 187 | * zero length packet to signal host end of the transfer. |
196 | */ | 188 | */ |
197 | endpoints[ep_num].cnt -= max; | 189 | endpoints[ep_num].cnt -= max; |
198 | endpoints[ep_num].buf += xfer_size; | 190 | endpoints[ep_num].buf += xfer_size; |
199 | } | 191 | } |
200 | 192 | ||
201 | static void blk_in_irq_handler(int ep_num) | 193 | static void blk_read(int ep) |
202 | { | ||
203 | uint32_t txstat = BIN_TXSTAT(ep_num); | ||
204 | struct endpoint_t *endp = &endpoints[ep_num]; | ||
205 | |||
206 | if (txstat & TXERR) | ||
207 | { | ||
208 | panicf("error condition ep%d, %ld", ep_num, current_tick); | ||
209 | } | ||
210 | |||
211 | if (txstat & TXCFINT) | ||
212 | { | ||
213 | logf("blk_write: cf(0x%x), %ld", ep_num, current_tick); | ||
214 | /* bit cleared by read */ | ||
215 | usb_drv_stall(ep_num, false, true); | ||
216 | } | ||
217 | |||
218 | if (txstat & TXACK) /* check TxACK flag */ | ||
219 | { | ||
220 | if (endp->cnt > 0) | ||
221 | { | ||
222 | logf("blk_write: ack(0x%x), %ld", ep_num, current_tick); | ||
223 | /* we still have data to send (or ZLP) */ | ||
224 | blk_write(ep_num); | ||
225 | } | ||
226 | else | ||
227 | { | ||
228 | logf("udc_intr: usb_core_transfer_complete(0x%x, USB_DIR_IN, 0, 0x%x), %ld", | ||
229 | ep_num, endp->len, current_tick); | ||
230 | |||
231 | /* final ack received */ | ||
232 | usb_core_transfer_complete(ep_num, /* ep */ | ||
233 | USB_DIR_IN, /* dir */ | ||
234 | 0, /* status */ | ||
235 | endp->len); /* length */ | ||
236 | |||
237 | /* release semaphore for blocking transfer */ | ||
238 | if (endp->block) | ||
239 | { | ||
240 | logf("udc_intr: ep=0x%x, semaphore_release(), %ld", | ||
241 | ep_num, current_tick); | ||
242 | |||
243 | semaphore_release(&endp->complete); | ||
244 | } | ||
245 | } | ||
246 | } | ||
247 | } | ||
248 | |||
249 | static void blk_out_irq_handler(int ep_num) | ||
250 | { | 194 | { |
251 | uint32_t rxstat = BOUT_RXSTAT(ep_num); | 195 | int ep_num = EP_NUM(ep); |
252 | int xfer_size = rxstat & 0xffff; | 196 | int xfer_size = BOUT_RXSTAT(ep_num) & 0xffff; |
253 | int max = usb_drv_port_speed() ? BLK_HS_MAX_SIZE : BLK_FS_MAX_SIZE; | 197 | |
254 | struct endpoint_t *endp = &endpoints[ep_num]; | 198 | /* clear NAK bit */ |
255 | 199 | BOUT_RXCON(ep_num) &= ~RXNAK; | |
256 | if (rxstat & RXERR) | 200 | |
257 | { | 201 | endpoints[ep_num].cnt -= xfer_size; |
258 | panicf("error condition ep%d, %ld", ep_num, current_tick); | 202 | endpoints[ep_num].buf += xfer_size; |
259 | } | 203 | |
260 | 204 | BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)endpoints[ep_num].buf; | |
261 | if (rxstat & RXOVF) | 205 | BOUT_DMAOUTCTL(ep_num) = DMA_START; |
262 | { | ||
263 | panicf("rxovf ep%d, %ld", ep_num, current_tick); | ||
264 | } | ||
265 | |||
266 | if (rxstat & RXCFINT) | ||
267 | { | ||
268 | logf("blk_read:cf(0x%x), %ld", ep_num, current_tick); | ||
269 | usb_drv_stall(ep_num, false, false); | ||
270 | } | ||
271 | |||
272 | if ((rxstat & RXACK) && endp->cnt > 0) | ||
273 | { | ||
274 | logf("blk_read:ack(0x%x,0x%x), %ld", ep_num, xfer_size, current_tick); | ||
275 | |||
276 | /* clear NAK bit */ | ||
277 | BOUT_RXCON(ep_num) &= ~RXNAK; | ||
278 | |||
279 | endp->cnt -= xfer_size; | ||
280 | endp->buf += xfer_size; | ||
281 | |||
282 | /* if the transfer was short or if the total count is zero, | ||
283 | * transfer is complete | ||
284 | */ | ||
285 | if (endp->cnt == 0 || xfer_size < max) | ||
286 | { | ||
287 | logf("udc_intr: usb_core_transfer_complete(0x%x, USB_DIR_OUT, 0, 0x%x), %ld", | ||
288 | ep_num, endp->len, current_tick); | ||
289 | |||
290 | usb_core_transfer_complete(ep_num, /* ep */ | ||
291 | USB_DIR_OUT, /* dir */ | ||
292 | 0, /* status */ | ||
293 | endp->len - endp->cnt); /* length */ | ||
294 | endp->cnt = 0; | ||
295 | } | ||
296 | else | ||
297 | { | ||
298 | BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)endp->buf; | ||
299 | BOUT_DMAOUTCTL(ep_num) = DMA_START; | ||
300 | } | ||
301 | } | ||
302 | } | 206 | } |
303 | 207 | ||
304 | static void int_write(int ep) | 208 | static void int_write(int ep) |
305 | { | 209 | { |
306 | int ep_num = EP_NUM(ep); | 210 | int ep_num = EP_NUM(ep); |
307 | int max = usb_drv_port_speed() ? INT_HS_MAX_SIZE : INT_FS_MAX_SIZE; | 211 | int max = usb_drv_port_speed() ? 1024 : 64; |
308 | int xfer_size = MIN(endpoints[ep_num].cnt, max); | 212 | int xfer_size = (endpoints[ep_num].cnt > max) ? max : endpoints[ep_num].cnt; |
309 | unsigned int timeout = current_tick + HZ/10; | 213 | unsigned int timeout = current_tick + HZ/10; |
310 | 214 | ||
311 | while (IIN_TXBUF(ep_num) & TXFULL) | 215 | while (IIN_TXBUF(ep_num) & TXFULL) /* TXFULL flag */ |
312 | { | 216 | { |
313 | if (TIME_AFTER(current_tick, timeout)) | 217 | if(TIME_AFTER(current_tick, timeout)) |
314 | break; | 218 | break; |
315 | } | 219 | } |
316 | 220 | ||
@@ -330,99 +234,167 @@ static void int_write(int ep) | |||
330 | endpoints[ep_num].buf += xfer_size; | 234 | endpoints[ep_num].buf += xfer_size; |
331 | } | 235 | } |
332 | 236 | ||
333 | static void int_in_irq_handler(int ep_num) | 237 | /* UDC ISR function */ |
238 | void INT_UDC(void) | ||
334 | { | 239 | { |
335 | uint32_t txstat = IIN_TXSTAT(ep_num); | 240 | uint32_t txstat, rxstat; |
336 | struct endpoint_t *endp = &endpoints[ep_num]; | 241 | int tmp, ep_num; |
337 | 242 | ||
338 | if (txstat & TXCFINT) | 243 | /* read what caused UDC irq */ |
244 | uint32_t intsrc = INT2FLAG & 0x7fffff; | ||
245 | |||
246 | if (intsrc & SETUP_INTR) /* setup interrupt */ | ||
339 | { | 247 | { |
340 | logf("int_write: cf(0x%x), %ld", ep_num, current_tick); | 248 | setup_received(); |
341 | /* bit cleared by read */ | ||
342 | usb_drv_stall(ep_num, false, true); | ||
343 | } | 249 | } |
344 | 250 | else if (intsrc & IN0_INTR) /* ep0 in interrupt */ | |
345 | if (txstat & TXERR) | ||
346 | { | 251 | { |
347 | panicf("error condition ep%d, %ld", ep_num, current_tick); | 252 | txstat = TX0STAT; /* read clears flags */ |
253 | |||
254 | /* TODO handle errors */ | ||
255 | if (txstat & TXACK) /* check TxACK flag */ | ||
256 | { | ||
257 | if (ctrlep[DIR_IN].cnt >= 0) | ||
258 | { | ||
259 | /* we still have data to send (or ZLP) */ | ||
260 | ctr_write(); | ||
261 | } | ||
262 | else | ||
263 | { | ||
264 | /* final ack received */ | ||
265 | usb_core_transfer_complete(0, /* ep */ | ||
266 | USB_DIR_IN, /* dir */ | ||
267 | 0, /* status */ | ||
268 | ctrlep[DIR_IN].len); /* length */ | ||
269 | |||
270 | /* release semaphore for blocking transfer */ | ||
271 | if (ctrlep[DIR_IN].block) | ||
272 | semaphore_release(&ctrlep[DIR_IN].complete); | ||
273 | } | ||
274 | } | ||
348 | } | 275 | } |
276 | else if (intsrc & OUT0_INTR) /* ep0 out interrupt */ | ||
277 | { | ||
278 | rxstat = RX0STAT; | ||
349 | 279 | ||
350 | if (txstat & TXACK) /* check TxACK flag */ | 280 | /* TODO handle errors */ |
281 | if (rxstat & RXACK) /* RxACK */ | ||
282 | { | ||
283 | if (ctrlep[DIR_OUT].cnt > 0) | ||
284 | ctr_read(); | ||
285 | else | ||
286 | usb_core_transfer_complete(0, /* ep */ | ||
287 | USB_DIR_OUT, /* dir */ | ||
288 | 0, /* status */ | ||
289 | ctrlep[DIR_OUT].len); /* length */ | ||
290 | } | ||
291 | } | ||
292 | else if (intsrc & USBRST_INTR) /* usb reset */ | ||
351 | { | 293 | { |
352 | if (endp->cnt > 0) | 294 | usb_drv_init(); |
295 | } | ||
296 | else if (intsrc & RESUME_INTR) /* usb resume */ | ||
297 | { | ||
298 | TX0CON |= TXCLR; /* TxClr */ | ||
299 | TX0CON &= ~TXCLR; | ||
300 | RX0CON |= RXCLR; /* RxClr */ | ||
301 | RX0CON &= ~RXCLR; | ||
302 | } | ||
303 | else if (intsrc & SUSP_INTR) /* usb suspend */ | ||
304 | { | ||
305 | } | ||
306 | else if (intsrc & CONN_INTR) /* usb connect */ | ||
307 | { | ||
308 | } | ||
309 | else | ||
310 | { | ||
311 | /* lets figure out which ep generated irq */ | ||
312 | tmp = intsrc >> 7; | ||
313 | for (ep_num=1; ep_num < 15; ep_num++) | ||
353 | { | 314 | { |
354 | logf("int_write: ack(0x%x), %ld", ep_num, current_tick); | 315 | tmp >>= ep_num; |
355 | /* we still have data to send (or ZLP) */ | 316 | if (tmp & 0x01) |
356 | int_write(ep_num); | 317 | break; |
357 | } | 318 | } |
358 | else | 319 | |
320 | if (intsrc & ((1<<8)|(1<<11)|(1<<14)|(1<<17)|(1<<20))) | ||
359 | { | 321 | { |
360 | logf("udc_intr: usb_core_transfer_complete(0x%x, USB_DIR_IN, 0, 0x%x), %ld", | 322 | /* bulk out */ |
361 | ep_num, endp->len, current_tick); | 323 | rxstat = BOUT_RXSTAT(ep_num); |
362 | 324 | ||
363 | /* final ack received */ | 325 | /* TODO handle errors */ |
364 | usb_core_transfer_complete(ep_num, /* ep */ | 326 | if (rxstat & (1<<18)) /* RxACK */ |
365 | USB_DIR_IN, /* dir */ | ||
366 | 0, /* status */ | ||
367 | endp->len); /* length */ | ||
368 | |||
369 | /* release semaphore for blocking transfer */ | ||
370 | if (endp->block) | ||
371 | { | 327 | { |
372 | logf("udc_intr: ep=0x%x, semaphore_release(), %ld", | 328 | if (endpoints[ep_num].cnt > 0) |
373 | ep_num, current_tick); | 329 | blk_read(ep_num); |
374 | 330 | else | |
375 | semaphore_release(&endp->complete); | 331 | usb_core_transfer_complete(ep_num, /* ep */ |
332 | USB_DIR_OUT, /* dir */ | ||
333 | 0, /* status */ | ||
334 | endpoints[ep_num].len); /* length */ | ||
376 | } | 335 | } |
377 | } | 336 | } |
378 | } | 337 | else if (intsrc & ((1<<9)|(1<<12)|(1<<15)|(1<<18)|(1<<21))) |
379 | } | ||
380 | |||
381 | static void udc_phy_reset(void) | ||
382 | { | ||
383 | DEV_CTL |= SOFT_POR; | ||
384 | udelay(10000); /* min 10ms */ | ||
385 | DEV_CTL &= ~SOFT_POR; | ||
386 | } | ||
387 | |||
388 | static void udc_soft_connect(void) | ||
389 | { | ||
390 | DEV_CTL |= CSR_DONE | | ||
391 | DEV_SOFT_CN | | ||
392 | DEV_SELF_PWR; | ||
393 | } | ||
394 | |||
395 | static void udc_helper(void) | ||
396 | { | ||
397 | uint32_t dev_info = DEV_INFO; | ||
398 | |||
399 | /* This polls for DEV_EN bit set in DEV_INFO register | ||
400 | * as well as tracks current requested configuration | ||
401 | * (DEV_INFO [11:8]). On state change it notifies usb stack | ||
402 | * about it. | ||
403 | */ | ||
404 | |||
405 | /* SET ADDRESS request */ | ||
406 | if (set_address == false) | ||
407 | if ((dev_info & 0x7f)) | ||
408 | { | 338 | { |
409 | set_address = true; | 339 | /* bulk in */ |
410 | usb_core_notify_set_address(dev_info & 0x7f); | 340 | txstat = BIN_TXSTAT(ep_num); |
341 | |||
342 | /* TODO handle errors */ | ||
343 | if (txstat & (1<<18)) /* check TxACK flag */ | ||
344 | { | ||
345 | if (endpoints[ep_num].cnt >= 0) | ||
346 | { | ||
347 | /* we still have data to send (or ZLP) */ | ||
348 | blk_write(ep_num); | ||
349 | } | ||
350 | else | ||
351 | { | ||
352 | /* final ack received */ | ||
353 | usb_core_transfer_complete(ep_num, /* ep */ | ||
354 | USB_DIR_IN, /* dir */ | ||
355 | 0, /* status */ | ||
356 | endpoints[ep_num].len); /* length */ | ||
357 | |||
358 | /* release semaphore for blocking transfer */ | ||
359 | if (endpoints[ep_num].block) | ||
360 | semaphore_release(&endpoints[ep_num].complete); | ||
361 | } | ||
362 | } | ||
411 | } | 363 | } |
412 | 364 | else if (intsrc & ((1<<10)|(1<13)|(1<<16)|(1<<19)|(1<<22))) | |
413 | /* SET CONFIGURATION request */ | ||
414 | if (set_configuration == false) | ||
415 | if (dev_info & DEV_EN) | ||
416 | { | 365 | { |
417 | set_configuration = true; | 366 | /* int in */ |
418 | usb_core_notify_set_config(((dev_info >> 7) & 0xf) + 1); | 367 | txstat = IIN_TXSTAT(ep_num); |
368 | |||
369 | /* TODO handle errors */ | ||
370 | if (txstat & TXACK) /* check TxACK flag */ | ||
371 | { | ||
372 | if (endpoints[ep_num].cnt >= 0) | ||
373 | { | ||
374 | /* we still have data to send (or ZLP) */ | ||
375 | int_write(ep_num); | ||
376 | } | ||
377 | else | ||
378 | { | ||
379 | /* final ack received */ | ||
380 | usb_core_transfer_complete(ep_num, /* ep */ | ||
381 | USB_DIR_IN, /* dir */ | ||
382 | 0, /* status */ | ||
383 | endpoints[ep_num].len); /* length */ | ||
384 | |||
385 | /* release semaphore for blocking transfer */ | ||
386 | if (endpoints[ep_num].block) | ||
387 | semaphore_release(&endpoints[ep_num].complete); | ||
388 | } | ||
389 | } | ||
419 | } | 390 | } |
391 | } | ||
420 | } | 392 | } |
421 | 393 | ||
422 | /* return port speed */ | 394 | /* return port speed FS=0, HS=1 */ |
423 | int usb_drv_port_speed(void) | 395 | int usb_drv_port_speed(void) |
424 | { | 396 | { |
425 | return ((DEV_INFO & DEV_SPEED) ? USB_FULL_SPEED : USB_HIGH_SPEED); | 397 | return ((DEV_INFO & DEV_SPEED) == 0) ? 0 : 1; |
426 | } | 398 | } |
427 | 399 | ||
428 | /* Reserve endpoint */ | 400 | /* Reserve endpoint */ |
@@ -438,7 +410,7 @@ int usb_drv_request_endpoint(int type, int dir) | |||
438 | logf("req: %s %s", XFER_DIR_STR(ep_dir), XFER_TYPE_STR(ep_type)); | 410 | logf("req: %s %s", XFER_DIR_STR(ep_dir), XFER_TYPE_STR(ep_type)); |
439 | 411 | ||
440 | /* Find an available ep/dir pair */ | 412 | /* Find an available ep/dir pair */ |
441 | for (ep_num = 1; ep_num < USB_NUM_ENDPOINTS; ep_num++) | 413 | for (ep_num=1;ep_num<USB_NUM_ENDPOINTS;ep_num++) |
442 | { | 414 | { |
443 | struct endpoint_t* endpoint = &endpoints[ep_num]; | 415 | struct endpoint_t* endpoint = &endpoints[ep_num]; |
444 | 416 | ||
@@ -448,35 +420,7 @@ int usb_drv_request_endpoint(int type, int dir) | |||
448 | { | 420 | { |
449 | /* mark endpoint as taken */ | 421 | /* mark endpoint as taken */ |
450 | endpoint->allocated = true; | 422 | endpoint->allocated = true; |
451 | 423 | ||
452 | if (ep_num%3 == 0) /* IIN 3, 6, 9, 12, 15 */ | ||
453 | { | ||
454 | IIN_TXCON(ep_num) = (ep_num<<8) | /* set ep number */ | ||
455 | TXERRINTEN | | ||
456 | TXEPEN | /* endpoint enable */ | ||
457 | TXNAK | /* respond with NAK */ | ||
458 | TXACKINTEN | /* irq on ACK */ | ||
459 | TXCFINTE; /* irq on Clear feature */ | ||
460 | } | ||
461 | else if (ep_num%3 == 1) /* BOUT 1, 4, 7, 10, 13 */ | ||
462 | { | ||
463 | BOUT_RXCON(ep_num) = (ep_num<<8) | /* set ep number */ | ||
464 | RXERRINTEN | | ||
465 | RXEPEN | /* endpoint enable */ | ||
466 | RXNAK | /* respond with NAK */ | ||
467 | RXACKINTEN | /* irq on ACK */ | ||
468 | RXCFINTE; /* irq on Clear feature */ | ||
469 | } | ||
470 | else if (ep_num%3 == 2) /* BIN 2, 5, 8, 11, 14 */ | ||
471 | { | ||
472 | BIN_TXCON(ep_num) = (ep_num<<8) | /* set ep number */ | ||
473 | TXERRINTEN | | ||
474 | TXEPEN | /* endpoint enable */ | ||
475 | TXNAK | /* respond with NAK */ | ||
476 | TXACKINTEN | /* irq on ACK */ | ||
477 | TXCFINTE; /* irq on Clear feature */ | ||
478 | } | ||
479 | |||
480 | /* enable interrupt from this endpoint */ | 424 | /* enable interrupt from this endpoint */ |
481 | EN_INT |= (1<<(ep_num+7)); | 425 | EN_INT |= (1<<(ep_num+7)); |
482 | 426 | ||
@@ -491,7 +435,10 @@ int usb_drv_request_endpoint(int type, int dir) | |||
491 | void usb_drv_release_endpoint(int ep) | 435 | void usb_drv_release_endpoint(int ep) |
492 | { | 436 | { |
493 | int ep_num = EP_NUM(ep); | 437 | int ep_num = EP_NUM(ep); |
494 | logf("rel: ep%d %s", ep_num, XFER_DIR_STR(EP_DIR(ep))); | 438 | int ep_dir = EP_DIR(ep); |
439 | (void) ep_dir; | ||
440 | |||
441 | logf("rel: ep%d %s", ep_num, XFER_DIR_STR(ep_dir)); | ||
495 | endpoints[ep_num].allocated = false; | 442 | endpoints[ep_num].allocated = false; |
496 | 443 | ||
497 | /* disable interrupt from this endpoint */ | 444 | /* disable interrupt from this endpoint */ |
@@ -507,20 +454,14 @@ void usb_drv_release_endpoint(int ep) | |||
507 | void usb_drv_set_address(int address) | 454 | void usb_drv_set_address(int address) |
508 | { | 455 | { |
509 | (void)address; | 456 | (void)address; |
510 | /* UDC sets this automaticaly */ | 457 | /* UDC seems to set this automaticaly */ |
511 | } | 458 | } |
512 | 459 | ||
513 | static int _usb_drv_send(int endpoint, void *ptr, int length, bool block) | 460 | static int _usb_drv_send(int endpoint, void *ptr, int length, bool block) |
514 | { | 461 | { |
515 | struct endpoint_t *ep; | 462 | struct endpoint_t *ep; |
516 | int ep_num = EP_NUM(endpoint); | 463 | int ep_num = EP_NUM(endpoint); |
517 | 464 | ||
518 | /* for send transfers, make sure the data is committed */ | ||
519 | commit_discard_dcache_range(ptr, length); | ||
520 | |||
521 | logf("_usb_drv_send: endpt=0x%x, len=0x%x, block=%d", | ||
522 | endpoint, length, block); | ||
523 | |||
524 | if (ep_num == 0) | 465 | if (ep_num == 0) |
525 | ep = &ctrlep[DIR_IN]; | 466 | ep = &ctrlep[DIR_IN]; |
526 | else | 467 | else |
@@ -536,7 +477,7 @@ static int _usb_drv_send(int endpoint, void *ptr, int length, bool block) | |||
536 | 477 | ||
537 | switch (ep->type) | 478 | switch (ep->type) |
538 | { | 479 | { |
539 | case USB_ENDPOINT_XFER_CONTROL: | 480 | case USB_ENDPOINT_XFER_CONTROL: |
540 | ctr_write(); | 481 | ctr_write(); |
541 | break; | 482 | break; |
542 | 483 | ||
@@ -574,40 +515,30 @@ int usb_drv_recv(int endpoint, void* ptr, int length) | |||
574 | struct endpoint_t *ep; | 515 | struct endpoint_t *ep; |
575 | int ep_num = EP_NUM(endpoint); | 516 | int ep_num = EP_NUM(endpoint); |
576 | 517 | ||
577 | logf("usb_drv_recv: endpt=0x%x, len=0x%x, %ld", | ||
578 | endpoint, length, current_tick); | ||
579 | |||
580 | /* for recv, discard the cache lines related to the buffer */ | ||
581 | commit_discard_dcache_range(ptr, length); | ||
582 | |||
583 | if (ep_num == 0) | 518 | if (ep_num == 0) |
584 | { | 519 | { |
585 | ep = &ctrlep[DIR_OUT]; | 520 | ep = &ctrlep[DIR_OUT]; |
586 | ep->buf = ptr; | 521 | |
587 | ep->len = ep->cnt = length; | 522 | ctr_read(); |
588 | |||
589 | /* clear NAK bit */ | ||
590 | RX0CON &= ~RXNAK; | ||
591 | RX0DMAOUTLMADDR = (uint32_t)ptr; /* buffer address */ | ||
592 | RX0DMACTLO = DMA_START; /* start DMA */ | ||
593 | } | 523 | } |
594 | else | 524 | else |
595 | { | 525 | { |
596 | ep = &endpoints[ep_num]; | 526 | ep = &endpoints[ep_num]; |
597 | ep->buf = ptr; | 527 | |
598 | ep->len = ep->cnt = length; | ||
599 | |||
600 | /* clear NAK bit */ | 528 | /* clear NAK bit */ |
601 | BOUT_RXCON(ep_num) &= ~RXNAK; | 529 | BOUT_RXCON(ep_num) &= ~RXNAK; |
602 | BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)ptr; | 530 | BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)ptr; |
603 | BOUT_DMAOUTCTL(ep_num) = DMA_START; | 531 | BOUT_DMAOUTCTL(ep_num) = DMA_START; |
604 | } | 532 | } |
533 | |||
534 | ep->buf = ptr; | ||
535 | ep->len = ep->cnt = length; | ||
605 | 536 | ||
606 | return 0; | 537 | return 0; |
607 | } | 538 | } |
608 | 539 | ||
609 | /* Kill all transfers. Usually you need to set a bit for each endpoint | 540 | /* Kill all transfers. Usually you need to set a bit for each endpoint |
610 | * and flush fifos. You should also call the completion handler with | 541 | * and flush fifos. You should also call the completion handler with |
611 | * error status for everything | 542 | * error status for everything |
612 | */ | 543 | */ |
613 | void usb_drv_cancel_all_transfers(void) | 544 | void usb_drv_cancel_all_transfers(void) |
@@ -661,8 +592,6 @@ bool usb_drv_stalled(int endpoint, bool in) | |||
661 | void usb_drv_stall(int endpoint, bool stall, bool in) | 592 | void usb_drv_stall(int endpoint, bool stall, bool in) |
662 | { | 593 | { |
663 | int ep_num = EP_NUM(endpoint); | 594 | int ep_num = EP_NUM(endpoint); |
664 | logf("usb_drv: %sstall EP%d %s", | ||
665 | stall ? "": "un", ep_num, in ? "IN" : "OUT"); | ||
666 | 595 | ||
667 | switch (endpoints[ep_num].type) | 596 | switch (endpoints[ep_num].type) |
668 | { | 597 | { |
@@ -716,23 +645,87 @@ void usb_drv_stall(int endpoint, bool stall, bool in) | |||
716 | void usb_drv_init(void) | 645 | void usb_drv_init(void) |
717 | { | 646 | { |
718 | int ep_num; | 647 | int ep_num; |
648 | |||
649 | /* enable USB clock */ | ||
650 | SCU_CLKCFG &= ~CLKCFG_UDC; | ||
651 | |||
652 | /* 1. do soft disconnect */ | ||
653 | DEV_CTL = DEV_SELF_PWR; | ||
654 | |||
655 | /* 2. do power on reset to PHY */ | ||
656 | DEV_CTL = DEV_SELF_PWR | | ||
657 | SOFT_POR; | ||
658 | |||
659 | /* 3. wait more than 10ms */ | ||
660 | udelay(20000); | ||
661 | |||
662 | /* 4. clear SOFT_POR bit */ | ||
663 | DEV_CTL &= ~SOFT_POR; | ||
664 | |||
665 | /* 5. configure minimal EN_INT */ | ||
666 | EN_INT = EN_SUSP_INTR | /* Enable Suspend Interrupt */ | ||
667 | EN_RESUME_INTR | /* Enable Resume Interrupt */ | ||
668 | EN_USBRST_INTR | /* Enable USB Reset Interrupt */ | ||
669 | EN_OUT0_INTR | /* Enable OUT Token receive Interrupt EP0 */ | ||
670 | EN_IN0_INTR | /* Enable IN Token transmits Interrupt EP0 */ | ||
671 | EN_SETUP_INTR; /* Enable SETUP Packet Receive Interrupt */ | ||
672 | |||
673 | /* 6. configure INTCON */ | ||
674 | INTCON = UDC_INTHIGH_ACT | /* interrupt high active */ | ||
675 | UDC_INTEN; /* enable EP0 interrupts */ | ||
676 | |||
677 | /* 7. configure EP0 control registers */ | ||
678 | TX0CON = TXACKINTEN | /* Set as one to enable the EP0 tx irq */ | ||
679 | TXNAK; /* Set as one to response NAK handshake */ | ||
680 | |||
681 | RX0CON = RXACKINTEN | | ||
682 | RXEPEN | /* Endpoint 0 Enable. When cleared the endpoint does | ||
683 | * not respond to an SETUP or OUT token | ||
684 | */ | ||
685 | |||
686 | RXNAK; /* Set as one to response NAK handshake */ | ||
687 | |||
688 | /* 8. write final bits to DEV_CTL */ | ||
689 | DEV_CTL = CSR_DONE | /* Configure CSR done */ | ||
690 | DEV_PHY16BIT | /* 16-bit data path enabled. udc_clk = 30MHz */ | ||
691 | DEV_SOFT_CN | /* Device soft connect */ | ||
692 | DEV_SELF_PWR; /* Device self power */ | ||
719 | 693 | ||
720 | /* init semaphore of ep0 */ | 694 | /* init semaphore of ep0 */ |
721 | semaphore_init(&ctrlep[DIR_OUT].complete, 1, 0); | 695 | semaphore_init(&ctrlep[DIR_OUT].complete, 1, 0); |
722 | semaphore_init(&ctrlep[DIR_IN].complete, 1, 0); | 696 | semaphore_init(&ctrlep[DIR_IN].complete, 1, 0); |
723 | 697 | ||
724 | /* init semaphores for other endpoints */ | ||
725 | for (ep_num = 1; ep_num < USB_NUM_ENDPOINTS; ep_num++) | 698 | for (ep_num = 1; ep_num < USB_NUM_ENDPOINTS; ep_num++) |
699 | { | ||
726 | semaphore_init(&endpoints[ep_num].complete, 1, 0); | 700 | semaphore_init(&endpoints[ep_num].complete, 1, 0); |
701 | |||
702 | if (ep_num%3 == 0) /* IIN 3, 6, 9, 12, 15 */ | ||
703 | { | ||
704 | IIN_TXCON(ep_num) |= (ep_num<<8)|TXEPEN|TXNAK; /* ep_num, enable, NAK */ | ||
705 | } | ||
706 | else if (ep_num%3 == 1) /* BOUT 1, 4, 7, 10, 13 */ | ||
707 | { | ||
708 | BOUT_RXCON(ep_num) |= (ep_num<<8)|RXEPEN|RXNAK; /* ep_num, NAK, enable */ | ||
709 | } | ||
710 | else if (ep_num%3 == 2) /* BIN 2, 5, 8, 11, 14 */ | ||
711 | { | ||
712 | BIN_TXCON(ep_num) |= (ep_num<<8)|TXEPEN|TXNAK; /* ep_num, enable, NAK */ | ||
713 | } | ||
714 | } | ||
727 | } | 715 | } |
728 | 716 | ||
729 | /* turn off usb core */ | 717 | /* turn off usb core */ |
730 | void usb_drv_exit(void) | 718 | void usb_drv_exit(void) |
731 | { | 719 | { |
732 | /* udc module reset */ | 720 | DEV_CTL = DEV_SELF_PWR; |
733 | SCU_RSTCFG |= (1<<1); | 721 | |
734 | udelay(10); | 722 | /* disable USB interrupts in interrupt controller */ |
735 | SCU_RSTCFG &= ~(1<<1); | 723 | INTC_IMR &= ~IRQ_ARM_UDC; |
724 | INTC_IECR &= ~IRQ_ARM_UDC; | ||
725 | |||
726 | /* we cannot disable UDC clock since this causes data abort | ||
727 | * when reading DEV_INFO in order to check usb connect event | ||
728 | */ | ||
736 | } | 729 | } |
737 | 730 | ||
738 | int usb_detect(void) | 731 | int usb_detect(void) |
@@ -743,140 +736,3 @@ int usb_detect(void) | |||
743 | return USB_EXTRACTED; | 736 | return USB_EXTRACTED; |
744 | } | 737 | } |
745 | 738 | ||
746 | /* UDC ISR function */ | ||
747 | void INT_UDC(void) | ||
748 | { | ||
749 | uint32_t txstat, rxstat; | ||
750 | int ep_num; | ||
751 | |||
752 | /* read what caused UDC irq */ | ||
753 | uint32_t intsrc = INT2FLAG & 0x7fffff; | ||
754 | |||
755 | if (intsrc & USBRST_INTR) /* usb reset */ | ||
756 | { | ||
757 | logf("udc_int: reset, %ld", current_tick); | ||
758 | |||
759 | EN_INT = EN_SUSP_INTR | /* Enable Suspend Irq */ | ||
760 | EN_RESUME_INTR | /* Enable Resume Irq */ | ||
761 | EN_USBRST_INTR | /* Enable USB Reset Irq */ | ||
762 | EN_OUT0_INTR | /* Enable OUT Token receive Irq EP0 */ | ||
763 | EN_IN0_INTR | /* Enable IN Token transmit Irq EP0 */ | ||
764 | EN_SETUP_INTR; /* Enable SETUP Packet Receive Irq */ | ||
765 | |||
766 | INTCON = UDC_INTHIGH_ACT | /* interrupt high active */ | ||
767 | UDC_INTEN; /* enable EP0 irqs */ | ||
768 | |||
769 | TX0CON = TXACKINTEN | /* Set as one to enable the EP0 tx irq */ | ||
770 | TXNAK; /* Set as one to response NAK handshake */ | ||
771 | |||
772 | RX0CON = RXACKINTEN | | ||
773 | RXEPEN | /* Endpoint 0 Enable. When cleared the | ||
774 | * endpoint does not respond to an SETUP | ||
775 | * or OUT token */ | ||
776 | RXNAK; /* Set as one to response NAK handshake */ | ||
777 | |||
778 | set_address = false; | ||
779 | set_configuration = false; | ||
780 | } | ||
781 | |||
782 | /* This needs to be processed AFTER usb reset */ | ||
783 | udc_helper(); | ||
784 | |||
785 | if (intsrc & SETUP_INTR) /* setup interrupt */ | ||
786 | { | ||
787 | setup_irq_handler(); | ||
788 | } | ||
789 | |||
790 | if (intsrc & IN0_INTR) /* ep0 in interrupt */ | ||
791 | { | ||
792 | txstat = TX0STAT; /* read clears flags */ | ||
793 | |||
794 | /* TODO handle errors */ | ||
795 | if (txstat & TXACK) /* check TxACK flag */ | ||
796 | { | ||
797 | if (ctrlep[DIR_IN].cnt >= 0) | ||
798 | { | ||
799 | /* we still have data to send (or ZLP) */ | ||
800 | ctr_write(); | ||
801 | } | ||
802 | else | ||
803 | { | ||
804 | /* final ack received */ | ||
805 | usb_core_transfer_complete(0, /* ep */ | ||
806 | USB_DIR_IN, /* dir */ | ||
807 | 0, /* status */ | ||
808 | ctrlep[DIR_IN].len); /* length */ | ||
809 | |||
810 | /* release semaphore for blocking transfer */ | ||
811 | if (ctrlep[DIR_IN].block) | ||
812 | semaphore_release(&ctrlep[DIR_IN].complete); | ||
813 | } | ||
814 | } | ||
815 | } | ||
816 | |||
817 | if (intsrc & OUT0_INTR) /* ep0 out interrupt */ | ||
818 | { | ||
819 | rxstat = RX0STAT; | ||
820 | |||
821 | /* TODO handle errors */ | ||
822 | if (rxstat & RXACK) /* RxACK */ | ||
823 | { | ||
824 | if (ctrlep[DIR_OUT].cnt > 0) | ||
825 | ctr_read(); | ||
826 | else | ||
827 | usb_core_transfer_complete(0, /* ep */ | ||
828 | USB_DIR_OUT, /* dir */ | ||
829 | 0, /* status */ | ||
830 | ctrlep[DIR_OUT].len); /* length */ | ||
831 | } | ||
832 | } | ||
833 | |||
834 | if (intsrc & RESUME_INTR) /* usb resume */ | ||
835 | { | ||
836 | TX0CON |= TXCLR; /* TxClr */ | ||
837 | TX0CON &= ~TXCLR; | ||
838 | |||
839 | RX0CON |= RXCLR; /* RxClr */ | ||
840 | RX0CON &= ~RXCLR; | ||
841 | } | ||
842 | |||
843 | if (intsrc & SUSP_INTR) /* usb suspend */ | ||
844 | { | ||
845 | } | ||
846 | |||
847 | if (intsrc & CONN_INTR) /* usb connect */ | ||
848 | { | ||
849 | udc_phy_reset(); | ||
850 | udelay(10000); /* wait at least 10ms */ | ||
851 | udc_soft_connect(); | ||
852 | } | ||
853 | |||
854 | /* endpoints other then EP0 */ | ||
855 | if (intsrc & 0x7fff00) | ||
856 | { | ||
857 | /* lets figure out which ep generated irq */ | ||
858 | for (ep_num = 1; ep_num < USB_NUM_ENDPOINTS; ep_num++) | ||
859 | { | ||
860 | struct endpoint_t *ep = &endpoints[ep_num]; | ||
861 | |||
862 | if ((intsrc & ep->intr_mask) && ep->allocated) | ||
863 | { | ||
864 | switch (ep->type) | ||
865 | { | ||
866 | case USB_ENDPOINT_XFER_BULK: | ||
867 | if (ep->dir == DIR_OUT) | ||
868 | blk_out_irq_handler(ep_num); | ||
869 | else | ||
870 | blk_in_irq_handler(ep_num); | ||
871 | |||
872 | break; | ||
873 | |||
874 | case USB_ENDPOINT_XFER_INT: | ||
875 | int_in_irq_handler(ep_num); | ||
876 | |||
877 | break; | ||
878 | } | ||
879 | } | ||
880 | } | ||
881 | } | ||
882 | } | ||
diff --git a/firmware/target/arm/rk27xx/usb-rk27xx.c b/firmware/target/arm/rk27xx/usb-rk27xx.c index 09c9090a3b..20bf867c8d 100644 --- a/firmware/target/arm/rk27xx/usb-rk27xx.c +++ b/firmware/target/arm/rk27xx/usb-rk27xx.c | |||
@@ -32,20 +32,6 @@ int usb_status = USB_EXTRACTED; | |||
32 | 32 | ||
33 | void usb_init_device(void) | 33 | void usb_init_device(void) |
34 | { | 34 | { |
35 | /* enable UDC interrupt */ | ||
36 | INTC_IMR |= (1<<16); | ||
37 | INTC_IECR |= (1<<16); | ||
38 | |||
39 | EN_INT = EN_SUSP_INTR | /* Enable Suspend Interrupt */ | ||
40 | EN_RESUME_INTR | /* Enable Resume Interrupt */ | ||
41 | EN_USBRST_INTR | /* Enable USB Reset Interrupt */ | ||
42 | EN_OUT0_INTR | /* Enable OUT Token receive Interrupt EP0 */ | ||
43 | EN_IN0_INTR | /* Enable IN Token transmits Interrupt EP0 */ | ||
44 | EN_SETUP_INTR; /* Enable SETUP Packet Receive Interrupt */ | ||
45 | |||
46 | /* configure INTCON */ | ||
47 | INTCON = UDC_INTHIGH_ACT | /* interrupt high active */ | ||
48 | UDC_INTEN; /* enable EP0 interrupts */ | ||
49 | } | 35 | } |
50 | 36 | ||
51 | void usb_attach(void) | 37 | void usb_attach(void) |