Khoronzhuk, Ivan | e165b1d | 2014-10-22 17:47:56 +0300 | [diff] [blame] | 1 | /* |
| 2 | * Enhanced Direct Memory Access (EDMA3) Controller |
| 3 | * |
| 4 | * (C) Copyright 2014 |
| 5 | * Texas Instruments Incorporated, <www.ti.com> |
| 6 | * |
| 7 | * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com> |
| 8 | * |
| 9 | * SPDX-License-Identifier: GPL-2.0+ |
| 10 | */ |
| 11 | |
| 12 | #include <asm/io.h> |
| 13 | #include <common.h> |
Simon Glass | 9d92245 | 2017-05-17 17:18:03 -0600 | [diff] [blame] | 14 | #include <dm.h> |
Mugunthan V N | 1218e5c | 2016-02-15 15:31:41 +0530 | [diff] [blame] | 15 | #include <dma.h> |
Mugunthan V N | 1218e5c | 2016-02-15 15:31:41 +0530 | [diff] [blame] | 16 | #include <asm/omap_common.h> |
Khoronzhuk, Ivan | e165b1d | 2014-10-22 17:47:56 +0300 | [diff] [blame] | 17 | #include <asm/ti-common/ti-edma3.h> |
| 18 | |
| 19 | #define EDMA3_SL_BASE(slot) (0x4000 + ((slot) << 5)) |
| 20 | #define EDMA3_SL_MAX_NUM 512 |
| 21 | #define EDMA3_SLOPT_FIFO_WIDTH_MASK (0x7 << 8) |
| 22 | |
| 23 | #define EDMA3_QCHMAP(ch) 0x0200 + ((ch) << 2) |
| 24 | #define EDMA3_CHMAP_PARSET_MASK 0x1ff |
| 25 | #define EDMA3_CHMAP_PARSET_SHIFT 0x5 |
| 26 | #define EDMA3_CHMAP_TRIGWORD_SHIFT 0x2 |
| 27 | |
| 28 | #define EDMA3_QEMCR 0x314 |
| 29 | #define EDMA3_IPR 0x1068 |
| 30 | #define EDMA3_IPRH 0x106c |
| 31 | #define EDMA3_ICR 0x1070 |
| 32 | #define EDMA3_ICRH 0x1074 |
| 33 | #define EDMA3_QEECR 0x1088 |
| 34 | #define EDMA3_QEESR 0x108c |
| 35 | #define EDMA3_QSECR 0x1094 |
| 36 | |
Mugunthan V N | 1218e5c | 2016-02-15 15:31:41 +0530 | [diff] [blame] | 37 | struct ti_edma3_priv { |
| 38 | u32 base; |
| 39 | }; |
| 40 | |
Khoronzhuk, Ivan | e165b1d | 2014-10-22 17:47:56 +0300 | [diff] [blame] | 41 | /** |
| 42 | * qedma3_start - start qdma on a channel |
| 43 | * @base: base address of edma |
| 44 | * @cfg: pinter to struct edma3_channel_config where you can set |
| 45 | * the slot number to associate with, the chnum, which corresponds |
| 46 | * your quick channel number 0-7, complete code - transfer complete code |
| 47 | * and trigger slot word - which has to correspond to the word number in |
| 48 | * edma3_slot_layout struct for generating event. |
| 49 | * |
| 50 | */ |
| 51 | void qedma3_start(u32 base, struct edma3_channel_config *cfg) |
| 52 | { |
| 53 | u32 qchmap; |
| 54 | |
| 55 | /* Clear the pending int bit */ |
| 56 | if (cfg->complete_code < 32) |
| 57 | __raw_writel(1 << cfg->complete_code, base + EDMA3_ICR); |
| 58 | else |
| 59 | __raw_writel(1 << cfg->complete_code, base + EDMA3_ICRH); |
| 60 | |
| 61 | /* Map parameter set and trigger word 7 to quick channel */ |
| 62 | qchmap = ((EDMA3_CHMAP_PARSET_MASK & cfg->slot) |
| 63 | << EDMA3_CHMAP_PARSET_SHIFT) | |
| 64 | (cfg->trigger_slot_word << EDMA3_CHMAP_TRIGWORD_SHIFT); |
| 65 | |
| 66 | __raw_writel(qchmap, base + EDMA3_QCHMAP(cfg->chnum)); |
| 67 | |
| 68 | /* Clear missed event if set*/ |
| 69 | __raw_writel(1 << cfg->chnum, base + EDMA3_QSECR); |
| 70 | __raw_writel(1 << cfg->chnum, base + EDMA3_QEMCR); |
| 71 | |
| 72 | /* Enable qdma channel event */ |
| 73 | __raw_writel(1 << cfg->chnum, base + EDMA3_QEESR); |
| 74 | } |
| 75 | |
| 76 | /** |
| 77 | * edma3_set_dest - set initial DMA destination address in parameter RAM slot |
| 78 | * @base: base address of edma |
| 79 | * @slot: parameter RAM slot being configured |
| 80 | * @dst: physical address of destination (memory, controller FIFO, etc) |
| 81 | * @addressMode: INCR, except in very rare cases |
| 82 | * @width: ignored unless @addressMode is FIFO, else specifies the |
| 83 | * width to use when addressing the fifo (e.g. W8BIT, W32BIT) |
| 84 | * |
| 85 | * Note that the destination address is modified during the DMA transfer |
| 86 | * according to edma3_set_dest_index(). |
| 87 | */ |
| 88 | void edma3_set_dest(u32 base, int slot, u32 dst, enum edma3_address_mode mode, |
| 89 | enum edma3_fifo_width width) |
| 90 | { |
| 91 | u32 opt; |
| 92 | struct edma3_slot_layout *rg; |
| 93 | |
| 94 | rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot)); |
| 95 | |
| 96 | opt = __raw_readl(&rg->opt); |
| 97 | if (mode == FIFO) |
| 98 | opt = (opt & EDMA3_SLOPT_FIFO_WIDTH_MASK) | |
| 99 | (EDMA3_SLOPT_DST_ADDR_CONST_MODE | |
| 100 | EDMA3_SLOPT_FIFO_WIDTH_SET(width)); |
| 101 | else |
| 102 | opt &= ~EDMA3_SLOPT_DST_ADDR_CONST_MODE; |
| 103 | |
| 104 | __raw_writel(opt, &rg->opt); |
| 105 | __raw_writel(dst, &rg->dst); |
| 106 | } |
| 107 | |
| 108 | /** |
| 109 | * edma3_set_dest_index - configure DMA destination address indexing |
| 110 | * @base: base address of edma |
| 111 | * @slot: parameter RAM slot being configured |
| 112 | * @bidx: byte offset between destination arrays in a frame |
| 113 | * @cidx: byte offset between destination frames in a block |
| 114 | * |
| 115 | * Offsets are specified to support either contiguous or discontiguous |
| 116 | * memory transfers, or repeated access to a hardware register, as needed. |
| 117 | * When accessing hardware registers, both offsets are normally zero. |
| 118 | */ |
| 119 | void edma3_set_dest_index(u32 base, unsigned slot, int bidx, int cidx) |
| 120 | { |
| 121 | u32 src_dst_bidx; |
| 122 | u32 src_dst_cidx; |
| 123 | struct edma3_slot_layout *rg; |
| 124 | |
| 125 | rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot)); |
| 126 | |
| 127 | src_dst_bidx = __raw_readl(&rg->src_dst_bidx); |
| 128 | src_dst_cidx = __raw_readl(&rg->src_dst_cidx); |
| 129 | |
| 130 | __raw_writel((src_dst_bidx & 0x0000ffff) | (bidx << 16), |
| 131 | &rg->src_dst_bidx); |
| 132 | __raw_writel((src_dst_cidx & 0x0000ffff) | (cidx << 16), |
| 133 | &rg->src_dst_cidx); |
| 134 | } |
| 135 | |
| 136 | /** |
| 137 | * edma3_set_dest_addr - set destination address for slot only |
| 138 | */ |
| 139 | void edma3_set_dest_addr(u32 base, int slot, u32 dst) |
| 140 | { |
| 141 | struct edma3_slot_layout *rg; |
| 142 | |
| 143 | rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot)); |
| 144 | __raw_writel(dst, &rg->dst); |
| 145 | } |
| 146 | |
| 147 | /** |
| 148 | * edma3_set_src - set initial DMA source address in parameter RAM slot |
| 149 | * @base: base address of edma |
| 150 | * @slot: parameter RAM slot being configured |
| 151 | * @src_port: physical address of source (memory, controller FIFO, etc) |
| 152 | * @mode: INCR, except in very rare cases |
| 153 | * @width: ignored unless @addressMode is FIFO, else specifies the |
| 154 | * width to use when addressing the fifo (e.g. W8BIT, W32BIT) |
| 155 | * |
| 156 | * Note that the source address is modified during the DMA transfer |
| 157 | * according to edma3_set_src_index(). |
| 158 | */ |
| 159 | void edma3_set_src(u32 base, int slot, u32 src, enum edma3_address_mode mode, |
| 160 | enum edma3_fifo_width width) |
| 161 | { |
| 162 | u32 opt; |
| 163 | struct edma3_slot_layout *rg; |
| 164 | |
| 165 | rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot)); |
| 166 | |
| 167 | opt = __raw_readl(&rg->opt); |
| 168 | if (mode == FIFO) |
| 169 | opt = (opt & EDMA3_SLOPT_FIFO_WIDTH_MASK) | |
| 170 | (EDMA3_SLOPT_DST_ADDR_CONST_MODE | |
| 171 | EDMA3_SLOPT_FIFO_WIDTH_SET(width)); |
| 172 | else |
| 173 | opt &= ~EDMA3_SLOPT_DST_ADDR_CONST_MODE; |
| 174 | |
| 175 | __raw_writel(opt, &rg->opt); |
| 176 | __raw_writel(src, &rg->src); |
| 177 | } |
| 178 | |
| 179 | /** |
| 180 | * edma3_set_src_index - configure DMA source address indexing |
| 181 | * @base: base address of edma |
| 182 | * @slot: parameter RAM slot being configured |
| 183 | * @bidx: byte offset between source arrays in a frame |
| 184 | * @cidx: byte offset between source frames in a block |
| 185 | * |
| 186 | * Offsets are specified to support either contiguous or discontiguous |
| 187 | * memory transfers, or repeated access to a hardware register, as needed. |
| 188 | * When accessing hardware registers, both offsets are normally zero. |
| 189 | */ |
| 190 | void edma3_set_src_index(u32 base, unsigned slot, int bidx, int cidx) |
| 191 | { |
| 192 | u32 src_dst_bidx; |
| 193 | u32 src_dst_cidx; |
| 194 | struct edma3_slot_layout *rg; |
| 195 | |
| 196 | rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot)); |
| 197 | |
| 198 | src_dst_bidx = __raw_readl(&rg->src_dst_bidx); |
| 199 | src_dst_cidx = __raw_readl(&rg->src_dst_cidx); |
| 200 | |
| 201 | __raw_writel((src_dst_bidx & 0xffff0000) | bidx, |
| 202 | &rg->src_dst_bidx); |
| 203 | __raw_writel((src_dst_cidx & 0xffff0000) | cidx, |
| 204 | &rg->src_dst_cidx); |
| 205 | } |
| 206 | |
| 207 | /** |
| 208 | * edma3_set_src_addr - set source address for slot only |
| 209 | */ |
| 210 | void edma3_set_src_addr(u32 base, int slot, u32 src) |
| 211 | { |
| 212 | struct edma3_slot_layout *rg; |
| 213 | |
| 214 | rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot)); |
| 215 | __raw_writel(src, &rg->src); |
| 216 | } |
| 217 | |
| 218 | /** |
| 219 | * edma3_set_transfer_params - configure DMA transfer parameters |
| 220 | * @base: base address of edma |
| 221 | * @slot: parameter RAM slot being configured |
| 222 | * @acnt: how many bytes per array (at least one) |
| 223 | * @bcnt: how many arrays per frame (at least one) |
| 224 | * @ccnt: how many frames per block (at least one) |
| 225 | * @bcnt_rld: used only for A-Synchronized transfers; this specifies |
| 226 | * the value to reload into bcnt when it decrements to zero |
| 227 | * @sync_mode: ASYNC or ABSYNC |
| 228 | * |
| 229 | * See the EDMA3 documentation to understand how to configure and link |
| 230 | * transfers using the fields in PaRAM slots. If you are not doing it |
| 231 | * all at once with edma3_write_slot(), you will use this routine |
| 232 | * plus two calls each for source and destination, setting the initial |
| 233 | * address and saying how to index that address. |
| 234 | * |
| 235 | * An example of an A-Synchronized transfer is a serial link using a |
| 236 | * single word shift register. In that case, @acnt would be equal to |
| 237 | * that word size; the serial controller issues a DMA synchronization |
| 238 | * event to transfer each word, and memory access by the DMA transfer |
| 239 | * controller will be word-at-a-time. |
| 240 | * |
| 241 | * An example of an AB-Synchronized transfer is a device using a FIFO. |
| 242 | * In that case, @acnt equals the FIFO width and @bcnt equals its depth. |
| 243 | * The controller with the FIFO issues DMA synchronization events when |
| 244 | * the FIFO threshold is reached, and the DMA transfer controller will |
| 245 | * transfer one frame to (or from) the FIFO. It will probably use |
| 246 | * efficient burst modes to access memory. |
| 247 | */ |
| 248 | void edma3_set_transfer_params(u32 base, int slot, int acnt, |
| 249 | int bcnt, int ccnt, u16 bcnt_rld, |
| 250 | enum edma3_sync_dimension sync_mode) |
| 251 | { |
| 252 | u32 opt; |
| 253 | u32 link_bcntrld; |
| 254 | struct edma3_slot_layout *rg; |
| 255 | |
| 256 | rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot)); |
| 257 | |
| 258 | link_bcntrld = __raw_readl(&rg->link_bcntrld); |
| 259 | |
| 260 | __raw_writel((bcnt_rld << 16) | (0x0000ffff & link_bcntrld), |
| 261 | &rg->link_bcntrld); |
| 262 | |
| 263 | opt = __raw_readl(&rg->opt); |
| 264 | if (sync_mode == ASYNC) |
| 265 | __raw_writel(opt & ~EDMA3_SLOPT_AB_SYNC, &rg->opt); |
| 266 | else |
| 267 | __raw_writel(opt | EDMA3_SLOPT_AB_SYNC, &rg->opt); |
| 268 | |
| 269 | /* Set the acount, bcount, ccount registers */ |
| 270 | __raw_writel((bcnt << 16) | (acnt & 0xffff), &rg->a_b_cnt); |
| 271 | __raw_writel(0xffff & ccnt, &rg->ccnt); |
| 272 | } |
| 273 | |
| 274 | /** |
| 275 | * edma3_write_slot - write parameter RAM data for slot |
| 276 | * @base: base address of edma |
| 277 | * @slot: number of parameter RAM slot being modified |
| 278 | * @param: data to be written into parameter RAM slot |
| 279 | * |
| 280 | * Use this to assign all parameters of a transfer at once. This |
| 281 | * allows more efficient setup of transfers than issuing multiple |
| 282 | * calls to set up those parameters in small pieces, and provides |
| 283 | * complete control over all transfer options. |
| 284 | */ |
| 285 | void edma3_write_slot(u32 base, int slot, struct edma3_slot_layout *param) |
| 286 | { |
| 287 | int i; |
| 288 | u32 *p = (u32 *)param; |
| 289 | u32 *addr = (u32 *)(base + EDMA3_SL_BASE(slot)); |
| 290 | |
| 291 | for (i = 0; i < sizeof(struct edma3_slot_layout)/4; i += 4) |
| 292 | __raw_writel(*p++, addr++); |
| 293 | } |
| 294 | |
| 295 | /** |
| 296 | * edma3_read_slot - read parameter RAM data from slot |
| 297 | * @base: base address of edma |
| 298 | * @slot: number of parameter RAM slot being copied |
| 299 | * @param: where to store copy of parameter RAM data |
| 300 | * |
| 301 | * Use this to read data from a parameter RAM slot, perhaps to |
| 302 | * save them as a template for later reuse. |
| 303 | */ |
| 304 | void edma3_read_slot(u32 base, int slot, struct edma3_slot_layout *param) |
| 305 | { |
| 306 | int i; |
| 307 | u32 *p = (u32 *)param; |
| 308 | u32 *addr = (u32 *)(base + EDMA3_SL_BASE(slot)); |
| 309 | |
| 310 | for (i = 0; i < sizeof(struct edma3_slot_layout)/4; i += 4) |
| 311 | *p++ = __raw_readl(addr++); |
| 312 | } |
| 313 | |
| 314 | void edma3_slot_configure(u32 base, int slot, struct edma3_slot_config *cfg) |
| 315 | { |
| 316 | struct edma3_slot_layout *rg; |
| 317 | |
| 318 | rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot)); |
| 319 | |
| 320 | __raw_writel(cfg->opt, &rg->opt); |
| 321 | __raw_writel(cfg->src, &rg->src); |
| 322 | __raw_writel((cfg->bcnt << 16) | (cfg->acnt & 0xffff), &rg->a_b_cnt); |
| 323 | __raw_writel(cfg->dst, &rg->dst); |
| 324 | __raw_writel((cfg->dst_bidx << 16) | |
| 325 | (cfg->src_bidx & 0xffff), &rg->src_dst_bidx); |
| 326 | __raw_writel((cfg->bcntrld << 16) | |
| 327 | (cfg->link & 0xffff), &rg->link_bcntrld); |
| 328 | __raw_writel((cfg->dst_cidx << 16) | |
| 329 | (cfg->src_cidx & 0xffff), &rg->src_dst_cidx); |
| 330 | __raw_writel(0xffff & cfg->ccnt, &rg->ccnt); |
| 331 | } |
| 332 | |
| 333 | /** |
| 334 | * edma3_check_for_transfer - check if transfer coplete by checking |
| 335 | * interrupt pending bit. Clear interrupt pending bit if complete. |
| 336 | * @base: base address of edma |
| 337 | * @cfg: pinter to struct edma3_channel_config which was passed |
| 338 | * to qedma3_start when you started qdma channel |
| 339 | * |
| 340 | * Return 0 if complete, 1 if not. |
| 341 | */ |
| 342 | int edma3_check_for_transfer(u32 base, struct edma3_channel_config *cfg) |
| 343 | { |
| 344 | u32 inum; |
| 345 | u32 ipr_base; |
| 346 | u32 icr_base; |
| 347 | |
| 348 | if (cfg->complete_code < 32) { |
| 349 | ipr_base = base + EDMA3_IPR; |
| 350 | icr_base = base + EDMA3_ICR; |
| 351 | inum = 1 << cfg->complete_code; |
| 352 | } else { |
| 353 | ipr_base = base + EDMA3_IPRH; |
| 354 | icr_base = base + EDMA3_ICRH; |
| 355 | inum = 1 << (cfg->complete_code - 32); |
| 356 | } |
| 357 | |
| 358 | /* check complete interrupt */ |
| 359 | if (!(__raw_readl(ipr_base) & inum)) |
| 360 | return 1; |
| 361 | |
| 362 | /* clean up the pending int bit */ |
| 363 | __raw_writel(inum, icr_base); |
| 364 | |
| 365 | return 0; |
| 366 | } |
| 367 | |
| 368 | /** |
| 369 | * qedma3_stop - stops dma on the channel passed |
| 370 | * @base: base address of edma |
| 371 | * @cfg: pinter to struct edma3_channel_config which was passed |
| 372 | * to qedma3_start when you started qdma channel |
| 373 | */ |
| 374 | void qedma3_stop(u32 base, struct edma3_channel_config *cfg) |
| 375 | { |
| 376 | /* Disable qdma channel event */ |
| 377 | __raw_writel(1 << cfg->chnum, base + EDMA3_QEECR); |
| 378 | |
| 379 | /* clean up the interrupt indication */ |
| 380 | if (cfg->complete_code < 32) |
| 381 | __raw_writel(1 << cfg->complete_code, base + EDMA3_ICR); |
| 382 | else |
| 383 | __raw_writel(1 << cfg->complete_code, base + EDMA3_ICRH); |
| 384 | |
| 385 | /* Clear missed event if set*/ |
| 386 | __raw_writel(1 << cfg->chnum, base + EDMA3_QSECR); |
| 387 | __raw_writel(1 << cfg->chnum, base + EDMA3_QEMCR); |
| 388 | |
| 389 | /* Clear the channel map */ |
| 390 | __raw_writel(0, base + EDMA3_QCHMAP(cfg->chnum)); |
| 391 | } |
Vignesh R | 664ab2c | 2015-08-17 13:29:55 +0530 | [diff] [blame] | 392 | |
Mugunthan V N | 1218e5c | 2016-02-15 15:31:41 +0530 | [diff] [blame] | 393 | void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num, |
| 394 | void *dst, void *src, size_t len) |
Vignesh R | 664ab2c | 2015-08-17 13:29:55 +0530 | [diff] [blame] | 395 | { |
| 396 | struct edma3_slot_config slot; |
| 397 | struct edma3_channel_config edma_channel; |
| 398 | int b_cnt_value = 1; |
| 399 | int rem_bytes = 0; |
| 400 | int a_cnt_value = len; |
| 401 | unsigned int addr = (unsigned int) (dst); |
| 402 | unsigned int max_acnt = 0x7FFFU; |
| 403 | |
| 404 | if (len > max_acnt) { |
| 405 | b_cnt_value = (len / max_acnt); |
| 406 | rem_bytes = (len % max_acnt); |
| 407 | a_cnt_value = max_acnt; |
| 408 | } |
| 409 | |
| 410 | slot.opt = 0; |
| 411 | slot.src = ((unsigned int) src); |
| 412 | slot.acnt = a_cnt_value; |
| 413 | slot.bcnt = b_cnt_value; |
| 414 | slot.ccnt = 1; |
| 415 | slot.src_bidx = a_cnt_value; |
| 416 | slot.dst_bidx = a_cnt_value; |
| 417 | slot.src_cidx = 0; |
| 418 | slot.dst_cidx = 0; |
| 419 | slot.link = EDMA3_PARSET_NULL_LINK; |
| 420 | slot.bcntrld = 0; |
| 421 | slot.opt = EDMA3_SLOPT_TRANS_COMP_INT_ENB | |
| 422 | EDMA3_SLOPT_COMP_CODE(0) | |
| 423 | EDMA3_SLOPT_STATIC | EDMA3_SLOPT_AB_SYNC; |
| 424 | |
| 425 | edma3_slot_configure(edma3_base_addr, edma_slot_num, &slot); |
| 426 | edma_channel.slot = edma_slot_num; |
| 427 | edma_channel.chnum = 0; |
| 428 | edma_channel.complete_code = 0; |
| 429 | /* set event trigger to dst update */ |
| 430 | edma_channel.trigger_slot_word = EDMA3_TWORD(dst); |
| 431 | |
| 432 | qedma3_start(edma3_base_addr, &edma_channel); |
| 433 | edma3_set_dest_addr(edma3_base_addr, edma_channel.slot, addr); |
| 434 | |
| 435 | while (edma3_check_for_transfer(edma3_base_addr, &edma_channel)) |
| 436 | ; |
| 437 | qedma3_stop(edma3_base_addr, &edma_channel); |
| 438 | |
| 439 | if (rem_bytes != 0) { |
| 440 | slot.opt = 0; |
| 441 | slot.src = |
| 442 | (b_cnt_value * max_acnt) + ((unsigned int) src); |
| 443 | slot.acnt = rem_bytes; |
| 444 | slot.bcnt = 1; |
| 445 | slot.ccnt = 1; |
| 446 | slot.src_bidx = rem_bytes; |
| 447 | slot.dst_bidx = rem_bytes; |
| 448 | slot.src_cidx = 0; |
| 449 | slot.dst_cidx = 0; |
| 450 | slot.link = EDMA3_PARSET_NULL_LINK; |
| 451 | slot.bcntrld = 0; |
| 452 | slot.opt = EDMA3_SLOPT_TRANS_COMP_INT_ENB | |
| 453 | EDMA3_SLOPT_COMP_CODE(0) | |
| 454 | EDMA3_SLOPT_STATIC | EDMA3_SLOPT_AB_SYNC; |
| 455 | edma3_slot_configure(edma3_base_addr, edma_slot_num, &slot); |
| 456 | edma_channel.slot = edma_slot_num; |
| 457 | edma_channel.chnum = 0; |
| 458 | edma_channel.complete_code = 0; |
| 459 | /* set event trigger to dst update */ |
| 460 | edma_channel.trigger_slot_word = EDMA3_TWORD(dst); |
| 461 | |
| 462 | qedma3_start(edma3_base_addr, &edma_channel); |
| 463 | edma3_set_dest_addr(edma3_base_addr, edma_channel.slot, addr + |
| 464 | (max_acnt * b_cnt_value)); |
| 465 | while (edma3_check_for_transfer(edma3_base_addr, &edma_channel)) |
| 466 | ; |
| 467 | qedma3_stop(edma3_base_addr, &edma_channel); |
| 468 | } |
| 469 | } |
Mugunthan V N | 1218e5c | 2016-02-15 15:31:41 +0530 | [diff] [blame] | 470 | |
| 471 | #ifndef CONFIG_DMA |
| 472 | |
| 473 | void edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num, |
| 474 | void *dst, void *src, size_t len) |
| 475 | { |
| 476 | __edma3_transfer(edma3_base_addr, edma_slot_num, dst, src, len); |
| 477 | } |
| 478 | |
| 479 | #else |
| 480 | |
| 481 | static int ti_edma3_transfer(struct udevice *dev, int direction, void *dst, |
| 482 | void *src, size_t len) |
| 483 | { |
| 484 | struct ti_edma3_priv *priv = dev_get_priv(dev); |
| 485 | |
| 486 | /* enable edma3 clocks */ |
| 487 | enable_edma3_clocks(); |
| 488 | |
| 489 | switch (direction) { |
| 490 | case DMA_MEM_TO_MEM: |
| 491 | __edma3_transfer(priv->base, 1, dst, src, len); |
| 492 | break; |
| 493 | default: |
Masahiro Yamada | 9b643e3 | 2017-09-16 14:10:41 +0900 | [diff] [blame] | 494 | pr_err("Transfer type not implemented in DMA driver\n"); |
Mugunthan V N | 1218e5c | 2016-02-15 15:31:41 +0530 | [diff] [blame] | 495 | break; |
| 496 | } |
| 497 | |
| 498 | /* disable edma3 clocks */ |
| 499 | disable_edma3_clocks(); |
| 500 | |
| 501 | return 0; |
| 502 | } |
| 503 | |
| 504 | static int ti_edma3_ofdata_to_platdata(struct udevice *dev) |
| 505 | { |
| 506 | struct ti_edma3_priv *priv = dev_get_priv(dev); |
| 507 | |
Simon Glass | a821c4a | 2017-05-17 17:18:05 -0600 | [diff] [blame] | 508 | priv->base = devfdt_get_addr(dev); |
Mugunthan V N | 1218e5c | 2016-02-15 15:31:41 +0530 | [diff] [blame] | 509 | |
| 510 | return 0; |
| 511 | } |
| 512 | |
| 513 | static int ti_edma3_probe(struct udevice *dev) |
| 514 | { |
| 515 | struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev); |
| 516 | |
| 517 | uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM; |
| 518 | |
| 519 | return 0; |
| 520 | } |
| 521 | |
| 522 | static const struct dma_ops ti_edma3_ops = { |
| 523 | .transfer = ti_edma3_transfer, |
| 524 | }; |
| 525 | |
| 526 | static const struct udevice_id ti_edma3_ids[] = { |
| 527 | { .compatible = "ti,edma3" }, |
| 528 | { } |
| 529 | }; |
| 530 | |
| 531 | U_BOOT_DRIVER(ti_edma3) = { |
| 532 | .name = "ti_edma3", |
| 533 | .id = UCLASS_DMA, |
| 534 | .of_match = ti_edma3_ids, |
| 535 | .ops = &ti_edma3_ops, |
| 536 | .ofdata_to_platdata = ti_edma3_ofdata_to_platdata, |
| 537 | .probe = ti_edma3_probe, |
| 538 | .priv_auto_alloc_size = sizeof(struct ti_edma3_priv), |
| 539 | }; |
| 540 | #endif /* CONFIG_DMA */ |