static int get_pcie_bar(struct udevice *dev, u32 *base, u32 *len) { u32 pciexbar_reg; *base = 0; *len = 0; dm_pci_read_config32(dev, PCIEXBAR, &pciexbar_reg); 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; }
static int rtl8169_eth_probe(struct udevice *dev) { struct pci_child_platdata *pplat = dev_get_parent_platdata(dev); struct rtl8169_private *priv = dev_get_priv(dev); struct eth_pdata *plat = dev_get_platdata(dev); u32 iobase; int region; int ret; debug("rtl8169: REALTEK RTL8169 @0x%x\n", iobase); switch (pplat->device) { case 0x8168: region = 2; break; default: region = 1; break; } dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0 + region * 4, &iobase); iobase &= ~0xf; priv->iobase = (int)dm_pci_mem_to_phys(dev, iobase); ret = rtl_init(priv->iobase, dev->name, plat->enetaddr); if (ret < 0) { printf(pr_fmt("failed to initialize card: %d\n"), ret); return ret; } return 0; }
static int pch7_get_gpio_base(struct udevice *dev, u32 *gbasep) { u32 base; /* * GPIO_BASE moved to its current offset with ICH6, but prior to * that it was unused (or undocumented). Check that it looks * okay: not all ones or zeros. * * Note we don't need check bit0 here, because the Tunnel Creek * GPIO base address register bit0 is reserved (read returns 0), * while on the Ivybridge the bit0 is used to indicate it is an * I/O space. */ dm_pci_read_config32(dev, GPIO_BASE, &base); if (base == 0x00000000 || base == 0xffffffff) { debug("%s: unexpected BASE value\n", __func__); return -ENODEV; } /* * Okay, I guess we're looking at the right device. The actual * GPIO registers are in the PCI device's I/O space, starting * at the offset that we just read. Bit 0 indicates that it's * an I/O address, not a memory address, so mask that off. */ *gbasep = base & 1 ? base & ~3 : base & ~15; return 0; }
static inline void me_read_dword_ptr(struct udevice *dev, void *ptr, int offset) { u32 dword; dm_pci_read_config32(dev, offset, &dword); memcpy(ptr, &dword, sizeof(dword)); }
static int bd82x6x_northbridge_early_init(struct udevice *dev) { const int chipset_type = SANDYBRIDGE_MOBILE; u32 capid0_a; u8 reg8; /* Device ID Override Enable should be done very early */ dm_pci_read_config32(dev, 0xe4, &capid0_a); if (capid0_a & (1 << 10)) { dm_pci_read_config8(dev, 0xf3, ®8); reg8 &= ~7; /* Clear 2:0 */ if (chipset_type == SANDYBRIDGE_MOBILE) reg8 |= 1; /* Set bit 0 */ dm_pci_write_config8(dev, 0xf3, reg8); } sandybridge_setup_northbridge_bars(dev); /* Device Enable */ dm_pci_write_config32(dev, DEVEN, DEVEN_HOST | DEVEN_IGD); return 0; }
static int pch9_get_spi_base(struct udevice *dev, ulong *sbasep) { uint32_t sbase_addr; dm_pci_read_config32(dev, SBASE_ADDR, &sbase_addr); *sbasep = sbase_addr & 0xfffffe00; return 0; }
static inline u32 sir_read(struct udevice *dev, int idx) { u32 data; dm_pci_write_config32(dev, SATA_SIRI, idx); dm_pci_read_config32(dev, SATA_SIRD, &data); return data; }
static int pch7_get_spi_base(struct udevice *dev, ulong *sbasep) { u32 rcba; dm_pci_read_config32(dev, PCH_RCBA, &rcba); /* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable */ rcba = rcba & 0xffffc000; *sbasep = rcba + 0x3020; return 0; }
static int pch9_get_io_base(struct udevice *dev, u32 *iobasep) { u32 base; dm_pci_read_config32(dev, IO_BASE, &base); if (base == 0x00000000 || base == 0xffffffff) { debug("%s: unexpected BASE value\n", __func__); return -ENODEV; } *iobasep = base & 1 ? base & ~3 : base & ~15; return 0; }
static unsigned long get_top_of_ram(struct udevice *dev) { /* * Base of DPR is top of usable DRAM below 4GiB. The register has * 1 MiB alignment and reports the TOP of the range, the base * must be calculated from the size in MiB in bits 11:4. */ u32 dpr, tom; dm_pci_read_config32(dev, DPR, &dpr); tom = dpr & ~((1 << 20) - 1); debug("dpt %08x tom %08x\n", dpr, tom); /* Subtract DMA Protected Range size if enabled */ if (dpr & DPR_EPM) tom -= (dpr & DPR_SIZE_MASK) << 16; return (unsigned long)tom; }
/** * sandybridge_init_iommu() - Set up IOMMU so that azalia can be used * * It is not obvious where these values come from. They may be undocumented. */ static void sandybridge_init_iommu(struct udevice *dev) { u32 capid0_a; dm_pci_read_config32(dev, 0xe4, &capid0_a); if (capid0_a & (1 << 23)) { log_debug("capid0_a not needed\n"); return; } /* setup BARs */ writel(IOMMU_BASE1 >> 32, MCHBAR_REG(0x5404)); writel(IOMMU_BASE1 | 1, MCHBAR_REG(0x5400)); writel(IOMMU_BASE2 >> 32, MCHBAR_REG(0x5414)); writel(IOMMU_BASE2 | 1, MCHBAR_REG(0x5410)); /* lock policies */ writel(0x80000000, IOMMU_BASE1 + 0xff0); /* Enable azalia sound */ writel(0x20000000, IOMMU_BASE2 + 0xff0); writel(0xa0000000, IOMMU_BASE2 + 0xff0); }
int intel_me_hsio_version(struct udevice *dev, uint16_t *versionp, uint16_t *checksump) { int count; u32 hsiover; struct me_hfs hfs; /* Query for HSIO version, overloads H_GS and HFS */ dm_pci_write_config32(dev, PCI_ME_H_GS, ME_HSIO_MESSAGE | ME_HSIO_CMD_GETHSIOVER); /* Must wait for ME acknowledgement */ for (count = ME_RETRY; count > 0; --count) { me_read_dword_ptr(dev, &hfs, PCI_ME_HFS); if (hfs.bios_msg_ack) break; udelay(ME_DELAY); } if (!count) { debug("ERROR: ME failed to respond\n"); return -ETIMEDOUT; } /* HSIO version should be in HFS_5 */ dm_pci_read_config32(dev, PCI_ME_HFS5, &hsiover); *versionp = hsiover >> 16; *checksump = hsiover & 0xffff; debug("ME: HSIO Version : %d (CRC 0x%04x)\n", *versionp, *checksump); /* Reset registers to normal behavior */ dm_pci_write_config32(dev, PCI_ME_H_GS, ME_HSIO_MESSAGE | ME_HSIO_CMD_GETHSIOVER); return 0; }
static void xhci_pci_init(struct udevice *dev, struct xhci_hccr **ret_hccr, struct xhci_hcor **ret_hcor) { struct xhci_hccr *hccr; struct xhci_hcor *hcor; u32 cmd; hccr = (struct xhci_hccr *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); hcor = (struct xhci_hcor *)((uintptr_t) hccr + HC_LENGTH(xhci_readl(&hccr->cr_capbase))); debug("XHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n", (u32)hccr, (u32)hcor, (u32)HC_LENGTH(xhci_readl(&hccr->cr_capbase))); *ret_hccr = hccr; *ret_hcor = hcor; /* enable busmaster */ dm_pci_read_config32(dev, PCI_COMMAND, &cmd); cmd |= PCI_COMMAND_MASTER; dm_pci_write_config32(dev, PCI_COMMAND, cmd); }
int pci_bar_show(struct udevice *dev) { u8 header_type; int bar_cnt, bar_id, mem_type; bool is_64, is_io; u32 base_low, base_high; u32 size_low, size_high; u64 base, size; u32 reg_addr; int prefetchable; dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type); if (header_type == PCI_HEADER_TYPE_CARDBUS) { printf("CardBus doesn't support BARs\n"); return -ENOSYS; } bar_cnt = (header_type == PCI_HEADER_TYPE_NORMAL) ? 6 : 2; printf("ID Base Size Width Type\n"); printf("----------------------------------------------------------\n"); bar_id = 0; reg_addr = PCI_BASE_ADDRESS_0; while (bar_cnt) { dm_pci_read_config32(dev, reg_addr, &base_low); dm_pci_write_config32(dev, reg_addr, 0xffffffff); dm_pci_read_config32(dev, reg_addr, &size_low); dm_pci_write_config32(dev, reg_addr, base_low); reg_addr += 4; base = base_low & ~0xf; size = size_low & ~0xf; base_high = 0x0; size_high = 0xffffffff; is_64 = 0; prefetchable = base_low & PCI_BASE_ADDRESS_MEM_PREFETCH; is_io = base_low & PCI_BASE_ADDRESS_SPACE_IO; mem_type = base_low & PCI_BASE_ADDRESS_MEM_TYPE_MASK; if (mem_type == PCI_BASE_ADDRESS_MEM_TYPE_64) { dm_pci_read_config32(dev, reg_addr, &base_high); dm_pci_write_config32(dev, reg_addr, 0xffffffff); dm_pci_read_config32(dev, reg_addr, &size_high); dm_pci_write_config32(dev, reg_addr, base_high); bar_cnt--; reg_addr += 4; is_64 = 1; } base = base | ((u64)base_high << 32); size = size | ((u64)size_high << 32); if ((!is_64 && size_low) || (is_64 && size)) { size = ~size + 1; printf(" %d %#016llx %#016llx %d %s %s\n", bar_id, (unsigned long long)base, (unsigned long long)size, is_64 ? 64 : 32, is_io ? "I/O" : "MEM", prefetchable ? "Prefetchable" : ""); } bar_id++; bar_cnt--; } return 0; }
/** * sdram_find() - Find available memory * * This is a bit complicated since on x86 there are system memory holes all * over the place. We create a list of available memory blocks * * @dev: Northbridge device */ static int sdram_find(struct udevice *dev) { struct memory_info *info = &gd->arch.meminfo; uint32_t tseg_base, uma_size, tolud; uint64_t tom, me_base, touud; uint64_t uma_memory_base = 0; uint64_t uma_memory_size; unsigned long long tomk; uint16_t ggc; u32 val; /* Total Memory 2GB example: * * 00000000 0000MB-1992MB 1992MB RAM (writeback) * 7c800000 1992MB-2000MB 8MB TSEG (SMRR) * 7d000000 2000MB-2002MB 2MB GFX GTT (uncached) * 7d200000 2002MB-2034MB 32MB GFX UMA (uncached) * 7f200000 2034MB TOLUD * 7f800000 2040MB MEBASE * 7f800000 2040MB-2048MB 8MB ME UMA (uncached) * 80000000 2048MB TOM * 100000000 4096MB-4102MB 6MB RAM (writeback) * * Total Memory 4GB example: * * 00000000 0000MB-2768MB 2768MB RAM (writeback) * ad000000 2768MB-2776MB 8MB TSEG (SMRR) * ad800000 2776MB-2778MB 2MB GFX GTT (uncached) * ada00000 2778MB-2810MB 32MB GFX UMA (uncached) * afa00000 2810MB TOLUD * ff800000 4088MB MEBASE * ff800000 4088MB-4096MB 8MB ME UMA (uncached) * 100000000 4096MB TOM * 100000000 4096MB-5374MB 1278MB RAM (writeback) * 14fe00000 5368MB TOUUD */ /* Top of Upper Usable DRAM, including remap */ dm_pci_read_config32(dev, TOUUD + 4, &val); touud = (uint64_t)val << 32; dm_pci_read_config32(dev, TOUUD, &val); touud |= val; /* Top of Lower Usable DRAM */ dm_pci_read_config32(dev, TOLUD, &tolud); /* Top of Memory - does not account for any UMA */ dm_pci_read_config32(dev, 0xa4, &val); tom = (uint64_t)val << 32; dm_pci_read_config32(dev, 0xa0, &val); tom |= val; debug("TOUUD %llx TOLUD %08x TOM %llx\n", touud, tolud, tom); /* ME UMA needs excluding if total memory <4GB */ dm_pci_read_config32(dev, 0x74, &val); me_base = (uint64_t)val << 32; dm_pci_read_config32(dev, 0x70, &val); me_base |= val; debug("MEBASE %llx\n", me_base); /* TODO: Get rid of all this shifting by 10 bits */ tomk = tolud >> 10; if (me_base == tolud) { /* ME is from MEBASE-TOM */ uma_size = (tom - me_base) >> 10; /* Increment TOLUD to account for ME as RAM */ tolud += uma_size << 10; /* UMA starts at old TOLUD */ uma_memory_base = tomk * 1024ULL; uma_memory_size = uma_size * 1024ULL; debug("ME UMA base %llx size %uM\n", me_base, uma_size >> 10); }
void dm_pciauto_setup_device(struct udevice *dev, int bars_num, struct pci_region *mem, struct pci_region *prefetch, struct pci_region *io, bool enum_only) { u32 bar_response; pci_size_t bar_size; u16 cmdstat = 0; int bar, bar_nr = 0; u8 header_type; int rom_addr; pci_addr_t bar_value; struct pci_region *bar_res; int found_mem64 = 0; u16 class; dm_pci_read_config16(dev, PCI_COMMAND, &cmdstat); cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | PCI_COMMAND_MASTER; for (bar = PCI_BASE_ADDRESS_0; bar < PCI_BASE_ADDRESS_0 + (bars_num * 4); bar += 4) { /* Tickle the BAR and get the response */ if (!enum_only) dm_pci_write_config32(dev, bar, 0xffffffff); dm_pci_read_config32(dev, bar, &bar_response); /* If BAR is not implemented go to the next BAR */ if (!bar_response) continue; found_mem64 = 0; /* Check the BAR type and set our address mask */ if (bar_response & PCI_BASE_ADDRESS_SPACE) { bar_size = ((~(bar_response & PCI_BASE_ADDRESS_IO_MASK)) & 0xffff) + 1; if (!enum_only) bar_res = io; debug("PCI Autoconfig: BAR %d, I/O, size=0x%llx, ", bar_nr, (unsigned long long)bar_size); } else { if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) { u32 bar_response_upper; u64 bar64; if (!enum_only) { dm_pci_write_config32(dev, bar + 4, 0xffffffff); } dm_pci_read_config32(dev, bar + 4, &bar_response_upper); bar64 = ((u64)bar_response_upper << 32) | bar_response; bar_size = ~(bar64 & PCI_BASE_ADDRESS_MEM_MASK) + 1; if (!enum_only) found_mem64 = 1; } else { bar_size = (u32)(~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1); } if (!enum_only) { if (prefetch && (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH)) { bar_res = prefetch; } else { bar_res = mem; } } debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ", bar_nr, bar_res == prefetch ? "Prf" : "Mem", (unsigned long long)bar_size); } if (!enum_only && pciauto_region_allocate(bar_res, bar_size, &bar_value) == 0) { /* Write it out and update our limit */ dm_pci_write_config32(dev, bar, (u32)bar_value); if (found_mem64) { bar += 4; #ifdef CONFIG_SYS_PCI_64BIT dm_pci_write_config32(dev, bar, (u32)(bar_value >> 32)); #else /* * If we are a 64-bit decoder then increment to * the upper 32 bits of the bar and force it to * locate in the lower 4GB of memory. */ dm_pci_write_config32(dev, bar, 0x00000000); #endif } } cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ? PCI_COMMAND_IO : PCI_COMMAND_MEMORY; debug("\n"); bar_nr++; }
static int create_pirq_routing_table(struct udevice *dev) { struct irq_router *priv = dev_get_priv(dev); const void *blob = gd->fdt_blob; int node; int len, count; const u32 *cell; struct irq_routing_table *rt; struct irq_info *slot, *slot_base; int irq_entries = 0; int i; int ret; node = dev->of_offset; /* extract the bdf from fdt_pci_addr */ priv->bdf = dm_pci_get_bdf(dev->parent); ret = fdt_stringlist_search(blob, node, "intel,pirq-config", "pci"); if (!ret) { priv->config = PIRQ_VIA_PCI; } else { ret = fdt_stringlist_search(blob, node, "intel,pirq-config", "ibase"); if (!ret) priv->config = PIRQ_VIA_IBASE; else return -EINVAL; } ret = fdtdec_get_int(blob, node, "intel,pirq-link", -1); if (ret == -1) return ret; priv->link_base = ret; priv->irq_mask = fdtdec_get_int(blob, node, "intel,pirq-mask", PIRQ_BITMAP); if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { /* Reserve IRQ9 for SCI */ priv->irq_mask &= ~(1 << 9); } if (priv->config == PIRQ_VIA_IBASE) { int ibase_off; ibase_off = fdtdec_get_int(blob, node, "intel,ibase-offset", 0); if (!ibase_off) return -EINVAL; /* * Here we assume that the IBASE register has already been * properly configured by U-Boot before. * * By 'valid' we mean: * 1) a valid memory space carved within system memory space * assigned to IBASE register block. * 2) memory range decoding is enabled. * Hence we don't do any santify test here. */ dm_pci_read_config32(dev->parent, ibase_off, &priv->ibase); priv->ibase &= ~0xf; } priv->actl_8bit = fdtdec_get_bool(blob, node, "intel,actl-8bit"); priv->actl_addr = fdtdec_get_int(blob, node, "intel,actl-addr", 0); cell = fdt_getprop(blob, node, "intel,pirq-routing", &len); if (!cell || len % sizeof(struct pirq_routing)) return -EINVAL; count = len / sizeof(struct pirq_routing); rt = calloc(1, sizeof(struct irq_routing_table)); if (!rt) return -ENOMEM; /* Populate the PIRQ table fields */ rt->signature = PIRQ_SIGNATURE; rt->version = PIRQ_VERSION; rt->rtr_bus = PCI_BUS(priv->bdf); rt->rtr_devfn = (PCI_DEV(priv->bdf) << 3) | PCI_FUNC(priv->bdf); rt->rtr_vendor = PCI_VENDOR_ID_INTEL; rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31; slot_base = rt->slots; /* Now fill in the irq_info entries in the PIRQ table */ for (i = 0; i < count; i++, cell += sizeof(struct pirq_routing) / sizeof(u32)) { struct pirq_routing pr; pr.bdf = fdt_addr_to_cpu(cell[0]); pr.pin = fdt_addr_to_cpu(cell[1]); pr.pirq = fdt_addr_to_cpu(cell[2]); debug("irq_info %d: b.d.f %x.%x.%x INT%c PIRQ%c\n", i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), PCI_FUNC(pr.bdf), 'A' + pr.pin - 1, 'A' + pr.pirq); slot = check_dup_entry(slot_base, irq_entries, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf)); if (slot) { debug("found entry for bus %d device %d, ", PCI_BUS(pr.bdf), PCI_DEV(pr.bdf)); if (slot->irq[pr.pin - 1].link) { debug("skipping\n"); /* * Sanity test on the routed PIRQ pin * * If they don't match, show a warning to tell * there might be something wrong with the PIRQ * routing information in the device tree. */ if (slot->irq[pr.pin - 1].link != LINK_N2V(pr.pirq, priv->link_base)) debug("WARNING: Inconsistent PIRQ routing information\n"); continue; } } else { slot = slot_base + irq_entries++; } debug("writing INT%c\n", 'A' + pr.pin - 1); fill_irq_info(priv, slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin, pr.pirq); } rt->size = irq_entries * sizeof(struct irq_info) + 32; /* Fix up the table checksum */ rt->checksum = table_compute_checksum(rt, rt->size); pirq_routing_table = rt; return 0; }