123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 |
- #include <asm/io.h>
- #include <common.h>
- #include <dma.h>
- #include <dm/device.h>
- #include <asm/omap_common.h>
- #include <asm/ti-common/ti-edma3.h>
- #define EDMA3_SL_BASE(slot) (0x4000 + ((slot) << 5))
- #define EDMA3_SL_MAX_NUM 512
- #define EDMA3_SLOPT_FIFO_WIDTH_MASK (0x7 << 8)
- #define EDMA3_QCHMAP(ch) 0x0200 + ((ch) << 2)
- #define EDMA3_CHMAP_PARSET_MASK 0x1ff
- #define EDMA3_CHMAP_PARSET_SHIFT 0x5
- #define EDMA3_CHMAP_TRIGWORD_SHIFT 0x2
- #define EDMA3_QEMCR 0x314
- #define EDMA3_IPR 0x1068
- #define EDMA3_IPRH 0x106c
- #define EDMA3_ICR 0x1070
- #define EDMA3_ICRH 0x1074
- #define EDMA3_QEECR 0x1088
- #define EDMA3_QEESR 0x108c
- #define EDMA3_QSECR 0x1094
- #define EDMA_FILL_BUFFER_SIZE 512
- struct ti_edma3_priv {
- u32 base;
- };
- static u8 edma_fill_buffer[EDMA_FILL_BUFFER_SIZE] __aligned(ARCH_DMA_MINALIGN);
- void qedma3_start(u32 base, struct edma3_channel_config *cfg)
- {
- u32 qchmap;
-
- if (cfg->complete_code < 32)
- __raw_writel(1 << cfg->complete_code, base + EDMA3_ICR);
- else
- __raw_writel(1 << cfg->complete_code, base + EDMA3_ICRH);
-
- qchmap = ((EDMA3_CHMAP_PARSET_MASK & cfg->slot)
- << EDMA3_CHMAP_PARSET_SHIFT) |
- (cfg->trigger_slot_word << EDMA3_CHMAP_TRIGWORD_SHIFT);
- __raw_writel(qchmap, base + EDMA3_QCHMAP(cfg->chnum));
-
- __raw_writel(1 << cfg->chnum, base + EDMA3_QSECR);
- __raw_writel(1 << cfg->chnum, base + EDMA3_QEMCR);
-
- __raw_writel(1 << cfg->chnum, base + EDMA3_QEESR);
- }
- void edma3_set_dest(u32 base, int slot, u32 dst, enum edma3_address_mode mode,
- enum edma3_fifo_width width)
- {
- u32 opt;
- struct edma3_slot_layout *rg;
- rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
- opt = __raw_readl(&rg->opt);
- if (mode == FIFO)
- opt = (opt & EDMA3_SLOPT_FIFO_WIDTH_MASK) |
- (EDMA3_SLOPT_DST_ADDR_CONST_MODE |
- EDMA3_SLOPT_FIFO_WIDTH_SET(width));
- else
- opt &= ~EDMA3_SLOPT_DST_ADDR_CONST_MODE;
- __raw_writel(opt, &rg->opt);
- __raw_writel(dst, &rg->dst);
- }
- void edma3_set_dest_index(u32 base, unsigned slot, int bidx, int cidx)
- {
- u32 src_dst_bidx;
- u32 src_dst_cidx;
- struct edma3_slot_layout *rg;
- rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
- src_dst_bidx = __raw_readl(&rg->src_dst_bidx);
- src_dst_cidx = __raw_readl(&rg->src_dst_cidx);
- __raw_writel((src_dst_bidx & 0x0000ffff) | (bidx << 16),
- &rg->src_dst_bidx);
- __raw_writel((src_dst_cidx & 0x0000ffff) | (cidx << 16),
- &rg->src_dst_cidx);
- }
- void edma3_set_dest_addr(u32 base, int slot, u32 dst)
- {
- struct edma3_slot_layout *rg;
- rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
- __raw_writel(dst, &rg->dst);
- }
- void edma3_set_src(u32 base, int slot, u32 src, enum edma3_address_mode mode,
- enum edma3_fifo_width width)
- {
- u32 opt;
- struct edma3_slot_layout *rg;
- rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
- opt = __raw_readl(&rg->opt);
- if (mode == FIFO)
- opt = (opt & EDMA3_SLOPT_FIFO_WIDTH_MASK) |
- (EDMA3_SLOPT_DST_ADDR_CONST_MODE |
- EDMA3_SLOPT_FIFO_WIDTH_SET(width));
- else
- opt &= ~EDMA3_SLOPT_DST_ADDR_CONST_MODE;
- __raw_writel(opt, &rg->opt);
- __raw_writel(src, &rg->src);
- }
- void edma3_set_src_index(u32 base, unsigned slot, int bidx, int cidx)
- {
- u32 src_dst_bidx;
- u32 src_dst_cidx;
- struct edma3_slot_layout *rg;
- rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
- src_dst_bidx = __raw_readl(&rg->src_dst_bidx);
- src_dst_cidx = __raw_readl(&rg->src_dst_cidx);
- __raw_writel((src_dst_bidx & 0xffff0000) | bidx,
- &rg->src_dst_bidx);
- __raw_writel((src_dst_cidx & 0xffff0000) | cidx,
- &rg->src_dst_cidx);
- }
- void edma3_set_src_addr(u32 base, int slot, u32 src)
- {
- struct edma3_slot_layout *rg;
- rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
- __raw_writel(src, &rg->src);
- }
- void edma3_set_transfer_params(u32 base, int slot, int acnt,
- int bcnt, int ccnt, u16 bcnt_rld,
- enum edma3_sync_dimension sync_mode)
- {
- u32 opt;
- u32 link_bcntrld;
- struct edma3_slot_layout *rg;
- rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
- link_bcntrld = __raw_readl(&rg->link_bcntrld);
- __raw_writel((bcnt_rld << 16) | (0x0000ffff & link_bcntrld),
- &rg->link_bcntrld);
- opt = __raw_readl(&rg->opt);
- if (sync_mode == ASYNC)
- __raw_writel(opt & ~EDMA3_SLOPT_AB_SYNC, &rg->opt);
- else
- __raw_writel(opt | EDMA3_SLOPT_AB_SYNC, &rg->opt);
-
- __raw_writel((bcnt << 16) | (acnt & 0xffff), &rg->a_b_cnt);
- __raw_writel(0xffff & ccnt, &rg->ccnt);
- }
- void edma3_write_slot(u32 base, int slot, struct edma3_slot_layout *param)
- {
- int i;
- u32 *p = (u32 *)param;
- u32 *addr = (u32 *)(base + EDMA3_SL_BASE(slot));
- for (i = 0; i < sizeof(struct edma3_slot_layout)/4; i += 4)
- __raw_writel(*p++, addr++);
- }
- void edma3_read_slot(u32 base, int slot, struct edma3_slot_layout *param)
- {
- int i;
- u32 *p = (u32 *)param;
- u32 *addr = (u32 *)(base + EDMA3_SL_BASE(slot));
- for (i = 0; i < sizeof(struct edma3_slot_layout)/4; i += 4)
- *p++ = __raw_readl(addr++);
- }
- void edma3_slot_configure(u32 base, int slot, struct edma3_slot_config *cfg)
- {
- struct edma3_slot_layout *rg;
- rg = (struct edma3_slot_layout *)(base + EDMA3_SL_BASE(slot));
- __raw_writel(cfg->opt, &rg->opt);
- __raw_writel(cfg->src, &rg->src);
- __raw_writel((cfg->bcnt << 16) | (cfg->acnt & 0xffff), &rg->a_b_cnt);
- __raw_writel(cfg->dst, &rg->dst);
- __raw_writel((cfg->dst_bidx << 16) |
- (cfg->src_bidx & 0xffff), &rg->src_dst_bidx);
- __raw_writel((cfg->bcntrld << 16) |
- (cfg->link & 0xffff), &rg->link_bcntrld);
- __raw_writel((cfg->dst_cidx << 16) |
- (cfg->src_cidx & 0xffff), &rg->src_dst_cidx);
- __raw_writel(0xffff & cfg->ccnt, &rg->ccnt);
- }
- int edma3_check_for_transfer(u32 base, struct edma3_channel_config *cfg)
- {
- u32 inum;
- u32 ipr_base;
- u32 icr_base;
- if (cfg->complete_code < 32) {
- ipr_base = base + EDMA3_IPR;
- icr_base = base + EDMA3_ICR;
- inum = 1 << cfg->complete_code;
- } else {
- ipr_base = base + EDMA3_IPRH;
- icr_base = base + EDMA3_ICRH;
- inum = 1 << (cfg->complete_code - 32);
- }
-
- if (!(__raw_readl(ipr_base) & inum))
- return 1;
-
- __raw_writel(inum, icr_base);
- return 0;
- }
- void qedma3_stop(u32 base, struct edma3_channel_config *cfg)
- {
-
- __raw_writel(1 << cfg->chnum, base + EDMA3_QEECR);
-
- if (cfg->complete_code < 32)
- __raw_writel(1 << cfg->complete_code, base + EDMA3_ICR);
- else
- __raw_writel(1 << cfg->complete_code, base + EDMA3_ICRH);
-
- __raw_writel(1 << cfg->chnum, base + EDMA3_QSECR);
- __raw_writel(1 << cfg->chnum, base + EDMA3_QEMCR);
-
- __raw_writel(0, base + EDMA3_QCHMAP(cfg->chnum));
- }
- void __edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num,
- void *dst, void *src, size_t len, size_t s_len)
- {
- struct edma3_slot_config slot;
- struct edma3_channel_config edma_channel;
- int b_cnt_value = 1;
- int rem_bytes = 0;
- int a_cnt_value = len;
- unsigned int addr = (unsigned int) (dst);
- unsigned int max_acnt = 0x7FFFU;
- if (len > s_len) {
- b_cnt_value = (len / s_len);
- rem_bytes = (len % s_len);
- a_cnt_value = s_len;
- } else if (len > max_acnt) {
- b_cnt_value = (len / max_acnt);
- rem_bytes = (len % max_acnt);
- a_cnt_value = max_acnt;
- }
- slot.opt = 0;
- slot.src = ((unsigned int) src);
- slot.acnt = a_cnt_value;
- slot.bcnt = b_cnt_value;
- slot.ccnt = 1;
- if (len == s_len)
- slot.src_bidx = a_cnt_value;
- else
- slot.src_bidx = 0;
- slot.dst_bidx = a_cnt_value;
- slot.src_cidx = 0;
- slot.dst_cidx = 0;
- slot.link = EDMA3_PARSET_NULL_LINK;
- slot.bcntrld = 0;
- slot.opt = EDMA3_SLOPT_TRANS_COMP_INT_ENB |
- EDMA3_SLOPT_COMP_CODE(0) |
- EDMA3_SLOPT_STATIC | EDMA3_SLOPT_AB_SYNC;
- edma3_slot_configure(edma3_base_addr, edma_slot_num, &slot);
- edma_channel.slot = edma_slot_num;
- edma_channel.chnum = 0;
- edma_channel.complete_code = 0;
-
- edma_channel.trigger_slot_word = EDMA3_TWORD(dst);
- qedma3_start(edma3_base_addr, &edma_channel);
- edma3_set_dest_addr(edma3_base_addr, edma_channel.slot, addr);
- while (edma3_check_for_transfer(edma3_base_addr, &edma_channel))
- ;
- qedma3_stop(edma3_base_addr, &edma_channel);
- if (rem_bytes != 0) {
- slot.opt = 0;
- if (len == s_len)
- slot.src =
- (b_cnt_value * max_acnt) + ((unsigned int) src);
- else
- slot.src = (unsigned int) src;
- slot.acnt = rem_bytes;
- slot.bcnt = 1;
- slot.ccnt = 1;
- slot.src_bidx = rem_bytes;
- slot.dst_bidx = rem_bytes;
- slot.src_cidx = 0;
- slot.dst_cidx = 0;
- slot.link = EDMA3_PARSET_NULL_LINK;
- slot.bcntrld = 0;
- slot.opt = EDMA3_SLOPT_TRANS_COMP_INT_ENB |
- EDMA3_SLOPT_COMP_CODE(0) |
- EDMA3_SLOPT_STATIC | EDMA3_SLOPT_AB_SYNC;
- edma3_slot_configure(edma3_base_addr, edma_slot_num, &slot);
- edma_channel.slot = edma_slot_num;
- edma_channel.chnum = 0;
- edma_channel.complete_code = 0;
-
- edma_channel.trigger_slot_word = EDMA3_TWORD(dst);
- qedma3_start(edma3_base_addr, &edma_channel);
- edma3_set_dest_addr(edma3_base_addr, edma_channel.slot, addr +
- (max_acnt * b_cnt_value));
- while (edma3_check_for_transfer(edma3_base_addr, &edma_channel))
- ;
- qedma3_stop(edma3_base_addr, &edma_channel);
- }
- }
- void __edma3_fill(unsigned long edma3_base_addr, unsigned int edma_slot_num,
- void *dst, u8 val, size_t len)
- {
- int xfer_len;
- int max_xfer = EDMA_FILL_BUFFER_SIZE * 65535;
- memset((void *)edma_fill_buffer, val, sizeof(edma_fill_buffer));
- while (len) {
- xfer_len = len;
- if (xfer_len > max_xfer)
- xfer_len = max_xfer;
- __edma3_transfer(edma3_base_addr, edma_slot_num, dst,
- edma_fill_buffer, xfer_len,
- EDMA_FILL_BUFFER_SIZE);
- len -= xfer_len;
- dst += xfer_len;
- }
- }
- #ifndef CONFIG_DMA
- void edma3_transfer(unsigned long edma3_base_addr, unsigned int edma_slot_num,
- void *dst, void *src, size_t len)
- {
- __edma3_transfer(edma3_base_addr, edma_slot_num, dst, src, len, len);
- }
- void edma3_fill(unsigned long edma3_base_addr, unsigned int edma_slot_num,
- void *dst, u8 val, size_t len)
- {
- __edma3_fill(edma3_base_addr, edma_slot_num, dst, val, len);
- }
- #else
- static int ti_edma3_transfer(struct udevice *dev, int direction, void *dst,
- void *src, size_t len)
- {
- struct ti_edma3_priv *priv = dev_get_priv(dev);
-
- enable_edma3_clocks();
- switch (direction) {
- case DMA_MEM_TO_MEM:
- __edma3_transfer(priv->base, 1, dst, src, len, len);
- break;
- default:
- error("Transfer type not implemented in DMA driver\n");
- break;
- }
-
- disable_edma3_clocks();
- return 0;
- }
- static int ti_edma3_ofdata_to_platdata(struct udevice *dev)
- {
- struct ti_edma3_priv *priv = dev_get_priv(dev);
- priv->base = dev_get_addr(dev);
- return 0;
- }
- static int ti_edma3_probe(struct udevice *dev)
- {
- struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev);
- uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM;
- return 0;
- }
- static const struct dma_ops ti_edma3_ops = {
- .transfer = ti_edma3_transfer,
- };
- static const struct udevice_id ti_edma3_ids[] = {
- { .compatible = "ti,edma3" },
- { }
- };
- U_BOOT_DRIVER(ti_edma3) = {
- .name = "ti_edma3",
- .id = UCLASS_DMA,
- .of_match = ti_edma3_ids,
- .ops = &ti_edma3_ops,
- .ofdata_to_platdata = ti_edma3_ofdata_to_platdata,
- .probe = ti_edma3_probe,
- .priv_auto_alloc_size = sizeof(struct ti_edma3_priv),
- };
- #endif
|