1 /*
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 
109 extern 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))
_out16r(unsigned int address,unsigned short data)118 void _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))
_out32r(unsigned int address,unsigned int data)130 void _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))
_in16r(unsigned int address)145 unsigned 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))
_in32r(unsigned int address)156 unsigned 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 
174 void usb_show_td(int max);
175 #ifdef	USB_UHCI_DEBUG
176 void 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 
182 static int grusb_irq = -1;	/* irq vector, if -1 uhci is stopped / reseted */
183 unsigned int usb_base_addr;	/* base address */
184 
185 static uhci_td_t td_int[8] __attribute__ ((aligned(16)));	/* Interrupt Transfer descriptors */
186 static uhci_qh_t qh_cntrl __attribute__ ((aligned(16)));	/* control Queue Head */
187 static uhci_qh_t qh_bulk __attribute__ ((aligned(16)));	/*  bulk Queue Head */
188 static uhci_qh_t qh_end __attribute__ ((aligned(16)));	/* end Queue Head */
189 static uhci_td_t td_last __attribute__ ((aligned(16)));	/* last TD (linked with end chain) */
190 
191 /* temporary tds */
192 static uhci_td_t tmp_td[USB_MAX_TEMP_TD] __attribute__ ((aligned(16)));	/* temporary bulk/control td's  */
193 static uhci_td_t tmp_int_td[USB_MAX_TEMP_INT_TD] __attribute__ ((aligned(16)));	/* temporary interrupt td's  */
194 
195 static unsigned long framelist[1024] __attribute__ ((aligned(0x1000)));	/* frame list */
196 
197 static struct virt_root_hub rh;	/* struct for root hub */
198 
199 /**********************************************************************
200  * some forward decleration
201  */
202 int 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  */
usb_fill_td(uhci_td_t * td,unsigned long link,unsigned long status,unsigned long info,unsigned long buffer,unsigned long dev)210 void 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  */
usb_fill_qh(uhci_qh_t * qh,unsigned long head,unsigned long element)227 void 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  */
usb_uhci_td_stat(unsigned long status)236 unsigned 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  */
usb_get_td_status(uhci_td_t * td,struct usb_device * dev)252 int 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  *-------------------------------------------------------------------*/
dummy(void)284 int 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  */
submit_control_msg(struct usb_device * dev,unsigned long pipe,void * buffer,int transfer_len,struct devrequest * setup)293 int 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  */
submit_bulk_msg(struct usb_device * dev,unsigned long pipe,void * buffer,int transfer_len)384 int 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  */
uhci_alloc_int_td(void)440 uhci_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  */
submit_int_msg(struct usb_device * dev,unsigned long pipe,void * buffer,int transfer_len,int interval)453 int 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 
reset_hc(void)509 void 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 
start_hc(void)523 void 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  */
usb_init_skel(void)546 void 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  */
usb_check_skel(void)587 void 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  */
usb_check_int_chain(void)618 void 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  */
handle_usb_interrupt(void)663 void 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  */
usb_lowlevel_init(void)709 int 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  */
usb_lowlevel_stop(void)748 int 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)
766 static void usb_display_wValue(unsigned short wValue, unsigned short wIndex);
767 static void usb_display_Req(unsigned short req);
768 #else
769 #define USB_RH_PRINTF(fmt,args...)
usb_display_wValue(unsigned short wValue,unsigned short wIndex)770 static void usb_display_wValue(unsigned short wValue, unsigned short wIndex)
771 {
772 }
usb_display_Req(unsigned short req)773 static void usb_display_Req(unsigned short req)
774 {
775 }
776 #endif
777 
778 static 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 */
800 static 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 
833 static 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 
845 static 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 
852 static 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 
uhci_submit_rh_msg(struct usb_device * dev,unsigned long pipe,void * buffer,int transfer_len,struct devrequest * cmd)887 int 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 
904 	if (usb_pipeint(pipe)) {
905 		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 
usb_display_Req(unsigned short req)1145 static 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 
usb_display_wValue(unsigned short wValue,unsigned short wIndex)1198 static 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 
usb_display_td(uhci_td_t * td)1236 static 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 
usb_show_td(int max)1275 void 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 
grusb_show_regs(void)1290 void 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 */
1314