307 lines
6.0 KiB
C
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;
|
|
}
|
|
|