diff --git a/src/soc/amd/common/block/include/amdblocks/stb.h b/src/soc/amd/common/block/include/amdblocks/stb.h new file mode 100644 index 0000000000..51b01948f8 --- /dev/null +++ b/src/soc/amd/common/block/include/amdblocks/stb.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef AMD_BLOCK_STB_H +#define AMD_BLOCK_STB_H + +#include + +#define AMD_STB_PMI_0 0x30600 + +#define AMD_STB_COREBOOT_MARKER 0xBAADF00D + +struct stb_entry_struct { + uint32_t ts; + uint32_t val; +}; + +void write_stb_to_console(void); +void init_spill_buffer(void); +void add_stb_to_timestamp_buffer(void); + +#endif /* AMD_BLOCK_STB_H */ diff --git a/src/soc/amd/common/block/stb/Kconfig b/src/soc/amd/common/block/stb/Kconfig new file mode 100644 index 0000000000..8935e92556 --- /dev/null +++ b/src/soc/amd/common/block/stb/Kconfig @@ -0,0 +1,17 @@ +config SOC_AMD_COMMON_BLOCK_STB + bool + select SOC_AMD_COMMON_BLOCK_SMN + help + Select in the SOC if it supports the Smart Trace Buffer + +if SOC_AMD_COMMON_BLOCK_STB + +config WRITE_STB_BUFFER_TO_CONSOLE + bool "Write STB entries to the console log" + default n + help + This option will tell coreboot to print the STB buffer at various + points through the boot process. Note that this will prevent the + entries from being stored if the Spill-to-DRAM feature is enabled. + +endif diff --git a/src/soc/amd/common/block/stb/Makefile.inc b/src/soc/amd/common/block/stb/Makefile.inc new file mode 100644 index 0000000000..5ce9c4b228 --- /dev/null +++ b/src/soc/amd/common/block/stb/Makefile.inc @@ -0,0 +1,7 @@ +ifeq ($(CONFIG_SOC_AMD_COMMON_BLOCK_STB),y) + +bootblock-y += stb.c +romstage-y += stb.c +ramstage-y += stb.c + +endif # CONFIG_SOC_AMD_COMMON_BLOCK_STB diff --git a/src/soc/amd/common/block/stb/stb.c b/src/soc/amd/common/block/stb/stb.c new file mode 100644 index 0000000000..074a4ed714 --- /dev/null +++ b/src/soc/amd/common/block/stb/stb.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include + +#define STB_ENTRIES_PER_ROW 4 + +static void stb_write32(uint32_t reg, uint32_t val) +{ + smn_write32(STB_CFG_SMN_ADDR + reg, val); +} + +static uint32_t stb_read32(uint32_t reg) +{ + return smn_read32(STB_CFG_SMN_ADDR + reg); +} + +void write_stb_to_console(void) +{ + int i; + int printed_data = 0; + struct stb_entry_struct stb_val; + + /* Add a marker into the STB so it's easy to see where the end is. */ + stb_write32(AMD_STB_PMI_0, AMD_STB_COREBOOT_MARKER); + + for (i = 0; i < AMD_STB_SDRAM_FIFO_SIZE; i++) { + /* + * It's possible to do a single read and leave the timestamp as the first + * value of a pair, but by default the value will be first and time stamp + * second. We're just assuming that nothing has messed up the ordering. + */ + stb_val.val = stb_read32(AMD_STB_PMI_0); + stb_val.ts = stb_read32(AMD_STB_PMI_0); + + if (stb_val.val == AMD_STB_COREBOOT_MARKER) { + if (!printed_data) + printk(BIOS_DEBUG, "No Smart Trace Buffer Data available.\n"); + else + // Don't print the coreboot marker + printk(BIOS_DEBUG, "\n"); + return; + } + + if (i == 0) + printk(BIOS_DEBUG, "Available Smart Trace Buffer data:\n"); + if ((i % STB_ENTRIES_PER_ROW) == 0) + printk(BIOS_DEBUG, "%04d,", i); + printk(BIOS_DEBUG, " 0x%08x,0x%08x, ", stb_val.ts, stb_val.val); + if ((i % STB_ENTRIES_PER_ROW) == STB_ENTRIES_PER_ROW - 1) + printk(BIOS_DEBUG, "\n"); + printed_data = 1; + + } + +} + +static void final_stb_console(void *unused) +{ + if (CONFIG(WRITE_STB_BUFFER_TO_CONSOLE)) + write_stb_to_console(); +} + +BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, final_stb_console, NULL);