sb/inte/common/gpio: Implement gpio_input() and gpio_output()

Implement the two functions defined as prototypes in gpio.h.
Allows to drop custom SMI handler code and use the generic function
from gpio.c instead.

Change-Id: I795af83374118d3fc2b46837b1822205c966fda6
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/88508
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Patrick Rudolph 2025-07-21 09:15:39 +02:00 committed by Matt DeVillier
commit c54fde5040
3 changed files with 80 additions and 86 deletions

View file

@ -10,64 +10,25 @@
#include <device/pci_def.h>
#include <device/pci_ops.h>
#include <northbridge/intel/sandybridge/sandybridge.h>
#include <gpio.h>
#include <soc/nvs.h>
#include <southbridge/intel/bd82x6x/me.h>
#include <southbridge/intel/common/finalize.h>
#include <southbridge/intel/common/gpio.h>
#include <southbridge/intel/common/pmutil.h>
#include <types.h>
#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)

View file

@ -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);
}

View file

@ -7,6 +7,7 @@
#include <device/pci_def.h>
#include <cpu/intel/em64t101_save_state.h>
#include <cpu/intel/model_2065x/model_2065x.h>
#include <gpio.h>
#include <southbridge/intel/common/finalize.h>
#include <southbridge/intel/common/pmbase.h>
#include <southbridge/intel/ibexpeak/me.h>
@ -17,58 +18,18 @@
* 2. we don't need to worry about how we leave 0xcf8/0xcfc behind
*/
#include <northbridge/intel/ironlake/ironlake.h>
#include <southbridge/intel/common/gpio.h>
#include <southbridge/intel/common/pmutil.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(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)