You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
354 lines
12 KiB
354 lines
12 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2020. All rights reserved.
|
|
* Description: mailbox driver in liteos
|
|
*/
|
|
#include "drv_mbx.h"
|
|
#include "mbx_common.h"
|
|
#include "los_mbx.h"
|
|
|
|
#include "los_printf.h"
|
|
#include "los_base.h"
|
|
#include "los_memory.h"
|
|
#include "los_mux.h"
|
|
|
|
#define SC_GEN18 (void *)(td_uintptr_t)0x841448
|
|
|
|
static td_bool is_v2_chipset(td_void)
|
|
{
|
|
if (MBX_READL(SC_GEN18) & (0x1 << 13)) { /* if SC_GEN18[13]==1 then V2(CS) chipset */
|
|
return TD_TRUE;
|
|
}
|
|
|
|
return TD_FALSE;
|
|
}
|
|
|
|
td_s32 drv_mbx_open(td_u32 session_id)
|
|
{
|
|
return mbx_open(session_id, MBX_RX_BUFF_SIZE, MBX_TX_BUFF_SIZE);
|
|
}
|
|
|
|
td_s32 drv_mbx_close(td_u32 handle)
|
|
{
|
|
return mbx_close(handle);
|
|
}
|
|
|
|
td_s32 drv_mbx_register_irq_callback(td_u32 handle, session_callback func, const td_void * const data)
|
|
{
|
|
return mbx_register_irq_callback(handle, func, data);
|
|
}
|
|
|
|
td_s32 drv_mbx_rx(td_u32 handle, td_u8 *msg, td_u32 msg_len, const td_u32 * const rx_len, td_u32 timeout)
|
|
{
|
|
return mbx_rx(handle, msg, msg_len, (td_u32 *)rx_len, timeout);
|
|
}
|
|
|
|
td_s32 drv_mbx_tx(td_u32 handle, const td_u8 *msg, td_u32 msg_len, const td_u32 * const tx_len,
|
|
td_u32 timeout)
|
|
{
|
|
return mbx_tx(handle, msg, msg_len, (td_u32 *)tx_len, timeout);
|
|
}
|
|
|
|
|
|
td_void mbx_polling_rx(td_void)
|
|
{
|
|
#ifndef SUPPORT_MBX_INTERRUPT
|
|
struct mailbox *mailbox = NULL;
|
|
|
|
mailbox = get_mailbox_data();
|
|
if (mailbox == NULL) {
|
|
return;
|
|
}
|
|
mbx_rx_msg((td_void *)mailbox->acpu_vmcu0.rx_head_addr);
|
|
mbx_rx_msg((td_void *)mailbox->tcpu_vmcu0.rx_head_addr);
|
|
#endif
|
|
return;
|
|
}
|
|
static void init_acpu_reg(struct session * const session, const struct mailbox *mailbox)
|
|
{
|
|
if (session == NULL || mailbox == NULL) {
|
|
return;
|
|
}
|
|
if (mailbox->acpu_vmcu0.base_addr == NULL) {
|
|
return;
|
|
}
|
|
session->tx_reg = (struct reg *)MBX_MALLOC(sizeof(struct reg));
|
|
if (session->tx_reg == NULL) {
|
|
return;
|
|
}
|
|
if (is_v2_chipset() == TD_TRUE) {
|
|
session->tx_reg->argv_size = VMCU_TO_ACPU_ARGS_V2_NUM;
|
|
session->tx_reg->argv = mailbox->acpu_vmcu0.base_addr + VMCU_TO_ACPU_ARGS_V2_OFFSET;
|
|
} else {
|
|
session->tx_reg->argv_size = VMCU_TO_ACPU_ARGS_NUM;
|
|
session->tx_reg->argv = mailbox->acpu_vmcu0.base_addr + VMCU_TO_ACPU_ARGS_OFFSET;
|
|
}
|
|
#ifdef CHIP_TYPE_RESERVED23
|
|
session->tx_reg->argv_size = VMCU_TO_ACPU_ARGS_V2_NUM;
|
|
session->tx_reg->argv = mailbox->acpu_vmcu0.base_addr + VMCU_TO_ACPU_ARGS_V2_OFFSET;
|
|
#endif
|
|
session->tx_reg->version = mailbox->acpu_vmcu0.base_addr + MAILBOX_VERSION_OFFSET;
|
|
session->tx_reg->head = mailbox->acpu_vmcu0.base_addr + VMCU_TO_ACPU_HEAD_OFFSET;
|
|
session->tx_reg->trigger_rx = mailbox->acpu_vmcu0.base_addr + VMCU_TO_ACPU_SEND_OFFSET;
|
|
session->tx_reg->pending = mailbox->acpu_vmcu0.base_addr + ACPU_INTR_FROM_VMCU_OFFSET;
|
|
session->tx_reg->lock = (td_u32 *)&mailbox->tx_acpu_lock;
|
|
|
|
session->rx_reg = (struct reg *)MBX_MALLOC(sizeof(struct reg));
|
|
if (session->rx_reg == NULL) {
|
|
return;
|
|
}
|
|
session->rx_reg->argv_size = ACPU_TO_VMCU_ARGS_NUM;
|
|
session->rx_reg->version = mailbox->acpu_vmcu0.base_addr + MAILBOX_VERSION_OFFSET;
|
|
session->rx_reg->head = mailbox->acpu_vmcu0.base_addr + ACPU_TO_VMCU_HEAD_OFFSET;
|
|
session->rx_reg->argv = mailbox->acpu_vmcu0.base_addr + ACPU_TO_VMCU_ARGS_OFFSET;
|
|
session->rx_reg->trigger_rx = mailbox->acpu_vmcu0.base_addr + ACPU_TO_VMCU_SEND_OFFSET;
|
|
session->rx_reg->pending = mailbox->acpu_vmcu0.base_addr + VMCU_INTR_FROM_ACPU_OFFSET;
|
|
|
|
return;
|
|
}
|
|
|
|
static void init_tcpu_reg(struct session * const session, const struct mailbox * const mailbox)
|
|
{
|
|
if (session == NULL || mailbox == NULL) {
|
|
return;
|
|
}
|
|
if (mailbox->tcpu_vmcu0.base_addr == NULL) {
|
|
return;
|
|
}
|
|
session->tx_reg = (struct reg *)MBX_MALLOC(sizeof(struct reg));
|
|
if (session->tx_reg == NULL) {
|
|
return;
|
|
}
|
|
session->tx_reg->argv_size = VMCU_TO_TCPU_ARGS_NUM;
|
|
session->tx_reg->version = mailbox->tcpu_vmcu0.base_addr + MAILBOX_VERSION_OFFSET;
|
|
session->tx_reg->head = mailbox->tcpu_vmcu0.base_addr + VMCU_TO_TCPU_HEAD_OFFSET;
|
|
session->tx_reg->argv = mailbox->tcpu_vmcu0.base_addr + VMCU_TO_TCPU_ARGS_OFFSET;
|
|
session->tx_reg->trigger_rx = mailbox->tcpu_vmcu0.base_addr + VMCU_TO_TCPU_SEND_OFFSET;
|
|
session->tx_reg->pending = mailbox->tcpu_vmcu0.base_addr + TCPU_INTR_FROM_VMCU_OFFSET;
|
|
session->tx_reg->lock = (td_u32 *)&mailbox->tx_tcpu_lock;
|
|
|
|
session->rx_reg = (struct reg *)MBX_MALLOC(sizeof(struct reg));
|
|
if (session->rx_reg == NULL) {
|
|
return;
|
|
}
|
|
session->rx_reg->argv_size = TCPU_TO_VMCU_ARGS_NUM;
|
|
session->rx_reg->version = mailbox->tcpu_vmcu0.base_addr + MAILBOX_VERSION_OFFSET;
|
|
session->rx_reg->head = mailbox->tcpu_vmcu0.base_addr + TCPU_TO_VMCU_HEAD_OFFSET;
|
|
session->rx_reg->argv = mailbox->tcpu_vmcu0.base_addr + TCPU_TO_VMCU_ARGS_OFFSET;
|
|
session->rx_reg->trigger_rx = mailbox->tcpu_vmcu0.base_addr + TCPU_TO_VMCU_SEND_OFFSET;
|
|
session->rx_reg->pending = mailbox->tcpu_vmcu0.base_addr + VMCU_INTR_FROM_TCPU_OFFSET;
|
|
|
|
return;
|
|
}
|
|
|
|
static void init_dmcu0_reg(struct session *session, const struct mailbox *mailbox)
|
|
{
|
|
if (session == NULL || mailbox == NULL) {
|
|
return;
|
|
}
|
|
if (mailbox->acpu_dmcu0.base_addr == NULL) {
|
|
return;
|
|
}
|
|
session->tx_reg = (struct reg *)MBX_MALLOC(sizeof(struct reg));
|
|
if (session->tx_reg == NULL) {
|
|
return;
|
|
}
|
|
session->tx_reg->argv_size = DMCU_TO_ACPU_ARGS_V2_NUM;
|
|
session->tx_reg->argv = mailbox->acpu_dmcu0.base_addr + DMCU_TO_ACPU_ARGS_V2_OFFSET;
|
|
session->tx_reg->version = mailbox->acpu_dmcu0.base_addr + MAILBOX_VERSION_OFFSET;
|
|
session->tx_reg->head = mailbox->acpu_dmcu0.base_addr + DMCU_TO_ACPU_HEAD_OFFSET;
|
|
session->tx_reg->trigger_rx = mailbox->acpu_dmcu0.base_addr + DMCU_TO_ACPU_SEND_OFFSET;
|
|
session->tx_reg->pending = mailbox->acpu_dmcu0.base_addr + ACPU_INTR_FROM_DMCU_OFFSET;
|
|
session->tx_reg->lock = (td_u32 *)&mailbox->tx_dmcu0_lock;
|
|
|
|
session->rx_reg = (struct reg *)MBX_MALLOC(sizeof(struct reg));
|
|
if (session->rx_reg == NULL) {
|
|
MBX_FREE(session->tx_reg);
|
|
return;
|
|
}
|
|
session->rx_reg->argv_size = ACPU_TO_DMCU_ARGS_NUM;
|
|
session->rx_reg->version = mailbox->acpu_dmcu0.base_addr + MAILBOX_VERSION_OFFSET;
|
|
session->rx_reg->head = mailbox->acpu_dmcu0.base_addr + ACPU_TO_DMCU_HEAD_OFFSET;
|
|
session->rx_reg->argv = mailbox->acpu_dmcu0.base_addr + ACPU_TO_DMCU_ARGS_OFFSET;
|
|
session->rx_reg->trigger_rx = mailbox->acpu_dmcu0.base_addr + ACPU_TO_DMCU_SEND_OFFSET;
|
|
session->rx_reg->pending = mailbox->acpu_dmcu0.base_addr + DMCU_INTR_FROM_ACPU_OFFSET;
|
|
|
|
return;
|
|
}
|
|
|
|
td_void init_mailbox_reg(struct session *session, td_u32 session_id, const struct mailbox *mailbox)
|
|
{
|
|
td_u32 local_side, remote_side;
|
|
|
|
if (mailbox == NULL) {
|
|
return;
|
|
}
|
|
|
|
local_side = mailbox->local_cpu;
|
|
remote_side = SESSION_ID_SIDE0(session_id) == local_side ? \
|
|
SESSION_ID_SIDE1(session_id) : SESSION_ID_SIDE0(session_id);
|
|
|
|
if (local_side != SESSION_ID_SIDE0(session_id) && \
|
|
local_side != SESSION_ID_SIDE1(session_id)) {
|
|
return;
|
|
}
|
|
if (session == NULL) {
|
|
return;
|
|
}
|
|
switch (local_side) {
|
|
case VMCU0:
|
|
if (remote_side == ACPU) {
|
|
init_acpu_reg(session, mailbox);
|
|
} else if (remote_side == TCPU) {
|
|
init_tcpu_reg(session, mailbox);
|
|
} else {
|
|
session->tx_reg = NULL;
|
|
session->rx_reg = NULL;
|
|
}
|
|
break;
|
|
case DMCU0:
|
|
if (remote_side == ACPU) {
|
|
init_dmcu0_reg(session, mailbox);
|
|
} else {
|
|
session->tx_reg = NULL;
|
|
session->rx_reg = NULL;
|
|
}
|
|
break;
|
|
default:
|
|
session->tx_reg = NULL;
|
|
session->rx_reg = NULL;
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
#ifdef SUPPORT_MBX_INTERRUPT
|
|
#ifdef CONFIG_DRIVERS_MBX_DMCU
|
|
static MBX_IRQ_RET mailbox_dmcu0_irq_handler(int irq, void *dev_id)
|
|
{
|
|
int ret;
|
|
struct mailbox *mailbox;
|
|
|
|
mailbox = get_mailbox_data();
|
|
if (mailbox == NULL || mailbox->acpu_dmcu0.rx_head_addr == NULL) {
|
|
return MBX_IRQ_HANDLED;
|
|
}
|
|
ret = mbx_rx_msg((void *)mailbox->acpu_dmcu0.rx_head_addr);
|
|
if (ret != SOC_MBX_SUCCESS) {
|
|
MBX_WRITEL(0x00, mailbox->acpu_dmcu0.base_addr + DMCU_INTR_FROM_ACPU_OFFSET);
|
|
MBX_ERR_PRINT("mbx_rx_msg dmcu0 error and ret:0x%x\n", ret);
|
|
}
|
|
|
|
return MBX_IRQ_HANDLED;
|
|
}
|
|
#else
|
|
static MBX_IRQ_RET mailbox_acpu_irq_handler(td_void *dev_id)
|
|
{
|
|
td_s32 ret;
|
|
struct mailbox *mailbox;
|
|
|
|
mailbox = get_mailbox_data();
|
|
if (mailbox == NULL || (mailbox->acpu_vmcu0.rx_head_addr == NULL) || mailbox->acpu_vmcu0.base_addr == NULL) {
|
|
return MBX_IRQ_HANDLED;
|
|
}
|
|
ret = mbx_rx_msg((td_void *)mailbox->acpu_vmcu0.rx_head_addr);
|
|
if (ret != SOC_MBX_SUCCESS) {
|
|
MBX_WRITEL(0x00, mailbox->acpu_vmcu0.base_addr + VMCU_INTR_FROM_ACPU_OFFSET);
|
|
MBX_ERR_PRINT("mbx_rx_msg error from acpu and ret:0x%x\n", ret);
|
|
}
|
|
|
|
return MBX_IRQ_HANDLED;
|
|
}
|
|
|
|
static MBX_IRQ_RET mailbox_tcpu_irq_handler(td_void *dev_id)
|
|
{
|
|
td_s32 ret;
|
|
struct mailbox *mailbox;
|
|
|
|
mailbox = get_mailbox_data();
|
|
if ((mailbox == NULL) || (mailbox->tcpu_vmcu0.rx_head_addr == NULL) || (mailbox->tcpu_vmcu0.base_addr == NULL)) {
|
|
return MBX_IRQ_HANDLED;
|
|
}
|
|
ret = mbx_rx_msg((td_void *)mailbox->tcpu_vmcu0.rx_head_addr);
|
|
if (ret != SOC_MBX_SUCCESS) {
|
|
MBX_WRITEL(0x00, mailbox->tcpu_vmcu0.base_addr + VMCU_INTR_FROM_TCPU_OFFSET);
|
|
MBX_ERR_PRINT("mbx_rx_msg error from tcpu and ret:0x%x\n", ret);
|
|
}
|
|
|
|
return MBX_IRQ_HANDLED;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
td_s32 drv_mbx_init(enum cpu_id local_cpu)
|
|
{
|
|
struct mailbox *mailbox;
|
|
#ifdef SUPPORT_MBX_INTERRUPT
|
|
td_s32 ret;
|
|
#endif
|
|
|
|
mailbox = get_mailbox_data();
|
|
if ((mailbox == NULL) || (local_cpu >= CPU_MAX) || (mailbox->initalized != TD_FALSE)) {
|
|
return SOC_ERR_MAILBOX_NOT_SUPPORT;
|
|
}
|
|
MBX_INIT_LIST_HEAD(&mailbox->list_head);
|
|
mailbox->local_cpu = local_cpu;
|
|
MBX_MUTEX_INIT(&mailbox->list_lock);
|
|
#ifdef CONFIG_DRIVERS_MBX_DMCU
|
|
MBX_MUTEX_INIT(&mailbox->tx_dmcu0_lock);
|
|
mailbox->acpu_dmcu0.base_addr = (td_u32 *)(MBX_ACPU_DMCU0_BASE_ADDR);
|
|
mailbox->acpu_dmcu0.rx_head_addr = mailbox->acpu_dmcu0.base_addr + ACPU_TO_DMCU_HEAD_OFFSET;
|
|
mailbox->initalized = TRUE;
|
|
#ifdef SUPPORT_MBX_INTERRUPT
|
|
ret = (td_s32)LOS_HwiCreate(MBX_IRQ_ACPU2DMCU, 0x01, 0, (HWI_PROC_FUNC)mailbox_dmcu0_irq_handler, 0);
|
|
if (ret != 0) {
|
|
MBX_ERR_PRINT("Request MBX_IRQ_ACPU2DMCU IRQ failed\n");
|
|
return SOC_ERR_MAILBOX_NOT_INIT;
|
|
}
|
|
LOS_HwiEnable(MBX_IRQ_ACPU2DMCU);
|
|
#endif
|
|
#else
|
|
MBX_MUTEX_INIT(&mailbox->tx_acpu_lock);
|
|
MBX_MUTEX_INIT(&mailbox->tx_tcpu_lock);
|
|
mailbox->acpu_vmcu0.base_addr = (td_u32 *)MBX_VMCU0_BASE_ADDR;
|
|
mailbox->acpu_vmcu0.rx_head_addr = mailbox->acpu_vmcu0.base_addr + ACPU_TO_VMCU_HEAD_OFFSET;
|
|
mailbox->tcpu_vmcu0.base_addr = (td_u32 *)MBX_VMCU0_BASE_ADDR;
|
|
mailbox->tcpu_vmcu0.rx_head_addr = mailbox->acpu_vmcu0.base_addr + TCPU_TO_VMCU_HEAD_OFFSET;
|
|
mailbox->initalized = TRUE;
|
|
#ifdef SUPPORT_MBX_INTERRUPT
|
|
ret = (td_s32)LOS_HwiCreate(MBX_IRQ_ACPU2VMCU, 0x01, 0, (HWI_PROC_FUNC)mailbox_acpu_irq_handler, 0);
|
|
if (ret != 0) {
|
|
MBX_ERR_PRINT("Request MBX_IRQ_ACPU2VMCU IRQ failed\n");
|
|
return SOC_ERR_MAILBOX_NOT_INIT;
|
|
}
|
|
LOS_InterruptUnmask(MBX_IRQ_ACPU2VMCU);
|
|
ret = (td_s32)LOS_HwiCreate(MBX_IRQ_TCPU2VMCU, 0x01, 0, (HWI_PROC_FUNC)mailbox_tcpu_irq_handler, 0);
|
|
if (ret != 0) {
|
|
MBX_ERR_PRINT("Request MBX_IRQ_TCPU2VMCU IRQ failed\n");
|
|
return SOC_ERR_MAILBOX_NOT_INIT;
|
|
}
|
|
LOS_InterruptUnmask(MBX_IRQ_TCPU2VMCU);
|
|
#endif
|
|
#endif
|
|
|
|
return SOC_MBX_SUCCESS;
|
|
}
|
|
|
|
td_s32 drv_mbx_deinit(td_void)
|
|
{
|
|
struct mailbox *mailbox;
|
|
|
|
mailbox = get_mailbox_data();
|
|
if (mailbox == NULL) {
|
|
return SOC_ERR_MAILBOX_NOT_SUPPORT;
|
|
}
|
|
mailbox->initalized = FALSE;
|
|
mailbox->local_cpu = 0;
|
|
#ifdef SUPPORT_MBX_INTERRUPT
|
|
LOS_HwiDelete(MBX_IRQ_ACPU2VMCU, 0);
|
|
LOS_HwiDelete(MBX_IRQ_TCPU2VMCU, 0);
|
|
#endif
|
|
|
|
return SOC_MBX_SUCCESS;
|
|
}
|