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