diff options
-rw-r--r-- | src/drivers/spi/Kconfig | 6 | ||||
-rw-r--r-- | src/drivers/spi/Makefile.mk | 1 | ||||
-rw-r--r-- | src/drivers/spi/spi_flash.c | 5 | ||||
-rw-r--r-- | src/drivers/spi/spi_flash_internal.h | 3 | ||||
-rw-r--r-- | src/drivers/spi/spi_flash_rpmc.c | 32 | ||||
-rw-r--r-- | src/include/spi_flash.h | 9 |
6 files changed, 56 insertions, 0 deletions
diff --git a/src/drivers/spi/Kconfig b/src/drivers/spi/Kconfig index 72fcec5e93..5d9698e16a 100644 --- a/src/drivers/spi/Kconfig +++ b/src/drivers/spi/Kconfig @@ -194,6 +194,12 @@ config SPI_FLASH_SFDP help Include serial flash discoverable parameters (SFDP) support. +config SPI_FLASH_RPMC + bool + select SPI_FLASH_SFDP + help + Include replay-protected monotonic counter (RPMC) support. + endif # SPI_FLASH config HAVE_EM100PRO_SPI_CONSOLE_SUPPORT diff --git a/src/drivers/spi/Makefile.mk b/src/drivers/spi/Makefile.mk index d873c90627..3310b968c3 100644 --- a/src/drivers/spi/Makefile.mk +++ b/src/drivers/spi/Makefile.mk @@ -32,6 +32,7 @@ $(1)-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.c $(1)-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c $(1)-$(CONFIG_SPI_FLASH_ISSI) += issi.c $(1)-$(CONFIG_SPI_FLASH_SFDP) += spi_flash_sfdp.c +$(1)-$(CONFIG_SPI_FLASH_RPMC) += spi_flash_rpmc.c endef $(eval $(call add_spi_stage,bootblock,_EARLY)) diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c index 6ecd29f773..b7a024c4c2 100644 --- a/src/drivers/spi/spi_flash.c +++ b/src/drivers/spi/spi_flash.c @@ -569,6 +569,11 @@ int spi_flash_probe(unsigned int bus, unsigned int cs, struct spi_flash *flash) spi_flash_cmd(&flash->spi, CMD_EXIT_4BYTE_ADDR_MODE, NULL, 0); } + /* TODO: only do this in stages that will need to call those functions? */ + if (CONFIG(SPI_FLASH_RPMC)) { + spi_flash_fill_rpmc_caps(flash); + } + return 0; } diff --git a/src/drivers/spi/spi_flash_internal.h b/src/drivers/spi/spi_flash_internal.h index 830a178e97..a30f58f9a5 100644 --- a/src/drivers/spi/spi_flash_internal.h +++ b/src/drivers/spi/spi_flash_internal.h @@ -159,4 +159,7 @@ struct sfdp_rpmc_info { enum cb_err spi_flash_get_sfdp_rpmc(const struct spi_flash *flash, struct sfdp_rpmc_info *rpmc_info); +/* Fill rpmc_caps field in spi_flash struct with RPMC config from SFDP */ +void spi_flash_fill_rpmc_caps(struct spi_flash *flash); + #endif /* SPI_FLASH_INTERNAL_H */ diff --git a/src/drivers/spi/spi_flash_rpmc.c b/src/drivers/spi/spi_flash_rpmc.c new file mode 100644 index 0000000000..148e3bb8a1 --- /dev/null +++ b/src/drivers/spi/spi_flash_rpmc.c @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <console/console.h> +#include <spi-generic.h> +#include <spi_flash.h> +#include <string.h> +#include <timer.h> +#include <types.h> + +#include "spi_flash_internal.h" + +void spi_flash_fill_rpmc_caps(struct spi_flash *flash) +{ + struct sfdp_rpmc_info rpmc_info; + + flash->rpmc_caps.rpmc_available = false; + + if (spi_flash_get_sfdp_rpmc(flash, &rpmc_info) != CB_SUCCESS) + return; + + if (rpmc_info.monotonic_counter_size != SFDP_RPMC_COUNTER_BITS_32) { + printk(BIOS_WARNING, "RPMC: unexpected counter size\n"); + return; + } + + flash->rpmc_caps.poll_op2_ext_stat = rpmc_info.busy_polling_method == + SFDP_RPMC_POLL_OP2_EXTENDED_STATUS; + flash->rpmc_caps.number_of_counters = rpmc_info.number_of_counters; + flash->rpmc_caps.op1_write_cmd = rpmc_info.op1_write_command; + flash->rpmc_caps.op2_read_cmd = rpmc_info.op2_read_command; + flash->rpmc_caps.rpmc_available = true; +} diff --git a/src/include/spi_flash.h b/src/include/spi_flash.h index 7736a940f5..76c33be5ea 100644 --- a/src/include/spi_flash.h +++ b/src/include/spi_flash.h @@ -95,6 +95,14 @@ struct spi_flash_protection_ops { struct spi_flash_part_id; +struct spi_flash_rpmc_cap { + bool rpmc_available; + bool poll_op2_ext_stat; + unsigned int number_of_counters; + uint8_t op1_write_cmd; + uint8_t op2_read_cmd; +}; + struct spi_flash { struct spi_slave spi; u8 vendor; @@ -118,6 +126,7 @@ struct spi_flash { /* If !NULL all protection callbacks exist. */ const struct spi_flash_protection_ops *prot_ops; const struct spi_flash_part_id *part; + struct spi_flash_rpmc_cap rpmc_caps; }; void lb_spi_flash(struct lb_header *header); |