diff --git a/src/soc/amd/common/block/include/amdblocks/psp_efs.h b/src/soc/amd/common/block/include/amdblocks/psp_efs.h new file mode 100644 index 0000000000..7afd295df3 --- /dev/null +++ b/src/soc/amd/common/block/include/amdblocks/psp_efs.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + + +#ifndef AMD_COMMON_PSP_EFS_H +#define AMD_COMMON_PSP_EFS_H + +#include + +#define EFS_OFFSET (0xffffff - (0x80000 << CONFIG_AMD_FWM_POSITION_INDEX) + 0x20000 + 1) +#define EFS_ADDRESS (0xff000000 + EFS_OFFSET) + +#define EMBEDDED_FW_SIGNATURE 0x55aa55aa + +#if CONFIG(SOC_AMD_STONEYRIDGE) + #define SPI_MODE_FIELD spi_readmode_f15_mod_60_6f + #define SPI_SPEED_FIELD fast_speed_new_f15_mod_60_6f +#elif CONFIG(SOC_AMD_PICASSO) + #define SPI_MODE_FIELD spi_readmode_f17_mod_00_2f + #define SPI_SPEED_FIELD spi_fastspeed_f17_mod_00_2f +#elif CONFIG(SOC_AMD_CEZANNE) + #define SPI_MODE_FIELD spi_readmode_f17_mod_30_3f + #define SPI_SPEED_FIELD spi_fastspeed_f17_mod_30_3f +#else + #error +#endif + + +struct second_gen_efs { /* todo: expand for Server products */ + int gen:1; /* Client products only use bit 0 */ + int reserved:31; +} __attribute__((packed)); + +/* Copied from coreboot/util/amdfwtool.h */ +typedef struct _embedded_firmware { + uint32_t signature; /* 0x55aa55aa */ + uint32_t imc_entry; + uint32_t gec_entry; + uint32_t xhci_entry; + uint32_t psp_entry; + uint32_t comboable; + uint32_t bios0_entry; + uint32_t bios1_entry; + uint32_t bios2_entry; + struct second_gen_efs efs_gen; + uint32_t bios3_entry; + uint32_t reserved_2Ch; + uint32_t promontory_fw_ptr; + uint32_t lp_promontory_fw_ptr; + uint32_t reserved_38h; + uint32_t reserved_3Ch; + uint8_t spi_readmode_f15_mod_60_6f; + uint8_t fast_speed_new_f15_mod_60_6f; + uint8_t reserved_42h; + uint8_t spi_readmode_f17_mod_00_2f; + uint8_t spi_fastspeed_f17_mod_00_2f; + uint8_t qpr_dummy_cycle_f17_mod_00_2f; + uint8_t reserved_46h; + uint8_t spi_readmode_f17_mod_30_3f; + uint8_t spi_fastspeed_f17_mod_30_3f; + uint8_t micron_detect_f17_mod_30_3f; + uint8_t reserved_4Ah; + uint8_t reserved_4Bh; + uint32_t reserved_4Ch; +} __attribute__((packed, aligned(16))) embedded_firmware; + +bool efs_is_valid(void); +bool read_efs_spi_settings(uint8_t *mode, uint8_t *speed); + +#endif /* AMD_COMMON_PSP_EFS_H */ diff --git a/src/soc/amd/common/block/psp/Makefile.inc b/src/soc/amd/common/block/psp/Makefile.inc index 3bb03f7e81..db9ebda594 100644 --- a/src/soc/amd/common/block/psp/Makefile.inc +++ b/src/soc/amd/common/block/psp/Makefile.inc @@ -22,4 +22,6 @@ ramstage-y += psp_gen2.c smm-y += psp_gen2.c smm-y += psp_smm_gen2.c +bootblock-y += psp_efs.c + endif # CONFIG_SOC_AMD_COMMON_BLOCK_PSP_GEN2 diff --git a/src/soc/amd/common/block/psp/psp_efs.c b/src/soc/amd/common/block/psp/psp_efs.c new file mode 100644 index 0000000000..b0397f6ae8 --- /dev/null +++ b/src/soc/amd/common/block/psp/psp_efs.c @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include + +struct _embedded_firmware *efs = (struct _embedded_firmware *)EFS_ADDRESS; + +bool efs_is_valid(void) +{ + if (efs->signature != EMBEDDED_FW_SIGNATURE) + return false; + + return true; +} + +bool read_efs_spi_settings(uint8_t *mode, uint8_t *speed) +{ + if (!efs_is_valid()) + return false; + + *mode = efs->SPI_MODE_FIELD; + *speed = efs->SPI_SPEED_FIELD; + return true; +} diff --git a/src/soc/amd/common/block/spi/fch_spi.c b/src/soc/amd/common/block/spi/fch_spi.c index 7ef98392e0..a8425149aa 100644 --- a/src/soc/amd/common/block/spi/fch_spi.c +++ b/src/soc/amd/common/block/spi/fch_spi.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -9,7 +10,23 @@ #include #include -static void fch_spi_set_spi100(int norm, int fast, int alt, int tpm) +static uint8_t lower_speed(uint8_t speed1, uint8_t speed2) +{ + uint8_t speeds[] = {SPI_SPEED_800K, SPI_SPEED_16M, SPI_SPEED_22M, + SPI_SPEED_33M, SPI_SPEED_66M, SPI_SPEED_100M}; + + for (int i = 0; i < ARRAY_SIZE(speeds); i++) { + if (speed1 == speeds[i]) + return speed1; + if (speed2 == speeds[i]) + return speed2; + } + + /* Fall back to 16MHz if we got invalid speed values */ + return SPI_SPEED_16M; +} + +static void fch_spi_set_spi100(uint8_t norm, uint8_t fast, uint8_t alt, uint8_t tpm) { spi_write16(SPI100_SPEED_CONFIG, SPI_SPEED_CFG(norm, fast, alt, tpm)); spi_write16(SPI100_ENABLE, SPI_USE_SPI100); @@ -34,32 +51,26 @@ static void fch_spi_set_read_mode(u32 mode) spi_write32(SPI_CNTRL0, val | SPI_READ_MODE(mode)); } -static void fch_spi_config_mb_modes(void) -{ - const struct soc_amd_common_config *cfg = soc_get_common_config(); - - if (!cfg) - die("Common config structure is NULL!\n"); - - const struct spi_config *spi_cfg = &cfg->spi_config; - - fch_spi_set_read_mode(spi_cfg->read_mode); - fch_spi_set_spi100(spi_cfg->normal_speed, spi_cfg->fast_speed, - spi_cfg->altio_speed, spi_cfg->tpm_speed); -} - -static void fch_spi_config_em100_modes(void) -{ - fch_spi_set_read_mode(SPI_READ_MODE_NORMAL33M); - fch_spi_set_spi100(SPI_SPEED_16M, SPI_SPEED_16M, SPI_SPEED_16M, SPI_SPEED_16M); -} - static void fch_spi_config_modes(void) { - if (CONFIG(EM100)) - fch_spi_config_em100_modes(); - else - fch_spi_config_mb_modes(); + uint8_t read_mode, fast_speed; + uint8_t normal_speed = CONFIG_NORMAL_READ_SPI_SPEED; + uint8_t alt_speed = CONFIG_ALT_SPI_SPEED; + uint8_t tpm_speed = CONFIG_TPM_SPI_SPEED; + + if (!read_efs_spi_settings(&read_mode, &fast_speed)) { + read_mode = CONFIG_EFS_SPI_READ_MODE; + fast_speed = CONFIG_EFS_SPI_SPEED; + } + + if (fast_speed != CONFIG_EFS_SPI_SPEED) { + normal_speed = lower_speed(normal_speed, fast_speed); + tpm_speed = lower_speed(tpm_speed, fast_speed); + alt_speed = lower_speed(alt_speed, fast_speed); + } + + fch_spi_set_read_mode((u32)read_mode); + fch_spi_set_spi100(normal_speed, fast_speed, alt_speed, tpm_speed); } void fch_spi_early_init(void)