1 /*
2  * Copyright (c) 2015 Brian Swetland
3  * Copyright (c) 2008 Google, Inc.
4  *
5  * Use of this source code is governed by a MIT-style
6  * license that can be found in the LICENSE file or at
7  * https://opensource.org/licenses/MIT
8  */
9 
10 #include <string.h>
11 #include <stdlib.h>
12 #include <printf.h>
13 #include <assert.h>
14 #include <lk/debug.h>
15 #include <lk/reg.h>
16 #include <arch/arm/cm.h>
17 #include <kernel/thread.h>
18 #include <kernel/spinlock.h>
19 
20 #include <platform/lpc43xx-usb.h>
21 static_assert(sizeof(usb_dqh_t) == 64, "");
22 static_assert(sizeof(usb_dtd_t) == 32, "");
23 
24 #include <dev/udc.h>
25 
26 #include "udc-common.h"
27 
28 #define F_LL_INIT   1
29 #define F_UDC_INIT  2
30 
31 // NOTE: I cheat a bit with the locking because this is a UP Cortex-M
32 // NOTE: device.  I use spinlocks for code that might be called from
33 // NOTE: userspace or irq context, but for the irq-only code I don't
34 // NOTE: bother with locking because it's impossible for it to execute
35 // NOTE: while the lock is held from userspace.
36 
37 typedef struct {
38     u32 base;
39     spin_lock_t lock;
40 
41     usb_dqh_t *qh;
42     usb_dtd_t *dtd_freelist;
43 
44     udc_endpoint_t *ep0in;
45     udc_endpoint_t *ep0out;
46     udc_request_t *ep0req;
47     u8 txd[8];
48     u8 rxd[8];
49 
50     udc_endpoint_t *ept_list;
51     uint8_t online;
52     uint8_t highspeed;
53     uint8_t config_value;
54     uint8_t flags;
55 
56     udc_device_t *device;
57     udc_gadget_t *gadget;
58 
59     uint32_t ept_alloc_table;
60 } usb_t;
61 
62 static usb_t USB;
63 
64 typedef struct usb_request {
65     udc_request_t req;
66     struct usb_request *next;
67     usb_dtd_t *dtd;
68 } usb_request_t;
69 
70 struct udc_endpoint {
71     udc_endpoint_t *next;
72     usb_dqh_t *head;
73     usb_request_t *req;
74     usb_request_t *last;
75     usb_t *usb;
76     uint32_t bit;
77     uint16_t maxpkt;
78     uint8_t num;
79     uint8_t in;
80 };
81 
82 // ---- endpoint management
83 
84 #if 1
85 #define DBG(x...) do {} while(0)
86 #else
87 #define DBG(x...) dprintf(INFO, x)
88 #endif
89 
_udc_endpoint_alloc(usb_t * usb,unsigned num,unsigned in,unsigned max_pkt)90 static udc_endpoint_t *_udc_endpoint_alloc(usb_t *usb,
91         unsigned num, unsigned in, unsigned max_pkt) {
92     udc_endpoint_t *ept;
93     unsigned cfg;
94 
95     ept = malloc(sizeof(*ept));
96     ept->maxpkt = max_pkt;
97     ept->num = num;
98     ept->in = !!in;
99     ept->req = 0;
100     ept->last = 0;
101     ept->usb = usb;
102 
103     cfg = DQH_CFG_MAXPKT(max_pkt) | DQH_CFG_ZLT;
104 
105     if (ept->in) {
106         ept->bit = EPT_TX(ept->num);
107     } else {
108         ept->bit = EPT_RX(ept->num);
109         if (num == 0) {
110             cfg |= DQH_CFG_IOS;
111         }
112     }
113 
114     ept->head = usb->qh + (num * 2) + (ept->in);
115     ept->head->config = cfg;
116     ept->next = usb->ept_list;
117     usb->ept_list = ept;
118 
119     DBG("ept%d %s @%p/%p max=%d bit=%x\n",
120         num, in ? "in":"out", ept, ept->head, max_pkt, ept->bit);
121 
122     return ept;
123 }
124 
udc_endpoint_alloc(unsigned type,unsigned maxpkt)125 udc_endpoint_t *udc_endpoint_alloc(unsigned type, unsigned maxpkt) {
126     udc_endpoint_t *ept;
127     unsigned n;
128     unsigned in = !!(type & 0x80);
129 
130     if (!(USB.flags & F_UDC_INIT)) {
131         panic("udc_init() must be called before udc_endpoint_alloc()\n");
132     }
133 
134     for (n = 1; n < 6; n++) {
135         unsigned bit = in ? EPT_TX(n) : EPT_RX(n);
136         if (USB.ept_alloc_table & bit) {
137             continue;
138         }
139         if ((ept = _udc_endpoint_alloc(&USB, n, in, maxpkt))) {
140             USB.ept_alloc_table |= bit;
141         }
142         return ept;
143     }
144     return 0;
145 }
146 
udc_endpoint_free(struct udc_endpoint * ept)147 void udc_endpoint_free(struct udc_endpoint *ept) {
148     // todo
149 }
150 
151 static void handle_ept_complete(struct udc_endpoint *ept);
152 
endpoint_flush(usb_t * usb,udc_endpoint_t * ept)153 static void endpoint_flush(usb_t *usb, udc_endpoint_t *ept) {
154     if (ept->req) {
155         // flush outstanding transfers
156         writel(ept->bit, usb->base + USB_ENDPTFLUSH);
157         while (readl(usb->base + USB_ENDPTFLUSH)) ;
158         while (ept->req) {
159             handle_ept_complete(ept);
160         }
161     }
162 }
163 
endpoint_reset(usb_t * usb,udc_endpoint_t * ept)164 static void endpoint_reset(usb_t *usb, udc_endpoint_t *ept) {
165     unsigned n = readl(usb->base + USB_ENDPTCTRL(ept->num));
166     n |= ept->in ? EPCTRL_TXR : EPCTRL_RXR;
167     writel(n, usb->base + USB_ENDPTCTRL(ept->num));
168 }
169 
endpoint_enable(usb_t * usb,udc_endpoint_t * ept,unsigned yes)170 static void endpoint_enable(usb_t *usb, udc_endpoint_t *ept, unsigned yes) {
171     unsigned n = readl(usb->base + USB_ENDPTCTRL(ept->num));
172 
173     if (yes) {
174         if (ept->in) {
175             n |= (EPCTRL_TXE | EPCTRL_TXR | EPCTRL_TX_BULK);
176         } else {
177             n |= (EPCTRL_RXE | EPCTRL_RXR | EPCTRL_RX_BULK);
178         }
179 
180         if (ept->num != 0) {
181             // todo: support non-max-sized packet sizes
182             if (usb->highspeed) {
183                 ept->head->config = DQH_CFG_MAXPKT(512) | DQH_CFG_ZLT;
184             } else {
185                 ept->head->config = DQH_CFG_MAXPKT(64) | DQH_CFG_ZLT;
186             }
187         }
188     }
189     writel(n, usb->base + USB_ENDPTCTRL(ept->num));
190 }
191 
192 // ---- request management
193 
udc_request_alloc(void)194 udc_request_t *udc_request_alloc(void) {
195     spin_lock_saved_state_t state;
196     usb_request_t *req;
197     if ((req = malloc(sizeof(*req))) == NULL) {
198         return NULL;
199     }
200 
201     spin_lock_irqsave(&USB.lock, state);
202     if (USB.dtd_freelist == NULL) {
203         spin_unlock_irqrestore(&USB.lock, state);
204         free(req);
205         return NULL;
206     } else {
207         req->dtd = USB.dtd_freelist;
208         USB.dtd_freelist = req->dtd->next;
209         spin_unlock_irqrestore(&USB.lock, state);
210 
211         req->req.buffer = 0;
212         req->req.length = 0;
213         return &req->req;
214     }
215 }
216 
udc_request_free(struct udc_request * req)217 void udc_request_free(struct udc_request *req) {
218     // todo: check if active?
219     free(req);
220 }
221 
udc_request_queue(udc_endpoint_t * ept,struct udc_request * _req)222 int udc_request_queue(udc_endpoint_t *ept, struct udc_request *_req) {
223     spin_lock_saved_state_t state;
224     usb_request_t *req = (usb_request_t *) _req;
225     usb_dtd_t *dtd = req->dtd;
226     unsigned phys = (unsigned) req->req.buffer;
227     int ret = 0;
228 
229     dtd->next_dtd = 1; // terminate bit
230     dtd->config = DTD_LEN(req->req.length) | DTD_IOC | DTD_ACTIVE;
231     dtd->bptr0 = phys;
232     phys &= 0xfffff000;
233     dtd->bptr1 = phys + 0x1000;
234     dtd->bptr2 = phys + 0x2000;
235     dtd->bptr3 = phys + 0x3000;
236     dtd->bptr4 = phys + 0x4000;
237 
238     req->next = 0;
239     spin_lock_irqsave(&ept->usb->lock, state);
240     if (!USB.online && ept->num) {
241         ret = -1;
242     } else if (ept->req) {
243         // already a transfer in flight, add us to the list
244         // we'll get queue'd by the irq handler when it's our turn
245         ept->last->next = req;
246     } else {
247         ept->head->next_dtd = (unsigned) dtd;
248         ept->head->dtd_config = 0;
249         DSB;
250         writel(ept->bit, ept->usb->base + USB_ENDPTPRIME);
251         ept->req = req;
252     }
253     ept->last = req;
254     spin_unlock_irqrestore(&ept->usb->lock, state);
255 
256     DBG("ept%d %s queue req=%p\n", ept->num, ept->in ? "in" : "out", req);
257     return ret;
258 }
259 
handle_ept_complete(struct udc_endpoint * ept)260 static void handle_ept_complete(struct udc_endpoint *ept) {
261     usb_request_t *req;
262     usb_dtd_t *dtd;
263     unsigned actual;
264     int status;
265 
266     DBG("ept%d %s complete req=%p\n",
267         ept->num, ept->in ? "in" : "out", ept->req);
268 
269     if ((req = ept->req)) {
270         if (req->next) {
271             // queue next req to hw
272             ept->head->next_dtd = (unsigned) req->next->dtd;
273             ept->head->dtd_config = 0;
274             DSB;
275             writel(ept->bit, ept->usb->base + USB_ENDPTPRIME);
276             ept->req = req->next;
277         } else {
278             ept->req = 0;
279             ept->last = 0;
280         }
281         dtd = req->dtd;
282         if (dtd->config & 0xff) {
283             actual = 0;
284             status = -1;
285             dprintf(INFO, "EP%d/%s FAIL nfo=%x pg0=%x\n",
286                     ept->num, ept->in ? "in" : "out", dtd->config, dtd->bptr0);
287         } else {
288             actual = req->req.length - ((dtd->config >> 16) & 0x7fff);
289             status = 0;
290         }
291         if (req->req.complete) {
292             req->req.complete(&req->req, actual, status);
293         }
294     }
295 }
296 
setup_ack(usb_t * usb)297 static void setup_ack(usb_t *usb) {
298     usb->ep0req->complete = 0;
299     usb->ep0req->length = 0;
300     udc_request_queue(usb->ep0in, usb->ep0req);
301 }
302 
ep0in_complete(struct udc_request * req,unsigned actual,int status)303 static void ep0in_complete(struct udc_request *req, unsigned actual, int status) {
304     usb_t *usb = (usb_t *) req->context;
305     DBG("ep0in_complete %p %d %d\n", req, actual, status);
306     if (status == 0) {
307         req->length = 0;
308         req->complete = 0;
309         udc_request_queue(usb->ep0out, req);
310     }
311 }
312 
setup_tx(usb_t * usb,void * buf,unsigned len)313 static void setup_tx(usb_t *usb, void *buf, unsigned len) {
314     DBG("setup_tx %p %d\n", buf, len);
315     usb->ep0req->buffer = buf;
316     usb->ep0req->complete = ep0in_complete;
317     usb->ep0req->length = len;
318     udc_request_queue(usb->ep0in, usb->ep0req);
319 }
320 
notify_gadgets(udc_gadget_t * gadget,unsigned event)321 static void notify_gadgets(udc_gadget_t *gadget, unsigned event) {
322     while (gadget) {
323         if (gadget->notify) {
324             gadget->notify(gadget, event);
325         }
326         gadget = gadget->next;
327     }
328 }
329 
330 #define SETUP(type,request) (((type) << 8) | (request))
331 
handle_setup(usb_t * usb)332 static void handle_setup(usb_t *usb) {
333     union setup_packet s;
334 
335     // setup procedure, per databook
336     // a. clear setup status by writing and waiting for 0 (1-2uS)
337     writel(1, usb->base + USB_ENDPTSETUPSTAT);
338     while (readl(usb->base + USB_ENDPTSETUPSTAT) & 1) ;
339     do {
340         // b. write 1 to tripwire
341         writel(CMD_RUN | CMD_SUTW, usb->base + USB_CMD);
342         // c. extract setup data
343         s.w0 = usb->qh[0].setup0;
344         s.w1 = usb->qh[0].setup1;
345         // d. if tripwire clear, retry
346     } while ((readl(usb->base + USB_CMD) & CMD_SUTW) == 0);
347     // e. clear tripwire
348     writel(CMD_RUN, usb->base + USB_CMD);
349     // flush any pending io from previous setup transactions
350     usb->ep0in->req = 0;
351     usb->ep0out->req = 0;
352     // f. process packet
353     // g. ensure setup status is 0
354 
355     DBG("setup 0x%02x 0x%02x %d %d %d\n",
356         s.type, s.request, s.value, s.index, s.length);
357 
358     switch (SETUP(s.type,s.request)) {
359         case SETUP(DEVICE_READ, GET_STATUS): {
360             static unsigned zero = 0;
361             if (s.length == 2) {
362                 setup_tx(usb, &zero, 2);
363                 return;
364             }
365             break;
366         }
367         case SETUP(DEVICE_READ, GET_DESCRIPTOR): {
368             struct udc_descriptor *desc = udc_descriptor_find(s.value);
369             if (desc) {
370                 unsigned len = desc->len;
371                 if (len > s.length) len = s.length;
372                 setup_tx(usb, desc->data, len);
373                 return;
374             }
375             break;
376         }
377         case SETUP(DEVICE_READ, GET_CONFIGURATION):
378             if ((s.value == 0) && (s.index == 0) && (s.length == 1)) {
379                 setup_tx(usb, &usb->config_value, 1);
380                 return;
381             }
382             break;
383         case SETUP(DEVICE_WRITE, SET_CONFIGURATION):
384             if (s.value == 1) {
385                 struct udc_endpoint *ept;
386                 /* enable endpoints */
387                 for (ept = usb->ept_list; ept; ept = ept->next) {
388                     if (ept->num != 0) {
389                         endpoint_enable(usb, ept, 1);
390                     }
391                 }
392                 usb->config_value = 1;
393                 notify_gadgets(usb->gadget, UDC_EVENT_ONLINE);
394             } else {
395                 writel(0, usb->base + USB_ENDPTCTRL(1));
396                 usb->config_value = 0;
397                 notify_gadgets(usb->gadget, UDC_EVENT_OFFLINE);
398             }
399             setup_ack(usb);
400             usb->online = s.value ? 1 : 0;
401             return;
402         case SETUP(DEVICE_WRITE, SET_ADDRESS):
403             // write address delayed (will take effect after the next IN txn)
404             writel(((s.value & 0x7F) << 25) | (1 << 24), usb->base + USB_DEVICEADDR);
405             setup_ack(usb);
406             return;
407         case SETUP(INTERFACE_WRITE, SET_INTERFACE):
408             goto stall;
409         case SETUP(ENDPOINT_WRITE, CLEAR_FEATURE): {
410             udc_endpoint_t *ept;
411             unsigned num = s.index & 15;
412             unsigned in = !!(s.index & 0x80);
413 
414             if ((s.value != 0) || (s.length != 0)) {
415                 break;
416             }
417             DBG("clr feat %d %d\n", num, in);
418             for (ept = usb->ept_list; ept; ept = ept->next) {
419                 if ((ept->num == num) && (ept->in == in)) {
420                     endpoint_flush(usb, ept);
421                     // todo: if callback requeues this could be ugly...
422                     endpoint_reset(usb, ept);
423                     setup_ack(usb);
424                     return;
425                 }
426             }
427             break;
428         }
429     }
430 
431     dprintf(INFO, "udc: stall %02x %02x %04x %04x %04x\n",
432             s.type, s.request, s.value, s.index, s.length);
433 
434 stall:
435     writel(EPCTRL_RXS | EPCTRL_TXS, usb->base + USB_ENDPTCTRL(0));
436 }
437 
lpc43xx_usb_init(u32 dmabase,size_t dmasize)438 int lpc43xx_usb_init(u32 dmabase, size_t dmasize) {
439     usb_t *usb = &USB;
440     printf("usb_init()\n");
441     if ((dmabase & 0x7FF) || (dmasize < 1024)) {
442         return -1;
443     }
444     usb->qh = (void *) dmabase;
445     usb->dtd_freelist = NULL;
446     memset(usb->qh, 0, dmasize);
447     usb->base = USB0_BASE;
448     dmabase += 768;
449     dmasize -= 768;
450     while (dmasize > sizeof(usb_dtd_t)) {
451         usb_dtd_t *dtd = (void *) dmabase;
452         dtd->next = usb->dtd_freelist;
453         usb->dtd_freelist = dtd;
454         dmabase += sizeof(usb_dtd_t);
455         dmasize -= sizeof(usb_dtd_t);
456     }
457     writel(CMD_RST, usb->base + USB_CMD);
458     while (readl(usb->base + USB_CMD) & CMD_RST) ;
459     printf("usb_init(): reset ok\n");
460     thread_sleep(250);
461 
462     // enable USB0 PHY via CREG0
463     writel(readl(0x40043004) & (~0x20), 0x40043004);
464 
465     writel(MODE_DEVICE | MODE_SLOM, usb->base + USB_MODE);
466 
467     // enable termination in OTG control (required for device mode)
468     writel(OTG_OT, usb->base + USB_OTGSC);
469 
470     writel((u32) usb->qh, usb->base + USB_ENDPOINTLISTADDR);
471     usb->flags |= F_LL_INIT;
472     return 0;
473 }
474 
usb_enable(usb_t * usb,int yes)475 static void usb_enable(usb_t *usb, int yes) {
476     if (yes) {
477         writel(INTR_UE | INTR_UEE | INTR_PCE | INTR_SEE | INTR_URE,
478                usb->base + USB_INTR);
479 
480         writel(CMD_RUN, usb->base + USB_CMD);
481         NVIC_EnableIRQ(USB0_IRQn);
482     } else {
483         NVIC_DisableIRQ(USB0_IRQn);
484         writel(CMD_STOP, usb->base + USB_CMD);
485     }
486 }
487 
488 
lpc43xx_USB0_IRQ(void)489 void lpc43xx_USB0_IRQ(void) {
490     udc_endpoint_t *ept;
491     usb_t *usb = &USB;
492     int ret = 0;
493     unsigned n;
494 
495     arm_cm_irq_entry();
496 
497     n = readl(usb->base + USB_STS);
498     writel(n, usb->base + USB_STS);
499 
500     if (n & STS_URI) {
501         // reset procedure, per databook
502         // 1. clear setup token semaphores
503         writel(readl(usb->base + USB_ENDPTSETUPSTAT),
504                usb->base + USB_ENDPTSETUPSTAT);
505         // 2. clear completion status bits
506         writel(readl(usb->base + USB_ENDPTCOMPLETE),
507                usb->base + USB_ENDPTCOMPLETE);
508         // 3. cancel primed transfers
509         while (readl(usb->base + USB_ENDPTPRIME)) ;
510         writel(0xFFFFFFFF, usb->base + USB_ENDPTFLUSH);
511         // 4. ensure we finished while reset still active
512         if (!(readl(usb->base + USB_PORTSC1) & PORTSC1_RC)) {
513             printf("usb: failed to reset in time\n");
514         }
515         // 5. free active DTDs
516         usb->online = 0;
517         usb->config_value = 0;
518         notify_gadgets(usb->gadget, UDC_EVENT_OFFLINE);
519         for (ept = usb->ept_list; ept; ept = ept->next) {
520             if (ept->req) {
521                 ept->req->dtd->config = DTD_HALTED;
522                 handle_ept_complete(ept);
523             }
524         }
525     }
526     if (n & STS_PCI) {
527         unsigned x = readl(usb->base + USB_PORTSC1);
528         usb->highspeed = (x & PORTSC1_HSP) ? 1 : 0;
529     }
530     if (n & (STS_UI | STS_UEI)) {
531         if (readl(usb->base + USB_ENDPTSETUPSTAT) & 1) {
532             handle_setup(usb);
533         }
534         n = readl(usb->base + USB_ENDPTCOMPLETE);
535         writel(n, usb->base + USB_ENDPTCOMPLETE);
536 
537         for (ept = usb->ept_list; ept; ept = ept->next) {
538             if (n & ept->bit) {
539                 handle_ept_complete(ept);
540                 ret = INT_RESCHEDULE;
541             }
542         }
543     }
544     if (n & STS_SEI) {
545         panic("<SEI>");
546     }
547     arm_cm_irq_exit(ret);
548 }
549 
550 // ---- UDC API
551 
udc_init(struct udc_device * dev)552 int udc_init(struct udc_device *dev) {
553     USB.device = dev;
554     USB.ep0out = _udc_endpoint_alloc(&USB, 0, 0, 64);
555     USB.ep0in = _udc_endpoint_alloc(&USB, 0, 1, 64);
556     USB.ep0req = udc_request_alloc();
557     USB.ep0req->context = &USB;
558     USB.flags |= F_UDC_INIT;
559     return 0;
560 }
561 
udc_register_gadget(udc_gadget_t * gadget)562 int udc_register_gadget(udc_gadget_t *gadget) {
563     if (USB.gadget) {
564         udc_gadget_t *last = USB.gadget;
565         while (last->next) {
566             last = last->next;
567         }
568         last->next = gadget;
569     } else {
570         USB.gadget = gadget;
571     }
572     gadget->next = NULL;
573     return 0;
574 }
575 
udc_ept_desc_fill(udc_endpoint_t * ept,unsigned char * data)576 void udc_ept_desc_fill(udc_endpoint_t *ept, unsigned char *data) {
577     data[0] = 7;
578     data[1] = TYPE_ENDPOINT;
579     data[2] = ept->num | (ept->in ? 0x80 : 0x00);
580     data[3] = 0x02; // bulk -- the only kind we support
581     data[4] = ept->maxpkt;
582     data[5] = ept->maxpkt >> 8;
583     data[6] = ept->in ? 0x00 : 0x01;
584 }
585 
udc_start(void)586 int udc_start(void) {
587     usb_t *usb = &USB;
588 
589     dprintf(INFO, "udc_start()\n");
590     if (!(usb->flags & F_LL_INIT)) {
591         panic("udc cannot start before hw init\n");
592     }
593     if (!usb->device) {
594         panic("udc cannot start before init\n");
595     }
596     if (!usb->gadget) {
597         panic("udc has no gadget registered\n");
598     }
599     udc_create_descriptors(usb->device, usb->gadget);
600 
601     usb_enable(usb, 1);
602     return 0;
603 }
604 
udc_stop(void)605 int udc_stop(void) {
606     usb_enable(&USB, 0);
607     thread_sleep(10);
608     return 0;
609 }
610 
611