diff options
author | Furquan Shaikh <furquan@google.com> | 2021-04-10 14:27:16 -0700 |
---|---|---|
committer | Michael Niewöhner <foss@mniewoehner.de> | 2021-04-16 17:42:47 +0000 |
commit | d9ce2859a3d43f27773c3e5448d6c0b65420f352 (patch) | |
tree | fb56fc661058d742800b2a208bdb50fa97837745 /src/soc | |
parent | e07532fb160e54b9ded934c3964a2cf80f5ae780 (diff) | |
download | coreboot-d9ce2859a3d43f27773c3e5448d6c0b65420f352.tar.xz |
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>
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/intel/common/block/gpio/Kconfig | 1 | ||||
-rw-r--r-- | src/soc/intel/common/block/gpio/gpio.c | 85 |
2 files changed, 86 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/gpio/Kconfig b/src/soc/intel/common/block/gpio/Kconfig index 7e8970646f..c946545355 100644 --- a/src/soc/intel/common/block/gpio/Kconfig +++ b/src/soc/intel/common/block/gpio/Kconfig @@ -1,6 +1,7 @@ config SOC_INTEL_COMMON_BLOCK_GPIO bool select HAVE_DEBUG_GPIO + select HAVE_GPIO_SNAPSHOT_VERIFY_SUPPORT help Intel Processor common GPIO support diff --git a/src/soc/intel/common/block/gpio/gpio.c b/src/soc/intel/common/block/gpio/gpio.c index ca30fb5dc3..4398c9fb62 100644 --- a/src/soc/intel/common/block/gpio/gpio.c +++ b/src/soc/intel/common/block/gpio/gpio.c @@ -1,13 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ #include <assert.h> +#include <bootstate.h> #include <console/console.h> #include <device/device.h> +#include <fsp/debug.h> #include <intelblocks/gpio.h> #include <gpio.h> #include <intelblocks/itss.h> #include <intelblocks/pcr.h> #include <soc/pm.h> +#include <stdlib.h> #include <types.h> #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); 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); |