/* * Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved. * * SPDX-License-Identifier: MIT */ #ifndef __MAIL_IN_H__ #define __MAIL_IN_H__ #include "mailbox.h" #include "mailbox-api.h" #include "gcc_compiler_attributes.h" #define UNUSED(x) ((void)(x)) #define ACK_OK 1 #define ACK_FAIL 2 #define MHU_MB_STK_SIZE 2048 #define QUEUE_LENGTH 20 #define TASK_POOL_SIZE 3 #define MAILBOX_BUFFER_SIZE MHU_MAX_SIZE #define MAILBOX_CMD_MAX 0xFFFF #define PRINT_DBG(...) //printf(__VA_ARGS__) #define aml_writel32(val, reg) (REG32(reg) = val) #define aml_readl32(reg) (REG32(reg)) #ifndef MAILBOX_DSPA2AO #define MAILBOX_DSPA2AO 0xc #endif #ifndef MAILBOX_AO2DSPA #define MAILBOX_AO2DSPA 0xd #endif enum sync_type { MB_ASYNC = 1, MB_SYNC, }; struct MbStat { uint32_t cmd : 16; uint32_t size : 9; uint32_t sync : 7; }; union MbStat_in { struct MbStat st; uint32_t reg; }; struct __packed mbHeadInfo { uint32_t status; uint64_t taskid; uint64_t complete; uint64_t ullclt; }; struct __packed mboxData { uint32_t status; uint64_t taskid; uint64_t complete; uint64_t ullclt; uint8_t data[MHU_DATA_SIZE]; }; struct __packed mbPackInfo { struct mboxData mbdata; // hack to pass more data uint32_t ulCmd; uint32_t ulSize; uint32_t ulChan; }; #define VALID_CMD_SIZE(cmd, size) \ configASSERT(cmd <= MAILBOX_CMD_MAX && size <= MAILBOX_BUFFER_SIZE) #define VALID_CHANNEL(chan) \ configASSERT(chan == AOREE_CHANNEL || chan == AOTEE_CHANNEL || chan == AODSPA_CHANNEL) #define VALID_BUFFER_SIZE(size) configASSERT(size <= MAILBOX_BUFFER_SIZE) static inline struct MbStat xGetMboxStats(uint32_t reg) { union MbStat_in stat; stat.reg = aml_readl32(reg); return stat.st; } static inline void vSetMboxStats(uint32_t reg, struct MbStat st) { union MbStat_in stat; stat.st = st; aml_writel32(stat.reg, reg); } static inline void vClrMboxStats(uint32_t reg) { aml_writel32(0xFFFFFFFF, reg); } static inline uint32_t xGetChan(uint32_t mbox) { switch (mbox) { case MAILBOX_ARMREE2AO: return AOREE_CHANNEL; case MAILBOX_ARMTEE2AO: return AOTEE_CHANNEL; case MAILBOX_DSPA2AO: return AODSPA_CHANNEL; default: configASSERT(0); } } static inline uint32_t xGetRevMbox(uint32_t ulChan) { switch (ulChan) { case AOREE_CHANNEL: return MAILBOX_ARMREE2AO; case AOTEE_CHANNEL: return MAILBOX_ARMTEE2AO; case AODSPA_CHANNEL: return MAILBOX_DSPA2AO; default: configASSERT(0); } } static inline uint32_t xGetSendMbox(uint32_t ulChan) { switch (ulChan) { case AODSPA_CHANNEL: return MAILBOX_AO2DSPA; case AOREE_CHANNEL: case AOTEE_CHANNEL: default: configASSERT(0); } return 0; } static inline uint32_t xDspRevAddr(uint32_t ulChan) { switch (ulChan) { case AOREE_CHANNEL: case AOTEE_CHANNEL: case AODSPA_CHANNEL: return PAYLOAD_RD_BASE(xGetRevMbox(ulChan)); default: configASSERT(0); } } static inline uint32_t xSendAddr(uint32_t ulChan) { switch (ulChan) { case AOREE_CHANNEL: case AOTEE_CHANNEL: case AODSPA_CHANNEL: return PAYLOAD_WR_BASE(xGetSendMbox(ulChan)); default: configASSERT(0); } } /*send back for sync api*/ static inline uint32_t xSendAddrBack(uint32_t ulChan) { switch (ulChan) { case AOREE_CHANNEL: case AOTEE_CHANNEL: case AODSPA_CHANNEL: return PAYLOAD_RD_BASE(xGetSendMbox(ulChan)); default: configASSERT(0); } } static inline uint32_t xRevAddrMbox(uint32_t mbox) { return PAYLOAD_RD_BASE(mbox); } static inline uint32_t xSendAddrMbox(uint32_t mbox) { return PAYLOAD_WR_BASE(mbox); } static inline void MbWrite(uint32_t to, void *from, long count) { int i = 0; int len = count / 4 + ((count % 4) ? 1 : 0); uint32_t *p = from; PRINT_DBG("vMbWrite Count: 0x%x, len: 0x%x\n", count, len); while (len > 0) { aml_writel32(p[i], to + (4 * i)); PRINT_DBG("write: 0x%x\n", REG32(to + 4 * i + 0x800)); len--; i++; } } static inline void MbRead(void *to, uint32_t from, long count) { int i = 0; int len = count / 4 + ((count % 4) ? 1 : 0); uint32_t *p = to; PRINT_DBG("vMbRead Count:0x%x, len: 0x%x\n", count, len); while (len > 0) { p[i] = aml_readl32(from + (4 * i)); PRINT_DBG("read: 0x%x\n", p[i]); len--; i++; } } static inline void xGetPayloadHead(uint32_t addr, void *head) { struct mbHeadInfo *phead = head; MbRead(&phead->status, addr, 0x4); MbRead(&phead->taskid, addr + 0x4, 0x8); MbRead(&phead->complete, addr + 0xc, 0x8); MbRead(&phead->ullclt, addr + 0x14, 0x8); } static inline void xBuildPayloadHead(uint32_t addr, void *head) { struct mbHeadInfo *phead = head; MbWrite(addr, &phead->status, 0x4); MbWrite(addr + 0x4, &phead->taskid, 0x8); MbWrite(addr + 0xc, &phead->complete, 0x8); MbWrite(addr + 0x14, &phead->ullclt, 0x8); } static inline void vGetPayload(uint32_t addr, void *data, size_t size) { VALID_BUFFER_SIZE(size); PRINT_DBG("%s addr:0x%x\n", __func__, addr); if (data != NULL) MbRead(data, addr, size); } static inline void vBuildPayload(uint32_t addr, void *data, size_t size) { VALID_BUFFER_SIZE(size); PRINT_DBG("%s addr:0x%x\n", __func__, addr); if (data != NULL) MbWrite(addr, data, size); } static inline void vReBuildPayload(uint32_t addr, void *data, size_t size) { VALID_BUFFER_SIZE(size); PRINT_DBG("%s addr:0x%x\n", __func__, addr); if (data != NULL) { MbWrite(addr, 0, MAILBOX_BUFFER_SIZE); MbWrite(addr, data, size); } } #endif