xref: /aosp_15_r20/external/coreboot/src/soc/amd/common/block/stb/stb.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include "commonlib/bsd/cb_err.h"
4 #include <amdblocks/smn.h>
5 #include <amdblocks/smu.h>
6 #include <amdblocks/stb.h>
7 #include <bootstate.h>
8 #include <cbmem.h>
9 #include <console/console.h>
10 #include <soc/smu.h>
11 #include <soc/stb.h>
12 
13 #define STB_ENTRIES_PER_ROW 4
14 
stb_write32(uint32_t reg,uint32_t val)15 static void stb_write32(uint32_t reg, uint32_t val)
16 {
17 	smn_write32(STB_CFG_SMN_ADDR + reg, val);
18 }
19 
stb_read32(uint32_t reg)20 static uint32_t stb_read32(uint32_t reg)
21 {
22 	return smn_read32(STB_CFG_SMN_ADDR + reg);
23 }
24 
soc_post_code(uint8_t value)25 void soc_post_code(uint8_t value)
26 {
27 	if (CONFIG(ADD_POSTCODES_TO_STB))
28 		stb_write32(AMD_STB_PMI_0, AMD_STB_COREBOOT_POST_PREFIX | value);
29 }
30 
write_stb_to_console(void)31 void write_stb_to_console(void)
32 {
33 	int i;
34 	int printed_data = 0;
35 	struct stb_entry_struct stb_val;
36 
37 	/* Add a marker into the STB so it's easy to see where the end is. */
38 	stb_write32(AMD_STB_PMI_0, AMD_STB_COREBOOT_MARKER);
39 
40 	for (i = 0; i < AMD_STB_SDRAM_FIFO_SIZE; i++) {
41 		/*
42 		 * It's possible to do a single read and leave the timestamp as the first
43 		 * value of a pair, but by default the value will be first and time stamp
44 		 * second.  We're just assuming that nothing has messed up the ordering.
45 		 */
46 		stb_val.val = stb_read32(AMD_STB_PMI_0);
47 		stb_val.ts = stb_read32(AMD_STB_PMI_0);
48 
49 		if (stb_val.val == AMD_STB_COREBOOT_MARKER) {
50 			if (!printed_data)
51 				printk(BIOS_DEBUG, "No Smart Trace Buffer Data available.\n");
52 			else
53 				// Don't print the coreboot marker
54 				printk(BIOS_DEBUG, "\n");
55 			return;
56 		}
57 
58 		if (i == 0)
59 			printk(BIOS_DEBUG, "Available Smart Trace Buffer data:\n");
60 		if ((i % STB_ENTRIES_PER_ROW) == 0)
61 			printk(BIOS_DEBUG, "%04d,", i);
62 		printk(BIOS_DEBUG, " 0x%08x,0x%08x, ", stb_val.ts, stb_val.val);
63 		if ((i % STB_ENTRIES_PER_ROW) == STB_ENTRIES_PER_ROW - 1)
64 			printk(BIOS_DEBUG, "\n");
65 		printed_data = 1;
66 	}
67 }
68 
init_spill_buffer(void * unused)69 static void init_spill_buffer(void *unused)
70 {
71 	struct smu_payload smu_payload = {0};
72 	uintptr_t stb;
73 	uint32_t size = CONFIG_AMD_STB_SIZE_IN_MB * MiB;
74 	int i;
75 
76 	if (!CONFIG(ENABLE_STB_SPILL_TO_DRAM))
77 		return;
78 
79 	stb = (uintptr_t)cbmem_add(CBMEM_ID_AMD_STB, size);
80 	if (!stb) {
81 		printk(BIOS_ERR, "Could not allocate cbmem buffer for STB\n");
82 		return;
83 	}
84 
85 	smu_payload.msg[0] = (uint32_t)stb;
86 	smu_payload.msg[1] = 0;
87 	smu_payload.msg[2] = size;
88 
89 	printk(BIOS_DEBUG, "STB spill buffer: allocated %d MiB at %lx\n",
90 	       CONFIG_AMD_STB_SIZE_IN_MB, stb);
91 
92 	if (send_smu_message(SMC_MSG_SET_S2D_ADDR, &smu_payload) == CB_ERR)
93 		printk(BIOS_ERR, "Could not enable STB Spill-to-dram\n");
94 
95 	for (i = 0; i < SMU_NUM_ARGS; i++)
96 		printk(BIOS_DEBUG, "smu_payload.msg[%d]: 0x%x\n", i, smu_payload.msg[i]);
97 }
98 
final_stb_console(void * unused)99 static void final_stb_console(void *unused)
100 {
101 	if (CONFIG(WRITE_STB_BUFFER_TO_CONSOLE))
102 		write_stb_to_console();
103 }
104 
105 BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, init_spill_buffer, NULL);
106 BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, final_stb_console, NULL);
107