void pci_init_board(void) { struct pci_controller* hose = (struct pci_controller *)&local_hose; u16 reg16; hose->first_busno = 0; hose->last_busno = 0xff; pci_set_region(hose->regions + 0, CONFIG_SYS_PCI_MEMORY_BUS, CONFIG_SYS_PCI_MEMORY_PHYS, CONFIG_SYS_PCI_MEMORY_SIZE, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); /* PCI memory space */ pci_set_region(hose->regions + 1, CONFIG_SYS_PCI_MEM_BUS, CONFIG_SYS_PCI_MEM_PHYS, CONFIG_SYS_PCI_MEM_SIZE, PCI_REGION_MEM); /* ISA/PCI memory space */ pci_set_region(hose->regions + 2, CONFIG_SYS_ISA_MEM_BUS, CONFIG_SYS_ISA_MEM_PHYS, CONFIG_SYS_ISA_MEM_SIZE, PCI_REGION_MEM); /* PCI I/O space */ pci_set_region(hose->regions + 3, CONFIG_SYS_PCI_IO_BUS, CONFIG_SYS_PCI_IO_PHYS, CONFIG_SYS_PCI_IO_SIZE, PCI_REGION_IO); /* ISA/PCI I/O space */ pci_set_region(hose->regions + 4, CONFIG_SYS_ISA_IO_BUS, CONFIG_SYS_ISA_IO_PHYS, CONFIG_SYS_ISA_IO_SIZE, PCI_REGION_IO); hose->region_count = 5; pci_setup_indirect(hose, MPC106_REG_ADDR, MPC106_REG_DATA); pci_register_hose(hose); hose->last_busno = pci_hose_scan(hose); /* Initialises the MPC10x PCI Configuration regs. */ pci_read_config_word (PCI_BDF(0,0,0), PCI_COMMAND, ®16); reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; pci_write_config_word(PCI_BDF(0,0,0), PCI_COMMAND, reg16); /* Clear non-reserved bits in status register */ pci_write_config_word(PCI_BDF(0,0,0), PCI_STATUS, 0xffff); }
void pci_init_board(void) { struct pci_controller *hose; fsl_pcie_init_board(0); hose = find_hose_by_cfg_addr((void *)(CONFIG_SYS_PCIE3_ADDR)); if (hose) { u32 temp32; u8 uli_busno = hose->first_busno + 2; /* * Activate ULI1575 legacy chip by performing a fake * memory access. Needed to make ULI RTC work. * Device 1d has the first on-board memory BAR. */ pci_hose_read_config_dword(hose, PCI_BDF(uli_busno, 0x1d, 0), PCI_BASE_ADDRESS_1, &temp32); if (temp32 >= CONFIG_SYS_PCIE3_MEM_BUS) { void *p = pci_mem_to_virt(PCI_BDF(uli_busno, 0x1d, 0), temp32, 4, 0); debug(" uli1572 read to %p\n", p); in_be32(p); } } }
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; for (hose = 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); #else bdf < PCI_BDF(bus+1,0,0); #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--; } } } return (-1); }
static void qemu_chipset_init(void) { u16 device, xbcs; int pam, i; /* * i440FX and Q35 chipset have different PAM register offset, but with * the same bitfield layout. Here we determine the offset based on its * PCI device ID. */ pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID, &device); i440fx = (device == PCI_DEVICE_ID_INTEL_82441); pam = i440fx ? I440FX_PAM : Q35_PAM; /* * Initialize Programmable Attribute Map (PAM) Registers * * Configure legacy segments C/D/E/F to system RAM */ for (i = 0; i < PAM_NUM; i++) pci_write_config8(PCI_BDF(0, 0, 0), pam + i, PAM_RW); if (i440fx) { /* * Enable legacy IDE I/O ports decode * * Note: QEMU always decode legacy IDE I/O port on PIIX chipset. * However Linux ata_piix driver does sanity check on these two * registers to see whether legacy ports decode is turned on. * This is to make Linux ata_piix driver happy. */ pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN); pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN); /* Enable I/O APIC */ pci_read_config16(PIIX_ISA, XBCS, &xbcs); xbcs |= APIC_EN; pci_write_config16(PIIX_ISA, XBCS, xbcs); enable_pm_piix(); } else { /* Configure PCIe ECAM base address */ pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR, CONFIG_PCIE_ECAM_BASE | BAR_EN); enable_pm_ich9(); } #ifdef CONFIG_QFW qemu_fwcfg_init(&fwcfg_x86_ops); #endif }
static int get_pcie_bar(u32 *base, u32 *len) { pci_dev_t dev = PCI_BDF(0, 0, 0); u32 pciexbar_reg; *base = 0; *len = 0; pciexbar_reg = x86_pci_read_config32(dev, PCIEXBAR); if (!(pciexbar_reg & (1 << 0))) return 0; switch ((pciexbar_reg >> 1) & 3) { case 0: /* 256MB */ *base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | (1 << 28)); *len = 256 * 1024 * 1024; return 1; case 1: /* 128M */ *base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | (1 << 28) | (1 << 27)); *len = 128 * 1024 * 1024; return 1; case 2: /* 64M */ *base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | (1 << 28) | (1 << 27) | (1 << 26)); *len = 64 * 1024 * 1024; return 1; } return 0; }
/** * pciinfo() - Show a list of devices on the PCI bus * * Show information about devices on PCI bus. Depending on @short_pci_listing * the output will be more or less exhaustive. * * @bus_num: The number of the bus to be scanned * @short_pci_listing: true to use short form, showing only a brief header * for each device */ void pciinfo(int bus_num, int short_pci_listing) { struct pci_controller *hose = pci_bus_to_hose(bus_num); int device; int function; unsigned char header_type; unsigned short vendor_id; pci_dev_t dev; int ret; if (!hose) return; pciinfo_header(bus_num, short_pci_listing); for (device = 0; device < PCI_MAX_PCI_DEVICES; device++) { header_type = 0; vendor_id = 0; for (function = 0; function < PCI_MAX_PCI_FUNCTIONS; function++) { /* * If this is not a multi-function device, we skip * the rest. */ if (function && !(header_type & 0x80)) break; dev = PCI_BDF(bus_num, device, function); if (pci_skip_dev(hose, dev)) continue; ret = pci_read_config_word(dev, PCI_VENDOR_ID, &vendor_id); if (ret) goto error; if ((vendor_id == 0xFFFF) || (vendor_id == 0x0000)) continue; if (!function) { pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); } if (short_pci_listing) { printf("%02x.%02x.%02x ", bus_num, device, function); pci_header_show_brief(dev); } else { printf("\nFound PCI device %02x.%02x.%02x:\n", bus_num, device, function); pci_header_show(dev); } } } return; error: printf("Cannot read bus configuration: %d\n", ret); }
static int pcie_write_config(struct pci_controller *hose, unsigned int devfn, int offset, int len, u32 val) { /* * 440SPE implements only one function per port */ if (!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 1))) return 0; devfn = PCI_BDF(0,0,0); offset += devfn << 4; switch (len) { case 1: out_8(hose->cfg_data + offset, val); break; case 2: out_le16((u16 *)(hose->cfg_data + offset), val); break; default: out_le32((u32 *)(hose->cfg_data + offset), val); break; } return 0; }
void eepro100_srom_load (unsigned short *destination) { int count; struct eth_device onboard_dev; #ifdef DEBUG int lr = 0; printf ("eepro100_srom_download:\n"); #endif /* get onboard network iobase */ pci_read_config_dword(PCI_BDF(0,0x10,0), PCI_BASE_ADDRESS_0, &onboard_dev.iobase); onboard_dev.iobase &= ~0xf; memset (destination, 0x65, 128); for (count=0; count < 0x40; count++) { *destination++ = read_eeprom (struct eth_device*)&onboard_dev, count, EE_ADDR_BITS); #ifdef DEBUG printf ("%04x ", *(destination - 1)); if (lr++ == 7) { printf("\n"); lr = 0; } #endif } }
void pci_assign_irqs(int bus, int device, u8 irq[4]) { pci_dev_t bdf; int func; u16 vendor; u8 pin, line; for (func = 0; func < 8; func++) { bdf = PCI_BDF(bus, device, func); vendor = x86_pci_read_config16(bdf, PCI_VENDOR_ID); if (vendor == 0xffff || vendor == 0x0000) continue; pin = x86_pci_read_config8(bdf, PCI_INTERRUPT_PIN); /* PCI spec says all values except 1..4 are reserved */ if ((pin < 1) || (pin > 4)) continue; line = irq[pin - 1]; if (!line) continue; debug("Assigning IRQ %d to PCI device %d.%x.%d (INT%c)\n", line, bus, device, func, 'A' + pin - 1); x86_pci_write_config8(bdf, PCI_INTERRUPT_LINE, line); } }
/* Config the VIA chip */ void mpc85xx_config_via(struct pci_controller *hose, pci_dev_t dev, struct pci_config_table *tab) { pci_dev_t bridge; unsigned int cmdstat; /* Enable USB and IDE functions */ pci_hose_write_config_byte(hose, dev, 0x48, 0x08); pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat); cmdstat |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY| PCI_COMMAND_MASTER; pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat); pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08); pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); /* * Force the backplane P2P bridge to have a window * open from 0x00000000-0x00001fff in PCI I/O space. * This allows legacy I/O (i8259, etc) on the VIA * southbridge to be accessed. */ bridge = PCI_BDF(0,BRIDGE_ID,0); pci_hose_write_config_byte(hose, bridge, PCI_IO_BASE, 0); pci_hose_write_config_word(hose, bridge, PCI_IO_BASE_UPPER16, 0); pci_hose_write_config_byte(hose, bridge, PCI_IO_LIMIT, 0x10); pci_hose_write_config_word(hose, bridge, PCI_IO_LIMIT_UPPER16, 0); }
/* Test that we can use the swapcase device correctly */ static int dm_test_pci_swapcase(struct unit_test_state *uts) { struct udevice *emul, *swap; ulong io_addr, mem_addr; char *ptr; /* Check that asking for the device automatically fires up PCI */ ut_assertok(uclass_get_device(UCLASS_PCI_EMUL, 0, &emul)); ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap)); ut_assert(device_active(swap)); /* First test I/O */ io_addr = dm_pci_read_bar32(swap, 0); outb(2, io_addr); ut_asserteq(2, inb(io_addr)); /* * Now test memory mapping - note we must unmap and remap to cause * the swapcase emulation to see our data and response. */ mem_addr = dm_pci_read_bar32(swap, 1); ptr = map_sysmem(mem_addr, 20); strcpy(ptr, "This is a TesT"); unmap_sysmem(ptr); ptr = map_sysmem(mem_addr, 20); ut_asserteq_str("tHIS IS A tESt", ptr); unmap_sysmem(ptr); return 0; }
void pci_target_init(struct pci_controller *hose) { /* First do 440EP(x) common setup */ __pci_target_init(hose); /* * Set up Configuration registers for on-board NEC uPD720101 USB * controller. */ pci_write_config_dword(PCI_BDF(0x0, 0xC, 0x0), 0xE4, 0x00000020); }
void host_bridge_init (void) { /* The bridge chip is at a fixed location. */ pci_dev_t dev = PCI_BDF (0, 10, 0); /* Set PCI Class code -- The primary side sees this class code at 0x08 in the primary config space. This must be something other then a bridge, or MS Windows starts doing weird stuff to me. */ pci_write_config_dword (dev, 0x48, 0x04800000); /* Set subsystem ID -- The primary side sees this value at 0x2c. We set it here so that the host can tell what sort of device this is: We are a Picture Elements [0x12c5] JSE [0x008a]. */ pci_write_config_dword (dev, 0x6c, 0x008a12c5); /* Downstream (Primary-to-Secondary) BARs are set up mostly off. We need only the Memory-0 Bar so that the host can get at the CSR region to set up tables and the lot. */ /* Downstream Memory 0 setup (4K for CSR) */ pci_write_config_dword (dev, 0xac, 0xfffff000); /* Downstream Memory 1 setup (off) */ pci_write_config_dword (dev, 0xb0, 0x00000000); /* Downstream Memory 2 setup (off) */ pci_write_config_dword (dev, 0xb4, 0x00000000); /* Downstream Memory 3 setup (off) */ pci_write_config_dword (dev, 0xb8, 0x00000000); /* Upstream (Secondary-to-Primary) BARs are used to get at host memory from the JSE card. Create two regions: a small one to manage individual word reads/writes, and a larger one for doing bulk frame moves. */ /* Upstream Memory 0 Setup -- (BAR2) 4K non-prefetchable */ pci_write_config_dword (dev, 0xc4, 0xfffff000); /* Upstream Memory 1 setup -- (BAR3) 4K non-prefetchable */ pci_write_config_dword (dev, 0xc8, 0xfffff000); /* Upstream Memory 2 (BAR4) uses page translation, and is set up in CCR1. Configure for 4K pages. */ /* Set CCR1,0 reigsters. This clears the Primary PCI Lockout bit as well, so we are done configuring after this point. Therefore, this must be the last step. CC1[15:12]= 0 (disable I2O message unit) CC1[11:8] = 0x5 (4K page size) CC0[11] = 1 (Secondary Clock Disable: disable clock) CC0[10] = 0 (Primary Access Lockout: allow primary access) */ pci_write_config_dword (dev, 0xcc, 0x05000800); }
void fsl_pci_init(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data) { u16 temp16; u32 temp32; int enabled, r, inbound = 0; u16 ltssm; u8 temp8, pcie_cap; volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *)cfg_addr; struct pci_region *reg = hose->regions + hose->region_count; pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0); /* Initialize ATMU registers based on hose regions and flags */ volatile pot_t *po = &pci->pot[1]; /* skip 0 */ volatile pit_t *pi = &pci->pit[2]; /* ranges from: 3 to 1 */ u64 out_hi = 0, out_lo = -1ULL; u32 pcicsrbar, pcicsrbar_sz; #ifdef DEBUG int neg_link_w; #endif pci_setup_indirect(hose, cfg_addr, cfg_data); /* Handle setup of outbound windows first */ for (r = 0; r < hose->region_count; r++) { unsigned long flags = hose->regions[r].flags; u32 sz = (__ilog2_u64((u64)hose->regions[r].size) - 1); flags &= PCI_REGION_SYS_MEMORY|PCI_REGION_TYPE; if (flags != PCI_REGION_SYS_MEMORY) { u64 start = hose->regions[r].bus_start; u64 end = start + hose->regions[r].size; out_be32(&po->powbar, hose->regions[r].phys_start >> 12); out_be32(&po->potar, start >> 12); #ifdef CONFIG_SYS_PCI_64BIT out_be32(&po->potear, start >> 44); #else out_be32(&po->potear, 0); #endif if (hose->regions[r].flags & PCI_REGION_IO) { out_be32(&po->powar, POWAR_EN | sz | POWAR_IO_READ | POWAR_IO_WRITE); } else { out_be32(&po->powar, POWAR_EN | sz | POWAR_MEM_READ | POWAR_MEM_WRITE); out_lo = min(start, out_lo); out_hi = max(end, out_hi); } po++; } }
/* * Subroutine: pciinfo * * Description: Show information about devices on PCI bus. * Depending on the define CONFIG_SYS_SHORT_PCI_LISTING * the output will be more or less exhaustive. * * Inputs: bus_no the number of the bus to be scanned. * * Return: None * */ void pciinfo(u32 BusNum) { int Device; int Function; unsigned char HeaderType; unsigned short VendorID; pci_dev_t dev; int ShortPCIListing; printf("Scanning PCI devices on bus %d\r\n", BusNum); ShortPCIListing = 0; if (ShortPCIListing) { printf("BusDevFun VendorId DeviceId Device Class Sub-Class\r\n"); printf("_____________________________________________________________\r\n"); } for (Device = 0; Device < PCI_MAX_PCI_DEVICES; Device++) { HeaderType = 0; VendorID = 0; for (Function = 0; Function < PCI_MAX_PCI_FUNCTIONS; Function++) { /* * If this is not a multi-function device, we skip the rest. */ if (Function && !(HeaderType & 0x80)) break; dev = PCI_BDF(BusNum, Device, Function); pci_read_config_word(dev, PCI_VENDOR_ID, &VendorID); if ((VendorID == 0xFFFF) || (VendorID == 0x0000)) continue; if (!Function) pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType); if (ShortPCIListing) { printf("%02x %02x %02x ", BusNum, Device, Function); pci_header_show_brief(dev); } else { printf("\nFound PCI device %02x %02x %02x:\r\n", BusNum, Device, Function); pci_header_show(dev); } } } }
/* * Unlock the configuration bit so that the host system can begin booting * * This should be used after you have: * 1) Called mpc83xx_pci_init() * 2) Set up your inbound translation windows to the appropriate size */ void mpc83xx_pcislave_unlock(int bus) { struct pci_controller *hose = &pci_hose[bus]; u32 dev; u16 reg16; /* Unlock configuration lock in PCI function configuration register */ dev = PCI_BDF(hose->first_busno, 0, 0); pci_hose_read_config_word (hose, dev, PCI_FUNCTION_CONFIG, ®16); reg16 &= ~(PCI_FUNCTION_CFG_LOCK); pci_hose_write_config_word (hose, dev, PCI_FUNCTION_CONFIG, reg16); /* The configuration bit is now unlocked, so we can scan the bus */ hose->last_busno = pci_hose_scan(hose); }
int bridge_silicon_revision(void) { if (bridge_revision_id < 0) { struct cpuid_result result; uint8_t stepping, bridge_id; pci_dev_t dev; result = cpuid(1); stepping = result.eax & 0xf; dev = PCI_BDF(0, 0, 0); bridge_id = x86_pci_read_config16(dev, PCI_DEVICE_ID) & 0xf0; bridge_revision_id = bridge_id | stepping; } return bridge_revision_id; }
static int broadwell_pch_early_init(struct udevice *dev) { struct gpio_desc desc; struct udevice *bus; pci_dev_t bdf; int ret; dm_pci_write_config32(dev, PCH_RCBA, RCB_BASE_ADDRESS | 1); dm_pci_write_config32(dev, PMBASE, ACPI_BASE_ADDRESS | 1); dm_pci_write_config8(dev, ACPI_CNTL, ACPI_EN); dm_pci_write_config32(dev, GPIO_BASE, GPIO_BASE_ADDRESS | 1); dm_pci_write_config8(dev, GPIO_CNTL, GPIO_EN); /* Enable IOAPIC */ writew(0x1000, RCB_REG(OIC)); /* Read back for posted write */ readw(RCB_REG(OIC)); /* Set HPET address and enable it */ clrsetbits_le32(RCB_REG(HPTC), 3, 1 << 7); /* Read back for posted write */ readl(RCB_REG(HPTC)); /* Enable HPET to start counter */ setbits_le32(HPET_BASE_ADDRESS + 0x10, 1 << 0); setbits_le32(RCB_REG(GCS), 1 << 5); /* * Enable PP3300_AUTOBAHN_EN after initial GPIO setup * to prevent possible brownout. This will cause the GPIOs to be set * up if it has not been done already. */ ret = gpio_request_by_name(dev, "power-enable-gpio", 0, &desc, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); if (ret) return ret; /* 8.14 Additional PCI Express Programming Steps, step #1 */ bdf = PCI_BDF(0, 0x1c, 0); bus = pci_get_controller(dev); pci_bus_clrset_config32(bus, bdf, 0xf4, 0x60, 0); pci_bus_clrset_config32(bus, bdf, 0xf4, 0x80, 0x80); pci_bus_clrset_config32(bus, bdf, 0xe2, 0x30, 0x30); return 0; }
/* * Configure the internal clock of both SIO HS-UARTs, if they are enabled * via FSP */ int arch_cpu_init_dm(void) { struct udevice *dev; void *base; int ret; int i; /* Loop over the 2 HS-UARTs */ for (i = 0; i < 2; i++) { ret = dm_pci_bus_find_bdf(PCI_BDF(0, 0x1e, 3 + i), &dev); if (!ret) { base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); hsuart_clock_set(base); } } return 0; }
int eepro100_srom_store (unsigned short *source) { int count; struct eth_device onboard_dev; /* get onboard network iobase */ pci_read_config_dword(PCI_BDF(0,0x10,0), PCI_BASE_ADDRESS_0, &onboard_dev.iobase); onboard_dev.iobase &= ~0xf; source[63] = eepro100_srom_checksum (source); for (count=0; count < EE_SIZE; count++) { if ( eepro100_write_eeprom ((struct eth_device*)&onboard_dev, count, EE_ADDR_BITS, SROM_SHORT(source)) == -1 ) return -1; source++; } return 0; }
void fsl_pci_init(struct pci_controller *hose) { u16 temp16; u32 temp32; int busno = hose->first_busno; int enabled; u16 ltssm; u8 temp8; int r; int bridge; int inbound = 0; volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *) hose->cfg_addr; pci_dev_t dev = PCI_BDF(busno,0,0); /* Initialize ATMU registers based on hose regions and flags */ volatile pot_t *po = &pci->pot[1]; /* skip 0 */ volatile pit_t *pi = &pci->pit[0]; /* ranges from: 3 to 1 */ #ifdef DEBUG int neg_link_w; #endif for (r=0; r<hose->region_count; r++) { u32 sz = (__ilog2_u64((u64)hose->regions[r].size) - 1); if (hose->regions[r].flags & PCI_REGION_SYS_MEMORY) { /* inbound */ u32 flag = PIWAR_EN | PIWAR_LOCAL | PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP; pi->pitar = (hose->regions[r].phys_start >> 12); pi->piwbar = (hose->regions[r].bus_start >> 12); #ifdef CONFIG_SYS_PCI_64BIT pi->piwbear = (hose->regions[r].bus_start >> 44); #else pi->piwbear = 0; #endif if (hose->regions[r].flags & PCI_REGION_PREFETCH) flag |= PIWAR_PF; pi->piwar = flag | sz; pi++; inbound = hose->regions[r].size > 0; } else { /* Outbound */
int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq) { u8 irq; if (i440fx) { /* * Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not * connected to I/O APIC INTPIN#16-19. Instead they are routed * to an irq number controled by the PIRQ routing register. */ irq = x86_pci_read_config8(PCI_BDF(bus, dev, func), PCI_INTERRUPT_LINE); } else { /* * ICH9's PIRQ[A-H] are not consecutive numbers from 0 to 7. * PIRQ[A-D] still maps to [0-3] but PIRQ[E-H] maps to [8-11]. */ irq = pirq < 8 ? pirq + 16 : pirq + 12; } return irq; }
/* Convert the "bus.device.function" identifier into a number. */ static pci_dev_t get_pci_dev(char* name) { char cnum[12]; int len, i, iold, n; int bdfs[3] = {0,0,0}; len = strlen(name); if (len > 8) return -1; for (i = 0, iold = 0, n = 0; i < len; i++) { if (name[i] == '.') { memcpy(cnum, &name[iold], i - iold); cnum[i - iold] = '\0'; bdfs[n++] = simple_strtoul(cnum, NULL, 16); iold = i + 1; } } strcpy(cnum, &name[iold]); if (n == 0) n = 1; bdfs[n] = simple_strtoul(cnum, NULL, 16); return PCI_BDF(bdfs[0], bdfs[1], bdfs[2]); }
void pci_mpc8250_init (struct pci_controller *hose) { u16 tempShort; volatile immap_t *immap = (immap_t *) CFG_IMMR; pci_dev_t host_devno = PCI_BDF (0, 0, 0); pci_setup_indirect (hose, CFG_IMMR + PCI_CFG_ADDR_REG, CFG_IMMR + PCI_CFG_DATA_REG); /* * Setting required to enable local bus for PCI (SIUMCR [LBPC]). */ #ifdef CONFIG_MPC8266ADS immap->im_siu_conf.sc_siumcr = (immap->im_siu_conf.sc_siumcr & ~SIUMCR_LBPC11) | SIUMCR_LBPC01; #elif defined CONFIG_MPC8272 immap->im_siu_conf.sc_siumcr = (immap->im_siu_conf.sc_siumcr & ~SIUMCR_BBD & ~SIUMCR_ESE & ~SIUMCR_PBSE & ~SIUMCR_CDIS & ~SIUMCR_DPPC11 & ~SIUMCR_L2CPC11 & ~SIUMCR_LBPC11 & ~SIUMCR_APPC11 & ~SIUMCR_CS10PC11 & ~SIUMCR_BCTLC11 & ~SIUMCR_MMR11) | SIUMCR_DPPC11 | SIUMCR_L2CPC01 | SIUMCR_LBPC00 | SIUMCR_APPC10 | SIUMCR_CS10PC00 | SIUMCR_BCTLC00 | SIUMCR_MMR11; #elif defined(CONFIG_TQM8272) /* nothing to do for this Board here */ #else /* * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]), * and local bus for PCI (SIUMCR [LBPC]). */ immap->im_siu_conf.sc_siumcr = (immap->im_siu_conf.sc_siumcr & ~SIUMCR_LBPC11 & ~SIUMCR_CS10PC11 & ~SIUMCR_LBPC11) | SIUMCR_LBPC01 | SIUMCR_CS10PC01 | SIUMCR_APPC10; #endif /* Make PCI lowest priority */ /* Each 4 bits is a device bus request and the MS 4bits is highest priority */ /* Bus 4bit value --- ---------- CPM high 0b0000 CPM middle 0b0001 CPM low 0b0010 PCI reguest 0b0011 Reserved 0b0100 Reserved 0b0101 Internal Core 0b0110 External Master 1 0b0111 External Master 2 0b1000 External Master 3 0b1001 The rest are reserved */ immap->im_siu_conf.sc_ppc_alrh = 0x61207893; /* Park bus on core while modifying PCI Bus accesses */ immap->im_siu_conf.sc_ppc_acr = 0x6; /* * Set up master windows that allow the CPU to access PCI space. These * windows are set up using the two SIU PCIBR registers. */ immap->im_memctl.memc_pcimsk0 = PCIMSK0_MASK; immap->im_memctl.memc_pcibr0 = PCI_MSTR0_LOCAL | PCIBR_ENABLE; #if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272 immap->im_memctl.memc_pcimsk1 = PCIMSK1_MASK; immap->im_memctl.memc_pcibr1 = PCI_MSTR1_LOCAL | PCIBR_ENABLE; #endif /* Release PCI RST (by default the PCI RST signal is held low) */ immap->im_pci.pci_gcr = cpu_to_le32 (PCIGCR_PCI_BUS_EN); /* give it some time */ { #if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272 /* Give the PCI cards more time to initialize before query This might be good for other boards also */ int i; for (i = 0; i < 1000; ++i) #endif udelay (1000); } /* * Set up master window that allows the CPU to access PCI Memory (prefetch) * space. This window is set up using the first set of Outbound ATU registers. */ immap->im_pci.pci_potar0 = cpu_to_le32 (PCI_MSTR_MEM_BUS >> 12); /* PCI base */ immap->im_pci.pci_pobar0 = cpu_to_le32 (PCI_MSTR_MEM_LOCAL >> 12); /* Local base */ immap->im_pci.pci_pocmr0 = cpu_to_le32 (POCMR0_MASK_ATTRIB); /* Size & attribute */ /* * Set up master window that allows the CPU to access PCI Memory (non-prefetch) * space. This window is set up using the second set of Outbound ATU registers. */ immap->im_pci.pci_potar1 = cpu_to_le32 (PCI_MSTR_MEMIO_BUS >> 12); /* PCI base */ immap->im_pci.pci_pobar1 = cpu_to_le32 (PCI_MSTR_MEMIO_LOCAL >> 12); /* Local base */ immap->im_pci.pci_pocmr1 = cpu_to_le32 (POCMR1_MASK_ATTRIB); /* Size & attribute */ /* * Set up master window that allows the CPU to access PCI IO space. This window * is set up using the third set of Outbound ATU registers. */ immap->im_pci.pci_potar2 = cpu_to_le32 (PCI_MSTR_IO_BUS >> 12); /* PCI base */ immap->im_pci.pci_pobar2 = cpu_to_le32 (PCI_MSTR_IO_LOCAL >> 12); /* Local base */ immap->im_pci.pci_pocmr2 = cpu_to_le32 (POCMR2_MASK_ATTRIB); /* Size & attribute */ /* * Set up slave window that allows PCI masters to access MPC826x local memory. * This window is set up using the first set of Inbound ATU registers */ immap->im_pci.pci_pitar0 = cpu_to_le32 (PCI_SLV_MEM_LOCAL >> 12); /* PCI base */ immap->im_pci.pci_pibar0 = cpu_to_le32 (PCI_SLV_MEM_BUS >> 12); /* Local base */ immap->im_pci.pci_picmr0 = cpu_to_le32 (PICMR0_MASK_ATTRIB); /* Size & attribute */ /* See above for description - puts PCI request as highest priority */ #ifdef CONFIG_MPC8272 immap->im_siu_conf.sc_ppc_alrh = 0x01236745; #else immap->im_siu_conf.sc_ppc_alrh = 0x03124567; #endif /* Park the bus on the PCI */ immap->im_siu_conf.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI; /* Host mode - specify the bridge as a host-PCI bridge */ pci_hose_write_config_byte (hose, host_devno, PCI_CLASS_CODE, PCI_CLASS_BRIDGE_CTLR); /* Enable the host bridge to be a master on the PCI bus, and to act as a PCI memory target */ pci_hose_read_config_word (hose, host_devno, PCI_COMMAND, &tempShort); pci_hose_write_config_word (hose, host_devno, PCI_COMMAND, tempShort | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); /* do some bridge init, should be done on all 8260 based bridges */ pci_hose_write_config_byte (hose, host_devno, PCI_CACHE_LINE_SIZE, 0x08); pci_hose_write_config_byte (hose, host_devno, PCI_LATENCY_TIMER, 0xF8); hose->first_busno = 0; hose->last_busno = 0xff; /* System memory space */ #if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272 || defined CONFIG_PM826 pci_set_region (hose->regions + 0, PCI_SLV_MEM_BUS, PCI_SLV_MEM_LOCAL, gd->ram_size, PCI_REGION_MEM | PCI_REGION_MEMORY); #else pci_set_region (hose->regions + 0, CFG_SDRAM_BASE, CFG_SDRAM_BASE, 0x4000000, PCI_REGION_MEM | PCI_REGION_MEMORY); #endif /* PCI memory space */ #if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272 pci_set_region (hose->regions + 1, PCI_MSTR_MEMIO_BUS, PCI_MSTR_MEMIO_LOCAL, PCI_MSTR_MEMIO_SIZE, PCI_REGION_MEM); #else pci_set_region (hose->regions + 1, PCI_MSTR_MEM_BUS, PCI_MSTR_MEM_LOCAL, PCI_MSTR_MEM_SIZE, PCI_REGION_MEM); #endif /* PCI I/O space */ pci_set_region (hose->regions + 2, PCI_MSTR_IO_BUS, PCI_MSTR_IO_LOCAL, PCI_MSTR_IO_SIZE, PCI_REGION_IO); hose->region_count = 3; pci_register_hose (hose); /* Mask off master abort machine checks */ immap->im_pci.pci_emr &= cpu_to_le32 (~PCI_ERROR_PCI_NO_RSP); eieio (); hose->last_busno = pci_hose_scan (hose); /* clear the error in the error status register */ immap->im_pci.pci_esr = cpu_to_le32 (PCI_ERROR_PCI_NO_RSP); /* unmask master abort machine checks */ immap->im_pci.pci_emr |= cpu_to_le32 (PCI_ERROR_PCI_NO_RSP); }
void pci_init_board (void) { struct fsl_pci_info pci_info[2]; int first_free_busno = 0; int num = 0; int pcie_ep; __maybe_unused int pcie_configured; volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); u32 devdisr = in_be32(&gur->devdisr); u32 pordevsr = in_be32(&gur->pordevsr); __maybe_unused uint io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >> MPC85xx_PORDEVSR_IO_SEL_SHIFT; #ifdef CONFIG_PCI1 uint pci_32 = in_be32(&gur->pordevsr) & MPC85xx_PORDEVSR_PCI1_PCI32; uint pci_arb = in_be32(&gur->pordevsr) & MPC85xx_PORDEVSR_PCI1_ARB; uint pci_speed = CONFIG_SYS_CLK_FREQ; /* PCI PSPEED in [4:5] */ uint pci_clk_sel = in_be32(&gur->porpllsr) & MPC85xx_PORDEVSR_PCI1_SPD; if (!(devdisr & MPC85xx_DEVDISR_PCI1)) { SET_STD_PCI_INFO(pci_info[num], 1); pcie_ep = fsl_setup_hose(&pci1_hose, pci_info[num].regs); printf("PCI1: %d bit, %s MHz, %s, %s, %s\n", (pci_32) ? 32 : 64, (pci_speed == 33333333) ? "33" : (pci_speed == 66666666) ? "66" : "unknown", pci_clk_sel ? "sync" : "async", pcie_ep ? "agent" : "host", pci_arb ? "arbiter" : "external-arbiter"); first_free_busno = fsl_pci_init_port(&pci_info[num++], &pci1_hose, first_free_busno); #ifdef CONFIG_PCIX_CHECK if (!(in_be32(&gur->pordevsr) & MPC85xx_PORDEVSR_PCI1)) { ushort reg16 = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ | PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E; uint dev = PCI_BDF(0, 0, 0); /* PCI-X init */ if (CONFIG_SYS_CLK_FREQ < 66000000) puts ("PCI-X will only work at 66 MHz\n"); pci_write_config_word(dev, PCIX_COMMAND, reg16); } #endif } else { printf("PCI1: disabled\n"); } #else setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCI1); #endif #ifdef CONFIG_PCIE1 pcie_configured = is_fsl_pci_cfg(LAW_TRGT_IF_PCIE_1, io_sel); if (pcie_configured && !(devdisr & MPC85xx_DEVDISR_PCIE)) { SET_STD_PCIE_INFO(pci_info[num], 1); pcie_ep = fsl_setup_hose(&pcie1_hose, pci_info[num].regs); printf("PCIE1: connected as %s\n", pcie_ep ? "Endpoint" : "Root Complex"); first_free_busno = fsl_pci_init_port(&pci_info[num++], &pcie1_hose, first_free_busno); } else { printf("PCIE1: disabled\n"); } #else setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCIE); #endif /* CONFIG_PCIE1 */ }
/* * Subroutine: pciinfo * * Description: Show information about devices on PCI bus. * Depending on the define CONFIG_SYS_SHORT_PCI_LISTING * the output will be more or less exhaustive. * * Inputs: bus_no the number of the bus to be scanned. * * Return: None * */ void pciinfo(int BusNum, int ShortPCIListing) { struct pci_controller *hose = pci_bus_to_hose(BusNum); int Device; int Function; unsigned char HeaderType; unsigned short VendorID; pci_dev_t dev; int ret; if (!hose) return; printf("Scanning PCI devices on bus %d\n", BusNum); if (ShortPCIListing) { printf("BusDevFun VendorId DeviceId Device Class Sub-Class\n"); printf("_____________________________________________________________\n"); } for (Device = 0; Device < PCI_MAX_PCI_DEVICES; Device++) { HeaderType = 0; VendorID = 0; for (Function = 0; Function < PCI_MAX_PCI_FUNCTIONS; Function++) { /* * If this is not a multi-function device, we skip the rest. */ if (Function && !(HeaderType & 0x80)) break; dev = PCI_BDF(BusNum, Device, Function); if (pci_skip_dev(hose, dev)) continue; ret = pci_read_config_word(dev, PCI_VENDOR_ID, &VendorID); if (ret) goto error; if ((VendorID == 0xFFFF) || (VendorID == 0x0000)) continue; if (!Function) pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType); if (ShortPCIListing) { printf("%02x.%02x.%02x ", BusNum, Device, Function); pci_header_show_brief(dev); } else { printf("\nFound PCI device %02x.%02x.%02x:\n", BusNum, Device, Function); pci_header_show(dev); } } } return; error: printf("Cannot read bus configuration: %d\n", ret); }
static void pci_init_bus(int bus, struct pci_region *reg) { volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR; volatile pot83xx_t *pot = immr->ios.pot; volatile pcictrl83xx_t *pci_ctrl = &immr->pci_ctrl[bus]; struct pci_controller *hose = &pci_hose[bus]; u32 dev; u16 reg16; int i; if (bus == 1) pot += 3; /* Setup outbound translation windows */ for (i = 0; i < 3; i++, reg++, pot++) { if (reg->size == 0) break; hose->regions[i] = *reg; hose->region_count++; pot->potar = reg->bus_start >> 12; pot->pobar = reg->phys_start >> 12; pot->pocmr = ~(reg->size - 1) >> 12; if (reg->flags & PCI_REGION_IO) pot->pocmr |= POCMR_IO; #ifdef CONFIG_83XX_PCI_STREAMING else if (reg->flags & PCI_REGION_PREFETCH) pot->pocmr |= POCMR_SE; #endif if (bus == 1) pot->pocmr |= POCMR_DST; pot->pocmr |= POCMR_EN; } /* Point inbound translation at RAM */ pci_ctrl->pitar1 = 0; pci_ctrl->pibar1 = 0; pci_ctrl->piebar1 = 0; pci_ctrl->piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP | (__ilog2(gd->ram_size - 1)); i = hose->region_count++; hose->regions[i].bus_start = 0; hose->regions[i].phys_start = 0; hose->regions[i].size = gd->ram_size; hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY; hose->first_busno = pci_last_busno() + 1; hose->last_busno = 0xff; pci_setup_indirect(hose, CONFIG_SYS_IMMR + 0x8300 + bus * 0x80, CONFIG_SYS_IMMR + 0x8304 + bus * 0x80); pci_register_hose(hose); /* * Write to Command register */ reg16 = 0xff; dev = PCI_BDF(hose->first_busno, 0, 0); pci_hose_read_config_word(hose, dev, PCI_COMMAND, ®16); reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16); /* * Clear non-reserved bits in status register. */ pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff); pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08); #ifdef CONFIG_PCI_SCAN_SHOW printf("PCI: Bus Dev VenId DevId Class Int\n"); #endif #ifndef CONFIG_PCISLAVE /* * Hose scan. */ hose->last_busno = pci_hose_scan(hose); #endif }
void pci_init_board(void) { volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); struct fsl_pci_info pci_info[3]; u32 devdisr, pordevsr, io_sel, temp32; int first_free_busno = 0; int num = 0; int pcie_ep, pcie_configured; devdisr = in_be32(&gur->devdisr); pordevsr = in_be32(&gur->pordevsr); io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >> 19; debug (" pci_init_board: devdisr=%x, io_sel=%x\n", devdisr, io_sel); if (!(pordevsr & MPC85xx_PORDEVSR_SGMII1_DIS)) printf("eTSEC1 is in sgmii mode.\n"); if (!(pordevsr & MPC85xx_PORDEVSR_SGMII2_DIS)) printf("eTSEC2 is in sgmii mode.\n"); if (!(pordevsr & MPC85xx_PORDEVSR_SGMII3_DIS)) printf("eTSEC3 is in sgmii mode.\n"); if (!(pordevsr & MPC85xx_PORDEVSR_SGMII4_DIS)) printf("eTSEC4 is in sgmii mode.\n"); puts("\n"); #ifdef CONFIG_PCIE3 pcie_configured = is_fsl_pci_cfg(LAW_TRGT_IF_PCIE_3, io_sel); if (pcie_configured && !(devdisr & MPC85xx_DEVDISR_PCIE3)){ SET_STD_PCIE_INFO(pci_info[num], 3); pcie_ep = fsl_setup_hose(&pcie3_hose, pci_info[num].regs); printf("PCIE3: connected to ULI as %s (base addr %lx)\n", pcie_ep ? "Endpoint" : "Root Complex", pci_info[num].regs); first_free_busno = fsl_pci_init_port(&pci_info[num++], &pcie3_hose, first_free_busno); /* * Activate ULI1575 legacy chip by performing a fake * memory access. Needed to make ULI RTC work. * Device 1d has the first on-board memory BAR. */ pci_hose_read_config_dword(&pcie3_hose, PCI_BDF(2, 0x1d, 0), PCI_BASE_ADDRESS_1, &temp32); if (temp32 >= CONFIG_SYS_PCIE3_MEM_BUS) { void *p = pci_mem_to_virt(PCI_BDF(2, 0x1d, 0), temp32, 4, 0); debug(" uli1572 read to %p\n", p); in_be32(p); } } else { printf("PCIE3: disabled\n"); } puts("\n"); #else setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCIE3); /* disable */ #endif #ifdef CONFIG_PCIE2 pcie_configured = is_fsl_pci_cfg(LAW_TRGT_IF_PCIE_2, io_sel); if (pcie_configured && !(devdisr & MPC85xx_DEVDISR_PCIE2)){ SET_STD_PCIE_INFO(pci_info[num], 2); pcie_ep = fsl_setup_hose(&pcie2_hose, pci_info[num].regs); printf("PCIE2: connected to Slot 1 as %s (base addr %lx)\n", pcie_ep ? "Endpoint" : "Root Complex", pci_info[num].regs); first_free_busno = fsl_pci_init_port(&pci_info[num++], &pcie2_hose, first_free_busno); } else { printf("PCIE2: disabled\n"); } puts("\n"); #else setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCIE2); /* disable */ #endif #ifdef CONFIG_PCIE1 pcie_configured = is_fsl_pci_cfg(LAW_TRGT_IF_PCIE_1, io_sel); if (pcie_configured && !(devdisr & MPC85xx_DEVDISR_PCIE)){ SET_STD_PCIE_INFO(pci_info[num], 1); pcie_ep = fsl_setup_hose(&pcie1_hose, pci_info[num].regs); printf("PCIE1: connected to Slot 2 as %s (base addr %lx)\n", pcie_ep ? "Endpoint" : "Root Complex", pci_info[num].regs); first_free_busno = fsl_pci_init_port(&pci_info[num++], &pcie1_hose, first_free_busno); } else { printf("PCIE1: disabled\n"); } puts("\n"); #else setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_PCIE); /* disable */ #endif }
static void pci_bus_scan(struct ftpci100_data *priv) { struct pci_controller *hose = (struct pci_controller *)&local_hose; unsigned int bus, dev, func; pci_dev_t dev_nu; unsigned int data32; unsigned int tmp; unsigned char header; unsigned char int_pin; unsigned int niobars; unsigned int nmbars; priv->ndevs = 1; nmbars = 0; niobars = 0; for (bus = 0; bus < MAX_BUS_NUM; bus++) for (dev = 0; dev < MAX_DEV_NUM; dev++) for (func = 0; func < MAX_FUN_NUM; func++) { dev_nu = PCI_BDF(bus, dev, func); pci_hose_read_config_dword(hose, dev_nu, PCI_VENDOR_ID, &data32); /* * some broken boards return 0 or ~0, * if a slot is empty. */ if (data32 == 0xffffffff || data32 == 0x00000000 || data32 == 0x0000ffff || data32 == 0xffff0000) continue; pci_hose_read_config_dword(hose, dev_nu, PCI_HEADER_TYPE, &tmp); header = (unsigned char)tmp; setup_pci_bar(bus, dev, func, header, priv); devs[priv->ndevs].v_id = (u16)(data32 & \ 0x0000ffff); devs[priv->ndevs].d_id = (u16)((data32 & \ 0xffff0000) >> 16); /* Figure out what INTX# line the card uses */ pci_hose_read_config_byte(hose, dev_nu, PCI_INTERRUPT_PIN, &int_pin); /* assign the appropriate irq line */ if (int_pin > PCI_IRQ_LINES) { printf("more irq lines than expect\n"); } else if (int_pin != 0) { /* This device uses an interrupt line */ devs[priv->ndevs].pin = int_pin; } pci_hose_read_config_dword(hose, dev_nu, PCI_CLASS_DEVICE, &data32); debug("%06d %03d %03d " \ "%04d %08x %08x " \ "%03d %08x %06d %08x\n", priv->ndevs, devs[priv->ndevs].bus, devs[priv->ndevs].dev, devs[priv->ndevs].func, devs[priv->ndevs].d_id, devs[priv->ndevs].v_id, devs[priv->ndevs].pin, devs[priv->ndevs].bar[0].addr, devs[priv->ndevs].bar[0].size, data32 >> 8); priv->ndevs++; } }
static void setup_pci_bar(unsigned int bus, unsigned int dev, unsigned func, unsigned char header, struct ftpci100_data *priv) { struct pci_controller *hose = (struct pci_controller *)&local_hose; unsigned int i, tmp32, bar_no, iovsmem = 1; pci_dev_t dev_nu; /* A device is present, add an entry to the array */ devs[priv->ndevs].bus = bus; devs[priv->ndevs].dev = dev; devs[priv->ndevs].func = func; dev_nu = PCI_BDF(bus, dev, func); if ((header & 0x7f) == 0x01) /* PCI-PCI Bridge */ bar_no = 2; else bar_no = 6; /* Allocate address spaces by configuring BARs */ for (i = 0; i < bar_no; i++) { pci_hose_write_config_dword(hose, dev_nu, PCI_BASE_ADDRESS_0 + i * 4, 0xffffffff); pci_hose_read_config_dword(hose, dev_nu, PCI_BASE_ADDRESS_0 + i * 4, &tmp32); if (tmp32 == 0x0) continue; /* IO space */ if (tmp32 & 0x1) { iovsmem = 0; unsigned int size_mask = ~(tmp32 & 0xfffffffc); if (priv->io_base & size_mask) priv->io_base = (priv->io_base & ~size_mask) + \ size_mask + 1; devs[priv->ndevs].bar[i].addr = priv->io_base; devs[priv->ndevs].bar[i].size = size_mask + 1; pci_hose_write_config_dword(hose, dev_nu, PCI_BASE_ADDRESS_0 + i * 4, priv->io_base); debug("Allocated IO address 0x%X-" \ "0x%X for Bus %d, Device %d, Function %d\n", priv->io_base, priv->io_base + size_mask, bus, dev, func); priv->io_base += size_mask + 1; } else { /* Memory space */ unsigned int is_64bit = ((tmp32 & 0x6) == 0x4); unsigned int is_pref = tmp32 & 0x8; unsigned int size_mask = ~(tmp32 & 0xfffffff0); unsigned int alloc_base; unsigned int *addr_mem_base; if (is_pref) addr_mem_base = &priv->mem_base; else addr_mem_base = &priv->mmio_base; alloc_base = *addr_mem_base; if (alloc_base & size_mask) alloc_base = (alloc_base & ~size_mask) \ + size_mask + 1; pci_hose_write_config_dword(hose, dev_nu, PCI_BASE_ADDRESS_0 + i * 4, alloc_base); debug("Allocated %s address 0x%X-" \ "0x%X for Bus %d, Device %d, Function %d\n", is_pref ? "MEM" : "MMIO", alloc_base, alloc_base + size_mask, bus, dev, func); devs[priv->ndevs].bar[i].addr = alloc_base; devs[priv->ndevs].bar[i].size = size_mask + 1; debug("BAR address BAR size\n"); debug("%010x %08d\n", devs[priv->ndevs].bar[0].addr, devs[priv->ndevs].bar[0].size); alloc_base += size_mask + 1; *addr_mem_base = alloc_base; if (is_64bit) { i++; pci_hose_write_config_dword(hose, dev_nu, PCI_BASE_ADDRESS_0 + i * 4, 0x0); } } } /* Enable Bus Master, Memory Space, and IO Space */ pci_hose_read_config_dword(hose, dev_nu, PCI_CACHE_LINE_SIZE, &tmp32); pci_hose_write_config_dword(hose, dev_nu, PCI_CACHE_LINE_SIZE, 0x08); pci_hose_read_config_dword(hose, dev_nu, PCI_CACHE_LINE_SIZE, &tmp32); pci_hose_read_config_dword(hose, dev_nu, PCI_COMMAND, &tmp32); tmp32 &= 0xffff; if (iovsmem == 0) tmp32 |= 0x5; else tmp32 |= 0x6; pci_hose_write_config_dword(hose, dev_nu, PCI_COMMAND, tmp32); }