1 /*
2 * Copyright (c) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "dmac_hi35xx.h"
17 #include "device_resource_if.h"
18 #include "dmac_core.h"
19 #include "hdf_device_desc.h"
20 #include "hdf_dlist.h"
21 #include "hdf_log.h"
22 #include "los_hw.h"
23 #include "los_hwi.h"
24 #include "los_vm_phys.h"
25 #include "osal_io.h"
26 #include "osal_mem.h"
27 #include "osal_time.h"
28
29 #define HDF_LOG_TAG dmac_hi35xx
30
31 #ifdef __cplusplus
32 #if __cplusplus
33 extern "C" {
34 #endif /* __cplusplus */
35 #endif /* __cplusplus */
36
37 static struct HiDmacPeripheral g_peripheral[HIDMAC_MAX_PERIPHERALS] = {
38 { 0, I2C0_RX_FIFO, HIDMAC_HOST0, 0x40000004, PERI_MODE_8BIT, 0 },
39 { 1, I2C0_TX_FIFO, HIDMAC_HOST0, 0x80000004, PERI_MODE_8BIT, 1 },
40 { 2, I2C1_RX_FIFO, HIDMAC_HOST0, 0x40000004, PERI_MODE_8BIT, 2 },
41 { 3, I2C1_TX_FIFO, HIDMAC_HOST0, 0x80000004, PERI_MODE_8BIT, 3 },
42 { 4, I2C2_RX_FIFO, HIDMAC_HOST0, 0x40000004, PERI_MODE_8BIT, 4 },
43 { 5, I2C2_TX_FIFO, HIDMAC_HOST0, 0x80000004, PERI_MODE_8BIT, 5 },
44 { 6, 0, HIDMAC_NOT_USE, 0, 0, 6 },
45 { 7, 0, HIDMAC_NOT_USE, 0, 0, 7 },
46 { 8, 0, HIDMAC_NOT_USE, 0, 0, 8 },
47 { 9, 0, HIDMAC_NOT_USE, 0, 0, 9 },
48 { 10, 0, HIDMAC_NOT_USE, 0, 0, 10 },
49 { 11, 0, HIDMAC_NOT_USE, 0, 0, 11 },
50 { 12, 0, HIDMAC_NOT_USE, 0, 0, 12 },
51 { 13, 0, HIDMAC_NOT_USE, 0, 0, 13 },
52 { 14, 0, HIDMAC_NOT_USE, 0, 0, 14 },
53 { 15, 0, HIDMAC_NOT_USE, 0, 0, 15 },
54 { 16, UART0_RX_ADDR, HIDMAC_HOST0, 0x47700004, PERI_MODE_8BIT, 16 },
55 { 17, UART0_TX_ADDR, HIDMAC_HOST0, 0x87700004, PERI_MODE_8BIT, 17 },
56 { 18, UART1_RX_ADDR, HIDMAC_HOST0, 0x47700004, PERI_MODE_8BIT, 18 },
57 { 19, UART1_TX_ADDR, HIDMAC_HOST0, 0x87700004, PERI_MODE_8BIT, 19 },
58 { 20, UART2_RX_ADDR, HIDMAC_HOST0, 0x47700004, PERI_MODE_8BIT, 20 },
59 { 21, UART2_TX_ADDR, HIDMAC_HOST0, 0x87700004, PERI_MODE_8BIT, 21 },
60 { 22, 0, HIDMAC_NOT_USE, 0, 0, 22 },
61 { 23, 0, HIDMAC_NOT_USE, 0, 0, 23 },
62 { 24, 0, HIDMAC_NOT_USE, 0, 0, 24 },
63 { 25, 0, HIDMAC_NOT_USE, 0, 0, 25 },
64 { 26, SPI0_RX_FIFO, HIDMAC_HOST0, 0x40000004, PERI_MODE_8BIT, 26 },
65 { 27, SPI0_TX_FIFO, HIDMAC_HOST0, 0x80000004, PERI_MODE_8BIT, 27 },
66 { 28, SPI1_RX_FIFO, HIDMAC_HOST0, 0x40000004, PERI_MODE_16BIT, 28 },
67 { 29, SPI1_TX_FIFO, HIDMAC_HOST0, 0x80000004, PERI_MODE_16BIT, 29 },
68 { 30, SPI2_RX_FIFO, HIDMAC_HOST0, 0x40000004, PERI_MODE_16BIT, 30 },
69 { 31, SPI2_TX_FIFO, HIDMAC_HOST0, 0x80000004, PERI_MODE_16BIT, 31 },
70 };
71 #define HIDMAC_PERIPH_ID_MAX 32
72
73 #define ERROR_STATUS_NUM_0 0
74 #define ERROR_STATUS_NUM_1 1
75 #define ERROR_STATUS_NUM_2 2
76 #define ERROR_STATUS_MAX 3
77
HiDmacIsrErrProc(struct DmaCntlr * cntlr,uint16_t chan)78 static int HiDmacIsrErrProc(struct DmaCntlr *cntlr, uint16_t chan)
79 {
80 unsigned int chanErrStats[ERROR_STATUS_MAX];
81
82 chanErrStats[ERROR_STATUS_NUM_0] = OSAL_READL(cntlr->remapBase + HIDMAC_INT_ERR1_OFFSET);
83 chanErrStats[ERROR_STATUS_NUM_0] = (chanErrStats[ERROR_STATUS_NUM_0] >> chan) & 0x01;
84 chanErrStats[ERROR_STATUS_NUM_1] = OSAL_READL(cntlr->remapBase + HIDMAC_INT_ERR2_OFFSET);
85 chanErrStats[ERROR_STATUS_NUM_1] = (chanErrStats[ERROR_STATUS_NUM_1] >> chan) & 0x01;
86 chanErrStats[ERROR_STATUS_NUM_2] = OSAL_READL(cntlr->remapBase + HIDMAC_INT_ERR3_OFFSET);
87 chanErrStats[ERROR_STATUS_NUM_2] = (chanErrStats[ERROR_STATUS_NUM_2] >> chan) & 0x01;
88 if ((chanErrStats[ERROR_STATUS_NUM_0] | chanErrStats[ERROR_STATUS_NUM_1] |
89 chanErrStats[ERROR_STATUS_NUM_2]) != 0) {
90 HDF_LOGE("%s: Err in hidma %d finish, ERR1:0x%x, ERR2:0x%x, ERR3:0x%x", __func__,
91 chan, chanErrStats[ERROR_STATUS_NUM_0], chanErrStats[ERROR_STATUS_NUM_1],
92 chanErrStats[ERROR_STATUS_NUM_2]);
93 OSAL_WRITEL(1 << chan, cntlr->remapBase + HIDMAC_INT_ERR1_RAW_OFFSET);
94 HDF_LOGE("HIDMAC_INT_ERR1_RAW = 0x%x", OSAL_READL(cntlr->remapBase + HIDMAC_INT_ERR1_RAW_OFFSET));
95 OSAL_WRITEL(1 << chan, cntlr->remapBase + HIDMAC_INT_ERR2_RAW_OFFSET);
96 HDF_LOGE("HIDMAC_INT_ERR2_RAW = 0x%x", OSAL_READL(cntlr->remapBase + HIDMAC_INT_ERR2_RAW_OFFSET));
97 OSAL_WRITEL(1 << chan, cntlr->remapBase + HIDMAC_INT_ERR3_RAW_OFFSET);
98 HDF_LOGE("HIDMAC_INT_ERR3_RAW = 0x%x", OSAL_READL(cntlr->remapBase + HIDMAC_INT_ERR3_RAW_OFFSET));
99 return DMAC_CHN_ERROR;
100 }
101 return 0;
102 }
103
HiDmacGetChanStat(struct DmaCntlr * cntlr,uint16_t chan)104 static int HiDmacGetChanStat(struct DmaCntlr *cntlr, uint16_t chan)
105 {
106 int ret;
107 unsigned long chanStatus;
108 unsigned long chanTcStatus;
109
110 chanStatus = OSAL_READL(cntlr->remapBase + HIDMAC_INT_STAT_OFFSET);
111 if ((chanStatus >> chan) & 0x1) {
112 chanTcStatus = OSAL_READL(cntlr->remapBase + HIDMAC_INT_TC1_OFFSET);
113 #ifdef DMAC_HI35XX_DEBUG
114 HDF_LOGD("%s: HIDMAC_INT_TC1 = 0x%lx, chan = %u", __func__, chanTcStatus, chan);
115 #endif
116 chanTcStatus = (chanTcStatus >> chan) & 0x1;
117 if (chanTcStatus != 0) {
118 OSAL_WRITEL(chanTcStatus << chan, cntlr->remapBase + HIDMAC_INT_TC1_RAW_OFFSET);
119 return DMAC_CHN_SUCCESS;
120 }
121 ret = HiDmacIsrErrProc(cntlr, chan);
122 if (ret != 0) {
123 HDF_LOGE("%s: fail, ret = %d", __func__, ret);
124 return DMAC_CHN_ERROR;
125 }
126 chanTcStatus = OSAL_READL(cntlr->remapBase + HIDMAC_INT_TC2_OFFSET);
127 #ifdef DMAC_HI35XX_DEBUG
128 HDF_LOGD("%s: HIDMAC_INT_TC2 = 0x%lx, chan = %u", __func__, chanTcStatus, chan);
129 #endif
130 chanTcStatus = (chanTcStatus >> chan) & 0x1;
131 if (chanTcStatus != 0) {
132 OSAL_WRITEL(chanTcStatus << chan, cntlr->remapBase + HIDMAC_INT_TC2_RAW_OFFSET);
133 }
134 }
135 return DMAC_NOT_FINISHED;
136 }
137
HiDmacGetPriId(uintptr_t periphAddr,int transType)138 static unsigned int HiDmacGetPriId(uintptr_t periphAddr, int transType)
139 {
140 unsigned int i;
141
142 /* only check p2m and m2p */
143 for (i = transType - 1; i < HIDMAC_MAX_PERIPHERALS; i += 2) {
144 if (g_peripheral[i].periphAddr == periphAddr) {
145 return i;
146 }
147 }
148 HDF_LOGE("%s: invalid peripheral addr", __func__);
149 return HIDMAC_PERIPH_ID_MAX;
150 }
151
HiDmacToLocalWitdh(uint32_t transferWitdh,uint32_t defaultWidth)152 static uint8_t HiDmacToLocalWitdh(uint32_t transferWitdh, uint32_t defaultWidth)
153 {
154 switch (transferWitdh) {
155 case 0x1:
156 return PERI_MODE_8BIT;
157 case 0x2:
158 return PERI_MODE_16BIT;
159 case 0x3:
160 return PERI_MODE_32BIT;
161 case 0x4:
162 return PERI_MODE_64BIT;
163 default:
164 break;
165 }
166 return defaultWidth;
167 }
168
HiDmacGetChanInfo(struct DmaCntlr * cntlr,struct DmacChanInfo * chanInfo,struct DmacMsg * msg)169 static int32_t HiDmacGetChanInfo(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo, struct DmacMsg *msg)
170 {
171 unsigned int periphId;
172 uint8_t localSrcWidth;
173 uint8_t localDstWidth;
174
175 if (cntlr == NULL) {
176 return HDF_ERR_INVALID_OBJECT;
177 }
178 if (chanInfo == NULL || msg == NULL) {
179 return HDF_ERR_INVALID_PARAM;
180 }
181
182 if (chanInfo->transType == TRASFER_TYPE_P2M || chanInfo->transType == TRASFER_TYPE_M2P) {
183 periphId = HiDmacGetPriId(DmacMsgGetPeriphAddr(msg), chanInfo->transType);
184 if (periphId >= HIDMAC_PERIPH_ID_MAX) {
185 HDF_LOGE("%s: invalid io address", __func__);
186 return HDF_ERR_INVALID_PARAM;
187 }
188 if (msg->srcWidth != msg->destWidth) {
189 HDF_LOGE("%s: src width:%u != dest width:%u", __func__, msg->srcWidth, msg->destWidth);
190 return HDF_ERR_INVALID_PARAM;
191 }
192 chanInfo->srcWidth = msg->srcWidth;
193 chanInfo->destWidth = chanInfo->srcWidth;
194 localSrcWidth = HiDmacToLocalWitdh(chanInfo->srcWidth, g_peripheral[periphId].transWidth);
195 localDstWidth = localSrcWidth;
196 chanInfo->config = g_peripheral[periphId].transCfg |
197 (localSrcWidth << HIDMAC_SRC_WIDTH_OFFSET) |
198 (localDstWidth << HIDMAC_DST_WIDTH_OFFSET) |
199 (g_peripheral[periphId].dynPeripNum << HIDMAC_PERI_ID_OFFSET);
200 }
201 chanInfo->lliEnFlag = HIDMAC_LLI_ENABLE;
202 return HDF_SUCCESS;
203 }
204
HiDmacDisable(struct DmaCntlr * cntlr,uint16_t channel)205 static inline void HiDmacDisable(struct DmaCntlr *cntlr, uint16_t channel)
206 {
207 if (cntlr != NULL) {
208 OSAL_WRITEL(HIDMAC_CX_DISABLE, cntlr->remapBase + HIDMAC_CX_CFG_OFFSET(channel));
209 }
210 }
211
212
213 #define HIDMAC_32BITS_MASK 0xFFFFFFFF
214 #define HIDMAC_32BITS_SHIFT 32
215
HiDmacStartM2M(struct DmaCntlr * cntlr,struct DmacChanInfo * chanInfo,uintptr_t psrc,uintptr_t pdst,size_t len)216 static int32_t HiDmacStartM2M(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo,
217 uintptr_t psrc, uintptr_t pdst, size_t len)
218 {
219 if (cntlr == NULL) {
220 HDF_LOGE("%s: invalid cntlr", __func__);
221 return HDF_ERR_INVALID_OBJECT;
222 }
223 if (chanInfo == NULL || len == 0) {
224 HDF_LOGE("%s: chanInfo null or invalid len:%zu", __func__, len);
225 return HDF_ERR_INVALID_PARAM;
226 }
227
228 OSAL_WRITEL(psrc & HIDMAC_32BITS_MASK, cntlr->remapBase + HIDMAC_CX_SRC_OFFSET_L(chanInfo->channel));
229 #ifdef LOSCFG_AARCH64
230 OSAL_WRITEL((psrc >> HIDMAC_32BITS_SHIFT) & HIDMAC_32BITS_MASK,
231 cntlr->remapBase + HIDMAC_CX_SRC_OFFSET_H(chanInfo->channel));
232 #else
233 OSAL_WRITEL(0, cntlr->remapBase + HIDMAC_CX_SRC_OFFSET_H(chanInfo->channel));
234 #endif
235
236 OSAL_WRITEL(pdst & HIDMAC_32BITS_MASK, cntlr->remapBase + HIDMAC_CX_DST_OFFSET_L(chanInfo->channel));
237 #ifdef LOSCFG_AARCH64
238 OSAL_WRITEL((pdst >> HIDMAC_32BITS_SHIFT) & HIDMAC_32BITS_MASK,
239 cntlr->remapBase + HIDMAC_CX_DST_OFFSET_H(chanInfo->channel));
240 #else
241 OSAL_WRITEL(0, cntlr->remapBase + HIDMAC_CX_DST_OFFSET_H(chanInfo->channel));
242 #endif
243
244 OSAL_WRITEL(0, cntlr->remapBase + HIDMAC_CX_LLI_OFFSET_L(chanInfo->channel));
245 OSAL_WRITEL(len, cntlr->remapBase + HIDMAC_CX_CNT0_OFFSET(chanInfo->channel));
246 OSAL_WRITEL(HIDMAC_CX_CFG_M2M, cntlr->remapBase + HIDMAC_CX_CFG_OFFSET(chanInfo->channel));
247 return HDF_SUCCESS;
248 }
249
HiDmacStartLli(struct DmaCntlr * cntlr,struct DmacChanInfo * chanInfo)250 static int32_t HiDmacStartLli(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo)
251 {
252 struct DmacLli *plli = NULL;
253
254 if (cntlr == NULL) {
255 HDF_LOGE("%s: invalid cntlr", __func__);
256 return HDF_ERR_INVALID_OBJECT;
257 }
258 if (chanInfo == NULL || chanInfo->lli == NULL) {
259 HDF_LOGE("%s: chanInfo or lli is null", __func__);
260 return HDF_ERR_INVALID_PARAM;
261 }
262 plli = chanInfo->lli;
263
264 OSAL_WRITEL(plli->srcAddr & HIDMAC_32BITS_MASK, cntlr->remapBase + HIDMAC_CX_SRC_OFFSET_L(chanInfo->channel));
265 #ifdef LOSCFG_AARCH64
266 OSAL_WRITEL((plli->srcAddr >> HIDMAC_32BITS_SHIFT) & HIDMAC_32BITS_MASK,
267 cntlr->remapBase + HIDMAC_CX_SRC_OFFSET_H(chanInfo->channel));
268 #else
269 OSAL_WRITEL(0, cntlr->remapBase + HIDMAC_CX_SRC_OFFSET_H(chanInfo->channel));
270 #endif
271
272 OSAL_WRITEL(plli->destAddr & HIDMAC_32BITS_MASK, cntlr->remapBase + HIDMAC_CX_DST_OFFSET_L(chanInfo->channel));
273 #ifdef LOSCFG_AARCH64
274 OSAL_WRITEL((plli->destAddr >> HIDMAC_32BITS_SHIFT) & HIDMAC_32BITS_MASK,
275 cntlr->remapBase + HIDMAC_CX_DST_OFFSET_H(chanInfo->channel));
276 #else
277 OSAL_WRITEL(0, cntlr->remapBase + HIDMAC_CX_DST_OFFSET_H(chanInfo->channel));
278 #endif
279
280 OSAL_WRITEL(plli->nextLli & HIDMAC_32BITS_MASK, cntlr->remapBase + HIDMAC_CX_LLI_OFFSET_L(chanInfo->channel));
281 #ifdef LOSCFG_AARCH64
282 OSAL_WRITEL((plli->nextLli >> HIDMAC_32BITS_SHIFT) & HIDMAC_32BITS_MASK,
283 cntlr->remapBase + HIDMAC_CX_LLI_OFFSET_H(chanInfo->channel));
284 #else
285 OSAL_WRITEL(0, cntlr->remapBase + HIDMAC_CX_LLI_OFFSET_H(chanInfo->channel));
286 #endif
287
288 OSAL_WRITEL(plli->count, cntlr->remapBase + HIDMAC_CX_CNT0_OFFSET(chanInfo->channel));
289
290 OSAL_WRITEL(plli->config | HIDMAC_CX_CFG_CHN_START, cntlr->remapBase + HIDMAC_CX_CFG_OFFSET(chanInfo->channel));
291 return HDF_SUCCESS;
292 }
293
HiDmacGetCurrDstAddr(struct DmaCntlr * cntlr,uint16_t channel)294 static uintptr_t HiDmacGetCurrDstAddr(struct DmaCntlr *cntlr, uint16_t channel)
295 {
296 if (cntlr == NULL || channel >= HIDMAC_CHANNEL_NUM) {
297 return 0;
298 }
299 return OSAL_READL(cntlr->remapBase + HIDMAC_CX_CUR_DST_OFFSET(channel));
300 }
301
HiDmacClkEn(uint16_t index)302 static void HiDmacClkEn(uint16_t index)
303 {
304 unsigned long tmp;
305
306 if (index == 0) {
307 tmp = OSAL_READL(CRG_REG_BASE + HIDMAC_PERI_CRG101_OFFSET);
308 tmp |= 1 << HIDMA0_CLK_OFFSET | 1 << HIDMA0_AXI_OFFSET;
309 OSAL_WRITEL(tmp, CRG_REG_BASE + HIDMAC_PERI_CRG101_OFFSET);
310 }
311 }
312
HiDmacUnReset(uint16_t index)313 static void HiDmacUnReset(uint16_t index)
314 {
315 unsigned long tmp;
316
317 if (index == 0) {
318 tmp = OSAL_READL(CRG_REG_BASE + HIDMAC_PERI_CRG101_OFFSET);
319 tmp |= 1 << HIDMA0_RST_OFFSET;
320 OSAL_WRITEL(tmp, CRG_REG_BASE + HIDMAC_PERI_CRG101_OFFSET);
321
322 tmp = OSAL_READL(CRG_REG_BASE + HIDMAC_PERI_CRG101_OFFSET);
323 tmp &= ~(1 << HIDMA0_RST_OFFSET);
324 OSAL_WRITEL(tmp, CRG_REG_BASE + HIDMAC_PERI_CRG101_OFFSET);
325 }
326 }
327
Hi35xxDmacInit(struct DmaCntlr * cntlr)328 static int32_t Hi35xxDmacInit(struct DmaCntlr *cntlr)
329 {
330 HDF_LOGI("%s: enter", __func__);
331
332 HiDmacClkEn(cntlr->index);
333 HiDmacUnReset(cntlr->index);
334
335 OSAL_WRITEL(HIDMAC_ALL_CHAN_CLR, cntlr->remapBase + HIDMAC_INT_TC1_RAW_OFFSET);
336 OSAL_WRITEL(HIDMAC_ALL_CHAN_CLR, cntlr->remapBase + HIDMAC_INT_TC2_RAW_OFFSET);
337 OSAL_WRITEL(HIDMAC_ALL_CHAN_CLR, cntlr->remapBase + HIDMAC_INT_ERR1_RAW_OFFSET);
338 OSAL_WRITEL(HIDMAC_ALL_CHAN_CLR, cntlr->remapBase + HIDMAC_INT_ERR2_RAW_OFFSET);
339 OSAL_WRITEL(HIDMAC_ALL_CHAN_CLR, cntlr->remapBase + HIDMAC_INT_ERR3_RAW_OFFSET);
340 OSAL_WRITEL(HIDMAC_INT_ENABLE_ALL_CHAN, cntlr->remapBase + HIDMAC_INT_TC1_MASK_OFFSET);
341 OSAL_WRITEL(HIDMAC_INT_ENABLE_ALL_CHAN, cntlr->remapBase + HIDMAC_INT_TC2_MASK_OFFSET);
342 OSAL_WRITEL(HIDMAC_INT_ENABLE_ALL_CHAN, cntlr->remapBase + HIDMAC_INT_ERR1_MASK_OFFSET);
343 OSAL_WRITEL(HIDMAC_INT_ENABLE_ALL_CHAN, cntlr->remapBase + HIDMAC_INT_ERR2_MASK_OFFSET);
344 OSAL_WRITEL(HIDMAC_INT_ENABLE_ALL_CHAN, cntlr->remapBase + HIDMAC_INT_ERR3_MASK_OFFSET);
345 return HDF_SUCCESS;
346 }
347
HiDmacVaddrToPaddr(void * vaddr)348 static uintptr_t HiDmacVaddrToPaddr(void *vaddr)
349 {
350 return (uintptr_t)LOS_PaddrQuery(vaddr);
351 }
352
HiDmacPaddrToVaddr(uintptr_t paddr)353 static void *HiDmacPaddrToVaddr(uintptr_t paddr)
354 {
355 return LOS_PaddrToKVaddr((paddr_t)paddr);
356 }
357
HiDmacCacheInv(uintptr_t vaddr,uintptr_t vend)358 static void HiDmacCacheInv(uintptr_t vaddr, uintptr_t vend)
359 {
360 if (vaddr == 0 || vend == 0) {
361 return;
362 }
363 DCacheInvRange(vaddr, vend);
364 }
365
HiDmacCacheFlush(uintptr_t vaddr,uintptr_t vend)366 static void HiDmacCacheFlush(uintptr_t vaddr, uintptr_t vend)
367 {
368 if (vaddr == 0 || vend == 0) {
369 return;
370 }
371 DCacheFlushRange(vaddr, vend);
372 }
373
HiDmacParseHcs(struct DmaCntlr * cntlr,const struct DeviceResourceNode * node)374 static int32_t HiDmacParseHcs(struct DmaCntlr *cntlr, const struct DeviceResourceNode *node)
375 {
376 int32_t ret;
377 struct DeviceResourceIface *drsOps = NULL;
378
379 if (cntlr == NULL) {
380 return HDF_ERR_INVALID_OBJECT;
381 }
382 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
383 if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL) {
384 HDF_LOGE("%s: invalid drs ops", __func__);
385 return HDF_ERR_NOT_SUPPORT;
386 }
387
388 ret = drsOps->GetUint32(node, "reg_pbase", &cntlr->phyBase, 0);
389 if (ret != HDF_SUCCESS) {
390 HDF_LOGE("%s: read reg base fail", __func__);
391 return ret;
392 }
393 cntlr->remapBase = OsalIoRemap((unsigned long)cntlr->phyBase, (unsigned long)cntlr->regSize);
394
395 ret = drsOps->GetUint32(node, "reg_size", &cntlr->regSize, 0);
396 if (ret != HDF_SUCCESS) {
397 HDF_LOGE("%s: read reg size fail", __func__);
398 return ret;
399 }
400 ret = drsOps->GetUint16(node, "index", &cntlr->index, 0);
401 if (ret != HDF_SUCCESS) {
402 HDF_LOGE("%s: read index fail", __func__);
403 return ret;
404 }
405 ret = drsOps->GetUint32(node, "irq", &cntlr->irq, 0);
406 if (ret != HDF_SUCCESS) {
407 HDF_LOGE("%s: read irq fail", __func__);
408 return ret;
409 }
410 ret = drsOps->GetUint32(node, "max_transfer_size", &cntlr->maxTransSize, 0);
411 if (ret != HDF_SUCCESS) {
412 HDF_LOGE("%s: read max transfer size fail", __func__);
413 return ret;
414 }
415 ret = drsOps->GetUint16(node, "channel_num", &cntlr->channelNum, 0);
416 if (ret != HDF_SUCCESS) {
417 HDF_LOGE("%s: read channel num fail", __func__);
418 return ret;
419 }
420 HDF_LOGI("phybase:0x%x, size:0x%x, index:0x%x, irq:0x%x, max_trans_size:0x%x, chan_num:0x%x",
421 cntlr->phyBase, cntlr->regSize, cntlr->index, cntlr->irq, cntlr->maxTransSize, cntlr->channelNum);
422 return HDF_SUCCESS;
423 }
424
HiDmacBind(struct HdfDeviceObject * device)425 static int32_t HiDmacBind(struct HdfDeviceObject *device)
426 {
427 struct DmaCntlr *cntlr = NULL;
428
429 cntlr = DmaCntlrCreate(device);
430 if (cntlr == NULL) {
431 return HDF_ERR_MALLOC_FAIL;
432 }
433 cntlr->getChanInfo = HiDmacGetChanInfo;
434 cntlr->dmacCacheFlush = HiDmacCacheFlush;
435 cntlr->dmacCacheInv = HiDmacCacheInv;
436 cntlr->dmaChanEnable = HiDmacStartLli;
437 cntlr->dmaM2mChanEnable = HiDmacStartM2M;
438 cntlr->dmacChanDisable = HiDmacDisable;
439 cntlr->dmacVaddrToPaddr = HiDmacVaddrToPaddr;
440 cntlr->dmacPaddrToVaddr = HiDmacPaddrToVaddr;
441 cntlr->dmacGetChanStatus = HiDmacGetChanStat;
442 cntlr->dmacGetCurrDestAddr = HiDmacGetCurrDstAddr;
443 device->service = &cntlr->service;
444 return HDF_SUCCESS;
445 }
446
HiDmacInit(struct HdfDeviceObject * device)447 static int32_t HiDmacInit(struct HdfDeviceObject *device)
448 {
449 int32_t ret;
450 struct DmaCntlr *cntlr = NULL;
451
452 if (device == NULL || device->property == NULL) {
453 HDF_LOGE("%s: device or property null", __func__);
454 return HDF_ERR_INVALID_OBJECT;
455 }
456
457 cntlr = CONTAINER_OF(device->service, struct DmaCntlr, service);
458 ret = HiDmacParseHcs(cntlr, device->property);
459 if (ret != HDF_SUCCESS) {
460 return ret;
461 }
462 ret = Hi35xxDmacInit(cntlr);
463 if (ret != HDF_SUCCESS) {
464 return ret;
465 }
466 return DmacCntlrAdd(cntlr);
467 }
468
HiDmacRelease(struct HdfDeviceObject * device)469 static void HiDmacRelease(struct HdfDeviceObject *device)
470 {
471 struct DmaCntlr *cntlr = NULL;
472
473 if (device == NULL) {
474 return;
475 }
476 cntlr = CONTAINER_OF(device->service, struct DmaCntlr, service);
477 DmacCntlrRemove(cntlr);
478 DmaCntlrDestroy(cntlr);
479 }
480
481 struct HdfDriverEntry g_hiDmacEntry = {
482 .moduleVersion = 1,
483 .Bind = HiDmacBind,
484 .Init = HiDmacInit,
485 .Release = HiDmacRelease,
486 .moduleName = "HDF_PLATFORM_DMAC",
487 };
488 HDF_INIT(g_hiDmacEntry);
489 #ifdef __cplusplus
490 #if __cplusplus
491 }
492 #endif /* __cplusplus */
493 #endif /* __cplusplus */
494