X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fpci%2Fpci.c;h=221054593ef221abb9e05e779a9cf18f3b1b5399;hb=5b2c9a6ce3ce66796e8c375133da8340c7ab2adc;hp=3babd948056da4a25d58a8d593b0cc36761fcfc1;hpb=b8d7652c81689a69bc6eaa206cf875bbe632831c;p=u-boot diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 3babd94805..221054593e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1,15 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH * Andreas Heppel * * (C) Copyright 2002, 2003 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * SPDX-License-Identifier: GPL-2.0+ */ /* - * PCI routines + * Old PCI routines + * + * Do not change this file. Instead, convert your board to use CONFIG_DM_PCI + * and change pci-uclass.c. */ #include @@ -172,11 +174,7 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) int bus; 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 bdf = pci_hose_find_devices(hose, bus, ids, &index); if (bdf != -1) return bdf; @@ -186,72 +184,6 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) return -1; } -/* - * - */ - -int __pci_hose_phys_to_bus(struct pci_controller *hose, - phys_addr_t phys_addr, - unsigned long flags, - unsigned long skip_mask, - pci_addr_t *ba) -{ - struct pci_region *res; - pci_addr_t bus_addr; - 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; - - bus_addr = phys_addr - res->phys_start + res->bus_start; - - if (bus_addr >= res->bus_start && - bus_addr < res->bus_start + res->size) { - *ba = bus_addr; - return 0; - } - } - - return 1; -} - -pci_addr_t pci_hose_phys_to_bus (struct pci_controller *hose, - phys_addr_t phys_addr, - unsigned long flags) -{ - pci_addr_t bus_addr = 0; - int ret; - - if (!hose) { - puts("pci_hose_phys_to_bus: invalid hose\n"); - return bus_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_phys_to_bus(hose, phys_addr, - flags, PCI_REGION_SYS_MEMORY, &bus_addr); - if (!ret) - return bus_addr; - } - - ret = __pci_hose_phys_to_bus(hose, phys_addr, flags, 0, &bus_addr); - - if (ret) - puts("pci_hose_phys_to_bus: invalid physical address\n"); - - return bus_addr; -} - int pci_hose_config_device(struct pci_controller *hose, pci_dev_t dev, unsigned long io, @@ -335,7 +267,8 @@ int pci_hose_config_device(struct pci_controller *hose, /* Disable interrupt line, if device says it wants to use interrupts */ pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin); if (pin != 0) { - pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 0xff); + pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, + PCI_INTERRUPT_LINE_DISABLE); } pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &old_command); @@ -493,7 +426,7 @@ int pci_hose_scan(struct pci_controller *hose) if (!gd->pcidelay_done) { /* wait "pcidelay" ms (if defined)... */ - s = getenv("pcidelay"); + s = env_get("pcidelay"); if (s) { int val = simple_strtoul(s, NULL, 10); for (i = 0; i < val; i++) @@ -503,6 +436,10 @@ int pci_hose_scan(struct pci_controller *hose) } #endif /* CONFIG_PCI_BOOTDELAY */ +#ifdef CONFIG_PCI_SCAN_SHOW + puts("PCI:\n"); +#endif + /* * Start scan at current_busno. * PCIe will start scan at first_busno+1. @@ -520,6 +457,10 @@ void pci_init(void) { hose_head = NULL; + /* allow env to disable pci init/enum */ + if (env_get("pcidisable") != NULL) + return; + /* now call board specific pci_init()... */ pci_init_board(); } @@ -588,3 +529,56 @@ int pci_find_cap(struct pci_controller *hose, pci_dev_t dev, int pos, int cap) } return 0; } + +/** + * pci_find_next_ext_capability - Find an extended capability + * + * Returns the address of the next matching extended capability structure + * within the device's PCI configuration space or 0 if the device does + * not support it. Some capabilities can occur several times, e.g., the + * vendor-specific capability, and this provides a way to find them all. + */ +int pci_find_next_ext_capability(struct pci_controller *hose, pci_dev_t dev, + int start, int cap) +{ + u32 header; + int ttl, pos = PCI_CFG_SPACE_SIZE; + + /* minimum 8 bytes per capability */ + ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; + + if (start) + pos = start; + + pci_hose_read_config_dword(hose, dev, pos, &header); + if (header == 0xffffffff || header == 0) + return 0; + + while (ttl-- > 0) { + if (PCI_EXT_CAP_ID(header) == cap && pos != start) + return pos; + + pos = PCI_EXT_CAP_NEXT(header); + if (pos < PCI_CFG_SPACE_SIZE) + break; + + pci_hose_read_config_dword(hose, dev, pos, &header); + if (header == 0xffffffff || header == 0) + break; + } + + return 0; +} + +/** + * pci_hose_find_ext_capability - Find an extended capability + * + * Returns the address of the requested extended capability structure + * within the device's PCI configuration space or 0 if the device does + * not support it. + */ +int pci_hose_find_ext_capability(struct pci_controller *hose, pci_dev_t dev, + int cap) +{ + return pci_find_next_ext_capability(hose, dev, 0, cap); +}