1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Main Module File: usbmain.c
6 * Main module that invokes the top of the USB stack from CFE.
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
48 #include "lib_types.h"
49 #include "lib_malloc.h"
50 #include "lib_string.h"
51 #include "lib_printf.h"
52 #include "lib_queue.h"
53 #include "lib_physio.h"
55 #include "cfe_timer.h"
56 #include "ui_command.h"
66 #include "bsp_config.h"
69 /* *********************************************************************
71 ********************************************************************* */
73 extern usb_hcdrv_t ohci_driver
; /* OHCI Driver dispatch */
75 extern int ohcidebug
; /* OHCI debug control */
76 extern int usb_noisy
; /* USBD debug control */
78 int usb_init(void); /* forward */
79 int ui_init_usbcmds(void); /* forward */
81 /* *********************************************************************
83 ********************************************************************* */
86 * We keep track of the pointers to USB buses in globals.
87 * One entry in this array per USB bus (the Opti controller
88 * on the SWARM has two functions, so it's two buses)
93 usbbus_t
*usb_buses
[USB_MAX_BUS
];
96 /* *********************************************************************
99 * This routine is called periodically by CFE's timer routines
100 * to give the USB subsystem some time. Basically we scan
101 * for work to do to manage configuration updates, and handle
102 * interrupts from the USB controllers.
105 * arg - value we passed when the timer was initialized
110 ********************************************************************* */
112 static void usb_cfe_timer(void *arg
)
115 static int in_poll
= 0;
118 * We sometimes call the timer routines in here, which calls
119 * the polling loop. This code is not reentrant, so
120 * prevent us from running the interrupt routine or
121 * bus daemon while we are already in there.
127 * Do not allow nested "interrupts."
132 for (idx
= 0; idx
< usb_buscnt
; idx
++) {
133 if (usb_buses
[idx
]) {
134 usb_poll(usb_buses
[idx
]);
135 usb_daemon(usb_buses
[idx
]);
140 * Okay to call polling again.
147 /* *********************************************************************
148 * usb_init_one_ohci(addr)
150 * Initialize one USB controller.
153 * addr - physical address of OHCI registers
158 ********************************************************************* */
159 static int usb_init_one_ohci(uint32_t addr
)
164 bus
= UBCREATE(&ohci_driver
, addr
);
167 printf("USB: Could not create OHCI driver structure for controller at 0x%08X\n",addr
);
171 bus
->ub_num
= usb_buscnt
;
176 printf("USB: Could not init OHCI controller at 0x%08X\n",addr
);
181 usb_buses
[usb_buscnt
++] = bus
;
189 /* *********************************************************************
190 * usb_init_pci_ohci()
192 * Initialize all PCI-based OHCI controllers
200 ********************************************************************* */
201 static int usb_init_pci_ohci(void)
211 while (pci_find_class(PCI_CLASS_SERIALBUS
,idx
,&tag
) == 0) {
212 pciclass
= pci_conf_read(tag
,PCI_CLASS_REG
);
213 if ((PCI_SUBCLASS(pciclass
) == PCI_SUBCLASS_SERIALBUS_USB
) &&
214 (PCI_INTERFACE(pciclass
) == 0x10)) {
215 bar
= (physaddr_t
) pci_conf_read(tag
,PCI_MAPREG_START
);
216 pci_tagprintf(tag
,"OHCI USB controller found at %08X\n",(uint32_t) bar
);
218 /* On the BCM1250, this sets the address to "match bits" mode,
219 which eliminates the need for byte swaps of data to/from the registers. */
222 res
= usb_init_one_ohci(bar
);
234 /* *********************************************************************
237 * Initialize the USB subsystem
245 ********************************************************************* */
249 static int initdone
= 0;
252 printf("USB has already been initialized.\n");
256 printf("Initializing USB.\n");
266 #if CFG_USB_OHCI_BASE
267 usb_init_one_ohci(CFG_USB_OHCI_BASE
);
270 cfe_bg_add(usb_cfe_timer
,NULL
);
277 static int ui_cmd_usb_start(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
281 if (cmd_sw_isset(cmd
,"-o")) ohcidebug
++;
282 if (cmd_sw_isset(cmd
,"-oo")) ohcidebug
+=2;
283 if (cmd_sw_isset(cmd
,"-u")) usb_noisy
++;
284 if (cmd_sw_isset(cmd
,"-uu")) usb_noisy
+=2;
286 if (usb_buscnt
== 0) {
294 static int ui_cmd_usb_show(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
302 x
= cmd_getarg(cmd
,1);
304 else devnum
= atoi(x
);
306 x
= cmd_getarg(cmd
,0);
310 if (busnum
>= usb_buscnt
) {
311 printf("Invalid bus number, %d USB Buses currently configured.\n",usb_buscnt
);
315 arg
= cmd_sw_isset(cmd
,"-v") ? 0x100 : 0;
316 arg
|= (devnum
& 0xFF);
319 for (idx
= 0; idx
< usb_buscnt
; idx
++) {
320 usbhub_dumpbus(usb_buses
[idx
],arg
);
324 usbhub_dumpbus(usb_buses
[busnum
],arg
);
331 /* *********************************************************************
332 * ui_init_usbcmds(void)
334 * Initialize the USB commands
341 ********************************************************************* */
343 int ui_init_usbcmds(void)
345 cmd_addcmd("usb init",
348 "Initialize the USB controller.",
350 "-o;OHCI debug messages|"
351 "-oo;more OHCI debug messages|"
352 "-u;USBD debug messages|"
353 "-uu;more USBD debug messages");
356 cmd_addcmd("show usb",
359 "Display devices connected to USB bus.",
360 "usb show [bus [device]]\n\n"
361 "Displays the configuration descriptors for devices connected to the USB\n"
362 "If you specify a bus, the entire bus is displayed. If you specify the\n"
363 "device number as well, only the specified device is displayed\n",
364 "-v;Display descriptors from the devices");