diff --git a/support/platform/include/dmac_core.h b/support/platform/include/dmac_core.h index 4e4eab4a7acc7c01cb8f221721cdbef861133a11..2f852574bc4c2dd9df61e3c2828ae240f6184127 100644 --- a/support/platform/include/dmac_core.h +++ b/support/platform/include/dmac_core.h @@ -13,9 +13,9 @@ #include "hdf_device.h" #include "hdf_device_desc.h" #include "hdf_object.h" +#include "los_event.h" #include "osal_mutex.h" #include "osal_spinlock.h" -#include "los_event.h" #ifdef __cplusplus #if __cplusplus @@ -23,114 +23,185 @@ extern "C" { #endif #endif /* __cplusplus */ -typedef void DmacCallback(void *callbackData, int status); -typedef EVENT_CB_S DmacEvent; +#define PERIPH_ADDR_INVALID 0xfff +#define DMAC_CHAN_NUM_MAX 100 -#define DmaEventInit(event) LOS_EventInit(event) -#define DmaEventSignal(event, bit) LOS_EventWrite(event, bit) +#define DmaEventInit(event) LOS_EventInit(event) +#define DmaEventSignal(event, bit) LOS_EventWrite(event, bit) #define DmaEventWait(event, bit, timeout) LOS_EventRead(event, bit, LOS_WAITMODE_OR + LOS_WAITMODE_CLR, timeout) +typedef void DmacCallback(void *callbackData, int status); +typedef EVENT_CB_S DmacEvent; + /* definition for the return value */ -#define DMAC_ERROR_BASE 0x100 -#define DMAC_CHANNEL_INVALID ((DMAC_ERROR_BASE) + 1) -#define DMAC_TRXFERSIZE_INVALID ((DMAC_ERROR_BASE) + 2) -#define DMAC_SOURCE_ADDRESS_INVALID ((DMAC_ERROR_BASE) + 3) -#define DMAC_DESTINATION_ADDRESS_INVALID ((DMAC_ERROR_BASE) + 4) -#define DMAC_MEMORY_ADDRESS_INVALID ((DMAC_ERROR_BASE) + 5) -#define DMAC_PERIPHERAL_ID_INVALID ((DMAC_ERROR_BASE) + 6) -#define DMAC_DIRECTION_ERROR ((DMAC_ERROR_BASE) + 7) -#define DMAC_TRXFER_ERROR ((DMAC_ERROR_BASE) + 8) -#define DMAC_LLIHEAD_ERROR ((DMAC_ERROR_BASE) + 9) -#define DMAC_SWIDTH_ERROR ((DMAC_ERROR_BASE) + 0xa) -#define DMAC_LLI_ADDRESS_INVALID ((DMAC_ERROR_BASE) + 0xb) -#define DMAC_TRANS_CONTROL_INVALID ((DMAC_ERROR_BASE) + 0xc) -#define DMAC_MEMORY_ALLOCATE_ERROR ((DMAC_ERROR_BASE) + 0xd) -#define DMAC_NOT_FINISHED ((DMAC_ERROR_BASE) + 0xe) -#define DMAC_TIMEOUT ((DMAC_ERROR_BASE) + 0xf) -#define DMAC_CHN_SUCCESS ((DMAC_ERROR_BASE) + 0x10) -#define DMAC_CHN_ERROR ((DMAC_ERROR_BASE) + 0x11) -#define DMAC_CHN_TIMEOUT ((DMAC_ERROR_BASE) + 0x12) -#define DMAC_CHN_ALLOCAT ((DMAC_ERROR_BASE) + 0x13) -#define DMAC_CHN_VACANCY ((DMAC_ERROR_BASE) + 0x14) - -#define DMA_EVENT_WAIT_DEF_TIME ((LOSCFG_BASE_CORE_TICK_PER_SECOND) * 5) -#define DMAC_EVENT_DONE 0x1 -#define DMAC_EVENT_ERROR 0x2 - -#define TRASFER_TYPE_M2M 0x0 -#define TRASFER_TYPE_P2M 0x1 -#define TRASFER_TYPE_M2P 0x2 -#define PERIPHERALID_INVILD 0xfff - -#define DMAC_CHAN_NUM_MAX 100 +enum DmacErrorNumber { + DMAC_ERROR_BASE = 0x100, + DMAC_CHANNEL_INVALID = DMAC_ERROR_BASE + 1, + DMAC_TRXFERSIZE_INVALID = DMAC_ERROR_BASE + 2, + DMAC_SOURCE_ADDRESS_INVALID = DMAC_ERROR_BASE + 3, + DMAC_DESTINATION_ADDRESS_INVALID = DMAC_ERROR_BASE + 4, + DMAC_MEMORY_ADDRESS_INVALID = DMAC_ERROR_BASE + 5, + DMAC_PERIPHERAL_ID_INVALID = DMAC_ERROR_BASE + 6, + DMAC_DIRECTION_ERROR = DMAC_ERROR_BASE + 7, + DMAC_TRXFER_ERROR = DMAC_ERROR_BASE + 8, + DMAC_LLIHEAD_ERROR = DMAC_ERROR_BASE + 9, + DMAC_SWIDTH_ERROR = DMAC_ERROR_BASE + 0xa, + DMAC_LLI_ADDRESS_INVALID = DMAC_ERROR_BASE + 0xb, + DMAC_TRANS_CONTROL_INVALID = DMAC_ERROR_BASE + 0xc, + DMAC_MEMORY_ALLOCATE_ERROR = DMAC_ERROR_BASE + 0xd, + DMAC_NOT_FINISHED = DMAC_ERROR_BASE + 0xe, + DMAC_TIMEOUT = DMAC_ERROR_BASE + 0xf, + DMAC_CHN_SUCCESS = DMAC_ERROR_BASE + 0x10, + DMAC_CHN_ERROR = DMAC_ERROR_BASE + 0x11, + DMAC_CHN_TIMEOUT = DMAC_ERROR_BASE + 0x12, + DMAC_CHN_ALLOCAT = DMAC_ERROR_BASE + 0x13, + DMAC_CHN_VACANCY = DMAC_ERROR_BASE + 0x14, +}; + +enum DmacEvent { + DMAC_EVENT_DONE = 0x1, + DMAC_EVENT_ERROR = 0x2, +}; +#define DMA_EVENT_WAIT_DEF_TIME ((LOSCFG_BASE_CORE_TICK_PER_SECOND) * 5) + +enum DmacTransferType { + TRASFER_TYPE_M2M = 0x0, + TRASFER_TYPE_P2M = 0x1, + TRASFER_TYPE_M2P = 0x2, +}; struct DmacMsg { - UINTPTR srcAddr; - UINTPTR destAddr; - unsigned int transferSize; - unsigned int direct; /* 0: mem to mem; 1: periph to mem; 2:mem to periph */ + uintptr_t srcAddr; + uintptr_t destAddr; + uint8_t srcWidth; // src data width in bytes + uint8_t destWidth; // dest data width in bytes + uint8_t transType; // 0: mem to mem; 1: periph to mem; 2:mem to periph + size_t transLen; DmacCallback *cb; void *para; }; -/* structure for LLI */ +static inline uintptr_t DmacMsgGetPeriphAddr(struct DmacMsg *msg) +{ + return (msg->transType == TRASFER_TYPE_M2P) ? msg->destAddr : + (msg->transType == TRASFER_TYPE_P2M) ? msg->srcAddr : PERIPH_ADDR_INVALID; +} + +#define DMAC_LLI_HEAD \ + uintptr_t nextLli; \ + uintptr_t reserved0[6]; \ + unsigned long count; \ + uintptr_t srcAddr; \ + uintptr_t reserved1; \ + uintptr_t destAddr; \ + uintptr_t reserved2; \ + unsigned long config; + +struct DmacLliHead { + DMAC_LLI_HEAD +}; +#define DMAC_LLI_HEAD_SIZE (sizeof(struct DmacLliHead)) + +#define DMAC_LLI_SIZE 64 // must be 64 Bytes aligned struct DmacLli { - /* must be 64Byte aligned */ - long long nextLli; - unsigned int reserved[5]; - unsigned int count; - long long srcAddr; - long long destAddr; - unsigned int config; - unsigned int pad[51]; + DMAC_LLI_HEAD + uint8_t pad[DMAC_LLI_SIZE - DMAC_LLI_HEAD_SIZE]; }; struct DmacChanInfo { - unsigned int channel; - unsigned int status; - unsigned int useStatus; - unsigned int transferType; - unsigned int width; - unsigned int config; - long long lliEnFlag; + uint16_t channel; + int status; + int useStatus; + int transType; + uint8_t srcWidth; // src data width in bytes + uint8_t destWidth; // dest data width in bytes + unsigned long config; // cpu width expected + uintptr_t lliEnFlag; DmacEvent waitEvent; DmacCallback *callback; void *callbackData; - unsigned int lliCnt; + uint16_t lliCnt; struct DmacLli *lli; + void *dummyPage; }; struct DmaCntlr { struct IDeviceIoService service; struct HdfDeviceObject *device; - unsigned int index; - unsigned int irq; - unsigned int phyBase; - char *remapBase; - unsigned int regSize; - unsigned int maxTransSize; - unsigned int channelNum; + uint16_t index; + uint32_t irq; + uintptr_t phyBase; + volatile unsigned char *remapBase; + size_t regSize; + size_t maxTransSize; + uint16_t channelNum; OsalSpinlock lock; struct DmacChanInfo *channelList; - int (*getChanInfo)(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo, unsigned int periphAddr); - int (*dmaChanEnable)(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo); - int (*dmaM2mChanEnable)(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo, - UINTPTR src, UINTPTR dest, unsigned int length); - void (*dmacChanDisable)(struct DmaCntlr *cntlr, unsigned int channel); - void (*dmacCacheInv)(UINTPTR addr, UINTPTR end); - void (*dmacCacheFlush)(UINTPTR addr, UINTPTR end); - void *(*dmacPaddrToVaddr)(long long paddr); - unsigned long (*dmacVaddrToPaddr)(void *vaddr); - unsigned int (*dmacGetChanStatus)(struct DmaCntlr *cntlr, unsigned int chan); - unsigned int (*dmacGetCurrDestAddr)(struct DmaCntlr *cntlr, unsigned int chan); + int32_t (*getChanInfo)(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo, struct DmacMsg *msg); + int32_t (*dmaChanEnable)(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo); + int32_t (*dmaM2mChanEnable)(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo, + uintptr_t src, uintptr_t dest, size_t length); + void (*dmacChanDisable)(struct DmaCntlr *cntlr, uint16_t channel); + void (*dmacCacheInv)(uintptr_t vaddr, uintptr_t vend); + void (*dmacCacheFlush)(uintptr_t vaddr, uintptr_t vend); + void *(*dmacPaddrToVaddr)(uintptr_t paddr); + uintptr_t (*dmacVaddrToPaddr)(void *vaddr); + int (*dmacGetChanStatus)(struct DmaCntlr *cntlr, uint16_t chan); + uintptr_t (*dmacGetCurrDestAddr)(struct DmaCntlr *cntlr, uint16_t chan); void *private; }; +#ifdef LOSCFG_DRIVERS_HDF_PLATFORM_DMAC struct DmaCntlr *DmaCntlrCreate(struct HdfDeviceObject *dev); + void DmaCntlrDestroy(struct DmaCntlr *cntlr); + +int32_t DmacCntlrAdd(struct DmaCntlr *cntlr); + +void DmacCntlrRemove(struct DmaCntlr *cntlr); + int32_t DmaCntlrTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg); -int DmacInit(struct DmaCntlr *cntlr); -unsigned int DmaGetCurrChanDestAddr(struct DmaCntlr *cntlr, unsigned int chan); + +uintptr_t DmaGetCurrChanDestAddr(struct DmaCntlr *cntlr, uint16_t chan); +#else +static inline struct DmaCntlr *DmaCntlrCreate(struct HdfDeviceObject *dev) +{ + (void)dev; + return NULL; +} + +static inline void DmaCntlrDestroy(struct DmaCntlr *cntlr) +{ + (void)cntlr; + return; +} + +static inline int32_t DmacCntlrAdd(struct DmaCntlr *cntlr) +{ + (void)cntlr; + return HDF_ERR_NOT_SUPPORT; +} + +static inline void DmacCntlrRemove(struct DmaCntlr *cntlr) +{ + (void)cntlr; + return; +} + +static inline int32_t DmaCntlrTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg) +{ + (void)cntlr; + (void)msg; + return HDF_ERR_NOT_SUPPORT; +} + +static inline uintptr_t DmaGetCurrChanDestAddr(struct DmaCntlr *cntlr, uint16_t chan) +{ + (void)cntlr; + (void)chan; + return 0; +} +#endif #ifdef __cplusplus #if __cplusplus diff --git a/support/platform/src/dmac_core.c b/support/platform/src/dmac_core.c index b2b207b4c2696000d1129cc671c10ca5071dddda..c5d529f0bd4317fb1b935ea7e446f85ef4626d3f 100644 --- a/support/platform/src/dmac_core.c +++ b/support/platform/src/dmac_core.c @@ -18,21 +18,94 @@ #define DMA_ALIGN_SIZE 256 #define DMA_MAX_TRANS_SIZE_DEFAULT 256 -static int DmacCheck(struct DmaCntlr *cntlr) +static int32_t DmacCntlrCheckOps(struct DmaCntlr *cntlr) { - if (cntlr == NULL || - cntlr->channelNum == 0 || - cntlr->dmacGetChanStatus == NULL || - cntlr->dmacCacheFlush == NULL || - cntlr->dmacCacheInv == NULL || - cntlr->dmaM2mChanEnable == NULL || - cntlr->dmacPaddrToVaddr == NULL || - cntlr->dmaChanEnable == NULL || - cntlr->dmacVaddrToPaddr == NULL || - cntlr->getChanInfo == NULL || - cntlr->dmacChanDisable == NULL || - cntlr->dmacGetCurrDestAddr == NULL) { - return HDF_FAILURE; + if (cntlr->getChanInfo == NULL) { + HDF_LOGE("%s: getChanInfo is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->dmaChanEnable == NULL) { + HDF_LOGE("%s: dmaChanEnable is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->dmaM2mChanEnable == NULL) { + HDF_LOGE("%s: dmaM2mChanEnable is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->dmacChanDisable == NULL) { + HDF_LOGE("%s: dmacChanDisable is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->dmacCacheInv == NULL) { + HDF_LOGE("%s: dmacCacheInv null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->dmacCacheFlush == NULL) { + HDF_LOGE("%s: dmacCacheFlush null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->dmacPaddrToVaddr == NULL) { + HDF_LOGE("%s: dmacPaddrToVaddr null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->dmacVaddrToPaddr == NULL) { + HDF_LOGE("%s: dmacVaddrToPaddr null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->dmacGetChanStatus == NULL) { + HDF_LOGE("%s: dmacGetChanStatus null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->dmacGetCurrDestAddr == NULL) { + HDF_LOGE("%s: dmacGetCurrDestAddr null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + return HDF_SUCCESS; +} + +static int32_t DmacCntlrCheckParam(struct DmaCntlr *cntlr) +{ + if (cntlr == NULL) { + HDF_LOGE("%s: cntlr is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->maxTransSize == 0) { + HDF_LOGE("%s: cntlr is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + if (cntlr->channelNum == 0 || cntlr->channelNum > DMAC_CHAN_NUM_MAX) { + HDF_LOGE("%s: invalid channelNum:%u", __func__, cntlr->channelNum); + return HDF_ERR_INVALID_OBJECT; + } + return HDF_SUCCESS; +} + +static int32_t DmacCntlrCheckInit(struct DmaCntlr *cntlr) +{ + int32_t ret; + + ret = DmacCntlrCheckParam(cntlr); + if (ret != HDF_SUCCESS) { + return ret; + } + ret = DmacCntlrCheckOps(cntlr); + if (ret != HDF_SUCCESS) { + return ret; + } + return HDF_SUCCESS; +} + +static int32_t DmacCntlrCheck(struct DmaCntlr *cntlr) +{ + int32_t ret; + + ret = DmacCntlrCheckInit(cntlr); + if (ret != HDF_SUCCESS) { + return ret; + } + if (cntlr->channelList == NULL) { + HDF_LOGE("%s: channelList is null", __func__); + return HDF_ERR_INVALID_OBJECT; } return HDF_SUCCESS; } @@ -46,7 +119,6 @@ struct DmaCntlr *DmaCntlrCreate(struct HdfDeviceObject *device) } cntlr = (struct DmaCntlr *)OsalMemCalloc(sizeof(struct DmaCntlr)); if (cntlr == NULL) { - HDF_LOGE("service malloc fail!\n"); return NULL; } cntlr->device = device; @@ -55,7 +127,7 @@ struct DmaCntlr *DmaCntlrCreate(struct HdfDeviceObject *device) static void DmacFreeLli(struct DmacChanInfo *chanInfo) { - if (chanInfo->lli != NULL) { + if (chanInfo != NULL && chanInfo->lli != NULL) { OsalMemFree(chanInfo->lli); chanInfo->lli = NULL; chanInfo->lliCnt = 0; @@ -67,10 +139,10 @@ static void DmacFreeLli(struct DmacChanInfo *chanInfo) */ void DmaCntlrDestroy(struct DmaCntlr *cntlr) { - unsigned int i; + uint16_t i; if (cntlr == NULL || cntlr->channelNum > DMAC_CHAN_NUM_MAX) { - HDF_LOGE("%s: cntlr null or channel invalid!", __func__); + HDF_LOGE("dma cntlr null or channel invalid!"); return; } if (cntlr->channelList != NULL) { @@ -97,7 +169,7 @@ static void DmacEventCallback(struct DmacChanInfo *chanInfo) static void DmacCallbackHandle(struct DmacChanInfo *chanInfo) { - if (chanInfo->transferType == TRASFER_TYPE_M2M) { + if (chanInfo->transType == TRASFER_TYPE_M2M) { DmacEventCallback(chanInfo); return; } @@ -106,37 +178,34 @@ static void DmacCallbackHandle(struct DmacChanInfo *chanInfo) } } -static int DmacWaitM2mSendComplete(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo) +static int32_t DmacWaitM2mSendComplete(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo) { uint32_t ret; - if (DmacCheck(cntlr) != HDF_SUCCESS) { - HDF_LOGE("check fail"); - return HDF_FAILURE; + if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) { + return HDF_ERR_INVALID_OBJECT; } ret = DmaEventWait(&chanInfo->waitEvent, DMAC_EVENT_DONE | DMAC_EVENT_ERROR, DMA_EVENT_WAIT_DEF_TIME); if (ret == DMAC_EVENT_ERROR) { - HDF_LOGE("wait event error!"); + HDF_LOGE("%s: wait event error", __func__); return DMAC_CHN_ERROR; } else if (ret == LOS_ERRNO_EVENT_READ_TIMEOUT) { - HDF_LOGE("wait event timeout!"); + HDF_LOGE("%s: wait event timeout", __func__); return DMAC_CHN_TIMEOUT; } cntlr->dmacChanDisable(cntlr, chanInfo->channel); - HDF_LOGD("event finish!"); return DMAC_CHN_SUCCESS; } -static int DmacAllocateChannel(struct DmaCntlr *cntlr) +static uint16_t DmacAllocateChannel(struct DmaCntlr *cntlr) { - uint32_t flags; int i; + uint32_t flags; - if (DmacCheck(cntlr) != HDF_SUCCESS) { - HDF_LOGE("check fail"); - return HDF_FAILURE; + if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) { + return HDF_ERR_INVALID_OBJECT; } OsalSpinLockIrqSave(&cntlr->lock, &flags); @@ -151,12 +220,11 @@ static int DmacAllocateChannel(struct DmaCntlr *cntlr) return HDF_FAILURE; } -static void DmacFreeChannel(struct DmaCntlr *cntlr, unsigned int channel) +static void DmacFreeChannel(struct DmaCntlr *cntlr, uint16_t channel) { uint32_t flags; - if (DmacCheck(cntlr) != HDF_SUCCESS) { - HDF_LOGE("check fail"); + if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) { return; } @@ -165,150 +233,180 @@ static void DmacFreeChannel(struct DmaCntlr *cntlr, unsigned int channel) OsalSpinUnlockIrqRestore(&cntlr->lock, &flags); } -static struct DmacChanInfo *DmacRequestChannel(struct DmaCntlr *cntlr, - int type, unsigned int periphAddr) +static struct DmacChanInfo *DmacRequestChannel(struct DmaCntlr *cntlr, struct DmacMsg *msg) { - int ret; - struct DmacChanInfo *chanInfo = NULL; + int32_t ret; int chan; + struct DmacChanInfo *chanInfo = NULL; - if (DmacCheck(cntlr) != HDF_SUCCESS) { - HDF_LOGE("check fail"); + if (DmacCntlrCheck(cntlr) != HDF_SUCCESS || msg == NULL) { + HDF_LOGE("%s: cntlr check failed or msg invalid", __func__); return NULL; } chan = DmacAllocateChannel(cntlr); if (chan < 0) { - HDF_LOGE("%s: getChannel is NULL", __func__); + HDF_LOGE("%s: allocate channel failed", __func__); return NULL; } chanInfo = &(cntlr->channelList[chan]); chanInfo->channel = (unsigned int)chan; - chanInfo->transferType = type; - ret = cntlr->getChanInfo(cntlr, chanInfo, periphAddr); + chanInfo->transType = msg->transType; + ret = cntlr->getChanInfo(cntlr, chanInfo, msg); if (ret < 0) { DmacFreeChannel(cntlr, chan); - HDF_LOGE("%s: get channel fail ret = %d", __func__, ret); + HDF_LOGE("%s: get channel info failed ret = %d", __func__, ret); return NULL; } - HDF_LOGD("channel = %d, transfer type = %u width = %u, config = 0x%x, lliflag = 0x%x", - ret, chanInfo->transferType, chanInfo->width, chanInfo->config, chanInfo->lliEnFlag); +#ifdef DMA_CORE_DEBUG + HDF_LOGD("chan = %d, type = %d srcWidth = %u, destWidth = %u, config = 0x%x, lliEnflag = 0x%x", + chan, chanInfo->transType, chanInfo->srcWidth, chanInfo->destWidth, chanInfo->config, chanInfo->lliEnFlag); +#endif return chanInfo; } -static int DmacFillLli(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo, - UINTPTR srcaddr, UINTPTR dstaddr, unsigned int length) +static uintptr_t DmacGetDummyBuf(struct DmaCntlr *cntlr, struct DmacChanInfo *chan) { - unsigned int i; + if (chan->dummyPage == NULL) { + chan->dummyPage = OsalMemCalloc(sizeof(cntlr->maxTransSize)); + } + + return (chan->dummyPage == NULL) ? 0 : (uintptr_t)LOS_PaddrQuery(chan->dummyPage); +} + +static inline size_t DmacAlignedTransMax(size_t maxSize, uint8_t srcWidth, uint8_t destWidth) +{ + size_t ret; + uint8_t maxWidth = (srcWidth >= destWidth) ? srcWidth : destWidth; + + ret = (maxWidth == 0) ? maxSize : maxSize - (maxSize % maxWidth); +#ifdef DMA_CORE_DEBUG + HDF_LOGD("%s: max:%zu, srcwidth:%u, dstwidth:%u, alignedmax:%zu", __func__, maxSize, srcWidth, destWidth, ret); +#endif + return ret; +} + +static int32_t DmacFillLli(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo, + uintptr_t srcaddr, uintptr_t dstaddr, size_t length) +{ + int32_t ret = HDF_SUCCESS; + uint16_t i; + uint16_t lliNum; struct DmacLli *plli = NULL; - unsigned int lliNum; + size_t alignedMax; + uintptr_t srcDummy = 0; + uintptr_t dstDummy = 0; - if (DmacCheck(cntlr) != HDF_SUCCESS) { - HDF_LOGE("check fail"); - return HDF_FAILURE; + if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) { + return HDF_ERR_INVALID_OBJECT; + } + if (chanInfo == NULL || chanInfo->lli == NULL) { + HDF_LOGE("%s: chanInfo or lli is null", __func__); + return HDF_ERR_INVALID_PARAM; + } + alignedMax = DmacAlignedTransMax(cntlr->maxTransSize, chanInfo->srcWidth, chanInfo->destWidth); + if (alignedMax == 0) { + HDF_LOGE("%s: maxTransSize:%zu srcWidth:%u dstWidth:%u", __func__, + cntlr->maxTransSize, chanInfo->srcWidth, chanInfo->destWidth); + return HDF_ERR_INVALID_PARAM; } - plli = chanInfo->lli; - if (plli == NULL) { - HDF_LOGE("lli is NULL!\n"); - return HDF_FAILURE; + + if (srcaddr == 0) { + srcaddr = srcDummy = DmacGetDummyBuf(cntlr, chanInfo); } - lliNum = chanInfo->lliCnt; - for (i = 0; i < lliNum; i++) { - plli->nextLli = (long long)cntlr->dmacVaddrToPaddr((void *)plli) + (long long)(i + 1) * sizeof(struct DmacLli); - if (i < lliNum - 1) { - plli->nextLli += chanInfo->lliEnFlag; - plli->count = cntlr->maxTransSize; - } else { - plli->nextLli = 0; - plli->count = cntlr->maxTransSize == 0 ? length : (length % cntlr->maxTransSize); - } + if (dstaddr == 0) { + dstaddr = dstDummy = DmacGetDummyBuf(cntlr, chanInfo); + } + if (srcaddr == 0 || dstaddr == 0) { + return HDF_ERR_MALLOC_FAIL; + } + + for (i = 0, lliNum = chanInfo->lliCnt; i < lliNum; i++, plli++) { + plli->nextLli = (uintptr_t)cntlr->dmacVaddrToPaddr((void *)plli) + (uintptr_t)sizeof(struct DmacLli); + plli->nextLli = (i < lliNum - 1) ? (plli->nextLli + chanInfo->lliEnFlag) : 0; + plli->count = ((i < lliNum - 1) || ((length % alignedMax) == 0)) ? alignedMax : (length % alignedMax); - plli->srcAddr = (long long)srcaddr; - plli->destAddr = (long long)dstaddr; + plli->srcAddr = srcaddr; + plli->destAddr = dstaddr; plli->config = chanInfo->config; - if (chanInfo->transferType == TRASFER_TYPE_P2M) { - dstaddr += plli->count; - } else if (chanInfo->transferType == TRASFER_TYPE_M2P) { - srcaddr += plli->count; - } - plli++; +#ifdef DMA_CORE_DEBUG + HDF_LOGD("plli=0x%lx, next=0x%lx, count=0x%lx, src=0x%lx, dst=0x%lx, cfg=0x%lx", + (uintptr_t)cntlr->dmacVaddrToPaddr(plli), plli->nextLli, + plli->count, plli->srcAddr, plli->destAddr, plli->config); +#endif + dstaddr += (chanInfo->transType == TRASFER_TYPE_P2M && dstDummy == 0) ? plli->count : 0; + srcaddr += (chanInfo->transType == TRASFER_TYPE_M2P && srcDummy == 0) ? plli->count : 0; } plli = chanInfo->lli; - cntlr->dmacCacheFlush((UINTPTR)plli, (UINTPTR)plli + (UINTPTR)(sizeof(struct DmacLli) * lliNum)); - HDF_LOGD("alloc_addr = 0x%x, alloc_addr + (sizeof(DmacLli) * lli_num)= 0x%x\n", - (UINTPTR)plli, (UINTPTR)plli + (UINTPTR)(sizeof(struct DmacLli) * lliNum)); - return HDF_SUCCESS; + cntlr->dmacCacheFlush((uintptr_t)plli, (uintptr_t)plli + (uintptr_t)(sizeof(struct DmacLli) * lliNum)); + return ret; } -int DmacAllocLli(struct DmacChanInfo *chanInfo, unsigned int length, unsigned int maxSize) +static int32_t DmacAllocLli(struct DmacChanInfo *chanInfo, size_t length, size_t maxSize) { - unsigned int lliNum; - unsigned int allocLength; - unsigned long *allocAddr = NULL; + size_t lliNum; + size_t allocLength; + void *allocAddr = NULL; - if (maxSize == 0 || chanInfo == NULL) { - return HDF_FAILURE; - } - lliNum = length / maxSize; - if ((length % maxSize) > 0) { - lliNum++; + if (chanInfo == NULL || maxSize == 0) { + return HDF_ERR_INVALID_PARAM; } + lliNum = (length / maxSize) + ((length % maxSize) > 0 ? 1 : 0); if (lliNum > 2048) { /* 2048: lliNum is not more than 2048 */ - HDF_LOGE("lliNum %u is bigger than 2048", lliNum); - return HDF_FAILURE; + HDF_LOGE("%s: lliNum %u is bigger than 2048", __func__, lliNum); + return HDF_ERR_INVALID_PARAM; } + allocLength = lliNum * sizeof(struct DmacLli); allocLength = ALIGN(allocLength, CACHE_ALIGNED_SIZE); - allocAddr = (unsigned long *)OsalMemAllocAlign(DMA_ALIGN_SIZE, allocLength); + allocAddr = OsalMemAllocAlign(DMA_ALIGN_SIZE, allocLength); if (allocAddr == NULL) { - HDF_LOGE("can't malloc llimem for dma!\n "); + HDF_LOGE("%s: alloc lli mem failed", __func__); return HDF_FAILURE; } if (memset_s(allocAddr, allocLength, 0, allocLength) != EOK) { - HDF_LOGE("memset_s fail"); OsalMemFree(allocAddr); return HDF_FAILURE; } - chanInfo->lliCnt = lliNum; + chanInfo->lliCnt = (uint16_t)lliNum; chanInfo->lli = (struct DmacLli *)allocAddr; return HDF_SUCCESS; } -static int32_t DmacPeriphTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg, unsigned int periphAddr) +static int32_t DmacPeriphTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg) { - int ret; + int32_t ret; struct DmacChanInfo *chanInfo = NULL; - if (DmacCheck(cntlr) != HDF_SUCCESS) { - HDF_LOGE("check fail"); - return HDF_FAILURE; - } - chanInfo = DmacRequestChannel(cntlr, msg->direct, periphAddr); + chanInfo = DmacRequestChannel(cntlr, msg); if (chanInfo == NULL) { - HDF_LOGE("allocate dma channel fail"); - return HDF_FAILURE; + HDF_LOGE("%s: request channel failed", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (msg->srcAddr == 0 && msg->destAddr == 0) { + HDF_LOGE("%s: src addr & dest addr both null", __func__); + return HDF_ERR_INVALID_PARAM; } chanInfo->callbackData = msg->para; chanInfo->callback = (DmacCallback *)msg->cb; - ret = DmacAllocLli(chanInfo, msg->transferSize, cntlr->maxTransSize); + ret = DmacAllocLli(chanInfo, msg->transLen, + DmacAlignedTransMax(cntlr->maxTransSize, chanInfo->srcWidth, chanInfo->destWidth)); if (ret != HDF_SUCCESS) { - HDF_LOGE("malloc dmalli space failed"); DmacFreeChannel(cntlr, chanInfo->channel); - return HDF_FAILURE; + return ret; } - ret = DmacFillLli(cntlr, chanInfo, msg->srcAddr, msg->destAddr, msg->transferSize); + ret = DmacFillLli(cntlr, chanInfo, msg->srcAddr, msg->destAddr, msg->transLen); if (ret != HDF_SUCCESS) { - HDF_LOGE("build edmalli failed"); DmacFreeLli(chanInfo); DmacFreeChannel(cntlr, chanInfo->channel); - return HDF_FAILURE; + return ret; } ret = cntlr->dmaChanEnable(cntlr, chanInfo); if (ret != HDF_SUCCESS) { - HDF_LOGE("start edma failed!"); + HDF_LOGE("%s: enable channel failed", __func__); DmacFreeLli(chanInfo); DmacFreeChannel(cntlr, chanInfo->channel); return HDF_FAILURE; @@ -316,58 +414,49 @@ static int32_t DmacPeriphTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg, u return HDF_SUCCESS; } -static int DmacM2mTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg) +static int32_t DmacM2mTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg) { + int32_t ret; + size_t leftSize; + size_t dmaSize; + size_t dmaCount = 0; struct DmacChanInfo *chanInfo = NULL; - unsigned int leftSize; - unsigned int dmaCount = 0; - unsigned int dmaSize; - int ret; - if (DmacCheck(cntlr) != HDF_SUCCESS) { - HDF_LOGE("check fail"); - return HDF_FAILURE; + if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) { + return HDF_ERR_INVALID_OBJECT; } - chanInfo = DmacRequestChannel(cntlr, TRASFER_TYPE_M2M, PERIPHERALID_INVILD); + chanInfo = DmacRequestChannel(cntlr, msg); if (chanInfo == NULL) { - HDF_LOGE("allocate channel fail\n"); - return -1; + HDF_LOGE("%s: request channel failed", __func__); + return HDF_FAILURE; } chanInfo->callback = msg->cb; chanInfo->callbackData = msg->para; - cntlr->dmacCacheFlush((UINTPTR)msg->srcAddr, (UINTPTR)(msg->srcAddr + msg->transferSize)); - cntlr->dmacCacheInv((UINTPTR)msg->destAddr, (UINTPTR)(msg->destAddr + msg->transferSize)); - leftSize = msg->transferSize; + cntlr->dmacCacheFlush((uintptr_t)msg->srcAddr, (uintptr_t)(msg->srcAddr + msg->transLen)); + cntlr->dmacCacheInv((uintptr_t)msg->destAddr, (uintptr_t)(msg->destAddr + msg->transLen)); + leftSize = msg->transLen; while (leftSize > 0) { - if (leftSize >= cntlr->maxTransSize) { - dmaSize = cntlr->maxTransSize; - } else { - dmaSize = leftSize; - } + dmaSize = (leftSize >= cntlr->maxTransSize) ? cntlr->maxTransSize : leftSize; ret = cntlr->dmaM2mChanEnable(cntlr, chanInfo, msg->srcAddr + dmaCount * cntlr->maxTransSize, msg->destAddr + dmaCount * cntlr->maxTransSize, dmaSize); - if (ret != 0) { - HDF_LOGE("HiedmacStartM2m error"); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: enable channel m2m failed", __func__); DmacFreeChannel(cntlr, chanInfo->channel); if (chanInfo->callback != NULL) { chanInfo->callback(chanInfo->callbackData, DMAC_CHN_ERROR); } - return HDF_FAILURE; + return ret; } ret = DmacWaitM2mSendComplete(cntlr, chanInfo); if (ret != DMAC_CHN_SUCCESS) { - HDF_LOGE("dma transfer error"); + HDF_LOGE("%s: m2m transfer failed, ret = %d", __func__, ret); DmacFreeChannel(cntlr, chanInfo->channel); if (chanInfo->callback != NULL) { chanInfo->callback(chanInfo->callbackData, ret); } return HDF_FAILURE; } - if (dmaSize == 0) { - DmacFreeChannel(cntlr, chanInfo->channel); - return HDF_FAILURE; - } leftSize -= dmaSize; dmaCount++; } @@ -380,57 +469,54 @@ static int DmacM2mTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg) int32_t DmaCntlrTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg) { - unsigned int periphAddr; + uintptr_t phyAddr; - if (DmacCheck(cntlr) != HDF_SUCCESS) { - HDF_LOGE("check fail"); - return HDF_FAILURE; + if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) { + return HDF_ERR_INVALID_OBJECT; } if (msg == NULL) { - return HDF_FAILURE; + return HDF_ERR_INVALID_PARAM; } - if (msg->direct == TRASFER_TYPE_P2M) { - periphAddr = msg->srcAddr; - cntlr->dmacCacheInv((UINTPTR)cntlr->dmacPaddrToVaddr((paddr_t)msg->destAddr), - (UINTPTR)cntlr->dmacPaddrToVaddr((paddr_t)msg->destAddr) + msg->transferSize); - } else if (msg->direct == TRASFER_TYPE_M2P) { - periphAddr = msg->destAddr; - cntlr->dmacCacheFlush((UINTPTR)cntlr->dmacPaddrToVaddr((paddr_t)msg->srcAddr), - (UINTPTR)cntlr->dmacPaddrToVaddr((paddr_t)msg->srcAddr) + msg->transferSize); - } else if (msg->direct == TRASFER_TYPE_M2M) { + if (msg->transType == TRASFER_TYPE_P2M) { + if (msg->destAddr != 0) { + phyAddr = (uintptr_t)cntlr->dmacPaddrToVaddr((paddr_t)msg->destAddr); + cntlr->dmacCacheInv(phyAddr, (uintptr_t)(phyAddr + msg->transLen)); + } + } else if (msg->transType == TRASFER_TYPE_M2P) { + if (msg->srcAddr != 0) { + phyAddr = (uintptr_t)cntlr->dmacPaddrToVaddr((paddr_t)msg->srcAddr); + cntlr->dmacCacheFlush(phyAddr, (uintptr_t)(phyAddr + msg->transLen)); + } + } else if (msg->transType == TRASFER_TYPE_M2M) { return DmacM2mTransfer(cntlr, msg); } else { - HDF_LOGE("%s: invalid direct %u", __func__, msg->direct); + HDF_LOGE("%s: invalid transType %d", __func__, msg->transType); return HDF_FAILURE; } - return DmacPeriphTransfer(cntlr, msg, periphAddr); + return DmacPeriphTransfer(cntlr, msg); } -unsigned int DmaGetCurrChanDestAddr(struct DmaCntlr *cntlr, unsigned int chan) +uintptr_t DmaGetCurrChanDestAddr(struct DmaCntlr *cntlr, uint16_t chan) { - if (DmacCheck(cntlr) != HDF_SUCCESS) { - HDF_LOGE("check fail"); - return HDF_FAILURE; + if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) { + return HDF_ERR_INVALID_OBJECT; } - return cntlr->dmacGetCurrDestAddr(cntlr, chan); } static uint32_t DmacIsr(uint32_t irq, void *dev) { + uint16_t i; + int channelStatus; struct DmaCntlr *cntlr = (struct DmaCntlr *)dev; - unsigned int channelStatus; - unsigned int i; - if (DmacCheck(cntlr) != HDF_SUCCESS) { - HDF_LOGE("check fail"); - return HDF_FAILURE; + if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) { + return HDF_ERR_INVALID_OBJECT; } if (irq != cntlr->irq || cntlr->channelNum > DMAC_CHAN_NUM_MAX) { - HDF_LOGE("%s: cntlr param err! irq:%u, channel:%u", - __func__, cntlr->irq, cntlr->channelNum); - return HDF_ERR_INVALID_PARAM; + HDF_LOGE("%s: cntlr parm err! irq:%d, channel:%u", __func__, cntlr->irq, cntlr->channelNum); + return HDF_ERR_INVALID_OBJECT; } for (i = 0; i < cntlr->channelNum; i++) { channelStatus = cntlr->dmacGetChanStatus(cntlr, i); @@ -443,44 +529,39 @@ static uint32_t DmacIsr(uint32_t irq, void *dev) return HDF_SUCCESS; } -int DmacInit(struct DmaCntlr *cntlr) +int32_t DmacCntlrAdd(struct DmaCntlr *cntlr) { - int i; - int ret; + int32_t ret; + uint16_t i; - if (DmacCheck(cntlr) != HDF_SUCCESS) { - HDF_LOGE("check fail"); - return HDF_FAILURE; - } - if (cntlr->channelNum == 0 || cntlr->channelNum > DMAC_CHAN_NUM_MAX) { - HDF_LOGE("%s: invalid channel:%u", __func__, cntlr->channelNum); - return HDF_FAILURE; - } - if (cntlr->maxTransSize == 0) { - cntlr->maxTransSize = DMA_MAX_TRANS_SIZE_DEFAULT; + ret = DmacCntlrCheckInit(cntlr); + if (ret != HDF_SUCCESS) { + return ret; } - cntlr->remapBase = (char *)OsalIoRemap((unsigned long)cntlr->phyBase, (unsigned long)cntlr->regSize); + (void)OsalSpinInit(&cntlr->lock); + ret = OsalRegisterIrq(cntlr->irq, 0, (OsalIRQHandle)DmacIsr, "PlatDmac", cntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: request irq %u failed, ret = %d", __func__, cntlr->irq, ret); + (void)OsalSpinDestroy(&cntlr->lock); + return ret; + } cntlr->channelList = (struct DmacChanInfo *)OsalMemCalloc(sizeof(struct DmacChanInfo) * cntlr->channelNum); if (cntlr->channelList == NULL) { - HDF_LOGE("channel list malloc fail"); + HDF_LOGE("%s: alloc channel list failed", __func__); + (void)OsalUnregisterIrq(cntlr->irq, cntlr); (void)OsalSpinDestroy(&cntlr->lock); - OsalIoUnmap((void *)cntlr->remapBase); - return HDF_FAILURE; + return HDF_ERR_MALLOC_FAIL; } for (i = 0; i < cntlr->channelNum; i++) { cntlr->dmacChanDisable(cntlr, i); DmaEventInit(&(cntlr->channelList[i].waitEvent)); cntlr->channelList[i].useStatus = DMAC_CHN_VACANCY; } - ret = OsalRegisterIrq(cntlr->irq, 0, (OsalIRQHandle)DmacIsr, "PlatDmac", cntlr); - if (ret != HDF_SUCCESS) { - HDF_LOGE("DMA Irq %u request failed, ret = %d\n", cntlr->irq, ret); - OsalMemFree(cntlr->channelList); - cntlr->channelList = NULL; - (void)OsalSpinDestroy(&cntlr->lock); - OsalIoUnmap((void *)cntlr->remapBase); - } - return ret; + return HDF_SUCCESS; } +void DmacCntlrRemove(struct DmaCntlr *cntlr) +{ + (void)cntlr; +} diff --git a/support/platform/test/unittest/common/hdf_spi_test.cpp b/support/platform/test/unittest/common/hdf_spi_test.cpp index 1a9eef0f34ef45667c905de3da704c9966850bcf..050d053ae6bf9996c323b32f65449d8b204a8da3 100644 --- a/support/platform/test/unittest/common/hdf_spi_test.cpp +++ b/support/platform/test/unittest/common/hdf_spi_test.cpp @@ -20,13 +20,24 @@ using namespace testing::ext; // pal spi test case number enum HdfTestCaseCmd { + SPI_TRANSFER_TEST, + SPI_DMA_TRANSFER_TEST, + SPI_INT_TRANSFER_TEST, + SPI_RELIABILITY_TEST, + SPI_PERFORMANCE_TEST, +}; + +/*enum HdfTestCaseCmd { SPI_SET_CFG_TEST = 0, SPI_TRANSFER_TEST, SPI_WRITE_TEST, SPI_READ_TEST, + SPI_DMA_TEST, + SPI_INTERRUPT_TEST, SPI_RELIABILITY_TEST, SPI_PERFORMANCE_TEST, }; +*/ class HdfLiteSpiTest : public testing::Test { public: @@ -60,11 +71,12 @@ void HdfLiteSpiTest::TearDown() * @tc.type: FUNC * @tc.require: SR000DQ0VO */ -HWTEST_F(HdfLiteSpiTest, SpiSetCfgTest001, TestSize.Level1) +/*HWTEST_F(HdfLiteSpiTest, SpiSetCfgTest001, TestSize.Level1) { struct HdfTestMsg msg = {TEST_PAL_SPI_TYPE, SPI_SET_CFG_TEST, -1}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } +*/ /** * @tc.name: SpiTransferTest001 @@ -84,11 +96,12 @@ HWTEST_F(HdfLiteSpiTest, SpiTransferTest001, TestSize.Level1) * @tc.type: FUNC * @tc.require: SR000DQ0VO */ -HWTEST_F(HdfLiteSpiTest, SpiWriteTest001, TestSize.Level1) +/*HWTEST_F(HdfLiteSpiTest, SpiWriteTest001, TestSize.Level1) { struct HdfTestMsg msg = { TEST_PAL_SPI_TYPE, SPI_WRITE_TEST, -1}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } +*/ /** * @tc.name: SpiReadTest001 @@ -96,11 +109,36 @@ HWTEST_F(HdfLiteSpiTest, SpiWriteTest001, TestSize.Level1) * @tc.type: FUNC * @tc.require: SR000DQ0VO */ -HWTEST_F(HdfLiteSpiTest, SpiReadTest001, TestSize.Level1) +/*HWTEST_F(HdfLiteSpiTest, SpiReadTest001, TestSize.Level1) { struct HdfTestMsg msg = {TEST_PAL_SPI_TYPE, SPI_READ_TEST, -1}; EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); } +*/ + +/** + * @tc.name: SpiDmaTransferTest001 + * @tc.desc: Spi function test + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(HdfLiteSpiTest, SpiDmaTransferTest001, TestSize.Level1) +{ + struct HdfTestMsg msg = {TEST_PAL_SPI_TYPE, SPI_DMA_TRANSFER_TEST, -1}; + EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); +} + +/** + * @tc.name: SpiIntTransferTest001 + * @tc.desc: Spi function test + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(HdfLiteSpiTest, SpiIntTransferTest001, TestSize.Level1) +{ + struct HdfTestMsg msg = {TEST_PAL_SPI_TYPE, SPI_INT_TRANSFER_TEST, -1}; + EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); +} /** * @tc.name: SpiReliabilityTest001 diff --git a/test/unittest/platform/common/spi_test.c b/test/unittest/platform/common/spi_test.c index 507376eec619107042f903fbf8eb469642b18bc1..ee09d21684693deb7230ef5dd13d05b8582fc1d9 100644 --- a/test/unittest/platform/common/spi_test.c +++ b/test/unittest/platform/common/spi_test.c @@ -15,6 +15,11 @@ #include "spi_test.h" #define HDF_LOG_TAG spi_test_c + +#define SPI_TEST_4BITS 4 +#define SPI_TEST_8BITS 8 +#define SPI_TEST_16BITS 16 + struct SpiTestFunc { enum SpiTestCmd type; int32_t (*Func)(struct SpiTest *test); @@ -38,65 +43,226 @@ static void SpiTestReleaseHandle(DevHandle handle) SpiClose(handle); } -#define BITS_PER_WORD 10 -#define MAX_SPEED_HZ 10000000 -static int32_t SpiSetCfgTest(struct SpiTest *test) +#define BITS_PER_WORD_DEFAULT 8 +#define BITS_PER_WORD_8BITS 8 +#define BITS_PER_WORD_10BITS 10 +#define MAX_SPEED_HZ 10000000 + +static struct SpiCfg g_spiCfg = { + .mode = SPI_CLK_PHASE | SPI_MODE_LOOP, + .bitsPerWord = BITS_PER_WORD_DEFAULT, + .maxSpeedHz = MAX_SPEED_HZ, + .transferMode = SPI_POLLING_TRANSFER, +}; + +#define SPI_TEST_ONE_BYTE 1 +#define SPI_TEST_TWO_BYTE 2 + +static int32_t SpiCmpMemByBits(uint8_t *wbuf, uint8_t *rbuf, uint32_t len, uint8_t bits) +{ + int32_t i; + uint16_t vw; + uint16_t vr; + + if (bits < SPI_TEST_4BITS) { + bits = SPI_TEST_4BITS; + } else if (bits > SPI_TEST_16BITS) { + bits = SPI_TEST_16BITS; + } + + for (i = 0; i < len;) { + if (bits <= SPI_TEST_8BITS) { + vw = *((uint8_t *)(wbuf + i)) & (~(0xFFFF << bits)); + vr = *((uint8_t *)(rbuf + i)) & (~(0xFFFF << bits)); + } else { + vw = *((uint16_t *)(wbuf + i)) & (~(0xFFFF << bits)); + vr = *((uint16_t *)(rbuf + i)) & (~(0xFFFF << bits)); + } + if (vw != vr) { + HDF_LOGE("%s: compare mem fail(i=%d, vw=%u, vr=%u, bits = %u, len=%u)", + __func__, i, vw, vr, bits, len); + return HDF_FAILURE; + } + i += (bits <= SPI_TEST_8BITS) ? SPI_TEST_ONE_BYTE : SPI_TEST_TWO_BYTE; + } + HDF_LOGE("%s: mem size(%u) compare success", __func__, len); + return HDF_SUCCESS; +} + +static int32_t SpiDoTransferTest(struct SpiTest *test, struct SpiCfg *cfg, struct SpiMsg *msg) { int32_t ret; - struct SpiCfg cfg; - cfg.mode = SPI_CLK_PHASE | SPI_MODE_LOOP; - cfg.bitsPerWord = BITS_PER_WORD; - cfg.maxSpeedHz = MAX_SPEED_HZ; - cfg.transferMode = SPI_INTERRUPT_TRANSFER; - ret = SpiSetCfg(test->handle, &cfg); + ret = SpiSetCfg(test->handle, cfg); if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: error", __func__); - return HDF_FAILURE; + HDF_LOGE("%s: set config fail", __func__); + return ret; + } + + ret = SpiTransfer(test->handle, msg, 1); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: spi transfer err", __func__); + return ret; + } + + ret = SpiCmpMemByBits(msg->wbuf, msg->rbuf, msg->len, g_spiCfg.bitsPerWord); + if (ret != HDF_SUCCESS) { + return ret; } + + ret = SpiWrite(test->handle, msg->wbuf, msg->len); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: spi write err", __func__); + return ret; + } + + ret = SpiRead(test->handle, msg->rbuf, msg->len); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: spi read err", __func__); + return ret; + } + HDF_LOGE("%s: success", __func__); - return ret; + return HDF_SUCCESS; } static int32_t SpiTransferTest(struct SpiTest *test) { - int32_t i; + int32_t ret; struct SpiMsg msg; + g_spiCfg.bitsPerWord = BITS_PER_WORD_8BITS; + g_spiCfg.transferMode = SPI_POLLING_TRANSFER; + msg.rbuf = test->rbuf; msg.wbuf = test->wbuf; msg.len = test->len; msg.csChange = 1; // switch off the CS after transfer msg.delayUs = 0; msg.speed = 0; // use default speed - if (SpiTransfer(test->handle, &msg, 1) != HDF_SUCCESS) { - HDF_LOGE("%s: spi transfer err", __func__); - return HDF_FAILURE; + + ret = SpiDoTransferTest(test, &g_spiCfg, &msg); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: fail, bitsPerWord = %u, ret = %d", __func__, g_spiCfg.bitsPerWord, ret); + return ret; } - for (i = 0; i < test->len; i++) { - HDF_LOGE("%s: wbuf[%d] = 0x%x rbuff[%d] = 0x%x", __func__, i, test->wbuf[i], i, test->rbuf[i]); + + g_spiCfg.bitsPerWord = BITS_PER_WORD_10BITS; + ret = SpiDoTransferTest(test, &g_spiCfg, &msg); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: fail, bitsPerWord = %u, ret = %d", __func__, g_spiCfg.bitsPerWord, ret); + return ret; } - HDF_LOGE("%s: success", __func__); + return HDF_SUCCESS; } -static int32_t SpiWriteTest(struct SpiTest *test) +#define DMA_TRANSFER_SINGLE_MAX (1024 * 64 - 1) +#define DMA_TRANSFER_SIZE_TOTAL (DMA_TRANSFER_SINGLE_MAX * 2 + 65532) +#define DMA_TRANSFER_BUF_SEED 0x5A +#define DMA_ALIGN_SIZE 64 + +static int32_t SpiSetDmaIntMsg(struct SpiMsg *msg, uint32_t len) { - if (SpiWrite(test->handle, test->wbuf, test->len) != HDF_SUCCESS) { - HDF_LOGE("%s: spi write err\n", __func__); - return HDF_FAILURE; + uint32_t i; + uint8_t *wbuf = NULL; + uint8_t *rbuf = NULL; + + msg->wbuf = msg->rbuf = NULL; + + wbuf = (uint8_t *)OsalMemAllocAlign(DMA_ALIGN_SIZE, len); + if (wbuf == NULL) { + return HDF_ERR_MALLOC_FAIL; } - HDF_LOGE("%s: success", __func__); + rbuf = (uint8_t *)OsalMemAllocAlign(DMA_ALIGN_SIZE, len); + if (wbuf == NULL) { + OsalMemFree(wbuf); + return HDF_ERR_MALLOC_FAIL; + } + + wbuf[0] = DMA_TRANSFER_BUF_SEED; + for (i = 1; i < len; i++) { + wbuf[i] = wbuf[i - 1] + 1; + rbuf[i] = 0; + } + msg->wbuf = wbuf; + msg->rbuf = rbuf; + msg->len = len; + msg->csChange = 1; + msg->delayUs = 0, // switch off the CS after transfer + msg->speed = 0; // using default speed return HDF_SUCCESS; } -static int32_t SpiReadTest(struct SpiTest *test) +static void SpiUnsetDmaIntMsg(struct SpiMsg *msg) { - if (SpiRead(test->handle, test->rbuf, test->len) != HDF_SUCCESS) { - HDF_LOGE("%s: spi read err\n", __func__); - return HDF_FAILURE; + if (msg != NULL) { + OsalMemFree(msg->wbuf); + OsalMemFree(msg->rbuf); + msg->wbuf = NULL; + msg->rbuf = NULL; } - HDF_LOGE("%s: success", __func__); +} + +static int32_t SpiDmaTransferTest(struct SpiTest *test) +{ + int32_t ret; + struct SpiMsg msg; + + g_spiCfg.transferMode = SPI_DMA_TRANSFER; + g_spiCfg.bitsPerWord = BITS_PER_WORD_8BITS; + + ret = SpiSetDmaIntMsg(&msg, DMA_TRANSFER_SIZE_TOTAL); + if (ret != HDF_SUCCESS) { + return ret; + } + + ret = SpiDoTransferTest(test, &g_spiCfg, &msg); + if (ret != HDF_SUCCESS) { + SpiUnsetDmaIntMsg(&msg); + HDF_LOGE("%s: fail, bitsPerWord = %u, ret = %d", __func__, g_spiCfg.bitsPerWord, ret); + return ret; + } + + g_spiCfg.bitsPerWord = BITS_PER_WORD_10BITS; + ret = SpiDoTransferTest(test, &g_spiCfg, &msg); + if (ret != HDF_SUCCESS) { + SpiUnsetDmaIntMsg(&msg); + HDF_LOGE("%s: fail, bitsPerWord = %u, ret = %d", __func__, g_spiCfg.bitsPerWord, ret); + return ret; + } + + return HDF_SUCCESS; +} + +static int32_t SpiIntTransferTest(struct SpiTest *test) +{ + int32_t ret; + struct SpiMsg msg; + + g_spiCfg.transferMode = SPI_INTERRUPT_TRANSFER; + g_spiCfg.bitsPerWord = BITS_PER_WORD_8BITS; + + ret = SpiSetDmaIntMsg(&msg, DMA_TRANSFER_SIZE_TOTAL); + if (ret != HDF_SUCCESS) { + return ret; + } + + ret = SpiDoTransferTest(test, &g_spiCfg, &msg); + if (ret != HDF_SUCCESS) { + SpiUnsetDmaIntMsg(&msg); + HDF_LOGE("%s: fail, bitsPerWord = %u, ret = %d", __func__, g_spiCfg.bitsPerWord, ret); + return ret; + } + + g_spiCfg.bitsPerWord = BITS_PER_WORD_10BITS; + ret = SpiDoTransferTest(test, &g_spiCfg, &msg); + if (ret != HDF_SUCCESS) { + SpiUnsetDmaIntMsg(&msg); + HDF_LOGE("%s: fail, bitsPerWord = %u, ret = %d", __func__, g_spiCfg.bitsPerWord, ret); + return ret; + } + return HDF_SUCCESS; } @@ -113,6 +279,8 @@ static int32_t SpiReliabilityTest(struct SpiTest *test) (void)SpiWrite(test->handle, NULL, -1); (void)SpiRead(test->handle, test->rbuf, test->len); (void)SpiRead(test->handle, NULL, -1); + + (void)test; HDF_LOGE("%s: success", __func__); return HDF_SUCCESS; } @@ -122,35 +290,34 @@ static int32_t SpiTestAll(struct SpiTest *test) int32_t total = 0; int32_t error = 0; - if (SpiSetCfgTest(test) != HDF_SUCCESS) { - error++; - } - total++; if (SpiTransferTest(test) != HDF_SUCCESS) { error++; } total++; - if (SpiWriteTest(test) != HDF_SUCCESS) { + + if (SpiDmaTransferTest(test) != HDF_SUCCESS) { error++; } total++; - if (SpiReadTest(test) != HDF_SUCCESS) { + + if (SpiIntTransferTest(test) != HDF_SUCCESS) { error++; } total++; + if (SpiReliabilityTest(test) != HDF_SUCCESS) { error++; } total++; + HDF_LOGE("%s: Spi Test Total %d Error %d", __func__, total, error); return HDF_SUCCESS; } -struct SpiTestFunc g_spiTestFunc[] = { - {SPI_SET_CFG_TEST, SpiSetCfgTest}, +static struct SpiTestFunc g_spiTestFunc[] = { {SPI_TRANSFER_TEST, SpiTransferTest}, - {SPI_WRITE_TEST, SpiWriteTest}, - {SPI_READ_TEST, SpiReadTest}, + {SPI_DMA_TRANSFER_TEST, SpiDmaTransferTest}, + {SPI_INT_TRANSFER_TEST, SpiIntTransferTest}, {SPI_RELIABILITY_TEST, SpiReliabilityTest}, {SPI_PERFORMANCE_TEST, NULL}, {SPI_TEST_ALL, SpiTestAll}, @@ -161,6 +328,7 @@ static int32_t SpiTestEntry(struct SpiTest *test, int32_t cmd) int32_t i; int32_t ret = HDF_ERR_NOT_SUPPORT; + HDF_LOGE("%s: enter cmd %d", __func__, cmd); if (test == NULL) { return HDF_ERR_INVALID_OBJECT; } diff --git a/test/unittest/platform/common/spi_test.h b/test/unittest/platform/common/spi_test.h index 31d474a3bddbae963895f1fe4db84da648d4c5c3..fe9cc0ba2266dbf3ce29009a314b7dcb565feb88 100644 --- a/test/unittest/platform/common/spi_test.h +++ b/test/unittest/platform/common/spi_test.h @@ -13,10 +13,9 @@ #include "hdf_platform.h" enum SpiTestCmd { - SPI_SET_CFG_TEST = 0, SPI_TRANSFER_TEST, - SPI_WRITE_TEST, - SPI_READ_TEST, + SPI_DMA_TRANSFER_TEST, + SPI_INT_TRANSFER_TEST, SPI_RELIABILITY_TEST, SPI_PERFORMANCE_TEST, SPI_TEST_ALL,