From c6e7a1f7d75342b11093b058e0cf47e7a636f852 Mon Sep 17 00:00:00 2001 From: Kristofer Jonsson Date: Tue, 24 Nov 2020 09:20:14 +0100 Subject: Update handling of soft reset Change-Id: Ia22b2934b4c85e3c480931c8b92608365351a877 --- include/ethosu_device.h | 2 +- src/ethosu_device.c | 35 +++++++++++++++++++++++++---------- src/ethosu_driver.c | 16 +++++++++++----- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/include/ethosu_device.h b/include/ethosu_device.h index dd34201..eff9054 100644 --- a/include/ethosu_device.h +++ b/include/ethosu_device.h @@ -55,7 +55,7 @@ enum ethosu_error_codes struct ethosu_device { volatile uint32_t *base_address; - uint32_t reset; + uint32_t proto; uint32_t pmcr; uint32_t pmccntr[2]; uint32_t pmcnten; diff --git a/src/ethosu_device.c b/src/ethosu_device.c index adfdbb1..f8250bc 100644 --- a/src/ethosu_device.c +++ b/src/ethosu_device.c @@ -170,6 +170,7 @@ enum ethosu_error_codes ethosu_clear_irq_status(struct ethosu_device *dev) cmd.clock_q_enable = oldcmd.clock_q_enable; cmd.power_q_enable = oldcmd.power_q_enable; ethosu_write_reg(dev, NPU_REG_CMD, cmd.word); + LOG_DEBUG("CMD=0x%08x\n", cmd.word); #else UNUSED(dev); #endif @@ -187,23 +188,29 @@ enum ethosu_error_codes ethosu_soft_reset(struct ethosu_device *dev) reset.pending_CPL = dev->privileged ? PRIVILEGE_LEVEL_PRIVILEGED : PRIVILEGE_LEVEL_USER; reset.pending_CSL = dev->secure ? SECURITY_LEVEL_SECURE : SECURITY_LEVEL_NON_SECURE; - prot.word = ethosu_read_reg(dev, NPU_REG_PROT); - - if (prot.active_CPL < reset.pending_CPL && prot.active_CSL > reset.pending_CSL) - { - LOG_ERR("Failed to reset NPU\n"); - // Register access not permitted - return ETHOSU_GENERIC_FAILURE; - } - // Reset and set security level + LOG_INFO("Soft reset NPU\n"); ethosu_write_reg(dev, NPU_REG_RESET, reset.word); // Wait for reset to complete return_code = ethosu_wait_for_reset(dev); + if (return_code != ETHOSU_SUCCESS) + { + LOG_ERR("Soft reset timed out\n"); + return return_code; + } + + // Verify that NPU has switched security state and privilege level + prot.word = ethosu_read_reg(dev, NPU_REG_PROT); + if (prot.active_CPL != reset.pending_CPL || prot.active_CSL != reset.pending_CSL) + { + LOG_ERR("Failed to switch security state and privilege level\n"); + // Register access not permitted + return ETHOSU_GENERIC_FAILURE; + } // Save the prot register - dev->reset = ethosu_read_reg(dev, NPU_REG_PROT); + dev->proto = ethosu_read_reg(dev, NPU_REG_PROT); // Soft reset will clear the PMU configuration and counters. The shadow PMU counters // are cleared by saving the PMU counters to ram, which will read back zeros. @@ -277,6 +284,7 @@ enum ethosu_error_codes ethosu_set_qconfig(struct ethosu_device *dev, enum ethos } #if !defined(ARM_NPU_STUB) ethosu_write_reg(dev, NPU_REG_QCONFIG, memory_type); + LOG_DEBUG("QCONFIG=0x%08x\n", memory_type); #else // NPU stubbed UNUSED(dev); @@ -324,6 +332,7 @@ enum ethosu_error_codes ethosu_set_axi_limit0(struct ethosu_device *dev, axi_limit0.max_outstanding_write_m1 = max_writes - 1; ethosu_write_reg(dev, NPU_REG_AXI_LIMIT0, axi_limit0.word); + LOG_DEBUG("AXI_LIMIT0=0x%08x\n", axi_limit0.word); #else // NPU stubbed UNUSED(dev); @@ -351,6 +360,7 @@ enum ethosu_error_codes ethosu_set_axi_limit1(struct ethosu_device *dev, axi_limit1.max_outstanding_write_m1 = max_writes - 1; ethosu_write_reg(dev, NPU_REG_AXI_LIMIT1, axi_limit1.word); + LOG_DEBUG("AXI_LIMIT1=0x%08x\n", axi_limit1.word); #else // NPU stubbed UNUSED(dev); @@ -378,6 +388,7 @@ enum ethosu_error_codes ethosu_set_axi_limit2(struct ethosu_device *dev, axi_limit2.max_outstanding_write_m1 = max_writes - 1; ethosu_write_reg(dev, NPU_REG_AXI_LIMIT2, axi_limit2.word); + LOG_DEBUG("AXI_LIMIT2=0x%08x\n", axi_limit2.word); #else // NPU stubbed UNUSED(dev); @@ -405,6 +416,7 @@ enum ethosu_error_codes ethosu_set_axi_limit3(struct ethosu_device *dev, axi_limit3.max_outstanding_write_m1 = max_writes - 1; ethosu_write_reg(dev, NPU_REG_AXI_LIMIT3, axi_limit3.word); + LOG_DEBUG("AXI_LIMIT3=0x%08x\n", axi_limit3.word); #else // NPU stubbed UNUSED(dev); @@ -479,6 +491,7 @@ enum ethosu_error_codes ethosu_clear_irq_history_mask(struct ethosu_device *dev, cmd.power_q_enable = oldcmd.power_q_enable; cmd.clear_irq_history = irq_history_clear_mask; ethosu_write_reg(dev, NPU_REG_CMD, cmd.word); + LOG_DEBUG("CMD=0x%08x\n", cmd.word); #else UNUSED(dev); UNUSED(irq_history_clear_mask); @@ -498,6 +511,7 @@ enum ethosu_error_codes ethosu_set_command_run(struct ethosu_device *dev) cmd.clock_q_enable = oldcmd.clock_q_enable; cmd.power_q_enable = oldcmd.power_q_enable; ethosu_write_reg(dev, NPU_REG_CMD, cmd.word); + LOG_DEBUG("CMD=0x%08x\n", cmd.word); #else UNUSED(dev); #endif @@ -537,6 +551,7 @@ enum ethosu_error_codes ethosu_set_clock_and_power(struct ethosu_device *dev, cmd.clock_q_enable = clock_q; cmd.power_q_enable = power_q; ethosu_write_reg(dev, NPU_REG_CMD, cmd.word); + LOG_DEBUG("CMD=0x%08x\n", cmd.word); #else UNUSED(dev); UNUSED(clock_q); diff --git a/src/ethosu_driver.c b/src/ethosu_driver.c index 3c9c55b..3b6ebcf 100644 --- a/src/ethosu_driver.c +++ b/src/ethosu_driver.c @@ -149,7 +149,7 @@ struct opt_cfg_s ******************************************************************************/ struct ethosu_driver ethosu_drv = { - .dev = {.base_address = NULL, .reset = 0, .pmccntr = {0}, .pmu_evcntr = {0, 0, 0, 0}, .pmu_evtypr = {0, 0, 0, 0}}, + .dev = {.base_address = NULL, .proto = 0, .pmccntr = {0}, .pmu_evcntr = {0, 0, 0, 0}, .pmu_evtypr = {0, 0, 0, 0}}, .abort_inference = false, .status_error = false}; @@ -356,13 +356,15 @@ int ethosu_invoke_v2(const void *custom_data_ptr, *fast_memory = ethosu_drv.fast_memory; } - if (ethosu_drv.dev.reset != ethosu_read_reg(ðosu_drv.dev, NPU_REG_PROT)) + // Only soft reset if securty state or privilege level needs changing + if (ethosu_drv.dev.proto != ethosu_read_reg(ðosu_drv.dev, NPU_REG_PROT)) { if (ETHOSU_SUCCESS != ethosu_soft_reset(ðosu_drv.dev)) { return -1; } } + ethosu_drv.status_error = false; ethosu_set_clock_and_power(ðosu_drv.dev, ETHOSU_CLOCK_Q_ENABLE, ETHOSU_POWER_Q_DISABLE); ethosu_restore_pmu_config(ðosu_drv.dev); @@ -575,8 +577,10 @@ static int handle_command_stream(struct ethosu_driver *drv, const size_t *base_addr_size, const int num_base_addr) { - uint32_t qread = 0; - uint32_t cms_bytes = cms_length * BYTES_IN_32_BITS; + uint32_t qread = 0; + uint32_t cms_bytes = cms_length * BYTES_IN_32_BITS; + ptrdiff_t cmd_stream_ptr = (ptrdiff_t)cmd_stream; + LOG_INFO("handle_command_stream: cmd_stream=%p, cms_length %d\n", cmd_stream, cms_length); if (0 != ((ptrdiff_t)cmd_stream & MASK_16_BYTE_ALIGN)) @@ -594,10 +598,12 @@ static int handle_command_stream(struct ethosu_driver *drv, base_addr_invalid = true; } } + if (base_addr_invalid) { return -1; } + npu_axi_init(drv); /* Flush the cache if available on our CPU. @@ -608,7 +614,7 @@ static int handle_command_stream(struct ethosu_driver *drv, if (base_addr_size != NULL) { - ethosu_flush_dcache((uint32_t *)cmd_stream, cms_bytes); + ethosu_flush_dcache((uint32_t *)cmd_stream_ptr, cms_bytes); for (int i = 0; i < num_base_addr; i++) { ethosu_flush_dcache((uint32_t *)base_addr[i], base_addr_size[i]); -- cgit v1.2.1