]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
refactor(ethos-n): split up SMC call handling
authorMikael Olsson <mikael.olsson@arm.com>
Fri, 27 Jan 2023 17:26:36 +0000 (18:26 +0100)
committerJoanna Farley <joanna.farley@arm.com>
Tue, 4 Apr 2023 09:37:19 +0000 (11:37 +0200)
Doing all the SMC call handling in a single function and using specific
names for the x1-4 parameters is no longer practical for upcoming
additions to the SiP service. Handling of the different SMC functions
have therefore been split into separate functions.

Signed-off-by: Mikael Olsson <mikael.olsson@arm.com>
Change-Id: If28da8df0f13c449d1fdb2bd9d792d818ec5e1af

drivers/arm/ethosn/ethosn_smc.c

index e314577a3aa0a4d8585d4dfe5afe8f3aebdc098f..124de924373de5f51551e49260f3b2fd9dc4e357 100644 (file)
@@ -188,13 +188,13 @@ static int ethosn_core_is_sleeping(uintptr_t core_addr)
        return ((mmio_read_32(sysctrl0_reg) & sleeping_mask) == sleeping_mask);
 }
 
-static bool ethosn_reset(uintptr_t core_addr, int hard_reset)
+static bool ethosn_core_reset(uintptr_t core_addr, bool hard_reset)
 {
        unsigned int timeout;
        const uintptr_t sysctrl0_reg =
                ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG);
-       const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET
-                                                   : SEC_SYSCTRL0_SOFT_RESET;
+       const uint32_t reset_val = hard_reset ? SEC_SYSCTRL0_HARD_RESET :
+                                               SEC_SYSCTRL0_SOFT_RESET;
 
        mmio_write_32(sysctrl0_reg, reset_val);
 
@@ -212,99 +212,133 @@ static bool ethosn_reset(uintptr_t core_addr, int hard_reset)
        return timeout < ETHOSN_RESET_TIMEOUT_US;
 }
 
-uintptr_t ethosn_smc_handler(uint32_t smc_fid,
-                            u_register_t core_addr,
-                            u_register_t asset_alloc_idx,
-                            u_register_t reset_type,
-                            u_register_t is_protected,
-                            void *cookie,
-                            void *handle,
-                            u_register_t flags)
+static int ethosn_core_full_reset(const struct ethosn_device_t *device,
+                                 const struct ethosn_core_t *core,
+                                 bool hard_reset,
+                                 u_register_t asset_alloc_idx,
+                                 u_register_t is_protected)
 {
-       int hard_reset = 0;
-       const struct ethosn_device_t *device = NULL;
-       const struct ethosn_core_t *core = NULL;
-       const uint32_t fid = smc_fid & FUNCID_NUM_MASK;
-
-       /* Only SiP fast calls are expected */
-       if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
-               (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) {
-               SMC_RET1(handle, SMC_UNK);
+       if (!device->has_reserved_memory &&
+           asset_alloc_idx >= device->num_allocators) {
+               WARN("ETHOSN: Unknown asset allocator index given to SMC call.\n");
+               return ETHOSN_UNKNOWN_ALLOCATOR_IDX;
        }
 
-       /* Truncate parameters to 32-bits for SMC32 */
-       if (GET_SMC_CC(smc_fid) == SMC_32) {
-               core_addr &= 0xFFFFFFFF;
-               asset_alloc_idx &= 0xFFFFFFFF;
-               reset_type &= 0xFFFFFFFF;
-               is_protected &= 0xFFFFFFFF;
+       if (!ethosn_core_reset(core->addr, hard_reset)) {
+               return ETHOSN_FAILURE;
        }
 
-       if (!is_ethosn_fid(smc_fid) || (fid > ETHOSN_FNUM_IS_SLEEPING)) {
-               WARN("ETHOSN: Unknown SMC call: 0x%x\n", smc_fid);
-               SMC_RET1(handle, SMC_UNK);
+       if (!device->has_reserved_memory) {
+               ethosn_configure_smmu_streams(device, core, asset_alloc_idx);
+
+#if ARM_ETHOSN_NPU_TZMP1
+               ethosn_configure_stream_nsaid(core, is_protected);
+#endif
        }
 
-       /* Commands that do not require a valid core address */
-       switch (fid) {
-       case ETHOSN_FNUM_VERSION:
-               SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
+       ethosn_delegate_to_ns(core->addr);
+
+       return ETHOSN_SUCCESS;
+}
+
+static uintptr_t ethosn_smc_core_reset_handler(const struct ethosn_device_t *device,
+                                              const struct ethosn_core_t *core,
+                                              bool hard_reset,
+                                              u_register_t asset_alloc_idx,
+                                              u_register_t reset_type,
+                                              u_register_t is_protected,
+                                              void *handle)
+{
+       int ret;
+
+       switch (reset_type) {
+       case ETHOSN_RESET_TYPE_FULL:
+               ret = ethosn_core_full_reset(device, core, hard_reset,
+                                            asset_alloc_idx, is_protected);
+               break;
+       case ETHOSN_RESET_TYPE_HALT:
+               ret = ethosn_core_reset(core->addr, hard_reset) ? ETHOSN_SUCCESS : ETHOSN_FAILURE;
+               break;
+       default:
+               WARN("ETHOSN: Invalid reset type given to SMC call.\n");
+               ret = ETHOSN_INVALID_PARAMETER;
+               break;
        }
 
+       SMC_RET1(handle, ret);
+}
+
+static uintptr_t ethosn_smc_core_handler(uint32_t fid,
+                                        u_register_t core_addr,
+                                        u_register_t asset_alloc_idx,
+                                        u_register_t reset_type,
+                                        u_register_t is_protected,
+                                        void *handle)
+{
+       bool hard_reset = false;
+       const struct ethosn_device_t *device = NULL;
+       const struct ethosn_core_t *core = NULL;
+
        if (!ethosn_get_device_and_core(core_addr, &device, &core))  {
                SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS);
        }
 
-       /* Commands that require a valid core address */
        switch (fid) {
        case ETHOSN_FNUM_IS_SEC:
                SMC_RET1(handle, ethosn_is_sec(core->addr));
        case ETHOSN_FNUM_IS_SLEEPING:
                SMC_RET1(handle, ethosn_core_is_sleeping(core->addr));
-       }
-
-       if (!device->has_reserved_memory &&
-           asset_alloc_idx >= device->num_allocators) {
-               WARN("ETHOSN: Unknown asset allocator index given to SMC call.\n");
-               SMC_RET1(handle, ETHOSN_UNKNOWN_ALLOCATOR_IDX);
-       }
-
-       if (reset_type > ETHOSN_RESET_TYPE_HALT) {
-               WARN("ETHOSN: Invalid reset type given to SMC call.\n");
-               SMC_RET1(handle, ETHOSN_INVALID_PARAMETER);
-       }
-
-       /*
-        * Commands that require a valid device, reset type,
-        * core and asset allocator
-        */
-       switch (fid) {
        case ETHOSN_FNUM_HARD_RESET:
-               hard_reset = 1;
+               hard_reset = true;
                /* Fallthrough */
        case ETHOSN_FNUM_SOFT_RESET:
-               if (!ethosn_reset(core->addr, hard_reset)) {
-                       SMC_RET1(handle, ETHOSN_FAILURE);
-               }
+               return ethosn_smc_core_reset_handler(device, core,
+                                                    hard_reset,
+                                                    asset_alloc_idx,
+                                                    reset_type,
+                                                    is_protected,
+                                                    handle);
+       default:
+               WARN("ETHOSN: Unimplemented SMC call: 0x%x\n", fid);
+               SMC_RET1(handle, SMC_UNK);
+       }
+}
+
+uintptr_t ethosn_smc_handler(uint32_t smc_fid,
+                            u_register_t x1,
+                            u_register_t x2,
+                            u_register_t x3,
+                            u_register_t x4,
+                            void *cookie,
+                            void *handle,
+                            u_register_t flags)
+{
+       const uint32_t fid = smc_fid & FUNCID_NUM_MASK;
 
-               if (reset_type == ETHOSN_RESET_TYPE_FULL) {
-                       if (!device->has_reserved_memory) {
-                               ethosn_configure_smmu_streams(device, core,
-                                                       asset_alloc_idx);
+       /* Only SiP fast calls are expected */
+       if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
+               (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) {
+               SMC_RET1(handle, SMC_UNK);
+       }
 
-                               #if ARM_ETHOSN_NPU_TZMP1
-                               ethosn_configure_stream_nsaid(core,
-                                                             is_protected);
-                               #endif
-                       }
+       /* Truncate parameters to 32-bits for SMC32 */
+       if (GET_SMC_CC(smc_fid) == SMC_32) {
+               x1 &= 0xFFFFFFFF;
+               x2 &= 0xFFFFFFFF;
+               x3 &= 0xFFFFFFFF;
+               x4 &= 0xFFFFFFFF;
+       }
 
-                       ethosn_delegate_to_ns(core->addr);
-               }
-               SMC_RET1(handle, ETHOSN_SUCCESS);
-       default:
-               WARN("ETHOSN: Unimplemented SMC call: 0x%x\n", fid);
+       if (!is_ethosn_fid(smc_fid) || (fid > ETHOSN_FNUM_IS_SLEEPING)) {
+               WARN("ETHOSN: Unknown SMC call: 0x%x\n", smc_fid);
                SMC_RET1(handle, SMC_UNK);
        }
+
+       if (fid == ETHOSN_FNUM_VERSION) {
+               SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
+       }
+
+       return ethosn_smc_core_handler(fid, x1, x2, x3, x4, handle);
 }
 
 int ethosn_smc_setup(void)