/*
 * Copyright 2020, 2022 NXP
 * All rights reserved.
 *
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef __FSL_RPMSG_ADAPTER_H__
#define __FSL_RPMSG_ADAPTER_H__

#if defined(SDK_OS_FREE_RTOS)
#include "FreeRTOS.h"
#endif

/*!
 * @addtogroup RPMSG_Adapter
 * @{
 */

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*! @brief RPMSG Msaster/Remote role definition (0 - Master, 1 - Remote) */
#ifndef HAL_RPMSG_SELECT_ROLE
#define HAL_RPMSG_SELECT_ROLE (1U)
#endif

/*! @brief RPMSG handle size definition */
#define HAL_RPMSG_HANDLE_SIZE (52U)

#ifndef REMOTE_CORE_BOOT_ADDRESS
#define REMOTE_CORE_BOOT_ADDRESS (0x01000000U)
#endif

#ifndef MAX_EP_COUNT
#define MAX_EP_COUNT (5U)
#endif

/*!
 * @brief Defines the rpmsg handle
 *
 * This macro is used to define a 4 byte aligned rpmsg handle.
 * Then use "(hal_rpmsg_handle_t)name" to get the rpmsg handle.
 *
 * The macro should be global and could be optional. You could also define rpmsg handle by yourself.
 *
 * This is an example,
 * @code
 * RPMSG_HANDLE_DEFINE(rpmsgHandle);
 * @endcode
 *
 * @param name The name string of the rpmsg handle.
 */
#define RPMSG_HANDLE_DEFINE(name) uint32_t name[((HAL_RPMSG_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))]

/*! @brief The handle of RPMSG adapter */
typedef void *hal_rpmsg_handle_t;

/*! @brief RPMSG status */
typedef enum _hal_rpmsg_status
{
    kStatus_HAL_RpmsgSuccess = 0U,
    kStatus_HAL_RpmsgError,
    kStatus_HAL_RpmsgRxBusy,
    kStatus_HAL_RpmsgTxBusy,
    kStatus_HAL_RpmsgTxIdle,
    kStatus_HAL_RpmsgRxIdle,
} hal_rpmsg_status_t;

/*! @brief RPMSG return status */
typedef enum _hal_rpmsg_return_status
{
    kStatus_HAL_RL_RELEASE = 0U,
    kStatus_HAL_RL_HOLD,
} hal_rpmsg_return_status_t;

/*! @brief The callback function of RPMSG adapter.
 *
 * @note If Rpmsg RX callback function return kStatus_HAL_RL_RELEASE mode, no need to call HAL_RpmsgFreeRxBuffer.
 * @note If Rpmsg RX callback function return kStatus_HAL_RL_HOLD mode,then need to call HAL_RpmsgFreeRxBuffer.
 *
 */
typedef hal_rpmsg_return_status_t (*rpmsg_rx_callback_t)(void *param, uint8_t *data, uint32_t len);

/*! @brief The configure structure of RPMSG adapter. */
typedef struct _hal_rpmsg_config
{
    uint8_t local_addr;           /* Local address for rx */
    uint8_t remote_addr;          /* Remote address for tx */
    rpmsg_rx_callback_t callback; /* RPMGS Rx callback  */
    void *param;                  /* RPMGS Rx callback parameter */
} hal_rpmsg_config_t;

/*******************************************************************************
 * API
 ******************************************************************************/

#if defined(__cplusplus)
extern "C" {
#endif /* _cplusplus */

/*!
 * @brief Initializes the RPMSG adapter module for dual core communication.
 *
 * @note This API should be called at the beginning of the application using the RPMSG adapter driver.
 *
 * @retval kStatus_HAL_RpmsgSuccess RPMSG module initialize succeed.
 */
hal_rpmsg_status_t HAL_RpmsgMcmgrInit(void);

/*!
 * @brief Initializes the RPMSG adapter for RPMSG channel configure.
 *
 * @note This API should be called to software RPMSG communication configure, and it be
 * called whenever application need it.
 *
 * @param handle Pointer to point to a memory space of size #HAL_RPMSG_HANDLE_SIZE allocated by the caller.
 * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices.
 * You can define the handle in the following two ways:
 * #RPMSG_HANDLE_DEFINE(handle);
 * or
 * uint32_t handle[((HAL_RPMSG_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))];
 * @param config           Used for config local/remote endpoint addr.
 * @retval kStatus_HAL_RpmsgSuccess RPMSG module initialize succeed.
 */
hal_rpmsg_status_t HAL_RpmsgInit(hal_rpmsg_handle_t handle, hal_rpmsg_config_t *config);

/*!
 * @brief DeInitilizate the RPMSG adapter module.
 *
 * @note This API should be called when not using the RPMSG adapter driver anymore.
 *
 * @param handle           RPMSG handle pointer.
 * @retval kStatus_HAL_RpmsgSuccess RPMSG module deinitialize succeed.
 */
hal_rpmsg_status_t HAL_RpmsgDeinit(hal_rpmsg_handle_t handle);

/*!
 * @brief Send data to another RPMSG module.
 *
 * This function will send a specified length of data to another core by RPMSG.
 *
 * @note This API should be called to send data.
 *
 * @param handle           RPMSG handle pointer.
 * @param data             Pointer to where the send data from.
 * @param length           The send data length.
 * @retval kStatus_HAL_RpmsgSuccess RPMSG send data succeed.
 */
hal_rpmsg_status_t HAL_RpmsgSend(hal_rpmsg_handle_t handle, uint8_t *data, uint32_t length);

/*!
 * @brief Allocates the tx buffer for message payload.
 *
 * This API can only be called at process context to get the tx buffer in vring. By this way, the
 * application can directly put its message into the vring tx buffer without copy from an application buffer.
 * It is the application responsibility to correctly fill the allocated tx buffer by data and passing correct
 * parameters to the rpmsg_lite_send_nocopy() function to perform data no-copy-send mechanism.
 *
 *
 * @param handle           RPMSG handle pointer.
 * @param size           The send data length.
 * @retval The tx buffer address on success and RL_NULL on failure.
 */
void *HAL_RpmsgAllocTxBuffer(hal_rpmsg_handle_t handle, uint32_t size);

/*!
 * @brief Send data with NoCopy to another RPMSG module.
 *
 * This function will send a specified length of data to another core by RPMSG.
 * This function sends txbuf of length len to the remote dst address,
 * and uses ept->addr as the source address.
 * The application has to take the responsibility for:
 *  1. tx buffer allocation (HAL_RpmsgAllocTxBuffer())
 *  2. filling the data to be sent into the pre-allocated tx buffer
 *  3. not exceeding the buffer size when filling the data
 *  4. data cache coherency
 *
 * After the HAL_RpmsgNoCopySend() function is issued the tx buffer is no more owned
 * by the sending task and must not be touched anymore unless the HAL_RpmsgNoCopySend()
 * function fails and returns an error.
 *
 * @note This API should be called to send data.
 *
 * @param handle           RPMSG handle pointer.
 * @param data             Pointer to where the send data from.
 * @param length           The send data length.
 * @retval kStatus_HAL_RpmsgSuccess RPMSG send data succeed.
 */
hal_rpmsg_status_t HAL_RpmsgNoCopySend(hal_rpmsg_handle_t handle, uint8_t *data, uint32_t length);

/*!
 * @brief Releases the rx buffer for future reuse in vring.
 * This API can be called at process context when the
 * message in rx buffer is processed.
 *
 * @note The HAL_RpmsgFreeRxBuffer need be called only if Rpmsg RX callback function return kStatus_HAL_RL_HOLD mode.
 *
 * @param handle           RPMSG handle pointer.
 * @param data             Pointer to where the received data from perr.

 *
 * @return Status of function execution, RL_SUCCESS on success.
 */
hal_rpmsg_status_t HAL_RpmsgFreeRxBuffer(hal_rpmsg_handle_t handle, uint8_t *data);

/*!
 * @brief Install RPMSG rx callback.
 *
 * @note The function must be called because rpmsg adapter just support asynchronous receive mode
 *        should make sure the callback function is installed before the data received from peer soc,
 *        and the rx callback function will be called when the rx process complete.
 *
 *
 * @param handle    RPMSG handle pointer.
 * @retval kStatus_HAL_RpmsgSuccess RPMSG install rx callback succeed.
 */
hal_rpmsg_status_t HAL_RpmsgInstallRxCallback(hal_rpmsg_handle_t handle, rpmsg_rx_callback_t callback, void *param);

/*!
 * @brief Prepares to enter low power consumption.
 *
 * This function is used to prepare to enter low power consumption.
 *
 * @param handle           RPMSG handle pointer.
 * @retval kStatus_HAL_RpmsgSuccess Successful operation.
 * @retval kStatus_HAL_RpmsgError An error occurred.
 */
hal_rpmsg_status_t HAL_RpmsgEnterLowpower(hal_rpmsg_handle_t handle);

/*!
 * @brief Prepares to exit low power consumption.
 *
 * This function is used to restore from low power consumption.
 *
 * @param handle           RPMSG handle pointer.
 * @retval kStatus_HAL_RpmsgSuccess Successful operation.
 * @retval kStatus_HAL_RpmsgError An error occurred.
 */
hal_rpmsg_status_t HAL_RpmsgExitLowpower(hal_rpmsg_handle_t handle);

/*! @}*/

#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* __FSL_RPMSG_ADAPTER_H__ */
