blob: 8f99e1db194e61eaeeeadd43689de1f6e3490caa [file] [log] [blame]
Daniel Hellstrom1e9a1642008-03-26 22:51:29 +01001/*
2 * Part of this code has been derived from linux:
3 * Universal Host Controller Interface driver for USB (take II).
4 *
5 * (c) 1999-2001 Georg Acher, acher@in.tum.de (executive slave) (base guitar)
6 * Deti Fliegl, deti@fliegl.de (executive slave) (lead voice)
7 * Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader)
8 * Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter)
9 * (c) 2000 Yggdrasil Computing, Inc. (port of new PCI interface support
10 * from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
11 * (C) 2000 David Brownell, david-b@pacbell.net (usb-ohci.c)
12 *
13 * HW-initalization based on material of
14 *
15 * (C) Copyright 1999 Linus Torvalds
16 * (C) Copyright 1999 Johannes Erdfelt
17 * (C) Copyright 1999 Randy Dunlap
18 * (C) Copyright 1999 Gregory P. Smith
19 *
20 *
21 * Adapted for U-Boot:
22 * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
23 * (C) Copyright 2008, Daniel Hellström, daniel@gaisler.com
24 * Added AMBA Plug&Play detection of GRUSB, modified interrupt handler.
25 * Added cache flushes where needed.
26 *
27 * See file CREDITS for list of people who contributed to this
28 * project.
29 *
30 * This program is free software; you can redistribute it and/or
31 * modify it under the terms of the GNU General Public License as
32 * published by the Free Software Foundation; either version 2 of
33 * the License, or (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License
41 * along with this program; if not, write to the Free Software
42 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
43 * MA 02111-1307 USA
44 *
45 *
46 */
47
48/**********************************************************************
49 * How it works:
50 * -------------
51 * The framelist / Transfer descriptor / Queue Heads are similar like
52 * in the linux usb_uhci.c.
53 *
54 * During initialization, the following skeleton is allocated in init_skel:
55 *
56 * framespecific | common chain
57 *
58 * framelist[]
59 * [ 0 ]-----> TD ---------\
60 * [ 1 ]-----> TD ----------> TD ------> QH -------> QH -------> QH ---> NULL
61 * ... TD ---------/
62 * [1023]-----> TD --------/
63 *
64 * ^^ ^^ ^^ ^^ ^^
65 * 7 TDs for 1 TD for Start of Start of End Chain
66 * INT (2-128ms) 1ms-INT CTRL Chain BULK Chain
67 *
68 *
69 * Since this is a bootloader, the isochronous transfer descriptor have been removed.
70 *
71 * Interrupt Transfers.
72 * --------------------
73 * For Interupt transfers USB_MAX_TEMP_INT_TD Transfer descriptor are available. They
74 * will be inserted after the appropriate (depending the interval setting) skeleton TD.
75 * If an interrupt has been detected the dev->irqhandler is called. The status and number
76 * of transfered bytes is stored in dev->irq_status resp. dev->irq_act_len. If the
77 * dev->irqhandler returns 0, the interrupt TD is removed and disabled. If an 1 is returned,
78 * the interrupt TD will be reactivated.
79 *
80 * Control Transfers
81 * -----------------
82 * Control Transfers are issued by filling the tmp_td with the appropriate data and connect
83 * them to the qh_cntrl queue header. Before other control/bulk transfers can be issued,
84 * the programm has to wait for completion. This does not allows asynchronous data transfer.
85 *
86 * Bulk Transfers
87 * --------------
88 * Bulk Transfers are issued by filling the tmp_td with the appropriate data and connect
89 * them to the qh_bulk queue header. Before other control/bulk transfers can be issued,
90 * the programm has to wait for completion. This does not allows asynchronous data transfer.
91 *
92 *
93 */
94
95#include <common.h>
96#include <ambapp.h>
97#include <asm/leon.h>
98#include <asm/leon3.h>
99#include <asm/processor.h>
100
101#ifdef CONFIG_USB_UHCI
102
103#include <usb.h>
104#include "usb_uhci.h"
105
106#define USB_MAX_TEMP_TD 128 /* number of temporary TDs for bulk and control transfers */
107#define USB_MAX_TEMP_INT_TD 32 /* number of temporary TDs for Interrupt transfers */
108
109extern int leon3_snooping_avail;
110/*
111#define out16r(address,data) (*(unsigned short *)(address) = \
112 (unsigned short)( \
113 (((unsigned short)(data)&0xff)<<8) | \
114 (((unsigned short)(data)&0xff00)>>8) \
115 ))
116 */
117#define out16r(address,data) _out16r((unsigned int)(address), (unsigned short)(data))
118void _out16r(unsigned int address, unsigned short data)
119{
120 unsigned short val = (unsigned short)((((unsigned short)(data) & 0xff)
121 << 8) | (((unsigned short)(data)
122 & 0xff00) >> 8));
123#ifdef UHCI_DEBUG_REGS
124 printf("out16r(0x%lx,0x%04x = 0x%04x)\n", address, val, data);
125#endif
126 *(unsigned short *)(address) = val;
127}
128
129#define out32r(address,data) _out32r((unsigned int)(address), (unsigned int)(data))
130void _out32r(unsigned int address, unsigned int data)
131{
132 unsigned int val = (unsigned int)((((unsigned int)(data) & 0x000000ff)
133 << 24) | (((unsigned int)(data) &
134 0x0000ff00) << 8) |
135 (((unsigned int)(data) & 0x00ff0000)
136 >> 8) | (((unsigned int)(data) &
137 0xff000000) >> 24));
138#ifdef UHCI_DEBUG_REGS
139 printf("out32r(0x%lx,0x%lx = 0x%lx)\n", address, val, data);
140#endif
141 *(unsigned int *)address = val;
142}
143
144#define in16r(address) _in16r((unsigned int)(address))
145unsigned short _in16r(unsigned int address)
146{
147 unsigned short val = sparc_load_reg_cachemiss_word(address);
148 val = ((val << 8) & 0xff00) | ((val >> 8) & 0xff);
149#ifdef UHCI_DEBUG_REGS
150 printf("in16r(0x%lx): 0x%04x\n", address, val);
151#endif
152 return val;
153}
154
155#define in32r(address) _in32r((unsigned int)(address))
156unsigned int _in32r(unsigned int address)
157{
158 unsigned int val = sparc_load_reg_cachemiss(address);
159 val =
160 ((val << 24) & 0xff000000) | ((val << 8) & 0xff0000) | ((val >> 8) &
161 0xff00) |
162 ((val >> 24) & 0xff);
163#ifdef UHCI_DEBUG_REGS
164 printf("in32r(0x%lx): 0x%08x\n", address, val);
165#endif
166 return val;
167}
168
169#define READ32(address) sparc_load_reg_cachemiss((unsigned int)(address))
170
171/*#define USB_UHCI_DEBUG*/
172#undef USB_UHCI_DEBUG
173
174void usb_show_td(int max);
175#ifdef USB_UHCI_DEBUG
176void grusb_show_regs(void);
177#define USB_UHCI_PRINTF(fmt,args...) printf (fmt ,##args)
178#else
179#define USB_UHCI_PRINTF(fmt,args...)
180#endif
181
182static int grusb_irq = -1; /* irq vector, if -1 uhci is stopped / reseted */
183unsigned int usb_base_addr; /* base address */
184
185static uhci_td_t td_int[8] __attribute__ ((aligned(16))); /* Interrupt Transfer descriptors */
186static uhci_qh_t qh_cntrl __attribute__ ((aligned(16))); /* control Queue Head */
187static uhci_qh_t qh_bulk __attribute__ ((aligned(16))); /* bulk Queue Head */
188static uhci_qh_t qh_end __attribute__ ((aligned(16))); /* end Queue Head */
189static uhci_td_t td_last __attribute__ ((aligned(16))); /* last TD (linked with end chain) */
190
191/* temporary tds */
192static uhci_td_t tmp_td[USB_MAX_TEMP_TD] __attribute__ ((aligned(16))); /* temporary bulk/control td's */
193static uhci_td_t tmp_int_td[USB_MAX_TEMP_INT_TD] __attribute__ ((aligned(16))); /* temporary interrupt td's */
194
195static unsigned long framelist[1024] __attribute__ ((aligned(0x1000))); /* frame list */
196
197static struct virt_root_hub rh; /* struct for root hub */
198
199/**********************************************************************
200 * some forward decleration
201 */
202int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
203 void *buffer, int transfer_len,
204 struct devrequest *setup);
205
206/* fill a td with the approproiate data. Link, status, info and buffer
207 * are used by the USB controller itselfes, dev is used to identify the
208 * "connected" device
209 */
210void usb_fill_td(uhci_td_t * td, unsigned long link, unsigned long status,
211 unsigned long info, unsigned long buffer, unsigned long dev)
212{
213 td->link = swap_32(link);
214 td->status = swap_32(status);
215 if ((info & UHCI_PID) == 0)
216 info |= USB_PID_OUT;
217 td->info = swap_32(info);
218 td->buffer = swap_32(buffer);
219 td->dev_ptr = dev;
220}
221
222/* fill a qh with the approproiate data. Head and element are used by the USB controller
223 * itselfes. As soon as a valid dev_ptr is filled, a td chain is connected to the qh.
224 * Please note, that after completion of the td chain, the entry element is removed /
225 * marked invalid by the USB controller.
226 */
227void usb_fill_qh(uhci_qh_t * qh, unsigned long head, unsigned long element)
228{
229 qh->head = swap_32(head);
230 qh->element = swap_32(element);
231 qh->dev_ptr = 0L;
232}
233
234/* get the status of a td->status
235 */
236unsigned long usb_uhci_td_stat(unsigned long status)
237{
238 unsigned long result = 0;
239 result |= (status & TD_CTRL_NAK) ? USB_ST_NAK_REC : 0;
240 result |= (status & TD_CTRL_STALLED) ? USB_ST_STALLED : 0;
241 result |= (status & TD_CTRL_DBUFERR) ? USB_ST_BUF_ERR : 0;
242 result |= (status & TD_CTRL_BABBLE) ? USB_ST_BABBLE_DET : 0;
243 result |= (status & TD_CTRL_CRCTIMEO) ? USB_ST_CRC_ERR : 0;
244 result |= (status & TD_CTRL_BITSTUFF) ? USB_ST_BIT_ERR : 0;
245 result |= (status & TD_CTRL_ACTIVE) ? USB_ST_NOT_PROC : 0;
246 return result;
247}
248
249/* get the status and the transfered len of a td chain.
250 * called from the completion handler
251 */
252int usb_get_td_status(uhci_td_t * td, struct usb_device *dev)
253{
254 unsigned long temp, info;
255 unsigned long stat;
256 uhci_td_t *mytd = td;
257
258 if (dev->devnum == rh.devnum)
259 return 0;
260 dev->act_len = 0;
261 stat = 0;
262 do {
263 temp = swap_32((unsigned long)READ32(&mytd->status));
264 stat = usb_uhci_td_stat(temp);
265 info = swap_32((unsigned long)READ32(&mytd->info));
266 if (((info & 0xff) != USB_PID_SETUP) && (((info >> 21) & 0x7ff) != 0x7ff) && (temp & 0x7FF) != 0x7ff) { /* if not setup and not null data pack */
267 dev->act_len += (temp & 0x7FF) + 1; /* the transfered len is act_len + 1 */
268 }
269 if (stat) { /* status no ok */
270 dev->status = stat;
271 return -1;
272 }
273 temp = swap_32((unsigned long)READ32(&mytd->link));
274 mytd = (uhci_td_t *) (temp & 0xfffffff0);
275 } while ((temp & 0x1) == 0); /* process all TDs */
276 dev->status = stat;
277 return 0; /* Ok */
278}
279
280/*-------------------------------------------------------------------
281 * LOW LEVEL STUFF
282 * assembles QHs und TDs for control, bulk and iso
283 *-------------------------------------------------------------------*/
284int dummy(void)
285{
286 USB_UHCI_PRINTF("DUMMY\n");
287 return 0;
288}
289
290/* Submits a control message. That is a Setup, Data and Status transfer.
291 * Routine does not wait for completion.
292 */
293int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
294 int transfer_len, struct devrequest *setup)
295{
296 unsigned long destination, status;
297 int maxsze = usb_maxpacket(dev, pipe);
298 unsigned long dataptr;
299 int len;
300 int pktsze;
301 int i = 0;
302
303 if (!maxsze) {
304 USB_UHCI_PRINTF
305 ("uhci_submit_control_urb: pipesize for pipe %lx is zero\n",
306 pipe);
307 return -1;
308 }
309 if (((pipe >> 8) & 0x7f) == rh.devnum) {
310 /* this is the root hub -> redirect it */
311 return uhci_submit_rh_msg(dev, pipe, buffer, transfer_len,
312 setup);
313 }
314 USB_UHCI_PRINTF("uhci_submit_control start len %x, maxsize %x\n",
315 transfer_len, maxsze);
316 /* The "pipe" thing contains the destination in bits 8--18 */
317 destination = (pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; /* Setup stage */
318 /* 3 errors */
319 status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
320 /* (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD); */
321 /* Build the TD for the control request, try forever, 8 bytes of data */
322 usb_fill_td(&tmp_td[i], UHCI_PTR_TERM, status, destination | (7 << 21),
323 (unsigned long)setup, (unsigned long)dev);
324#ifdef DEBUG_EXTRA
325 {
326 char *sp = (char *)setup;
327 printf("SETUP to pipe %lx: %x %x %x %x %x %x %x %x\n", pipe,
328 sp[0], sp[1], sp[2], sp[3], sp[4], sp[5], sp[6], sp[7]);
329 }
330#endif
331 dataptr = (unsigned long)buffer;
332 len = transfer_len;
333
334 /* If direction is "send", change the frame from SETUP (0x2D)
335 to OUT (0xE1). Else change it from SETUP to IN (0x69). */
336 destination =
337 (pipe & PIPE_DEVEP_MASK) | ((pipe & USB_DIR_IN) ==
338 0 ? USB_PID_OUT : USB_PID_IN);
339 while (len > 0) {
340 /* data stage */
341 pktsze = len;
342 i++;
343 if (pktsze > maxsze)
344 pktsze = maxsze;
345 destination ^= 1 << TD_TOKEN_TOGGLE; /* toggle DATA0/1 */
346 usb_fill_td(&tmp_td[i], UHCI_PTR_TERM, status, destination | ((pktsze - 1) << 21), dataptr, (unsigned long)dev); /* Status, pktsze bytes of data */
347 tmp_td[i - 1].link = swap_32((unsigned long)&tmp_td[i]);
348
349 dataptr += pktsze;
350 len -= pktsze;
351 }
352
353 /* Build the final TD for control status */
354 /* It's only IN if the pipe is out AND we aren't expecting data */
355
356 destination &= ~UHCI_PID;
357 if (((pipe & USB_DIR_IN) == 0) || (transfer_len == 0))
358 destination |= USB_PID_IN;
359 else
360 destination |= USB_PID_OUT;
361 destination |= 1 << TD_TOKEN_TOGGLE; /* End in Data1 */
362 i++;
363 status &= ~TD_CTRL_SPD;
364 /* no limit on errors on final packet , 0 bytes of data */
365 usb_fill_td(&tmp_td[i], UHCI_PTR_TERM, status | TD_CTRL_IOC,
366 destination | (UHCI_NULL_DATA_SIZE << 21), 0,
367 (unsigned long)dev);
368 tmp_td[i - 1].link = swap_32((unsigned long)&tmp_td[i]); /* queue status td */
369 /* usb_show_td(i+1); */
370 USB_UHCI_PRINTF("uhci_submit_control end (%d tmp_tds used)\n", i);
371 /* first mark the control QH element terminated */
372 qh_cntrl.element = 0xffffffffL;
373 /* set qh active */
374 qh_cntrl.dev_ptr = (unsigned long)dev;
375 /* fill in tmp_td_chain */
376 dummy();
377 qh_cntrl.element = swap_32((unsigned long)&tmp_td[0]);
378 return 0;
379}
380
381/*-------------------------------------------------------------------
382 * Prepare TDs for bulk transfers.
383 */
384int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
385 int transfer_len)
386{
387 unsigned long destination, status, info;
388 unsigned long dataptr;
389 int maxsze = usb_maxpacket(dev, pipe);
390 int len;
391 int i = 0;
392
393 if (transfer_len < 0) {
394 printf("Negative transfer length in submit_bulk\n");
395 return -1;
396 }
397 if (!maxsze)
398 return -1;
399 /* The "pipe" thing contains the destination in bits 8--18. */
400 destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid(pipe);
401 /* 3 errors */
402 status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
403 /* ((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27); */
404 /* Build the TDs for the bulk request */
405 len = transfer_len;
406 dataptr = (unsigned long)buffer;
407 do {
408 int pktsze = len;
409 if (pktsze > maxsze)
410 pktsze = maxsze;
411 /* pktsze bytes of data */
412 info =
413 destination | (((pktsze - 1) & UHCI_NULL_DATA_SIZE) << 21) |
414 (usb_gettoggle
415 (dev, usb_pipeendpoint(pipe),
416 usb_pipeout(pipe)) << TD_TOKEN_TOGGLE);
417
418 if ((len - pktsze) == 0)
419 status |= TD_CTRL_IOC; /* last one generates INT */
420
421 usb_fill_td(&tmp_td[i], UHCI_PTR_TERM, status, info, dataptr, (unsigned long)dev); /* Status, pktsze bytes of data */
422 if (i > 0)
423 tmp_td[i - 1].link = swap_32((unsigned long)&tmp_td[i]);
424 i++;
425 dataptr += pktsze;
426 len -= pktsze;
427 usb_dotoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
428 } while (len > 0);
429 /* first mark the bulk QH element terminated */
430 qh_bulk.element = 0xffffffffL;
431 /* set qh active */
432 qh_bulk.dev_ptr = (unsigned long)dev;
433 /* fill in tmp_td_chain */
434 qh_bulk.element = swap_32((unsigned long)&tmp_td[0]);
435 return 0;
436}
437
438/* search a free interrupt td
439 */
440uhci_td_t *uhci_alloc_int_td(void)
441{
442 int i;
443 for (i = 0; i < USB_MAX_TEMP_INT_TD; i++) {
444 if (tmp_int_td[i].dev_ptr == 0) /* no device assigned -> free TD */
445 return &tmp_int_td[i];
446 }
447 return NULL;
448}
449
450/*-------------------------------------------------------------------
451 * submits USB interrupt (ie. polling ;-)
452 */
453int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
454 int transfer_len, int interval)
455{
456 int nint, n;
457 unsigned long status, destination;
458 unsigned long info, tmp;
459 uhci_td_t *mytd;
460 if (interval < 0 || interval >= 256)
461 return -1;
462
463 if (interval == 0)
464 nint = 0;
465 else {
466 for (nint = 0, n = 1; nint <= 8; nint++, n += n) { /* round interval down to 2^n */
467 if (interval < n) {
468 interval = n / 2;
469 break;
470 }
471 }
472 nint--;
473 }
474
475 USB_UHCI_PRINTF("Rounded interval to %i, chain %i\n", interval, nint);
476 mytd = uhci_alloc_int_td();
477 if (mytd == NULL) {
478 printf("No free INT TDs found\n");
479 return -1;
480 }
481 status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | (3 << 27);
482/* (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
483*/
484
485 destination =
486 (pipe & PIPE_DEVEP_MASK) | usb_packetid(pipe) |
487 (((transfer_len - 1) & 0x7ff) << 21);
488
489 info =
490 destination |
491 (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) <<
492 TD_TOKEN_TOGGLE);
493 tmp = swap_32(td_int[nint].link);
494 usb_fill_td(mytd, tmp, status, info, (unsigned long)buffer,
495 (unsigned long)dev);
496 /* Link it */
497 tmp = swap_32((unsigned long)mytd);
498 td_int[nint].link = tmp;
499
500 usb_dotoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
501
502 return 0;
503}
504
505/**********************************************************************
506 * Low Level functions
507 */
508
509void reset_hc(void)
510{
511
512 /* Global reset for 100ms */
513 out16r(usb_base_addr + USBPORTSC1, 0x0204);
514 out16r(usb_base_addr + USBPORTSC2, 0x0204);
515 out16r(usb_base_addr + USBCMD, USBCMD_GRESET | USBCMD_RS);
516 /* Turn off all interrupts */
517 out16r(usb_base_addr + USBINTR, 0);
518 wait_ms(50);
519 out16r(usb_base_addr + USBCMD, 0);
520 wait_ms(10);
521}
522
523void start_hc(void)
524{
525 int timeout = 1000;
526
527 while (in16r(usb_base_addr + USBCMD) & USBCMD_HCRESET) {
528 if (!--timeout) {
529 printf("USBCMD_HCRESET timed out!\n");
530 break;
531 }
532 }
533 /* Turn on all interrupts */
534 out16r(usb_base_addr + USBINTR,
535 USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP);
536 /* Start at frame 0 */
537 out16r(usb_base_addr + USBFRNUM, 0);
538 /* set Framebuffer base address */
539 out32r(usb_base_addr + USBFLBASEADD, (unsigned long)&framelist);
540 /* Run and mark it configured with a 64-byte max packet */
541 out16r(usb_base_addr + USBCMD, USBCMD_RS | USBCMD_CF | USBCMD_MAXP);
542}
543
544/* Initialize the skeleton
545 */
546void usb_init_skel(void)
547{
548 unsigned long temp;
549 int n;
550
551 for (n = 0; n < USB_MAX_TEMP_INT_TD; n++)
552 tmp_int_td[n].dev_ptr = 0L; /* no devices connected */
553 /* last td */
554 usb_fill_td(&td_last, UHCI_PTR_TERM, TD_CTRL_IOC, USB_PID_OUT, 0, 0L);
555 /* usb_fill_td(&td_last,UHCI_PTR_TERM,0,0,0); */
556 /* End Queue Header */
557 usb_fill_qh(&qh_end, UHCI_PTR_TERM, (unsigned long)&td_last);
558 /* Bulk Queue Header */
559 temp = (unsigned long)&qh_end;
560 usb_fill_qh(&qh_bulk, temp | UHCI_PTR_QH, UHCI_PTR_TERM);
561 /* Control Queue Header */
562 temp = (unsigned long)&qh_bulk;
563 usb_fill_qh(&qh_cntrl, temp | UHCI_PTR_QH, UHCI_PTR_TERM);
564 /* 1ms Interrupt td */
565 temp = (unsigned long)&qh_cntrl;
566 usb_fill_td(&td_int[0], temp | UHCI_PTR_QH, 0, USB_PID_OUT, 0, 0L);
567 temp = (unsigned long)&td_int[0];
568 for (n = 1; n < 8; n++)
569 usb_fill_td(&td_int[n], temp, 0, USB_PID_OUT, 0, 0L);
570 for (n = 0; n < 1024; n++) {
571 /* link all framelist pointers to one of the interrupts */
572 int m, o;
573 if ((n & 127) == 127)
574 framelist[n] = swap_32((unsigned long)&td_int[0]);
575 else
576 for (o = 1, m = 2; m <= 128; o++, m += m)
577 if ((n & (m - 1)) == ((m - 1) / 2))
578 framelist[n] =
579 swap_32((unsigned long)&td_int[o]);
580
581 }
582}
583
584/* check the common skeleton for completed transfers, and update the status
585 * of the "connected" device. Called from the IRQ routine.
586 */
587void usb_check_skel(void)
588{
589 struct usb_device *dev;
590 /* start with the control qh */
591 if (qh_cntrl.dev_ptr != 0) { /* it's a device assigned check if this caused IRQ */
592 dev = (struct usb_device *)qh_cntrl.dev_ptr;
593 /* Flush cache now that hardware updated DATA and TDs/QHs */
594 if (!leon3_snooping_avail)
595 sparc_dcache_flush_all();
596 usb_get_td_status(&tmp_td[0], dev); /* update status */
597 if (!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */
598 qh_cntrl.dev_ptr = 0;
599 }
600 }
601 /* now process the bulk */
602 if (qh_bulk.dev_ptr != 0) { /* it's a device assigned check if this caused IRQ */
603 dev = (struct usb_device *)qh_bulk.dev_ptr;
604 /* Flush cache now that hardware updated DATA and TDs/QHs */
605 if (!leon3_snooping_avail)
606 sparc_dcache_flush_all();
607 usb_get_td_status(&tmp_td[0], dev); /* update status */
608 if (!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */
609 qh_bulk.dev_ptr = 0;
610 }
611 }
612}
613
614/* check the interrupt chain, ubdate the status of the appropriate device,
615 * call the appropriate irqhandler and reactivate the TD if the irqhandler
616 * returns with 1
617 */
618void usb_check_int_chain(void)
619{
620 int i, res;
621 unsigned long link, status;
622 struct usb_device *dev;
623 uhci_td_t *td, *prevtd;
624
625 for (i = 0; i < 8; i++) {
626 prevtd = &td_int[i]; /* the first previous td is the skeleton td */
627 link = swap_32(READ32(&td_int[i].link)) & 0xfffffff0; /* next in chain */
628 td = (uhci_td_t *) link; /* assign it */
629 /* all interrupt TDs are finally linked to the td_int[0].
630 * so we process all until we find the td_int[0].
631 * if int0 chain points to a QH, we're also done
632 */
633 while (((i > 0) && (link != (unsigned long)&td_int[0])) ||
634 ((i == 0)
635 && !(swap_32(READ32(&td->link)) & UHCI_PTR_QH))) {
636 /* check if a device is assigned with this td */
637 status = swap_32(READ32(&td->status));
638 if ((td->dev_ptr != 0L) && !(status & TD_CTRL_ACTIVE)) {
639 /* td is not active and a device is assigned -> call irqhandler */
640 dev = (struct usb_device *)td->dev_ptr;
641 dev->irq_act_len = ((status & 0x7FF) == 0x7FF) ? 0 : (status & 0x7FF) + 1; /* transfered length */
642 dev->irq_status = usb_uhci_td_stat(status); /* get status */
643 res = dev->irq_handle(dev); /* call irqhandler */
644 if (res == 1) {
645 /* reactivate */
646 status |= TD_CTRL_ACTIVE;
647 td->status = swap_32(status);
648 prevtd = td; /* previous td = this td */
649 } else {
650 prevtd->link = READ32(&td->link); /* link previous td directly to the nex td -> unlinked */
651 /* remove device pointer */
652 td->dev_ptr = 0L;
653 }
654 } /* if we call the irq handler */
655 link = swap_32(READ32(&td->link)) & 0xfffffff0; /* next in chain */
656 td = (uhci_td_t *) link; /* assign it */
657 } /* process all td in this int chain */
658 } /* next interrupt chain */
659}
660
661/* usb interrupt service routine.
662 */
663void handle_usb_interrupt(void)
664{
665 unsigned short status;
666 static int error = 0;
667
668 /*
669 * Read the interrupt status, and write it back to clear the
670 * interrupt cause
671 */
672
673 status = in16r(usb_base_addr + USBSTS);
674
675 if (!status) /* shared interrupt, not mine */
676 return;
677 if (status != 1) {
678 /* remove host controller halted state */
679 if ((status & (USBSTS_HCPE | USBSTS_HCH)) ==
680 (USBSTS_HCPE | USBSTS_HCH)) {
681 /* Stop due to bug in driver, or hardware */
682 out16r(usb_base_addr + USBSTS, status);
683 out16r(usb_base_addr + USBCMD,
684 USBCMD_HCRESET | USBCMD_GRESET);
685 printf
686 ("GRUSB: HW detected error(s) in USB Descriptors (STS: 0x%x)\n",
687 status);
688 usb_show_td(8);
689 return;
690 } else if ((status & 0x20)
691 && ((in16r(usb_base_addr + USBCMD) & USBCMD_RS) ==
692 0)) {
693 if (error < 10) {
694 out16r(usb_base_addr + USBCMD,
695 USBCMD_RS | in16r(usb_base_addr +
696 USBCMD));
697 error++;
698 }
699 } else
700 error = 0;
701 }
702 usb_check_int_chain(); /* call interrupt handlers for int tds */
703 usb_check_skel(); /* call completion handler for common transfer routines */
704 out16r(usb_base_addr + USBSTS, status);
705}
706
707/* init uhci
708 */
709int usb_lowlevel_init(void)
710{
711 unsigned char temp;
712 ambapp_ahbdev ahbdev;
713
714 /* Find GRUSB core using AMBA Plug&Play information */
715 if (ambapp_ahbslv_first(VENDOR_GAISLER, GAISLER_UHCI, &ahbdev) != 1) {
716 printf("USB UHCI: Failed to find GRUSB controller\n");
717 return -1;
718 }
719 usb_base_addr = ahbdev.address[0];
720 grusb_irq = ahbdev.irq;
721 /*
722 usb_base_addr = 0xfffa0000;
723 grusb_irq = 10;
724 */
725#ifdef USB_UHCI_DEBUG
726 grusb_show_regs();
727#endif
728 memset(td_int, 0, sizeof(td_int));
729 memset(tmp_td, 0, sizeof(tmp_td));
730 memset(tmp_int_td, 0, sizeof(tmp_int_td));
731 memset(&qh_cntrl, 0, sizeof(qh_cntrl));
732 memset(&qh_end, 0, sizeof(qh_end));
733 memset(&td_last, 0, sizeof(td_last));
734
735 irq_free_handler(grusb_irq);
736 USB_UHCI_PRINTF("GRUSB: at 0x%lx irq %d\n", usb_base_addr, grusb_irq);
737 rh.devnum = 0;
738 usb_init_skel();
739 reset_hc();
740 start_hc();
741 irq_install_handler(grusb_irq,
742 (interrupt_handler_t *) handle_usb_interrupt, NULL);
743 return 0;
744}
745
746/* stop uhci
747 */
748int usb_lowlevel_stop(void)
749{
750 if (grusb_irq == -1)
751 return 1;
752 irq_free_handler(grusb_irq);
753 reset_hc();
754 grusb_irq = -1;
755 return 0;
756}
757
758/*******************************************************************************************
759 * Virtual Root Hub
760 * Since the uhci does not have a real HUB, we simulate one ;-)
761 */
762#undef USB_RH_DEBUG
763
764#ifdef USB_RH_DEBUG
765#define USB_RH_PRINTF(fmt,args...) printf (fmt ,##args)
766static void usb_display_wValue(unsigned short wValue, unsigned short wIndex);
767static void usb_display_Req(unsigned short req);
768#else
769#define USB_RH_PRINTF(fmt,args...)
770static void usb_display_wValue(unsigned short wValue, unsigned short wIndex)
771{
772}
773static void usb_display_Req(unsigned short req)
774{
775}
776#endif
777
778static unsigned char root_hub_dev_des[] = {
779 0x12, /* __u8 bLength; */
780 0x01, /* __u8 bDescriptorType; Device */
781 0x00, /* __u16 bcdUSB; v1.0 */
782 0x01,
783 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
784 0x00, /* __u8 bDeviceSubClass; */
785 0x00, /* __u8 bDeviceProtocol; */
786 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
787 0x00, /* __u16 idVendor; */
788 0x00,
789 0x00, /* __u16 idProduct; */
790 0x00,
791 0x00, /* __u16 bcdDevice; */
792 0x00,
793 0x01, /* __u8 iManufacturer; */
794 0x00, /* __u8 iProduct; */
795 0x00, /* __u8 iSerialNumber; */
796 0x01 /* __u8 bNumConfigurations; */
797};
798
799/* Configuration descriptor */
800static unsigned char root_hub_config_des[] = {
801 0x09, /* __u8 bLength; */
802 0x02, /* __u8 bDescriptorType; Configuration */
803 0x19, /* __u16 wTotalLength; */
804 0x00,
805 0x01, /* __u8 bNumInterfaces; */
806 0x01, /* __u8 bConfigurationValue; */
807 0x00, /* __u8 iConfiguration; */
808 0x40, /* __u8 bmAttributes;
809 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
810 0x00, /* __u8 MaxPower; */
811
812 /* interface */
813 0x09, /* __u8 if_bLength; */
814 0x04, /* __u8 if_bDescriptorType; Interface */
815 0x00, /* __u8 if_bInterfaceNumber; */
816 0x00, /* __u8 if_bAlternateSetting; */
817 0x01, /* __u8 if_bNumEndpoints; */
818 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
819 0x00, /* __u8 if_bInterfaceSubClass; */
820 0x00, /* __u8 if_bInterfaceProtocol; */
821 0x00, /* __u8 if_iInterface; */
822
823 /* endpoint */
824 0x07, /* __u8 ep_bLength; */
825 0x05, /* __u8 ep_bDescriptorType; Endpoint */
826 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
827 0x03, /* __u8 ep_bmAttributes; Interrupt */
828 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */
829 0x00,
830 0xff /* __u8 ep_bInterval; 255 ms */
831};
832
833static unsigned char root_hub_hub_des[] = {
834 0x09, /* __u8 bLength; */
835 0x29, /* __u8 bDescriptorType; Hub-descriptor */
836 0x02, /* __u8 bNbrPorts; */
837 0x00, /* __u16 wHubCharacteristics; */
838 0x00,
839 0x01, /* __u8 bPwrOn2pwrGood; 2ms */
840 0x00, /* __u8 bHubContrCurrent; 0 mA */
841 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */
842 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
843};
844
845static unsigned char root_hub_str_index0[] = {
846 0x04, /* __u8 bLength; */
847 0x03, /* __u8 bDescriptorType; String-descriptor */
848 0x09, /* __u8 lang ID */
849 0x04, /* __u8 lang ID */
850};
851
852static unsigned char root_hub_str_index1[] = {
853 28, /* __u8 bLength; */
854 0x03, /* __u8 bDescriptorType; String-descriptor */
855 'U', /* __u8 Unicode */
856 0, /* __u8 Unicode */
857 'H', /* __u8 Unicode */
858 0, /* __u8 Unicode */
859 'C', /* __u8 Unicode */
860 0, /* __u8 Unicode */
861 'I', /* __u8 Unicode */
862 0, /* __u8 Unicode */
863 ' ', /* __u8 Unicode */
864 0, /* __u8 Unicode */
865 'R', /* __u8 Unicode */
866 0, /* __u8 Unicode */
867 'o', /* __u8 Unicode */
868 0, /* __u8 Unicode */
869 'o', /* __u8 Unicode */
870 0, /* __u8 Unicode */
871 't', /* __u8 Unicode */
872 0, /* __u8 Unicode */
873 ' ', /* __u8 Unicode */
874 0, /* __u8 Unicode */
875 'H', /* __u8 Unicode */
876 0, /* __u8 Unicode */
877 'u', /* __u8 Unicode */
878 0, /* __u8 Unicode */
879 'b', /* __u8 Unicode */
880 0, /* __u8 Unicode */
881};
882
883/*
884 * Root Hub Control Pipe (interrupt Pipes are not supported)
885 */
886
887int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
888 int transfer_len, struct devrequest *cmd)
889{
890 void *data = buffer;
891 int leni = transfer_len;
892 int len = 0;
893 int status = 0;
894 int stat = 0;
895 int i;
896
897 unsigned short cstatus;
898
899 unsigned short bmRType_bReq;
900 unsigned short wValue;
901 unsigned short wIndex;
902 unsigned short wLength;
903
Remy Bohmer9dbc3662008-10-10 10:23:22 +0200904 if (usb_pipeint(pipe)) {
Daniel Hellstrom1e9a1642008-03-26 22:51:29 +0100905 printf("Root-Hub submit IRQ: NOT implemented\n");
906 return 0;
907 }
908 bmRType_bReq = cmd->requesttype | cmd->request << 8;
909 wValue = swap_16(cmd->value);
910 wIndex = swap_16(cmd->index);
911 wLength = swap_16(cmd->length);
912 usb_display_Req(bmRType_bReq);
913 for (i = 0; i < 8; i++)
914 rh.c_p_r[i] = 0;
915 USB_RH_PRINTF("Root-Hub: adr: %2x cmd(%1x): %02x%02x %04x %04x %04x\n",
916 dev->devnum, 8, cmd->requesttype, cmd->request, wValue,
917 wIndex, wLength);
918
919 switch (bmRType_bReq) {
920 /* Request Destination:
921 without flags: Device,
922 RH_INTERFACE: interface,
923 RH_ENDPOINT: endpoint,
924 RH_CLASS means HUB here,
925 RH_OTHER | RH_CLASS almost ever means HUB_PORT here
926 */
927
928 case RH_GET_STATUS:
929 *(unsigned short *)data = swap_16(1);
930 len = 2;
931 break;
932 case RH_GET_STATUS | RH_INTERFACE:
933 *(unsigned short *)data = swap_16(0);
934 len = 2;
935 break;
936 case RH_GET_STATUS | RH_ENDPOINT:
937 *(unsigned short *)data = swap_16(0);
938 len = 2;
939 break;
940 case RH_GET_STATUS | RH_CLASS:
941 *(unsigned long *)data = swap_32(0);
942 len = 4;
943 break; /* hub power ** */
944 case RH_GET_STATUS | RH_OTHER | RH_CLASS:
945
946 status = in16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1));
947 cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |
948 ((status & USBPORTSC_PEC) >> (3 - 1)) |
949 (rh.c_p_r[wIndex - 1] << (0 + 4));
950 status = (status & USBPORTSC_CCS) | ((status & USBPORTSC_PE) >> (2 - 1)) | ((status & USBPORTSC_SUSP) >> (12 - 2)) | ((status & USBPORTSC_PR) >> (9 - 4)) | (1 << 8) | /* power on ** */
951 ((status & USBPORTSC_LSDA) << (-8 + 9));
952
953 *(unsigned short *)data = swap_16(status);
954 *(unsigned short *)(data + 2) = swap_16(cstatus);
955 len = 4;
956 break;
957 case RH_CLEAR_FEATURE | RH_ENDPOINT:
958 switch (wValue) {
959 case (RH_ENDPOINT_STALL):
960 len = 0;
961 break;
962 }
963 break;
964
965 case RH_CLEAR_FEATURE | RH_CLASS:
966 switch (wValue) {
967 case (RH_C_HUB_OVER_CURRENT):
968 len = 0; /* hub power over current ** */
969 break;
970 }
971 break;
972
973 case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
974 usb_display_wValue(wValue, wIndex);
975 switch (wValue) {
976 case (RH_PORT_ENABLE):
977 status =
978 in16r(usb_base_addr + USBPORTSC1 +
979 2 * (wIndex - 1));
980 status = (status & 0xfff5) & ~USBPORTSC_PE;
981 out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
982 status);
983 len = 0;
984 break;
985 case (RH_PORT_SUSPEND):
986 status =
987 in16r(usb_base_addr + USBPORTSC1 +
988 2 * (wIndex - 1));
989 status = (status & 0xfff5) & ~USBPORTSC_SUSP;
990 out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
991 status);
992 len = 0;
993 break;
994 case (RH_PORT_POWER):
995 len = 0; /* port power ** */
996 break;
997 case (RH_C_PORT_CONNECTION):
998 status =
999 in16r(usb_base_addr + USBPORTSC1 +
1000 2 * (wIndex - 1));
1001 status = (status & 0xfff5) | USBPORTSC_CSC;
1002 out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
1003 status);
1004 len = 0;
1005 break;
1006 case (RH_C_PORT_ENABLE):
1007 status =
1008 in16r(usb_base_addr + USBPORTSC1 +
1009 2 * (wIndex - 1));
1010 status = (status & 0xfff5) | USBPORTSC_PEC;
1011 out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
1012 status);
1013 len = 0;
1014 break;
1015 case (RH_C_PORT_SUSPEND):
1016/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
1017 len = 0;
1018 break;
1019 case (RH_C_PORT_OVER_CURRENT):
1020 len = 0;
1021 break;
1022 case (RH_C_PORT_RESET):
1023 rh.c_p_r[wIndex - 1] = 0;
1024 len = 0;
1025 break;
1026 }
1027 break;
1028 case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
1029 usb_display_wValue(wValue, wIndex);
1030 switch (wValue) {
1031 case (RH_PORT_SUSPEND):
1032 status =
1033 in16r(usb_base_addr + USBPORTSC1 +
1034 2 * (wIndex - 1));
1035 status = (status & 0xfff5) | USBPORTSC_SUSP;
1036 out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
1037 status);
1038 len = 0;
1039 break;
1040 case (RH_PORT_RESET):
1041 status =
1042 in16r(usb_base_addr + USBPORTSC1 +
1043 2 * (wIndex - 1));
1044 status = (status & 0xfff5) | USBPORTSC_PR;
1045 out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
1046 status);
1047 wait_ms(10);
1048 status = (status & 0xfff5) & ~USBPORTSC_PR;
1049 out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
1050 status);
1051 udelay(10);
1052 status = (status & 0xfff5) | USBPORTSC_PE;
1053 out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
1054 status);
1055 wait_ms(10);
1056 status = (status & 0xfff5) | 0xa;
1057 out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
1058 status);
1059 len = 0;
1060 break;
1061 case (RH_PORT_POWER):
1062 len = 0; /* port power ** */
1063 break;
1064 case (RH_PORT_ENABLE):
1065 status =
1066 in16r(usb_base_addr + USBPORTSC1 +
1067 2 * (wIndex - 1));
1068 status = (status & 0xfff5) | USBPORTSC_PE;
1069 out16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1),
1070 status);
1071 len = 0;
1072 break;
1073 }
1074 break;
1075
1076 case RH_SET_ADDRESS:
1077 rh.devnum = wValue;
1078 len = 0;
1079 break;
1080 case RH_GET_DESCRIPTOR:
1081 switch ((wValue & 0xff00) >> 8) {
1082 case (0x01): /* device descriptor */
1083 i = sizeof(root_hub_config_des);
1084 status = i > wLength ? wLength : i;
1085 len = leni > status ? status : leni;
1086 memcpy(data, root_hub_dev_des, len);
1087 break;
1088 case (0x02): /* configuration descriptor */
1089 i = sizeof(root_hub_config_des);
1090 status = i > wLength ? wLength : i;
1091 len = leni > status ? status : leni;
1092 memcpy(data, root_hub_config_des, len);
1093 break;
1094 case (0x03): /*string descriptors */
1095 if (wValue == 0x0300) {
1096 i = sizeof(root_hub_str_index0);
1097 status = i > wLength ? wLength : i;
1098 len = leni > status ? status : leni;
1099 memcpy(data, root_hub_str_index0, len);
1100 break;
1101 }
1102 if (wValue == 0x0301) {
1103 i = sizeof(root_hub_str_index1);
1104 status = i > wLength ? wLength : i;
1105 len = leni > status ? status : leni;
1106 memcpy(data, root_hub_str_index1, len);
1107 break;
1108 }
1109 stat = USB_ST_STALLED;
1110 }
1111 break;
1112
1113 case RH_GET_DESCRIPTOR | RH_CLASS:
1114 root_hub_hub_des[2] = 2;
1115 i = sizeof(root_hub_hub_des);
1116 status = i > wLength ? wLength : i;
1117 len = leni > status ? status : leni;
1118 memcpy(data, root_hub_hub_des, len);
1119 break;
1120 case RH_GET_CONFIGURATION:
1121 *(unsigned char *)data = 0x01;
1122 len = 1;
1123 break;
1124 case RH_SET_CONFIGURATION:
1125 len = 0;
1126 break;
1127 default:
1128 stat = USB_ST_STALLED;
1129 }
1130 USB_RH_PRINTF("Root-Hub stat %lx port1: %x port2: %x\n\n", stat,
1131 in16r(usb_base_addr + USBPORTSC1),
1132 in16r(usb_base_addr + USBPORTSC2));
1133 dev->act_len = len;
1134 dev->status = stat;
1135 return stat;
1136
1137}
1138
1139/********************************************************************************
1140 * Some Debug Routines
1141 */
1142
1143#ifdef USB_RH_DEBUG
1144
1145static void usb_display_Req(unsigned short req)
1146{
1147 USB_RH_PRINTF("- Root-Hub Request: ");
1148 switch (req) {
1149 case RH_GET_STATUS:
1150 USB_RH_PRINTF("Get Status ");
1151 break;
1152 case RH_GET_STATUS | RH_INTERFACE:
1153 USB_RH_PRINTF("Get Status Interface ");
1154 break;
1155 case RH_GET_STATUS | RH_ENDPOINT:
1156 USB_RH_PRINTF("Get Status Endpoint ");
1157 break;
1158 case RH_GET_STATUS | RH_CLASS:
1159 USB_RH_PRINTF("Get Status Class");
1160 break; /* hub power ** */
1161 case RH_GET_STATUS | RH_OTHER | RH_CLASS:
1162 USB_RH_PRINTF("Get Status Class Others");
1163 break;
1164 case RH_CLEAR_FEATURE | RH_ENDPOINT:
1165 USB_RH_PRINTF("Clear Feature Endpoint ");
1166 break;
1167 case RH_CLEAR_FEATURE | RH_CLASS:
1168 USB_RH_PRINTF("Clear Feature Class ");
1169 break;
1170 case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
1171 USB_RH_PRINTF("Clear Feature Other Class ");
1172 break;
1173 case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
1174 USB_RH_PRINTF("Set Feature Other Class ");
1175 break;
1176 case RH_SET_ADDRESS:
1177 USB_RH_PRINTF("Set Address ");
1178 break;
1179 case RH_GET_DESCRIPTOR:
1180 USB_RH_PRINTF("Get Descriptor ");
1181 break;
1182 case RH_GET_DESCRIPTOR | RH_CLASS:
1183 USB_RH_PRINTF("Get Descriptor Class ");
1184 break;
1185 case RH_GET_CONFIGURATION:
1186 USB_RH_PRINTF("Get Configuration ");
1187 break;
1188 case RH_SET_CONFIGURATION:
1189 USB_RH_PRINTF("Get Configuration ");
1190 break;
1191 default:
1192 USB_RH_PRINTF("****UNKNOWN**** 0x%04X ", req);
1193 }
1194 USB_RH_PRINTF("\n");
1195
1196}
1197
1198static void usb_display_wValue(unsigned short wValue, unsigned short wIndex)
1199{
1200 switch (wValue) {
1201 case (RH_PORT_ENABLE):
1202 USB_RH_PRINTF("Root-Hub: Enable Port %d\n", wIndex);
1203 break;
1204 case (RH_PORT_SUSPEND):
1205 USB_RH_PRINTF("Root-Hub: Suspend Port %d\n", wIndex);
1206 break;
1207 case (RH_PORT_POWER):
1208 USB_RH_PRINTF("Root-Hub: Port Power %d\n", wIndex);
1209 break;
1210 case (RH_C_PORT_CONNECTION):
1211 USB_RH_PRINTF("Root-Hub: C Port Connection Port %d\n", wIndex);
1212 break;
1213 case (RH_C_PORT_ENABLE):
1214 USB_RH_PRINTF("Root-Hub: C Port Enable Port %d\n", wIndex);
1215 break;
1216 case (RH_C_PORT_SUSPEND):
1217 USB_RH_PRINTF("Root-Hub: C Port Suspend Port %d\n", wIndex);
1218 break;
1219 case (RH_C_PORT_OVER_CURRENT):
1220 USB_RH_PRINTF("Root-Hub: C Port Over Current Port %d\n",
1221 wIndex);
1222 break;
1223 case (RH_C_PORT_RESET):
1224 USB_RH_PRINTF("Root-Hub: C Port reset Port %d\n", wIndex);
1225 break;
1226 default:
1227 USB_RH_PRINTF("Root-Hub: unknown %x %x\n", wValue, wIndex);
1228 break;
1229 }
1230}
1231
1232#endif
1233
1234/*#ifdef USB_UHCI_DEBUG*/
1235
1236static int usb_display_td(uhci_td_t * td)
1237{
1238 unsigned long tmp;
1239 int valid;
1240
1241 printf("TD at %p:\n", td);
1242
1243 tmp = swap_32(READ32(&td->link));
1244 printf("Link points to 0x%08lX, %s first, %s, %s\n", tmp & 0xfffffff0,
1245 ((tmp & 0x4) == 0x4) ? "Depth" : "Breath",
1246 ((tmp & 0x2) == 0x2) ? "QH" : "TD",
1247 ((tmp & 0x1) == 0x1) ? "invalid" : "valid");
1248 valid = ((tmp & 0x1) == 0x0);
1249 tmp = swap_32(READ32(&td->status));
1250 printf
1251 (" %s %ld Errors %s %s %s \n %s %s %s %s %s %s\n Len 0x%lX\n",
1252 (((tmp >> 29) & 0x1) == 0x1) ? "SPD Enable" : "SPD Disable",
1253 ((tmp >> 28) & 0x3),
1254 (((tmp >> 26) & 0x1) == 0x1) ? "Low Speed" : "Full Speed",
1255 (((tmp >> 25) & 0x1) == 0x1) ? "ISO " : "",
1256 (((tmp >> 24) & 0x1) == 0x1) ? "IOC " : "",
1257 (((tmp >> 23) & 0x1) == 0x1) ? "Active " : "Inactive ",
1258 (((tmp >> 22) & 0x1) == 0x1) ? "Stalled" : "",
1259 (((tmp >> 21) & 0x1) == 0x1) ? "Data Buffer Error" : "",
1260 (((tmp >> 20) & 0x1) == 0x1) ? "Babble" : "",
1261 (((tmp >> 19) & 0x1) == 0x1) ? "NAK" : "",
1262 (((tmp >> 18) & 0x1) == 0x1) ? "Bitstuff Error" : "",
1263 (tmp & 0x7ff));
1264 tmp = swap_32(READ32(&td->info));
1265 printf(" MaxLen 0x%lX\n", ((tmp >> 21) & 0x7FF));
1266 printf(" %sEndpoint 0x%lX Dev Addr 0x%lX PID 0x%lX\n",
1267 ((tmp >> 19) & 0x1) == 0x1 ? "TOGGLE " : "", ((tmp >> 15) & 0xF),
1268 ((tmp >> 8) & 0x7F), tmp & 0xFF);
1269 tmp = swap_32(READ32(&td->buffer));
1270 printf(" Buffer 0x%08lX\n", tmp);
1271 printf(" DEV %08lX\n", td->dev_ptr);
1272 return valid;
1273}
1274
1275void usb_show_td(int max)
1276{
1277 int i;
1278 if (max > 0) {
1279 for (i = 0; i < max; i++) {
1280 usb_display_td(&tmp_td[i]);
1281 }
1282 } else {
1283 i = 0;
1284 do {
1285 printf("tmp_td[%d]\n", i);
1286 } while (usb_display_td(&tmp_td[i++]));
1287 }
1288}
1289
1290void grusb_show_regs(void)
1291{
1292 unsigned int tmp;
1293
1294 tmp = in16r(usb_base_addr + USBCMD);
1295 printf(" USBCMD: 0x%04x\n", tmp);
1296 tmp = in16r(usb_base_addr + USBSTS);
1297 printf(" USBSTS: 0x%04x\n", tmp);
1298 tmp = in16r(usb_base_addr + USBINTR);
1299 printf(" USBINTR: 0x%04x\n", tmp);
1300 tmp = in16r(usb_base_addr + USBFRNUM);
1301 printf(" FRNUM: 0x%04x\n", tmp);
1302 tmp = in32r(usb_base_addr + USBFLBASEADD);
1303 printf(" FLBASEADD: 0x%08x\n", tmp);
1304 tmp = in16r(usb_base_addr + USBSOF);
1305 printf(" SOFMOD: 0x%04x\n", tmp);
1306 tmp = in16r(usb_base_addr + USBPORTSC1);
1307 printf(" PORTSC1: 0x%04x\n", tmp);
1308}
1309
1310/*#endif*/
1311#endif /* CONFIG_USB_UHCI */
1312
1313/* EOF */