summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFelix Held <felix-coreboot@felixheld.de>2024-08-05 21:41:35 +0200
committerFelix Held <felix-coreboot@felixheld.de>2024-08-07 16:39:38 +0000
commit5c1a69328b443e442f0176e76f78ceca36592f78 (patch)
tree0984d4f0378ced6e3aec4e229e14cc3a964bc075 /src
parent20b79eca820c9eece0b85e1ec1434b9d5b8791d2 (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.c115
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;
}