diff --git a/src/southbridge/intel/bd82x6x/smihandler.c b/src/southbridge/intel/bd82x6x/smihandler.c index d4833a2673..fa166a4244 100644 --- a/src/southbridge/intel/bd82x6x/smihandler.c +++ b/src/southbridge/intel/bd82x6x/smihandler.c @@ -10,64 +10,25 @@ #include #include #include +#include #include #include #include -#include #include #include #include "pch.h" -static void southbridge_gate_memory_reset_real(int offset, - u16 use, u16 io, u16 lvl) -{ - u32 reg32; - - /* Make sure it is set as GPIO */ - reg32 = inl(use); - if (!(reg32 & (1 << offset))) { - reg32 |= (1 << offset); - outl(reg32, use); - } - - /* Make sure it is set as output */ - reg32 = inl(io); - if (reg32 & (1 << offset)) { - reg32 &= ~(1 << offset); - outl(reg32, io); - } - - /* Drive the output low */ - reg32 = inl(lvl); - reg32 &= ~(1 << offset); - outl(reg32, lvl); -} - /* - * Drive GPIO 60 low to gate memory reset in S3. + * Drive reset gate GPIO low to gate memory reset in S3. * * Intel reference designs all use GPIO 60 but it is * not a requirement and boards could use a different pin. */ void southbridge_gate_memory_reset(void) { - u16 gpiobase; - gpiobase = pci_read_config16(PCH_LPC_DEV, GPIOBASE) & 0xfffc; - if (!gpiobase) - return; - - if (CONFIG_DRAM_RESET_GATE_GPIO >= 32) - southbridge_gate_memory_reset_real(CONFIG_DRAM_RESET_GATE_GPIO - 32, - gpiobase + GPIO_USE_SEL2, - gpiobase + GP_IO_SEL2, - gpiobase + GP_LVL2); - else - southbridge_gate_memory_reset_real(CONFIG_DRAM_RESET_GATE_GPIO, - gpiobase + GPIO_USE_SEL, - gpiobase + GP_IO_SEL, - gpiobase + GP_LVL); + gpio_output(CONFIG_DRAM_RESET_GATE_GPIO, 0); } void southbridge_smi_monitor(void) diff --git a/src/southbridge/intel/common/gpio.c b/src/southbridge/intel/common/gpio.c index 8ce77fbcb6..a1b2b5426b 100644 --- a/src/southbridge/intel/common/gpio.c +++ b/src/southbridge/intel/common/gpio.c @@ -146,7 +146,79 @@ int gpio_is_native(int gpio_num) return !(config & (1 << bit)); } -void gpio_input(gpio_t gpio) +static void gpio_set_gpio(gpio_t gpio_num) { - // FIXME: Implement + static const int gpio_use_reg_offsets[] = { + GPIO_USE_SEL, GPIO_USE_SEL2, GPIO_USE_SEL3 + }; + u16 gpio_base = get_gpio_base(); + int index, bit; + u32 config; + + if (gpio_num > MAX_GPIO_NUMBER) + return; /* Just ignore wrong gpio numbers. */ + + index = gpio_num / 32; + bit = gpio_num % 32; + + config = inl(gpio_base + gpio_use_reg_offsets[index]); + if (config & (GPIO_MODE_GPIO << bit)) + return; + + config |= GPIO_MODE_GPIO << bit; + outl(gpio_base + gpio_use_reg_offsets[index], config); +} + +void gpio_input(gpio_t gpio_num) +{ + static const int gpio_io_reg_offsets[] = { + GP_IO_SEL, GP_IO_SEL2, GP_IO_SEL3 + }; + u16 gpio_base = get_gpio_base(); + int index, bit; + u32 config; + + if (gpio_num > MAX_GPIO_NUMBER) + return; /* Just ignore wrong gpio numbers. */ + + gpio_set_gpio(gpio_num); + + index = gpio_num / 32; + bit = gpio_num % 32; + + config = inl(gpio_base + gpio_io_reg_offsets[index]); + if (((config >> bit) & 1) == GPIO_DIR_INPUT) + return; + + config |= 1 << bit; + outl(gpio_base + gpio_io_reg_offsets[index], config); +} + +void gpio_output(gpio_t gpio_num, int value) +{ + static const int gpio_io_reg_offsets[] = { + GP_IO_SEL, GP_IO_SEL2, GP_IO_SEL3 + }; + u16 gpio_base = get_gpio_base(); + int index, bit; + u32 config; + + if (gpio_num > MAX_GPIO_NUMBER) + return; /* Just ignore wrong gpio numbers. */ + + gpio_set_gpio(gpio_num); + gpio_set(gpio_num, value); + + index = gpio_num / 32; + bit = gpio_num % 32; + + config = inl(gpio_base + gpio_io_reg_offsets[index]); + if (((config >> bit) & 1) == GPIO_DIR_OUTPUT) + return; + + config &= ~(1 << bit); + outl(gpio_base + gpio_io_reg_offsets[index], config); + + /* Set value again in case output register was gated */ + gpio_set(gpio_num, value); } diff --git a/src/southbridge/intel/ibexpeak/smihandler.c b/src/southbridge/intel/ibexpeak/smihandler.c index cb4f65ea95..5ced6a7c04 100644 --- a/src/southbridge/intel/ibexpeak/smihandler.c +++ b/src/southbridge/intel/ibexpeak/smihandler.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -17,58 +18,18 @@ * 2. we don't need to worry about how we leave 0xcf8/0xcfc behind */ #include -#include #include -static void southbridge_gate_memory_reset_real(int offset, - u16 use, u16 io, u16 lvl) -{ - u32 reg32; - - /* Make sure it is set as GPIO */ - reg32 = inl(use); - if (!(reg32 & (1 << offset))) { - reg32 |= (1 << offset); - outl(reg32, use); - } - - /* Make sure it is set as output */ - reg32 = inl(io); - if (reg32 & (1 << offset)) { - reg32 &= ~(1 << offset); - outl(reg32, io); - } - - /* Drive the output low */ - reg32 = inl(lvl); - reg32 &= ~(1 << offset); - outl(reg32, lvl); -} - /* - * Drive GPIO 60 low to gate memory reset in S3. + * Drive reset gate GPIO low to gate memory reset in S3. * * Intel reference designs all use GPIO 60 but it is * not a requirement and boards could use a different pin. */ void southbridge_gate_memory_reset(void) { - u16 gpiobase; - gpiobase = pci_read_config16(PCI_DEV(0, 0x1f, 0), GPIOBASE) & 0xfffc; - if (!gpiobase) - return; - - if (CONFIG_DRAM_RESET_GATE_GPIO >= 32) - southbridge_gate_memory_reset_real(CONFIG_DRAM_RESET_GATE_GPIO - 32, - gpiobase + GPIO_USE_SEL2, - gpiobase + GP_IO_SEL2, - gpiobase + GP_LVL2); - else - southbridge_gate_memory_reset_real(CONFIG_DRAM_RESET_GATE_GPIO, - gpiobase + GPIO_USE_SEL, - gpiobase + GP_IO_SEL, - gpiobase + GP_LVL); + gpio_output(CONFIG_DRAM_RESET_GATE_GPIO, 0); } void southbridge_smi_monitor(void)