diff options
author | Felix Held <felix-coreboot@felixheld.de> | 2024-08-02 23:42:41 +0200 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2024-08-07 16:39:22 +0000 |
commit | 20b79eca820c9eece0b85e1ec1434b9d5b8791d2 (patch) | |
tree | 8c32fa45323479eea36a21186fff6812bada836c /src/soc | |
parent | 8cfb73c777e2123189021c26929bc9faa75867d8 (diff) |
soc/amd/common/psp_smi_flash: implement SPI info command
Detect the block size of the SPI flash and number of flash blocks
reserved for the flash region corresponding to the 'target_nv_id' field
in the command buffer. This information is then written to the
corresponding fields in the command buffer. Since detecting the flash
chip still might result in accesses to it, make sure that it's available
for use and not currently used by an OS driver. Since this code is
inside the SMI handler, we don't have to worry about this code to be
interrupted, so we don't need to set some bit to tell other code that
we're currently using the SPI controller in the SMI handler.
This patch is a modified version of parts of CB:65523.
Document #55758 Rev. 2.04 was used as a reference.
Test=When selecting SOC_AMD_COMMON_BLOCK_PSP_SMI, Mandolin still builds
Signed-off-by: Felix Held <felix-coreboot@felixheld.de>
Signed-off-by: Ritul Guru <ritul.bits@gmail.com>
Change-Id: I19041a27a9e8f901d42c3f60af834df625455ea6
Reviewed-on: https://review.coreboot.org/c/coreboot/+/83776
Reviewed-by: Martin Roth <martin.roth@amd.corp-partner.google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/amd/common/block/psp/psp_smi_flash.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/src/soc/amd/common/block/psp/psp_smi_flash.c b/src/soc/amd/common/block/psp/psp_smi_flash.c index 367baef256..420fb948a4 100644 --- a/src/soc/amd/common/block/psp/psp_smi_flash.c +++ b/src/soc/amd/common/block/psp/psp_smi_flash.c @@ -72,6 +72,19 @@ static bool is_valid_psp_spi_erase(struct mbox_pspv2_cmd_spi_erase *cmd_buf) return is_valid_psp_spi_id(read64(&cmd_buf->req.target_nv_id)); } +static u64 get_psp_spi_info_id(struct mbox_pspv2_cmd_spi_info *cmd_buf) +{ + return read64(&cmd_buf->req.target_nv_id); +} + +static void set_psp_spi_info(struct mbox_pspv2_cmd_spi_info *cmd_buf, + u64 lba, u64 block_size, u64 num_blocks) +{ + write64(&cmd_buf->req.lba, lba); + write64(&cmd_buf->req.block_size, block_size); + write64(&cmd_buf->req.num_blocks, num_blocks); +} + static const char *id_to_region_name(u64 target_nv_id) { switch (target_nv_id) { @@ -117,7 +130,7 @@ static int lookup_store(u64 target_nv_id, struct region_device *rstore) return rdev_chain(rstore, rdev, 0, region_device_sz(rdev)); } -static inline enum mbox_p2c_status find_psp_spi_flash_device_region(u64 target_nv_id, +static enum mbox_p2c_status find_psp_spi_flash_device_region(u64 target_nv_id, struct region_device *store, const struct spi_flash **flash) { @@ -135,7 +148,7 @@ static inline enum mbox_p2c_status find_psp_spi_flash_device_region(u64 target_n return MBOX_PSP_SUCCESS; } -static inline bool spi_controller_available(void) +static bool spi_controller_available(void) { return !(spi_read8(SPI_MISC_CNTRL) & SPI_SEMAPHORE_DRIVER_LOCKED); } @@ -144,13 +157,40 @@ enum mbox_p2c_status psp_smi_spi_get_info(struct mbox_default_buffer *buffer) { struct mbox_pspv2_cmd_spi_info *const cmd_buf = (struct mbox_pspv2_cmd_spi_info *)buffer; + const struct spi_flash *flash; + struct region_device store; + u64 target_nv_id; + u64 block_size; + u64 num_blocks; + enum mbox_p2c_status ret; printk(BIOS_SPEW, "PSP: SPI info request\n"); if (!is_valid_psp_spi_info(cmd_buf)) return MBOX_PSP_COMMAND_PROCESS_ERROR; - return MBOX_PSP_UNSUPPORTED; + if (!spi_controller_available()) { + printk(BIOS_NOTICE, "PSP: SPI controller busy\n"); + return MBOX_PSP_SPI_BUSY; + } + + target_nv_id = get_psp_spi_info_id(cmd_buf); + + ret = find_psp_spi_flash_device_region(target_nv_id, &store, &flash); + + if (ret != MBOX_PSP_SUCCESS) + return ret; + + block_size = flash->sector_size; + + if (!block_size) + return MBOX_PSP_COMMAND_PROCESS_ERROR; + + num_blocks = region_device_sz(&store) / block_size; + + set_psp_spi_info(cmd_buf, 0, block_size, num_blocks); + + return MBOX_PSP_SUCCESS; } enum mbox_p2c_status psp_smi_spi_read(struct mbox_default_buffer *buffer) |