diff options
Diffstat (limited to 'src/southbridge')
-rw-r--r-- | src/southbridge/amd/agesa/hudson/Makefile.inc | 4 | ||||
-rw-r--r-- | src/southbridge/amd/agesa/hudson/smi.c | 43 | ||||
-rw-r--r-- | src/southbridge/amd/agesa/hudson/smi.h | 21 | ||||
-rw-r--r-- | src/southbridge/amd/agesa/hudson/smi_util.c | 79 |
4 files changed, 95 insertions, 52 deletions
diff --git a/src/southbridge/amd/agesa/hudson/Makefile.inc b/src/southbridge/amd/agesa/hudson/Makefile.inc index b92e850664..398ca90ce3 100644 --- a/src/southbridge/amd/agesa/hudson/Makefile.inc +++ b/src/southbridge/amd/agesa/hudson/Makefile.inc @@ -22,8 +22,8 @@ ramstage-$(CONFIG_HAVE_ACPI_RESUME) += resume.c romstage-y += imc.c ramstage-y += imc.c -smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c -ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c +smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c smi_util.c +ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smi.c smi_util.c # ROMSIG At ROMBASE + 0x20000: # +-----------+---------------+----------------+------------+ diff --git a/src/southbridge/amd/agesa/hudson/smi.c b/src/southbridge/amd/agesa/hudson/smi.c index 168f2acb4a..1d58afe3f8 100644 --- a/src/southbridge/amd/agesa/hudson/smi.c +++ b/src/southbridge/amd/agesa/hudson/smi.c @@ -10,8 +10,6 @@ #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"); @@ -25,44 +23,3 @@ void hudson_enable_smi_generation(void) reg |= SMITRG0_EOS; /* Set EOS bit */ smi_write32(SMI_REG_SMITRIG0, reg); } - -static void enable_smi(uint8_t smi_num) -{ - uint8_t reg32_offset, bit_offset; - uint32_t reg32; - - /* SMI sources range from [0:149] */ - if (smi_num > 149) { - printk(BIOS_WARNING, "BUG: Invalid SMI: %u\n", smi_num); - return; - } - - /* 16 sources per register, 2 bits per source; registers are 4 bytes */ - reg32_offset = (smi_num / 16) * 4; - bit_offset = (smi_num % 16) * 2; - - reg32 = smi_read32(SMI_REG_CONTROL0 + reg32_offset); - reg32 &= ~(3 << (bit_offset)); - reg32 |= (SMI_SRC_MODE_SMI << (bit_offset)); - smi_write32(SMI_REG_CONTROL0 + reg32_offset, reg32); - -} - -/** Enable generation of SMIs for given GPE */ -void hudson_enable_gevent_smi(uint8_t gevent) -{ - /* GEVENT pins range from [0:23] */ - if (gevent > 23) { - printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent); - return; - } - - /* 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 7932228280..53da00adfa 100644 --- a/src/southbridge/amd/agesa/hudson/smi.h +++ b/src/southbridge/amd/agesa/hudson/smi.h @@ -22,11 +22,16 @@ #define SMI_REG_CONTROL0 0xa0 -enum smi_src_mode { - SMI_SRC_MODE_DISABLE = 0, - SMI_SRC_MODE_SMI = 1, - SMI_SRC_MODE_NMI = 2, - SMI_SRC_MODE_IRQ13 = 3, +enum smi_mode { + SMI_MODE_DISABLE = 0, + SMI_MODE_SMI = 1, + SMI_MODE_NMI = 2, + SMI_MODE_IRQ13 = 3, +}; + +enum smi_lvl { + SMI_LVL_LOW = 0, + SMI_LVL_HIGH = 1, }; static inline uint32_t smi_read32(uint8_t offset) @@ -49,10 +54,12 @@ static inline void smi_write16(uint8_t offset, uint16_t value) write16(SMI_BASE + offset, value); } +void hudson_configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level); +void hudson_disable_gevent_smi(uint8_t gevent); +void hudson_enable_acpi_cmd_smi(void); + #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/smi_util.c b/src/southbridge/amd/agesa/hudson/smi_util.c new file mode 100644 index 0000000000..6076cd43b3 --- /dev/null +++ b/src/southbridge/amd/agesa/hudson/smi_util.c @@ -0,0 +1,79 @@ +/* + * SMM utilities used in both SMM and normal mode + * + * Copyright (C) 2014 Alexandru Gagniuc <mr.nuke.me@gmail.com> + * Subject to the GNU GPL v2, or (at your option) any later version. + */ + +#include "smi.h" + +#include <console/console.h> + +#define HUDSON_SMI_ACPI_COMMAND 75 + +static void configure_smi(uint8_t smi_num, uint8_t mode) +{ + uint8_t reg32_offset, bit_offset; + uint32_t reg32; + + /* SMI sources range from [0:149] */ + if (smi_num > 149) { + printk(BIOS_WARNING, "BUG: Invalid SMI: %u\n", smi_num); + return; + } + + /* 16 sources per register, 2 bits per source; registers are 4 bytes */ + reg32_offset = (smi_num / 16) * 4; + bit_offset = (smi_num % 16) * 2; + + reg32 = smi_read32(SMI_REG_CONTROL0 + reg32_offset); + reg32 &= ~(0x3 << (bit_offset)); + reg32 |= (mode & 0x3) << bit_offset; + smi_write32(SMI_REG_CONTROL0 + reg32_offset, reg32); +} + +/** + * Configure generation of interrupts for given GEVENT pin + * + * @param gevent The GEVENT pin number. Valid values are 0 thru 23 + * @param mode The type of event this pin should generate. Note that only + * SMI_MODE_SMI generates an SMI. SMI_MODE_DISABLE disables events. + * @param level SMI_LVL_LOW or SMI_LVL_HIGH + */ +void hudson_configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level) +{ + uint32_t reg32; + /* GEVENT pins range from [0:23] */ + if (gevent > 23) { + printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent); + return; + } + + /* SMI0 source is GEVENT0 and so on */ + configure_smi(gevent, mode); + + /* And set set the trigger level */ + reg32 = smi_read32(SMI_REG_SMITRIG0); + reg32 &= ~(1 << gevent); + reg32 |= (level & 0x1) << gevent; + smi_write32(SMI_REG_SMITRIG0, reg32); +} + +/** Disable events from given GEVENT pin */ +void hudson_disable_gevent_smi(uint8_t gevent) +{ + /* GEVENT pins range from [0:23] */ + if (gevent > 23) { + printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent); + return; + } + + /* SMI0 source is GEVENT0 and so on */ + configure_smi(gevent, SMI_MODE_DISABLE); +} + +/** Enable SMIs on writes to ACPI SMI command port */ +void hudson_enable_acpi_cmd_smi(void) +{ + configure_smi(HUDSON_SMI_ACPI_COMMAND, SMI_MODE_SMI); +} |