southbridge/hudson: Add support for ACPI enable/disable via SMI 11/5511/3
authorAlexandru Gagniuc <mr.nuke.me@gmail.com>
Mon, 14 Apr 2014 21:35:34 +0000 (16:35 -0500)
committerAlexandru Gagniuc <mr.nuke.me@gmail.com>
Thu, 17 Apr 2014 02:42:44 +0000 (04:42 +0200)
This enables the ACPI SMI command port in the FADT table, and sets up
the hardware accordingly. If we have SMI enabled, then we don't set
the SCI_EN bit at boot, causing the OS to send the ACPI_ENABLE
command, as required by the ACPI spec. This gives us a chance to hook
into the mainboard_smi_apmc() handler.

Change-Id: Ib4c63d55b3132578dcae48bfe2092d4ea35821dd
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Reviewed-on: http://review.coreboot.org/5511
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@gmail.com>
src/southbridge/amd/agesa/hudson/fadt.c
src/southbridge/amd/agesa/hudson/hudson.h
src/southbridge/amd/agesa/hudson/smi.c
src/southbridge/amd/agesa/hudson/smi.h
src/southbridge/amd/agesa/hudson/smihandler.c

index 04c5a59..fcfbb44 100644 (file)
@@ -27,6 +27,7 @@
 #include <arch/io.h>
 #include <device/device.h>
 #include "hudson.h"
+#include "smi.h"
 
 #if CONFIG_HUDSON_LEGACY_FREE
        #define FADT_BOOT_ARCH ACPI_FADT_LEGACY_FREE
@@ -63,26 +64,41 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt)
        fadt->model = 0;                /* reserved, should be 0 ACPI 3.0 */
        fadt->preferred_pm_profile = FADT_PM_PROFILE;
        fadt->sci_int = 9;              /* HUDSON - IRQ 09 – ACPI SCI */
-       fadt->smi_cmd = 0;              /* disable system management mode */
-       fadt->acpi_enable = 0;  /* unused if SMI_CMD = 0 */
-       fadt->acpi_disable = 0; /* unused if SMI_CMD = 0 */
-       fadt->s4bios_req = 0;   /* unused if SMI_CMD = 0 */
-       fadt->pstate_cnt = 0;   /* unused if SMI_CMD = 0 */
 
-       pm_write16(0x60, ACPI_PM_EVT_BLK);
+       /* We write to this port further down; configure it first */
        pm_write16(0x62, ACPI_PM1_CNT_BLK);
+
+       if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)) {
+               fadt->smi_cmd = ACPI_SMI_CTL_PORT;
+               fadt->acpi_enable = ACPI_SMI_CMD_ENABLE;
+               fadt->acpi_disable = ACPI_SMI_CMD_DISABLE;
+               fadt->s4bios_req = 0;   /* Not supported */
+               fadt->pstate_cnt = 0;   /* Not supported */
+               fadt->cst_cnt = 0;      /* Not supported */
+               hudson_enable_acpi_cmd_smi();
+               outl(0x0, ACPI_PM1_CNT_BLK);    /* clear SCI_EN */
+       } else {
+               fadt->smi_cmd = 0;      /* disable system management mode */
+               fadt->acpi_enable = 0;  /* unused if SMI_CMD = 0 */
+               fadt->acpi_disable = 0; /* unused if SMI_CMD = 0 */
+               fadt->s4bios_req = 0;   /* unused if SMI_CMD = 0 */
+               fadt->pstate_cnt = 0;   /* unused if SMI_CMD = 0 */
+               fadt->cst_cnt = 0x00;   /* unused if SMI_CMD = 0 */
+               outl(0x1, ACPI_PM1_CNT_BLK);    /* set SCI_EN */
+       }
+
+       pm_write16(0x60, ACPI_PM_EVT_BLK);
        pm_write16(0x64, ACPI_PM_TMR_BLK);
        pm_write16(0x68, ACPI_GPE0_BLK);
        /* CpuControl is in \_PR.CPU0, 6 bytes */
        pm_write16(0x66, ACPI_CPU_CONTROL);
-       pm_write16(0x6A, 0);    /* AcpiSmiCmd */
+       pm_write16(0x6a, fadt->smi_cmd);
 
        pm_write8(0x74, 1<<0 | 1<<1 | 1<<4 | 1<<2); /* AcpiDecodeEnable, When set, SB uses
                                        * the contents of the PM registers at
                                        * index 60-6B to decode ACPI I/O address.
                                        * AcpiSmiEn & SmiCmdEn*/
-       /* RTC_En_En, TMR_En_En, GBL_EN_EN */
-       outl(0x1, ACPI_PM1_CNT_BLK);                    /* set SCI_EN */
+
        fadt->pm1a_evt_blk = ACPI_PM_EVT_BLK;
        fadt->pm1b_evt_blk = 0x0000;
        fadt->pm1a_cnt_blk = ACPI_PM1_CNT_BLK;
@@ -100,7 +116,6 @@ void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt)
        fadt->gpe1_blk_len = 0;
        fadt->gpe1_base = 0;
 
-       fadt->cst_cnt = 0x00;   /* unused if SMI_CMD = 0 */
        fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
        fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
        fadt->flush_size = 0;   /* set to 0 if WBINVD is 1 in flags */
index 73e7bd4..86b4238 100644 (file)
@@ -29,6 +29,8 @@
 #define BIOSRAM_DATA   0xcd5
 #define PM_INDEX       0xcd6
 #define PM_DATA                0xcd7
+#define PM2_INDEX      0xcd0
+#define PM2_DATA       0xcd1
 
 #define HUDSON_ACPI_IO_BASE 0x800
 
 #define PM1_TMR_BLK_ADDRESS                     0x808                           //      AcpiPmTmrBlkAddr;
 #define CPU_CNT_BLK_ADDRESS                     0x810                           //      CpuControlBlkAddr;
 #define GPE0_BLK_ADDRESS                        0x820                           //  AcpiGpe0BlkAddr;
-#define SMI_CMD_PORT                            0xB0                            //      SmiCmdPortAddr;
 #define SPIROM_BASE_ADDRESS_REGISTER    0xA0
 
+#define ACPI_SMI_CTL_PORT              0xb2
+#define ACPI_SMI_CMD_CST_CONTROL       0xde
+#define ACPI_SMI_CMD_PST_CONTROL       0xad
+#define ACPI_SMI_CMD_DISABLE           0xbe
+#define ACPI_SMI_CMD_ENABLE            0xef
+#define ACPI_SMI_CMD_S4_REQ            0xc0
+
+#ifndef __SMM__
+
 void pm_write8(u8 reg, u8 value);
 u8 pm_read8(u8 reg);
 void pm_write16(u8 reg, u16 value);
@@ -70,6 +80,7 @@ void hudson_enable(device_t dev);
 void __attribute__((weak)) hudson_setup_sata_phys(struct device *dev);
 void s3_resume_init_data(void *FchParams);
 
-#endif
+#endif /* __PRE_RAM__ */
+#endif /* __SMM__ */
 
 #endif /* HUDSON_H */
index bb5e192..168f2ac 100644 (file)
@@ -10,6 +10,8 @@
 #include <console/console.h>
 #include <cpu/cpu.h>
 
+#define HUDSON_SMI_ACPI_COMMAND                75
+
 void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
 {
        printk(BIOS_DEBUG, "smm_setup_structures STUB!!!\n");
@@ -58,3 +60,9 @@ void hudson_enable_gevent_smi(uint8_t gevent)
        /* SMI0 source is GEVENT0 and so on */
        enable_smi(gevent);
 }
+
+/** Enable SMIs on writes to ACPI SMI command port */
+void hudson_enable_acpi_cmd_smi(void)
+{
+       enable_smi(HUDSON_SMI_ACPI_COMMAND);
+}
index f7120c8..7932228 100644 (file)
@@ -52,6 +52,7 @@ static inline void smi_write16(uint8_t offset, uint16_t value)
 #ifndef __SMM__
 void hudson_enable_smi_generation(void);
 void hudson_enable_gevent_smi(uint8_t gevent);
+void hudson_enable_acpi_cmd_smi(void);
 #endif
 
 #endif /* _SOUTHBRIDGE_AMD_AGESA_HUDSON_SMI_H */
index 923fd93..e762d0b 100644 (file)
@@ -5,12 +5,14 @@
  * Subject to the GNU GPL v2, or (at your option) any later version.
  */
 
+#include "hudson.h"
 #include "smi.h"
 
 #include <console/console.h>
 #include <cpu/x86/smm.h>
 #include <delay.h>
 
+#define SMI_0x88_ACPI_COMMAND          (1 << 11)
 
 enum smi_source {
        SMI_SOURCE_SCI = (1 << 0),
@@ -21,6 +23,28 @@ enum smi_source {
        SMI_SOURCE_0x90 = (1 << 5)
 };
 
+static void hudson_apmc_smi_handler(void)
+{
+       u32 reg32;
+       const uint8_t cmd = inb(ACPI_SMI_CTL_PORT);
+
+       switch (cmd) {
+       case ACPI_SMI_CMD_ENABLE:
+               reg32 = inl(ACPI_PM1_CNT_BLK);
+               reg32 |= (1 << 0);      /* SCI_EN */
+               outl(reg32, ACPI_PM1_CNT_BLK);
+               break;
+       case ACPI_SMI_CMD_DISABLE:
+               reg32 = inl(ACPI_PM1_CNT_BLK);
+               reg32 &= ~(1 << 0);     /* clear SCI_EN */
+               outl(ACPI_PM1_CNT_BLK, reg32);
+               break;
+       }
+
+       if (mainboard_smi_apmc)
+               mainboard_smi_apmc(cmd);
+}
+
 int southbridge_io_trap_handler(int smif)
 {
        return 0;
@@ -62,6 +86,10 @@ static void process_smi_0x88(void)
 {
        const uint32_t status = smi_read32(0x88);
 
+       if (status & SMI_0x88_ACPI_COMMAND) {
+               /* Command received via ACPI SMI command port */
+               hudson_apmc_smi_handler();
+       }
        /* Clear events to prevent re-entering SMI if event isn't handled */
        smi_write32(0x88, status);
 }