• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2023 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "dmac_core.h"
10 #include <string.h>
11 #include "hdf_log.h"
12 #include "osal_io.h"
13 #include "osal_irq.h"
14 #include "osal_mem.h"
15 
16 #define HDF_LOG_TAG dmac_core
17 
18 #define DMA_ALIGN_SIZE 256
19 #define DMA_MAX_TRANS_SIZE_DEFAULT 256
20 
DmacCntlrCheckOps(struct DmaCntlr * cntlr)21 static int32_t DmacCntlrCheckOps(struct DmaCntlr *cntlr)
22 {
23     if (cntlr->getChanInfo == NULL) {
24         HDF_LOGE("DmacCntlrCheckOps: getChanInfo is null!");
25         return HDF_ERR_INVALID_OBJECT;
26     }
27     if (cntlr->dmaChanEnable == NULL) {
28         HDF_LOGE("DmacCntlrCheckOps: dmaChanEnable is null!");
29         return HDF_ERR_INVALID_OBJECT;
30     }
31     if (cntlr->dmaM2mChanEnable == NULL) {
32         HDF_LOGE("DmacCntlrCheckOps: dmaM2mChanEnable is null!");
33         return HDF_ERR_INVALID_OBJECT;
34     }
35     if (cntlr->dmacChanDisable == NULL) {
36         HDF_LOGE("DmacCntlrCheckOps: dmacChanDisable is null!");
37         return HDF_ERR_INVALID_OBJECT;
38     }
39     if (cntlr->dmacCacheInv == NULL) {
40         HDF_LOGE("DmacCntlrCheckOps: dmacCacheInv is null!");
41         return HDF_ERR_INVALID_OBJECT;
42     }
43     if (cntlr->dmacCacheFlush == NULL) {
44         HDF_LOGE("DmacCntlrCheckOps: dmacCacheFlush is null!");
45         return HDF_ERR_INVALID_OBJECT;
46     }
47     if (cntlr->dmacPaddrToVaddr == NULL) {
48         HDF_LOGE("DmacCntlrCheckOps: dmacPaddrToVaddr is null!");
49         return HDF_ERR_INVALID_OBJECT;
50     }
51     if (cntlr->dmacVaddrToPaddr == NULL) {
52         HDF_LOGE("DmacCntlrCheckOps: dmacVaddrToPaddr is null!");
53         return HDF_ERR_INVALID_OBJECT;
54     }
55     if (cntlr->dmacGetChanStatus == NULL) {
56         HDF_LOGE("DmacCntlrCheckOps: dmacGetChanStatus is null!");
57         return HDF_ERR_INVALID_OBJECT;
58     }
59     if (cntlr->dmacGetCurrDestAddr == NULL) {
60         HDF_LOGE("DmacCntlrCheckOps: dmacGetCurrDestAddr is null!");
61         return HDF_ERR_INVALID_OBJECT;
62     }
63     return HDF_SUCCESS;
64 }
65 
DmacCntlrCheckParam(struct DmaCntlr * cntlr)66 static int32_t DmacCntlrCheckParam(struct DmaCntlr *cntlr)
67 {
68     if (cntlr == NULL) {
69         HDF_LOGE("DmacCntlrCheckParam: cntlr is null!");
70         return HDF_ERR_INVALID_OBJECT;
71     }
72     if (cntlr->maxTransSize == 0) {
73         HDF_LOGE("DmacCntlrCheckParam: maxTransSize is invaild!");
74         return HDF_ERR_INVALID_OBJECT;
75     }
76     if (cntlr->channelNum == 0 || cntlr->channelNum > DMAC_CHAN_NUM_MAX) {
77         HDF_LOGE("DmacCntlrCheckParam: invalid channelNum:%u!", cntlr->channelNum);
78         return HDF_ERR_INVALID_OBJECT;
79     }
80     return HDF_SUCCESS;
81 }
82 
DmacCntlrCheckInit(struct DmaCntlr * cntlr)83 static int32_t DmacCntlrCheckInit(struct DmaCntlr *cntlr)
84 {
85     int32_t ret;
86 
87     ret = DmacCntlrCheckParam(cntlr);
88     if (ret != HDF_SUCCESS) {
89         HDF_LOGE("DmacCntlrCheckInit: dmac cntlr check param fail!");
90         return ret;
91     }
92     ret = DmacCntlrCheckOps(cntlr);
93     if (ret != HDF_SUCCESS) {
94         HDF_LOGE("DmacCntlrCheckInit: dmac cntlr check ops fail!");
95         return ret;
96     }
97     return HDF_SUCCESS;
98 }
99 
DmacCntlrCheck(struct DmaCntlr * cntlr)100 static int32_t DmacCntlrCheck(struct DmaCntlr *cntlr)
101 {
102     int32_t ret;
103 
104     ret = DmacCntlrCheckInit(cntlr);
105     if (ret != HDF_SUCCESS) {
106         HDF_LOGE("DmacCntlrCheck: dmac cntlr check init fail!");
107         return ret;
108     }
109     if (cntlr->channelList == NULL) {
110         HDF_LOGE("DmacCntlrCheck: channelList is null!");
111         return HDF_ERR_INVALID_OBJECT;
112     }
113     return HDF_SUCCESS;
114 }
115 
DmaCntlrCreate(struct HdfDeviceObject * device)116 struct DmaCntlr *DmaCntlrCreate(struct HdfDeviceObject *device)
117 {
118     struct DmaCntlr *cntlr = NULL;
119 
120     if (device == NULL) {
121         HDF_LOGE("DmaCntlrCreate: device is null!");
122         return NULL;
123     }
124     cntlr = (struct DmaCntlr *)OsalMemCalloc(sizeof(struct DmaCntlr));
125     if (cntlr == NULL) {
126         HDF_LOGE("DmaCntlrCreate: memcalloc cntlr fail!");
127         return NULL;
128     }
129     cntlr->device = device;
130     return cntlr;
131 }
132 
DmacFreeLli(struct DmacChanInfo * chanInfo)133 static void DmacFreeLli(struct DmacChanInfo *chanInfo)
134 {
135     if (chanInfo != NULL && chanInfo->lli != NULL) {
136         OsalMemFree(chanInfo->lli);
137         chanInfo->lli = NULL;
138         chanInfo->lliCnt = 0;
139     }
140 }
141 
142 /*
143  * If private is allocated, release private before calling this function
144  */
DmaCntlrDestroy(struct DmaCntlr * cntlr)145 void DmaCntlrDestroy(struct DmaCntlr *cntlr)
146 {
147     uint16_t i;
148 
149     if (cntlr == NULL || cntlr->channelNum > DMAC_CHAN_NUM_MAX) {
150         HDF_LOGE("DmaCntlrDestroy: dma cntlr is null or channel is invalid!");
151         return;
152     }
153     if (cntlr->channelList != NULL) {
154         for (i = 0; i < cntlr->channelNum; i++) {
155             DmacFreeLli(&(cntlr->channelList[i]));
156         }
157         OsalMemFree(cntlr->channelList);
158         cntlr->channelList = NULL;
159         cntlr->channelNum = 0;
160     }
161     /* Private is released by the caller */
162     cntlr->private = NULL;
163     OsalMemFree(cntlr);
164 }
165 
DmacEventCallback(struct DmacChanInfo * chanInfo)166 static void DmacEventCallback(struct DmacChanInfo *chanInfo)
167 {
168     if (chanInfo->status == DMAC_CHN_ERROR) {
169         DmaEventSignal(&chanInfo->waitEvent, DMAC_EVENT_ERROR);
170     } else {
171         DmaEventSignal(&chanInfo->waitEvent, DMAC_EVENT_DONE);
172     }
173 }
174 
DmacCallbackHandle(struct DmacChanInfo * chanInfo)175 static void DmacCallbackHandle(struct DmacChanInfo *chanInfo)
176 {
177     if (chanInfo->transType == TRASFER_TYPE_M2M) {
178         DmacEventCallback(chanInfo);
179         return;
180     }
181     if (chanInfo->callback != NULL) {
182         chanInfo->callback(chanInfo->callbackData, chanInfo->status);
183     }
184 }
185 
DmacWaitM2mSendComplete(struct DmaCntlr * cntlr,struct DmacChanInfo * chanInfo)186 static int32_t DmacWaitM2mSendComplete(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo)
187 {
188     uint32_t ret;
189 
190     if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
191         HDF_LOGE("DmacWaitM2mSendComplete: dmac cntlr check fail!");
192         return HDF_ERR_INVALID_OBJECT;
193     }
194 
195     ret = DmaEventWait(&chanInfo->waitEvent, DMAC_EVENT_DONE | DMAC_EVENT_ERROR, DMA_EVENT_WAIT_DEF_TIME);
196     if (ret == DMAC_EVENT_ERROR) {
197         HDF_LOGE("DmacWaitM2mSendComplete: wait event error!");
198         return DMAC_CHN_ERROR;
199     } else if (ret == LOS_ERRNO_EVENT_READ_TIMEOUT) {
200         HDF_LOGE("DmacWaitM2mSendComplete: wait event timeout!");
201         return DMAC_CHN_TIMEOUT;
202     }
203 
204     cntlr->dmacChanDisable(cntlr, chanInfo->channel);
205     return DMAC_CHN_SUCCESS;
206 }
207 
DmacAllocateChannel(struct DmaCntlr * cntlr)208 static int32_t DmacAllocateChannel(struct DmaCntlr *cntlr)
209 {
210     uint16_t i;
211     uint32_t flags;
212 
213     if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
214         HDF_LOGE("DmacAllocateChannel: dmac cntlr check fail!");
215         return HDF_ERR_INVALID_OBJECT;
216     }
217 
218     OsalSpinLockIrqSave(&cntlr->lock, &flags);
219     for (i = 0; i < cntlr->channelNum; i++) {
220         if (cntlr->channelList[i].useStatus ==  DMAC_CHN_VACANCY) {
221             cntlr->channelList[i].useStatus = DMAC_CHN_ALLOCAT;
222             OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
223             return (int32_t)i;
224         }
225     }
226     OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
227     HDF_LOGE("DmacAllocateChannel: dmac allocate channel fail!");
228     return HDF_FAILURE;
229 }
230 
DmacFreeChannel(struct DmaCntlr * cntlr,uint16_t channel)231 static void DmacFreeChannel(struct DmaCntlr *cntlr, uint16_t channel)
232 {
233     uint32_t flags;
234 
235     if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
236         HDF_LOGE("DmacFreeChannel: dmac cntlr check fail!");
237         return;
238     }
239 
240     OsalSpinLockIrqSave(&cntlr->lock, &flags);
241     DmacFreeLli(&cntlr->channelList[channel]);
242     cntlr->channelList[channel].useStatus = DMAC_CHN_VACANCY;
243     OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
244 }
245 
DmacRequestChannel(struct DmaCntlr * cntlr,struct DmacMsg * msg)246 static struct DmacChanInfo *DmacRequestChannel(struct DmaCntlr *cntlr, struct DmacMsg *msg)
247 {
248     int32_t ret;
249     int32_t chan;
250     struct DmacChanInfo *chanInfo = NULL;
251 
252     if (DmacCntlrCheck(cntlr) != HDF_SUCCESS || msg == NULL) {
253         HDF_LOGE("DmacRequestChannel: cntlr check fail or msg is null!");
254         return NULL;
255     }
256 
257     chan = DmacAllocateChannel(cntlr);
258     if (chan < 0) {
259         HDF_LOGE("DmacRequestChannel: dmac allocate channel fail!");
260         return NULL;
261     }
262     chanInfo = &(cntlr->channelList[chan]);
263     chanInfo->channel = (unsigned int)chan;
264     chanInfo->transType = msg->transType;
265     ret = cntlr->getChanInfo(cntlr, chanInfo, msg);
266     if (ret < 0) {
267         DmacFreeChannel(cntlr, chan);
268         HDF_LOGE("DmacRequestChannel: get channel info fail, ret = %d!", ret);
269         return NULL;
270     }
271 #ifdef DMA_CORE_DEBUG
272     HDF_LOGD("DmacRequestChannel: chan = %d, type = %d srcWidth = %u, destWidth = %u, config = 0x%x, lliEnflag = 0x%x",
273         chan, chanInfo->transType, chanInfo->srcWidth, chanInfo->destWidth, chanInfo->config, chanInfo->lliEnFlag);
274 #endif
275     return chanInfo;
276 }
277 
DmacGetDummyBuf(struct DmaCntlr * cntlr,struct DmacChanInfo * chan)278 static uintptr_t DmacGetDummyBuf(struct DmaCntlr *cntlr, struct DmacChanInfo *chan)
279 {
280     if (chan->dummyPage == NULL) {
281         chan->dummyPage = OsalMemCalloc(sizeof(cntlr->maxTransSize));
282     }
283 
284     return (chan->dummyPage == NULL) ? 0 : (uintptr_t)LOS_PaddrQuery(chan->dummyPage);
285 }
286 
DmacAlignedTransMax(size_t maxSize,uint8_t srcWidth,uint8_t destWidth)287 static inline size_t DmacAlignedTransMax(size_t maxSize, uint8_t srcWidth, uint8_t destWidth)
288 {
289     size_t ret;
290     uint8_t maxWidth = (srcWidth >= destWidth) ? srcWidth : destWidth;
291 
292     ret = ((maxWidth == 0) ? maxSize : (maxSize - (maxSize % maxWidth)));
293 #ifdef DMA_CORE_DEBUG
294     HDF_LOGD("DmacAlignedTransMax: max:%zu, srcwidth:%u, dstwidth:%hhu, alignedmax:%zu!",
295         maxSize, srcWidth, destWidth, ret);
296 #endif
297     return ret;
298 }
299 
DmacFillLli(struct DmaCntlr * cntlr,struct DmacChanInfo * chanInfo,uintptr_t srcaddr,uintptr_t dstaddr,size_t length)300 static int32_t DmacFillLli(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo,
301     uintptr_t srcaddr, uintptr_t dstaddr, size_t length)
302 {
303     int32_t ret = HDF_SUCCESS;
304     uint16_t i;
305     uint16_t lliNum;
306     struct DmacLli  *plli = NULL;
307     size_t alignedMax;
308     uintptr_t srcDummy = 0;
309     uintptr_t dstDummy = 0;
310 
311     if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
312         return HDF_ERR_INVALID_OBJECT;
313     }
314     if (chanInfo == NULL || chanInfo->lli == NULL) {
315         HDF_LOGE("DmacFillLli: chanInfo or lli is null!");
316         return HDF_ERR_INVALID_PARAM;
317     }
318     alignedMax = DmacAlignedTransMax(cntlr->maxTransSize, chanInfo->srcWidth, chanInfo->destWidth);
319     if (alignedMax == 0) {
320         HDF_LOGE("DmacFillLli: maxTransSize:%zu srcWidth:%u dstWidth:%u!", cntlr->maxTransSize,
321             chanInfo->srcWidth, chanInfo->destWidth);
322         return HDF_ERR_INVALID_PARAM;
323     }
324     plli = chanInfo->lli;
325 
326     if (srcaddr == 0) {
327         srcaddr = srcDummy = DmacGetDummyBuf(cntlr, chanInfo);
328     }
329     if (dstaddr == 0) {
330         dstaddr = dstDummy = DmacGetDummyBuf(cntlr, chanInfo);
331     }
332     if (srcaddr == 0 || dstaddr == 0) {
333         return HDF_ERR_MALLOC_FAIL;
334     }
335 
336     for (i = 0, lliNum = chanInfo->lliCnt; i < lliNum; i++, plli++) {
337         plli->nextLli = (uintptr_t)cntlr->dmacVaddrToPaddr((void *)plli) + (uintptr_t)sizeof(struct DmacLli);
338         plli->nextLli = (i < lliNum - 1) ? (plli->nextLli + chanInfo->lliEnFlag) : 0;
339         plli->count = ((i < lliNum - 1) || ((length % alignedMax) == 0)) ? alignedMax : (length % alignedMax);
340 
341         plli->srcAddr = srcaddr;
342         plli->destAddr = dstaddr;
343         plli->config = chanInfo->config;
344 
345 #ifdef DMA_CORE_DEBUG
346         HDF_LOGD("DmacFillLli: plli=0x%lx, next=0x%lx, count=0x%lx, src=0x%lx, dst=0x%lx, cfg=0x%lx",
347             (uintptr_t)cntlr->dmacVaddrToPaddr(plli), plli->nextLli,
348             plli->count, plli->srcAddr, plli->destAddr, plli->config);
349 #endif
350         dstaddr += (chanInfo->transType == TRASFER_TYPE_P2M && dstDummy == 0) ? plli->count : 0;
351         srcaddr += (chanInfo->transType == TRASFER_TYPE_M2P && srcDummy == 0) ? plli->count : 0;
352     }
353     plli = chanInfo->lli;
354     cntlr->dmacCacheFlush((uintptr_t)plli, (uintptr_t)plli + (uintptr_t)(sizeof(struct DmacLli) * lliNum));
355     return ret;
356 }
357 
DmacAllocLli(struct DmacChanInfo * chanInfo,size_t length,size_t maxSize)358 static int32_t DmacAllocLli(struct DmacChanInfo *chanInfo, size_t length, size_t maxSize)
359 {
360     size_t lliNum;
361     size_t allocLength;
362     void *allocAddr = NULL;
363 
364     if (chanInfo == NULL || maxSize == 0) {
365         HDF_LOGE("DmacAllocLli: chanInfo is null or maxSize is invalid!");
366         return HDF_ERR_INVALID_PARAM;
367     }
368     lliNum = (length / maxSize) + ((length % maxSize) > 0 ? 1 : 0);
369     if (lliNum > 2048) {  /* 2048: lliNum is not more than 2048 */
370         HDF_LOGE("DmacAllocLli: lliNum %zu is bigger than 2048!", lliNum);
371         return HDF_ERR_INVALID_PARAM;
372     }
373 
374     allocLength = lliNum * sizeof(struct DmacLli);
375     allocLength = ALIGN(allocLength, CACHE_ALIGNED_SIZE);
376     allocAddr = OsalMemAllocAlign(DMA_ALIGN_SIZE, allocLength);
377     if (allocAddr == NULL) {
378         HDF_LOGE("DmacAllocLli: memalloc lli fail!");
379         return HDF_FAILURE;
380     }
381     if (memset_s(allocAddr, allocLength, 0, allocLength) != EOK) {
382         OsalMemFree(allocAddr);
383         HDF_LOGE("DmacAllocLli: memset_s fail");
384         return HDF_FAILURE;
385     }
386 
387     chanInfo->lliCnt = (uint16_t)lliNum;
388     chanInfo->lli = (struct DmacLli *)allocAddr;
389     return HDF_SUCCESS;
390 }
391 
DmacPeriphTransfer(struct DmaCntlr * cntlr,struct DmacMsg * msg)392 static int32_t DmacPeriphTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg)
393 {
394     int32_t ret;
395     struct DmacChanInfo *chanInfo = NULL;
396 
397     chanInfo = DmacRequestChannel(cntlr, msg);
398     if (chanInfo == NULL) {
399         HDF_LOGE("DmacPeriphTransfer: request channel fail!");
400         return HDF_ERR_INVALID_PARAM;
401     }
402     if (msg->srcAddr == 0 && msg->destAddr == 0) {
403         HDF_LOGE("DmacPeriphTransfer: src addr & dest addr both null!");
404         return HDF_ERR_INVALID_PARAM;
405     }
406     chanInfo->callbackData = msg->para;
407     chanInfo->callback = (DmacCallback *)msg->cb;
408     ret = DmacAllocLli(chanInfo, msg->transLen,
409         DmacAlignedTransMax(cntlr->maxTransSize, chanInfo->srcWidth, chanInfo->destWidth));
410     if (ret != HDF_SUCCESS) {
411         DmacFreeChannel(cntlr, chanInfo->channel);
412         HDF_LOGE("DmacPeriphTransfer: dmac aligned trans max fail!");
413         return ret;
414     }
415     ret = DmacFillLli(cntlr, chanInfo, msg->srcAddr, msg->destAddr, msg->transLen);
416     if (ret != HDF_SUCCESS) {
417         DmacFreeLli(chanInfo);
418         DmacFreeChannel(cntlr, chanInfo->channel);
419         HDF_LOGE("DmacPeriphTransfer: dmac fill Lli fail!");
420         return ret;
421     }
422     ret = cntlr->dmaChanEnable(cntlr, chanInfo);
423     if (ret != HDF_SUCCESS) {
424         HDF_LOGE("DmacPeriphTransfer: enable channel fail!");
425         DmacFreeLli(chanInfo);
426         DmacFreeChannel(cntlr, chanInfo->channel);
427         return HDF_FAILURE;
428     }
429     return HDF_SUCCESS;
430 }
431 
DmacM2mTransfer(struct DmaCntlr * cntlr,struct DmacMsg * msg)432 static int32_t DmacM2mTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg)
433 {
434     int32_t ret;
435     size_t leftSize;
436     size_t dmaSize;
437     size_t dmaCount = 0;
438     struct DmacChanInfo *chanInfo = NULL;
439 
440     if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
441         HDF_LOGE("DmacM2mTransfer: dmac cntlr check fail!");
442         return HDF_ERR_INVALID_OBJECT;
443     }
444 
445     chanInfo = DmacRequestChannel(cntlr, msg);
446     if (chanInfo == NULL) {
447         HDF_LOGE("DmacM2mTransfer: request channel fail!");
448         return HDF_FAILURE;
449     }
450     chanInfo->callback = msg->cb;
451     chanInfo->callbackData = msg->para;
452     cntlr->dmacCacheFlush((uintptr_t)msg->srcAddr, (uintptr_t)(msg->srcAddr + msg->transLen));
453     cntlr->dmacCacheInv((uintptr_t)msg->destAddr, (uintptr_t)(msg->destAddr + msg->transLen));
454     leftSize = msg->transLen;
455     while (leftSize > 0) {
456         dmaSize = (leftSize >= cntlr->maxTransSize) ? cntlr->maxTransSize : leftSize;
457         ret = cntlr->dmaM2mChanEnable(cntlr, chanInfo, msg->srcAddr + dmaCount * cntlr->maxTransSize,
458             msg->destAddr + dmaCount * cntlr->maxTransSize, dmaSize);
459         if (ret != HDF_SUCCESS) {
460             HDF_LOGE("DmacM2mTransfer: enable channel m2m fail!");
461             DmacFreeChannel(cntlr, chanInfo->channel);
462             if (chanInfo->callback != NULL) {
463                 chanInfo->callback(chanInfo->callbackData, DMAC_CHN_ERROR);
464             }
465             return ret;
466         }
467         ret = DmacWaitM2mSendComplete(cntlr, chanInfo);
468         if (ret != DMAC_CHN_SUCCESS) {
469             HDF_LOGE("DmacM2mTransfer: m2m transfer fail, ret = %d!", ret);
470             DmacFreeChannel(cntlr, chanInfo->channel);
471             if (chanInfo->callback != NULL) {
472                 chanInfo->callback(chanInfo->callbackData, ret);
473             }
474             return HDF_FAILURE;
475         }
476         leftSize -= dmaSize;
477         dmaCount++;
478     }
479     DmacFreeChannel(cntlr, chanInfo->channel);
480     if (chanInfo->callback != NULL) {
481         chanInfo->callback(chanInfo->callbackData, DMAC_CHN_SUCCESS);
482     }
483     return HDF_SUCCESS;
484 }
485 
DmaCntlrTransfer(struct DmaCntlr * cntlr,struct DmacMsg * msg)486 int32_t DmaCntlrTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg)
487 {
488     uintptr_t phyAddr;
489 
490     if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
491         HDF_LOGE("DmaCntlrTransfer: dmac cntlr check fail!");
492         return HDF_ERR_INVALID_OBJECT;
493     }
494     if (msg == NULL) {
495         HDF_LOGE("DmaCntlrTransfer: msg is null!");
496         return HDF_ERR_INVALID_PARAM;
497     }
498     if (msg->transType == TRASFER_TYPE_P2M) {
499         if (msg->destAddr != 0) {
500             phyAddr = (uintptr_t)cntlr->dmacPaddrToVaddr((paddr_t)msg->destAddr);
501             cntlr->dmacCacheInv(phyAddr, (uintptr_t)(phyAddr + msg->transLen));
502         }
503     } else if (msg->transType == TRASFER_TYPE_M2P) {
504         if (msg->srcAddr != 0) {
505             phyAddr = (uintptr_t)cntlr->dmacPaddrToVaddr((paddr_t)msg->srcAddr);
506             cntlr->dmacCacheFlush(phyAddr, (uintptr_t)(phyAddr + msg->transLen));
507         }
508     } else if (msg->transType == TRASFER_TYPE_M2M) {
509         return DmacM2mTransfer(cntlr, msg);
510     } else {
511         HDF_LOGE("DmaCntlrTransfer: invalid transType %d!", msg->transType);
512         return HDF_FAILURE;
513     }
514     return DmacPeriphTransfer(cntlr, msg);
515 }
516 
DmaGetCurrChanDestAddr(struct DmaCntlr * cntlr,uint16_t chan)517 uintptr_t DmaGetCurrChanDestAddr(struct DmaCntlr *cntlr, uint16_t chan)
518 {
519     if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
520         HDF_LOGE("DmaGetCurrChanDestAddr: dmac cntlr check fail!");
521         return HDF_ERR_INVALID_OBJECT;
522     }
523     return cntlr->dmacGetCurrDestAddr(cntlr, chan);
524 }
525 
DmacIsr(uint32_t irq,void * dev)526 static uint32_t DmacIsr(uint32_t irq, void *dev)
527 {
528     uint16_t i;
529     int channelStatus;
530     struct DmaCntlr *cntlr = (struct DmaCntlr *)dev;
531 
532     if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
533         HDF_LOGE("DmacIsr: dmac cntlr check fail!");
534         return HDF_ERR_INVALID_OBJECT;
535     }
536 
537     if (irq != cntlr->irq || cntlr->channelNum > DMAC_CHAN_NUM_MAX) {
538         HDF_LOGE("DmacIsr: cntlr parm err! irq:%d, channel:%u!", cntlr->irq, cntlr->channelNum);
539         return HDF_ERR_INVALID_OBJECT;
540     }
541     for (i = 0; i < cntlr->channelNum; i++) {
542         channelStatus = cntlr->dmacGetChanStatus(cntlr, i);
543         if (channelStatus == DMAC_CHN_SUCCESS || channelStatus == DMAC_CHN_ERROR) {
544             cntlr->channelList[i].status = channelStatus;
545             DmacCallbackHandle(&(cntlr->channelList[i]));
546             DmacFreeChannel(cntlr, cntlr->channelList[i].channel);
547         }
548     }
549     return HDF_SUCCESS;
550 }
551 
DmacCntlrAdd(struct DmaCntlr * cntlr)552 int32_t DmacCntlrAdd(struct DmaCntlr *cntlr)
553 {
554     int32_t ret;
555     uint16_t i;
556 
557     ret = DmacCntlrCheckInit(cntlr);
558     if (ret != HDF_SUCCESS) {
559         HDF_LOGE("DmacCntlrAdd: dmac cntlr check fail!");
560         return ret;
561     }
562 
563     (void)OsalSpinInit(&cntlr->lock);
564     ret = OsalRegisterIrq(cntlr->irq, 0, (OsalIRQHandle)DmacIsr, "PlatDmac", cntlr);
565     if (ret != HDF_SUCCESS) {
566         HDF_LOGE("DmacCntlrAdd: request irq %u fail, ret = %d!", cntlr->irq, ret);
567         (void)OsalSpinDestroy(&cntlr->lock);
568         return ret;
569     }
570     cntlr->channelList = (struct DmacChanInfo *)OsalMemCalloc(sizeof(struct DmacChanInfo) * cntlr->channelNum);
571     if (cntlr->channelList == NULL) {
572         HDF_LOGE("DmacCntlrAdd: memcalloc channelList fail!");
573         (void)OsalUnregisterIrq(cntlr->irq, cntlr);
574         (void)OsalSpinDestroy(&cntlr->lock);
575         return HDF_ERR_MALLOC_FAIL;
576     }
577     for (i = 0; i < cntlr->channelNum; i++) {
578         cntlr->dmacChanDisable(cntlr, i);
579         DmaEventInit(&(cntlr->channelList[i].waitEvent));
580         cntlr->channelList[i].useStatus = DMAC_CHN_VACANCY;
581     }
582     return HDF_SUCCESS;
583 }
584 
DmacCntlrRemove(struct DmaCntlr * cntlr)585 void DmacCntlrRemove(struct DmaCntlr *cntlr)
586 {
587     (void)cntlr;
588 }
589