static struct USB_BD_t *
usb_get_bd(struct usbd_ep_pipe_state_t *s)
{
- return (&bdt[(s->ep_num << 2) | (s->ep_dir << 1) | s->pingpong]);
+ return (&bdt[(s->ep_num << 2) | (s->ep_dir << 1) | s->pingpong]);
}
static struct USB_BD_t *
usb_get_bd_stat(struct USB_STAT_t *stat)
{
- return (((void *)(uintptr_t)bdt + (stat->raw << 1)));
+ return (((void *)(uintptr_t)bdt + (stat->raw << 1)));
}
void *usb_get_xfer_data(struct usb_xfer_info *i)
{
- return (usb_get_bd_stat(i)->addr);
+ return (usb_get_bd_stat(i)->addr);
}
enum usb_tok_pid usb_get_xfer_pid(struct usb_xfer_info *i)
{
- return (usb_get_bd_stat(i)->tok_pid);
+ return (usb_get_bd_stat(i)->tok_pid);
}
int usb_get_xfer_ep(struct usb_xfer_info *i)
{
- return (i->ep);
+ return (i->ep);
}
enum usb_ep_dir usb_get_xfer_dir(struct usb_xfer_info *i)
{
- return (i->dir);
+ return (i->dir);
}
void usb_enable_xfers(void)
{
- USB0.ctl.raw = ((struct USB_CTL_t){
- .txd_suspend = 0,
- .usben = 1
- }).raw;
+ USB0.ctl.raw = ((struct USB_CTL_t){
+ .txd_suspend = 0,
+ .usben = 1
+ }).raw;
}
void usb_set_addr(int addr)
{
- USB0.addr.raw = addr;
+ USB0.addr.raw = addr;
}
void usb_pipe_stall(struct usbd_ep_pipe_state_t *s)
{
- volatile struct USB_BD_t *bd = usb_get_bd(s);
- bd->raw = ((struct USB_BD_BITS_t){
- .stall = 1,
- .own = 1
- }).raw;
+ volatile struct USB_BD_t *bd = usb_get_bd(s);
+ bd->raw = ((struct USB_BD_BITS_t){
+ .stall = 1,
+ .own = 1
+ }).raw;
}
void usb_pipe_unstall(struct usbd_ep_pipe_state_t *s)
{
- volatile struct USB_BD_t *bd = usb_get_bd(s);
- struct USB_BD_BITS_t state = { .raw = bd->raw };
+ volatile struct USB_BD_t *bd = usb_get_bd(s);
+ struct USB_BD_BITS_t state = { .raw = bd->raw };
- if (state.own && state.stall)
- bd->raw = 0;
+ if (state.own && state.stall)
+ bd->raw = 0;
}
void usb_pipe_enable(struct usbd_ep_pipe_state_t *s)
{
- USB0.endpt[s->ep_num].raw |= ((struct USB_ENDPT_t){
- .eptxen = s->ep_dir == USB_EP_TX,
- .eprxen = s->ep_dir == USB_EP_RX,
- .ephshk = 1, /* XXX ISO */
- .epctldis = s->ep_num != 0
- }).raw;
+ USB0.endpt[s->ep_num].raw |= ((struct USB_ENDPT_t){
+ .eptxen = s->ep_dir == USB_EP_TX,
+ .eprxen = s->ep_dir == USB_EP_RX,
+ .ephshk = 1, /* XXX ISO */
+ .epctldis = s->ep_num != 0
+ }).raw;
}
void usb_pipe_disable(struct usbd_ep_pipe_state_t *s)
{
- USB0.endpt[s->ep_num].raw &= ~((struct USB_ENDPT_t){
- .eptxen = s->ep_dir == USB_EP_TX,
- .eprxen = s->ep_dir == USB_EP_RX,
- .epctldis = 1
- }).raw;
+ USB0.endpt[s->ep_num].raw &= ~((struct USB_ENDPT_t){
+ .eptxen = s->ep_dir == USB_EP_TX,
+ .eprxen = s->ep_dir == USB_EP_RX,
+ .epctldis = 1
+ }).raw;
}
size_t usb_ep_get_transfer_size(struct usbd_ep_pipe_state_t *s)
{
- struct USB_BD_t *bd = usb_get_bd(s);
- return (bd->bc);
+ struct USB_BD_t *bd = usb_get_bd(s);
+ return (bd->bc);
}
void usb_queue_next(struct usbd_ep_pipe_state_t *s, void *addr, size_t len)
{
- volatile struct USB_BD_t *bd = usb_get_bd(s);
-
- bd->addr = addr;
- /* damn you bitfield problems */
- bd->raw = ((struct USB_BD_BITS_t){
- .dts = 1,
- .own = 1,
- .data01 = s->data01,
- .bc = len,
- }).raw;
+ volatile struct USB_BD_t *bd = usb_get_bd(s);
+
+ bd->addr = addr;
+ /* damn you bitfield problems */
+ bd->raw = ((struct USB_BD_BITS_t){
+ .dts = 1,
+ .own = 1,
+ .data01 = s->data01,
+ .bc = len,
+ }).raw;
}
static void usb_reset(void)
{
- /* reset pingpong state */
- /* For some obscure reason, we need to use or here. */
- USB0.ctl.raw |= ((struct USB_CTL_t){
- .txd_suspend = 1,
- .oddrst = 1,
- }).raw;
-
- /* clear all interrupt bits - not sure if needed */
- USB0.istat.raw = 0xff;
- USB0.errstat.raw = 0xff;
- USB0.otgistat.raw = 0xff;
-
- /* zap also BDT pingpong & queued transactions */
- memset(bdt, 0, sizeof(bdt));
- USB0.addr.raw = 0;
-
- usb_restart();
-
- USB0.ctl.raw = ((struct USB_CTL_t){
- .txd_suspend = 0,
- .usben = 1
- }).raw;
-
- /* we're only interested in reset and transfers */
- USB0.inten.raw = ((struct USB_ISTAT_t){
- .tokdne = 1,
- .usbrst = 1,
- .stall = 1,
- .sleep = 1,
- }).raw;
-
- USB0.usbtrc0.usbresmen = 0;
- USB0.usbctrl.susp = 0;
+ /* reset pingpong state */
+ /* For some obscure reason, we need to use or here. */
+ USB0.ctl.raw |= ((struct USB_CTL_t){
+ .txd_suspend = 1,
+ .oddrst = 1,
+ }).raw;
+
+ /* clear all interrupt bits - not sure if needed */
+ USB0.istat.raw = 0xff;
+ USB0.errstat.raw = 0xff;
+ USB0.otgistat.raw = 0xff;
+
+ /* zap also BDT pingpong & queued transactions */
+ memset(bdt, 0, sizeof(bdt));
+ USB0.addr.raw = 0;
+
+ usb_restart();
+
+ USB0.ctl.raw = ((struct USB_CTL_t){
+ .txd_suspend = 0,
+ .usben = 1
+ }).raw;
+
+ /* we're only interested in reset and transfers */
+ USB0.inten.raw = ((struct USB_ISTAT_t){
+ .tokdne = 1,
+ .usbrst = 1,
+ .stall = 1,
+ .sleep = 1,
+ }).raw;
+
+ USB0.usbtrc0.usbresmen = 0;
+ USB0.usbctrl.susp = 0;
}
void usb_enable(void)
{
- SIM.sopt2.usbsrc = 1; /* usb from mcg */
- SIM.scgc4.usbotg = 1; /* enable usb clock */
-
- /* reset module - not sure if needed */
- USB0.usbtrc0.raw = ((struct USB_USBTRC0_t){
- .usbreset = 1,
- .usbresmen = 1
- }).raw;
- while (USB0.usbtrc0.usbreset)
- /* NOTHING */;
-
- USB0.bdtpage1 = (uintptr_t)bdt >> 8;
- USB0.bdtpage2 = (uintptr_t)bdt >> 16;
- USB0.bdtpage3 = (uintptr_t)bdt >> 24;
-
- USB0.control.raw = ((struct USB_CONTROL_t){
- .dppullupnonotg = 1 /* enable pullup */
- }).raw;
-
- USB0.usbctrl.raw = 0; /* resume peripheral & disable pulldowns */
- usb_reset(); /* this will start usb processing */
-
- /* really only one thing we want */
- USB0.inten.raw = ((struct USB_ISTAT_t){
- .usbrst = 1,
- }).raw;
-
- /**
- * Suspend transceiver now - we'll wake up at reset again.
- */
+ SIM.sopt2.usbsrc = 1; /* usb from mcg */
+ SIM.scgc4.usbotg = 1; /* enable usb clock */
+
+ /* reset module - not sure if needed */
+ USB0.usbtrc0.raw = ((struct USB_USBTRC0_t){
+ .usbreset = 1,
+ .usbresmen = 1
+ }).raw;
+ while (USB0.usbtrc0.usbreset)
+ /* NOTHING */;
+
+ USB0.bdtpage1 = (uintptr_t)bdt >> 8;
+ USB0.bdtpage2 = (uintptr_t)bdt >> 16;
+ USB0.bdtpage3 = (uintptr_t)bdt >> 24;
+
+ USB0.control.raw = ((struct USB_CONTROL_t){
+ .dppullupnonotg = 1 /* enable pullup */
+ }).raw;
+
+ USB0.usbctrl.raw = 0; /* resume peripheral & disable pulldowns */
+ usb_reset(); /* this will start usb processing */
+
+ /* really only one thing we want */
+ USB0.inten.raw = ((struct USB_ISTAT_t){
+ .usbrst = 1,
+ }).raw;
+
+ /**
+ * Suspend transceiver now - we'll wake up at reset again.
+ */
// TODO - Possible removal
- USB0.usbctrl.susp = 1;
- USB0.usbtrc0.usbresmen = 1;
+ USB0.usbctrl.susp = 1;
+ USB0.usbtrc0.usbresmen = 1;
}
void USB0_Handler(void)
{
- struct USB_ISTAT_t stat = {.raw = USB0.istat.raw };
-
- if (stat.usbrst) {
- usb_reset();
- return;
- }
- if (stat.stall) {
- /* XXX need more work for non-0 ep */
- volatile struct USB_BD_t *bd = usb_get_bd(&usb.ep_state[0].rx);
- if (bd->stall)
- usb_setup_control();
- }
- if (stat.tokdne) {
- struct usb_xfer_info stat = USB0.stat;
- usb_handle_transaction(&stat);
- }
- if (stat.sleep) {
- USB0.inten.sleep = 0;
- USB0.inten.resume = 1;
- USB0.usbctrl.susp = 1;
- USB0.usbtrc0.usbresmen = 1;
-
- /**
- * Clear interrupts now so that we can detect a fresh
- * resume later on.
- */
- USB0.istat.raw = stat.raw;
-
- const struct usbd_config *c = usb_get_config_data(-1);
- if (c && c->suspend)
- c->suspend();
- }
- /**
- * XXX it is unclear whether we will receive a synchronous
- * resume interrupt if we were in sleep. This code assumes we
- * do.
- */
- if (stat.resume || USB0.usbtrc0.usb_resume_int) {
- USB0.inten.resume = 0;
- USB0.inten.sleep = 1;
- USB0.usbtrc0.usbresmen = 0;
- USB0.usbctrl.susp = 0;
-
- const struct usbd_config *c = usb_get_config_data(-1);
- if (c && c->resume)
- c->resume();
-
- stat.resume = 1; /* always clear bit */
- }
- USB0.istat.raw = stat.raw;
+ struct USB_ISTAT_t stat = {.raw = USB0.istat.raw };
+
+ if (stat.usbrst) {
+ usb_reset();
+ return;
+ }
+ if (stat.stall) {
+ /* XXX need more work for non-0 ep */
+ volatile struct USB_BD_t *bd = usb_get_bd(&usb.ep_state[0].rx);
+ if (bd->stall)
+ usb_setup_control();
+ }
+ if (stat.tokdne) {
+ struct usb_xfer_info stat = USB0.stat;
+ usb_handle_transaction(&stat);
+ }
+ if (stat.sleep) {
+ USB0.inten.sleep = 0;
+ USB0.inten.resume = 1;
+ USB0.usbctrl.susp = 1;
+ USB0.usbtrc0.usbresmen = 1;
+
+ /**
+ * Clear interrupts now so that we can detect a fresh
+ * resume later on.
+ */
+ USB0.istat.raw = stat.raw;
+
+ const struct usbd_config *c = usb_get_config_data(-1);
+ if (c && c->suspend)
+ c->suspend();
+ }
+ /**
+ * XXX it is unclear whether we will receive a synchronous
+ * resume interrupt if we were in sleep. This code assumes we
+ * do.
+ */
+ if (stat.resume || USB0.usbtrc0.usb_resume_int) {
+ USB0.inten.resume = 0;
+ USB0.inten.sleep = 1;
+ USB0.usbtrc0.usbresmen = 0;
+ USB0.usbctrl.susp = 0;
+
+ const struct usbd_config *c = usb_get_config_data(-1);
+ if (c && c->resume)
+ c->resume();
+
+ stat.resume = 1; /* always clear bit */
+ }
+ USB0.istat.raw = stat.raw;
}
void usb_poll(void)
{
- USB0_Handler();
+ USB0_Handler();
}
int usb_tx_serialno(size_t reqlen)
{
- struct usb_desc_string_t *d;
- const size_t nregs = 3;
- /**
- * actually 4, but UIDH is 0xffffffff. Also our output buffer
- * is only 64 bytes, and 128 bit + desc header exceeds this by
- * 2 bytes.
- */
- const size_t len = nregs * 4 * 2 * 2 + sizeof(*d);
-
- d = usb_ep0_tx_inplace_prepare(len);
-
- if (d == NULL)
- return (-1);
-
- d->bLength = len;
- d->bDescriptorType = USB_DESC_STRING;
-
- size_t bufpos = 0;
- for (size_t reg = 0; reg < nregs; ++reg) {
- /* registers run MSW first */
- uint32_t val = (&SIM.uidmh)[reg];
-
- for (size_t bits = 32; bits > 0; bits -= 4, val <<= 4) {
- int nibble = val >> 28;
-
- if (nibble > 9)
- nibble += 'a' - '9' - 1;
- ((char16_t *)d->bString)[bufpos++] = nibble + '0';
- }
- }
- usb_ep0_tx(d, len, reqlen, NULL, NULL);
- return (0);
+ struct usb_desc_string_t *d;
+ const size_t nregs = 3;
+ /**
+ * actually 4, but UIDH is 0xffffffff. Also our output buffer
+ * is only 64 bytes, and 128 bit + desc header exceeds this by
+ * 2 bytes.
+ */
+ const size_t len = nregs * 4 * 2 * 2 + sizeof(*d);
+
+ d = usb_ep0_tx_inplace_prepare(len);
+
+ if (d == NULL)
+ return (-1);
+
+ d->bLength = len;
+ d->bDescriptorType = USB_DESC_STRING;
+
+ size_t bufpos = 0;
+ for (size_t reg = 0; reg < nregs; ++reg) {
+ /* registers run MSW first */
+ uint32_t val = (&SIM.uidmh)[reg];
+
+ for (size_t bits = 32; bits > 0; bits -= 4, val <<= 4) {
+ int nibble = val >> 28;
+
+ if (nibble > 9)
+ nibble += 'a' - '9' - 1;
+ ((char16_t *)d->bString)[bufpos++] = nibble + '0';
+ }
+ }
+ usb_ep0_tx(d, len, reqlen, NULL, NULL);
+ return (0);
}