Lines Matching +full:dma +full:- +full:pl330
4 * SPDX-License-Identifier: Apache-2.0
8 #include <zephyr/drivers/dma.h>
34 srcbytewidth = BYTE_WIDTH(ch_handle->src_burst_sz); in dma_pl330_get_counter()
35 dstbytewidth = BYTE_WIDTH(ch_handle->dst_burst_sz); in dma_pl330_get_counter()
37 loop_counter = ch_handle->trans_size / in dma_pl330_get_counter()
38 (srcbytewidth * (ch_handle->src_burst_len + 1)); in dma_pl330_get_counter()
40 residue = ch_handle->trans_size - loop_counter * in dma_pl330_get_counter()
41 (srcbytewidth * (ch_handle->src_burst_len + 1)); in dma_pl330_get_counter()
52 int secure = ch_handle->nonsec_mode ? SRC_PRI_NONSEC_VALUE : in dma_pl330_ch_ccr()
55 ccr = ((ch_handle->dst_cache_ctrl & CC_SRCCCTRL_MASK) << in dma_pl330_ch_ccr()
57 ((ch_handle->nonsec_mode) << CC_DSTNS_SHIFT) + in dma_pl330_ch_ccr()
58 (ch_handle->dst_burst_len << CC_DSTBRSTLEN_SHIFT) + in dma_pl330_ch_ccr()
59 (ch_handle->dst_burst_sz << CC_DSTBRSTSIZE_SHIFT) + in dma_pl330_ch_ccr()
60 (ch_handle->dst_inc << CC_DSTINC_SHIFT) + in dma_pl330_ch_ccr()
61 ((ch_handle->src_cache_ctrl & CC_SRCCCTRL_MASK) << in dma_pl330_ch_ccr()
64 (ch_handle->src_burst_len << CC_SRCBRSTLEN_SHIFT) + in dma_pl330_ch_ccr()
65 (ch_handle->src_burst_sz << CC_SRCBRSTSIZE_SHIFT) + in dma_pl330_ch_ccr()
66 (ch_handle->src_inc << CC_SRCINC_SHIFT); in dma_pl330_ch_ccr()
79 while ((src | dst | size) & ((BYTE_WIDTH(burst_sz)) - 1)) { in dma_pl330_calc_burstsz_len()
80 burst_sz--; in dma_pl330_calc_burstsz_len()
92 burst_len--; in dma_pl330_calc_burstsz_len()
95 ch_handle->src_burst_len = burst_len; in dma_pl330_calc_burstsz_len()
96 ch_handle->src_burst_sz = burst_sz; in dma_pl330_calc_burstsz_len()
97 ch_handle->dst_burst_len = burst_len; in dma_pl330_calc_burstsz_len()
98 ch_handle->dst_burst_sz = burst_sz; in dma_pl330_calc_burstsz_len()
122 struct dma_pl330_ch_internal *ch_handle = &ch_cfg->internal; in dma_pl330_config_channel()
124 ch_handle->src_addr = src; in dma_pl330_config_channel()
125 ch_handle->dst_addr = dst; in dma_pl330_config_channel()
126 ch_handle->trans_size = size; in dma_pl330_config_channel()
128 if (ch_cfg->src_addr_adj == DMA_ADDR_ADJ_INCREMENT) { in dma_pl330_config_channel()
129 ch_handle->src_inc = 1; in dma_pl330_config_channel()
132 if (ch_cfg->dst_addr_adj == DMA_ADDR_ADJ_INCREMENT) { in dma_pl330_config_channel()
133 ch_handle->dst_inc = 1; in dma_pl330_config_channel()
167 struct dma_pl330_dev_data *const dev_data = dev->data; in dma_pl330_setup_ch()
169 int secure = ch_dat->nonsec_mode ? SRC_PRI_NONSEC_VALUE : in dma_pl330_setup_ch()
172 channel_cfg = &dev_data->channels[ch]; in dma_pl330_setup_ch()
173 dma_exec_addr = channel_cfg->dma_exec_addr; in dma_pl330_setup_ch()
176 SAR, ch_dat->src_addr); in dma_pl330_setup_ch()
179 DAR, ch_dat->dst_addr); in dma_pl330_setup_ch()
190 loop_counter0 = PL330_LOOP_COUNTER0_MAX - 1; in dma_pl330_setup_ch()
191 loop_counter1 = loop_counter / PL330_LOOP_COUNTER0_MAX - 1; in dma_pl330_setup_ch()
204 ((offset - lp0_start) & 0xff)); in dma_pl330_setup_ch()
209 loop_counter1--; in dma_pl330_setup_ch()
211 ((offset - lp1_start) & 0xff)); in dma_pl330_setup_ch()
216 loop_counter0 = (loop_counter % PL330_LOOP_COUNTER0_MAX) - 1; in dma_pl330_setup_ch()
220 loop_counter1--; in dma_pl330_setup_ch()
226 ((offset - lp0_start) & 0xff)); in dma_pl330_setup_ch()
231 ccr = ((ch_dat->nonsec_mode) << CC_DSTNS_SHIFT) + in dma_pl330_setup_ch()
234 (ch_dat->dst_inc << CC_DSTINC_SHIFT) + in dma_pl330_setup_ch()
238 ch_dat->src_inc; in dma_pl330_setup_ch()
242 ((residue - 1) & 0xff)); in dma_pl330_setup_ch()
249 ((offset - lp0_start) & 0xff)); in dma_pl330_setup_ch()
264 struct dma_pl330_dev_data *const dev_data = dev->data; in dma_pl330_start_dma_ch()
269 channel_cfg = &dev_data->channels[ch]; in dma_pl330_start_dma_ch()
273 return -ETIMEDOUT; in dma_pl330_start_dma_ch()
283 sys_write32(channel_cfg->dma_exec_addr, in dma_pl330_start_dma_ch()
292 return -ETIMEDOUT; in dma_pl330_start_dma_ch()
307 return -ETIMEDOUT; in dma_pl330_wait()
319 struct dma_pl330_dev_data *const dev_data = dev->data; in dma_pl330_xfer()
320 const struct dma_pl330_config *const dev_cfg = dev->config; in dma_pl330_xfer()
326 channel_cfg = &dev_data->channels[channel]; in dma_pl330_xfer()
327 ch_handle = &channel_cfg->internal; in dma_pl330_xfer()
331 max_size = GET_MAX_DMA_SIZE((1 << ch_handle->src_burst_sz), in dma_pl330_xfer()
332 ch_handle->src_burst_len); in dma_pl330_xfer()
341 * Pl330 supports only 4GB boundary, but boundary region can be in dma_pl330_xfer()
344 * in pl330 registers and higher 4bit address are configured in in dma_pl330_xfer()
349 dma_pl330_cfg_dmac_add_control(dev_cfg->control_reg_base, in dma_pl330_xfer()
354 LOG_ERR("Failed to setup channel for DMA PL330"); in dma_pl330_xfer()
358 ret = dma_pl330_start_dma_ch(dev, dev_cfg->reg_base, channel, in dma_pl330_xfer()
359 ch_handle->nonsec_mode); in dma_pl330_xfer()
361 LOG_ERR("Failed to start DMA PL330"); in dma_pl330_xfer()
365 ret = dma_pl330_wait(dev_cfg->reg_base, channel); in dma_pl330_xfer()
367 LOG_ERR("Failed waiting to finish DMA PL330"); in dma_pl330_xfer()
387 * Pl330 has only 32bit registers and supports 4GB memory. in dma_pl330_handle_boundary()
390 * Divide the DMA operation in 2 parts, 1st DMA from given address in dma_pl330_handle_boundary()
391 * to boundary (0xffffffff) and 2nd DMA on remaining size. in dma_pl330_handle_boundary()
394 if (size > (PL330_MAX_OFFSET - dst_low)) { in dma_pl330_handle_boundary()
395 transfer_size = PL330_MAX_OFFSET - dst_low; in dma_pl330_handle_boundary()
404 size -= transfer_size; in dma_pl330_handle_boundary()
408 if (size > (PL330_MAX_OFFSET - src_low)) { in dma_pl330_handle_boundary()
409 transfer_size = PL330_MAX_OFFSET - src_low; in dma_pl330_handle_boundary()
417 size -= transfer_size; in dma_pl330_handle_boundary()
434 * Pl330 has only 32bit registers and supports 4GB memory. in dma_pl330_submit()
437 * DMA on boundary condition is taken care in below function. in dma_pl330_submit()
440 if ((size > (PL330_MAX_OFFSET - (uint32_t)dst)) || in dma_pl330_submit()
441 (size > (PL330_MAX_OFFSET - (uint32_t)src))) { in dma_pl330_submit()
454 return -EFAULT; in dma_pl330_submit()
456 size -= xfer_size; in dma_pl330_submit()
467 struct dma_pl330_dev_data *const dev_data = dev->data; in dma_pl330_configure()
472 return -EINVAL; in dma_pl330_configure()
475 channel_cfg = &dev_data->channels[channel]; in dma_pl330_configure()
476 k_mutex_lock(&channel_cfg->ch_mutex, K_FOREVER); in dma_pl330_configure()
477 if (channel_cfg->channel_active) { in dma_pl330_configure()
478 k_mutex_unlock(&channel_cfg->ch_mutex); in dma_pl330_configure()
479 return -EBUSY; in dma_pl330_configure()
481 channel_cfg->channel_active = 1; in dma_pl330_configure()
482 k_mutex_unlock(&channel_cfg->ch_mutex); in dma_pl330_configure()
484 if (cfg->channel_direction != MEMORY_TO_MEMORY) { in dma_pl330_configure()
485 return -ENOTSUP; in dma_pl330_configure()
488 ch_handle = &channel_cfg->internal; in dma_pl330_configure()
491 channel_cfg->direction = cfg->channel_direction; in dma_pl330_configure()
492 channel_cfg->dst_addr_adj = cfg->head_block->dest_addr_adj; in dma_pl330_configure()
494 channel_cfg->src_addr = cfg->head_block->source_address; in dma_pl330_configure()
495 channel_cfg->dst_addr = cfg->head_block->dest_address; in dma_pl330_configure()
496 channel_cfg->trans_size = cfg->head_block->block_size; in dma_pl330_configure()
498 channel_cfg->dma_callback = cfg->dma_callback; in dma_pl330_configure()
499 channel_cfg->user_data = cfg->user_data; in dma_pl330_configure()
501 if (cfg->head_block->source_addr_adj == DMA_ADDR_ADJ_INCREMENT || in dma_pl330_configure()
502 cfg->head_block->source_addr_adj == DMA_ADDR_ADJ_NO_CHANGE) { in dma_pl330_configure()
503 channel_cfg->src_addr_adj = cfg->head_block->source_addr_adj; in dma_pl330_configure()
505 return -ENOTSUP; in dma_pl330_configure()
508 if (cfg->head_block->dest_addr_adj == DMA_ADDR_ADJ_INCREMENT || in dma_pl330_configure()
509 cfg->head_block->dest_addr_adj == DMA_ADDR_ADJ_NO_CHANGE) { in dma_pl330_configure()
510 channel_cfg->dst_addr_adj = cfg->head_block->dest_addr_adj; in dma_pl330_configure()
512 return -ENOTSUP; in dma_pl330_configure()
521 struct dma_pl330_dev_data *const dev_data = dev->data; in dma_pl330_transfer_start()
526 return -EINVAL; in dma_pl330_transfer_start()
529 channel_cfg = &dev_data->channels[channel]; in dma_pl330_transfer_start()
530 ret = dma_pl330_submit(dev, channel_cfg->dst_addr, in dma_pl330_transfer_start()
531 channel_cfg->src_addr, channel, in dma_pl330_transfer_start()
532 channel_cfg->trans_size); in dma_pl330_transfer_start()
534 k_mutex_lock(&channel_cfg->ch_mutex, K_FOREVER); in dma_pl330_transfer_start()
535 channel_cfg->channel_active = 0; in dma_pl330_transfer_start()
536 k_mutex_unlock(&channel_cfg->ch_mutex); in dma_pl330_transfer_start()
544 return -EINVAL; in dma_pl330_transfer_stop()
553 const struct dma_pl330_config *const dev_cfg = dev->config; in dma_pl330_initialize()
554 struct dma_pl330_dev_data *const dev_data = dev->data; in dma_pl330_initialize()
558 channel_cfg = &dev_data->channels[channel]; in dma_pl330_initialize()
559 channel_cfg->dma_exec_addr = dev_cfg->mcode_base + in dma_pl330_initialize()
561 k_mutex_init(&channel_cfg->ch_mutex); in dma_pl330_initialize()
564 LOG_INF("Device %s initialized", dev->name); in dma_pl330_initialize()
568 static DEVICE_API(dma, pl330_driver_api) = {