On 11/16/10 7:41 PM, Fengwei Zhang wrote:
> I followed the smmhandler.S code in /src/cpu/x86/smm/ directory
> If I put my rsm instruction before ljmp instruction, I could invoke
> SMI successfully.
>     /* Enable protected mode */
>     data32  ljmp    $0x08, $1f
>
> but if I put rsm instruction below that(even commented out the C
> procedure), my machine will freeze after the invoking.
>
> The only difference between my code and ICH4 implementation is:
> I didn't copy the smm bin file(include smmhandler.S smihandler.c
> smm.ld), to location 0xa0000, I just copied the smmhandler.S file to
> location 0xa0000 and wrote a jmp statement at 0xa8000.
>
> In order to make it simple, I commented out the C procedure, and only
> assembly in smmhandler.
That won't work. Just leave the sequence as it is, and adapt the
southbridge/northbridge specific code to your chipset.

Pretty much like the attached patch, but it's not complete yet.


Signed-off-by: Stefan Reinauer <[email protected]>

Index: src/southbridge/via/vt8237r/Makefile.inc
===================================================================
--- src/southbridge/via/vt8237r/Makefile.inc    (revision 6080)
+++ src/southbridge/via/vt8237r/Makefile.inc    (working copy)
@@ -25,3 +25,7 @@
 driver-y += vt8237r_usb.c
 driver-y += vt8237r_nic.c
 ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += vt8237_fadt.c
+
+smm-$(CONFIG_HAVE_SMI_HANDLER) += vt8237r_smihandler.c
+
+
Index: src/southbridge/via/vt8237r/vt8237r.h
===================================================================
--- src/southbridge/via/vt8237r/vt8237r.h       (revision 6080)
+++ src/southbridge/via/vt8237r/vt8237r.h       (working copy)
@@ -20,12 +20,11 @@
 #ifndef SOUTHBRIDGE_VIA_VT8237R_VT8237R_H
 #define SOUTHBRIDGE_VIA_VT8237R_VT8237R_H
 
-#include <stdint.h>
-
 /* Static resources for the VT8237R southbridge */
 
 #define VT8237R_APIC_ID                        0x2
 #define VT8237R_ACPI_IO_BASE           0x500
+#define DEFAULT_PMBASE                 VT8237R_ACPI_IO_BASE
 #define VT8237R_SMBUS_IO_BASE          0x400
 /* 0x0 disabled, 0x2 reserved, 0xf = IRQ15 */
 #define VT8237R_ACPI_IRQ               0x9
@@ -36,6 +35,74 @@
 #endif
 #define VT8237R_HPET_ADDR              0xfed00000ULL
 
+/* PMBASE FIXME mostly taken from ich7 */
+#define PM1_STS                0x00
+#define   WAK_STS      (1 << 15)
+#define   PCIEXPWAK_STS        (1 << 14)
+#define   PRBTNOR_STS  (1 << 11)
+#define   RTC_STS      (1 << 10)
+#define   PWRBTN_STS   (1 << 8)
+#define   GBL_STS      (1 << 5)
+#define   BM_STS       (1 << 4)
+#define   TMROF_STS    (1 << 0)
+#define PM1_EN         0x02
+#define   PCIEXPWAK_DIS        (1 << 14)
+#define   RTC_EN       (1 << 10)
+#define   PWRBTN_EN    (1 << 8)
+#define   GBL_EN       (1 << 5)
+#define   TMROF_EN     (1 << 0)
+#define PM1_CNT                0x04
+#define   SLP_EN       (1 << 13)
+#define   SLP_TYP      (7 << 10)
+#define   GBL_RLS      (1 << 2)
+#define   BM_RLD       (1 << 1)
+#define   SCI_EN       (1 << 0)
+#define PM1_TMR                0x08
+#define PROC_CNT       0x10
+#define LV2            0x14
+#define LV3            0x15
+#define LV4            0x16
+#define PM2_CNT                0x20 // mobile only
+#define GPE0_STS       0x28
+#define   USB4_STS     (1 << 14)
+#define   PME_B0_STS   (1 << 13)
+#define   USB3_STS     (1 << 12)
+#define   PME_STS      (1 << 11)
+#define   BATLOW_STS   (1 << 10)
+#define   PCI_EXP_STS  (1 << 9)
+#define   RI_STS       (1 << 8)
+#define   SMB_WAK_STS  (1 << 7)
+#define   TCOSCI_STS   (1 << 6)
+#define   AC97_STS     (1 << 5)
+#define   USB2_STS     (1 << 4)
+#define   USB1_STS     (1 << 3)
+#define   SWGPE_STS    (1 << 2)
+#define   HOT_PLUG_STS (1 << 1)
+#define   THRM_STS     (1 << 0)
+#define GPE0_EN                0x2c
+#define   PME_B0_EN    (1 << 13)
+#define   PME_EN       (1 << 11)
+#define SMI_EN         0x30
+#define   LEGACY_USB2_EN (1 << 17) // Legacy USB2 SMI logic
+#define   PERIODIC_EN   (1 << 14) // SMI on PERIODIC_STS in SMI_STS
+#define   TCO_EN        (1 << 13) // Enable TCO Logic (BIOSWE et al)
+#define   MCSMI_EN      (1 << 11) // Trap microcontroller range access
+#define   BIOS_RLS      (1 <<  7) // asserts SCI on bit set
+#define   SWSMI_TMR_EN  (1 <<  6) // start software smi timer on bit set
+#define   APMC_EN       (1 <<  5) // Writes to APM_CNT cause SMI#
+#define   SLP_SMI_EN    (1 <<  4) // Write to SLP_EN in PM1_CNT asserts SMI#
+#define   LEGACY_USB_EN  (1 <<  3) // Legacy USB circuit SMI logic
+#define   BIOS_EN       (1 <<  2) // Assert SMI# on setting GBL_RLS bit
+#define   EOS           (1 <<  1) // End of SMI (deassert SMI#)
+#define   GBL_SMI_EN    (1 <<  0) // SMI# generation at all?
+#define SMI_STS                0x34
+#define ALT_GP_SMI_EN  0x38
+#define ALT_GP_SMI_STS 0x3a
+#define GPE_CNTL       0x42
+#define DEVACT_STS     0x44
+#define SS_CNT         0x50
+#define C3_RES         0x54
+
 /* IDE */
 #define IDE_CS                         0x40
 #define IDE_CONF_I                     0x41
@@ -107,6 +174,15 @@
 #endif
 ;
 
+#define MAINBOARD_POWER_OFF    0
+#define MAINBOARD_POWER_ON     1
+#define MAINBOARD_POWER_KEEP   2
+
+#ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL
+#define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
+#endif
+
+
 #ifdef __PRE_RAM__
 #ifndef __ROMCC__
 u8 smbus_read_byte(u8 dimm, u8 offset);
@@ -119,8 +195,7 @@
 int vt8237_early_network_init(struct vt8237_network_rom *rom);
 #endif
 #else
-#include <device/device.h>
-void writeback(struct device *dev, u16 where, u8 what);
+void writeback(device_t dev, u16 where, u8 what);
 void dump_south(device_t dev);
 u32 vt8237_ide_80pin_detect(struct device *dev);
 #endif
Index: src/southbridge/via/vt8237r/vt8237r_smihandler.c
===================================================================
--- src/southbridge/via/vt8237r/vt8237r_smihandler.c    (revision 0)
+++ src/southbridge/via/vt8237r/vt8237r_smihandler.c    (revision 0)
@@ -0,0 +1,643 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <types.h>
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include <device/pci_def.h>
+#include "vt8237r.h"
+
+#define APM_CNT                0xb2
+#define   CST_CONTROL  0x85
+#define   PST_CONTROL  0x80
+#define   ACPI_DISABLE 0x1e
+#define   ACPI_ENABLE  0xe1
+#define   GNVS_UPDATE   0xea
+#define APM_STS                0xb3
+
+#include "vt8237r_nvs.h"
+
+/* While we read PMBASE dynamically in case it changed, let's
+ * initialize it with a sane value
+ */
+u16 pmbase = DEFAULT_PMBASE;
+u8 smm_initialized = 0;
+
+/* GNVS needs to be updated by an 0xEA PM Trap (B2) after it has been located
+ * by coreboot.
+ */
+global_nvs_t *gnvs = (global_nvs_t *)0x0;
+void *tcg = (void *)0x0;
+void *smi1 = (void *)0x0;
+
+/**
+ * @brief read and clear PM1_STS
+ * @return PM1_STS register
+ */
+static u16 reset_pm1_status(void)
+{
+       u16 reg16;
+
+       reg16 = inw(pmbase + PM1_STS);
+       /* set status bits are cleared by writing 1 to them */
+       outw(reg16, pmbase + PM1_STS);
+
+       return reg16;
+}
+
+static void dump_pm1_status(u16 pm1_sts)
+{
+       printk(BIOS_SPEW, "PM1_STS: ");
+       if (pm1_sts & (1 << 15)) printk(BIOS_SPEW, "WAK ");
+       if (pm1_sts & (1 << 14)) printk(BIOS_SPEW, "PCIEXPWAK ");
+       if (pm1_sts & (1 << 11)) printk(BIOS_SPEW, "PRBTNOR ");
+       if (pm1_sts & (1 << 10)) printk(BIOS_SPEW, "RTC ");
+       if (pm1_sts & (1 <<  8)) printk(BIOS_SPEW, "PWRBTN ");
+       if (pm1_sts & (1 <<  5)) printk(BIOS_SPEW, "GBL ");
+       if (pm1_sts & (1 <<  4)) printk(BIOS_SPEW, "BM ");
+       if (pm1_sts & (1 <<  0)) printk(BIOS_SPEW, "TMROF ");
+       printk(BIOS_SPEW, "\n");
+       int reg16 = inw(pmbase + PM1_EN);
+       printk(BIOS_SPEW, "PM1_EN: %x\n", reg16);
+}
+
+/**
+ * @brief read and clear SMI_STS
+ * @return SMI_STS register
+ */
+static u32 reset_smi_status(void)
+{
+       u32 reg32;
+
+       reg32 = inl(pmbase + SMI_STS);
+       /* set status bits are cleared by writing 1 to them */
+       outl(reg32, pmbase + SMI_STS);
+
+       return reg32;
+}
+
+static void dump_smi_status(u32 smi_sts)
+{
+       printk(BIOS_DEBUG, "SMI_STS: ");
+       if (smi_sts & (1 << 26)) printk(BIOS_DEBUG, "SPI ");
+       if (smi_sts & (1 << 25)) printk(BIOS_DEBUG, "EL_SMI ");
+       if (smi_sts & (1 << 21)) printk(BIOS_DEBUG, "MONITOR ");
+       if (smi_sts & (1 << 20)) printk(BIOS_DEBUG, "PCI_EXP_SMI ");
+       if (smi_sts & (1 << 18)) printk(BIOS_DEBUG, "INTEL_USB2 ");
+       if (smi_sts & (1 << 17)) printk(BIOS_DEBUG, "LEGACY_USB2 ");
+       if (smi_sts & (1 << 16)) printk(BIOS_DEBUG, "SMBUS_SMI ");
+       if (smi_sts & (1 << 15)) printk(BIOS_DEBUG, "SERIRQ_SMI ");
+       if (smi_sts & (1 << 14)) printk(BIOS_DEBUG, "PERIODIC ");
+       if (smi_sts & (1 << 13)) printk(BIOS_DEBUG, "TCO ");
+       if (smi_sts & (1 << 12)) printk(BIOS_DEBUG, "DEVMON ");
+       if (smi_sts & (1 << 11)) printk(BIOS_DEBUG, "MCSMI ");
+       if (smi_sts & (1 << 10)) printk(BIOS_DEBUG, "GPI ");
+       if (smi_sts & (1 <<  9)) printk(BIOS_DEBUG, "GPE0 ");
+       if (smi_sts & (1 <<  8)) printk(BIOS_DEBUG, "PM1 ");
+       if (smi_sts & (1 <<  6)) printk(BIOS_DEBUG, "SWSMI_TMR ");
+       if (smi_sts & (1 <<  5)) printk(BIOS_DEBUG, "APM ");
+       if (smi_sts & (1 <<  4)) printk(BIOS_DEBUG, "SLP_SMI ");
+       if (smi_sts & (1 <<  3)) printk(BIOS_DEBUG, "LEGACY_USB ");
+       if (smi_sts & (1 <<  2)) printk(BIOS_DEBUG, "BIOS ");
+       printk(BIOS_DEBUG, "\n");
+}
+
+
+/**
+ * @brief read and clear GPE0_STS
+ * @return GPE0_STS register
+ */
+static u32 reset_gpe0_status(void)
+{
+       u32 reg32;
+
+       reg32 = inl(pmbase + GPE0_STS);
+       /* set status bits are cleared by writing 1 to them */
+       outl(reg32, pmbase + GPE0_STS);
+
+       return reg32;
+}
+
+static void dump_gpe0_status(u32 gpe0_sts)
+{
+       int i;
+       printk(BIOS_DEBUG, "GPE0_STS: ");
+       for (i=31; i<= 16; i--) {
+               if (gpe0_sts & (1 << i)) printk(BIOS_DEBUG, "GPIO%d ", (i-16));
+       }
+       if (gpe0_sts & (1 << 14)) printk(BIOS_DEBUG, "USB4 ");
+       if (gpe0_sts & (1 << 13)) printk(BIOS_DEBUG, "PME_B0 ");
+       if (gpe0_sts & (1 << 12)) printk(BIOS_DEBUG, "USB3 ");
+       if (gpe0_sts & (1 << 11)) printk(BIOS_DEBUG, "PME ");
+       if (gpe0_sts & (1 << 10)) printk(BIOS_DEBUG, "EL_SCI/BATLOW ");
+       if (gpe0_sts & (1 <<  9)) printk(BIOS_DEBUG, "PCI_EXP ");
+       if (gpe0_sts & (1 <<  8)) printk(BIOS_DEBUG, "RI ");
+       if (gpe0_sts & (1 <<  7)) printk(BIOS_DEBUG, "SMB_WAK ");
+       if (gpe0_sts & (1 <<  6)) printk(BIOS_DEBUG, "TCO_SCI ");
+       if (gpe0_sts & (1 <<  5)) printk(BIOS_DEBUG, "AC97 ");
+       if (gpe0_sts & (1 <<  4)) printk(BIOS_DEBUG, "USB2 ");
+       if (gpe0_sts & (1 <<  3)) printk(BIOS_DEBUG, "USB1 ");
+       if (gpe0_sts & (1 <<  2)) printk(BIOS_DEBUG, "HOT_PLUG ");
+       if (gpe0_sts & (1 <<  0)) printk(BIOS_DEBUG, "THRM ");
+       printk(BIOS_DEBUG, "\n");
+}
+
+
+/**
+ * @brief read and clear TCOx_STS
+ * @return TCOx_STS registers
+ */
+static u32 reset_tco_status(void)
+{
+       u32 tcobase = pmbase + 0x60;
+       u32 reg32;
+
+       reg32 = inl(tcobase + 0x04);
+       /* set status bits are cleared by writing 1 to them */
+       outl(reg32 & ~(1<<18), tcobase + 0x04); //  Don't clear BOOT_STS before 
SECOND_TO_STS
+       if (reg32 & (1 << 18))
+               outl(reg32 & (1<<18), tcobase + 0x04); // clear BOOT_STS
+
+       return reg32;
+}
+
+
+static void dump_tco_status(u32 tco_sts)
+{
+       printk(BIOS_DEBUG, "TCO_STS: ");
+       if (tco_sts & (1 << 20)) printk(BIOS_DEBUG, "SMLINK_SLV ");
+       if (tco_sts & (1 << 18)) printk(BIOS_DEBUG, "BOOT ");
+       if (tco_sts & (1 << 17)) printk(BIOS_DEBUG, "SECOND_TO ");
+       if (tco_sts & (1 << 16)) printk(BIOS_DEBUG, "INTRD_DET ");
+       if (tco_sts & (1 << 12)) printk(BIOS_DEBUG, "DMISERR ");
+       if (tco_sts & (1 << 10)) printk(BIOS_DEBUG, "DMISMI ");
+       if (tco_sts & (1 <<  9)) printk(BIOS_DEBUG, "DMISCI ");
+       if (tco_sts & (1 <<  8)) printk(BIOS_DEBUG, "BIOSWR ");
+       if (tco_sts & (1 <<  7)) printk(BIOS_DEBUG, "NEWCENTURY ");
+       if (tco_sts & (1 <<  3)) printk(BIOS_DEBUG, "TIMEOUT ");
+       if (tco_sts & (1 <<  2)) printk(BIOS_DEBUG, "TCO_INT ");
+       if (tco_sts & (1 <<  1)) printk(BIOS_DEBUG, "SW_TCO ");
+       if (tco_sts & (1 <<  0)) printk(BIOS_DEBUG, "NMI2SMI ");
+       printk(BIOS_DEBUG, "\n");
+}
+
+/* We are using PCIe accesses for now
+ *  1. the chipset can do it
+ *  2. we don't need to worry about how we leave 0xcf8/0xcfc behind
+ */
+#include "../../../northbridge/amd/amdk8/pcie_config.c"
+
+int southbridge_io_trap_handler(int smif)
+{
+       switch (smif) {
+       case 0x32:
+               printk(BIOS_DEBUG, "OS Init\n");
+               /* gnvs->smif:
+                *  On success, the IO Trap Handler returns 0
+                *  On failure, the IO Trap Handler returns a value != 0
+                */
+               gnvs->smif = 0;
+               return 1; /* IO trap handled */
+       }
+
+       /* Not handled */
+       return 0;
+}
+
+/**
+ * @brief Set the EOS bit
+ */
+void southbridge_smi_set_eos(void)
+{
+       u8 reg8;
+
+       reg8 = inb(pmbase + SMI_EN);
+       reg8 |= EOS;
+       outb(reg8, pmbase + SMI_EN);
+}
+
+static void busmaster_disable_on_bus(int bus)
+{
+        int slot, func;
+        unsigned int val;
+        unsigned char hdr;
+
+        for (slot = 0; slot < 0x20; slot++) {
+                for (func = 0; func < 8; func++) {
+                        u32 reg32;
+                        device_t dev = PCI_DEV(bus, slot, func);
+
+                        val = pci_read_config32(dev, PCI_VENDOR_ID);
+
+                        if (val == 0xffffffff || val == 0x00000000 ||
+                            val == 0x0000ffff || val == 0xffff0000)
+                                continue;
+
+                        /* Disable Bus Mastering for this one device */
+                        reg32 = pci_read_config32(dev, PCI_COMMAND);
+                        reg32 &= ~PCI_COMMAND_MASTER;
+                        pci_write_config32(dev, PCI_COMMAND, reg32);
+
+                        /* If this is a bridge, then follow it. */
+                        hdr = pci_read_config8(dev, PCI_HEADER_TYPE);
+                        hdr &= 0x7f;
+                        if (hdr == PCI_HEADER_TYPE_BRIDGE ||
+                            hdr == PCI_HEADER_TYPE_CARDBUS) {
+                                unsigned int buses;
+                                buses = pci_read_config32(dev, 
PCI_PRIMARY_BUS);
+                                busmaster_disable_on_bus((buses >> 8) & 0xff);
+                        }
+                }
+        }
+}
+
+
+static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t 
*state_save)
+{
+       u8 reg8;
+       u32 reg32;
+       u8 slp_typ;
+
+       /* FIXME: the power state on boot should be read from
+        * CMOS or even better from GNVS. Right now it's hard
+        * coded at compile time.
+        */
+       u8 s5pwr = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
+
+       /* First, disable further SMIs */
+       reg8 = inb(pmbase + SMI_EN);
+       reg8 &= ~SLP_SMI_EN;
+       outb(reg8, pmbase + SMI_EN);
+
+       /* Figure out SLP_TYP */
+       reg32 = inl(pmbase + PM1_CNT);
+       printk(BIOS_SPEW, "SMI#: SLP = 0x%08x\n", reg32);
+       slp_typ = (reg32 >> 10) & 7;
+
+       /* Next, do the deed.
+        */
+
+       switch (slp_typ) {
+       case 0: printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n"); break;
+       case 1: printk(BIOS_DEBUG, "SMI#: Entering S1 (Assert STPCLK#)\n"); 
break;
+       case 5:
+               printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n");
+               /* Invalidate the cache before going to S3 */
+               wbinvd();
+               break;
+       case 6: printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n"); 
break;
+       case 7:
+               printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n");
+
+               outl(0, pmbase + GPE0_EN);
+
+               /* Should we keep the power state after a power loss?
+                * In case the setting is "ON" or "OFF" we don't have
+                * to do anything. But if it's "KEEP" we have to switch
+                * to "OFF" before entering S5.
+                */
+               if (s5pwr == MAINBOARD_POWER_KEEP) {
+                       // FIXME vt8237r code missing
+                       //reg8 = pcie_read_config8(PCI_DEV(0, 0x1f, 0), 
GEN_PMCON_3);
+                       //reg8 |= 1;
+                       //pcie_write_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3, 
reg8);
+               }
+
+               /* also iterates over all bridges on bus 0 */
+               busmaster_disable_on_bus(0);
+               break;
+       default: printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n"); break;
+       }
+
+       /* Write back to the SLP register to cause the originally intended
+        * event again. We need to set BIT13 (SLP_EN) though to make the
+        * sleep happen.
+        */
+       outl(reg32 | SLP_EN, pmbase + PM1_CNT);
+
+       /* In most sleep states, the code flow of this function ends at
+        * the line above. However, if we entered sleep state S1 and wake
+        * up again, we will continue to execute code in this function.
+        */
+       reg32 = inl(pmbase + PM1_CNT);
+       if (reg32 & SCI_EN) {
+               /* The OS is not an ACPI OS, so we set the state to S0 */
+               reg32 &= ~(SLP_EN | SLP_TYP);
+               outl(reg32, pmbase + PM1_CNT);
+       }
+}
+
+static void southbridge_smi_apmc(unsigned int node, smm_state_save_area_t 
*state_save)
+{
+       u32 pmctrl;
+       u8 reg8;
+
+       /* Emulate B2 register as the FADT / Linux expects it */
+
+       reg8 = inb(APM_CNT);
+       switch (reg8) {
+       case CST_CONTROL:
+               /* Calling this function seems to cause
+                * some kind of race condition in Linux
+                * and causes a kernel oops
+                */
+               printk(BIOS_DEBUG, "C-state control\n");
+               break;
+       case PST_CONTROL:
+               /* Calling this function seems to cause
+                * some kind of race condition in Linux
+                * and causes a kernel oops
+                */
+               printk(BIOS_DEBUG, "P-state control\n");
+               break;
+       case ACPI_DISABLE:
+               pmctrl = inl(pmbase + PM1_CNT);
+               pmctrl &= ~SCI_EN;
+               outl(pmctrl, pmbase + PM1_CNT);
+               printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n");
+               break;
+       case ACPI_ENABLE:
+               pmctrl = inl(pmbase + PM1_CNT);
+               pmctrl |= SCI_EN;
+               outl(pmctrl, pmbase + PM1_CNT);
+               printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n");
+               break;
+       case GNVS_UPDATE:
+               if (smm_initialized) {
+                       printk(BIOS_DEBUG, "SMI#: SMM structures already 
initialized!\n");
+                       return;
+               }
+               gnvs = *(global_nvs_t **)0x500;
+               tcg  = *(void **)0x504;
+               smi1 = *(void **)0x508;
+               smm_initialized = 1;
+               printk(BIOS_DEBUG, "SMI#: Setting up structures to %p, %p, 
%p\n", gnvs, tcg, smi1);
+               break;
+       default:
+               printk(BIOS_DEBUG, "SMI#: Unknown function APM_CNT=%02x\n", 
reg8);
+       }
+}
+
+static void southbridge_smi_pm1(unsigned int node, smm_state_save_area_t 
*state_save)
+{
+       u16 pm1_sts;
+
+       pm1_sts = reset_pm1_status();
+       dump_pm1_status(pm1_sts);
+
+       /* While OSPM is not active, poweroff immediately
+        * on a power button event.
+        */
+       if (pm1_sts & PWRBTN_STS) {
+               // power button pressed
+               u32 reg32;
+               reg32 = (7 << 10) | (1 << 13);
+               outl(reg32, pmbase + PM1_CNT);
+       }
+}
+
+static void southbridge_smi_gpe0(unsigned int node, smm_state_save_area_t 
*state_save)
+{
+       u32 gpe0_sts;
+
+       gpe0_sts = reset_gpe0_status();
+       dump_gpe0_status(gpe0_sts);
+}
+
+static void southbridge_smi_gpi(unsigned int node, smm_state_save_area_t 
*state_save)
+{
+       u16 reg16;
+       reg16 = inw(pmbase + ALT_GP_SMI_STS);
+       outl(reg16, pmbase + ALT_GP_SMI_STS);
+
+       reg16 &= inw(pmbase + ALT_GP_SMI_EN);
+
+       if (mainboard_smi_gpi) {
+               mainboard_smi_gpi(reg16);
+       } else {
+               if (reg16)
+                       printk(BIOS_DEBUG, "GPI (mask %04x)\n",reg16);
+       }
+}
+
+static void southbridge_smi_mc(unsigned int node, smm_state_save_area_t 
*state_save)
+{
+       u32 reg32;
+
+       reg32 = inl(pmbase + SMI_EN);
+
+       /* Are periodic SMIs enabled? */
+       if ((reg32 & MCSMI_EN) == 0)
+               return;
+
+       printk(BIOS_DEBUG, "Microcontroller SMI.\n");
+}
+
+
+
+static void southbridge_smi_tco(unsigned int node, smm_state_save_area_t 
*state_save)
+{
+       u32 tco_sts;
+
+       tco_sts = reset_tco_status();
+
+       /* Any TCO event? */
+       if (!tco_sts)
+               return;
+
+       if (tco_sts & (1 << 8)) { // BIOSWR
+               u8 bios_cntl;
+
+               bios_cntl = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0xdc);
+
+               if (bios_cntl & 1) {
+                       /* BWE is RW, so the SMI was caused by a
+                        * write to BWE, not by a write to the BIOS
+                        */
+
+                       /* This is the place where we notice someone
+                        * is trying to tinker with the BIOS. We are
+                        * trying to be nice and just ignore it. A more
+                        * resolute answer would be to power down the
+                        * box.
+                        */
+                       printk(BIOS_DEBUG, "Switching back to RO\n");
+                       pcie_write_config32(PCI_DEV(0, 0x1f, 0), 0xdc, 
(bios_cntl & ~1));
+               } /* No else for now? */
+       } else if (tco_sts & (1 << 3)) { /* TIMEOUT */
+               /* Handle TCO timeout */
+               printk(BIOS_DEBUG, "TCO Timeout.\n");
+       } else if (!tco_sts) {
+               dump_tco_status(tco_sts);
+       }
+}
+
+static void southbridge_smi_periodic(unsigned int node, smm_state_save_area_t 
*state_save)
+{
+       u32 reg32;
+
+       reg32 = inl(pmbase + SMI_EN);
+
+       /* Are periodic SMIs enabled? */
+       if ((reg32 & PERIODIC_EN) == 0)
+               return;
+
+       printk(BIOS_DEBUG, "Periodic SMI.\n");
+}
+
+static void southbridge_smi_monitor(unsigned int node, smm_state_save_area_t 
*state_save)
+{
+#if 0
+#define IOTRAP(x) (trap_sts & (1 << x))
+       u32 trap_sts, trap_cycle;
+       u32 data, mask = 0;
+       int i;
+
+       trap_sts = RCBA32(0x1e00); // TRSR - Trap Status Register
+       RCBA32(0x1e00) = trap_sts; // Clear trap(s) in TRSR
+
+       trap_cycle = RCBA32(0x1e10);
+       for (i=16; i<20; i++) {
+               if (trap_cycle & (1 << i))
+                       mask |= (0xff << ((i - 16) << 2));
+       }
+
+
+       /* IOTRAP(3) SMI function call */
+       if (IOTRAP(3)) {
+               if (gnvs && gnvs->smif)
+                       io_trap_handler(gnvs->smif); // call function smif
+               return;
+       }
+
+       /* IOTRAP(2) currently unused
+        * IOTRAP(1) currently unused */
+
+       /* IOTRAP(0) SMIC */
+       if (IOTRAP(0)) {
+               if (!(trap_cycle & (1 << 24))) { // It's a write
+                       printk(BIOS_DEBUG, "SMI1 command\n");
+                       data = RCBA32(0x1e18);
+                       data &= mask;
+                       // if (smi1)
+                       //      southbridge_smi_command(data);
+                       // return;
+               }
+               // Fall through to debug
+       }
+
+       printk(BIOS_DEBUG, "  trapped io address = 0x%x\n", trap_cycle & 
0xfffc);
+       for (i=0; i < 4; i++) if(IOTRAP(i)) printk(BIOS_DEBUG, "  TRAP = 
%d\n", i);
+       printk(BIOS_DEBUG, "  AHBE = %x\n", (trap_cycle >> 16) & 0xf);
+       printk(BIOS_DEBUG, "  MASK = 0x%08x\n", mask);
+       printk(BIOS_DEBUG, "  read/write: %s\n", (trap_cycle & (1 << 24)) ? 
"read" : "write");
+
+       if (!(trap_cycle & (1 << 24))) {
+               /* Write Cycle */
+               data = RCBA32(0x1e18);
+               printk(BIOS_DEBUG, "  iotrap written data = 0x%08x\n", data);
+       }
+#undef IOTRAP
+#endif
+}
+
+typedef void (*smi_handler_t)(unsigned int node,
+               smm_state_save_area_t *state_save);
+
+smi_handler_t southbridge_smi[32] = {
+       NULL,                     //  [0] reserved
+       NULL,                     //  [1] reserved
+       NULL,                     //  [2] BIOS_STS
+       NULL,                     //  [3] LEGACY_USB_STS
+       southbridge_smi_sleep,    //  [4] SLP_SMI_STS
+       southbridge_smi_apmc,     //  [5] APM_STS
+       NULL,                     //  [6] SWSMI_TMR_STS
+       NULL,                     //  [7] reserved
+       southbridge_smi_pm1,      //  [8] PM1_STS
+       southbridge_smi_gpe0,     //  [9] GPE0_STS
+       southbridge_smi_gpi,      // [10] GPI_STS
+       southbridge_smi_mc,       // [11] MCSMI_STS
+       NULL,                     // [12] DEVMON_STS
+       southbridge_smi_tco,      // [13] TCO_STS
+       southbridge_smi_periodic, // [14] PERIODIC_STS
+       NULL,                     // [15] SERIRQ_SMI_STS
+       NULL,                     // [16] SMBUS_SMI_STS
+       NULL,                     // [17] LEGACY_USB2_STS
+       NULL,                     // [18] INTEL_USB2_STS
+       NULL,                     // [19] reserved
+       NULL,                     // [20] PCI_EXP_SMI_STS
+       southbridge_smi_monitor,  // [21] MONITOR_STS
+       NULL,                     // [22] reserved
+       NULL,                     // [23] reserved
+       NULL,                     // [24] reserved
+       NULL,                     // [25] EL_SMI_STS
+       NULL,                     // [26] SPI_STS
+       NULL,                     // [27] reserved
+       NULL,                     // [28] reserved
+       NULL,                     // [29] reserved
+       NULL,                     // [30] reserved
+       NULL                      // [31] reserved
+};
+
+/**
+ * @brief Interrupt handler for SMI#
+ *
+ * @param smm_revision revision of the smm state save map
+ */
+
+void southbridge_smi_handler(unsigned int node, smm_state_save_area_t 
*state_save)
+{
+       int i, dump = 0;
+       u32 smi_sts;
+
+       /* Update global variable pmbase */
+       pmbase = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
+
+       /* We need to clear the SMI status registers, or we won't see what's
+        * happening in the following calls.
+        */
+       smi_sts = reset_smi_status();
+
+       /* Filter all non-enabled SMI events */
+       // FIXME Double check, this clears MONITOR
+       // smi_sts &= inl(pmbase + SMI_EN);
+
+       /* Call SMI sub handler for each of the status bits */
+       for (i = 0; i < 31; i++) {
+               if (smi_sts & (1 << i)) {
+                       if (southbridge_smi[i])
+                               southbridge_smi[i](node, state_save);
+                       else {
+                               printk(BIOS_DEBUG, "SMI_STS[%d] occured, but no 
"
+                                               "handler available.\n", i);
+                               dump = 1;
+                       }
+               }
+       }
+
+       if(dump) {
+               dump_smi_status(smi_sts);
+       }
+
+}
Index: src/southbridge/via/vt8237r/vt8237r_nvs.h
===================================================================
--- src/southbridge/via/vt8237r/vt8237r_nvs.h   (revision 0)
+++ src/southbridge/via/vt8237r/vt8237r_nvs.h   (revision 0)
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+typedef struct {
+       /* Miscellaneous */
+       u16     osys; /* 0x00 - Operating System */
+       u8      smif; /* 0x02 - SMI function call ("TRAP") */
+       u8      prm0; /* 0x03 - SMI function call parameter */
+       u8      prm1; /* 0x04 - SMI function call parameter */
+       u8      scif; /* 0x05 - SCI function call (via _L00) */
+       u8      prm2; /* 0x06 - SCI function call parameter */
+       u8      prm3; /* 0x07 - SCI function call parameter */
+       u8      lckf; /* 0x08 - Global Lock function for EC */
+       u8      prm4; /* 0x09 - Lock function parameter */
+       u8      prm5; /* 0x0a - Lock function parameter */
+       u32     p80d; /* 0x0b - Debug port (IO 0x80) value */
+       u8      lids; /* 0x0f - LID state (open = 1) */
+       u8      pwrs; /* 0x10 - Power state (AC = 1) */
+       u8      dbgs; /* 0x11 - Debug state */
+       u8      linx; /* 0x12 - Linux OS */
+       u8      dckn; /* 0x13 - PCIe docking state */
+       u8      rsvd[0x28-0x14];
+       /* Processor Identification */
+       u8      apic; /* 0x28 - APIC enabled */
+       u8      mpen; /* 0x29 - MP capable/enabled */
+       u8      pcp0; /* 0x2a - PDC CPU/CORE 0 */
+       u8      pcp1; /* 0x2b - PDC CPU/CORE 1 */
+       u8      ppcm; /* 0x2c - Max. PPC state */
+} __attribute__((packed)) global_nvs_t;
+
Index: src/southbridge/via/vt8237r/vt8237r_lpc.c
===================================================================
--- src/southbridge/via/vt8237r/vt8237r_lpc.c   (revision 6080)
+++ src/southbridge/via/vt8237r/vt8237r_lpc.c   (working copy)
@@ -28,6 +28,7 @@
 #include <pc80/mc146818rtc.h>
 #include <arch/ioapic.h>
 #include <cpu/x86/lapic.h>
+#include <cpu/cpu.h>
 #include <pc80/keyboard.h>
 #include <pc80/i8259.h>
 #include <stdlib.h>
@@ -217,12 +218,9 @@
        /* Disable SMI on GPIO. */
        outw(0x0, VT8237R_ACPI_IO_BASE + 0x24);
 
-       /* Disable all global enable SMIs. */
-       outw(0x0, VT8237R_ACPI_IO_BASE + 0x2a);
+       /* Disable all global enable SMIs, except SW SMI */
+       outw(0x40, VT8237R_ACPI_IO_BASE + 0x2a);
 
-       /* All SMI off, both IDE buses ON, PSON rising edge. */
-       outw(0x0, VT8237R_ACPI_IO_BASE + 0x2c);
-
        /* Primary activity SMI disable. */
        outl(0x0, VT8237R_ACPI_IO_BASE + 0x34);
 
@@ -238,6 +236,10 @@
        acpi_slp_type = ((tmp & (7 << 10)) >> 10) == 1 ? 3 : 0 ;
        printk(BIOS_DEBUG, "SLP_TYP type was %x %x\n", tmp, acpi_slp_type);
 #endif
+
+       /* All SMI on, both IDE buses ON, PSON rising edge. */
+       outw(0x1, VT8237R_ACPI_IO_BASE + 0x2c);
+
        /* clear sleep */
        tmp &= ~(7 << 10);
        tmp |= 1;
@@ -501,6 +503,7 @@
        /* Enable serial IRQ, 6PCI clocks. */
        pci_write_config8(dev, 0x52, 0x9);
 
+       smm_init();
 #endif
 
        /* Power management setup */
Index: src/include/cpu/x86/smm.h
===================================================================
--- src/include/cpu/x86/smm.h   (revision 6080)
+++ src/include/cpu/x86/smm.h   (working copy)
@@ -254,7 +254,7 @@
 
 void io_trap_handler(int smif);
 int southbridge_io_trap_handler(int smif);
-int mainboard_io_trap_handler(int smif);
+int __attribute__((weak)) mainboard_io_trap_handler(int smif);
 
 void southbridge_smi_set_eos(void);
 
Index: src/cpu/amd/socket_S1G1/Makefile.inc
===================================================================
--- src/cpu/amd/socket_S1G1/Makefile.inc        (revision 6080)
+++ src/cpu/amd/socket_S1G1/Makefile.inc        (working copy)
@@ -7,7 +7,8 @@
 subdirs-y += ../../x86/lapic
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/pae
+subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/smm
-subdirs-y += ../../x86/mtrr
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_940/Makefile.inc
===================================================================
--- src/cpu/amd/socket_940/Makefile.inc (revision 6080)
+++ src/cpu/amd/socket_940/Makefile.inc (working copy)
@@ -8,5 +8,7 @@
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/pae
+subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/model_fxx/model_fxx_init.c
===================================================================
--- src/cpu/amd/model_fxx/model_fxx_init.c      (revision 6080)
+++ src/cpu/amd/model_fxx/model_fxx_init.c      (working copy)
@@ -499,11 +499,6 @@
 
        k8_errata();
 
-       /* Set SMMLOCK to avoid exploits messing with SMM */
-       msr = rdmsr(HWCR_MSR);
-       msr.lo |= (1 << 0);
-       wrmsr(HWCR_MSR, msr);
-
        enable_cache();
 
        /* Set the processor name string */
Index: src/cpu/amd/socket_AM2/Makefile.inc
===================================================================
--- src/cpu/amd/socket_AM2/Makefile.inc (revision 6080)
+++ src/cpu/amd/socket_AM2/Makefile.inc (working copy)
@@ -9,5 +9,6 @@
 subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/pae
 subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_754/Makefile.inc
===================================================================
--- src/cpu/amd/socket_754/Makefile.inc (revision 6080)
+++ src/cpu/amd/socket_754/Makefile.inc (working copy)
@@ -8,5 +8,7 @@
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/pae
+subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_AM3/Makefile.inc
===================================================================
--- src/cpu/amd/socket_AM3/Makefile.inc (revision 6080)
+++ src/cpu/amd/socket_AM3/Makefile.inc (working copy)
@@ -7,7 +7,8 @@
 subdirs-y += ../../x86/lapic
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/pae
+subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/smm
-subdirs-y += ../../x86/mtrr
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_AM2r2/Makefile.inc
===================================================================
--- src/cpu/amd/socket_AM2r2/Makefile.inc       (revision 6080)
+++ src/cpu/amd/socket_AM2r2/Makefile.inc       (working copy)
@@ -7,7 +7,8 @@
 subdirs-y += ../../x86/lapic
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/pae
+subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/smm
-subdirs-y += ../../x86/mtrr
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/smm/smm_init.c
===================================================================
--- src/cpu/amd/smm/smm_init.c  (revision 0)
+++ src/cpu/amd/smm/smm_init.c  (revision 0)
@@ -0,0 +1,64 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include <string.h>
+
+#define SMM_ADDR 0xc0010112
+#define SMM_MASK 0xc0010113
+#define SMM_BASE 0xa0000
+
+extern unsigned char _binary_smm_start;
+extern unsigned char _binary_smm_size;
+
+void smm_init(void)
+{
+       msr_t msr;
+       /* enable the SMM memory window */
+       
+       msr = rdmsr(SMM_MASK);
+       msr.lo |= (1 << 0); // Enable ASEG SMRAM Range
+       msr.lo &= ~(1 << 2); // Open ASEG SMRAM Range
+       wrmsr(SMM_MASK, msr);
+
+       /* copy the real SMM handler */
+       memcpy((void *)SMM_BASE, &_binary_smm_start, (size_t)&_binary_smm_size);
+       wbinvd();
+
+       msr = rdmsr(SMM_MASK);
+       msr.lo |= ~(1 << 2); // Close ASEG SMRAM Range
+       wrmsr(SMM_MASK, msr);
+
+       msr = rdmsr(SMM_ADDR);
+       msr.lo &= 0x0001ffff;
+       msr.hi &= 0xffffff00;
+       msr.lo |= (SMM_BASE << 17);
+       msr.hi |= (SMM_BASE >> 15);
+       wrmsr(SMM_ADDR, msr);
+
+       /* Set SMMLOCK to avoid exploits messing with SMM */
+       msr = rdmsr(HWCR_MSR);
+       msr.lo |= (1 << 0);
+       wrmsr(HWCR_MSR, msr);
+}
Index: src/cpu/amd/smm/Makefile.inc
===================================================================
--- src/cpu/amd/smm/Makefile.inc        (revision 0)
+++ src/cpu/amd/smm/Makefile.inc        (revision 0)
@@ -0,0 +1,2 @@
+
+ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smm_init.c
Index: src/cpu/amd/socket_939/Makefile.inc
===================================================================
--- src/cpu/amd/socket_939/Makefile.inc (revision 6080)
+++ src/cpu/amd/socket_939/Makefile.inc (working copy)
@@ -8,5 +8,7 @@
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/pae
+subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_F/Makefile.inc
===================================================================
--- src/cpu/amd/socket_F/Makefile.inc   (revision 6080)
+++ src/cpu/amd/socket_F/Makefile.inc   (working copy)
@@ -9,5 +9,6 @@
 subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/pae
 subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_ASB2/Makefile.inc
===================================================================
--- src/cpu/amd/socket_ASB2/Makefile.inc        (revision 6080)
+++ src/cpu/amd/socket_ASB2/Makefile.inc        (working copy)
@@ -7,7 +7,8 @@
 subdirs-y += ../../x86/lapic
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/pae
+subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/smm
-subdirs-y += ../../x86/mtrr
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_F_1207/Makefile.inc
===================================================================
--- src/cpu/amd/socket_F_1207/Makefile.inc      (revision 6080)
+++ src/cpu/amd/socket_F_1207/Makefile.inc      (working copy)
@@ -9,5 +9,6 @@
 subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/pae
 subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/x86/smm/smmrelocate.S
===================================================================
--- src/cpu/x86/smm/smmrelocate.S       (revision 6080)
+++ src/cpu/x86/smm/smmrelocate.S       (working copy)
@@ -22,6 +22,8 @@
 // Make sure no stage 2 code is included:
 #define __PRE_RAM__
 
+#if !defined(CONFIG_NORTHBRIDGE_AMD_AMDK8) && 
!defined(CONFIG_NORTHBRIDGE_AMD_FAM10)
+
 // FIXME: Is this piece of code southbridge specific, or
 // can it be cleaned up so this include is not required?
 // It's needed right now because we get our DEFAULT_PMBASE from
@@ -175,4 +177,4 @@
        /* That's it. return */
        rsm
 smm_relocation_end:
-
+#endif
Index: src/mainboard/asus/m2v-mx_se/Kconfig
===================================================================
--- src/mainboard/asus/m2v-mx_se/Kconfig        (revision 6080)
+++ src/mainboard/asus/m2v-mx_se/Kconfig        (working copy)
@@ -37,6 +37,7 @@
        select TINY_BOOTBLOCK
        select HAVE_MAINBOARD_RESOURCES
        select QRANK_DIMM_SUPPORT
+       select HAVE_SMI_HANDLER
        select SET_FIDVID
 
 config MAINBOARD_DIR
Index: src/northbridge/amd/amdk8/pcie_config.c
===================================================================
--- src/northbridge/amd/amdk8/pcie_config.c     (revision 0)
+++ src/northbridge/amd/amdk8/pcie_config.c     (revision 0)
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include "amdk8.h"
+
+static inline __attribute__ ((always_inline))
+u8 pcie_read_config8(device_t dev, unsigned int where)
+{
+       unsigned long addr;
+       addr = DEFAULT_PCIEXBAR | dev | where;
+       return read8(addr);
+}
+
+static inline __attribute__ ((always_inline))
+u16 pcie_read_config16(device_t dev, unsigned int where)
+{
+       unsigned long addr;
+       addr = DEFAULT_PCIEXBAR | dev | where;
+       return read16(addr);
+}
+
+static inline __attribute__ ((always_inline))
+u32 pcie_read_config32(device_t dev, unsigned int where)
+{
+       unsigned long addr;
+       addr = DEFAULT_PCIEXBAR | dev | where;
+       return read32(addr);
+}
+
+static inline __attribute__ ((always_inline))
+void pcie_write_config8(device_t dev, unsigned int where, u8 value)
+{
+       unsigned long addr;
+       addr = DEFAULT_PCIEXBAR | dev | where;
+       write8(addr, value);
+}
+
+static inline __attribute__ ((always_inline))
+void pcie_write_config16(device_t dev, unsigned int where, u16 value)
+{
+       unsigned long addr;
+       addr = DEFAULT_PCIEXBAR | dev | where;
+       write16(addr, value);
+}
+
+static inline __attribute__ ((always_inline))
+void pcie_write_config32(device_t dev, unsigned int where, u32 value)
+{
+       unsigned long addr;
+       addr = DEFAULT_PCIEXBAR | dev | where;
+       write32(addr, value);
+}
Index: src/northbridge/amd/amdk8/amdk8.h
===================================================================
--- src/northbridge/amd/amdk8/amdk8.h   (revision 6080)
+++ src/northbridge/amd/amdk8/amdk8.h   (working copy)
@@ -2,6 +2,8 @@
 
 #define AMDK8_H
 
+#define DEFAULT_PCIEXBAR 0xe0000000
+
 #if CONFIG_K8_REV_F_SUPPORT == 1
         #include "amdk8_f.h"
 #else
-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to