aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/soc/intel/apollolake/gpio.c32
-rw-r--r--src/soc/intel/apollolake/include/soc/gpio_defs.h1
2 files changed, 33 insertions, 0 deletions
diff --git a/src/soc/intel/apollolake/gpio.c b/src/soc/intel/apollolake/gpio.c
index 699c8fea28..a3ffb3de0f 100644
--- a/src/soc/intel/apollolake/gpio.c
+++ b/src/soc/intel/apollolake/gpio.c
@@ -19,6 +19,7 @@
#include <gpio.h>
#include <soc/gpio.h>
#include <soc/iosf.h>
+#include <soc/itss.h>
#include <soc/pm.h>
/* This list must be in order, from highest pad numbers, to lowest pad numbers*/
@@ -53,12 +54,43 @@ static const struct pad_community *gpio_get_community(uint16_t pad)
return map;
}
+static void gpio_configure_itss(const struct pad_config *cfg,
+ uint16_t port, uint16_t pad_cfg_offset)
+{
+ int irq;
+
+ /* Set up ITSS polarity if pad is routed to APIC.
+ *
+ * The ITSS takes only active high interrupt signals. Therefore,
+ * if the pad configuration indicates an inversion assume the
+ * intent is for the ITSS polarity. Before forwarding on the
+ * request to the APIC there's an inversion setting for how the
+ * signal is forwarded to the APIC. Honor the inversion setting
+ * in the GPIO pad configuration so that a hardware active low
+ * signal looks that way to the APIC (double inversion).
+ */
+ if (!(cfg->config0 & PAD_CFG0_ROUTE_IOAPIC))
+ return;
+
+ irq = iosf_read(port, pad_cfg_offset + sizeof(uint32_t));
+ irq &= PAD_CFG1_IRQ_MASK;
+ if (!irq) {
+ printk(BIOS_ERR, "GPIO %u doesn't support APIC routing,\n",
+ cfg->pad);
+ return;
+ }
+
+ itss_set_irq_polarity(irq, !!(cfg->config0 & PAD_CFG0_RX_POL_INVERT));
+}
+
void gpio_configure_pad(const struct pad_config *cfg)
{
const struct pad_community *comm = gpio_get_community(cfg->pad);
uint16_t config_offset = PAD_CFG_OFFSET(cfg->pad - comm->first_pad);
iosf_write(comm->port, config_offset, cfg->config0);
iosf_write(comm->port, config_offset + sizeof(uint32_t), cfg->config1);
+
+ gpio_configure_itss(cfg, comm->port, config_offset);
}
void gpio_configure_pads(const struct pad_config *cfg, size_t num_pads)
diff --git a/src/soc/intel/apollolake/include/soc/gpio_defs.h b/src/soc/intel/apollolake/include/soc/gpio_defs.h
index c6e2c3cf91..48e08e783e 100644
--- a/src/soc/intel/apollolake/include/soc/gpio_defs.h
+++ b/src/soc/intel/apollolake/include/soc/gpio_defs.h
@@ -75,6 +75,7 @@
#define PAD_CFG0_RESET_PLTRST (2 << 30)
#define PAD_CFG0_RESET_RSMRST (3 << 30)
+#define PAD_CFG1_IRQ_MASK (0xff << 0)
#define PAD_CFG1_PULL_MASK (0xf << 10)
#define PAD_CFG1_PULL_NONE (0x0 << 10)
#define PAD_CFG1_PULL_DN_5K (0x2 << 10)