diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/Makefile b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/Makefile index 8bc23868a..274c51b63 100644 --- a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/Makefile @@ -3,8 +3,10 @@ SRC_DIR := board/rzv2l_smarc SRC_DIR += fsp/src/bsp/cmsis/Device/RENESAS/Source SRC_DIR += fsp/src/bsp/mcu/all SRC_DIR += fsp/src/r_ioport +SRC_DIR += fsp/src/r_mhu_ns SRC_DIR += fsp/src/r_scif_uart SRC_DIR += fsp/src/r_gtm +SRC_DIR += linaro SRC_FILES := $(wildcard *.c) diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/fsp/inc/api/r_mhu_api.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/fsp/inc/api/r_mhu_api.h new file mode 100644 index 000000000..cbdad3c10 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/fsp/inc/api/r_mhu_api.h @@ -0,0 +1,172 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics Corporation and/or its affiliates and may only + * be used with products of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. + * Renesas products are sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for + * the selection and use of Renesas products and Renesas assumes no liability. No license, express or implied, to any + * intellectual property right is granted by Renesas. This software is protected under all applicable laws, including + * copyright laws. Renesas reserves the right to change or discontinue this software and/or this documentation. + * THE SOFTWARE AND DOCUMENTATION IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND + * TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, + * INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE + * SOFTWARE OR DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR + * DOCUMENTATION (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, + * INCLUDING, WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY + * LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * @ingroup RENESAS_INTERFACES + * @defgroup MHU_API MHU Interface (for secure and non secure channels) + * @brief Interface for Message Handling Unit + * + * @section MHU_API_SUMMARY Summary + * The Message Handling Unit interface provides a common API for MHU HAL drivers. + * The Message Handling Unit interface supports: + * - Message communication between Cortex-A55 and Cortex-M33. + * - 32-bit data can be communicated between CPUs via shared memory. + * + * Implemented by: + * - @ref MHU_S + * - @ref MHU_NS + * + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +/* Register definitions, common services and error codes. */ +#include "bsp_api.h" + +#ifndef R_MHU_API_H + #define R_MHU_API_H + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + #define MHU_API_VERSION_MAJOR (1U) + #define MHU_API_VERSION_MINOR (0U) + +/********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ + +typedef enum e_mhu_send_type +{ + MHU_SEND_TYPE_MSG = 0, ///< Channel for sending "message" and receiving "response". + MHU_SEND_TYPE_RSP, ///< Channel for sending "response" and receiving "message". +} mhu_send_type_t; + +/** MHU callback parameter definition */ +typedef struct st_mhu_callback_args +{ + /** Placeholder for user data. Set in @ref mhu_api_t::open function in @ref mhu_cfg_t. */ + void const * p_context; + uint32_t channel; ///< Channel where the receive interrupt occurred. + uint32_t msg; ///< 32-bit received data. +} mhu_callback_args_t; + +/** MHU configuration block */ +typedef struct st_mhu_cfg +{ + /** Generic configuration */ + uint32_t channel; ///< Identifier recognizable by implementation + uint8_t rx_ipl; ///< Receive interrupt priority + IRQn_Type rx_irq; ///< Receive interrupt ID + + /** Parameters to control software behavior */ + void (* p_callback)(mhu_callback_args_t * p_args); ///< Pointer to callback function + + void const * p_shared_memory; ///< Pointer to 64-bit send/receive data buffer. + + /** Placeholder for user data. Passed to the user callback in @ref mhu_callback_args_t. */ + void const * p_context; +} mhu_cfg_t; + +/** MHU control block. Allocate an instance specific control block to pass into the MHU API calls. + * @par Implemented as + * - mhu_instance_ctrl_t + */ +typedef void mhu_ctrl_t; + +/** Interface definition for MHU */ +typedef struct st_mhu_api +{ + /** Opens the MHU driver and initializes the hardware. + * @par Implemented as + * - @ref R_MHU_S_Open() + * - @ref R_MHU_NS_Open() + * + * @param[in] p_ctrl Pointer to control block. Must be declared by user. Elements are set here. + * @param[in] p_cfg Pointer to configuration structure. + */ + fsp_err_t (* open)(mhu_ctrl_t * const p_ctrl, mhu_cfg_t const * const p_cfg); + + /** Performs a send operation on an MHU device. + * @par Implemented as + * - @ref R_MHU_S_MsgSend() + * - @ref R_MHU_NS_MsgSend() + * + * @param[in] p_ctrl Pointer to control block set in mhu_api_t::open call. + * @param[in] msg 32bit send data. + */ + fsp_err_t (* msgSend)(mhu_ctrl_t * const p_ctrl, uint32_t const msg); + + /** + * Specify callback function and optional context pointer and working memory pointer. + * @par Implemented as + * - @ref R_MHU_S_CallbackSet() + * - @ref R_MHU_NS_CallbackSet() + * + * @param[in] p_ctrl Control block set in @ref mhu_api_t::open call for this channel. + * @param[in] p_callback Callback function to register + * @param[in] p_context Pointer to send to callback function + * @param[in] p_callback_memory Pointer to volatile memory where callback structure can be allocated. + * Callback arguments allocated here are only valid during the callback. + */ + fsp_err_t (* callbackSet)(mhu_ctrl_t * const p_api_ctrl, void (* p_callback)(mhu_callback_args_t *), + void const * const p_context, mhu_callback_args_t * const p_callback_memory); + + /** Closes the driver and releases the MHU device. + * @par Implemented as + * - @ref R_MHU_S_Close() + * - @ref R_MHU_NS_Close() + * + * @param[in] p_ctrl Pointer to control block set in mhu_api_t::open call. + */ + fsp_err_t (* close)(mhu_ctrl_t * const p_ctrl); + + /* DEPRECATED Get version and stores it in provided pointer p_version. + * @par Implemented as + * - @ref R_MHU_S_VersionGet() + * - @ref R_MHU_NS_VersionGet() + * + * @param[out] p_version Code and API version used. + */ + fsp_err_t (* versionGet)(fsp_version_t * const p_version); +} mhu_api_t; + +/** This structure encompasses everything that is needed to use an instance of this interface. */ +typedef struct st_mhu_instance +{ + mhu_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance + mhu_cfg_t const * p_cfg; ///< Pointer to the configuration structure for this instance + mhu_api_t const * p_api; ///< Pointer to the API structure for this instance +} mhu_instance_t; + +/******************************************************************************************************************//** + * @} (end addtogroup MHU_API) + *********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif /* R_MHU_API_H */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/fsp/inc/instances/r_mhu_ns.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/fsp/inc/instances/r_mhu_ns.h new file mode 100644 index 000000000..0041d3f7e --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/fsp/inc/instances/r_mhu_ns.h @@ -0,0 +1,109 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics Corporation and/or its affiliates and may only + * be used with products of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. + * Renesas products are sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for + * the selection and use of Renesas products and Renesas assumes no liability. No license, express or implied, to any + * intellectual property right is granted by Renesas. This software is protected under all applicable laws, including + * copyright laws. Renesas reserves the right to change or discontinue this software and/or this documentation. + * THE SOFTWARE AND DOCUMENTATION IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND + * TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, + * INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE + * SOFTWARE OR DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR + * DOCUMENTATION (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, + * INCLUDING, WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY + * LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * @addtogroup MHU_NS + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_mhu_api.h" + +#ifndef R_MHU_NS_H + #define R_MHU_NS_H + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ +FSP_HEADER + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + + #define MHU_NS_CODE_VERSION_MAJOR (1U) + #define MHU_NS_CODE_VERSION_MINOR (0U) + +/************************************************************************************************* + * Type defines + *************************************************************************************************/ + +/** Channel control block. DO NOT INITIALIZE. Initialization occurs when @ref mhu_api_t::open is called. */ +typedef struct st_mhu_ns_instance_ctrl +{ + uint32_t open; ///< Indicates whether the open() API has been successfully called. + mhu_cfg_t const * p_cfg; ///< Pointer to instance configuration + R_MHU0_Type * p_regs; ///< Base register for this channel + + uint32_t channel; ///< channel + mhu_send_type_t send_type; ///< Send Type: Message or Response + uint32_t * p_shared_memory_tx; ///< Pointer to send data area + uint32_t * p_shared_memory_rx; ///< Pointer to recv data area + + #if BSP_TZ_SECURE_BUILD + bool callback_is_secure; ///< p_callback is in secure memory + #endif + + /* Pointer to callback and optional working memory */ + void (* p_callback)(mhu_callback_args_t *); + + /* Pointer to non-secure memory that can be used to pass arguments to a callback in non-secure memory. */ + mhu_callback_args_t * p_callback_memory; + + /* Pointer to context to be passed into callback function */ + void const * p_context; +} mhu_ns_instance_ctrl_t; + +/********************************************************************************************************************** + * Exported global variables + **********************************************************************************************************************/ + +/** @cond INC_HEADER_DEFS_SEC */ +/** Filled in Interface API structure for this Instance. */ +extern const mhu_api_t g_mhu_ns_on_mhu_ns; + +/** @endcond */ + +/*********************************************************************************************************************** + * Public APIs + **********************************************************************************************************************/ +fsp_err_t R_MHU_NS_Open(mhu_ctrl_t * p_ctrl, mhu_cfg_t const * const p_cfg); + +fsp_err_t R_MHU_NS_MsgSend(mhu_ctrl_t * const p_ctrl, uint32_t const msg); + +fsp_err_t R_MHU_NS_Close(mhu_ctrl_t * const p_ctrl); + +fsp_err_t R_MHU_NS_VersionGet(fsp_version_t * p_version); + +fsp_err_t R_MHU_NS_CallbackSet(mhu_ctrl_t * const p_api_ctrl, + void ( * p_callback)(mhu_callback_args_t *), + void const * const p_context, + mhu_callback_args_t * const p_callback_memory); + +void R_MHU_NS_IsrSub(uint32_t irq); + +/** Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ +FSP_FOOTER + +#endif /* R_MHU_NS_H */ + +/*******************************************************************************************************************//** + * @} (end defgroup MHU_NS) + **********************************************************************************************************************/ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/fsp/src/r_mhu_ns/Makefile b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/fsp/src/r_mhu_ns/Makefile new file mode 100644 index 000000000..ffae04ed4 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/fsp/src/r_mhu_ns/Makefile @@ -0,0 +1,5 @@ + +SRC_DIR := +SRC_FILES := $(wildcard *.c) + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/fsp/src/r_mhu_ns/r_mhu_ns.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/fsp/src/r_mhu_ns/r_mhu_ns.c new file mode 100644 index 000000000..4d2230806 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/fsp/src/r_mhu_ns/r_mhu_ns.c @@ -0,0 +1,563 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics Corporation and/or its affiliates and may only + * be used with products of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. + * Renesas products are sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for + * the selection and use of Renesas products and Renesas assumes no liability. No license, express or implied, to any + * intellectual property right is granted by Renesas. This software is protected under all applicable laws, including + * copyright laws. Renesas reserves the right to change or discontinue this software and/or this documentation. + * THE SOFTWARE AND DOCUMENTATION IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND + * TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, + * INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE + * SOFTWARE OR DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR + * DOCUMENTATION (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, + * INCLUDING, WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY + * LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ +#include "r_mhu_ns.h" +#include + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/** "MHU" in ASCII, used to determine if channel is open. */ +#define MHU_NS_OPEN (0x00774855ULL) + +#define MHU_NS_SHMEM_CH_SIZE (0x8) +#define MHU_NS_SHMEM_TXD_OFFSET (0x0) +#define MHU_NS_SHMEM_RXD_OFFSET (0x4) + +/********************************************************************************************************************** + * Typedef definitions + **********************************************************************************************************************/ +#if defined(__ARMCC_VERSION) || defined(__ICCARM__) +typedef void (BSP_CMSE_NONSECURE_CALL * mhu_ns_prv_ns_callback)(mhu_callback_args_t * p_args); +#elif defined(__GNUC__) +typedef BSP_CMSE_NONSECURE_CALL void (*volatile mhu_ns_prv_ns_callback)(mhu_callback_args_t * p_args); +#endif + +/*********************************************************************************************************************** + * Private function prototypes + **********************************************************************************************************************/ +static void r_mhu_ns_set_send_data(mhu_ns_instance_ctrl_t * p_instance_ctrl, uint32_t msg); + +static fsp_err_t r_mhu_ns_common_preamble(mhu_ns_instance_ctrl_t * p_instance_ctrl); + +#if MHU_NS_CFG_PARAM_CHECKING_ENABLE +static fsp_err_t r_mhu_ns_open_param_checking(mhu_ns_instance_ctrl_t * p_instance_ctrl, mhu_cfg_t const * const p_cfg); + +#endif + +/* ISRs. */ +void mhu_ns_int_isr(void); +void metal_irq_isr_wrapper(void); +void metal_irq_isr(uint32_t vector); + +/*********************************************************************************************************************** + * Private global variables + **********************************************************************************************************************/ + +/** Version data structure. */ +static const fsp_version_t s_mhu_ns_version = +{ + .api_version_minor = MHU_API_VERSION_MINOR, + .api_version_major = MHU_API_VERSION_MAJOR, + .code_version_minor = MHU_NS_CODE_VERSION_MINOR, + .code_version_major = MHU_NS_CODE_VERSION_MAJOR, +}; + +extern uint32_t __mhu_shmem_start; + +static const uint32_t g_shmem_base = (uint32_t) &__mhu_shmem_start; + +/*********************************************************************************************************************** + * Global Variables + **********************************************************************************************************************/ + +/** MHU_NS Implementation of MHU Driver */ +const mhu_api_t g_mhu_ns_on_mhu_ns = +{ + .open = R_MHU_NS_Open, + .msgSend = R_MHU_NS_MsgSend, + .callbackSet = R_MHU_NS_CallbackSet, + .close = R_MHU_NS_Close, + .versionGet = R_MHU_NS_VersionGet +}; + +/*******************************************************************************************************************//** + * @addtogroup MHU_NS + * @{ + **********************************************************************************************************************/ + +/*********************************************************************************************************************** + * Functions + **********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Initializes the MHU_NS module instance. Implements @ref mhu_api_t::open. + * + * @retval FSP_SUCCESS Initialization was successful. + * @retval FSP_ERR_ASSERTION A required input pointer is NULL. + * @retval FSP_ERR_ALREADY_OPEN R_MHU_NS_Open has already been called for this p_ctrl. + * @retval FSP_ERR_INVALID_ARGUMENT The specified IRQ number is invalid. + * @retval FSP_ERR_INVALID_CHANNEL Requested channel number is not available on MHU_NS. + **********************************************************************************************************************/ +fsp_err_t R_MHU_NS_Open (mhu_ctrl_t * const p_ctrl, mhu_cfg_t const * const p_cfg) +{ + mhu_ns_instance_ctrl_t * p_instance_ctrl = (mhu_ns_instance_ctrl_t *) p_ctrl; + +#if MHU_NS_CFG_PARAM_CHECKING_ENABLE + fsp_err_t err = r_mhu_ns_open_param_checking(p_instance_ctrl, p_cfg); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); +#endif + + p_instance_ctrl->p_regs = (R_MHU0_Type *) (R_MHU0_BASE + + (p_cfg->channel * ((intptr_t) R_MHU1_BASE - (intptr_t) R_MHU0_BASE))); + p_instance_ctrl->p_cfg = p_cfg; + p_instance_ctrl->channel = p_cfg->channel; + + switch (p_cfg->channel) + { + case 4: + case 5: + { + p_instance_ctrl->send_type = MHU_SEND_TYPE_MSG; + break; + } + + case 1: + case 3: + { + p_instance_ctrl->send_type = MHU_SEND_TYPE_RSP; + break; + } + + default: + { + p_instance_ctrl->send_type = MHU_SEND_TYPE_MSG; + break; + } + } + + if (0 != p_cfg->p_shared_memory) + { + /* Use specified address */ + p_instance_ctrl->p_shared_memory_tx = (uint32_t *) p_cfg->p_shared_memory; + p_instance_ctrl->p_shared_memory_rx = (uint32_t *) (((uint32_t) p_cfg->p_shared_memory) + 0x4); + } + else + { + /* Use default location */ + p_instance_ctrl->p_shared_memory_tx = (uint32_t *) (g_shmem_base + (MHU_NS_SHMEM_CH_SIZE * p_cfg->channel) + + MHU_NS_SHMEM_TXD_OFFSET); + p_instance_ctrl->p_shared_memory_rx = (uint32_t *) (g_shmem_base + (MHU_NS_SHMEM_CH_SIZE * p_cfg->channel) + + MHU_NS_SHMEM_RXD_OFFSET); + } + + /* Power on the MHU_NS channel. */ + R_BSP_MODULE_START(FSP_IP_MHU, p_cfg->channel); + R_BSP_MODULE_CLKON(FSP_IP_MHU, p_cfg->channel); + R_BSP_MODULE_RSTOFF(FSP_IP_MHU, p_cfg->channel); + + R_BSP_IrqCfgEnable(p_cfg->rx_irq, p_cfg->rx_ipl, p_instance_ctrl); + + /* Set callback and context pointers */ + +#if BSP_TZ_SECURE_BUILD + + /* If this is a secure build, the callback provided in p_cfg must be secure. */ + p_instance_ctrl->callback_is_secure = true; +#endif + p_instance_ctrl->p_callback = p_cfg->p_callback; + p_instance_ctrl->p_context = p_cfg->p_context; + p_instance_ctrl->p_callback_memory = NULL; + + p_instance_ctrl->open = MHU_NS_OPEN; + + /* All done. */ + return FSP_SUCCESS; +} + +/********************************************************************************************************************** + * End of function R_MHU_NS_Open + *********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Send message via MHU. + * Implements @ref mhu_api_t::msgSend. + * + * @retval FSP_SUCCESS Send message successfully. + * @retval FSP_ERR_ASSERTION A required pointer was NULL. + * @retval FSP_ERR_NOT_OPEN The instance control structure is not opened. + **********************************************************************************************************************/ +fsp_err_t R_MHU_NS_MsgSend (mhu_ctrl_t * const p_ctrl, uint32_t const msg) +{ + mhu_ns_instance_ctrl_t * p_instance_ctrl = (mhu_ns_instance_ctrl_t *) p_ctrl; +#if MHU_NS_CFG_PARAM_CHECKING_ENABLE +#endif + + fsp_err_t err = r_mhu_ns_common_preamble(p_instance_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Set msg. */ + r_mhu_ns_set_send_data(p_instance_ctrl, msg); + + return FSP_SUCCESS; +} + +/********************************************************************************************************************** + * End of function R_MHU_NS_MsgSend + *********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Updates the user callback with the option to provide memory for the callback argument structure. + * Implements @ref mhu_api_t::callbackSet. + * + * @retval FSP_SUCCESS Callback updated successfully. + * @retval FSP_ERR_ASSERTION A required pointer is NULL. + * @retval FSP_ERR_NOT_OPEN The control block has not been opened. + * @retval FSP_ERR_NO_CALLBACK_MEMORY p_callback is non-secure and p_callback_memory is either secure or NULL. + **********************************************************************************************************************/ +fsp_err_t R_MHU_NS_CallbackSet (mhu_ctrl_t * const p_api_ctrl, + void ( * p_callback)(mhu_callback_args_t *), + void const * const p_context, + mhu_callback_args_t * const p_callback_memory) +{ + mhu_ns_instance_ctrl_t * p_ctrl = (mhu_ns_instance_ctrl_t *) p_api_ctrl; + +#if MHU_NS_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(p_ctrl); + FSP_ASSERT(p_callback); + FSP_ERROR_RETURN(MHU_NS_OPEN == p_ctrl->open, FSP_ERR_NOT_OPEN); +#endif + +#if BSP_TZ_SECURE_BUILD + + /* Get security state of p_callback */ + p_ctrl->callback_is_secure = + (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE)); + + #if MHU_NS_CFG_PARAM_CHECKING_ENABLE + + /* In secure projects, p_callback_memory must be provided in non-secure space if p_callback is non-secure */ + mhu_callback_args_t * const p_callback_memory_checked = cmse_check_pointed_object(p_callback_memory, + CMSE_AU_NONSECURE); + FSP_ERROR_RETURN(p_ctrl->callback_is_secure || (NULL != p_callback_memory_checked), FSP_ERR_NO_CALLBACK_MEMORY); + #endif +#endif + + /* Store callback and context */ + +#if BSP_TZ_SECURE_BUILD + + /* cmse_check_address_range returns NULL if p_callback is located in secure memory */ + p_ctrl->callback_is_secure = + (NULL == cmse_check_address_range((void *) p_callback, sizeof(void *), CMSE_AU_NONSECURE)); +#endif + p_ctrl->p_callback = p_callback; + p_ctrl->p_context = p_context; + p_ctrl->p_callback_memory = p_callback_memory; + + return FSP_SUCCESS; +} + +/********************************************************************************************************************** + * End of function R_MHU_NS_CallbackSet + *********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Disables interrupts, clears internal driver data. + * @ref mhu_api_t::close. + * + * @retval FSP_SUCCESS MHU_NS closed. + * @retval FSP_ERR_ASSERTION p_ctrl is NULL. + * @retval FSP_ERR_NOT_OPEN The instance control structure is not opened. + **********************************************************************************************************************/ +fsp_err_t R_MHU_NS_Close (mhu_ctrl_t * const p_ctrl) +{ + mhu_ns_instance_ctrl_t * p_instance_ctrl = (mhu_ns_instance_ctrl_t *) p_ctrl; + + fsp_err_t err = r_mhu_ns_common_preamble(p_instance_ctrl); + FSP_ERROR_RETURN(FSP_SUCCESS == err, err); + + /* Cleanup the device: disable interrupts */ + + NVIC_DisableIRQ(p_instance_ctrl->p_cfg->rx_irq); + R_FSP_IsrContextSet(p_instance_ctrl->p_cfg->rx_irq, p_instance_ctrl); + + p_instance_ctrl->open = 0U; + + return FSP_SUCCESS; +} + +/********************************************************************************************************************** + * End of function R_MHU_NS_Close + *********************************************************************************************************************/ + +/*********************************************************************************************************************** + * DEPRECATED Sets driver version based on compile time macros. Implements @ref mhu_api_t::versionGet. + * + * @retval FSP_SUCCESS Version in p_version. + * @retval FSP_ERR_ASSERTION The parameter p_version is NULL. + **********************************************************************************************************************/ +fsp_err_t R_MHU_NS_VersionGet (fsp_version_t * const p_version) +{ +#if MHU_NS_CFG_PARAM_CHECKING_ENABLE + + /* Verify parameters are valid */ + FSP_ASSERT(NULL != p_version); +#endif + + p_version->version_id = s_mhu_ns_version.version_id; + + return FSP_SUCCESS; +} + +/********************************************************************************************************************** + * End of function R_MHU_NS_VersionGet + *********************************************************************************************************************/ + +/** @} (end addtogroup MHU_NS) */ + +/*********************************************************************************************************************** + * Private Functions + **********************************************************************************************************************/ + +#if MHU_NS_CFG_PARAM_CHECKING_ENABLE + +/*******************************************************************************************************************//** + * Parameter checking for R_MHU_NS_Open. + * + * @param[in] p_instance_ctrl Pointer to instance control structure. + * @param[in] p_cfg Configuration structure for this instance + * + * @retval FSP_SUCCESS Initialization was successful. + * @retval FSP_ERR_ASSERTION A required input pointer is NULL. + * @retval FSP_ERR_ALREADY_OPEN R_MHU_NS_Open has already been called for this p_ctrl. + * @retval FSP_ERR_INVALID_ARGUMENT The specified IRQ number is invalid. + * @retval FSP_ERR_INVALID_CHANNEL Requested channel number is not available on MHU_NS. + **********************************************************************************************************************/ +static fsp_err_t r_mhu_ns_open_param_checking (mhu_ns_instance_ctrl_t * p_instance_ctrl, mhu_cfg_t const * const p_cfg) +{ + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ASSERT(NULL != p_cfg); + FSP_ERROR_RETURN(MHU_NS_OPEN != p_instance_ctrl->open, FSP_ERR_ALREADY_OPEN); + + /* Validate channel number. */ + FSP_ERROR_RETURN(((1U << p_cfg->channel) & BSP_FEATURE_MHU_NS_VALID_CHANNEL_MASK), FSP_ERR_INVALID_CHANNEL); + + FSP_ERROR_RETURN(FSP_INVALID_VECTOR != p_cfg->rx_irq, FSP_ERR_INVALID_ARGUMENT); + + return FSP_SUCCESS; +} + +#endif + +/*******************************************************************************************************************//** + * Common code at the beginning of all MHU_NS functions except open. + * + * @param[in] p_instance_ctrl Pointer to instance control structure. + * + * @retval FSP_SUCCESS No invalid conditions detected, MHU_NS state matches expected state. + * @retval FSP_ERR_ASSERTION p_ctrl is null. + * @retval FSP_ERR_NOT_OPEN The instance control structure is not opened. + **********************************************************************************************************************/ +static fsp_err_t r_mhu_ns_common_preamble (mhu_ns_instance_ctrl_t * p_instance_ctrl) +{ +#if MHU_NS_CFG_PARAM_CHECKING_ENABLE + FSP_ASSERT(NULL != p_instance_ctrl); + FSP_ERROR_RETURN(MHU_NS_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN); +#else + FSP_PARAMETER_NOT_USED(p_instance_ctrl); +#endif + + return FSP_SUCCESS; +} + +/********************************************************************************************************************** + * End of function r_mhu_ns_common_preamble + *********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * Write a message to shared memory and generate inter-core interrupt + * + * @param[in] p_instance_ctrl Control block for this instance + * @param[in] msg 32bit send data + **********************************************************************************************************************/ +static void r_mhu_ns_set_send_data (mhu_ns_instance_ctrl_t * p_instance_ctrl, uint32_t msg) +{ + if (MHU_SEND_TYPE_MSG == p_instance_ctrl->send_type) + { + /* Check interrupt status: Has the previous message been received? */ + do + { + /* Do Nothing */ + } while (0 != p_instance_ctrl->p_regs->MSG_INT_STSn); + + /* Store the message data. */ + *p_instance_ctrl->p_shared_memory_tx = msg; + + /* Assert interrupt. */ + p_instance_ctrl->p_regs->MSG_INT_SETn = 1; + } + else + { + /* Check interrupt status: Has the previous message been received? */ + do + { + /* Do Nothing */ + } while (0 != p_instance_ctrl->p_regs->RSP_INT_STSn); + + /* Store the message data. */ + *p_instance_ctrl->p_shared_memory_tx = msg; + + /* Assert interrupt. */ + p_instance_ctrl->p_regs->RSP_INT_SETn = 1; + } +} + +/********************************************************************************************************************** + * End of function r_mhu_ns_set_send_data + *********************************************************************************************************************/ + +/********************************************************************************************************************* + * MHU_NS receive interrupt (for OpenAMP) + **********************************************************************************************************************/ +void metal_irq_isr_wrapper (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + + metal_irq_isr(irq); + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} + +/********************************************************************************************************************** + * End of function metal_irq_isr_wrapper + *********************************************************************************************************************/ + +/********************************************************************************************************************* + * MHU_NS receive interrupt (for bere mhu_ns application). + **********************************************************************************************************************/ +void mhu_ns_int_isr (void) +{ + /* Save context if RTOS is used */ + FSP_CONTEXT_SAVE + + IRQn_Type irq = R_FSP_CurrentIrqGet(); + + R_MHU_NS_IsrSub(irq); + + /* Restore context if RTOS is used */ + FSP_CONTEXT_RESTORE +} + +/********************************************************************************************************************** + * End of function mhu_ns_int_isr + *********************************************************************************************************************/ + +/*******************************************************************************************************************//** + * MHU_NS receive interrupt sub function (for OpenAMP) + * + * @param[in] irq irq number for inter-core interrupt + **********************************************************************************************************************/ +void R_MHU_NS_IsrSub (uint32_t irq) +{ + uint32_t msg; + + /* Clear pending IRQ to make sure it doesn't fire again after exiting */ + R_BSP_IrqStatusClear(irq); + + /* Recover ISR context saved in open. */ + mhu_ns_instance_ctrl_t * p_instance_ctrl = (mhu_ns_instance_ctrl_t *) R_FSP_IsrContextGet(irq); + + /* Check interrupt reason */ + if ( + ((MHU_SEND_TYPE_RSP == p_instance_ctrl->send_type) && (0 != p_instance_ctrl->p_regs->MSG_INT_STSn)) || + ((MHU_SEND_TYPE_MSG == p_instance_ctrl->send_type) && (0 != p_instance_ctrl->p_regs->RSP_INT_STSn))) + { + /* Read data */ + msg = *p_instance_ctrl->p_shared_memory_rx; + + /* Clear interrupt */ + if (MHU_SEND_TYPE_RSP == p_instance_ctrl->send_type) + { + p_instance_ctrl->p_regs->MSG_INT_CLRn = 1; + } + else + { + p_instance_ctrl->p_regs->RSP_INT_CLRn = 1; + } + + /* Invoke the callback function if it is set. */ + if (NULL != p_instance_ctrl->p_callback) + { + /* Setup parameters for the user-supplied callback function. */ + mhu_callback_args_t callback_args; + + /* Store callback arguments in memory provided by user if available. This allows callback arguments to be + * stored in non-secure memory so they can be accessed by a non-secure callback function. */ + mhu_callback_args_t * p_args = p_instance_ctrl->p_callback_memory; + if (NULL == p_args) + { + /* Store on stack */ + p_args = &callback_args; + } + else + { + /* Save current arguments on the stack in case this is a nested interrupt. */ + callback_args = *p_args; + } + + p_args->p_context = p_instance_ctrl->p_context; + + p_args->channel = p_instance_ctrl->channel; + p_args->msg = msg; + +#if BSP_TZ_SECURE_BUILD + + /* p_callback can point to a secure function or a non-secure function. */ + if (p_instance_ctrl->callback_is_secure) + { + /* If p_callback is secure, then the project does not need to change security state. */ + p_instance_ctrl->p_callback(p_args); + } + else + { + /* If p_callback is Non-secure, then the project must change to Non-secure state + * in order to call the callback. */ + mhu_ns_prv_ns_callback p_callback = (mhu_ns_prv_ns_callback) (p_instance_ctrl->p_callback); + p_callback(p_args); + } + +#else + + /* If the project is not Trustzone Secure, then it will never need to change security state + * in order to call the callback. */ + p_instance_ctrl->p_callback(p_args); +#endif + + if (NULL != p_instance_ctrl->p_callback_memory) + { + /* Restore callback memory in case this is a nested interrupt. */ + *p_instance_ctrl->p_callback_memory = callback_args; + } + } + } +} + +/********************************************************************************************************************** + * End of function R_MHU_NS_IsrSub + *********************************************************************************************************************/ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/Makefile b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/Makefile new file mode 100644 index 000000000..6c16c3967 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/Makefile @@ -0,0 +1,8 @@ +SRC_DIR := libmetal/lib +SRC_DIR += open-amp/lib/remoteproc +SRC_DIR += open-amp/lib/rpmsg +SRC_DIR += open-amp/lib/virtio + +SRC_FILES := $(wildcard *.c) + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/LICENSE.md b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/LICENSE.md new file mode 100644 index 000000000..5d1645a80 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/LICENSE.md @@ -0,0 +1,41 @@ +Software License Agreement (BSD License) +======================================== + +Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of Xilinx nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + +Notes +========================================= +Use the following tag instead of the full license text in the individual files: + + SPDX-License-Identifier: BSD-3-Clause + +This enables machine processing of license information based on the SPDX +License Identifiers that are here available: http://spdx.org/licenses/ + diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/MAINTAINERS.md b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/MAINTAINERS.md new file mode 100644 index 000000000..5c0bc967f --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/MAINTAINERS.md @@ -0,0 +1,21 @@ +# libmetal Maintainers + +libmetal project is maintained by the OpenAMP open source community. +Everyone is encouraged to submit issues and changes to improve libmetal. + +The intention of this file is to provide a set of names that developers can +consult when they have a question about OpenAMP and to provide a a set of +names to be CC'd when submitting a patch. + +## Project Administration +Wendy Liang + +### All patches CC here +open-amp@googlegroups.com + +## Machines +### Xilinx Platform - Zynq-7000 +Wendy Liang + +### Xilinx Platform - Zynq UltraScale+ MPSoC +Wendy Liang diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/README.md b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/README.md new file mode 100644 index 000000000..810511399 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/README.md @@ -0,0 +1,220 @@ +# libmetal + +## Overview + +Libmetal provides common user APIs to access devices, handle device interrupts +and request memory across the following operating environments: + * Linux user space (based on UIO and VFIO support in the kernel) + * RTOS (with and without virtual memory) + * Bare-metal environments + +## Build Steps + +### Building for Linux Host +``` + $ git clone https://github.com/OpenAMP/libmetal.git + $ mkdir -p libmetal/ + $ cd libmetal/ + $ cmake .. + $ make VERBOSE=1 DESTDIR= install +``` + +### Cross Compiling for Linux Target +Use [meta-openamp](https://github.com/openamp/meta-openamp) to build +libmetal library. +Use package `libmetal` in your yocto config file. + +### Building for Baremetal + +To build on baremetal, you will need to provide a toolchain file. Here is an +example toolchain file: +``` + set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "") + set (MACHINE "zynqmp_r5" CACHE STRING "") + + set (CROSS_PREFIX "armr5-none-eabi-" CACHE STRING "") + set (CMAKE_C_FLAGS "-mfloat-abi=soft -mcpu=cortex-r5 -Wall -Werror -Wextra \ + -flto -Os -I/ws/xsdk/r5_0_bsp/psu_cortexr5_0/include" CACHE STRING "") + + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") + SET(CMAKE_AR "gcc-ar" CACHE STRING "") + SET(CMAKE_C_ARCHIVE_CREATE " qcs ") + SET(CMAKE_C_ARCHIVE_FINISH true) + + include (cross-generic-gcc) +``` +* Note: other toolchain files can be found in the `cmake/platforms/` directory. +* Compile with your toolchain file. +``` + $ mkdir -p build-libmetal + $ cd build-libmetal + $ cmake -DCMAKE_TOOLCHAIN_FILE= + $ make VERBOSE=1 DESTDIR= install +``` + +### Building for Zephyr +As Zephyr uses CMake, we build libmetal library and test application as +targets of Zephyr CMake project. Here is how to build libmetal for Zephyr: +``` + $ export ZEPHYR_GCC_VARIANT=zephyr + $ export ZEPHYR_SDK_INSTALL_DIR= + $ source /zephyr-env.sh + + $ cmake -DWITH_ZEPHYR=on -DBOARD=qemu_cortex_m3 \ + [-DWITH_TESTS=on] + $ make VERBOSE=1 all + # If we have turned on tests with "-DWITH_TESTS=on" when we run cmake, + # we launch libmetal test on Zephyr QEMU platform as follows: + $ make VERBOSE=1 run +``` + +## Interfaces + +The following subsections give an overview of interfaces provided by libmetal. + +### Platform and OS Independent Utilities + +These interfaces do not need to be ported across to new operating systems. + +#### I/O + +The libmetal I/O region abstraction provides access to memory mapped I/O and +shared memory regions. This includes: + * primitives to read and write memory with ordering constraints, and + * ability to translate between physical and virtual addressing on systems + that support virtual memory. + +#### Log + +The libmetal logging interface is used to plug log messages generated by +libmetal into application specific logging mechanisms (e.g. syslog). This +also provides basic message prioritization and filtering mechanisms. + +#### List + +This is a simple doubly linked list implementation used internally within +libmetal, and also available for application use. + +#### Other Utilities + +The following utilities are provided in lib/utilities.h: + * Min/max, round up/down, etc. + * Bitmap operations + * Helper to compute container structure pointers + * ... and more ... + +#### Version + +The libmetal version interface allows user to get the version of the library. + +### Top Level Interfaces + +The users will need to call two top level interfaces to use libmetal APIs: + * metal_init - initialize the libmetal resource + * metal_finish - release libmetal resource + +Each system needs to have their own implementation inside libmetal for these +two APIs to call: + * metal_sys_init + * metal_sys_finish + +For the current release, libmetal provides Linux userspace and bare-metal +implementation for metal_sys_init and metal_sys_finish. + +For Linux userspace, metal_sys_init sets up a table for available shared pages, +checks whether UIO/VFIO drivers are avail, and starts interrupt handling +thread. + +For bare-metal, metal_sys_init and metal_sys_finish just returns. + +### Atomics + +The libmetal atomic operations API is consistent with the C11/C++11 stdatomics +interface. The stdatomics interface is commonly provided by recent toolchains +including GCC and LLVM/Clang. When porting to a different toolchain, it may be +necessary to provide an stdatomic compatible implementation if the toolchain +does not already provide one. + +### Alloc + +libmetal provides memory allocation and release APIs. + +### Locking + +libmetal provides the following locking APIs. + +#### Mutex + +libmetal has a generic mutex implementation which is a busy wait. It is +recommended to have OS specific implementation for mutex. + +The Linux userspace mutex implementation uses futex to wait for the lock +and wakeup a waiter. + +#### Condition Variable +libmetal condition variable APIs provide "wait" for user applications to wait +on some condition to be met, and "signal" to indicate a particular even occurs. + +#### Spinlock +libmetal spinlock APIs provides busy waiting mechanism to acquire a lock. + +### Shmem + +libmetal has a generic static shared memory implementation. If your OS has a +global shared memory allocation, you will need to port it for the OS. + +The Linux userspace shmem implementation uses libhugetlbfs to support huge page +sizes. + +### Bus and Device Abstraction + +libmetal has a static generic implementation. If your OS has a driver model +implementation, you will need to port it for the OS. + +The Linux userspace abstraction binds the devices to UIO or VFIO driver. +The user applications specify which device to use, e.g. bus "platform" bus, +device "f8000000.slcr", and then the abstraction will check if platform UIO +driver or platform VFIO driver is there. If platform VFIO driver exists, +it will bind the device to the platform VFIO driver, otherwise, if UIO driver +exists, it will bind the device to the platform UIO driver. + +The VFIO support is not yet implemented. + +### Interrupt + +libmetal provides APIs to register an interrupt, disable interrupts and restore +interrupts. + +The Linux userspace implementation will use a thread to call select() function +to listen to the file descriptors of the devices to see if there is an interrupt +triggered. If there is an interrupt triggered, it will call the interrupt +handler registered by the user application. + +### Cache + +libmetal provides APIs to flush and invalidate caches. + +The cache APIs for Linux userspace are empty functions for now as cache +operations system calls are not avaiable for all architectures. + +### DMA + +libmetal DMA APIs provide DMA map and unmap implementation. + +After calling DMA map, the DMA device will own the memory. +After calling DMA unmap, the cpu will own the memory. + +For Linux userspace, it only supports to use UIO device memory as DMA +memory for this release. + +### Time +libmetal time APIs provide getting timestamp implementation. + +### Sleep +libmetal sleep APIs provide getting delay execution implementation. + +### Compiler + +This API is for compiler dependent functions. For this release, there is only +a GCC implementation, and compiler specific code is limited to atomic +operations. diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/alloc.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/alloc.h new file mode 100644 index 000000000..5e4dffc7e --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/alloc.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file alloc.h + * @brief Memory allocation handling primitives for libmetal. + */ + +#ifndef __METAL_ALLOC__H__ +#define __METAL_ALLOC__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup Memory Allocation Interfaces + * @{ */ + +/** + * @brief allocate requested memory size + * return a pointer to the allocated memory + * + * @param[in] size size in byte of requested memory + * @return memory pointer, or 0 if it failed to allocate + */ +static inline void *metal_allocate_memory(unsigned int size); + +/** + * @brief free the memory previously allocated + * + * @param[in] ptr pointer to memory + */ +static inline void metal_free_memory(void *ptr); + +#include + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_ALLOC__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/assert.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/assert.h new file mode 100644 index 000000000..f861de1f1 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/assert.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file assert.h + * @brief Assertion support. + */ + +#ifndef __METAL_ASSERT__H__ +#define __METAL_ASSERT__H__ + +#ifdef double_assert +#error recursive +#endif + +#include + +/** + * @brief Assertion macro. + * @param cond Condition to test. + */ +#define metal_assert(cond) metal_sys_assert(cond) + +#endif /* __METAL_ASSERT_H__ */ + diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/atomic.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/atomic.h new file mode 100644 index 000000000..eff4d8542 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/atomic.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file atomic.h + * @brief Atomic primitives for libmetal. + */ + +#ifndef __METAL_ATOMIC__H__ +#define __METAL_ATOMIC__H__ + +#include + +#if defined(HAVE_STDATOMIC_H) && !defined(__STDC_NO_ATOMICS__) && \ + !defined(__cplusplus) +# include +#elif defined(__GNUC__) +# include +#else +# include +#endif + +#endif /* __METAL_ATOMIC__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/cache.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/cache.h new file mode 100644 index 000000000..d1f0939f2 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/cache.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file cache.h + * @brief CACHE operation primitives for libmetal. + */ + +#ifndef __METAL_CACHE__H__ +#define __METAL_CACHE__H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/** \defgroup cache CACHE Interfaces + * @{ */ + +/** + * @brief flush specified data cache + * + * @param[in] addr start memory logical address + * @param[in] len length of memory + * If addr is NULL, and len is 0, + * It will flush the whole data cache. + */ +static inline void metal_cache_flush(void *addr, unsigned int len) +{ + __metal_cache_flush(addr, len); +} + +/** + * @brief invalidate specified data cache + * + * @param[in] addr start memory logical address + * @param[in] len length of memory + * If addr is NULL, and len is 0, + * It will invalidate the whole data cache. + */ +static inline void metal_cache_invalidate(void *addr, unsigned int len) +{ + __metal_cache_invalidate(addr, len); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_CACHE__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/compiler.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/compiler.h new file mode 100644 index 000000000..f2851e573 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/compiler.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file compiler.h + * @brief Compiler specific primitives for libmetal. + */ + +#ifndef __METAL_COMPILER__H__ +#define __METAL_COMPILER__H__ + +#if defined(__CC_ARM) +# include +#elif defined(__GNUC__) +# include +#elif defined(__ICCARM__) +# include +#else +# error "Missing compiler support" +#endif + +#endif /* __METAL_COMPILER__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/compiler/gcc/atomic.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/compiler/gcc/atomic.h new file mode 100644 index 000000000..4470342db --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/compiler/gcc/atomic.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file gcc/atomic.h + * @brief GCC specific atomic primitives for libmetal. + */ + +#ifndef __METAL_GCC_ATOMIC__H__ +#define __METAL_GCC_ATOMIC__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int atomic_flag; +typedef char atomic_char; +typedef unsigned char atomic_uchar; +typedef short atomic_short; +typedef unsigned short atomic_ushort; +typedef int atomic_int; +typedef unsigned int atomic_uint; +typedef long atomic_long; +typedef unsigned long atomic_ulong; +typedef long long atomic_llong; +typedef unsigned long long atomic_ullong; + +#define ATOMIC_FLAG_INIT 0 +#define ATOMIC_VAR_INIT(VAL) (VAL) + +typedef enum { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst, +} memory_order; + +#define atomic_flag_test_and_set(FLAG) \ + __sync_lock_test_and_set((FLAG), 1) +#define atomic_flag_test_and_set_explicit(FLAG, MO) \ + atomic_flag_test_and_set(FLAG) +#define atomic_flag_clear(FLAG) \ + __sync_lock_release((FLAG)) +#define atomic_flag_clear_explicit(FLAG, MO) \ + atomic_flag_clear(FLAG) +#define atomic_init(OBJ, VAL) \ + do { *(OBJ) = (VAL); } while (0) +#define atomic_is_lock_free(OBJ) \ + (sizeof(*(OBJ)) <= sizeof(long)) +#define atomic_store(OBJ, VAL) \ + do { *(OBJ) = (VAL); __sync_synchronize(); } while (0) +#define atomic_store_explicit(OBJ, VAL, MO) \ + atomic_store((OBJ), (VAL)) +#define atomic_load(OBJ) \ + ({ __sync_synchronize(); *(OBJ); }) +#define atomic_load_explicit(OBJ, MO) \ + atomic_load(OBJ) +#define atomic_exchange(OBJ, DES) \ + ({ \ + typeof(OBJ) obj = (OBJ); \ + typeof(*obj) des = (DES); \ + typeof(*obj) expval; \ + typeof(*obj) oldval = atomic_load(obj); \ + do { \ + expval = oldval; \ + oldval = __sync_val_compare_and_swap( \ + obj, expval, des); \ + } while (oldval != expval); \ + oldval; \ + }) +#define atomic_exchange_explicit(OBJ, DES, MO) \ + atomic_exchange((OBJ), (DES)) +#define atomic_compare_exchange_strong(OBJ, EXP, DES) \ + ({ \ + typeof(OBJ) obj = (OBJ); \ + typeof(EXP) exp = (EXP); \ + typeof(*obj) expval = *exp; \ + typeof(*obj) oldval = __sync_val_compare_and_swap( \ + obj, expval, (DES)); \ + *exp = oldval; \ + oldval == expval; \ + }) +#define atomic_compare_exchange_strong_explicit(OBJ, EXP, DES, MO) \ + atomic_compare_exchange_strong((OBJ), (EXP), (DES)) +#define atomic_compare_exchange_weak(OBJ, EXP, DES) \ + atomic_compare_exchange_strong((OBJ), (EXP), (DES)) +#define atomic_compare_exchange_weak_explicit(OBJ, EXP, DES, MO) \ + atomic_compare_exchange_weak((OBJ), (EXP), (DES)) +#define atomic_fetch_add(OBJ, VAL) \ + __sync_fetch_and_add((OBJ), (VAL)) +#define atomic_fetch_add_explicit(OBJ, VAL, MO) \ + atomic_fetch_add((OBJ), (VAL)) +#define atomic_fetch_sub(OBJ, VAL) \ + __sync_fetch_and_sub((OBJ), (VAL)) +#define atomic_fetch_sub_explicit(OBJ, VAL, MO) \ + atomic_fetch_sub((OBJ), (VAL)) +#define atomic_fetch_or(OBJ, VAL) \ + __sync_fetch_and_or((OBJ), (VAL)) +#define atomic_fetch_or_explicit(OBJ, VAL, MO) \ + atomic_fetch_or((OBJ), (VAL)) +#define atomic_fetch_xor(OBJ, VAL) \ + __sync_fetch_and_xor((OBJ), (VAL)) +#define atomic_fetch_xor_explicit(OBJ, VAL, MO) \ + atomic_fetch_xor((OBJ), (VAL)) +#define atomic_fetch_and(OBJ, VAL) \ + __sync_fetch_and_and((OBJ), (VAL)) +#define atomic_fetch_and_explicit(OBJ, VAL, MO) \ + atomic_fetch_and((OBJ), (VAL)) +#define atomic_thread_fence(MO) \ + __sync_synchronize() +#define atomic_signal_fence(MO) \ + __sync_synchronize() + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GCC_ATOMIC__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/compiler/gcc/compiler.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/compiler/gcc/compiler.h new file mode 100644 index 000000000..7295ca899 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/compiler/gcc/compiler.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file gcc/compiler.h + * @brief GCC specific primitives for libmetal. + */ + +#ifndef __METAL_GCC_COMPILER__H__ +#define __METAL_GCC_COMPILER__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define restrict __restrict__ +#define metal_align(n) __attribute__((aligned(n))) +#define metal_weak __attribute__((weak)) + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_GCC_COMPILER__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/condition.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/condition.h new file mode 100644 index 000000000..acbc69e4e --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/condition.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file condition.h + * @brief Condition variable for libmetal. + */ + +#ifndef __METAL_CONDITION__H__ +#define __METAL_CONDITION__H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup condition Condition Variable Interfaces + * @{ */ + +/** Opaque libmetal condition variable data structure. */ +struct metal_condition; + +/** + * @brief Initialize a libmetal condition variable. + * @param[in] cv condition variable to initialize. + */ +static inline void metal_condition_init(struct metal_condition *cv); + +/** + * @brief Notify one waiter. + * Before calling this function, the caller + * should have acquired the mutex. + * @param[in] cv condition variable + * @return zero on no errors, non-zero on errors + * @see metal_condition_wait, metal_condition_broadcast + */ +static inline int metal_condition_signal(struct metal_condition *cv); + +/** + * @brief Notify all waiters. + * Before calling this function, the caller + * should have acquired the mutex. + * @param[in] cv condition variable + * @return zero on no errors, non-zero on errors + * @see metal_condition_wait, metal_condition_signal + */ +static inline int metal_condition_broadcast(struct metal_condition *cv); + +/** + * @brief Block until the condition variable is notified. + * Before calling this function, the caller should + * have acquired the mutex. + * @param[in] cv condition variable + * @param[in] m mutex + * @return 0 on success, non-zero on failure. + * @see metal_condition_signal + */ +int metal_condition_wait(struct metal_condition *cv, metal_mutex_t *m); + +#include + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_CONDITION__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/config.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/config.h new file mode 100644 index 000000000..ceb5ac9ac --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/config.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file config.h + * @brief Generated configuration settings for libmetal. + */ + +#ifndef __METAL_CONFIG__H__ +#define __METAL_CONFIG__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Library major version number. */ +#define METAL_VER_MAJOR 0 + +/** Library minor version number. */ +#define METAL_VER_MINOR 1 + +/** Library patch level. */ +#define METAL_VER_PATCH 0 + +/** Library version string. */ +#define METAL_VER "0.1.0" + +/** System type (linux, generic, ...). */ +#define METAL_SYSTEM "xizi" +#define METAL_SYSTEM_FREERTOS + +/** Processor type (arm, x86_64, ...). */ +#define METAL_PROCESSOR "arm" +#define METAL_PROCESSOR_ARM + +/** Machine type (zynq, zynqmp, ...). */ +#define METAL_MACHINE "generic" +#define METAL_MACHINE_GENERIC + +#if !defined(__CC_ARM) +#define HAVE_STDATOMIC_H +#endif +#if (defined(__GNUC__) && !defined(__CC_ARM__)) || !defined(__ICCARM__) +#define HAVE_FUTEX_H +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_CONFIG__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/cpu.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/cpu.h new file mode 100644 index 000000000..5537afba4 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/cpu.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file cpu.h + * @brief CPU primitives for libmetal. + */ + +#ifndef __METAL_CPU__H__ +#define __METAL_CPU__H__ + +# include + +#endif /* __METAL_CPU__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/device.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/device.h new file mode 100644 index 000000000..c78b50dd1 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/device.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file device.h + * @brief Bus abstraction for libmetal. + */ + +#ifndef __METAL_BUS__H__ +#define __METAL_BUS__H__ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup device Bus Abstraction + * @{ */ + +#ifndef METAL_MAX_DEVICE_REGIONS +#define METAL_MAX_DEVICE_REGIONS 32 +#endif + +struct metal_bus; +struct metal_device; + +/** Bus operations. */ +struct metal_bus_ops { + void (*bus_close)(struct metal_bus *bus); + int (*dev_open)(struct metal_bus *bus, + const char *dev_name, + struct metal_device **device); + void (*dev_close)(struct metal_bus *bus, + struct metal_device *device); + void (*dev_irq_ack)(struct metal_bus *bus, + struct metal_device *device, + int irq); + int (*dev_dma_map)(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out); + void (*dev_dma_unmap)(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg, + int nents); +}; + +/** Libmetal bus structure. */ +struct metal_bus { + const char *name; + struct metal_bus_ops ops; + struct metal_list devices; + struct metal_list node; +}; + +/** Libmetal generic bus. */ +extern struct metal_bus metal_generic_bus; + +/** Libmetal device structure. */ +struct metal_device { + const char *name; /**< Device name */ + struct metal_bus *bus; /**< Bus that contains device */ + unsigned num_regions; /**< Number of I/O regions in + device */ + struct metal_io_region regions[METAL_MAX_DEVICE_REGIONS]; /**< Array of + I/O regions in device*/ + struct metal_list node; /**< Node on bus' list of devices */ + int irq_num; /**< Number of IRQs per device */ + void *irq_info; /**< IRQ ID */ +}; + +/** + * @brief Register a libmetal bus. + * @param[in] bus Pre-initialized bus structure. + * @return 0 on success, or -errno on failure. + */ +extern int metal_bus_register(struct metal_bus *bus); + +/** + * @brief Unregister a libmetal bus. + * @param[in] bus Pre-registered bus structure. + * @return 0 on success, or -errno on failure. + */ +extern int metal_bus_unregister(struct metal_bus *bus); + +/** + * @brief Find a libmetal bus by name. + * @param[in] name Bus name. + * @param[out] bus Returned bus handle. + * @return 0 on success, or -errno on failure. + */ +extern int metal_bus_find(const char *name, struct metal_bus **bus); + +/** + * @brief Statically register a generic libmetal device. + * + * In non-Linux systems, devices are always required to be statically + * registered at application initialization. + * In Linux system, devices can be dynamically opened via sysfs or libfdt based + * enumeration at runtime. + * This interface is used for static registration of devices. Subsequent calls + * to metal_device_open() look up in this list of pre-registered devices on the + * "generic" bus. + * "generic" bus is used on non-Linux system to group the memory mapped devices. + * + * @param[in] device Generic device. + * @return 0 on success, or -errno on failure. + */ +extern int metal_register_generic_device(struct metal_device *device); + +/** + * @brief Open a libmetal device by name. + * @param[in] bus_name Bus name. + * @param[in] dev_name Device name. + * @param[out] device Returned device handle. + * @return 0 on success, or -errno on failure. + */ +extern int metal_device_open(const char *bus_name, const char *dev_name, + struct metal_device **device); + +/** + * @brief Close a libmetal device. + * @param[in] device Device handle. + */ +extern void metal_device_close(struct metal_device *device); + +/** + * @brief Get an I/O region accessor for a device region. + * + * @param[in] device Device handle. + * @param[in] index Region index. + * @return I/O accessor handle, or NULL on failure. + */ +static inline struct metal_io_region * +metal_device_io_region(struct metal_device *device, unsigned index) +{ + return (index < device->num_regions + ? &device->regions[index] + : NULL); +} + +/** @} */ + +#ifdef METAL_INTERNAL +extern int metal_generic_dev_sys_open(struct metal_device *dev); +extern int metal_generic_dev_open(struct metal_bus *bus, const char *dev_name, + struct metal_device **device); +extern int metal_generic_dev_dma_map(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out); +extern void metal_generic_dev_dma_unmap(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg, + int nents); +#endif /* METAL_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_BUS__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/dma.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/dma.h new file mode 100644 index 000000000..1c8e8b11c --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/dma.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file dma.h + * @brief DMA primitives for libmetal. + */ + +#ifndef __METAL_DMA__H__ +#define __METAL_DMA__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup dma DMA Interfaces + * @{ */ + +#include +#include + +#define METAL_DMA_DEV_R 1 /**< DMA direction, device read */ +#define METAL_DMA_DEV_W 2 /**< DMA direction, device write */ +#define METAL_DMA_DEV_WR 3 /**< DMA direction, device read/write */ + +/** + * @brief scatter/gather list element structure + */ +struct metal_sg { + void *virt; /**< CPU virtual address */ + struct metal_io_region *io; /**< IO region */ + int len; /**< length */ +}; + +struct metal_device; + +/** + * @brief Map memory for DMA transaction. + * After the memory is DMA mapped, the memory should be + * accessed by the DMA device but not the CPU. + * + * @param[in] dev DMA device + * @param[in] dir DMA direction + * @param[in] sg_in sg list of memory to map + * @param[in] nents_in number of sg list entries of memory to map + * @param[out] sg_out sg list of mapped memory + * @return number of mapped sg entries, -error on failure. + */ +int metal_dma_map(struct metal_device *dev, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out); + +/** + * @brief Unmap DMA memory + * After the memory is DMA unmapped, the memory should + * be accessed by the CPU but not the DMA device. + * + * @param[in] dev DMA device + * @param[in] dir DMA direction + * @param[in] sg sg list of mapped DMA memory + * @param[in] nents number of sg list entries of DMA memory + */ +void metal_dma_unmap(struct metal_device *dev, + uint32_t dir, + struct metal_sg *sg, + int nents); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_DMA__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/errno.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/errno.h new file mode 100644 index 000000000..9aae86d48 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/errno.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * Copyright (c) 2019, eForce.Co.Ltd + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file errno.h + */ + +#ifndef __METAL_ERRNO__H__ +#define __METAL_ERRNO__H__ + +#if defined(__CC_ARM) && defined(__GNUC__) +# include +#elif defined(__GNUC__) +# include +#elif defined(__ICCARM__) +# include +#endif + +#endif /* __METAL_ERRNO_H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/io.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/io.h new file mode 100644 index 000000000..c26f0ccf9 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/io.h @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2015 - 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file io.h + * @brief I/O access primitives for libmetal. + */ + +#ifndef __METAL_IO__H__ +#define __METAL_IO__H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup io IO Interfaces + * @{ */ + +#ifdef __MICROBLAZE__ +#define NO_ATOMIC_64_SUPPORT +#endif + +struct metal_io_region; + +/** Generic I/O operations. */ +struct metal_io_ops { + uint64_t (*read)(struct metal_io_region *io, + unsigned long offset, + memory_order order, + int width); + void (*write)(struct metal_io_region *io, + unsigned long offset, + uint64_t value, + memory_order order, + int width); + int (*block_read)(struct metal_io_region *io, + unsigned long offset, + void *restrict dst, + memory_order order, + int len); + int (*block_write)(struct metal_io_region *io, + unsigned long offset, + const void *restrict src, + memory_order order, + int len); + void (*block_set)(struct metal_io_region *io, + unsigned long offset, + unsigned char value, + memory_order order, + int len); + void (*close)(struct metal_io_region *io); +}; + +/** Libmetal I/O region structure. */ +struct metal_io_region { + void *virt; /**< base virtual address */ + const metal_phys_addr_t *physmap; /**< table of base physical address + of each of the pages in the I/O + region */ + size_t size; /**< size of the I/O region */ + unsigned long page_shift; /**< page shift of I/O region */ + metal_phys_addr_t page_mask; /**< page mask of I/O region */ + unsigned int mem_flags; /**< memory attribute of the + I/O region */ + struct metal_io_ops ops; /**< I/O region operations */ +}; + +/** + * @brief Open a libmetal I/O region. + * + * @param[in, out] io I/O region handle. + * @param[in] virt Virtual address of region. + * @param[in] physmap Array of physical addresses per page. + * @param[in] size Size of region. + * @param[in] page_shift Log2 of page size (-1 for single page). + * @param[in] mem_flags Memory flags + * @param[in] ops ops + */ +void +metal_io_init(struct metal_io_region *io, void *virt, + const metal_phys_addr_t *physmap, size_t size, + unsigned page_shift, unsigned int mem_flags, + const struct metal_io_ops *ops); + +/** + * @brief Close a libmetal shared memory segment. + * @param[in] io I/O region handle. + */ +static inline void metal_io_finish(struct metal_io_region *io) +{ + if (io->ops.close) + (*io->ops.close)(io); + memset(io, 0, sizeof(*io)); +} + +/** + * @brief Get size of I/O region. + * + * @param[in] io I/O region handle. + * @return Size of I/O region. + */ +static inline size_t metal_io_region_size(struct metal_io_region *io) +{ + return io->size; +} + +/** + * @brief Get virtual address for a given offset into the I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into shared memory segment. + * @return NULL if offset is out of range, or pointer to offset. + */ +static inline void * +metal_io_virt(struct metal_io_region *io, unsigned long offset) +{ + return (io->virt != METAL_BAD_VA && offset <= io->size + ? (uint8_t *)io->virt + offset + : NULL); +} + +/** + * @brief Convert a virtual address to offset within I/O region. + * @param[in] io I/O region handle. + * @param[in] virt Virtual address within segment. + * @return METAL_BAD_OFFSET if out of range, or offset. + */ +static inline unsigned long +metal_io_virt_to_offset(struct metal_io_region *io, void *virt) +{ + size_t offset = (uint8_t *)virt - (uint8_t *)io->virt; + return (offset < io->size ? offset : METAL_BAD_OFFSET); +} + +/** + * @brief Get physical address for a given offset into the I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into shared memory segment. + * @return METAL_BAD_PHYS if offset is out of range, or physical address + * of offset. + */ +static inline metal_phys_addr_t +metal_io_phys(struct metal_io_region *io, unsigned long offset) +{ + unsigned long page = (io->page_shift >= + sizeof(offset) * CHAR_BIT ? + 0 : offset >> io->page_shift); + return (io->physmap != NULL && offset <= io->size + ? io->physmap[page] + (offset & io->page_mask) + : METAL_BAD_PHYS); +} + +/** + * @brief Convert a physical address to offset within I/O region. + * @param[in] io I/O region handle. + * @param[in] phys Physical address within segment. + * @return METAL_BAD_OFFSET if out of range, or offset. + */ +static inline unsigned long +metal_io_phys_to_offset(struct metal_io_region *io, metal_phys_addr_t phys) +{ + unsigned long offset = + (io->page_mask == (metal_phys_addr_t)(-1) ? + phys - io->physmap[0] : phys & io->page_mask); + do { + if (metal_io_phys(io, offset) == phys) + return offset; + offset += io->page_mask + 1; + } while (offset < io->size); + return METAL_BAD_OFFSET; +} + +/** + * @brief Convert a physical address to virtual address. + * @param[in] io Shared memory segment handle. + * @param[in] phys Physical address within segment. + * @return NULL if out of range, or corresponding virtual address. + */ +static inline void * +metal_io_phys_to_virt(struct metal_io_region *io, metal_phys_addr_t phys) +{ + return metal_io_virt(io, metal_io_phys_to_offset(io, phys)); +} + +/** + * @brief Convert a virtual address to physical address. + * @param[in] io Shared memory segment handle. + * @param[in] virt Virtual address within segment. + * @return METAL_BAD_PHYS if out of range, or corresponding + * physical address. + */ +static inline metal_phys_addr_t +metal_io_virt_to_phys(struct metal_io_region *io, void *virt) +{ + return metal_io_phys(io, metal_io_virt_to_offset(io, virt)); +} + +/** + * @brief Read a value from an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] order Memory ordering. + * @param[in] width Width in bytes of datatype to read. This must be 1, 2, + * 4, or 8, and a compile time constant for this function + * to inline cleanly. + * @return Value. + */ +static inline uint64_t +metal_io_read(struct metal_io_region *io, unsigned long offset, + memory_order order, int width) +{ + void *ptr = metal_io_virt(io, offset); + + if (io->ops.read) + return (*io->ops.read)(io, offset, order, width); + else if (ptr && sizeof(atomic_uchar) == width) + return atomic_load_explicit((atomic_uchar *)ptr, order); + else if (ptr && sizeof(atomic_ushort) == width) + return atomic_load_explicit((atomic_ushort *)ptr, order); + else if (ptr && sizeof(atomic_uint) == width) + return atomic_load_explicit((atomic_uint *)ptr, order); + else if (ptr && sizeof(atomic_ulong) == width) + return atomic_load_explicit((atomic_ulong *)ptr, order); +#ifndef NO_ATOMIC_64_SUPPORT + else if (ptr && sizeof(atomic_ullong) == width) + return atomic_load_explicit((atomic_ullong *)ptr, order); +#endif + metal_assert(0); + return 0; /* quiet compiler */ +} + +/** + * @brief Write a value into an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] value Value to write. + * @param[in] order Memory ordering. + * @param[in] width Width in bytes of datatype to read. This must be 1, 2, + * 4, or 8, and a compile time constant for this function + * to inline cleanly. + */ +static inline void +metal_io_write(struct metal_io_region *io, unsigned long offset, + uint64_t value, memory_order order, int width) +{ + void *ptr = metal_io_virt(io, offset); + if (io->ops.write) + (*io->ops.write)(io, offset, value, order, width); + else if (ptr && sizeof(atomic_uchar) == width) + atomic_store_explicit((atomic_uchar *)ptr, value, order); + else if (ptr && sizeof(atomic_ushort) == width) + atomic_store_explicit((atomic_ushort *)ptr, value, order); + else if (ptr && sizeof(atomic_uint) == width) + atomic_store_explicit((atomic_uint *)ptr, value, order); + else if (ptr && sizeof(atomic_ulong) == width) + atomic_store_explicit((atomic_ulong *)ptr, value, order); +#ifndef NO_ATOMIC_64_SUPPORT + else if (ptr && sizeof(atomic_ullong) == width) + atomic_store_explicit((atomic_ullong *)ptr, value, order); +#endif + else + metal_assert (0); +} + +#define metal_io_read8_explicit(_io, _ofs, _order) \ + metal_io_read((_io), (_ofs), (_order), 1) +#define metal_io_read8(_io, _ofs) \ + metal_io_read((_io), (_ofs), memory_order_seq_cst, 1) +#define metal_io_write8_explicit(_io, _ofs, _val, _order) \ + metal_io_write((_io), (_ofs), (_val), (_order), 1) +#define metal_io_write8(_io, _ofs, _val) \ + metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 1) + +#define metal_io_read16_explicit(_io, _ofs, _order) \ + metal_io_read((_io), (_ofs), (_order), 2) +#define metal_io_read16(_io, _ofs) \ + metal_io_read((_io), (_ofs), memory_order_seq_cst, 2) +#define metal_io_write16_explicit(_io, _ofs, _val, _order) \ + metal_io_write((_io), (_ofs), (_val), (_order), 2) +#define metal_io_write16(_io, _ofs, _val) \ + metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 2) + +#define metal_io_read32_explicit(_io, _ofs, _order) \ + metal_io_read((_io), (_ofs), (_order), 4) +#define metal_io_read32(_io, _ofs) \ + metal_io_read((_io), (_ofs), memory_order_seq_cst, 4) +#define metal_io_write32_explicit(_io, _ofs, _val, _order) \ + metal_io_write((_io), (_ofs), (_val), (_order), 4) +#define metal_io_write32(_io, _ofs, _val) \ + metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 4) + +#define metal_io_read64_explicit(_io, _ofs, _order) \ + metal_io_read((_io), (_ofs), (_order), 8) +#define metal_io_read64(_io, _ofs) \ + metal_io_read((_io), (_ofs), memory_order_seq_cst, 8) +#define metal_io_write64_explicit(_io, _ofs, _val, _order) \ + metal_io_write((_io), (_ofs), (_val), (_order), 8) +#define metal_io_write64(_io, _ofs, _val) \ + metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 8) + +/** + * @brief Read a block from an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] dst destination to store the read data. + * @param[in] len length in bytes to read. + * @return On success, number of bytes read. On failure, negative value + */ +int metal_io_block_read(struct metal_io_region *io, unsigned long offset, + void *restrict dst, int len); + +/** + * @brief Write a block into an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] src source to write. + * @param[in] len length in bytes to write. + * @return On success, number of bytes written. On failure, negative value + */ +int metal_io_block_write(struct metal_io_region *io, unsigned long offset, + const void *restrict src, int len); + +/** + * @brief fill a block of an I/O region. + * @param[in] io I/O region handle. + * @param[in] offset Offset into I/O region. + * @param[in] value value to fill into the block + * @param[in] len length in bytes to fill. + * @return On success, number of bytes filled. On failure, negative value + */ +int metal_io_block_set(struct metal_io_region *io, unsigned long offset, + unsigned char value, int len); + +#include + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_IO__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/irq.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/irq.h new file mode 100644 index 000000000..2b3bd5879 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/irq.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file irq.h + * @brief Interrupt handling primitives for libmetal. + */ + +#ifndef __METAL_IRQ__H__ +#define __METAL_IRQ__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup irq Interrupt Handling Interfaces + * @{ */ + +#include + +/** IRQ handled status */ +#define METAL_IRQ_NOT_HANDLED 0 +#define METAL_IRQ_HANDLED 1 + +/** + * @brief type of interrupt handler + * @param[in] irq interrupt id + * @param[in] priv private data + * @return irq handled status + */ +typedef int (*metal_irq_handler) (int irq, void *priv); + +struct metal_device; + +/** + * @brief Register interrupt handler for driver ID/device. + * + * @param[in] irq interrupt id + * @param[in] irq_handler interrupt handler + * @param[in] dev metal device this irq belongs to (can be NULL). + * @param[in] drv_id driver id is a unique interrupt handler identifier. + * It can also be used for driver data. + * @return 0 for success, non-zero on failure + */ +int metal_irq_register(int irq, + metal_irq_handler irq_handler, + struct metal_device *dev, + void *drv_id); + +/** + * @brief Unregister interrupt handler for driver ID and/or device. + * + * If interrupt handler (hd), driver ID (drv_id) and device (dev) + * are NULL, unregister all handlers for this interrupt. + * + * If interrupt handler (hd), device (dev) or driver ID (drv_id), + * are not NULL, unregister handlers matching non NULL criterias. + * e.g: when call is made with drv_id and dev non NULL, + * all handlers matching both are unregistered. + * + * If interrupt is not found, or other criterias not matching, + * return -ENOENT + * + * @param[in] irq interrupt id + * @param[in] irq_handler interrupt handler + * @param[in] dev metal device this irq belongs to + * @param[in] drv_id driver id. It can be used for driver data. + * @return 0 for success, non-zero on failure + */ +int metal_irq_unregister(int irq, + metal_irq_handler irq_handler, + struct metal_device *dev, + void *drv_id); + +/** + * @brief disable interrupts + * @return interrupts state + */ +unsigned int metal_irq_save_disable(void); + +/** + * @brief restore interrupts to their previous state + * @param[in] flags previous interrupts state + */ +void metal_irq_restore_enable(unsigned int flags); + +/** + * @brief metal_irq_enable + * + * Enables the given interrupt + * + * @param vector - interrupt vector number + */ +void metal_irq_enable(unsigned int vector); + +/** + * @brief metal_irq_disable + * + * Disables the given interrupt + * + * @param vector - interrupt vector number + */ +void metal_irq_disable(unsigned int vector); + +#include + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_IRQ__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/list.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/list.h new file mode 100644 index 000000000..a9395ba77 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/list.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file list.h + * @brief List primitives for libmetal. + */ + +#ifndef __METAL_LIST__H__ +#define __METAL_LIST__H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup list List Primitives + * @{ */ + +struct metal_list { + struct metal_list *next, *prev; +}; + +/* + * METAL_INIT_LIST - used for initializing an list elmenet in a static struct + * or global + */ +#define METAL_INIT_LIST(name) { .next = &name, .prev = &name } +/* + * METAL_DECLARE_LIST - used for defining and initializing a global or + * static singleton list + */ +#define METAL_DECLARE_LIST(name) \ + struct metal_list name = METAL_INIT_LIST(name) + +static inline void metal_list_init(struct metal_list *list) +{ + list->next = list->prev = list; +} + +static inline void metal_list_add_before(struct metal_list *node, + struct metal_list *new_node) +{ + new_node->prev = node->prev; + new_node->next = node; + new_node->next->prev = new_node; + new_node->prev->next = new_node; +} + +static inline void metal_list_add_after(struct metal_list *node, + struct metal_list *new_node) +{ + new_node->prev = node; + new_node->next = node->next; + new_node->next->prev = new_node; + new_node->prev->next = new_node; +} + +static inline void metal_list_add_head(struct metal_list *list, + struct metal_list *node) +{ + metal_list_add_after(list, node); +} + +static inline void metal_list_add_tail(struct metal_list *list, + struct metal_list *node) +{ + metal_list_add_before(list, node); +} + +static inline int metal_list_is_empty(struct metal_list *list) +{ + return list->next == list; +} + +static inline void metal_list_del(struct metal_list *node) +{ + node->next->prev = node->prev; + node->prev->next = node->next; + node->next = node->prev = node; +} + +static inline struct metal_list *metal_list_first(struct metal_list *list) +{ + return metal_list_is_empty(list) ? NULL : list->next; +} + +#define metal_list_for_each(list, node) \ + for ((node) = (list)->next; \ + (node) != (list); \ + (node) = (node)->next) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_LIST__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/log.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/log.h new file mode 100644 index 000000000..77e6d219f --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/log.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file log.h + * @brief Logging support for libmetal. + */ + +#ifndef __METAL_METAL_LOG__H__ +#define __METAL_METAL_LOG__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup logging Library Logging Interfaces + * @{ */ + +/** Log message priority levels for libmetal. */ +enum metal_log_level { + METAL_LOG_EMERGENCY, /**< system is unusable. */ + METAL_LOG_ALERT, /**< action must be taken immediately. */ + METAL_LOG_CRITICAL, /**< critical conditions. */ + METAL_LOG_ERROR, /**< error conditions. */ + METAL_LOG_WARNING, /**< warning conditions. */ + METAL_LOG_NOTICE, /**< normal but significant condition. */ + METAL_LOG_INFO, /**< informational messages. */ + METAL_LOG_DEBUG, /**< debug-level messages. */ +}; + +/** Log message handler type. */ +typedef void (*metal_log_handler)(enum metal_log_level level, + const char *format, ...); + +/** + * @brief Set libmetal log handler. + * @param[in] handler log message handler. + * @return 0 on success, or -errno on failure. + */ +extern void metal_set_log_handler(metal_log_handler handler); + +/** + * @brief Get the current libmetal log handler. + * @return Current log handler. + */ +extern metal_log_handler metal_get_log_handler(void); + +/** + * @brief Set the level for libmetal logging. + * @param[in] level log message level. + */ +extern void metal_set_log_level(enum metal_log_level level); + +/** + * @brief Get the current level for libmetal logging. + * @return Current log level. + */ +extern enum metal_log_level metal_get_log_level(void); + +/** + * @brief Default libmetal log handler. This handler prints libmetal log + * mesages to stderr. + * @param[in] level log message level. + * @param[in] format log message format string. + * @return 0 on success, or -errno on failure. + */ +extern void metal_default_log_handler(enum metal_log_level level, + const char *format, ...); + + +/** + * Emit a log message if the log level permits. + * + * @param level Log level. + * @param ... Format string and arguments. + */ +#define metal_log(level, ...) \ + ((level <= _metal.common.log_level && _metal.common.log_handler) \ + ? (void)_metal.common.log_handler(level, __VA_ARGS__) \ + : (void)0) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#include + +#endif /* __METAL_METAL_LOG__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/mutex.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/mutex.h new file mode 100644 index 000000000..ed9df9f96 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/mutex.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file mutex.h + * @brief Mutex primitives for libmetal. + */ + +#ifndef __METAL_MUTEX__H__ +#define __METAL_MUTEX__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup mutex Mutex Interfaces + * @{ */ + +#include + +/** + * @brief Initialize a libmetal mutex. + * @param[in] mutex Mutex to initialize. + */ +static inline void metal_mutex_init(metal_mutex_t *mutex) +{ + __metal_mutex_init(mutex); +} + +/** + * @brief Deinitialize a libmetal mutex. + * @param[in] mutex Mutex to deinitialize. + */ +static inline void metal_mutex_deinit(metal_mutex_t *mutex) +{ + __metal_mutex_deinit(mutex); +} + +/** + * @brief Try to acquire a mutex + * @param[in] mutex Mutex to mutex. + * @return 0 on failure to acquire, non-zero on success. + */ +static inline int metal_mutex_try_acquire(metal_mutex_t *mutex) +{ + return __metal_mutex_try_acquire(mutex); +} + +/** + * @brief Acquire a mutex + * @param[in] mutex Mutex to mutex. + */ +static inline void metal_mutex_acquire(metal_mutex_t *mutex) +{ + __metal_mutex_acquire(mutex); +} + +/** + * @brief Release a previously acquired mutex. + * @param[in] mutex Mutex to mutex. + * @see metal_mutex_try_acquire, metal_mutex_acquire + */ +static inline void metal_mutex_release(metal_mutex_t *mutex) +{ + __metal_mutex_release(mutex); +} + +/** + * @brief Checked if a mutex has been acquired. + * @param[in] mutex mutex to check. + * @see metal_mutex_try_acquire, metal_mutex_acquire + */ +static inline int metal_mutex_is_acquired(metal_mutex_t *mutex) +{ + return __metal_mutex_is_acquired(mutex); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_MUTEX__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/processor/arm/atomic.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/processor/arm/atomic.h new file mode 100644 index 000000000..f3ad956b0 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/processor/arm/atomic.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file gcc/atomic.h + * @brief GCC specific atomic primitives for libmetal. + */ + +#ifndef __METAL_ARM_ATOMIC__H__ +#define __METAL_ARM_ATOMIC__H__ + +#endif /* __METAL_ARM_ATOMIC__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/processor/arm/cpu.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/processor/arm/cpu.h new file mode 100644 index 000000000..62af1e287 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/processor/arm/cpu.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file cpu.h + * @brief CPU specific primatives + */ + +#ifndef __METAL_ARM_CPU__H__ +#define __METAL_ARM_CPU__H__ + +#include + +#define metal_cpu_yield() YieldOsAssign() + +#endif /* __METAL_ARM_CPU__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/shmem.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/shmem.h new file mode 100644 index 000000000..19f282caf --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/shmem.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file shmem.h + * @brief Shared memory primitives for libmetal. + */ + +#ifndef __METAL_SHMEM__H__ +#define __METAL_SHMEM__H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup shmem Shared Memory Interfaces + * @{ */ + +/** Generic shared memory data structure. */ +struct metal_generic_shmem { + const char *name; + struct metal_io_region io; + struct metal_list node; +}; + +/** + * @brief Open a libmetal shared memory segment. + * + * Open a shared memory segment. + * + * @param[in] name Name of segment to open. + * @param[in] size Size of segment. + * @param[out] io I/O region handle, if successful. + * @return 0 on success, or -errno on failure. + * + * @see metal_shmem_create + */ +extern int metal_shmem_open(const char *name, size_t size, + struct metal_io_region **io); + +/** + * @brief Statically register a generic shared memory region. + * + * Shared memory regions may be statically registered at application + * initialization, or may be dynamically opened. This interface is used for + * static registration of regions. Subsequent calls to metal_shmem_open() look + * up in this list of pre-registered regions. + * + * @param[in] shmem Generic shmem structure. + * @return 0 on success, or -errno on failure. + */ +extern int metal_shmem_register_generic(struct metal_generic_shmem *shmem); + +#ifdef METAL_INTERNAL + +/** + * @brief Open a statically registered shmem segment. + * + * This interface is meant for internal libmetal use within system specific + * shmem implementations. + * + * @param[in] name Name of segment to open. + * @param[in] size Size of segment. + * @param[out] io I/O region handle, if successful. + * @return 0 on success, or -errno on failure. + */ +int metal_shmem_open_generic(const char *name, size_t size, + struct metal_io_region **result); + +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_SHMEM__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/sleep.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/sleep.h new file mode 100644 index 000000000..1330254ba --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/sleep.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file sleep.h + * @brief Sleep primitives for libmetal. + */ + +#ifndef __METAL_SLEEP__H__ +#define __METAL_SLEEP__H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup sleep Sleep Interfaces + * @{ */ + +/** + * @brief delay in microseconds + * delay the next execution in the calling thread + * fo usec microseconds. + * + * @param[in] usec microsecond intervals + * @return 0 on success, non-zero for failures + */ +static inline int metal_sleep_usec(unsigned int usec) +{ + return __metal_sleep_usec(usec); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_SLEEP__H__ */ + diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/spinlock.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/spinlock.h new file mode 100644 index 000000000..b30fcfd1f --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/spinlock.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file spinlock.h + * @brief Spinlock primitives for libmetal. + */ + +#ifndef __METAL_SPINLOCK__H__ +#define __METAL_SPINLOCK__H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup spinlock Spinlock Interfaces + * @{ */ +struct metal_spinlock { + atomic_flag v; +}; + +/** Static metal spinlock initialization. */ +#define METAL_SPINLOCK_INIT {ATOMIC_FLAG_INIT} + +/** + * @brief Initialize a libmetal spinlock. + * @param[in] slock Spinlock to initialize. + */ +static inline void metal_spinlock_init(struct metal_spinlock *slock) +{ + atomic_flag_clear(&slock->v); +} + +/** + * @brief Acquire a spinlock. + * @param[in] slock Spinlock to acquire. + * @see metal_spinlock_release + */ +static inline void metal_spinlock_acquire(struct metal_spinlock *slock) +{ + while (atomic_flag_test_and_set(&slock->v)) { + metal_cpu_yield(); + } +} + +/** + * @brief Release a previously acquired spinlock. + * @param[in] slock Spinlock to release. + * @see metal_spinlock_acquire + */ +static inline void metal_spinlock_release(struct metal_spinlock *slock) +{ + atomic_flag_clear(&slock->v); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_SPINLOCK__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/sys.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/sys.h new file mode 100644 index 000000000..adbd26a60 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/sys.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file sys.h + * @brief System primitives for libmetal. + * @brief Top level include internal to libmetal library code. + */ + +#ifndef __METAL_SYS__H__ +#define __METAL_SYS__H__ + +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup system Top Level Interfaces + * @{ */ + +/** Physical address type. */ +typedef unsigned long metal_phys_addr_t; + +/** Interrupt request number. */ +typedef int metal_irq_t; + +/** Bad offset into shared memory or I/O region. */ +#define METAL_BAD_OFFSET ((unsigned long)-1) + +/** Bad physical address value. */ +#define METAL_BAD_PHYS ((metal_phys_addr_t)-1) + +/** Bad virtual address value. */ +#define METAL_BAD_VA ((void *)-1) + +/** Bad IRQ. */ +#define METAL_BAD_IRQ ((metal_irq_t)-1) + +/** + * Initialization configuration for libmetal. + */ +struct metal_init_params { + + /** log message handler (defaults to stderr). */ + metal_log_handler log_handler; + + /** default log message level (defaults to emergency). */ + enum metal_log_level log_level; +}; + +/** + * System independent runtime state for libmetal. This is part of a system + * specific singleton data structure (@see _metal). + */ +struct metal_common_state { + /** Current log level. */ + enum metal_log_level log_level; + + /** Current log handler (null for none). */ + metal_log_handler log_handler; + + /** List of registered buses. */ + struct metal_list bus_list; + + /** Generic statically defined shared memory segments. */ + struct metal_list generic_shmem_list; + + /** Generic statically defined devices. */ + struct metal_list generic_device_list; +}; + +struct metal_state; + +#include + +#ifndef METAL_INIT_DEFAULTS +#define METAL_INIT_DEFAULTS \ +{ \ + .log_handler = metal_default_log_handler, \ + .log_level = METAL_LOG_INFO, \ +} +#endif + +/** System specific runtime data. */ +extern struct metal_state _metal; + +/** + * @brief Initialize libmetal. + * + * Initialize the libmetal library. + * + * @param[in] params Initialization params (@see metal_init_params). + * + * @return 0 on success, or -errno on failure. + * + * @see metal_finish + */ +extern int metal_init(const struct metal_init_params *params); + +/** + * @brief Shutdown libmetal. + * + * Shutdown the libmetal library, and release all reserved resources. + * + * @see metal_init + */ +extern void metal_finish(void); + +#ifdef METAL_INTERNAL + +/** + * @brief libmetal system initialization. + * + * This function initializes libmetal on Linux or Generic platforms. This + * involves obtaining necessary pieces of system information (sysfs mount path, + * page size, etc.). + * + * @param[in] params Initialization parameters (@see metal_init_params). + * @return 0 on success, or -errno on failure. + */ +extern int metal_sys_init(const struct metal_init_params *params); + +/** + * @brief libmetal system shutdown. + * + * This function shuts down and releases resources held by libmetal Linux or + * Generic platform layers. + * + * @see metal_sys_init + */ +extern void metal_sys_finish(void); + +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_SYS__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/alloc.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/alloc.h new file mode 100644 index 000000000..4cbe588b3 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/alloc.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/alloc.c + * @brief FreeRTOS libmetal memory allocattion definitions. + */ + +#ifndef __METAL_ALLOC__H__ +#error "Include metal/alloc.h instead of metal/xizi/alloc.h" +#endif + +#ifndef __METAL_FREERTOS_ALLOC__H__ +#define __METAL_FREERTOS_ALLOC__H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void *metal_allocate_memory(unsigned int size) +{ + return (x_malloc(size)); +} + +static inline void metal_free_memory(void *ptr) +{ + x_free(ptr); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_FREERTOS_ALLOC__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/assert.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/assert.h new file mode 100644 index 000000000..48497fe6b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/assert.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file assert.h + * @brief FreeRTOS assertion support. + */ +#ifndef __METAL_ASSERT__H__ +#error "Include metal/assert.h instead of metal/xizi/assert.h" +#endif + +#ifndef __METAL_FREERTOS_ASSERT__H__ +#define __METAL_FREERTOS_ASSERT__H__ + +#ifdef double_assert +#error recursive2 +#endif + +#define double_assert + +//#include +#include + + +#undef double_assert + +/** + * @brief Assertion macro for FreeRTOS applications. + * @param cond Condition to evaluate. + */ +#define metal_sys_assert(cond) assert(cond) + +#endif /* __METAL_FREERTOS_ASSERT__H__ */ + diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/cache.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/cache.h new file mode 100644 index 000000000..2273504b1 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/cache.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/cache.h + * @brief FreeRTOS cache operation primitives for libmetal. + */ + +#ifndef __METAL_CACHE__H__ +#error "Include metal/cache.h instead of metal/xizi/cache.h" +#endif + +#ifndef __METAL_FREERTOS_CACHE__H__ +#define __METAL_FREERTOS_CACHE__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void metal_machine_cache_flush(void *addr, unsigned int len); +extern void metal_machine_cache_invalidate(void *addr, unsigned int len); + +static inline void __metal_cache_flush(void *addr, unsigned int len) +{ + metal_machine_cache_flush(addr, len); +} + +static inline void __metal_cache_invalidate(void *addr, unsigned int len) +{ + metal_machine_cache_invalidate(addr, len); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_FREERTOS_CACHE__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/condition.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/condition.h new file mode 100644 index 000000000..e6a2ea23c --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/condition.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/condition.h + * @brief Generic condition variable primitives for libmetal. + */ + +#ifndef __METAL_CONDITION__H__ +#error "Include metal/condition.h instead of metal/xizi/condition.h" +#endif + +#ifndef __METAL_FREERTOS_CONDITION__H__ +#define __METAL_FREERTOS_CONDITION__H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct metal_condition { + metal_mutex_t *m; /**< mutex. + The condition variable is attached to + this mutex when it is waiting. + It is also used to check correctness + in case there are multiple waiters. */ + + atomic_int v; /**< condition variable value. */ +}; + +/** Static metal condition variable initialization. */ +#define METAL_CONDITION_INIT { NULL, ATOMIC_VAR_INIT(0) } + +static inline void metal_condition_init(struct metal_condition *cv) +{ + /* TODO: Implement condition variable for FreeRTOS */ + (void)cv; + return; +} + +static inline int metal_condition_signal(struct metal_condition *cv) +{ + /* TODO: Implement condition variable for FreeRTOS */ + (void)cv; + return 0; +} + +static inline int metal_condition_broadcast(struct metal_condition *cv) +{ + /* TODO: Implement condition variable for FreeRTOS */ + (void)cv; + return 0; +} + + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_FREERTOS_CONDITION__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/io.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/io.h new file mode 100644 index 000000000..f806cdcf2 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/io.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/io.h + * @brief FreeRTOS specific io definitions. + */ + +#ifndef __METAL_IO__H__ +#error "Include metal/io.h instead of metal/xizi/io.h" +#endif + +#ifndef __METAL_FREEROTS_IO__H__ +#define __METAL_FREEROTS_IO__H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef METAL_INTERNAL + +/** + * @brief memory mapping for an I/O region + */ +void metal_sys_io_mem_map(struct metal_io_region *io); + +/** + * @brief memory mapping + */ +void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa, + size_t size, unsigned int flags); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_FREEROTS_IO__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/irq.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/irq.h new file mode 100644 index 000000000..b23b24a41 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/irq.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/irq.c + * @brief FreeRTOS libmetal irq definitions. + */ + +#ifndef __METAL_IRQ__H__ +#error "Include metal/irq.h instead of metal/xizi/irq.h" +#endif + +#ifndef __METAL_FREERTOS_IRQ__H__ +#define __METAL_FREERTOS_IRQ__H__ + +#endif /* __METAL_FREERTOS_IRQ__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/log.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/log.h new file mode 100644 index 000000000..bc736cee5 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/log.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Linaro nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file freertos/log.h + * @brief FreeRTOS libmetal log handler definition. + */ + +#ifndef __METAL_METAL_LOG__H__ +#error "Include metal/log.h instead of metal/xizi/log.h" +#endif + +#ifndef __METAL_FREERTOS_LOG__H__ +#define __METAL_FREERTOS_LOG__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_FREERTOS_LOG__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/mutex.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/mutex.h new file mode 100644 index 000000000..9f592989e --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/mutex.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/mutex.h + * @brief FreeRTOS mutex primitives for libmetal. + */ + +#ifndef __METAL_MUTEX__H__ +#error "Include metal/mutex.h instead of metal/xizi/mutex.h" +#endif + +#ifndef __METAL_FREERTOS_MUTEX__H__ +#define __METAL_FREERTOS_MUTEX__H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + atomic_int v; +} metal_mutex_t; + +/* + * METAL_MUTEX_INIT - used for initializing an mutex elmenet in a static struct + * or global + */ +#define METAL_MUTEX_INIT(m) { ATOMIC_VAR_INIT(0) } +/* + * METAL_MUTEX_DEFINE - used for defining and initializing a global or + * static singleton mutex + */ +#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m) + +static inline void __metal_mutex_init(metal_mutex_t *mutex) +{ + atomic_store(&mutex->v, 0); +} + +static inline void __metal_mutex_deinit(metal_mutex_t *mutex) +{ + (void)mutex; +} + +static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex) +{ + return 1 - atomic_flag_test_and_set(&mutex->v); +} + +static inline void __metal_mutex_acquire(metal_mutex_t *mutex) +{ + while (atomic_flag_test_and_set(&mutex->v)) { + ; + } +} + +static inline void __metal_mutex_release(metal_mutex_t *mutex) +{ + atomic_flag_clear(&mutex->v); +} + +static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex) +{ + return atomic_load(&mutex->v); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_FREERTOS_MUTEX__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/rzv2/sys.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/rzv2/sys.h new file mode 100644 index 000000000..fa4a38812 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/rzv2/sys.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * Copyright (c) 2020, eForce.Co.Ltd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Xilinx nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file freertos/rzv2/sys.h + * @brief FreeRTOS Renesas RZ/V2 system primitives for libmetal. + */ + +#ifndef __METAL_FREERTOS_SYS__H__ +#error "Include metal/sys.h instead of metal/xizi/rzv2/sys.h" +#endif + +#include "bsp_api.h" + +#ifndef __METAL_FREERTOS_RZV2_SYS__H__ +#define __METAL_FREERTOS_RZV2_SYS__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define NO_ATOMIC_64_SUPPORT + +#if !defined(MAX_IRQS) +#define MAX_IRQS ((int)479U) /**< maximum number of irqs */ +#endif + +static inline void sys_irq_enable(unsigned int vector) +{ + (void)R_BSP_IrqEnable(vector); +} + +static inline void sys_irq_disable(unsigned int vector) +{ + (void)R_BSP_IrqDisable(vector); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_FREERTOS_RZV2_SYS__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/sleep.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/sleep.h new file mode 100644 index 000000000..0107f4cf1 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/sleep.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/sleep.h + * @brief FreeRTOS sleep primitives for libmetal. + */ + +#ifndef __METAL_SLEEP__H__ +#error "Include metal/sleep.h instead of metal/xizi/sleep.h" +#endif + +#ifndef __METAL_FREERTOS_SLEEP__H__ +#define __METAL_FREERTOS_SLEEP__H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static inline int __metal_sleep_usec(unsigned int usec) +{ + DelayKTask(usec); + // const TickType_t xDelay = usec / portTICK_PERIOD_MS; + // vTaskDelay(xDelay); + // return 0; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_FREERTOS_SLEEP__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/sys.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/sys.h new file mode 100644 index 000000000..3004fddf4 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/system/xizi/sys.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * Copyright (c) 2017-2020, eForce Co Ltd. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/sys.h + * @brief FreeRTOS system primitives for libmetal. + */ + +#ifndef __METAL_SYS__H__ +#error "Include metal/sys.h instead of metal/xizi/sys.h" +#endif + +#ifndef __METAL_FREERTOS_SYS__H__ +#define __METAL_FREERTOS_SYS__H__ + +#include +#include +#include +#include +#include +#include + +#include "./rzv2/sys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef METAL_MAX_DEVICE_REGIONS +#define METAL_MAX_DEVICE_REGIONS 1 +#endif + +/** Structure for FreeRTOS libmetal runtime state. */ +struct metal_state { + + /** Common (system independent) data. */ + struct metal_common_state common; +}; + +#ifdef METAL_INTERNAL + +/** + * @brief restore interrupts to state before disable_global_interrupt() + */ +void sys_irq_restore_enable(unsigned int flags); + +/** + * @brief disable all interrupts + */ +unsigned int sys_irq_save_disable(void); + +#endif /* METAL_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_FREERTOS_SYS__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/time.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/time.h new file mode 100644 index 000000000..b05e6794a --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/time.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file time.h + * @brief Time primitives for libmetal. + */ + +#ifndef __METAL_TIME__H__ +#define __METAL_TIME__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup time TIME Interfaces + * @{ */ + +#include +#include + +/** + * @brief get timestamp + * This function returns the timestampe as unsigned long long + * value. + * + * @return timestamp + */ +unsigned long long metal_get_timestamp(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_TIME__H__ */ + diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/utilities.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/utilities.h new file mode 100644 index 000000000..4a65f45c5 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/utilities.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file utilities.h + * @brief Utility routines for libmetal. + */ + +#ifndef __METAL_UTILITIES__H__ +#define __METAL_UTILITIES__H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup utilities Simple Utilities + * @{ */ + +/** Marker for unused function arguments/variables. */ +#define metal_unused(x) do { (x) = (x); } while (0) + +/** Figure out number of elements in an array. */ +#define metal_dim(x) (sizeof(x) / sizeof(x[0])) + +/** Minimum of two numbers (warning: multiple evaluation!). */ +#define metal_min(x, y) ((x) < (y) ? (x) : (y)) + +/** Maximum of two numbers (warning: multiple evaluation!). */ +#define metal_max(x, y) ((x) > (y) ? (x) : (y)) + +/** Sign of a number [-1, 0, or 1] (warning: multiple evaluation!). */ +#define metal_sign(x) ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0)) + +/** Align 'size' down to a multiple of 'align' (must be a power of two). */ +#define metal_align_down(size, align) \ + ((size) & ~((align) - 1)) + +/** Align 'size' up to a multiple of 'align' (must be a power of two). */ +#define metal_align_up(size, align) \ + metal_align_down((size) + (align) - 1, align) + +/** Divide (and round down). */ +#define metal_div_round_down(num, den) \ + ((num) / (den)) + +/** Divide (and round up). */ +#define metal_div_round_up(num, den) \ + metal_div_round_down((num) + (den) - 1, (den)) + +/** Align 'ptr' down to a multiple of 'align' (must be a power of two). */ +#define metal_ptr_align_down(ptr, align) \ + (void *)(metal_align_down((uintptr_t)(ptr), (uintptr_t)(align))) + +/** Align 'ptr' up to a multiple of 'align' (must be a power of two). */ +#define metal_ptr_align_up(ptr, align) \ + (void *)(metal_align_up((uintptr_t)(ptr), (uintptr_t)(align))) + +/** Compute offset of a field within a structure. */ +#define metal_offset_of(structure, member) \ + ((uintptr_t) &(((structure *) 0)->member)) + +/** Compute pointer to a structure given a pointer to one of its fields. */ +#define metal_container_of(ptr, structure, member) \ + (void *)((uintptr_t)(ptr) - metal_offset_of(structure, member)) + +#define METAL_BITS_PER_ULONG (8 * sizeof(unsigned long)) + +#define metal_bit(bit) (1UL << (bit)) + +#define metal_bitmap_longs(x) metal_div_round_up((x), METAL_BITS_PER_ULONG) + +static inline void metal_bitmap_set_bit(unsigned long *bitmap, int bit) +{ + bitmap[bit / METAL_BITS_PER_ULONG] |= + metal_bit(bit & (METAL_BITS_PER_ULONG - 1)); +} + +static inline int metal_bitmap_is_bit_set(unsigned long *bitmap, int bit) +{ + return ((bitmap[bit / METAL_BITS_PER_ULONG] & + metal_bit(bit & (METAL_BITS_PER_ULONG - 1))) == 0) ? 0 : 1; +} + +static inline void metal_bitmap_clear_bit(unsigned long *bitmap, int bit) +{ + bitmap[bit / METAL_BITS_PER_ULONG] &= + ~metal_bit(bit & (METAL_BITS_PER_ULONG - 1)); +} + +static inline int metal_bitmap_is_bit_clear(unsigned long *bitmap, int bit) +{ + return !metal_bitmap_is_bit_set(bitmap, bit); +} + +static inline unsigned int +metal_bitmap_next_set_bit(unsigned long *bitmap, unsigned int start, + unsigned int max) +{ + unsigned int bit; + for (bit = start; + bit < max && !metal_bitmap_is_bit_set(bitmap, bit); + bit ++) + ; + return bit; +} + +#define metal_bitmap_for_each_set_bit(bitmap, bit, max) \ + for ((bit) = metal_bitmap_next_set_bit((bitmap), 0, (max)); \ + (bit) < (max); \ + (bit) = metal_bitmap_next_set_bit((bitmap), (bit + 1), (max))) + +static inline unsigned int +metal_bitmap_next_clear_bit(unsigned long *bitmap, unsigned int start, + unsigned int max) +{ + unsigned int bit; + for (bit = start; + bit < max && !metal_bitmap_is_bit_clear(bitmap, bit); + bit ++) + ; + return bit; +} + +#define metal_bitmap_for_each_clear_bit(bitmap, bit, max) \ + for ((bit) = metal_bitmap_next_clear_bit((bitmap), 0, (max)); \ + (bit) < (max); \ + (bit) = metal_bitmap_next_clear_bit((bitmap), (bit + 1), (max))) + +static inline unsigned long metal_log2(unsigned long in) +{ + unsigned long result; + + metal_assert((in & (in - 1)) == 0); + + for (result = 0; (1UL << result) < in; result ++) + ; + return result; +} + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_UTILITIES__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/version.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/version.h new file mode 100644 index 000000000..96666b3aa --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/include/metal/version.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file version.h + * @brief Library version information for libmetal. + */ + +#ifndef __METAL_VERSION__H__ +#define __METAL_VERSION__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup versions Library Version Interfaces + * @{ */ + +/** + * @brief Library major version number. + * + * Return the major version number of the library linked into the application. + * This is required to match the value of METAL_VER_MAJOR, which is the major + * version of the library that the application was compiled against. + * + * @return Library major version number. + * @see METAL_VER_MAJOR + */ +extern int metal_ver_major(void); + +/** + * @brief Library minor version number. + * + * Return the minor version number of the library linked into the application. + * This could differ from the value of METAL_VER_MINOR, which is the minor + * version of the library that the application was compiled against. + * + * @return Library minor version number. + * @see METAL_VER_MINOR + */ +extern int metal_ver_minor(void); + +/** + * @brief Library patch level. + * + * Return the patch level of the library linked into the application. This + * could differ from the value of METAL_VER_PATCH, which is the patch level of + * the library that the application was compiled against. + * + * @return Library patch level. + * @see METAL_VER_PATCH + */ +extern int metal_ver_patch(void); + +/** + * @brief Library version string. + * + * Return the version string of the library linked into the application. This + * could differ from the value of METAL_VER, which is the version string of + * the library that the application was compiled against. + * + * @return Library version string. + * @see METAL_VER + */ +extern const char *metal_ver(void); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __METAL_VERSION__H__ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/Makefile b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/Makefile new file mode 100644 index 000000000..776a3c566 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/Makefile @@ -0,0 +1,5 @@ +SRC_DIR := system/xizi + +SRC_FILES := $(wildcard *.c) + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/device.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/device.c new file mode 100644 index 000000000..3978ae101 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/device.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * Copyright (c) 2020, eForce.Co.Ltd + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include + +int metal_bus_register(struct metal_bus *bus) +{ + if (!bus || !bus->name || !strlen(bus->name)) + return -EINVAL; + if (metal_bus_find(bus->name, NULL) == 0) + return -EEXIST; + metal_list_init(&bus->devices); + metal_list_add_tail(&_metal.common.bus_list, &bus->node); + metal_log(METAL_LOG_DEBUG, "registered %s bus\n", bus->name); + return 0; +} + +int metal_bus_unregister(struct metal_bus *bus) +{ + metal_list_del(&bus->node); + if (bus->ops.bus_close) + bus->ops.bus_close(bus); + metal_log(METAL_LOG_DEBUG, "unregistered %s bus\n", bus->name); + return 0; +} + +int metal_bus_find(const char *name, struct metal_bus **result) +{ + struct metal_list *node; + struct metal_bus *bus; + + metal_list_for_each(&_metal.common.bus_list, node) { + bus = metal_container_of(node, struct metal_bus, node); + if (strcmp(bus->name, name) != 0) + continue; + if (result) + *result = bus; + return 0; + } + return -ENOENT; +} + +int metal_device_open(const char *bus_name, const char *dev_name, + struct metal_device **device) +{ + struct metal_bus *bus; + int error; + + if (!bus_name || !strlen(bus_name) || + !dev_name || !strlen(dev_name) || + !device) + return -EINVAL; + + error = metal_bus_find(bus_name, &bus); + if (error) + return error; + + if (!bus->ops.dev_open) + return -ENODEV; + + error = (*bus->ops.dev_open)(bus, dev_name, device); + if (error) + return error; + + return 0; +} + +void metal_device_close(struct metal_device *device) +{ + metal_assert(device && device->bus); + if (device->bus->ops.dev_close) + device->bus->ops.dev_close(device->bus, device); +} + +int metal_register_generic_device(struct metal_device *device) +{ + if (!device->name || !strlen(device->name) || + device->num_regions > METAL_MAX_DEVICE_REGIONS) + return -EINVAL; + + device->bus = &metal_generic_bus; + metal_list_add_tail(&_metal.common.generic_device_list, + &device->node); + return 0; +} + +int metal_generic_dev_open(struct metal_bus *bus, const char *dev_name, + struct metal_device **device) +{ + struct metal_list *node; + struct metal_device *dev; + + (void)bus; + + metal_list_for_each(&_metal.common.generic_device_list, node) { + dev = metal_container_of(node, struct metal_device, node); + if (strcmp(dev->name, dev_name) != 0) + continue; + *device = dev; + return metal_generic_dev_sys_open(dev); + } + + return -ENODEV; +} + +int metal_generic_dev_dma_map(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out) +{ + (void)bus; + (void)device; + int i; + + if (sg_out != sg_in) + memcpy(sg_out, sg_in, nents_in*(sizeof(struct metal_sg))); + for (i = 0; i < nents_in; i++) { + if (dir == METAL_DMA_DEV_W) { + metal_cache_flush(sg_out[i].virt, sg_out[i].len); + } + metal_cache_invalidate(sg_out[i].virt, sg_out[i].len); + } + + return nents_in; +} + +void metal_generic_dev_dma_unmap(struct metal_bus *bus, + struct metal_device *device, + uint32_t dir, + struct metal_sg *sg, + int nents) +{ + (void)bus; + (void)device; + (void)dir; + int i; + + for (i = 0; i < nents; i++) { + metal_cache_invalidate(sg[i].virt, sg[i].len); + } +} + +struct metal_bus metal_weak metal_generic_bus = { + .name = "generic", + .ops = { + .bus_close = NULL, + .dev_open = metal_generic_dev_open, + .dev_close = NULL, + .dev_irq_ack = NULL, + .dev_dma_map = metal_generic_dev_dma_map, + .dev_dma_unmap = metal_generic_dev_dma_unmap, + }, +}; diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/dma.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/dma.c new file mode 100644 index 000000000..5cdd3726b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/dma.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * Copyright (c) 2020, eForce.Co.Ltd + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +//#include +#include +#include +#include +#include +#include + +int metal_dma_map(struct metal_device *dev, + uint32_t dir, + struct metal_sg *sg_in, + int nents_in, + struct metal_sg *sg_out) +{ + int nents_out; + + if (!dev || !sg_in || !sg_out) + return -EINVAL; + if (!dev->bus->ops.dev_dma_map) + return -ENODEV; + + /* memory barrier */ + if (dir == METAL_DMA_DEV_R) + /* If it is device read, apply memory write fence. */ + atomic_thread_fence(memory_order_release); + else + /* If it is device write or device r/w, + apply memory r/w fence. */ + atomic_thread_fence(memory_order_acq_rel); + nents_out = dev->bus->ops.dev_dma_map(dev->bus, + dev, dir, sg_in, nents_in, sg_out); + return nents_out; +} + +void metal_dma_unmap(struct metal_device *dev, + uint32_t dir, + struct metal_sg *sg, + int nents) +{ + /* memory barrier */ + if (dir == METAL_DMA_DEV_R) + /* If it is device read, apply memory write fence. */ + atomic_thread_fence(memory_order_release); + else + /* If it is device write or device r/w, + apply memory r/w fence. */ + atomic_thread_fence(memory_order_acq_rel); + + if (!dev || !dev->bus->ops.dev_dma_unmap || !sg) + return; + dev->bus->ops.dev_dma_unmap(dev->bus, + dev, dir, sg, nents); +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/init.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/init.c new file mode 100644 index 000000000..33e5124dc --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/init.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +int metal_init(const struct metal_init_params *params) +{ + int error = 0; + + memset(&_metal, 0, sizeof(_metal)); + + _metal.common.log_handler = params->log_handler; + _metal.common.log_level = params->log_level; + + metal_list_init(&_metal.common.bus_list); + metal_list_init(&_metal.common.generic_shmem_list); + metal_list_init(&_metal.common.generic_device_list); + + error = metal_sys_init(params); + if (error) + return error; + + return error; +} + +void metal_finish(void) +{ + metal_sys_finish(); + memset(&_metal, 0, sizeof(_metal)); +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/io.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/io.c new file mode 100644 index 000000000..b8cac65d5 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/io.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * Copyright (c) 2020, eForce.Co.Ltd + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +//#include +#include +#include +#include + +void metal_io_init(struct metal_io_region *io, void *virt, + const metal_phys_addr_t *physmap, size_t size, + unsigned page_shift, unsigned int mem_flags, + const struct metal_io_ops *ops) +{ + const struct metal_io_ops nops = {NULL, NULL, NULL, NULL, NULL, NULL}; + + io->virt = virt; + io->physmap = physmap; + io->size = size; + io->page_shift = page_shift; + if (page_shift >= sizeof(io->page_mask) * CHAR_BIT) + /* avoid overflow */ + io->page_mask = -1UL; + else + io->page_mask = (1UL << page_shift) - 1UL; + io->mem_flags = mem_flags; + io->ops = ops ? *ops : nops; + metal_sys_io_mem_map(io); +} + +int metal_io_block_read(struct metal_io_region *io, unsigned long offset, + void *restrict dst, int len) +{ + unsigned char *ptr = metal_io_virt(io, offset); + unsigned char *dest = dst; + int retlen; + + if (offset > io->size) + return -ERANGE; + if ((offset + len) > io->size) + len = io->size - offset; + retlen = len; + if (io->ops.block_read) { + retlen = (*io->ops.block_read)( + io, offset, dst, memory_order_seq_cst, len); + } else { + atomic_thread_fence(memory_order_seq_cst); + while ( len && ( + ((uintptr_t)dest % sizeof(int)) || + ((uintptr_t)ptr % sizeof(int)))) { + *(unsigned char *)dest = + *(const unsigned char *)ptr; + dest++; + ptr++; + len--; + } + for (; len >= (int)sizeof(int); dest += sizeof(int), + ptr += sizeof(int), + len -= sizeof(int)) + *(unsigned int *)dest = *(const unsigned int *)ptr; + for (; len != 0; dest++, ptr++, len--) + *(unsigned char *)dest = + *(const unsigned char *)ptr; + } + return retlen; +} + +int metal_io_block_write(struct metal_io_region *io, unsigned long offset, + const void *restrict src, int len) +{ + unsigned char *ptr = metal_io_virt(io, offset); + const unsigned char *source = src; + int retlen; + + if (offset > io->size) + return -ERANGE; + if ((offset + len) > io->size) + len = io->size - offset; + retlen = len; + if (io->ops.block_write) { + retlen = (*io->ops.block_write)( + io, offset, src, memory_order_seq_cst, len); + } else { + while ( len && ( + ((uintptr_t)ptr % sizeof(int)) || + ((uintptr_t)source % sizeof(int)))) { + *(unsigned char *)ptr = + *(const unsigned char *)source; + ptr++; + source++; + len--; + } + for (; len >= (int)sizeof(int); ptr += sizeof(int), + source += sizeof(int), + len -= sizeof(int)) + *(unsigned int *)ptr = *(const unsigned int *)source; + for (; len != 0; ptr++, source++, len--) + *(unsigned char *)ptr = + *(const unsigned char *)source; + atomic_thread_fence(memory_order_seq_cst); + } + return retlen; +} + +int metal_io_block_set(struct metal_io_region *io, unsigned long offset, + unsigned char value, int len) +{ + unsigned char *ptr = metal_io_virt(io, offset); + int retlen = len; + + if (offset > io->size) + return -ERANGE; + if ((offset + len) > io->size) + len = io->size - offset; + retlen = len; + if (io->ops.block_set) { + (*io->ops.block_set)( + io, offset, value, memory_order_seq_cst, len); + } else { + unsigned int cint = value; + unsigned int i; + + for (i = 1; i < sizeof(int); i++) + cint |= ((unsigned int)value << (8 * i)); + + for (; len && ((uintptr_t)ptr % sizeof(int)); ptr++, len--) + *(unsigned char *)ptr = (unsigned char) value; + for (; len >= (int)sizeof(int); ptr += sizeof(int), + len -= sizeof(int)) + *(unsigned int *)ptr = cint; + for (; len != 0; ptr++, len--) + *(unsigned char *)ptr = (unsigned char) value; + atomic_thread_fence(memory_order_seq_cst); + } + return retlen; +} + diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/log.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/log.c new file mode 100644 index 000000000..1549ff914 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/log.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +void metal_default_log_handler(enum metal_log_level level, + const char *format, ...) +{ +#ifdef DEFAULT_LOGGER_ON + 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; + + fprintf(stderr, "%s%s", level_strs[level], msg); +#else + (void)level; + (void)format; +#endif +} + +void metal_set_log_handler(metal_log_handler handler) +{ + _metal.common.log_handler = handler; +} + +metal_log_handler metal_get_log_handler(void) +{ + return _metal.common.log_handler; +} + +void metal_set_log_level(enum metal_log_level level) +{ + _metal.common.log_level = level; +} + +enum metal_log_level metal_get_log_level(void) +{ + return _metal.common.log_level; +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/shmem.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/shmem.c new file mode 100644 index 000000000..1a6875d2f --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/shmem.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * Copyright (c) 2020, eForce.Co.Ltd + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file generic/shmem.c + * @brief Generic libmetal shared memory handling. + */ + +#include +//#include +#include +#include +#include +#include + +int metal_shmem_register_generic(struct metal_generic_shmem *shmem) +{ + /* Make sure that we can be found. */ + metal_assert(shmem->name && strlen(shmem->name) != 0); + + /* Statically registered shmem regions cannot have a destructor. */ + metal_assert(!shmem->io.ops.close); + + metal_list_add_tail(&_metal.common.generic_shmem_list, + &shmem->node); + return 0; +} + +int metal_shmem_open_generic(const char *name, size_t size, + struct metal_io_region **result) +{ + struct metal_generic_shmem *shmem; + struct metal_list *node; + + metal_list_for_each(&_metal.common.generic_shmem_list, node) { + shmem = metal_container_of(node, struct metal_generic_shmem, node); + if (strcmp(shmem->name, name) != 0) + continue; + if (size > metal_io_region_size(&shmem->io)) + continue; + *result = &shmem->io; + return 0; + } + + return -ENOENT; +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/Makefile b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/Makefile new file mode 100644 index 000000000..9409b9c72 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/Makefile @@ -0,0 +1,5 @@ +SRC_DIR := rzv2 + +SRC_FILES := $(wildcard *.c) + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/condition.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/condition.c new file mode 100644 index 000000000..75d8ef7e1 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/condition.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Xilinx nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file generic/condition.c + * @brief Generic libmetal condition variable handling. + */ + +#include "metal/condition.h" + +int metal_condition_wait(struct metal_condition *cv, + metal_mutex_t *m) +{ + /* TODO: Implement condition variable for FreeRTOS */ + (void)cv; + (void)m; + return 0; +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/device.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/device.c new file mode 100644 index 000000000..34c67de63 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/device.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved. + * Copyright (c) 2018, eForce Co,Ltd. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/device.c + * @brief Generic libmetal device operations. + */ + +#include +#include +#include +#include + +int metal_generic_dev_sys_open(struct metal_device *dev) +{ + struct metal_io_region *io; + unsigned i; + + /* map I/O memory regions */ + for (i = 0; i < dev->num_regions; i++) { + io = &dev->regions[i]; + if (!io->size) + break; + metal_sys_io_mem_map(io); + } + + return 0; +} + diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/init.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/init.c new file mode 100644 index 000000000..7507bd0ca --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/init.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/init.c + * @brief FreeRTOS libmetal initialization. + */ + +#include +#include +#include + +struct metal_state _metal; + +int metal_sys_init(const struct metal_init_params *params) +{ + metal_unused(params); + metal_bus_register(&metal_generic_bus); + return 0; +} + +void metal_sys_finish(void) +{ + metal_bus_unregister(&metal_generic_bus); +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/io.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/io.c new file mode 100644 index 000000000..057e5a834 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/io.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/io.c + * @brief FreeRTOS libmetal io operations + */ + +#include + +void metal_sys_io_mem_map(struct metal_io_region *io) +{ + unsigned long p; + size_t psize; + void *va; + + va = io->virt; + psize = io->size; + if (psize) { + if (psize >> io->page_shift) + psize = (size_t)1 << io->page_shift; + for (p = 0; p <= (io->size >> io->page_shift); p++) { + metal_machine_io_mem_map(va, io->physmap[p], + psize, io->mem_flags); + va += psize; + } + } +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/irq.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/irq.c new file mode 100644 index 000000000..cfe128682 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/irq.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2016 - 2017, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/irq.c + * @brief FreeRTOS libmetal irq definitions. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** IRQ handlers descriptor structure */ +struct metal_irq_hddesc { + metal_irq_handler hd; /**< irq handler */ + void *drv_id; /**< id to identify the driver + of the irq handler */ + struct metal_device *dev; /**< device identifier */ + struct metal_list node; /**< node on irq handlers list */ +}; + +/** IRQ descriptor structure */ +struct metal_irq_desc { + int irq; /**< interrupt number */ + struct metal_list hdls; /**< interrupt handlers */ + struct metal_list node; /**< node on irqs list */ +}; + +/** IRQ state structure */ +struct metal_irqs_state { + struct metal_list irqs; /**< interrupt descriptors */ + metal_mutex_t irq_lock; /**< access lock */ +}; + +static struct metal_irqs_state _irqs = { + .irqs = METAL_INIT_LIST(_irqs.irqs), + .irq_lock = METAL_MUTEX_INIT(_irqs.irq_lock), +}; + +int metal_irq_register(int irq, + metal_irq_handler hd, + struct metal_device *dev, + void *drv_id) +{ + struct metal_irq_desc *irq_p = NULL; + struct metal_irq_hddesc *hdl_p; + struct metal_list *node; + unsigned int irq_flags_save; + + if (irq < 0) { + metal_log(METAL_LOG_ERROR, + "%s: irq %d need to be a positive number\n", + __func__, irq); + return -EINVAL; + } + + if ((drv_id == NULL) || (hd == NULL)) { + metal_log(METAL_LOG_ERROR, "%s: irq %d need drv_id and hd.\n", + __func__, irq); + return -EINVAL; + } + + /* Search for irq in list */ + metal_mutex_acquire(&_irqs.irq_lock); + metal_list_for_each(&_irqs.irqs, node) { + irq_p = metal_container_of(node, struct metal_irq_desc, node); + + if (irq_p->irq == irq) { + struct metal_list *h_node; + + /* Check if drv_id already exist */ + metal_list_for_each(&irq_p->hdls, h_node) { + hdl_p = metal_container_of(h_node, + struct metal_irq_hddesc, + node); + + /* if drv_id already exist reject */ + if ((hdl_p->drv_id == drv_id) && + ((dev == NULL) || (hdl_p->dev == dev))) { + metal_log(METAL_LOG_ERROR, + "%s: irq %d already registered." + "Will not register again.\n", + __func__, irq); + metal_mutex_release(&_irqs.irq_lock); + return -EINVAL; + } + } + /* irq found and drv_id not used, get out of metal_list_for_each */ + break; + } + } + + /* Either need to add handler to an existing list or to a new one */ + hdl_p = metal_allocate_memory(sizeof(struct metal_irq_hddesc)); + if (hdl_p == NULL) { + metal_log(METAL_LOG_ERROR, + "%s: irq %d cannot allocate mem for drv_id %d.\n", + __func__, irq, drv_id); + metal_mutex_release(&_irqs.irq_lock); + return -ENOMEM; + } + hdl_p->hd = hd; + hdl_p->drv_id = drv_id; + hdl_p->dev = dev; + + /* interrupt already registered, add handler to existing list*/ + if ((irq_p != NULL) && (irq_p->irq == irq)) { + irq_flags_save = metal_irq_save_disable(); + metal_list_add_tail(&irq_p->hdls, &hdl_p->node); + metal_irq_restore_enable(irq_flags_save); + + metal_log(METAL_LOG_DEBUG, "%s: success, irq %d add drv_id %p \n", + __func__, irq, drv_id); + metal_mutex_release(&_irqs.irq_lock); + return 0; + } + + /* interrupt was not already registered, add */ + irq_p = metal_allocate_memory(sizeof(struct metal_irq_desc)); + if (irq_p == NULL) { + metal_log(METAL_LOG_ERROR, "%s: irq %d cannot allocate mem.\n", + __func__, irq); + metal_mutex_release(&_irqs.irq_lock); + return -ENOMEM; + } + irq_p->irq = irq; + metal_list_init(&irq_p->hdls); + metal_list_add_tail(&irq_p->hdls, &hdl_p->node); + + irq_flags_save = metal_irq_save_disable(); + metal_list_add_tail(&_irqs.irqs, &irq_p->node); + metal_irq_restore_enable(irq_flags_save); + + metal_log(METAL_LOG_DEBUG, "%s: success, added irq %d\n", __func__, irq); + metal_mutex_release(&_irqs.irq_lock); + return 0; +} + +/* helper function for metal_irq_unregister() */ +static void metal_irq_delete_node(struct metal_list *node, void *p_to_free) +{ + unsigned int irq_flags_save; + + irq_flags_save=metal_irq_save_disable(); + metal_list_del(node); + metal_irq_restore_enable(irq_flags_save); + metal_free_memory(p_to_free); +} + +int metal_irq_unregister(int irq, + metal_irq_handler hd, + struct metal_device *dev, + void *drv_id) +{ + struct metal_irq_desc *irq_p; + struct metal_list *node; + + if (irq < 0) { + metal_log(METAL_LOG_ERROR, "%s: irq %d need to be a positive number\n", + __func__, irq); + return -EINVAL; + } + + /* Search for irq in list */ + metal_mutex_acquire(&_irqs.irq_lock); + metal_list_for_each(&_irqs.irqs, node) { + + irq_p = metal_container_of(node, struct metal_irq_desc, node); + + if (irq_p->irq == irq) { + struct metal_list *h_node, *h_prenode; + struct metal_irq_hddesc *hdl_p; + unsigned int delete_count = 0; + + metal_log(METAL_LOG_DEBUG, "%s: found irq %d\n", + __func__, irq); + + /* Search through handlers */ + metal_list_for_each(&irq_p->hdls, h_node) { + hdl_p = metal_container_of(h_node, + struct metal_irq_hddesc, + node); + + if (((hd == NULL) || (hdl_p->hd == hd)) && + ((drv_id == NULL) || (hdl_p->drv_id == drv_id)) && + ((dev == NULL) || (hdl_p->dev == dev))) { + metal_log(METAL_LOG_DEBUG, + "%s: unregister hd=%p drv_id=%p dev=%p\n", + __func__, hdl_p->hd, hdl_p->drv_id, hdl_p->dev); + h_prenode = h_node->prev; + metal_irq_delete_node(h_node, hdl_p); + delete_count++; + h_node = h_prenode; + } + } + + /* we did not find any handler to delete */ + if (!delete_count) { + metal_log(METAL_LOG_DEBUG, "%s: No matching entry\n", + __func__); + metal_mutex_release(&_irqs.irq_lock); + return -ENOENT; + + } + + /* if interrupt handlers list is empty, unregister interrupt */ + if (metal_list_is_empty(&irq_p->hdls)) { + metal_log(METAL_LOG_DEBUG, + "%s: handlers list empty, unregister interrupt\n", + __func__); + metal_irq_delete_node(node, irq_p); + } + + metal_log(METAL_LOG_DEBUG, "%s: success\n", __func__); + + metal_mutex_release(&_irqs.irq_lock); + return 0; + } + } + + metal_log(METAL_LOG_DEBUG, "%s: No matching IRQ entry\n", __func__); + + metal_mutex_release(&_irqs.irq_lock); + return -ENOENT; +} + +unsigned int metal_irq_save_disable(void) +{ + return sys_irq_save_disable(); +} + +void metal_irq_restore_enable(unsigned int flags) +{ + sys_irq_restore_enable(flags); +} + +void metal_irq_enable(unsigned int vector) +{ + sys_irq_enable(vector); +} + +void metal_irq_disable(unsigned int vector) +{ + sys_irq_disable(vector); +} + +/** + * @brief default handler + */ +void metal_irq_isr(unsigned int vector) +{ + struct metal_list *node; + struct metal_irq_desc *irq_p; + + metal_list_for_each(&_irqs.irqs, node) { + irq_p = metal_container_of(node, struct metal_irq_desc, node); + + if ((unsigned int)irq_p->irq == vector) { + struct metal_list *h_node; + struct metal_irq_hddesc *hdl_p; + + metal_list_for_each(&irq_p->hdls, h_node) { + hdl_p = metal_container_of(h_node, + struct metal_irq_hddesc, + node); + + (hdl_p->hd)(vector, hdl_p->drv_id); + } + } + } +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/rzv2/Makefile b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/rzv2/Makefile new file mode 100644 index 000000000..962b34d0b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/rzv2/Makefile @@ -0,0 +1,5 @@ +SRC_DIR := + +SRC_FILES := $(wildcard *.c) + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/rzv2/sys.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/rzv2/sys.c new file mode 100644 index 000000000..e2468cea9 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/rzv2/sys.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * Copyright (c) 2017, eForce Co Ltd. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Xilinx nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file rzv2/sys.c + * @brief machine specific system primitives implementation. + */ + +#include +#include "metal/io.h" +#include "metal/sys.h" +#include "bsp_api.h" +#include + +void sys_irq_restore_enable(unsigned int flags) +{ +#if 0 + (void)IRQ_SetPriorityMask(flags); +#else + ENABLE_INTERRUPT(flags); +#endif +} + +unsigned int sys_irq_save_disable(void) +{ +#if 0 + int32_t imask; + imask= IRQ_GetPriorityMask(); + + if (imask != 0) { + (void)IRQ_SetPriorityMask(0); + } + return imask; +#else + // return ulSetInterruptMask(); + return DISABLE_INTERRUPT(); +#endif +} + +void metal_machine_cache_flush(void *addr, unsigned int len) +{ + //SCB_InvalidateDCache_by_Addr(addr, len); +} + +void metal_machine_cache_invalidate(void *addr, unsigned int len) +{ + //SCB_CleanDCache_by_Addr(addr, len); +} + +/** + * @brief poll function until some event happens + */ +void __attribute__((weak)) metal_generic_default_poll(void) +{ + __asm__ volatile("wfi"); +} + +void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa, + size_t size, unsigned int flags) +{ + (void)pa; + (void)size; + (void)flags; + return va; +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/shmem.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/shmem.c new file mode 100644 index 000000000..1d98c8862 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/shmem.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/shmem.c + * @brief FreeRTOS libmetal shared memory handling. + */ + +#include + +int metal_shmem_open(const char *name, size_t size, + struct metal_io_region **io) +{ + return metal_shmem_open_generic(name, size, io); +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/time.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/time.c new file mode 100644 index 000000000..5c7ac15b9 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/system/xizi/time.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * @file freertos/time.c + * @brief freertos libmetal time handling. + */ + +// #include +// #include +#include +#include + +unsigned long long metal_get_timestamp(void) +{ + return (unsigned long long)CurrentTicksGain(); +} + diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/version.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/version.c new file mode 100644 index 000000000..8810ac686 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/libmetal/lib/version.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +int metal_ver_major(void) +{ + return METAL_VER_MAJOR; +} + +int metal_ver_minor(void) +{ + return METAL_VER_MINOR; +} + +int metal_ver_patch(void) +{ + return METAL_VER_PATCH; +} + +const char *metal_ver(void) +{ + return METAL_VER; +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/LICENSE.md b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/LICENSE.md new file mode 100644 index 000000000..9bc2dfa9b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/LICENSE.md @@ -0,0 +1,69 @@ +Software License Agreement (BSD 3-Clause License) +======================================== + +Copyright (c) 2014, Mentor Graphics Corporation. All rights reserved. +Copyright (c) 2015 - 2016 Xilinx, Inc. All rights reserved. +Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +BSD 2-Clause License +------------------------- + +Copyright (c) . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Notes +========================================= +Use the following tag instead of the full license text in the individual files: + + SPDX-License-Identifier: BSD-3-Clause + SPDX-License-Identifier: BSD-2-Clause + +This enables machine processing of license information based on the SPDX +License Identifiers that are here available: http://spdx.org/licenses/ + diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/MAINTAINERS.md b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/MAINTAINERS.md new file mode 100644 index 000000000..ab86b1660 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/MAINTAINERS.md @@ -0,0 +1,22 @@ +# OpenAMP Maintainers + +OpenAMP project is maintained by the OpenAMP open source community. Everyone +is encouraged to submit issues and changes to improve OpenAMP. + +The intention of this file is to provide a set of names that developers can +consult when they have a question about OpenAMP and to provide a a set of +names to be CC'd when submitting a patch. + + +## Project Administration +Wendy Liang + +### All patches CC here +open-amp@googlegroups.com + +## Machines +### Xilinx Platform - Zynq-7000 +Wendy Liang + +### Xilinx Platform - Zynq UltraScale+ MPSoC +Wendy Liang diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/README.md b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/README.md new file mode 100644 index 000000000..f50836dd9 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/README.md @@ -0,0 +1,242 @@ +# open-amp +This repository is the home for the Open Asymmetric Multi Processing (OpenAMP) +framework project. The OpenAMP framework provides software components that +enable development of software applications for Asymmetric Multiprocessing +(AMP) systems. The framework provides the following key capabilities. + +1. Provides Life Cycle Management, and Inter Processor Communication + capabilities for management of remote compute resources and their associated + software contexts. +2. Provides a stand alone library usable with RTOS and Baremetal software + environments +3. Compatibility with upstream Linux remoteproc and rpmsg components +4. Following AMP configurations supported + a. Linux master/Generic(Baremetal) remote + b. Generic(Baremetal) master/Linux remote +5. Proxy infrastructure and supplied demos showcase ability of proxy on master + to handle printf, scanf, open, close, read, write calls from Bare metal + based remote contexts. + +## OpenAMP Source Structure +``` +|- lib/ +| |- common/ # common helper functions +| |- virtio/ # virtio implementation +| |- rpmsg/ # rpmsg implementation +| |- remoteproc/ # remoteproc implementation +| | |- drivers # remoteproc drivers +| |- proxy/ # implement one processor access device on the +| | # other processor with file operations +|- apps/ # demonstration/testing applications +| |- machine/ # common files for machine can be shared by applications +| # It is up to each app to decide whether to use these files. +| |- system/ # common files for system can be shared by applications +| # It is up to each app to decide whether to use these files. +|- obsolete # It is used to build libs which may also required when +| # building the apps. It will be removed in future since +| # user can specify which libs to use when compiling the apps. +|- cmake # CMake files +``` + +OpenAMP library libopen_amp is composed of the following directories in `lib/`: +* `common/` +* `virtio/` +* `rpmsg/` +* `remoteproc/` +* `proxy/` + +OpenAMP system/machine support has been moved to libmetal, the system/machine +layer in the `apps/` directory is for system application initialization, and +resource table definition. + +### libmetal APIs used in OpenAMP +Here are the libmetal APIs used by OpenAMP, if you want to port OpenAMP for your +system, you will need to implement the following libmetal APIs in the libmetal's +`lib/system/` directory: +* alloc, for memory allocation and memory free +* cache, for flushing cache and invalidating cache +* io, for memory mapping. OpenAMP required memory mapping in order to access + vrings and carved out memory. +* irq, for IRQ handler registration, IRQ disable/enable and global IRQ handling. +* mutex +* shmem (For RTOS, you can usually use the implementation from + `lib/system/generic/`) +* sleep, at the moment, OpenAMP only requires microseconds sleep as when OpenAMP + fails to get a buffer to send messages, it will call this function to sleep and + then try again. +* time, for timestamp +* init, for libmetal initialization. +* atomic + +Please refer to `lib/system/generic` when you port libmetal for your system. + +If you a different compiler to GNU gcc, please refer to `lib/compiler/gcc/` to +port libmetal for your compiler. At the moment, OpenAMP needs the atomic +operations defined in `lib/compiler/gcc/atomic.h`. + +## OpenAMP Compilation +OpenAMP uses CMake for library and demonstration application compilation. +OpenAMP requires libmetal library. For now, you will need to download and +compile libmetal library separately before you compiling OpenAMP library. +In future, we will try to make libmetal as a submodule to OpenAMP to make this +flow easier. + +### Example to compile OpenAMP for Zephyr +You can compile OpenAMP library for Zephyr. +As OpenAMP uses libmetal, please refer to libmetal README to build libmetal +for Zephyr before building OpenAMP library for Zephyr. +As Zephyr uses CMake, we build OpenAMP library as a target of Zephyr CMake +project. Here is how to build libmetal for Zephyr: +``` + $ export ZEPHRY_GCC_VARIANT=zephyr + $ export ZEPHRY_SDK_INSTALL_DIR= + $ source /zephyr-env.sh + + $ cmake \ + -DWITH_ZEPHYR=on -DBOARD=qemu_cortex_m3 \ + -DCMAKE_INCLUDE_PATH="/lib/include" \ + -DCMAKE_LIBRARY_PATH="/lib" \ + $ make VERBOSE=1 all +``` + +### Example to compile OpenAMP for communication between Linux processes: +* Install libsysfs devel and libhugetlbfs devel packages on your Linux host. +* build libmetal library on your host as follows: + + ``` + $ mkdir -p build-libmetal + $ cd build-libmetal + $ cmake + $ make VERBOSE=1 DESTDIR= install + ``` + +* build OpenAMP library on your host as follows: + + $ mkdir -p build-openamp + $ cd build-openamp + $ cmake -DCMAKE_INCLUDE_PATH= \ + -DCMAKE_LIBRARY_PATH= [-DWITH_APPS=ON] + $ make VERBOSE=1 DESTDIR=$(pwd) install + +The OpenAMP library will be generated to `build/usr/local/lib` directory, +headers will be generated to `build/usr/local/include` directory, and the +applications executable will be generated to `build/usr/local/bin` +directory. + +* cmake option `-DWITH_APPS=ON` is to build the demonstration applications. +* If you have used `-DWITH_APPS=ON` to build the demos, you can try them on + your Linux host as follows: + + ``` + # Start echo test server to wait for message to echo + $ sudo LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib \ + build/usr/local/bin/rpmsg-echo-shared + # Run echo test to send message to echo test server + $ sudo LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib \ + build/usr/local/bin/rpmsg-echo-ping-shared 1 + ``` + +### Example to compile Zynq UltraScale+ MPSoC R5 generic(baremetal) remote: +* build libmetal library on your host as follows: + * Create your on cmake toolchain file to compile libmetal for your generic + (baremetal) platform. Here is the example of the toolchain file: + + ``` + set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "") + set (MACHINE "zynqmp_r5" CACHE STRING "") + + set (CROSS_PREFIX "armr5-none-eabi-" CACHE STRING "") + set (CMAKE_C_FLAGS "-mfloat-abi=soft -mcpu=cortex-r5 -Wall -Werror -Wextra \ + -flto -Os -I/ws/xsdk/r5_0_bsp/psu_cortexr5_0/include" CACHE STRING "") + + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") + SET(CMAKE_AR "gcc-ar" CACHE STRING "") + SET(CMAKE_C_ARCHIVE_CREATE " qcs ") + SET(CMAKE_C_ARCHIVE_FINISH true) + + include (cross-generic-gcc) + ``` + + * Compile libmetal library: + + ``` + $ mkdir -p build-libmetal + $ cd build-libmetal + $ cmake -DCMAKE_TOOLCHAIN_FILE= + $ make VERBOSE=1 DESTDIR= install + ``` + +* build OpenAMP library on your host as follows: + * Create your on cmake toolchain file to compile openamp for your generic + (baremetal) platform. Here is the example of the toolchain file: + ``` + set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "") + set (MACHINE "zynqmp_r5" CACHE STRING "") + set (CROSS_PREFIX "armr5-none-eabi-" CACHE STRING "") + set (CMAKE_C_FLAGS "-mfloat-abi=soft -mcpu=cortex-r5 -Os -flto \ + -I/ws/libmetal-r5-generic/usr/local/include \ + -I/ws/xsdk/r5_0_bsp/psu_cortexr5_0/include" CACHE STRING "") + set (CMAKE_ASM_FLAGS "-mfloat-abi=soft -mcpu=cortex-r5" CACHE STRING "") + set (PLATFORM_LIB_DEPS "-lxil -lc -lm" CACHE STRING "") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") + SET(CMAKE_AR "gcc-ar" CACHE STRING "") + SET(CMAKE_C_ARCHIVE_CREATE " qcs ") + SET(CMAKE_C_ARCHIVE_FINISH true) + set (CMAKE_FIND_ROOT_PATH /ws/libmetal-r5-generic/usr/local/lib \ + /ws/xsdk/r5_bsp/psu_cortexr5_0/lib ) + + include (cross_generic_gcc) + ``` + + * We use cmake `find_path` and `find_library` to check if libmetal includes + and libmetal library is in the includes and library search paths. However, + for non-linux system, it doesn't work with `CMAKE_INCLUDE_PATH` and + `CMAKE_LIBRARY_PATH` variables, and thus, we need to specify those paths + in the toolchain file with `CMAKE_C_FLAGS` and `CMAKE_FIND_ROOT_PATH`. +* Compile the OpenAMP library: + + ``` + $ mkdir -p build-openamp + $ cd build-openamp + $ cmake -DCMAKE_TOOLCHAIN_FILE= + $ make VERBOSE=1 DESTDIR=$(pwd) install + ``` + +The OpenAMP library will be generated to `build/usr/local/lib` directory, +headers will be generated to `build/usr/local/include` directory, and the +applications executable will be generated to `build/usr/local/bin` +directory. + + +### Example to compile OpenAMP Linux Userspace for Zynq UltraScale+ MPSoC +We can use yocto to build the OpenAMP Linux userspace library and application. +open-amp and libmetal recipes are in this yocto layer: +https://github.com/OpenAMP/meta-openamp +* Add the `meta-openamp` layer to your layers in your yocto build project's `bblayers.conf` file. +* Add `libmetal` and `open-amp` to your packages list. E.g. add `libmetal` and `open-amp` to the + `IMAGE_INSTALL_append` in the `local.conf` file. +* You can also add OpenAMP demos Linux applications packages to your yocto packages list. OpenAMP + demo examples recipes are also in `meta-openamp`: + https://github.com/OpenAMP/meta-openamp/tree/master/recipes-openamp/openamp-examples + +In order to user OpenAMP(RPMsg) in Linux userspace, you will need to have put the IPI device, + vring memory and shared buffer memory to your Linux kernel device tree. The device tree example + can be found here: + https://github.com/OpenAMP/open-amp/blob/master/apps/machine/zynqmp/openamp-linux-userspace.dtsi + +## Supported System and Machines +For now, it supports: +* Zynq generic slave +* Zynq UltraScale+ MPSoC R5 generic slave +* Linux host OpenAMP between Linux userspace processes +* Linux userspace OpenAMP RPMsg master +* Linux userspace OpenAMP RPMsg slave + +## Known Limitations: +1. In case of OpenAMP on Linux userspace for inter processors communication, + it only supports static vrings and shared buffers. +2. `sudo` is required to run the OpenAMP demos between Linux processes, as + it doesn't work on some systems if you are normal users. + +For using the framework please refer to the wiki of the OpenAMP repo. +Subscribe to the open-amp mailing list at https://groups.google.com/group/open-amp. diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/compiler.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/compiler.h new file mode 100644 index 000000000..4253efc6d --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/compiler.h @@ -0,0 +1,71 @@ +#ifndef _COMPILER_H_ +#define _COMPILER_H_ + +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/************************************************************************** + * FILE NAME + * + * compiler.h + * + * DESCRIPTION + * + * This file defines compiler-specific macros. + * + ***************************************************************************/ +#if defined __cplusplus +extern "C" { +#endif + +/* IAR ARM build tools */ +#if defined(__ICCARM__) + +#ifndef OPENAMP_PACKED_BEGIN +#define OPENAMP_PACKED_BEGIN __packed +#endif + +#ifndef OPENAMP_PACKED_END +#define OPENAMP_PACKED_END +#endif + +/* GNUC */ +#elif defined(__GNUC__) + +#ifndef OPENAMP_PACKED_BEGIN +#define OPENAMP_PACKED_BEGIN +#endif + +#ifndef OPENAMP_PACKED_END +#define OPENAMP_PACKED_END __attribute__((__packed__)) +#endif + +/* ARM GCC */ +#elif defined(__CC_ARM) + +#ifndef OPENAMP_PACKED_BEGIN +#define OPENAMP_PACKED_BEGIN _Pragma("pack(1U)") +#endif + +#ifndef OPENAMP_PACKED_END +#define OPENAMP_PACKED_END _Pragma("pack()") +#endif + +#else +/* + * There is no default definition here to avoid wrong structures packing in case + * of not supported compiler + */ +#error Please implement the structure packing macros for your compiler here! +#endif + +#if defined __cplusplus +} +#endif + +#endif /* _COMPILER_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/elf_loader.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/elf_loader.h new file mode 100644 index 000000000..acf3d2991 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/elf_loader.h @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ELF_LOADER_H_ +#define ELF_LOADER_H_ + +#include +#include + +#if defined __cplusplus +extern "C" { +#endif + +/* ELF32 base types - 32-bit. */ +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +/* ELF64 base types - 64-bit. */ +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* Size of ELF identifier field in the ELF file header. */ +#define EI_NIDENT 16 + +/* ELF32 file header */ +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +/* ELF64 file header */ +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* e_ident */ +#define ET_NONE 0 +#define ET_REL 1 /* Re-locatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_LOOS 0xfe00 /* Operating system-specific */ +#define ET_HIOS 0xfeff /* Operating system-specific */ +#define ET_LOPROC 0xff00 /* remote_proc-specific */ +#define ET_HIPROC 0xffff /* remote_proc-specific */ + +/* e_machine */ +#define EM_ARM 40 /* ARM/Thumb Architecture */ + +/* e_version */ +#define EV_CURRENT 1 /* Current version */ + +/* e_ident[] Identification Indexes */ +#define EI_MAG0 0 /* File identification */ +#define EI_MAG1 1 /* File identification */ +#define EI_MAG2 2 /* File identification */ +#define EI_MAG3 3 /* File identification */ +#define EI_CLASS 4 /* File class */ +#define EI_DATA 5 /* Data encoding */ +#define EI_VERSION 6 /* File version */ +#define EI_OSABI 7 /* Operating system/ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define EI_PAD 9 /* Start of padding bytes */ +#define EI_NIDENT 16 /* Size of e_ident[] */ + +/* + * EI_MAG0 to EI_MAG3 - A file's first 4 bytes hold amagic number, identifying + * the file as an ELF object file + */ +#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +/* + * EI_CLASS - The next byte, e_ident[EI_CLASS], identifies the file's class, or + * capacity. + */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ + +/* + * EI_DATA - Byte e_ident[EI_DATA] specifies the data encoding of the + * remote_proc-specific data in the object file. The following encodings are + * currently defined. + */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* See Data encodings, below */ +#define ELFDATA2MSB 2 /* See Data encodings, below */ + +/* EI_OSABI - We do not define an OS specific ABI */ +#define ELFOSABI_NONE 0 + +/* ELF32 program header */ +typedef struct elf32_phdr{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* ELF64 program header */ +typedef struct elf64_phdr { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + +/* segment types */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* OS-specific */ +#define PT_HIOS 0x6fffffff /* OS-specific */ +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +/* ELF32 section header. */ +typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +/* ELF64 section header. */ +typedef struct { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +/* sh_type */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_PREINIT_ARRAY 16 +#define SHT_GROUP 17 +#define SHT_SYMTAB_SHNDX 18 +#define SHT_LOOS 0x60000000 +#define SHT_HIOS 0x6fffffff +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* sh_flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* Relocation entry (without addend) */ +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + +} Elf32_Rel; + +typedef struct { + Elf64_Addr r_offset; + Elf64_Xword r_info; + +} Elf64_Rel; + +/* Relocation entry with addend */ +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; + +} Elf32_Rela; + +typedef struct elf64_rela { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + +/* Macros to extract information from 'r_info' field of relocation entries */ +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) + +/* Symbol table entry */ +typedef struct { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; + +} Elf32_Sym; + +typedef struct elf64_sym { + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +/* ARM specific dynamic relocation codes */ +#define R_ARM_GLOB_DAT 21 /* 0x15 */ +#define R_ARM_JUMP_SLOT 22 /* 0x16 */ +#define R_ARM_RELATIVE 23 /* 0x17 */ +#define R_ARM_ABS32 2 /* 0x02 */ + +/* ELF decoding information */ +struct elf32_info { + Elf32_Ehdr ehdr; + unsigned int load_state; + Elf32_Phdr *phdrs; + Elf32_Shdr *shdrs; + void *shstrtab; +}; + +struct elf64_info { + Elf64_Ehdr ehdr; + unsigned int load_state; + Elf64_Phdr *phdrs; + Elf64_Shdr *shdrs; + void *shstrtab; +}; + +#define ELF_STATE_INIT 0x0UL +#define ELF_STATE_WAIT_FOR_PHDRS 0x100UL +#define ELF_STATE_WAIT_FOR_SHDRS 0x200UL +#define ELF_STATE_WAIT_FOR_SHSTRTAB 0x400UL +#define ELF_STATE_HDRS_COMPLETE 0x800UL +#define ELF_STATE_MASK 0xFF00UL +#define ELF_NEXT_SEGMENT_MASK 0x00FFUL + +extern struct loader_ops elf_ops; + +/** + * elf_identify - check if it is an ELF file + * + * It will check if the input image header is an ELF header. + * + * @img_data: firmware private data which will be passed to user defined loader + * operations + * @len: firmware header length + * + * return 0 for success or negative value for failure. + */ +int elf_identify(const void *img_data, size_t len); + +/** + * elf_load_header - Load ELF headers + * + * It will get the ELF header, the program header, and the section header. + * + * @img_data: image data + * @offset: input image data offset to the start of image file + * @len: input image data length + * @img_info: pointer to store image information data + * @last_load_state: last state return by this function + * @noffset: pointer to next offset required by loading ELF header + * @nlen: pointer to next data length required by loading ELF header + * + * return ELF loading header state, or negative value for failure + */ +int elf_load_header(const void *img_data, size_t offset, size_t len, + void **img_info, int last_load_state, + size_t *noffset, size_t *nlen); + +/** + * elf_load - load ELF data + * + * It will parse the ELF image and return the target device address, + * offset to the start of the ELF image of the data to load and the + * length of the data to load. + * + * @rproc: pointer to remoteproc instance + * @img_data: image data which will passed to the function. + * it can be NULL, if image data doesn't need to be handled + * by the load function. E.g. binary data which was + * loaded to the target memory. + * @offset: last loaded image data offset to the start of image file + * @len: last loaded image data length + * @img_info: pointer to store image information data + * @last_load_state: the returned state of the last function call. + * @da: target device address, if the data to load is not for target memory + * the da will be set to ANY. + * @noffset: pointer to next offset required by loading ELF header + * @nlen: pointer to next data length required by loading ELF header + * @padding: value to pad it is possible that a size of a segment in memory + * is larger than what it is in the ELF image. e.g. a segment + * can have stack section .bss. It doesn't need to copy image file + * space, in this case, it will be packed with 0. + * @nmemsize: pointer to next data target memory size. The size of a segment + * in the target memory can be larger than the its size in the + * image file. + * + * return 0 for success, otherwise negative value for failure + */ +int elf_load(struct remoteproc *rproc, const void *img_data, + size_t offset, size_t len, + void **img_info, int last_load_state, + metal_phys_addr_t *da, + size_t *noffset, size_t *nlen, + unsigned char *padding, size_t *nmemsize); + +/** + * elf_release - Release ELF image information + * + * It will release ELF image information data. + * + * @img_info: pointer to ELF image information + */ +void elf_release(void *img_info); + +/** + * elf_get_entry - Get entry point + * + * It will return entry point specified in the ELF file. + * + * @img_info: pointer to ELF image information + * + * return entry address + */ +metal_phys_addr_t elf_get_entry(void *img_info); + +/** + * elf_locate_rsc_table - locate the resource table information + * + * It will return the length of the resource table, and the device address of + * the resource table. + * + * @img_info: pointer to ELF image information + * @da: pointer to the device address + * @offset: pointer to the offset to in the ELF image of the resource + * table section. + * @size: pointer to the size of the resource table section. + * + * return 0 if successfully locate the resource table, negative value for + * failure. + */ +int elf_locate_rsc_table(void *img_info, metal_phys_addr_t *da, + size_t *offset, size_t *size); + +#if defined __cplusplus +} +#endif + +#endif /* ELF_LOADER_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/open_amp.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/open_amp.h new file mode 100644 index 000000000..603ecdd52 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/open_amp.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OPEN_AMP_H_ +#define OPEN_AMP_H_ + +#include +#include +#include +#include + + +#endif /* OPEN_AMP_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/remoteproc.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/remoteproc.h new file mode 100644 index 000000000..6b2495c37 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/remoteproc.h @@ -0,0 +1,871 @@ +/* + * Remoteproc Framework + * + * Copyright(c) 2018 Xilinx Ltd. + * Copyright(c) 2011 Texas Instruments, Inc. + * Copyright(c) 2011 Google, Inc. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef REMOTEPROC_H +#define REMOTEPROC_H + +#include +#include +#include + +#if defined __cplusplus +extern "C" { +#endif + +#define RSC_NOTIFY_ID_ANY 0xFFFFFFFFUL + +/** + * struct resource_table - firmware resource table header + * @ver: version number + * @num: number of resource entries + * @reserved: reserved (must be zero) + * @offset: array of offsets pointing at the various resource entries + * + * A resource table is essentially a list of system resources required + * by the remote remote_proc. It may also include configuration entries. + * If needed, the remote remote_proc firmware should contain this table + * as a dedicated ".resource_table" ELF section. + * + * Some resources entries are mere announcements, where the host is informed + * of specific remoteproc configuration. Other entries require the host to + * do something (e.g. allocate a system resource). Sometimes a negotiation + * is expected, where the firmware requests a resource, and once allocated, + * the host should provide back its details (e.g. address of an allocated + * memory region). + * + * The header of the resource table, as expressed by this structure, + * contains a version number (should we need to change this format in the + * future), the number of available resource entries, and their offsets + * in the table. + * + * Immediately following this header are the resource entries themselves, + * each of which begins with a resource entry header (as described below). + */ +OPENAMP_PACKED_BEGIN +struct resource_table { + uint32_t ver; + uint32_t num; + uint32_t reserved[2]; + uint32_t offset[0]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_hdr - firmware resource entry header + * @type: resource type + * @data: resource data + * + * Every resource entry begins with a 'struct fw_rsc_hdr' header providing + * its @type. The content of the entry itself will immediately follow + * this header, and it should be parsed according to the resource type. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_hdr { + uint32_t type; + uint8_t data[0]; +} OPENAMP_PACKED_END; + +/** + * enum fw_resource_type - types of resource entries + * + * @RSC_CARVEOUT: request for allocation of a physically contiguous + * memory region. + * @RSC_DEVMEM: request to iommu_map a memory-based peripheral. + * @RSC_TRACE: announces the availability of a trace buffer into which + * the remote remote_proc will be writing logs. + * @RSC_VDEV: declare support for a virtio device, and serve as its + * virtio header. + * @RSC_VENDOR_START: start of the vendor specific resource types range + * @RSC_VENDOR_END : end of the vendor specific resource types range + * @RSC_LAST: just keep this one at the end + * + * For more details regarding a specific resource type, please see its + * dedicated structure below. + * + * Please note that these values are used as indices to the rproc_handle_rsc + * lookup table, so please keep them sane. Moreover, @RSC_LAST is used to + * check the validity of an index before the lookup table is accessed, so + * please update it as needed. + */ +enum fw_resource_type { + RSC_CARVEOUT = 0, + RSC_DEVMEM = 1, + RSC_TRACE = 2, + RSC_VDEV = 3, + RSC_RPROC_MEM = 4, + RSC_FW_CHKSUM = 5, + RSC_LAST = 6, + RSC_VENDOR_START = 128, + RSC_VENDOR_END = 512, +}; + +#define FW_RSC_ADDR_ANY (0xFFFFFFFFFFFFFFFF) +#define FW_RSC_U32_ADDR_ANY (0xFFFFFFFF) + +/** + * struct fw_rsc_carveout - physically contiguous memory request + * @da: device address + * @pa: physical address + * @len: length (in bytes) + * @flags: iommu protection flags + * @reserved: reserved (must be zero) + * @name: human-readable name of the requested memory region + * + * This resource entry requests the host to allocate a physically contiguous + * memory region. + * + * These request entries should precede other firmware resource entries, + * as other entries might request placing other data objects inside + * these memory regions (e.g. data/code segments, trace resource entries, ...). + * + * Allocating memory this way helps utilizing the reserved physical memory + * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries + * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB + * pressure is important; it may have a substantial impact on performance. + * + * If the firmware is compiled with static addresses, then @da should specify + * the expected device address of this memory region. If @da is set to + * FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then + * overwrite @da with the dynamically allocated address. + * + * We will always use @da to negotiate the device addresses, even if it + * isn't using an iommu. In that case, though, it will obviously contain + * physical addresses. + * + * Some remote remote_procs needs to know the allocated physical address + * even if they do use an iommu. This is needed, e.g., if they control + * hardware accelerators which access the physical memory directly (this + * is the case with OMAP4 for instance). In that case, the host will + * overwrite @pa with the dynamically allocated physical address. + * Generally we don't want to expose physical addresses if we don't have to + * (remote remote_procs are generally _not_ trusted), so we might want to + * change this to happen _only_ when explicitly required by the hardware. + * + * @flags is used to provide IOMMU protection flags, and @name should + * (optionally) contain a human readable name of this carveout region + * (mainly for debugging purposes). + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_carveout { + uint32_t type; + uint32_t da; + uint32_t pa; + uint32_t len; + uint32_t flags; + uint32_t reserved; + uint8_t name[32]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_devmem - iommu mapping request + * @da: device address + * @pa: physical address + * @len: length (in bytes) + * @flags: iommu protection flags + * @reserved: reserved (must be zero) + * @name: human-readable name of the requested region to be mapped + * + * This resource entry requests the host to iommu map a physically contiguous + * memory region. This is needed in case the remote remote_proc requires + * access to certain memory-based peripherals; _never_ use it to access + * regular memory. + * + * This is obviously only needed if the remote remote_proc is accessing memory + * via an iommu. + * + * @da should specify the required device address, @pa should specify + * the physical address we want to map, @len should specify the size of + * the mapping and @flags is the IOMMU protection flags. As always, @name may + * (optionally) contain a human readable name of this mapping (mainly for + * debugging purposes). + * + * Note: at this point we just "trust" those devmem entries to contain valid + * physical addresses, but this isn't safe and will be changed: eventually we + * want remoteproc implementations to provide us ranges of physical addresses + * the firmware is allowed to request, and not allow firmwares to request + * access to physical addresses that are outside those ranges. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_devmem { + uint32_t type; + uint32_t da; + uint32_t pa; + uint32_t len; + uint32_t flags; + uint32_t reserved; + uint8_t name[32]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_trace - trace buffer declaration + * @da: device address + * @len: length (in bytes) + * @reserved: reserved (must be zero) + * @name: human-readable name of the trace buffer + * + * This resource entry provides the host information about a trace buffer + * into which the remote remote_proc will write log messages. + * + * @da specifies the device address of the buffer, @len specifies + * its size, and @name may contain a human readable name of the trace buffer. + * + * After booting the remote remote_proc, the trace buffers are exposed to the + * user via debugfs entries (called trace0, trace1, etc..). + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_trace { + uint32_t type; + uint32_t da; + uint32_t len; + uint32_t reserved; + uint8_t name[32]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_vdev_vring - vring descriptor entry + * @da: device address + * @align: the alignment between the consumer and producer parts of the vring + * @num: num of buffers supported by this vring (must be power of two) + * @notifyid is a unique rproc-wide notify index for this vring. This notify + * index is used when kicking a remote remote_proc, to let it know that this + * vring is triggered. + * @reserved: reserved (must be zero) + * + * This descriptor is not a resource entry by itself; it is part of the + * vdev resource type (see below). + * + * Note that @da should either contain the device address where + * the remote remote_proc is expecting the vring, or indicate that + * dynamically allocation of the vring's device address is supported. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_vdev_vring { + uint32_t da; + uint32_t align; + uint32_t num; + uint32_t notifyid; + uint32_t reserved; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_vdev - virtio device header + * @id: virtio device id (as in virtio_ids.h) + * @notifyid is a unique rproc-wide notify index for this vdev. This notify + * index is used when kicking a remote remote_proc, to let it know that the + * status/features of this vdev have changes. + * @dfeatures specifies the virtio device features supported by the firmware + * @gfeatures is a place holder used by the host to write back the + * negotiated features that are supported by both sides. + * @config_len is the size of the virtio config space of this vdev. The config + * space lies in the resource table immediate after this vdev header. + * @status is a place holder where the host will indicate its virtio progress. + * @num_of_vrings indicates how many vrings are described in this vdev header + * @reserved: reserved (must be zero) + * @vring is an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'. + * + * This resource is a virtio device header: it provides information about + * the vdev, and is then used by the host and its peer remote remote_procs + * to negotiate and share certain virtio properties. + * + * By providing this resource entry, the firmware essentially asks remoteproc + * to statically allocate a vdev upon registration of the rproc (dynamic vdev + * allocation is not yet supported). + * + * Note: unlike virtualization systems, the term 'host' here means + * the Linux side which is running remoteproc to control the remote + * remote_procs. We use the name 'gfeatures' to comply with virtio's terms, + * though there isn't really any virtualized guest OS here: it's the host + * which is responsible for negotiating the final features. + * Yeah, it's a bit confusing. + * + * Note: immediately following this structure is the virtio config space for + * this vdev (which is specific to the vdev; for more info, read the virtio + * spec). the size of the config space is specified by @config_len. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_vdev { + uint32_t type; + uint32_t id; + uint32_t notifyid; + uint32_t dfeatures; + uint32_t gfeatures; + uint32_t config_len; + uint8_t status; + uint8_t num_of_vrings; + uint8_t reserved[2]; + struct fw_rsc_vdev_vring vring[0]; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_vendor - remote processor vendor specific resource + * @len: length of the resource + * + * This resource entry tells the host the vendor specific resource + * required by the remote. + * + * These request entries should precede other shared resource entries + * such as vdevs, vrings. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_vendor { + uint32_t type; + uint32_t len; +} OPENAMP_PACKED_END; + +/** + * struct fw_rsc_rproc_mem - remote processor memory + * @da: device address + * @pa: physical address + * @len: length (in bytes) + * @reserved: reserved (must be zero) + * + * This resource entry tells the host to the remote processor + * memory that the host can be used as shared memory. + * + * These request entries should precede other shared resource entries + * such as vdevs, vrings. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_rproc_mem { + uint32_t type; + uint32_t da; + uint32_t pa; + uint32_t len; + uint32_t reserved; +} OPENAMP_PACKED_END; + +/* + * struct fw_rsc_fw_chksum - firmware checksum + * @algo: algorithm to generate the cheksum + * @chksum: checksum of the firmware loadable sections. + * + * This resource entry provides checksum for the firmware loadable sections. + * It is used to check if the remote already runs with the expected firmware to + * decide if it needs to start the remote if the remote is already running. + */ +OPENAMP_PACKED_BEGIN +struct fw_rsc_fw_chksum { + uint32_t type; + uint8_t algo[16]; + uint8_t chksum[64]; +} OPENAMP_PACKED_END; + +struct loader_ops; +struct image_store_ops; +struct remoteproc_ops; + +/** + * struct remoteproc_mem + * + * This structure presents the memory used by the remote processor + * + * @da: device memory + * @pa: physical memory + * @size: size of the memory + * @io: pointer to the I/O region + * @node: list node + */ +struct remoteproc_mem { + metal_phys_addr_t da; + metal_phys_addr_t pa; + size_t size; + char name[32]; + struct metal_io_region *io; + struct metal_list node; +}; + +/** + * struct remoteproc + * + * This structure is maintained by the remoteproc to represent the remote + * processor instance. This structure acts as a prime parameter to use + * the remoteproc APIs. + * + * @bootadd: boot address + * @loader: executable loader + * @lock: mutext lock + * @ops: remoteproc operations + * @rsc_table: pointer to resource table + * @rsc_len: length of resource table + * @rsc_io: metal I/O region of resource table + * @mems: remoteproc memories + * @vdevs: remoteproc virtio devices + * @bitmap: bitmap for notify IDs for remoteproc subdevices + * @state: remote processor state + * @priv: private data + */ +struct remoteproc { + metal_mutex_t lock; + void *rsc_table; + size_t rsc_len; + struct metal_io_region *rsc_io; + struct metal_list mems; + struct metal_list vdevs; + unsigned long bitmap; + struct remoteproc_ops *ops; + metal_phys_addr_t bootaddr; + struct loader_ops *loader; + unsigned int state; + void *priv; +}; + +/** + * struct remoteproc_ops + * + * remoteproc operations needs to be implemented by each remoteproc driver + * + * @init: initialize the remoteproc instance + * @remove: remove the remoteproc instance + * @mmap: memory mapped the mempory with physical address or destination + * address as input. + * @handle_rsc: handle the vendor specific resource + * @config: configure the remoteproc to make it ready to load and run + * executable + * @start: kick the remoteproc to run application + * @stop: stop the remoteproc from running application, the resource such as + * memory may not be off. + * @shutdown: shutdown the remoteproc and release its resources. + * @notify: notify the remote + */ +struct remoteproc_ops { + struct remoteproc *(*init)(struct remoteproc *rproc, + struct remoteproc_ops *ops, void *arg); + void (*remove)(struct remoteproc *rproc); + void *(*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); + int (*handle_rsc)(struct remoteproc *rproc, void *rsc, size_t len); + int (*config)(struct remoteproc *rproc, void *data); + int (*start)(struct remoteproc *rproc); + int (*stop)(struct remoteproc *rproc); + int (*shutdown)(struct remoteproc *rproc); + int (*notify)(struct remoteproc *rproc, uint32_t id); +}; + +/* Remoteproc error codes */ +#define RPROC_EBASE 0 +#define RPROC_ENOMEM (RPROC_EBASE + 1) +#define RPROC_EINVAL (RPROC_EBASE + 2) +#define RPROC_ENODEV (RPROC_EBASE + 3) +#define RPROC_EAGAIN (RPROC_EBASE + 4) +#define RPROC_ERR_RSC_TAB_TRUNC (RPROC_EBASE + 5) +#define RPROC_ERR_RSC_TAB_VER (RPROC_EBASE + 6) +#define RPROC_ERR_RSC_TAB_RSVD (RPROC_EBASE + 7) +#define RPROC_ERR_RSC_TAB_VDEV_NRINGS (RPROC_EBASE + 9) +#define RPROC_ERR_RSC_TAB_NP (RPROC_EBASE + 10) +#define RPROC_ERR_RSC_TAB_NS (RPROC_EBASE + 11) +#define RPROC_ERR_LOADER_STATE (RPROC_EBASE + 12) +#define RPROC_EMAX (RPROC_EBASE + 16) +#define RPROC_EPTR (void *)(-1) +#define RPROC_EOF (void *)(-1) + +static inline long RPROC_PTR_ERR(const void *ptr) +{ + return (long)ptr; +} + +static inline int RPROC_IS_ERR(const void *ptr) +{ + if ((unsigned long)ptr >= (unsigned long)(-RPROC_EMAX)) + return 1; + else + return 0; +} + +static inline void *RPROC_ERR_PTR(long error) +{ + return (void *)error; +} + +/** + * enum rproc_state - remote processor states + * @RPROC_OFFLINE: remote is offline + * @RPROC_READY: remote is ready to start + * @RPROC_RUNNING: remote is up and running + * @RPROC_SUSPENDED: remote is suspended + * @RPROC_ERROR: remote has error; need to recover + * @RPROC_STOPPED: remote is stopped + * @RPROC_LAST: just keep this one at the end + */ +enum remoteproc_state { + RPROC_OFFLINE = 0, + RPROC_CONFIGURED = 1, + RPROC_READY = 2, + RPROC_RUNNING = 3, + RPROC_SUSPENDED = 4, + RPROC_ERROR = 5, + RPROC_STOPPED = 6, + RPROC_LAST = 7, +}; + +/** + * remoteproc_init + * + * Initializes remoteproc resource. + * + * @rproc - pointer to remoteproc instance + * @ops - pointer to remoteproc operations + * @priv - pointer to private data + * + * @returns created remoteproc pointer + */ +struct remoteproc *remoteproc_init(struct remoteproc *rproc, + struct remoteproc_ops *ops, void *priv); + +/** + * remoteproc_remove + * + * Remove remoteproc resource + * + * @rproc - pointer to remoteproc instance + * + * returns 0 for success, negative value for failure + */ +int remoteproc_remove(struct remoteproc *rproc); + +/** + * remoteproc_init_mem + * + * Initialize remoteproc memory + * + * @mem - pointer to remoteproc memory + * @char - memory name + * @pa - physcial address + * @da - device address + * @size - memory size + * @io - pointer to the I/O region + */ +static inline void +remoteproc_init_mem(struct remoteproc_mem *mem, const char *name, + metal_phys_addr_t pa, metal_phys_addr_t da, + size_t size, struct metal_io_region *io) +{ + if (!mem) + return; + if (name) + strncpy(mem->name, name, sizeof(mem->name)); + else + mem->name[0] = 0; + mem->pa = pa; + mem->da = da; + mem->io = io; + mem->size = size; +} + +/** + * remoteproc_add_mem + * + * Add remoteproc memory + * + * @rproc - pointer to remoteproc + * @mem - pointer to remoteproc memory + */ +static inline void +remoteproc_add_mem(struct remoteproc *rproc, struct remoteproc_mem *mem) +{ + if (!rproc || !mem) + return; + metal_list_add_tail(&rproc->mems, &mem->node); +} + +/** + * remoteproc_get_io_with_name + * + * get remoteproc memory I/O region with name + * + * @rproc - pointer to the remote processor + * @name - name of the shared memory + * @io - pointer to the pointer of the I/O region + * + * returns metal I/O region pointer, NULL for failure + */ +struct metal_io_region * +remoteproc_get_io_with_name(struct remoteproc *rproc, + const char *name); + +/** + * remoteproc_get_io_with_pa + * + * get remoteproc memory I/O region with physical address + * + * @rproc - pointer to the remote processor + * @pa - physical address + * + * returns metal I/O region pointer, NULL for failure + */ +struct metal_io_region * +remoteproc_get_io_with_pa(struct remoteproc *rproc, + metal_phys_addr_t pa); + +/** + * remoteproc_get_io_with_da + * + * get remoteproc memory I/O region with device address + * + * @rproc - pointer to the remote processor + * @da - device address + * @offset - I/O region offset of the device address + * + * returns metal I/O region pointer, NULL for failure + */ +struct metal_io_region * +remoteproc_get_io_with_da(struct remoteproc *rproc, + metal_phys_addr_t da, + unsigned long *offset); + +/** + * remoteproc_get_io_with_va + * + * get remoteproc memory I/O region with virtual address + * + * @rproc - pointer to the remote processor + * @va - virtual address + * + * returns metal I/O region pointer, NULL for failure + */ +struct metal_io_region * +remoteproc_get_io_with_va(struct remoteproc *rproc, + void *va); + +/** + * remoteproc_mmap + * + * remoteproc mmap memory + * + * @rproc - pointer to the remote processor + * @pa - physical address pointer + * @da - device address pointer + * @size - size of the memory + * @attribute - memory attribute + * @io - pointer to the I/O region + * + * returns pointer to the memory + */ +void *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); + +/** + * remoteproc_parse_rsc_table + * + * Parse resource table of remoteproc + * + * @rproc - pointer to remoteproc instance + * @rsc_table - pointer to resource table + * @rsc_size - resource table size + * + * returns 0 for success and negative value for errors + */ +int remoteproc_parse_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, + size_t rsc_size); + +/** + * remoteproc_set_rsc_table + * + * Parse and set resource table of remoteproc + * + * @rproc - pointer to remoteproc instance + * @rsc_table - pointer to resource table + * @rsc_size - resource table size + * + * returns 0 for success and negative value for errors + */ +int remoteproc_set_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, + size_t rsc_size); + +/** + * remoteproc_config + * + * This function configures the remote processor to get it + * ready to load and run executable. + * + * @rproc - pointer to remoteproc instance to start + * @data - configuration data + * + * returns 0 for success and negative value for errors + */ +int remoteproc_config(struct remoteproc *rproc, void *data); + +/** + * remoteproc_start + * + * This function starts the remote processor. + * It assumes the firmware is already loaded, + * + * @rproc - pointer to remoteproc instance to start + * + * returns 0 for success and negative value for errors + */ +int remoteproc_start(struct remoteproc *rproc); + +/** + * remoteproc_stop + * + * This function stops the remote processor but it + * will not release its resource. + * + * @rproc - pointer to remoteproc instance + * + * returns 0 for success and negative value for errors + */ +int remoteproc_stop(struct remoteproc *rproc); + +/** + * remoteproc_shutdown + * + * This function shutdown the remote processor and + * release its resources. + * + * @rproc - pointer to remoteproc instance + * + * returns 0 for success and negative value for errors + */ +int remoteproc_shutdown(struct remoteproc *rproc); + +/** + * remoteproc_load + * + * load executable, it expects the user application defines how to + * open the executable file and how to get data from the executable file + * and how to load data to the target memory. + * + * @rproc: pointer to the remoteproc instance + * @path: optional path to the image file + * @store: pointer to user defined image store argument + * @store_ops: pointer to image store operations + * @image_info: pointer to memory which stores image information used + * by remoteproc loader + * + * return 0 for success and negative value for failure + */ +int remoteproc_load(struct remoteproc *rproc, const char *path, + void *store, struct image_store_ops *store_ops, + void **img_info); + +/** + * remoteproc_load_noblock + * + * load executable, it expects the caller has loaded image data to local + * memory and passed to the this function. If the function needs more + * image data it will return the next expected image data offset and + * the next expected image data length. If the function requires the + * caller to download image data to the target memory, it will also + * return the target physical address besides the offset and length. + * This function can be used to load firmware in stream mode. In this + * mode, you cannot do seek to the executable file. If the executable + * is ELF, it cannot get the resource table section before it loads + * the full ELF file. Furthermore, application usually don't store + * the data which is loaded to local memory in streaming mode, and + * thus, in this mode, it will load the binrary to the target memory + * before it gets the resource table. And thus, when calling this funciton + * don't put the target exectuable memory in the resource table, as + * this function will parse the resource table after it loads the binary + * to target memory. + * + * @rproc: pointer to the remoteproc instance + * @img_data: pointer to image data for remoteproc loader to parse + * @offset: image data offset to the beginning of the image file + * @len: image data length + * @image_info: pointer to memory which stores image information used + * by remoteproc loader + * @pa: pointer to the target memory physical address. If the next expected + * data doesn't need to load to the target memory, the function will + * set it to ANY. + * @io: pointer to the target memory physical address. If the next expected + * data doesn't need to load to the target memory, the function will + * set it to ANY. + * @noffset: pointer to the next image data offset to the beginning of + * the image file needs to load to local or to the target + * memory. + * @nlen: pointer to the next image data length needs to load to local + * or to the target memory. + * @nmlen: pointer to the memory size. It is only used when the next + * expected data is going to be loaded to the target memory. E.g. + * in ELF, it is possible that loadable segment in memory is + * larger that the segment data in the ELF file. In this case, + * application will need to pad the rest of the memory with + * padding. + * @padding: pointer to the padding value. It is only used when the next + * expected data is going to be loaded to the target memory. + * and the target memory size is larger than the segment data in + * the executable file. + * + * return 0 for success and negative value for failure + */ +int remoteproc_load_noblock(struct remoteproc *rproc, + const void *img_data, size_t offset, size_t len, + void **img_info, + metal_phys_addr_t *pa, struct metal_io_region **io, + size_t *noffset, size_t *nlen, + size_t *nmlen, unsigned char *padding); + +/** + * remoteproc_allocate_id + * + * allocate notifyid for resource + * + * @rproc - pointer to the remoteproc instance + * @start - start of the id range + * @end - end of the id range + * + * return allocated notify id + */ +unsigned int remoteproc_allocate_id(struct remoteproc *rproc, + unsigned int start, + unsigned int end); + +/* remoteproc_create_virtio + * + * create virtio device, it returns pointer to the created virtio device. + * + * @rproc: pointer to the remoteproc instance + * @vdev_id: virtio device ID + * @role: virtio device role + * @rst_cb: virtio device reset callback + * + * return pointer to the created virtio device, NULL for failure. + */ +struct virtio_device * +remoteproc_create_virtio(struct remoteproc *rproc, + int vdev_id, unsigned int role, + void (*rst_cb)(struct virtio_device *vdev)); + +/* remoteproc_remove_virtio + * + * Remove virtio device + * + * @rproc: pointer to the remoteproc instance + * @vdev: pointer to the virtio device + * + */ +void remoteproc_remove_virtio(struct remoteproc *rproc, + struct virtio_device *vdev); + +/* remoteproc_get_notification + * + * remoteproc is got notified, it will check its subdevices + * for the notification + * + * @rproc - pointer to the remoteproc instance + * @notifyid - notificatin id + * + * return 0 for succeed, negative value for failure + */ +int remoteproc_get_notification(struct remoteproc *rproc, + uint32_t notifyid); +#if defined __cplusplus +} +#endif + +#endif /* REMOTEPROC_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/remoteproc_loader.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/remoteproc_loader.h new file mode 100644 index 000000000..dce3dbb0b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/remoteproc_loader.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/************************************************************************** + * FILE NAME + * + * remoteproc_loader.h + * + * COMPONENT + * + * OpenAMP stack. + * + * DESCRIPTION + * + * This file provides definitions for remoteproc loader + * + * + **************************************************************************/ +#ifndef REMOTEPROC_LOADER_H_ +#define REMOTEPROC_LOADER_H_ + +#include +#include +#include +#include + +#if defined __cplusplus +extern "C" { +#endif + +/* Loader feature macros */ +#define SUPPORT_SEEK 1UL + +/* Remoteproc loader any address */ +#define RPROC_LOAD_ANYADDR ((metal_phys_addr_t)-1) + +/* Remoteproc loader Exectuable Image Parsing States */ +/* Remoteproc loader parser intial state */ +#define RPROC_LOADER_NOT_READY 0x0UL +/* Remoteproc loader ready to load, even it can be not finish parsing */ +#define RPROC_LOADER_READY_TO_LOAD 0x10000UL +/* Remoteproc loader post data load */ +#define RPROC_LOADER_POST_DATA_LOAD 0x20000UL +/* Remoteproc loader finished loading */ +#define RPROC_LOADER_LOAD_COMPLETE 0x40000UL +/* Remoteproc loader state mask */ +#define RPROC_LOADER_MASK 0x00FF0000UL +/* Remoteproc loader private mask */ +#define RPROC_LOADER_PRIVATE_MASK 0x0000FFFFUL +/* Remoteproc loader reserved mask */ +#define RPROC_LOADER_RESERVED_MASK 0x0F000000UL + +/** + * struct image_store_ops - user defined image store operations + * @open: user defined callback to open the "firmware" to prepare loading + * @close: user defined callback to close the "firmware" to clean up + * after loading + * @load: user defined callback to load the firmware contents to target + * memory or local memory + * @features: loader supported features. e.g. seek + */ +struct image_store_ops { + int (*open)(void *store, const char *path, const void **img_data); + void (*close)(void *store); + int (*load)(void *store, size_t offset, size_t size, + const void **data, + metal_phys_addr_t pa, + struct metal_io_region *io, char is_blocking); + unsigned int features; +}; + +/** + * struct loader_ops - loader oeprations + * @load_header: define how to get the executable headers + * @load_data: define how to load the target data + * @locate_rsc_table: define how to get the resource table target address, + * offset to the ELF image file and size of the resource + * table. + * @release: define how to release the loader + * @get_entry: get entry address + * @get_load_state: get load state from the image information + */ +struct loader_ops { + int (*load_header)(const void *img_data, size_t offset, size_t len, + void **img_info, int last_state, + size_t *noffset, size_t *nlen); + int (*load_data)(struct remoteproc *rproc, + const void *img_data, size_t offset, size_t len, + void **img_info, int last_load_state, + metal_phys_addr_t *da, + size_t *noffset, size_t *nlen, + unsigned char *padding, size_t *nmemsize); + int (*locate_rsc_table)(void *img_info, metal_phys_addr_t *da, + size_t *offset, size_t *size); + void (*release)(void *img_info); + metal_phys_addr_t (*get_entry)(void *img_info); + int (*get_load_state)(void *img_info); +}; + +#if defined __cplusplus +} +#endif + +#endif /* REMOTEPROC_LOADER_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/remoteproc_virtio.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/remoteproc_virtio.h new file mode 100644 index 000000000..fc1627e45 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/remoteproc_virtio.h @@ -0,0 +1,150 @@ +/* + * Remoteproc Virtio Framework + * + * Copyright(c) 2018 Xilinx Ltd. + * Copyright(c) 2011 Texas Instruments, Inc. + * Copyright(c) 2011 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Texas Instruments nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef REMOTEPROC_VIRTIO_H +#define REMOTEPROC_VIRTIO_H + +#include +#include +#include + +#if defined __cplusplus +extern "C" { +#endif + +/* define vdev notification funciton user should implement */ +typedef int (*rpvdev_notify_func)(void *priv, uint32_t id); + +/** + * struct remoteproc_virtio + * @priv pointer to private data + * @notifyid notification id + * @vdev_rsc address of vdev resource + * @vdev_rsc_io metal I/O region of vdev_info, can be NULL + * @notify notification function + * @vdev virtio device + * @node list node + */ +struct remoteproc_virtio { + void *priv; + uint32_t notify_id; + void *vdev_rsc; + struct metal_io_region *vdev_rsc_io; + rpvdev_notify_func notify; + struct virtio_device vdev; + struct metal_list node; +}; + +/** + * rproc_virtio_create_vdev + * + * Create rproc virtio vdev + * + * @role: 0 - virtio master, 1 - virtio slave + * @notifyid: virtio device notification id + * @rsc: pointer to the virtio device resource + * @rsc_io: pointer to the virtio device resource I/O region + * @priv: pointer to the private data + * @notify: vdev and virtqueue notification function + * @rst_cb: reset virtio device callback + * + * return pointer to the created virtio device for success, + * NULL for failure. + */ +struct virtio_device * +rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid, + void *rsc, struct metal_io_region *rsc_io, + void *priv, + rpvdev_notify_func notify, + virtio_dev_reset_cb rst_cb); + +/** + * rproc_virtio_remove_vdev + * + * Create rproc virtio vdev + * + * @vdev - pointer to the virtio device + */ +void rproc_virtio_remove_vdev(struct virtio_device *vdev); + +/** + * rproc_virtio_create_vring + * + * Create rproc virtio vring + * + * @vdev: pointer to the virtio device + * @index: vring index in the virtio device + * @notifyid: remoteproc vring notification id + * @va: vring virtual address + * @io: pointer to vring I/O region + * @num_desc: number of descriptors + * @align: vring alignment + * + * return 0 for success, negative value for failure. + */ +int rproc_virtio_init_vring(struct virtio_device *vdev, unsigned int index, + unsigned int notifyid, void *va, + struct metal_io_region *io, + unsigned int num_descs, unsigned int align); + +/** + * rproc_virtio_notified + * + * remoteproc virtio is got notified + * + * @vdev - pointer to the virtio device + * @notifyid - notify id + * + * return 0 for successful, negative value for failure + */ +int rproc_virtio_notified(struct virtio_device *vdev, uint32_t notifyid); + +/** + * rproc_virtio_wait_remote_ready + * + * Blocking function, waiting for the remote core is ready to start + * communications. + * + * @vdev - pointer to the virtio device + * + * return true when remote processor is ready. + */ +void rproc_virtio_wait_remote_ready(struct virtio_device *vdev); + +#if defined __cplusplus +} +#endif + +#endif /* REMOTEPROC_VIRTIO_H */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/rpmsg.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/rpmsg.h new file mode 100644 index 000000000..868175159 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/rpmsg.h @@ -0,0 +1,357 @@ +/* + * Remote processor messaging + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Copyright (C) 2011 Google, Inc. + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _RPMSG_H_ +#define _RPMSG_H_ + +#include +#include +#include +#include +#include +#include + +#if defined __cplusplus +extern "C" { +#endif + +/* Configurable parameters */ +#define RPMSG_NAME_SIZE (32) +#define RPMSG_ADDR_BMP_SIZE (4) + +#define RPMSG_NS_EPT_ADDR (0x35) +#define RPMSG_ADDR_ANY 0xFFFFFFFF + +/* Error macros. */ +#define RPMSG_SUCCESS 0 +#define RPMSG_ERROR_BASE -2000 +#define RPMSG_ERR_NO_MEM (RPMSG_ERROR_BASE - 1) +#define RPMSG_ERR_NO_BUFF (RPMSG_ERROR_BASE - 2) +#define RPMSG_ERR_PARAM (RPMSG_ERROR_BASE - 3) +#define RPMSG_ERR_DEV_STATE (RPMSG_ERROR_BASE - 4) +#define RPMSG_ERR_BUFF_SIZE (RPMSG_ERROR_BASE - 5) +#define RPMSG_ERR_INIT (RPMSG_ERROR_BASE - 6) +#define RPMSG_ERR_ADDR (RPMSG_ERROR_BASE - 7) + +struct rpmsg_endpoint; +struct rpmsg_device; + +typedef int (*rpmsg_ept_cb)(struct rpmsg_endpoint *ept, void *data, + size_t len, uint32_t src, void *priv); +typedef void (*rpmsg_ns_unbind_cb)(struct rpmsg_endpoint *ept); +typedef void (*rpmsg_ns_bind_cb)(struct rpmsg_device *rdev, + const char *name, uint32_t dest); + +/** + * struct rpmsg_endpoint - binds a local rpmsg address to its user + * @name:name of the service supported + * @rdev: pointer to the rpmsg device + * @addr: local address of the endpoint + * @dest_addr: address of the default remote endpoint binded. + * @cb: user rx callback, return value of this callback is reserved + * for future use, for now, only allow RPMSG_SUCCESS as return value. + * @ns_unbind_cb: end point service service unbind callback, called when remote + * ept is destroyed. + * @node: end point node. + * @addr: local rpmsg address + * @priv: private data for the driver's use + * + * In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as + * it binds an rpmsg address with an rx callback handler. + */ +struct rpmsg_endpoint { + char name[RPMSG_NAME_SIZE]; + struct rpmsg_device *rdev; + uint32_t addr; + uint32_t dest_addr; + rpmsg_ept_cb cb; + rpmsg_ns_unbind_cb ns_unbind_cb; + struct metal_list node; + void *priv; +}; + +/** + * struct rpmsg_device_ops - RPMsg device operations + * @send_offchannel_raw: send RPMsg data + */ +struct rpmsg_device_ops { + int (*send_offchannel_raw)(struct rpmsg_device *rdev, + uint32_t src, uint32_t dst, + const void *data, int size, int wait); +}; + +/** + * struct rpmsg_device - representation of a RPMsg device + * @endpoints: list of endpoints + * @ns_ept: name service endpoint + * @bitmap: table endpoin address allocation. + * @lock: mutex lock for rpmsg management + * @ns_bind_cb: callback handler for name service announcement without local + * endpoints waiting to bind. + * @ops: RPMsg device operations + */ +struct rpmsg_device { + struct metal_list endpoints; + struct rpmsg_endpoint ns_ept; + unsigned long bitmap[RPMSG_ADDR_BMP_SIZE]; + metal_mutex_t lock; + rpmsg_ns_bind_cb ns_bind_cb; + struct rpmsg_device_ops ops; +}; + +/** + * rpmsg_send_offchannel_raw() - send a message across to the remote processor, + * specifying source and destination address. + * @ept: the rpmsg endpoint + * @data: payload of the message + * @len: length of the payload + * + * This function sends @data of length @len to the remote @dst address from + * the source @src address. + * The message will be sent to the remote processor which the channel belongs + * to. + * In case there are no TX buffers available, the function will block until + * one becomes available, or a timeout of 15 seconds elapses. When the latter + * happens, -ERESTARTSYS is returned. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, + uint32_t dst, const void *data, int size, + int wait); + +/** + * rpmsg_send() - send a message across to the remote processor + * @ept: the rpmsg endpoint + * @data: payload of the message + * @len: length of the payload + * + * This function sends @data of length @len based on the @ept. + * The message will be sent to the remote processor which the channel belongs + * to, using @ept's source and destination addresses. + * In case there are no TX buffers available, the function will block until + * one becomes available, or a timeout of 15 seconds elapses. When the latter + * happens, -ERESTARTSYS is returned. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_send(struct rpmsg_endpoint *ept, const void *data, + int len) +{ + if (ept->dest_addr == RPMSG_ADDR_ANY) + return RPMSG_ERR_ADDR; + return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data, + len, true); +} + +/** + * rpmsg_sendto() - send a message across to the remote processor, specify dst + * @ept: the rpmsg endpoint + * @data: payload of message + * @len: length of payload + * @dst: destination address + * + * This function sends @data of length @len to the remote @dst address. + * The message will be sent to the remote processor which the @ept + * channel belongs to, using @ept's source address. + * In case there are no TX buffers available, the function will block until + * one becomes available, or a timeout of 15 seconds elapses. When the latter + * happens, -ERESTARTSYS is returned. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_sendto(struct rpmsg_endpoint *ept, const void *data, + int len, uint32_t dst) +{ + return rpmsg_send_offchannel_raw(ept, ept->addr, dst, data, len, true); +} + +/** + * rpmsg_send_offchannel() - send a message using explicit src/dst addresses + * @ept: the rpmsg endpoint + * @src: source address + * @dst: destination address + * @data: payload of message + * @len: length of payload + * + * This function sends @data of length @len to the remote @dst address, + * and uses @src as the source address. + * The message will be sent to the remote processor which the @ept + * channel belongs to. + * In case there are no TX buffers available, the function will block until + * one becomes available, or a timeout of 15 seconds elapses. When the latter + * happens, -ERESTARTSYS is returned. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, + uint32_t src, uint32_t dst, + const void *data, int len) +{ + return rpmsg_send_offchannel_raw(ept, src, dst, data, len, true); +} + +/** + * rpmsg_trysend() - send a message across to the remote processor + * @ept: the rpmsg endpoint + * @data: payload of message + * @len: length of payload + * + * This function sends @data of length @len on the @ept channel. + * The message will be sent to the remote processor which the @ept + * channel belongs to, using @ept's source and destination addresses. + * In case there are no TX buffers available, the function will immediately + * return -ENOMEM without waiting until one becomes available. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_trysend(struct rpmsg_endpoint *ept, const void *data, + int len) +{ + if (ept->dest_addr == RPMSG_ADDR_ANY) + return RPMSG_ERR_ADDR; + return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data, + len, false); +} + +/** + * rpmsg_trysendto() - send a message across to the remote processor, + * specify dst + * @ept: the rpmsg endpoint + * @data: payload of message + * @len: length of payload + * @dst: destination address + * + * This function sends @data of length @len to the remote @dst address. + * The message will be sent to the remote processor which the @ept + * channel belongs to, using @ept's source address. + * In case there are no TX buffers available, the function will immediately + * return -ENOMEM without waiting until one becomes available. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_trysendto(struct rpmsg_endpoint *ept, const void *data, + int len, uint32_t dst) +{ + return rpmsg_send_offchannel_raw(ept, ept->addr, dst, data, len, false); +} + +/** + * rpmsg_trysend_offchannel() - send a message using explicit src/dst addresses + * @ept: the rpmsg endpoint + * @src: source address + * @dst: destination address + * @data: payload of message + * @len: length of payload + * + * This function sends @data of length @len to the remote @dst address, + * and uses @src as the source address. + * The message will be sent to the remote processor which the @ept + * channel belongs to. + * In case there are no TX buffers available, the function will immediately + * return -ENOMEM without waiting until one becomes available. + * + * Returns number of bytes it has sent or negative error value on failure. + */ +static inline int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, + uint32_t src, uint32_t dst, + const void *data, int len) +{ + return rpmsg_send_offchannel_raw(ept, src, dst, data, len, false); +} + +/** + * rpmsg_init_ept - initialize rpmsg endpoint + * + * Initialize an RPMsg endpoint with a name, source address, + * remoteproc address, endpoitn callback, and destroy endpoint callback. + * + * @ept: pointer to rpmsg endpoint + * @name: service name associated to the endpoint + * @src: local address of the endpoint + * @dest: target address of the endpoint + * @cb: endpoint callback + * @ns_unbind_cb: end point service unbind callback, called when remote ept is + * destroyed. + */ +static inline void rpmsg_init_ept(struct rpmsg_endpoint *ept, + const char *name, + uint32_t src, uint32_t dest, + rpmsg_ept_cb cb, + rpmsg_ns_unbind_cb ns_unbind_cb) +{ + strncpy(ept->name, name, sizeof(ept->name)); + ept->addr = src; + ept->dest_addr = dest; + ept->cb = cb; + ept->ns_unbind_cb = ns_unbind_cb; +} + +/** + * rpmsg_create_ept - create rpmsg endpoint and register it to rpmsg device + * + * Create a RPMsg endpoint, initialize it with a name, source address, + * remoteproc address, endpoitn callback, and destroy endpoint callback, + * and register it to the RPMsg device. + * + * @ept: pointer to rpmsg endpoint + * @name: service name associated to the endpoint + * @src: local address of the endpoint + * @dest: target address of the endpoint + * @cb: endpoint callback + * @ns_unbind_cb: end point service unbind callback, called when remote ept is + * destroyed. + * + * In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as + * it binds an rpmsg address with an rx callback handler. + * + * Rpmsg client should create an endpoint to discuss with remote. rpmsg client + * provide at least a channel name, a callback for message notification and by + * default endpoint source address should be set to RPMSG_ADDR_ANY. + * + * As an option Some rpmsg clients can specify an endpoint with a specific + * source address. + */ + +int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, + const char *name, uint32_t src, uint32_t dest, + rpmsg_ept_cb cb, rpmsg_ns_unbind_cb ns_unbind_cb); + +/** + * rpmsg_destroy_ept - destroy rpmsg endpoint and unregister it from rpmsg + * device + * + * @ept: pointer to the rpmsg endpoint + * + * It unregisters the rpmsg endpoint from the rpmsg device and calls the + * destroy endpoint callback if it is provided. + */ +void rpmsg_destroy_ept(struct rpmsg_endpoint *ept); + +/** + * is_rpmsg_ept_ready - check if the rpmsg endpoint ready to send + * + * @ept: pointer to rpmsg endpoint + * + * Returns 1 if the rpmsg endpoint has both local addr and destination + * addr set, 0 otherwise + */ +static inline unsigned int is_rpmsg_ept_ready(struct rpmsg_endpoint *ept) +{ + return (ept->dest_addr != RPMSG_ADDR_ANY && + ept->addr != RPMSG_ADDR_ANY); +} + +#if defined __cplusplus +} +#endif + +#endif /* _RPMSG_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/rpmsg_retarget.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/rpmsg_retarget.h new file mode 100644 index 000000000..1cde0ad08 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/rpmsg_retarget.h @@ -0,0 +1,119 @@ +#ifndef RPMSG_RETARGET_H +#define RPMSG_RETARGET_H + +#include +#include +#include + +#if defined __cplusplus +extern "C" { +#endif + +/* File Operations System call definitions */ +#define OPEN_SYSCALL_ID 0x1UL +#define CLOSE_SYSCALL_ID 0x2UL +#define WRITE_SYSCALL_ID 0x3UL +#define READ_SYSCALL_ID 0x4UL +#define ACK_STATUS_ID 0x5UL + +#define TERM_SYSCALL_ID 0x6UL + +#define DEFAULT_PROXY_ENDPOINT 0xFFUL + +struct rpmsg_rpc_data; + +typedef int (*rpmsg_rpc_poll)(void *arg); +typedef void (*rpmsg_rpc_shutdown_cb)(struct rpmsg_rpc_data *rpc); + +struct rpmsg_rpc_syscall_header { + int32_t int_field1; + int32_t int_field2; + uint32_t data_len; +}; + +struct rpmsg_rpc_syscall { + uint32_t id; + struct rpmsg_rpc_syscall_header args; +}; + +struct rpmsg_rpc_data { + struct rpmsg_endpoint ept; + int ept_destroyed; + atomic_flag nacked; + void *respbuf; + size_t respbuf_len; + rpmsg_rpc_poll poll; + void *poll_arg; + rpmsg_rpc_shutdown_cb shutdown_cb; + metal_mutex_t lock; + struct metal_spinlock buflock; +}; + +/** + * rpmsg_rpc_init - initialize RPMsg remote procedure call + * + * This function is to intialize the remote procedure call + * global data. RPMsg RPC will send request to remote and + * wait for callback. + * + * @rpc: pointer to the global remote procedure call data + * @rdev: pointer to the rpmsg device + * @ept_name: name of the endpoint used by RPC + * @ept_addr: address of the endpoint used by RPC + * @ept_raddr: remote address of the endpoint used by RPC + * @poll_arg: pointer to poll function argument + * @poll: poll function + * @shutdown_cb: shutdown callback function + * + * return 0 for success, and negative value for failure. + */ +int rpmsg_rpc_init(struct rpmsg_rpc_data *rpc, + struct rpmsg_device *rdev, + const char *ept_name, uint32_t ept_addr, + uint32_t ept_raddr, + void *poll_arg, rpmsg_rpc_poll poll, + rpmsg_rpc_shutdown_cb shutdown_cb); + +/** + * rpmsg_rpc_release - release RPMsg remote procedure call + * + * This function is to release remoteproc procedure call + * global data. + * + * @rpc: pointer to the globacl remote procedure call + */ +void rpmsg_rpc_release(struct rpmsg_rpc_data *rpc); + +/** + * rpmsg_rpc_send - Request RPMsg RPC call + * + * This function sends RPC request it will return with the length + * of data and the response buffer. + * + * @rpc: pointer to remoteproc procedure call data struct + * @req: pointer to request buffer + * @len: length of the request data + * @resp: pointer to where store the response buffer + * @resp_len: length of the response buffer + * + * return length of the received response, negative value for failure. + */ +int rpmsg_rpc_send(struct rpmsg_rpc_data *rpc, + void *req, size_t len, + void *resp, size_t resp_len); + +/** + * rpmsg_set_default_rpc - set default RPMsg RPC data + * + * The default RPC data is used to redirect standard C file operations + * to RPMsg channels. + * + * @rpc: pointer to remoteproc procedure call data struct + */ +void rpmsg_set_default_rpc(struct rpmsg_rpc_data *rpc); + +#if defined __cplusplus +} +#endif + +#endif /* RPMSG_RETARGET_H */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/rpmsg_virtio.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/rpmsg_virtio.h new file mode 100644 index 000000000..ea0a255d5 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/rpmsg_virtio.h @@ -0,0 +1,190 @@ +/* + * rpmsg based on virtio + * + * Copyright (C) 2018 Linaro, Inc. + * + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _RPMSG_VIRTIO_H_ +#define _RPMSG_VIRTIO_H_ + +#include +#include +#include +#include + +#if defined __cplusplus +extern "C" { +#endif + +/* Configurable parameters */ +#ifndef RPMSG_BUFFER_SIZE +#define RPMSG_BUFFER_SIZE (512) +#endif + +/* The feature bitmap for virtio rpmsg */ +#define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ + +struct rpmsg_virtio_shm_pool; +/** + * struct rpmsg_virtio_shm_pool - shared memory pool used for rpmsg buffers + * @get_buffer: function to get buffer from the pool + * @base: base address of the memory pool + * @avail: available memory size + * @size: total pool size + */ +struct rpmsg_virtio_shm_pool { + void *base; + size_t avail; + size_t size; +}; + +/** + * struct rpmsg_virtio_device - representation of a rpmsg device based on virtio + * @rdev: rpmsg device, first property in the struct + * @vdev: pointer to the virtio device + * @rvq: pointer to receive virtqueue + * @svq: pointer to send virtqueue + * @shbuf_io: pointer to the shared buffer I/O region + * @shpool: pointer to the shared buffers pool + * @endpoints: list of endpoints. + */ +struct rpmsg_virtio_device { + struct rpmsg_device rdev; + struct virtio_device *vdev; + struct virtqueue *rvq; + struct virtqueue *svq; + struct metal_io_region *shbuf_io; + struct rpmsg_virtio_shm_pool *shpool; +}; + +#define RPMSG_REMOTE VIRTIO_DEV_SLAVE +#define RPMSG_MASTER VIRTIO_DEV_MASTER +static inline unsigned int + rpmsg_virtio_get_role(struct rpmsg_virtio_device *rvdev) +{ + return rvdev->vdev->role; +} + +static inline void rpmsg_virtio_set_status(struct rpmsg_virtio_device *rvdev, + uint8_t status) +{ + rvdev->vdev->func->set_status(rvdev->vdev, status); +} + +static inline uint8_t rpmsg_virtio_get_status(struct rpmsg_virtio_device *rvdev) +{ + return rvdev->vdev->func->get_status(rvdev->vdev); +} + +static inline uint32_t + rpmsg_virtio_get_features(struct rpmsg_virtio_device *rvdev) +{ + return rvdev->vdev->func->get_features(rvdev->vdev); +} + +static inline int + rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev, + int flags, unsigned int nvqs, + const char *names[], + vq_callback * callbacks[]) +{ + return virtio_create_virtqueues(rvdev->vdev, flags, nvqs, names, + callbacks); +} + +/** + * rpmsg_virtio_get_buffer_size - get rpmsg virtio buffer size + * + * @rdev - pointer to the rpmsg device + * + * @return - next available buffer size for text, negative value for failure + */ +int rpmsg_virtio_get_buffer_size(struct rpmsg_device *rdev); + +/** + * rpmsg_init_vdev - initialize rpmsg virtio device + * Master side: + * Initialize RPMsg virtio queues and shared buffers, the address of shm can be + * ANY. In this case, function will get shared memory from system shared memory + * pools. If the vdev has RPMsg name service feature, this API will create an + * name service endpoint. + * + * Slave side: + * This API will not return until the driver ready is set by the master side. + * + * @param rvdev - pointer to the rpmsg virtio device + * @param vdev - pointer to the virtio device + * @param ns_bind_cb - callback handler for name service announcement without + * local endpoints waiting to bind. + * @param shm_io - pointer to the share memory I/O region. + * @param shpool - pointer to shared memory pool. rpmsg_virtio_init_shm_pool has + * to be called first to fill this structure. + * + * @return - status of function execution + */ +int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + struct virtio_device *vdev, + rpmsg_ns_bind_cb ns_bind_cb, + struct metal_io_region *shm_io, + struct rpmsg_virtio_shm_pool *shpool); + +/** + * rpmsg_deinit_vdev - deinitialize rpmsg virtio device + * + * @param rvdev - pointer to the rpmsg virtio device + */ +void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev); + +/** + * rpmsg_virtio_init_shm_pool - initialize default shared buffers pool + * + * RPMsg virtio has default shared buffers pool implementation. + * The memory assigned to this pool will be dedicated to the RPMsg + * virtio. This function has to be called before calling rpmsg_init_vdev, + * to initialize the rpmsg_virtio_shm_pool structure. + * + * @param shpool - pointer to the shared buffers pool structure + * @param shbuf - pointer to the beginning of shared buffers + * @param size - shared buffers total size + */ +void rpmsg_virtio_init_shm_pool(struct rpmsg_virtio_shm_pool *shpool, + void *shbuf, size_t size); + +/** + * rpmsg_virtio_get_rpmsg_device - get RPMsg device from RPMsg virtio device + * + * @param rvdev - pointer to RPMsg virtio device + * @return - RPMsg device pointed by RPMsg virtio device + */ +static inline struct rpmsg_device * +rpmsg_virtio_get_rpmsg_device(struct rpmsg_virtio_device *rvdev) +{ + return &rvdev->rdev; +} + +/** + * rpmsg_virtio_shm_pool_get_buffer - get buffer in the shared memory pool + * + * RPMsg virtio has default shared buffers pool implementation. + * The memory assigned to this pool will be dedicated to the RPMsg + * virtio. If you prefer to have other shared buffers allocation, + * you can implement your rpmsg_virtio_shm_pool_get_buffer function. + * + * @param shpool - pointer to the shared buffers pool + * @param size - shared buffers total size + * @return - buffer pointer if free buffer is available, NULL otherwise. + */ +metal_weak void * +rpmsg_virtio_shm_pool_get_buffer(struct rpmsg_virtio_shm_pool *shpool, + size_t size); + +#if defined __cplusplus +} +#endif + +#endif /* _RPMSG_VIRTIO_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/rsc_table_parser.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/rsc_table_parser.h new file mode 100644 index 000000000..6802d03fd --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/rsc_table_parser.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RSC_TABLE_PARSER_H +#define RSC_TABLE_PARSER_H + +#include + +#if defined __cplusplus +extern "C" { +#endif + +#define RSC_TAB_SUPPORTED_VERSION 1 +#define RSC_TAB_HEADER_SIZE 12 +#define RSC_TAB_MAX_VRINGS 2 + +/* Standard control request handling. */ +typedef int (*rsc_handler) (struct remoteproc *rproc, void *rsc); + +/** + * handle_rsc_table + * + * This function parses resource table. + * + * @param rproc - pointer to remote remoteproc + * @param rsc_table - resource table to parse + * @param size - size of rsc table + * @param io - pointer to the resource table I/O region + * It can be NULL if the resource table + * is in the local memory. + * + * @returns - execution status + * + */ +int handle_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, int len, + struct metal_io_region *io); +int handle_carve_out_rsc(struct remoteproc *rproc, void *rsc); +int handle_trace_rsc(struct remoteproc *rproc, void *rsc); +int handle_vdev_rsc(struct remoteproc *rproc, void *rsc); +int handle_vendor_rsc(struct remoteproc *rproc, void *rsc); + +/** + * find_rsc + * + * find out location of a resource type in the resource table. + * + * @rsc_table - pointer to the resource table + * @rsc_type - type of the resource + * @index - index of the resource of the specified type + * + * return the offset to the resource on success, or 0 on failure + */ +size_t find_rsc(void *rsc_table, unsigned int rsc_type, unsigned int index); + +#if defined __cplusplus +} +#endif + +#endif /* RSC_TABLE_PARSER_H */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/virtio.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/virtio.h new file mode 100644 index 000000000..51a4740f5 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/virtio.h @@ -0,0 +1,176 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * $FreeBSD$ + */ + +#ifndef _VIRTIO_H_ +#define _VIRTIO_H_ + +#include +#include + +#if defined __cplusplus +extern "C" { +#endif + +/* TODO: define this as compiler flags */ +#ifndef VIRTIO_MAX_NUM_VRINGS +#define VIRTIO_MAX_NUM_VRINGS 2 +#endif + +/* VirtIO device IDs. */ +#define VIRTIO_ID_NETWORK 0x01UL +#define VIRTIO_ID_BLOCK 0x02UL +#define VIRTIO_ID_CONSOLE 0x03UL +#define VIRTIO_ID_ENTROPY 0x04UL +#define VIRTIO_ID_BALLOON 0x05UL +#define VIRTIO_ID_IOMEMORY 0x06UL +#define VIRTIO_ID_RPMSG 0x07UL /* remote processor messaging */ +#define VIRTIO_ID_SCSI 0x08UL +#define VIRTIO_ID_9P 0x09UL +#define VIRTIO_DEV_ANY_ID (-1)UL + +/* Status byte for guest to report progress. */ +#define VIRTIO_CONFIG_STATUS_ACK 0x01 +#define VIRTIO_CONFIG_STATUS_DRIVER 0x02 +#define VIRTIO_CONFIG_STATUS_DRIVER_OK 0x04 +#define VIRTIO_CONFIG_STATUS_NEEDS_RESET 0x40 +#define VIRTIO_CONFIG_STATUS_FAILED 0x80 + +/* Virtio device role */ +#define VIRTIO_DEV_MASTER 0UL +#define VIRTIO_DEV_SLAVE 1UL + +struct virtio_device_id { + uint32_t device; + uint32_t vendor; +}; + +/* + * Generate interrupt when the virtqueue ring is + * completely used, even if we've suppressed them. + */ +#define VIRTIO_F_NOTIFY_ON_EMPTY (1 << 24) + +/* + * The guest should never negotiate this feature; it + * is used to detect faulty drivers. + */ +#define VIRTIO_F_BAD_FEATURE (1 << 30) + +/* + * Some VirtIO feature bits (currently bits 28 through 31) are + * reserved for the transport being used (eg. virtio_ring), the + * rest are per-device feature bits. + */ +#define VIRTIO_TRANSPORT_F_START 28 +#define VIRTIO_TRANSPORT_F_END 32 + +typedef void (*virtio_dev_reset_cb)(struct virtio_device *vdev); + +struct virtio_dispatch; + +struct virtio_feature_desc { + uint32_t vfd_val; + const char *vfd_str; +}; + +/** + * struct proc_shm + * + * This structure is maintained by hardware interface layer for + * shared memory information. The shared memory provides buffers + * for use by the vring to exchange messages between the cores. + * + */ +struct virtio_buffer_info { + /* Start address of shared memory used for buffers. */ + void *vaddr; + /* Start physical address of shared memory used for buffers. */ + metal_phys_addr_t paddr; + /* sharmed memory I/O region */ + struct metal_io_region *io; + /* Size of shared memory. */ + unsigned long size; +}; + +/** + * struct remoteproc_vring - remoteproc vring structure + * @vq virtio queue + * @va logical address + * @notifyid vring notify id + * @num_descs number of descriptors + * @align vring alignment + * @io metal I/O region of the vring memory, can be NULL + */ +struct virtio_vring_info { + struct virtqueue *vq; + struct vring_alloc_info info; + uint32_t notifyid; + struct metal_io_region *io; +}; + +/* + * Structure definition for virtio devices for use by the + * applications/drivers + */ + +struct virtio_device { + uint32_t index; /**< unique position on the virtio bus */ + struct virtio_device_id id; /**< the device type identification + * (used to match it with a driver + */ + uint64_t features; /**< the features supported by both ends. */ + unsigned int role; /**< if it is virtio backend or front end. */ + virtio_dev_reset_cb reset_cb; /**< user registered device callback */ + const struct virtio_dispatch *func; /**< Virtio dispatch table */ + void *priv; /**< TODO: remove pointer to virtio_device private data */ + unsigned int vrings_num; /**< number of vrings */ + struct virtio_vring_info *vrings_info; +}; + +/* + * Helper functions. + */ +const char *virtio_dev_name(uint16_t devid); +void virtio_describe(struct virtio_device *dev, const char *msg, + uint32_t features, + struct virtio_feature_desc *feature_desc); + +/* + * Functions for virtio device configuration as defined in Rusty Russell's + * paper. + * Drivers are expected to implement these functions in their respective codes. + */ + +struct virtio_dispatch { + uint8_t (*get_status)(struct virtio_device *dev); + void (*set_status)(struct virtio_device *dev, uint8_t status); + uint32_t (*get_features)(struct virtio_device *dev); + void (*set_features)(struct virtio_device *dev, uint32_t feature); + uint32_t (*negotiate_features)(struct virtio_device *dev, + uint32_t features); + + /* + * Read/write a variable amount from the device specific (ie, network) + * configuration region. This region is encoded in the same endian as + * the guest. + */ + void (*read_config)(struct virtio_device *dev, uint32_t offset, + void *dst, int length); + void (*write_config)(struct virtio_device *dev, uint32_t offset, + void *src, int length); + void (*reset_device)(struct virtio_device *dev); + void (*notify)(struct virtqueue *vq); +}; + +int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags, + unsigned int nvqs, const char *names[], + vq_callback *callbacks[]); + +#if defined __cplusplus +} +#endif + +#endif /* _VIRTIO_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/virtio_ring.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/virtio_ring.h new file mode 100644 index 000000000..3f348e3fa --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/virtio_ring.h @@ -0,0 +1,152 @@ +/* + * Copyright Rusty Russell IBM Corporation 2007. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * $FreeBSD$ + */ + +#ifndef VIRTIO_RING_H +#define VIRTIO_RING_H + +#if defined __cplusplus +extern "C" { +#endif + +/* This marks a buffer as continuing via the next field. */ +#define VRING_DESC_F_NEXT 1 +/* This marks a buffer as write-only (otherwise read-only). */ +#define VRING_DESC_F_WRITE 2 +/* This means the buffer contains a list of buffer descriptors. */ +#define VRING_DESC_F_INDIRECT 4 + +/* The Host uses this in used->flags to advise the Guest: don't kick me + * when you add a buffer. It's unreliable, so it's simply an + * optimization. Guest will still kick if it's out of buffers. + */ +#define VRING_USED_F_NO_NOTIFY 1 +/* The Guest uses this in avail->flags to advise the Host: don't + * interrupt me when you consume a buffer. It's unreliable, so it's + * simply an optimization. + */ +#define VRING_AVAIL_F_NO_INTERRUPT 1 + +/* VirtIO ring descriptors: 16 bytes. + * These can chain together via "next". + */ +struct vring_desc { + /* Address (guest-physical). */ + uint64_t addr; + /* Length. */ + uint32_t len; + /* The flags as indicated above. */ + uint16_t flags; + /* We chain unused descriptors via this, too. */ + uint16_t next; +}; + +struct vring_avail { + uint16_t flags; + uint16_t idx; + uint16_t ring[0]; +}; + +/* uint32_t is used here for ids for padding reasons. */ +struct vring_used_elem { + /* Index of start of used descriptor chain. */ + uint32_t id; + /* Total length of the descriptor chain which was written to. */ + uint32_t len; +}; + +struct vring_used { + uint16_t flags; + uint16_t idx; + struct vring_used_elem ring[0]; +}; + +struct vring { + unsigned int num; + + struct vring_desc *desc; + struct vring_avail *avail; + struct vring_used *used; +}; + +/* The standard layout for the ring is a continuous chunk of memory which + * looks like this. We assume num is a power of 2. + * + * struct vring { + * // The actual descriptors (16 bytes each) + * struct vring_desc desc[num]; + * + * // A ring of available descriptor heads with free-running index. + * __u16 avail_flags; + * __u16 avail_idx; + * __u16 available[num]; + * __u16 used_event_idx; + * + * // Padding to the next align boundary. + * char pad[]; + * + * // A ring of used descriptor heads with free-running index. + * __u16 used_flags; + * __u16 used_idx; + * struct vring_used_elem used[num]; + * __u16 avail_event_idx; + * }; + * + * NOTE: for VirtIO PCI, align is 4096. + */ + +/* + * We publish the used event index at the end of the available ring, and vice + * versa. They are at the end for backwards compatibility. + */ +#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num]) +#define vring_avail_event(vr) ((vr)->used->ring[(vr)->num].id & 0xFFFF) + +static inline int vring_size(unsigned int num, unsigned long align) +{ + int size; + + size = num * sizeof(struct vring_desc); + size += sizeof(struct vring_avail) + (num * sizeof(uint16_t)) + + sizeof(uint16_t); + size = (size + align - 1) & ~(align - 1); + size += sizeof(struct vring_used) + + (num * sizeof(struct vring_used_elem)) + sizeof(uint16_t); + + return size; +} + +static inline void +vring_init(struct vring *vr, unsigned int num, uint8_t *p, unsigned long align) +{ + vr->num = num; + vr->desc = (struct vring_desc *)p; + vr->avail = (struct vring_avail *)(p + num * sizeof(struct vring_desc)); + vr->used = (struct vring_used *) + (((unsigned long)&vr->avail->ring[num] + sizeof(uint16_t) + + align - 1) & ~(align - 1)); +} + +/* + * The following is used with VIRTIO_RING_F_EVENT_IDX. + * + * Assuming a given event_idx value from the other size, if we have + * just incremented index from old to new_idx, should we trigger an + * event? + */ +static inline int +vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old) +{ + return (uint16_t)(new_idx - event_idx - 1) < + (uint16_t)(new_idx - old); +} + +#if defined __cplusplus +} +#endif + +#endif /* VIRTIO_RING_H */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/virtqueue.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/virtqueue.h new file mode 100644 index 000000000..74e8411a6 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/include/openamp/virtqueue.h @@ -0,0 +1,238 @@ +#ifndef VIRTQUEUE_H_ +#define VIRTQUEUE_H_ + +/*- + * Copyright (c) 2011, Bryan Venteicher + * All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + * + * $FreeBSD$ + */ + +#include +#include + +#if defined __cplusplus +extern "C" { +#endif + +typedef uint8_t boolean; + +#include +#include +#include + +/*Error Codes*/ +#define VQ_ERROR_BASE -3000 +#define ERROR_VRING_FULL (VQ_ERROR_BASE - 1) +#define ERROR_INVLD_DESC_IDX (VQ_ERROR_BASE - 2) +#define ERROR_EMPTY_RING (VQ_ERROR_BASE - 3) +#define ERROR_NO_MEM (VQ_ERROR_BASE - 4) +#define ERROR_VRING_MAX_DESC (VQ_ERROR_BASE - 5) +#define ERROR_VRING_ALIGN (VQ_ERROR_BASE - 6) +#define ERROR_VRING_NO_BUFF (VQ_ERROR_BASE - 7) +#define ERROR_VQUEUE_INVLD_PARAM (VQ_ERROR_BASE - 8) + +#define VQUEUE_SUCCESS 0 + +/* The maximum virtqueue size is 2^15. Use that value as the end of + * descriptor chain terminator since it will never be a valid index + * in the descriptor table. This is used to verify we are correctly + * handling vq_free_cnt. + */ +#define VQ_RING_DESC_CHAIN_END 32768 +#define VIRTQUEUE_FLAG_INDIRECT 0x0001 +#define VIRTQUEUE_FLAG_EVENT_IDX 0x0002 +#define VIRTQUEUE_MAX_NAME_SZ 32 + +/* Support for indirect buffer descriptors. */ +#define VIRTIO_RING_F_INDIRECT_DESC (1 << 28) + +/* Support to suppress interrupt until specific index is reached. */ +#define VIRTIO_RING_F_EVENT_IDX (1 << 29) + +struct virtqueue_buf { + void *buf; + int len; +}; + +struct vq_desc_extra { + void *cookie; + uint16_t ndescs; +}; + +struct virtqueue { + struct virtio_device *vq_dev; + const char *vq_name; + uint16_t vq_queue_index; + uint16_t vq_nentries; + uint32_t vq_flags; + void (*callback)(struct virtqueue *vq); + void (*notify)(struct virtqueue *vq); + struct vring vq_ring; + uint16_t vq_free_cnt; + uint16_t vq_queued_cnt; + void *shm_io; /* opaque pointer to data needed to allow v2p & p2v */ + + /* + * Head of the free chain in the descriptor table. If + * there are no free descriptors, this will be set to + * VQ_RING_DESC_CHAIN_END. + */ + uint16_t vq_desc_head_idx; + + /* + * Last consumed descriptor in the used table, + * trails vq_ring.used->idx. + */ + uint16_t vq_used_cons_idx; + + /* + * Last consumed descriptor in the available table - + * used by the consumer side. + */ + uint16_t vq_available_idx; + +#ifdef VQUEUE_DEBUG + boolean vq_inuse; +#endif + + /* + * Used by the host side during callback. Cookie + * holds the address of buffer received from other side. + * Other fields in this structure are not used currently. + */ + + struct vq_desc_extra vq_descx[0]; +}; + +/* struct to hold vring specific information */ +struct vring_alloc_info { + void *vaddr; + uint32_t align; + uint16_t num_descs; + uint16_t pad; +}; + +typedef void vq_callback(struct virtqueue *); +typedef void vq_notify(struct virtqueue *); + +#ifdef VQUEUE_DEBUG +#include +#include + +#define VQASSERT(_vq, _exp, _msg) \ + do { \ + if (!(_exp)) { \ + metal_log(METAL_LOG_EMERGENCY, \ + "%s: %s - _msg", __func__, (_vq)->vq_name); \ + metal_assert(_exp); \ + } \ + } while (0) + +#define VQ_RING_ASSERT_VALID_IDX(_vq, _idx) \ + VQASSERT((_vq), (_idx) < (_vq)->vq_nentries, "invalid ring index") + +#define VQ_RING_ASSERT_CHAIN_TERM(_vq) \ + VQASSERT((_vq), (_vq)->vq_desc_head_idx == \ + VQ_RING_DESC_CHAIN_END, \ + "full ring terminated incorrectly: invalid head") + +#define VQ_PARAM_CHK(condition, status_var, status_err) \ + do { \ + if (((status_var) == 0) && (condition)) { \ + status_var = status_err; \ + } \ + } while (0) + +#define VQUEUE_BUSY(vq) \ + do { \ + if (!(vq)->vq_inuse) \ + (vq)->vq_inuse = true; \ + else \ + VQASSERT(vq, !(vq)->vq_inuse,\ + "VirtQueue already in use"); \ + } while (0) + +#define VQUEUE_IDLE(vq) ((vq)->vq_inuse = false) + +#else + +#define KASSERT(cond, str) +#define VQASSERT(_vq, _exp, _msg) +#define VQ_RING_ASSERT_VALID_IDX(_vq, _idx) +#define VQ_RING_ASSERT_CHAIN_TERM(_vq) +#define VQ_PARAM_CHK(condition, status_var, status_err) +#define VQUEUE_BUSY(vq) +#define VQUEUE_IDLE(vq) + +#endif + +int virtqueue_create(struct virtio_device *device, unsigned short id, + const char *name, struct vring_alloc_info *ring, + void (*callback)(struct virtqueue *vq), + void (*notify)(struct virtqueue *vq), + struct virtqueue *v_queue); + +/* + * virtqueue_set_shmem_io + * + * set virtqueue shared memory I/O region + * + * @vq - virt queue + * @io - pointer to the shared memory I/O region + */ +static inline void virtqueue_set_shmem_io(struct virtqueue *vq, + struct metal_io_region *io) +{ + vq->shm_io = io; +} + +int virtqueue_add_buffer(struct virtqueue *vq, struct virtqueue_buf *buf_list, + int readable, int writable, void *cookie); + +void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len, uint16_t *idx); + +void *virtqueue_get_available_buffer(struct virtqueue *vq, uint16_t *avail_idx, + uint32_t *len); + +int virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx, + uint32_t len); + +void virtqueue_disable_cb(struct virtqueue *vq); + +int virtqueue_enable_cb(struct virtqueue *vq); + +void virtqueue_kick(struct virtqueue *vq); + +static inline struct virtqueue *virtqueue_allocate(unsigned int num_desc_extra) +{ + struct virtqueue *vqs; + uint32_t vq_size = sizeof(struct virtqueue) + + num_desc_extra * sizeof(struct vq_desc_extra); + + vqs = (struct virtqueue *)metal_allocate_memory(vq_size); + + if (vqs) { + memset(vqs, 0x00, vq_size); + } + + return vqs; +} + +void virtqueue_free(struct virtqueue *vq); + +void virtqueue_dump(struct virtqueue *vq); + +void virtqueue_notification(struct virtqueue *vq); + +uint32_t virtqueue_get_desc_size(struct virtqueue *vq); + +uint32_t virtqueue_get_buffer_length(struct virtqueue *vq, uint16_t idx); + +#if defined __cplusplus +} +#endif + +#endif /* VIRTQUEUE_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/Makefile b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/Makefile new file mode 100644 index 000000000..962b34d0b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/Makefile @@ -0,0 +1,5 @@ +SRC_DIR := + +SRC_FILES := $(wildcard *.c) + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/elf_loader.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/elf_loader.c new file mode 100644 index 000000000..835acc856 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/elf_loader.c @@ -0,0 +1,711 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +static int elf_is_64(const void *elf_info) +{ + const unsigned char *tmp = elf_info; + + if (tmp[EI_CLASS] == ELFCLASS64) + return 1; + else + return 0; +} + +static size_t elf_ehdr_size(const void *elf_info) +{ + if (elf_info == NULL) + return sizeof(Elf64_Ehdr); + else if (elf_is_64(elf_info) != 0) + return sizeof(Elf64_Ehdr); + else + return sizeof(Elf32_Ehdr); +} + +static size_t elf_phoff(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_phoff; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_phoff; + } +} + +static size_t elf_phentsize(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_phentsize; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_phentsize; + } +} + +static int elf_phnum(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_phnum; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_phnum; + } +} + +static size_t elf_shoff(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_shoff; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_shoff; + } +} + +static size_t elf_shentsize(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_shentsize; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_shentsize; + } +} + +static int elf_shnum(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_shnum; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_shnum; + } +} + +static int elf_shstrndx(const void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Ehdr *ehdr = elf_info; + + return ehdr->e_shstrndx; + } else { + const Elf64_Ehdr *ehdr = elf_info; + + return ehdr->e_shstrndx; + } +} + +static void *elf_phtable_ptr(void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + + return (void *)&einfo->phdrs; + } else { + struct elf64_info *einfo = elf_info; + + return (void *)&einfo->phdrs; + } +} + +static void *elf_shtable_ptr(void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + + return (void *)(&einfo->shdrs); + } else { + struct elf64_info *einfo = elf_info; + + return (void *)(&einfo->shdrs); + } +} + +static void **elf_shstrtab_ptr(void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + + return &einfo->shstrtab; + } else { + struct elf64_info *einfo = elf_info; + + return &einfo->shstrtab; + } +} + +static unsigned int *elf_load_state(void *elf_info) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + + return &einfo->load_state; + } else { + struct elf64_info *einfo = elf_info; + + return &einfo->load_state; + } +} + +static void elf_parse_segment(void *elf_info, const void *elf_phdr, + unsigned int *p_type, size_t *p_offset, + metal_phys_addr_t *p_vaddr, + metal_phys_addr_t *p_paddr, + size_t *p_filesz, size_t *p_memsz) +{ + if (elf_is_64(elf_info) == 0) { + const Elf32_Phdr *phdr = elf_phdr; + + if (p_type != NULL) + *p_type = (unsigned int)phdr->p_type; + if (p_offset != NULL) + *p_offset = (size_t)phdr->p_offset; + if (p_vaddr != NULL) + *p_vaddr = (metal_phys_addr_t)phdr->p_vaddr; + if (p_paddr != NULL) + *p_paddr = (metal_phys_addr_t)phdr->p_paddr; + if (p_filesz != NULL) + *p_filesz = (size_t)phdr->p_filesz; + if (p_memsz != NULL) + *p_memsz = (size_t)phdr->p_memsz; + } else { + const Elf64_Phdr *phdr = elf_phdr; + + if (p_type != NULL) + *p_type = (unsigned int)phdr->p_type; + if (p_offset != NULL) + *p_offset = (size_t)phdr->p_offset; + if (p_vaddr != NULL) + if (p_vaddr != NULL) + *p_vaddr = (metal_phys_addr_t)phdr->p_vaddr; + if (p_paddr != NULL) + *p_paddr = (metal_phys_addr_t)phdr->p_paddr; + if (p_filesz != NULL) + *p_filesz = (size_t)phdr->p_filesz; + if (p_memsz != NULL) + *p_memsz = (size_t)phdr->p_memsz; + } +} + +static const void *elf_get_segment_from_index(void *elf_info, int index) +{ + if (elf_is_64(elf_info) == 0) { + const struct elf32_info *einfo = elf_info; + const Elf32_Ehdr *ehdr = &einfo->ehdr; + const Elf32_Phdr *phdrs = einfo->phdrs; + + if (phdrs == NULL) + return NULL; + if (index < 0 || index > ehdr->e_phnum) + return NULL; + return &phdrs[index]; + } else { + const struct elf64_info *einfo = elf_info; + const Elf64_Ehdr *ehdr = &einfo->ehdr; + const Elf64_Phdr *phdrs = einfo->phdrs; + + if (phdrs == NULL) + return NULL; + if (index < 0 || index > ehdr->e_phnum) + return NULL; + return &phdrs[index]; + } +} + +static void *elf_get_section_from_name(void *elf_info, const char *name) +{ + unsigned int i; + const char *name_table; + + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + Elf32_Ehdr *ehdr = &einfo->ehdr; + Elf32_Shdr *shdr = einfo->shdrs; + + name_table = einfo->shstrtab; + if (shdr == NULL || name_table == NULL) + return NULL; + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + if (strcmp(name, name_table + shdr->sh_name)) + continue; + else + return shdr; + } + } else { + struct elf64_info *einfo = elf_info; + Elf64_Ehdr *ehdr = &einfo->ehdr; + Elf64_Shdr *shdr = einfo->shdrs; + + name_table = einfo->shstrtab; + if (shdr == NULL || name_table == NULL) + return NULL; + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + if (strcmp(name, name_table + shdr->sh_name)) + continue; + else + return shdr; + } + } + return NULL; +} + +static void *elf_get_section_from_index(void *elf_info, int index) +{ + if (elf_is_64(elf_info) == 0) { + struct elf32_info *einfo = elf_info; + Elf32_Ehdr *ehdr = &einfo->ehdr; + Elf32_Shdr *shdr = einfo->shdrs; + + if (shdr == NULL) + return NULL; + if (index > ehdr->e_shnum) + return NULL; + return &einfo->shdrs[index]; + } else { + struct elf64_info *einfo = elf_info; + Elf64_Ehdr *ehdr = &einfo->ehdr; + Elf64_Shdr *shdr = einfo->shdrs; + + if (shdr == NULL) + return NULL; + if (index > ehdr->e_shnum) + return NULL; + return &einfo->shdrs[index]; + } +} + +static void elf_parse_section(void *elf_info, void *elf_shdr, + unsigned int *sh_type, unsigned int *sh_flags, + metal_phys_addr_t *sh_addr, + size_t *sh_offset, size_t *sh_size, + unsigned int *sh_link, unsigned int *sh_info, + unsigned int *sh_addralign, + size_t *sh_entsize) +{ + if (elf_is_64(elf_info) == 0) { + Elf32_Shdr *shdr = elf_shdr; + + if (sh_type != NULL) + *sh_type = shdr->sh_type; + if (sh_flags != NULL) + *sh_flags = shdr->sh_flags; + if (sh_addr != NULL) + *sh_addr = (metal_phys_addr_t)shdr->sh_addr; + if (sh_offset != NULL) + *sh_offset = shdr->sh_offset; + if (sh_size != NULL) + *sh_size = shdr->sh_size; + if (sh_link != NULL) + *sh_link = shdr->sh_link; + if (sh_info != NULL) + *sh_info = shdr->sh_info; + if (sh_addralign != NULL) + *sh_addralign = shdr->sh_addralign; + if (sh_entsize != NULL) + *sh_entsize = shdr->sh_entsize; + } else { + Elf64_Shdr *shdr = elf_shdr; + + if (sh_type != NULL) + *sh_type = shdr->sh_type; + if (sh_flags != NULL) + *sh_flags = shdr->sh_flags; + if (sh_addr != NULL) + *sh_addr = (metal_phys_addr_t)(shdr->sh_addr & + (metal_phys_addr_t)(-1)); + if (sh_offset != NULL) + *sh_offset = shdr->sh_offset; + if (sh_size != NULL) + *sh_size = shdr->sh_size; + if (sh_link != NULL) + *sh_link = shdr->sh_link; + if (sh_info != NULL) + *sh_info = shdr->sh_info; + if (sh_addralign != NULL) + *sh_addralign = shdr->sh_addralign; + if (sh_entsize != NULL) + *sh_entsize = shdr->sh_entsize; + } +} + +static const void *elf_next_load_segment(void *elf_info, int *nseg, + metal_phys_addr_t *da, + size_t *noffset, size_t *nfsize, + size_t *nmsize) +{ + const void *phdr; + unsigned int p_type = PT_NULL; + + if (elf_info == NULL || nseg == NULL) + return NULL; + while(p_type != PT_LOAD) { + phdr = elf_get_segment_from_index(elf_info, *nseg); + if (phdr == NULL) + return NULL; + elf_parse_segment(elf_info, phdr, &p_type, noffset, + da, NULL, nfsize, nmsize); + *nseg = *nseg + 1; + } + return phdr; +} + +static size_t elf_info_size(const void *img_data) +{ + if (elf_is_64(img_data) == 0) + return sizeof(struct elf32_info); + else + return sizeof(struct elf64_info); +} + +int elf_identify(const void *img_data, size_t len) +{ + if (len < SELFMAG || img_data == NULL) + return -RPROC_EINVAL; + if (memcmp(img_data, ELFMAG, SELFMAG) != 0) + return -RPROC_EINVAL; + else + return 0; +} + +int elf_load_header(const void *img_data, size_t offset, size_t len, + void **img_info, int last_load_state, + size_t *noffset, size_t *nlen) +{ + unsigned int *load_state; + + metal_assert(noffset != NULL); + metal_assert(nlen != NULL); + /* Get ELF header */ + if (last_load_state == ELF_STATE_INIT) { + size_t tmpsize; + + metal_log(METAL_LOG_DEBUG, "Loading ELF headering\r\n"); + tmpsize = elf_ehdr_size(img_data); + if (len < tmpsize) { + *noffset = 0; + *nlen = tmpsize; + return ELF_STATE_INIT; + } else { + size_t infosize = elf_info_size(img_data); + + if (*img_info == NULL) { + *img_info = metal_allocate_memory(infosize); + if (*img_info == NULL) + return -ENOMEM; + memset(*img_info, 0, infosize); + } + memcpy(*img_info, img_data, tmpsize); + load_state = elf_load_state(*img_info); + *load_state = ELF_STATE_WAIT_FOR_PHDRS; + last_load_state = ELF_STATE_WAIT_FOR_PHDRS; + } + } + metal_assert(*img_info != NULL); + load_state = elf_load_state(*img_info); + if (last_load_state != (int)*load_state) + return -RPROC_EINVAL; + /* Get ELF program headers */ + if (*load_state == ELF_STATE_WAIT_FOR_PHDRS) { + size_t phdrs_size; + size_t phdrs_offset; + char **phdrs; + const void *img_phdrs; + + metal_log(METAL_LOG_DEBUG, "Loading ELF program header.\r\n"); + phdrs_offset = elf_phoff(*img_info); + phdrs_size = elf_phnum(*img_info) * elf_phentsize(*img_info); + if (offset > phdrs_offset || + offset + len < phdrs_offset + phdrs_size) { + *noffset = phdrs_offset; + *nlen = phdrs_size; + return (int)*load_state; + } + /* caculate the programs headers offset to the image_data */ + phdrs_offset -= offset; + img_phdrs = (const void *) + ((const char *)img_data + phdrs_offset); + phdrs = (char **)elf_phtable_ptr(*img_info); + (*phdrs) = metal_allocate_memory(phdrs_size); + if (*phdrs == NULL) + return -ENOMEM; + memcpy((void *)(*phdrs), img_phdrs, phdrs_size); + *load_state = ELF_STATE_WAIT_FOR_SHDRS | + RPROC_LOADER_READY_TO_LOAD; + } + /* Get ELF Section Headers */ + if ((*load_state & ELF_STATE_WAIT_FOR_SHDRS) != 0) { + size_t shdrs_size; + size_t shdrs_offset; + char **shdrs; + const void *img_shdrs; + + metal_log(METAL_LOG_DEBUG, "Loading ELF section header.\r\n"); + shdrs_offset = elf_shoff(*img_info); + if (elf_shnum(*img_info) == 0) { + *load_state = (*load_state & (~ELF_STATE_MASK)) | + ELF_STATE_HDRS_COMPLETE; + *nlen = 0; + return (int)*load_state; + } + shdrs_size = elf_shnum(*img_info) * elf_shentsize(*img_info); + if (offset > shdrs_offset || + offset + len < shdrs_offset + shdrs_size) { + *noffset = shdrs_offset; + *nlen = shdrs_size; + return (int)*load_state; + } + /* caculate the sections headers offset to the image_data */ + shdrs_offset -= offset; + img_shdrs = (const void *) + ((const char *)img_data + shdrs_offset); + shdrs = (char **)elf_shtable_ptr(*img_info); + (*shdrs) = metal_allocate_memory(shdrs_size); + if (*shdrs == NULL) + return -ENOMEM; + memcpy((void *)*shdrs, img_shdrs, shdrs_size); + *load_state = (*load_state & (~ELF_STATE_MASK)) | + ELF_STATE_WAIT_FOR_SHSTRTAB; + metal_log(METAL_LOG_DEBUG, + "Loading ELF section header complete.\r\n"); + } + /* Get ELF SHSTRTAB section */ + if ((*load_state & ELF_STATE_WAIT_FOR_SHSTRTAB) != 0) { + size_t shstrtab_size; + size_t shstrtab_offset; + int shstrndx; + void *shdr; + void **shstrtab; + + metal_log(METAL_LOG_DEBUG, "Loading ELF shstrtab.\r\n"); + shstrndx = elf_shstrndx(*img_info); + shdr = elf_get_section_from_index(*img_info, shstrndx); + if (shdr == NULL) + return -RPROC_EINVAL; + elf_parse_section(*img_info, shdr, NULL, NULL, + NULL, &shstrtab_offset, + &shstrtab_size, NULL, NULL, + NULL, NULL); + if (offset > shstrtab_offset || + offset + len < shstrtab_offset + shstrtab_size) { + *noffset = shstrtab_offset; + *nlen = shstrtab_size; + return (int)*load_state; + } + /* Caculate shstrtab section offset to the input image data */ + shstrtab_offset -= offset; + shstrtab = elf_shstrtab_ptr(*img_info); + *shstrtab = metal_allocate_memory(shstrtab_size); + if (*shstrtab == NULL) + return -ENOMEM; + memcpy(*shstrtab, + (const void *)((const char *)img_data + shstrtab_offset), + shstrtab_size); + *load_state = (*load_state & (~ELF_STATE_MASK)) | + ELF_STATE_HDRS_COMPLETE; + *nlen = 0; + return *load_state; + } + return last_load_state; +} + +int elf_load(struct remoteproc *rproc, + const void *img_data, size_t offset, size_t len, + void **img_info, int last_load_state, + metal_phys_addr_t *da, + size_t *noffset, size_t *nlen, + unsigned char *padding, size_t *nmemsize) +{ + unsigned int *load_state; + const void *phdr; + + (void)rproc; + metal_assert(da != NULL); + metal_assert(noffset != NULL); + metal_assert(nlen != NULL); + if ((last_load_state & RPROC_LOADER_MASK) == RPROC_LOADER_NOT_READY) { + metal_log(METAL_LOG_DEBUG, + "%s, needs to load header first\r\n"); + last_load_state = elf_load_header(img_data, offset, len, + img_info, last_load_state, + noffset, nlen); + if ((last_load_state & RPROC_LOADER_MASK) == + RPROC_LOADER_NOT_READY) { + *da = RPROC_LOAD_ANYADDR; + return last_load_state; + } + } + metal_assert(img_info != NULL && *img_info != NULL); + load_state = elf_load_state(*img_info); + /* For ELF, segment padding value is 0 */ + if (padding != NULL) + *padding = 0; + if ((*load_state & RPROC_LOADER_READY_TO_LOAD) != 0) { + int nsegment; + size_t nsegmsize = 0; + size_t nsize = 0; + int phnums = 0; + + nsegment = (int)(*load_state & ELF_NEXT_SEGMENT_MASK); + phdr = elf_next_load_segment(*img_info, &nsegment, da, + noffset, &nsize, &nsegmsize); + if (phdr == NULL) { + metal_log(METAL_LOG_DEBUG, "cannot find more segement\r\n"); + *load_state = (*load_state & (~ELF_NEXT_SEGMENT_MASK)) | + (unsigned int)(nsegment & ELF_NEXT_SEGMENT_MASK); + return *load_state; + } + *nlen = nsize; + *nmemsize = nsegmsize; + phnums = elf_phnum(*img_info); + metal_log(METAL_LOG_DEBUG, "segment: %d, total segs %d\r\n", + nsegment, phnums); + if (nsegment == elf_phnum(*img_info)) { + *load_state = (*load_state & (~RPROC_LOADER_MASK)) | + RPROC_LOADER_POST_DATA_LOAD; + } + *load_state = (*load_state & (~ELF_NEXT_SEGMENT_MASK)) | + (unsigned int)(nsegment & ELF_NEXT_SEGMENT_MASK); + } else if ((*load_state & RPROC_LOADER_POST_DATA_LOAD) != 0) { + if ((*load_state & ELF_STATE_HDRS_COMPLETE) == 0) { + last_load_state = elf_load_header(img_data, offset, + len, img_info, + last_load_state, + noffset, nlen); + if (last_load_state < 0) + return last_load_state; + if ((last_load_state & ELF_STATE_HDRS_COMPLETE) != 0) { + *load_state = (*load_state & + (~RPROC_LOADER_MASK)) | + RPROC_LOADER_LOAD_COMPLETE; + *nlen = 0; + } + *da = RPROC_LOAD_ANYADDR; + } else { + /* TODO: will handle relocate later */ + *nlen = 0; + *load_state = (*load_state & + (~RPROC_LOADER_MASK)) | + RPROC_LOADER_LOAD_COMPLETE; + } + } + return *load_state; +} + +void elf_release(void *img_info) +{ + if (img_info == NULL) + return; + if (elf_is_64(img_info) == 0) { + struct elf32_info *elf_info = img_info; + + if (elf_info->phdrs != NULL) + metal_free_memory(elf_info->phdrs); + if (elf_info->shdrs != NULL) + metal_free_memory(elf_info->shdrs); + if (elf_info->shstrtab != NULL) + metal_free_memory(elf_info->shstrtab); + metal_free_memory(img_info); + + } else { + struct elf64_info *elf_info = img_info; + + if (elf_info->phdrs != NULL) + metal_free_memory(elf_info->phdrs); + if (elf_info->shdrs != NULL) + metal_free_memory(elf_info->shdrs); + if (elf_info->shstrtab != NULL) + metal_free_memory(elf_info->shstrtab); + metal_free_memory(img_info); + } +} + +metal_phys_addr_t elf_get_entry(void *elf_info) +{ + if (!elf_info) + return METAL_BAD_PHYS; + + if (elf_is_64(elf_info) == 0) { + Elf32_Ehdr *elf_ehdr = (Elf32_Ehdr *)elf_info; + Elf32_Addr e_entry; + + e_entry = elf_ehdr->e_entry; + return (metal_phys_addr_t)e_entry; + } else { + Elf64_Ehdr *elf_ehdr = (Elf64_Ehdr *)elf_info; + Elf64_Addr e_entry; + + e_entry = elf_ehdr->e_entry; + return (metal_phys_addr_t)(e_entry & (metal_phys_addr_t)(-1)); + } +} + +int elf_locate_rsc_table(void *elf_info, metal_phys_addr_t *da, + size_t *offset, size_t *size) +{ + char *sect_name = ".resource_table"; + void *shdr; + unsigned int *load_state; + + if (elf_info == NULL) + return -RPROC_EINVAL; + + load_state = elf_load_state(elf_info); + if ((*load_state & ELF_STATE_HDRS_COMPLETE) == 0) + return -RPROC_ERR_LOADER_STATE; + shdr = elf_get_section_from_name(elf_info, sect_name); + if (shdr == NULL) { + metal_assert(size != NULL); + *size = 0; + return 0; + } + elf_parse_section(elf_info, shdr, NULL, NULL, + da, offset, size, + NULL, NULL, NULL, NULL); + return 0; +} + +int elf_get_load_state(void *img_info) +{ + unsigned int *load_state; + + if (img_info == NULL) + return -RPROC_EINVAL; + load_state = elf_load_state(img_info); + return (int)(*load_state); +} + +struct loader_ops elf_ops = { + .load_header = elf_load_header, + .load_data = elf_load, + .locate_rsc_table = elf_locate_rsc_table, + .release = elf_release, + .get_entry = elf_get_entry, + .get_load_state = elf_get_load_state, +}; diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/remoteproc.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/remoteproc.c new file mode 100644 index 000000000..50888c118 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/remoteproc.c @@ -0,0 +1,965 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2015 Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + * static functions + *****************************************************************************/ +static struct loader_ops * +remoteproc_check_fw_format(const void *img_data, size_t img_len) +{ + if (img_len <= 0) + return NULL; + else if (elf_identify(img_data, img_len) == 0) + return &elf_ops; + else + return NULL; +} + +static struct remoteproc_mem * +remoteproc_get_mem(struct remoteproc *rproc, const char *name, + metal_phys_addr_t pa, metal_phys_addr_t da, + void *va, size_t size) +{ + struct metal_list *node; + struct remoteproc_mem *mem; + + metal_list_for_each(&rproc->mems, node) { + mem = metal_container_of(node, struct remoteproc_mem, node); + if (name) { + if (!strncmp(name, mem->name, sizeof(mem->name))) + return mem; + } else if (pa != METAL_BAD_PHYS) { + metal_phys_addr_t pa_start, pa_end; + + pa_start = mem->pa; + pa_end = pa_start + mem->size; + if (pa >= pa_start && (pa + size) <= pa_end) + return mem; + } else if (da != METAL_BAD_PHYS) { + metal_phys_addr_t da_start, da_end; + + da_start = mem->da; + da_end = da_start + mem->size; + if (da >= da_start && (da + size) <= da_end) + return mem; + } else if (va) { + if (metal_io_virt_to_offset(mem->io, va) != + METAL_BAD_OFFSET) + return mem; + + } else { + return NULL; + } + } + return NULL; +} + +static metal_phys_addr_t +remoteproc_datopa(struct remoteproc_mem *mem, metal_phys_addr_t da) +{ + metal_phys_addr_t pa; + + pa = mem->pa + da - mem->da; + return pa; +} + +static metal_phys_addr_t +remoteproc_patoda(struct remoteproc_mem *mem, metal_phys_addr_t pa) +{ + metal_phys_addr_t da; + + da = mem->da + pa - mem->pa; + return da; +} + +static void *remoteproc_get_rsc_table(struct remoteproc *rproc, + void *store, + struct image_store_ops *store_ops, + size_t offset, + size_t len) +{ + int ret; + void *rsc_table = NULL; + const void *img_data; + + /* Copy the resource table to local memory, + * the caller should be responsible to release the memory + */ + rsc_table = metal_allocate_memory(len); + if (!rsc_table) { + return RPROC_ERR_PTR(-RPROC_ENOMEM); + } + ret = store_ops->load(store, offset, len, &img_data, RPROC_LOAD_ANYADDR, + NULL, 1); + if (ret < 0 || ret < (int)len || img_data == NULL) { + metal_log(METAL_LOG_ERROR, + "get rsc failed: 0x%llx, 0x%llx\r\n", offset, len); + rsc_table = RPROC_ERR_PTR(-RPROC_EINVAL); + goto error; + } + memcpy(rsc_table, img_data, len); + + ret = handle_rsc_table(rproc, rsc_table, len, NULL); + if (ret < 0) { + rsc_table = RPROC_ERR_PTR(ret); + goto error; + } + return rsc_table; + +error: + metal_free_memory(rsc_table); + return rsc_table; +} + +int remoteproc_parse_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, + size_t rsc_size) +{ + struct metal_io_region *io; + + io = remoteproc_get_io_with_va(rproc, (void *)rsc_table); + return handle_rsc_table(rproc, rsc_table, rsc_size, io); +} + +int remoteproc_set_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, + size_t rsc_size) +{ + int ret; + struct metal_io_region *io; + + io = remoteproc_get_io_with_va(rproc, (void *)rsc_table); + if (!io) + return -EINVAL; + ret = remoteproc_parse_rsc_table(rproc, rsc_table, rsc_size); + if (!ret) { + rproc->rsc_table = rsc_table; + rproc->rsc_len = rsc_size; + rproc->rsc_io = io; + } + return ret; + +} + +struct remoteproc *remoteproc_init(struct remoteproc *rproc, + struct remoteproc_ops *ops, void *priv) +{ + if (rproc) { + memset(rproc, 0, sizeof (*rproc)); + rproc->state = RPROC_OFFLINE; + metal_mutex_init(&rproc->lock); + metal_list_init(&rproc->mems); + metal_list_init(&rproc->vdevs); + } + rproc = ops->init(rproc, ops, priv); + return rproc; +} + +int remoteproc_remove(struct remoteproc *rproc) +{ + int ret = 0; + + if (rproc) { + metal_mutex_acquire(&rproc->lock); + if (rproc->state == RPROC_OFFLINE) + rproc->ops->remove(rproc); + else + ret = -EBUSY; + metal_mutex_release(&rproc->lock); + } else { + ret = -EINVAL; + } + return ret; +} + +int remoteproc_config(struct remoteproc *rproc, void *data) +{ + int ret = -RPROC_ENODEV; + + if (rproc) { + metal_mutex_acquire(&rproc->lock); + if (rproc->state == RPROC_OFFLINE) { + /* configure operation is allowed if the state is + * offline or ready. This function can be called + * mulitple times before start the remote. + */ + if (rproc->ops->config) + ret = rproc->ops->config(rproc, data); + rproc->state = RPROC_READY; + } else { + ret = -RPROC_EINVAL; + } + metal_mutex_release(&rproc->lock); + } + return ret; +} + +int remoteproc_start(struct remoteproc *rproc) +{ + int ret = -RPROC_ENODEV; + + if (rproc) { + metal_mutex_acquire(&rproc->lock); + if (rproc->state == RPROC_READY) { + ret = rproc->ops->start(rproc); + rproc->state = RPROC_RUNNING; + } else { + ret = -RPROC_EINVAL; + } + metal_mutex_release(&rproc->lock); + } + return ret; +} + +int remoteproc_stop(struct remoteproc *rproc) +{ + int ret = -RPROC_ENODEV; + + if (rproc) { + metal_mutex_acquire(&rproc->lock); + if (rproc->state != RPROC_STOPPED && + rproc->state != RPROC_OFFLINE) { + if (rproc->ops->stop) + ret = rproc->ops->stop(rproc); + rproc->state = RPROC_STOPPED; + } else { + ret = 0; + } + metal_mutex_release(&rproc->lock); + } + return ret; +} + +int remoteproc_shutdown(struct remoteproc *rproc) +{ + int ret = -RPROC_ENODEV; + + if (rproc) { + ret = 0; + metal_mutex_acquire(&rproc->lock); + if (rproc->state != RPROC_OFFLINE) { + if (rproc->state != RPROC_STOPPED) { + if (rproc->ops->stop) + ret = rproc->ops->stop(rproc); + } + if (!ret) { + if (rproc->ops->shutdown) + ret = rproc->ops->shutdown(rproc); + if (!ret) { + rproc->state = RPROC_OFFLINE; + } + } + } + metal_mutex_release(&rproc->lock); + } + return ret; +} + +struct metal_io_region * +remoteproc_get_io_with_name(struct remoteproc *rproc, + const char *name) +{ + struct remoteproc_mem *mem; + + mem = remoteproc_get_mem(rproc, name, + METAL_BAD_PHYS, METAL_BAD_PHYS, NULL, 0); + if (mem) + return mem->io; + else + return NULL; +} + +struct metal_io_region * +remoteproc_get_io_with_pa(struct remoteproc *rproc, + metal_phys_addr_t pa) +{ + struct remoteproc_mem *mem; + + mem = remoteproc_get_mem(rproc, NULL, pa, METAL_BAD_PHYS, NULL, 0); + if (mem) + return mem->io; + else + return NULL; +} + +struct metal_io_region * +remoteproc_get_io_with_da(struct remoteproc *rproc, + metal_phys_addr_t da, + unsigned long *offset) +{ + struct remoteproc_mem *mem; + + mem = remoteproc_get_mem(rproc, NULL, METAL_BAD_PHYS, da, NULL, 0); + if (mem) { + struct metal_io_region *io; + metal_phys_addr_t pa; + + io = mem->io; + pa = remoteproc_datopa(mem, da); + *offset = metal_io_phys_to_offset(io, pa); + return io; + } else { + return NULL; + } +} + +struct metal_io_region * +remoteproc_get_io_with_va(struct remoteproc *rproc, void *va) +{ + struct remoteproc_mem *mem; + + mem = remoteproc_get_mem(rproc, NULL, METAL_BAD_PHYS, METAL_BAD_PHYS, + va, 0); + if (mem) + return mem->io; + else + return NULL; +} + +void *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) +{ + void *va = NULL; + metal_phys_addr_t lpa, lda; + struct remoteproc_mem *mem; + + if (!rproc) + return NULL; + else if (!pa && !da) + return NULL; + if (pa) + lpa = *pa; + else + lpa = METAL_BAD_PHYS; + if (da) + lda = *da; + else + lda = METAL_BAD_PHYS; + mem = remoteproc_get_mem(rproc, NULL, lpa, lda, NULL, size); + if (mem) { + if (lpa != METAL_BAD_PHYS) + lda = remoteproc_patoda(mem, lpa); + else if (lda != METAL_BAD_PHYS) + lpa = remoteproc_datopa(mem, lda); + if (io) + *io = mem->io; + va = metal_io_phys_to_virt(mem->io, lpa); + } else if (rproc->ops->mmap) { + va = rproc->ops->mmap(rproc, &lpa, &lda, size, attribute, io); + } + + if (pa) + *pa = lpa; + if (da) + *da = lda; + return va; +} + +int remoteproc_load(struct remoteproc *rproc, const char *path, + void *store, struct image_store_ops *store_ops, + void **img_info) +{ + int ret; + struct loader_ops *loader; + const void *img_data; + void *limg_info = NULL; + size_t offset, noffset; + size_t len, nlen; + int last_load_state; + metal_phys_addr_t da, rsc_da; + int rsc_len; + size_t rsc_size; + void *rsc_table = NULL; + struct metal_io_region *io = NULL; + + if (!rproc) + return -RPROC_ENODEV; + + metal_mutex_acquire(&rproc->lock); + metal_log(METAL_LOG_DEBUG, "%s: check remoteproc status\r\n", __func__); + /* If remoteproc is not in ready state, cannot load executable */ + if (rproc->state != RPROC_READY && rproc->state != RPROC_CONFIGURED) { + metal_log(METAL_LOG_ERROR, + "load failure: invalid rproc state %d.\r\n", + rproc->state); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + + if (!store_ops) { + metal_log(METAL_LOG_ERROR, + "load failure: loader ops is not set.\r\n"); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + + /* Open exectuable to get ready to parse */ + metal_log(METAL_LOG_DEBUG, "%s: open exectuable image\r\n", __func__); + ret = store_ops->open(store, path, &img_data); + if (ret <= 0) { + metal_log(METAL_LOG_ERROR, + "load failure: failed to open firmware %d.\n", + ret); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + len = ret; + metal_assert(img_data != NULL); + + /* Check executable format to select a parser */ + loader = rproc->loader; + if (!loader) { + metal_log(METAL_LOG_DEBUG, "%s: check loader\r\n", __func__); + loader = remoteproc_check_fw_format(img_data, len); + if (!loader) { + metal_log(METAL_LOG_ERROR, + "load failure: failed to get store ops.\n"); + ret = -RPROC_EINVAL; + goto error1; + } + rproc->loader = loader; + } + + /* Load exectuable headers */ + metal_log(METAL_LOG_DEBUG, "%s: loading headers\r\n", __func__); + offset = 0; + last_load_state = RPROC_LOADER_NOT_READY; + while(1) { + ret = loader->load_header(img_data, offset, len, + &limg_info, last_load_state, + &noffset, &nlen); + last_load_state = (unsigned int)ret; + metal_log(METAL_LOG_DEBUG, + "%s, load header 0x%lx, 0x%x, next 0x%lx, 0x%x\r\n", + __func__, offset, len, noffset, nlen); + if (ret < 0) { + metal_log(METAL_LOG_ERROR, + "load header failed 0x%lx,%d.\r\n", + offset, len); + + goto error2; + } else if ((ret & RPROC_LOADER_READY_TO_LOAD) != 0) { + if (nlen == 0) + break; + else if ((noffset > (offset + len)) && + (store_ops->features & SUPPORT_SEEK) == 0) { + /* Required data is not continued, however + * seek is not supported, stop to load + * headers such as ELF section headers which + * is usually located to the end of image. + * Continue to load binary data to target + * memory. + */ + break; + } + } + /* Continue to load headers image data */ + img_data = NULL; + ret = store_ops->load(store, noffset, nlen, + &img_data, + RPROC_LOAD_ANYADDR, + NULL, 1); + if (ret < (int)nlen) { + metal_log(METAL_LOG_ERROR, + "load image data failed 0x%x,%d\r\n", + noffset, nlen); + goto error2; + } + offset = noffset; + len = nlen; + } + ret = elf_locate_rsc_table(limg_info, &rsc_da, &offset, &rsc_size); + if (ret == 0 && rsc_size > 0) { + /* parse resource table */ + rsc_len = (int)rsc_size; + rsc_table = remoteproc_get_rsc_table(rproc, store, store_ops, + offset, rsc_len); + } else { + rsc_len = ret; + } + + /* load executable data */ + metal_log(METAL_LOG_DEBUG, "%s: load executable data\r\n", __func__); + offset = 0; + len = 0; + ret = -EINVAL; + while(1) { + unsigned char padding; + size_t nmemsize; + metal_phys_addr_t pa; + + da = RPROC_LOAD_ANYADDR; + nlen = 0; + nmemsize = 0; + noffset = 0; + ret = loader->load_data(rproc, img_data, offset, len, + &limg_info, last_load_state, &da, + &noffset, &nlen, &padding, &nmemsize); + if (ret < 0) { + metal_log(METAL_LOG_ERROR, + "load data failed,0x%lx,%d\r\n", + noffset, nlen); + goto error3; + } + metal_log(METAL_LOG_DEBUG, + "load data: da 0x%lx, offset 0x%lx, len = 0x%lx, memsize = 0x%lx, state 0x%x\r\n", + da, noffset, nlen, nmemsize, ret); + last_load_state = ret; + if (da != RPROC_LOAD_ANYADDR) { + /* Data is supposed to be loaded to target memory */ + img_data = NULL; + /* get the I/O region from remoteproc */ + pa = METAL_BAD_PHYS; + (void)remoteproc_mmap(rproc, &pa, &da, nmemsize, 0, &io); + if (pa == METAL_BAD_PHYS || io == NULL) { + metal_log(METAL_LOG_ERROR, + "load failed, no mapping for 0x%llx.\r\n", + da); + ret = -RPROC_EINVAL; + goto error3; + } + if (nlen > 0) { + ret = store_ops->load(store, noffset, nlen, + &img_data, pa, io, 1); + if (ret != (int)nlen) { + metal_log(METAL_LOG_ERROR, + "load data failed 0x%lx, 0x%lx, 0x%x\r\n", + pa, noffset, nlen); + ret = -RPROC_EINVAL; + goto error3; + } + } + if (nmemsize > nlen) { + size_t tmpoffset; + + tmpoffset = metal_io_phys_to_offset(io, + pa + nlen); + metal_io_block_set(io, tmpoffset, + padding, (nmemsize - nlen)); + } + } else if (nlen != 0) { + ret = store_ops->load(store, noffset, nlen, + &img_data, + RPROC_LOAD_ANYADDR, + NULL, 1); + if (ret < (int)nlen) { + if ((last_load_state & + RPROC_LOADER_POST_DATA_LOAD) != 0) { + metal_log(METAL_LOG_WARNING, + "not all the headers are loaded\r\n"); + break; + } + metal_log(METAL_LOG_ERROR, + "post-load image data failed 0x%x,%d\r\n", + noffset, nlen); + goto error3; + } + offset = noffset; + len = nlen; + } else { + /* (last_load_state & RPROC_LOADER_LOAD_COMPLETE) != 0 */ + break; + } + } + + if (rsc_len < 0) { + ret = elf_locate_rsc_table(limg_info, &rsc_da, + &offset, &rsc_size); + if (ret == 0 && rsc_size > 0) { + /* parse resource table */ + rsc_len = (int)rsc_size; + rsc_table = remoteproc_get_rsc_table(rproc, store, + store_ops, + offset, + rsc_len); + } + } + + /* Update resource table */ + if (rsc_len && rsc_da != METAL_BAD_PHYS) { + void *rsc_table_cp = rsc_table; + + metal_log(METAL_LOG_DEBUG, + "%s, update resource table\r\n", __func__); + rsc_table = remoteproc_mmap(rproc, NULL, &rsc_da, + rsc_len, 0, &io); + if (rsc_table) { + size_t rsc_io_offset; + + /* Update resource table */ + rsc_io_offset = metal_io_virt_to_offset(io, rsc_table); + ret = metal_io_block_write(io, rsc_io_offset, + rsc_table_cp, rsc_len); + if (ret != rsc_len) { + metal_log(METAL_LOG_WARNING, + "load: failed to update rsc\r\n"); + } + rproc->rsc_table = rsc_table; + rproc->rsc_len = rsc_len; + } else { + metal_log(METAL_LOG_WARNING, + "load: not able to update rsc table.\n"); + } + metal_free_memory(rsc_table_cp); + /* So that the rsc_table will not get released */ + rsc_table = NULL; + } + + metal_log(METAL_LOG_DEBUG, "%s: successfully load firmware\r\n", + __func__); + /* get entry point from the firmware */ + rproc->bootaddr = loader->get_entry(limg_info); + rproc->state = RPROC_READY; + + metal_mutex_release(&rproc->lock); + if (img_info) + *img_info = limg_info; + else + loader->release(limg_info); + store_ops->close(store); + return 0; + +error3: + if (rsc_table) + metal_free_memory(rsc_table); +error2: + loader->release(limg_info); +error1: + store_ops->close(store); + metal_mutex_release(&rproc->lock); + return ret; +} + +int remoteproc_load_noblock(struct remoteproc *rproc, + const void *img_data, size_t offset, size_t len, + void **img_info, + metal_phys_addr_t *pa, struct metal_io_region **io, + size_t *noffset, size_t *nlen, + size_t *nmlen, unsigned char *padding) +{ + int ret; + struct loader_ops *loader; + void *limg_info = NULL; + int last_load_state; + metal_phys_addr_t da, rsc_da; + size_t rsc_size; + void *rsc_table = NULL, *lrsc_table = NULL; + + if (!rproc) + return -RPROC_ENODEV; + + metal_assert(pa != NULL); + metal_assert(io != NULL); + metal_assert(noffset != NULL); + metal_assert(nlen != NULL); + metal_assert(nmlen != NULL); + metal_assert(padding != NULL); + + metal_mutex_acquire(&rproc->lock); + metal_log(METAL_LOG_DEBUG, "%s: check remoteproc status\r\n", __func__); + /* If remoteproc is not in ready state, cannot load executable */ + if (rproc->state != RPROC_READY) { + metal_log(METAL_LOG_ERROR, + "load failure: invalid rproc state %d.\r\n", + rproc->state); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + + /* Check executable format to select a parser */ + loader = rproc->loader; + if (!loader) { + metal_log(METAL_LOG_DEBUG, "%s: check loader\r\n", __func__); + if (img_data == NULL || offset != 0 || len == 0) { + metal_log(METAL_LOG_ERROR, + "load failure, invalid inputs, not able to identify image.\r\n"); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + loader = remoteproc_check_fw_format(img_data, len); + if (!loader) { + metal_log(METAL_LOG_ERROR, + "load failure: failed to identify image.\n"); + ret = -RPROC_EINVAL; + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + rproc->loader = loader; + } + if (img_info == NULL || *img_info == NULL ) { + last_load_state = 0; + } else { + limg_info = *img_info; + last_load_state = loader->get_load_state(limg_info); + if (last_load_state < 0) { + metal_log(METAL_LOG_ERROR, + "load failure, not able get load state.\r\n"); + metal_mutex_release(&rproc->lock); + return -RPROC_EINVAL; + } + } + da = RPROC_LOAD_ANYADDR; + *nlen = 0; + if ((last_load_state & RPROC_LOADER_READY_TO_LOAD) == 0 && + (last_load_state & RPROC_LOADER_LOAD_COMPLETE) == 0) { + /* Get the mandatory executable headers */ + ret = loader->load_header(img_data, offset, len, + &limg_info, last_load_state, + noffset, nlen); + last_load_state = (unsigned int)ret; + metal_log(METAL_LOG_DEBUG, + "%s, load header 0x%lx, 0x%x, next 0x%lx, 0x%x\r\n", + __func__, offset, len, *noffset, *nlen); + if (ret < 0) { + metal_log(METAL_LOG_ERROR, + "load header failed 0x%lx,%d.\r\n", + offset, len); + + goto error1; + } + last_load_state = loader->get_load_state(limg_info); + if (*nlen != 0 && + (last_load_state & RPROC_LOADER_READY_TO_LOAD) == 0) + goto out; + } + if ((last_load_state & RPROC_LOADER_READY_TO_LOAD) != 0 || + (last_load_state & RPROC_LOADER_POST_DATA_LOAD) != 0) { + /* Enough information to know which target memory for + * which data. + */ + ret = loader->load_data(rproc, img_data, offset, len, + &limg_info, last_load_state, &da, + noffset, nlen, padding, nmlen); + metal_log(METAL_LOG_DEBUG, + "%s, load data 0x%lx, 0x%x, next 0x%lx, 0x%x\r\n", + __func__, offset, len, *noffset, *nlen); + if (ret < 0) { + metal_log(METAL_LOG_ERROR, + "load data failed,0x%lx,%d\r\n", + offset, len); + goto error1; + } + if (da != RPROC_LOAD_ANYADDR) { + /* get the I/O region from remoteproc */ + *pa = METAL_BAD_PHYS; + (void)remoteproc_mmap(rproc, pa, &da, *nmlen, 0, io); + if (*pa == METAL_BAD_PHYS || io == NULL) { + metal_log(METAL_LOG_ERROR, + "load failed, no mapping for 0x%llx.\r\n", + da); + ret = -RPROC_EINVAL; + goto error1; + } + } + if (*nlen != 0) + goto out; + else + last_load_state = loader->get_load_state(limg_info); + } + if ((last_load_state & RPROC_LOADER_LOAD_COMPLETE) != 0) { + /* Get resource table */ + size_t rsc_offset; + size_t rsc_io_offset; + + ret = elf_locate_rsc_table(limg_info, &rsc_da, + &rsc_offset, &rsc_size); + if (ret == 0 && rsc_size > 0) { + lrsc_table = metal_allocate_memory(rsc_size); + if (lrsc_table == NULL) { + ret = -RPROC_ENOMEM; + goto error1; + } + rsc_table = remoteproc_mmap(rproc, NULL, &rsc_da, + rsc_size, 0, io); + if (*io == NULL) { + metal_log(METAL_LOG_ERROR, + "load failed: failed to mmap rsc\r\n"); + metal_free_memory(lrsc_table); + goto error1; + } + rsc_io_offset = metal_io_virt_to_offset(*io, rsc_table); + ret = metal_io_block_read(*io, rsc_io_offset, + lrsc_table, (int)rsc_size); + if (ret != (int)rsc_size) { + metal_log(METAL_LOG_ERROR, + "load failed: failed to get rsc\r\n"); + metal_free_memory(lrsc_table); + goto error1; + } + /* parse resource table */ + ret = remoteproc_parse_rsc_table(rproc, lrsc_table, + rsc_size); + if (ret == (int)rsc_size) { + metal_log(METAL_LOG_ERROR, + "load failed: failed to parse rsc\r\n"); + metal_free_memory(lrsc_table); + goto error1; + } + /* Update resource table */ + ret = metal_io_block_write(*io, rsc_io_offset, + lrsc_table, (int)rsc_size); + if (ret != (int)rsc_size) { + metal_log(METAL_LOG_WARNING, + "load exectuable, failed to update rsc\r\n"); + } + rproc->rsc_table = rsc_table; + rproc->rsc_len = (int)rsc_size; + metal_free_memory(lrsc_table); + } + } +out: + if (img_info != NULL) + *img_info = limg_info; + else + loader->release(limg_info); + metal_mutex_release(&rproc->lock); + return 0; + +error1: + loader->release(limg_info); + metal_mutex_release(&rproc->lock); + return ret; +} + +unsigned int remoteproc_allocate_id(struct remoteproc *rproc, + unsigned int start, + unsigned int end) +{ + unsigned int notifyid; + + if (start == RSC_NOTIFY_ID_ANY) + start = 0; + if (end == RSC_NOTIFY_ID_ANY) + end = METAL_BITS_PER_ULONG; + notifyid = metal_bitmap_next_clear_bit(&rproc->bitmap, + start, end); + if (notifyid != end) + metal_bitmap_set_bit(&rproc->bitmap, notifyid); + else + notifyid = RSC_NOTIFY_ID_ANY; + return notifyid; +} + +static int remoteproc_virtio_notify(void *priv, uint32_t id) +{ + struct remoteproc *rproc = priv; + + return rproc->ops->notify(rproc, id); +} + +struct virtio_device * +remoteproc_create_virtio(struct remoteproc *rproc, + int vdev_id, unsigned int role, + void (*rst_cb)(struct virtio_device *vdev)) +{ + char *rsc_table; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *vdev_rsc_io; + struct virtio_device *vdev; + struct remoteproc_virtio *rpvdev; + size_t vdev_rsc_offset; + unsigned int notifyid; + unsigned int num_vrings, i; + struct metal_list *node; + + metal_assert(rproc); + metal_mutex_acquire(&rproc->lock); + rsc_table = rproc->rsc_table; + vdev_rsc_io = rproc->rsc_io; + vdev_rsc_offset = find_rsc(rsc_table, RSC_VDEV, vdev_id); + if (!vdev_rsc_offset) { + metal_mutex_release(&rproc->lock); + return NULL; + } + vdev_rsc = (struct fw_rsc_vdev *)(rsc_table + vdev_rsc_offset); + notifyid = vdev_rsc->notifyid; + /* Check if the virtio device is already created */ + metal_list_for_each(&rproc->vdevs, node) { + rpvdev = metal_container_of(node, struct remoteproc_virtio, + node); + if (rpvdev->vdev.index == notifyid) + return &rpvdev->vdev; + } + vdev = rproc_virtio_create_vdev(role, notifyid, + vdev_rsc, vdev_rsc_io, rproc, + remoteproc_virtio_notify, + rst_cb); + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + metal_list_add_tail(&rproc->vdevs, &rpvdev->node); + num_vrings = vdev_rsc->num_of_vrings; + /* set the notification id for vrings */ + for (i = 0; i < num_vrings; i++) { + struct fw_rsc_vdev_vring *vring_rsc; + metal_phys_addr_t da; + unsigned int num_descs, align; + struct metal_io_region *io; + void *va; + size_t size; + int ret; + + vring_rsc = &vdev_rsc->vring[i]; + notifyid = vring_rsc->notifyid; + da = vring_rsc->da; + num_descs = vring_rsc->num; + align = vring_rsc->align; + size = vring_size(num_descs, align); + va = remoteproc_mmap(rproc, NULL, &da, size, 0, &io); + if (!va) + goto err1; + ret = rproc_virtio_init_vring(vdev, i, notifyid, + va, io, num_descs, align); + if (ret) + goto err1; + } + metal_mutex_release(&rproc->lock); + return vdev; + +err1: + remoteproc_remove_virtio(rproc, vdev); + metal_mutex_release(&rproc->lock); + return NULL; +} + +void remoteproc_remove_virtio(struct remoteproc *rproc, + struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + + (void)rproc; + metal_assert(vdev); + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + metal_list_del(&rpvdev->node); + rproc_virtio_remove_vdev(&rpvdev->vdev); +} + +int remoteproc_get_notification(struct remoteproc *rproc, uint32_t notifyid) +{ + struct remoteproc_virtio *rpvdev; + struct metal_list *node; + int ret; + + metal_list_for_each(&rproc->vdevs, node) { + rpvdev = metal_container_of(node, struct remoteproc_virtio, + node); + ret = rproc_virtio_notified(&rpvdev->vdev, notifyid); + if (ret) + return ret; + } + return 0; +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/remoteproc_virtio.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/remoteproc_virtio.c new file mode 100644 index 000000000..011a5ed3b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/remoteproc_virtio.c @@ -0,0 +1,330 @@ +/* + * Remoteproc Virtio Framework Implementation + * + * Copyright(c) 2018 Xilinx Ltd. + * Copyright(c) 2011 Texas Instruments, Inc. + * Copyright(c) 2011 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Texas Instruments nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +static void rproc_virtio_virtqueue_notify(struct virtqueue *vq) +{ + struct remoteproc_virtio *rpvdev; + struct virtio_vring_info *vring_info; + struct virtio_device *vdev; + unsigned int vq_id = vq->vq_queue_index; + + vdev = vq->vq_dev; + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + metal_assert(vq_id <= vdev->vrings_num); + vring_info = &vdev->vrings_info[vq_id]; + rpvdev->notify(rpvdev->priv, vring_info->notifyid); +} + +static unsigned char rproc_virtio_get_status(struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *io; + char status; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vdev_rsc = rpvdev->vdev_rsc; + io = rpvdev->vdev_rsc_io; + status = metal_io_read8(io, + metal_io_virt_to_offset(io, &vdev_rsc->status)); + return status; +} + +#ifndef VIRTIO_SLAVE_ONLY +static void rproc_virtio_set_status(struct virtio_device *vdev, + unsigned char status) +{ + struct remoteproc_virtio *rpvdev; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *io; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vdev_rsc = rpvdev->vdev_rsc; + io = rpvdev->vdev_rsc_io; + metal_io_write8(io, + metal_io_virt_to_offset(io, &vdev_rsc->status), + status); + rpvdev->notify(rpvdev->priv, vdev->index); +} +#endif + +static uint32_t rproc_virtio_get_features(struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *io; + uint32_t features; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vdev_rsc = rpvdev->vdev_rsc; + io = rpvdev->vdev_rsc_io; + /* TODO: shall we get features based on the role ? */ + features = metal_io_read32(io, + metal_io_virt_to_offset(io, &vdev_rsc->dfeatures)); + + return features; +} + +#ifndef VIRTIO_SLAVE_ONLY +static void rproc_virtio_set_features(struct virtio_device *vdev, + uint32_t features) +{ + struct remoteproc_virtio *rpvdev; + struct fw_rsc_vdev *vdev_rsc; + struct metal_io_region *io; + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + vdev_rsc = rpvdev->vdev_rsc; + io = rpvdev->vdev_rsc_io; + /* TODO: shall we set features based on the role ? */ + metal_io_write32(io, + metal_io_virt_to_offset(io, &vdev_rsc->dfeatures), + features); + rpvdev->notify(rpvdev->priv, vdev->index); +} +#endif + +static uint32_t rproc_virtio_negotiate_features(struct virtio_device *vdev, + uint32_t features) +{ + (void)vdev; + (void)features; + + return 0; +} + +static void rproc_virtio_read_config(struct virtio_device *vdev, + uint32_t offset, void *dst, int length) +{ + (void)vdev; + (void)offset; + (void)dst; + (void)length; +} + +#ifndef VIRTIO_SLAVE_ONLY +static void rproc_virtio_write_config(struct virtio_device *vdev, + uint32_t offset, void *src, int length) +{ + (void)vdev; + (void)offset; + (void)src; + (void)length; +} + +static void rproc_virtio_reset_device(struct virtio_device *vdev) +{ + if (vdev->role == VIRTIO_DEV_MASTER) + rproc_virtio_set_status(vdev, + VIRTIO_CONFIG_STATUS_NEEDS_RESET); +} +#endif + +const struct virtio_dispatch remoteproc_virtio_dispatch_funcs = { + .get_status = rproc_virtio_get_status, + .get_features = rproc_virtio_get_features, + .read_config = rproc_virtio_read_config, + .notify = rproc_virtio_virtqueue_notify, + .negotiate_features = rproc_virtio_negotiate_features, +#ifndef VIRTIO_SLAVE_ONLY + /* + * We suppose here that the vdev is in a shared memory so that can + * be access only by one core: the master. In this case salve core has + * only read access right. + */ + .set_status = rproc_virtio_set_status, + .set_features = rproc_virtio_set_features, + .write_config = rproc_virtio_write_config, + .reset_device = rproc_virtio_reset_device, +#endif +}; + +struct virtio_device * +rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid, + void *rsc, struct metal_io_region *rsc_io, + void *priv, + rpvdev_notify_func notify, + virtio_dev_reset_cb rst_cb) +{ + struct remoteproc_virtio *rpvdev; + struct virtio_vring_info *vrings_info; + struct fw_rsc_vdev *vdev_rsc = rsc; + struct virtio_device *vdev; + unsigned int num_vrings = vdev_rsc->num_of_vrings; + unsigned int i; + + rpvdev = metal_allocate_memory(sizeof(*rpvdev)); + if (!rpvdev) + return NULL; + vrings_info = metal_allocate_memory(sizeof(*vrings_info) * num_vrings); + if (!vrings_info) + goto err0; + memset(rpvdev, 0, sizeof(*rpvdev)); + memset(vrings_info, 0, sizeof(*vrings_info)); + vdev = &rpvdev->vdev; + + for (i = 0; i < num_vrings; i++) { + struct virtqueue *vq; + struct fw_rsc_vdev_vring *vring_rsc; + unsigned int num_extra_desc = 0; + + vring_rsc = &vdev_rsc->vring[i]; + if (role == VIRTIO_DEV_MASTER) { + num_extra_desc = vring_rsc->num; + } + vq = virtqueue_allocate(num_extra_desc); + if (!vq) + goto err1; + vrings_info[i].vq = vq; + } + + /* FIXME commended as seems not nedded, already stored in vdev */ + //rpvdev->notifyid = notifyid; + rpvdev->notify = notify; + rpvdev->priv = priv; + vdev->vrings_info = vrings_info; + /* Assuming the shared memory has been mapped and registered if + * necessary + */ + rpvdev->vdev_rsc = vdev_rsc; + rpvdev->vdev_rsc_io = rsc_io; + + vdev->index = notifyid; + vdev->role = role; + vdev->reset_cb = rst_cb; + vdev->vrings_num = num_vrings; + vdev->func = &remoteproc_virtio_dispatch_funcs; + /* TODO: Shall we set features here ? */ + + return &rpvdev->vdev; + +err1: + for (i = 0; i < num_vrings; i++) { + if (vrings_info[i].vq) + metal_free_memory(vrings_info[i].vq); + } + metal_free_memory(vrings_info); +err0: + metal_free_memory(rpvdev); + return NULL; +} + +void rproc_virtio_remove_vdev(struct virtio_device *vdev) +{ + struct remoteproc_virtio *rpvdev; + unsigned int i; + + if (!vdev) + return; + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + for (i = 0; i < vdev->vrings_num; i++) { + struct virtqueue *vq; + + vq = vdev->vrings_info[i].vq; + if (vq) + metal_free_memory(vq); + } + metal_free_memory(vdev->vrings_info); + metal_free_memory(rpvdev); +} + +int rproc_virtio_init_vring(struct virtio_device *vdev, unsigned int index, + unsigned int notifyid, void *va, + struct metal_io_region *io, + unsigned int num_descs, unsigned int align) +{ + struct virtio_vring_info *vring_info; + unsigned int num_vrings; + + num_vrings = vdev->vrings_num; + if (index >= num_vrings) + return -RPROC_EINVAL; + vring_info = &vdev->vrings_info[index]; + vring_info->io = io; + vring_info->notifyid = notifyid; + vring_info->info.vaddr = va; + vring_info->info.num_descs = num_descs; + vring_info->info.align = align; + + return 0; +} + +int rproc_virtio_notified(struct virtio_device *vdev, uint32_t notifyid) +{ + unsigned int num_vrings, i; + struct virtio_vring_info *vring_info; + struct virtqueue *vq; + + if (!vdev) + return -EINVAL; + /* We do nothing for vdev notification in this implementation */ + if (vdev->index == notifyid) + return 0; + num_vrings = vdev->vrings_num; + for (i = 0; i < num_vrings; i++) { + vring_info = &vdev->vrings_info[i]; + if (vring_info->notifyid == notifyid || + notifyid == RSC_NOTIFY_ID_ANY) { + vq = vring_info->vq; + virtqueue_notification(vq); + } + } + return 0; +} + +void rproc_virtio_wait_remote_ready(struct virtio_device *vdev) +{ + uint8_t status; + + /* + * No status available for slave. As Master has not to wait + * slave action, we can return. Behavior should be updated + * in future if a slave status is added. + */ + if (vdev->role == VIRTIO_DEV_MASTER) + return; + + while (1) { + status = rproc_virtio_get_status(vdev); + if (status & VIRTIO_CONFIG_STATUS_DRIVER_OK) + return; + } +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/rsc_table_parser.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/rsc_table_parser.c new file mode 100644 index 000000000..bf7f3368a --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/remoteproc/rsc_table_parser.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * Copyright (c) 2018, Xilinx Inc. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +static int handle_dummy_rsc(struct remoteproc *rproc, void *rsc); + +/* Resources handler */ +rsc_handler rsc_handler_table[] = { + handle_carve_out_rsc, /**< carved out resource */ + handle_dummy_rsc, /**< IOMMU dev mem resource */ + handle_trace_rsc, /**< trace buffer resource */ + handle_vdev_rsc, /**< virtio resource */ + handle_dummy_rsc, /**< rproc shared memory resource */ + handle_dummy_rsc, /**< firmware checksum resource */ +}; + +int handle_rsc_table(struct remoteproc *rproc, + struct resource_table *rsc_table, int size, + struct metal_io_region *io) +{ + char *rsc_start; + unsigned int rsc_type; + unsigned int idx, offset; + int status = 0; + + /* Validate rsc table header fields */ + + /* Minimum rsc table size */ + if (sizeof(struct resource_table) > (unsigned int)size) { + return -RPROC_ERR_RSC_TAB_TRUNC; + } + + /* Supported version */ + if (rsc_table->ver != RSC_TAB_SUPPORTED_VERSION) { + return -RPROC_ERR_RSC_TAB_VER; + } + + /* Offset array */ + offset = sizeof(struct resource_table) + + rsc_table->num * sizeof(rsc_table->offset[0]); + + if (offset > (unsigned int)size) { + return -RPROC_ERR_RSC_TAB_TRUNC; + } + + /* Reserved fields - must be zero */ + if ((rsc_table->reserved[0] != 0 || rsc_table->reserved[1]) != 0) { + return -RPROC_ERR_RSC_TAB_RSVD; + } + + /* Loop through the offset array and parse each resource entry */ + for (idx = 0; idx < rsc_table->num; idx++) { + rsc_start = (char *)rsc_table; + rsc_start += rsc_table->offset[idx]; + if (io && + metal_io_virt_to_offset(io, rsc_start) == METAL_BAD_OFFSET) + return -RPROC_ERR_RSC_TAB_TRUNC; + rsc_type = *((uint32_t *)rsc_start); + if (rsc_type < RSC_LAST) + status = rsc_handler_table[rsc_type](rproc, + rsc_start); + else if (rsc_type >= RSC_VENDOR_START && + rsc_type <= RSC_VENDOR_END) + status = handle_vendor_rsc(rproc, rsc_start); + if (status == -RPROC_ERR_RSC_TAB_NS) { + status = 0; + continue; + } + else if (status) + break; + } + + return status; +} + +/** + * handle_carve_out_rsc + * + * Carveout resource handler. + * + * @param rproc - pointer to remote remoteproc + * @param rsc - pointer to carveout resource + * + * @returns - 0 for success, or negative value for failure + * + */ +int handle_carve_out_rsc(struct remoteproc *rproc, void *rsc) +{ + struct fw_rsc_carveout *carve_rsc = (struct fw_rsc_carveout *)rsc; + metal_phys_addr_t da; + metal_phys_addr_t pa; + size_t size; + unsigned int attribute; + + /* Validate resource fields */ + if (!carve_rsc) { + return -RPROC_ERR_RSC_TAB_NP; + } + + if (carve_rsc->reserved) { + return -RPROC_ERR_RSC_TAB_RSVD; + } + pa = carve_rsc->pa; + da = carve_rsc->da; + size = carve_rsc->len; + attribute = carve_rsc->flags; + if (remoteproc_mmap(rproc, &pa, &da, size, attribute, NULL)) + return 0; + else + return -RPROC_EINVAL; +} + +int handle_vendor_rsc(struct remoteproc *rproc, void *rsc) +{ + if (rproc && rproc->ops->handle_rsc) { + struct fw_rsc_vendor *vend_rsc = rsc; + size_t len = vend_rsc->len; + + return rproc->ops->handle_rsc(rproc, rsc, len); + } + return -RPROC_ERR_RSC_TAB_NS; +} + +int handle_vdev_rsc(struct remoteproc *rproc, void *rsc) +{ + struct fw_rsc_vdev *vdev_rsc = (struct fw_rsc_vdev *)rsc; + unsigned int notifyid, i, num_vrings; + + /* only assign notification IDs but do not initialize vdev */ + notifyid = vdev_rsc->notifyid; + notifyid = remoteproc_allocate_id(rproc, + notifyid, notifyid + 1); + if (notifyid != RSC_NOTIFY_ID_ANY) { + vdev_rsc->notifyid = notifyid; + } + + num_vrings = vdev_rsc->num_of_vrings; + for (i = 0; i < num_vrings; i++) { + struct fw_rsc_vdev_vring *vring_rsc; + + vring_rsc = &vdev_rsc->vring[i]; + notifyid = vring_rsc->notifyid; + notifyid = remoteproc_allocate_id(rproc, + notifyid, + notifyid + 1); + if (notifyid != RSC_NOTIFY_ID_ANY) { + vdev_rsc->notifyid = notifyid; + } + } + + return 0; +} + +/** + * handle_trace_rsc + * + * trace resource handler. + * + * @param rproc - pointer to remote remoteproc + * @param rsc - pointer to trace resource + * + * @returns - no service error + * + */ +int handle_trace_rsc(struct remoteproc *rproc, void *rsc) +{ + struct fw_rsc_trace *vdev_rsc = (struct fw_rsc_trace *)rsc; + (void)rproc; + + if (vdev_rsc->da != FW_RSC_U32_ADDR_ANY && vdev_rsc->len != 0) + return 0; + /* FIXME: master should allocated a memory used by slave */ + + return -RPROC_ERR_RSC_TAB_NS; +} + +/** + * handle_dummy_rsc + * + * dummy resource handler. + * + * @param rproc - pointer to remote remoteproc + * @param rsc - pointer to trace resource + * + * @returns - no service error + * + */ +static int handle_dummy_rsc(struct remoteproc *rproc, void *rsc) +{ + (void)rproc; + (void)rsc; + + return -RPROC_ERR_RSC_TAB_NS; +} + +size_t find_rsc(void *rsc_table, unsigned int rsc_type, unsigned int index) +{ + struct resource_table *r_table = rsc_table; + unsigned int i, rsc_index; + unsigned int lrsc_type; + char *rsc_start; + + metal_assert(r_table); + /* Loop through the offset array and parse each resource entry */ + rsc_index = 0; + for (i = 0; i < r_table->num; i++) { + rsc_start = (char *)r_table; + rsc_start += r_table->offset[i]; + lrsc_type = *((uint32_t *)rsc_start); + if (lrsc_type == rsc_type) { + if (rsc_index++ == index) + return r_table->offset[i]; + } + } + return 0; +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/rpmsg/Makefile b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/rpmsg/Makefile new file mode 100644 index 000000000..962b34d0b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/rpmsg/Makefile @@ -0,0 +1,5 @@ +SRC_DIR := + +SRC_FILES := $(wildcard *.c) + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/rpmsg/rpmsg.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/rpmsg/rpmsg.c new file mode 100644 index 000000000..2c9a4a8e3 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/rpmsg/rpmsg.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * Copyright (c) 2018 Linaro, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "rpmsg_internal.h" + +/** + * rpmsg_get_address + * + * This function provides unique 32 bit address. + * + * @param bitmap - bit map for addresses + * @param size - size of bitmap + * + * return - a unique address + */ +static uint32_t rpmsg_get_address(unsigned long *bitmap, int size) +{ + unsigned int addr = RPMSG_ADDR_ANY; + unsigned int nextbit; + + nextbit = metal_bitmap_next_clear_bit(bitmap, 0, size); + if (nextbit < (uint32_t)size) { + addr = nextbit; + metal_bitmap_set_bit(bitmap, nextbit); + } + + return addr; +} + +/** + * rpmsg_release_address + * + * Frees the given address. + * + * @param bitmap - bit map for addresses + * @param size - size of bitmap + * @param addr - address to free + */ +static void rpmsg_release_address(unsigned long *bitmap, int size, + int addr) +{ + if (addr < size) + metal_bitmap_clear_bit(bitmap, addr); +} + +/** + * rpmsg_is_address_set + * + * Checks whether address is used or free. + * + * @param bitmap - bit map for addresses + * @param size - size of bitmap + * @param addr - address to free + * + * return - TRUE/FALSE + */ +static int rpmsg_is_address_set(unsigned long *bitmap, int size, int addr) +{ + if (addr < size) + return metal_bitmap_is_bit_set(bitmap, addr); + else + return RPMSG_ERR_PARAM; +} + +/** + * rpmsg_set_address + * + * Marks the address as consumed. + * + * @param bitmap - bit map for addresses + * @param size - size of bitmap + * @param addr - address to free + * + * return - none + */ +static int rpmsg_set_address(unsigned long *bitmap, int size, int addr) +{ + if (addr < size) { + metal_bitmap_set_bit(bitmap, addr); + return RPMSG_SUCCESS; + } else { + return RPMSG_ERR_PARAM; + } +} + +/** + * This function sends rpmsg "message" to remote device. + * + * @param ept - pointer to end point + * @param src - source address of channel + * @param dst - destination address of channel + * @param data - data to transmit + * @param size - size of data + * @param wait - boolean, wait or not for buffer to become + * available + * + * @return - size of data sent or negative value for failure. + * + */ +int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, + uint32_t dst, const void *data, int size, + int wait) +{ + struct rpmsg_device *rdev; + + if (!ept || !ept->rdev || !data || dst == RPMSG_ADDR_ANY) + return RPMSG_ERR_PARAM; + + rdev = ept->rdev; + + if (rdev->ops.send_offchannel_raw) + return rdev->ops.send_offchannel_raw(rdev, src, dst, data, + size, wait); + + return RPMSG_ERR_PARAM; +} + +int rpmsg_send_ns_message(struct rpmsg_endpoint *ept, unsigned long flags) +{ + struct rpmsg_ns_msg ns_msg; + int ret; + + ns_msg.flags = flags; + ns_msg.addr = ept->addr; + strncpy(ns_msg.name, ept->name, sizeof(ns_msg.name)); + ret = rpmsg_send_offchannel_raw(ept, ept->addr, + RPMSG_NS_EPT_ADDR, + &ns_msg, sizeof(ns_msg), true); + if (ret < 0) + return ret; + else + return RPMSG_SUCCESS; +} + +struct rpmsg_endpoint *rpmsg_get_endpoint(struct rpmsg_device *rdev, + const char *name, uint32_t addr, + uint32_t dest_addr) +{ + struct metal_list *node; + struct rpmsg_endpoint *ept; + + metal_list_for_each(&rdev->endpoints, node) { + int name_match = 0; + + ept = metal_container_of(node, struct rpmsg_endpoint, node); + /* try to get by local address only */ + if (addr != RPMSG_ADDR_ANY && ept->addr == addr) + return ept; + /* try to find match on local end remote address */ + if (addr == ept->addr && dest_addr == ept->dest_addr) + return ept; + /* else use name service and destination address */ + if (name) + name_match = !strncmp(ept->name, name, + sizeof(ept->name)); + if (!name || !name_match) + continue; + /* destination address is known, equal to ept remote address*/ + if (dest_addr != RPMSG_ADDR_ANY && ept->dest_addr == dest_addr) + return ept; + /* ept is registered but not associated to remote ept*/ + if (addr == RPMSG_ADDR_ANY && ept->dest_addr == RPMSG_ADDR_ANY) + return ept; + } + return NULL; +} + +static void rpmsg_unregister_endpoint(struct rpmsg_endpoint *ept) +{ + struct rpmsg_device *rdev; + + if (!ept) + return; + + rdev = ept->rdev; + + if (ept->addr != RPMSG_ADDR_ANY) + rpmsg_release_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, + ept->addr); + metal_list_del(&ept->node); +} + +int rpmsg_register_endpoint(struct rpmsg_device *rdev, + struct rpmsg_endpoint *ept) +{ + ept->rdev = rdev; + + metal_list_add_tail(&rdev->endpoints, &ept->node); + return RPMSG_SUCCESS; +} + +int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, + const char *name, uint32_t src, uint32_t dest, + rpmsg_ept_cb cb, rpmsg_ns_unbind_cb unbind_cb) +{ + int status; + uint32_t addr = src; + + if (!ept) + return RPMSG_ERR_PARAM; + + metal_mutex_acquire(&rdev->lock); + if (src != RPMSG_ADDR_ANY) { + status = rpmsg_is_address_set(rdev->bitmap, + RPMSG_ADDR_BMP_SIZE, src); + if (!status) { + /* Mark the address as used in the address bitmap. */ + rpmsg_set_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, + src); + } else if (status > 0) { + status = RPMSG_SUCCESS; + goto ret_status; + } else { + goto ret_status; + } + } else { + addr = rpmsg_get_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE); + } + + rpmsg_init_ept(ept, name, addr, dest, cb, unbind_cb); + + status = rpmsg_register_endpoint(rdev, ept); + if (status < 0) + rpmsg_release_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, addr); + + if (!status && ept->dest_addr == RPMSG_ADDR_ANY) { + /* Send NS announcement to remote processor */ + metal_mutex_release(&rdev->lock); + status = rpmsg_send_ns_message(ept, RPMSG_NS_CREATE); + metal_mutex_acquire(&rdev->lock); + if (status) + rpmsg_unregister_endpoint(ept); + } + +ret_status: + metal_mutex_release(&rdev->lock); + return status; +} + +/** + * rpmsg_destroy_ept + * + * This function deletes rpmsg endpoint and performs cleanup. + * + * @param ept - pointer to endpoint to destroy + * + */ +void rpmsg_destroy_ept(struct rpmsg_endpoint *ept) +{ + struct rpmsg_device *rdev; + + if (!ept) + return; + + rdev = ept->rdev; + if (ept->addr != RPMSG_NS_EPT_ADDR) + (void)rpmsg_send_ns_message(ept, RPMSG_NS_DESTROY); + metal_mutex_acquire(&rdev->lock); + rpmsg_unregister_endpoint(ept); + metal_mutex_release(&rdev->lock); +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/rpmsg/rpmsg_internal.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/rpmsg/rpmsg_internal.h new file mode 100644 index 000000000..535a83545 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/rpmsg/rpmsg_internal.h @@ -0,0 +1,105 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * $FreeBSD$ + */ + +#ifndef _RPMSG_INTERNAL_H_ +#define _RPMSG_INTERNAL_H_ + +#include +#include + +#if defined __cplusplus +extern "C" { +#endif + +#ifdef RPMSG_DEBUG +#define RPMSG_ASSERT(_exp, _msg) do { \ + if (!(_exp)) { \ + openamp_print("FATAL: %s - _msg", __func__); \ + while (1) { \ + ; \ + } \ + } \ + } while (0) +#else +#define RPMSG_ASSERT(_exp, _msg) do { \ + if (!(_exp)) \ + while (1) { \ + ; \ + } \ + } while (0) +#endif + +#define RPMSG_LOCATE_DATA(p) ((unsigned char *)(p) + sizeof(struct rpmsg_hdr)) +/** + * enum rpmsg_ns_flags - dynamic name service announcement flags + * + * @RPMSG_NS_CREATE: a new remote service was just created + * @RPMSG_NS_DESTROY: a known remote service was just destroyed + * @RPMSG_NS_CREATE_WITH_ACK: a new remote service was just created waiting + * acknowledgment. + */ +enum rpmsg_ns_flags { + RPMSG_NS_CREATE = 0, + RPMSG_NS_DESTROY = 1, +}; + +/** + * struct rpmsg_hdr - common header for all rpmsg messages + * @src: source address + * @dst: destination address + * @reserved: reserved for future use + * @len: length of payload (in bytes) + * @flags: message flags + * + * Every message sent(/received) on the rpmsg bus begins with this header. + */ +OPENAMP_PACKED_BEGIN +struct rpmsg_hdr { + uint32_t src; + uint32_t dst; + uint32_t reserved; + uint16_t len; + uint16_t flags; +} OPENAMP_PACKED_END; + +/** + * struct rpmsg_ns_msg - dynamic name service announcement message + * @name: name of remote service that is published + * @addr: address of remote service that is published + * @flags: indicates whether service is created or destroyed + * + * This message is sent across to publish a new service, or announce + * about its removal. When we receive these messages, an appropriate + * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe() + * or ->remove() handler of the appropriate rpmsg driver will be invoked + * (if/as-soon-as one is registered). + */ +OPENAMP_PACKED_BEGIN +struct rpmsg_ns_msg { + char name[RPMSG_NAME_SIZE]; + uint32_t addr; + uint32_t flags; +} OPENAMP_PACKED_END; + +int rpmsg_send_ns_message(struct rpmsg_endpoint *ept, unsigned long flags); + +struct rpmsg_endpoint *rpmsg_get_endpoint(struct rpmsg_device *rvdev, + const char *name, uint32_t addr, + uint32_t dest_addr); +int rpmsg_register_endpoint(struct rpmsg_device *rdev, + struct rpmsg_endpoint *ept); + +static inline struct rpmsg_endpoint * +rpmsg_get_ept_from_addr(struct rpmsg_device *rdev, uint32_t addr) +{ + return rpmsg_get_endpoint(rdev, NULL, addr, RPMSG_ADDR_ANY); +} + +#if defined __cplusplus +} +#endif + +#endif /* _RPMSG_INTERNAL_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/rpmsg/rpmsg_virtio.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/rpmsg/rpmsg_virtio.c new file mode 100644 index 000000000..93ada2985 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/rpmsg/rpmsg_virtio.c @@ -0,0 +1,681 @@ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + * Copyright (c) 2018 Linaro, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "rpmsg_internal.h" + +#include + +#define RPMSG_NUM_VRINGS (2) + +/* Total tick count for 15secs - 1msec tick. */ +#define RPMSG_TICK_COUNT 15000 + +/* Time to wait - In multiple of 10 msecs. */ +#define RPMSG_TICKS_PER_INTERVAL 10 + +#define WORD_SIZE sizeof(unsigned long) +#define WORD_ALIGN(a) ((((a) & (WORD_SIZE - 1)) != 0) ? \ + (((a) & (~(WORD_SIZE - 1))) + WORD_SIZE) : (a)) + +#ifndef VIRTIO_SLAVE_ONLY +metal_weak void * +rpmsg_virtio_shm_pool_get_buffer(struct rpmsg_virtio_shm_pool *shpool, + size_t size) +{ + void *buffer; + + if (shpool->avail < size) + return NULL; + buffer = (void *)((char *)shpool->base + shpool->size - shpool->avail); + shpool->avail -= size; + + return buffer; +} +#endif /*!VIRTIO_SLAVE_ONLY*/ + +void rpmsg_virtio_init_shm_pool(struct rpmsg_virtio_shm_pool *shpool, + void *shb, size_t size) +{ + if (!shpool) + return; + shpool->base = shb; + shpool->size = WORD_ALIGN(size); + shpool->avail = WORD_ALIGN(size); +} + +/** + * rpmsg_virtio_return_buffer + * + * Places the used buffer back on the virtqueue. + * + * @param rvdev - pointer to remote core + * @param buffer - buffer pointer + * @param len - buffer length + * @param idx - buffer index + * + */ +static void rpmsg_virtio_return_buffer(struct rpmsg_virtio_device *rvdev, + void *buffer, unsigned long len, + unsigned short idx) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + struct virtqueue_buf vqbuf; + + (void)idx; + /* Initialize buffer node */ + vqbuf.buf = buffer; + vqbuf.len = len; + virtqueue_add_buffer(rvdev->rvq, &vqbuf, 0, 1, buffer); + } +#endif /*VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + (void)buffer; + virtqueue_add_consumed_buffer(rvdev->rvq, idx, len); + } +#endif /*VIRTIO_MASTER_ONLY*/ +} + +/** + * rpmsg_virtio_enqueue_buffer + * + * Places buffer on the virtqueue for consumption by the other side. + * + * @param rvdev - pointer to rpmsg virtio + * @param buffer - buffer pointer + * @param len - buffer length + * @param idx - buffer index + * + * @return - status of function execution + */ +static int rpmsg_virtio_enqueue_buffer(struct rpmsg_virtio_device *rvdev, + void *buffer, unsigned long len, + unsigned short idx) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + struct virtqueue_buf vqbuf; + (void)idx; + + /* Initialize buffer node */ + vqbuf.buf = buffer; + vqbuf.len = len; + return virtqueue_add_buffer(rvdev->svq, &vqbuf, 0, 1, buffer); + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + (void)buffer; + return virtqueue_add_consumed_buffer(rvdev->svq, idx, len); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + return 0; +} + +/** + * rpmsg_virtio_get_tx_buffer + * + * Provides buffer to transmit messages. + * + * @param rvdev - pointer to rpmsg device + * @param len - length of returned buffer + * @param idx - buffer index + * + * return - pointer to buffer. + */ +static void *rpmsg_virtio_get_tx_buffer(struct rpmsg_virtio_device *rvdev, + unsigned long *len, + unsigned short *idx) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); + void *data = NULL; + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + data = virtqueue_get_buffer(rvdev->svq, (uint32_t *)len, idx); + if (!data && rvdev->svq->vq_free_cnt) { + data = rpmsg_virtio_shm_pool_get_buffer(rvdev->shpool, + RPMSG_BUFFER_SIZE); + *len = RPMSG_BUFFER_SIZE; + *idx = 0; + } + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + data = virtqueue_get_available_buffer(rvdev->svq, idx, + (uint32_t *)len); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + + return data; +} + +/** + * rpmsg_virtio_get_rx_buffer + * + * Retrieves the received buffer from the virtqueue. + * + * @param rvdev - pointer to rpmsg device + * @param len - size of received buffer + * @param idx - index of buffer + * + * @return - pointer to received buffer + * + */ +static void *rpmsg_virtio_get_rx_buffer(struct rpmsg_virtio_device *rvdev, + unsigned long *len, + unsigned short *idx) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); + void *data = NULL; + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + data = virtqueue_get_buffer(rvdev->rvq, (uint32_t *)len, idx); + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + data = + virtqueue_get_available_buffer(rvdev->rvq, idx, + (uint32_t *)len); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + + if (data) { + /* FIX ME: library should not worry about if it needs + * to flush/invalidate cache, it is shared memory. + * The shared memory should be mapped properly before + * using it. + */ + metal_cache_invalidate(data, (unsigned int)(*len)); + } + + return data; +} + +#ifndef VIRTIO_MASTER_ONLY +/** + * check if the remote is ready to start RPMsg communication + */ +static int rpmsg_virtio_wait_remote_ready(struct rpmsg_virtio_device *rvdev) +{ + uint8_t status; + + while (1) { + status = rpmsg_virtio_get_status(rvdev); + /* Busy wait until the remote is ready */ + if (status & VIRTIO_CONFIG_STATUS_NEEDS_RESET) { + rpmsg_virtio_set_status(rvdev, 0); + /* TODO notify remote processor */ + } else if (status & VIRTIO_CONFIG_STATUS_DRIVER_OK) { + return true; + } + /* TODO: clarify metal_cpu_yield usage*/ + metal_cpu_yield(); + } + + return false; +} +#endif /*!VIRTIO_MASTER_ONLY*/ + +/** + * _rpmsg_virtio_get_buffer_size + * + * Returns buffer size available for sending messages. + * + * @param channel - pointer to rpmsg channel + * + * @return - buffer size + * + */ +static int _rpmsg_virtio_get_buffer_size(struct rpmsg_virtio_device *rvdev) +{ + unsigned int role = rpmsg_virtio_get_role(rvdev); + int length = 0; + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + /* + * If device role is Remote then buffers are provided by us + * (RPMSG Master), so just provide the macro. + */ + length = RPMSG_BUFFER_SIZE - sizeof(struct rpmsg_hdr); + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + /* + * If other core is Master then buffers are provided by it, + * so get the buffer size from the virtqueue. + */ + length = + (int)virtqueue_get_desc_size(rvdev->svq) - + sizeof(struct rpmsg_hdr); + if (length < 0) { + length = 0; + } + } +#endif /*!VIRTIO_MASTER_ONLY*/ + + return length; +} + +/** + * This function sends rpmsg "message" to remote device. + * + * @param rdev - pointer to rpmsg device + * @param src - source address of channel + * @param dst - destination address of channel + * @param data - data to transmit + * @param size - size of data + * @param wait - boolean, wait or not for buffer to become + * available + * + * @return - size of data sent or negative value for failure. + * + */ +static int rpmsg_virtio_send_offchannel_raw(struct rpmsg_device *rdev, + uint32_t src, uint32_t dst, + const void *data, + int size, int wait) +{ + struct rpmsg_virtio_device *rvdev; + struct rpmsg_hdr rp_hdr; + void *buffer = NULL; + unsigned short idx; + int tick_count = 0; + unsigned long buff_len; + int status; + struct metal_io_region *io; + + /* Get the associated remote device for channel. */ + rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev); + + status = rpmsg_virtio_get_status(rvdev); + /* Validate device state */ + if (!(status & VIRTIO_CONFIG_STATUS_DRIVER_OK)) { + return RPMSG_ERR_DEV_STATE; + } + + if (wait) + tick_count = RPMSG_TICK_COUNT / RPMSG_TICKS_PER_INTERVAL; + else + tick_count = 0; + + while (1) { + int avail_size; + + /* Lock the device to enable exclusive access to virtqueues */ + metal_mutex_acquire(&rdev->lock); + avail_size = _rpmsg_virtio_get_buffer_size(rvdev); + if (size <= avail_size) + buffer = rpmsg_virtio_get_tx_buffer(rvdev, &buff_len, + &idx); + metal_mutex_release(&rdev->lock); + if (buffer || !tick_count) + break; + metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL); + tick_count--; + } + if (!buffer) + return RPMSG_ERR_NO_BUFF; + + /* Initialize RPMSG header. */ + rp_hdr.dst = dst; + rp_hdr.src = src; + rp_hdr.len = size; + rp_hdr.reserved = 0; + + /* Copy data to rpmsg buffer. */ + io = rvdev->shbuf_io; + status = metal_io_block_write(io, metal_io_virt_to_offset(io, buffer), + &rp_hdr, sizeof(rp_hdr)); + RPMSG_ASSERT(status == sizeof(rp_hdr), "failed to write header\n"); + + status = metal_io_block_write(io, + metal_io_virt_to_offset(io, + RPMSG_LOCATE_DATA(buffer)), + data, size); + RPMSG_ASSERT(status == size, "failed to write buffer\n"); + metal_mutex_acquire(&rdev->lock); + + /* Enqueue buffer on virtqueue. */ + status = rpmsg_virtio_enqueue_buffer(rvdev, buffer, buff_len, idx); + RPMSG_ASSERT(status == VQUEUE_SUCCESS, "failed to enqueue buffer\n"); + /* Let the other side know that there is a job to process. */ + virtqueue_kick(rvdev->svq); + + metal_mutex_release(&rdev->lock); + + return size; +} + +/** + * rpmsg_virtio_tx_callback + * + * Tx callback function. + * + * @param vq - pointer to virtqueue on which Tx is has been + * completed. + * + */ +static void rpmsg_virtio_tx_callback(struct virtqueue *vq) +{ + (void)vq; +} + +/** + * rpmsg_virtio_rx_callback + * + * Rx callback function. + * + * @param vq - pointer to virtqueue on which messages is received + * + */ +static void rpmsg_virtio_rx_callback(struct virtqueue *vq) +{ + struct virtio_device *vdev = vq->vq_dev; + struct rpmsg_virtio_device *rvdev = vdev->priv; + struct rpmsg_device *rdev = &rvdev->rdev; + struct rpmsg_endpoint *ept; + struct rpmsg_hdr *rp_hdr; + unsigned long len; + unsigned short idx; + int status; + + metal_mutex_acquire(&rdev->lock); + + /* Process the received data from remote node */ + rp_hdr = (struct rpmsg_hdr *)rpmsg_virtio_get_rx_buffer(rvdev, + &len, &idx); + + metal_mutex_release(&rdev->lock); + + while (rp_hdr) { + /* Get the channel node from the remote device channels list. */ + metal_mutex_acquire(&rdev->lock); + ept = rpmsg_get_ept_from_addr(rdev, rp_hdr->dst); + metal_mutex_release(&rdev->lock); + + if (!ept) + /* Fatal error no endpoint for the given dst addr. */ + return; + + if (ept->dest_addr == RPMSG_ADDR_ANY) { + /* + * First message received from the remote side, + * update channel destination address + */ + ept->dest_addr = rp_hdr->src; + } + status = ept->cb(ept, (void *)RPMSG_LOCATE_DATA(rp_hdr), + rp_hdr->len, ept->addr, ept->priv); + + RPMSG_ASSERT(status == RPMSG_SUCCESS, + "unexpected callback status\n"); + metal_mutex_acquire(&rdev->lock); + + /* Return used buffers. */ + rpmsg_virtio_return_buffer(rvdev, rp_hdr, len, idx); + + rp_hdr = (struct rpmsg_hdr *) + rpmsg_virtio_get_rx_buffer(rvdev, &len, &idx); + metal_mutex_release(&rdev->lock); + } +} + +/** + * rpmsg_virtio_ns_callback + * + * This callback handles name service announcement from the remote device + * and creates/deletes rpmsg channels. + * + * @param server_chnl - pointer to server channel control block. + * @param data - pointer to received messages + * @param len - length of received data + * @param priv - any private data + * @param src - source address + * + * @return - rpmag endpoint callback handled + */ +static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, + size_t len, uint32_t src, void *priv) +{ + struct rpmsg_device *rdev = ept->rdev; + struct rpmsg_virtio_device *rvdev = (struct rpmsg_virtio_device *)rdev; + struct metal_io_region *io = rvdev->shbuf_io; + struct rpmsg_endpoint *_ept; + struct rpmsg_ns_msg *ns_msg; + uint32_t dest; + char name[RPMSG_NAME_SIZE]; + + (void)priv; + (void)src; + + ns_msg = (struct rpmsg_ns_msg *)data; + if (len != sizeof(*ns_msg)) + /* Returns as the message is corrupted */ + return RPMSG_SUCCESS; + metal_io_block_read(io, + metal_io_virt_to_offset(io, ns_msg->name), + &name, sizeof(name)); + dest = ns_msg->addr; + + /* check if a Ept has been locally registered */ + metal_mutex_acquire(&rdev->lock); + _ept = rpmsg_get_endpoint(rdev, name, RPMSG_ADDR_ANY, dest); + + if (ns_msg->flags & RPMSG_NS_DESTROY) { + if (_ept) + _ept->dest_addr = RPMSG_ADDR_ANY; + metal_mutex_release(&rdev->lock); + if (_ept && _ept->ns_unbind_cb) + _ept->ns_unbind_cb(ept); + } else { + if (!_ept) { + /* + * send callback to application, that can + * - create the associated endpoints. + * - store information for future use. + * - just ignore the request as service not supported. + */ + metal_mutex_release(&rdev->lock); + if (rdev->ns_bind_cb) + rdev->ns_bind_cb(rdev, name, dest); + } else { + _ept->dest_addr = dest; + metal_mutex_release(&rdev->lock); + } + } + + return RPMSG_SUCCESS; +} + +int rpmsg_virtio_get_buffer_size(struct rpmsg_device *rdev) +{ + int size; + struct rpmsg_virtio_device *rvdev; + + if (!rdev) + return RPMSG_ERR_PARAM; + metal_mutex_acquire(&rdev->lock); + rvdev = (struct rpmsg_virtio_device *)rdev; + size = _rpmsg_virtio_get_buffer_size(rvdev); + metal_mutex_release(&rdev->lock); + return size; +} + +int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + struct virtio_device *vdev, + rpmsg_ns_bind_cb ns_bind_cb, + struct metal_io_region *shm_io, + struct rpmsg_virtio_shm_pool *shpool) +{ + struct rpmsg_device *rdev; + const char *vq_names[RPMSG_NUM_VRINGS]; + typedef void (*vqcallback)(struct virtqueue *vq); + vqcallback callback[RPMSG_NUM_VRINGS]; + unsigned long dev_features; + int status; + unsigned int i, role; + + rdev = &rvdev->rdev; + memset(rdev, 0, sizeof(*rdev)); + metal_mutex_init(&rdev->lock); + rvdev->vdev = vdev; + rdev->ns_bind_cb = ns_bind_cb; + vdev->priv = rvdev; + rdev->ops.send_offchannel_raw = rpmsg_virtio_send_offchannel_raw; + role = rpmsg_virtio_get_role(rvdev); + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + /* + * Since device is RPMSG Remote so we need to manage the + * shared buffers. Create shared memory pool to handle buffers. + */ + if (!shpool) + return RPMSG_ERR_PARAM; + if (!shpool->size) + return RPMSG_ERR_NO_BUFF; + rvdev->shpool = shpool; + + vq_names[0] = "rx_vq"; + vq_names[1] = "tx_vq"; + callback[0] = rpmsg_virtio_rx_callback; + callback[1] = rpmsg_virtio_tx_callback; + rvdev->rvq = vdev->vrings_info[0].vq; + rvdev->svq = vdev->vrings_info[1].vq; + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + +#ifndef VIRTIO_MASTER_ONLY + (void)shpool; + if (role == RPMSG_REMOTE) { + vq_names[0] = "tx_vq"; + vq_names[1] = "rx_vq"; + callback[0] = rpmsg_virtio_tx_callback; + callback[1] = rpmsg_virtio_rx_callback; + rvdev->rvq = vdev->vrings_info[1].vq; + rvdev->svq = vdev->vrings_info[0].vq; + } +#endif /*!VIRTIO_MASTER_ONLY*/ + rvdev->shbuf_io = shm_io; + +#ifndef VIRTIO_MASTER_ONLY + if (role == RPMSG_REMOTE) { + /* wait synchro with the master */ + rpmsg_virtio_wait_remote_ready(rvdev); + } +#endif /*!VIRTIO_MASTER_ONLY*/ + + /* Create virtqueues for remote device */ + status = rpmsg_virtio_create_virtqueues(rvdev, 0, RPMSG_NUM_VRINGS, + vq_names, callback); + if (status != RPMSG_SUCCESS) + return status; + + /* TODO: can have a virtio function to set the shared memory I/O */ + for (i = 0; i < RPMSG_NUM_VRINGS; i++) { + struct virtqueue *vq; + + vq = vdev->vrings_info[i].vq; + vq->shm_io = shm_io; + } + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + struct virtqueue_buf vqbuf; + unsigned int idx; + void *buffer; + + vqbuf.len = RPMSG_BUFFER_SIZE; + for (idx = 0; idx < rvdev->rvq->vq_nentries; idx++) { + /* Initialize TX virtqueue buffers for remote device */ + buffer = rpmsg_virtio_shm_pool_get_buffer(shpool, + RPMSG_BUFFER_SIZE); + + if (!buffer) { + return RPMSG_ERR_NO_BUFF; + } + + vqbuf.buf = buffer; + + metal_io_block_set(shm_io, + metal_io_virt_to_offset(shm_io, + buffer), + 0x00, RPMSG_BUFFER_SIZE); + status = + virtqueue_add_buffer(rvdev->rvq, &vqbuf, 0, 1, + buffer); + + if (status != RPMSG_SUCCESS) { + return status; + } + } + } +#endif /*!VIRTIO_SLAVE_ONLY*/ + /* Initialize channels and endpoints list */ + metal_list_init(&rdev->endpoints); + + dev_features = rpmsg_virtio_get_features(rvdev); + + /* + * Create name service announcement endpoint if device supports name + * service announcement feature. + */ + if ((dev_features & (1 << VIRTIO_RPMSG_F_NS))) { + rpmsg_init_ept(&rdev->ns_ept, "NS", + RPMSG_NS_EPT_ADDR, RPMSG_NS_EPT_ADDR, + rpmsg_virtio_ns_callback, NULL); + (void)rpmsg_register_endpoint(rdev, &rdev->ns_ept); + } + +#ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) + rpmsg_virtio_set_status(rvdev, VIRTIO_CONFIG_STATUS_DRIVER_OK); +#endif /*!VIRTIO_SLAVE_ONLY*/ + return status; +} + +void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev) +{ + struct metal_list *node; + struct rpmsg_device *rdev; + struct rpmsg_endpoint *ept; + + rdev = &rvdev->rdev; + while (!metal_list_is_empty(&rdev->endpoints)) { + node = rdev->endpoints.next; + ept = metal_container_of(node, struct rpmsg_endpoint, node); + rpmsg_destroy_ept(ept); + } + + rvdev->rvq = 0; + rvdev->svq = 0; + + metal_mutex_deinit(&rdev->lock); +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/virtio/Makefile b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/virtio/Makefile new file mode 100644 index 000000000..962b34d0b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/virtio/Makefile @@ -0,0 +1,5 @@ +SRC_DIR := + +SRC_FILES := $(wildcard *.c) + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/virtio/virtio.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/virtio/virtio.c new file mode 100644 index 000000000..01b4e6fc5 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/virtio/virtio.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2011, Bryan Venteicher + * All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#include + +static const char *virtio_feature_name(unsigned long feature, + const struct virtio_feature_desc *); + +//TODO : This structure may change depending on the types of devices we support. +static const struct virtio_ident { + unsigned short devid; + const char *name; +} virtio_ident_table[] = { + { + VIRTIO_ID_NETWORK, "Network"}, { + VIRTIO_ID_BLOCK, "Block"}, { + VIRTIO_ID_CONSOLE, "Console"}, { + VIRTIO_ID_ENTROPY, "Entropy"}, { + VIRTIO_ID_BALLOON, "Balloon"}, { + VIRTIO_ID_IOMEMORY, "IOMemory"}, { + VIRTIO_ID_SCSI, "SCSI"}, { + VIRTIO_ID_9P, "9P Transport"}, { + 0, NULL} +}; + +/* Device independent features. */ +static const struct virtio_feature_desc virtio_common_feature_desc[] = { + {VIRTIO_F_NOTIFY_ON_EMPTY, "NotifyOnEmpty"}, + {VIRTIO_RING_F_INDIRECT_DESC, "RingIndirect"}, + {VIRTIO_RING_F_EVENT_IDX, "EventIdx"}, + {VIRTIO_F_BAD_FEATURE, "BadFeature"}, + + {0, NULL} +}; + +const char *virtio_dev_name(unsigned short devid) +{ + const struct virtio_ident *ident; + + for (ident = virtio_ident_table; ident->name != NULL; ident++) { + if (ident->devid == devid) + return (ident->name); + } + + return (NULL); +} + +static const char *virtio_feature_name(unsigned long val, + const struct virtio_feature_desc *desc) +{ + int i, j; + const struct virtio_feature_desc *descs[2] = { desc, + virtio_common_feature_desc + }; + + for (i = 0; i < 2; i++) { + if (!descs[i]) + continue; + + for (j = 0; descs[i][j].vfd_val != 0; j++) { + if (val == descs[i][j].vfd_val) + return (descs[i][j].vfd_str); + } + } + + return (NULL); +} + +void virtio_describe(struct virtio_device *dev, const char *msg, + uint32_t features, struct virtio_feature_desc *desc) +{ + (void)dev; + (void)msg; + (void)features; + + // TODO: Not used currently - keeping it for future use + virtio_feature_name(0, desc); +} + +int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags, + unsigned int nvqs, const char *names[], + vq_callback *callbacks[]) +{ + struct virtio_vring_info *vring_info; + struct vring_alloc_info *vring_alloc; + unsigned int num_vrings, i; + int ret; + (void)flags; + + num_vrings = vdev->vrings_num; + if (nvqs > num_vrings) + return ERROR_VQUEUE_INVLD_PARAM; + /* Initialize virtqueue for each vring */ + for (i = 0; i < nvqs; i++) { + vring_info = &vdev->vrings_info[i]; + + vring_alloc = &vring_info->info; +#ifndef VIRTIO_SLAVE_ONLY + if (vdev->role == VIRTIO_DEV_MASTER) { + size_t offset; + struct metal_io_region *io = vring_info->io; + + offset = metal_io_virt_to_offset(io, + vring_alloc->vaddr); + metal_io_block_set(io, offset, 0, + vring_size(vring_alloc->num_descs, + vring_alloc->align)); + } +#endif + ret = virtqueue_create(vdev, i, names[i], vring_alloc, + callbacks[i], vdev->func->notify, + vring_info->vq); + if (ret) + return ret; + } + return 0; +} + diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/virtio/virtqueue.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/virtio/virtqueue.c new file mode 100644 index 000000000..1f4655209 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv/linaro/open-amp/lib/virtio/virtqueue.c @@ -0,0 +1,618 @@ +/*- + * Copyright (c) 2011, Bryan Venteicher + * All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +/* Prototype for internal functions. */ +static void vq_ring_init(struct virtqueue *, void *, int); +static void vq_ring_update_avail(struct virtqueue *, uint16_t); +static uint16_t vq_ring_add_buffer(struct virtqueue *, struct vring_desc *, + uint16_t, struct virtqueue_buf *, int, int); +static int vq_ring_enable_interrupt(struct virtqueue *, uint16_t); +static void vq_ring_free_chain(struct virtqueue *, uint16_t); +static int vq_ring_must_notify_host(struct virtqueue *vq); +static void vq_ring_notify_host(struct virtqueue *vq); +static int virtqueue_nused(struct virtqueue *vq); + +/* Default implementation of P2V based on libmetal */ +static inline void *virtqueue_phys_to_virt(struct virtqueue *vq, + metal_phys_addr_t phys) +{ + struct metal_io_region *io = vq->shm_io; + + return metal_io_phys_to_virt(io, phys); +} + +/* Default implementation of V2P based on libmetal */ +static inline metal_phys_addr_t virtqueue_virt_to_phys(struct virtqueue *vq, + void *buf) +{ + struct metal_io_region *io = vq->shm_io; + + return metal_io_virt_to_phys(io, buf); +} + +/** + * virtqueue_create - Creates new VirtIO queue + * + * @param device - Pointer to VirtIO device + * @param id - VirtIO queue ID , must be unique + * @param name - Name of VirtIO queue + * @param ring - Pointer to vring_alloc_info control block + * @param callback - Pointer to callback function, invoked + * when message is available on VirtIO queue + * @param notify - Pointer to notify function, used to notify + * other side that there is job available for it + * @param vq - Created VirtIO queue. + * + * @return - Function status + */ +int virtqueue_create(struct virtio_device *virt_dev, unsigned short id, + const char *name, struct vring_alloc_info *ring, + void (*callback)(struct virtqueue *vq), + void (*notify)(struct virtqueue *vq), + struct virtqueue *vq) +{ + int status = VQUEUE_SUCCESS; + + VQ_PARAM_CHK(ring == NULL, status, ERROR_VQUEUE_INVLD_PARAM); + VQ_PARAM_CHK(ring->num_descs == 0, status, ERROR_VQUEUE_INVLD_PARAM); + VQ_PARAM_CHK(ring->num_descs & (ring->num_descs - 1), status, + ERROR_VRING_ALIGN); + VQ_PARAM_CHK(vq == NULL, status, ERROR_NO_MEM); + + if (status == VQUEUE_SUCCESS) { + vq->vq_dev = virt_dev; + vq->vq_name = name; + vq->vq_queue_index = id; + vq->vq_nentries = ring->num_descs; + vq->vq_free_cnt = vq->vq_nentries; + vq->callback = callback; + vq->notify = notify; + + /* Initialize vring control block in virtqueue. */ + vq_ring_init(vq, (void *)ring->vaddr, ring->align); + + /* Disable callbacks - will be enabled by the application + * once initialization is completed. + */ + virtqueue_disable_cb(vq); + } + + return (status); +} + +/** + * virtqueue_add_buffer() - Enqueues new buffer in vring for consumption + * by other side. Readable buffers are always + * inserted before writable buffers + * + * @param vq - Pointer to VirtIO queue control block. + * @param buf_list - Pointer to a list of virtqueue buffers. + * @param readable - Number of readable buffers + * @param writable - Number of writable buffers + * @param cookie - Pointer to hold call back data + * + * @return - Function status + */ +int virtqueue_add_buffer(struct virtqueue *vq, struct virtqueue_buf *buf_list, + int readable, int writable, void *cookie) +{ + struct vq_desc_extra *dxp = NULL; + int status = VQUEUE_SUCCESS; + uint16_t head_idx; + uint16_t idx; + int needed; + + needed = readable + writable; + + VQ_PARAM_CHK(vq == NULL, status, ERROR_VQUEUE_INVLD_PARAM); + VQ_PARAM_CHK(needed < 1, status, ERROR_VQUEUE_INVLD_PARAM); + VQ_PARAM_CHK(vq->vq_free_cnt == 0, status, ERROR_VRING_FULL); + + VQUEUE_BUSY(vq); + + if (status == VQUEUE_SUCCESS) { + VQASSERT(vq, cookie != NULL, "enqueuing with no cookie"); + + head_idx = vq->vq_desc_head_idx; + VQ_RING_ASSERT_VALID_IDX(vq, head_idx); + dxp = &vq->vq_descx[head_idx]; + + VQASSERT(vq, dxp->cookie == NULL, + "cookie already exists for index"); + + dxp->cookie = cookie; + dxp->ndescs = needed; + + /* Enqueue buffer onto the ring. */ + idx = vq_ring_add_buffer(vq, vq->vq_ring.desc, head_idx, + buf_list, readable, writable); + + vq->vq_desc_head_idx = idx; + vq->vq_free_cnt -= needed; + + if (vq->vq_free_cnt == 0) { + VQ_RING_ASSERT_CHAIN_TERM(vq); + } else { + VQ_RING_ASSERT_VALID_IDX(vq, idx); + } + + /* + * Update vring_avail control block fields so that other + * side can get buffer using it. + */ + vq_ring_update_avail(vq, head_idx); + } + + VQUEUE_IDLE(vq); + + return status; +} + +/** + * virtqueue_get_buffer - Returns used buffers from VirtIO queue + * + * @param vq - Pointer to VirtIO queue control block + * @param len - Length of conumed buffer + * @param idx - index of the buffer + * + * @return - Pointer to used buffer + */ +void *virtqueue_get_buffer(struct virtqueue *vq, uint32_t *len, uint16_t *idx) +{ + struct vring_used_elem *uep; + void *cookie; + uint16_t used_idx, desc_idx; + + if (!vq || vq->vq_used_cons_idx == vq->vq_ring.used->idx) + return (NULL); + + VQUEUE_BUSY(vq); + + used_idx = vq->vq_used_cons_idx++ & (vq->vq_nentries - 1); + uep = &vq->vq_ring.used->ring[used_idx]; + + atomic_thread_fence(memory_order_seq_cst); + + desc_idx = (uint16_t)uep->id; + if (len) + *len = uep->len; + + vq_ring_free_chain(vq, desc_idx); + + cookie = vq->vq_descx[desc_idx].cookie; + vq->vq_descx[desc_idx].cookie = NULL; + + if (idx) + *idx = used_idx; + VQUEUE_IDLE(vq); + + return cookie; +} + +uint32_t virtqueue_get_buffer_length(struct virtqueue *vq, uint16_t idx) +{ + return vq->vq_ring.desc[idx].len; +} + +/** + * virtqueue_free - Frees VirtIO queue resources + * + * @param vq - Pointer to VirtIO queue control block + * + */ +void virtqueue_free(struct virtqueue *vq) +{ + if (vq) { + if (vq->vq_free_cnt != vq->vq_nentries) { + metal_log(METAL_LOG_WARNING, + "%s: freeing non-empty virtqueue\r\n", + vq->vq_name); + } + + metal_free_memory(vq); + } +} + +/** + * virtqueue_get_available_buffer - Returns buffer available for use in the + * VirtIO queue + * + * @param vq - Pointer to VirtIO queue control block + * @param avail_idx - Pointer to index used in vring desc table + * @param len - Length of buffer + * + * @return - Pointer to available buffer + */ +void *virtqueue_get_available_buffer(struct virtqueue *vq, uint16_t *avail_idx, + uint32_t *len) +{ + uint16_t head_idx = 0; + void *buffer; + + atomic_thread_fence(memory_order_seq_cst); + if (vq->vq_available_idx == vq->vq_ring.avail->idx) { + return NULL; + } + + VQUEUE_BUSY(vq); + + head_idx = vq->vq_available_idx++ & (vq->vq_nentries - 1); + *avail_idx = vq->vq_ring.avail->ring[head_idx]; + + buffer = virtqueue_phys_to_virt(vq, vq->vq_ring.desc[*avail_idx].addr); + *len = vq->vq_ring.desc[*avail_idx].len; + + VQUEUE_IDLE(vq); + + return buffer; +} + +/** + * virtqueue_add_consumed_buffer - Returns consumed buffer back to VirtIO queue + * + * @param vq - Pointer to VirtIO queue control block + * @param head_idx - Index of vring desc containing used buffer + * @param len - Length of buffer + * + * @return - Function status + */ +int virtqueue_add_consumed_buffer(struct virtqueue *vq, uint16_t head_idx, + uint32_t len) +{ + struct vring_used_elem *used_desc = NULL; + uint16_t used_idx; + + if (head_idx > vq->vq_nentries) { + return ERROR_VRING_NO_BUFF; + } + + VQUEUE_BUSY(vq); + + used_idx = vq->vq_ring.used->idx & (vq->vq_nentries - 1); + used_desc = &vq->vq_ring.used->ring[used_idx]; + used_desc->id = head_idx; + used_desc->len = len; + + atomic_thread_fence(memory_order_seq_cst); + + vq->vq_ring.used->idx++; + + VQUEUE_IDLE(vq); + + return VQUEUE_SUCCESS; +} + +/** + * virtqueue_enable_cb - Enables callback generation + * + * @param vq - Pointer to VirtIO queue control block + * + * @return - Function status + */ +int virtqueue_enable_cb(struct virtqueue *vq) +{ + return vq_ring_enable_interrupt(vq, 0); +} + +/** + * virtqueue_enable_cb - Disables callback generation + * + * @param vq - Pointer to VirtIO queue control block + * + */ +void virtqueue_disable_cb(struct virtqueue *vq) +{ + VQUEUE_BUSY(vq); + + if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) { + vring_used_event(&vq->vq_ring) = + vq->vq_used_cons_idx - vq->vq_nentries - 1; + } else { + vq->vq_ring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; + } + + VQUEUE_IDLE(vq); +} + +/** + * virtqueue_kick - Notifies other side that there is buffer available for it. + * + * @param vq - Pointer to VirtIO queue control block + */ +void virtqueue_kick(struct virtqueue *vq) +{ + VQUEUE_BUSY(vq); + + /* Ensure updated avail->idx is visible to host. */ + atomic_thread_fence(memory_order_seq_cst); + + if (vq_ring_must_notify_host(vq)) + vq_ring_notify_host(vq); + + vq->vq_queued_cnt = 0; + + VQUEUE_IDLE(vq); +} + +/** + * virtqueue_dump Dumps important virtqueue fields , use for debugging purposes + * + * @param vq - Pointer to VirtIO queue control block + */ +void virtqueue_dump(struct virtqueue *vq) +{ + if (!vq) + return; + + metal_log(METAL_LOG_DEBUG, + "VQ: %s - size=%d; free=%d; used=%d; queued=%d; " + "desc_head_idx=%d; avail.idx=%d; used_cons_idx=%d; " + "used.idx=%d; avail.flags=0x%x; used.flags=0x%x\r\n", + vq->vq_name, vq->vq_nentries, vq->vq_free_cnt, + virtqueue_nused(vq), vq->vq_queued_cnt, vq->vq_desc_head_idx, + vq->vq_ring.avail->idx, vq->vq_used_cons_idx, + vq->vq_ring.used->idx, vq->vq_ring.avail->flags, + vq->vq_ring.used->flags); +} + +/** + * virtqueue_get_desc_size - Returns vring descriptor size + * + * @param vq - Pointer to VirtIO queue control block + * + * @return - Descriptor length + */ +uint32_t virtqueue_get_desc_size(struct virtqueue *vq) +{ + uint16_t head_idx = 0; + uint16_t avail_idx = 0; + uint32_t len = 0; + + if (vq->vq_available_idx == vq->vq_ring.avail->idx) { + return 0; + } + + VQUEUE_BUSY(vq); + + head_idx = vq->vq_available_idx & (vq->vq_nentries - 1); + avail_idx = vq->vq_ring.avail->ring[head_idx]; + len = vq->vq_ring.desc[avail_idx].len; + + VQUEUE_IDLE(vq); + + return len; +} + +/************************************************************************** + * Helper Functions * + **************************************************************************/ + +/** + * + * vq_ring_add_buffer + * + */ +static uint16_t vq_ring_add_buffer(struct virtqueue *vq, + struct vring_desc *desc, uint16_t head_idx, + struct virtqueue_buf *buf_list, int readable, + int writable) +{ + struct vring_desc *dp; + int i, needed; + uint16_t idx; + + (void)vq; + + needed = readable + writable; + + for (i = 0, idx = head_idx; i < needed; i++, idx = dp->next) { + VQASSERT(vq, idx != VQ_RING_DESC_CHAIN_END, + "premature end of free desc chain"); + + dp = &desc[idx]; + dp->addr = virtqueue_virt_to_phys(vq, buf_list[i].buf); + dp->len = buf_list[i].len; + dp->flags = 0; + + if (i < needed - 1) + dp->flags |= VRING_DESC_F_NEXT; + + /* + * Readable buffers are inserted into vring before the + * writable buffers. + */ + if (i >= readable) + dp->flags |= VRING_DESC_F_WRITE; + } + + return (idx); +} + +/** + * + * vq_ring_free_chain + * + */ +static void vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx) +{ + struct vring_desc *dp; + struct vq_desc_extra *dxp; + + VQ_RING_ASSERT_VALID_IDX(vq, desc_idx); + dp = &vq->vq_ring.desc[desc_idx]; + dxp = &vq->vq_descx[desc_idx]; + + if (vq->vq_free_cnt == 0) { + VQ_RING_ASSERT_CHAIN_TERM(vq); + } + + vq->vq_free_cnt += dxp->ndescs; + dxp->ndescs--; + + if ((dp->flags & VRING_DESC_F_INDIRECT) == 0) { + while (dp->flags & VRING_DESC_F_NEXT) { + VQ_RING_ASSERT_VALID_IDX(vq, dp->next); + dp = &vq->vq_ring.desc[dp->next]; + dxp->ndescs--; + } + } + + VQASSERT(vq, (dxp->ndescs == 0), + "failed to free entire desc chain, remaining"); + + /* + * We must append the existing free chain, if any, to the end of + * newly freed chain. If the virtqueue was completely used, then + * head would be VQ_RING_DESC_CHAIN_END (ASSERTed above). + */ + dp->next = vq->vq_desc_head_idx; + vq->vq_desc_head_idx = desc_idx; +} + +/** + * + * vq_ring_init + * + */ +static void vq_ring_init(struct virtqueue *vq, void *ring_mem, int alignment) +{ + struct vring *vr; + int i, size; + + size = vq->vq_nentries; + vr = &vq->vq_ring; + + vring_init(vr, size, (unsigned char *)ring_mem, alignment); + + for (i = 0; i < size - 1; i++) + vr->desc[i].next = i + 1; + vr->desc[i].next = VQ_RING_DESC_CHAIN_END; +} + +/** + * + * vq_ring_update_avail + * + */ +static void vq_ring_update_avail(struct virtqueue *vq, uint16_t desc_idx) +{ + uint16_t avail_idx; + + /* + * Place the head of the descriptor chain into the next slot and make + * it usable to the host. The chain is made available now rather than + * deferring to virtqueue_notify() in the hopes that if the host is + * currently running on another CPU, we can keep it processing the new + * descriptor. + */ + avail_idx = vq->vq_ring.avail->idx & (vq->vq_nentries - 1); + vq->vq_ring.avail->ring[avail_idx] = desc_idx; + + atomic_thread_fence(memory_order_seq_cst); + + vq->vq_ring.avail->idx++; + + /* Keep pending count until virtqueue_notify(). */ + vq->vq_queued_cnt++; +} + +/** + * + * vq_ring_enable_interrupt + * + */ +static int vq_ring_enable_interrupt(struct virtqueue *vq, uint16_t ndesc) +{ + /* + * Enable interrupts, making sure we get the latest index of + * what's already been consumed. + */ + if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) { + vring_used_event(&vq->vq_ring) = vq->vq_used_cons_idx + ndesc; + } else { + vq->vq_ring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; + } + + atomic_thread_fence(memory_order_seq_cst); + + /* + * Enough items may have already been consumed to meet our threshold + * since we last checked. Let our caller know so it processes the new + * entries. + */ + if (virtqueue_nused(vq) > ndesc) { + return 1; + } + + return 0; +} + +/** + * + * virtqueue_interrupt + * + */ +void virtqueue_notification(struct virtqueue *vq) +{ + atomic_thread_fence(memory_order_seq_cst); + if (vq->callback) + vq->callback(vq); +} + +/** + * + * vq_ring_must_notify_host + * + */ +static int vq_ring_must_notify_host(struct virtqueue *vq) +{ + uint16_t new_idx, prev_idx, event_idx; + + if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) { + new_idx = vq->vq_ring.avail->idx; + prev_idx = new_idx - vq->vq_queued_cnt; + event_idx = vring_avail_event(&vq->vq_ring); + + return (vring_need_event(event_idx, new_idx, prev_idx) != 0); + } + + return ((vq->vq_ring.used->flags & VRING_USED_F_NO_NOTIFY) == 0); +} + +/** + * + * vq_ring_notify_host + * + */ +static void vq_ring_notify_host(struct virtqueue *vq) +{ + if (vq->notify) + vq->notify(vq); +} + +/** + * + * virtqueue_nused + * + */ +static int virtqueue_nused(struct virtqueue *vq) +{ + uint16_t used_idx, nused; + + used_idx = vq->vq_ring.used->idx; + + nused = (uint16_t)(used_idx - vq->vq_used_cons_idx); + VQASSERT(vq, nused <= vq->vq_nentries, "used more than available"); + + return nused; +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_cfg/fsp_cfg/r_mhu_ns_cfg.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_cfg/fsp_cfg/r_mhu_ns_cfg.h new file mode 100644 index 000000000..a5f533503 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_cfg/fsp_cfg/r_mhu_ns_cfg.h @@ -0,0 +1,5 @@ +/* generated configuration header file - do not edit */ +#ifndef R_MHU_NS_CFG_H_ +#define R_MHU_NS_CFG_H_ +#define MHU_NS_CFG_PARAM_CHECKING_ENABLE (BSP_CFG_PARAM_CHECKING_ENABLE) +#endif /* R_MHU_NS_CFG_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/hal_data.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/hal_data.c index f223bcc09..a44612a69 100644 --- a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/hal_data.c +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/hal_data.c @@ -59,6 +59,25 @@ const uart_instance_t g_uart2 = .p_api = &g_uart_on_scif }; +mhu_ns_instance_ctrl_t g_mhu_ns0_ctrl; + +const mhu_cfg_t g_mhu_ns0_cfg = +{ + .channel = 1, + .rx_ipl = 12, + .rx_irq = MHU_MSG1_NS_IRQn, + .p_callback = NULL, + .p_shared_memory = 0, + .p_context = NULL, +}; +/* Instance structure to use this module. */ +const mhu_instance_t g_mhu_ns0 = +{ + .p_ctrl = &g_mhu_ns0_ctrl, + .p_cfg = &g_mhu_ns0_cfg, + .p_api = &g_mhu_ns_on_mhu_ns +}; + gtm_instance_ctrl_t g_timer2_ctrl; const gtm_extended_cfg_t g_timer2_extend = @@ -71,7 +90,7 @@ const timer_cfg_t g_timer2_cfg = { .mode = TIMER_MODE_PERIODIC, // .period_counts = 99999 /* Actual period: 0.001 seconds. */, - .period_counts = 100000000 /* Actual period: 0.001 seconds. */, + .period_counts = 1000000 /* Actual period: 0.001 seconds. */, .channel = 2, .p_callback = NULL, .p_context = NULL, diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/hal_data.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/hal_data.h index c0907d5f6..e621f7288 100644 --- a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/hal_data.h +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/hal_data.h @@ -7,6 +7,7 @@ #include "r_uart_api.h" #include "r_scif_uart.h" #include "r_timer_api.h" +#include "r_mhu_ns.h" #include "r_gtm.h" FSP_HEADER @@ -19,6 +20,13 @@ extern scif_uart_instance_ctrl_t g_uart2_ctrl; extern const uart_cfg_t g_uart2_cfg; extern const scif_uart_extended_cfg_t g_uart2_cfg_extend; +/** MHU Instance */ +extern const mhu_instance_t g_mhu_ns0; + +/** Access the MHU instance using these structures when calling API functions directly (::p_api is not used). */ +extern mhu_ns_instance_ctrl_t g_mhu_ns0_ctrl; +extern const mhu_cfg_t g_mhu_ns0_cfg; + /** GTM Timer Instance */ extern const timer_instance_t g_timer2; diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/open_amp_cfg.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/open_amp_cfg.h new file mode 100644 index 000000000..4306b76b4 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/open_amp_cfg.h @@ -0,0 +1,79 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics Corporation and/or its affiliates and may only + * be used with products of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. + * Renesas products are sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for + * the selection and use of Renesas products and Renesas assumes no liability. No license, express or implied, to any + * intellectual property right is granted by Renesas. This software is protected under all applicable laws, including + * copyright laws. Renesas reserves the right to change or discontinue this software and/or this documentation. + * THE SOFTWARE AND DOCUMENTATION IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND + * TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, + * INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE + * SOFTWARE OR DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR + * DOCUMENTATION (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, + * INCLUDING, WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY + * LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ +/** + * @file OpenAMP_RPMsg_cfg.h + * @brief OpenAMP configurations + * @date 2020.10.21 + * @author Copyright (c) 2020, eForce Co., Ltd. All rights reserved. + * + **************************************************************************** + * @par History + * - rev 1.0 (2020.10.21) Imada + * Initial version for RZ/V2. + **************************************************************************** + */ + +#ifndef __OPEN_AMP_CFG_H__ +#define __OPEN_AMP_CFG_H__ + +// RPMSG config +#define APP_EPT_ADDR (0x0U) + +// Memory region reserved between 0x43000000 - 0x437FFFFF for RPMSG +#define RPMSG_MEM_BASE (0x43000000U) +#define RPMSG_MEM_SIZE (0x00800000U) + +#define VRING_SIZE (0x100000U) +#define VRING_SHM_SIZE (0x300000U) + +#define CFG_RPMSG_SVCNO (0x2U) + +// RPMSG channel #0 +#define CFG_RPMSG_SVC_NAME0 "rpmsg-service-0" +#define CFG_VRING0_BASE0_PA (0x43000000U) +#define CFG_VRING0_BASE0_VA (0x63000000U) +#define CFG_VRING1_BASE0_PA (0x43050000U) +#define CFG_VRING1_BASE0_VA (0x63050000U) +#define CFG_VRING_SIZE0 (VRING_SIZE) +#define CFG_VRING_ALIGN0 (0x100U) +#define CFG_RPMSG_NUM_BUFS0 (512U) +#define CFG_VRING_SHM_BASE0_PA (0x43200000U) +#define CFG_VRING_SHM_BASE0_VA (0x63200000U) +#define CFG_VRING_SHM_SIZE0 (VRING_SHM_SIZE) +#define CFG_VRING_CTL_NAME0 "43000000.vring-ctl0" +#define CFG_VRING_SHM_NAME0 "43200000.vring-shm0" +#define VRING_NOTIFYID0 (0U) + +// RPMSG channel #1 +#define CFG_RPMSG_SVC_NAME1 "rpmsg-service-1" +#define CFG_VRING0_BASE1_PA (0x43100000U) +#define CFG_VRING0_BASE1_VA (0x63100000U) +#define CFG_VRING1_BASE1_PA (0x43150000U) +#define CFG_VRING1_BASE1_VA (0x63150000U) +#define CFG_VRING_SIZE1 (VRING_SIZE) +#define CFG_VRING_ALIGN1 (0x100U) +#define CFG_RPMSG_NUM_BUFS1 (512U) +#define CFG_VRING_SHM_BASE1_PA (0x43500000U) +#define CFG_VRING_SHM_BASE1_VA (0x63500000U) +#define CFG_VRING_SHM_SIZE1 (VRING_SHM_SIZE) +#define CFG_VRING_CTL_NAME1 "43100000.vring-ctl1" +#define CFG_VRING_SHM_NAME1 "43500000.vring-shm1" +#define VRING_NOTIFYID1 (1U) +#endif /* OPENAMP_RPMSG_CFG_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/platform_info.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/platform_info.c new file mode 100644 index 000000000..29b61092b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/platform_info.c @@ -0,0 +1,417 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics Corporation and/or its affiliates and may only + * be used with products of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. + * Renesas products are sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for + * the selection and use of Renesas products and Renesas assumes no liability. No license, express or implied, to any + * intellectual property right is granted by Renesas. This software is protected under all applicable laws, including + * copyright laws. Renesas reserves the right to change or discontinue this software and/or this documentation. + * THE SOFTWARE AND DOCUMENTATION IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND + * TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, + * INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE + * SOFTWARE OR DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR + * DOCUMENTATION (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, + * INCLUDING, WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY + * LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2017 Xilinx, Inc. + * Copyright (c) 2020, eForce Co., Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/************************************************************************** + * FILE NAME + * + * platform_info.c + * + * DESCRIPTION + * + * This file define platform specific data and implements APIs to set + * platform specific information for OpenAMP. + * + * @par History + * - rev 1.0 (2020.10.21) Imada + * Initial version. + * + **************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "platform_info.h" +#include "rsc_table.h" + #include + #include + +static int32 ipi_tsk_id[CFG_RPMSG_SVCNO] = {-1, -1}; + +struct ipi_info ipi = +{ + MBX_DEV_NAME, // name + DEV_BUS_NAME, // bus_name + NULL, // dev + NULL, // io + MBX_INT_NUM, // irq_info + 0, // registered + {0, 0}, // mbx_chn (not used on this SoC) + 0, // chn_mask (not used on this SoC) + {-1, -1}, // ipi_mutx_id +}; + +/* vring information */ +struct vring_info vrinfo[CFG_RPMSG_SVCNO] = +{ + { // vinfo[0] + { // rsc + CFG_RSCTBL_DEV_NAME, // name + DEV_BUS_NAME, // bus_name + NULL, // dev + NULL, // io + {0}, // mem + }, + { // ctl + CFG_VRING_CTL_NAME0, // name + DEV_BUS_NAME, // bus_name + NULL, // dev + NULL, // io + {0}, // mem + }, + { // shm + CFG_VRING_SHM_NAME0, // name + DEV_BUS_NAME, // bus_name + NULL, // dev + NULL, // io + {0}, // mem + }, + }, + { // vinfo[1] + { // rsc + CFG_RSCTBL_DEV_NAME, // name + DEV_BUS_NAME, // bus_name + NULL, // dev + NULL, // io + {0}, // mem + }, + { // ctl + CFG_VRING_CTL_NAME1, // name + DEV_BUS_NAME, // bus_name + NULL, // dev + NULL, // io + {0}, // mem + }, + { // shm + CFG_VRING_SHM_NAME1, // name + DEV_BUS_NAME, // bus_name + NULL, // dev + NULL, // io + {0}, // mem + }, + }, +}; + +/* processor operations at RZ/V2. It defines + * notification operatio0n and remote processor managementi operations. */ +extern struct remoteproc_ops rzv2_proc_ops; + +/* RPMsg virtio shared buffer pool */ +static struct rpmsg_virtio_shm_pool shpool; + +static void start_ipi_task(void * platform); + +static struct remoteproc * platform_create_proc (int proc_index, int rsc_index) +{ + void * rsc_table; + unsigned int rsc_size; + int ret; + struct remoteproc * rproc_inst; + struct remoteproc_priv * rproc_priv; + + /* Allocate and initialize remoteproc_priv instance */ + rproc_priv = metal_allocate_memory(sizeof(struct remoteproc_priv)); + if (!rproc_priv) + { + return NULL; + } + + memset(rproc_priv, 0, sizeof(*rproc_priv)); + rproc_priv->notify_id = (unsigned int) proc_index; + rproc_priv->vr_info = &vrinfo[rsc_index]; + + /* Allocate remoteproc instance */ + rproc_inst = metal_allocate_memory(sizeof(struct remoteproc)); + if (!rproc_inst) + { + goto err1; + } + + memset(rproc_inst, 0, sizeof(*rproc_inst)); + + /* remoteproc initialization */ + if (!remoteproc_init(rproc_inst, &rzv2_proc_ops, rproc_priv)) + { + goto err2; + } + + /* + * Mmap shared memories + * Or shall we constraint that they will be set as carved out + * in the resource table? + */ + rsc_table = get_resource_table(rsc_index, &rsc_size); + rproc_inst->rsc_io = rproc_priv->vr_info->rsc.io; + + /* Parse resource table to remoteproc */ + ret = remoteproc_set_rsc_table(rproc_inst, rsc_table, rsc_size); + if (ret) + { + LPRINTF("Failed to initialize remoteproc\n"); + goto err2; + } + + LPRINTF("Initialize remoteproc successfully.\n"); + + return rproc_inst; +err2: + (void) remoteproc_remove(rproc_inst); + metal_free_memory(rproc_inst); +err1: + metal_free_memory(rproc_priv); + + return NULL; +} + +struct rpmsg_device * platform_create_rpmsg_vdev (void * platform, + unsigned int vdev_index, + unsigned int role, + void ( * rst_cb)(struct virtio_device * vdev), + rpmsg_ns_bind_cb ns_bind_cb) +{ + struct remoteproc * rproc = platform; + struct remoteproc_priv * prproc; + struct rpmsg_virtio_device * rpmsg_vdev; + struct virtio_device * vdev; + struct metal_io_region * shbuf_io; + metal_phys_addr_t pa; + + int ret; + + prproc = rproc->priv; + + rpmsg_vdev = metal_allocate_memory(sizeof(*rpmsg_vdev)); + if (!rpmsg_vdev) + { + return NULL; + } + + memset(rpmsg_vdev, 0, sizeof(*rpmsg_vdev)); + + LPRINTF("creating remoteproc virtio\n"); + vdev = remoteproc_create_virtio(rproc, (int) vdev_index, role, rst_cb); + if (!vdev) + { + LPRINTF("failed remoteproc_create_virtio\n"); + goto err; + } + + pa = metal_io_phys(prproc->vr_info->shm.io, 0x0U); + shbuf_io = remoteproc_get_io_with_pa(rproc, pa); + if (!shbuf_io) + { + LPRINTF("failed remoteproc_get_io_with_pa\n"); + goto err; + } + + /* Only RPMsg virtio master needs to initialize the shared buffers pool */ + LPRINTF("initializing rpmsg vdev\n"); + + /* RPMsg virtio slave can set shared buffers pool argument to NULL */ + ret = rpmsg_init_vdev(rpmsg_vdev, vdev, ns_bind_cb, shbuf_io, &shpool); + if (ret) + { + LPRINTF("failed rpmsg_init_vdev\n"); + goto err; + } + + start_ipi_task(rproc); + + return rpmsg_virtio_get_rpmsg_device(rpmsg_vdev); +err: + remoteproc_remove_virtio(rproc, vdev); + metal_free_memory(rpmsg_vdev); + + return NULL; +} + +int platform_poll (void * priv) +{ + (void) priv; + + return 0; +} + +int platform_init (unsigned long proc_id, unsigned long rsc_id, void ** platform) +{ + struct remoteproc * rproc; + + if (!platform) + { + LPRINTF("Failed to initialize platform," "NULL pointer to store platform data.\n"); + + return -EINVAL; + } + + if ((proc_id >= RSC_MAX_NUM) || (rsc_id >= RSC_MAX_NUM)) + { + LPRINTF("Invalid rproc number specified.\n"); + + return -EINVAL; + } + + rproc = platform_create_proc((int) proc_id, (int) rsc_id); + if (!rproc) + { + LPRINTF("Failed to create remoteproc device.\n"); + + return -EINVAL; + } + + *platform = rproc; + + return 0; +} + +void platform_release_rpmsg_vdev (void * platform, struct rpmsg_device * rpdev) +{ + /* Need to free memory regions already allocated but not used anymore? */ + struct remoteproc * rproc = platform; + struct rpmsg_virtio_device * rpmsg_vdev; + struct remoteproc_priv * prproc = rproc->priv; + + KTaskDelete(ipi_tsk_id[prproc->notify_id]); + ipi_tsk_id[prproc->notify_id] = -1; + + KMutexDelete(ipi.ipi_mutx_id[prproc->notify_id]); + ipi.ipi_mutx_id[prproc->notify_id] = -1; + + rpmsg_vdev = metal_container_of(rpdev, struct rpmsg_virtio_device, rdev); + rpmsg_deinit_vdev(rpmsg_vdev); + remoteproc_remove_virtio(rproc, rpmsg_vdev->vdev); + metal_free_memory(rpmsg_vdev); +} + +void platform_cleanup (void * platform) +{ + struct remoteproc * rproc = platform; + struct remoteproc_priv * prproc; + struct metal_device * dev; + + if (rproc) + { + prproc = rproc->priv; + if (rproc->priv) + { + /* Release allocated resource */ + /* Shared memory devices */ + metal_list_del(&(prproc->vr_info->ctl.mem.node)); + dev = prproc->vr_info->ctl.dev; + if (dev) + { + metal_device_close(dev); + } + + metal_list_del(&(prproc->vr_info->shm.mem.node)); + dev = prproc->vr_info->shm.dev; + if (dev) + { + metal_device_close(dev); + } + + /* Resource table device */ + metal_list_del(&(prproc->vr_info->rsc.mem.node)); + dev = prproc->vr_info->rsc.dev; + if (dev) + { + metal_device_close(dev); + } + + /* Release the private area */ + metal_free_memory(rproc->priv); + } + + (void) remoteproc_remove(rproc); + metal_free_memory(rproc); + } +} + +static void* IpiTask(void * exinf); + +static void* IpiTask (void * exinf) +{ + struct remoteproc * rproc = exinf; + struct remoteproc_priv * prproc = rproc->priv; + int ret; + + while (1) + { + // extern long ShowTask(void); + // ShowTask(); + + KMutexObtain(ipi.ipi_mutx_id[prproc->notify_id], WAITING_FOREVER); + // KPrintf("IpiTask: after KSemaphoreObtain\n"); + + /* Ignore a incoming interrupt if the virtio layer of a target remoteproc is not yet initialized */ + if (metal_list_is_empty(&rproc->vdevs)) + { + continue; + } + ret = remoteproc_get_notification(rproc, RSC_NOTIFY_ID_ANY); + // KPrintf("IpiTask: after remoteproc_get_notification\n"); + if (ret) + { + LPRINTF("remoteproc_get_notification() failed with %d", ret); + break; + } + + DelayKTask(10); + } +} + +static void start_ipi_task (void * platform) +{ + struct remoteproc * rproc = platform; + struct remoteproc_priv * prproc = rproc->priv; + + int32 mutx_id = KMutexCreate(); + + if (mutx_id < 0) + { + KPrintf("start_ipi_task: create sem fail!\n"); + return ; + } + ipi.ipi_mutx_id[prproc->notify_id] = mutx_id; + + KPrintf("start_ipi_task: prproc->notify_id = %d, ipi.ipi_mutx_id[prproc->notify_id] = %d \n",prproc->notify_id,ipi.ipi_mutx_id[prproc->notify_id]); + + int32 ipi_task_id = -1; + ipi_task_id = KTaskCreate("ipi_task",IpiTask,platform,4096,SHELL_TASK_PRIORITY + 1); + + if (ipi_task_id < 0) + { + LPRINTF("Failed to register an interrupt service routine.\n"); + return ; + } + + ipi_tsk_id[prproc->notify_id] = ipi_task_id; + + StartupKTask(ipi_task_id); +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/platform_info.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/platform_info.h new file mode 100644 index 000000000..285772102 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/platform_info.h @@ -0,0 +1,154 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics Corporation and/or its affiliates and may only + * be used with products of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. + * Renesas products are sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for + * the selection and use of Renesas products and Renesas assumes no liability. No license, express or implied, to any + * intellectual property right is granted by Renesas. This software is protected under all applicable laws, including + * copyright laws. Renesas reserves the right to change or discontinue this software and/or this documentation. + * THE SOFTWARE AND DOCUMENTATION IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND + * TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, + * INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE + * SOFTWARE OR DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR + * DOCUMENTATION (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, + * INCLUDING, WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY + * LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ +/* + * @file platform_info.h + * @brief Platform specific configurations for OpenAMP and Shared memory + * @date 2020.10.21 + * @author Copyright (c) 2020, eForce Co., Ltd. All rights reserved. + * + **************************************************************************** + * @par History + * - rev 1.0 (2020.10.21) Imada + * Initial version for RZ/V2. + **************************************************************************** + */ + +#ifndef PLATFORM_INFO_H_ +#define PLATFORM_INFO_H_ + +#include +#include +#include "open_amp_cfg.h" +#include "bsp_api.h" +#include +#include "r_mhu_api.h" + +#define DEV_BUS_NAME "generic" +#define MBX_REG_PA 0x10400000 +#define MBX_REG_VA 0x40400000 +#define MBX_MAP_SIZE 0x00000800 +#define MBX_INT_NUM 69 // MSG1_NS_IRQn +#define RSC_MAX_NUM 2 + +#define LPRINTF(format, ...) (KPrintf(format, ## __VA_ARGS__)) +#define LPERROR(format, ...) (LPRINTF("ERROR: " format, ## __VA_ARGS__)) + +// Page size on Linux (Default: 4KB) +#define PAGE_SIZE (0x01000U) // 4KB page size as the dafault value + +// Mailbox config +#define MBX_DEV_NAME "0x10400000.mbox-uio" +#define MBX_NO (0x0U) /* Maibox number (0, 1, ..., or 7) this program uses */ + +struct ipi_info +{ + const char * name; + const char * bus_name; + struct metal_device * dev; + struct metal_io_region * io; + uintptr_t irq_info; + int registered; + unsigned int mbx_chn[CFG_RPMSG_SVCNO]; + unsigned int chn_mask; /**< IPI channel mask */ + int32 ipi_mutx_id[CFG_RPMSG_SVCNO]; +}; + +struct shm_info +{ + const char * name; + const char * bus_name; + struct metal_device * dev; /**< pointer to shared memory device */ + struct metal_io_region * io; /**< pointer to shared memory i/o region */ + struct remoteproc_mem mem; /**< shared memory */ +}; + +struct vring_info +{ + struct shm_info rsc; + struct shm_info ctl; + struct shm_info shm; +}; + +struct remoteproc_priv +{ + unsigned int notify_id; + unsigned int mbx_chn_id; + struct vring_info * vr_info; +}; + +/** + * platform_init - initialize the platform + * + * It will initialize the platform. + * + * @proc_id: processor id + * @rsc_id: resource id + * @platform: pointer to store the platform data pointer + * + * return 0 for success or negative value for failure + */ +int platform_init(unsigned long proc_id, unsigned long rsc_id, void ** platform); + +/** + * platform_create_rpmsg_vdev - create rpmsg vdev + * + * It will create rpmsg virtio device, and returns the rpmsg virtio + * device pointer. + * + * @platform: pointer to the private data + * @vdev_index: index of the virtio device, there can more than one vdev + * on the platform. + * @role: virtio master or virtio slave of the vdev + * @rst_cb: virtio device reset callback + * @ns_bind_cb: rpmsg name service bind callback + * + * return pointer to the rpmsg virtio device + */ +struct rpmsg_device * platform_create_rpmsg_vdev(void * platform, + unsigned int vdev_index, + unsigned int role, + void ( * rst_cb)(struct virtio_device * vdev), + rpmsg_ns_bind_cb ns_bind_cb); + +/** + * platform_poll - platform poll function + * + * @platform: pointer to the platform + * + * return negative value for errors, otherwise 0. + */ +int platform_poll(void * platform); + +/** + * platform_release_rpmsg_vdev - release rpmsg virtio device + * + * @platform: pointer to the platform + * @rpdev: pointer to the rpmsg device + */ +void platform_release_rpmsg_vdev(void * platform, struct rpmsg_device * rpdev); + +/** + * platform_cleanup - clean up the platform resource + * + * @platform: pointer to the platform + */ +void platform_cleanup(void * platform); + +#endif /* PLATFORM_INFO_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rpmsg_demo.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rpmsg_demo.c new file mode 100644 index 000000000..28b8d0848 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rpmsg_demo.c @@ -0,0 +1,198 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics Corporation and/or its affiliates and may only + * be used with products of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. + * Renesas products are sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for + * the selection and use of Renesas products and Renesas assumes no liability. No license, express or implied, to any + * intellectual property right is granted by Renesas. This software is protected under all applicable laws, including + * copyright laws. Renesas reserves the right to change or discontinue this software and/or this documentation. + * THE SOFTWARE AND DOCUMENTATION IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND + * TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, + * INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE + * SOFTWARE OR DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR + * DOCUMENTATION (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, + * INCLUDING, WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY + * LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ +/** + * @file sample_rpmsg.c + * @brief rpmsg sample program for FreeRTOS + * @date 2020.03.24 + * @author Copyright (c) 2020, eForce Co., Ltd. All rights reserved. + * + **************************************************************************** + * @par History + * - rev 1.0 (2020.01.28) Imada + * Initial version. + * - rev 1.1 (2020.03.24) Imada + * Employed a dedicated function to set a string for Shared memory API. + **************************************************************************** + */ +#include +#include "platform_info.h" +#include "rsc_table.h" +#include + +extern int init_system(void); +extern void cleanup_system(void); + +#define SHUTDOWN_MSG (0xEF56A55A) + +/* Local variables */ + +/*-----------------------------------------------------------------------------* + * RPMSG callbacks setup by remoteproc_resource_init() + *-----------------------------------------------------------------------------*/ + +/* Local variables */ + +static struct rpmsg_endpoint rp_ept[CFG_RPMSG_SVCNO] = {0}; + +volatile static int evt_svc_unbind[CFG_RPMSG_SVCNO] = {0}; + +/** + * Callback Function: rpmsg_endpoint_cb + * + * @param[in] rp_svc + * @param[in] data + * @param[in] len + * @param[in] priv + * @param[in] src + */ +static int rpmsg_endpoint_cb0 (struct rpmsg_endpoint * cb_rp_ept, void * data, size_t len, uint32_t src, void * priv) +{ + /* service 0 */ + (void) priv; + (void) src; + /* On reception of a shutdown we signal the application to terminate */ + if ((*(unsigned int *) data) == SHUTDOWN_MSG) + { + evt_svc_unbind[0] = 1; + + return RPMSG_SUCCESS; + } + KPrintf("rpmsg_endpoint_cb0: recv data = %p, *data = %d,len = %d\n",data,*((int*)(data)),len); + /* Send data back to master */ + if (rpmsg_send(cb_rp_ept, data, (int) len) < 0) + { + LPERROR("rpmsg_send failed\n"); + + return -1; + } + return RPMSG_SUCCESS; +} + +static int rpmsg_endpoint_cb1 (struct rpmsg_endpoint * cb_rp_ept, void * data, size_t len, uint32_t src, void * priv) +{ + /* service 1 */ + (void) priv; + (void) src; + + /* On reception of a shutdown we signal the application to terminate */ + if ((*(unsigned int *) data) == SHUTDOWN_MSG) + { + evt_svc_unbind[1] = 1; + + return RPMSG_SUCCESS; + } + + /* Send data back to master */ + if (rpmsg_send(cb_rp_ept, data, (int) len) < 0) + { + LPERROR("rpmsg_send failed \n"); + + return -1; + } + + return RPMSG_SUCCESS; +} + +/** + * Callback Function: rpmsg_service_unbind + * + * @param[in] ept + */ +static void rpmsg_service_unbind0 (struct rpmsg_endpoint * ept) +{ + (void) ept; + + /* service 0 */ + rpmsg_destroy_ept(&rp_ept[0]); + memset(&rp_ept[0], 0x0, sizeof(struct rpmsg_endpoint)); + evt_svc_unbind[0] = 1; +} + +static void rpmsg_service_unbind1 (struct rpmsg_endpoint * ept) +{ + (void) ept; + + /* service 1 */ + rpmsg_destroy_ept(&rp_ept[1]); + memset(&rp_ept[1], 0x0, sizeof(struct rpmsg_endpoint)); + evt_svc_unbind[1] = 1; +} + +/*-----------------------------------------------------------------------------* + * Application + *-----------------------------------------------------------------------------*/ +int app (struct rpmsg_device * rdev, void * platform, unsigned long svcno) +{ + (void) platform; + int ret; + + if (svcno == 0UL) + { + ret = rpmsg_create_ept(&rp_ept[0], + rdev, + CFG_RPMSG_SVC_NAME0, + APP_EPT_ADDR, + RPMSG_ADDR_ANY, + rpmsg_endpoint_cb0, + rpmsg_service_unbind0); + if (ret) + { + LPERROR("Failed to create endpoint.\n"); + + return -1; + } + + KPrintf("app: Success to create endpoint rp_ept[0]\n"); + } + else + { + ret = rpmsg_create_ept(&rp_ept[1], + rdev, + CFG_RPMSG_SVC_NAME1, + APP_EPT_ADDR, + RPMSG_ADDR_ANY, + rpmsg_endpoint_cb1, + rpmsg_service_unbind1); + if (ret) + { + LPERROR("Failed to create endpoint.\n"); + + return -1; + } + } + + LPRINTF("Waiting for events...\n"); + + while (1) + { + DelayKTask(100); + + /* we got a shutdown request, exit */ + if (evt_svc_unbind[svcno]) + { + break; + } + } + + /* Clear shutdown flag */ + evt_svc_unbind[svcno] = 0; + + return 0; +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rpmsg_task.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rpmsg_task.c new file mode 100644 index 000000000..734df45d9 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rpmsg_task.c @@ -0,0 +1,71 @@ +#include +#include "rpmsg_task.h" +#include "platform_info.h" +#include + +extern int init_system (void); +extern void cleanup_system (void); +extern int app (struct rpmsg_device * rdev, void * platform, unsigned long svcno); + +void* RPMsgTask_Entry(void* param) +{ + unsigned long proc_id = 0UL; + unsigned long rsc_id = 0UL; + struct rpmsg_device * rpdev; + void * platform; + int ret; + + ret = init_system(); + if (ret) + { + LPERROR("Failed to init remoteproc device.\n"); + goto err; + } + + ret = platform_init(proc_id, rsc_id, &platform); + if (ret) + { + LPERROR("Failed to create remoteproc device.\n"); + goto err; + } + else + { + do + { + /* RTOS is Master, but this setting must remote in this release. */ + rpdev = platform_create_rpmsg_vdev(platform, 0x0U, VIRTIO_DEV_SLAVE, NULL, NULL); + if (!rpdev) + { + LPERROR("Fail, platform_create_rpmsg_vdev.\n"); + goto err; + } + // KPrintf("RPMsgTask_Entry: Success platform_create_rpmsg_vdev.\n"); + /* Kick the application */ + (void) app(rpdev, platform, proc_id); + + platform_release_rpmsg_vdev(platform, rpdev); + KPrintf("RPMsgTask_Entry: Success platform_release_rpmsg_vdev.\n"); + + DelayKTask(RECONNECT_DLY); + } while (RECONNECT_FLG); + } + +err: + KPrintf("RPMsgTask_Entry: err \n"); +} + +void CreateRPMsgTask(void) +{ + // 创建的任务优先级与SHELL终端一致,防止该任务无法执行 + int32 rpmsg_task_id = KTaskCreate("rpmsg_task",RPMsgTask_Entry,NULL,2048,SHELL_TASK_PRIORITY); + + if (rpmsg_task_id < 0) + { + KPrintf("CreateRPMsgTask: create rpmsg task fail!\n"); + return ; + } + + // 将该任务放入调用 + StartupKTask(rpmsg_task_id); +} + diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rpmsg_task.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rpmsg_task.h new file mode 100644 index 000000000..9670bf64e --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rpmsg_task.h @@ -0,0 +1,14 @@ +#ifndef __RPMSG_TASK_H__ +#define __RPMSG_TASK_H__ +#include "bsp_api.h" +#include "hal_data.h" + +#include + +#define RECONNECT_FLG (1) +#define RECONNECT_DLY (1000U) + +// 创建 RPMsg 任务的接口 +void CreateRPMsgTask(void); + +#endif /* MAINTASK_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rsc_table.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rsc_table.c new file mode 100644 index 000000000..ca0be56fb --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rsc_table.c @@ -0,0 +1,119 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics Corporation and/or its affiliates and may only + * be used with products of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. + * Renesas products are sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for + * the selection and use of Renesas products and Renesas assumes no liability. No license, express or implied, to any + * intellectual property right is granted by Renesas. This software is protected under all applicable laws, including + * copyright laws. Renesas reserves the right to change or discontinue this software and/or this documentation. + * THE SOFTWARE AND DOCUMENTATION IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND + * TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, + * INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE + * SOFTWARE OR DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR + * DOCUMENTATION (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, + * INCLUDING, WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY + * LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ +/** + * @file rsc_table.c + * @brief The remote resource table. + * @date 2020.10.20 + * @author Copyright (c) 2020, eForce Co., Ltd. All rights reserved. + * + **************************************************************************** + * @par History + * - rev 1.0 (2020.10.20) Imada + * First release for RZ/V2 + **************************************************************************** + */ + +#include "rsc_table.h" + +struct remote_resource_table __resource resources[2]; + +struct remote_resource_table resources_init[] = +{ + {/* Version */ + 1, + + /* NUmber of table entries */ + NUM_TABLE_ENTRIES, + + /* reserved fields */ + {0, 0}, + + /* Offsets of rsc entries */ + { + offsetof(struct remote_resource_table, rproc_mem), + offsetof(struct remote_resource_table, rpmsg_vdev) + }, + + {RSC_RPROC_MEM, RPMSG_MEM_BASE, RPMSG_MEM_BASE, RPMSG_MEM_SIZE, 0}, + + /* Virtio device entry */ + { + RSC_VDEV, + VIRTIO_ID_RPMSG_, + 0, + RPMSG_IPU_C0_FEATURES, + 0, + 0, + 0, + NUM_VRINGS, + {0, 0}, + }, + + /* Vring rsc entry - part of vdev rsc entry */ + {CFG_VRING0_BASE0_PA, CFG_VRING_ALIGN0, CFG_RPMSG_NUM_BUFS0, 0, 0}, + {CFG_VRING1_BASE0_PA, CFG_VRING_ALIGN0, CFG_RPMSG_NUM_BUFS0, 0, 0} + }, + {/* Version */ + 1, + + /* NUmber of table entries */ + NUM_TABLE_ENTRIES, + + /* reserved fields */ + {0, 0}, + + /* Offsets of rsc entries */ + { + offsetof(struct remote_resource_table, rproc_mem), + offsetof(struct remote_resource_table, rpmsg_vdev) + }, + + {RSC_RPROC_MEM, RPMSG_MEM_BASE, RPMSG_MEM_BASE, RPMSG_MEM_SIZE, 0}, + + /* Virtio device entry */ + { + RSC_VDEV, + VIRTIO_ID_RPMSG_, + 0, + RPMSG_IPU_C0_FEATURES, + 0, + 0, + 0, + NUM_VRINGS, + {0, 0}, + }, + + /* Vring rsc entry - part of vdev rsc entry */ + {CFG_VRING0_BASE1_PA, CFG_VRING_ALIGN1, CFG_RPMSG_NUM_BUFS1, 1, 0}, + {CFG_VRING1_BASE1_PA, CFG_VRING_ALIGN1, CFG_RPMSG_NUM_BUFS1, 1, 0} + }, +}; + +void init_resource_table(void) +{ + memcpy(resources, resources_init, sizeof(resources_init)); +} + +void *get_resource_table(int rsc_id, unsigned int *len) +{ + *len = sizeof(resources[rsc_id]); + + return (void *)&resources[rsc_id]; +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rsc_table.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rsc_table.h new file mode 100644 index 000000000..c415cb010 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rsc_table.h @@ -0,0 +1,78 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics Corporation and/or its affiliates and may only + * be used with products of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. + * Renesas products are sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for + * the selection and use of Renesas products and Renesas assumes no liability. No license, express or implied, to any + * intellectual property right is granted by Renesas. This software is protected under all applicable laws, including + * copyright laws. Renesas reserves the right to change or discontinue this software and/or this documentation. + * THE SOFTWARE AND DOCUMENTATION IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND + * TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, + * INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE + * SOFTWARE OR DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR + * DOCUMENTATION (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, + * INCLUDING, WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY + * LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ +/** + * @file rsc_table.h + * @brief Configurations for the resource table. + * @date 2020.03.24 + * @author Copyright (c) 2020, eForce Co., Ltd. All rights reserved. + * + **************************************************************************** + * @par History + * - rev 1.0 (2020.03.24) Imada + * First release for AM65xx + **************************************************************************** + */ + +#ifndef RSC_TABLE_H_ +#define RSC_TABLE_H_ + +#include +#include +#include "platform_info.h" + +/* Place resource table in special ELF section */ +#define __section_t(S) __attribute__((__section__(#S))) +#define __resource __section_t(.resource_table) + +#define RPMSG_IPU_C0_FEATURES (1U) + +/* VirtIO rpmsg device id */ +#define VIRTIO_ID_RPMSG_ (7U) + +#define NUM_VRINGS (2U) +#define NUM_TABLE_ENTRIES (2U) +#define NO_RESOURCE_ENTRIES (2U) + +/* Resource table UIO device */ +#define CFG_RSCTBL_DEV_NAME "42F00000.rsctbl" +#define CFG_RSCTBL_MEM_VA (0x62F00000U) +#define CFG_RSCTBL_MEM_PA (0x42F00000U) +#define CFG_RSCTBL_MAP_SIZE (0x00001000U) // 4KB + +/* MDK_ARM compiler does not apply __packed__ for this */ +struct remote_resource_table +{ + unsigned int version; + unsigned int num; + unsigned int reserved[2]; + unsigned int offset[NO_RESOURCE_ENTRIES]; + + /* rproc memory entry */ + struct fw_rsc_rproc_mem rproc_mem; + + /* rpmsg vdev entry */ + struct fw_rsc_vdev rpmsg_vdev; + struct fw_rsc_vdev_vring rpmsg_vring0; + struct fw_rsc_vdev_vring rpmsg_vring1; +}; + +void * get_resource_table(int rsc_id, unsigned int * len); + +#endif /* RSC_TABLE_H_ */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rzv2_rproc.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rzv2_rproc.c new file mode 100644 index 000000000..4dd67c69a --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/rzv2_rproc.c @@ -0,0 +1,280 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics Corporation and/or its affiliates and may only + * be used with products of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. + * Renesas products are sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for + * the selection and use of Renesas products and Renesas assumes no liability. No license, express or implied, to any + * intellectual property right is granted by Renesas. This software is protected under all applicable laws, including + * copyright laws. Renesas reserves the right to change or discontinue this software and/or this documentation. + * THE SOFTWARE AND DOCUMENTATION IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND + * TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, + * INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE + * SOFTWARE OR DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR + * DOCUMENTATION (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, + * INCLUDING, WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY + * LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ +/* + * Copyright (c) 2014, Mentor Graphics Corporation + * All rights reserved. + * Copyright (c) 2017 Xilinx, Inc. + * Copyright (c) 2020, eForce Co., Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/************************************************************************** + * FILE NAME + * + * rzv2_rproc.c + * + * DESCRIPTION + * + * This file defines RZ/V2 CA5X/CR7 remoteproc implementation. + * + * @par History + * - rev 1.0 (2020.10.21) Imada + * Initial version. + * + **************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include "platform_info.h" +#include +#include "hal_data.h" + +extern struct ipi_info ipi; + +/* Inline functions to add accessing address check to corresponding + * libmetal functions to avoid accessing a reserved region. + * They are mainly required because of larger (uio) mmap size due the + * 4KB page size on Verified Linux. They are also utilized for FreeRTOS because + * accessing a reserved area of registers can cause system failure. + */ +static int init_memory_device (struct remoteproc * rproc, struct shm_info * info) { + struct metal_device * dev; + metal_phys_addr_t mem_pa; + int ret; + + ret = metal_device_open(info->bus_name, info->name, &dev); + if (ret) + { + LPERROR("Failed to open uio device %s: %d.\n", info->name, ret); + goto err; + } + + LPRINTF("Successfully open uio device: %s.\n", info->name); + + info->dev = dev; + info->io = metal_device_io_region(dev, 0x0U); + if (!info->io) + { + goto err; + } + + mem_pa = metal_io_phys(info->io, 0x0U); + remoteproc_init_mem(&info->mem, info->name, mem_pa, mem_pa, metal_io_region_size(info->io), info->io); + remoteproc_add_mem(rproc, &info->mem); + LPRINTF("Successfully added memory device %s.\n", info->name); + + return 0; +err: + if (info->dev) + { + metal_device_close(info->dev); + } + + return ret; +} + +static int rzv2_mhu_callback (mhu_callback_args_t * p_args) +{ + unsigned int val = 0U; + /* Clear the interrupt: Already done by MHU driver */ + + /* Get a massage from the mailbox */ + val = p_args->msg; + + if (val >= RSC_MAX_NUM) /* val should have the notify_id of the sender */ + { + return METAL_IRQ_NOT_HANDLED; /* Invalid message arrived */ + } + + if (ipi.ipi_mutx_id[val] >= 0) + { + KMutexAbandon(ipi.ipi_mutx_id[val]); + } + else + { + return METAL_IRQ_NOT_HANDLED; + } + + return METAL_IRQ_HANDLED; +} + +static int rzv2_enable_interrupt (struct remoteproc * rproc, struct metal_device * ipi_dev) +{ + unsigned int irq_vect; + int ret = 0; + + if (!ipi.registered) + { + /* Register interrupt handler and enable interrupt for RZ/V2 CA5X or CR7 */ + irq_vect = (uintptr_t) ipi_dev->irq_info; + ret = metal_irq_register((int) irq_vect, R_MHU_NS_IsrSub, ipi_dev, rproc); + if (ret) + { + LPRINTF("metal_irq_register() failed with %d", ret); + + return ret; + } + + metal_irq_enable(irq_vect); + } + + return ret; +} + +static void rzv2_disable_interrupt (struct remoteproc * rproc) +{ + (void) rproc; + struct metal_device * dev; + int ret; + + dev = ipi.dev; + if (dev) + { + metal_irq_disable((uintptr_t) dev->irq_info); + ret = metal_irq_unregister((int) dev->irq_info, NULL, NULL, NULL); + if (ret) + { + LPRINTF("metal_irq_unregister() failed with %d", ret); + + return; + } + + metal_device_close(dev); + ipi.registered = 0; + } +} + +static struct remoteproc * rzv2_proc_init (struct remoteproc * rproc, struct remoteproc_ops * ops, void * arg) +{ + struct remoteproc_priv * prproc = arg; + struct metal_device * dev; + int ret; + + /* Initialize MHU driver */ + g_mhu_ns0.p_api->open(g_mhu_ns0.p_ctrl, g_mhu_ns0.p_cfg); + g_mhu_ns0.p_api->callbackSet(g_mhu_ns0.p_ctrl, rzv2_mhu_callback, NULL, NULL); + + if ((!rproc) || (!prproc) || (!ops)) + { + return NULL; + } + + rproc->priv = prproc; + rproc->ops = ops; + + if (!ipi.registered) + { + /* Get an IPI device (Mailbox) */ + ret = metal_device_open(ipi.bus_name, ipi.name, &dev); + if (ret) + { + LPERROR("Failed to open ipi device: %d.\n", ret); + + return NULL; + } + + ipi.dev = dev; + ipi.io = metal_device_io_region(dev, 0x0U); + if (!ipi.io) + { + goto err1; + } + + LPRINTF("Successfully probed IPI device\n"); + } + + ret = rzv2_enable_interrupt(rproc, ipi.dev); + if (ret) + { + LPERROR("Failed to register the interrupt handler.\n"); + goto err1; + } + + ipi.registered++; + + /* Get the resource table device */ + if (init_memory_device(rproc, &prproc->vr_info->rsc)) + { + goto err1; + } + + /* Get VRING related devices */ + if (init_memory_device(rproc, &prproc->vr_info->ctl)) + { + goto err1; + } + + if (init_memory_device(rproc, &prproc->vr_info->shm)) + { + goto err1; + } + + return rproc; +err1: + metal_device_close(ipi.dev); + + return NULL; +} + +static void rzv2_proc_remove (struct remoteproc * rproc) +{ + if (!rproc) + { + return; + } + + if (ipi.registered > 1) + { + ipi.registered--; + + return; + } + + /* Disable interrupts */ + rzv2_disable_interrupt(rproc); +} + +static int rzv2_proc_notify (struct remoteproc * rproc, uint32_t id) +{ + struct remoteproc_priv * prproc = rproc->priv; + + g_mhu_ns0.p_api->msgSend(g_mhu_ns0.p_ctrl, prproc->notify_id); + + return 0; +} + +/* processor operations in rzv2. It defines + * notification operation and remote processor managementi operations. */ +struct remoteproc_ops rzv2_proc_ops = +{ + .init = rzv2_proc_init, + .remove = rzv2_proc_remove, + .mmap = NULL, + .notify = rzv2_proc_notify, + .start = NULL, + .stop = NULL, + .shutdown = NULL, +}; diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/sys_init.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/sys_init.c new file mode 100644 index 000000000..ad1e687ba --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/sys_init.c @@ -0,0 +1,195 @@ +/*********************************************************************************************************************** + * Copyright [2020-2021] Renesas Electronics Corporation and/or its affiliates. All Rights Reserved. + * + * This software and documentation are supplied by Renesas Electronics Corporation and/or its affiliates and may only + * be used with products of Renesas Electronics Corp. and its affiliates ("Renesas"). No other uses are authorized. + * Renesas products are sold pursuant to Renesas terms and conditions of sale. Purchasers are solely responsible for + * the selection and use of Renesas products and Renesas assumes no liability. No license, express or implied, to any + * intellectual property right is granted by Renesas. This software is protected under all applicable laws, including + * copyright laws. Renesas reserves the right to change or discontinue this software and/or this documentation. + * THE SOFTWARE AND DOCUMENTATION IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND + * TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, + * INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE + * SOFTWARE OR DOCUMENTATION. RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH. + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR + * DOCUMENTATION (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, + * INCLUDING, WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY + * LOST PROFITS, OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE + * POSSIBILITY OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS. + **********************************************************************************************************************/ +/** + * @file sys_init.c + * @brief Metal device definitions + * @date 2020.10.15 + * @author Copyright (c) 2020, eForce Co., Ltd. All rights reserved. + * + **************************************************************************** + * @par History + * - rev 1.0 (2020.10.15) Imada + * First release + **************************************************************************** + */ + +#include +#include +#include +#include +#include +#include "bsp_api.h" + +extern void init_resource_table(void); + +const metal_phys_addr_t metal_phys[] = + { + MBX_REG_PA, + CFG_RSCTBL_MEM_PA, + CFG_VRING0_BASE0_PA, + CFG_VRING0_BASE1_PA, + CFG_VRING_SHM_BASE0_PA, + CFG_VRING_SHM_BASE1_PA, +}; + +struct metal_device metal_dev_table[] = +{ + /* Mailbox device */ + { + MBX_DEV_NAME, + NULL, + 1, + {{(void *)MBX_REG_VA, + &metal_phys[0], + MBX_MAP_SIZE, + (sizeof(metal_phys_addr_t) << 3), + (metal_phys_addr_t)(-1), + 0, + {NULL}}}, + {NULL}, + 1, + (void *)MBX_INT_NUM, + }, + /* Resource table */ + { + CFG_RSCTBL_DEV_NAME, + NULL, + 1, + {{ + (void *)(CFG_RSCTBL_MEM_VA), + &metal_phys[1], + CFG_RSCTBL_MAP_SIZE, + (sizeof(metal_phys_addr_t) << 3), + (unsigned long)(-1), + 0, + {NULL}, + }}, + {NULL}, + 0, + NULL, + }, + /* RPMSG (vring) */ + { + /* vring #0 CTL */ + CFG_VRING_CTL_NAME0, + NULL, + 1, + {{ + (void *)(CFG_VRING0_BASE0_VA), + &metal_phys[2], + CFG_VRING_SIZE0, + (sizeof(metal_phys_addr_t) << 3), + (unsigned long)(-1), + 0, + {NULL}, + }}, + {NULL}, + 0, + NULL, + }, + { + /* vring #1 CTL */ + CFG_VRING_CTL_NAME1, + NULL, + 1, + {{ + (void *)(CFG_VRING0_BASE1_VA), + &metal_phys[3], + CFG_VRING_SIZE1, + (sizeof(metal_phys_addr_t) << 3), + (unsigned long)(-1), + 0, + {NULL}, + }}, + {NULL}, + 0, + NULL, + }, + { + /* vring #0 SHM */ + CFG_VRING_SHM_NAME0, + NULL, + 1, + {{ + (void *)(CFG_VRING_SHM_BASE0_VA), + &metal_phys[4], + CFG_VRING_SHM_SIZE0, + (sizeof(metal_phys_addr_t) << 3), + (unsigned long)(-1), + 0, + {NULL}, + }}, + {NULL}, + 0, + NULL, + }, + { + /* vring #1 SHM */ + CFG_VRING_SHM_NAME1, + NULL, + 1, + {{ + (void *)(CFG_VRING_SHM_BASE1_VA), + &metal_phys[5], + CFG_VRING_SHM_SIZE1, + (sizeof(metal_phys_addr_t) << 3), + (unsigned long)(-1), + 0, + {NULL}, + }}, + {NULL}, + 0, + NULL, + }, +}; + +int init_system(void) +{ + unsigned int i; + int ret; + struct metal_init_params metal_param = METAL_INIT_DEFAULTS; + struct metal_device *dev; + + init_resource_table(); + + ret = metal_init(&metal_param); + if (ret) + { + return ret; + } + + /* register device */ + for (i = 0U; i < (sizeof(metal_dev_table) / sizeof(struct metal_device)); i++) + { + dev = &metal_dev_table[i]; + ret = metal_register_generic_device(dev); + if (ret) + { + break; + } + } + + return ret; +} + +void cleanup_system(void) +{ + metal_finish(); +} diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/vector_data.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/vector_data.c index 46c3cdc0f..0c0f7cee2 100644 --- a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/vector_data.c +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/vector_data.c @@ -76,7 +76,7 @@ BSP_DONT_REMOVE fsp_vector_t g_vector_table[BSP_ICU_VECTOR_MAX_ENTRIES] BSP_PLAC Default_Handler, /* IRQ:66 */ Default_Handler, /* IRQ:67 */ Default_Handler, /* IRQ:68 */ - Default_Handler, /* IRQ:69 */ + metal_irq_isr_wrapper, /* IRQ:69 MHU1 MSG_INT_NS (Non-Secure Message Interrupt ch1) */ Default_Handler, /* IRQ:70 */ Default_Handler, /* IRQ:71 */ Default_Handler, /* IRQ:72 */ diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/vector_data.h b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/vector_data.h index 1cd4dae79..a2ea190f8 100644 --- a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/vector_data.h +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/rzv_gen/vector_data.h @@ -3,7 +3,7 @@ #define VECTOR_DATA_H /* Number of interrupts allocated */ #ifndef VECTOR_DATA_IRQ_COUNT -#define VECTOR_DATA_IRQ_COUNT (6) +#define VECTOR_DATA_IRQ_COUNT (7) #endif /** Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ @@ -16,6 +16,7 @@ void scif_uart_bri_isr(void); void scif_uart_rxi_isr(void); void scif_uart_txi_isr(void); void scif_uart_tei_isr(void); +void metal_irq_isr_wrapper(void); /** Common macro for FSP header files. There is also a corresponding FSP_HEADER macro at the top of this file. */ FSP_FOOTER diff --git a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/src/hal_entry.c b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/src/hal_entry.c index 9b122fc02..a4ee705f7 100644 --- a/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/src/hal_entry.c +++ b/Ubiquitous/XiZi_IIoT/board/rzv2l-m33/src/hal_entry.c @@ -3,11 +3,25 @@ #include #include #include +#include // FSP_CPP_HEADER void R_BSP_WarmStart(bsp_warm_start_event_t event); // FSP_CPP_FOOTER +void* TaskSample(void * args) +{ + while (1) + { + for (int i = 0; i < 100000; i++) + { + ; + } + + KPrintf("TaskSample: %s\n",(char*)args); + } +} + void XiZi_SysTick_Handler(void) { x_base lock = DISABLE_INTERRUPT(); @@ -41,6 +55,13 @@ void hal_entry(void) CreateEnvInitTask(); + // RPMsg 任务入口 + CreateRPMsgTask(); + + // StartupKTask(KTaskCreate("test-task-a",TaskSample,"test-task-a",512,20)); + // StartupKTask(KTaskCreate("test-task-b",TaskSample,"test-task-b",512,20)); + // StartupKTask(KTaskCreate("test-task-c",TaskSample,"test-task-c",512,20)); + KPrintf("hal_entry: init kernel envirement final!\n"); x_base lock = DISABLE_INTERRUPT(); diff --git a/Ubiquitous/XiZi_IIoT/fs/Kconfig b/Ubiquitous/XiZi_IIoT/fs/Kconfig index 4670355d9..37fc0e8fc 100644 --- a/Ubiquitous/XiZi_IIoT/fs/Kconfig +++ b/Ubiquitous/XiZi_IIoT/fs/Kconfig @@ -3,7 +3,7 @@ menu "File system" menuconfig FS_VFS bool "Using device virtual file system" select KERNEL_MUTEX - default y + default n help The device file system is a light weight virtual file system. diff --git a/Ubiquitous/XiZi_IIoT/path_kernel.mk b/Ubiquitous/XiZi_IIoT/path_kernel.mk index af3abfc4e..da5ec9324 100755 --- a/Ubiquitous/XiZi_IIoT/path_kernel.mk +++ b/Ubiquitous/XiZi_IIoT/path_kernel.mk @@ -34,7 +34,9 @@ KERNELPATHS += \ -I$(BSP_ROOT)/rzv/fsp/src/bsp/mcu/rzv2l \ -I$(BSP_ROOT)/rzv_cfg/fsp_cfg \ -I$(BSP_ROOT)/rzv_cfg/fsp_cfg/bsp \ - -I$(BSP_ROOT)/rzv_gen # + -I$(BSP_ROOT)/rzv_gen \ + -I$(BSP_ROOT)/rzv/linaro/libmetal/include \ + -I$(BSP_ROOT)/rzv/linaro/open-amp/lib/include # endif ifeq ($(BSP_ROOT),$(KERNEL_ROOT)/board/xidatong-arm32)