diff --git a/src/southbridge/intel/lynxpoint/lp_gpio.c b/src/southbridge/intel/lynxpoint/lp_gpio.c index b90e5ba4b8..7d1a28d73c 100644 --- a/src/southbridge/intel/lynxpoint/lp_gpio.c +++ b/src/southbridge/intel/lynxpoint/lp_gpio.c @@ -36,6 +36,35 @@ static u16 get_gpio_base(void) #endif } + +/* + * This function will return a number that indicates which PIRQ + * this GPIO maps to. If this is not a PIRQ capable GPIO then + * it will return -1. The GPIO to PIRQ mapping is not linear. + */ +static int lp_gpio_to_pirq(int gpio) +{ + switch (gpio) { + case 8: return 0; /* PIRQI */ + case 9: return 1; /* PIRQJ */ + case 10: return 2; /* PIRQK */ + case 13: return 3; /* PIRQL */ + case 14: return 4; /* PIRQM */ + case 45: return 5; /* PIRQN */ + case 46: return 6; /* PIRQO */ + case 47: return 7; /* PIRQP */ + case 48: return 8; /* PIRQQ */ + case 49: return 9; /* PIRQR */ + case 50: return 10; /* PIRQS */ + case 51: return 11; /* PIRQT */ + case 52: return 12; /* PIRQU */ + case 53: return 13; /* PIRQV */ + case 54: return 14; /* PIRQW */ + case 55: return 15; /* PIRQX */ + default: return -1; + }; +} + void setup_pch_lp_gpios(const struct pch_lp_gpio_map map[]) { u16 gpio_base = get_gpio_base(); @@ -45,6 +74,7 @@ void setup_pch_lp_gpios(const struct pch_lp_gpio_map map[]) u32 irqen[3] = {0}; u32 reset[3] = {0}; u32 blink = 0; + u16 pirq2apic = 0; int set, bit, gpio = 0; for (config = map; config->conf0 != GPIO_LIST_END; config++, gpio++) { @@ -67,6 +97,13 @@ void setup_pch_lp_gpios(const struct pch_lp_gpio_map map[]) if (set == 0) blink |= config->blink << bit; + + /* PIRQ to IO-APIC map */ + if (config->pirq == GPIO_PIRQ_APIC_ROUTE) { + set = lp_gpio_to_pirq(gpio); + if (set >= 0) + pirq2apic |= 1 << set; + } } for (set = 0; set <= 2; set++) { @@ -77,6 +114,7 @@ void setup_pch_lp_gpios(const struct pch_lp_gpio_map map[]) } outl(blink, gpio_base + GPIO_BLINK); + outl(pirq2apic, gpio_base + GPIO_PIRQ_APIC_EN); } int get_gpio(int gpio_num) diff --git a/src/southbridge/intel/lynxpoint/lp_gpio.h b/src/southbridge/intel/lynxpoint/lp_gpio.h index d9927dc975..f1b2717423 100644 --- a/src/southbridge/intel/lynxpoint/lp_gpio.h +++ b/src/southbridge/intel/lynxpoint/lp_gpio.h @@ -93,6 +93,11 @@ #define GPIO_RESET_PWROK 0 #define GPIO_RESET_RSMRST 1 +/* pirq route to io-apic */ + +#define GPIO_PIRQ_APIC_MASK 0 +#define GPIO_PIRQ_APIC_ROUTE 1 + #define LP_GPIO_END \ { .conf0 = GPIO_LIST_END } @@ -128,6 +133,11 @@ .owner = GPIO_OWNER_GPIO, \ .irqen = GPIO_IRQ_ENABLE } +#define LP_GPIO_PIRQ \ + { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_INPUT, \ + .owner = GPIO_OWNER_GPIO, \ + .pirq = GPIO_PIRQ_APIC_ROUTE } + #define LP_GPIO_OUT_HIGH \ { .conf0 = GPIO_MODE_GPIO | GPIO_DIR_OUTPUT | GPO_LEVEL_HIGH, \ .owner = GPIO_OWNER_GPIO, \ @@ -147,6 +157,7 @@ struct pch_lp_gpio_map { u8 irqen; u8 reset; u8 blink; + u8 pirq; } __attribute__ ((packed)); /* Configure GPIOs with mainboard provided settings */ diff --git a/src/southbridge/intel/lynxpoint/lpc.c b/src/southbridge/intel/lynxpoint/lpc.c index 33d74f1903..ff50476a62 100644 --- a/src/southbridge/intel/lynxpoint/lpc.c +++ b/src/southbridge/intel/lynxpoint/lpc.c @@ -59,6 +59,11 @@ static void pch_enable_ioapic(struct device *dev) /* affirm full set of redirection table entries ("write once") */ reg32 = io_apic_read(IO_APIC_ADDR, 0x01); + if (pch_is_lp()) { + /* PCH-LP has 39 redirection entries */ + reg32 &= ~0x00ff0000; + reg32 |= 0x00270000; + } io_apic_write(IO_APIC_ADDR, 0x01, reg32); /*