447 lines
12 KiB
C
447 lines
12 KiB
C
/*
|
|
* Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#include "queue.h"
|
|
#include "semphr.h"
|
|
#include <unistd.h>
|
|
#include "n200_eclic.h"
|
|
#include "n200_func.h"
|
|
#include "uart.h"
|
|
#include "common.h"
|
|
#include "riscv_encoding.h"
|
|
|
|
#include "mailbox-common.h"
|
|
#include "mailbox_soc.h"
|
|
#include "mailbox-pl.h"
|
|
#include "mailbox-htbl.h"
|
|
#include "mailbox-api.h"
|
|
#include "mailbox-rpc-test.h"
|
|
|
|
#define MBTAG "AOCPU"
|
|
#define PRINT_DBG(...) //printf(__VA_ARGS__)
|
|
#define PRINT_ERR(...) printf(__VA_ARGS__)
|
|
#define PRINT(...) printf(__VA_ARGS__)
|
|
|
|
#define AO_MBOX_ONLY_SYNC 1
|
|
#define MHU_MB_TASK_PRIORITIES (configMAX_PRIORITIES - 1)
|
|
|
|
void *g_tbl_ao;
|
|
void *pvClientIdTab;
|
|
struct xClientMboxChan *pxReeMboxChan;
|
|
struct xClientMboxChan *pxTeeMboxChan;
|
|
TaskHandle_t ReeMboxHandler;
|
|
TaskHandle_t TeeMboxHandler;
|
|
static uint32_t ulReeSyncTaskWake;
|
|
static uint32_t ulTeeSyncTaskWake;
|
|
struct mboxPackInfo syncReeMboxInfo;
|
|
struct mboxPackInfo syncTeeMboxInfo;
|
|
|
|
static void vGetPayload(uint32_t addr, void *data, size_t size)
|
|
{
|
|
VALID_BUFFER_SIZE(size);
|
|
|
|
PRINT_DBG("%s: addr:0x%x, 0x%x\n", __func__,
|
|
(unsigned int)addr, size);
|
|
if (data != NULL)
|
|
pvMboxMemCpy((void *)(uintptr_t)data, (void *)(uintptr_t)addr, size);
|
|
}
|
|
|
|
static void prvBuildPayload(uint32_t addr, void *data, size_t size)
|
|
{
|
|
VALID_BUFFER_SIZE(size);
|
|
|
|
PRINT_DBG("%s: addr:0x%x\n", __func__, (unsigned int)addr);
|
|
if (data != NULL) {
|
|
pvMboxMemSet((void *)(uintptr_t)addr, 0, MAILBOX_BUFFER_SIZE);
|
|
pvMboxMemCpy((void *)(uintptr_t)addr, (void *)(uintptr_t)data, size);
|
|
}
|
|
}
|
|
|
|
/* ARMTEE to AOCPU mailbox handler */
|
|
static void vAoRevTeeMboxHandler(uint32_t mbox)
|
|
{
|
|
(void)mbox;
|
|
BaseType_t xYieldRequired = pdFALSE;
|
|
struct mboxPackInfo mbInfo;
|
|
union MbStat_in st_in;
|
|
uint32_t ulMbCmd, ulSize, ulSync;
|
|
uint32_t ulRdAddr = 0;
|
|
uint32_t ulClrAddr = 0;
|
|
|
|
DisableIrq(MAILBOX_AOCPU_TEE_IRQ);
|
|
PRINT_DBG("[%s]: TeeMbox 0x%x\n", MBTAG, (unsigned int)mbox);
|
|
st_in.reg = REG32(pxTeeMboxChan->pxMboxChan->ulStatAddr);
|
|
ulRdAddr = pxTeeMboxChan->pxMboxChan->ulRdAddr;
|
|
ulClrAddr = pxTeeMboxChan->pxMboxChan->ulClrAddr;
|
|
|
|
if (st_in.reg == 0 || ulRdAddr == 0) {
|
|
PRINT_ERR("[%s] invalid mbox status or address!\n", MBTAG);
|
|
vClrMboxStats(ulClrAddr);
|
|
ClearPendingIrq(MAILBOX_AOCPU_TEE_IRQ);
|
|
EnableIrq(MAILBOX_AOCPU_TEE_IRQ);
|
|
return;
|
|
}
|
|
|
|
ulMbCmd = st_in.st.cmd;
|
|
ulSize = st_in.st.size;
|
|
ulSync = st_in.st.sync;
|
|
PRINT_DBG("[%s]: 0x%x, 0x%x, 0x%x, 0x%x\n", MBTAG,
|
|
(unsigned int)mbox,
|
|
(unsigned int)ulMbCmd,
|
|
(unsigned int)ulSize,
|
|
(unsigned int)ulSync);
|
|
|
|
if (ulMbCmd == 0) {
|
|
PRINT_ERR("[%s]: Err: mbox cmd is 0\n", MBTAG);
|
|
vClrMboxStats(ulClrAddr);
|
|
ClearPendingIrq(MAILBOX_AOCPU_TEE_IRQ);
|
|
EnableIrq(MAILBOX_AOCPU_TEE_IRQ);
|
|
return;
|
|
}
|
|
|
|
if (ulSize != 0)
|
|
vGetPayload(ulRdAddr, &mbInfo.mbdata, ulSize);
|
|
|
|
PRINT_DBG("%s taskid: 0x%llx\n", MBTAG, mbInfo.mbdata.taskid);
|
|
PRINT_DBG("%s complete: 0x%llx\n", MBTAG, mbInfo.mbdata.complete);
|
|
PRINT_DBG("%s ullclt: 0x%llx\n", MBTAG, mbInfo.mbdata.ullclt);
|
|
|
|
switch (ulSync) {
|
|
case MB_SYNC:
|
|
if (ulTeeSyncTaskWake) {
|
|
PRINT_ERR("TeeSyncTaskWake Busy\n");
|
|
break;
|
|
}
|
|
PRINT_DBG("[%s]: SYNC\n", MBTAG);
|
|
mbInfo.ulCmd = ulMbCmd;
|
|
mbInfo.ulSize = ulSize;
|
|
pvMboxMemCpy(&syncTeeMboxInfo, &mbInfo, sizeof(syncTeeMboxInfo));
|
|
;
|
|
vTaskNotifyGiveFromISR(TeeMboxHandler, &xYieldRequired);
|
|
portYIELD_FROM_ISR(xYieldRequired);
|
|
break;
|
|
case MB_ASYNC:
|
|
#ifdef AO_MBOX_ONLY_SYNC
|
|
PRINT_DBG("[%s]: ASYNC no support\n", MBTAG);
|
|
vClrMboxStats(ulClrAddr);
|
|
ClearPendingIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
EnableIrq(MAILBOX_AOCPU_TEE_IRQ);
|
|
#endif
|
|
break;
|
|
default:
|
|
PRINT_ERR("[%s]: Not SYNC or ASYNC, Fail\n", MBTAG);
|
|
vClrMboxStats(ulClrAddr);
|
|
ClearPendingIrq(MAILBOX_AOCPU_TEE_IRQ);
|
|
EnableIrq(MAILBOX_AOCPU_TEE_IRQ);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* TEE to AOCPU mailbox handle task on sync mode */
|
|
static void vTeeSyncTask(void *pvParameters)
|
|
{
|
|
uint32_t ulWrAddr;
|
|
uint32_t ulClrAddr;
|
|
int index = 0;
|
|
|
|
(void)pvParameters;
|
|
ulWrAddr = pxTeeMboxChan->pxMboxChan->ulWrAddr;
|
|
ulClrAddr = pxTeeMboxChan->pxMboxChan->ulClrAddr;
|
|
|
|
while (1) {
|
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
PRINT_DBG("[%s]:TeeSyncTask\n", MBTAG);
|
|
|
|
index = mailbox_htbl_invokeCmd(g_tbl_ao, syncTeeMboxInfo.ulCmd,
|
|
syncTeeMboxInfo.mbdata.data);
|
|
PRINT_DBG("[%s]:mbox:%d\n", MBTAG, pxTeeMboxChan->pxMboxChan->ucMboxChId);
|
|
if (index != 0) {
|
|
if (index == MAX_ENTRY_NUM) {
|
|
pvMboxMemSet(&syncTeeMboxInfo.mbdata.data, 0,
|
|
sizeof(syncTeeMboxInfo.mbdata.data));
|
|
syncTeeMboxInfo.mbdata.status = ACK_FAIL;
|
|
if (ulWrAddr)
|
|
prvBuildPayload(ulWrAddr, &syncTeeMboxInfo.mbdata,
|
|
sizeof(syncTeeMboxInfo.mbdata));
|
|
PRINT_DBG("[%s]: undefine cmd or no callback\n", MBTAG);
|
|
} else {
|
|
PRINT_DBG("[%s]:TeeSync re len:%d\n", MBTAG,
|
|
sizeof(syncTeeMboxInfo.mbdata));
|
|
syncTeeMboxInfo.mbdata.status = ACK_OK;
|
|
if (ulWrAddr)
|
|
prvBuildPayload(ulWrAddr, &syncTeeMboxInfo.mbdata,
|
|
sizeof(syncTeeMboxInfo.mbdata));
|
|
}
|
|
}
|
|
|
|
vEnterCritical();
|
|
PRINT_DBG("[%s]:TeeSync clear mbox:%d\n", MBTAG,
|
|
pxTeeMboxChan->pxMboxChan->ucMboxChId);
|
|
ulTeeSyncTaskWake = 0;
|
|
vClrMboxStats(ulClrAddr);
|
|
ClearPendingIrq(MAILBOX_AOCPU_TEE_IRQ);
|
|
EnableIrq(MAILBOX_AOCPU_TEE_IRQ);
|
|
vExitCritical();
|
|
}
|
|
}
|
|
|
|
/* ARMREE to AOCPU mailbox handler */
|
|
static void vAoRevReeMboxHandler(uint32_t mbox)
|
|
{
|
|
(void)mbox;
|
|
BaseType_t xYieldRequired = pdFALSE;
|
|
struct mboxPackInfo mbInfo;
|
|
union MbStat_in st_in;
|
|
uint32_t ulMbCmd, ulSize, ulSync;
|
|
uint32_t ulRdAddr = 0;
|
|
uint32_t ulClrAddr = 0;
|
|
|
|
DisableIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
PRINT_DBG("[%s]: Reembox %d\n", MBTAG, mbox);
|
|
st_in.reg = REG32(pxReeMboxChan->pxMboxChan->ulStatAddr);
|
|
ulRdAddr = pxReeMboxChan->pxMboxChan->ulRdAddr;
|
|
ulClrAddr = pxReeMboxChan->pxMboxChan->ulClrAddr;
|
|
if (st_in.reg == 0 || ulRdAddr == 0) {
|
|
PRINT_ERR("[%s] invalid mbox status or address!\n", MBTAG);
|
|
vClrMboxStats(ulClrAddr);
|
|
ClearPendingIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
EnableIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
return;
|
|
}
|
|
|
|
ulMbCmd = st_in.st.cmd;
|
|
ulSize = st_in.st.size;
|
|
ulSync = st_in.st.sync;
|
|
PRINT_DBG("[%s]: 0x%x, 0x%x, 0x%x, 0x%x\n", MBTAG,
|
|
(unsigned int)mbox,
|
|
(unsigned int)ulMbCmd,
|
|
(unsigned int)ulSize,
|
|
(unsigned int)ulSync);
|
|
|
|
if (ulMbCmd == 0) {
|
|
PRINT_DBG("[%s]:Err: mbox cmd is 0\n", MBTAG);
|
|
vClrMboxStats(ulClrAddr);
|
|
ClearPendingIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
EnableIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
return;
|
|
}
|
|
|
|
if (ulSize != 0)
|
|
vGetPayload(ulRdAddr, &mbInfo.mbdata, ulSize);
|
|
|
|
PRINT_DBG("%s taskid: 0x%llx\n", MBTAG, mbInfo.mbdata.taskid);
|
|
PRINT_DBG("%s complete: 0x%llx\n", MBTAG, mbInfo.mbdata.complete);
|
|
PRINT_DBG("%s ullclt: 0x%llx\n", MBTAG, mbInfo.mbdata.ullclt);
|
|
|
|
switch (ulSync) {
|
|
case MB_SYNC:
|
|
if (ulReeSyncTaskWake) {
|
|
PRINT("ulReeSyncTaskWake Busy\n");
|
|
break;
|
|
}
|
|
PRINT_DBG("[%s]: SYNC\n", MBTAG);
|
|
ulReeSyncTaskWake = 1;
|
|
mbInfo.ulCmd = ulMbCmd;
|
|
mbInfo.ulSize = ulSize;
|
|
pvMboxMemCpy(&syncReeMboxInfo, &mbInfo, sizeof(syncReeMboxInfo));
|
|
vTaskNotifyGiveFromISR(ReeMboxHandler, &xYieldRequired);
|
|
portYIELD_FROM_ISR(xYieldRequired);
|
|
break;
|
|
case MB_ASYNC:
|
|
#ifdef AO_MBOX_ONLY_SYNC
|
|
PRINT_ERR("[%s]: ASYNC no support\n", MBTAG);
|
|
vClrMboxStats(ulClrAddr);
|
|
ClearPendingIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
EnableIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
#endif
|
|
break;
|
|
default:
|
|
PRINT_ERR("[%s]: Not SYNC or ASYNC, Fail\n", MBTAG);
|
|
vClrMboxStats(ulClrAddr);
|
|
ClearPendingIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
EnableIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_MAILBOX_SEND
|
|
/* AOCPU to remote mailbox ACK handler */
|
|
static void vAoAckMboxHandler(uint32_t mbox)
|
|
{
|
|
uint32_t addr = ulRevAddrMbox(mbox);
|
|
struct mbHeadInfo mbHead;
|
|
BaseType_t xYieldRequired = pdFALSE;
|
|
|
|
DisableIrq(MAILBOX_AOCPU_REEACK_IRQ);
|
|
PRINT_DBG("[%s]: AO ACK handler, mboxid = %d\n", MBTAG,
|
|
(unsigned int)mbox);
|
|
xGetPayloadHead(addr, &mbHead);
|
|
if (mbHead.taskid)
|
|
vTaskNotifyGiveFromISR((TaskHandle_t)((uint32_t)mbHead.taskid), &xYieldRequired);
|
|
ClearPendingIrq(MAILBOX_AOCPU_REEACK_IRQ);
|
|
EnableIrq(MAILBOX_AOCPU_REEACK_IRQ);
|
|
portYIELD_FROM_ISR(xYieldRequired);
|
|
}
|
|
#endif
|
|
|
|
static void vReeSyncTask(void *pvParameters)
|
|
{
|
|
uint32_t ulWrAddr;
|
|
uint32_t ulClrAddr;
|
|
int index = 0;
|
|
|
|
(void)pvParameters;
|
|
ulWrAddr = pxReeMboxChan->pxMboxChan->ulWrAddr;
|
|
ulClrAddr = pxReeMboxChan->pxMboxChan->ulClrAddr;
|
|
|
|
while (1) {
|
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
PRINT_DBG("[%s]:ReeSyncTask\n", MBTAG);
|
|
|
|
index = mailbox_htbl_invokeCmd(g_tbl_ao, syncReeMboxInfo.ulCmd,
|
|
syncReeMboxInfo.mbdata.data);
|
|
PRINT_DBG("[%s]:mbox:%d\n", MBTAG, pxReeMboxChan->pxMboxChan->ucMboxChId);
|
|
if (index != 0) {
|
|
if (index == MAX_ENTRY_NUM) {
|
|
pvMboxMemSet(&syncReeMboxInfo.mbdata.data, 0,
|
|
sizeof(syncReeMboxInfo.mbdata.data));
|
|
syncReeMboxInfo.mbdata.status = ACK_FAIL;
|
|
if (ulWrAddr)
|
|
prvBuildPayload(ulWrAddr, &syncReeMboxInfo.mbdata,
|
|
sizeof(syncReeMboxInfo.mbdata));
|
|
PRINT_DBG("[%s]: undefine cmd or no callback\n", MBTAG);
|
|
} else {
|
|
PRINT_DBG("[%s]:ReeSync re len:%d\n", MBTAG,
|
|
sizeof(syncReeMboxInfo.mbdata));
|
|
syncReeMboxInfo.mbdata.status = ACK_OK;
|
|
if (ulWrAddr)
|
|
prvBuildPayload(ulWrAddr, &syncReeMboxInfo.mbdata,
|
|
sizeof(syncReeMboxInfo.mbdata));
|
|
}
|
|
}
|
|
|
|
vEnterCritical();
|
|
PRINT_DBG("[%s]:ReeSync clear mbox:%d\n", MBTAG,
|
|
pxReeMboxChan->pxMboxChan->ucMboxChId);
|
|
ulReeSyncTaskWake = 0;
|
|
vClrMboxStats(ulClrAddr);
|
|
ClearPendingIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
EnableIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
vExitCritical();
|
|
}
|
|
}
|
|
|
|
static void vMboxHandleReeIsr(void)
|
|
{
|
|
vAoRevReeMboxHandler(REE2AO_CHANNEL);
|
|
}
|
|
|
|
#ifdef CONFIG_MAILBOX_SEND
|
|
static void vMboxHandleReeAckIsr(void)
|
|
{
|
|
vAoAckMboxHandler(AO2REE_CHANNEL);
|
|
}
|
|
#endif
|
|
|
|
static void vMboxHandleTeeIsr(void)
|
|
{
|
|
vAoRevTeeMboxHandler(TEE2AO_CHANNEL);
|
|
}
|
|
|
|
int iMboxInit(void)
|
|
{
|
|
int ret;
|
|
|
|
PRINT("[%s]: mbox pl init\n", MBTAG);
|
|
mailbox_htbl_init(&g_tbl_ao);
|
|
iMboxClientIdTabInit(&pvClientIdTab);
|
|
|
|
/* Request mailbox channel for remote core to AOCPU */
|
|
pxReeMboxChan = xMboxRequestChan(REE2AO_DRV);
|
|
pxTeeMboxChan = xMboxRequestChan(TEE2AO_DRV);
|
|
|
|
/* Register and enable mailbox IRQ */
|
|
RegisterIrq(MAILBOX_AOCPU_REE_IRQ, 6, vMboxHandleReeIsr);
|
|
RegisterIrq(MAILBOX_AOCPU_TEE_IRQ, 6, vMboxHandleTeeIsr);
|
|
#ifdef CONFIG_MAILBOX_SEND
|
|
RegisterIrq(MAILBOX_AOCPU_REEACK_IRQ, 6, vMboxHandleReeAckIsr);
|
|
EnableIrq(MAILBOX_AOCPU_REEACK_IRQ);
|
|
#endif
|
|
EnableIrq(MAILBOX_AOCPU_REE_IRQ);
|
|
EnableIrq(MAILBOX_AOCPU_TEE_IRQ);
|
|
|
|
xTaskCreate(vTeeSyncTask, "AoTeeSyncTask", configMINIMAL_STACK_SIZE, 0,
|
|
MHU_MB_TASK_PRIORITIES, (TaskHandle_t *)&TeeMboxHandler);
|
|
|
|
xTaskCreate(vReeSyncTask, "AoReeSyncTask", configMINIMAL_STACK_SIZE, 0,
|
|
MHU_MB_TASK_PRIORITIES, (TaskHandle_t *)&ReeMboxHandler);
|
|
|
|
#ifdef CONFIG_MAILBOX_SEND
|
|
vInitMboxChLock();
|
|
#endif
|
|
ret = vRpcUserCmdInit();
|
|
PRINT("[%s]: mbox pl init end\n", MBTAG);
|
|
return ret;
|
|
}
|
|
|
|
#ifdef CONFIG_MAILBOX_SEND
|
|
int iMboxTransData(struct xClientMboxChan *pxChan, struct xMboxData *pxData)
|
|
{
|
|
struct mboxData xMboxData;
|
|
uint32_t ulSize;
|
|
union MbStat_in xMboxStatIn;
|
|
struct MbStat *pxMboxStat;
|
|
uint32_t ulVal = 0;
|
|
uint8_t ucChId;
|
|
uint8_t ucClientId;
|
|
int iRet = 0;
|
|
|
|
ucClientId = pxChan->ucClientChId;
|
|
ucChId = pxChan->pxMboxChan->ucMboxChId;
|
|
SEND_VALID_CHANNEL(ucChId);
|
|
PRINT_DBG("[%s]: mboxid = %ld\n", MBTAG, ucChId);
|
|
PRINT_DBG("[%s]: cmd = 0x%x\n", MBTAG, (unsigned int)pxData->ulCmd);
|
|
PRINT_DBG("[%s]: set_addr = 0x%x\n", MBTAG,
|
|
(unsigned int)pxChan->pxMboxChan->ulSetAddr);
|
|
|
|
xMuteLock(pxChan->pxMboxChan->xLock);
|
|
ulSize = pxData->ucTxSize + sizeof(struct mbHeadInfo);
|
|
pxMboxStat = &xMboxStatIn.st;
|
|
pxMboxStat->cmd = pxData->ulCmd;
|
|
pxMboxStat->size = ulSize;
|
|
pxMboxStat->sync = MB_ASYNC;
|
|
strncpy((char *)xMboxData.data, pxData->pvTxbuf, pxData->ucTxSize);
|
|
xMboxData.taskid = (uint32_t)(void *)xTaskGetCurrentTaskHandle();
|
|
xMboxData.status = ucClientId;
|
|
xMboxData.complete = 0;
|
|
prvBuildPayload(pxChan->pxMboxChan->ulWrAddr, &xMboxData, ulSize);
|
|
PRINT_DBG("[%s]: set command 0x%x\n", MBTAG, pxMboxStat->cmd);
|
|
vSetMboxStats(pxChan->pxMboxChan->ulSetAddr, xMboxStatIn.st);
|
|
ulVal = ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(3000));
|
|
if (ulVal == 0) {
|
|
PRINT_ERR("[%s]: mailbox transfer message time out!\n", MBTAG);
|
|
xMboxData.taskid = 0;
|
|
xMboxData.status = 0;
|
|
prvBuildPayload(pxChan->pxMboxChan->ulWrAddr, &xMboxData, ulSize);
|
|
xMboxStatIn.reg = 0;
|
|
vSetMboxStats(pxChan->pxMboxChan->ulSetAddr, xMboxStatIn.st);
|
|
iRet = ERR_MBOX(ETIME);
|
|
} else {
|
|
PRINT_DBG("[%s]: task wait ACK done\n", MBTAG);
|
|
iRet = pdTRUE;
|
|
}
|
|
xMuteUnlock(pxChan->pxMboxChan->xLock);
|
|
|
|
return iRet;
|
|
}
|
|
#endif
|