summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Held <felix-coreboot@felixheld.de>2024-08-02 23:42:41 +0200
committerFelix Held <felix-coreboot@felixheld.de>2024-08-07 16:39:22 +0000
commit20b79eca820c9eece0b85e1ec1434b9d5b8791d2 (patch)
tree8c32fa45323479eea36a21186fff6812bada836c
parent8cfb73c777e2123189021c26929bc9faa75867d8 (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>
-rw-r--r--src/soc/amd/common/block/psp/psp_smi_flash.c46
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)