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>
This commit is contained in:
parent
20b79eca82
commit
5c1a69328b
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user