diff --git a/src/southbridge/amd/agesa/hudson/fadt.c b/src/southbridge/amd/agesa/hudson/fadt.c index 04c5a59b8e..fcfbb44580 100644 --- a/src/southbridge/amd/agesa/hudson/fadt.c +++ b/src/southbridge/amd/agesa/hudson/fadt.c @@ -27,6 +27,7 @@ #include #include #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 */ + + /* 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(0x62, ACPI_PM1_CNT_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 */ diff --git a/src/southbridge/amd/agesa/hudson/hudson.h b/src/southbridge/amd/agesa/hudson/hudson.h index 73e7bd4140..86b42385ee 100644 --- a/src/southbridge/amd/agesa/hudson/hudson.h +++ b/src/southbridge/amd/agesa/hudson/hudson.h @@ -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 @@ -46,9 +48,17 @@ #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 */ diff --git a/src/southbridge/amd/agesa/hudson/smi.c b/src/southbridge/amd/agesa/hudson/smi.c index bb5e192f53..168f2acb4a 100644 --- a/src/southbridge/amd/agesa/hudson/smi.c +++ b/src/southbridge/amd/agesa/hudson/smi.c @@ -10,6 +10,8 @@ #include #include +#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); +} diff --git a/src/southbridge/amd/agesa/hudson/smi.h b/src/southbridge/amd/agesa/hudson/smi.h index f7120c8b19..7932228280 100644 --- a/src/southbridge/amd/agesa/hudson/smi.h +++ b/src/southbridge/amd/agesa/hudson/smi.h @@ -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 */ diff --git a/src/southbridge/amd/agesa/hudson/smihandler.c b/src/southbridge/amd/agesa/hudson/smihandler.c index 923fd93bf0..e762d0bb96 100644 --- a/src/southbridge/amd/agesa/hudson/smihandler.c +++ b/src/southbridge/amd/agesa/hudson/smihandler.c @@ -5,12 +5,14 @@ * Subject to the GNU GPL v2, or (at your option) any later version. */ +#include "hudson.h" #include "smi.h" #include #include #include +#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); }