Kiibohd Controller
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

kinetis.c 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /* Copyright (c) 2011,2012 Simon Schubert <[email protected]>.
  2. * Modifications by Jacob Alexander 2014 <[email protected]>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. // ----- Defines -----
  18. #define usb_xfer_info USB_STAT_t
  19. // ----- Local Includes -----
  20. #include "mchck.h"
  21. #include "usb-internal.h"
  22. // ----- Functions -----
  23. /**
  24. * Kinetis USB driver notes:
  25. * We need to manually maintain the DATA0/1 toggling for the SIE.
  26. * SETUP transactions always start with a DATA0.
  27. *
  28. * The SIE internally uses pingpong (double) buffering, which is
  29. * easily confused with DATA0/DATA1 toggling, and I think even the
  30. * Freescale docs confuse the two notions. When BD->DTS is set,
  31. * BD->DATA01 will be used to verify/discard incoming DATAx and it
  32. * will set the DATAx PID for outgoing tokens. This is not described
  33. * as such in the Freescale Kinetis docs, but the Microchip PIC32 OTG
  34. * docs are more clear on this; it seems that both Freescale and
  35. * Microchip use different versions of the same USB OTG IP core.
  36. *
  37. * http://ww1.microchip.com/downloads/en/DeviceDoc/61126F.pdf
  38. *
  39. * Clear CTL->TOKEN_BUSY after SETUP tokens.
  40. */
  41. static struct USB_BD_t bdt[USB_MAX_EP * 2 *2] __attribute__((section(".usbdescriptortable")));
  42. static struct USB_BD_t *
  43. usb_get_bd(struct usbd_ep_pipe_state_t *s)
  44. {
  45. return (&bdt[(s->ep_num << 2) | (s->ep_dir << 1) | s->pingpong]);
  46. }
  47. static struct USB_BD_t *
  48. usb_get_bd_stat(struct USB_STAT_t *stat)
  49. {
  50. return (((void *)(uintptr_t)bdt + (stat->raw << 1)));
  51. }
  52. void *usb_get_xfer_data(struct usb_xfer_info *i)
  53. {
  54. return (usb_get_bd_stat(i)->addr);
  55. }
  56. enum usb_tok_pid usb_get_xfer_pid(struct usb_xfer_info *i)
  57. {
  58. return (usb_get_bd_stat(i)->tok_pid);
  59. }
  60. int usb_get_xfer_ep(struct usb_xfer_info *i)
  61. {
  62. return (i->ep);
  63. }
  64. enum usb_ep_dir usb_get_xfer_dir(struct usb_xfer_info *i)
  65. {
  66. return (i->dir);
  67. }
  68. void usb_enable_xfers(void)
  69. {
  70. USB0.ctl.raw = ((struct USB_CTL_t){
  71. .txd_suspend = 0,
  72. .usben = 1
  73. }).raw;
  74. }
  75. void usb_set_addr(int addr)
  76. {
  77. USB0.addr.raw = addr;
  78. }
  79. void usb_pipe_stall(struct usbd_ep_pipe_state_t *s)
  80. {
  81. volatile struct USB_BD_t *bd = usb_get_bd(s);
  82. bd->raw = ((struct USB_BD_BITS_t){
  83. .stall = 1,
  84. .own = 1
  85. }).raw;
  86. }
  87. void usb_pipe_unstall(struct usbd_ep_pipe_state_t *s)
  88. {
  89. volatile struct USB_BD_t *bd = usb_get_bd(s);
  90. struct USB_BD_BITS_t state = { .raw = bd->raw };
  91. if (state.own && state.stall)
  92. bd->raw = 0;
  93. }
  94. void usb_pipe_enable(struct usbd_ep_pipe_state_t *s)
  95. {
  96. USB0.endpt[s->ep_num].raw |= ((struct USB_ENDPT_t){
  97. .eptxen = s->ep_dir == USB_EP_TX,
  98. .eprxen = s->ep_dir == USB_EP_RX,
  99. .ephshk = 1, /* XXX ISO */
  100. .epctldis = s->ep_num != 0
  101. }).raw;
  102. }
  103. void usb_pipe_disable(struct usbd_ep_pipe_state_t *s)
  104. {
  105. USB0.endpt[s->ep_num].raw &= ~((struct USB_ENDPT_t){
  106. .eptxen = s->ep_dir == USB_EP_TX,
  107. .eprxen = s->ep_dir == USB_EP_RX,
  108. .epctldis = 1
  109. }).raw;
  110. }
  111. size_t usb_ep_get_transfer_size(struct usbd_ep_pipe_state_t *s)
  112. {
  113. struct USB_BD_t *bd = usb_get_bd(s);
  114. return (bd->bc);
  115. }
  116. void usb_queue_next(struct usbd_ep_pipe_state_t *s, void *addr, size_t len)
  117. {
  118. volatile struct USB_BD_t *bd = usb_get_bd(s);
  119. bd->addr = addr;
  120. /* damn you bitfield problems */
  121. bd->raw = ((struct USB_BD_BITS_t){
  122. .dts = 1,
  123. .own = 1,
  124. .data01 = s->data01,
  125. .bc = len,
  126. }).raw;
  127. }
  128. static void usb_reset(void)
  129. {
  130. /* reset pingpong state */
  131. /* For some obscure reason, we need to use or here. */
  132. USB0.ctl.raw |= ((struct USB_CTL_t){
  133. .txd_suspend = 1,
  134. .oddrst = 1,
  135. }).raw;
  136. /* clear all interrupt bits - not sure if needed */
  137. USB0.istat.raw = 0xff;
  138. USB0.errstat.raw = 0xff;
  139. USB0.otgistat.raw = 0xff;
  140. /* zap also BDT pingpong & queued transactions */
  141. memset(bdt, 0, sizeof(bdt));
  142. USB0.addr.raw = 0;
  143. usb_restart();
  144. USB0.ctl.raw = ((struct USB_CTL_t){
  145. .txd_suspend = 0,
  146. .usben = 1
  147. }).raw;
  148. /* we're only interested in reset and transfers */
  149. USB0.inten.raw = ((struct USB_ISTAT_t){
  150. .tokdne = 1,
  151. .usbrst = 1,
  152. .stall = 1,
  153. .sleep = 1,
  154. }).raw;
  155. USB0.usbtrc0.usbresmen = 0;
  156. USB0.usbctrl.susp = 0;
  157. }
  158. void usb_enable(void)
  159. {
  160. SIM.sopt2.usbsrc = 1; /* usb from mcg */
  161. SIM.scgc4.usbotg = 1; /* enable usb clock */
  162. /* reset module - not sure if needed */
  163. USB0.usbtrc0.raw = ((struct USB_USBTRC0_t){
  164. .usbreset = 1,
  165. .usbresmen = 1
  166. }).raw;
  167. while (USB0.usbtrc0.usbreset)
  168. /* NOTHING */;
  169. USB0.bdtpage1 = (uintptr_t)bdt >> 8;
  170. USB0.bdtpage2 = (uintptr_t)bdt >> 16;
  171. USB0.bdtpage3 = (uintptr_t)bdt >> 24;
  172. USB0.control.raw = ((struct USB_CONTROL_t){
  173. .dppullupnonotg = 1 /* enable pullup */
  174. }).raw;
  175. USB0.usbctrl.raw = 0; /* resume peripheral & disable pulldowns */
  176. usb_reset(); /* this will start usb processing */
  177. /* really only one thing we want */
  178. USB0.inten.raw = ((struct USB_ISTAT_t){
  179. .usbrst = 1,
  180. }).raw;
  181. /**
  182. * Suspend transceiver now - we'll wake up at reset again.
  183. */
  184. // TODO - Possible removal
  185. USB0.usbctrl.susp = 1;
  186. USB0.usbtrc0.usbresmen = 1;
  187. }
  188. void USB0_Handler(void)
  189. {
  190. struct USB_ISTAT_t stat = {.raw = USB0.istat.raw };
  191. if (stat.usbrst) {
  192. usb_reset();
  193. return;
  194. }
  195. if (stat.stall) {
  196. /* XXX need more work for non-0 ep */
  197. volatile struct USB_BD_t *bd = usb_get_bd(&usb.ep_state[0].rx);
  198. if (bd->stall)
  199. usb_setup_control();
  200. }
  201. if (stat.tokdne) {
  202. struct usb_xfer_info stat = USB0.stat;
  203. usb_handle_transaction(&stat);
  204. }
  205. if (stat.sleep) {
  206. USB0.inten.sleep = 0;
  207. USB0.inten.resume = 1;
  208. USB0.usbctrl.susp = 1;
  209. USB0.usbtrc0.usbresmen = 1;
  210. /**
  211. * Clear interrupts now so that we can detect a fresh
  212. * resume later on.
  213. */
  214. USB0.istat.raw = stat.raw;
  215. const struct usbd_config *c = usb_get_config_data(-1);
  216. if (c && c->suspend)
  217. c->suspend();
  218. }
  219. /**
  220. * XXX it is unclear whether we will receive a synchronous
  221. * resume interrupt if we were in sleep. This code assumes we
  222. * do.
  223. */
  224. if (stat.resume || USB0.usbtrc0.usb_resume_int) {
  225. USB0.inten.resume = 0;
  226. USB0.inten.sleep = 1;
  227. USB0.usbtrc0.usbresmen = 0;
  228. USB0.usbctrl.susp = 0;
  229. const struct usbd_config *c = usb_get_config_data(-1);
  230. if (c && c->resume)
  231. c->resume();
  232. stat.resume = 1; /* always clear bit */
  233. }
  234. USB0.istat.raw = stat.raw;
  235. }
  236. void usb_poll(void)
  237. {
  238. USB0_Handler();
  239. }
  240. int usb_tx_serialno(size_t reqlen)
  241. {
  242. struct usb_desc_string_t *d;
  243. const size_t nregs = 3;
  244. /**
  245. * actually 4, but UIDH is 0xffffffff. Also our output buffer
  246. * is only 64 bytes, and 128 bit + desc header exceeds this by
  247. * 2 bytes.
  248. */
  249. const size_t len = nregs * 4 * 2 * 2 + sizeof(*d);
  250. d = usb_ep0_tx_inplace_prepare(len);
  251. if (d == NULL)
  252. return (-1);
  253. d->bLength = len;
  254. d->bDescriptorType = USB_DESC_STRING;
  255. size_t bufpos = 0;
  256. for (size_t reg = 0; reg < nregs; ++reg) {
  257. /* registers run MSW first */
  258. uint32_t val = (&SIM.uidmh)[reg];
  259. for (size_t bits = 32; bits > 0; bits -= 4, val <<= 4) {
  260. int nibble = val >> 28;
  261. if (nibble > 9)
  262. nibble += 'a' - '9' - 1;
  263. ((char16_t *)d->bString)[bufpos++] = nibble + '0';
  264. }
  265. }
  266. usb_ep0_tx(d, len, reqlen, NULL, NULL);
  267. return (0);
  268. }