xref: /aosp_15_r20/external/coreboot/src/soc/amd/picasso/soc_util.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <cpu/cpu.h>
5 #include <fsp/util.h>
6 #include <FspGuids.h>
7 #include <misc_data.h>
8 #include <soc/cpu.h>
9 #include <soc/soc_util.h>
10 #include <types.h>
11 
12 /*
13  * The Zen/Zen+ based APUs can be RV (sometimes called RV1), PCO or RV2 silicon. RV2 has less
14  * PCIe, USB3 and DisplayPort connectivity than RV(1) or PCO. A Picasso SoC is always PCO
15  * silicon, a Dali SoC can either be RV2 or fused-down PCO silicon that has the same
16  * connectivity as the RV2 one and Pollock is always RV2 silicon. Picasso and Dali are in a FP5
17  * package while Pollock is in the smaller FT5 package.
18  */
19 
20 #define SOCKET_TYPE_SHIFT	28
21 #define SOCKET_TYPE_MASK	(0xf << SOCKET_TYPE_SHIFT)
22 
23 /* some Pollock engineering samples return the wrong socket type */
get_socket_type(void)24 enum socket_type get_socket_type(void)
25 {
26 	uint32_t ebx = cpuid_ebx(0x80000001);
27 	ebx = (ebx & SOCKET_TYPE_MASK) >> SOCKET_TYPE_SHIFT;
28 	return (enum socket_type)ebx;
29 }
30 
print_socket_type(void)31 void print_socket_type(void)
32 {
33 	enum socket_type socket = get_socket_type();
34 
35 	printk(BIOS_INFO, "Socket type: ");
36 
37 	switch (socket) {
38 	case SOCKET_FP5:
39 		printk(BIOS_INFO, "FP5\n");
40 		break;
41 	case SOCKET_AM4:
42 		printk(BIOS_INFO, "AM4\n");
43 		break;
44 	case SOCKET_FT5:
45 		printk(BIOS_INFO, "FT5\n");
46 		break;
47 	default:
48 		printk(BIOS_INFO, "unknown\n");
49 	}
50 }
51 
52 /* returns 0 in case or errors */
get_internal_silicon_type(void)53 static uint32_t get_internal_silicon_type(void)
54 {
55 	static uint32_t silicon_type;
56 	size_t hob_size = 0;
57 	const struct picasso_misc_data *hob;
58 
59 	if (silicon_type)
60 		return silicon_type;
61 
62 	hob = fsp_find_extension_hob_by_guid(PICASSO_MISC_DATA_HOB_GUID.b, &hob_size);
63 
64 	if (hob == NULL || hob_size == 0) {
65 		printk(BIOS_ERR, "Couldn't find Picasso misc data HOB.\n");
66 		return 0;
67 	}
68 
69 	if (hob->version != PICASSO_MISC_DATA_VERSION) {
70 		printk(BIOS_ERR, "Unexpected Picasso misc data HOB version.\n");
71 		return 0;
72 	}
73 
74 	silicon_type = hob->silicon_id;
75 
76 	printk(BIOS_DEBUG, "Silicon ID = 0x%x\n", silicon_type);
77 
78 	return silicon_type;
79 }
80 
81 #define SILICON_IS_MYSTERY_MEAT	(1 << 31)
82 #define SILICON_IS_RV2		(1 << 30)
83 
is_rv2_silicon(void)84 static bool is_rv2_silicon(void)
85 {
86 	return get_internal_silicon_type() & SILICON_IS_RV2;
87 }
88 
is_mystery_silicon(void)89 static bool is_mystery_silicon(void)
90 {
91 	return get_internal_silicon_type() & SILICON_IS_MYSTERY_MEAT;
92 }
93 
is_fam17_1x(void)94 static bool is_fam17_1x(void)
95 {
96 	return cpuid_match(cpuid_eax(1), PICASSO_B0_CPUID,
97 			   CPUID_ALL_STEPPINGS_AND_BASE_MODELS_MASK);
98 }
99 
is_fam17_11(void)100 static bool is_fam17_11(void)
101 {
102 	return cpuid_match(cpuid_eax(1), RAVEN1_B0_CPUID, CPUID_ALL_STEPPINGS_MASK);
103 }
104 
is_fam17_18(void)105 static bool is_fam17_18(void)
106 {
107 	return cpuid_match(cpuid_eax(1), PICASSO_B0_CPUID, CPUID_ALL_STEPPINGS_MASK);
108 }
109 
is_fam17_2x(void)110 static bool is_fam17_2x(void)
111 {
112 	return cpuid_match(cpuid_eax(1), RAVEN2_A0_CPUID,
113 			   CPUID_ALL_STEPPINGS_AND_BASE_MODELS_MASK);
114 }
115 
is_fam17_20(void)116 static bool is_fam17_20(void)
117 {
118 	return cpuid_match(cpuid_eax(1), RAVEN2_A0_CPUID, CPUID_ALL_STEPPINGS_MASK);
119 }
120 
get_silicon_type(void)121 enum silicon_type get_silicon_type(void)
122 {
123 	/*
124 	 * RV2 is fam17_20, but might return a fam17_1x CPUID in the is_mystery_silicon() case.
125 	 * is_rv2_silicon() has the correct information, but requires the HOB to be present.
126 	 */
127 	if (is_fam17_20() || is_rv2_silicon())
128 		return SILICON_RV2;
129 
130 	if (is_fam17_18() && !is_rv2_silicon())
131 		return SILICON_PCO;
132 
133 	if (is_fam17_11() && !is_rv2_silicon())
134 		return SILICON_RV1;
135 
136 	/* some cases might still be missing */
137 
138 	return SILICON_UNKNOWN;
139 }
140 
141 /* some Pollock engineering samples return the wrong socket type and get detected as Dali */
get_soc_type(void)142 enum soc_type get_soc_type(void)
143 {
144 	switch (get_socket_type()) {
145 	case SOCKET_FP5:
146 		if (is_fam17_1x() && !is_mystery_silicon())
147 			return SOC_PICASSO;
148 
149 		if (is_fam17_2x() || (is_fam17_1x() && is_mystery_silicon()))
150 			return SOC_DALI;
151 
152 		break;
153 	case SOCKET_FT5:
154 		/* add is_fam17_20() CPUID sanity check here? */
155 		return SOC_POLLOCK;
156 	case SOCKET_AM4:
157 		/* AM4 SoC type detection logic not implemented */
158 		break;
159 	}
160 
161 	return SOC_UNKNOWN;
162 }
163 
print_silicon_type(void)164 void print_silicon_type(void)
165 {
166 	const enum silicon_type silicon = get_silicon_type();
167 
168 	printk(BIOS_INFO, "Silicon type: ");
169 
170 	switch (silicon) {
171 	case SILICON_RV1:
172 		printk(BIOS_INFO, "RV1\n");
173 		break;
174 	case SILICON_PCO:
175 		printk(BIOS_INFO, "PCO\n");
176 		break;
177 	case SILICON_RV2:
178 		printk(BIOS_INFO, "RV2\n");
179 		break;
180 	default:
181 		printk(BIOS_INFO, "unknown\n");
182 	}
183 }
184 
print_soc_type(void)185 void print_soc_type(void)
186 {
187 	const enum soc_type soc = get_soc_type();
188 
189 	printk(BIOS_INFO, "SoC type: ");
190 
191 	switch (soc) {
192 	case SOC_PICASSO:
193 		printk(BIOS_INFO, "Picasso\n");
194 		break;
195 	case SOC_DALI:
196 		printk(BIOS_INFO, "Dali\n");
197 		break;
198 	case SOC_POLLOCK:
199 		printk(BIOS_INFO, "Pollock\n");
200 		break;
201 	default:
202 		printk(BIOS_INFO, "unknown\n");
203 	}
204 }
205 
soc_is_reduced_io_sku(void)206 bool soc_is_reduced_io_sku(void)
207 {
208 	return get_silicon_type() == SILICON_RV2 || get_soc_type() == SOC_DALI;
209 }
210 
soc_is_raven2(void)211 bool soc_is_raven2(void)
212 {
213 	return get_silicon_type() == SILICON_RV2;
214 }
215