Beispiel #1
0
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
}
Beispiel #2
0
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
}
Beispiel #3
0
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();
}
Beispiel #4
0
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);
    }
}
Beispiel #5
0
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);
}
Beispiel #6
0
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));
}
Beispiel #8
0
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);
}
Beispiel #9
0
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");
}
Beispiel #10
0
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);
}
Beispiel #11
0
/* 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);
}
Beispiel #12
0
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;
}
Beispiel #13
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;
}
Beispiel #14
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;
}