[SeaBIOS] [PATCH] seabios: acpi: add mcfg table.
Isaku Yamahata
yamahata at valinux.co.jp
Thu Aug 19 04:57:23 CEST 2010
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 at valinux.co.jp>
In-Reply-To: <cover.1282186223.git.yamahata at valinux.co.jp>
References: <cover.1282186223.git.yamahata at valinux.co.jp>
From: Isaku Yamahata <yamahata at 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 at 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,
};
--
1.7.1.1
--
yamahata
More information about the SeaBIOS
mailing list