summaryrefslogtreecommitdiff
path: root/src/soc/amd
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/amd')
-rw-r--r--src/soc/amd/picasso/include/soc/soc_util.h24
-rw-r--r--src/soc/amd/picasso/soc_util.c179
2 files changed, 187 insertions, 16 deletions
diff --git a/src/soc/amd/picasso/include/soc/soc_util.h b/src/soc/amd/picasso/include/soc/soc_util.h
index 6515761a8a..6399e42bb9 100644
--- a/src/soc/amd/picasso/include/soc/soc_util.h
+++ b/src/soc/amd/picasso/include/soc/soc_util.h
@@ -11,12 +11,34 @@ enum socket_type {
SOCKET_FT5 = 3,
};
+enum silicon_type {
+ SILICON_RV1,
+ SILICON_PCO,
+ SILICON_RV2,
+ SILICON_UNKNOWN,
+};
+
+enum soc_type {
+ SOC_PICASSO,
+ SOC_DALI,
+ SOC_POLLOCK,
+ SOC_UNKNOWN,
+};
+
+enum socket_type get_socket_type(void);
+enum silicon_type get_silicon_type(void);
+enum soc_type get_soc_type(void);
+
void print_socket_type(void);
+void print_silicon_type(void);
+void print_soc_type(void);
+/* functions to determine the connectivity feature set */
bool soc_is_pollock(void);
bool soc_is_dali(void);
bool soc_is_picasso(void);
+
+/* function to determine the iGPU type */
bool soc_is_raven2(void);
-bool soc_is_zen_plus(void);
#endif /* __PICASSO_SOC_UTIL_H__ */
diff --git a/src/soc/amd/picasso/soc_util.c b/src/soc/amd/picasso/soc_util.c
index 89aa0a40ff..70cc578ec9 100644
--- a/src/soc/amd/picasso/soc_util.c
+++ b/src/soc/amd/picasso/soc_util.c
@@ -2,6 +2,9 @@
#include <arch/cpu.h>
#include <console/console.h>
+#include <FspGuids.h>
+#include <fsp/util.h>
+#include <misc_data.h>
#include <soc/cpu.h>
#include <soc/soc_util.h>
#include <types.h>
@@ -9,7 +12,7 @@
#define SOCKET_TYPE_SHIFT 28
#define SOCKET_TYPSE_MASK (0xf << SOCKET_TYPE_SHIFT)
-static enum socket_type get_socket_type(void)
+enum socket_type get_socket_type(void)
{
uint32_t ebx = cpuid_ebx(0x80000001);
ebx = (ebx & SOCKET_TYPSE_MASK) >> SOCKET_TYPE_SHIFT;
@@ -37,33 +40,179 @@ void print_socket_type(void)
}
}
-bool soc_is_pollock(void)
+/* returns 0 in case or errors */
+static uint32_t get_internal_silicon_type(void)
{
- return soc_is_zen_plus() && get_socket_type() == SOCKET_FT5;
+ static uint32_t silicon_type;
+ size_t hob_size = 0;
+ const struct picasso_misc_data *hob;
+
+ if (silicon_type)
+ return silicon_type;
+
+ hob = fsp_find_extension_hob_by_guid(PICASSO_MISC_DATA_HOB_GUID.b, &hob_size);
+
+ if (hob == NULL || hob_size == 0) {
+ printk(BIOS_ERR, "Couldn't find Picasso misc data HOB.\n");
+ return 0;
+ }
+
+ if (hob->version != PICASSO_MISC_DATA_VERSION) {
+ printk(BIOS_ERR, "Unexpected Picasso misc data HOB version.\n");
+ return 0;
+ }
+
+ silicon_type = hob->silicon_id;
+
+ printk(BIOS_DEBUG, "Silicon ID = 0x%x\n", silicon_type);
+
+ return silicon_type;
}
-/*
- * TODO: This detection works for the Dali SKUs used in Chrome-devices, but fails for other
- * Dali SKUs, since other Dali SKUs have a Zen+ CPUID and not a Raven2 one.
- */
-bool soc_is_dali(void)
+#define SILICON_IS_MYSTERY_MEAT (1 << 31)
+#define SILICON_IS_RV2 (1 << 30)
+
+static bool is_rv2_silicon(void)
{
- return soc_is_raven2() && get_socket_type() == SOCKET_FP5;
+ return get_internal_silicon_type() & SILICON_IS_RV2;
}
-bool soc_is_picasso(void)
+static bool is_mystery_silicon(void)
{
- return soc_is_zen_plus() && get_socket_type() == SOCKET_FP5;
+ return get_internal_silicon_type() & SILICON_IS_MYSTERY_MEAT;
}
-bool soc_is_raven2(void)
+static bool is_fam17_1x(void)
{
/* mask lower model number nibble and stepping */
- return cpuid_eax(1) >> 8 == RAVEN2_CPUID >> 8;
+ return cpuid_eax(1) >> 8 == PICASSO_CPUID >> 8;
+}
+
+static bool is_fam17_11(void)
+{
+ /* only mask stepping */
+ return cpuid_eax(1) >> 4 == RAVEN1_CPUID >> 4;
+}
+
+static bool is_fam17_18(void)
+{
+ /* only mask stepping */
+ return cpuid_eax(1) >> 4 == PICASSO_CPUID >> 4;
}
-bool soc_is_zen_plus(void)
+static bool is_fam17_2x(void)
{
/* mask lower model number nibble and stepping */
- return cpuid_eax(1) >> 8 == PICASSO_CPUID >> 8;
+ return cpuid_eax(1) >> 8 == RAVEN2_CPUID >> 8;
+}
+
+static bool is_fam17_20(void)
+{
+ /* only mask stepping */
+ return cpuid_eax(1) >> 4 == RAVEN2_A1_CPUID >> 4;
+}
+
+enum silicon_type get_silicon_type(void)
+{
+ /*
+ * RV2 is fam17_20, but might return a fam17_1x CPUID in the is_mystery_silicon() case.
+ * is_rv2_silicon() has the correct information, but requires the HOB to be present.
+ */
+ if (is_fam17_20() || is_rv2_silicon())
+ return SILICON_RV2;
+
+ if (is_fam17_18() && !is_rv2_silicon())
+ return SILICON_PCO;
+
+ if (is_fam17_11() && !is_rv2_silicon())
+ return SILICON_RV1;
+
+ /* some cases might still be missing */
+
+ return SILICON_UNKNOWN;
+}
+
+enum soc_type get_soc_type(void)
+{
+ switch (get_socket_type()) {
+ case SOCKET_FP5:
+ if (is_fam17_1x() && !is_mystery_silicon())
+ return SOC_PICASSO;
+
+ if (is_fam17_2x() || (is_fam17_1x() && is_mystery_silicon()))
+ return SOC_DALI;
+
+ break;
+ case SOCKET_FT5:
+ /* add is_fam17_20() CPUID sanity check here? */
+ return SOC_POLLOCK;
+ break;
+ case SOCKET_AM4:
+ /* AM4 SoC type detection logic not implemented */
+ break;
+ }
+
+ return SOC_UNKNOWN;
+}
+
+void print_silicon_type(void)
+{
+ const enum silicon_type silicon = get_silicon_type();
+
+ printk(BIOS_INFO, "Silicon type: ");
+
+ switch (silicon) {
+ case SILICON_RV1:
+ printk(BIOS_INFO, "RV1\n");
+ break;
+ case SILICON_PCO:
+ printk(BIOS_INFO, "PCO\n");
+ break;
+ case SILICON_RV2:
+ printk(BIOS_INFO, "RV2\n");
+ break;
+ default:
+ printk(BIOS_INFO, "unknown\n");
+ }
+}
+
+void print_soc_type(void)
+{
+ const enum soc_type soc = get_soc_type();
+
+ printk(BIOS_INFO, "SoC type: ");
+
+ switch (soc) {
+ case SOC_PICASSO:
+ printk(BIOS_INFO, "Picasso\n");
+ break;
+ case SOC_DALI:
+ printk(BIOS_INFO, "Dali\n");
+ break;
+ case SOC_POLLOCK:
+ printk(BIOS_INFO, "Pollock\n");
+ break;
+ default:
+ printk(BIOS_INFO, "unknown\n");
+ }
+}
+
+bool soc_is_pollock(void)
+{
+ return get_soc_type() == SOC_POLLOCK;
+}
+
+bool soc_is_dali(void)
+{
+ return get_soc_type() == SOC_DALI;
+}
+
+bool soc_is_picasso(void)
+{
+ return get_soc_type() == SOC_PICASSO;
+}
+
+bool soc_is_raven2(void)
+{
+ return get_silicon_type() == SILICON_RV2;
}