Files
2026-08-24 10:03:24 +08:00

307 lines
6.0 KiB
C

/*
* Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved.
*
* SPDX-License-Identifier: MIT
*/
#include <stdlib.h>
#include <string.h>
#include "FreeRTOS.h"
#include "common.h"
#include "queue.h"
#include "semphr.h"
#include "mailbox-common.h"
#include "mailbox-htbl.h"
#define MBTAG "AOCPU"
#define PRINT_ERR(...) printf(__VA_ARGS__)
#define PRINT_DBG(...) //printf(__VA_ARGS__)
static QueueHandle_t xClientTabLock;
void vEnterCritical(void)
{
taskENTER_CRITICAL();
}
void vExitCritical(void)
{
taskEXIT_CRITICAL();
}
void vSetMboxStats(uint32_t reg, struct MbStat st)
{
union MbStat_in stat;
stat.st = st;
aml_writel32(stat.reg, reg);
}
void vClrMboxStats(uint32_t reg)
{
aml_writel32(0xFFFFFFFF, reg);
}
static uint32_t ulGetMboxChanNums(struct xMboxChan *pxMboxChan)
{
uint32_t ulChanNum = 0;
int iIdx;
for (iIdx = 0; pxMboxChan[iIdx].ucMboxChId != 0; iIdx++)
ulChanNum++;
return ulChanNum;
}
static uint32_t ulGetMboxIdNums(struct xMboxIdTab *pxMboxIdTab)
{
uint32_t ulIdNum = 0;
int iIdx;
for (iIdx = 0; pxMboxIdTab[iIdx].ucMboxChId != 0; iIdx++)
ulIdNum++;
return ulIdNum;
}
struct xMboxChan *xGetMboxChan(uint8_t ucClientChId)
{
uint32_t iIdx;
uint8_t ucMboxChId = MBOX_CH_ID_UNDEFINED;
struct xMboxChan *pxChan = NULL;
uint32_t ulChanNums;
uint32_t ulIdNums;
ulIdNums = ulGetMboxIdNums(pxMboxIdTabs);
for (iIdx = 0; iIdx < ulIdNums; iIdx++) {
if (pxMboxIdTabs[iIdx].ucClientChId == ucClientChId) {
ucMboxChId = pxMboxIdTabs[iIdx].ucMboxChId;
break;
}
}
if (iIdx == ulIdNums) {
PRINT_ERR("[%s]: Can't find mbox driver ID!\n", MBTAG);
return NULL;
}
ulChanNums = ulGetMboxChanNums(pxMboxChans);
for (iIdx = 0; iIdx < ulChanNums; iIdx++) {
if (pxMboxChans[iIdx].ucMboxChId == ucMboxChId) {
pxChan = &pxMboxChans[iIdx];
break;
}
}
if (iIdx == ulChanNums) {
PRINT_ERR("[%s]: Can't find mbox channel ID!\n", MBTAG);
return NULL;
}
return pxChan;
}
struct xMboxChan *xGetMboxChanById(uint8_t ucMboxChId)
{
uint32_t iIdx;
struct xMboxChan *pxChan = NULL;
uint32_t ulChanNums;
ulChanNums = ulGetMboxChanNums(pxMboxChans);
for (iIdx = 0; iIdx < ulChanNums; iIdx++) {
if (pxMboxChans[iIdx].ucMboxChId == ucMboxChId) {
pxChan = &pxMboxChans[iIdx];
break;
}
}
if (iIdx == ulChanNums) {
PRINT_ERR("[%s]: get mbox chan id fail!\n", MBTAG);
return NULL;
}
return pxChan;
}
/* Get mailbox data receive address */
uint32_t ulRevAddrMbox(uint8_t ucMboxChId)
{
uint32_t reg;
struct xMboxChan *pxChan;
pxChan = xGetMboxChanById(ucMboxChId);
if (pxChan) {
reg = pxChan->ulRdAddr;
} else {
reg = 0;
PRINT_ERR("[%s]: get mbox rev addr fail!\n", MBTAG);
}
return reg;
}
void vMboxWrite(uint32_t to, void *from, long count)
{
int i = 0;
int len = count / 4 + ((count % 4) ? 1 : 0);
uint32_t *p = from;
PRINT_DBG("%s Count: 0x%lx, len: %d\n", __func__, count, len);
while (len > 0) {
aml_writel32(p[i], to + (4 * i));
PRINT_DBG("reg: 0x%x\n", REG32(to + 4 * i + 0x800));
len--;
i++;
}
}
void vMboxRead(void *to, uint32_t from, long count)
{
int i = 0;
int len = count / 4 + ((count % 4) ? 1 : 0);
uint32_t *p = to;
PRINT_DBG("%s Count:0x%lx, len: %d\n", __func__, count, len);
while (len > 0) {
p[i] = aml_readl32(from + (4 * i));
PRINT_DBG("p: 0x%x\n", p[i]);
len--;
i++;
}
}
void *pvMboxMemSet(void *pDst, int iVal, size_t xCnt)
{
char *pcVal = pDst;
while (xCnt--)
*pcVal++ = (char)iVal;
return pDst;
}
void *pvMboxMemCpy(void *pDst, const void *pSrc, size_t xLen)
{
const char *pcSrc = pSrc;
char *pcDst = pDst;
while (xLen--)
*pcDst++ = *pcSrc++;
return pDst;
}
void xGetPayloadHead(uint32_t addr, void *head)
{
struct mbHeadInfo *phead = head;
vMboxRead(&phead->status, addr, 0x4);
vMboxRead(&phead->taskid, addr + 0x4, 0x8);
vMboxRead(&phead->complete, addr + 0xc, 0x8);
vMboxRead(&phead->ullclt, addr + 0x14, 0x8);
}
uint32_t ulChkHtblInit(void *pHtbl)
{
struct entry *pTable = pHtbl;
uint32_t ulTabLen;
ulTabLen = pTable->tabLen;
if (ulTabLen == MAX_ENTRY_NUM)
return 0;
else
return 1;
}
int iMboxClientIdTabInit(void **pTab)
{
uint8_t *pucTab = NULL;
size_t xSize;
xSize = sizeof(uint8_t) * MBOX_CL_ID_TAB_LEN;
pucTab = malloc(xSize);
if (pucTab == NULL)
return ERR_MBOX(ENOMEM);
pvMboxMemSet(pucTab, MBOX_CH_ID_UNDEFINED, xSize);
*pTab = pucTab;
xClientTabLock = xMutexInit();
return 0;
}
#ifdef CONFIG_MAILBOX_SEND
void vInitMboxChLock(void)
{
struct xMboxChan *pxChan;
pxChan = xGetMboxChanById(AO2REE_CHANNEL);
pxChan->xLock = xMutexInit();
#ifdef DSPA2AO_CHANNEL
pxChan = xGetMboxChanById(AO2DSPA_CHANNEL);
pxChan->xLock = xMutexInit();
#endif
}
#endif
BaseType_t xRegMboxClientChId(uint8_t ucClientChId)
{
uint8_t *pucTab = pvClientIdTab;
int iIdx;
if (pucTab == NULL) {
PRINT_ERR("[%s]: client ID table uninitialized!\n", MBTAG);
return ERR_MBOX(EINVAL);
}
/* Check if this ucClientChId is already registered */
xMuteLock(xClientTabLock);
for (iIdx = 0; iIdx < MBOX_CL_ID_TAB_LEN; iIdx++) {
if (pucTab[iIdx] == ucClientChId) {
PRINT_ERR("[%s]: client ID 0x%x is already registered!\n",
MBTAG, ucClientChId);
xMuteUnlock(xClientTabLock);
return ERR_MBOX(EINVAL);
}
}
/* Check if client ID table is full */
for (iIdx = 0; iIdx < MBOX_CL_ID_TAB_LEN; iIdx++) {
if (pucTab[iIdx] == MBOX_CH_ID_UNDEFINED)
break;
}
if (iIdx == MBOX_CL_ID_TAB_LEN) {
PRINT_ERR("[%s]: client ID table is full!\n", MBTAG);
xMuteUnlock(xClientTabLock);
return ERR_MBOX(ENOMEM);
}
pucTab[iIdx] = ucClientChId;
xMuteUnlock(xClientTabLock);
return 0;
}
BaseType_t xFreeMboxClientChId(uint8_t ucClientChId)
{
uint8_t *pucTab = pvClientIdTab;
int iIdx;
if (pucTab == NULL) {
PRINT_ERR("[%s]: client ID table uninitialized!\n", MBTAG);
return ERR_MBOX(EINVAL);
}
for (iIdx = 0; iIdx < MBOX_CL_ID_TAB_LEN; iIdx++) {
if (pucTab[iIdx] == ucClientChId) {
pucTab[iIdx] = MBOX_CH_ID_UNDEFINED;
break;
}
}
if (iIdx == MBOX_CL_ID_TAB_LEN) {
PRINT_ERR("[%s]: client ID 0x%x is not registered!\n",
MBTAG, ucClientChId);
return ERR_MBOX(EINVAL);
}
return 0;
}