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 <marcj303@gmail.com>
Reviewed-on: https://review.coreboot.org/22095
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
Marc Jones
2017-10-04 22:12:31 -06:00
committed by Aaron Durbin
parent f1c8ea35b3
commit e8e72bd0ca
4 changed files with 98 additions and 5 deletions

View File

@@ -20,7 +20,18 @@
#include <arch/io.h> #include <arch/io.h>
#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_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 */ /* SMI source and status */
#define SMITYPE_AGPIO65 0 #define SMITYPE_AGPIO65 0
@@ -189,9 +200,21 @@ enum smi_mode {
SMI_MODE_IRQ13 = 3, SMI_MODE_IRQ13 = 3,
}; };
enum smi_lvl { enum smi_sci_type {
SMI_LVL_LOW = 0, NONE,
SMI_LVL_HIGH = 1, 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 { struct smi_sources_t {
@@ -199,10 +222,19 @@ struct smi_sources_t {
void (*handler)(void); 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); uint16_t pm_acpi_smi_cmd_port(void);
void configure_smi(uint8_t smi_num, uint8_t mode); 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_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 disable_gevent_smi(uint8_t gevent);
void gpe_configure_sci(const struct sci_source *scis, size_t num_gpes);
#ifndef __SMM__ #ifndef __SMM__
void enable_smi_generation(void); void enable_smi_generation(void);

View File

@@ -276,8 +276,10 @@ u32 pm_read32(u8 reg);
void pm_write8(u8 reg, u8 value); void pm_write8(u8 reg, u8 value);
void pm_write16(u8 reg, u16 value); void pm_write16(u8 reg, u16 value);
void pm_write32(u8 reg, u32 value); void pm_write32(u8 reg, u32 value);
u8 smi_read8(u8 reg);
u16 smi_read16(u8 reg); u16 smi_read16(u8 reg);
u32 smi_read32(u8 reg); u32 smi_read32(u8 reg);
void smi_write8(u8 reg, u8 value);
void smi_write16(u8 reg, u16 value); void smi_write16(u8 reg, u16 value);
void smi_write32(u8 reg, u32 value); void smi_write32(u8 reg, u32 value);
uint16_t pm_acpi_pm_cnt_blk(void); uint16_t pm_acpi_pm_cnt_blk(void);

View File

@@ -65,6 +65,16 @@ void smi_write16(uint8_t offset, uint16_t value)
write16((void *)(APU_SMI_BASE + offset), 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) uint16_t pm_acpi_pm_cnt_blk(void)
{ {
return pm_read16(PM1_CNT_BLK); return pm_read16(PM1_CNT_BLK);

View File

@@ -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 gevent The GEVENT pin number. Valid values are 0 thru 23
* @param mode The type of event this pin should generate. Note that only * @param mode The type of event this pin should generate. Note that only
* SMI_MODE_SMI generates an SMI. SMI_MODE_DISABLE disables events. * 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) void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level)
{ {
uint32_t reg32; uint32_t reg32;
/* GEVENT pins range from [0:23] */ /* GEVENT pins range from [0:23] */
if (gevent > 23) { if (gevent >= SMI_GEVENTS) {
printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent); printk(BIOS_WARNING, "BUG: Invalid GEVENT: %u\n", gevent);
return; return;
} }
@@ -56,6 +56,55 @@ void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level)
smi_write32(SMI_REG_SMITRIG0, reg32); 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 */ /** Disable events from given GEVENT pin */
void disable_gevent_smi(uint8_t gevent) void disable_gevent_smi(uint8_t gevent)
{ {