[coreboot-gerrit] Patch set updated for coreboot: 12c994b intel SMI handlers: Refactor GPI SMI/SCI routing

Kyösti Mälkki (kyosti.malkki@gmail.com) gerrit at coreboot.org
Thu Jan 8 18:41:21 CET 2015


Kyösti Mälkki (kyosti.malkki at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/7967

-gerrit

commit 12c994b3d1a8ec1c59a04c8711c4d6b55a66115c
Author: Kyösti Mälkki <kyosti.malkki at gmail.com>
Date:   Mon Dec 29 11:32:27 2014 +0200

    intel SMI handlers: Refactor GPI SMI/SCI routing
    
    For lenovo/x201, this also changes GPI_ROUT (0xb8-0xbb)
    programming to change GPI1 between SCI/SMI modes, while
    previous programming was for GPI12.
    
    Change-Id: Iab14cf347584513793f417febc47f0559e17f5a5
    Signed-off-by: Kyösti Mälkki <kyosti.malkki at gmail.com>
---
 src/mainboard/apple/macbook21/smihandler.c    | 22 +++-----------
 src/mainboard/google/parrot/smihandler.c      | 43 ++-------------------------
 src/mainboard/lenovo/t420s/smihandler.c       | 37 +++++------------------
 src/mainboard/lenovo/t520/smihandler.c        | 37 +++++------------------
 src/mainboard/lenovo/t530/smihandler.c        | 37 +++++------------------
 src/mainboard/lenovo/t60/smihandler.c         | 24 ++++-----------
 src/mainboard/lenovo/x201/smihandler.c        | 37 +++++------------------
 src/mainboard/lenovo/x220/smihandler.c        | 37 +++++------------------
 src/mainboard/lenovo/x230/smihandler.c        | 38 +++++------------------
 src/mainboard/lenovo/x60/smihandler.c         | 24 ++++-----------
 src/mainboard/packardbell/ms2290/smihandler.c | 24 +++++----------
 src/southbridge/intel/bd82x6x/lpc.c           |  2 +-
 src/southbridge/intel/bd82x6x/pch.h           |  6 ++++
 src/southbridge/intel/bd82x6x/smihandler.c    | 36 ++++++++++++++++++++++
 src/southbridge/intel/fsp_bd82x6x/lpc.c       |  2 +-
 src/southbridge/intel/i82801gx/i82801gx.h     |  7 +++++
 src/southbridge/intel/i82801gx/lpc.c          |  2 +-
 src/southbridge/intel/i82801gx/smihandler.c   | 36 ++++++++++++++++++++++
 src/southbridge/intel/ibexpeak/lpc.c          |  2 +-
 src/southbridge/intel/ibexpeak/pch.h          |  6 ++++
 src/southbridge/intel/ibexpeak/smihandler.c   | 36 ++++++++++++++++++++++
 src/southbridge/intel/lynxpoint/lpc.c         |  2 +-
 22 files changed, 198 insertions(+), 299 deletions(-)

diff --git a/src/mainboard/apple/macbook21/smihandler.c b/src/mainboard/apple/macbook21/smihandler.c
index 449e367..4e4a4b6 100644
--- a/src/mainboard/apple/macbook21/smihandler.c
+++ b/src/mainboard/apple/macbook21/smihandler.c
@@ -27,6 +27,8 @@
 #include <pc80/mc146818rtc.h>
 #include <delay.h>
 
+#define GPE_H8SCI	12
+
 /* The southbridge SMI handler checks whether gnvs has a
  * valid pointer before calling the trap handler
  */
@@ -58,30 +60,14 @@ int mainboard_io_trap_handler(int smif)
 
 int mainboard_smi_apmc(u8 data)
 {
-	u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-	u8 tmp;
-
-	printk(BIOS_DEBUG, "%s: pmbase %04X, data %02X\n", __func__, pmbase, data);
-
-	if (!pmbase)
-		return 0;
-
 	switch(data) {
 		case APM_CNT_ACPI_ENABLE:
 			/* route H8SCI to SCI */
-			outw(inw(pmbase + ALT_GP_SMI_EN) & ~0x1000, pmbase + ALT_GP_SMI_EN);
-			tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-			tmp &= ~0x03;
-			tmp |= 0x02;
-			pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+			gpi_route_interrupt(GPE_H8SCI, GPI_IS_SCI);
 			break;
 		case APM_CNT_ACPI_DISABLE:
 			/* route H8SCI# to SMI */
-			outw(inw(pmbase + ALT_GP_SMI_EN) | 0x1000, pmbase + ALT_GP_SMI_EN);
-			tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-			tmp &= ~0x03;
-			tmp |= 0x01;
-			pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+			gpi_route_interrupt(GPE_H8SCI, GPI_IS_SMI);
 			break;
 		default:
 			break;
diff --git a/src/mainboard/google/parrot/smihandler.c b/src/mainboard/google/parrot/smihandler.c
index 4a189f8..1d1b23c 100644
--- a/src/mainboard/google/parrot/smihandler.c
+++ b/src/mainboard/google/parrot/smihandler.c
@@ -29,44 +29,6 @@
 #include <ec/compal/ene932/ec.h>
 #include "ec.h"
 
-/* Power Management PCI Configuration Registers
- * Bus 0, Device 31, Function 0, Offset 0xB8
- * 00 = No Effect
- * 01 = SMI#
- * 10 = SCI
- * 11 = NMI
- */
-#define GPI_ROUT	0x8000F8B8
-#define GPI_IS_SMI	0x01
-#define GPI_IS_SCI	0x02
-
-static void set_lid_gpi_mode(u32 mode)
-{
-	u32 reg32 = 0;
-	u16 reg16 = 0;
-
-	/* read the GPI register, clear the lid GPI's mode, write the new mode
-	 * and write out the register.
-	 */
-	outl(GPI_ROUT, 0xcf8);
-	reg32 = inl(0xcfc);
-	reg32 &= ~(0x03 << (EC_LID_GPI * 2));
-	reg32 |= (mode << (EC_LID_GPI * 2));
-	outl(GPI_ROUT, 0xcf8);
-	outl(reg32, 0xcfc);
-
-	/* Set or Disable Lid GPE as SMI source in the ALT_GPI_SMI_EN register. */
-	reg16 = inw(smm_get_pmbase() + ALT_GP_SMI_EN);
-	if (mode == GPI_IS_SCI) {
-		reg16 &= ~(1 << EC_LID_GPI);
-	} else {
-		reg16 |= (1 << EC_LID_GPI);
-	}
-	outw(reg16, smm_get_pmbase() + ALT_GP_SMI_EN);
-
-	return;
-}
-
 int mainboard_io_trap_handler(int smif)
 {
 	printk(BIOS_DEBUG, "mainboard_io_trap_handler: %x\n", smif);
@@ -200,8 +162,7 @@ int mainboard_smi_apmc(u8 apmc)
 		ec_kbc_write_ib(0xE8);
 
 		/* Set LID GPI to generate SCIs */
-		set_lid_gpi_mode(GPI_IS_SCI);
-
+		gpi_route_interrupt(EC_LID_GPI, GPI_IS_SCI);
 		break;
 	case APMC_ACPI_DIS:
 		printk(BIOS_DEBUG, "APMC: ACPI_DIS\n");
@@ -211,7 +172,7 @@ int mainboard_smi_apmc(u8 apmc)
 		ec_kbc_write_ib(0xE9);
 
 		/* Set LID GPI to generate SMIs */
-		set_lid_gpi_mode(GPI_IS_SMI);
+		gpi_route_interrupt(EC_LID_GPI, GPI_IS_SMI);
 		break;
 	}
 	return 0;
diff --git a/src/mainboard/lenovo/t420s/smihandler.c b/src/mainboard/lenovo/t420s/smihandler.c
index 6c80573..80a4e80 100644
--- a/src/mainboard/lenovo/t420s/smihandler.c
+++ b/src/mainboard/lenovo/t420s/smihandler.c
@@ -33,6 +33,9 @@
 #include <northbridge/intel/sandybridge/sandybridge.h>
 #include <cpu/intel/model_206ax/model_206ax.h>
 
+#define GPE_H8SCI	12
+#define GPE_EC_WAKE	13
+
 /* The southbridge SMI handler checks whether gnvs has a
  * valid pointer before calling the trap handler
  */
@@ -108,7 +111,7 @@ static void mainboard_smi_handle_ec_sci(void)
 
 void mainboard_smi_gpi(u32 gpi_sts)
 {
-	if (gpi_sts & (1 << 12))
+	if (gpi_sts & (1 << GPE_H8SCI))
 		mainboard_smi_handle_ec_sci();
 }
 
@@ -116,25 +119,12 @@ static int mainboard_finalized = 0;
 
 int mainboard_smi_apmc(u8 data)
 {
-	u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-	u8 tmp;
-
-	printk(BIOS_DEBUG, "%s: pmbase %04X, data %02X\n", __func__, pmbase,
-	       data);
-
-	if (!pmbase)
-		return 0;
-
 	switch (data) {
 		case APM_CNT_ACPI_ENABLE:
 			/* use 0x1600/0x1604 to prevent races with userspace */
 			ec_set_ports(0x1604, 0x1600);
 			/* route H8SCI to SCI */
-			outw(inw(pmbase + ALT_GP_SMI_EN) & ~0x1000, pmbase + ALT_GP_SMI_EN);
-			tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-			tmp &= ~0x03;
-			tmp |= 0x02;
-			pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+			gpi_route_interrupt(GPE_H8SCI, GPI_IS_SCI);
 			/* discard all events, and enable attention */
 			ec_write(0x80, 0x01);
 			break;
@@ -143,12 +133,7 @@ int mainboard_smi_apmc(u8 data)
 			   provide a EC query function */
 			ec_set_ports(0x66, 0x62);
 			/* route H8SCI# to SMI */
-			outw(inw(pmbase + ALT_GP_SMI_EN) | 0x1000,
-			     pmbase + ALT_GP_SMI_EN);
-			tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-			tmp &= ~0x03;
-			tmp |= 0x01;
-			pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+			gpi_route_interrupt(GPE_H8SCI, GPI_IS_SMI);
 			/* discard all events, and enable attention */
 			ec_write(0x80, 0x01);
 			break;
@@ -179,16 +164,8 @@ void mainboard_smi_sleep(u8 slp_typ)
 		u8 ec_wake = ec_read(0x32);
 		/* If EC wake events are enabled, enable wake on EC WAKE GPE.  */
 		if (ec_wake & 0x14) {
-			u32 gpe_rout;
-			u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-
-			/* Enable EC WAKE GPE.  */
-			outl(inl(pmbase + GPE0_EN) | (1 << 29), pmbase + GPE0_EN);
-			gpe_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT);
 			/* Redirect EC WAKE GPE to SCI.  */
-			gpe_rout &= ~(3 << 26);
-			gpe_rout |= (2 << 26);
-			pci_write_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT, gpe_rout);
+			gpi_route_interrupt(GPE_EC_WAKE, GPI_IS_SCI);
 		}
 	}
 }
diff --git a/src/mainboard/lenovo/t520/smihandler.c b/src/mainboard/lenovo/t520/smihandler.c
index bb3ad78..18fac5d 100644
--- a/src/mainboard/lenovo/t520/smihandler.c
+++ b/src/mainboard/lenovo/t520/smihandler.c
@@ -33,6 +33,9 @@
 #include <northbridge/intel/sandybridge/sandybridge.h>
 #include <cpu/intel/model_206ax/model_206ax.h>
 
+#define GPE_H8SCI	12
+#define GPE_EC_WAKE	13
+
 /* The southbridge SMI handler checks whether gnvs has a
  * valid pointer before calling the trap handler
  */
@@ -103,7 +106,7 @@ static void mainboard_smi_handle_ec_sci(void)
 
 void mainboard_smi_gpi(u32 gpi_sts)
 {
-	if (gpi_sts & (1 << 12))
+	if (gpi_sts & (1 << GPE_H8SCI))
 		mainboard_smi_handle_ec_sci();
 }
 
@@ -111,25 +114,12 @@ static int mainboard_finalized = 0;
 
 int mainboard_smi_apmc(u8 data)
 {
-	u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-	u8 tmp;
-
-	printk(BIOS_DEBUG, "%s: pmbase %04X, data %02X\n", __func__, pmbase,
-	       data);
-
-	if (!pmbase)
-		return 0;
-
 	switch (data) {
 	case APM_CNT_ACPI_ENABLE:
 		/* use 0x1600/0x1604 to prevent races with userspace */
 		ec_set_ports(0x1604, 0x1600);
 		/* route H8SCI to SCI */
-		outw(inw(pmbase + ALT_GP_SMI_EN) & ~0x1000, pmbase + ALT_GP_SMI_EN);
-		tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-		tmp &= ~0x03;
-		tmp |= 0x02;
-		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+		gpi_route_interrupt(GPE_H8SCI, GPI_IS_SCI);
 		/* discard all events, and enable attention */
 		ec_write(0x80, 0x01);
 		break;
@@ -138,12 +128,7 @@ int mainboard_smi_apmc(u8 data)
 		   provide a EC query function */
 		ec_set_ports(0x66, 0x62);
 		/* route H8SCI# to SMI */
-		outw(inw(pmbase + ALT_GP_SMI_EN) | 0x1000,
-		     pmbase + ALT_GP_SMI_EN);
-		tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-		tmp &= ~0x03;
-		tmp |= 0x01;
-		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+		gpi_route_interrupt(GPE_H8SCI, GPI_IS_SMI);
 		/* discard all events, and enable attention */
 		ec_write(0x80, 0x01);
 		break;
@@ -174,16 +159,8 @@ void mainboard_smi_sleep(u8 slp_typ)
 		u8 ec_wake = ec_read(0x32);
 		/* If EC wake events are enabled, enable wake on EC WAKE GPE.  */
 		if (ec_wake & 0x14) {
-			u32 gpe_rout;
-			u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-
-			/* Enable EC WAKE GPE.  */
-			outl(inl(pmbase + GPE0_EN) | (1 << 29), pmbase + GPE0_EN);
-			gpe_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT);
 			/* Redirect EC WAKE GPE to SCI.  */
-			gpe_rout &= ~(3 << 26);
-			gpe_rout |= (2 << 26);
-			pci_write_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT, gpe_rout);
+			gpi_route_interrupt(GPE_EC_WAKE, GPI_IS_SCI);
 		}
 	}
 }
diff --git a/src/mainboard/lenovo/t530/smihandler.c b/src/mainboard/lenovo/t530/smihandler.c
index 6f6cca1..fe7cd65 100644
--- a/src/mainboard/lenovo/t530/smihandler.c
+++ b/src/mainboard/lenovo/t530/smihandler.c
@@ -33,6 +33,9 @@
 #include <northbridge/intel/sandybridge/sandybridge.h>
 #include <cpu/intel/model_206ax/model_206ax.h>
 
+#define GPE_H8SCI	12
+#define GPE_EC_WAKE	13
+
 /* The southbridge SMI handler checks whether gnvs has a
  * valid pointer before calling the trap handler
  */
@@ -108,7 +111,7 @@ static void mainboard_smi_handle_ec_sci(void)
 
 void mainboard_smi_gpi(u32 gpi_sts)
 {
-	if (gpi_sts & (1 << 12))
+	if (gpi_sts & (1 << GPE_H8SCI))
 		mainboard_smi_handle_ec_sci();
 }
 
@@ -116,25 +119,12 @@ static int mainboard_finalized = 0;
 
 int mainboard_smi_apmc(u8 data)
 {
-	u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-	u8 tmp;
-
-	printk(BIOS_DEBUG, "%s: pmbase %04X, data %02X\n", __func__, pmbase,
-	       data);
-
-	if (!pmbase)
-		return 0;
-
 	switch (data) {
 	case APM_CNT_ACPI_ENABLE:
 		/* use 0x1600/0x1604 to prevent races with userspace */
 		ec_set_ports(0x1604, 0x1600);
 		/* route H8SCI to SCI */
-		outw(inw(pmbase + ALT_GP_SMI_EN) & ~0x1000, pmbase + ALT_GP_SMI_EN);
-		tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-		tmp &= ~0x03;
-		tmp |= 0x02;
-		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+		gpi_route_interrupt(GPE_H8SCI, GPI_IS_SCI);
 		/* discard all events, and enable attention */
 		ec_write(0x80, 0x01);
 		break;
@@ -143,12 +133,7 @@ int mainboard_smi_apmc(u8 data)
 		   provide a EC query function */
 		ec_set_ports(0x66, 0x62);
 		/* route H8SCI# to SMI */
-		outw(inw(pmbase + ALT_GP_SMI_EN) | 0x1000,
-		     pmbase + ALT_GP_SMI_EN);
-		tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-		tmp &= ~0x03;
-		tmp |= 0x01;
-		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+		gpi_route_interrupt(GPE_H8SCI, GPI_IS_SMI);
 		/* discard all events, and enable attention */
 		ec_write(0x80, 0x01);
 		break;
@@ -179,16 +164,8 @@ void mainboard_smi_sleep(u8 slp_typ)
 		u8 ec_wake = ec_read(0x32);
 		/* If EC wake events are enabled, enable wake on EC WAKE GPE.  */
 		if (ec_wake & 0x14) {
-			u32 gpe_rout;
-			u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-
-			/* Enable EC WAKE GPE.  */
-			outl(inl(pmbase + GPE0_EN) | (1 << 29), pmbase + GPE0_EN);
-			gpe_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT);
 			/* Redirect EC WAKE GPE to SCI.  */
-			gpe_rout &= ~(3 << 26);
-			gpe_rout |= (2 << 26);
-			pci_write_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT, gpe_rout);
+			gpi_route_interrupt(GPE_EC_WAKE, GPI_IS_SCI);
 		}
 	}
 }
diff --git a/src/mainboard/lenovo/t60/smihandler.c b/src/mainboard/lenovo/t60/smihandler.c
index 36495dc..d3ada43 100644
--- a/src/mainboard/lenovo/t60/smihandler.c
+++ b/src/mainboard/lenovo/t60/smihandler.c
@@ -28,6 +28,8 @@
 #include "dock.h"
 #include "smi.h"
 
+#define GPE_H8SCI	12
+
 #define LVTMA_BL_MOD_LEVEL 0x7af9 /* ATI Radeon backlight level */
 /* The southbridge SMI handler checks whether gnvs has a
  * valid pointer before calling the trap handler
@@ -154,41 +156,25 @@ static void mainboard_smi_handle_ec_sci(void)
 
 void mainboard_smi_gpi(u32 gpi)
 {
-	if (gpi & (1 << 12))
+	if (gpi & (1 << GPE_H8SCI))
 		mainboard_smi_handle_ec_sci();
 }
 
 int mainboard_smi_apmc(u8 data)
 {
-	u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-	u8 tmp;
-
-	printk(BIOS_DEBUG, "%s: pmbase %04X, data %02X\n", __func__, pmbase, data);
-
-	if (!pmbase)
-		return 0;
-
 	switch(data) {
 		case APM_CNT_ACPI_ENABLE:
 			/* use 0x1600/0x1604 to prevent races with userspace */
 			ec_set_ports(0x1604, 0x1600);
 			/* route H8SCI to SCI */
-			outw(inw(pmbase + ALT_GP_SMI_EN) & ~0x1000, pmbase + ALT_GP_SMI_EN);
-			tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-			tmp &= ~0x03;
-			tmp |= 0x02;
-			pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+			gpi_route_interrupt(GPE_H8SCI, GPI_IS_SCI);
 			break;
 		case APM_CNT_ACPI_DISABLE:
 			/* we have to use port 0x62/0x66, as 0x1600/0x1604 doesn't
 			   provide a EC query function */
 			ec_set_ports(0x66, 0x62);
 			/* route H8SCI# to SMI */
-			outw(inw(pmbase + ALT_GP_SMI_EN) | 0x1000, pmbase + ALT_GP_SMI_EN);
-			tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-			tmp &= ~0x03;
-			tmp |= 0x01;
-			pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+			gpi_route_interrupt(GPE_H8SCI, GPI_IS_SMI);
 			break;
 		default:
 			break;
diff --git a/src/mainboard/lenovo/x201/smihandler.c b/src/mainboard/lenovo/x201/smihandler.c
index 7af613b..de40cea 100644
--- a/src/mainboard/lenovo/x201/smihandler.c
+++ b/src/mainboard/lenovo/x201/smihandler.c
@@ -34,6 +34,9 @@
 #include "dock.h"
 #include "smi.h"
 
+#define GPE_H8SCI	1
+#define GPE_EC_WAKE	13
+
 /* The southbridge SMI handler checks whether gnvs has a
  * valid pointer before calling the trap handler
  */
@@ -137,7 +140,7 @@ static void mainboard_smi_handle_ec_sci(void)
 
 void mainboard_smi_gpi(u32 gpi_sts)
 {
-	if (gpi_sts & (1 << 1))
+	if (gpi_sts & (1 << GPE_H8SCI))
 		mainboard_smi_handle_ec_sci();
 }
 
@@ -145,15 +148,6 @@ static int mainboard_finalized = 0;
 
 int mainboard_smi_apmc(u8 data)
 {
-	u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-	u8 tmp;
-
-	printk(BIOS_DEBUG, "%s: pmbase %04X, data %02X\n", __func__, pmbase,
-	       data);
-
-	if (!pmbase)
-		return 0;
-
 	switch (data) {
 	case APM_CNT_FINALIZE:
 		printk(BIOS_DEBUG, "APMC: FINALIZE\n");
@@ -173,11 +167,7 @@ int mainboard_smi_apmc(u8 data)
 		/* use 0x1600/0x1604 to prevent races with userspace */
 		ec_set_ports(0x1604, 0x1600);
 		/* route H8SCI to SCI */
-		outw(inw(pmbase + ALT_GP_SMI_EN) & ~0x1000, pmbase + ALT_GP_SMI_EN);
-		tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-		tmp &= ~0x03;
-		tmp |= 0x02;
-		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+		gpi_route_interrupt(GPE_H8SCI, GPI_IS_SCI);
 		/* discard all events, and enable attention */
 		ec_write(0x80, 0x01);
 		break;
@@ -186,12 +176,7 @@ int mainboard_smi_apmc(u8 data)
 		   provide a EC query function */
 		ec_set_ports(0x66, 0x62);
 		/* route H8SCI# to SMI */
-		outw(inw(pmbase + ALT_GP_SMI_EN) | 0x1000,
-		     pmbase + ALT_GP_SMI_EN);
-		tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-		tmp &= ~0x03;
-		tmp |= 0x01;
-		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+		gpi_route_interrupt(GPE_H8SCI, GPI_IS_SMI);
 		/* discard all events, and enable attention */
 		ec_write(0x80, 0x01);
 		break;
@@ -207,16 +192,8 @@ void mainboard_smi_sleep(u8 slp_typ)
 		u8 ec_wake = ec_read(0x32);
 		/* If EC wake events are enabled, enable wake on EC WAKE GPE.  */
 		if (ec_wake & 0x14) {
-			u32 gpe_rout;
-			u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-
-			/* Enable EC WAKE GPE.  */
-			outl(inl(pmbase + GPE0_EN) | (1 << 29), pmbase + GPE0_EN);
-			gpe_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT);
 			/* Redirect EC WAKE GPE to SCI.  */
-			gpe_rout &= ~(3 << 26);
-			gpe_rout |= (2 << 26);
-			pci_write_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT, gpe_rout);
+			gpi_route_interrupt(GPE_EC_WAKE, GPI_IS_SCI);
 		}
 	}
 }
diff --git a/src/mainboard/lenovo/x220/smihandler.c b/src/mainboard/lenovo/x220/smihandler.c
index 6f6cca1..fe7cd65 100644
--- a/src/mainboard/lenovo/x220/smihandler.c
+++ b/src/mainboard/lenovo/x220/smihandler.c
@@ -33,6 +33,9 @@
 #include <northbridge/intel/sandybridge/sandybridge.h>
 #include <cpu/intel/model_206ax/model_206ax.h>
 
+#define GPE_H8SCI	12
+#define GPE_EC_WAKE	13
+
 /* The southbridge SMI handler checks whether gnvs has a
  * valid pointer before calling the trap handler
  */
@@ -108,7 +111,7 @@ static void mainboard_smi_handle_ec_sci(void)
 
 void mainboard_smi_gpi(u32 gpi_sts)
 {
-	if (gpi_sts & (1 << 12))
+	if (gpi_sts & (1 << GPE_H8SCI))
 		mainboard_smi_handle_ec_sci();
 }
 
@@ -116,25 +119,12 @@ static int mainboard_finalized = 0;
 
 int mainboard_smi_apmc(u8 data)
 {
-	u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-	u8 tmp;
-
-	printk(BIOS_DEBUG, "%s: pmbase %04X, data %02X\n", __func__, pmbase,
-	       data);
-
-	if (!pmbase)
-		return 0;
-
 	switch (data) {
 	case APM_CNT_ACPI_ENABLE:
 		/* use 0x1600/0x1604 to prevent races with userspace */
 		ec_set_ports(0x1604, 0x1600);
 		/* route H8SCI to SCI */
-		outw(inw(pmbase + ALT_GP_SMI_EN) & ~0x1000, pmbase + ALT_GP_SMI_EN);
-		tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-		tmp &= ~0x03;
-		tmp |= 0x02;
-		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+		gpi_route_interrupt(GPE_H8SCI, GPI_IS_SCI);
 		/* discard all events, and enable attention */
 		ec_write(0x80, 0x01);
 		break;
@@ -143,12 +133,7 @@ int mainboard_smi_apmc(u8 data)
 		   provide a EC query function */
 		ec_set_ports(0x66, 0x62);
 		/* route H8SCI# to SMI */
-		outw(inw(pmbase + ALT_GP_SMI_EN) | 0x1000,
-		     pmbase + ALT_GP_SMI_EN);
-		tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-		tmp &= ~0x03;
-		tmp |= 0x01;
-		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+		gpi_route_interrupt(GPE_H8SCI, GPI_IS_SMI);
 		/* discard all events, and enable attention */
 		ec_write(0x80, 0x01);
 		break;
@@ -179,16 +164,8 @@ void mainboard_smi_sleep(u8 slp_typ)
 		u8 ec_wake = ec_read(0x32);
 		/* If EC wake events are enabled, enable wake on EC WAKE GPE.  */
 		if (ec_wake & 0x14) {
-			u32 gpe_rout;
-			u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-
-			/* Enable EC WAKE GPE.  */
-			outl(inl(pmbase + GPE0_EN) | (1 << 29), pmbase + GPE0_EN);
-			gpe_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT);
 			/* Redirect EC WAKE GPE to SCI.  */
-			gpe_rout &= ~(3 << 26);
-			gpe_rout |= (2 << 26);
-			pci_write_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT, gpe_rout);
+			gpi_route_interrupt(GPE_EC_WAKE, GPI_IS_SCI);
 		}
 	}
 }
diff --git a/src/mainboard/lenovo/x230/smihandler.c b/src/mainboard/lenovo/x230/smihandler.c
index 6f6cca1..f8b723b 100644
--- a/src/mainboard/lenovo/x230/smihandler.c
+++ b/src/mainboard/lenovo/x230/smihandler.c
@@ -33,6 +33,10 @@
 #include <northbridge/intel/sandybridge/sandybridge.h>
 #include <cpu/intel/model_206ax/model_206ax.h>
 
+
+#define GPE_H8SCI	12
+#define GPE_EC_WAKE	13
+
 /* The southbridge SMI handler checks whether gnvs has a
  * valid pointer before calling the trap handler
  */
@@ -108,7 +112,7 @@ static void mainboard_smi_handle_ec_sci(void)
 
 void mainboard_smi_gpi(u32 gpi_sts)
 {
-	if (gpi_sts & (1 << 12))
+	if (gpi_sts & (1 << GPE_H8SCI))
 		mainboard_smi_handle_ec_sci();
 }
 
@@ -116,25 +120,12 @@ static int mainboard_finalized = 0;
 
 int mainboard_smi_apmc(u8 data)
 {
-	u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-	u8 tmp;
-
-	printk(BIOS_DEBUG, "%s: pmbase %04X, data %02X\n", __func__, pmbase,
-	       data);
-
-	if (!pmbase)
-		return 0;
-
 	switch (data) {
 	case APM_CNT_ACPI_ENABLE:
 		/* use 0x1600/0x1604 to prevent races with userspace */
 		ec_set_ports(0x1604, 0x1600);
 		/* route H8SCI to SCI */
-		outw(inw(pmbase + ALT_GP_SMI_EN) & ~0x1000, pmbase + ALT_GP_SMI_EN);
-		tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-		tmp &= ~0x03;
-		tmp |= 0x02;
-		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+		gpi_route_interrupt(GPE_H8SCI, GPI_IS_SCI);
 		/* discard all events, and enable attention */
 		ec_write(0x80, 0x01);
 		break;
@@ -143,12 +134,7 @@ int mainboard_smi_apmc(u8 data)
 		   provide a EC query function */
 		ec_set_ports(0x66, 0x62);
 		/* route H8SCI# to SMI */
-		outw(inw(pmbase + ALT_GP_SMI_EN) | 0x1000,
-		     pmbase + ALT_GP_SMI_EN);
-		tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-		tmp &= ~0x03;
-		tmp |= 0x01;
-		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+		gpi_route_interrupt(GPE_H8SCI, GPI_IS_SMI);
 		/* discard all events, and enable attention */
 		ec_write(0x80, 0x01);
 		break;
@@ -179,16 +165,8 @@ void mainboard_smi_sleep(u8 slp_typ)
 		u8 ec_wake = ec_read(0x32);
 		/* If EC wake events are enabled, enable wake on EC WAKE GPE.  */
 		if (ec_wake & 0x14) {
-			u32 gpe_rout;
-			u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-
-			/* Enable EC WAKE GPE.  */
-			outl(inl(pmbase + GPE0_EN) | (1 << 29), pmbase + GPE0_EN);
-			gpe_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT);
 			/* Redirect EC WAKE GPE to SCI.  */
-			gpe_rout &= ~(3 << 26);
-			gpe_rout |= (2 << 26);
-			pci_write_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT, gpe_rout);
+			gpi_route_interrupt(GPE_EC_WAKE, GPI_IS_SCI);
 		}
 	}
 }
diff --git a/src/mainboard/lenovo/x60/smihandler.c b/src/mainboard/lenovo/x60/smihandler.c
index ccc328e..054400e 100644
--- a/src/mainboard/lenovo/x60/smihandler.c
+++ b/src/mainboard/lenovo/x60/smihandler.c
@@ -31,6 +31,8 @@
 #include "dock.h"
 #include "smi.h"
 
+#define GPE_H8SCI	12
+
 /* The southbridge SMI handler checks whether gnvs has a
  * valid pointer before calling the trap handler
  */
@@ -160,30 +162,18 @@ static void mainboard_smi_handle_ec_sci(void)
 
 void mainboard_smi_gpi(u32 gpi)
 {
-	if (gpi & (1 << 12))
+	if (gpi & (1 << GPE_H8SCI))
 		mainboard_smi_handle_ec_sci();
 }
 
 int mainboard_smi_apmc(u8 data)
 {
-	u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-	u8 tmp;
-
-	printk(BIOS_DEBUG, "%s: pmbase %04X, data %02X\n", __func__, pmbase, data);
-
-	if (!pmbase)
-		return 0;
-
 	switch(data) {
 		case APM_CNT_ACPI_ENABLE:
 			/* use 0x1600/0x1604 to prevent races with userspace */
 			ec_set_ports(0x1604, 0x1600);
 			/* route H8SCI to SCI */
-			outw(inw(pmbase + ALT_GP_SMI_EN) & ~0x1000, pmbase + ALT_GP_SMI_EN);
-			tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-			tmp &= ~0x03;
-			tmp |= 0x02;
-			pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+			gpi_route_interrupt(GPE_H8SCI, GPI_IS_SCI);
 			/* discard all events, and enable attention */
 			ec_write(0x80, 0x01);
 			break;
@@ -192,11 +182,7 @@ int mainboard_smi_apmc(u8 data)
 			   provide a EC query function */
 			ec_set_ports(0x66, 0x62);
 			/* route H8SCI# to SMI */
-			outw(inw(pmbase + ALT_GP_SMI_EN) | 0x1000, pmbase + ALT_GP_SMI_EN);
-			tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-			tmp &= ~0x03;
-			tmp |= 0x01;
-			pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+			gpi_route_interrupt(GPE_H8SCI, GPI_IS_SMI);
 			/* discard all events, and enable attention */
 			ec_write(0x80, 0x01);
 			break;
diff --git a/src/mainboard/packardbell/ms2290/smihandler.c b/src/mainboard/packardbell/ms2290/smihandler.c
index f04ff90..eda17f3 100644
--- a/src/mainboard/packardbell/ms2290/smihandler.c
+++ b/src/mainboard/packardbell/ms2290/smihandler.c
@@ -31,6 +31,9 @@
 #include <pc80/mc146818rtc.h>
 #include <delay.h>
 
+/* This GPI is not confirmed. */
+#define MS2290_ENABLE_GPI12	1
+
 /* The southbridge SMI handler checks whether gnvs has a
  * valid pointer before calling the trap handler
  */
@@ -69,15 +72,6 @@ static int mainboard_finalized = 0;
 
 int mainboard_smi_apmc(u8 data)
 {
-	u16 pmbase = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
-	u8 tmp;
-
-	printk(BIOS_DEBUG, "%s: pmbase %04X, data %02X\n", __func__, pmbase,
-	       data);
-
-	if (!pmbase)
-		return 0;
-
 	switch (data) {
 	case APM_CNT_FINALIZE:
 		printk(BIOS_DEBUG, "APMC: FINALIZE\n");
@@ -94,16 +88,12 @@ int mainboard_smi_apmc(u8 data)
 		mainboard_finalized = 1;
 		break;
 	case APM_CNT_ACPI_ENABLE:
-		tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-		tmp &= ~0x03;
-		tmp |= 0x02;
-		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+		if (MS2290_ENABLE_GPI12)
+			gpi_route_interrupt(12, GPI_IS_SCI);
 		break;
 	case APM_CNT_ACPI_DISABLE:
-		tmp = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xbb);
-		tmp &= ~0x03;
-		tmp |= 0x01;
-		pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xbb, tmp);
+		if (MS2290_ENABLE_GPI12)
+			gpi_route_interrupt(12, GPI_IS_SMI);
 		break;
 	default:
 		break;
diff --git a/src/southbridge/intel/bd82x6x/lpc.c b/src/southbridge/intel/bd82x6x/lpc.c
index 11b765a..98f13be 100644
--- a/src/southbridge/intel/bd82x6x/lpc.c
+++ b/src/southbridge/intel/bd82x6x/lpc.c
@@ -167,7 +167,7 @@ static void pch_gpi_routing(device_t dev)
 	reg32 |= (config->gpi14_routing & 0x03) << 28;
 	reg32 |= (config->gpi15_routing & 0x03) << 30;
 
-	pci_write_config32(dev, 0xb8, reg32);
+	pci_write_config32(dev, GPIO_ROUT, reg32);
 }
 
 static void pch_power_options(device_t dev)
diff --git a/src/southbridge/intel/bd82x6x/pch.h b/src/southbridge/intel/bd82x6x/pch.h
index 7cde7bc..c0a6c56 100644
--- a/src/southbridge/intel/bd82x6x/pch.h
+++ b/src/southbridge/intel/bd82x6x/pch.h
@@ -66,6 +66,7 @@ int pch_silicon_revision(void);
 int pch_silicon_type(void);
 int pch_silicon_supported(int type, int rev);
 void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue);
+void gpi_route_interrupt(u8 gpi, u8 mode);
 #if CONFIG_ELOG
 void pch_log_state(void);
 #endif
@@ -142,7 +143,12 @@ early_usb_init (const struct southbridge_usb_port *portmap);
 #define BIOS_CNTL		0xDC
 #define GPIO_BASE		0x48 /* LPC GPIO Base Address Register */
 #define GPIO_CNTL		0x4C /* LPC GPIO Control Register */
+
 #define GPIO_ROUT		0xb8
+#define   GPI_DISABLE		0x00
+#define   GPI_IS_SMI		0x01
+#define   GPI_IS_SCI		0x02
+#define   GPI_IS_NMI		0x03
 
 #define PIRQA_ROUT		0x60
 #define PIRQB_ROUT		0x61
diff --git a/src/southbridge/intel/bd82x6x/smihandler.c b/src/southbridge/intel/bd82x6x/smihandler.c
index 45612d0..8f69af9 100644
--- a/src/southbridge/intel/bd82x6x/smihandler.c
+++ b/src/southbridge/intel/bd82x6x/smihandler.c
@@ -75,6 +75,42 @@ void tseg_relocate(void **ptr)
 }
 #endif
 
+static void alt_gpi_mask(u16 clr, u16 set)
+{
+	u16 alt_gp = inw(pmbase + ALT_GP_SMI_EN);
+	alt_gp &= ~clr;
+	alt_gp |= set;
+	outw(alt_gp, pmbase + ALT_GP_SMI_EN);
+}
+
+static void gpe0_mask(u32 clr, u32 set)
+{
+	u32 gpe0 = inl(pmbase + GPE0_EN);
+	gpe0 &= ~clr;
+	gpe0 |= set;
+	outl(gpe0, pmbase + GPE0_EN);
+}
+
+void gpi_route_interrupt(u8 gpi, u8 mode)
+{
+	u32 gpi_rout;
+	if (gpi >= 16)
+		return;
+
+	alt_gpi_mask(1 << gpi, 0);
+	gpe0_mask(1 << (gpi+16), 0);
+
+	gpi_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT);
+	gpi_rout &= ~(3 << (2 * gpi));
+	gpi_rout |= ((mode & 3) << (2 * gpi));
+	pci_write_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT, gpi_rout);
+
+	if (mode == GPI_IS_SCI)
+		gpe0_mask(0, 1 << (gpi+16));
+	else if (mode == GPI_IS_SMI)
+		alt_gpi_mask(0, 1 << gpi);
+}
+
 /**
  * @brief read and clear PM1_STS
  * @return PM1_STS register
diff --git a/src/southbridge/intel/fsp_bd82x6x/lpc.c b/src/southbridge/intel/fsp_bd82x6x/lpc.c
index f9961f9..6b95d08 100644
--- a/src/southbridge/intel/fsp_bd82x6x/lpc.c
+++ b/src/southbridge/intel/fsp_bd82x6x/lpc.c
@@ -185,7 +185,7 @@ static void pch_gpi_routing(device_t dev)
 	reg32 |= (config->gpi14_routing & 0x03) << 28;
 	reg32 |= (config->gpi15_routing & 0x03) << 30;
 
-	pci_write_config32(dev, 0xb8, reg32);
+	pci_write_config32(dev, GPIO_ROUT, reg32);
 }
 
 static void pch_power_options(device_t dev)
diff --git a/src/southbridge/intel/i82801gx/i82801gx.h b/src/southbridge/intel/i82801gx/i82801gx.h
index ee13b7d..c436209 100644
--- a/src/southbridge/intel/i82801gx/i82801gx.h
+++ b/src/southbridge/intel/i82801gx/i82801gx.h
@@ -41,6 +41,7 @@
 #if !defined(__PRE_RAM__)
 #include "chip.h"
 extern void i82801gx_enable(device_t dev);
+void gpi_route_interrupt(u8 gpi, u8 mode);
 #else
 void enable_smbus(void);
 int smbus_read_byte(unsigned device, unsigned address);
@@ -74,6 +75,12 @@ int southbridge_detect_s3_resume(void);
 #define GEN_PMCON_2		0xa2
 #define GEN_PMCON_3		0xa4
 
+#define GPIO_ROUT		0xb8
+#define   GPI_DISABLE		0x00
+#define   GPI_IS_SMI		0x01
+#define   GPI_IS_SCI		0x02
+#define   GPI_IS_NMI		0x03
+
 /* GEN_PMCON_3 bits */
 #define RTC_BATTERY_DEAD	(1 << 2)
 #define RTC_POWER_FAILED	(1 << 1)
diff --git a/src/southbridge/intel/i82801gx/lpc.c b/src/southbridge/intel/i82801gx/lpc.c
index 6b9d11e..aae0be6 100644
--- a/src/southbridge/intel/i82801gx/lpc.c
+++ b/src/southbridge/intel/i82801gx/lpc.c
@@ -158,7 +158,7 @@ static void i82801gx_gpi_routing(device_t dev)
 	reg32 |= (config->gpi14_routing & 0x03) << 28;
 	reg32 |= (config->gpi15_routing & 0x03) << 30;
 
-	pci_write_config32(dev, 0xb8, reg32);
+	pci_write_config32(dev, GPIO_ROUT, reg32);
 }
 
 static void i82801gx_power_options(device_t dev)
diff --git a/src/southbridge/intel/i82801gx/smihandler.c b/src/southbridge/intel/i82801gx/smihandler.c
index e2505ce..fb439c6 100644
--- a/src/southbridge/intel/i82801gx/smihandler.c
+++ b/src/southbridge/intel/i82801gx/smihandler.c
@@ -50,6 +50,42 @@ u8 smm_initialized = 0;
  */
 global_nvs_t *gnvs = (global_nvs_t *)0x0;
 
+static void alt_gpi_mask(u16 clr, u16 set)
+{
+	u16 alt_gp = inw(pmbase + ALT_GP_SMI_EN);
+	alt_gp &= ~clr;
+	alt_gp |= set;
+	outw(alt_gp, pmbase + ALT_GP_SMI_EN);
+}
+
+static void gpe0_mask(u32 clr, u32 set)
+{
+	u32 gpe0 = inl(pmbase + GPE0_EN);
+	gpe0 &= ~clr;
+	gpe0 |= set;
+	outl(gpe0, pmbase + GPE0_EN);
+}
+
+void gpi_route_interrupt(u8 gpi, u8 mode)
+{
+	u32 gpi_rout;
+	if (gpi >= 16)
+		return;
+
+	alt_gpi_mask(1 << gpi, 0);
+	gpe0_mask(1 << (gpi+16), 0);
+
+	gpi_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT);
+	gpi_rout &= ~(3 << (2 * gpi));
+	gpi_rout |= ((mode & 3) << (2 * gpi));
+	pci_write_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT, gpi_rout);
+
+	if (mode == GPI_IS_SCI)
+		gpe0_mask(0, 1 << (gpi+16));
+	else if (mode == GPI_IS_SMI)
+		alt_gpi_mask(0, 1 << gpi);
+}
+
 /**
  * @brief read and clear PM1_STS
  * @return PM1_STS register
diff --git a/src/southbridge/intel/ibexpeak/lpc.c b/src/southbridge/intel/ibexpeak/lpc.c
index 2124711..7ccc00b 100644
--- a/src/southbridge/intel/ibexpeak/lpc.c
+++ b/src/southbridge/intel/ibexpeak/lpc.c
@@ -166,7 +166,7 @@ static void pch_gpi_routing(device_t dev)
 	reg32 |= (config->gpi14_routing & 0x03) << 28;
 	reg32 |= (config->gpi15_routing & 0x03) << 30;
 
-	pci_write_config32(dev, 0xb8, reg32);
+	pci_write_config32(dev, GPIO_ROUT, reg32);
 }
 
 static void pch_power_options(device_t dev)
diff --git a/src/southbridge/intel/ibexpeak/pch.h b/src/southbridge/intel/ibexpeak/pch.h
index bd94689..4840a1a 100644
--- a/src/southbridge/intel/ibexpeak/pch.h
+++ b/src/southbridge/intel/ibexpeak/pch.h
@@ -67,6 +67,7 @@ int pch_silicon_revision(void);
 int pch_silicon_type(void);
 int pch_silicon_supported(int type, int rev);
 void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue);
+void gpi_route_interrupt(u8 gpi, u8 mode);
 #if CONFIG_ELOG
 void pch_log_state(void);
 #endif
@@ -129,7 +130,12 @@ void southbridge_configure_default_intmap(void);
 #define BIOS_CNTL		0xDC
 #define GPIO_BASE		0x48 /* LPC GPIO Base Address Register */
 #define GPIO_CNTL		0x4C /* LPC GPIO Control Register */
+
 #define GPIO_ROUT		0xb8
+#define   GPI_DISABLE		0x00
+#define   GPI_IS_SMI		0x01
+#define   GPI_IS_SCI		0x02
+#define   GPI_IS_NMI		0x03
 
 #define PIRQA_ROUT		0x60
 #define PIRQB_ROUT		0x61
diff --git a/src/southbridge/intel/ibexpeak/smihandler.c b/src/southbridge/intel/ibexpeak/smihandler.c
index e2032ad..95530c4 100644
--- a/src/southbridge/intel/ibexpeak/smihandler.c
+++ b/src/southbridge/intel/ibexpeak/smihandler.c
@@ -75,6 +75,42 @@ void tseg_relocate(void **ptr)
 }
 #endif
 
+static void alt_gpi_mask(u16 clr, u16 set)
+{
+	u16 alt_gp = inw(pmbase + ALT_GP_SMI_EN);
+	alt_gp &= ~clr;
+	alt_gp |= set;
+	outw(alt_gp, pmbase + ALT_GP_SMI_EN);
+}
+
+static void gpe0_mask(u32 clr, u32 set)
+{
+	u32 gpe0 = inl(pmbase + GPE0_EN);
+	gpe0 &= ~clr;
+	gpe0 |= set;
+	outl(gpe0, pmbase + GPE0_EN);
+}
+
+void gpi_route_interrupt(u8 gpi, u8 mode)
+{
+	u32 gpi_rout;
+	if (gpi >= 16)
+		return;
+
+	alt_gpi_mask(1 << gpi, 0);
+	gpe0_mask(1 << (gpi+16), 0);
+
+	gpi_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT);
+	gpi_rout &= ~(3 << (2 * gpi));
+	gpi_rout |= ((mode & 3) << (2 * gpi));
+	pci_write_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT, gpi_rout);
+
+	if (mode == GPI_IS_SCI)
+		gpe0_mask(0, 1 << (gpi+16));
+	else if (mode == GPI_IS_SMI)
+		alt_gpi_mask(0, 1 << gpi);
+}
+
 /**
  * @brief read and clear PM1_STS
  * @return PM1_STS register
diff --git a/src/southbridge/intel/lynxpoint/lpc.c b/src/southbridge/intel/lynxpoint/lpc.c
index 563cb0a..c551c8b 100644
--- a/src/southbridge/intel/lynxpoint/lpc.c
+++ b/src/southbridge/intel/lynxpoint/lpc.c
@@ -175,7 +175,7 @@ static void pch_gpi_routing(device_t dev)
 	reg32 |= (config->gpi14_routing & 0x03) << 28;
 	reg32 |= (config->gpi15_routing & 0x03) << 30;
 
-	pci_write_config32(dev, 0xb8, reg32);
+	pci_write_config32(dev, GPIO_ROUT, reg32);
 }
 
 static void pch_power_options(device_t dev)



More information about the coreboot-gerrit mailing list