diff options
-rw-r--r-- | src/soc/intel/quark/include/soc/iomap.h | 9 | ||||
-rw-r--r-- | src/soc/intel/quark/include/soc/reg_access.h | 22 | ||||
-rw-r--r-- | src/soc/intel/quark/lpc.c | 18 | ||||
-rw-r--r-- | src/soc/intel/quark/reg_access.c | 35 | ||||
-rw-r--r-- | src/soc/intel/quark/romstage/romstage.c | 19 |
5 files changed, 97 insertions, 6 deletions
diff --git a/src/soc/intel/quark/include/soc/iomap.h b/src/soc/intel/quark/include/soc/iomap.h index ce92676c54..61773d5d4c 100644 --- a/src/soc/intel/quark/include/soc/iomap.h +++ b/src/soc/intel/quark/include/soc/iomap.h @@ -30,10 +30,13 @@ /* * I/O port address space */ -#define ACPI_BASE_ADDRESS 0x1000 -#define ACPI_BASE_SIZE 0x100 +#define GPE0_BASE_ADDRESS 0x2000 +#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 IO_ADDRESS_VALID 0x80000000 diff --git a/src/soc/intel/quark/include/soc/reg_access.h b/src/soc/intel/quark/include/soc/reg_access.h index 580400c331..e7a8963b8c 100644 --- a/src/soc/intel/quark/include/soc/reg_access.h +++ b/src/soc/intel/quark/include/soc/reg_access.h @@ -35,6 +35,7 @@ enum { GPIO_REGS, PCIE_AFE_REGS, PCIE_RESET, + GPE0_REGS, }; enum { @@ -46,6 +47,27 @@ enum { _REG_SCRIPT_ENCODE_RAW(REG_SCRIPT_COMMAND_##cmd_, SOC_TYPE, \ 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 */ #define REG_GPIO_ACCESS(cmd_, reg_, mask_, value_, timeout_) \ SOC_ACCESS(cmd_, reg_, REG_SCRIPT_SIZE_32, mask_, value_, timeout_, \ diff --git a/src/soc/intel/quark/lpc.c b/src/soc/intel/quark/lpc.c index fbed93582e..e57b71746d 100644 --- a/src/soc/intel/quark/lpc.c +++ b/src/soc/intel/quark/lpc.c @@ -30,10 +30,22 @@ static void pmc_read_resources(device_t dev) /* Get the normal PCI resources of this device. */ pci_dev_read_resources(dev); - /* PMBASE */ + /* GPE0 */ res = new_resource(dev, index++); - res->base = ACPI_BASE_ADDRESS; - res->size = ACPI_BASE_SIZE; + res->base = GPE0_BASE_ADDRESS; + 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; } diff --git a/src/soc/intel/quark/reg_access.c b/src/soc/intel/quark/reg_access.c index f7820e9f4c..30cc7db18a 100644 --- a/src/soc/intel/quark/reg_access.c +++ b/src/soc/intel/quark/reg_access.c @@ -19,6 +19,19 @@ #include <soc/pci_devs.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) { uint32_t gpio_base_address; @@ -83,6 +96,18 @@ void mea_write(uint32_t reg_address) & 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) { /* 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; return 0; + case GPE0_REGS: + ctx->display_prefix = "GPE0: "; + value = reg_gpe0_read(step->reg); + break; + case GPIO_REGS: ctx->display_prefix = "GPIO: "; 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; return; + case GPE0_REGS: + ctx->display_prefix = "GPE0: "; + reg_gpe0_write(step->reg, (uint32_t)step->value); + break; + case GPIO_REGS: ctx->display_prefix = "GPIO: "; reg_gpio_write(step->reg, (uint32_t)step->value); diff --git a/src/soc/intel/quark/romstage/romstage.c b/src/soc/intel/quark/romstage/romstage.c index 4ed5863179..c4f9844754 100644 --- a/src/soc/intel/quark/romstage/romstage.c +++ b/src/soc/intel/quark/romstage/romstage.c @@ -30,10 +30,22 @@ #include <soc/romstage.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[] = { /* Temporarily enable the legacy GPIO controller */ REG_PCI_WRITE32(R_QNC_LPC_GBA_BASE, IO_ADDRESS_VALID | 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_SCRIPT_END }; @@ -81,6 +93,7 @@ void soc_memory_init_params(struct romstage_params *params, char *pdat_file; size_t pdat_file_len; const struct soc_intel_quark_config *config; + struct chipset_power_state *ps = car_get_var_ptr(&power_state); /* Locate the pdat.bin file */ 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 */ 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) |