• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved.
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 #include "plat_addr_map.h"
16 #include "cmsis_nvic.h"
17 #include "hal_chipid.h"
18 #include "hal_cmu.h"
19 #include "hal_dma.h"
20 #include "hal_location.h"
21 #include "hal_timer.h"
22 #include "hal_trace.h"
23 #include "reg_dma.h"
24 
25 #if (defined(CHIP_BEST1000) || defined(CHIP_BEST2000) || defined(CHIP_BEST2300)) && !(defined(ROM_BUILD) || defined(PROGRAMMER))
26 #define DMA_REMAP
27 #endif
28 
29 #if (defined(CHIP_BEST1501SIMU) && !defined(__FPGA_1501P__)) || defined(CHIP_BEST1600SIMU)
30 enum HAL_DMA_INST_T {
31     HAL_DMA_INST_AUDMA = 1,
32     HAL_DMA_INST_GPDMA = HAL_DMA_INST_AUDMA,
33     HAL_DMA_INST_QTY
34 };
35 #else
36 enum HAL_DMA_INST_T {
37     HAL_DMA_INST_AUDMA = 0,
38 #if (CHIP_HAS_DMA == 1)
39     HAL_DMA_INST_GPDMA = HAL_DMA_INST_AUDMA,
40 #else
41     HAL_DMA_INST_GPDMA,
42 #endif
43 
44     HAL_DMA_INST_QTY
45 };
46 #endif
47 
48 struct HAL_DMA_FIFO_ADDR_T {
49     uint32_t count;
50     const uint32_t *addr;
51 };
52 
53 struct HAL_DMA_FIFO_PERIPH_T {
54     uint32_t count;
55     const enum HAL_DMA_PERIPH_T *periph;
56 #ifdef DMA_REMAP
57     const enum HAL_DMA_PERIPH_T *periph_remap;
58 #endif
59 };
60 
61 /*****************************************************************************
62  * Private types/enumerations/variables
63  ****************************************************************************/
64 
65 #include CHIP_SPECIFIC_HDR(hal_dmacfg)
66 
67 static struct DMA_T * const dma[HAL_DMA_INST_QTY] = {
68     (struct DMA_T *)AUDMA_BASE,
69 #if (CHIP_HAS_DMA > 1)
70     (struct DMA_T *)GPDMA_BASE,
71 #endif
72 };
73 
74 static const IRQn_Type irq_type[HAL_DMA_INST_QTY] = {
75     AUDMA_IRQn,
76 #if (CHIP_HAS_DMA > 1)
77     GPDMA_IRQn,
78 #endif
79 };
80 
81 static void hal_audma_irq_handler(void);
82 #if (CHIP_HAS_DMA > 1)
83 static void hal_gpdma_irq_handler(void);
84 #endif
85 
86 static const uint32_t irq_entry[HAL_DMA_INST_QTY] = {
87     (uint32_t)hal_audma_irq_handler,
88 #if (CHIP_HAS_DMA > 1)
89     (uint32_t)hal_gpdma_irq_handler,
90 #endif
91 };
92 
93 static const struct HAL_DMA_FIFO_ADDR_T fifo_addr[HAL_DMA_INST_QTY] = {
94     {
95         .count = ARRAY_SIZE(audma_fifo_addr),
96         .addr = audma_fifo_addr,
97     },
98 #if (CHIP_HAS_DMA > 1)
99     {
100         .count = ARRAY_SIZE(gpdma_fifo_addr),
101         .addr = gpdma_fifo_addr,
102     },
103 #endif
104 };
105 
106 static const struct HAL_DMA_FIFO_PERIPH_T fifo_periph[HAL_DMA_INST_QTY] = {
107     {
108         .count = ARRAY_SIZE(audma_fifo_periph),
109         .periph = audma_fifo_periph,
110 #ifdef DMA_REMAP
111         .periph_remap = audma_fifo_periph_remap,
112 #endif
113     },
114 #if (CHIP_HAS_DMA > 1)
115     {
116         .count = ARRAY_SIZE(gpdma_fifo_periph),
117         .periph = gpdma_fifo_periph,
118 #ifdef DMA_REMAP
119         .periph_remap = gpdma_fifo_periph_remap,
120 #endif
121     },
122 #endif
123 };
124 
125 static const uint8_t chan_start[HAL_DMA_INST_QTY] = {
126     AUDMA_CHAN_START,
127 #if (CHIP_HAS_DMA > 1)
128     GPDMA_CHAN_START,
129 #endif
130 };
131 
132 static const uint8_t chan_num[HAL_DMA_INST_QTY] = {
133     AUDMA_CHAN_NUM,
134 #if (CHIP_HAS_DMA > 1)
135     GPDMA_CHAN_NUM,
136 #endif
137 };
138 
139 /* Channel array to monitor free channel */
140 static bool chan_enabled[HAL_DMA_INST_QTY][DMA_NUMBER_CHANNELS];
141 
142 static HAL_DMA_IRQ_HANDLER_T handler[HAL_DMA_INST_QTY][DMA_NUMBER_CHANNELS];
143 
144 #ifdef DMA_REMAP
145 static uint32_t periph_remap_bitmap[HAL_DMA_INST_QTY];
146 #endif
147 
148 #ifdef CORE_SLEEP_POWER_DOWN
149 static uint32_t saved_dma_regs[HAL_DMA_INST_QTY];
150 #endif
151 
152 static const char * const err_invalid_inst = "Invalid DMA inst: %u";
153 
154 static const char * const err_invalid_chan[HAL_DMA_INST_QTY] = {
155     "Invalid AUDMA chan: %u",
156 #if (CHIP_HAS_DMA > 1)
157     "Invalid GPDMA chan: %u",
158 #endif
159 };
160 
161 static bool dma_opened = false;
162 
163 static HAL_DMA_DELAY_FUNC dma_delay = NULL;
164 
165 #ifdef DMA_DEBUG
166 #if (CHIP_HAS_DMA > 1) && (GPDMA_CHAN_NUM > AUDMA_CHAN_NUM)
167 #define MAX_CHAN_NUM_PER_INST               GPDMA_CHAN_NUM
168 #else
169 #define MAX_CHAN_NUM_PER_INST               AUDMA_CHAN_NUM
170 #endif
171 static void *chan_user[HAL_DMA_INST_QTY][MAX_CHAN_NUM_PER_INST];
172 static uint32_t debug_user_map[HAL_DMA_INST_QTY];
173 STATIC_ASSERT(sizeof(debug_user_map[0]) * 8 >= MAX_CHAN_NUM_PER_INST, "debug_user_map size too small");
174 #endif
175 
176 /*****************************************************************************
177  * Public types/enumerations/variables
178  ****************************************************************************/
179 
180 /*****************************************************************************
181  * Private functions
182  ****************************************************************************/
hal_dma_delay(uint32_t ms)183 static void hal_dma_delay(uint32_t ms)
184 {
185     if (dma_delay && !in_isr()) {
186         dma_delay(ms);
187     } else {
188         hal_sys_timer_delay(MS_TO_TICKS(ms));
189     }
190 }
191 
generate_chan(enum HAL_DMA_INST_T inst,uint8_t hwch)192 static inline uint8_t generate_chan(enum HAL_DMA_INST_T inst, uint8_t hwch)
193 {
194     return ((inst << 4) | (hwch & 0xF));
195 }
196 
get_inst_from_chan(uint8_t ch)197 static inline enum HAL_DMA_INST_T get_inst_from_chan(uint8_t ch)
198 {
199     return (enum HAL_DMA_INST_T)(ch >> 4);
200 }
201 
get_hwch_from_chan(uint8_t ch)202 static inline uint8_t get_hwch_from_chan(uint8_t ch)
203 {
204     return (ch & 0xF);
205 }
206 
get_index_from_periph(enum HAL_DMA_PERIPH_T periph,enum HAL_DMA_INST_T * pinst,uint8_t * pidx)207 static inline int get_index_from_periph(enum HAL_DMA_PERIPH_T periph, enum HAL_DMA_INST_T *pinst, uint8_t *pidx)
208 {
209     enum HAL_DMA_INST_T inst;
210     int i;
211 
212     for (inst = 0; inst < HAL_DMA_INST_QTY; inst++) {
213         for (i = 0; i < fifo_periph[inst].count; i++) {
214             if (fifo_periph[inst].periph[i] == periph) {
215                 *pinst = inst;
216                 *pidx = i;
217                 return 0;
218             }
219         }
220     }
221 
222     return 1;
223 }
224 
225 #ifdef DMA_REMAP
get_remap_index_from_periph(enum HAL_DMA_INST_T inst,enum HAL_DMA_PERIPH_T periph,uint8_t * pidx)226 static inline int get_remap_index_from_periph(enum HAL_DMA_INST_T inst, enum HAL_DMA_PERIPH_T periph, uint8_t *pidx)
227 {
228     int i;
229 
230     if (fifo_periph[inst].periph_remap == NULL) {
231         return 1;
232     }
233 
234     for (i = 0; i < fifo_periph[inst].count; i++) {
235         if (fifo_periph[inst].periph_remap[i] == periph) {
236             *pidx = i;
237             return 0;
238         }
239     }
240 
241     return 2;
242 }
243 #endif
244 
hal_dma_get_periph_addr(enum HAL_DMA_PERIPH_T periph)245 static inline uint32_t hal_dma_get_periph_addr(enum HAL_DMA_PERIPH_T periph)
246 {
247     int ret;
248     enum HAL_DMA_INST_T inst;
249     uint8_t index;
250 
251     ret = get_index_from_periph(periph, &inst, &index);
252     if (ret) {
253         return 0;
254     }
255 
256     return fifo_addr[inst].addr[index];
257 }
258 
259 /* Initialize the DMA */
hal_dma_open_inst(enum HAL_DMA_INST_T inst)260 static void hal_dma_open_inst(enum HAL_DMA_INST_T inst)
261 {
262     uint8_t i;
263 
264     /* Reset all channel configuration register */
265     for (i = 0; i < DMA_NUMBER_CHANNELS; i++) {
266         dma[inst]->CH[i].CONFIG = 0;
267     }
268 
269     /* Clear all DMA interrupt and error flag */
270     dma[inst]->INTTCCLR = ~0UL;
271     dma[inst]->INTERRCLR = ~0UL;
272 
273     dma[inst]->DMACONFIG = (dma[inst]->DMACONFIG & ~(DMA_DMACONFIG_AHB1_BIGENDIAN |
274         DMA_DMACONFIG_AHB2_BIGENDIAN | DMA_DMACONFIG_CLK_EN_MASK)) |
275         DMA_DMACONFIG_EN | DMA_DMACONFIG_CROSS_1KB_EN |
276 #ifdef CHIP_BEST3001
277         DMA_DMACONFIG_TC_IRQ_EN_MASK |
278 #endif
279         0;
280 
281 #ifdef CHIP_BEST1400
282     dma[inst]->DMACONFIG &= ~DMA_DMACONFIG_TC_IRQ_EN_MASK;
283 #endif
284 
285     /* Reset all channels are free */
286     for (i = 0; i < DMA_NUMBER_CHANNELS; i++) {
287         chan_enabled[inst][i] = false;
288     }
289 
290     NVIC_SetVector(irq_type[inst], irq_entry[inst]);
291     if (inst == HAL_DMA_INST_AUDMA) {
292         NVIC_SetPriority(irq_type[inst], IRQ_PRIORITY_ABOVENORMAL);
293     } else {
294         NVIC_SetPriority(irq_type[inst], IRQ_PRIORITY_NORMAL);
295     }
296     NVIC_ClearPendingIRQ(irq_type[inst]);
297     NVIC_EnableIRQ(irq_type[inst]);
298 }
299 
300 /* Shutdown the DMA */
hal_dma_close_inst(enum HAL_DMA_INST_T inst)301 static void hal_dma_close_inst(enum HAL_DMA_INST_T inst)
302 {
303     NVIC_DisableIRQ(irq_type[inst]);
304     dma[inst]->DMACONFIG = 0;
305 }
306 
hal_dma_chan_busy_inst(enum HAL_DMA_INST_T inst,uint8_t hwch)307 static bool hal_dma_chan_busy_inst(enum HAL_DMA_INST_T inst, uint8_t hwch)
308 {
309     return !!(dma[inst]->ENBLDCHNS & DMA_STAT_CHAN(hwch));
310 }
311 
hal_dma_handle_chan_irq(enum HAL_DMA_INST_T inst,uint8_t hwch)312 static void hal_dma_handle_chan_irq(enum HAL_DMA_INST_T inst, uint8_t hwch)
313 {
314     uint32_t remains;
315     struct HAL_DMA_DESC_T *lli;
316     bool tcint, errint;
317 
318     /* Check counter terminal status */
319     tcint = !!(dma[inst]->INTTCSTAT & DMA_STAT_CHAN(hwch));
320     /* Check error terminal status */
321     errint = !!(dma[inst]->INTERRSTAT & DMA_STAT_CHAN(hwch));
322 
323     if (tcint || errint) {
324         if (tcint) {
325             /* Clear terminate counter Interrupt pending */
326             dma[inst]->INTTCCLR = DMA_STAT_CHAN(hwch);
327         }
328         if (errint) {
329             /* Clear error counter Interrupt pending */
330             dma[inst]->INTERRCLR = DMA_STAT_CHAN(hwch);
331         }
332 
333         if (handler[inst][hwch]) {
334             remains = GET_BITFIELD(dma[inst]->CH[hwch].CONTROL, DMA_CONTROL_TRANSFERSIZE);
335             lli = (struct HAL_DMA_DESC_T *)dma[inst]->CH[hwch].LLI;
336             handler[inst][hwch](generate_chan(inst, hwch), remains, errint, lli);
337         }
338     }
339 }
340 
hal_dma_irq_handler(enum HAL_DMA_INST_T inst)341 static void hal_dma_irq_handler(enum HAL_DMA_INST_T inst)
342 {
343     uint8_t hwch;
344 
345     for (hwch = 0; hwch < DMA_NUMBER_CHANNELS; hwch++) {
346         if ((dma[inst]->INTSTAT & DMA_STAT_CHAN(hwch)) == 0) {
347             continue;
348         }
349         hal_dma_handle_chan_irq(inst, hwch);
350     }
351 }
352 
hal_audma_irq_handler(void)353 static void hal_audma_irq_handler(void)
354 {
355     hal_dma_irq_handler(HAL_DMA_INST_AUDMA);
356 }
357 
358 #if (CHIP_HAS_DMA > 1)
hal_gpdma_irq_handler(void)359 static void hal_gpdma_irq_handler(void)
360 {
361     hal_dma_irq_handler(HAL_DMA_INST_GPDMA);
362 }
363 #endif
364 
hal_dma_init_control(uint32_t * ctrl,const struct HAL_DMA_CH_CFG_T * cfg,int tc_irq)365 static enum HAL_DMA_RET_T hal_dma_init_control(uint32_t *ctrl,
366                                                const struct HAL_DMA_CH_CFG_T *cfg,
367                                                int tc_irq)
368 {
369     uint32_t addr_inc;
370     enum HAL_DMA_FLOW_CONTROL_T type;
371 
372     if (cfg->src_tsize > HAL_DMA_MAX_DESC_XFER_SIZE) {
373         return HAL_DMA_ERR;
374     }
375 
376 #ifdef CHIP_BEST1000
377     type = cfg->type;
378 #else
379     type = cfg->type & ~HAL_DMA_FLOW_FLAG_MASK;
380 #endif
381 
382     switch (type) {
383         case HAL_DMA_FLOW_M2M_DMA:
384             addr_inc = DMA_CONTROL_SI | DMA_CONTROL_DI;
385             break;
386         case HAL_DMA_FLOW_M2P_DMA:
387         case HAL_DMA_FLOW_M2P_PERIPH:
388             addr_inc = DMA_CONTROL_SI;
389             break;
390         case HAL_DMA_FLOW_P2M_DMA:
391         case HAL_DMA_FLOW_P2M_PERIPH:
392             addr_inc = DMA_CONTROL_DI;
393             break;
394         case HAL_DMA_FLOW_P2P_DMA:
395         case HAL_DMA_FLOW_P2P_DSTPERIPH:
396         case HAL_DMA_FLOW_P2P_SRCPERIPH:
397             addr_inc = 0;
398             break;
399         default:
400             return HAL_DMA_ERR;
401     }
402 
403 #ifndef CHIP_BEST1000
404     if (cfg->type & HAL_DMA_FLOW_FLAG_SI) {
405         addr_inc |= DMA_CONTROL_SI;
406     }
407     if (cfg->type & HAL_DMA_FLOW_FLAG_DI) {
408         addr_inc |= DMA_CONTROL_DI;
409     }
410 #endif
411 
412     *ctrl = DMA_CONTROL_TRANSFERSIZE(cfg->src_tsize) |
413             DMA_CONTROL_SBSIZE(cfg->src_bsize) |
414             DMA_CONTROL_DBSIZE(cfg->dst_bsize) |
415             DMA_CONTROL_SWIDTH(cfg->src_width) |
416             DMA_CONTROL_DWIDTH(cfg->dst_width) |
417             (tc_irq ? DMA_CONTROL_TC_IRQ : 0) |
418             addr_inc;
419 
420     return HAL_DMA_OK;
421 }
422 
423 /*****************************************************************************
424  * Generic Public functions
425  ****************************************************************************/
426 
hal_dma_init_desc(struct HAL_DMA_DESC_T * desc,const struct HAL_DMA_CH_CFG_T * cfg,const struct HAL_DMA_DESC_T * next,int tc_irq)427 enum HAL_DMA_RET_T hal_dma_init_desc(struct HAL_DMA_DESC_T *desc,
428                                      const struct HAL_DMA_CH_CFG_T *cfg,
429                                      const struct HAL_DMA_DESC_T *next,
430                                      int tc_irq)
431 {
432     uint32_t ctrl;
433     enum HAL_DMA_RET_T ret;
434     enum HAL_DMA_FLOW_CONTROL_T type;
435 
436     ret = hal_dma_init_control(&ctrl, cfg, tc_irq);
437     if (ret != HAL_DMA_OK) {
438         return ret;
439     }
440 
441 #ifdef CHIP_BEST1000
442     type = cfg->type;
443 #else
444     type = cfg->type & ~HAL_DMA_FLOW_FLAG_MASK;
445 #endif
446 
447     if (type == HAL_DMA_FLOW_M2M_DMA || type == HAL_DMA_FLOW_M2P_DMA ||
448             type == HAL_DMA_FLOW_M2P_PERIPH) {
449         desc->src = cfg->src;
450     } else {
451         desc->src = hal_dma_get_periph_addr(cfg->src_periph);
452     }
453     if (type == HAL_DMA_FLOW_M2M_DMA || type == HAL_DMA_FLOW_P2M_DMA ||
454             type == HAL_DMA_FLOW_P2M_PERIPH) {
455         desc->dst = cfg->dst;
456     } else {
457         desc->dst = hal_dma_get_periph_addr(cfg->dst_periph);
458     }
459     desc->lli = (uint32_t)next;
460     desc->ctrl = ctrl;
461 
462     return HAL_DMA_OK;
463 }
464 
hal_dma_sg_2d_start(const struct HAL_DMA_DESC_T * desc,const struct HAL_DMA_CH_CFG_T * cfg,const struct HAL_DMA_2D_CFG_T * src_2d,const struct HAL_DMA_2D_CFG_T * dst_2d)465 enum HAL_DMA_RET_T hal_dma_sg_2d_start(const struct HAL_DMA_DESC_T *desc,
466                                        const struct HAL_DMA_CH_CFG_T *cfg,
467                                        const struct HAL_DMA_2D_CFG_T *src_2d,
468                                        const struct HAL_DMA_2D_CFG_T *dst_2d)
469 {
470     enum HAL_DMA_INST_T inst;
471     uint8_t hwch;
472     enum HAL_DMA_FLOW_CONTROL_T type;
473     uint8_t src_periph, dst_periph;
474     enum HAL_DMA_INST_T periph_inst;
475     int ret;
476     uint32_t irq_mask, try_burst;
477     uint32_t lock;
478 
479     inst = get_inst_from_chan(cfg->ch);
480     hwch = get_hwch_from_chan(cfg->ch);
481 
482     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
483     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
484 
485 #ifdef CHIP_BEST1000
486     type = cfg->type;
487 #else
488     type = cfg->type & ~HAL_DMA_FLOW_FLAG_MASK;
489 #endif
490 
491     if (type == HAL_DMA_FLOW_M2M_DMA || type == HAL_DMA_FLOW_M2P_DMA ||
492             type == HAL_DMA_FLOW_M2P_PERIPH) {
493         src_periph = 0;
494     } else {
495         ret = get_index_from_periph(cfg->src_periph, &periph_inst, &src_periph);
496         ASSERT(ret == 0, "Failed to get src periph: %d", cfg->src_periph);
497 #ifdef DMA_REMAP
498         if (periph_remap_bitmap[periph_inst] & (1 << src_periph)) {
499             periph_inst ^= 1;
500             ret = get_remap_index_from_periph(periph_inst, cfg->src_periph, &src_periph);
501             ASSERT(ret == 0, "Failed to get remap src periph: %d", cfg->src_periph);
502         }
503 #endif
504         ASSERT(inst == periph_inst, "Mismatch inst in chan=0x%02x and src periph %d", cfg->ch, cfg->src_periph);
505     }
506     if (type == HAL_DMA_FLOW_M2M_DMA || type == HAL_DMA_FLOW_P2M_DMA ||
507             type == HAL_DMA_FLOW_P2M_PERIPH) {
508         dst_periph = 0;
509     } else {
510         ret = get_index_from_periph(cfg->dst_periph, &periph_inst, &dst_periph);
511         ASSERT(ret == 0, "Failed to get dst periph: %d", cfg->dst_periph);
512 #ifdef DMA_REMAP
513         if (periph_remap_bitmap[periph_inst] & (1 << dst_periph)) {
514             periph_inst ^= 1;
515             ret = get_remap_index_from_periph(periph_inst, cfg->dst_periph, &dst_periph);
516             ASSERT(ret == 0, "Failed to get remap dst periph: %d", cfg->dst_periph);
517         }
518 #endif
519         ASSERT(inst == periph_inst, "Mismatch inst in chan=0x%02x and dst periph %d", cfg->ch, cfg->dst_periph);
520     }
521 
522     if (!chan_enabled[inst][hwch]) {
523         // Not acquired
524         return HAL_DMA_ERR;
525     }
526     if (hal_dma_chan_busy_inst(inst, hwch)) {
527         // Busy
528         return HAL_DMA_ERR;
529     }
530 
531     if (cfg->handler == NULL) {
532         irq_mask = 0;
533     } else {
534         irq_mask = DMA_CONFIG_ERR_IRQMASK | DMA_CONFIG_TC_IRQMASK;
535         handler[inst][hwch] = cfg->handler;
536     }
537 
538     try_burst = cfg->try_burst ? DMA_CONFIG_TRY_BURST : 0;
539 
540     /* Reset the Interrupt status */
541     dma[inst]->INTTCCLR = DMA_STAT_CHAN(hwch);
542     dma[inst]->INTERRCLR = DMA_STAT_CHAN(hwch);
543 
544     dma[inst]->CH[hwch].SRCADDR = desc->src;
545     dma[inst]->CH[hwch].DSTADDR = desc->dst;
546     dma[inst]->CH[hwch].LLI = desc->lli;
547     dma[inst]->CH[hwch].CONTROL = desc->ctrl;
548     dma[inst]->CH[hwch].CONFIG = DMA_CONFIG_SRCPERIPH(src_periph) |
549                                  DMA_CONFIG_DSTPERIPH(dst_periph) |
550                                  DMA_CONFIG_TRANSFERTYPE(type) |
551                                  irq_mask |
552                                  try_burst;
553 
554 #ifndef CHIP_BEST1000
555     if (src_2d) {
556         dma[inst]->_2D[hwch].SRCX = DMA_2D_MODIFY(src_2d->xmodify) | DMA_2D_COUNT(src_2d->xcount);
557         dma[inst]->_2D[hwch].SRCY = DMA_2D_MODIFY(src_2d->ymodify) | DMA_2D_COUNT(src_2d->ycount);
558         dma[inst]->_2D[hwch].CTRL |= DMA_2D_CTRL_SRC_EN;
559     } else {
560         dma[inst]->_2D[hwch].CTRL &= ~DMA_2D_CTRL_SRC_EN;
561     }
562     if (dst_2d) {
563         dma[inst]->_2D[hwch].DSTX = DMA_2D_MODIFY(dst_2d->xmodify) | DMA_2D_COUNT(dst_2d->xcount);
564         dma[inst]->_2D[hwch].DSTY = DMA_2D_MODIFY(dst_2d->ymodify) | DMA_2D_COUNT(dst_2d->ycount);
565         dma[inst]->_2D[hwch].CTRL |= DMA_2D_CTRL_DST_EN;
566     } else {
567         dma[inst]->_2D[hwch].CTRL &= ~DMA_2D_CTRL_DST_EN;
568     }
569 #endif
570 
571     lock = int_lock();
572     if (cfg->start_cb) {
573         cfg->start_cb(cfg->ch);
574     }
575     dma[inst]->CH[hwch].CONFIG |= DMA_CONFIG_EN;
576     int_unlock(lock);
577 
578     return HAL_DMA_OK;
579 }
580 
hal_dma_sg_start(const struct HAL_DMA_DESC_T * desc,const struct HAL_DMA_CH_CFG_T * cfg)581 enum HAL_DMA_RET_T hal_dma_sg_start(const struct HAL_DMA_DESC_T *desc,
582                                     const struct HAL_DMA_CH_CFG_T *cfg)
583 {
584     return hal_dma_sg_2d_start(desc, cfg, NULL, NULL);
585 }
586 
hal_dma_start(const struct HAL_DMA_CH_CFG_T * cfg)587 enum HAL_DMA_RET_T hal_dma_start(const struct HAL_DMA_CH_CFG_T *cfg)
588 {
589     struct HAL_DMA_DESC_T desc;
590     enum HAL_DMA_RET_T ret;
591 
592     ret = hal_dma_init_desc(&desc, cfg, NULL, 1);
593     if (ret != HAL_DMA_OK) {
594         return ret;
595     }
596 
597     ret = hal_dma_sg_start(&desc, cfg);
598     if (ret != HAL_DMA_OK) {
599         return ret;
600     }
601 
602     return HAL_DMA_OK;
603 }
604 
hal_dma_cancel(uint8_t ch)605 void hal_dma_cancel(uint8_t ch)
606 {
607     enum HAL_DMA_INST_T inst;
608     uint8_t hwch;
609 
610     inst = get_inst_from_chan(ch);
611     hwch = get_hwch_from_chan(ch);
612 
613     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
614     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
615 
616     dma[inst]->CH[hwch].CONFIG &= ~DMA_CONFIG_EN;
617     dma[inst]->INTTCCLR = DMA_STAT_CHAN(hwch);
618     dma[inst]->INTERRCLR = DMA_STAT_CHAN(hwch);
619 }
620 
hal_dma_stop(uint8_t ch)621 void hal_dma_stop(uint8_t ch)
622 {
623     enum HAL_DMA_INST_T inst;
624     uint8_t hwch;
625     uint8_t retry = 0;
626     const uint8_t max_retry = 10;
627 
628     inst = get_inst_from_chan(ch);
629     hwch = get_hwch_from_chan(ch);
630 
631     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
632     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
633 
634     dma[inst]->CH[hwch].CONFIG |= DMA_CONFIG_HALT;
635 #if 1
636     while ((dma[inst]->CH[hwch].CONFIG & DMA_CONFIG_ACTIVE) && (++retry < max_retry)) {
637         if (retry <= 3) {
638             hal_sys_timer_delay_us(10);
639         } else {
640             hal_dma_delay(1);
641         }
642     }
643 #else
644     while (dma[inst]->CH[hwch].CONFIG & DMA_CONFIG_ACTIVE);
645 #endif
646 
647     hal_dma_cancel(ch);
648 }
649 
hal_dma_get_chan(enum HAL_DMA_PERIPH_T periph,enum HAL_DMA_GET_CHAN_T policy)650 uint8_t hal_dma_get_chan(enum HAL_DMA_PERIPH_T periph, enum HAL_DMA_GET_CHAN_T policy)
651 {
652     enum HAL_DMA_INST_T inst;
653     int ret;
654     uint8_t i, hwch;
655     uint8_t got = HAL_DMA_CHAN_NONE;
656     uint32_t lock;
657 
658     ASSERT(policy == HAL_DMA_HIGH_PRIO || policy == HAL_DMA_LOW_PRIO || policy == HAL_DMA_LOW_PRIO_ONLY,
659         "Invalid DMA policy: %d", policy);
660 
661     if (periph == HAL_GPDMA_MEM) {
662         inst = HAL_DMA_INST_GPDMA;
663     } else if (periph == HAL_AUDMA_MEM) {
664         inst = HAL_DMA_INST_AUDMA;
665     } else {
666         ret = get_index_from_periph(periph, &inst, &i);
667         ASSERT(ret == 0, "Invalid DMA periph: %d", periph);
668 #ifdef DMA_REMAP
669         if (periph_remap_bitmap[inst] & (1 << i)) {
670             inst ^= 1;
671         }
672 #endif
673     }
674 
675     lock = int_lock();
676     for (i = 0; i < DMA_NUMBER_CHANNELS; i++) {
677         if (policy == HAL_DMA_HIGH_PRIO) {
678             hwch = i;
679         } else if (policy == HAL_DMA_LOW_PRIO) {
680             hwch = DMA_NUMBER_CHANNELS - 1 - i;
681         } else {
682             hwch = DMA_NUMBER_CHANNELS - 1 - i;
683             if (hwch < 6) {
684                 break;
685             }
686         }
687 
688         if (!chan_enabled[inst][hwch] && !hal_dma_chan_busy_inst(inst, hwch)) {
689             chan_enabled[inst][hwch] = true;
690             got = generate_chan(inst, hwch);
691             dma[inst]->DMACONFIG |= DMA_DMACONFIG_CLK_EN(1 << hwch);
692             break;
693         }
694     }
695     int_unlock(lock);
696 
697 #ifdef DMA_DEBUG
698     if (got != HAL_DMA_CHAN_NONE) {
699         chan_user[inst][hwch] = __builtin_return_address(0);
700     }
701 #endif
702 
703     return got;
704 }
705 
hal_dma_free_chan(uint8_t ch)706 void hal_dma_free_chan(uint8_t ch)
707 {
708     enum HAL_DMA_INST_T inst;
709     uint8_t hwch;
710     uint32_t lock;
711 
712     inst = get_inst_from_chan(ch);
713     hwch = get_hwch_from_chan(ch);
714 
715     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
716     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
717     ASSERT(chan_enabled[inst][hwch], "DMA chan not enabled: inst=%u hwch=%u", inst, hwch);
718 
719     hal_dma_cancel(ch);
720 
721     lock = int_lock();
722     chan_enabled[inst][hwch] = false;
723     dma[inst]->DMACONFIG &= ~DMA_DMACONFIG_CLK_EN(1 << hwch);
724     int_unlock(lock);
725 }
726 
hal_dma_get_cur_src_addr(uint8_t ch)727 uint32_t hal_dma_get_cur_src_addr(uint8_t ch)
728 {
729     enum HAL_DMA_INST_T inst;
730     uint8_t hwch;
731 
732     inst = get_inst_from_chan(ch);
733     hwch = get_hwch_from_chan(ch);
734 
735     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
736     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
737 
738     return dma[inst]->CH[hwch].SRCADDR;
739 }
740 
hal_dma_get_cur_dst_addr(uint8_t ch)741 uint32_t hal_dma_get_cur_dst_addr(uint8_t ch)
742 {
743     enum HAL_DMA_INST_T inst;
744     uint8_t hwch;
745 
746     inst = get_inst_from_chan(ch);
747     hwch = get_hwch_from_chan(ch);
748 
749     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
750     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
751 
752     return dma[inst]->CH[hwch].DSTADDR;
753 }
754 
hal_dma_get_cur_src_remain_and_addr(uint8_t ch,uint32_t * remain,uint32_t * src)755 void SRAM_TEXT_LOC hal_dma_get_cur_src_remain_and_addr(uint8_t ch, uint32_t *remain, uint32_t *src)
756 {
757     enum HAL_DMA_INST_T inst;
758     uint8_t hwch;
759     uint32_t lock;
760     uint32_t size[2];
761     uint32_t srcaddr[2];
762 
763     inst = get_inst_from_chan(ch);
764     hwch = get_hwch_from_chan(ch);
765 
766     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
767     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
768 
769     lock = int_lock();
770     size[0] = dma[inst]->CH[hwch].CONTROL;
771     srcaddr[0] = dma[inst]->CH[hwch].SRCADDR;
772     size[1] = dma[inst]->CH[hwch].CONTROL;
773     srcaddr[1] = dma[inst]->CH[hwch].SRCADDR;
774     int_unlock(lock);
775 
776     size[0] = GET_BITFIELD(size[0], DMA_CONTROL_TRANSFERSIZE);
777     size[1] = GET_BITFIELD(size[1], DMA_CONTROL_TRANSFERSIZE);
778 
779     if (size[0] == size[1]) {
780         *remain = size[0];
781         *src = srcaddr[0];
782     } else {
783         *remain = size[1];
784         *src = srcaddr[1];
785     }
786 
787     return;
788 }
789 
hal_dma_irq_run_chan(uint8_t ch)790 enum HAL_DMA_RET_T hal_dma_irq_run_chan(uint8_t ch)
791 {
792     enum HAL_DMA_INST_T inst;
793     uint8_t hwch;
794 
795     inst = get_inst_from_chan(ch);
796     hwch = get_hwch_from_chan(ch);
797 
798     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
799     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
800 
801     if ((dma[inst]->INTSTAT & DMA_STAT_CHAN(hwch)) == 0) {
802         return HAL_DMA_ERR;
803     }
804 
805     hal_dma_handle_chan_irq(inst, hwch);
806 
807     return HAL_DMA_OK;
808 }
809 
hal_dma_chan_busy(uint8_t ch)810 bool hal_dma_chan_busy(uint8_t ch)
811 {
812     enum HAL_DMA_INST_T inst;
813     uint8_t hwch;
814 
815     inst = get_inst_from_chan(ch);
816     hwch = get_hwch_from_chan(ch);
817 
818     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
819     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
820 
821     return hal_dma_chan_busy_inst(inst, hwch);
822 }
823 
hal_dma_busy(void)824 bool hal_dma_busy(void)
825 {
826     enum HAL_DMA_INST_T inst;
827     int hwch;
828 
829     for (inst = HAL_DMA_INST_AUDMA; inst < HAL_DMA_INST_QTY; inst++) {
830         for (hwch = chan_start[inst]; hwch < chan_num[inst]; hwch++) {
831             if (hal_dma_chan_busy_inst(inst, hwch)) {
832                 return true;
833             }
834         }
835     }
836 
837     return false;
838 }
839 
hal_dma_get_sg_remain_size(uint8_t ch)840 uint32_t hal_dma_get_sg_remain_size(uint8_t ch)
841 {
842     enum HAL_DMA_INST_T inst;
843     uint8_t hwch;
844     uint32_t remains;
845     const struct HAL_DMA_DESC_T *desc, *first;
846 
847     inst = get_inst_from_chan(ch);
848     hwch = get_hwch_from_chan(ch);
849 
850     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
851     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
852 
853     remains = GET_BITFIELD(dma[inst]->CH[hwch].CONTROL, DMA_CONTROL_TRANSFERSIZE);
854     first = (const struct HAL_DMA_DESC_T *)dma[inst]->CH[hwch].LLI;
855     desc = first;
856     while (desc) {
857         remains += GET_BITFIELD(desc->ctrl, DMA_CONTROL_TRANSFERSIZE);
858         desc = (const struct HAL_DMA_DESC_T *)desc->lli;
859         if (desc == first) {
860             break;
861         }
862     }
863 
864     return remains;
865 }
866 
hal_dma_tc_irq_enable(uint8_t ch)867 void hal_dma_tc_irq_enable(uint8_t ch)
868 {
869 #if !(defined(CHIP_BEST1000) || defined(CHIP_BEST2000) || defined(CHIP_BEST3001) || defined(CHIP_BEST3005))
870     enum HAL_DMA_INST_T inst;
871     uint8_t hwch;
872     uint32_t lock;
873 
874     inst = get_inst_from_chan(ch);
875     hwch = get_hwch_from_chan(ch);
876 
877     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
878     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
879 
880     lock = int_lock();
881 #ifdef CHIP_BEST2300
882     if (inst == HAL_DMA_INST_AUDMA) {
883         hal_cmu_dma_tc_irq_set_chan(hwch);
884     }
885 #else
886     dma[inst]->DMACONFIG |= DMA_DMACONFIG_TC_IRQ_EN(1 << hwch);
887 #endif
888     int_unlock(lock);
889 #endif
890 }
891 
hal_dma_tc_irq_disable(uint8_t ch)892 void hal_dma_tc_irq_disable(uint8_t ch)
893 {
894 #if !(defined(CHIP_BEST1000) || defined(CHIP_BEST2000) || defined(CHIP_BEST3001) || defined(CHIP_BEST3005))
895     enum HAL_DMA_INST_T inst;
896     uint8_t hwch;
897     uint32_t lock;
898 
899     inst = get_inst_from_chan(ch);
900     hwch = get_hwch_from_chan(ch);
901 
902     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
903     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
904 
905     lock = int_lock();
906 #ifdef CHIP_BEST2300
907     if (inst == HAL_DMA_INST_AUDMA) {
908         hal_cmu_dma_tc_irq_clear_chan(hwch);
909     }
910 #else
911     dma[inst]->DMACONFIG &= ~DMA_DMACONFIG_TC_IRQ_EN(1 << hwch);
912 #endif
913     int_unlock(lock);
914 #endif
915 }
916 
hal_dma_set_burst_addr_inc(uint8_t ch,const struct HAL_DMA_BURST_ADDR_INC_T * inc)917 void hal_dma_set_burst_addr_inc(uint8_t ch, const struct HAL_DMA_BURST_ADDR_INC_T *inc)
918 {
919 #if !(defined(CHIP_BEST1000) || defined(CHIP_BEST2000) || defined(CHIP_BEST3001) || defined(CHIP_BEST3005))
920     enum HAL_DMA_INST_T inst;
921     uint8_t hwch;
922     uint32_t lock;
923 
924     inst = get_inst_from_chan(ch);
925     hwch = get_hwch_from_chan(ch);
926 
927     ASSERT(inst < HAL_DMA_INST_QTY, err_invalid_inst, inst);
928     ASSERT(hwch < DMA_NUMBER_CHANNELS, err_invalid_chan[inst], hwch);
929 
930     lock = int_lock();
931     if (inc && inc->src_inc_en) {
932         dma[inst]->CH[hwch].CONTROL |= DMA_CONTROL_BURST_SI;
933         dma[inst]->_2D[hwch].SRC_INC = SET_BITFIELD(dma[inst]->_2D[hwch].SRC_INC, DMA_BURST_SRC_INC_VAL, inc->src_inc_val);
934     } else {
935         dma[inst]->CH[hwch].CONTROL &= ~DMA_CONTROL_BURST_SI;
936     }
937     if (inc && inc->dst_inc_en) {
938         dma[inst]->CH[hwch].CONTROL |= DMA_CONTROL_BURST_DI;
939         dma[inst]->_2D[hwch].DST_INC = SET_BITFIELD(dma[inst]->_2D[hwch].DST_INC, DMA_BURST_DST_INC_VAL, inc->dst_inc_val);
940     } else {
941         dma[inst]->CH[hwch].CONTROL &= ~DMA_CONTROL_BURST_DI;
942     }
943     int_unlock(lock);
944 #endif
945 }
946 
hal_dma_clear_burst_addr_inc(uint8_t ch)947 void hal_dma_clear_burst_addr_inc(uint8_t ch)
948 {
949     hal_dma_set_burst_addr_inc(ch, NULL);
950 }
951 
hal_dma_set_desc_burst_addr_inc(struct HAL_DMA_DESC_T * desc,const struct HAL_DMA_BURST_ADDR_INC_T * inc)952 void hal_dma_set_desc_burst_addr_inc(struct HAL_DMA_DESC_T *desc, const struct HAL_DMA_BURST_ADDR_INC_T *inc)
953 {
954 #if !(defined(CHIP_BEST1000) || defined(CHIP_BEST2000) || defined(CHIP_BEST3001) || defined(CHIP_BEST3005))
955     if (inc && inc->src_inc_en) {
956         desc->ctrl |= DMA_CONTROL_BURST_SI;
957     } else {
958         desc->ctrl &= ~DMA_CONTROL_BURST_SI;
959     }
960     if (inc && inc->dst_inc_en) {
961         desc->ctrl |= DMA_CONTROL_BURST_DI;
962     } else {
963         desc->ctrl &= ~DMA_CONTROL_BURST_DI;
964     }
965 #endif
966 }
967 
hal_dma_clear_desc_burst_addr_inc(struct HAL_DMA_DESC_T * desc)968 void hal_dma_clear_desc_burst_addr_inc(struct HAL_DMA_DESC_T *desc)
969 {
970     hal_dma_set_desc_burst_addr_inc(desc, NULL);
971 }
972 
973 #ifdef DMA_REMAP
hal_dma_remap_periph(enum HAL_DMA_PERIPH_T periph,int enable)974 void hal_dma_remap_periph(enum HAL_DMA_PERIPH_T periph, int enable)
975 {
976     enum HAL_DMA_INST_T inst1, inst2;
977     uint8_t index1, index2;
978     int ret;
979     uint32_t lock;
980 
981     // Tag the periph
982     ret = get_index_from_periph(periph, &inst1, &index1);
983     ASSERT(ret == 0, "Invalid DMA periph for remap1: %d", periph);
984 
985     // Tag the peer periph
986     inst2 = inst1 ^ 1;
987     ret = get_remap_index_from_periph(inst2, periph, &index2);
988     ASSERT(ret == 0, "Invalid DMA periph for remap2: %d", periph);
989 
990     lock = int_lock();
991     if (enable) {
992         periph_remap_bitmap[inst1] |= (1 << index1);
993         periph_remap_bitmap[inst2] |= (1 << index2);
994 #ifndef CHIP_BEST1000
995         // For best2000, index1 == index2
996         hal_cmu_dma_swap_enable(index1);
997 #endif
998     } else {
999         periph_remap_bitmap[inst1] &= ~(1 << index1);
1000         periph_remap_bitmap[inst2] &= ~(1 << index2);
1001 #ifndef CHIP_BEST1000
1002         hal_cmu_dma_swap_disable(index1);
1003 #endif
1004     }
1005     int_unlock(lock);
1006 }
1007 #endif
1008 
hal_dma_open(void)1009 void hal_dma_open(void)
1010 {
1011     enum HAL_DMA_INST_T inst;
1012 
1013     if (dma_opened) {
1014         return;
1015     }
1016 
1017     for (inst = HAL_DMA_INST_AUDMA; inst < HAL_DMA_INST_QTY; inst++) {
1018         hal_dma_open_inst(inst);
1019     }
1020 
1021 #ifdef DMA_REMAP
1022 #ifdef CHIP_BEST1000
1023     if (hal_get_chip_metal_id() >= HAL_CHIP_METAL_ID_4) {
1024         hal_dma_remap_periph(HAL_AUDMA_I2S0_RX, 1);
1025         hal_dma_remap_periph(HAL_AUDMA_I2S0_TX, 1);
1026         hal_dma_remap_periph(HAL_AUDMA_SPDIF0_RX, 1);
1027         hal_dma_remap_periph(HAL_AUDMA_SPDIF0_TX, 1);
1028     }
1029 #endif
1030 #endif
1031 
1032     dma_opened = true;
1033 }
1034 
hal_dma_close(void)1035 void hal_dma_close(void)
1036 {
1037     enum HAL_DMA_INST_T inst;
1038 
1039     if (!dma_opened) {
1040         return;
1041     }
1042 
1043     for (inst = 0; inst < HAL_DMA_INST_QTY; inst++) {
1044         hal_dma_close_inst(inst);
1045     }
1046 
1047     dma_opened = false;
1048 }
1049 
1050 #ifdef CORE_SLEEP_POWER_DOWN
hal_dma_sleep(void)1051 void hal_dma_sleep(void)
1052 {
1053     enum HAL_DMA_INST_T inst;
1054 
1055     for (inst = 0; inst < HAL_DMA_INST_QTY; inst++) {
1056         saved_dma_regs[inst] = dma[inst]->DMACONFIG;
1057     }
1058 }
1059 
hal_dma_wakeup(void)1060 void hal_dma_wakeup(void)
1061 {
1062     enum HAL_DMA_INST_T inst;
1063 
1064     for (inst = 0; inst < HAL_DMA_INST_QTY; inst++) {
1065         dma[inst]->DMACONFIG = saved_dma_regs[inst];
1066     }
1067 }
1068 #endif
1069 
hal_dma_set_delay_func(HAL_DMA_DELAY_FUNC new_func)1070 HAL_DMA_DELAY_FUNC hal_dma_set_delay_func(HAL_DMA_DELAY_FUNC new_func)
1071 {
1072     HAL_DMA_DELAY_FUNC old_func = dma_delay;
1073     dma_delay = new_func;
1074     return old_func;
1075 }
1076 
hal_dma_record_busy_chan(void)1077 void hal_dma_record_busy_chan(void)
1078 {
1079 #ifdef DMA_DEBUG
1080     enum HAL_DMA_INST_T inst;
1081     int hwch;
1082 
1083     for (inst = HAL_DMA_INST_AUDMA; inst < HAL_DMA_INST_QTY; inst++) {
1084         debug_user_map[inst] = 0;
1085         for (hwch = chan_start[inst]; hwch < chan_num[inst]; hwch++) {
1086             if (hal_dma_chan_busy_inst(inst, hwch)) {
1087                 debug_user_map[inst] |= (1 << hwch);
1088             }
1089         }
1090     }
1091 #endif
1092 }
1093 
hal_dma_print_busy_chan(void)1094 void hal_dma_print_busy_chan(void)
1095 {
1096 #ifdef DMA_DEBUG
1097     enum HAL_DMA_INST_T inst;
1098     int hwch;
1099 
1100     for (inst = HAL_DMA_INST_AUDMA; inst < HAL_DMA_INST_QTY; inst++) {
1101         for (hwch = chan_start[inst]; hwch < chan_num[inst]; hwch++) {
1102             if (debug_user_map[inst] & (1 << hwch)) {
1103                 TRACE(0, "*** DMA CHAN BUSY: %u-%u %8X", inst, hwch, (uint32_t)chan_user[inst][hwch]);
1104             }
1105         }
1106     }
1107 #endif
1108 }
1109 
1110