[coreboot-gerrit] New patch to review for coreboot: soc/intel/apollolake: work around FSP for gpio interrupt polarity

Aaron Durbin (adurbin@chromium.org) gerrit at coreboot.org
Wed Jul 13 09:00:43 CEST 2016


Aaron Durbin (adurbin at chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15649

-gerrit

commit 64b534b08ddc8185e8118a0a4ecf7c1e284881d9
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Wed Jul 13 01:49:10 2016 -0500

    soc/intel/apollolake: work around FSP for gpio interrupt polarity
    
    FSP is currently setting a hard-coded policy for the interrupt
    polarity settings. When the mainboard has already set the GPIO
    settings up prior to SiliconInit being called that results
    in the previous settings being dropped. Work around FSP's
    default policy until FSP is fixed.
    
    BUG=chrome-os-partner:54955
    
    Change-Id: Ibbd8c4894d8fbce479aeb73aa775b67df15dae85
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/soc/intel/apollolake/chip.c             |  8 +++
 src/soc/intel/apollolake/include/soc/itss.h |  7 +++
 src/soc/intel/apollolake/itss.c             | 86 +++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+)

diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c
index ae9f09e..0d4cfce 100644
--- a/src/soc/intel/apollolake/chip.c
+++ b/src/soc/intel/apollolake/chip.c
@@ -29,6 +29,7 @@
 #include <soc/iomap.h>
 #include <soc/cpu.h>
 #include <soc/intel/common/vbt.h>
+#include <soc/itss.h>
 #include <soc/nvs.h>
 #include <soc/pci_devs.h>
 #include <spi-generic.h>
@@ -149,11 +150,18 @@ static void soc_init(void *data)
 	if (locate_vbt(&vbt_rdev) != CB_ERR)
 		vbt = rdev_mmap_full(&vbt_rdev);
 
+	/* Snapshot the current GPIO IRQ polarities. FSP is setting a
+	 * default policy that doesn't honor boards' requirements. */
+	itss_snapshot_irq_polarities(GPIO_IRQ_START, GPIO_IRQ_END);
+
 	/* TODO: tigten this resource range */
 	/* TODO: fix for S3 resume, as this would corrupt OS memory */
 	range_entry_init(&range, 0x200000, 4ULL*GiB, 0);
 	fsp_silicon_init(&range);
 
+	/* Restore GPIO IRQ polarities back to previous settings. */
+	itss_restore_irq_polarities(GPIO_IRQ_START, GPIO_IRQ_END);
+
 	/*
 	 * Keep the P2SB device visible so it and the other devices are
 	 * visible in coreboot for driver support and PCI resource allocation.
diff --git a/src/soc/intel/apollolake/include/soc/itss.h b/src/soc/intel/apollolake/include/soc/itss.h
index 1de7226..2f47ec6 100644
--- a/src/soc/intel/apollolake/include/soc/itss.h
+++ b/src/soc/intel/apollolake/include/soc/itss.h
@@ -16,7 +16,14 @@
 #ifndef _SOC_APOLLOLAKE_ITSS_H_
 #define _SOC_APOLLOLAKE_ITSS_H_
 
+#define GPIO_IRQ_START 50
+#define GPIO_IRQ_END 119
+
 /* Set the interrupt polarity for provided IRQ to the APIC. */
 void itss_set_irq_polarity(int irq, int active_low);
 
+/* Snapshot and restore IRQ polarity settings for the inclusive range. */
+void itss_snapshot_irq_polarities(int start, int end);
+void itss_restore_irq_polarities(int start, int end);
+
 #endif /* _SOC_APOLLOLAKE_ITSS_H_ */
diff --git a/src/soc/intel/apollolake/itss.c b/src/soc/intel/apollolake/itss.c
index 60d3e06..9c49d6c 100644
--- a/src/soc/intel/apollolake/itss.c
+++ b/src/soc/intel/apollolake/itss.c
@@ -13,6 +13,8 @@
  * GNU General Public License for more details.
  */
 
+#include <commonlib/helpers.h>
+#include <console/console.h>
 #include <stdint.h>
 #include <soc/iosf.h>
 #include <soc/itss.h>
@@ -21,6 +23,7 @@
 #define ITSS_MAX_IRQ		119
 #define IPC0			0x3200
 #define IRQS_PER_IPC		32
+#define NUM_IPC_REGS		((ITSS_MAX_IRQ + IRQS_PER_IPC - 1)/IRQS_PER_IPC)
 
 void itss_set_irq_polarity(int irq, int active_low)
 {
@@ -41,3 +44,86 @@ void itss_set_irq_polarity(int irq, int active_low)
 	val |= active_low ? mask : 0;
 	iosf_write(port, reg, val);
 }
+
+static uint32_t irq_snapshot[NUM_IPC_REGS];
+
+void itss_snapshot_irq_polarities(int start, int end)
+{
+	int i;
+	int reg_start;
+	int reg_end;
+	const uint16_t port = IOSF_ITSS_PORT_ID;
+
+	if (start < 0 || start > ITSS_MAX_IRQ ||
+	    end < 0 || end > ITSS_MAX_IRQ || end < start)
+		return;
+
+	reg_start = start / IRQS_PER_IPC;
+	reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC;
+
+	for (i = reg_start; i < reg_end; i++) {
+		uint16_t reg = IPC0 + sizeof(uint32_t) * i;
+		irq_snapshot[i] = iosf_read(port, reg);
+	}
+}
+
+static void show_irq_polarities(const char *msg)
+{
+	int i;
+	const uint16_t port = IOSF_ITSS_PORT_ID;
+
+	printk(BIOS_INFO, "ITSS IRQ Polarities %s:\n", msg);
+	for (i = 0; i < NUM_IPC_REGS; i++) {
+		uint16_t reg = IPC0 + sizeof(uint32_t) * i;
+		printk(BIOS_INFO, "IPC%d: 0x%08x\n", i, iosf_read(port, reg));
+	}
+}
+
+void itss_restore_irq_polarities(int start, int end)
+{
+	int i;
+	int reg_start;
+	int reg_end;
+	const uint16_t port = IOSF_ITSS_PORT_ID;
+
+	if (start < 0 || start > ITSS_MAX_IRQ ||
+	    end < 0 || end > ITSS_MAX_IRQ || end < start)
+		return;
+
+	show_irq_polarities("Before");
+
+	reg_start = start / IRQS_PER_IPC;
+	reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC;
+
+	for (i = reg_start; i < reg_end; i++) {
+		uint32_t mask;
+		uint32_t val;
+		uint16_t reg;
+		int irq_start;
+		int irq_end;
+
+		irq_start = i * IRQS_PER_IPC;
+		irq_end = MIN(irq_start + IRQS_PER_IPC - 1, ITSS_MAX_IRQ);
+
+		if (start > irq_end)
+			continue;
+		if (end < irq_start)
+			break;
+
+		/* Track bits within the bounds of of the register. */
+		irq_start = MAX(start, irq_start) % IRQS_PER_IPC;
+		irq_end = MIN(end, irq_end) % IRQS_PER_IPC;
+
+		/* Create bitmask of the inclusive range of start and end. */
+		mask = (((1U << irq_end) - 1) | (1U << irq_end));
+		mask &= ~((1U << irq_start) - 1);
+
+		reg = IPC0 + sizeof(uint32_t) * i;
+		val = iosf_read(port, reg);
+		val &= ~mask;
+		val |= mask & irq_snapshot[i];
+		iosf_write(port, reg, val);
+	}
+
+	show_irq_polarities("After");
+}



More information about the coreboot-gerrit mailing list