Lines Matching +full:dma +full:- +full:offset

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()
162 uint32_t offset = 0, ccr; in dma_pl330_setup_ch() local
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()
175 offset += dma_pl330_gen_mov(dma_exec_addr, in dma_pl330_setup_ch()
176 SAR, ch_dat->src_addr); in dma_pl330_setup_ch()
178 offset += dma_pl330_gen_mov(dma_exec_addr + offset, in dma_pl330_setup_ch()
179 DAR, ch_dat->dst_addr); in dma_pl330_setup_ch()
183 offset += dma_pl330_gen_mov(dma_exec_addr + offset, 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()
192 dma_pl330_gen_op(OP_DMA_LOOP_COUNT1, dma_exec_addr + offset, in dma_pl330_setup_ch()
194 offset = offset + 2; in dma_pl330_setup_ch()
195 dma_pl330_gen_op(OP_DMA_LOOP, dma_exec_addr + offset, in dma_pl330_setup_ch()
197 offset = offset + 2; in dma_pl330_setup_ch()
198 lp1_start = offset; in dma_pl330_setup_ch()
199 lp0_start = offset; in dma_pl330_setup_ch()
200 sys_write8(OP_DMA_LD, dma_exec_addr + offset); in dma_pl330_setup_ch()
201 sys_write8(OP_DMA_ST, dma_exec_addr + offset + 1); in dma_pl330_setup_ch()
202 offset = offset + 2; in dma_pl330_setup_ch()
203 dma_pl330_gen_op(OP_DMA_LP_BK_JMP1, dma_exec_addr + offset, in dma_pl330_setup_ch()
204 ((offset - lp0_start) & 0xff)); in dma_pl330_setup_ch()
205 offset = offset + 2; in dma_pl330_setup_ch()
206 dma_pl330_gen_op(OP_DMA_LOOP, dma_exec_addr + offset, in dma_pl330_setup_ch()
208 offset = offset + 2; in dma_pl330_setup_ch()
209 loop_counter1--; in dma_pl330_setup_ch()
210 dma_pl330_gen_op(OP_DMA_LP_BK_JMP2, dma_exec_addr + offset, in dma_pl330_setup_ch()
211 ((offset - lp1_start) & 0xff)); in dma_pl330_setup_ch()
212 offset = offset + 2; in dma_pl330_setup_ch()
216 loop_counter0 = (loop_counter % PL330_LOOP_COUNTER0_MAX) - 1; in dma_pl330_setup_ch()
217 dma_pl330_gen_op(OP_DMA_LOOP, dma_exec_addr + offset, in dma_pl330_setup_ch()
219 offset = offset + 2; in dma_pl330_setup_ch()
220 loop_counter1--; in dma_pl330_setup_ch()
221 lp0_start = offset; in dma_pl330_setup_ch()
222 sys_write8(OP_DMA_LD, dma_exec_addr + offset); in dma_pl330_setup_ch()
223 sys_write8(OP_DMA_ST, dma_exec_addr + offset + 1); in dma_pl330_setup_ch()
224 offset = offset + 2; in dma_pl330_setup_ch()
225 dma_pl330_gen_op(OP_DMA_LP_BK_JMP1, dma_exec_addr + offset, in dma_pl330_setup_ch()
226 ((offset - lp0_start) & 0xff)); in dma_pl330_setup_ch()
227 offset = offset + 2; 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()
239 offset += dma_pl330_gen_mov(dma_exec_addr + offset, in dma_pl330_setup_ch()
241 dma_pl330_gen_op(OP_DMA_LOOP, dma_exec_addr + offset, in dma_pl330_setup_ch()
242 ((residue - 1) & 0xff)); in dma_pl330_setup_ch()
243 offset = offset + 2; in dma_pl330_setup_ch()
244 lp0_start = offset; in dma_pl330_setup_ch()
245 sys_write8(OP_DMA_LD, dma_exec_addr + offset); in dma_pl330_setup_ch()
246 sys_write8(OP_DMA_ST, dma_exec_addr + offset + 1); in dma_pl330_setup_ch()
247 offset = offset + 2; in dma_pl330_setup_ch()
248 dma_pl330_gen_op(OP_DMA_LP_BK_JMP1, dma_exec_addr + offset, in dma_pl330_setup_ch()
249 ((offset - lp0_start) & 0xff)); in dma_pl330_setup_ch()
250 offset = offset + 2; in dma_pl330_setup_ch()
253 sys_write8(OP_DMA_END, dma_exec_addr + offset); in dma_pl330_setup_ch()
254 sys_write8(OP_DMA_END, dma_exec_addr + offset + 1); in dma_pl330_setup_ch()
255 sys_write8(OP_DMA_END, dma_exec_addr + offset + 2); in dma_pl330_setup_ch()
256 sys_write8(OP_DMA_END, dma_exec_addr + offset + 3); 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()
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()
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()
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) = {