summaryrefslogtreecommitdiffstats
path: root/drivers/fpga/intel-m10-bmc-sec-update.c
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>2023-01-16 11:08:45 +0100
committerLee Jones <lee@kernel.org>2023-01-30 09:14:02 +0100
commitacf63c458b55ecfb2015b33dd6ba3cc8fbc1c5d3 (patch)
tree9e6856de76c85b84434e86df06696ef5f55a39b4 /drivers/fpga/intel-m10-bmc-sec-update.c
parentmfd: intel-m10-bmc: Add PMCI driver (diff)
downloadlinux-acf63c458b55ecfb2015b33dd6ba3cc8fbc1c5d3.tar.xz
linux-acf63c458b55ecfb2015b33dd6ba3cc8fbc1c5d3.zip
fpga: m10bmc-sec: Add support for N6000
Add support for PMCI-based flash access path and N6000 sec update support. Access to flash staging area is different for N6000 from that of the SPI interfaced counterparts. Introduce intel_m10bmc_flash_bulk_ops to allow interface specific differentiations for the flash access path for sec update and make m10bmc_sec_read/write() in sec update driver to use the new operations. The .flash_mutex serializes read/read. Flash update (erase+write) must use ->lock/unlock_write() to prevent reads during update (reads would timeout on setting flash MUX as BMC will prevent it). Create a type specific RSU status reg handler for N6000 because the field has moved from doorbell to auth result register. If a failure is detected while altering the flash MUX, it seems safer to try to set it back and doesn't seem harmful. Likely there are enough troubles in that case anyway so setting it back fails too (which is harmless sans the small extra delay) or just confirms that the value wasn't changed. Co-developed-by: Tianfei zhang <tianfei.zhang@intel.com> Signed-off-by: Tianfei zhang <tianfei.zhang@intel.com> Co-developed-by: Russ Weight <russell.h.weight@intel.com> Signed-off-by: Russ Weight <russell.h.weight@intel.com> Acked-by: Xu Yilun <yilun.xu@intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Lee Jones <lee@kernel.org> Link: https://lore.kernel.org/r/20230116100845.6153-12-ilpo.jarvinen@linux.intel.com
Diffstat (limited to 'drivers/fpga/intel-m10-bmc-sec-update.c')
-rw-r--r--drivers/fpga/intel-m10-bmc-sec-update.c51
1 files changed, 46 insertions, 5 deletions
diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c
index 92145ee7333e..9b4cc75b48c5 100644
--- a/drivers/fpga/intel-m10-bmc-sec-update.c
+++ b/drivers/fpga/intel-m10-bmc-sec-update.c
@@ -48,6 +48,9 @@ static int m10bmc_sec_write(struct m10bmc_sec *sec, const u8 *buf, u32 offset, u
u32 leftover_tmp = 0;
int ret;
+ if (sec->m10bmc->flash_bulk_ops)
+ return sec->m10bmc->flash_bulk_ops->write(m10bmc, buf, offset, size);
+
if (WARN_ON_ONCE(stride > sizeof(leftover_tmp)))
return -EINVAL;
@@ -78,6 +81,9 @@ static int m10bmc_sec_read(struct m10bmc_sec *sec, u8 *buf, u32 addr, u32 size)
u32 leftover_tmp;
int ret;
+ if (sec->m10bmc->flash_bulk_ops)
+ return sec->m10bmc->flash_bulk_ops->read(m10bmc, buf, addr, size);
+
if (WARN_ON_ONCE(stride > sizeof(leftover_tmp)))
return -EINVAL;
@@ -277,6 +283,19 @@ static int m10bmc_sec_n3000_rsu_status(struct m10bmc_sec *sec)
return FIELD_GET(DRBL_RSU_STATUS, doorbell);
}
+static int m10bmc_sec_n6000_rsu_status(struct m10bmc_sec *sec)
+{
+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;
+ u32 auth_result;
+ int ret;
+
+ ret = m10bmc_sys_read(sec->m10bmc, csr_map->auth_result, &auth_result);
+ if (ret)
+ return ret;
+
+ return FIELD_GET(AUTH_RESULT_RSU_STATUS, auth_result);
+}
+
static bool rsu_status_ok(u32 status)
{
return (status == RSU_STAT_NORMAL ||
@@ -520,22 +539,33 @@ static enum fw_upload_err m10bmc_sec_prepare(struct fw_upload *fwl,
if (!size || size > M10BMC_STAGING_SIZE)
return FW_UPLOAD_ERR_INVALID_SIZE;
+ if (sec->m10bmc->flash_bulk_ops)
+ if (sec->m10bmc->flash_bulk_ops->lock_write(sec->m10bmc))
+ return FW_UPLOAD_ERR_BUSY;
+
ret = rsu_check_idle(sec);
if (ret != FW_UPLOAD_ERR_NONE)
- return ret;
+ goto unlock_flash;
ret = rsu_update_init(sec);
if (ret != FW_UPLOAD_ERR_NONE)
- return ret;
+ goto unlock_flash;
ret = rsu_prog_ready(sec);
if (ret != FW_UPLOAD_ERR_NONE)
- return ret;
+ goto unlock_flash;
- if (sec->cancel_request)
- return rsu_cancel(sec);
+ if (sec->cancel_request) {
+ ret = rsu_cancel(sec);
+ goto unlock_flash;
+ }
return FW_UPLOAD_ERR_NONE;
+
+unlock_flash:
+ if (sec->m10bmc->flash_bulk_ops)
+ sec->m10bmc->flash_bulk_ops->unlock_write(sec->m10bmc);
+ return ret;
}
#define WRITE_BLOCK_SIZE 0x4000 /* Default write-block size is 0x4000 bytes */
@@ -622,6 +652,9 @@ static void m10bmc_sec_cleanup(struct fw_upload *fwl)
struct m10bmc_sec *sec = fwl->dd_handle;
(void)rsu_cancel(sec);
+
+ if (sec->m10bmc->flash_bulk_ops)
+ sec->m10bmc->flash_bulk_ops->unlock_write(sec->m10bmc);
}
static const struct fw_upload_ops m10bmc_ops = {
@@ -636,6 +669,10 @@ static const struct m10bmc_sec_ops m10sec_n3000_ops = {
.rsu_status = m10bmc_sec_n3000_rsu_status,
};
+static const struct m10bmc_sec_ops m10sec_n6000_ops = {
+ .rsu_status = m10bmc_sec_n6000_rsu_status,
+};
+
#define SEC_UPDATE_LEN_MAX 32
static int m10bmc_sec_probe(struct platform_device *pdev)
{
@@ -698,6 +735,10 @@ static const struct platform_device_id intel_m10bmc_sec_ids[] = {
.name = "d5005bmc-sec-update",
.driver_data = (kernel_ulong_t)&m10sec_n3000_ops,
},
+ {
+ .name = "n6000bmc-sec-update",
+ .driver_data = (kernel_ulong_t)&m10sec_n6000_ops,
+ },
{ }
};
MODULE_DEVICE_TABLE(platform, intel_m10bmc_sec_ids);