diff options
author | Stefano Babic <sbabic@denx.de> | 2015-02-13 11:17:01 +0100 |
---|---|---|
committer | Stefano Babic <sbabic@denx.de> | 2015-02-13 11:17:01 +0100 |
commit | e72d344386bf80738fab7a6bd37cb321f443093a (patch) | |
tree | d3e02055e6aa903ab80ef87c78d2f38e93981dcf /drivers/pci | |
parent | 258c98f8d36ef35d7cb7604847ba73e64d702c2a (diff) | |
parent | bd2a4888b123713adec271d6c8040ca9f609aa2f (diff) | |
download | u-boot-imx-e72d344386bf80738fab7a6bd37cb321f443093a.zip u-boot-imx-e72d344386bf80738fab7a6bd37cb321f443093a.tar.gz u-boot-imx-e72d344386bf80738fab7a6bd37cb321f443093a.tar.bz2 |
Merge branch 'master' of git://git.denx.de/u-boot
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pci.c | 43 | ||||
-rw-r--r-- | drivers/pci/pci_auto.c | 28 | ||||
-rw-r--r-- | drivers/pci/pci_rom.c | 74 | ||||
-rw-r--r-- | drivers/pci/pci_tegra.c | 5 |
4 files changed, 125 insertions, 25 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 950a247..e1296ca 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -15,6 +15,7 @@ #include <common.h> #include <command.h> +#include <errno.h> #include <asm/processor.h> #include <asm/io.h> #include <pci.h> @@ -236,6 +237,48 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) return -1; } +pci_dev_t pci_find_class(uint 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; + + if (class != find_class) + continue; + /* + * Decrement the index. We want to return the + * correct device, so index is 0 for the first + * matching device, 1 for the second, etc. + */ + if (index) { + index--; + continue; + } + /* Return index'th controller. */ + return bdf; + } + } + } + + return -ENODEV; +} + pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index) { struct pci_device_id ids[2] = { {}, {0, 0} }; diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index 44470fa..ed92857 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -11,7 +11,7 @@ */ #include <common.h> - +#include <errno.h> #include <pci.h> #undef DEBUG @@ -191,6 +191,32 @@ void pciauto_setup_device(struct pci_controller *hose, pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); } +int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev) +{ + pci_addr_t bar_value; + pci_size_t bar_size; + u32 bar_response; + u16 cmdstat = 0; + + pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS, 0xfffffffe); + pci_hose_read_config_dword(hose, dev, PCI_ROM_ADDRESS, &bar_response); + if (!bar_response) + return -ENOENT; + + bar_size = -(bar_response & ~1); + DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size); + if (pciauto_region_allocate(hose->pci_mem, bar_size, &bar_value) == 0) { + pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS, + bar_value); + } + DEBUGF("\n"); + pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat); + cmdstat |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat); + + return 0; +} + void pciauto_prescan_setup_bridge(struct pci_controller *hose, pci_dev_t dev, int sub_bus) { diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 7d25cc9..48c0a77 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -66,6 +66,7 @@ static int pci_rom_probe(pci_dev_t dev, uint class, struct pci_rom_header *rom_header; struct pci_rom_data *rom_data; u16 vendor, device; + u16 rom_vendor, rom_device; u32 vendev; u32 mapped_vendev; u32 rom_address; @@ -80,7 +81,12 @@ static int pci_rom_probe(pci_dev_t dev, uint class, #ifdef CONFIG_X86_OPTION_ROM_ADDR rom_address = CONFIG_X86_OPTION_ROM_ADDR; #else - pci_write_config_dword(dev, PCI_ROM_ADDRESS, (u32)PCI_ROM_ADDRESS_MASK); + + if (pciauto_setup_rom(pci_bus_to_hose(PCI_BUS(dev)), dev)) { + debug("Cannot find option ROM\n"); + return -ENOENT; + } + pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_address); if (rom_address == 0x00000000 || rom_address == 0xffffffff) { debug("%s: rom_address=%x\n", __func__, rom_address); @@ -92,29 +98,31 @@ static int pci_rom_probe(pci_dev_t dev, uint class, rom_address | PCI_ROM_ADDRESS_ENABLE); #endif debug("Option ROM address %x\n", rom_address); - rom_header = (struct pci_rom_header *)rom_address; + rom_header = (struct pci_rom_header *)(unsigned long)rom_address; debug("PCI expansion ROM, signature %#04x, INIT size %#04x, data ptr %#04x\n", - le32_to_cpu(rom_header->signature), - rom_header->size * 512, le32_to_cpu(rom_header->data)); + le16_to_cpu(rom_header->signature), + rom_header->size * 512, le16_to_cpu(rom_header->data)); - if (le32_to_cpu(rom_header->signature) != PCI_ROM_HDR) { + if (le16_to_cpu(rom_header->signature) != PCI_ROM_HDR) { printf("Incorrect expansion ROM header signature %04x\n", - le32_to_cpu(rom_header->signature)); + le16_to_cpu(rom_header->signature)); return -EINVAL; } - rom_data = (((void *)rom_header) + le32_to_cpu(rom_header->data)); + rom_data = (((void *)rom_header) + le16_to_cpu(rom_header->data)); + rom_vendor = le16_to_cpu(rom_data->vendor); + rom_device = le16_to_cpu(rom_data->device); debug("PCI ROM image, vendor ID %04x, device ID %04x,\n", - rom_data->vendor, rom_data->device); + rom_vendor, rom_device); /* If the device id is mapped, a mismatch is expected */ - if ((vendor != rom_data->vendor || device != rom_data->device) && + if ((vendor != rom_vendor || device != rom_device) && (vendev == mapped_vendev)) { printf("ID mismatch: vendor ID %04x, device ID %04x\n", - rom_data->vendor, rom_data->device); - return -EPERM; + rom_vendor, rom_device); + /* Continue anyway */ } debug("PCI ROM image, Class Code %04x%02x, Code Type %02x\n", @@ -144,17 +152,23 @@ int pci_rom_load(uint16_t class, struct pci_rom_header *rom_header, image_size); rom_data = (struct pci_rom_data *)((void *)rom_header + - le32_to_cpu(rom_header->data)); + le16_to_cpu(rom_header->data)); - image_size = le32_to_cpu(rom_data->ilen) * 512; - } while ((rom_data->type != 0) && (rom_data->indicator != 0)); + image_size = le16_to_cpu(rom_data->ilen) * 512; + } while ((rom_data->type != 0) && (rom_data->indicator == 0)); if (rom_data->type != 0) return -EACCES; rom_size = rom_header->size * 512; +#ifdef PCI_VGA_RAM_IMAGE_START target = (void *)PCI_VGA_RAM_IMAGE_START; +#else + target = (void *)malloc(rom_size); + if (!target) + return -ENOMEM; +#endif if (target != rom_header) { ulong start = get_timer(0); @@ -214,11 +228,12 @@ int vbe_get_video_info(struct graphic_device *gdev) #endif } -int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate) +int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), int exec_method) { struct pci_rom_header *rom, *ram; int vesa_mode = -1; uint16_t class; + bool emulate; int ret; /* Only execute VGA ROMs */ @@ -248,6 +263,29 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate) vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE; #endif debug("Selected vesa mode %#x\n", vesa_mode); + + if (exec_method & PCI_ROM_USE_NATIVE) { +#ifdef CONFIG_X86 + emulate = false; +#else + if (!(exec_method & PCI_ROM_ALLOW_FALLBACK)) { + printf("BIOS native execution is only available on x86\n"); + return -ENOSYS; + } + emulate = true; +#endif + } else { +#ifdef CONFIG_BIOSEMU + emulate = true; +#else + if (!(exec_method & PCI_ROM_ALLOW_FALLBACK)) { + printf("BIOS emulation not available - see CONFIG_BIOSEMU\n"); + return -ENOSYS; + } + emulate = false; +#endif + } + if (emulate) { #ifdef CONFIG_BIOSEMU BE_VGAInfo *info; @@ -260,9 +298,6 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate) vesa_mode, &mode_info); if (ret) return ret; -#else - printf("BIOS emulation not available - see CONFIG_BIOSEMU\n"); - return -ENOSYS; #endif } else { #ifdef CONFIG_X86 @@ -270,9 +305,6 @@ int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), bool emulate) bios_run_on_x86(dev, (unsigned long)ram, vesa_mode, &mode_info); -#else - printf("BIOS native execution is only available on x86\n"); - return -ENOSYS; #endif } debug("Final vesa mode %#x\n", mode_info.video_mode); diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index f9e05ad..67b5fdf 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -459,7 +459,6 @@ static int tegra_pcie_parse_port_info(const void *fdt, int node, unsigned int *lanes) { struct fdt_pci_addr addr; - pci_dev_t bdf; int err; err = fdtdec_get_int(fdt, node, "nvidia,num-lanes", 0); @@ -470,13 +469,13 @@ static int tegra_pcie_parse_port_info(const void *fdt, int node, *lanes = err; - err = fdtdec_get_pci_bdf(fdt, node, &addr, &bdf); + err = fdtdec_get_pci_addr(fdt, node, 0, "reg", &addr); if (err < 0) { error("failed to parse \"reg\" property"); return err; } - *index = PCI_DEV(bdf) - 1; + *index = PCI_DEV(addr.phys_hi) - 1; return 0; } |