soc/intel/quark: Clear SMI interrupts and wake events

Migrate the clearing of the SMI interrupts and wake events from FSP into
coreboot.

TEST=Build and run on Galileo Gen2

Change-Id: Ia369801da87a16bc00fb2c05475831ebe8a315f8
Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com>
Reviewed-on: https://review.coreboot.org/14945
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
Lee Leahy 2016-05-22 11:52:28 -07:00 committed by Leroy P Leahy
parent 773ee2bb17
commit 7f4b053980
5 changed files with 97 additions and 6 deletions

View File

@ -30,10 +30,13 @@
/* /*
* I/O port address space * I/O port address space
*/ */
#define ACPI_BASE_ADDRESS 0x1000 #define GPE0_BASE_ADDRESS 0x2000
#define ACPI_BASE_SIZE 0x100 #define GPE0_SIZE 0x40
#define LEGACY_GPIO_BASE_ADDRESS 0x1080 #define PM1BLK_BASE_ADDRESS 0x2040
#define PM1BLK_SIZE 0x10
#define LEGACY_GPIO_BASE_ADDRESS 0x2080
#define LEGACY_GPIO_SIZE 0x80 #define LEGACY_GPIO_SIZE 0x80
#define IO_ADDRESS_VALID 0x80000000 #define IO_ADDRESS_VALID 0x80000000

View File

@ -35,6 +35,7 @@ enum {
GPIO_REGS, GPIO_REGS,
PCIE_AFE_REGS, PCIE_AFE_REGS,
PCIE_RESET, PCIE_RESET,
GPE0_REGS,
}; };
enum { enum {
@ -46,6 +47,27 @@ enum {
_REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_##cmd_, SOC_TYPE, \ _REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_##cmd_, SOC_TYPE, \
size_, reg_, mask_, value_, timeout_, reg_set_) size_, reg_, mask_, value_, timeout_, reg_set_)
/* GPE0 controller register access macros */
#define REG_GPE0_ACCESS(cmd_, reg_, mask_, value_, timeout_) \
SOC_ACCESS(cmd_, reg_, REG_SCRIPT_SIZE_32, mask_, value_, timeout_, \
GPE0_REGS)
#define REG_GPE0_READ(reg_) \
REG_GPE0_ACCESS(READ, reg_, 0, 0, 0)
#define REG_GPE0_WRITE(reg_, value_) \
REG_GPE0_ACCESS(WRITE, reg_, 0, value_, 0)
#define REG_GPE0_AND(reg_, value_) \
REG_GPE0_RMW(reg_, value_, 0)
#define REG_GPE0_RMW(reg_, mask_, value_) \
REG_GPE0_ACCESS(RMW, reg_, mask_, value_, 0)
#define REG_GPE0_RXW(reg_, mask_, value_) \
REG_GPE0_ACCESS(RXW, reg_, mask_, value_, 0)
#define REG_GPE0_OR(reg_, value_) \
REG_GPE0_RMW(reg_, 0xffffffff, value_)
#define REG_GPE0_POLL(reg_, mask_, value_, timeout_) \
REG_GPE0_ACCESS(POLL, reg_, mask_, value_, timeout_)
#define REG_GPE0_XOR(reg_, value_) \
REG_GPE0_RXW(reg_, 0xffffffff, value_)
/* GPIO controller register access macros */ /* GPIO controller register access macros */
#define REG_GPIO_ACCESS(cmd_, reg_, mask_, value_, timeout_) \ #define REG_GPIO_ACCESS(cmd_, reg_, mask_, value_, timeout_) \
SOC_ACCESS(cmd_, reg_, REG_SCRIPT_SIZE_32, mask_, value_, timeout_, \ SOC_ACCESS(cmd_, reg_, REG_SCRIPT_SIZE_32, mask_, value_, timeout_, \

View File

@ -30,10 +30,22 @@ static void pmc_read_resources(device_t dev)
/* Get the normal PCI resources of this device. */ /* Get the normal PCI resources of this device. */
pci_dev_read_resources(dev); pci_dev_read_resources(dev);
/* PMBASE */ /* GPE0 */
res = new_resource(dev, index++); res = new_resource(dev, index++);
res->base = ACPI_BASE_ADDRESS; res->base = GPE0_BASE_ADDRESS;
res->size = ACPI_BASE_SIZE; res->size = GPE0_SIZE;
res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
/* PM1BLK */
res = new_resource(dev, index++);
res->base = PM1BLK_BASE_ADDRESS;
res->size = PM1BLK_SIZE;
res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
/* Legacy GPIO */
res = new_resource(dev, index++);
res->base = LEGACY_GPIO_BASE_ADDRESS;
res->size = LEGACY_GPIO_SIZE;
res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
} }

View File

@ -19,6 +19,19 @@
#include <soc/pci_devs.h> #include <soc/pci_devs.h>
#include <soc/ramstage.h> #include <soc/ramstage.h>
static uint16_t get_gpe0_address(uint32_t reg_address)
{
uint32_t gpe0_base_address;
/* Get the GPE0 base address */
gpe0_base_address = pci_read_config32(LPC_BDF, R_QNC_LPC_GPE0BLK);
ASSERT (gpe0_base_address >= 0x80000000);
gpe0_base_address &= B_QNC_LPC_GPE0BLK_MASK;
/* Return the GPE0 register address */
return (uint16_t)(gpe0_base_address + reg_address);
}
static uint32_t *get_gpio_address(uint32_t reg_address) static uint32_t *get_gpio_address(uint32_t reg_address)
{ {
uint32_t gpio_base_address; uint32_t gpio_base_address;
@ -83,6 +96,18 @@ void mea_write(uint32_t reg_address)
& QNC_MEA_MASK); & QNC_MEA_MASK);
} }
static uint32_t reg_gpe0_read(uint32_t reg_address)
{
/* Read the GPE0 register */
return inl(get_gpe0_address(reg_address));
}
static void reg_gpe0_write(uint32_t reg_address, uint32_t value)
{
/* Write the GPE0 register */
outl(get_gpe0_address(reg_address), value);
}
static uint32_t reg_gpio_read(uint32_t reg_address) static uint32_t reg_gpio_read(uint32_t reg_address)
{ {
/* Read the GPIO register */ /* Read the GPIO register */
@ -190,6 +215,11 @@ static uint64_t reg_read(struct reg_script_context *ctx)
ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING; ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
return 0; return 0;
case GPE0_REGS:
ctx->display_prefix = "GPE0: ";
value = reg_gpe0_read(step->reg);
break;
case GPIO_REGS: case GPIO_REGS:
ctx->display_prefix = "GPIO: "; ctx->display_prefix = "GPIO: ";
value = reg_gpio_read(step->reg); value = reg_gpio_read(step->reg);
@ -234,6 +264,11 @@ static void reg_write(struct reg_script_context *ctx)
ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING; ctx->display_features = REG_SCRIPT_DISPLAY_NOTHING;
return; return;
case GPE0_REGS:
ctx->display_prefix = "GPE0: ";
reg_gpe0_write(step->reg, (uint32_t)step->value);
break;
case GPIO_REGS: case GPIO_REGS:
ctx->display_prefix = "GPIO: "; ctx->display_prefix = "GPIO: ";
reg_gpio_write(step->reg, (uint32_t)step->value); reg_gpio_write(step->reg, (uint32_t)step->value);

View File

@ -30,10 +30,22 @@
#include <soc/romstage.h> #include <soc/romstage.h>
#include <soc/reg_access.h> #include <soc/reg_access.h>
static const struct reg_script clear_smi_and_wake_events[] = {
/* Clear any SMI or wake events */
REG_GPE0_READ(R_QNC_GPE0BLK_GPE0S),
REG_GPE0_READ(R_QNC_GPE0BLK_SMIS),
REG_GPE0_OR(R_QNC_GPE0BLK_GPE0S, B_QNC_GPE0BLK_GPE0S_ALL),
REG_GPE0_OR(R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_ALL),
REG_SCRIPT_END
};
static const struct reg_script legacy_gpio_init[] = { static const struct reg_script legacy_gpio_init[] = {
/* Temporarily enable the legacy GPIO controller */ /* Temporarily enable the legacy GPIO controller */
REG_PCI_WRITE32(R_QNC_LPC_GBA_BASE, IO_ADDRESS_VALID REG_PCI_WRITE32(R_QNC_LPC_GBA_BASE, IO_ADDRESS_VALID
| LEGACY_GPIO_BASE_ADDRESS), | LEGACY_GPIO_BASE_ADDRESS),
/* Temporarily enable the GPE controller */
REG_PCI_WRITE32(R_QNC_LPC_GPE0BLK, IO_ADDRESS_VALID
| GPE0_BASE_ADDRESS),
REG_PCI_OR8(PCI_COMMAND, PCI_COMMAND_IO), REG_PCI_OR8(PCI_COMMAND, PCI_COMMAND_IO),
REG_SCRIPT_END REG_SCRIPT_END
}; };
@ -81,6 +93,7 @@ void soc_memory_init_params(struct romstage_params *params,
char *pdat_file; char *pdat_file;
size_t pdat_file_len; size_t pdat_file_len;
const struct soc_intel_quark_config *config; const struct soc_intel_quark_config *config;
struct chipset_power_state *ps = car_get_var_ptr(&power_state);
/* Locate the pdat.bin file */ /* Locate the pdat.bin file */
pdat_file = cbfs_boot_map_with_leak("pdat.bin", CBFS_TYPE_RAW, pdat_file = cbfs_boot_map_with_leak("pdat.bin", CBFS_TYPE_RAW,
@ -104,6 +117,12 @@ void soc_memory_init_params(struct romstage_params *params,
/* Display the ROM shadow data */ /* Display the ROM shadow data */
hexdump((void *)0x000ffff0, 0x10); hexdump((void *)0x000ffff0, 0x10);
/* Clear SMI and wake events */
if (ps->prev_sleep_state != 3) {
printk(BIOS_SPEW, "Clearing SMI interrupts and wake events\n");
reg_script_run_on_dev(LPC_BDF, clear_smi_and_wake_events);
}
} }
void soc_after_ram_init(struct romstage_params *params) void soc_after_ram_init(struct romstage_params *params)