On Tue, Aug 17, 2010 at 08:08:23PM -0400, Kevin O'Connor wrote:
On Fri, Jul 30, 2010 at 11:51:58AM +0900, Isaku Yamahata wrote:
add mcfg table. mcfg isn't populated at the moment. dev-q35 will use it later.
This patch slipped through the cracks - sorry.
This patch doesn't seem to do much right now as no IDs are defined. It looks like it is in preparation for follow up patches. However, I don't think it's possible to really judge this patch without seeing the follow up ones.
Fair enough. The following is the dev-q35 patch. I planned to post it at the same time I post the q35 patch, though.
From 5543f3a92e370fed2e1e34350d31e8c6f37c9813 Mon Sep 17 00:00:00 2001
Message-Id: 5543f3a92e370fed2e1e34350d31e8c6f37c9813.1282186223.git.yamahata@valinux.co.jp In-Reply-To: cover.1282186223.git.yamahata@valinux.co.jp References: cover.1282186223.git.yamahata@valinux.co.jp From: Isaku Yamahata yamahata@valinux.co.jp Date: Mon, 28 Jun 2010 12:02:58 +0900 Subject: [PATCH] seabios: add q35 initialization functions.
add q35 initialization functions.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- Makefile | 3 +- src/acpi.c | 10 ++++ src/dev-q35.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/dev-q35.h | 54 +++++++++++++++++++++ src/pciinit.c | 7 +++ src/shadow.c | 5 ++ src/smm.c | 3 + 7 files changed, 226 insertions(+), 1 deletions(-) create mode 100644 src/dev-q35.c create mode 100644 src/dev-q35.h
diff --git a/Makefile b/Makefile index 47f5625..ae6ce04 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,8 @@ SRCBOTH=misc.c pmm.c stacks.c output.c util.c block.c floppy.c ata.c mouse.c \ SRC16=$(SRCBOTH) system.c disk.c apm.c font.c SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \ acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \ - lzmadecode.c bootsplash.c jpeg.c usb-hub.c paravirt.c dev-i440fx.c + lzmadecode.c bootsplash.c jpeg.c usb-hub.c paravirt.c dev-i440fx.c \ + dev-q35.c SRC32SEG=util.c output.c pci.c pcibios.c apm.c stacks.c
cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \ diff --git a/src/acpi.c b/src/acpi.c index a51460d..1687674 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -14,6 +14,7 @@ #include "paravirt.h" #include "dev-i440fx.h" // piix4_fadt_init #include "post.h" +#include "dev-q35.h"
/****************************************************/ /* ACPI tables init */ @@ -218,6 +219,8 @@ static const struct pci_device_id fadt_init_tbl[] = { /* PIIX4 Power Management device (for ACPI) */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, piix4_fadt_init), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC, + ich9_lpc_fadt_init),
PCI_DEVICE_END }; @@ -581,10 +584,16 @@ build_srat(void) }
static const struct pci_device_id mcfg_find_tbl[] = { + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH, + mch_mcfg_find), + PCI_DEVICE_END, };
static const struct pci_device_id mcfg_init_tbl[] = { + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH, + mch_mcfg_init), + PCI_DEVICE_END, };
@@ -643,6 +652,7 @@ build_mcfg(void) static const struct pci_device_id acpi_find_tbl[] = { /* PIIX4 Power Management device. */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC, NULL),
PCI_DEVICE_END, }; diff --git a/src/dev-q35.c b/src/dev-q35.c new file mode 100644 index 0000000..835f94f --- /dev/null +++ b/src/dev-q35.c @@ -0,0 +1,145 @@ +// q35 chipset specific functions. +// +// Copyright (C) 2010 Isaku Yamahata <yamahata at valinux co jp> +// +// This file may be distributed under the terms of the GNU LGPLv3 license. +// + +#include "config.h" +#include "ioport.h" +#include "util.h" +#include "pci.h" +#include "pci_ids.h" +#include "pci_regs.h" +#include "post.h" +#include "dev-q35.h" + +/* PCI_VENDOR_ID_INTEL && DEVICE_ID_INTEL_Q35_MCH */ +void mch_bios_make_writable(u16 bdf, void *arg) +{ + make_bios_writable_intel(bdf, Q35_HOST_BRIDGE_PAM0); +} + +void mch_bios_make_readonly(u16 bdf, void *arg) +{ + make_bios_readonly_intel(bdf, Q35_HOST_BRIDGE_PAM0); +} + + +/* ICH9 LPC PCI to ISA bridge */ +/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */ +void mch_isa_bridge_init(u16 bdf, void *arg) +{ + int i, irq; + u8 elcr[2]; + + elcr[0] = 0x00; + elcr[1] = 0x00; + for (i = 0; i < 4; i++) { + irq = pci_irqs[i]; + /* set to trigger level */ + elcr[irq >> 3] |= (1 << (irq & 7)); + /* activate irq remapping in LPC */ + pci_config_writeb(bdf, ICH9_LPC_PIRQA_ROUT + i, irq); + } + outb(elcr[0], ICH9_LPC_PORT_ELCR1); + outb(elcr[1], ICH9_LPC_PORT_ELCR2); + dprintf(1, "Q35 LPC init: elcr=%02x %02x\n", elcr[0], elcr[1]); +} + +/* PCI_VENDOR_ID_INTEL && DEVICE_ID_INTEL_Q35_MCH */ +void mch_mcfg_find(u16 bdf, void *arg) +{ + struct acpi_mcfg *mcfg = arg; + mcfg->nr = 1; +} + +/* PCI_VENDOR_ID_INTEL && DEVICE_ID_INTEL_Q35_MCH */ +void mch_mcfg_init(u16 bdf, void *arg) +{ + u64 addr = Q35_HOST_BRIDGE_PCIEXBAR_ADDR | Q35_HOST_BRIDGE_PCIEXBAREN; + u32 upper = addr >> 32; + u32 lower = addr & 0xffffffff; + + /* at first disable the region. and then update/enable it. */ + pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0); + pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper); + pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower); + + struct acpi_mcfg *mcfg = arg; + struct acpi_mcfg_allocation *alloc = &mcfg->mcfg->allocation[0]; + alloc->address = Q35_HOST_BRIDGE_PCIEXBAR_ADDR; + alloc->pci_segment = Q35_HOST_PCIE_PCI_SEGMENT; + alloc->start_bus_number = Q35_HOST_PCIE_START_BUS_NUMBER; + alloc->end_bus_number = Q35_HOST_PCIE_END_BUS_NUMBER; + + mcfg->e820->start = Q35_HOST_BRIDGE_PCIEXBAR_ADDR; + mcfg->e820->size = Q35_HOST_BRIDGE_PCIEXBAR_SIZE; + mcfg->e820->type = E820_RESERVED; +} + +/* ICH9 LPC Power Management device (for ACPI) */ +/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */ +void ich9_lpc_pm_init(u16 bdf, void *arg) +{ + /* pm io base */ + pci_config_writel(bdf, ICH9_LPC_PMBASE, + PORT_ACPI_PM_BASE | ICH9_LPC_PMBASE_RTE); + + // acpi sci defaults to irq9. + pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9); + + /* acpi enable, SCI: IRQ9 000b = irq9*/ + pci_config_writeb(bdf, ICH9_LPC_ACPI_CTRL, ICH9_LPC_ACPI_CTRL_ACPI_EN); +} + +/* ICH9 SMBUS */ +/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_SMBUS */ +void ich9_smbus_init(u16 bdf, void *arg) +{ + /* map smbus into io space */ + pci_config_writel(bdf, ICH9_SMB_SMB_BASE, + PORT_SMB_BASE | PCI_BASE_ADDRESS_SPACE_IO); + + /* enable SMBus */ + pci_config_writeb(bdf, ICH9_SMB_HOSTC, ICH9_SMB_HOSTC_HST_EN); +} + +/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */ +void ich9_lpc_fadt_init(u16 bdf, void *arg) +{ + struct fadt_descriptor_rev1 *fadt = arg; + fadt->acpi_enable = ICH9_ACPI_ENABLE; + fadt->acpi_disable = ICH9_ACPI_DISABLE; + fadt->gpe0_blk = cpu_to_le32(PORT_ACPI_PM_BASE + ICH9_PMIO_GPE0_STS); + fadt->gpe0_blk_len = ICH9_PMIO_GPE0_BLK_LEN; +} + +/* PCI_VENDOR_ID_INTEL && PCI_DEVICE_ID_INTEL_ICH9_LPC */ +void ich9_lpc_apmc_smm_init(u16 bdf, void *arg) +{ + // This code is hardcoded for Q35 Power Management device. + int mch_bdf = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_Q35_MCH); + if (mch_bdf < 0) + return; + + /* check if SMM init is already done */ + u32 value = inl(PORT_ACPI_PM_BASE + ICH9_PMIO_SMI_EN); + if (value & ICH9_PMIO_SMI_EN_APMC_EN) + return; + + /* enable the SMM memory window */ + pci_config_writeb(mch_bdf, Q35_HOST_BRIDGE_SMRAM, 0x02 | 0x48); + + smm_save_and_copy(); + + /* enable SMI generation when writing to the APMC register */ + outl(value | ICH9_PMIO_SMI_EN_APMC_EN, + PORT_ACPI_PM_BASE + ICH9_PMIO_SMI_EN); + + smm_relocate_and_restore(); + + /* close the SMM memory window and enable normal SMM */ + pci_config_writeb(mch_bdf, Q35_HOST_BRIDGE_SMRAM, 0x02 | 0x08); +} diff --git a/src/dev-q35.h b/src/dev-q35.h new file mode 100644 index 0000000..a0c7e13 --- /dev/null +++ b/src/dev-q35.h @@ -0,0 +1,54 @@ +#ifndef __DEV_Q35_H +#define __DEV_Q35_H + +#include "types.h" // u16 + +#define PCI_DEVICE_ID_INTEL_Q35_MCH 0x29c0 +#define Q35_HOST_BRIDGE_PAM0 0x90 +#define Q35_HOST_BRIDGE_SMRAM 0x9d +#define Q35_HOST_BRIDGE_PCIEXBAR 0x60 +#define Q35_HOST_BRIDGE_PCIEXBAR_SIZE (256 * 1024 * 1024) +#define Q35_HOST_BRIDGE_PCIEXBAR_ADDR 0xe0000000 +#define Q35_HOST_BRIDGE_PCIEXBAREN ((u64)1) +#define Q35_HOST_PCIE_PCI_SEGMENT 0 +#define Q35_HOST_PCIE_START_BUS_NUMBER 0 +#define Q35_HOST_PCIE_END_BUS_NUMBER 255 + +#define PCI_DEVICE_ID_INTEL_ICH9_LPC 0x2918 +#define ICH9_LPC_PMBASE 0x40 +#define ICH9_LPC_PMBASE_RTE 0x1 + +#define ICH9_LPC_ACPI_CTRL 0x44 +#define ICH9_LPC_ACPI_CTRL_ACPI_EN 0x80 +#define ICH9_LPC_PIRQA_ROUT 0x60 +#define ICH9_LPC_PORT_ELCR1 0x4d0 +#define ICH9_LPC_PORT_ELCR2 0x4d1 +#define PCI_DEVICE_ID_INTEL_ICH9_SMBUS 0x2930 +#define ICH9_SMB_SMB_BASE 0x20 +#define ICH9_SMB_HOSTC 0x40 +#define ICH9_SMB_HOSTC_HST_EN 0x01 + +#define ICH9_ACPI_ENABLE 0x2 +#define ICH9_ACPI_DISABLE 0x3 + +/* ICH9 LPC PM I/O registers are 128 ports and 128-aligned */ +#define ICH9_PMIO_GPE0_STS 0x20 +#define ICH9_PMIO_GPE0_BLK_LEN 0x10 +#define ICH9_PMIO_SMI_EN 0x30 +#define ICH9_PMIO_SMI_EN_APMC_EN (1 << 5) + +/* FADT ACPI_ENABLE/ACPI_DISABLE */ +#define ICH9_APM_ACPI_ENABLE 0x2 +#define ICH9_APM_ACPI_DISABLE 0x3 + +void mch_bios_make_writable(u16 bdf, void *arg); +void mch_bios_make_readonly(u16 bdf, void *arg); +void mch_isa_bridge_init(u16 bdf, void *arg); +void mch_mcfg_find(u16 bdf, void *arg); +void mch_mcfg_init(u16 bdf, void *arg); +void ich9_lpc_pm_init(u16 bdf, void *arg); +void ich9_smbus_init(u16 bdf, void *arg); +void ich9_lpc_fadt_init(u16 bdf, void *arg); +void ich9_lpc_apmc_smm_init(u16 bdf, void *arg); + +#endif // dev-q35.h diff --git a/src/pciinit.c b/src/pciinit.c index f75e552..3f2c041 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -11,6 +11,7 @@ #include "pci_ids.h" // PCI_VENDOR_ID_INTEL #include "pci_regs.h" // PCI_COMMAND #include "dev-i440fx.h" +#include "dev-q35.h"
#define PCI_ROM_SLOT 6 #define PCI_NUM_REGIONS 7 @@ -148,6 +149,8 @@ static const struct pci_device_id pci_isa_bridge_tbl[] = { piix_isa_bridge_init), PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, piix_isa_bridge_init), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC, + mch_isa_bridge_init),
PCI_DEVICE_END }; @@ -295,6 +298,10 @@ static const struct pci_device_id pci_device_tbl[] = { /* PIIX4 Power Management device (for ACPI) */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, piix4_pm_init), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC, + ich9_lpc_pm_init), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_SMBUS, + ich9_smbus_init),
PCI_DEVICE_END, }; diff --git a/src/shadow.c b/src/shadow.c index e91e54e..22ebe62 100644 --- a/src/shadow.c +++ b/src/shadow.c @@ -10,6 +10,7 @@ #include "config.h" // CONFIG_* #include "pci_ids.h" // PCI_VENDOR_ID_INTEL #include "dev-i440fx.h" +#include "dev-q35.h"
// Test if 'addr' is in the range from 'start'..'start+size' #define IN_RANGE(addr, start, size) ({ \ @@ -102,6 +103,8 @@ make_bios_readonly_intel(u16 bdf, u32 pam0) static const struct pci_device_id dram_controller_make_writable_tbl[] = { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, i440fx_bios_make_writable), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH, + mch_bios_make_writable), PCI_DEVICE_END };
@@ -127,6 +130,8 @@ make_bios_writable(void) static const struct pci_device_id dram_controller_make_readonly_tbl[] = { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, i440fx_bios_make_readonly), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_Q35_MCH, + mch_bios_make_readonly), PCI_DEVICE_END };
diff --git a/src/smm.c b/src/smm.c index 7e52892..1c3ab69 100644 --- a/src/smm.c +++ b/src/smm.c @@ -11,6 +11,7 @@ #include "ioport.h" // outb #include "pci_ids.h" // PCI_VENDOR_ID_INTEL #include "dev-i440fx.h" +#include "dev-q35.h"
ASM32FLAT( ".global smm_relocation_start\n" @@ -109,6 +110,8 @@ smm_relocate_and_restore(void) static const struct pci_device_id smm_init_tbl[] = { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, piix4_apmc_smm_init), + PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_LPC, + ich9_lpc_apmc_smm_init),
PCI_DEVICE_END, };