Exemplo n.º 1
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
}
Exemplo n.º 2
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();
}
Exemplo n.º 3
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);
    }
}
Exemplo n.º 4
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);
}
Exemplo n.º 5
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);
}
Exemplo n.º 6
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");
}
Exemplo n.º 7
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);
}
Exemplo n.º 8
0
bool pirq_check_irq_routed(int link, u8 irq)
{
	u8 pirq;
	int base = irq_router.link_base;

	if (irq_router.config == PIRQ_VIA_PCI)
		pirq = x86_pci_read_config8(irq_router.bdf,
					    LINK_N2V(link, base));
	else
		pirq = readb(irq_router.ibase + LINK_N2V(link, base));

	pirq &= 0xf;

	/* IRQ# 0/1/2/8/13 are reserved */
	if (pirq < 3 || pirq == 8 || pirq == 13)
		return false;

	return pirq == irq ? true : false;
}
Exemplo n.º 9
0
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;
}
static int gpio_ich6_get_base(unsigned long base)
{
	pci_dev_t pci_dev;			/* handle for 0:1f:0 */
	u8 tmpbyte;
	u16 tmpword;
	u32 tmplong;

	/* Where should it be? */
	pci_dev = PCI_BDF(0, 0x1f, 0);

	/* Is the device present? */
	tmpword = x86_pci_read_config16(pci_dev, PCI_VENDOR_ID);
	if (tmpword != PCI_VENDOR_ID_INTEL) {
		debug("%s: wrong VendorID %x\n", __func__, tmpword);
		return -ENODEV;
	}

	tmpword = x86_pci_read_config16(pci_dev, PCI_DEVICE_ID);
	debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword);
	/*
	 * We'd like to validate the Device ID too, but pretty much any
	 * value is either a) correct with slight differences, or b)
	 * correct but undocumented. We'll have to check a bunch of other
	 * things instead...
	 */

	/* I/O should already be enabled (it's a RO bit). */
	tmpword = x86_pci_read_config16(pci_dev, PCI_COMMAND);
	if (!(tmpword & PCI_COMMAND_IO)) {
		debug("%s: device IO not enabled\n", __func__);
		return -ENODEV;
	}

	/* Header Type must be normal (bits 6-0 only; see spec.) */
	tmpbyte = x86_pci_read_config8(pci_dev, PCI_HEADER_TYPE);
	if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
		debug("%s: invalid Header type\n", __func__);
		return -ENODEV;
	}

	/* Base Class must be a bridge device */
	tmpbyte = x86_pci_read_config8(pci_dev, PCI_CLASS_CODE);
	if (tmpbyte != PCI_CLASS_CODE_BRIDGE) {
		debug("%s: invalid class\n", __func__);
		return -ENODEV;
	}
	/* Sub Class must be ISA */
	tmpbyte = x86_pci_read_config8(pci_dev, PCI_CLASS_SUB_CODE);
	if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) {
		debug("%s: invalid subclass\n", __func__);
		return -ENODEV;
	}

	/* Programming Interface must be 0x00 (no others exist) */
	tmpbyte = x86_pci_read_config8(pci_dev, PCI_CLASS_PROG);
	if (tmpbyte != 0x00) {
		debug("%s: invalid interface type\n", __func__);
		return -ENODEV;
	}

	/*
	 * GPIOBASE 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.
	 */
	tmplong = x86_pci_read_config32(pci_dev, base);
	if (tmplong == 0x00000000 || tmplong == 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.
	 */
	return tmplong & 1 ? tmplong & ~3 : tmplong & ~15;
}