BCM WL 6.30.102.9 (r366174)
[tomato.git] / release / src-rt / cfe / cfe / usb / usbmain.c
blobc39a7f6d69c26196188669571478ed315bf56ff5
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * Main Module File: usbmain.c
5 *
6 * Main module that invokes the top of the USB stack from CFE.
7 *
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
9 *
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"
58 #if CFG_PCI
59 #include "pcireg.h"
60 #include "pcivar.h"
61 #endif
63 #include "usbchap9.h"
64 #include "usbd.h"
66 #include "bsp_config.h"
69 /* *********************************************************************
70 * Externs
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 /* *********************************************************************
82 * Globals
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)
91 #define USB_MAX_BUS 4
92 int usb_buscnt = 0;
93 usbbus_t *usb_buses[USB_MAX_BUS];
96 /* *********************************************************************
97 * usb_cfe_timer(arg)
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.
104 * Input parameters:
105 * arg - value we passed when the timer was initialized
106 * (not used)
108 * Return value:
109 * nothing
110 ********************************************************************* */
112 static void usb_cfe_timer(void *arg)
114 int idx;
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.
124 if (in_poll) return;
127 * Do not allow nested "interrupts."
130 in_poll = 1;
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.
143 in_poll = 0;
147 /* *********************************************************************
148 * usb_init_one_ohci(addr)
150 * Initialize one USB controller.
152 * Input parameters:
153 * addr - physical address of OHCI registers
155 * Return value:
156 * 0 if ok
157 * else error
158 ********************************************************************* */
159 static int usb_init_one_ohci(uint32_t addr)
161 usbbus_t *bus;
162 int res;
164 bus = UBCREATE(&ohci_driver, addr);
166 if (bus == NULL) {
167 printf("USB: Could not create OHCI driver structure for controller at 0x%08X\n",addr);
168 return -1;
171 bus->ub_num = usb_buscnt;
173 res = UBSTART(bus);
175 if (res != 0) {
176 printf("USB: Could not init OHCI controller at 0x%08X\n",addr);
177 UBSTOP(bus);
178 return -1;
180 else {
181 usb_buses[usb_buscnt++] = bus;
182 usb_initroot(bus);
185 return 0;
188 #if CFG_PCI
189 /* *********************************************************************
190 * usb_init_pci_ohci()
192 * Initialize all PCI-based OHCI controllers
194 * Input parameters:
195 * nothing
197 * Return value:
198 * 0 if ok
199 * else error
200 ********************************************************************* */
201 static int usb_init_pci_ohci(void)
203 int res;
204 pcitag_t tag;
205 uint32_t pciclass;
206 physaddr_t bar;
207 int idx;
209 idx = 0;
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. */
220 bar |= 0x20000000;
222 res = usb_init_one_ohci(bar);
223 if (res < 0) break;
225 idx++;
228 return 0;
230 #endif
234 /* *********************************************************************
235 * usb_init()
237 * Initialize the USB subsystem
239 * Input parameters:
240 * nothing
242 * Return value:
243 * 0 if ok
244 * else error code
245 ********************************************************************* */
247 int usb_init(void)
249 static int initdone = 0;
251 if (initdone) {
252 printf("USB has already been initialized.\n");
253 return -1;
256 printf("Initializing USB.\n");
258 initdone = 1;
260 usb_buscnt = 0;
262 #if CFG_PCI
263 usb_init_pci_ohci();
264 #endif
266 #if CFG_USB_OHCI_BASE
267 usb_init_one_ohci(CFG_USB_OHCI_BASE);
268 #endif
270 cfe_bg_add(usb_cfe_timer,NULL);
272 return 0;
277 static int ui_cmd_usb_start(ui_cmdline_t *cmd,int argc,char *argv[])
279 int res = 0;
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) {
287 res = usb_init();
290 return res;
294 static int ui_cmd_usb_show(ui_cmdline_t *cmd,int argc,char *argv[])
296 int busnum;
297 int devnum;
298 char *x;
299 int idx;
300 uint32_t arg;
302 x = cmd_getarg(cmd,1);
303 if (!x) devnum = 0;
304 else devnum = atoi(x);
306 x = cmd_getarg(cmd,0);
307 if (!x) x = "*";
308 busnum = atoi(x);
310 if (busnum >= usb_buscnt) {
311 printf("Invalid bus number, %d USB Buses currently configured.\n",usb_buscnt);
312 return -1;
315 arg = cmd_sw_isset(cmd,"-v") ? 0x100 : 0;
316 arg |= (devnum & 0xFF);
318 if (x[0] == '*') {
319 for (idx = 0; idx < usb_buscnt; idx++) {
320 usbhub_dumpbus(usb_buses[idx],arg);
323 else {
324 usbhub_dumpbus(usb_buses[busnum],arg);
327 return 0;
331 /* *********************************************************************
332 * ui_init_usbcmds(void)
334 * Initialize the USB commands
336 * Input parameters:
337 * nothing
339 * Return value:
341 ********************************************************************* */
343 int ui_init_usbcmds(void)
345 cmd_addcmd("usb init",
346 ui_cmd_usb_start,
347 NULL,
348 "Initialize the USB controller.",
349 "usb init",
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",
357 ui_cmd_usb_show,
358 NULL,
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");
366 return 0;