X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fpci%2Fpci.c;h=3babd948056da4a25d58a8d593b0cc36761fcfc1;hb=36d0d3b4b4974f4183609ac8b4d77a1f46acba55;hp=4fd9c532b3fbf8df2b351537dca1b196298f5899;hpb=d878c9a932eae626aced58128357fc6155f88739;p=oweals%2Fu-boot.git diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4fd9c532b3..3babd94805 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -15,10 +15,13 @@ #include #include +#include #include #include #include +DECLARE_GLOBAL_DATA_PTR; + #define PCI_HOSE_OP(rw, size, type) \ int pci_hose_##rw##_config_##size(struct pci_controller *hose, \ pci_dev_t dev, \ @@ -98,31 +101,20 @@ PCI_READ_VIA_DWORD_OP(word, u16 *, 0x02) PCI_WRITE_VIA_DWORD_OP(byte, u8, 0x03, 0x000000ff) PCI_WRITE_VIA_DWORD_OP(word, u16, 0x02, 0x0000ffff) -/* Get a virtual address associated with a BAR region */ -void *pci_map_bar(pci_dev_t pdev, int bar, int flags) -{ - pci_addr_t pci_bus_addr; - u32 bar_response; - - /* read BAR address */ - pci_read_config_dword(pdev, bar, &bar_response); - pci_bus_addr = (pci_addr_t)(bar_response & ~0xf); - - /* - * Pass "0" as the length argument to pci_bus_to_virt. The arg - * isn't actualy used on any platform because u-boot assumes a static - * linear mapping. In the future, this could read the BAR size - * and pass that as the size if needed. - */ - return pci_bus_to_virt(pdev, pci_bus_addr, flags, 0, MAP_NOCACHE); -} - /* * */ static struct pci_controller* hose_head; +struct pci_controller *pci_get_hose_head(void) +{ + if (gd->hose) + return gd->hose; + + return hose_head; +} + void pci_register_hose(struct pci_controller* hose) { struct pci_controller **phose = &hose_head; @@ -139,7 +131,7 @@ struct pci_controller *pci_bus_to_hose(int bus) { struct pci_controller *hose; - for (hose = hose_head; hose; hose = hose->next) { + for (hose = pci_get_hose_head(); hose; hose = hose->next) { if (bus >= hose->first_busno && bus <= hose->last_busno) return hose; } @@ -152,7 +144,7 @@ struct pci_controller *find_hose_by_cfg_addr(void *cfg_addr) { struct pci_controller *hose; - for (hose = hose_head; hose; hose = hose->next) { + for (hose = pci_get_hose_head(); hose; hose = hose->next) { if (hose->cfg_addr == cfg_addr) return hose; } @@ -162,7 +154,7 @@ struct pci_controller *find_hose_by_cfg_addr(void *cfg_addr) int pci_last_busno(void) { - struct pci_controller *hose = hose_head; + struct pci_controller *hose = pci_get_hose_head(); if (!hose) return -1; @@ -176,68 +168,24 @@ int pci_last_busno(void) pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) { struct pci_controller * hose; - u16 vendor, device; - u8 header_type; pci_dev_t bdf; - int i, bus, found_multi = 0; + int bus; - for (hose = hose_head; hose; hose = hose->next) { + for (hose = pci_get_hose_head(); hose; hose = hose->next) { #ifdef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE - for (bus = hose->last_busno; bus >= hose->first_busno; bus--) -#else - for (bus = hose->first_busno; bus <= hose->last_busno; bus++) -#endif - for (bdf = PCI_BDF(bus, 0, 0); -#if defined(CONFIG_ELPPC) || defined(CONFIG_PPMC7XX) - bdf < PCI_BDF(bus, PCI_MAX_PCI_DEVICES - 1, - PCI_MAX_PCI_FUNCTIONS - 1); + for (bus = hose->last_busno; bus >= hose->first_busno; bus--) { #else - bdf < PCI_BDF(bus + 1, 0, 0); + for (bus = hose->first_busno; bus <= hose->last_busno; bus++) { #endif - bdf += PCI_BDF(0, 0, 1)) { - if (!PCI_FUNC(bdf)) { - pci_read_config_byte(bdf, - PCI_HEADER_TYPE, - &header_type); - - found_multi = header_type & 0x80; - } else { - if (!found_multi) - continue; - } - - pci_read_config_word(bdf, - PCI_VENDOR_ID, - &vendor); - pci_read_config_word(bdf, - PCI_DEVICE_ID, - &device); - - for (i = 0; ids[i].vendor != 0; i++) { - if (vendor == ids[i].vendor && - device == ids[i].device) { - if (index <= 0) - return bdf; - - index--; - } - } - } + bdf = pci_hose_find_devices(hose, bus, ids, &index); + if (bdf != -1) + return bdf; + } } return -1; } -pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index) -{ - static struct pci_device_id ids[2] = {{}, {0, 0}}; - - ids[0].vendor = vendor; - ids[0].device = device; - - return pci_find_devices(ids, index); -} - /* * */ @@ -304,69 +252,6 @@ pci_addr_t pci_hose_phys_to_bus (struct pci_controller *hose, return bus_addr; } -int __pci_hose_bus_to_phys(struct pci_controller *hose, - pci_addr_t bus_addr, - unsigned long flags, - unsigned long skip_mask, - phys_addr_t *pa) -{ - struct pci_region *res; - int i; - - for (i = 0; i < hose->region_count; i++) { - res = &hose->regions[i]; - - if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) - continue; - - if (res->flags & skip_mask) - continue; - - if (bus_addr >= res->bus_start && - (bus_addr - res->bus_start) < res->size) { - *pa = (bus_addr - res->bus_start + res->phys_start); - return 0; - } - } - - return 1; -} - -phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose, - pci_addr_t bus_addr, - unsigned long flags) -{ - phys_addr_t phys_addr = 0; - int ret; - - if (!hose) { - puts("pci_hose_bus_to_phys: invalid hose\n"); - return phys_addr; - } - - /* - * if PCI_REGION_MEM is set we do a two pass search with preference - * on matches that don't have PCI_REGION_SYS_MEMORY set - */ - if ((flags & PCI_REGION_MEM) == PCI_REGION_MEM) { - ret = __pci_hose_bus_to_phys(hose, bus_addr, - flags, PCI_REGION_SYS_MEMORY, &phys_addr); - if (!ret) - return phys_addr; - } - - ret = __pci_hose_bus_to_phys(hose, bus_addr, flags, 0, &phys_addr); - - if (ret) - puts("pci_hose_bus_to_phys: invalid physical address\n"); - - return phys_addr; -} - -/* - * - */ - int pci_hose_config_device(struct pci_controller *hose, pci_dev_t dev, unsigned long io, @@ -507,103 +392,14 @@ void pci_cfgfunc_do_nothing(struct pci_controller *hose, */ extern int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev); -#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI_SCAN_SHOW) -const char * pci_class_str(u8 class) -{ - switch (class) { - case PCI_CLASS_NOT_DEFINED: - return "Build before PCI Rev2.0"; - break; - case PCI_BASE_CLASS_STORAGE: - return "Mass storage controller"; - break; - case PCI_BASE_CLASS_NETWORK: - return "Network controller"; - break; - case PCI_BASE_CLASS_DISPLAY: - return "Display controller"; - break; - case PCI_BASE_CLASS_MULTIMEDIA: - return "Multimedia device"; - break; - case PCI_BASE_CLASS_MEMORY: - return "Memory controller"; - break; - case PCI_BASE_CLASS_BRIDGE: - return "Bridge device"; - break; - case PCI_BASE_CLASS_COMMUNICATION: - return "Simple comm. controller"; - break; - case PCI_BASE_CLASS_SYSTEM: - return "Base system peripheral"; - break; - case PCI_BASE_CLASS_INPUT: - return "Input device"; - break; - case PCI_BASE_CLASS_DOCKING: - return "Docking station"; - break; - case PCI_BASE_CLASS_PROCESSOR: - return "Processor"; - break; - case PCI_BASE_CLASS_SERIAL: - return "Serial bus controller"; - break; - case PCI_BASE_CLASS_INTELLIGENT: - return "Intelligent controller"; - break; - case PCI_BASE_CLASS_SATELLITE: - return "Satellite controller"; - break; - case PCI_BASE_CLASS_CRYPT: - return "Cryptographic device"; - break; - case PCI_BASE_CLASS_SIGNAL_PROCESSING: - return "DSP"; - break; - case PCI_CLASS_OTHERS: - return "Does not fit any class"; - break; - default: - return "???"; - break; - }; -} -#endif /* CONFIG_CMD_PCI || CONFIG_PCI_SCAN_SHOW */ - -int __pci_skip_dev(struct pci_controller *hose, pci_dev_t dev) -{ - /* - * Check if pci device should be skipped in configuration - */ - if (dev == PCI_BDF(hose->first_busno, 0, 0)) { -#if defined(CONFIG_PCI_CONFIG_HOST_BRIDGE) /* don't skip host bridge */ - /* - * Only skip configuration if "pciconfighost" is not set - */ - if (getenv("pciconfighost") == NULL) - return 1; -#else - return 1; -#endif - } - - return 0; -} -int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev) - __attribute__((weak, alias("__pci_skip_dev"))); - #ifdef CONFIG_PCI_SCAN_SHOW -int __pci_print_dev(struct pci_controller *hose, pci_dev_t dev) +__weak int pci_print_dev(struct pci_controller *hose, pci_dev_t dev) { if (dev == PCI_BDF(hose->first_busno, 0, 0)) return 0; return 1; } -int pci_print_dev(struct pci_controller *hose, pci_dev_t dev) - __attribute__((weak, alias("__pci_print_dev"))); #endif /* CONFIG_PCI_SCAN_SHOW */ int pci_hose_scan_bus(struct pci_controller *hose, int bus) @@ -648,6 +444,10 @@ int pci_hose_scan_bus(struct pci_controller *hose, int bus) pci_hose_read_config_word(hose, dev, PCI_DEVICE_ID, &device); pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class); +#ifdef CONFIG_PCI_FIXUP_DEV + board_pci_fixup_dev(hose, dev, vendor, device, class); +#endif + #ifdef CONFIG_PCI_SCAN_SHOW indent++; @@ -662,13 +462,15 @@ int pci_hose_scan_bus(struct pci_controller *hose, int bus) #endif #ifdef CONFIG_PCI_PNP - sub_bus = max(pciauto_config_device(hose, dev), sub_bus); + sub_bus = max((unsigned int)pciauto_config_device(hose, dev), + sub_bus); #else cfg = pci_find_config(hose, class, vendor, device, PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev)); if (cfg) { cfg->config_device(hose, dev, cfg); - sub_bus = max(sub_bus, hose->current_busno); + sub_bus = max(sub_bus, + (unsigned int)hose->current_busno); } #endif @@ -686,11 +488,10 @@ int pci_hose_scan_bus(struct pci_controller *hose, int bus) int pci_hose_scan(struct pci_controller *hose) { #if defined(CONFIG_PCI_BOOTDELAY) - static int pcidelay_done; char *s; int i; - if (!pcidelay_done) { + if (!gd->pcidelay_done) { /* wait "pcidelay" ms (if defined)... */ s = getenv("pcidelay"); if (s) { @@ -698,7 +499,7 @@ int pci_hose_scan(struct pci_controller *hose) for (i = 0; i < val; i++) udelay(1000); } - pcidelay_done = 1; + gd->pcidelay_done = 1; } #endif /* CONFIG_PCI_BOOTDELAY */