From b85a87b7d6f9f12d5c71c32741c8af731ed6be7e Mon Sep 17 00:00:00 2001 From: Kyösti Mälkki Date: Mon, 29 Dec 2014 11:32:27 +0200 Subject: intel SMI handlers: Refactor GPI SMI/SCI routing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the GPI interrupt routing selection between SMI/SCI from mainboards to southbridge. There is speculation if this is all just legacy APM stuff that could be removed with a followup. Change-Id: Iab14cf347584513793f417febc47f0559e17f5a5 Signed-off-by: Kyösti Mälkki Signed-off-by: Nicolas Reinecke Reviewed-on: http://review.coreboot.org/7967 Tested-by: build bot (Jenkins) Reviewed-by: Alexander Couzens --- src/mainboard/apple/macbook21/smihandler.c | 20 ++----------- src/mainboard/google/parrot/smihandler.c | 43 ++------------------------- src/mainboard/lenovo/t420s/smihandler.c | 34 +++------------------ src/mainboard/lenovo/t430s/smihandler.c | 34 +++------------------ src/mainboard/lenovo/t520/smihandler.c | 34 +++------------------ src/mainboard/lenovo/t530/smihandler.c | 34 +++------------------ src/mainboard/lenovo/t60/smihandler.c | 20 ++----------- src/mainboard/lenovo/x201/smihandler.c | 32 ++------------------ src/mainboard/lenovo/x220/smihandler.c | 34 +++------------------ src/mainboard/lenovo/x230/smihandler.c | 34 +++------------------ src/mainboard/lenovo/x60/smihandler.c | 20 ++----------- src/mainboard/packardbell/ms2290/smihandler.c | 8 ----- 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 +- 23 files changed, 167 insertions(+), 317 deletions(-) diff --git a/src/mainboard/apple/macbook21/smihandler.c b/src/mainboard/apple/macbook21/smihandler.c index f90bb38336..5c6cd443d9 100644 --- a/src/mainboard/apple/macbook21/smihandler.c +++ b/src/mainboard/apple/macbook21/smihandler.c @@ -60,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) & ~(1< #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 27a33cf838..430ad1ba77 100644 --- a/src/mainboard/lenovo/t420s/smihandler.c +++ b/src/mainboard/lenovo/t420s/smihandler.c @@ -119,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 EC_SCI to SCI */ - outw(inw(pmbase + ALT_GP_SMI_EN) & ~(1 << GPE_EC_SCI), 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_EC_SCI, GPI_IS_SCI); /* discard all events, and enable attention */ ec_write(0x80, 0x01); break; @@ -145,13 +132,8 @@ int mainboard_smi_apmc(u8 data) /* we have to use port 0x62/0x66, as 0x1600/0x1604 doesn't provide a EC query function */ ec_set_ports(0x66, 0x62); - /* route EC_SCI# to SMI */ - outw(inw(pmbase + ALT_GP_SMI_EN) | (1 << GPE_EC_SCI), - 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); + /* route EC_SCI to SMI */ + gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SMI); /* discard all events, and enable attention */ ec_write(0x80, 0x01); break; @@ -182,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 << (GPE_EC_WAKE + 16)), pmbase + GPE0_EN); - gpe_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT); /* Redirect EC WAKE GPE to SCI. */ - gpe_rout &= ~(3 << (GPE_EC_WAKE * 2)); - gpe_rout |= (2 << (GPE_EC_WAKE * 2)); - 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/t430s/smihandler.c b/src/mainboard/lenovo/t430s/smihandler.c index b384a730ca..2f690b4815 100644 --- a/src/mainboard/lenovo/t430s/smihandler.c +++ b/src/mainboard/lenovo/t430s/smihandler.c @@ -117,25 +117,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 EC_SCI to SCI */ - outw(inw(pmbase + ALT_GP_SMI_EN) & ~(1 << GPE_EC_SCI), 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_EC_SCI, GPI_IS_SCI); /* discard all events, and enable attention */ ec_write(0x80, 0x01); break; @@ -143,13 +130,8 @@ int mainboard_smi_apmc(u8 data) /* we have to use port 0x62/0x66, as 0x1600/0x1604 doesn't provide a EC query function */ ec_set_ports(0x66, 0x62); - /* route EC_SCI# to SMI */ - outw(inw(pmbase + ALT_GP_SMI_EN) | (1 << GPE_EC_SCI), - 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); + /* route EC_SCI to SMI */ + gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SMI); /* discard all events, and enable attention */ ec_write(0x80, 0x01); break; @@ -180,16 +162,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 << (GPE_EC_WAKE + 16)), pmbase + GPE0_EN); - gpe_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT); /* Redirect EC WAKE GPE to SCI. */ - gpe_rout &= ~(3 << (GPE_EC_WAKE * 2)); - gpe_rout |= (2 << (GPE_EC_WAKE * 2)); - 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 479ce0a8e4..4d874fd2eb 100644 --- a/src/mainboard/lenovo/t520/smihandler.c +++ b/src/mainboard/lenovo/t520/smihandler.c @@ -114,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 EC_SCI to SCI */ - outw(inw(pmbase + ALT_GP_SMI_EN) & ~(1 << GPE_EC_SCI), 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_EC_SCI, GPI_IS_SCI); /* discard all events, and enable attention */ ec_write(0x80, 0x01); break; @@ -140,13 +127,8 @@ int mainboard_smi_apmc(u8 data) /* we have to use port 0x62/0x66, as 0x1600/0x1604 doesn't provide a EC query function */ ec_set_ports(0x66, 0x62); - /* route EC_SCI# to SMI */ - outw(inw(pmbase + ALT_GP_SMI_EN) | (1 << GPE_EC_SCI), - 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); + /* route EC_SCI to SMI */ + gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SMI); /* discard all events, and enable attention */ ec_write(0x80, 0x01); break; @@ -177,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 << (GPE_EC_WAKE + 16)), pmbase + GPE0_EN); - gpe_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT); /* Redirect EC WAKE GPE to SCI. */ - gpe_rout &= ~(3 << (GPE_EC_WAKE * 2)); - gpe_rout |= (2 << (GPE_EC_WAKE * 2)); - 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 372f280a9f..8208fe735d 100644 --- a/src/mainboard/lenovo/t530/smihandler.c +++ b/src/mainboard/lenovo/t530/smihandler.c @@ -119,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 EC_SCI to SCI */ - outw(inw(pmbase + ALT_GP_SMI_EN) & ~(1 << GPE_EC_SCI), 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_EC_SCI, GPI_IS_SCI); /* discard all events, and enable attention */ ec_write(0x80, 0x01); break; @@ -145,13 +132,8 @@ int mainboard_smi_apmc(u8 data) /* we have to use port 0x62/0x66, as 0x1600/0x1604 doesn't provide a EC query function */ ec_set_ports(0x66, 0x62); - /* route EC_SCI# to SMI */ - outw(inw(pmbase + ALT_GP_SMI_EN) | (1 << GPE_EC_SCI), - 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); + /* route EC_SCI to SMI */ + gpi_route_interrupt(GPE_EC_SCI, GPI_IS_SMI); /* discard all events, and enable attention */ ec_write(0x80, 0x01); break; @@ -182,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 << (GPE_EC_WAKE + 16)), pmbase + GPE0_EN); - gpe_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT); /* Redirect EC WAKE GPE to SCI. */ - gpe_rout &= ~(3 << (GPE_EC_WAKE * 2)); - gpe_rout |= (2 << (GPE_EC_WAKE * 2)); - 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 3833ae24ff..6e46bfd77c 100644 --- a/src/mainboard/lenovo/t60/smihandler.c +++ b/src/mainboard/lenovo/t60/smihandler.c @@ -162,35 +162,19 @@ void mainboard_smi_gpi(u32 gpi) 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) & ~(1<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 4ec29035d1..a76bf365b6 100644 --- a/src/southbridge/intel/bd82x6x/pch.h +++ b/src/southbridge/intel/bd82x6x/pch.h @@ -70,6 +70,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 @@ -146,7 +147,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 f69c1f4dd8..7ecbd81e92 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 f9961f95ba..6b95d0874a 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 462484100d..815768bbca 100644 --- a/src/southbridge/intel/i82801gx/i82801gx.h +++ b/src/southbridge/intel/i82801gx/i82801gx.h @@ -45,6 +45,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); @@ -78,6 +79,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 b8edfe3fd9..2e3182bd2f 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 e83c722f0b..6db08319d6 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 db73b0add8..9550a9e974 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 12e9345bf7..23eb6cd923 100644 --- a/src/southbridge/intel/ibexpeak/pch.h +++ b/src/southbridge/intel/ibexpeak/pch.h @@ -71,6 +71,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 @@ -133,7 +134,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 019e6db276..bfe5f5d0af 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 d753bea776..d83ec0a1f2 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) -- cgit v1.2.3