diff options
author | Felix Held <felix-coreboot@felixheld.de> | 2024-08-05 21:41:35 +0200 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2024-08-07 16:39:38 +0000 |
commit | 5c1a69328b443e442f0176e76f78ceca36592f78 (patch) | |
tree | 0984d4f0378ced6e3aec4e229e14cc3a964bc075 /src | |
parent | 20b79eca820c9eece0b85e1ec1434b9d5b8791d2 (diff) |
soc/amd/common/psp_smi_flash: implement SPI read/write/erase command
Use coreboot's SPI flash access infrastructure to do the flash read,
write, or erase operations as requested from the PSP.
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: I4957a6d316015cc7037acf52facb6cc69188d446
Reviewed-on: https://review.coreboot.org/c/coreboot/+/83777
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin Roth <martin.roth@amd.corp-partner.google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/soc/amd/common/block/psp/psp_smi_flash.c | 115 |
1 files changed, 112 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 420fb948a4..2d075eff84 100644 --- a/src/soc/amd/common/block/psp/psp_smi_flash.c +++ b/src/soc/amd/common/block/psp/psp_smi_flash.c @@ -85,6 +85,25 @@ static void set_psp_spi_info(struct mbox_pspv2_cmd_spi_info *cmd_buf, write64(&cmd_buf->req.num_blocks, num_blocks); } +static void get_psp_spi_read_write(struct mbox_pspv2_cmd_spi_read_write *cmd_buf, + u64 *target_nv_id, u64 *lba, u64 *offset, + u64 *num_bytes, u8 **data) +{ + *target_nv_id = read64(&cmd_buf->req.target_nv_id); + *lba = read64(&cmd_buf->req.lba); + *offset = read64(&cmd_buf->req.offset); + *num_bytes = read64(&cmd_buf->req.num_bytes); + *data = cmd_buf->req.buffer; +} + +static void get_psp_spi_erase(struct mbox_pspv2_cmd_spi_erase *cmd_buf, + u64 *target_nv_id, u64 *lba, u64 *num_blocks) +{ + *target_nv_id = read64(&cmd_buf->req.target_nv_id); + *lba = read64(&cmd_buf->req.lba); + *num_blocks = read64(&cmd_buf->req.num_blocks); +} + static const char *id_to_region_name(u64 target_nv_id) { switch (target_nv_id) { @@ -197,37 +216,127 @@ enum mbox_p2c_status psp_smi_spi_read(struct mbox_default_buffer *buffer) { struct mbox_pspv2_cmd_spi_read_write *const cmd_buf = (struct mbox_pspv2_cmd_spi_read_write *)buffer; + enum mbox_p2c_status ret; + u64 target_nv_id; + u64 lba; + u64 offset; + u64 num_bytes; + u8 *data; + size_t addr; + const struct spi_flash *flash; + struct region_device store; printk(BIOS_SPEW, "PSP: SPI read request\n"); if (!is_valid_psp_spi_read_write(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; + } + + get_psp_spi_read_write(cmd_buf, &target_nv_id, &lba, &offset, &num_bytes, &data); + + ret = find_psp_spi_flash_device_region(target_nv_id, &store, &flash); + + if (ret != MBOX_PSP_SUCCESS) + return ret; + + addr = (lba * flash->sector_size) + offset; + + printk(BIOS_SPEW, "PSP: SPI read 0x%llx bytes at 0x%zx\n", num_bytes, addr); + + if (rdev_readat(&store, data, addr, (size_t)num_bytes) != (size_t)num_bytes) { + printk(BIOS_ERR, "PSP: Failed to read NVRAM data\n"); + return MBOX_PSP_COMMAND_PROCESS_ERROR; + } + + return MBOX_PSP_SUCCESS; } enum mbox_p2c_status psp_smi_spi_write(struct mbox_default_buffer *buffer) { struct mbox_pspv2_cmd_spi_read_write *const cmd_buf = (struct mbox_pspv2_cmd_spi_read_write *)buffer; + enum mbox_p2c_status ret; + u64 target_nv_id; + u64 lba; + u64 offset; + u64 num_bytes; + u8 *data; + size_t addr; + const struct spi_flash *flash; + struct region_device store; printk(BIOS_SPEW, "PSP: SPI write request\n"); if (!is_valid_psp_spi_read_write(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; + } + + get_psp_spi_read_write(cmd_buf, &target_nv_id, &lba, &offset, &num_bytes, &data); + + ret = find_psp_spi_flash_device_region(target_nv_id, &store, &flash); + + if (ret != MBOX_PSP_SUCCESS) + return ret; + + addr = (lba * flash->sector_size) + offset; + + printk(BIOS_SPEW, "PSP: SPI write 0x%llx bytes at 0x%zx\n", num_bytes, addr); + + if (rdev_writeat(&store, data, addr, (size_t)num_bytes) != (size_t)num_bytes) { + printk(BIOS_ERR, "PSP: Failed to write NVRAM data\n"); + return MBOX_PSP_COMMAND_PROCESS_ERROR; + } + + return MBOX_PSP_SUCCESS; } enum mbox_p2c_status psp_smi_spi_erase(struct mbox_default_buffer *buffer) { struct mbox_pspv2_cmd_spi_erase *const cmd_buf = (struct mbox_pspv2_cmd_spi_erase *)buffer; + enum mbox_p2c_status ret; + u64 target_nv_id; + u64 lba; + u64 num_blocks; + size_t addr; + size_t num_bytes; + const struct spi_flash *flash; + struct region_device store; printk(BIOS_SPEW, "PSP: SPI erase request\n"); if (!is_valid_psp_spi_erase(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; + } + + get_psp_spi_erase(cmd_buf, &target_nv_id, &lba, &num_blocks); + + ret = find_psp_spi_flash_device_region(target_nv_id, &store, &flash); + + if (ret != MBOX_PSP_SUCCESS) + return ret; + + addr = lba * flash->sector_size; + num_bytes = (size_t)num_blocks * flash->sector_size; + + printk(BIOS_SPEW, "PSP: SPI erase 0x%zx bytes at 0x%zx\n", num_bytes, addr); + + if (rdev_eraseat(&store, addr, num_bytes) != num_bytes) { + printk(BIOS_ERR, "PSP: Failed to erase SPI NVRAM data\n"); + return MBOX_PSP_COMMAND_PROCESS_ERROR; + } + + return MBOX_PSP_SUCCESS; } |