X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fusb%2Fhost%2Fehci-pci.c;h=991b19998b7e407a214f698939284577d61cb4da;hb=3deb013ae780c19f40b0704a7f421ad479962618;hp=020ab11355eb81c5acfc44b33521fec37704c7bf;hpb=9023ae305919d0aecb4a22726b9d08c6b08189d7;p=u-boot diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 020ab11355..991b19998b 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -19,11 +19,11 @@ */ #include +#include #include #include #include "ehci.h" -#include "ehci-core.h" #ifdef CONFIG_PCI_EHCI_DEVICE static struct pci_device_id ehci_pci_ids[] = { @@ -33,18 +33,78 @@ static struct pci_device_id ehci_pci_ids[] = { {0x12D8, 0x400F}, /* Pericom */ {0, 0} }; +#else +static pci_dev_t ehci_find_class(int index) +{ + int bus; + int devnum; + pci_dev_t bdf; + uint32_t class; + + for (bus = 0; bus <= pci_last_busno(); bus++) { + for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES-1; devnum++) { + pci_read_config_dword(PCI_BDF(bus, devnum, 0), + PCI_CLASS_REVISION, &class); + if (class >> 16 == 0xffff) + continue; + + for (bdf = PCI_BDF(bus, devnum, 0); + bdf <= PCI_BDF(bus, devnum, + PCI_MAX_PCI_FUNCTIONS - 1); + bdf += PCI_BDF(0, 0, 1)) { + pci_read_config_dword(bdf, PCI_CLASS_REVISION, + &class); + class >>= 8; + /* + * Here be dragons! In case we have multiple + * PCI EHCI controllers, this function will + * be called multiple times as well. This + * function will scan the PCI busses, always + * starting from bus 0, device 0, function 0, + * until it finds an USB controller. The USB + * stack gives us an 'index' of a controller + * that is currently being registered, which + * is a number, starting from 0 and growing + * in ascending order as controllers are added. + * To avoid probing the same controller in tne + * subsequent runs of this function, we will + * skip 'index - 1' detected controllers and + * report the index'th controller. + */ + if (class != PCI_CLASS_SERIAL_USB_EHCI) + continue; + if (index) { + index--; + continue; + } + /* Return index'th controller. */ + return bdf; + } + } + } + + return -ENODEV; +} #endif /* * Create the appropriate control structures to manage * a new EHCI host controller. */ -int ehci_hcd_init(void) +int ehci_hcd_init(int index, enum usb_init_type init, + struct ehci_hccr **ret_hccr, struct ehci_hcor **ret_hcor) { pci_dev_t pdev; + uint32_t cmd; + struct ehci_hccr *hccr; + struct ehci_hcor *hcor; +#ifdef CONFIG_PCI_EHCI_DEVICE pdev = pci_find_devices(ehci_pci_ids, CONFIG_PCI_EHCI_DEVICE); - if (pdev == -1) { +#else + pdev = ehci_find_class(index); +#endif + if (pdev < 0) { printf("EHCI host controller not found\n"); return -1; } @@ -58,6 +118,13 @@ int ehci_hcd_init(void) (uint32_t)hccr, (uint32_t)hcor, (uint32_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase))); + *ret_hccr = hccr; + *ret_hcor = hcor; + + /* enable busmaster */ + pci_read_config_dword(pdev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + pci_write_config_dword(pdev, PCI_COMMAND, cmd); return 0; } @@ -65,7 +132,7 @@ int ehci_hcd_init(void) * Destroy the appropriate control structures corresponding * the the EHCI host controller. */ -int ehci_hcd_stop(void) +int ehci_hcd_stop(int index) { return 0; }