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:
Alexandru Gagniuc 2014-04-17 23:33:50 -05:00
parent 2ad6ee9763
commit 599d668cdd
5 changed files with 96 additions and 53 deletions

View File

@ -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();
/*

View File

@ -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:
# +-----------+---------------+----------------+------------+

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);
}