summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/quark/include/soc/iomap.h9
-rw-r--r--src/soc/intel/quark/include/soc/reg_access.h22
-rw-r--r--src/soc/intel/quark/lpc.c18
-rw-r--r--src/soc/intel/quark/reg_access.c35
-rw-r--r--src/soc/intel/quark/romstage/romstage.c19
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)