alif: Implement Open-AMP port backend.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
This commit is contained in:
parent
6b4d46569b
commit
4f6f283abb
8 changed files with 403 additions and 2 deletions
|
|
@ -76,10 +76,10 @@ $(BUILD):
|
|||
$(MKDIR) -p $@
|
||||
|
||||
$(BUILD)/M55_HP/firmware.bin:
|
||||
make -f alif.mk MCU_CORE=M55_HP
|
||||
make -f alif.mk MCU_CORE=M55_HP MICROPY_PY_OPENAMP_MODE=0
|
||||
|
||||
$(BUILD)/M55_HE/firmware.bin:
|
||||
make -f alif.mk MCU_CORE=M55_HE
|
||||
make -f alif.mk MCU_CORE=M55_HE MICROPY_PY_OPENAMP_MODE=1
|
||||
|
||||
$(BUILD)/firmware.toc.bin: $(ALIF_TOC_APPS)
|
||||
$(Q)python $(ALIF_TOOLS)/app-gen-toc.py \
|
||||
|
|
|
|||
|
|
@ -203,6 +203,17 @@ $(BUILD)/tinyusb_port/tusb_alif_dcd.o: CFLAGS += -Wno-unused-variable -DTUSB_ALI
|
|||
$(BUILD)/$(ALIF_DFP_REL_TOP)/se_services/source/services_host_boot.o: CFLAGS += -Wno-stringop-truncation
|
||||
$(BUILD)/$(ALIF_DFP_REL_TOP)/se_services/source/services_host_system.o: CFLAGS += -Wno-maybe-uninitialized
|
||||
|
||||
# Add Alif-specific implementation of libmetal (and optionally OpenAMP's rproc).
|
||||
# Note: libmetal code is generated via a pre-processor so ensure that runs first.
|
||||
ifeq ($(MICROPY_PY_OPENAMP),1)
|
||||
SRC_C += mpmetalport.c
|
||||
$(BUILD)/mpmetalport.o: $(BUILD)/openamp/metal/config.h
|
||||
ifeq ($(MICROPY_PY_OPENAMP_REMOTEPROC),1)
|
||||
SRC_C += mpremoteprocport.c
|
||||
$(BUILD)/mpremoteprocport.o: $(BUILD)/openamp/metal/config.h
|
||||
endif
|
||||
endif
|
||||
|
||||
# List of sources for qstr extraction
|
||||
SRC_QSTR += $(SRC_C) $(SHARED_SRC_C) $(GEN_PINS_SRC)
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#define IRQ_PRI_UART_REPL NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 1, 0)
|
||||
#define IRQ_PRI_ADC NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 3, 0)
|
||||
#define IRQ_PRI_USB NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 5, 0)
|
||||
#define IRQ_PRI_HWSEM NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 8, 0)
|
||||
#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_7, 127, 0)
|
||||
|
||||
// these states correspond to values from query_irq, enable_irq and disable_irq
|
||||
|
|
|
|||
|
|
@ -114,6 +114,14 @@ SECTIONS
|
|||
* (.bss.sram0*)
|
||||
} > SRAM0
|
||||
|
||||
/* Open-AMP Shared Memory Region */
|
||||
.openamp_memory (NOLOAD) : ALIGN(32)
|
||||
{
|
||||
_openamp_shm_region_start = .;
|
||||
. = . + 64K;
|
||||
_openamp_shm_region_end = .;
|
||||
} >SRAM6_A
|
||||
|
||||
.bss : ALIGN(4)
|
||||
{
|
||||
__bss_start__ = .;
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@
|
|||
#define MICROPY_SCHEDULER_DEPTH (8)
|
||||
#define MICROPY_SCHEDULER_STATIC_NODES (1)
|
||||
#define MICROPY_USE_INTERNAL_ERRNO (1)
|
||||
#define MICROPY_TRACKED_ALLOC (MICROPY_PY_OPENAMP)
|
||||
|
||||
// Fine control over Python builtins, classes, modules, etc
|
||||
#define MICROPY_PY_SYS_PLATFORM "alif"
|
||||
|
|
|
|||
119
ports/alif/mpmetalport.c
Normal file
119
ports/alif/mpmetalport.c
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2024 OpenMV LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* libmetal Alif port.
|
||||
*/
|
||||
|
||||
#include ALIF_CMSIS_H
|
||||
#include "hwsem.h"
|
||||
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
#include "metal/sys.h"
|
||||
#include "metal/utilities.h"
|
||||
#include "metal/device.h"
|
||||
|
||||
struct metal_state _metal;
|
||||
static mp_sched_node_t rproc_notify_node;
|
||||
|
||||
int metal_sys_init(const struct metal_init_params *params) {
|
||||
metal_unused(params);
|
||||
|
||||
// Reset the hardware semaphore.
|
||||
hwsem_reset(METAL_HSEM_DEVICE);
|
||||
#if MICROPY_PY_OPENAMP_HOST
|
||||
hwsem_reset(METAL_HSEM_REMOTE);
|
||||
#endif
|
||||
|
||||
// Enable the hardware semaphore IRQ.
|
||||
NVIC_ClearPendingIRQ(METAL_HSEM_IRQn);
|
||||
NVIC_SetPriority(METAL_HSEM_IRQn, IRQ_PRI_HWSEM);
|
||||
NVIC_EnableIRQ(METAL_HSEM_IRQn);
|
||||
|
||||
// If cache management is not enabled, configure the MPU to disable
|
||||
// caching for the entire Open-AMP shared memory region.
|
||||
#ifndef VIRTIO_USE_DCACHE
|
||||
ARM_MPU_Disable();
|
||||
// NOTE: The startup code uses the first 4 attributes.
|
||||
#define MEMATTR_IDX_NORMAL_NON_CACHEABLE 4
|
||||
ARM_MPU_SetMemAttr(MEMATTR_IDX_NORMAL_NON_CACHEABLE, ARM_MPU_ATTR(
|
||||
ARM_MPU_ATTR_NON_CACHEABLE,
|
||||
ARM_MPU_ATTR_NON_CACHEABLE));
|
||||
MPU->RNR = METAL_MPU_REGION_ID;
|
||||
MPU->RBAR = ARM_MPU_RBAR(METAL_MPU_REGION_BASE, ARM_MPU_SH_NON, 0, 1, 0); // RO-0, NP-1, XN-0
|
||||
MPU->RLAR = ARM_MPU_RLAR(METAL_MPU_REGION_BASE + METAL_MPU_REGION_SIZE - 1, MEMATTR_IDX_NORMAL_NON_CACHEABLE);
|
||||
ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk);
|
||||
#endif
|
||||
|
||||
metal_bus_register(&metal_generic_bus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_sys_finish(void) {
|
||||
NVIC_DisableIRQ(METAL_HSEM_IRQn);
|
||||
NVIC_ClearPendingIRQ(METAL_HSEM_IRQn);
|
||||
hwsem_reset(METAL_HSEM_DEVICE);
|
||||
metal_bus_unregister(&metal_generic_bus);
|
||||
}
|
||||
|
||||
unsigned int sys_irq_save_disable(void) {
|
||||
return disable_irq();
|
||||
}
|
||||
|
||||
void sys_irq_restore_enable(unsigned int state) {
|
||||
enable_irq(state);
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags) {
|
||||
metal_unused(pa);
|
||||
metal_unused(size);
|
||||
metal_unused(flags);
|
||||
return va;
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len) {
|
||||
SCB_CleanDCache_by_Addr(addr, len);
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len) {
|
||||
SCB_InvalidateDCache_by_Addr(addr, len);
|
||||
}
|
||||
|
||||
int metal_rproc_notify(void *priv, uint32_t id) {
|
||||
// Release the HW semaphore to notify the other core.
|
||||
hwsem_release(METAL_HSEM_REMOTE, HWSEM_MASTERID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void METAL_HSEM_IRQ_HANDLER(void) {
|
||||
// Schedule the node only if the other core released the Semaphore.
|
||||
if (METAL_HSEM_DEVICE->HWSEM_REL_REG == 0) {
|
||||
mp_sched_schedule_node(&rproc_notify_node, openamp_remoteproc_notified);
|
||||
}
|
||||
hwsem_request(METAL_HSEM_DEVICE, METAL_HSEM_REMOTE_ID);
|
||||
}
|
||||
89
ports/alif/mpmetalport.h
Normal file
89
ports/alif/mpmetalport.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2024 OpenMV LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* libmetal alif port.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_ALIF_MPMETALPORT_H
|
||||
#define MICROPY_INCLUDED_ALIF_MPMETALPORT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "py/mphal.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#define METAL_HAVE_STDATOMIC_H 0
|
||||
#define METAL_HAVE_FUTEX_H 0
|
||||
|
||||
#define METAL_MAX_DEVICE_REGIONS 2
|
||||
|
||||
#if MICROPY_PY_OPENAMP_HOST
|
||||
#define METAL_HSEM_DEVICE ((HWSEM_Type *)HWSEM14_BASE)
|
||||
#define METAL_HSEM_REMOTE ((HWSEM_Type *)HWSEM15_BASE)
|
||||
#define METAL_HSEM_REMOTE_ID (0x410FD222U)
|
||||
#define METAL_HSEM_IRQn HWSEM_IRQ14_IRQn
|
||||
#define METAL_HSEM_IRQ_HANDLER HWSEM_IRQ14Handler
|
||||
#else
|
||||
#define METAL_HSEM_DEVICE ((HWSEM_Type *)HWSEM15_BASE)
|
||||
#define METAL_HSEM_REMOTE ((HWSEM_Type *)HWSEM14_BASE)
|
||||
#define METAL_HSEM_REMOTE_ID (0x410FD221U)
|
||||
#define METAL_HSEM_IRQn HWSEM_IRQ15_IRQn
|
||||
#define METAL_HSEM_IRQ_HANDLER HWSEM_IRQ15Handler
|
||||
#endif
|
||||
|
||||
// Set to 1 to enable log output.
|
||||
#define METAL_LOG_HANDLER_ENABLE 0
|
||||
|
||||
#define metal_cpu_yield()
|
||||
|
||||
// Shared memory config
|
||||
#define METAL_SHM_NAME "OPENAMP_SHM"
|
||||
// Note 1K must be reserved at the start of the openamp
|
||||
// shared memory region, for the shared resource table.
|
||||
#define METAL_RSC_ADDR ((void *)_openamp_shm_region_start)
|
||||
#define METAL_RSC_SIZE (1024)
|
||||
|
||||
#define METAL_SHM_ADDR ((metal_phys_addr_t)(_openamp_shm_region_start + METAL_RSC_SIZE))
|
||||
#define METAL_SHM_SIZE ((size_t)(_openamp_shm_region_end - _openamp_shm_region_start - METAL_RSC_SIZE))
|
||||
|
||||
#define METAL_MPU_REGION_ID (9) // NOTE: The startup code uses the first 9 regions.
|
||||
#define METAL_MPU_REGION_BASE ((uint32_t)_openamp_shm_region_start)
|
||||
#define METAL_MPU_REGION_SIZE (0x00010000U)
|
||||
|
||||
extern const char _openamp_shm_region_start[];
|
||||
extern const char _openamp_shm_region_end[];
|
||||
|
||||
int metal_rproc_notify(void *priv, uint32_t id);
|
||||
extern void openamp_remoteproc_notified(mp_sched_node_t *node);
|
||||
|
||||
static inline int __metal_sleep_usec(unsigned int usec) {
|
||||
mp_hal_delay_us(usec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void metal_generic_default_poll(void) {
|
||||
mp_event_handle_nowait();
|
||||
__WFI();
|
||||
}
|
||||
|
||||
#endif // MICROPY_INCLUDED_ALIF_METAL_PORT_H
|
||||
172
ports/alif/mpremoteprocport.c
Normal file
172
ports/alif/mpremoteprocport.c
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2024 OpenMV LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* modremoteproc alif port.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "metal/alloc.h"
|
||||
#include "metal/errno.h"
|
||||
#include "metal/io.h"
|
||||
#include "metal/sys.h"
|
||||
#include "metal/device.h"
|
||||
#include "metal/utilities.h"
|
||||
#include "extmod/modopenamp_remoteproc.h"
|
||||
#include "se_services.h"
|
||||
|
||||
typedef struct mmap {
|
||||
uintptr_t base;
|
||||
uintptr_t limit;
|
||||
} mmap_t;
|
||||
|
||||
static const mmap_t mmap_nocache[] = {
|
||||
{ .base = ITCM_BASE, .limit = ITCM_BASE + ITCM_SIZE },
|
||||
{ .base = DTCM_BASE, .limit = DTCM_BASE + ITCM_SIZE },
|
||||
{ .base = MRAM_BASE, .limit = MRAM_BASE + MRAM_SIZE }
|
||||
};
|
||||
|
||||
static bool is_cacheable(const void *p, size_t bytes) {
|
||||
uintptr_t base = (uintptr_t)p;
|
||||
if (bytes == 0) {
|
||||
return false;
|
||||
}
|
||||
uintptr_t limit = base + bytes;
|
||||
for (unsigned int i = 0; i < sizeof(mmap_nocache) / sizeof(mmap_nocache[0]); i++) {
|
||||
if (base >= mmap_nocache[i].base && limit < mmap_nocache[i].limit) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct remoteproc *mp_openamp_remoteproc_init(struct remoteproc *rproc,
|
||||
const struct remoteproc_ops *ops, void *arg) {
|
||||
metal_log(METAL_LOG_DEBUG, "rproc_init()\n");
|
||||
|
||||
rproc->ops = ops;
|
||||
rproc->state = RPROC_OFFLINE;
|
||||
// Allocate the image store and save it in private data.
|
||||
rproc->priv = mp_openamp_remoteproc_store_alloc();
|
||||
|
||||
// Reset the remote core.
|
||||
se_services_boot_reset_cpu(EXTSYS_1);
|
||||
return rproc;
|
||||
}
|
||||
|
||||
void *mp_openamp_remoteproc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa,
|
||||
metal_phys_addr_t *da, size_t size, unsigned int attribute,
|
||||
struct metal_io_region **io) {
|
||||
metal_log(METAL_LOG_DEBUG, "rproc_mmap(): pa 0x%p da 0x%p io 0x%p size %u\n", *pa, *da, *io, size);
|
||||
|
||||
struct remoteproc_mem *mem;
|
||||
metal_phys_addr_t lpa = *pa;
|
||||
metal_phys_addr_t lda = *da;
|
||||
|
||||
if (lda == METAL_BAD_PHYS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lpa == METAL_BAD_PHYS) {
|
||||
lpa = lda;
|
||||
}
|
||||
|
||||
// Currently this port doesn't support loading firmware to flash,
|
||||
// only SD/SRAM images are supported. Check of load address is in
|
||||
// the flash region, and if so return NULL.
|
||||
if (lda >= MRAM_BASE && lda < (MRAM_BASE + MRAM_SIZE)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mem = metal_allocate_memory(sizeof(*mem));
|
||||
if (!mem) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*io = metal_allocate_memory(sizeof(struct metal_io_region));
|
||||
if (!*io) {
|
||||
metal_free_memory(mem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
remoteproc_init_mem(mem, NULL, lpa, lda, size, *io);
|
||||
|
||||
metal_io_init(*io, (void *)mem->da, &mem->pa, size,
|
||||
sizeof(metal_phys_addr_t) << 3, attribute, NULL);
|
||||
|
||||
remoteproc_add_mem(rproc, mem);
|
||||
*pa = lpa;
|
||||
*da = lda;
|
||||
return metal_io_phys_to_virt(*io, mem->pa);
|
||||
}
|
||||
|
||||
int mp_openamp_remoteproc_start(struct remoteproc *rproc) {
|
||||
metal_log(METAL_LOG_DEBUG, "rproc_start()\n");
|
||||
|
||||
// Flush cached areas for the remote core.
|
||||
struct metal_list *node;
|
||||
metal_list_for_each(&rproc->mems, node) {
|
||||
struct remoteproc_mem *mem;
|
||||
mem = metal_container_of(node, struct remoteproc_mem, node);
|
||||
if (is_cacheable((uint32_t *)mem->pa, mem->size)) {
|
||||
SCB_CleanDCache_by_Addr((uint32_t *)mem->pa, mem->size);
|
||||
}
|
||||
}
|
||||
|
||||
se_services_boot_reset_cpu(EXTSYS_1);
|
||||
se_services_boot_cpu(EXTSYS_1, (uint32_t)rproc->bootaddr); // GlobalToLocal
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_openamp_remoteproc_stop(struct remoteproc *rproc) {
|
||||
metal_log(METAL_LOG_DEBUG, "rproc_stop()\n");
|
||||
if (rproc->state == RPROC_RUNNING) {
|
||||
se_services_boot_reset_cpu(EXTSYS_1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_openamp_remoteproc_config(struct remoteproc *rproc, void *data) {
|
||||
metal_log(METAL_LOG_DEBUG, "rproc_config()\n");
|
||||
(void)rproc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mp_openamp_remoteproc_remove(struct remoteproc *rproc) {
|
||||
metal_log(METAL_LOG_DEBUG, "rproc_remove()\n");
|
||||
(void)rproc;
|
||||
}
|
||||
|
||||
int mp_openamp_remoteproc_shutdown(struct remoteproc *rproc) {
|
||||
metal_log(METAL_LOG_DEBUG, "rproc_shutdown()\n");
|
||||
if (rproc->state == RPROC_RUNNING) {
|
||||
se_services_boot_reset_cpu(EXTSYS_1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in a new issue