summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/hwstub/stub/atj213x/usb_drv_atj213x.c246
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 @@
31volatile bool setup_data_valid = false; 31volatile bool setup_data_valid = false;
32volatile int udc_speed = USB_FULL_SPEED; 32volatile int udc_speed = USB_FULL_SPEED;
33 33
34struct endpoint_t
35{
36 void *buf;
37 int length;
38 bool zlp;
39 bool finished;
40};
41
42static volatile struct endpoint_t ep0in = {NULL,0,false,false};
43static volatile struct endpoint_t ep0out = {NULL,0,false,false};
44
45static void usb_copy_from(void *ptr, volatile void *reg, size_t sz) 34static 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
70void 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
81void usb_drv_init(void) 129void 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
138static 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 */
152int usb_drv_send(int endpoint, void *ptr, int length) 187int 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
176static 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 */
187int usb_drv_recv(int endpoint, void* ptr, int length) 219int 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
209void usb_drv_stall(int endpoint, bool stall, bool in) 253void usb_drv_stall(int endpoint, bool stall, bool in)
@@ -221,85 +265,3 @@ void usb_drv_stall(int endpoint, bool stall, bool in)
221void usb_drv_exit(void) 265void usb_drv_exit(void)
222{ 266{
223} 267}
224
225void 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}