examples: update Xilinx example code.

This provides bug fixes and enhancements to the Xilinx-specific example
code, and a couple of small fixes to the linux example code.

Signed-off-by: Ed Mooring <ed.mooring@linaro.org>
This commit is contained in:
Ben Levinsky
2020-01-31 09:19:40 +01:00
committed by Arnaud Pouliquen
parent f98eb2a670
commit 007f2fe640
16 changed files with 721 additions and 141 deletions
+1
View File
@@ -3,6 +3,7 @@ collector_create (APP_LIB_DIRS "")
collector_create (APP_INC_DIRS "")
collector_create (APP_LIB_DEPS "")
collector_create (APP_EXTRA_C_FLAGS "")
set (APPS_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set (APPS_SHARE_DIR "${CMAKE_CURRENT_BINARY_DIR}/share")
+8 -5
View File
@@ -1,5 +1,5 @@
set (_cflags "${CMAKE_C_FLAGS} ${APP_EXTRA_C_FLAGS}")
collector_list (_app_extra_c_flags APP_EXTRA_C_FLAGS)
set (_cflags "${CMAKE_C_FLAGS} ${_app_extra_c_flags}")
set (_fw_dir "${APPS_SHARE_DIR}")
collector_list (_list PROJECT_INC_DIRS)
@@ -11,21 +11,24 @@ collector_list (_app_list APP_LIB_DIRS)
link_directories (${_list} ${_app_list})
get_property (_linker_opt GLOBAL PROPERTY APP_LINKER_OPT)
collect (PROJECT_LIB_DEPS xilpm)
collector_list (_deps PROJECT_LIB_DEPS)
set (OPENAMP_LIB open_amp)
foreach (_app load_fw)
collector_list (_sources APP_COMMON_SOURCES)
list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/${_app}.c")
list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/mem_image_store.c")
list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/zynqmp_r5_lcm_rproc_example.c")
list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/zynqmp_apu_lcm_rproc_example.c")
list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/zynqmp_rpu_lcm_rproc_example.c")
list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/platform_info.c")
list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/${_app}.c")
if (WITH_STATIC_LIB)
add_executable (${_app}.out ${_sources})
set_source_files_properties(${_sources} PROPERTIES COMPILE_FLAGS "${_cflags}")
target_link_libraries(${_app}.out -Wl,-Map=${_app}.map -Wl,--gc-sections -T"${CMAKE_CURRENT_SOURCE_DIR}/lscript.ld" -Wl,--start-group ${OPENAMP_LIB}-static -lxilpm ${_deps} -Wl,--end-group)
target_link_libraries(${_app}.out -Wl,-Map=${_app}.map -Wl,--gc-sections -T"${CMAKE_CURRENT_SOURCE_DIR}/lscript.ld" -Wl,--start-group ${OPENAMP_LIB}-static ${_deps} -Wl,--end-group)
install (TARGETS ${_app}.out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif (WITH_STATIC_LIB)
+109
View File
@@ -0,0 +1,109 @@
/*
* Copyright(c) 2019 Xilinx Ltd.
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef COMMON_H_
#define COMMON_H_
#include <metal/alloc.h>
#include <metal/io.h>
#include <metal/sys.h>
#include <metal/utilities.h>
#include <openamp/remoteproc.h>
#include <openamp/remoteproc_loader.h>
#include <stdarg.h>
#include <stdio.h>
/* Xilinx headers */
#include <pm_api_sys.h>
#include <xil_mpu.h>
#include <xil_printf.h>
#include <xreg_cortexr5.h>
#ifdef versal
#include <xpm_nodeid.h>
#include <xpm_defs.h>
#ifndef NODE_APU_0
#define NODE_APU_0 PM_DEV_ACPU_0
#endif
#ifndef NODE_APU_1
#define NODE_APU_1 PM_DEV_ACPU_1
#endif
#ifndef NODE_RPU_0
#define NODE_RPU_0 PM_DEV_RPU0_0
#endif
#ifndef NODE_RPU
#define NODE_RPU PM_DEV_RPU0_0
#endif
#ifndef NODE_RPU_1
#define NODE_RPU_1 PM_DEV_RPU0_1
#endif
#ifndef NODE_TCM_0_A
#define NODE_TCM_0_A PM_DEV_TCM_0_A
#endif
#ifndef NODE_TCM_0_B
#define NODE_TCM_0_B PM_DEV_TCM_0_B
#endif
#ifndef NODE_TCM_1_A
#define NODE_TCM_1_A PM_DEV_TCM_1_A
#endif
#ifndef NODE_TCM_1_B
#define NODE_TCM_1_B PM_DEV_TCM_1_B
#endif
#ifndef NODE_DDR
#define NODE_DDR PM_DEV_DDR_0
#endif
#ifndef NODE_OCM_BANK_0
#define NODE_OCM_BANK_0 PM_DEV_OCM_0
#endif
#ifndef NODE_OCM_BANK_1
#define NODE_OCM_BANK_1 PM_DEV_OCM_1
#endif
#ifndef NODE_OCM_BANK_2
#define NODE_OCM_BANK_2 PM_DEV_OCM_2
#endif
#ifndef NODE_OCM_BANK_3
#define NODE_OCM_BANK_3 PM_DEV_OCM_3
#endif
/* Requirement limits */
#define XPM_MAX_CAPABILITY (PM_CAP_ACCESS | PM_CAP_CONTEXT | PM_CAP_WAKEUP)
#define XPM_MAX_LATENCY (0xFFFFU)
#define XPM_MAX_QOS (100)
#define XPM_MIN_CAPABILITY (0)
#define XPM_MIN_LATENCY (0)
#define XPM_MIN_QOS (0)
#define XPM_DEF_CAPABILITY XPM_MAX_CAPABILITY
#define XPM_DEF_LATENCY XPM_MAX_LATENCY
#define XPM_DEF_QOS XPM_MAX_QOS
enum XPmRequestAck {
REQUEST_ACK_NO = 1,
REQUEST_ACK_BLOCKING,
REQUEST_ACK_NON_BLOCKING,
REQUEST_ACK_CB_CERROR,
};
#else /* zynqmp */
#include <pm_defs.h>
#define XPM_MAX_QOS MAX_QOS
#define XPM_MIN_QOS (0)
#endif /* versal */
#define LPRINTF(format, ...) xil_printf(format, ##__VA_ARGS__)
//#define LPRINTF(format, ...)
#define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
struct rproc_priv {
struct remoteproc *rproc;
int cpu_id;
};
#endif /* COMMON_H_ */
+20 -97
View File
@@ -7,22 +7,9 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <metal/io.h>
#include <metal/sys.h>
#include <openamp/remoteproc.h>
#include <openamp/remoteproc_loader.h>
#include <stdarg.h>
#include <stdio.h>
/* Xilinx headers */
#include <pm_api_sys.h>
#include <pm_defs.h>
#include <xil_printf.h>
#include <platform_info.h>
#include <common.h>
#define LPRINTF(format, ...) xil_printf(format, ##__VA_ARGS__)
//#define LPRINTF(format, ...)
#define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
extern struct remoteproc_ops r5_rproc_ops;
extern struct image_store_ops mem_image_store_ops;
struct mem_file {
@@ -33,57 +20,6 @@ static struct mem_file image = {
.base = (void *)0x3ED00000,
};
static XIpiPsu IpiInst;
static XStatus IpiConfigure(XIpiPsu *const IpiInstPtr)
{
XStatus Status;
XIpiPsu_Config *IpiCfgPtr;
/* Look Up the config data */
IpiCfgPtr = XIpiPsu_LookupConfig(XPAR_XIPIPSU_0_DEVICE_ID);
if (NULL == IpiCfgPtr) {
Status = XST_FAILURE;
LPERROR("%s ERROR in getting CfgPtr\r\n", __func__);
return Status;
}
/* Init with the Cfg Data */
Status = XIpiPsu_CfgInitialize(IpiInstPtr, IpiCfgPtr,
IpiCfgPtr->BaseAddress);
if (XST_SUCCESS != Status) {
LPERROR("%s ERROR #%d in configuring IPI\r\n", __func__, Status);
return Status;
}
return Status;
}
static void app_log_handler(enum metal_log_level level,
const char *format, ...)
{
char msg[1024];
va_list args;
static const char *level_strs[] = {
"metal: emergency: ",
"metal: alert: ",
"metal: critical: ",
"metal: error: ",
"metal: warning: ",
"metal: notice: ",
"metal: info: ",
"metal: debug: ",
};
va_start(args, format);
vsnprintf(msg, sizeof(msg), format, args);
va_end(args);
if (level <= METAL_LOG_EMERGENCY || level > METAL_LOG_DEBUG)
level = METAL_LOG_EMERGENCY;
xil_printf("%s%s", level_strs[level], msg);
}
int load_exectuable_block(struct remoteproc *rproc,
struct image_store_ops *store_ops, void *store,
const char *img_path)
@@ -95,6 +31,7 @@ int load_exectuable_block(struct remoteproc *rproc,
return -EINVAL;
/* Configure remoteproc to get ready to load executable */
remoteproc_config(rproc, NULL);
/* Load remoteproc executable */
LPRINTF("Start to load executable with remoteproc_load() \r\n");
ret = remoteproc_load(rproc, NULL, store, store_ops, NULL);
@@ -109,6 +46,7 @@ int load_exectuable_block(struct remoteproc *rproc,
return ret;
}
LPRINTF("successfully started the processor\r\n");
#ifndef RPU_BOOT_LINUX
/* ... */
asm volatile("wfi");
LPRINTF("going to stop the processor\r\n");
@@ -116,9 +54,11 @@ int load_exectuable_block(struct remoteproc *rproc,
/* application may want to do some cleanup before shutdown */
LPRINTF("going to shutdown the processor\r\n");
remoteproc_shutdown(rproc);
#endif /* RPU_BOOT_LINUX */
return 0;
}
#ifndef RPU_BOOT_LINUX
int load_exectuable_noblock(struct remoteproc *rproc,
struct image_store_ops *store_ops, void *store,
const char *img_path)
@@ -196,55 +136,38 @@ int load_exectuable_noblock(struct remoteproc *rproc,
remoteproc_shutdown(rproc);
return 0;
}
#endif /* RPU_BOOT_LINUX */
int main(void)
{
struct remoteproc rproc;
struct remoteproc *ret_rproc;
struct remoteproc *rproc = NULL;
void *store = &image;
unsigned int cpu_id = NODE_RPU_1;
unsigned int cpu_id = LOAD_FW_TARGET;
int ret;
struct metal_init_params metal_param = {
.log_handler = app_log_handler,
.log_level = METAL_LOG_DEBUG,
};
if (XST_SUCCESS != IpiConfigure(&IpiInst)) {
LPERROR("Failed to config IPI instance\r\n");
LPRINTF("Loading Exectuable Demo\n");
rproc = app_init(cpu_id);
if (!rproc) {
LPERROR("app_init failed\r\n");
return -1;
}
if (XST_SUCCESS != XPm_InitXilpm(&IpiInst)) {
LPERROR("Failed to initialize PM\r\n");
return -1;
}
LPRINTF("Loading Exectuable Demo\r\n");
/* Initialize libmetal evironment */
metal_init(&metal_param);
/* Initialize remoteproc instance */
ret_rproc = remoteproc_init(&rproc, &r5_rproc_ops, &cpu_id);
if (!ret_rproc) {
LPRINTF("failed to initialize coprocessor\r\n");
return -1;
}
ret = load_exectuable_block(&rproc, &mem_image_store_ops, store, NULL);
ret = load_exectuable_block(rproc, &mem_image_store_ops, store, NULL);
if (ret < 0) {
LPERROR("load_exectuable_block failed\r\n");
/* Make sure the remote is shut down */
remoteproc_shutdown(&rproc);
remoteproc_shutdown(rproc);
return -1;
}
ret = load_exectuable_noblock(&rproc, &mem_image_store_ops, store,
#ifndef RPU_BOOT_LINUX
ret = load_exectuable_noblock(rproc, &mem_image_store_ops, store,
NULL);
if (ret < 0) {
LPERROR("load_exectuable_noblock failed\r\n");
/* Make sure the remote is shut down */
remoteproc_shutdown(&rproc);
remoteproc_shutdown(rproc);
return -1;
}
remoteproc_remove(&rproc);
#endif /* RPU_BOOT_LINUX */
remoteproc_remove(rproc);
return ret;
}
+2 -14
View File
@@ -7,19 +7,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <metal/io.h>
#include <metal/sys.h>
#include <openamp/remoteproc_loader.h>
#include <stdarg.h>
#include <stdio.h>
/* Xilinx headers */
#include <pm_api_sys.h>
#include <pm_defs.h>
#include <xil_printf.h>
#define LPRINTF(format, ...) xil_printf(format, ##__VA_ARGS__)
//#define LPRINTF(format, ...)
#define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
#include <common.h>
struct mem_file {
const void *base;
@@ -56,7 +44,7 @@ int mem_image_load(void *store, size_t offset, size_t size,
(void)is_blocking;
LPRINTF("%s: offset=0x%x, size=0x%x\r\n",
LPRINTF("%s: offset=0x%x, size=0x%x\n\r",
__func__, offset, size);
if (pa == METAL_BAD_PHYS) {
if (data == NULL) {
+103
View File
@@ -0,0 +1,103 @@
/*
* Copyright(c) 2019 Xilinx Ltd.
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform_info.h>
#include <common.h>
extern struct remoteproc_ops zynqmp_apu_rproc_ops;
extern struct remoteproc_ops zynqmp_rpu_rproc_ops;
static struct remoteproc rproc_inst;
static struct remoteproc_ops ops;
static struct remoteproc * platform_create_proc(unsigned int cpu_id)
{
struct remoteproc * rproc;
if (NODE_RPU_0 <= LOAD_FW_TARGET && LOAD_FW_TARGET <= NODE_RPU_1)
ops = zynqmp_rpu_rproc_ops;
else if (NODE_APU_0 <= LOAD_FW_TARGET && LOAD_FW_TARGET <= NODE_APU_1)
ops = zynqmp_apu_rproc_ops;
else
return NULL;
rproc = remoteproc_init(&rproc_inst, &ops, &cpu_id);
if (!rproc)
return NULL;
return &rproc_inst;
}
static void app_log_handler(enum metal_log_level level,
const char *format, ...)
{
char msg[1024];
va_list args;
static const char *level_strs[] = {
"metal: emergency: ",
"metal: alert: ",
"metal: critical: ",
"metal: error: ",
"metal: warning: ",
"metal: notice: ",
"metal: info: ",
"metal: debug: ",
};
va_start(args, format);
vsnprintf(msg, sizeof(msg), format, args);
va_end(args);
if (level <= METAL_LOG_EMERGENCY || level > METAL_LOG_DEBUG)
level = METAL_LOG_EMERGENCY;
xil_printf("%s%s", level_strs[level], msg);
}
static XIpiPsu IpiInst;
static XStatus IpiConfigure(XIpiPsu *const IpiInstPtr)
{
XStatus Status;
XIpiPsu_Config *IpiCfgPtr;
/* Look Up the config data */
IpiCfgPtr = XIpiPsu_LookupConfig(XPAR_XIPIPSU_0_DEVICE_ID);
if (NULL == IpiCfgPtr) {
Status = XST_FAILURE;
LPERROR("%s ERROR in getting CfgPtr\n", __func__);
return Status;
}
/* Init with the Cfg Data */
Status = XIpiPsu_CfgInitialize(IpiInstPtr, IpiCfgPtr,
IpiCfgPtr->BaseAddress);
if (XST_SUCCESS != Status) {
LPERROR("%s ERROR #%d in configuring IPI\n", __func__, Status);
return Status;
}
return Status;
}
struct remoteproc * app_init(unsigned int cpu_id){
struct metal_init_params metal_param = {
.log_handler = app_log_handler,
.log_level = METAL_LOG_DEBUG,
};
metal_init(&metal_param);
if (XST_SUCCESS != IpiConfigure(&IpiInst)) {
LPERROR("Failed to config IPI instance\r\n");
return NULL;
}
if (XST_SUCCESS != XPm_InitXilpm(&IpiInst)) {
LPERROR("Failed to initialize PM\r\n");
return NULL;
}
return platform_create_proc(cpu_id);
}
+11
View File
@@ -0,0 +1,11 @@
/*
* Copyright(c) 2019 Xilinx Ltd.
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLATFORM_INFO_H_
#define PLATFORM_INFO_H_
struct remoteproc * app_init(unsigned int cpu_id);
#endif /* PLATFORM_INFO_H_ */
@@ -0,0 +1,176 @@
/*
* ZynqMP APU life cycle management remoteproc example implementation
*
* Copyright(c) 2019 Xilinx Ltd.
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common.h>
static struct remoteproc *apu_rproc_init(struct remoteproc *rproc,
struct remoteproc_ops *ops, void *arg)
{
struct rproc_priv *priv;
unsigned int cpu_id = *((unsigned int *)arg);
if(cpu_id < NODE_APU_0 || cpu_id > NODE_APU_1) {
LPERROR("%s: invalid node id: %d \n\r",__func__, cpu_id);
return NULL;
}
LPRINTF("%s: node id: %d\n\r", __func__, cpu_id);
priv = metal_allocate_memory(sizeof(*priv));
if (!priv)
return NULL;
memset(priv, 0, sizeof(*priv));
priv->rproc = rproc;
priv->cpu_id = cpu_id;
priv->rproc->ops = ops;
metal_list_init(&priv->rproc->mems);
priv->rproc->priv = priv;
rproc->state = RPROC_READY;
return priv->rproc;
}
static void apu_rproc_remove(struct remoteproc *rproc)
{
struct rproc_priv *priv;
priv = (struct rproc_priv *)rproc->priv;
metal_free_memory(priv);
}
static void *apu_rproc_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)
{
struct remoteproc_mem *mem;
metal_phys_addr_t lpa, lda, lda_end;
if ((!da || !pa) || (*da == METAL_BAD_PHYS && *pa == METAL_BAD_PHYS))
return NULL;
LPRINTF("%s: pa=0x%x, da=0x%x, size=0x%x, atrribute=0x%x\n\r",
__func__, *pa, *da, size, attribute);
lda = *da;
lpa = *pa;
if (!attribute)
attribute = NORM_SHARED_NCACHE | PRIV_RW_USER_RW;
lda_end = lda + size;
if (lda_end <= 0x80000000)
XPm_RequestNode(NODE_DDR,PM_CAP_ACCESS,
XPM_MIN_QOS,REQUEST_ACK_NO);
if (lda >= 0xFFFC0000 && lda < 0xFFFD0000)
XPm_RequestNode(NODE_OCM_BANK_0,PM_CAP_ACCESS,
XPM_MIN_QOS,REQUEST_ACK_NO);
if (lda <= 0xFFFDFFFF && lda_end >= 0xFFFD0000)
XPm_RequestNode(NODE_OCM_BANK_1,PM_CAP_ACCESS,
XPM_MIN_QOS,REQUEST_ACK_NO);
if (lda <= 0xFFFEFFFF && lda_end >= 0xFFFE0000)
XPm_RequestNode(NODE_OCM_BANK_2,PM_CAP_ACCESS,
XPM_MIN_QOS,REQUEST_ACK_NO);
if (lda_end >= 0xFFFF0000)
XPm_RequestNode(NODE_OCM_BANK_3,PM_CAP_ACCESS,
XPM_MIN_QOS,REQUEST_ACK_NO);
mem = metal_allocate_memory(sizeof(*mem));
if (!mem)
return NULL;
mem->pa = lpa;
mem->da = lda;
*io = metal_allocate_memory(sizeof(struct metal_io_region));
if (!*io) {
metal_free_memory(mem);
return NULL;
}
/* This code only runs on the R5, which has a flat memory
* space. Therefore, we use the same value for the physical
* and virtual addresses we pass in to metal_io_init().
*/
metal_io_init(*io, (void *)mem->pa, &mem->pa, size,
sizeof(metal_phys_addr_t)<<3, attribute, NULL);
mem->io = *io;
metal_list_add_tail(&rproc->mems, &mem->node);
*pa = lpa;
*da = lda;
mem->size = size;
return metal_io_phys_to_virt(*io, mem->pa);
}
static int apu_rproc_start(struct remoteproc *rproc)
{
struct rproc_priv *priv;
int ret;
priv = rproc->priv;
ret = XPm_RequestWakeUp(priv->cpu_id, true,rproc->bootaddr,
REQUEST_ACK_NO);
if (ret != XST_SUCCESS) {
LPRINTF("%s: Failed to start APU 0x%x, ret=0x%x\n\r",
__func__, priv->cpu_id, ret);
return -1;
}
return 0;
}
static int apu_rproc_stop(struct remoteproc *rproc)
{
/* It is lacking a stop operation in the libPM */
(void)rproc;
return 0;
}
static int apu_rproc_shutdown(struct remoteproc *rproc)
{
struct rproc_priv *priv;
int ret;
struct remoteproc_mem *mem;
struct metal_list *node;
priv = rproc->priv;
/* Delete all the registered remoteproc memories */
metal_list_for_each(&rproc->mems, node) {
struct metal_list *tmpnode;
metal_phys_addr_t pa, pa_end;
mem = metal_container_of(node, struct remoteproc_mem, node);
tmpnode = node;
/* Release TCM resource */
pa = mem->pa;
pa_end = metal_io_phys(mem->io, metal_io_region_size(mem->io));
if (pa_end <= 0x7FFFFFFF)
XPm_ReleaseNode(NODE_DDR);
if (pa >= 0xFFFC0000 && pa < 0xFFFD0000)
XPm_ReleaseNode(NODE_OCM_BANK_0);
if (pa <= 0xFFFDFFFF && pa_end >= 0xFFFD0000)
XPm_ReleaseNode(NODE_OCM_BANK_1);
if (pa <= 0xFFFEFFFF && pa_end >= 0xFFFE0000)
XPm_ReleaseNode(NODE_OCM_BANK_2);
if (pa_end >= 0xFFFF0000)
XPm_ReleaseNode(NODE_OCM_BANK_3);
node = tmpnode->prev;
metal_list_del(tmpnode);
metal_free_memory(mem->io);
metal_free_memory(mem);
}
ret = XPm_ForcePowerDown(priv->cpu_id, REQUEST_ACK_NO);
if (ret != XST_SUCCESS)
return -1;
return 0;
}
struct remoteproc_ops zynqmp_apu_rproc_ops = {
.init = apu_rproc_init,
.remove = apu_rproc_remove,
.start = apu_rproc_start,
.stop = apu_rproc_stop,
.shutdown = apu_rproc_shutdown,
.mmap = apu_rproc_mmap,
};
@@ -0,0 +1,203 @@
/*
* ZynqMP RPU life cycle management remoteproc example implementation
*
* Copyright(c) 2019 Xilinx Ltd.
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common.h>
static struct remoteproc *rpu_rproc_init(struct remoteproc *rproc,
struct remoteproc_ops *ops, void *arg)
{
struct rproc_priv *priv;
unsigned int cpu_id = *((unsigned int *)arg);
if (cpu_id < NODE_RPU_0 || cpu_id > NODE_RPU_1) {
LPERROR("%s: invalid node id: %d\n\r", __func__, cpu_id);
return NULL;
}
LPRINTF("%s: node id: %d\n\r", __func__, cpu_id);
priv = metal_allocate_memory(sizeof(*priv));
if (!priv)
return NULL;
memset(priv, 0, sizeof(*priv));
priv->rproc = rproc;
priv->cpu_id = cpu_id;
priv->rproc->ops = ops;
metal_list_init(&priv->rproc->mems);
priv->rproc->priv = priv;
rproc->state = RPROC_READY;
return priv->rproc;
}
static void rpu_rproc_remove(struct remoteproc *rproc)
{
struct rproc_priv *priv;
priv = (struct rproc_priv *)rproc->priv;
metal_free_memory(priv);
}
static void *rpu_rproc_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)
{
struct remoteproc_mem *mem;
struct rproc_priv *priv;
metal_phys_addr_t lpa, lda, lda_end;
priv = rproc->priv;
if ((!da || !pa) || (*da == METAL_BAD_PHYS && *pa == METAL_BAD_PHYS))
return NULL;
LPRINTF("%s: pa=0x%x, da=0x%x, size=0x%x, atrribute=0x%x\n\r",
__func__, *pa, *da, size, attribute);
lda = *da;
lpa = *pa;
if (!attribute)
attribute = NORM_SHARED_NCACHE | PRIV_RW_USER_RW;
lda_end = lda + size;
/* call xilpm request node for relevant memory */
if (lda <= 0x40000) {
if (priv->cpu_id == NODE_RPU_0 || priv->cpu_id == NODE_RPU) {
lpa = 0xFFE00000 + lda;
if (lda < 0x10000)
XPm_RequestNode(NODE_TCM_0_A,PM_CAP_ACCESS,
XPM_MIN_QOS,REQUEST_ACK_NO);
if (lda <= 0x20000 && lda_end >= 0x10000)
XPm_RequestNode(NODE_TCM_1_A,PM_CAP_ACCESS,
XPM_MIN_QOS,REQUEST_ACK_NO);
if (lda <= 0x30000 && lda_end >= 0x20000)
XPm_RequestNode(NODE_TCM_0_B,PM_CAP_ACCESS,
XPM_MIN_QOS,REQUEST_ACK_NO);
if (lda <= 0x40000 && lda_end >= 0x30000)
XPm_RequestNode(NODE_TCM_1_B,PM_CAP_ACCESS,
XPM_MIN_QOS,REQUEST_ACK_NO);
} else if (priv->cpu_id == NODE_RPU_1) {
lpa = 0xFFE90000 + lda;
if (lda < 0x10000)
XPm_RequestNode(NODE_TCM_1_A,PM_CAP_ACCESS,
XPM_MIN_QOS,REQUEST_ACK_NO);
if (lda <= 0x30000 && lda_end >= 0x20000)
XPm_RequestNode(NODE_TCM_1_B,PM_CAP_ACCESS,
XPM_MIN_QOS,REQUEST_ACK_NO);
} else {
LPERROR("mmap failed: invalid cpu node: %d\r\n", priv->cpu_id);
return NULL;
}
}
mem = metal_allocate_memory(sizeof(*mem));
if (!mem)
return NULL;
mem->pa = lpa;
mem->da = lda;
*io = metal_allocate_memory(sizeof(struct metal_io_region));
if (!*io) {
metal_free_memory(mem);
return NULL;
}
/* This code only runs on the R5, which has a flat memory
* space. Therefore, we use the same value for the physical
* and virtual addresses we pass in to metal_io_init().
*/
metal_io_init(*io, (void *)mem->pa, &mem->pa, size,
sizeof(metal_phys_addr_t)<<3, attribute, NULL);
mem->io = *io;
metal_list_add_tail(&rproc->mems, &mem->node);
*pa = lpa;
*da = lda;
mem->size = size;
return metal_io_phys_to_virt(*io, mem->pa);
}
static int rpu_rproc_start(struct remoteproc *rproc)
{
struct rproc_priv *priv;
int ret;
priv = rproc->priv;
ret = XPm_RequestWakeUp(priv->cpu_id, true, rproc->bootaddr,
REQUEST_ACK_NO);
if (ret != XST_SUCCESS) {
LPRINTF("%s: Failed to start RPU 0x%x, ret=0x%x\n\r",
__func__, priv->cpu_id, ret);
return -1;
}
return 0;
}
static int rpu_rproc_stop(struct remoteproc *rproc)
{
/* It is lacking a stop operation in the libPM */
(void)rproc;
return 0;
}
static int rpu_rproc_shutdown(struct remoteproc *rproc)
{
struct rproc_priv *priv;
int ret;
struct remoteproc_mem *mem;
struct metal_list *node;
priv = rproc->priv;
/* Delete all the registered remoteproc memories */
metal_list_for_each(&rproc->mems, node) {
struct metal_list *tmpnode;
metal_phys_addr_t pa, pa_end;
mem = metal_container_of(node, struct remoteproc_mem, node);
tmpnode = node;
/* Release TCM resource */
pa = mem->pa;
pa_end = metal_io_phys(mem->io, metal_io_region_size(mem->io));
node = tmpnode->prev;
metal_list_del(tmpnode);
metal_free_memory(mem->io);
metal_free_memory(mem);
/* call xilpm release node for relevant memory */
if (pa <= 0x40000) {
if (priv->cpu_id == NODE_RPU_0 || priv->cpu_id == NODE_RPU) {
if (pa < 0x10000)
XPm_ReleaseNode(NODE_TCM_0_A);
if (pa <= 0x20000 && pa_end >= 0x10000)
XPm_ReleaseNode(NODE_TCM_1_A);
if (pa <= 0x30000 && pa_end >= 0x20000)
XPm_ReleaseNode(NODE_TCM_0_B);
if (pa <= 0x40000 && pa_end >= 0x30000)
XPm_ReleaseNode(NODE_TCM_1_B);
} else if (priv->cpu_id == NODE_RPU_1) {
if (pa < 0x10000)
XPm_ReleaseNode(NODE_TCM_1_A);
if (pa <= 0x30000 && pa_end >= 0x20000)
XPm_ReleaseNode(NODE_TCM_1_B);
} else {
LPERROR("unmap failed: invalid cpu node: %d\r\n", priv->cpu_id);
return NULL;
}
}
}
ret = XPm_ForcePowerDown(priv->cpu_id, REQUEST_ACK_NO);
if (ret != XST_SUCCESS)
return -1;
return 0;
}
struct remoteproc_ops zynqmp_rpu_rproc_ops = {
.init = rpu_rproc_init,
.remove = rpu_rproc_remove,
.start = rpu_rproc_start,
.stop = rpu_rproc_stop,
.shutdown = rpu_rproc_shutdown,
.mmap = rpu_rproc_mmap,
};
-1
View File
@@ -1,4 +1,3 @@
collect (APP_COMMON_SOURCES platform_info.c)
collect (APP_COMMON_SOURCES zynqmp_linux_r5_proc.c)
collect (APP_INC_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
+13 -8
View File
@@ -34,23 +34,28 @@
#define RPU_CPU_ID 0 /* RPU remote CPU Index. We only talk to
* one CPU in the exmaple. We set the CPU
* index to 0. */
#define IPI_CHN_BITMASK 0x00000100 /* IPI channel bit mask for IPI
#ifdef versal
#define IPI_CHN_BITMASK 0x08 /* IPI channel bit mask for IPI
* from/to RPU0 */
#define IPI_DEV_NAME "ff360000.ipi" /* IPI device name */
#else
#define IPI_CHN_BITMASK 0x00000100
#define IPI_DEV_NAME "ff340000.ipi"
#endif /* versal */
#define DEV_BUS_NAME "platform" /* device bus name. "platform" bus
* is used in Linux kernel for generic
* devices */
/* libmetal devices names used in the examples.
* They are platform devices, you find them in Linux sysfs
* sys/bus/platform/devices */
#define IPI_DEV_NAME "ff340000.ipi" /* IPI device name */
#define SHM_DEV_NAME "3ed20000.shm" /* shared device name */
#define RSC_MEM_PA 0x3ED20000UL
#define RSC_MEM_SIZE 0x2000UL
#define VRING_MEM_PA 0x3ED40000UL
#define VRING_MEM_SIZE 0x8000UL
#define SHARED_BUF_PA 0x3ED48000UL
#define SHARED_BUF_SIZE 0x40000UL
#define RSC_MEM_PA 0x3ED20000UL
#define RSC_MEM_SIZE 0x2000UL
#define VRING_MEM_PA 0x3ED40000UL
#define VRING_MEM_SIZE 0x8000UL
#define SHARED_BUF_PA 0x3ED48000UL
#define SHARED_BUF_SIZE 0x40000UL
struct remoteproc_priv rproc_priv = {
.ipi_name = IPI_DEV_NAME,
-3
View File
@@ -29,9 +29,6 @@
#define IPI_DEV_NAME "ipi_dev"
#define IPI_BUS_NAME "generic"
#define IPI_BASE_ADDR XPAR_XIPIPSU_0_BASE_ADDRESS /* IPI base address*/
#define IPI_CHN_BITMASK 0x01000000 /* IPI channel bit mask for IPI from/to
APU */
/* Cortex R5 memory attributes */
#define DEVICE_SHARED 0x00000001U /* device, shareable */
+10 -1
View File
@@ -17,7 +17,16 @@ extern "C" {
#define PRIV_RW_USER_RW (0x00000003U<<8U) /* Full Access */
/* Interrupt vectors */
#define IPI_IRQ_VECT_ID XPAR_XIPIPSU_0_INT_ID
#ifdef versal
#define IPI_IRQ_VECT_ID 63
#define IPI_BASE_ADDR 0xFF340000 /* IPI base address*/
#define IPI_CHN_BITMASK 0x0000020 /* IPI channel bit mask for IPI from/to
APU */
#else
#define IPI_IRQ_VECT_ID XPAR_XIPIPSU_0_INT_ID
#define IPI_BASE_ADDR XPAR_XIPIPSU_0_BASE_ADDRESS
#define IPI_CHN_BITMASK 0x01000000
#endif /* versal */
struct remoteproc_priv {
const char *ipi_name; /**< IPI device name */
@@ -1,3 +1,5 @@
include(CheckSymbolExists)
collect (APP_COMMON_SOURCES helper.c)
set (_linker_script "${CMAKE_CURRENT_SOURCE_DIR}/linker_remote.ld")
@@ -12,6 +14,23 @@ find_library(LIBXIL_LIB NAMES xil PATHS ${CMAKE_FIND_ROOT_PATH})
get_filename_component(LIBXIL_LIB_DIR ${LIBXIL_LIB} DIRECTORY)
collect(PROJECT_LIB_DIRS ${LIBXIL_LIB_DIR})
# check PM API for certain headers and set client version based
CHECK_SYMBOL_EXISTS(XPAR_XILPM_ENABLED "xparameters.h" PM_FOUND)
if(PM_FOUND)
find_library(HAS_PM_LIB NAMES xilpm PATHS ${CMAKE_FIND_ROOT_PATH})
collect (PROJECT_LIB_DEPS xilpm)
CHECK_SYMBOL_EXISTS(versal "xparameters.h" VERSION_2_PM_CLIENT)
if (VERSION_2_PM_CLIENT)
collect (APP_EXTRA_C_FLAGS " -DVERSION_2_PM_CLIENT ")
else()
collect (APP_EXTRA_C_FLAGS " -DVERSION_1_PM_CLIENT ")
endif(VERSION_2_PM_CLIENT)
endif(PM_FOUND)
collect(PROJECT_LIB_DEPS xil)
collect(PROJECT_LIB_DEPS c)
collect(PROJECT_LIB_DEPS m)
find_library(XILMEM_LIB NAMES xilmem PATHS ${CMAKE_FIND_ROOT_PATH})
if(XILMEM_LIB)
collect (PROJECT_LIB_DEPS xilmem)
endif(XILMEM_LIB)
@@ -23,6 +23,7 @@
#include <metal/io.h>
#include <metal/irq.h>
#include <metal/shmem.h>
#include <metal/scatterlist.h>
#include <metal/utilities.h>
#include <openamp/remoteproc.h>
#include <openamp/rpmsg_virtio.h>
@@ -58,20 +59,22 @@ struct remoteproc_priv {
int shm_size;
struct metal_io_region *shm_old_io;
struct metal_io_region shm_new_io;
struct metal_generic_shmem *metal_shm;
struct metal_scatter_list *sg;
struct remoteproc_mem shm;
struct vring_ipi_info ipi;
};
static struct remoteproc_priv rproc_priv_table [] = {
{
.shm_file = "openamp.shm",
.shm_file = "linux_shm/openamp.shm",
.shm_size = 0x80000,
.ipi = {
.path = "unixs:/tmp/openamp.event.0",
},
},
{
.shm_file = "openamp.shm",
.shm_file = "linux_shm/openamp.shm",
.shm_size = 0x80000,
.ipi = {
.path = "unix:/tmp/openamp.event.0",
@@ -228,6 +231,8 @@ linux_proc_init(struct remoteproc *rproc,
struct remoteproc_priv *prproc = arg;
struct metal_io_region *io;
struct remoteproc_mem *shm;
struct metal_generic_shmem *metal_shm = NULL;
struct metal_scatter_list *sg = NULL;
struct vring_ipi_info *ipi;
int ret;
@@ -235,12 +240,20 @@ linux_proc_init(struct remoteproc *rproc,
return NULL;
rproc->priv = prproc;
/* Create shared memory io */
ret = metal_shmem_open(prproc->shm_file, prproc->shm_size, &io);
ret = metal_shmem_open(prproc->shm_file, prproc->shm_size, 0, &metal_shm);
if (ret) {
printf("Failed to init rproc, failed to open shm %s.\r\n",
prproc->shm_file);
return NULL;
}
prproc->metal_shm = metal_shm;
sg = metal_shmem_mmap(metal_shm, prproc->shm_size);
if (sg == NULL) {
printf("Failed mmap shmem with libmetal.\n");
goto err;
}
prproc->sg = sg;
io = sg->ios;
prproc->shm_old_io = io;
shm = &prproc->shm;
shm->pa = 0;
@@ -270,6 +283,12 @@ linux_proc_init(struct remoteproc *rproc,
return rproc;
err:
if (sg != NULL) {
metal_shmem_munmap(metal_shm, sg);
}
if (metal_shm != NULL) {
metal_shmem_close(metal_shm);
}
return NULL;
}
@@ -278,7 +297,6 @@ static void linux_proc_remove(struct remoteproc *rproc)
{
struct remoteproc_priv *prproc;
struct vring_ipi_info *ipi;
struct metal_io_region *io;
if (!rproc)
return;
@@ -293,10 +311,11 @@ static void linux_proc_remove(struct remoteproc *rproc)
}
/* Close shared memory */
io = prproc->shm_old_io;
if (io && io->ops.close) {
io->ops.close(io);
prproc->shm_old_io = NULL;
if (prproc->metal_shm) {
if (prproc->sg) {
metal_shmem_munmap(prproc->metal_shm, prproc->sg);
}
metal_shmem_close(prproc->metal_shm);
}
}
@@ -371,19 +390,29 @@ static int platform_slave_setup_resource_table(const char *shm_file,
metal_phys_addr_t rsc_pa)
{
struct metal_io_region *io;
struct metal_generic_shmem *metal_shm = NULL;
struct metal_scatter_list *sg = NULL;
void *rsc_shm;
int ret;
ret = metal_shmem_open(shm_file, shm_size, &io);
/* Get shared memory io */
ret = metal_shmem_open(shm_file, shm_size, 0, &metal_shm);
if (ret) {
printf("Failed to init rproc, failed to open shm %s.\r\n",
printf("Failed to setup rsc table, failed to open shm %s.\r\n",
shm_file);
return -1;
}
sg = metal_shmem_mmap(metal_shm, shm_size);
if (sg == NULL) {
printf("Failed to setup rsc table, mmap with libmetal failed.\r\n");
metal_shmem_close(metal_shm);
return -1;
}
io = sg->ios;
rsc_shm = metal_io_virt(io, rsc_pa);
memcpy(rsc_shm, rsc_table, rsc_size);
io->ops.close(io);
free(io);
metal_shmem_munmap(metal_shm, sg);
metal_shmem_close(metal_shm);
return 0;
}
+5
View File
@@ -43,6 +43,11 @@ if (WITH_APPS)
endif (WITH_PROXY)
endif (WITH_APPS)
# LOAD_FW only allowed for R5, otherwise turn off
if (NOT ${MACHINE} STREQUAL "zynqmp_r5")
set (WITH_LOAD_FW OFF)
endif(NOT ${MACHINE} STREQUAL "zynqmp_r5")
option (WITH_VIRTIO_MASTER "Build with virtio master enabled" ON)
option (WITH_VIRTIO_SLAVE "Build with virtio slave enabled" ON)