southbridge/hudson: Compile refactored SMI setup utilities in SMM
Refactor hudson_enable_gevent_smi() to allow configuring the interrupt mode and trigger level. Move the utilities which are useful in SMM to a separate file that is included in both ramstage and SMM. This is useful for SMI handlers which need to enable or disable GEVENT SMIs on-the-fly. A follow-up patch makes use of this infrastructure. Change-Id: Ifa4c300c00c178b18d7280690cfc4b8367c669b8 Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com> Reviewed-on: http://review.coreboot.org/170 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@gmail.com>
This commit is contained in:
parent
2ad6ee9763
commit
599d668cdd
|
@ -41,7 +41,7 @@ static void mainboard_enable(device_t dev)
|
|||
|
||||
pavilion_m6_1035dx_ec_init();
|
||||
|
||||
hudson_enable_gevent_smi(EC_SMI_GEVENT);
|
||||
hudson_configure_gevent_smi(EC_SMI_GEVENT, SMI_MODE_SMI, SMI_LVL_HIGH);
|
||||
hudson_enable_smi_generation();
|
||||
|
||||
/*
|
||||
|
|
|
@ -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:
|
||||
# +-----------+---------------+----------------+------------+
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue