diff options
-rw-r--r-- | src/soc/intel/baytrail/baytrail/gpio.h | 20 | ||||
-rw-r--r-- | src/soc/intel/baytrail/baytrail/pmc.h | 5 | ||||
-rw-r--r-- | src/soc/intel/baytrail/baytrail/smm.h | 2 | ||||
-rw-r--r-- | src/soc/intel/baytrail/gpio.c | 28 | ||||
-rw-r--r-- | src/soc/intel/baytrail/smm.c | 39 |
5 files changed, 93 insertions, 1 deletions
diff --git a/src/soc/intel/baytrail/baytrail/gpio.h b/src/soc/intel/baytrail/baytrail/gpio.h index 8d7925b32b..8c90c89d26 100644 --- a/src/soc/intel/baytrail/baytrail/gpio.h +++ b/src/soc/intel/baytrail/baytrail/gpio.h @@ -204,6 +204,25 @@ #define GPIO_FUNC5 GPIO_FUNC(5, PULL_DISABLE, 10K) #define GPIO_FUNC6 GPIO_FUNC(6, PULL_DISABLE, 10K) +/* ACPI GPIO routing. Assume everything is externally pulled and negative edge + * triggered. */ +#define GPIO_ACPI_SCI \ + { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT | PAD_FUNC0, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT_ENABLE, \ + .use_sel = GPIO_USE_LEGACY, \ + .io_sel = GPIO_DIR_INPUT, \ + .tne = 1, \ + .wake_en = 1, } +#define GPIO_ACPI_SMI \ + { .pad_conf0 = PAD_PULL_DISABLE | PAD_CONFIG0_DEFAULT | PAD_FUNC0, \ + .pad_conf1 = PAD_CONFIG1_DEFAULT, \ + .pad_val = PAD_VAL_INPUT_ENABLE, \ + .use_sel = GPIO_USE_LEGACY, \ + .io_sel = GPIO_DIR_INPUT, \ + .tne = 1, \ + .smi = 1} + /* End marker */ #define GPIO_LIST_END 0xffffffff @@ -227,6 +246,7 @@ struct soc_gpio_map { u8 tpe : 1; u8 tne : 1; u8 wake_en : 1; + u8 smi : 1; } __attribute__ ((packed)); struct soc_gpio_config { diff --git a/src/soc/intel/baytrail/baytrail/pmc.h b/src/soc/intel/baytrail/baytrail/pmc.h index 1a7588cc20..f314d1dd76 100644 --- a/src/soc/intel/baytrail/baytrail/pmc.h +++ b/src/soc/intel/baytrail/baytrail/pmc.h @@ -68,6 +68,11 @@ # define USH_SS_PHY_DIS (1 << 2) # define OTG_SS_PHY_DIS (1 << 1) # define SMBUS_DIS (1 << 0) +#define GPIO_ROUT 0x58 +# define ROUTE_MASK 3 +# define ROUTE_NONE 0 +# define ROUTE_SMI 1 +# define ROUTE_SCI 2 /* IO Mapped registers behind ACPI_BASE_ADDRESS */ #define PM1_STS 0x00 diff --git a/src/soc/intel/baytrail/baytrail/smm.h b/src/soc/intel/baytrail/baytrail/smm.h index 19a0695df8..e00944d520 100644 --- a/src/soc/intel/baytrail/baytrail/smm.h +++ b/src/soc/intel/baytrail/baytrail/smm.h @@ -34,8 +34,10 @@ static inline int smm_region_size(void) void *smm_region_start(void); #if !defined(__PRE_RAM__) && !defined(__SMM___) +#include <stdint.h> void southcluster_smm_clear_state(void); void southcluster_smm_enable_smi(void); +void southcluster_smm_save_gpio_route(uint32_t route); #endif #endif /* _BAYTRAIL_SMM_H_ */ diff --git a/src/soc/intel/baytrail/gpio.c b/src/soc/intel/baytrail/gpio.c index 2916c999b6..824ed6560b 100644 --- a/src/soc/intel/baytrail/gpio.c +++ b/src/soc/intel/baytrail/gpio.c @@ -17,9 +17,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <baytrail/gpio.h> #include <device/pci.h> #include <console/console.h> +#include <baytrail/gpio.h> +#include <baytrail/pmc.h> +#include <baytrail/smm.h> /* GPIO-to-Pad LUTs */ static const u8 gpncore_gpio_to_pad[GPNCORE_COUNT] = @@ -154,12 +156,36 @@ static void setup_gpios(const struct soc_gpio_map *gpios, } } +static void setup_gpio_route(const struct soc_gpio_map *sus, + const struct soc_gpio_map *core) +{ + uint32_t route_reg = 0; + int i; + + for (i = 0; i < 8; i++) { + /* SMI takes precedence and wake_en implies SCI. */ + if (sus[i].smi) { + route_reg |= ROUTE_SMI << (2 * i); + } else if (sus[i].wake_en) { + route_reg |= ROUTE_SCI << (2 * i); + } + + if (core[i].smi) { + route_reg |= ROUTE_SMI << (2 * (i + 8)); + } else if (core[i].wake_en) { + route_reg |= ROUTE_SCI << (2 * (i + 8)); + } + } + southcluster_smm_save_gpio_route(route_reg); +} + void setup_soc_gpios(struct soc_gpio_config *config) { if (config) { setup_gpios(config->ncore, &gpncore_bank); setup_gpios(config->score, &gpscore_bank); setup_gpios(config->ssus, &gpssus_bank); + setup_gpio_route(config->ssus, config->score); } } diff --git a/src/soc/intel/baytrail/smm.c b/src/soc/intel/baytrail/smm.c index 124f93be59..1ba6246596 100644 --- a/src/soc/intel/baytrail/smm.c +++ b/src/soc/intel/baytrail/smm.c @@ -27,9 +27,19 @@ #include <cpu/x86/smm.h> #include <string.h> +#include <baytrail/iomap.h> #include <baytrail/pmc.h> #include <baytrail/smm.h> +/* Save the gpio route register. The settings are committed from + * southcluster_smm_enable_smi(). */ +static uint32_t gpio_route; + +void southcluster_smm_save_gpio_route(uint32_t route) +{ + gpio_route = route; +} + void southcluster_smm_clear_state(void) { uint32_t smi_en; @@ -53,13 +63,42 @@ void southcluster_smm_clear_state(void) clear_gpe_status(); } +static void southcluster_smm_route_gpios(void) +{ + const unsigned long gpio_rout = PMC_BASE_ADDRESS + GPIO_ROUT; + const unsigned short alt_gpio_smi = ACPI_BASE_ADDRESS + ALT_GPIO_SMI; + uint32_t alt_gpio_reg = 0; + uint32_t route_reg = gpio_route; + int i; + + printk(BIOS_DEBUG, "GPIO_ROUT = %08x\n", route_reg); + + /* Start the routing for the specific gpios. */ + write32(gpio_rout, route_reg); + + /* Enable SMIs for the gpios that are set to trigger the SMI. */ + for (i = 0; i < 16; i++) { + if ((route_reg & ROUTE_MASK) == ROUTE_SMI) { + alt_gpio_reg |= (1 << i); + } + route_reg >>= 2; + } + printk(BIOS_DEBUG, "ALT_GPIO_SMI = %08x\n", alt_gpio_reg); + + outl(alt_gpio_reg, alt_gpio_smi); +} + void southcluster_smm_enable_smi(void) { + printk(BIOS_DEBUG, "Enabling SMIs.\n"); /* Configure events */ enable_pm1(PWRBTN_EN | GBL_EN); disable_gpe(PME_B0_EN); + /* Set up the GPIO route. */ + southcluster_smm_route_gpios(); + /* Enable SMI generation: * - on TCO events * - on APMC writes (io 0xb2) |