From e8e72bd0ca3ea84ba21db4318589e5c903085419 Mon Sep 17 00:00:00 2001 From: Marc Jones Date: Wed, 4 Oct 2017 22:12:31 -0600 Subject: stoneyridge: Add SCI/GPE configuration Add functions for configuring the GPE ACPI SCI events. BUG=b:63268311 BRANCH=none TEST=With the Kahlee GPE setup patch, test lidswitch powers the device on and off at the login screen. Change-Id: I5c282268edbd7b92a3f2ca7c72896406c8f8512f Signed-off-by: Marc Jones Reviewed-on: https://review.coreboot.org/22095 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/soc/amd/stoneyridge/include/soc/smi.h | 38 ++++++++++++++-- src/soc/amd/stoneyridge/include/soc/southbridge.h | 2 + src/soc/amd/stoneyridge/sb_util.c | 10 +++++ src/soc/amd/stoneyridge/smi_util.c | 53 ++++++++++++++++++++++- 4 files changed, 98 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/soc/amd/stoneyridge/include/soc/smi.h b/src/soc/amd/stoneyridge/include/soc/smi.h index 797f4e8578..34d3d74848 100644 --- a/src/soc/amd/stoneyridge/include/soc/smi.h +++ b/src/soc/amd/stoneyridge/include/soc/smi.h @@ -20,7 +20,18 @@ #include +#define SMI_GEVENTS 24 +#define SCIMAPS 58 +#define SCI_GPES 32 + +#define SMI_EVENT_STATUS 0x0 +#define SMI_EVENT_ENABLE 0x04 +#define SMI_SCI_TRIG 0x08 +#define SMI_SCI_LEVEL 0x0c #define SMI_SCI_STATUS 0x10 +#define SMI_SCI_EN 0x14 +#define SMI_SCI_MAP0 0x40 +# define SMI_SCI_MAP(X) (SMI_SCI_MAP0 + (X)) /* SMI source and status */ #define SMITYPE_AGPIO65 0 @@ -189,9 +200,21 @@ enum smi_mode { SMI_MODE_IRQ13 = 3, }; -enum smi_lvl { - SMI_LVL_LOW = 0, - SMI_LVL_HIGH = 1, +enum smi_sci_type { + NONE, + SCI, + SMI, + BOTH, +}; + +enum smi_sci_lvl { + SMI_SCI_LVL_LOW, + SMI_SCI_LVL_HIGH, +}; + +enum smi_sci_dir { + SMI_SCI_EDG, + SMI_SCI_LVL, }; struct smi_sources_t { @@ -199,10 +222,19 @@ struct smi_sources_t { void (*handler)(void); }; +struct sci_source { + uint8_t scimap; /* SCIMAP 0-57 */ + uint8_t gpe; /* 32 GPEs */ + uint8_t direction; /* Active High or Low, smi_sci_lvl */ + uint8_t level; /* Edge or Level, smi_sci_dir */ +}; + uint16_t pm_acpi_smi_cmd_port(void); void configure_smi(uint8_t smi_num, uint8_t mode); void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level); +void configure_scimap(const struct sci_source *sci); void disable_gevent_smi(uint8_t gevent); +void gpe_configure_sci(const struct sci_source *scis, size_t num_gpes); #ifndef __SMM__ void enable_smi_generation(void); diff --git a/src/soc/amd/stoneyridge/include/soc/southbridge.h b/src/soc/amd/stoneyridge/include/soc/southbridge.h index 8e04b68ab2..55ded9ffa8 100644 --- a/src/soc/amd/stoneyridge/include/soc/southbridge.h +++ b/src/soc/amd/stoneyridge/include/soc/southbridge.h @@ -276,8 +276,10 @@ u32 pm_read32(u8 reg); void pm_write8(u8 reg, u8 value); void pm_write16(u8 reg, u16 value); void pm_write32(u8 reg, u32 value); +u8 smi_read8(u8 reg); u16 smi_read16(u8 reg); u32 smi_read32(u8 reg); +void smi_write8(u8 reg, u8 value); void smi_write16(u8 reg, u16 value); void smi_write32(u8 reg, u32 value); uint16_t pm_acpi_pm_cnt_blk(void); diff --git a/src/soc/amd/stoneyridge/sb_util.c b/src/soc/amd/stoneyridge/sb_util.c index bdb199aa1e..ebf791d6ff 100644 --- a/src/soc/amd/stoneyridge/sb_util.c +++ b/src/soc/amd/stoneyridge/sb_util.c @@ -65,6 +65,16 @@ void smi_write16(uint8_t offset, uint16_t value) write16((void *)(APU_SMI_BASE + offset), value); } +uint8_t smi_read8(uint8_t offset) +{ + return read8((void *)(APU_SMI_BASE + offset)); +} + +void smi_write8(uint8_t offset, uint8_t value) +{ + write8((void *)(APU_SMI_BASE + offset), value); +} + uint16_t pm_acpi_pm_cnt_blk(void) { return pm_read16(PM1_CNT_BLK); diff --git a/src/soc/amd/stoneyridge/smi_util.c b/src/soc/amd/stoneyridge/smi_util.c index 96e9d6156b..7b176dee30 100644 --- a/src/soc/amd/stoneyridge/smi_util.c +++ b/src/soc/amd/stoneyridge/smi_util.c @@ -35,13 +35,13 @@ void configure_smi(uint8_t smi_num, uint8_t mode) * @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 + * @param level SMI__SCI_LVL_LOW or SMI_SCI_LVL_HIGH */ void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level) { uint32_t reg32; /* GEVENT pins range from [0:23] */ - if (gevent > 23) { + if (gevent >= SMI_GEVENTS) { printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent); return; } @@ -56,6 +56,55 @@ void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level) smi_write32(SMI_REG_SMITRIG0, reg32); } +/** + * Configure generation of SCIs. + */ +void configure_scimap(const struct sci_source *sci) +{ + uint32_t reg32; + + /* GEVENT pins range */ + if (sci->scimap >= SCIMAPS) { + printk(BIOS_WARNING, "BUG: Invalid SCIMAP: %u\n", + sci->scimap); + return; + } + + /* GPEs range from [0:31] */ + if (sci->gpe >= SCI_GPES) { + printk(BIOS_WARNING, "BUG: Invalid SCI GPE: %u\n", sci->gpe); + return; + } + + printk(BIOS_DEBUG, "SCIMAP %u maps to GPE %u (active %s, %s trigger)\n", + sci->scimap, sci->gpe, + (!!sci->direction) ? "high" : "low", + (!!sci->level) ? "level" : "edge"); + + /* Map Gevent to SCI GPE# */ + smi_write8(SMI_SCI_MAP(sci->scimap), sci->gpe); + + /* Set the trigger direction (high/low) */ + reg32 = smi_read32(SMI_SCI_TRIG); + reg32 &= ~(1 << sci->gpe); + reg32 |= !!sci->direction << sci->gpe; + smi_write32(SMI_SCI_TRIG, reg32); + + /* Set the trigger level (edge/level) */ + reg32 = smi_read32(SMI_SCI_LEVEL); + reg32 &= ~(1 << sci->gpe); + reg32 |= !!sci->level << sci->gpe; + smi_write32(SMI_SCI_LEVEL, reg32); +} + +void gpe_configure_sci(const struct sci_source *scis, size_t num_gpes) +{ + size_t i; + + for (i = 0; i < num_gpes; i++) + configure_scimap(scis + i); +} + /** Disable events from given GEVENT pin */ void disable_gevent_smi(uint8_t gevent) { -- cgit v1.2.3