aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBhavik Patel <bhavik.patel@arm.com>2020-09-30 09:06:52 +0200
committerBhavik Patel <bhavik.patel@arm.com>2020-10-16 12:52:43 +0200
commit5f8dad185b3e3a381fe2e3d16580a8a8e99f9db0 (patch)
treeb7f7686f5fa9ee6b5850b9a273d6e383ec0d0a06 /src
parent51c18bac97dc3ae3393a786999f4602ca11c22f7 (diff)
downloadethos-u-core-driver-5f8dad185b3e3a381fe2e3d16580a8a8e99f9db0.tar.gz
MLBEDSW-3094 Improve soft reset of ETHOSU when running jobs
The ETHOSU is soft-reset only if the previous job failed or if the current privilege level is not user or if the current security level is not secure. Change-Id: Id10b96058d67805d179ac693537606d55e10379b
Diffstat (limited to 'src')
-rw-r--r--src/ethosu_device.c16
-rw-r--r--src/ethosu_driver.c34
2 files changed, 44 insertions, 6 deletions
diff --git a/src/ethosu_device.c b/src/ethosu_device.c
index 973caad..85dc022 100644
--- a/src/ethosu_device.c
+++ b/src/ethosu_device.c
@@ -193,6 +193,8 @@ enum ethosu_error_codes ethosu_soft_reset(struct ethosu_device *dev)
ethosu_write_reg(dev, NPU_REG_RESET, reset.word);
return_code = ethosu_wait_for_reset(dev);
+
+ dev->reset = ethosu_read_reg(dev, NPU_REG_PROT);
#else
UNUSED(dev);
#endif
@@ -618,3 +620,17 @@ enum ethosu_error_codes ethosu_restore_pmu_config(struct ethosu_device *dev)
return ETHOSU_SUCCESS;
}
+
+bool ethosu_status_has_error(struct ethosu_device *dev)
+{
+ bool status_error = false;
+#if !defined(ARM_NPU_STUB)
+ struct status_r status;
+ status.word = ethosu_read_reg(dev, NPU_REG_STATUS);
+ status_error = ((1 == status.bus_status) || (1 == status.cmd_parse_error) || (1 == status.wd_fault) ||
+ (1 == status.ecc_fault));
+#else
+ UNUSED(dev);
+#endif
+ return status_error;
+}
diff --git a/src/ethosu_driver.c b/src/ethosu_driver.c
index 2a2423f..6c55b0b 100644
--- a/src/ethosu_driver.c
+++ b/src/ethosu_driver.c
@@ -149,8 +149,9 @@ struct opt_cfg_s
******************************************************************************/
struct ethosu_driver ethosu_drv = {
- .dev = {.base_address = 0, .pmccntr = 0, .pmu_evcntr = {0, 0, 0, 0}, .pmu_evtypr = {0, 0, 0, 0}},
- .abort_inference = false};
+ .dev = {.base_address = NULL, .reset = 0, .pmccntr = 0, .pmu_evcntr = {0, 0, 0, 0}, .pmu_evtypr = {0, 0, 0, 0}},
+ .abort_inference = false,
+ .status_error = false};
// IRQ
static volatile bool irq_triggered = false;
@@ -172,9 +173,15 @@ void ethosu_irq_handler(void)
// Clear interrupt
(void)ethosu_clear_irq_status(&ethosu_drv.dev);
- // Verify that interrupt has been successfully cleard
+ // Verify that interrupt has been successfully cleared
(void)ethosu_is_irq_raised(&ethosu_drv.dev, &irq_raised);
ASSERT(irq_raised == 0);
+
+ if (ethosu_status_has_error(&ethosu_drv.dev))
+ {
+ ethosu_soft_reset(&ethosu_drv.dev);
+ ethosu_drv.status_error = true;
+ }
}
static inline void wait_for_irq(struct ethosu_driver *drv)
@@ -257,6 +264,7 @@ int ethosu_init_v2(const void *base_address, const void *fast_memory, const size
LOG_ERR("Failed reset of Ethos-U\n");
return -1;
}
+ ethosu_drv.status_error = false;
return return_code;
}
@@ -339,7 +347,11 @@ int ethosu_invoke_v2(const void *custom_data_ptr,
}
}
- ethosu_soft_reset(&ethosu_drv.dev);
+ if (ethosu_drv.dev.reset != ethosu_read_reg(&ethosu_drv.dev, NPU_REG_PROT))
+ {
+ ethosu_soft_reset(&ethosu_drv.dev);
+ }
+ ethosu_drv.status_error = false;
ethosu_set_clock_and_power(&ethosu_drv.dev, ETHOSU_CLOCK_Q_ENABLE, ETHOSU_POWER_Q_DISABLE);
ethosu_restore_pmu_config(&ethosu_drv.dev);
@@ -405,8 +417,11 @@ int ethosu_invoke_v2(const void *custom_data_ptr,
}
}
- ethosu_save_pmu_config(&ethosu_drv.dev);
- ethosu_set_clock_and_power(&ethosu_drv.dev, ETHOSU_CLOCK_Q_ENABLE, ETHOSU_POWER_Q_ENABLE);
+ if (!ethosu_drv.status_error)
+ {
+ ethosu_save_pmu_config(&ethosu_drv.dev);
+ ethosu_set_clock_and_power(&ethosu_drv.dev, ETHOSU_CLOCK_Q_ENABLE, ETHOSU_POWER_Q_ENABLE);
+ }
return return_code;
}
@@ -560,6 +575,13 @@ static int handle_command_stream(struct ethosu_driver *drv,
wait_for_irq(drv);
+ if (drv->status_error)
+ {
+ return -1;
+ }
+
+ // ETHOSU would have been reset in the IRQ handler if there were
+ // status error(s). So don't read the QREAD register.
(void)ethosu_get_qread(&drv->dev, &qread);
if (qread != cms_bytes)
{