static void lpc_init(struct device *dev) { printk(BIOS_DEBUG, "i82801ix: lpc_init\n"); /* Set the value for PCI command register. */ pci_write_config16(dev, PCI_COMMAND, 0x000f); /* IO APIC initialization. */ i82801ix_enable_apic(dev); i82801ix_enable_serial_irqs(dev); /* Setup the PIRQ. */ i82801ix_pirq_init(dev); /* Setup power options. */ i82801ix_power_options(dev); /* Configure Cx state registers */ if (LPC_IS_MOBILE(dev)) i82801ix_configure_cstates(dev); /* Initialize the real time clock. */ i82801ix_rtc_init(dev); /* Initialize ISA DMA. */ isa_dma_init(); /* Initialize the High Precision Event Timers, if present. */ enable_hpet(); /* Initialize Clock Gating */ enable_clock_gating(); setup_i8259(); /* The OS should do this? */ /* Interrupt 9 should be level triggered (SCI) */ i8259_configure_irq_trigger(9, 1); #if CONFIG_HAVE_SMI_HANDLER i82801ix_lock_smm(dev); #endif }
static void i82801ix_pcie_init(const config_t *const info) { device_t pciePort[6]; int i, slot_number = 1; /* Reserve slot number 0 for nb's PEG. */ u32 reg32; /* PCIe - BIOS must program... */ for (i = 0; i < 6; ++i) { pciePort[i] = dev_find_slot(0, PCI_DEVFN(0x1c, i)); if (!pciePort[i]) { printk(BIOS_EMERG, "PCIe port 00:1c.%x", i); die(" is not listed in devicetree.\n"); } #if CONFIG_MMCONF_SUPPORT reg32 = pci_mmio_read_config32(pciePort[i], 0x300); pci_mmio_write_config32(pciePort[i], 0x300, reg32 | (1 << 21)); pci_mmio_write_config8(pciePort[i], 0x324, 0x40); #else #error "MMIO needed for ICH9 PCIe" #endif } if (LPC_IS_MOBILE(dev_find_slot(0, PCI_DEVFN(0x1f, 0)))) { for (i = 0; i < 6; ++i) { if (pciePort[i]->enabled) { reg32 = pci_read_config32(pciePort[i], 0xe8); reg32 |= 1; pci_write_config32(pciePort[i], 0xe8, reg32); } } } for (i = 5; (i >= 0) && !pciePort[i]->enabled; --i) { /* Only for the top disabled ports. */ #if CONFIG_MMCONF_SUPPORT reg32 = pci_mmio_read_config32(pciePort[i], 0x300); reg32 |= 0x3 << 16; pci_mmio_write_config32(pciePort[i], 0x300, reg32); #else #error "MMIO needed for ICH9 PCIe" #endif } /* Set slot implemented, slot number and slot power limits. */ for (i = 0; i < 6; ++i) { const device_t dev = pciePort[i]; u32 xcap = pci_read_config32(dev, D28Fx_XCAP); if (info->pcie_slot_implemented & (1 << i)) xcap |= PCI_EXP_FLAGS_SLOT; else xcap &= ~PCI_EXP_FLAGS_SLOT; pci_write_config32(dev, D28Fx_XCAP, xcap); if (info->pcie_slot_implemented & (1 << i)) { u32 slcap = pci_read_config32(dev, D28Fx_SLCAP); slcap &= ~(0x1fff << 19); slcap |= (slot_number++ << 19); slcap &= ~(0x0003 << 16); slcap |= (info->pcie_power_limits[i].scale << 16); slcap &= ~(0x00ff << 7); slcap |= (info->pcie_power_limits[i].value << 7); pci_write_config32(dev, D28Fx_SLCAP, slcap); } } /* Lock R/WO ASPM support bits. */ for (i = 0; i < 6; ++i) { reg32 = pci_read_config32(pciePort[i], 0x4c); pci_write_config32(pciePort[i], 0x4c, reg32); } }
static void setup_aspm(const stepping_t stepping, const int peg_enabled) { u32 tmp32; const device_t pciex = PCI_DEV(0, 1, 0); /* Prerequisites for ASPM: */ if (peg_enabled) { tmp32 = pci_read_config32(pciex, 0x200) | (3 << 13); pci_write_config32(pciex, 0x200, tmp32); tmp32 = pci_read_config32(pciex, 0x0f0); tmp32 &= ~((1 << 27) | (1 << 26)); pci_write_config32(pciex, 0x0f0, tmp32); tmp32 = pci_read_config32(pciex, 0x0f0) | (3 << 24); pci_write_config32(pciex, 0x0f0, tmp32); tmp32 = pci_read_config32(pciex, 0x0f4) & ~(1 << 4); pci_write_config32(pciex, 0x0f4, tmp32); tmp32 = pci_read_config32(pciex, 0x0fc) | (1 << 0); pci_write_config32(pciex, 0x0fc, tmp32); tmp32 = pci_read_config32(pciex, 0x0fc) | (1 << 1); pci_write_config32(pciex, 0x0fc, tmp32); tmp32 = pci_read_config32(pciex, 0x0fc) | (1 << 4); pci_write_config32(pciex, 0x0fc, tmp32); tmp32 = pci_read_config32(pciex, 0x0fc) & ~(7 << 5); pci_write_config32(pciex, 0x0fc, tmp32); /* Set L0s, L1 supported in LCTL? */ tmp32 = pci_read_config32(pciex, 0x0b0) | (3 << 0); pci_write_config32(pciex, 0x0b0, tmp32); tmp32 = pci_read_config32(pciex, 0x0f0) | (3 << 24); pci_write_config32(pciex, 0x0f0, tmp32); tmp32 = pci_read_config32(pciex, 0x0f0); if ((stepping >= STEPPING_B0) && (stepping <= STEPPING_B1)) tmp32 |= (1 << 31); else if (stepping >= STEPPING_B2) tmp32 &= ~(1 << 31); pci_write_config32(pciex, 0x0f0, tmp32); tmp32 = pci_read_config32(pciex, 0x0fc); if ((stepping >= STEPPING_B0) && (stepping <= STEPPING_B1)) tmp32 |= (1 << 10); else if (stepping >= STEPPING_B2) tmp32 &= ~(1 << 10); pci_write_config32(pciex, 0x0fc, tmp32); tmp32 = pci_read_config32(pciex, 0x0fc); if (stepping >= STEPPING_B2) tmp32 |= (1 << 14); pci_write_config32(pciex, 0x0fc, tmp32); tmp32 = pci_read_config32(pciex, 0x0fc); if (stepping >= STEPPING_B1) tmp32 &= ~(1 << 13); pci_write_config32(pciex, 0x0fc, tmp32); } DMIBAR8 (0x0e1c) |= (1 << 0); DMIBAR16(0x0f00) |= (3 << 8); DMIBAR16(0x0f00) |= (7 << 3); DMIBAR32(0x0f14) &= ~(1 << 17); DMIBAR16(0x0e1c) &= ~(1 << 8); if (stepping >= STEPPING_B0) { DMIBAR32(0x0e28 + 4) = (DMIBAR32(0x0e28 + 4) & ~(0xf << (52 - 32))) | (0xd << (52 - 32)); DMIBAR32(0x0e2c) = 0x88d07333; } if (peg_enabled) { tmp32 = pci_read_config32(pciex, 0xa08) & ~(1 << 15); pci_write_config32(pciex, 0xa08, tmp32); tmp32 = pci_read_config32(pciex, 0xa84) | (1 << 8); pci_write_config32(pciex, 0xa84, tmp32); tmp32 = pci_read_config32(pciex, 0xb14) & ~(1 << 17); pci_write_config32(pciex, 0xb14, tmp32); tmp32 = pci_read_config32(pciex, 0xb00) | (3 << 8); pci_write_config32(pciex, 0xb00, tmp32); tmp32 = pci_read_config32(pciex, 0xb00) | (7 << 3); pci_write_config32(pciex, 0xb00, tmp32); tmp32 = pci_read_config32(pciex, 0xa84) & ~(1 << 8); pci_write_config32(pciex, 0xa84, tmp32); tmp32 = pci_read_config32(pciex, 0xa84) | (1 << 8); pci_write_config32(pciex, 0xa84, tmp32); tmp32 = pci_read_config32(pciex, 0xb04); tmp32 = (tmp32 & ~(0x1f << 23)) | (0xe << 23); pci_write_config32(pciex, 0xb04, tmp32); tmp32 = pci_read_config32(pciex, 0xb04); tmp32 |= (1 << 31); pci_write_config32(pciex, 0xb04, tmp32); tmp32 = pci_read_config32(pciex, 0xb04); tmp32 = (tmp32 & ~(0x03 << 29)) | (0x1 << 29); pci_write_config32(pciex, 0xb04, tmp32); } /*\ Setup ASPM on DMI \*/ /* Exit latencies should be checked to be supported by the endpoint (ICH), but ICH doesn't give any limits. */ if (LPC_IS_MOBILE(PCI_DEV(0, 0x1f, 0))) DMIBAR8(0x88) |= (3 << 0); // enable ASPM L0s, L1 (write-once) else DMIBAR8(0x88) |= (1 << 0); // enable ASPM L0s (write-once) /* timing */ DMIBAR32(0x84) = (DMIBAR32(0x84) & ~(63 << 12)) | (2 << 12) | (2 << 15); DMIBAR8(0x208 + 3) = 0; DMIBAR32(0x208) &= ~(3 << 20); /*\ Setup ASPM on PEG \*/ /* * Maybe we just have to advertise ASPM through LCAP[11:10] * (LCAP[17:15] == 010b is the default, will be locked, as it's R/WO), * set 0x208[31:24,23:22] to zero, 0x224[24:21] = 1 and let the * generic ASPM code do the rest? – Nico */ /* TODO: Prepare PEG for ASPM. */ }