/* * Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved. * * SPDX-License-Identifier: MIT */ #include #include #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; }