blob: 9616f26bf58919814fc748715849d17f74029e55 [file] [log] [blame]
Martin Roth97bd2a72020-02-17 13:17:19 -07001/* SPDX-License-Identifier: GPL-2.0-only */
Martin Roth97bd2a72020-02-17 13:17:19 -07002
Felix Heldbf213082020-05-18 20:27:04 +02003#include <console/console.h>
Elyes Haouasf743e0c2022-10-31 13:46:00 +01004#include <cpu/cpu.h>
Felix Held828ca062020-05-20 02:34:59 +02005#include <fsp/util.h>
Elyes Haouasf743e0c2022-10-31 13:46:00 +01006#include <FspGuids.h>
Felix Held828ca062020-05-20 02:34:59 +02007#include <misc_data.h>
Martin Roth97bd2a72020-02-17 13:17:19 -07008#include <soc/cpu.h>
9#include <soc/soc_util.h>
Felix Heldbf213082020-05-18 20:27:04 +020010#include <types.h>
11
Felix Heldaf05c862020-06-26 19:15:43 +020012/*
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
Felix Heldbf213082020-05-18 20:27:04 +020020#define SOCKET_TYPE_SHIFT 28
Angel Pons6ca33752021-03-18 00:58:26 +010021#define SOCKET_TYPE_MASK (0xf << SOCKET_TYPE_SHIFT)
Felix Heldbf213082020-05-18 20:27:04 +020022
Felix Held3c93b7e2020-05-27 23:25:38 +020023/* some Pollock engineering samples return the wrong socket type */
Felix Held828ca062020-05-20 02:34:59 +020024enum socket_type get_socket_type(void)
Felix Heldbf213082020-05-18 20:27:04 +020025{
26 uint32_t ebx = cpuid_ebx(0x80000001);
Angel Pons6ca33752021-03-18 00:58:26 +010027 ebx = (ebx & SOCKET_TYPE_MASK) >> SOCKET_TYPE_SHIFT;
Felix Heldbf213082020-05-18 20:27:04 +020028 return (enum socket_type)ebx;
29}
30
31void 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}
Martin Roth97bd2a72020-02-17 13:17:19 -070051
Felix Held828ca062020-05-20 02:34:59 +020052/* returns 0 in case or errors */
53static uint32_t get_internal_silicon_type(void)
Martin Roth97bd2a72020-02-17 13:17:19 -070054{
Felix Held828ca062020-05-20 02:34:59 +020055 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;
Martin Roth97bd2a72020-02-17 13:17:19 -070079}
80
Felix Held828ca062020-05-20 02:34:59 +020081#define SILICON_IS_MYSTERY_MEAT (1 << 31)
82#define SILICON_IS_RV2 (1 << 30)
83
84static bool is_rv2_silicon(void)
Martin Roth97bd2a72020-02-17 13:17:19 -070085{
Felix Held828ca062020-05-20 02:34:59 +020086 return get_internal_silicon_type() & SILICON_IS_RV2;
Martin Roth97bd2a72020-02-17 13:17:19 -070087}
88
Felix Held828ca062020-05-20 02:34:59 +020089static bool is_mystery_silicon(void)
Martin Roth97bd2a72020-02-17 13:17:19 -070090{
Felix Held828ca062020-05-20 02:34:59 +020091 return get_internal_silicon_type() & SILICON_IS_MYSTERY_MEAT;
Martin Roth97bd2a72020-02-17 13:17:19 -070092}
93
Felix Held828ca062020-05-20 02:34:59 +020094static bool is_fam17_1x(void)
95{
96 /* mask lower model number nibble and stepping */
Felix Heldab114c92020-05-22 02:40:40 +020097 return cpuid_eax(1) >> 8 == PICASSO_B1_CPUID >> 8;
Felix Held828ca062020-05-20 02:34:59 +020098}
99
100static bool is_fam17_11(void)
101{
102 /* only mask stepping */
Felix Heldab114c92020-05-22 02:40:40 +0200103 return cpuid_eax(1) >> 4 == RAVEN1_B0_CPUID >> 4;
Felix Held828ca062020-05-20 02:34:59 +0200104}
105
106static bool is_fam17_18(void)
107{
108 /* only mask stepping */
Felix Heldab114c92020-05-22 02:40:40 +0200109 return cpuid_eax(1) >> 4 == PICASSO_B1_CPUID >> 4;
Felix Held828ca062020-05-20 02:34:59 +0200110}
111
112static bool is_fam17_2x(void)
Martin Roth97bd2a72020-02-17 13:17:19 -0700113{
114 /* mask lower model number nibble and stepping */
Felix Heldab114c92020-05-22 02:40:40 +0200115 return cpuid_eax(1) >> 8 == RAVEN2_A1_CPUID >> 8;
Martin Roth97bd2a72020-02-17 13:17:19 -0700116}
117
Felix Held828ca062020-05-20 02:34:59 +0200118static bool is_fam17_20(void)
Martin Roth97bd2a72020-02-17 13:17:19 -0700119{
Felix Held828ca062020-05-20 02:34:59 +0200120 /* only mask stepping */
121 return cpuid_eax(1) >> 4 == RAVEN2_A1_CPUID >> 4;
122}
123
124enum silicon_type get_silicon_type(void)
125{
126 /*
127 * RV2 is fam17_20, but might return a fam17_1x CPUID in the is_mystery_silicon() case.
128 * is_rv2_silicon() has the correct information, but requires the HOB to be present.
129 */
130 if (is_fam17_20() || is_rv2_silicon())
131 return SILICON_RV2;
132
133 if (is_fam17_18() && !is_rv2_silicon())
134 return SILICON_PCO;
135
136 if (is_fam17_11() && !is_rv2_silicon())
137 return SILICON_RV1;
138
139 /* some cases might still be missing */
140
141 return SILICON_UNKNOWN;
142}
143
Felix Held3c93b7e2020-05-27 23:25:38 +0200144/* some Pollock engineering samples return the wrong socket type and get detected as Dali */
Felix Held828ca062020-05-20 02:34:59 +0200145enum soc_type get_soc_type(void)
146{
147 switch (get_socket_type()) {
148 case SOCKET_FP5:
149 if (is_fam17_1x() && !is_mystery_silicon())
150 return SOC_PICASSO;
151
152 if (is_fam17_2x() || (is_fam17_1x() && is_mystery_silicon()))
153 return SOC_DALI;
154
155 break;
156 case SOCKET_FT5:
157 /* add is_fam17_20() CPUID sanity check here? */
158 return SOC_POLLOCK;
159 break;
160 case SOCKET_AM4:
161 /* AM4 SoC type detection logic not implemented */
162 break;
163 }
164
165 return SOC_UNKNOWN;
166}
167
168void print_silicon_type(void)
169{
170 const enum silicon_type silicon = get_silicon_type();
171
172 printk(BIOS_INFO, "Silicon type: ");
173
174 switch (silicon) {
175 case SILICON_RV1:
176 printk(BIOS_INFO, "RV1\n");
177 break;
178 case SILICON_PCO:
179 printk(BIOS_INFO, "PCO\n");
180 break;
181 case SILICON_RV2:
182 printk(BIOS_INFO, "RV2\n");
183 break;
184 default:
185 printk(BIOS_INFO, "unknown\n");
186 }
187}
188
189void print_soc_type(void)
190{
191 const enum soc_type soc = get_soc_type();
192
193 printk(BIOS_INFO, "SoC type: ");
194
195 switch (soc) {
196 case SOC_PICASSO:
197 printk(BIOS_INFO, "Picasso\n");
198 break;
199 case SOC_DALI:
200 printk(BIOS_INFO, "Dali\n");
201 break;
202 case SOC_POLLOCK:
203 printk(BIOS_INFO, "Pollock\n");
204 break;
205 default:
206 printk(BIOS_INFO, "unknown\n");
207 }
208}
209
Felix Held42b0e8f2020-06-26 18:03:53 +0200210bool soc_is_reduced_io_sku(void)
Felix Held828ca062020-05-20 02:34:59 +0200211{
Felix Held42b0e8f2020-06-26 18:03:53 +0200212 return get_silicon_type() == SILICON_RV2 || get_soc_type() == SOC_DALI;
Felix Held828ca062020-05-20 02:34:59 +0200213}
214
Felix Held828ca062020-05-20 02:34:59 +0200215bool soc_is_raven2(void)
216{
217 return get_silicon_type() == SILICON_RV2;
Martin Roth97bd2a72020-02-17 13:17:19 -0700218}