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