1 /*
2  * Copyright 2024 Microchip Technology Inc. and its subsidiaries.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <stdbool.h>
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <device_mec5.h>
11 #include "mec_pcfg.h"
12 #include "mec_defs.h"
13 #include "mec_dmac_api.h"
14 #include "mec_ecia_api.h"
15 #include "mec_pcr_api.h"
16 #include "mec_retval.h"
17 
18 /* #define MEC_DMAC_DEBUG_REGS */
19 
20 #define MEC_DMA_CHAN_ALL_STATUS (MEC_BIT(MEC_DMA_CHAN_ISTATUS_BERR_Pos) \
21                                  | MEC_BIT(MEC_DMA_CHAN_ISTATUS_HFCREQ_Pos) \
22                                  | MEC_BIT(MEC_DMA_CHAN_ISTATUS_DONE_Pos) \
23                                  | MEC_BIT(MEC_DMA_CHAN_ISTATUS_HFCTERM_Pos))
24 
25 #define MEC_DMA_CHAN_STOP_WAIT 256u
26 
27 #define MEC_DMAC_GIRQ           14
28 #define MEC_DMAC_GIRQ_IDX       6
29 
30 #define MEC_DMAC_CHAN0_ECIA_INFO  MEC5_ECIA_INFO(14, 0, 6, 24)
31 #define MEC_DMAC_CHAN1_ECIA_INFO  MEC5_ECIA_INFO(14, 1, 6, 25)
32 #define MEC_DMAC_CHAN2_ECIA_INFO  MEC5_ECIA_INFO(14, 2, 6, 26)
33 #define MEC_DMAC_CHAN3_ECIA_INFO  MEC5_ECIA_INFO(14, 3, 6, 27)
34 #define MEC_DMAC_CHAN4_ECIA_INFO  MEC5_ECIA_INFO(14, 4, 6, 28)
35 #define MEC_DMAC_CHAN5_ECIA_INFO  MEC5_ECIA_INFO(14, 5, 6, 29)
36 #define MEC_DMAC_CHAN6_ECIA_INFO  MEC5_ECIA_INFO(14, 6, 6, 30)
37 #define MEC_DMAC_CHAN7_ECIA_INFO  MEC5_ECIA_INFO(14, 7, 6, 31)
38 #define MEC_DMAC_CHAN8_ECIA_INFO  MEC5_ECIA_INFO(14, 8, 6, 32)
39 #define MEC_DMAC_CHAN9_ECIA_INFO  MEC5_ECIA_INFO(14, 9, 6, 33)
40 #define MEC_DMAC_CHAN10_ECIA_INFO MEC5_ECIA_INFO(14, 10, 6, 34)
41 #define MEC_DMAC_CHAN11_ECIA_INFO MEC5_ECIA_INFO(14, 11, 6, 35)
42 #define MEC_DMAC_CHAN12_ECIA_INFO MEC5_ECIA_INFO(14, 12, 6, 36)
43 #define MEC_DMAC_CHAN13_ECIA_INFO MEC5_ECIA_INFO(14, 13, 6, 37)
44 #define MEC_DMAC_CHAN14_ECIA_INFO MEC5_ECIA_INFO(14, 14, 6, 38)
45 #define MEC_DMAC_CHAN15_ECIA_INFO MEC5_ECIA_INFO(14, 15, 6, 39)
46 #if MEC5_DMAC_NUM_CHANNELS == 20
47 #define MEC_DMAC_CHAN16_ECIA_INFO MEC5_ECIA_INFO(14, 16, 6, 194)
48 #define MEC_DMAC_CHAN17_ECIA_INFO MEC5_ECIA_INFO(14, 17, 6, 195)
49 #define MEC_DMAC_CHAN18_ECIA_INFO MEC5_ECIA_INFO(14, 18, 6, 196)
50 #define MEC_DMAC_CHAN19_ECIA_INFO MEC5_ECIA_INFO(14, 19, 6, 197)
51 #endif
52 
53 // MEC_DMAC_BASE, MEC_PCR_DMA, MEC5_DMAC_NUM_CHANNELS
54 // MEC_PCR_DMA
55 
56 const uint32_t dmac_ecia_info_table[MEC5_DMAC_NUM_CHANNELS] = {
57     MEC_DMAC_CHAN0_ECIA_INFO, MEC_DMAC_CHAN1_ECIA_INFO,
58     MEC_DMAC_CHAN2_ECIA_INFO, MEC_DMAC_CHAN3_ECIA_INFO,
59     MEC_DMAC_CHAN4_ECIA_INFO, MEC_DMAC_CHAN5_ECIA_INFO,
60     MEC_DMAC_CHAN6_ECIA_INFO, MEC_DMAC_CHAN7_ECIA_INFO,
61     MEC_DMAC_CHAN8_ECIA_INFO, MEC_DMAC_CHAN9_ECIA_INFO,
62     MEC_DMAC_CHAN10_ECIA_INFO, MEC_DMAC_CHAN11_ECIA_INFO,
63     MEC_DMAC_CHAN12_ECIA_INFO, MEC_DMAC_CHAN13_ECIA_INFO,
64     MEC_DMAC_CHAN14_ECIA_INFO, MEC_DMAC_CHAN15_ECIA_INFO,
65 #if MEC5_DMAC_NUM_CHANNELS == 20
66     MEC_DMAC_CHAN16_ECIA_INFO, MEC_DMAC_CHAN17_ECIA_INFO,
67     MEC_DMAC_CHAN18_ECIA_INFO, MEC_DMAC_CHAN19_ECIA_INFO,
68 #endif
69 };
70 
71 #ifdef MEC_DMAC_DEBUG_REGS
72 struct mec_dma_chan_regs_save {
73     uint32_t  actv;
74     uint32_t  mstart;
75     uint32_t  mend;
76     uint32_t  dstart;
77     uint32_t  ctrl;
78     uint32_t  istatus;
79     uint32_t  ien;
80     uint32_t  fsm;
81 };
82 
83 struct mec_dma_chan_regs_save dbg_mec_dma[MEC5_DMAC_NUM_CHANNELS];
84 #endif
85 
dmac_get_ecia_info(uint32_t channel)86 static uint32_t dmac_get_ecia_info(uint32_t channel)
87 {
88     if (channel < MEC5_DMAC_NUM_CHANNELS) {
89         return dmac_ecia_info_table[channel];
90     }
91 
92     return UINT32_MAX;
93 }
94 
dma_chan_ia_enable(uint32_t channel)95 static void dma_chan_ia_enable(uint32_t channel)
96 {
97     uint32_t devi = dmac_get_ecia_info(channel);
98 
99     mec_hal_girq_ctrl(devi, 1u);
100 }
101 
dma_chan_ia_disable(uint32_t channel)102 static void dma_chan_ia_disable(uint32_t channel)
103 {
104     uint32_t devi = dmac_get_ecia_info(channel);
105 
106     mec_hal_girq_ctrl(devi, 0);
107 }
108 
dmac_clr_ia_status(uint32_t channel)109 static void dmac_clr_ia_status(uint32_t channel)
110 {
111     uint32_t devi = dmac_get_ecia_info(channel);
112 
113     mec_hal_girq_clr_src(devi);
114 }
115 
dma_clr_ia_all(void)116 static void dma_clr_ia_all(void)
117 {
118     for (uint8_t chan = 0; chan < MEC5_DMAC_NUM_CHANNELS; chan++) {
119         mec_hal_girq_clr_src(dmac_ecia_info_table[chan]);
120     }
121 }
122 
mec_hal_dmac_girq_result(void)123 uint32_t mec_hal_dmac_girq_result(void)
124 {
125     return mec_hal_girq_result_get(MEC_DMAC_GIRQ);
126 }
127 
mec_hal_dmac_girq_aggr(uint8_t enable)128 void mec_hal_dmac_girq_aggr(uint8_t enable)
129 {
130     mec_hal_ecia_girq_aggr_enable(MEC_DMAC_GIRQ, enable);
131 }
132 
mec_hal_dmac_reset(void)133 int mec_hal_dmac_reset(void)
134 {
135     struct mec_dmac_regs *base = MEC_DMAC;
136 
137     base->MCTRL |= MEC_BIT(MEC_DMAC_MCTRL_MRST_Pos);
138 
139     return MEC_RET_OK;
140 }
141 
mec_hal_dmac_enable(uint8_t enable)142 int mec_hal_dmac_enable(uint8_t enable)
143 {
144     struct mec_dmac_regs *base = MEC_DMAC;
145 
146     if (enable) {
147         base->MCTRL |= MEC_BIT(MEC_DMAC_MCTRL_MACTV_Pos);
148     } else {
149         base->MCTRL &= (uint32_t)~MEC_BIT(MEC_DMAC_MCTRL_MACTV_Pos);
150     }
151 
152     return MEC_RET_OK;
153 }
154 
mec_hal_dmac_is_enabled(void)155 bool mec_hal_dmac_is_enabled(void)
156 {
157     struct mec_dmac_regs *base = MEC_DMAC;
158 
159     if (base->MCTRL & MEC_BIT(MEC_DMAC_MCTRL_MACTV_Pos)) {
160         return true;
161     }
162 
163     return false;
164 }
165 
mec_hal_dma_chan_ia_status_clr(enum mec_dmac_channel channel)166 int mec_hal_dma_chan_ia_status_clr(enum mec_dmac_channel channel)
167 {
168     if (channel >= MEC5_DMAC_NUM_CHANNELS) {
169         return MEC_RET_ERR_INVAL;
170     }
171 
172     dmac_clr_ia_status(channel);
173 
174     return MEC_RET_OK;
175 }
176 
mec_hal_dma_chan_ia_status_clr_mask(uint32_t chanmsk)177 int mec_hal_dma_chan_ia_status_clr_mask(uint32_t chanmsk)
178 {
179     chanmsk &= MEC_DMAC_ALL_CHAN_MASK;
180     if (!chanmsk) {
181         return MEC_RET_OK;
182     }
183 
184     MEC_ECIA0->GIRQ[MEC_DMAC_GIRQ_IDX].SOURCE = chanmsk;
185 
186     return MEC_RET_OK;
187 }
188 
mec_hal_dma_chan_ia_enable(enum mec_dmac_channel channel)189 int mec_hal_dma_chan_ia_enable(enum mec_dmac_channel channel)
190 {
191     if (channel >= MEC5_DMAC_NUM_CHANNELS) {
192         return MEC_RET_ERR_INVAL;
193     }
194 
195     dma_chan_ia_enable(channel);
196 
197     return MEC_RET_OK;
198 }
199 
mec_hal_dma_chan_ia_disable(enum mec_dmac_channel channel)200 int mec_hal_dma_chan_ia_disable(enum mec_dmac_channel channel)
201 {
202     if (channel >= MEC5_DMAC_NUM_CHANNELS) {
203         return MEC_RET_ERR_INVAL;
204     }
205 
206     dma_chan_ia_disable(channel);
207 
208     return MEC_RET_OK;
209 }
210 
mec_hal_dma_chan_ia_enable_mask(uint32_t chan_mask)211 int mec_hal_dma_chan_ia_enable_mask(uint32_t chan_mask)
212 {
213     if (!chan_mask) {
214         return MEC_RET_OK;
215     }
216 
217     for (uint32_t chan = 0; chan < MEC5_DMAC_NUM_CHANNELS; chan++) {
218         if (chan_mask & MEC_BIT(chan)) {
219             dma_chan_ia_enable(chan);
220         }
221     }
222 
223     return MEC_RET_OK;
224 }
225 
mec_hal_dma_chan_ia_disable_mask(uint32_t chan_mask)226 int mec_hal_dma_chan_ia_disable_mask(uint32_t chan_mask)
227 {
228     if (!chan_mask) {
229         return MEC_RET_OK;
230     }
231 
232     for (uint32_t chan = 0; chan < MEC5_DMAC_NUM_CHANNELS; chan++) {
233         if (chan_mask & MEC_BIT(chan)) {
234             dma_chan_ia_disable(chan);
235         }
236     }
237 
238     return MEC_RET_OK;
239 }
240 
mec_hal_dmac_init(uint32_t chan_mask)241 int mec_hal_dmac_init(uint32_t chan_mask)
242 {
243     mec_hal_pcr_clr_blk_slp_en(MEC_PCR_DMA); /* clocks gated ON */
244     mec_hal_dmac_reset();
245     dma_clr_ia_all();
246     mec_hal_dmac_enable(1u);
247     mec_hal_dma_chan_ia_enable_mask(chan_mask);
248 
249     return MEC_RET_OK;
250 }
251 
mec_hal_dma_chan_init(enum mec_dmac_channel chan)252 int mec_hal_dma_chan_init(enum mec_dmac_channel chan)
253 {
254     struct mec_dmac_regs *base = MEC_DMAC;
255 
256     if (chan >= MEC_DMAC_CHAN_MAX) {
257         return MEC_RET_ERR_INVAL;
258     }
259 
260     struct mec_dma_chan_regs *regs = &base->CHAN[chan];
261 
262     regs->MEND = 0;
263     regs->MSTART = 0;
264 
265     regs->ACTV = 0;
266     regs->CTRL = 0;
267     regs->DSTART = 0;
268     regs->IEN = 0;
269     regs->ISTATUS = MEC_DMA_CHAN_ALL_STATUS;
270 
271     return MEC_RET_OK;
272 }
273 
mec_hal_dma_chan_intr_status(enum mec_dmac_channel chan,uint32_t * status)274 int mec_hal_dma_chan_intr_status(enum mec_dmac_channel chan, uint32_t *status)
275 {
276     struct mec_dmac_regs *base = MEC_DMAC;
277     uint32_t hwsts = 0u, logical_sts = 0u;
278 
279     if (!status || (chan >= MEC_DMAC_CHAN_MAX)) {
280         return MEC_RET_ERR_INVAL;
281     }
282 
283     hwsts = base->CHAN[chan].ISTATUS;
284     if (hwsts & MEC_BIT(MEC_DMA_CHAN_ISTATUS_BERR_Pos)) {
285         logical_sts |= MEC_BIT(MEC_DMA_CHAN_STS_BUS_ERR_POS);
286     }
287 
288     if (hwsts & MEC_BIT(MEC_DMA_CHAN_ISTATUS_HFCREQ_Pos)) {
289         logical_sts |= MEC_BIT(MEC_DMA_CHAN_STS_HFC_OVF_POS);
290     }
291 
292     if (hwsts & MEC_BIT(MEC_DMA_CHAN_ISTATUS_DONE_Pos)) {
293         logical_sts |= MEC_BIT(MEC_DMA_CHAN_STS_DONE_POS);
294     }
295 
296     if (hwsts & MEC_BIT(MEC_DMA_CHAN_ISTATUS_HFCTERM_Pos)) {
297         logical_sts |= MEC_BIT(MEC_DMA_CHAN_STS_HFC_TERM_POS);
298     }
299 
300     *status = logical_sts;
301 
302     return MEC_RET_OK;
303 }
304 
mec_hal_dma_chan_intr_status_clr(enum mec_dmac_channel chan)305 int mec_hal_dma_chan_intr_status_clr(enum mec_dmac_channel chan)
306 {
307     struct mec_dmac_regs *base = MEC_DMAC;
308 
309     if (chan >= MEC_DMAC_CHAN_MAX) {
310         return MEC_RET_ERR_INVAL;
311     }
312 
313     base->CHAN[chan].ISTATUS = MEC_DMA_CHAN_ALL_STATUS;
314     MEC_ECIA0->GIRQ[MEC_DMAC_GIRQ_IDX].SOURCE = MEC_BIT(chan);
315 
316     return MEC_RET_OK;
317 }
318 
mec_hal_dma_chan_intr_en(enum mec_dmac_channel chan,uint8_t ien)319 int mec_hal_dma_chan_intr_en(enum mec_dmac_channel chan, uint8_t ien)
320 {
321     struct mec_dmac_regs *base = MEC_DMAC;
322     uint32_t ien_val = 0u;
323 
324     if (chan >= MEC_DMAC_CHAN_MAX) {
325         return MEC_RET_ERR_INVAL;
326     }
327 
328     if (ien) {
329         ien_val = MEC_BIT(MEC_DMA_CHAN_IEN_DONE_Pos) | MEC_BIT(MEC_DMA_CHAN_IEN_BERR_Pos);
330     }
331 
332     base->CHAN[chan].IEN = ien_val;
333 
334     return MEC_RET_OK;
335 }
336 
mec_hal_dma_chan_start(enum mec_dmac_channel chan)337 int mec_hal_dma_chan_start(enum mec_dmac_channel chan)
338 {
339     uint32_t ctrl = 0;
340     struct mec_dmac_regs *base = MEC_DMAC;
341     uint8_t start_pos = MEC_DMA_CHAN_CTRL_HFC_RUN_Pos;
342 
343     if (chan >= MEC_DMAC_CHAN_MAX) {
344         return MEC_RET_ERR_INVAL;
345     }
346 
347     struct mec_dma_chan_regs *regs = &base->CHAN[chan];
348 
349     regs->ACTV = 0;             /* clock gate */
350     ctrl = regs->CTRL;
351 
352     if (ctrl & MEC_BIT(MEC_DMA_CHAN_CTRL_DHFC_Pos)) {
353         start_pos = MEC_DMA_CHAN_CTRL_SWFC_RUN_Pos;
354     }
355 
356     ctrl &= (uint32_t)~(MEC_BIT(MEC_DMA_CHAN_CTRL_HFC_RUN_Pos)
357                         | MEC_BIT(MEC_DMA_CHAN_CTRL_SWFC_RUN_Pos));
358 
359 #ifdef MEC_DMAC_DEBUG_REGS
360     dbg_mec_dma[chan].actv = MEC_BIT(MEC_DMA_CHAN_ACTV_EN_Pos);
361     dbg_mec_dma[chan].mstart = regs->MSTART;
362     dbg_mec_dma[chan].mend = regs->MEND;
363     dbg_mec_dma[chan].dstart = regs->DSTART;
364     dbg_mec_dma[chan].ctrl = ctrl | MEC_BIT(start_pos);
365     dbg_mec_dma[chan].istatus = regs->ISTATUS;
366     dbg_mec_dma[chan].ien = regs->IEN;
367     dbg_mec_dma[chan].fsm = regs->FSM;
368 #endif
369 
370     regs->CTRL = ctrl | MEC_BIT(start_pos);
371     regs->ACTV = MEC_BIT(MEC_DMA_CHAN_ACTV_EN_Pos);
372 
373     return MEC_RET_OK;
374 }
375 
mec_hal_dma_chan_is_busy(enum mec_dmac_channel chan)376 bool mec_hal_dma_chan_is_busy(enum mec_dmac_channel chan)
377 {
378     struct mec_dmac_regs *base = MEC_DMAC;
379 
380     if (chan >= MEC_DMAC_CHAN_MAX) {
381         return false;
382     }
383 
384     if (base->CHAN[chan].CTRL & MEC_BIT(MEC_DMA_CHAN_CTRL_BUSY_Pos)) {
385         return true;
386     }
387 
388     return false;
389 }
390 
mec_hal_dma_chan_halt(enum mec_dmac_channel chan)391 int mec_hal_dma_chan_halt(enum mec_dmac_channel chan)
392 {
393     struct mec_dmac_regs *base = MEC_DMAC;
394     uint32_t halt = (MEC_BIT(MEC_DMA_CHAN_CTRL_HFC_RUN_Pos)
395                      | MEC_BIT(MEC_DMA_CHAN_CTRL_SWFC_RUN_Pos));
396 
397     if (chan >= MEC_DMAC_CHAN_MAX) {
398         return MEC_RET_ERR_INVAL;
399     }
400 
401     struct mec_dma_chan_regs *regs = &base->CHAN[chan];
402 
403     regs->CTRL &= ~halt;
404     regs->ACTV = 0;
405 
406     return MEC_RET_OK;
407 }
408 
mec_hal_dma_chan_stop(enum mec_dmac_channel chan)409 int mec_hal_dma_chan_stop(enum mec_dmac_channel chan)
410 {
411     struct mec_dmac_regs *base = MEC_DMAC;
412     uint32_t wait_cnt = MEC_DMA_CHAN_STOP_WAIT;
413     int ret = MEC_RET_OK;
414 
415     if (chan >= MEC_DMAC_CHAN_MAX) {
416         return MEC_RET_ERR_INVAL;
417     }
418 
419     struct mec_dma_chan_regs *regs = &base->CHAN[chan];
420 
421     if (regs->CTRL & MEC_BIT(MEC_DMA_CHAN_CTRL_BUSY_Pos)) {
422         regs->CTRL |= MEC_BIT(MEC_DMA_CHAN_CTRL_ABORT_Pos);
423         /* should stop on next byte boundary */
424         while (regs->CTRL & MEC_BIT(MEC_DMA_CHAN_CTRL_BUSY_Pos)) {
425             if (!wait_cnt) {
426                 ret = MEC_RET_ERR_TIMEOUT;
427                 break;
428             }
429             wait_cnt--;
430         }
431     }
432 
433     regs->CTRL &= (uint32_t)~(MEC_BIT(MEC_DMA_CHAN_CTRL_HFC_RUN_Pos)
434                               | MEC_BIT(MEC_DMA_CHAN_CTRL_SWFC_RUN_Pos));
435     regs->ACTV = 0;
436 
437     return ret;
438 }
439 
mec_hal_dma_chan_hwfc_set(enum mec_dmac_channel chan,enum mec_dmac_hwfc_dev_id hwfc_dev,uintptr_t dev_addr)440 int mec_hal_dma_chan_hwfc_set(enum mec_dmac_channel chan, enum mec_dmac_hwfc_dev_id hwfc_dev,
441                               uintptr_t dev_addr)
442 {
443     struct mec_dmac_regs *base = MEC_DMAC;
444     uint32_t ctrl = 0;
445 
446     if ((chan >= MEC_DMAC_CHAN_MAX) || (hwfc_dev >= MEC_DMAC_DEV_ID_MAX)) {
447         return MEC_RET_ERR_INVAL;
448     }
449 
450     struct mec_dma_chan_regs *regs = &base->CHAN[chan];
451 
452     ctrl = regs->CTRL & (uint32_t)~(MEC_DMA_CHAN_CTRL_HFC_DEV_Msk);
453     ctrl |= (((uint32_t)hwfc_dev << MEC_DMA_CHAN_CTRL_HFC_DEV_Pos)
454              & MEC_DMA_CHAN_CTRL_HFC_DEV_Msk);
455     regs->CTRL = ctrl;
456     regs->DSTART = dev_addr;
457 
458     return MEC_RET_OK;
459 }
460 
mec_hal_dma_chan_dir_set(enum mec_dmac_channel chan,enum mec_dmac_dir dir)461 int mec_hal_dma_chan_dir_set(enum mec_dmac_channel chan, enum mec_dmac_dir dir)
462 {
463     struct mec_dmac_regs *base = MEC_DMAC;
464 
465     if ((chan >= MEC_DMAC_CHAN_MAX) || (dir >= MEC_DMAC_DIR_MAX)) {
466         return MEC_RET_ERR_INVAL;
467     }
468 
469     struct mec_dma_chan_regs *regs = &base->CHAN[chan];
470 
471     if (dir == MEC_DMAC_DIR_MEM_TO_DEV) {
472         regs->CTRL |= MEC_BIT(MEC_DMA_CHAN_CTRL_MEM2DEV_Pos);
473     } else {
474         regs->CTRL &= (uint32_t)~MEC_BIT(MEC_DMA_CHAN_CTRL_MEM2DEV_Pos);
475     }
476 
477     return MEC_RET_OK;
478 }
479 
mec_hal_dma_chan_dir_get(enum mec_dmac_channel chan,enum mec_dmac_dir * dir)480 int mec_hal_dma_chan_dir_get(enum mec_dmac_channel chan, enum mec_dmac_dir * dir)
481 {
482     struct mec_dmac_regs *base = MEC_DMAC;
483 
484     if (!dir || (chan >= MEC_DMAC_CHAN_MAX)) {
485         return MEC_RET_ERR_INVAL;
486     }
487 
488     *dir = MEC_DMAC_DIR_DEV_TO_MEM;
489     if (base->CHAN[chan].CTRL & MEC_BIT(MEC_DMA_CHAN_CTRL_MEM2DEV_Pos)) {
490         *dir = MEC_DMAC_DIR_MEM_TO_DEV;
491     }
492 
493     return MEC_RET_OK;
494 }
495 
mec_hal_dma_chan_mem_set(enum mec_dmac_channel chan,uintptr_t maddr,size_t nbytes)496 int mec_hal_dma_chan_mem_set(enum mec_dmac_channel chan, uintptr_t maddr, size_t nbytes)
497 {
498     struct mec_dmac_regs *base = MEC_DMAC;
499 
500     if (chan >= MEC_DMAC_CHAN_MAX) {
501         return MEC_RET_ERR_INVAL;
502     }
503 
504     struct mec_dma_chan_regs *regs = &base->CHAN[chan];
505 
506     regs->MSTART = maddr;
507     regs->MEND = maddr + nbytes;
508 
509     return MEC_RET_OK;
510 }
511 
mec_hal_dma_chan_mem_units_set(enum mec_dmac_channel chan,enum mec_dmac_unit_size unitsz)512 int mec_hal_dma_chan_mem_units_set(enum mec_dmac_channel chan, enum mec_dmac_unit_size unitsz)
513 {
514     struct mec_dmac_regs *base = MEC_DMAC;
515     uint32_t ctrl = 0, v = 0;
516 
517     if (chan >= MEC_DMAC_CHAN_MAX) {
518         return MEC_RET_ERR_INVAL;
519     }
520 
521     struct mec_dma_chan_regs *regs = &base->CHAN[chan];
522 
523     v = 1u;
524     if ((unitsz == 4u) || (unitsz == 2u)) {
525         v = unitsz;
526     }
527 
528     v <<= MEC_DMA_CHAN_CTRL_UNITSZ_Pos;
529     ctrl = regs->CTRL & (uint32_t)~MEC_DMA_CHAN_CTRL_UNITSZ_Msk;
530     ctrl |= v;
531     regs->CTRL = ctrl;
532 
533     return MEC_RET_OK;
534 }
535 
mec_hal_dma_chan_rem_bytes(enum mec_dmac_channel chan,uint32_t * remsz)536 int mec_hal_dma_chan_rem_bytes(enum mec_dmac_channel chan, uint32_t *remsz)
537 {
538     struct mec_dmac_regs *base = MEC_DMAC;
539     uint32_t mstart = 0, mend = 0, nrem = 0;
540 
541     if (!remsz || (chan >= MEC_DMAC_CHAN_MAX)) {
542         return MEC_RET_ERR_INVAL;
543     }
544 
545     struct mec_dma_chan_regs *regs = &base->CHAN[chan];
546 
547     nrem = 0u;
548     mend = regs->MEND;
549     mstart = regs->MSTART;
550     if (mend > mstart) {
551         nrem = mend - mstart;
552     }
553 
554     *remsz = nrem;
555 
556     return 0;
557 }
558 
mec_hal_dma_chan_reload(enum mec_dmac_channel chan,uintptr_t src,uintptr_t dest,size_t nbytes)559 int mec_hal_dma_chan_reload(enum mec_dmac_channel chan, uintptr_t src, uintptr_t dest,
560                             size_t nbytes)
561 {
562     struct mec_dmac_regs *base = MEC_DMAC;
563 
564     if (chan >= MEC_DMAC_CHAN_MAX) {
565         return MEC_RET_ERR_INVAL;
566     }
567 
568     struct mec_dma_chan_regs *regs = &base->CHAN[chan];
569 
570     /* ensure HW is "done" by mstart == mend */
571     regs->MSTART = base->CHAN[chan].MEND;
572     regs->MEND = 0; /* keep mend <= mstart */
573 
574     if (regs->CTRL & MEC_BIT(MEC_DMA_CHAN_CTRL_MEM2DEV_Pos)) {
575         regs->MSTART = src;
576         regs->MEND = src + nbytes;
577         regs->DSTART = dest;
578     } else { /* device to memory */
579         regs->MSTART = dest;
580         regs->MEND = dest + nbytes;
581         regs->DSTART = src;
582     }
583 
584     return MEC_RET_OK;
585 }
586 
587 /* Configure a DMA channel for transfer.
588  * DMA termination is based on channel memory start address incrementing until it matches
589  * the memory end address. Device has start address register but no end address.
590  * Control register has a bit to select the direction Memory to Device or Device to Memory.
591  * Memory to Device: source is memory, destination is device.
592  *  Control direction bit = 1 (Mem2Dev)
593  *  Control Increment Mem = 1
594  *  Control Increment Dev is optional. Current MCHP peripherals which can use central DMA
595  *  expose their data as a single data register.
596  *  Memory Start address reg = source address
597  *  Memory End addresss reg = source address + transfer size in bytes
598  *  Device Start address reg = destination address
599  *
600  * Device to Memory: source is device HW register, destination is memory
601  *  Control direction bit = 0 (Dev2Mem)
602  *  Control Increment Mem = 1 may be 0 if writing same value to device.
603  *  Control Increment Dev is optional.
604  *  Memory Start address reg = destination address (memory)
605  *  Memory End address regs = destination address + transfer size in bytes
606  *  Device Start address reg = source address (device register address)
607  */
mec_hal_dma_chan_cfg(enum mec_dmac_channel chan,struct mec_dma_cfg * cfg)608 int mec_hal_dma_chan_cfg(enum mec_dmac_channel chan, struct mec_dma_cfg *cfg)
609 {
610     struct mec_dmac_regs *base = MEC_DMAC;
611     uint32_t ctrl = 0u; /* dir = Dev2Mem, IncrMem=0, IncrDev=0 */
612     uint32_t usz = 1u;
613 
614     if (!cfg || (chan >= MEC_DMAC_CHAN_MAX)) {
615         return MEC_RET_ERR_INVAL;
616     }
617 
618     mec_hal_dma_chan_init(chan);
619 
620     if ((cfg->unitsz == 4u) || (cfg->unitsz == 2u)) {
621         usz = cfg->unitsz;
622     }
623 
624     struct mec_dma_chan_regs *regs = &base->CHAN[chan];
625 
626     ctrl = usz << MEC_DMA_CHAN_CTRL_UNITSZ_Pos;
627     if (cfg->dir == MEC_DMAC_DIR_MEM_TO_DEV) {
628         ctrl |= MEC_BIT(MEC_DMA_CHAN_CTRL_MEM2DEV_Pos);
629         regs->MSTART = cfg->src_addr;
630         regs->MEND = cfg->src_addr + cfg->nbytes;
631         regs->DSTART = cfg->dst_addr;
632         if (cfg->flags & MEC_DMA_CFG_FLAG_INCR_SRC_ADDR) {
633             ctrl |= MEC_BIT(MEC_DMA_CHAN_CTRL_INCRM_Pos);
634         }
635         if (cfg->flags & MEC_DMA_CFG_FLAG_INCR_DST_ADDR) {
636             ctrl |= MEC_BIT(MEC_DMA_CHAN_CTRL_INCRD_Pos);
637         }
638     } else { /* device(source address) to memory(destination address) */
639         regs->MSTART = cfg->dst_addr;
640         regs->MEND = cfg->dst_addr + cfg->nbytes;
641         regs->DSTART = cfg->src_addr;
642         if (cfg->flags & MEC_DMA_CFG_FLAG_INCR_SRC_ADDR) {
643             ctrl |= MEC_BIT(MEC_DMA_CHAN_CTRL_INCRD_Pos);
644         }
645         if (cfg->flags & MEC_DMA_CFG_FLAG_INCR_DST_ADDR) {
646             ctrl |= MEC_BIT(MEC_DMA_CHAN_CTRL_INCRM_Pos);
647         }
648     }
649 
650     if (cfg->hwfc_dev < MEC_DMAC_DEV_ID_NONE) {
651         ctrl |= (((uint32_t)cfg->hwfc_dev << MEC_DMA_CHAN_CTRL_HFC_DEV_Pos)
652                  & MEC_DMA_CHAN_CTRL_HFC_DEV_Msk);
653     } else {
654         ctrl |= MEC_BIT(MEC_DMA_CHAN_CTRL_DHFC_Pos);
655     }
656 
657     regs->CTRL = ctrl;
658     regs->ACTV |= MEC_BIT(MEC_DMA_CHAN_ACTV_EN_Pos);
659 
660     return MEC_RET_OK;
661 }
662 
mec_hal_dma_chan_cfg_get(enum mec_dmac_channel chan,struct mec_dma_cfg * cfg)663 int mec_hal_dma_chan_cfg_get(enum mec_dmac_channel chan, struct mec_dma_cfg *cfg)
664 {
665     struct mec_dmac_regs *base = MEC_DMAC;
666     uint32_t ctrl = 0u, dstart = 0u, mstart = 0u, mend = 0u;
667 
668     if (!cfg || (chan >= MEC_DMAC_CHAN_MAX)) {
669         return MEC_RET_ERR_INVAL;
670     }
671 
672     struct mec_dma_chan_regs *regs = &base->CHAN[chan];
673 
674     cfg->flags = 0u;
675 
676     ctrl = regs->CTRL;
677     if (ctrl & MEC_BIT(MEC_DMA_CHAN_CTRL_DHFC_Pos)) {
678         cfg->hwfc_dev = MEC_DMAC_DEV_ID_NONE;
679     } else {
680         cfg->hwfc_dev =  (ctrl & MEC_DMA_CHAN_CTRL_HFC_DEV_Msk) >> MEC_DMA_CHAN_CTRL_HFC_DEV_Pos;
681     }
682 
683     if (ctrl & MEC_BIT(MEC_DMA_CHAN_CTRL_MEM2DEV_Pos)) {
684         cfg->dir = MEC_DMAC_DIR_MEM_TO_DEV;
685         if (ctrl & MEC_BIT(MEC_DMA_CHAN_CTRL_INCRM_Pos)) {
686             cfg->flags |= MEC_DMA_CFG_FLAG_INCR_SRC_ADDR;
687         }
688         if (ctrl & MEC_BIT(MEC_DMA_CHAN_CTRL_INCRD_Pos)) {
689             cfg->flags |= MEC_DMA_CFG_FLAG_INCR_DST_ADDR;
690         }
691     } else {
692         cfg->dir = MEC_DMAC_DIR_DEV_TO_MEM;
693         if (ctrl & MEC_BIT(MEC_DMA_CHAN_CTRL_INCRM_Pos)) {
694             cfg->flags |= MEC_DMA_CFG_FLAG_INCR_DST_ADDR;
695         }
696         if (ctrl & MEC_BIT(MEC_DMA_CHAN_CTRL_INCRD_Pos)) {
697             cfg->flags |= MEC_DMA_CFG_FLAG_INCR_SRC_ADDR;
698         }
699     }
700 
701     cfg->nbytes = 0u;
702     mstart = regs->MSTART;
703     mend = regs->MEND;
704     dstart = regs->DSTART;
705     if (mend > mstart) {
706         cfg->nbytes = mend - mstart;
707     }
708 
709     if (ctrl & MEC_BIT(MEC_DMA_CHAN_CTRL_MEM2DEV_Pos)) {
710         cfg->src_addr = mstart;
711         cfg->dst_addr = dstart;
712     } else {
713         cfg->src_addr = dstart;
714         cfg->dst_addr = mstart;
715     }
716 
717     return MEC_RET_OK;
718 }
719 /* end mec_dmac.c */
720