Lines Matching +full:tx +full:- +full:buffer +full:- +full:descriptors
2 * Copyright (c) 2020-2023 NXP
4 * SPDX-License-Identifier: Apache-2.0
71 ((DMA_Type *)((const struct dma_mcux_lpc_config *const)(dev)->config)->base)
74 ((struct channel_data *)(&(((struct dma_mcux_lpc_dma_data *)dev->data)->channel_data[ch])))
77 ((dma_handle_t *)(&(DEV_CHANNEL_DATA(dev, ch)->dma_handle)))
79 #define EMPTY_OTRIG -1
84 int ret = -EIO; in nxp_lpc_dma_callback()
86 uint32_t channel = handle->channel; in nxp_lpc_dma_callback()
96 data->busy = DMA_ChannelIsBusy(data->dma_handle.base, channel); in nxp_lpc_dma_callback()
98 if (data->dma_callback) { in nxp_lpc_dma_callback()
99 data->dma_callback(data->dev, data->user_data, channel, ret); in nxp_lpc_dma_callback()
108 * Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store in dma_mcux_lpc_irq_handler()
127 if (((block->source_address & 0xF8000000) == 0x18000000) || in rw6xx_dma_addr_fixup()
128 ((block->source_address & 0xF8000000) == 0x8000000)) { in rw6xx_dma_addr_fixup()
129 block->source_address = block->source_address + 0x40000000; in rw6xx_dma_addr_fixup()
131 if (((block->dest_address & 0xF8000000) == 0x18000000) || in rw6xx_dma_addr_fixup()
132 ((block->dest_address & 0xF8000000) == 0x8000000)) { in rw6xx_dma_addr_fixup()
133 block->dest_address = block->dest_address + 0x40000000; in rw6xx_dma_addr_fixup()
147 uint32_t width = data->width; in dma_mcux_lpc_queue_descriptors()
161 /* Descriptors are queued during dma_configure, do not add more in dma_mcux_lpc_queue_descriptors()
164 if (!data->descriptors_queued) { in dma_mcux_lpc_queue_descriptors()
165 /* Increase the number of descriptors queued */ in dma_mcux_lpc_queue_descriptors()
166 data->num_of_descriptors++; in dma_mcux_lpc_queue_descriptors()
168 if (data->num_of_descriptors >= CONFIG_DMA_MCUX_LPC_NUMBER_OF_DESCRIPTORS) { in dma_mcux_lpc_queue_descriptors()
169 return -ENOMEM; in dma_mcux_lpc_queue_descriptors()
171 /* Do we need to queue additional DMA descriptors for this block */ in dma_mcux_lpc_queue_descriptors()
174 /* Allocate DMA descriptors */ in dma_mcux_lpc_queue_descriptors()
176 &data->dma_descriptor_table[data->num_of_descriptors]; in dma_mcux_lpc_queue_descriptors()
185 /* No more descriptors */ in dma_mcux_lpc_queue_descriptors()
187 } else if (data->num_of_descriptors == 1) { in dma_mcux_lpc_queue_descriptors()
188 /* Allocate one more descriptors for in dma_mcux_lpc_queue_descriptors()
189 * ping-pong transfer in dma_mcux_lpc_queue_descriptors()
191 next_descriptor = &data->dma_descriptor_table[ in dma_mcux_lpc_queue_descriptors()
192 data->num_of_descriptors]; in dma_mcux_lpc_queue_descriptors()
197 next_descriptor = data->dma_descriptor_table; in dma_mcux_lpc_queue_descriptors()
202 /* Descriptors have already been allocated, reuse them as this in dma_mcux_lpc_queue_descriptors()
205 next_descriptor = data->curr_descriptor->linkToNextDesc; in dma_mcux_lpc_queue_descriptors()
208 /* SPI TX transfers need to queue a DMA descriptor to in dma_mcux_lpc_queue_descriptors()
238 /* Reload if we have more descriptors */ in dma_mcux_lpc_queue_descriptors()
256 DMA_SetupDescriptor(data->curr_descriptor, in dma_mcux_lpc_queue_descriptors()
262 data->curr_descriptor = next_descriptor; in dma_mcux_lpc_queue_descriptors()
265 local_block.block_size -= max_xfer_bytes; in dma_mcux_lpc_queue_descriptors()
280 /* Increase the number of descriptors queued */ in dma_mcux_lpc_queue_descriptors()
281 data->num_of_descriptors++; in dma_mcux_lpc_queue_descriptors()
284 next_descriptor = data->dma_descriptor_table; in dma_mcux_lpc_queue_descriptors()
302 DMA_SetupDescriptor(data->curr_descriptor, in dma_mcux_lpc_queue_descriptors()
314 data->dma_callback = NULL; in dma_mcux_lpc_clear_channel_data()
315 data->dir = 0; in dma_mcux_lpc_clear_channel_data()
316 data->src_inc = 0; in dma_mcux_lpc_clear_channel_data()
317 data->dst_inc = 0; in dma_mcux_lpc_clear_channel_data()
318 data->descriptors_queued = false; in dma_mcux_lpc_clear_channel_data()
319 data->num_of_descriptors = 0; in dma_mcux_lpc_clear_channel_data()
320 data->curr_descriptor = NULL; in dma_mcux_lpc_clear_channel_data()
321 data->width = 0; in dma_mcux_lpc_clear_channel_data()
344 return -EINVAL; in dma_mcux_lpc_configure()
347 dev_config = dev->config; in dma_mcux_lpc_configure()
348 dma_data = dev->data; in dma_mcux_lpc_configure()
349 block_config = config->head_block; in dma_mcux_lpc_configure()
355 assert(config->dest_data_size == config->source_data_size); in dma_mcux_lpc_configure()
356 width = config->dest_data_size; in dma_mcux_lpc_configure()
361 if (block_config->source_gather_en && block_config->dest_scatter_en) { in dma_mcux_lpc_configure()
362 assert(block_config->source_gather_interval == in dma_mcux_lpc_configure()
363 block_config->dest_scatter_interval); in dma_mcux_lpc_configure()
371 if (config->head_block->source_reload_en || in dma_mcux_lpc_configure()
372 config->head_block->dest_reload_en) { in dma_mcux_lpc_configure()
377 if (dma_data->num_channels_used > dev_config->num_of_channels) { in dma_mcux_lpc_configure()
379 return -EINVAL; in dma_mcux_lpc_configure()
383 if (channel >= dev_config->num_of_channels) { in dma_mcux_lpc_configure()
385 return -EINVAL; in dma_mcux_lpc_configure()
388 if (config->source_data_size != 4U && in dma_mcux_lpc_configure()
389 config->source_data_size != 2U && in dma_mcux_lpc_configure()
390 config->source_data_size != 1U) { in dma_mcux_lpc_configure()
391 LOG_ERR("Source unit size error, %d", config->source_data_size); in dma_mcux_lpc_configure()
392 return -EINVAL; in dma_mcux_lpc_configure()
395 if (config->dest_data_size != 4U && in dma_mcux_lpc_configure()
396 config->dest_data_size != 2U && in dma_mcux_lpc_configure()
397 config->dest_data_size != 1U) { in dma_mcux_lpc_configure()
398 LOG_ERR("Dest unit size error, %d", config->dest_data_size); in dma_mcux_lpc_configure()
399 return -EINVAL; in dma_mcux_lpc_configure()
402 switch (config->channel_direction) { in dma_mcux_lpc_configure()
405 if (block_config->source_gather_en) { in dma_mcux_lpc_configure()
406 src_inc = block_config->source_gather_interval / width; in dma_mcux_lpc_configure()
411 return -EINVAL; in dma_mcux_lpc_configure()
415 if (block_config->dest_scatter_en) { in dma_mcux_lpc_configure()
416 dst_inc = block_config->dest_scatter_interval / width; in dma_mcux_lpc_configure()
421 return -EINVAL; in dma_mcux_lpc_configure()
427 if (block_config->source_gather_en) { in dma_mcux_lpc_configure()
428 src_inc = block_config->source_gather_interval / width; in dma_mcux_lpc_configure()
433 return -EINVAL; in dma_mcux_lpc_configure()
443 if (block_config->dest_scatter_en) { in dma_mcux_lpc_configure()
444 dst_inc = block_config->dest_scatter_interval / width; in dma_mcux_lpc_configure()
449 return -EINVAL; in dma_mcux_lpc_configure()
455 return -EINVAL; in dma_mcux_lpc_configure()
459 if (block_config->source_addr_adj == DMA_ADDR_ADJ_NO_CHANGE) { in dma_mcux_lpc_configure()
463 if (block_config->dest_addr_adj == DMA_ADDR_ADJ_NO_CHANGE) { in dma_mcux_lpc_configure()
468 if (dma_data->channel_index[channel] == -1) { in dma_mcux_lpc_configure()
469 dma_data->channel_index[channel] = dma_data->num_channels_used; in dma_mcux_lpc_configure()
470 dma_data->num_channels_used++; in dma_mcux_lpc_configure()
472 virtual_channel = dma_data->channel_index[channel]; in dma_mcux_lpc_configure()
481 virtual_channel = dma_data->channel_index[channel]; in dma_mcux_lpc_configure()
489 data->dir = config->channel_direction; in dma_mcux_lpc_configure()
491 data->src_inc = src_inc; in dma_mcux_lpc_configure()
492 data->dst_inc = dst_inc; in dma_mcux_lpc_configure()
494 if (data->busy) { in dma_mcux_lpc_configure()
498 LOG_DBG("channel is %d", p_handle->channel); in dma_mcux_lpc_configure()
502 data->width = width; in dma_mcux_lpc_configure()
504 if (config->source_chaining_en || config->dest_chaining_en) { in dma_mcux_lpc_configure()
506 if (!dev_config->otrig_base_address || !dev_config->itrig_base_address) { in dma_mcux_lpc_configure()
511 return -ENXIO; in dma_mcux_lpc_configure()
515 channel, config->linked_channel); in dma_mcux_lpc_configure()
518 for (otrig_index = 0; otrig_index < dev_config->num_of_otrigs; in dma_mcux_lpc_configure()
520 if (dma_data->otrig_array[otrig_index].linked_channel == EMPTY_OTRIG || in dma_mcux_lpc_configure()
521 dma_data->otrig_array[otrig_index].source_channel == channel) { in dma_mcux_lpc_configure()
522 if (dma_data->otrig_array[otrig_index].source_channel == channel) { in dma_mcux_lpc_configure()
524 dma_data->otrig_array[otrig_index].linked_channel; in dma_mcux_lpc_configure()
526 DEV_BASE(dev)->CHANNEL[ChannelToDisable].CFG &= in dma_mcux_lpc_configure()
538 return -EINVAL; in dma_mcux_lpc_configure()
545 DEV_BASE(dev)->CHANNEL[config->linked_channel].CFG |= in dma_mcux_lpc_configure()
548 DMA_EnableChannel(DEV_BASE(dev), config->linked_channel); in dma_mcux_lpc_configure()
550 /* Link OTrig Muxes with passed-in channels */ in dma_mcux_lpc_configure()
552 dev_config->otrig_base_address + channel); in dma_mcux_lpc_configure()
553 INPUTMUX_AttachSignal(INPUTMUX, config->linked_channel, in dma_mcux_lpc_configure()
554 dev_config->itrig_base_address + otrig_index); in dma_mcux_lpc_configure()
557 dma_data->otrig_array[otrig_index].source_channel = channel; in dma_mcux_lpc_configure()
558 dma_data->otrig_array[otrig_index].linked_channel = config->linked_channel; in dma_mcux_lpc_configure()
561 for (otrig_index = 0; otrig_index < dev_config->num_of_otrigs; otrig_index++) { in dma_mcux_lpc_configure()
562 if (dma_data->otrig_array[otrig_index].linked_channel != EMPTY_OTRIG && in dma_mcux_lpc_configure()
563 (channel == dma_data->otrig_array[otrig_index].source_channel)) { in dma_mcux_lpc_configure()
565 dma_data->otrig_array[otrig_index].linked_channel; in dma_mcux_lpc_configure()
567 DEV_BASE(dev)->CHANNEL[ChannelToDisable].CFG &= in dma_mcux_lpc_configure()
569 dma_data->otrig_array[otrig_index].linked_channel = EMPTY_OTRIG; in dma_mcux_lpc_configure()
570 dma_data->otrig_array[otrig_index].source_channel = EMPTY_OTRIG; in dma_mcux_lpc_configure()
578 complete_callback = config->complete_callback_en; in dma_mcux_lpc_configure()
580 /* Check if we need to queue DMA descriptors */ in dma_mcux_lpc_configure()
581 if ((block_config->block_size > max_xfer_bytes) || in dma_mcux_lpc_configure()
582 (block_config->next_block != NULL)) { in dma_mcux_lpc_configure()
584 data->curr_descriptor = data->dma_descriptor_table; in dma_mcux_lpc_configure()
586 if (block_config->block_size > max_xfer_bytes) { in dma_mcux_lpc_configure()
603 block_config->block_size); in dma_mcux_lpc_configure()
611 block_config->block_size); in dma_mcux_lpc_configure()
614 assert(block_config->source_address == ROUND_UP(block_config->source_address, width)); in dma_mcux_lpc_configure()
615 assert(block_config->dest_address == ROUND_UP(block_config->dest_address, width)); in dma_mcux_lpc_configure()
623 (void *)block_config->source_address, in dma_mcux_lpc_configure()
624 (void *)block_config->dest_address, in dma_mcux_lpc_configure()
625 (void *)data->curr_descriptor); in dma_mcux_lpc_configure()
627 /* Start queuing DMA descriptors */ in dma_mcux_lpc_configure()
628 if (data->curr_descriptor) { in dma_mcux_lpc_configure()
629 if (block_config->block_size > max_xfer_bytes) { in dma_mcux_lpc_configure()
630 /* Queue additional DMA descriptors because the amount of data to in dma_mcux_lpc_configure()
631 * be transferred is greater that the DMA descriptors max XFERCOUNT. in dma_mcux_lpc_configure()
636 local_block.source_address = block_config->source_address in dma_mcux_lpc_configure()
639 local_block.source_address = block_config->source_address; in dma_mcux_lpc_configure()
642 local_block.dest_address = block_config->dest_address in dma_mcux_lpc_configure()
645 local_block.dest_address = block_config->dest_address; in dma_mcux_lpc_configure()
647 local_block.block_size = block_config->block_size - max_xfer_bytes; in dma_mcux_lpc_configure()
648 local_block.next_block = block_config->next_block; in dma_mcux_lpc_configure()
651 if (block_config->next_block == NULL) { in dma_mcux_lpc_configure()
658 return -ENOMEM; in dma_mcux_lpc_configure()
662 block_config = block_config->next_block; in dma_mcux_lpc_configure()
665 block_config->source_reload_en = reload; in dma_mcux_lpc_configure()
668 assert(block_config->source_address == in dma_mcux_lpc_configure()
669 ROUND_UP(block_config->source_address, width)); in dma_mcux_lpc_configure()
670 assert(block_config->dest_address == in dma_mcux_lpc_configure()
671 ROUND_UP(block_config->dest_address, width)); in dma_mcux_lpc_configure()
673 if (block_config->next_block == NULL) { in dma_mcux_lpc_configure()
679 return -ENOMEM; in dma_mcux_lpc_configure()
682 /* Get the next block and start queuing descriptors */ in dma_mcux_lpc_configure()
683 block_config = block_config->next_block; in dma_mcux_lpc_configure()
685 /* We have finished queuing DMA descriptors */ in dma_mcux_lpc_configure()
686 data->descriptors_queued = true; in dma_mcux_lpc_configure()
689 if (config->dma_slot) { in dma_mcux_lpc_configure()
693 if (config->dma_slot & LPC_DMA_PERIPH_REQ_EN) { in dma_mcux_lpc_configure()
696 if (config->dma_slot & LPC_DMA_HWTRIG_EN) { in dma_mcux_lpc_configure()
699 if (config->dma_slot & LPC_DMA_TRIGTYPE_LEVEL) { in dma_mcux_lpc_configure()
702 if (config->dma_slot & LPC_DMA_TRIGPOL_HIGH_RISING) { in dma_mcux_lpc_configure()
705 if (config->dma_slot & LPC_DMA_TRIGBURST) { in dma_mcux_lpc_configure()
708 LPC_DMA_GET_BURSTPOWER(config->dma_slot)); in dma_mcux_lpc_configure()
711 p_handle->base->CHANNEL[p_handle->channel].CFG = cfg_reg; in dma_mcux_lpc_configure()
713 DMA_EnableChannelPeriphRq(p_handle->base, p_handle->channel); in dma_mcux_lpc_configure()
715 DMA_DisableChannelPeriphRq(p_handle->base, p_handle->channel); in dma_mcux_lpc_configure()
717 DMA_SetChannelPriority(p_handle->base, p_handle->channel, config->channel_priority); in dma_mcux_lpc_configure()
719 data->busy = false; in dma_mcux_lpc_configure()
720 if (config->dma_callback) { in dma_mcux_lpc_configure()
722 data->user_data = config->user_data; in dma_mcux_lpc_configure()
723 data->dma_callback = config->dma_callback; in dma_mcux_lpc_configure()
724 data->dev = dev; in dma_mcux_lpc_configure()
732 struct dma_mcux_lpc_dma_data *dev_data = dev->data; in dma_mcux_lpc_start()
733 int8_t virtual_channel = dev_data->channel_index[channel]; in dma_mcux_lpc_start()
737 LOG_DBG("DMA CTRL 0x%x", DEV_BASE(dev)->CTRL); in dma_mcux_lpc_start()
738 data->busy = true; in dma_mcux_lpc_start()
745 struct dma_mcux_lpc_dma_data *dev_data = dev->data; in dma_mcux_lpc_stop()
746 int8_t virtual_channel = dev_data->channel_index[channel]; in dma_mcux_lpc_stop()
749 if (!data->busy) { in dma_mcux_lpc_stop()
755 data->busy = false; in dma_mcux_lpc_stop()
762 struct dma_mcux_lpc_dma_data *dev_data = dev->data; in dma_mcux_lpc_reload()
763 int8_t virtual_channel = dev_data->channel_index[channel]; in dma_mcux_lpc_reload()
768 assert(src == ROUND_UP(src, data->width)); in dma_mcux_lpc_reload()
769 assert(dst == ROUND_UP(dst, data->width)); in dma_mcux_lpc_reload()
771 if (!data->descriptors_queued) { in dma_mcux_lpc_reload()
776 /* Only one buffer, enable interrupt */ in dma_mcux_lpc_reload()
778 data->width, in dma_mcux_lpc_reload()
779 data->src_inc, in dma_mcux_lpc_reload()
780 data->dst_inc, in dma_mcux_lpc_reload()
795 data->src_inc, data->dst_inc, true); in dma_mcux_lpc_reload()
804 const struct dma_mcux_lpc_config *config = dev->config; in dma_mcux_lpc_get_status()
805 struct dma_mcux_lpc_dma_data *dev_data = dev->data; in dma_mcux_lpc_get_status()
806 int8_t virtual_channel = dev_data->channel_index[channel]; in dma_mcux_lpc_get_status()
809 if (channel > config->num_of_channels) { in dma_mcux_lpc_get_status()
810 return -EINVAL; in dma_mcux_lpc_get_status()
814 if (data->busy && (virtual_channel != -1)) { in dma_mcux_lpc_get_status()
815 status->busy = true; in dma_mcux_lpc_get_status()
816 status->pending_length = DMA_GetRemainingBytes(DEV_BASE(dev), channel); in dma_mcux_lpc_get_status()
818 status->busy = false; in dma_mcux_lpc_get_status()
819 status->pending_length = 0; in dma_mcux_lpc_get_status()
821 status->dir = data->dir; in dma_mcux_lpc_get_status()
822 LOG_DBG("DMA CR 0x%x", DEV_BASE(dev)->CTRL); in dma_mcux_lpc_get_status()
823 LOG_DBG("DMA INT 0x%x", DEV_BASE(dev)->INTSTAT); in dma_mcux_lpc_get_status()
830 const struct dma_mcux_lpc_config *config = dev->config; in dma_mcux_lpc_init()
831 struct dma_mcux_lpc_dma_data *data = dev->data; in dma_mcux_lpc_init()
834 for (int i = 0; i < config->num_of_otrigs; i++) { in dma_mcux_lpc_init()
835 data->otrig_array[i].source_channel = EMPTY_OTRIG; in dma_mcux_lpc_init()
836 data->otrig_array[i].linked_channel = EMPTY_OTRIG; in dma_mcux_lpc_init()
840 * Initialize to -1 to indicate dma channel does not have a slot in dma_mcux_lpc_init()
843 for (int i = 0; i < config->num_of_channels; i++) { in dma_mcux_lpc_init()
844 data->channel_index[i] = -1; in dma_mcux_lpc_init()
847 data->num_channels_used = 0; in dma_mcux_lpc_init()
852 config->irq_config_func(dev); in dma_mcux_lpc_init()