soc/intel/common/gpio: Implement GPIO snapshot/verify callbacks
This change implements `gpio_snapshot()` and `gpio_verify_snapshot()` callbacks that are useful for debugging any GPIO configuration changes across FSP-S. These can be utilized by all Intel SoCs that make use of the common block GPIO driver. Signed-off-by: Furquan Shaikh <furquan@google.com> Change-Id: I82a1f125c490b9d6e26e6e9527c2fcd55bb9d429 Reviewed-on: https://review.coreboot.org/c/coreboot/+/50990 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Michael Niewöhner <foss@mniewoehner.de>
This commit is contained in:
parent
e07532fb16
commit
d9ce2859a3
|
@ -1,6 +1,7 @@
|
||||||
config SOC_INTEL_COMMON_BLOCK_GPIO
|
config SOC_INTEL_COMMON_BLOCK_GPIO
|
||||||
bool
|
bool
|
||||||
select HAVE_DEBUG_GPIO
|
select HAVE_DEBUG_GPIO
|
||||||
|
select HAVE_GPIO_SNAPSHOT_VERIFY_SUPPORT
|
||||||
help
|
help
|
||||||
Intel Processor common GPIO support
|
Intel Processor common GPIO support
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <bootstate.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <device/device.h>
|
#include <device/device.h>
|
||||||
|
#include <fsp/debug.h>
|
||||||
#include <intelblocks/gpio.h>
|
#include <intelblocks/gpio.h>
|
||||||
#include <gpio.h>
|
#include <gpio.h>
|
||||||
#include <intelblocks/itss.h>
|
#include <intelblocks/itss.h>
|
||||||
#include <intelblocks/pcr.h>
|
#include <intelblocks/pcr.h>
|
||||||
#include <soc/pm.h>
|
#include <soc/pm.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
#define GPIO_DWx_SIZE(x) (sizeof(uint32_t) * (x))
|
#define GPIO_DWx_SIZE(x) (sizeof(uint32_t) * (x))
|
||||||
|
@ -678,3 +681,85 @@ size_t gpio_get_index_in_group(gpio_t pad)
|
||||||
pin = relative_pad_in_comm(comm, pad);
|
pin = relative_pad_in_comm(comm, pad);
|
||||||
return gpio_within_group(comm, pin);
|
return gpio_within_group(comm, pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t *snapshot;
|
||||||
|
|
||||||
|
static void *allocate_snapshot_space(void)
|
||||||
|
{
|
||||||
|
size_t gpio_communities, total = 0, i;
|
||||||
|
const struct pad_community *comm;
|
||||||
|
|
||||||
|
comm = soc_gpio_get_community(&gpio_communities);
|
||||||
|
for (i = 0; i < gpio_communities; i++, comm++)
|
||||||
|
total += comm->last_pad - comm->first_pad + 1;
|
||||||
|
|
||||||
|
if (total == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return malloc(total * GPIO_NUM_PAD_CFG_REGS * sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_snapshot(void)
|
||||||
|
{
|
||||||
|
size_t gpio_communities, index, i, pad, reg;
|
||||||
|
const struct pad_community *comm;
|
||||||
|
uint16_t config_offset;
|
||||||
|
|
||||||
|
if (snapshot == NULL) {
|
||||||
|
snapshot = allocate_snapshot_space();
|
||||||
|
if (snapshot == NULL)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
comm = soc_gpio_get_community(&gpio_communities);
|
||||||
|
for (i = 0, index = 0; i < gpio_communities; i++, comm++) {
|
||||||
|
for (pad = comm->first_pad; pad <= comm->last_pad; pad++) {
|
||||||
|
config_offset = pad_config_offset(comm, pad);
|
||||||
|
for (reg = 0; reg < GPIO_NUM_PAD_CFG_REGS; reg++) {
|
||||||
|
snapshot[index] = pcr_read32(comm->port,
|
||||||
|
PAD_CFG_OFFSET(config_offset, reg));
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t gpio_verify_snapshot(void)
|
||||||
|
{
|
||||||
|
size_t gpio_communities, index, i, pad, reg;
|
||||||
|
const struct pad_community *comm;
|
||||||
|
uint32_t curr_val;
|
||||||
|
uint16_t config_offset;
|
||||||
|
size_t changes = 0;
|
||||||
|
|
||||||
|
if (snapshot == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
comm = soc_gpio_get_community(&gpio_communities);
|
||||||
|
for (i = 0, index = 0; i < gpio_communities; i++, comm++) {
|
||||||
|
for (pad = comm->first_pad; pad <= comm->last_pad; pad++) {
|
||||||
|
config_offset = pad_config_offset(comm, pad);
|
||||||
|
for (reg = 0; reg < GPIO_NUM_PAD_CFG_REGS; reg++) {
|
||||||
|
curr_val = pcr_read32(comm->port,
|
||||||
|
PAD_CFG_OFFSET(config_offset, reg));
|
||||||
|
if (curr_val != snapshot[index]) {
|
||||||
|
printk(BIOS_SPEW,
|
||||||
|
"%zd(DW%zd): Changed from 0x%x to 0x%x\n",
|
||||||
|
pad, reg, snapshot[index], curr_val);
|
||||||
|
changes++;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void snapshot_cleanup(void *unused)
|
||||||
|
{
|
||||||
|
free(snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_EXIT, snapshot_cleanup, NULL);
|
||||||
|
BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, snapshot_cleanup, NULL);
|
||||||
|
|
Loading…
Reference in New Issue