Lines Matching +full:enable +full:- +full:channel

4  * SPDX-License-Identifier: Apache-2.0
30 /* Handles DMA interrupts and dispatches to the individual channel */
33 struct dma_sam0_data *data = dev->data; in dma_sam0_isr()
35 uint16_t pend = DMA_REGS->INTPEND.reg; in dma_sam0_isr()
36 uint32_t channel; in dma_sam0_isr() local
38 /* Acknowledge all interrupts for the channel in pend */ in dma_sam0_isr()
39 DMA_REGS->INTPEND.reg = pend; in dma_sam0_isr()
41 channel = (pend & DMAC_INTPEND_ID_Msk) >> DMAC_INTPEND_ID_Pos; in dma_sam0_isr()
42 chdata = &data->channels[channel]; in dma_sam0_isr()
45 if (chdata->cb) { in dma_sam0_isr()
46 chdata->cb(dev, chdata->user_data, in dma_sam0_isr()
47 channel, -DMAC_INTPEND_TERR); in dma_sam0_isr()
50 if (chdata->cb) { in dma_sam0_isr()
51 chdata->cb(dev, chdata->user_data, channel, 0); in dma_sam0_isr()
56 * If more than one channel is pending, we'll just immediately in dma_sam0_isr()
61 /* Configure a channel */
62 static int dma_sam0_config(const struct device *dev, uint32_t channel, in dma_sam0_config() argument
65 struct dma_sam0_data *data = dev->data; in dma_sam0_config()
66 DmacDescriptor *desc = &data->descriptors[channel]; in dma_sam0_config()
67 struct dma_block_config *block = config->head_block; in dma_sam0_config()
72 if (channel >= DMAC_CH_NUM) { in dma_sam0_config()
73 LOG_ERR("Unsupported channel"); in dma_sam0_config()
74 return -EINVAL; in dma_sam0_config()
77 if (config->block_count > 1) { in dma_sam0_config()
80 return -ENOTSUP; in dma_sam0_config()
83 if (config->dma_slot >= DMAC_TRIG_NUM) { in dma_sam0_config()
85 return -EINVAL; in dma_sam0_config()
88 /* Lock and page in the channel configuration */ in dma_sam0_config()
93 * independently accessible registers for each channel, while in dma_sam0_config()
94 * the other ones require an indirect channel selection before in dma_sam0_config()
100 /* Select the channel for configuration */ in dma_sam0_config()
101 DMA_REGS->CHID.reg = DMAC_CHID_ID(channel); in dma_sam0_config()
102 DMA_REGS->CHCTRLA.reg = 0; in dma_sam0_config()
105 if (config->channel_direction == MEMORY_TO_MEMORY) { in dma_sam0_config()
110 DMA_REGS->CHCTRLB.reg = DMAC_CHCTRLB_TRIGACT_TRANSACTION | in dma_sam0_config()
111 DMAC_CHCTRLB_TRIGSRC(config->dma_slot); in dma_sam0_config()
114 DMA_REGS->CHCTRLB.reg = DMAC_CHCTRLB_TRIGACT_BEAT | in dma_sam0_config()
115 DMAC_CHCTRLB_TRIGSRC(config->dma_slot); in dma_sam0_config()
119 if (config->channel_priority >= DMAC_LVL_NUM) { in dma_sam0_config()
124 DMA_REGS->CHCTRLB.bit.LVL = config->channel_priority; in dma_sam0_config()
126 /* Enable the interrupts */ in dma_sam0_config()
127 DMA_REGS->CHINTENSET.reg = DMAC_CHINTENSET_TCMPL; in dma_sam0_config()
128 if (!config->error_callback_dis) { in dma_sam0_config()
129 DMA_REGS->CHINTENSET.reg = DMAC_CHINTENSET_TERR; in dma_sam0_config()
131 DMA_REGS->CHINTENCLR.reg = DMAC_CHINTENSET_TERR; in dma_sam0_config()
134 DMA_REGS->CHINTFLAG.reg = DMAC_CHINTFLAG_TERR | DMAC_CHINTFLAG_TCMPL; in dma_sam0_config()
137 DmacChannel * chcfg = &DMA_REGS->Channel[channel]; in dma_sam0_config()
139 if (config->channel_direction == MEMORY_TO_MEMORY) { in dma_sam0_config()
144 chcfg->CHCTRLA.reg = DMAC_CHCTRLA_TRIGACT_TRANSACTION | in dma_sam0_config()
145 DMAC_CHCTRLA_TRIGSRC(config->dma_slot); in dma_sam0_config()
146 } else if ((config->channel_direction == MEMORY_TO_PERIPHERAL) || in dma_sam0_config()
147 (config->channel_direction == PERIPHERAL_TO_MEMORY)) { in dma_sam0_config()
149 chcfg->CHCTRLA.reg = DMAC_CHCTRLA_TRIGACT_BURST | in dma_sam0_config()
150 DMAC_CHCTRLA_TRIGSRC(config->dma_slot); in dma_sam0_config()
152 LOG_ERR("Direction error. %d", config->channel_direction); in dma_sam0_config()
157 if (config->channel_priority >= DMAC_LVL_NUM) { in dma_sam0_config()
162 chcfg->CHPRILVL.bit.PRILVL = config->channel_priority; in dma_sam0_config()
165 if (config->source_burst_length != config->dest_burst_length) { in dma_sam0_config()
170 if (config->source_burst_length > 16U) { in dma_sam0_config()
175 if (config->source_burst_length > 0U) { in dma_sam0_config()
176 chcfg->CHCTRLA.reg |= DMAC_CHCTRLA_BURSTLEN( in dma_sam0_config()
177 config->source_burst_length - 1U); in dma_sam0_config()
180 /* Enable the interrupts */ in dma_sam0_config()
181 chcfg->CHINTENSET.reg = DMAC_CHINTENSET_TCMPL; in dma_sam0_config()
182 if (!config->error_callback_dis) { in dma_sam0_config()
183 chcfg->CHINTENSET.reg = DMAC_CHINTENSET_TERR; in dma_sam0_config()
185 chcfg->CHINTENCLR.reg = DMAC_CHINTENSET_TERR; in dma_sam0_config()
188 chcfg->CHINTFLAG.reg = DMAC_CHINTFLAG_TERR | DMAC_CHINTFLAG_TCMPL; in dma_sam0_config()
192 if (config->source_data_size != config->dest_data_size) { in dma_sam0_config()
197 switch (config->source_data_size) { in dma_sam0_config()
213 desc->BTCNT.reg = block->block_size / config->source_data_size; in dma_sam0_config()
214 desc->DESCADDR.reg = 0; in dma_sam0_config()
217 switch (block->source_addr_adj) { in dma_sam0_config()
219 desc->SRCADDR.reg = block->source_address + block->block_size; in dma_sam0_config()
223 desc->SRCADDR.reg = block->source_address; in dma_sam0_config()
230 switch (block->dest_addr_adj) { in dma_sam0_config()
232 desc->DSTADDR.reg = block->dest_address + block->block_size; in dma_sam0_config()
236 desc->DSTADDR.reg = block->dest_address; in dma_sam0_config()
244 desc->BTCTRL = btctrl; in dma_sam0_config()
246 channel_control = &data->channels[channel]; in dma_sam0_config()
247 channel_control->cb = config->dma_callback; in dma_sam0_config()
248 channel_control->user_data = config->user_data; in dma_sam0_config()
250 LOG_DBG("Configured channel %d for %08X to %08X (%u)", in dma_sam0_config()
251 channel, in dma_sam0_config()
252 block->source_address, in dma_sam0_config()
253 block->dest_address, in dma_sam0_config()
254 block->block_size); in dma_sam0_config()
261 return -EINVAL; in dma_sam0_config()
264 static int dma_sam0_start(const struct device *dev, uint32_t channel) in dma_sam0_start() argument
271 DMA_REGS->CHID.reg = channel; in dma_sam0_start()
272 DMA_REGS->CHCTRLA.reg = DMAC_CHCTRLA_ENABLE; in dma_sam0_start()
274 if (DMA_REGS->CHCTRLB.bit.TRIGSRC == 0) { in dma_sam0_start()
276 DMA_REGS->SWTRIGCTRL.reg = 1U << channel; in dma_sam0_start()
280 DmacChannel * chcfg = &DMA_REGS->Channel[channel]; in dma_sam0_start()
282 chcfg->CHCTRLA.bit.ENABLE = 1; in dma_sam0_start()
284 if (chcfg->CHCTRLA.bit.TRIGSRC == 0) { in dma_sam0_start()
286 DMA_REGS->SWTRIGCTRL.reg = 1U << channel; in dma_sam0_start()
295 static int dma_sam0_stop(const struct device *dev, uint32_t channel) in dma_sam0_stop() argument
302 DMA_REGS->CHID.reg = channel; in dma_sam0_stop()
303 DMA_REGS->CHCTRLA.reg = 0; in dma_sam0_stop()
305 DmacChannel * chcfg = &DMA_REGS->Channel[channel]; in dma_sam0_stop()
307 chcfg->CHCTRLA.bit.ENABLE = 0; in dma_sam0_stop()
315 static int dma_sam0_reload(const struct device *dev, uint32_t channel, in dma_sam0_reload() argument
318 struct dma_sam0_data *data = dev->data; in dma_sam0_reload()
319 DmacDescriptor *desc = &data->descriptors[channel]; in dma_sam0_reload()
322 switch (desc->BTCTRL.bit.BEATSIZE) { in dma_sam0_reload()
324 desc->BTCNT.reg = size; in dma_sam0_reload()
327 desc->BTCNT.reg = size / 2U; in dma_sam0_reload()
330 desc->BTCNT.reg = size / 4U; in dma_sam0_reload()
336 if (desc->BTCTRL.bit.SRCINC) { in dma_sam0_reload()
337 desc->SRCADDR.reg = src + size; in dma_sam0_reload()
339 desc->SRCADDR.reg = src; in dma_sam0_reload()
342 if (desc->BTCTRL.bit.DSTINC) { in dma_sam0_reload()
343 desc->DSTADDR.reg = dst + size; in dma_sam0_reload()
345 desc->DSTADDR.reg = dst; in dma_sam0_reload()
348 LOG_DBG("Reloaded channel %d for %08X to %08X (%u)", in dma_sam0_reload()
349 channel, src, dst, size); in dma_sam0_reload()
356 return -EINVAL; in dma_sam0_reload()
359 static int dma_sam0_get_status(const struct device *dev, uint32_t channel, in dma_sam0_get_status() argument
362 struct dma_sam0_data *data = dev->data; in dma_sam0_get_status()
365 if (channel >= DMAC_CH_NUM || stat == NULL) { in dma_sam0_get_status()
366 return -EINVAL; in dma_sam0_get_status()
369 act = DMA_REGS->ACTIVE.reg; in dma_sam0_get_status()
371 ((act & DMAC_ACTIVE_ID_Msk) >> DMAC_ACTIVE_ID_Pos) == channel) { in dma_sam0_get_status()
372 stat->busy = true; in dma_sam0_get_status()
373 stat->pending_length = (act & DMAC_ACTIVE_BTCNT_Msk) >> in dma_sam0_get_status()
376 stat->busy = false; in dma_sam0_get_status()
377 stat->pending_length = data->descriptors_wb[channel].BTCNT.reg; in dma_sam0_get_status()
380 switch (data->descriptors[channel].BTCTRL.bit.BEATSIZE) { in dma_sam0_get_status()
384 stat->pending_length *= 2U; in dma_sam0_get_status()
387 stat->pending_length *= 4U; in dma_sam0_get_status()
390 return -EINVAL; in dma_sam0_get_status()
406 struct dma_sam0_data *data = dev->data; in dma_sam0_init()
408 /* Enable clocks. */ in dma_sam0_init()
410 MCLK->AHBMASK.bit.DMAC_ = 1; in dma_sam0_init()
412 PM->AHBMASK.bit.DMAC_ = 1; in dma_sam0_init()
413 PM->APBBMASK.bit.DMAC_ = 1; in dma_sam0_init()
417 DMA_REGS->BASEADDR.reg = (uintptr_t)&data->descriptors; in dma_sam0_init()
418 DMA_REGS->WRBADDR.reg = (uintptr_t)&data->descriptors_wb; in dma_sam0_init()
421 DMA_REGS->PRICTRL0.reg = in dma_sam0_init()
425 /* Enable the unit and enable all priorities */ in dma_sam0_init()
426 DMA_REGS->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN(0x0F); in dma_sam0_init()