diff options
Diffstat (limited to 'src/soc/amd')
-rw-r--r-- | src/soc/amd/picasso/include/soc/soc_util.h | 24 | ||||
-rw-r--r-- | src/soc/amd/picasso/soc_util.c | 179 |
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; } |