X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fusb%2Fhost%2Fehci-pci.c;h=991b19998b7e407a214f698939284577d61cb4da;hb=768f6096f9c389b5ed36bee2957bee16b085fc4a;hp=cff34389295c5d13ce12d8988bdad47ab8c64c0a;hpb=af68c066709f20fcfd0ce6cd955bfbe4642d0a15;p=u-boot diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index cff3438929..991b19998b 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -19,37 +19,98 @@ */ #include +#include #include #include #include "ehci.h" -#include "ehci-core.h" #ifdef CONFIG_PCI_EHCI_DEVICE static struct pci_device_id ehci_pci_ids[] = { /* Please add supported PCI EHCI controller ids here */ - {0x1033, 0x00E0}, + {0x1033, 0x00E0}, /* NEC */ + {0x10B9, 0x5239}, /* ULI1575 PCI EHCI module 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 addr; + 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; } - pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &addr); - hccr = (struct ehci_hccr *)addr; + hccr = (struct ehci_hccr *)pci_map_bar(pdev, + PCI_BASE_ADDRESS_0, PCI_REGION_MEM); hcor = (struct ehci_hcor *)((uint32_t) hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); @@ -57,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; } @@ -64,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; }