blob: 70bdc8f3df9215a0ac7ad02127e22a3beb54e2c4 [file] [log] [blame]
Patrick Georgid21f68b2008-09-02 16:06:22 +00001/*
2 * This file is part of the libpayload project.
3 *
4 * Copyright (C) 2008 coresystems GmbH
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
Jordan Crouse29061a52008-09-11 17:29:00 +000030#include <usb/usb.h>
Patrick Georgid21f68b2008-09-02 16:06:22 +000031#include "uhci.h"
32#include <arch/virtual.h>
33
34static void uhci_start (hci_t *controller);
35static void uhci_stop (hci_t *controller);
36static void uhci_reset (hci_t *controller);
37static void uhci_shutdown (hci_t *controller);
38static int uhci_packet (usbdev_t *dev, int endp, int pid, int toggle,
39 int length, u8 *data);
40static int uhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize);
41static int uhci_control (usbdev_t *dev, pid_t dir, int drlen, void *devreq,
42 int dalen, u8 *data);
43
44#if 0
45/* dump uhci */
46static void
47uhci_dump (hci_t *controller)
48{
49 printf ("dump:\nUSBCMD: %x\n", uhci_reg_read16 (controller, USBCMD));
50 printf ("USBSTS: %x\n", uhci_reg_read16 (controller, USBSTS));
51 printf ("USBINTR: %x\n", uhci_reg_read16 (controller, USBINTR));
52 printf ("FRNUM: %x\n", uhci_reg_read16 (controller, FRNUM));
53 printf ("FLBASEADD: %x\n", uhci_reg_read32 (controller, FLBASEADD));
54 printf ("SOFMOD: %x\n", uhci_reg_read8 (controller, SOFMOD));
55 printf ("PORTSC1: %x\n", uhci_reg_read16 (controller, PORTSC1));
56 printf ("PORTSC2: %x\n", uhci_reg_read16 (controller, PORTSC2));
57}
58#endif
59
60static void
61td_dump (td_t *td)
62{
63 printf ("%x packet (at %lx) to %x.%x failed\n", td->pid,
64 virt_to_phys (td), td->dev_addr, td->endp);
65 printf ("td (counter at %x) returns: ", td->counter);
66 printf (" bitstuff err: %x, ", td->status_bitstuff_err);
67 printf (" CRC err: %x, ", td->status_crc_err);
68 printf (" NAK rcvd: %x, ", td->status_nakrcvd);
69 printf (" Babble: %x, ", td->status_babble);
70 printf (" Data Buffer err: %x, ", td->status_databuf_err);
71 printf (" Stalled: %x, ", td->status_stalled);
72 printf (" Active: %x\n", td->status_active);
73 if (td->status_babble)
74 printf (" Babble because of %s\n",
75 td->status_bitstuff_err ? "host" : "device");
76 if (td->status_active)
77 printf (" still active - timeout?\n");
78}
79
80static void
81uhci_reset (hci_t *controller)
82{
83 /* reset */
84 uhci_reg_write16 (controller, USBCMD, 4);
85 mdelay (50);
86 uhci_reg_write16 (controller, USBCMD, 0);
87 mdelay (10);
88 uhci_reg_write16 (controller, USBCMD, 2);
89 while ((uhci_reg_read16 (controller, USBCMD) & 2) != 0)
90 mdelay (1);
91
92 uhci_reg_write32 (controller, FLBASEADD,
93 (u32) virt_to_phys (UHCI_INST (controller)->
94 framelistptr));
95 //printf ("framelist at %p\n",UHCI_INST(controller)->framelistptr);
96
97 /* disable irqs */
98 uhci_reg_write16 (controller, USBINTR, 0);
99
100 /* reset framelist index */
101 uhci_reg_write16 (controller, FRNUM, 0);
102
103 uhci_reg_mask16 (controller, USBCMD, ~0, 0xc0); // max packets, configure flag
104
105 uhci_start (controller);
106}
107
108hci_t *
109uhci_init (pcidev_t addr)
110{
111 int i;
112 hci_t *controller = new_controller ();
113
114 controller->instance = malloc (sizeof (uhci_t));
115 controller->start = uhci_start;
116 controller->stop = uhci_stop;
117 controller->reset = uhci_reset;
118 controller->shutdown = uhci_shutdown;
119 controller->packet = uhci_packet;
120 controller->bulk = uhci_bulk;
121 controller->control = uhci_control;
122 UHCI_INST (controller)->roothub = &(controller->devices[0]);
123
124 controller->bus_address = addr;
125 controller->reg_base = pci_read_config32 (controller->bus_address, 0x20) & ~1; /* ~1 clears the register type indicator that is set to 1 for IO space */
126
127 /* kill legacy support handler */
128 uhci_stop (controller);
129 mdelay (1);
130 uhci_reg_write16 (controller, USBSTS, 0x3f);
131 pci_write_config32 (controller->bus_address, 0xc0, 0x8f00);
132
133 UHCI_INST (controller)->framelistptr = memalign (0x1000, 1024 * sizeof (flistp_t *)); /* 4kb aligned to 4kb */
134 memset (UHCI_INST (controller)->framelistptr, 0,
135 1024 * sizeof (flistp_t));
136
137 UHCI_INST (controller)->qh_intr = memalign (16, sizeof (qh_t));
138 UHCI_INST (controller)->qh_data = memalign (16, sizeof (qh_t));
139 UHCI_INST (controller)->qh_last = memalign (16, sizeof (qh_t));
140
141 UHCI_INST (controller)->qh_intr->headlinkptr.ptr =
142 virt_to_phys (UHCI_INST (controller)->qh_data);
143 UHCI_INST (controller)->qh_intr->headlinkptr.queue_head = 1;
144 UHCI_INST (controller)->qh_intr->elementlinkptr.ptr = 0;
145 UHCI_INST (controller)->qh_intr->elementlinkptr.terminate = 1;
146
147 UHCI_INST (controller)->qh_data->headlinkptr.ptr =
148 virt_to_phys (UHCI_INST (controller)->qh_last);
149 UHCI_INST (controller)->qh_data->headlinkptr.queue_head = 1;
150 UHCI_INST (controller)->qh_data->elementlinkptr.ptr = 0;
151 UHCI_INST (controller)->qh_data->elementlinkptr.terminate = 1;
152
153 UHCI_INST (controller)->qh_last->headlinkptr.ptr = 0;
154 UHCI_INST (controller)->qh_last->headlinkptr.terminate = 1;
155 UHCI_INST (controller)->qh_last->elementlinkptr.ptr = 0;
156 UHCI_INST (controller)->qh_last->elementlinkptr.terminate = 1;
157
158 for (i = 0; i < 1024; i++) {
159 UHCI_INST (controller)->framelistptr[i].ptr =
160 virt_to_phys (UHCI_INST (controller)->qh_intr);
161 UHCI_INST (controller)->framelistptr[i].terminate = 0;
162 UHCI_INST (controller)->framelistptr[i].queue_head = 1;
163 }
164 for (i = 1; i < 128; i++) {
165 init_device_entry (controller, i);
166 }
167 controller->devices[0].controller = controller;
168 controller->devices[0].init = uhci_rh_init;
169 controller->devices[0].init (&controller->devices[0]);
170 uhci_reset (controller);
171 return controller;
172}
173
174static void
175uhci_shutdown (hci_t *controller)
176{
177 if (controller == 0)
178 return;
179 detach_controller (controller);
180 UHCI_INST (controller)->roothub->destroy (UHCI_INST (controller)->
181 roothub);
182 uhci_reg_mask16 (controller, USBCMD, 0, 0); // stop work
183 free (UHCI_INST (controller)->framelistptr);
184 free (UHCI_INST (controller)->qh_intr);
185 free (UHCI_INST (controller)->qh_data);
186 free (UHCI_INST (controller)->qh_last);
187 free (UHCI_INST (controller));
188 free (controller);
189}
190
191static void
192uhci_start (hci_t *controller)
193{
194 uhci_reg_mask16 (controller, USBCMD, ~0, 1); // start work on schedule
195}
196
197static void
198uhci_stop (hci_t *controller)
199{
200 uhci_reg_mask16 (controller, USBCMD, ~1, 0); // stop work on schedule
201}
202
203#define GET_TD(x) ((void*)(((unsigned int)(x))&~0xf))
204
205static td_t *
206wait_for_completed_qh (hci_t *controller, qh_t *qh)
207{
208 int timeout = 1000; /* max 30 ms. */
209 void *current = GET_TD (qh->elementlinkptr.ptr);
210 while ((qh->elementlinkptr.terminate == 0) && (timeout-- > 0)) {
211 if (current != GET_TD (qh->elementlinkptr.ptr)) {
212 current = GET_TD (qh->elementlinkptr.ptr);
213 timeout = 1000;
214 }
215 uhci_reg_mask16 (controller, USBSTS, ~0, 0); // clear resettable registers
216 udelay (30);
217 }
218 return (GET_TD (qh->elementlinkptr.ptr) ==
219 0) ? 0 : GET_TD (phys_to_virt (qh->elementlinkptr.ptr));
220}
221
222static void
223wait_for_completed_td (hci_t *controller, td_t *td)
224{
225 int timeout = 10000;
226 while ((td->status_active == 1)
227 && ((uhci_reg_read16 (controller, USBSTS) & 2) == 0)
228 && (timeout-- > 0)) {
229 uhci_reg_mask16 (controller, USBSTS, ~0, 0); // clear resettable registers
230 udelay (10);
231 }
232}
233
234static int
235maxlen (int size)
236{
237 return (size - 1) & 0x7ff;
238}
239
240static int
241min (int a, int b)
242{
243 if (a < b)
244 return a;
245 else
246 return b;
247}
248
249static int
250uhci_control (usbdev_t *dev, pid_t dir, int drlen, void *devreq, int dalen,
251 unsigned char *data)
252{
253 int endp = 0; /* this is control: always 0 */
254 int mlen = dev->endpoints[0].maxpacketsize;
255 int count = (2 + (dalen + mlen - 1) / mlen);
256 unsigned short req = ((unsigned short *) devreq)[0];
257 int i;
258 td_t *tds = memalign (16, sizeof (td_t) * count);
259 memset (tds, 0, sizeof (td_t) * count);
260 count--; /* to compensate for 0-indexed array */
261 for (i = 0; i < count; i++) {
262 tds[i].ptr = virt_to_phys (&tds[i + 1]);
263 tds[i].depth_first = 1;
264 tds[i].terminate = 0;
265 }
266 tds[count].ptr = 0;
267 tds[count].depth_first = 1;
268 tds[count].terminate = 1;
269
270 tds[0].pid = SETUP;
271 tds[0].dev_addr = dev->address;
272 tds[0].endp = endp;
273 tds[0].maxlen = maxlen (drlen);
274 tds[0].counter = 3;
275 tds[0].data_toggle = 0;
276 tds[0].lowspeed = dev->lowspeed;
277 tds[0].bufptr = virt_to_phys (devreq);
278 tds[0].status_active = 1;
279
280 int toggle = 1;
281 for (i = 1; i < count; i++) {
282 tds[i].pid = dir;
283 tds[i].dev_addr = dev->address;
284 tds[i].endp = endp;
285 tds[i].maxlen = maxlen (min (mlen, dalen));
286 tds[i].counter = 3;
287 tds[i].data_toggle = toggle;
288 tds[i].lowspeed = dev->lowspeed;
289 tds[i].bufptr = virt_to_phys (data);
290 tds[i].status_active = 1;
291 toggle ^= 1;
292 dalen -= mlen;
293 data += mlen;
294 }
295
296 tds[count].pid = (dir == OUT) ? IN : OUT;
297 tds[count].dev_addr = dev->address;
298 tds[count].endp = endp;
299 tds[count].maxlen = maxlen (0);
300 tds[count].counter = 0; /* as per linux 2.4.10 */
301 tds[count].data_toggle = 1;
302 tds[count].lowspeed = dev->lowspeed, tds[count].bufptr = 0;
303 tds[count].status_active = 1;
304 UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr =
305 virt_to_phys (tds);
306 UHCI_INST (dev->controller)->qh_data->elementlinkptr.queue_head = 0;
307 UHCI_INST (dev->controller)->qh_data->elementlinkptr.terminate = 0;
308 td_t *td = wait_for_completed_qh (dev->controller,
309 UHCI_INST (dev->controller)->
310 qh_data);
311 int result;
312 if (td == 0) {
313 result = 0;
314 } else {
315 printf ("control packet, req %x\n", req);
316 td_dump (td);
317 result = 1;
318 }
319 free (tds);
320 return result;
321}
322
323static int
324uhci_packet (usbdev_t *dev, int endp, int pid, int toggle, int length,
325 unsigned char *data)
326{
327 static td_t *td = 0;
328 if (td == 0)
329 td = memalign (16, sizeof (td_t));
330
331 memset (td, 0, sizeof (td_t));
332 td->ptr = 0;
333 td->terminate = 1;
334 td->queue_head = 0;
335
336 td->pid = pid;
337 td->dev_addr = dev->address;
338 td->endp = endp & 0xf;
339 td->maxlen = maxlen (length);
340 if (pid == SETUP)
341 td->counter = 3;
342 else
343 td->counter = 0;
344 td->data_toggle = toggle & 1;
345 td->lowspeed = dev->lowspeed;
346 td->bufptr = virt_to_phys (data);
347
348 td->status_active = 1;
349
350 UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr =
351 virt_to_phys (td);
352 UHCI_INST (dev->controller)->qh_data->elementlinkptr.queue_head = 0;
353 UHCI_INST (dev->controller)->qh_data->elementlinkptr.terminate = 0;
354 wait_for_completed_td (dev->controller, td);
355 if ((td->status & 0x7f) == 0) {
356 //printf("successfully sent a %x packet to %x.%x\n",pid, dev->address,endp);
357 // success
358 return 0;
359 } else {
360 td_dump (td);
361 return 1;
362 }
363}
364
365static td_t *
366create_schedule (int numpackets)
367{
368 if (numpackets == 0)
369 return 0;
370 td_t *tds = memalign (16, sizeof (td_t) * numpackets);
371 memset (tds, 0, sizeof (td_t) * numpackets);
372 int i;
373 for (i = 0; i < numpackets; i++) {
374 tds[i].ptr = virt_to_phys (&tds[i + 1]);
375 tds[i].terminate = 0;
376 tds[i].queue_head = 0;
377 tds[i].depth_first = 1;
378 }
379 tds[numpackets - 1].ptr = 0;
380 tds[numpackets - 1].terminate = 1;
381 tds[numpackets - 1].queue_head = 0;
382 tds[numpackets - 1].depth_first = 0;
383 return tds;
384}
385
386static void
387fill_schedule (td_t *td, endpoint_t *ep, int length, unsigned char *data,
388 int *toggle)
389{
390 td->pid = ep->direction;
391 td->dev_addr = ep->dev->address;
392 td->endp = ep->endpoint & 0xf;
393 td->maxlen = maxlen (length);
394 if (ep->direction == SETUP)
395 td->counter = 3;
396 else
397 td->counter = 0;
398 td->data_toggle = *toggle & 1;
399 td->lowspeed = ep->dev->lowspeed;
400 td->bufptr = virt_to_phys (data);
401
402 td->status_active = 1;
403 *toggle ^= 1;
404}
405
406static int
407run_schedule (usbdev_t *dev, td_t *td)
408{
409 UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr =
410 virt_to_phys (td);
411 UHCI_INST (dev->controller)->qh_data->elementlinkptr.queue_head = 0;
412 UHCI_INST (dev->controller)->qh_data->elementlinkptr.terminate = 0;
413 td = wait_for_completed_qh (dev->controller,
414 UHCI_INST (dev->controller)->qh_data);
415 if (td == 0) {
416 return 0;
417 } else {
418 td_dump (td);
419 return 1;
420 }
421}
422
423/* finalize == 1: if data is of packet aligned size, add a zero length packet */
424static int
425uhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize)
426{
427 int maxpsize = ep->maxpacketsize;
428 if (maxpsize == 0)
429 fatal ("MaxPacketSize == 0!!!");
430 int numpackets = (size + maxpsize - 1 + finalize) / maxpsize;
431 if (numpackets == 0)
432 return 0;
433 td_t *tds = create_schedule (numpackets);
434 int i = 0, toggle = ep->toggle;
435 while ((size > 0) || ((size == 0) && (finalize != 0))) {
436 fill_schedule (&tds[i], ep, min (size, maxpsize), data,
437 &toggle);
438 i++;
439 data += maxpsize;
440 size -= maxpsize;
441 }
442 if (run_schedule (ep->dev, tds) == 1) {
443 clear_stall (ep);
444 free (tds);
445 return 1;
446 }
447 ep->toggle = toggle;
448 free (tds);
449 return 0;
450}
451
452void
453uhci_reg_write32 (hci_t *ctrl, usbreg reg, u32 value)
454{
455 outl (value, ctrl->reg_base + reg);
456}
457
458u32
459uhci_reg_read32 (hci_t *ctrl, usbreg reg)
460{
461 return inl (ctrl->reg_base + reg);
462}
463
464void
465uhci_reg_write16 (hci_t *ctrl, usbreg reg, u16 value)
466{
467 outw (value, ctrl->reg_base + reg);
468}
469
470u16
471uhci_reg_read16 (hci_t *ctrl, usbreg reg)
472{
473 return inw (ctrl->reg_base + reg);
474}
475
476void
477uhci_reg_write8 (hci_t *ctrl, usbreg reg, u8 value)
478{
479 outb (value, ctrl->reg_base + reg);
480}
481
482u8
483uhci_reg_read8 (hci_t *ctrl, usbreg reg)
484{
485 return inb (ctrl->reg_base + reg);
486}
487
488void
489uhci_reg_mask32 (hci_t *ctrl, usbreg reg, u32 andmask, u32 ormask)
490{
491 uhci_reg_write32 (ctrl, reg,
492 (uhci_reg_read32 (ctrl, reg) & andmask) | ormask);
493}
494
495void
496uhci_reg_mask16 (hci_t *ctrl, usbreg reg, u16 andmask, u16 ormask)
497{
498 uhci_reg_write16 (ctrl, reg,
499 (uhci_reg_read16 (ctrl, reg) & andmask) | ormask);
500}
501
502void
503uhci_reg_mask8 (hci_t *ctrl, usbreg reg, u8 andmask, u8 ormask)
504{
505 uhci_reg_write8 (ctrl, reg,
506 (uhci_reg_read8 (ctrl, reg) & andmask) | ormask);
507}