add spi-dma support

This commit is contained in:
haizhouyang
2021-05-19 17:22:58 +08:00
parent 1bd436be41
commit 74f61de8e6
5 changed files with 534 additions and 273 deletions
+107 -76
View File
@@ -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,145 @@ extern "C" {
#endif
#endif /* __cplusplus */
#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 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;
#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)
/* 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)
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,
};
#define DMA_EVENT_WAIT_DEF_TIME ((LOSCFG_BASE_CORE_TICK_PER_SECOND) * 5)
#define DMAC_EVENT_DONE 0x1
#define DMAC_EVENT_ERROR 0x2
enum DmacEvent {
DMAC_EVENT_DONE = 0x1,
DMAC_EVENT_ERROR = 0x2,
};
#define DMA_EVENT_WAIT_DEF_TIME ((LOSCFG_BASE_CORE_TICK_PER_SECOND) * 5)
#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 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;
};
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);
#ifdef __cplusplus
#if __cplusplus
+279 -189
View File
@@ -1,5 +1,4 @@
/*
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
/* * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
@@ -17,21 +16,94 @@
#define DMA_ALIGN_SIZE 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;
}
@@ -45,7 +117,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;
@@ -54,7 +125,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;
@@ -66,10 +137,10 @@ static void DmacFreeLli(struct DmacChanInfo *chanInfo)
*/
void DmaCntlrDestroy(struct DmaCntlr *cntlr)
{
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) {
@@ -96,7 +167,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;
}
@@ -105,37 +176,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)
{
unsigned int 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)
{
unsigned int 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);
@@ -150,12 +218,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;
}
@@ -164,155 +231,189 @@ 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 = %d 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);
}
if (dstaddr == 0) {
dstaddr = dstDummy = DmacGetDummyBuf(cntlr, chanInfo);
}
if (srcaddr == 0 || dstaddr == 0) {
return HDF_ERR_MALLOC_FAIL;
}
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 = (length % cntlr->maxTransSize);
}
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) ? alignedMax: (length % alignedMax);
plli->srcAddr = (long long)srcaddr;
plli->destAddr = (long long)dstaddr;
plli->srcAddr = srcaddr;
plli->destAddr = dstaddr;
plli->config = chanInfo->config;
HDF_LOGD("plli->srcAddr = 0x%llx\n", plli->srcAddr);
HDF_LOGD("plli->destAddr = 0x%llx\n", plli->destAddr);
HDF_LOGD("plli->nextLli = 0x%llx\n", plli->nextLli);
HDF_LOGD("plli->config = 0x%x\n", plli->config);
HDF_LOGD("plli->count = 0x%x\n", plli->count);
#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
if (chanInfo->transferType == TRASFER_TYPE_P2M) {
if (chanInfo->transType == TRASFER_TYPE_P2M && dstDummy == 0) {
dstaddr += plli->count;
} else if (chanInfo->transferType == TRASFER_TYPE_M2P) {
} else if (chanInfo->transType == TRASFER_TYPE_M2P && srcDummy == 0) {
srcaddr += plli->count;
}
plli++;
}
cntlr->dmacCacheFlush((UINTPTR)plli, (UINTPTR)plli + (UINTPTR)(sizeof(struct DmacLli) * lliNum));
plli = chanInfo->lli;
cntlr->dmacCacheFlush((uintptr_t)plli, (uintptr_t)plli + (uintptr_t)(sizeof(struct DmacLli) * lliNum));
#ifdef DMA_CORE_DEBUG
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;
(uintptr_t)plli, (uintptr_t)plli + (uintptr_t)(sizeof(struct DmacLli) * lliNum));
#endif
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;
@@ -320,57 +421,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) {
return HDF_FAILURE;
}
leftSize -= dmaSize;
dmaCount++;
}
@@ -383,57 +476,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 %d", __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(int irq, void *dev)
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 parm err! irq:%d, channel:%u",
__func__, cntlr->irq, cntlr->channelNum);
return HDF_SUCCESS;
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);
@@ -446,39 +536,39 @@ static uint32_t DmacIsr(int 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;
ret = DmacCntlrCheckInit(cntlr);
if (ret != HDF_SUCCESS) {
return ret;
}
if (cntlr->channelNum > DMAC_CHAN_NUM_MAX) {
HDF_LOGE("%s: invalid channel:%d", __func__, cntlr->channelNum);
return HDF_FAILURE;
(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->remapBase = (char *)OsalIoRemap((unsigned long)cntlr->phyBase, (unsigned long)cntlr->regSize);
OsalSpinInit(&cntlr->lock);
cntlr->channelList = (struct DmacChanInfo *)OsalMemCalloc(sizeof(struct DmacChanInfo) * cntlr->channelNum);
if (cntlr->channelList == NULL) {
HDF_LOGE("channel list malloc fail");
OsalIoUnmap((void *)cntlr->remapBase);
return HDF_FAILURE;
HDF_LOGE("%s: alloc channel list failed", __func__);
(void)OsalUnregisterIrq(cntlr->irq, cntlr);
(void)OsalSpinDestroy(&cntlr->lock);
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 %d request failed, ret = %d\n", cntlr->irq, ret);
OsalMemFree(cntlr->channelList);
cntlr->channelList = NULL;
OsalIoUnmap((void *)cntlr->remapBase);
}
return ret;
return HDF_SUCCESS;
}
void DmacCntlrRemove(struct DmaCntlr *cntlr)
{
(void)cntlr;
}
@@ -24,6 +24,7 @@ enum HdfTestCaseCmd {
SPI_TRANSFER_TEST,
SPI_WRITE_TEST,
SPI_READ_TEST,
SPI_DMA_TEST,
SPI_RELIABILITY_TEST,
SPI_PERFORMANCE_TEST,
};
@@ -102,6 +103,18 @@ HWTEST_F(HdfLiteSpiTest, SpiReadTest001, TestSize.Level1)
EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
}
/**
* @tc.name: SpiDmaTest001
* @tc.desc: Spi function test
* @tc.type: FUNC
* @tc.require: NA
*/
HWTEST_F(HdfLiteSpiTest, SpiDmaTest001, TestSize.Level1)
{
struct HdfTestMsg msg = {TEST_PAL_SPI_TYPE, SPI_DMA_TEST, -1};
EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
}
/**
* @tc.name: SpiReliabilityTest001
* @tc.desc: spi function test
+134 -8
View File
@@ -40,16 +40,19 @@ static void SpiTestReleaseHandle(DevHandle handle)
#define BITS_PER_WORD 10
#define MAX_SPEED_HZ 10000000
static struct SpiCfg g_spiCfg = {
.mode = SPI_CLK_PHASE | SPI_MODE_LOOP,
.bitsPerWord = BITS_PER_WORD,
.maxSpeedHz = MAX_SPEED_HZ,
.transferMode = SPI_POLLING_TRANSFER,
};
static int32_t SpiSetCfgTest(struct SpiTest *test)
{
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, &g_spiCfg);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: error", __func__);
return HDF_FAILURE;
@@ -58,6 +61,37 @@ static int32_t SpiSetCfgTest(struct SpiTest *test)
return ret;
}
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 < 4) {
bits = 4;
} else if (bits > 16) {
bits = 16;
}
for (i = 0; i < len;) {
if (bits <= 8) {
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 <= 8) ? 1 : 2;
}
HDF_LOGE("%s: mem size(%u) compare success", __func__, len);
return HDF_SUCCESS;
}
static int32_t SpiTransferTest(struct SpiTest *test)
{
int32_t i;
@@ -74,7 +108,10 @@ static int32_t SpiTransferTest(struct SpiTest *test)
return HDF_FAILURE;
}
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]);
HDF_LOGE("%s: wbuf[%d] = 0x%x rbuf[%d] = 0x%x", __func__, i, test->wbuf[i], i, test->rbuf[i]);
}
if (SpiCmpMemByBits(msg.wbuf, msg.rbuf, msg.len, g_spiCfg.bitsPerWord) != HDF_SUCCESS) {
return HDF_FAILURE;
}
HDF_LOGE("%s: success", __func__);
return HDF_SUCCESS;
@@ -100,6 +137,87 @@ static int32_t SpiReadTest(struct SpiTest *test)
return HDF_SUCCESS;
}
#define DMA_TRANSFER_SINGLE_MAX (1024 * 64 - 1)
#define DMA_TRANSFER_SINGLE_CNT (4)
#define DMA_TRANSFER_SINGLE_LEFT (254)
#define DMA_TRANSFER_SIZE_TOTAL (DMA_TRANSFER_SINGLE_MAX * DMA_TRANSFER_SINGLE_CNT + DMA_TRANSFER_SINGLE_LEFT)
#define DMA_TRANSFER_BUF_SEED (0x5A)
static void SpiSetDmaMsg(struct SpiMsg *msg, uint8_t *wbuf, uint8_t *rbuf, uint32_t len)
{
uint32_t i;
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;
}
static int32_t SpiDmaTest(struct SpiTest *test)
{
int ret = HDF_SUCCESS;
uint8_t *wbuf = NULL;
uint8_t *rbuf = NULL;
uint8_t oldMode;
struct SpiMsg msg;
uint32_t len = DMA_TRANSFER_SIZE_TOTAL;
oldMode = g_spiCfg.transferMode;
g_spiCfg.transferMode = SPI_DMA_TRANSFER;
if (SpiSetCfg(test->handle, &g_spiCfg) != HDF_SUCCESS) {
return HDF_FAILURE;
}
wbuf = (uint8_t *)OsalMemAllocAlign(CACHE_ALIGNED_SIZE, len);
if (wbuf == NULL) {
return HDF_ERR_MALLOC_FAIL;
}
rbuf = (uint8_t *)OsalMemAllocAlign(CACHE_ALIGNED_SIZE, len);
if (wbuf == NULL) {
OsalMemFree(wbuf);
return HDF_ERR_MALLOC_FAIL;
}
SpiSetDmaMsg(&msg, wbuf, rbuf, len);
ret = SpiTransfer(test->handle, &msg, 1);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: spi transfer err", __func__);
goto __OUT;
}
ret = SpiCmpMemByBits(msg.wbuf, msg.rbuf, msg.len, g_spiCfg.bitsPerWord);
if (ret != HDF_SUCCESS) {
goto __OUT;
}
ret = SpiWrite(test->handle, msg.wbuf, msg.len);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: spi write err", __func__);
goto __OUT;
}
ret = SpiRead(test->handle, msg.rbuf, msg.len);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: spi read err", __func__);
goto __OUT;
}
__OUT:
OsalMemFree(wbuf);
OsalMemFree(rbuf);
g_spiCfg.transferMode = oldMode;
(void)SpiSetCfg(test->handle, &g_spiCfg);
HDF_LOGE("%s: success", __func__);
return ret;
}
static int32_t SpiReliabilityTest(struct SpiTest *test)
{
struct SpiCfg cfg = {0};
@@ -113,6 +231,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;
}
@@ -138,6 +258,10 @@ static int32_t SpiTestAll(struct SpiTest *test)
error++;
}
total++;
if (SpiDmaTest(test) != HDF_SUCCESS) {
error++;
}
total++;
if (SpiReliabilityTest(test) != HDF_SUCCESS) {
error++;
}
@@ -146,11 +270,12 @@ static int32_t SpiTestAll(struct SpiTest *test)
return HDF_SUCCESS;
}
struct SpiTestFunc g_spiTestFunc[] = {
static struct SpiTestFunc g_spiTestFunc[] = {
{SPI_SET_CFG_TEST, SpiSetCfgTest},
{SPI_TRANSFER_TEST, SpiTransferTest},
{SPI_WRITE_TEST, SpiWriteTest},
{SPI_READ_TEST, SpiReadTest},
{SPI_DMA_TEST, SpiDmaTest},
{SPI_RELIABILITY_TEST, SpiReliabilityTest},
{SPI_PERFORMANCE_TEST, NULL},
{SPI_TEST_ALL, SpiTestAll},
@@ -161,6 +286,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 ret %d", __func__, cmd, ret);
if (test == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
+1
View File
@@ -17,6 +17,7 @@ enum SpiTestCmd {
SPI_TRANSFER_TEST,
SPI_WRITE_TEST,
SPI_READ_TEST,
SPI_DMA_TEST,
SPI_RELIABILITY_TEST,
SPI_PERFORMANCE_TEST,
SPI_TEST_ALL,