static void pch_enable_serial_irqs(pci_dev_t dev) { u32 value; /* Set packet length and toggle silent mode bit for one frame. */ value = (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0); #ifdef CONFIG_SERIRQ_CONTINUOUS_MODE x86_pci_write_config8(dev, SERIRQ_CNTL, value); #else x86_pci_write_config8(dev, SERIRQ_CNTL, value | (1 << 6)); #endif }
static void pch_lock_smm(pci_dev_t dev) { #if TEST_SMM_FLASH_LOCKDOWN u8 reg8; #endif if (acpi_slp_type != 3) { #if ENABLE_ACPI_MODE_IN_COREBOOT debug("Enabling ACPI via APMC:\n"); outb(0xe1, 0xb2); /* Enable ACPI mode */ debug("done.\n"); #else debug("Disabling ACPI via APMC:\n"); outb(0x1e, 0xb2); /* Disable ACPI mode */ debug("done.\n"); #endif } /* Don't allow evil boot loaders, kernels, or * userspace applications to deceive us: */ smm_lock(); #if TEST_SMM_FLASH_LOCKDOWN /* Now try this: */ debug("Locking BIOS to RO... "); reg8 = x86_pci_read_config8(dev, 0xdc); /* BIOS_CNTL */ debug(" BLE: %s; BWE: %s\n", (reg8 & 2) ? "on" : "off", (reg8 & 1) ? "rw" : "ro"); reg8 &= ~(1 << 0); /* clear BIOSWE */ x86_pci_write_config8(dev, 0xdc, reg8); reg8 |= (1 << 1); /* set BLE */ x86_pci_write_config8(dev, 0xdc, reg8); debug("ok.\n"); reg8 = x86_pci_read_config8(dev, 0xdc); /* BIOS_CNTL */ debug(" BLE: %s; BWE: %s\n", (reg8 & 2) ? "on" : "off", (reg8 & 1) ? "rw" : "ro"); debug("Writing:\n"); writeb(0, 0xfff00000); debug("Testing:\n"); reg8 |= (1 << 0); /* set BIOSWE */ x86_pci_write_config8(dev, 0xdc, reg8); reg8 = x86_pci_read_config8(dev, 0xdc); /* BIOS_CNTL */ debug(" BLE: %s; BWE: %s\n", (reg8 & 2) ? "on" : "off", (reg8 & 1) ? "rw" : "ro"); debug("Done.\n"); #endif }
static void pch_rtc_init(pci_dev_t dev) { int rtc_failed; u8 reg8; reg8 = x86_pci_read_config8(dev, GEN_PMCON_3); rtc_failed = reg8 & RTC_BATTERY_DEAD; if (rtc_failed) { reg8 &= ~RTC_BATTERY_DEAD; x86_pci_write_config8(dev, GEN_PMCON_3, reg8); } debug("rtc_failed = 0x%x\n", rtc_failed); #if CONFIG_HAVE_ACPI_RESUME /* Avoid clearing pending interrupts and resetting the RTC control * register in the resume path because the Linux kernel relies on * this to know if it should restart the RTC timerqueue if the wake * was due to the RTC alarm. */ if (acpi_get_slp_type() == 3) return; #endif /* TODO: Handle power failure */ if (rtc_failed) printf("RTC power failed\n"); rtc_init(); }
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); } }
static void pch_disable_smm_only_flashing(pci_dev_t dev) { u8 reg8; debug("Enabling BIOS updates outside of SMM... "); reg8 = x86_pci_read_config8(dev, 0xdc); /* BIOS_CNTL */ reg8 &= ~(1 << 5); x86_pci_write_config8(dev, 0xdc, reg8); }
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. */ device = x86_pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID); 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++) x86_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. */ x86_pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN); x86_pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN); /* Enable I/O APIC */ xbcs = x86_pci_read_config16(PIIX_ISA, XBCS); xbcs |= APIC_EN; x86_pci_write_config16(PIIX_ISA, XBCS, xbcs); enable_pm_piix(); } else { /* Configure PCIe ECAM base address */ x86_pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR, CONFIG_PCIE_ECAM_BASE | BAR_EN); enable_pm_ich9(); } qemu_fwcfg_init(); }
void pirq_assign_irq(int link, u8 irq) { int base = irq_router.link_base; /* IRQ# 0/1/2/8/13 are reserved */ if (irq < 3 || irq == 8 || irq == 13) return; if (irq_router.config == PIRQ_VIA_PCI) x86_pci_write_config8(irq_router.bdf, LINK_N2V(link, base), irq); else writeb(irq, irq_router.ibase + LINK_N2V(link, base)); }
static void pch_fixups(pci_dev_t dev) { u8 gen_pmcon_2; /* Indicate DRAM init done for MRC S3 to know it can resume */ gen_pmcon_2 = x86_pci_read_config8(dev, GEN_PMCON_2); gen_pmcon_2 |= (1 << 7); x86_pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2); /* Enable DMI ASPM in the PCH */ clrbits_le32(RCB_REG(0x2304), 1 << 10); setbits_le32(RCB_REG(0x21a4), (1 << 11) | (1 << 10)); setbits_le32(RCB_REG(0x21a8), 0x3); }
static void pch_rtc_init(pci_dev_t dev) { int rtc_failed; u8 reg8; reg8 = x86_pci_read_config8(dev, GEN_PMCON_3); rtc_failed = reg8 & RTC_BATTERY_DEAD; if (rtc_failed) { reg8 &= ~RTC_BATTERY_DEAD; x86_pci_write_config8(dev, GEN_PMCON_3, reg8); } debug("rtc_failed = 0x%x\n", rtc_failed); /* TODO: Handle power failure */ if (rtc_failed) printf("RTC power failed\n"); }
static void enable_pm_piix(void) { u8 en; u16 cmd; /* Set the PM I/O base */ x86_pci_write_config32(PIIX_PM, PMBA, CONFIG_ACPI_PM1_BASE | 1); /* Enable access to the PM I/O space */ cmd = x86_pci_read_config16(PIIX_PM, PCI_COMMAND); cmd |= PCI_COMMAND_IO; x86_pci_write_config16(PIIX_PM, PCI_COMMAND, cmd); /* PM I/O Space Enable (PMIOSE) */ en = x86_pci_read_config8(PIIX_PM, PMREGMISC); en |= PMIOSE; x86_pci_write_config8(PIIX_PM, PMREGMISC, en); }
/* PantherPoint PCH Power Management init */ static void ppt_pm_init(pci_dev_t dev) { debug("PantherPoint PM init\n"); x86_pci_write_config8(dev, 0xa9, 0x47); setbits_le32(RCB_REG(0x2238), 1 << 0); setbits_le32(RCB_REG(0x228c), 1 << 0); setbits_le16(RCB_REG(0x1100), (1 << 13) | (1 << 14)); setbits_le16(RCB_REG(0x0900), 1 << 14); writel(0xc03b8400, RCB_REG(0x2304)); setbits_le32(RCB_REG(0x2314), (1 << 5) | (1 << 18)); setbits_le32(RCB_REG(0x2320), (1 << 15) | (1 << 1)); clrsetbits_le32(RCB_REG(0x3314), 0x1f, 0xf); writel(0x054f0000, RCB_REG(0x3318)); writel(0x04000000, RCB_REG(0x3324)); setbits_le32(RCB_REG(0x3340), 0xfffff); setbits_le32(RCB_REG(0x3344), (1 << 1) | (1 << 0)); writel(0x0001c000, RCB_REG(0x3360)); writel(0x00061100, RCB_REG(0x3368)); writel(0x7f8fdfff, RCB_REG(0x3378)); writel(0x000003fd, RCB_REG(0x337c)); writel(0x00001000, RCB_REG(0x3388)); writel(0x0001c000, RCB_REG(0x3390)); writel(0x00000800, RCB_REG(0x33a0)); writel(0x00001000, RCB_REG(0x33b0)); writel(0x00093900, RCB_REG(0x33c0)); writel(0x24653002, RCB_REG(0x33cc)); writel(0x067388fe, RCB_REG(0x33d0)); clrsetbits_le32(RCB_REG(0x33d4), 0x0fff0fff, 0x00670060); writel(0x01010000, RCB_REG(0x3a28)); writel(0x01010404, RCB_REG(0x3a2c)); writel(0x01040000, RCB_REG(0x3a80)); clrsetbits_le32(RCB_REG(0x3a84), 0x0000ffff, 0x00001001); /* SATA 2/3 disabled */ setbits_le32(RCB_REG(0x3a84), 1 << 24); /* SATA 4/5 disabled */ setbits_le32(RCB_REG(0x3a88), 1 << 0); writel(0x00000001, RCB_REG(0x3a6c)); clrsetbits_le32(RCB_REG(0x2344), 0xff0000ff, 0xff00000c); clrsetbits_le32(RCB_REG(0x80c), 0xff << 20, 0x11 << 20); setbits_le32(RCB_REG(0x33a4), (1 << 0)); writel(0, RCB_REG(0x33c8)); setbits_le32(RCB_REG(0x21b0), 0xf); }
static int pch_enable_apic(pci_dev_t dev) { u32 reg32; int i; /* Enable ACPI I/O and power management. Set SCI IRQ to IRQ9 */ x86_pci_write_config8(dev, ACPI_CNTL, 0x80); writel(0, IO_APIC_INDEX); writel(1 << 25, IO_APIC_DATA); /* affirm full set of redirection table entries ("write once") */ writel(1, IO_APIC_INDEX); reg32 = readl(IO_APIC_DATA); writel(1, IO_APIC_INDEX); writel(reg32, IO_APIC_DATA); writel(0, IO_APIC_INDEX); reg32 = readl(IO_APIC_DATA); debug("PCH APIC ID = %x\n", (reg32 >> 24) & 0x0f); if (reg32 != (1 << 25)) { printf("APIC Error - cannot write to registers\n"); return -EPERM; } debug("Dumping IOAPIC registers\n"); for (i = 0; i < 3; i++) { writel(i, IO_APIC_INDEX); debug(" reg 0x%04x:", i); reg32 = readl(IO_APIC_DATA); debug(" 0x%08x\n", reg32); } /* Select Boot Configuration register. */ writel(3, IO_APIC_INDEX); /* Use Processor System Bus to deliver interrupts. */ writel(1, IO_APIC_DATA); return 0; }
static int pch_pirq_init(const void *blob, int node, pci_dev_t dev) { uint8_t route[8], *ptr; if (fdtdec_get_byte_array(blob, node, "intel,pirq-routing", route, sizeof(route))) return -EINVAL; ptr = route; x86_pci_write_config8(dev, PIRQA_ROUT, *ptr++); x86_pci_write_config8(dev, PIRQB_ROUT, *ptr++); x86_pci_write_config8(dev, PIRQC_ROUT, *ptr++); x86_pci_write_config8(dev, PIRQD_ROUT, *ptr++); x86_pci_write_config8(dev, PIRQE_ROUT, *ptr++); x86_pci_write_config8(dev, PIRQF_ROUT, *ptr++); x86_pci_write_config8(dev, PIRQG_ROUT, *ptr++); x86_pci_write_config8(dev, PIRQH_ROUT, *ptr++); /* * TODO([email protected]): U-Boot does not set up the interrupts * here. It's unclear if it is needed */ return 0; }
int board_pci_post_scan(struct pci_controller *hose) { int ret = 0; u16 device, xbcs; int pam, i; pci_dev_t vga; ulong start; /* * 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. */ device = x86_pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID); 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++) x86_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. */ x86_pci_write_config16(PIIX_IDE, IDE0_TIM, IDE_DECODE_EN); x86_pci_write_config16(PIIX_IDE, IDE1_TIM, IDE_DECODE_EN); /* Enable I/O APIC */ xbcs = x86_pci_read_config16(PIIX_ISA, XBCS); xbcs |= APIC_EN; x86_pci_write_config16(PIIX_ISA, XBCS, xbcs); } else { /* Configure PCIe ECAM base address */ x86_pci_write_config32(PCI_BDF(0, 0, 0), PCIEX_BAR, CONFIG_PCIE_ECAM_BASE | BAR_EN); } /* * QEMU emulated graphic card shows in the PCI configuration space with * PCI vendor id and device id as an artificial pair 0x1234:0x1111. * It is on PCI bus 0, function 0, but device number is not consistent * for the two x86 targets it supports. For i440FX and PIIX chipset * board, it shows as device 2, while for Q35 and ICH9 chipset board, * it shows as device 1. */ vga = i440fx ? I440FX_VGA : Q35_VGA; start = get_timer(0); ret = pci_run_vga_bios(vga, NULL, PCI_ROM_USE_NATIVE); debug("BIOS ran in %lums\n", get_timer(start)); return ret; }