diff options
-rw-r--r-- | utils/hwstub/stub/atj213x/usb_drv_atj213x.c | 246 |
1 files changed, 104 insertions, 142 deletions
diff --git a/utils/hwstub/stub/atj213x/usb_drv_atj213x.c b/utils/hwstub/stub/atj213x/usb_drv_atj213x.c index 0017378473..ef66766527 100644 --- a/utils/hwstub/stub/atj213x/usb_drv_atj213x.c +++ b/utils/hwstub/stub/atj213x/usb_drv_atj213x.c | |||
@@ -31,17 +31,6 @@ | |||
31 | volatile bool setup_data_valid = false; | 31 | volatile bool setup_data_valid = false; |
32 | volatile int udc_speed = USB_FULL_SPEED; | 32 | volatile int udc_speed = USB_FULL_SPEED; |
33 | 33 | ||
34 | struct endpoint_t | ||
35 | { | ||
36 | void *buf; | ||
37 | int length; | ||
38 | bool zlp; | ||
39 | bool finished; | ||
40 | }; | ||
41 | |||
42 | static volatile struct endpoint_t ep0in = {NULL,0,false,false}; | ||
43 | static volatile struct endpoint_t ep0out = {NULL,0,false,false}; | ||
44 | |||
45 | static void usb_copy_from(void *ptr, volatile void *reg, size_t sz) | 34 | static void usb_copy_from(void *ptr, volatile void *reg, size_t sz) |
46 | { | 35 | { |
47 | uint32_t *p = ptr; | 36 | uint32_t *p = ptr; |
@@ -78,6 +67,65 @@ static void usb_copy_to(volatile void *reg, void *ptr, size_t sz) | |||
78 | *rp++ = *p++; | 67 | *rp++ = *p++; |
79 | } | 68 | } |
80 | 69 | ||
70 | void INT_UDC(void) | ||
71 | { | ||
72 | /* get possible sources */ | ||
73 | unsigned int usbirq = OTG_USBIRQ; | ||
74 | unsigned int otgirq = OTG_OTGIRQ; | ||
75 | #if 0 | ||
76 | unsigned int usbeirq = OTG_USBEIRQ; | ||
77 | unsigned int epinirq = OTG_IN04IRQ; | ||
78 | unsigned int epoutirq = OTG_OUT04IRQ; | ||
79 | #endif | ||
80 | |||
81 | /* HS, Reset, Setup */ | ||
82 | if (usbirq) | ||
83 | { | ||
84 | |||
85 | if (usbirq & (1<<5)) | ||
86 | { | ||
87 | /* HS irq */ | ||
88 | udc_speed = USB_HIGH_SPEED; | ||
89 | } | ||
90 | else if (usbirq & (1<<4)) | ||
91 | { | ||
92 | /* Reset */ | ||
93 | udc_speed = USB_FULL_SPEED; | ||
94 | |||
95 | /* clear all pending irqs */ | ||
96 | OTG_OUT04IRQ = 0xff; | ||
97 | OTG_IN04IRQ = 0xff; | ||
98 | } | ||
99 | else if (usbirq & (1<<0)) | ||
100 | { | ||
101 | /* Setup data valid */ | ||
102 | setup_data_valid = true; | ||
103 | } | ||
104 | |||
105 | /* clear irq flags */ | ||
106 | OTG_USBIRQ = usbirq; | ||
107 | } | ||
108 | |||
109 | #if 0 | ||
110 | if (epoutirq) | ||
111 | { | ||
112 | OTG_OUT04IRQ = epoutirq; | ||
113 | } | ||
114 | |||
115 | if (epinirq) | ||
116 | { | ||
117 | OTG_IN04IRQ = epinirq; | ||
118 | } | ||
119 | #endif | ||
120 | |||
121 | if (otgirq) | ||
122 | { | ||
123 | OTG_OTGIRQ = otgirq; | ||
124 | } | ||
125 | |||
126 | OTG_USBEIRQ = 0x50; | ||
127 | } | ||
128 | |||
81 | void usb_drv_init(void) | 129 | void usb_drv_init(void) |
82 | { | 130 | { |
83 | OTG_USBCS |= 0x40; /* soft disconnect */ | 131 | OTG_USBCS |= 0x40; /* soft disconnect */ |
@@ -96,9 +144,9 @@ void usb_drv_init(void) | |||
96 | OTG_USBIEN = (1<<5) | (1<<4) | (1<<0); /* HS, Reset, Setup_data */ | 144 | OTG_USBIEN = (1<<5) | (1<<4) | (1<<0); /* HS, Reset, Setup_data */ |
97 | OTG_OTGIEN = 0; | 145 | OTG_OTGIEN = 0; |
98 | 146 | ||
99 | /* enable interrupts from ep0 */ | 147 | /* disable interrupts from ep0 */ |
100 | OTG_IN04IEN = 1; | 148 | OTG_IN04IEN = 0; |
101 | OTG_OUT04IEN = 1; | 149 | OTG_OUT04IEN = 0; |
102 | 150 | ||
103 | /* unmask UDC interrupt in interrupt controller */ | 151 | /* unmask UDC interrupt in interrupt controller */ |
104 | INTC_MSK = (1<<4); | 152 | INTC_MSK = (1<<4); |
@@ -135,75 +183,71 @@ void usb_drv_set_address(int address) | |||
135 | /* UDC sets this automaticaly */ | 183 | /* UDC sets this automaticaly */ |
136 | } | 184 | } |
137 | 185 | ||
138 | static void ep0_write(void) | ||
139 | { | ||
140 | int xfer_size = MIN(ep0in.length, 64); | ||
141 | |||
142 | /* copy data to UDC buffer */ | ||
143 | usb_copy_to(&OTG_EP0INDAT, ep0in.buf, xfer_size); | ||
144 | ep0in.buf += xfer_size; | ||
145 | ep0in.length -= xfer_size; | ||
146 | |||
147 | /* this marks data as ready to send */ | ||
148 | OTG_IN0BC = xfer_size; | ||
149 | } | ||
150 | |||
151 | /* TODO: Maybe adapt to irq scheme */ | 186 | /* TODO: Maybe adapt to irq scheme */ |
152 | int usb_drv_send(int endpoint, void *ptr, int length) | 187 | int usb_drv_send(int endpoint, void *ptr, int length) |
153 | { | 188 | { |
154 | (void)endpoint; | 189 | (void)endpoint; |
155 | 190 | ||
156 | if (length) | 191 | int xfer_size, cnt = length; |
192 | |||
193 | while (cnt) | ||
157 | { | 194 | { |
158 | ep0in.length = length; | 195 | xfer_size = MIN(cnt, 64); |
159 | ep0in.buf = ptr; | ||
160 | ep0in.zlp = (length % 64 == 0) ? true : false; | ||
161 | ep0in.finished = false; | ||
162 | 196 | ||
163 | ep0_write(); | 197 | /* copy data to ep0in buffer */ |
198 | usb_copy_to(&OTG_EP0INDAT, ptr, xfer_size); | ||
164 | 199 | ||
165 | while(!ep0in.finished) | 200 | /* this marks data as ready to send */ |
201 | OTG_IN0BC = xfer_size; | ||
202 | |||
203 | /* wait for the transfer end */ | ||
204 | while(OTG_EP0CS & 0x04) | ||
166 | ; | 205 | ; |
206 | |||
207 | cnt -= xfer_size; | ||
208 | ptr += xfer_size; | ||
167 | } | 209 | } |
168 | else | 210 | |
169 | { | 211 | /* ZLP stage */ |
212 | if((length % 64) == 0) | ||
170 | OTG_EP0CS = 2; | 213 | OTG_EP0CS = 2; |
171 | } | ||
172 | 214 | ||
173 | return 0; | 215 | return 0; |
174 | } | 216 | } |
175 | 217 | ||
176 | static int ep0_read(void) | ||
177 | { | ||
178 | int xfer_size = OTG_OUT0BC; | ||
179 | usb_copy_from(ep0out.buf, &OTG_EP0OUTDAT, xfer_size); | ||
180 | ep0out.buf += xfer_size; | ||
181 | ep0out.length -= xfer_size; | ||
182 | |||
183 | return xfer_size; | ||
184 | } | ||
185 | |||
186 | /* TODO: Maybe adapt to irq scheme */ | 218 | /* TODO: Maybe adapt to irq scheme */ |
187 | int usb_drv_recv(int endpoint, void* ptr, int length) | 219 | int usb_drv_recv(int endpoint, void* ptr, int length) |
188 | { | 220 | { |
189 | (void)endpoint; | 221 | (void)endpoint; |
222 | int xfer_size, cnt = 0; | ||
190 | 223 | ||
191 | ep0out.length = length; | 224 | while (cnt < length) |
192 | ep0out.buf = ptr; | 225 | { |
193 | ep0out.zlp = (length == 0) ? true : false; | 226 | /* Arm receiving buffer by writing |
194 | ep0out.finished = false; | 227 | * any value to OUT0BC. This sets |
228 | * OUT_BUSY bit in EP0CS until the data | ||
229 | * are correctly received and ACK'd | ||
230 | */ | ||
231 | OTG_OUT0BC = 0; | ||
232 | |||
233 | while (OTG_EP0CS & 0x08) | ||
234 | ; | ||
195 | 235 | ||
196 | /* Arm receiving buffer by writing | 236 | xfer_size = OTG_OUT0BC; |
197 | * any value to OUT0BC. This sets | ||
198 | * OUT_BUSY bit in EP0CS until the data | ||
199 | * are correctly received and ACK'd | ||
200 | */ | ||
201 | OTG_OUT0BC = 0; | ||
202 | 237 | ||
203 | while (!ep0out.finished) | 238 | usb_copy_from(ptr, &OTG_EP0OUTDAT, xfer_size); |
204 | ; | 239 | cnt += xfer_size; |
240 | ptr += xfer_size; | ||
241 | |||
242 | if (xfer_size < 64) | ||
243 | break; | ||
244 | } | ||
205 | 245 | ||
206 | return (length - ep0out.length); | 246 | /* ZLP stage */ |
247 | if (length == 0) | ||
248 | OTG_EP0CS = 2; | ||
249 | |||
250 | return cnt; | ||
207 | } | 251 | } |
208 | 252 | ||
209 | void usb_drv_stall(int endpoint, bool stall, bool in) | 253 | void usb_drv_stall(int endpoint, bool stall, bool in) |
@@ -221,85 +265,3 @@ void usb_drv_stall(int endpoint, bool stall, bool in) | |||
221 | void usb_drv_exit(void) | 265 | void usb_drv_exit(void) |
222 | { | 266 | { |
223 | } | 267 | } |
224 | |||
225 | void INT_UDC(void) | ||
226 | { | ||
227 | /* get possible sources */ | ||
228 | unsigned int usbirq = OTG_USBIRQ; | ||
229 | unsigned int otgirq = OTG_OTGIRQ; | ||
230 | unsigned int epinirq = OTG_IN04IRQ; | ||
231 | unsigned int epoutirq = OTG_OUT04IRQ; | ||
232 | |||
233 | /* HS, Reset, Setup */ | ||
234 | if (usbirq) | ||
235 | { | ||
236 | |||
237 | if (usbirq & (1<<5)) | ||
238 | { | ||
239 | /* HS irq */ | ||
240 | udc_speed = USB_HIGH_SPEED; | ||
241 | } | ||
242 | else if (usbirq & (1<<4)) | ||
243 | { | ||
244 | /* Reset */ | ||
245 | udc_speed = USB_FULL_SPEED; | ||
246 | |||
247 | /* clear all pending irqs */ | ||
248 | OTG_OUT04IRQ = 0xff; | ||
249 | OTG_IN04IRQ = 0xff; | ||
250 | } | ||
251 | else if (usbirq & (1<<0)) | ||
252 | { | ||
253 | /* Setup data valid */ | ||
254 | setup_data_valid = true; | ||
255 | } | ||
256 | |||
257 | /* clear irq flags */ | ||
258 | OTG_USBIRQ = usbirq; | ||
259 | } | ||
260 | |||
261 | if (epoutirq) | ||
262 | { | ||
263 | if (ep0_read() == 64) | ||
264 | { | ||
265 | /* rearm receive buffer */ | ||
266 | OTG_OUT0BC = 0; | ||
267 | } | ||
268 | else | ||
269 | { | ||
270 | if (ep0out.length == 0 && ep0out.zlp) | ||
271 | { | ||
272 | OTG_EP0CS = 2; | ||
273 | } | ||
274 | ep0out.finished = true; | ||
275 | } | ||
276 | OTG_OUT04IRQ = epoutirq; | ||
277 | } | ||
278 | |||
279 | if (epinirq) | ||
280 | { | ||
281 | if (ep0in.length) | ||
282 | { | ||
283 | ep0_write(); | ||
284 | } | ||
285 | else | ||
286 | { | ||
287 | if (ep0in.zlp) | ||
288 | { | ||
289 | OTG_EP0CS = 2; | ||
290 | } | ||
291 | |||
292 | ep0in.finished = true; | ||
293 | } | ||
294 | |||
295 | /* ack interrupt */ | ||
296 | OTG_IN04IRQ = epinirq; | ||
297 | } | ||
298 | |||
299 | if (otgirq) | ||
300 | { | ||
301 | OTG_OTGIRQ = otgirq; | ||
302 | } | ||
303 | |||
304 | OTG_USBEIRQ = 0x50; | ||
305 | } | ||