diff options
Diffstat (limited to 'utils/hwstub/stub')
-rw-r--r-- | utils/hwstub/stub/atj213x/usb_drv_atj213x.c | 246 |
1 files changed, 142 insertions, 104 deletions
diff --git a/utils/hwstub/stub/atj213x/usb_drv_atj213x.c b/utils/hwstub/stub/atj213x/usb_drv_atj213x.c index ef66766527..0017378473 100644 --- a/utils/hwstub/stub/atj213x/usb_drv_atj213x.c +++ b/utils/hwstub/stub/atj213x/usb_drv_atj213x.c | |||
@@ -31,6 +31,17 @@ | |||
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 | |||
34 | static void usb_copy_from(void *ptr, volatile void *reg, size_t sz) | 45 | static void usb_copy_from(void *ptr, volatile void *reg, size_t sz) |
35 | { | 46 | { |
36 | uint32_t *p = ptr; | 47 | uint32_t *p = ptr; |
@@ -67,65 +78,6 @@ static void usb_copy_to(volatile void *reg, void *ptr, size_t sz) | |||
67 | *rp++ = *p++; | 78 | *rp++ = *p++; |
68 | } | 79 | } |
69 | 80 | ||
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 | |||
129 | void usb_drv_init(void) | 81 | void usb_drv_init(void) |
130 | { | 82 | { |
131 | OTG_USBCS |= 0x40; /* soft disconnect */ | 83 | OTG_USBCS |= 0x40; /* soft disconnect */ |
@@ -144,9 +96,9 @@ void usb_drv_init(void) | |||
144 | OTG_USBIEN = (1<<5) | (1<<4) | (1<<0); /* HS, Reset, Setup_data */ | 96 | OTG_USBIEN = (1<<5) | (1<<4) | (1<<0); /* HS, Reset, Setup_data */ |
145 | OTG_OTGIEN = 0; | 97 | OTG_OTGIEN = 0; |
146 | 98 | ||
147 | /* disable interrupts from ep0 */ | 99 | /* enable interrupts from ep0 */ |
148 | OTG_IN04IEN = 0; | 100 | OTG_IN04IEN = 1; |
149 | OTG_OUT04IEN = 0; | 101 | OTG_OUT04IEN = 1; |
150 | 102 | ||
151 | /* unmask UDC interrupt in interrupt controller */ | 103 | /* unmask UDC interrupt in interrupt controller */ |
152 | INTC_MSK = (1<<4); | 104 | INTC_MSK = (1<<4); |
@@ -183,71 +135,75 @@ void usb_drv_set_address(int address) | |||
183 | /* UDC sets this automaticaly */ | 135 | /* UDC sets this automaticaly */ |
184 | } | 136 | } |
185 | 137 | ||
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 | |||
186 | /* TODO: Maybe adapt to irq scheme */ | 151 | /* TODO: Maybe adapt to irq scheme */ |
187 | int usb_drv_send(int endpoint, void *ptr, int length) | 152 | int usb_drv_send(int endpoint, void *ptr, int length) |
188 | { | 153 | { |
189 | (void)endpoint; | 154 | (void)endpoint; |
190 | 155 | ||
191 | int xfer_size, cnt = length; | 156 | if (length) |
192 | |||
193 | while (cnt) | ||
194 | { | 157 | { |
195 | xfer_size = MIN(cnt, 64); | 158 | ep0in.length = length; |
159 | ep0in.buf = ptr; | ||
160 | ep0in.zlp = (length % 64 == 0) ? true : false; | ||
161 | ep0in.finished = false; | ||
196 | 162 | ||
197 | /* copy data to ep0in buffer */ | 163 | ep0_write(); |
198 | usb_copy_to(&OTG_EP0INDAT, ptr, xfer_size); | ||
199 | 164 | ||
200 | /* this marks data as ready to send */ | 165 | while(!ep0in.finished) |
201 | OTG_IN0BC = xfer_size; | ||
202 | |||
203 | /* wait for the transfer end */ | ||
204 | while(OTG_EP0CS & 0x04) | ||
205 | ; | 166 | ; |
206 | |||
207 | cnt -= xfer_size; | ||
208 | ptr += xfer_size; | ||
209 | } | 167 | } |
210 | 168 | else | |
211 | /* ZLP stage */ | 169 | { |
212 | if((length % 64) == 0) | ||
213 | OTG_EP0CS = 2; | 170 | OTG_EP0CS = 2; |
171 | } | ||
214 | 172 | ||
215 | return 0; | 173 | return 0; |
216 | } | 174 | } |
217 | 175 | ||
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 | |||
218 | /* TODO: Maybe adapt to irq scheme */ | 186 | /* TODO: Maybe adapt to irq scheme */ |
219 | int usb_drv_recv(int endpoint, void* ptr, int length) | 187 | int usb_drv_recv(int endpoint, void* ptr, int length) |
220 | { | 188 | { |
221 | (void)endpoint; | 189 | (void)endpoint; |
222 | int xfer_size, cnt = 0; | ||
223 | 190 | ||
224 | while (cnt < length) | 191 | ep0out.length = length; |
225 | { | 192 | ep0out.buf = ptr; |
226 | /* Arm receiving buffer by writing | 193 | ep0out.zlp = (length == 0) ? true : false; |
227 | * any value to OUT0BC. This sets | 194 | ep0out.finished = false; |
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 | ; | ||
235 | 195 | ||
236 | xfer_size = OTG_OUT0BC; | 196 | /* Arm receiving buffer by writing |
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; | ||
237 | 202 | ||
238 | usb_copy_from(ptr, &OTG_EP0OUTDAT, xfer_size); | 203 | while (!ep0out.finished) |
239 | cnt += xfer_size; | 204 | ; |
240 | ptr += xfer_size; | ||
241 | |||
242 | if (xfer_size < 64) | ||
243 | break; | ||
244 | } | ||
245 | 205 | ||
246 | /* ZLP stage */ | 206 | return (length - ep0out.length); |
247 | if (length == 0) | ||
248 | OTG_EP0CS = 2; | ||
249 | |||
250 | return cnt; | ||
251 | } | 207 | } |
252 | 208 | ||
253 | void usb_drv_stall(int endpoint, bool stall, bool in) | 209 | void usb_drv_stall(int endpoint, bool stall, bool in) |
@@ -265,3 +221,85 @@ void usb_drv_stall(int endpoint, bool stall, bool in) | |||
265 | void usb_drv_exit(void) | 221 | void usb_drv_exit(void) |
266 | { | 222 | { |
267 | } | 223 | } |
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 | } | ||