diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pci-uclass.c | 24 | ||||
-rw-r--r-- | drivers/pci/pci_auto.c | 15 | ||||
-rw-r--r-- | drivers/pci/pci_auto_old.c | 2 | ||||
-rw-r--r-- | drivers/pci/pci_compat.c | 15 | ||||
-rw-r--r-- | drivers/pci/pci_internal.h | 12 | ||||
-rw-r--r-- | drivers/pci/pci_mvebu.c | 14 | ||||
-rw-r--r-- | drivers/pci/pci_rom.c | 53 |
7 files changed, 96 insertions, 39 deletions
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 685df9d274..61292d72bd 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -22,7 +22,7 @@ DECLARE_GLOBAL_DATA_PTR; -static int pci_get_bus(int busnum, struct udevice **busp) +int pci_get_bus(int busnum, struct udevice **busp) { int ret; @@ -41,20 +41,6 @@ static int pci_get_bus(int busnum, struct udevice **busp) return ret; } -struct pci_controller *pci_bus_to_hose(int busnum) -{ - struct udevice *bus; - int ret; - - ret = pci_get_bus(busnum, &bus); - if (ret) { - debug("%s: Cannot get bus %d: ret=%d\n", __func__, busnum, ret); - return NULL; - } - - return dev_get_uclass_priv(bus); -} - struct udevice *pci_get_controller(struct udevice *dev) { while (device_is_on_pci_bus(dev)) @@ -1067,6 +1053,14 @@ u32 dm_pci_read_bar32(struct udevice *dev, int barnum) return addr & PCI_BASE_ADDRESS_MEM_MASK; } +void dm_pci_write_bar32(struct udevice *dev, int barnum, u32 addr) +{ + int bar; + + bar = PCI_BASE_ADDRESS_0 + barnum * 4; + dm_pci_write_config32(dev, bar, addr); +} + static int _dm_pci_bus_to_phys(struct udevice *ctlr, pci_addr_t bus_addr, unsigned long flags, unsigned long skip_mask, phys_addr_t *pa) diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index 842eafc4f8..88bc416c61 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -9,6 +9,7 @@ */ #include <common.h> +#include <dm.h> #include <errno.h> #include <pci.h> @@ -167,8 +168,8 @@ void dm_pciauto_prescan_setup_bridge(struct udevice *dev, int sub_bus) struct pci_region *pci_prefetch; struct pci_region *pci_io; u16 cmdstat, prefechable_64; - /* The root controller has the region information */ - struct pci_controller *ctlr_hose = pci_bus_to_hose(0); + struct udevice *ctlr = pci_get_controller(dev); + struct pci_controller *ctlr_hose = dev_get_uclass_priv(ctlr); pci_mem = ctlr_hose->pci_mem; pci_prefetch = ctlr_hose->pci_prefetch; @@ -248,9 +249,8 @@ void dm_pciauto_postscan_setup_bridge(struct udevice *dev, int sub_bus) struct pci_region *pci_mem; struct pci_region *pci_prefetch; struct pci_region *pci_io; - - /* The root controller has the region information */ - struct pci_controller *ctlr_hose = pci_bus_to_hose(0); + struct udevice *ctlr = pci_get_controller(dev); + struct pci_controller *ctlr_hose = dev_get_uclass_priv(ctlr); pci_mem = ctlr_hose->pci_mem; pci_prefetch = ctlr_hose->pci_prefetch; @@ -311,13 +311,13 @@ int dm_pciauto_config_device(struct udevice *dev) unsigned int sub_bus = PCI_BUS(dm_pci_get_bdf(dev)); unsigned short class; bool enum_only = false; + struct udevice *ctlr = pci_get_controller(dev); + struct pci_controller *ctlr_hose = dev_get_uclass_priv(ctlr); int n; #ifdef CONFIG_PCI_ENUM_ONLY enum_only = true; #endif - /* The root controller has the region information */ - struct pci_controller *ctlr_hose = pci_bus_to_hose(0); pci_mem = ctlr_hose->pci_mem; pci_prefetch = ctlr_hose->pci_prefetch; @@ -375,6 +375,7 @@ int dm_pciauto_config_device(struct udevice *dev) case PCI_CLASS_PROCESSOR_POWERPC: /* an agent or end-point */ debug("PCI AutoConfig: Found PowerPC device\n"); + /* fall through */ default: dm_pciauto_setup_device(dev, 6, pci_mem, pci_prefetch, pci_io, diff --git a/drivers/pci/pci_auto_old.c b/drivers/pci/pci_auto_old.c index 9126f78b89..edc9a7b3c1 100644 --- a/drivers/pci/pci_auto_old.c +++ b/drivers/pci/pci_auto_old.c @@ -101,11 +101,11 @@ void pciauto_setup_device(struct pci_controller *hose, bar_res = prefetch; else bar_res = mem; -#endif debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ", bar_nr, bar_res == prefetch ? "Prf" : "Mem", (unsigned long long)bar_size); +#endif } #ifndef CONFIG_PCI_ENUM_ONLY diff --git a/drivers/pci/pci_compat.c b/drivers/pci/pci_compat.c index dd15eb19f8..ddaf358e26 100644 --- a/drivers/pci/pci_compat.c +++ b/drivers/pci/pci_compat.c @@ -12,6 +12,7 @@ #include <pci.h> #include <dm/device-internal.h> #include <dm/lists.h> +#include "pci_internal.h" #define PCI_HOSE_OP(rw, name, size, type) \ int pci_hose_##rw##_config_##name(struct pci_controller *hose, \ @@ -36,3 +37,17 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) return -1; return dm_pci_get_bdf(dev); } + +struct pci_controller *pci_bus_to_hose(int busnum) +{ + struct udevice *bus; + int ret; + + ret = pci_get_bus(busnum, &bus); + if (ret) { + debug("%s: Cannot get bus %d: ret=%d\n", __func__, busnum, ret); + return NULL; + } + + return dev_get_uclass_priv(bus); +} diff --git a/drivers/pci/pci_internal.h b/drivers/pci/pci_internal.h index 0867575a58..616b9c174c 100644 --- a/drivers/pci/pci_internal.h +++ b/drivers/pci/pci_internal.h @@ -47,4 +47,16 @@ void dm_pciauto_postscan_setup_bridge(struct udevice *dev, int sub_bus); */ int dm_pciauto_config_device(struct udevice *dev); +/** + * pci_get_bus() - Get a pointer to a bus, given its number + * + * This looks up a PCI bus based on its bus number. The bus is probed if + * necessary. + * + * @busnum: PCI bus number to look up + * @busp: Returns PCI bus on success + * @return 0 on success, or -ve error + */ +int pci_get_bus(int busnum, struct udevice **busp); + #endif diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c index fd2744dbd4..4eedfe1cbb 100644 --- a/drivers/pci/pci_mvebu.c +++ b/drivers/pci/pci_mvebu.c @@ -155,6 +155,14 @@ static void mvebu_get_port_lane(struct mvebu_pcie *pcie, int pex_idx, } #endif +static int mvebu_pex_unit_is_x4(int pex_idx) +{ + int pex_unit = pex_idx < 9 ? pex_idx >> 2 : 3; + u32 mask = (0x0f << (pex_unit * 8)); + + return (readl(COMPHY_REFCLK_ALIGNMENT) & mask) == mask; +} + static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie) { u32 val; @@ -419,5 +427,11 @@ void pci_init_board(void) writel(0, pcie->base + PCIE_BAR_HI_OFF(0)); bus = hose->last_busno + 1; + + /* need to skip more for X4 links, otherwise scan will hang */ + if (mvebu_soc_family() == MVEBU_SOC_AXP) { + if (mvebu_pex_unit_is_x4(i)) + i += 3; + } } } diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 2cb81b66b7..d5bf6f4c47 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -129,14 +129,26 @@ static int pci_rom_probe(struct udevice *dev, struct pci_rom_header **hdrp) return 0; } -int pci_rom_load(struct pci_rom_header *rom_header, - struct pci_rom_header **ram_headerp) +/** + * pci_rom_load() - Load a ROM image and return a pointer to it + * + * @rom_header: Pointer to ROM image + * @ram_headerp: Returns a pointer to the image in RAM + * @allocedp: Returns true if @ram_headerp was allocated and needs + * to be freed + * @return 0 if OK, -ve on error. Note that @allocedp is set up regardless of + * the error state. Even if this function returns an error, it may have + * allocated memory. + */ +static int pci_rom_load(struct pci_rom_header *rom_header, + struct pci_rom_header **ram_headerp, bool *allocedp) { struct pci_rom_data *rom_data; unsigned int rom_size; unsigned int image_size = 0; void *target; + *allocedp = false; do { /* Get next image, until we see an x86 version */ rom_header = (struct pci_rom_header *)((void *)rom_header + @@ -159,6 +171,7 @@ int pci_rom_load(struct pci_rom_header *rom_header, target = (void *)malloc(rom_size); if (!target) return -ENOMEM; + *allocedp = true; #endif if (target != rom_header) { ulong start = get_timer(0); @@ -253,9 +266,9 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), int exec_method) { struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); - struct pci_rom_header *rom, *ram; + struct pci_rom_header *rom, *ram = NULL; int vesa_mode = -1; - bool emulate; + bool emulate, alloced; int ret; /* Only execute VGA ROMs */ @@ -272,12 +285,14 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), if (ret) return ret; - ret = pci_rom_load(rom, &ram); + ret = pci_rom_load(rom, &ram, &alloced); if (ret) - return ret; + goto err; - if (!board_should_run_oprom(dev)) - return -ENXIO; + if (!board_should_run_oprom(dev)) { + ret = -ENXIO; + goto err; + } #if defined(CONFIG_FRAMEBUFFER_SET_VESA_MODE) && \ defined(CONFIG_FRAMEBUFFER_VESA_MODE) @@ -291,7 +306,8 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), #else if (!(exec_method & PCI_ROM_ALLOW_FALLBACK)) { printf("BIOS native execution is only available on x86\n"); - return -ENOSYS; + ret = -ENOSYS; + goto err; } emulate = true; #endif @@ -301,7 +317,8 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), #else if (!(exec_method & PCI_ROM_ALLOW_FALLBACK)) { printf("BIOS emulation not available - see CONFIG_BIOSEMU\n"); - return -ENOSYS; + ret = -ENOSYS; + goto err; } emulate = false; #endif @@ -311,14 +328,14 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), #ifdef CONFIG_BIOSEMU BE_VGAInfo *info; - ret = biosemu_setup(dm_pci_get_bdf(dev), &info); + ret = biosemu_setup(dev, &info); if (ret) - return ret; + goto err; biosemu_set_interrupt_handler(0x15, int15_handler); - ret = biosemu_run(dm_pci_get_bdf(dev), (uchar *)ram, 1 << 16, - info, true, vesa_mode, &mode_info); + ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info, + true, vesa_mode, &mode_info); if (ret) - return ret; + goto err; #endif } else { #ifdef CONFIG_X86 @@ -329,6 +346,10 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), #endif } debug("Final vesa mode %#x\n", mode_info.video_mode); + ret = 0; - return 0; +err: + if (alloced) + free(ram); + return ret; } |