17bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King/* 27bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * OMAP DMAengine support 37bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * 47bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * This program is free software; you can redistribute it and/or modify 57bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * it under the terms of the GNU General Public License version 2 as 67bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * published by the Free Software Foundation. 77bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King */ 8fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King#include <linux/delay.h> 97bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King#include <linux/dmaengine.h> 107bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King#include <linux/dma-mapping.h> 117bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King#include <linux/err.h> 127bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King#include <linux/init.h> 137bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King#include <linux/interrupt.h> 147bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King#include <linux/list.h> 157bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King#include <linux/module.h> 167bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King#include <linux/omap-dma.h> 177bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King#include <linux/platform_device.h> 187bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King#include <linux/slab.h> 197bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King#include <linux/spinlock.h> 208d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter#include <linux/of_dma.h> 218d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter#include <linux/of_device.h> 227bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 237bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King#include "virt-dma.h" 247d7e1eba7e92c2f9c76db80adc24836e7a114bfbTony Lindgren 257bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstruct omap_dmadev { 267bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct dma_device ddev; 277bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spinlock_t lock; 287bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct tasklet_struct task; 297bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct list_head pending; 30596c471b69249764d8e241b004736878204daa0fRussell King void __iomem *base; 31596c471b69249764d8e241b004736878204daa0fRussell King const struct omap_dma_reg *reg_map; 321b416c4b41351c3eb8fc42dbb4cd8eba463c0813Russell King struct omap_system_dma_plat_info *plat; 336ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King bool legacy; 346ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King spinlock_t irq_lock; 356ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King uint32_t irq_enable_mask; 366ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King struct omap_chan *lch_map[32]; 377bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King}; 387bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 397bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstruct omap_chan { 407bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct virt_dma_chan vc; 417bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct list_head node; 42596c471b69249764d8e241b004736878204daa0fRussell King void __iomem *channel_base; 43596c471b69249764d8e241b004736878204daa0fRussell King const struct omap_dma_reg *reg_map; 44aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King uint32_t ccr; 457bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 467bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct dma_slave_config cfg; 477bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King unsigned dma_sig; 483a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King bool cyclic; 492dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi bool paused; 507bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 517bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King int dma_ch; 527bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_desc *desc; 537bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King unsigned sgidx; 547bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King}; 557bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 567bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstruct omap_sg { 577bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King dma_addr_t addr; 587bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King uint32_t en; /* number of elements (24-bit) */ 597bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King uint32_t fn; /* number of frames (16-bit) */ 607bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King}; 617bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 627bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstruct omap_desc { 637bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct virt_dma_desc vd; 647bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King enum dma_transfer_direction dir; 657bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King dma_addr_t dev_addr; 667bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 677c836bc7f9f71d62a8dc50712db122a69b405486Russell King int16_t fi; /* for OMAP_DMA_SYNC_PACKET */ 689043826d88467091543c1d3ab06eb4afeed34789Russell King uint8_t es; /* CSDP_DATA_TYPE_xxx */ 693ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King uint32_t ccr; /* CCR value */ 70965aeb4df1f2142f5a6407c6d40b7196be719582Russell King uint16_t clnk_ctrl; /* CLNK_CTRL value */ 71fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King uint16_t cicr; /* CICR value */ 722f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King uint32_t csdp; /* CSDP value */ 737bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 747bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King unsigned sglen; 757bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_sg sg[0]; 767bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King}; 777bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 789043826d88467091543c1d3ab06eb4afeed34789Russell Kingenum { 799043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_FS = BIT(5), 809043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_READ_PRIORITY = BIT(6), 819043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_ENABLE = BIT(7), 829043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_AUTO_INIT = BIT(8), /* OMAP1 only */ 839043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_REPEAT = BIT(9), /* OMAP1 only */ 849043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_OMAP31_DISABLE = BIT(10), /* OMAP1 only */ 859043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_SUSPEND_SENSITIVE = BIT(8), /* OMAP2+ only */ 869043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_RD_ACTIVE = BIT(9), /* OMAP2+ only */ 879043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_WR_ACTIVE = BIT(10), /* OMAP2+ only */ 889043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_SRC_AMODE_CONSTANT = 0 << 12, 899043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_SRC_AMODE_POSTINC = 1 << 12, 909043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_SRC_AMODE_SGLIDX = 2 << 12, 919043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_SRC_AMODE_DBLIDX = 3 << 12, 929043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_DST_AMODE_CONSTANT = 0 << 14, 939043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_DST_AMODE_POSTINC = 1 << 14, 949043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_DST_AMODE_SGLIDX = 2 << 14, 959043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_DST_AMODE_DBLIDX = 3 << 14, 969043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_CONSTANT_FILL = BIT(16), 979043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_TRANSPARENT_COPY = BIT(17), 989043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_BS = BIT(18), 999043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_SUPERVISOR = BIT(22), 1009043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_PREFETCH = BIT(23), 1019043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_TRIGGER_SRC = BIT(24), 1029043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_BUFFERING_DISABLE = BIT(25), 1039043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_WRITE_PRIORITY = BIT(26), 1049043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_SYNC_ELEMENT = 0, 1059043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_SYNC_FRAME = CCR_FS, 1069043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_SYNC_BLOCK = CCR_BS, 1079043826d88467091543c1d3ab06eb4afeed34789Russell King CCR_SYNC_PACKET = CCR_BS | CCR_FS, 1089043826d88467091543c1d3ab06eb4afeed34789Russell King 1099043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DATA_TYPE_8 = 0, 1109043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DATA_TYPE_16 = 1, 1119043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DATA_TYPE_32 = 2, 1129043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_SRC_PORT_EMIFF = 0 << 2, /* OMAP1 only */ 1139043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_SRC_PORT_EMIFS = 1 << 2, /* OMAP1 only */ 1149043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_SRC_PORT_OCP_T1 = 2 << 2, /* OMAP1 only */ 1159043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_SRC_PORT_TIPB = 3 << 2, /* OMAP1 only */ 1169043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_SRC_PORT_OCP_T2 = 4 << 2, /* OMAP1 only */ 1179043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_SRC_PORT_MPUI = 5 << 2, /* OMAP1 only */ 1189043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_SRC_PACKED = BIT(6), 1199043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_SRC_BURST_1 = 0 << 7, 1209043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_SRC_BURST_16 = 1 << 7, 1219043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_SRC_BURST_32 = 2 << 7, 1229043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_SRC_BURST_64 = 3 << 7, 1239043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DST_PORT_EMIFF = 0 << 9, /* OMAP1 only */ 1249043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DST_PORT_EMIFS = 1 << 9, /* OMAP1 only */ 1259043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DST_PORT_OCP_T1 = 2 << 9, /* OMAP1 only */ 1269043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DST_PORT_TIPB = 3 << 9, /* OMAP1 only */ 1279043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DST_PORT_OCP_T2 = 4 << 9, /* OMAP1 only */ 1289043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DST_PORT_MPUI = 5 << 9, /* OMAP1 only */ 1299043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DST_PACKED = BIT(13), 1309043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DST_BURST_1 = 0 << 14, 1319043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DST_BURST_16 = 1 << 14, 1329043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DST_BURST_32 = 2 << 14, 1339043826d88467091543c1d3ab06eb4afeed34789Russell King CSDP_DST_BURST_64 = 3 << 14, 1349043826d88467091543c1d3ab06eb4afeed34789Russell King 1359043826d88467091543c1d3ab06eb4afeed34789Russell King CICR_TOUT_IE = BIT(0), /* OMAP1 only */ 1369043826d88467091543c1d3ab06eb4afeed34789Russell King CICR_DROP_IE = BIT(1), 1379043826d88467091543c1d3ab06eb4afeed34789Russell King CICR_HALF_IE = BIT(2), 1389043826d88467091543c1d3ab06eb4afeed34789Russell King CICR_FRAME_IE = BIT(3), 1399043826d88467091543c1d3ab06eb4afeed34789Russell King CICR_LAST_IE = BIT(4), 1409043826d88467091543c1d3ab06eb4afeed34789Russell King CICR_BLOCK_IE = BIT(5), 1419043826d88467091543c1d3ab06eb4afeed34789Russell King CICR_PKT_IE = BIT(7), /* OMAP2+ only */ 1429043826d88467091543c1d3ab06eb4afeed34789Russell King CICR_TRANS_ERR_IE = BIT(8), /* OMAP2+ only */ 1439043826d88467091543c1d3ab06eb4afeed34789Russell King CICR_SUPERVISOR_ERR_IE = BIT(10), /* OMAP2+ only */ 1449043826d88467091543c1d3ab06eb4afeed34789Russell King CICR_MISALIGNED_ERR_IE = BIT(11), /* OMAP2+ only */ 1459043826d88467091543c1d3ab06eb4afeed34789Russell King CICR_DRAIN_IE = BIT(12), /* OMAP2+ only */ 1469043826d88467091543c1d3ab06eb4afeed34789Russell King CICR_SUPER_BLOCK_IE = BIT(14), /* OMAP2+ only */ 1479043826d88467091543c1d3ab06eb4afeed34789Russell King 1489043826d88467091543c1d3ab06eb4afeed34789Russell King CLNK_CTRL_ENABLE_LNK = BIT(15), 1499043826d88467091543c1d3ab06eb4afeed34789Russell King}; 1509043826d88467091543c1d3ab06eb4afeed34789Russell King 1517bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic const unsigned es_bytes[] = { 1529043826d88467091543c1d3ab06eb4afeed34789Russell King [CSDP_DATA_TYPE_8] = 1, 1539043826d88467091543c1d3ab06eb4afeed34789Russell King [CSDP_DATA_TYPE_16] = 2, 1549043826d88467091543c1d3ab06eb4afeed34789Russell King [CSDP_DATA_TYPE_32] = 4, 1557bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King}; 1567bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 1578d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunterstatic struct of_dma_filter_info omap_dma_info = { 1588d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter .filter_fn = omap_dma_filter_fn, 1598d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter}; 1608d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter 1617bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic inline struct omap_dmadev *to_omap_dma_dev(struct dma_device *d) 1627bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 1637bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return container_of(d, struct omap_dmadev, ddev); 1647bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 1657bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 1667bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic inline struct omap_chan *to_omap_dma_chan(struct dma_chan *c) 1677bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 1687bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return container_of(c, struct omap_chan, vc.chan); 1697bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 1707bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 1717bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic inline struct omap_desc *to_omap_dma_desc(struct dma_async_tx_descriptor *t) 1727bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 1737bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return container_of(t, struct omap_desc, vd.tx); 1747bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 1757bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 1767bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic void omap_dma_desc_free(struct virt_dma_desc *vd) 1777bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 1787bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King kfree(container_of(vd, struct omap_desc, vd)); 1797bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 1807bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 181596c471b69249764d8e241b004736878204daa0fRussell Kingstatic void omap_dma_write(uint32_t val, unsigned type, void __iomem *addr) 182596c471b69249764d8e241b004736878204daa0fRussell King{ 183596c471b69249764d8e241b004736878204daa0fRussell King switch (type) { 184596c471b69249764d8e241b004736878204daa0fRussell King case OMAP_DMA_REG_16BIT: 185596c471b69249764d8e241b004736878204daa0fRussell King writew_relaxed(val, addr); 186596c471b69249764d8e241b004736878204daa0fRussell King break; 187596c471b69249764d8e241b004736878204daa0fRussell King case OMAP_DMA_REG_2X16BIT: 188596c471b69249764d8e241b004736878204daa0fRussell King writew_relaxed(val, addr); 189596c471b69249764d8e241b004736878204daa0fRussell King writew_relaxed(val >> 16, addr + 2); 190596c471b69249764d8e241b004736878204daa0fRussell King break; 191596c471b69249764d8e241b004736878204daa0fRussell King case OMAP_DMA_REG_32BIT: 192596c471b69249764d8e241b004736878204daa0fRussell King writel_relaxed(val, addr); 193596c471b69249764d8e241b004736878204daa0fRussell King break; 194596c471b69249764d8e241b004736878204daa0fRussell King default: 195596c471b69249764d8e241b004736878204daa0fRussell King WARN_ON(1); 196596c471b69249764d8e241b004736878204daa0fRussell King } 197596c471b69249764d8e241b004736878204daa0fRussell King} 198596c471b69249764d8e241b004736878204daa0fRussell King 199596c471b69249764d8e241b004736878204daa0fRussell Kingstatic unsigned omap_dma_read(unsigned type, void __iomem *addr) 200596c471b69249764d8e241b004736878204daa0fRussell King{ 201596c471b69249764d8e241b004736878204daa0fRussell King unsigned val; 202596c471b69249764d8e241b004736878204daa0fRussell King 203596c471b69249764d8e241b004736878204daa0fRussell King switch (type) { 204596c471b69249764d8e241b004736878204daa0fRussell King case OMAP_DMA_REG_16BIT: 205596c471b69249764d8e241b004736878204daa0fRussell King val = readw_relaxed(addr); 206596c471b69249764d8e241b004736878204daa0fRussell King break; 207596c471b69249764d8e241b004736878204daa0fRussell King case OMAP_DMA_REG_2X16BIT: 208596c471b69249764d8e241b004736878204daa0fRussell King val = readw_relaxed(addr); 209596c471b69249764d8e241b004736878204daa0fRussell King val |= readw_relaxed(addr + 2) << 16; 210596c471b69249764d8e241b004736878204daa0fRussell King break; 211596c471b69249764d8e241b004736878204daa0fRussell King case OMAP_DMA_REG_32BIT: 212596c471b69249764d8e241b004736878204daa0fRussell King val = readl_relaxed(addr); 213596c471b69249764d8e241b004736878204daa0fRussell King break; 214596c471b69249764d8e241b004736878204daa0fRussell King default: 215596c471b69249764d8e241b004736878204daa0fRussell King WARN_ON(1); 216596c471b69249764d8e241b004736878204daa0fRussell King val = 0; 217596c471b69249764d8e241b004736878204daa0fRussell King } 218596c471b69249764d8e241b004736878204daa0fRussell King 219596c471b69249764d8e241b004736878204daa0fRussell King return val; 220596c471b69249764d8e241b004736878204daa0fRussell King} 221596c471b69249764d8e241b004736878204daa0fRussell King 222c5ed98b6ae79545284b7855a07ded32934865a6dRussell Kingstatic void omap_dma_glbl_write(struct omap_dmadev *od, unsigned reg, unsigned val) 223c5ed98b6ae79545284b7855a07ded32934865a6dRussell King{ 224596c471b69249764d8e241b004736878204daa0fRussell King const struct omap_dma_reg *r = od->reg_map + reg; 225596c471b69249764d8e241b004736878204daa0fRussell King 226596c471b69249764d8e241b004736878204daa0fRussell King WARN_ON(r->stride); 227596c471b69249764d8e241b004736878204daa0fRussell King 228596c471b69249764d8e241b004736878204daa0fRussell King omap_dma_write(val, r->type, od->base + r->offset); 229c5ed98b6ae79545284b7855a07ded32934865a6dRussell King} 230c5ed98b6ae79545284b7855a07ded32934865a6dRussell King 231c5ed98b6ae79545284b7855a07ded32934865a6dRussell Kingstatic unsigned omap_dma_glbl_read(struct omap_dmadev *od, unsigned reg) 232c5ed98b6ae79545284b7855a07ded32934865a6dRussell King{ 233596c471b69249764d8e241b004736878204daa0fRussell King const struct omap_dma_reg *r = od->reg_map + reg; 234596c471b69249764d8e241b004736878204daa0fRussell King 235596c471b69249764d8e241b004736878204daa0fRussell King WARN_ON(r->stride); 236596c471b69249764d8e241b004736878204daa0fRussell King 237596c471b69249764d8e241b004736878204daa0fRussell King return omap_dma_read(r->type, od->base + r->offset); 238c5ed98b6ae79545284b7855a07ded32934865a6dRussell King} 239c5ed98b6ae79545284b7855a07ded32934865a6dRussell King 240c5ed98b6ae79545284b7855a07ded32934865a6dRussell Kingstatic void omap_dma_chan_write(struct omap_chan *c, unsigned reg, unsigned val) 241c5ed98b6ae79545284b7855a07ded32934865a6dRussell King{ 242596c471b69249764d8e241b004736878204daa0fRussell King const struct omap_dma_reg *r = c->reg_map + reg; 243596c471b69249764d8e241b004736878204daa0fRussell King 244596c471b69249764d8e241b004736878204daa0fRussell King omap_dma_write(val, r->type, c->channel_base + r->offset); 245c5ed98b6ae79545284b7855a07ded32934865a6dRussell King} 246c5ed98b6ae79545284b7855a07ded32934865a6dRussell King 247c5ed98b6ae79545284b7855a07ded32934865a6dRussell Kingstatic unsigned omap_dma_chan_read(struct omap_chan *c, unsigned reg) 248c5ed98b6ae79545284b7855a07ded32934865a6dRussell King{ 249596c471b69249764d8e241b004736878204daa0fRussell King const struct omap_dma_reg *r = c->reg_map + reg; 250596c471b69249764d8e241b004736878204daa0fRussell King 251596c471b69249764d8e241b004736878204daa0fRussell King return omap_dma_read(r->type, c->channel_base + r->offset); 252c5ed98b6ae79545284b7855a07ded32934865a6dRussell King} 253c5ed98b6ae79545284b7855a07ded32934865a6dRussell King 254470b23f7308dd2af25bd075d14a724f8ccd93985Russell Kingstatic void omap_dma_clear_csr(struct omap_chan *c) 255470b23f7308dd2af25bd075d14a724f8ccd93985Russell King{ 256470b23f7308dd2af25bd075d14a724f8ccd93985Russell King if (dma_omap1()) 257c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_read(c, CSR); 258470b23f7308dd2af25bd075d14a724f8ccd93985Russell King else 259c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CSR, ~0); 260470b23f7308dd2af25bd075d14a724f8ccd93985Russell King} 261470b23f7308dd2af25bd075d14a724f8ccd93985Russell King 2626ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell Kingstatic unsigned omap_dma_get_csr(struct omap_chan *c) 2636ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King{ 2646ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King unsigned val = omap_dma_chan_read(c, CSR); 2656ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 2666ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King if (!dma_omap1()) 2676ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King omap_dma_chan_write(c, CSR, val); 2686ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 2696ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King return val; 2706ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King} 2716ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 272596c471b69249764d8e241b004736878204daa0fRussell Kingstatic void omap_dma_assign(struct omap_dmadev *od, struct omap_chan *c, 273596c471b69249764d8e241b004736878204daa0fRussell King unsigned lch) 274596c471b69249764d8e241b004736878204daa0fRussell King{ 275596c471b69249764d8e241b004736878204daa0fRussell King c->channel_base = od->base + od->plat->channel_stride * lch; 2766ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 2776ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King od->lch_map[lch] = c; 278596c471b69249764d8e241b004736878204daa0fRussell King} 279596c471b69249764d8e241b004736878204daa0fRussell King 280fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell Kingstatic void omap_dma_start(struct omap_chan *c, struct omap_desc *d) 281fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King{ 282fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); 283fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 284fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King if (__dma_omap15xx(od->plat->dma_attr)) 285c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CPC, 0); 286fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King else 287c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CDAC, 0); 288fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 289470b23f7308dd2af25bd075d14a724f8ccd93985Russell King omap_dma_clear_csr(c); 290fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 291fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King /* Enable interrupts */ 292c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CICR, d->cicr); 293fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 29445da7b0451b1fe15e882b08c79be58458cbe7a2fRussell King /* Enable channel */ 295c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CCR, d->ccr | CCR_ENABLE); 296fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King} 297fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 298fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell Kingstatic void omap_dma_stop(struct omap_chan *c) 299fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King{ 300fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); 301fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King uint32_t val; 302fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 303fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King /* disable irq */ 304c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CICR, 0); 305fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 306470b23f7308dd2af25bd075d14a724f8ccd93985Russell King omap_dma_clear_csr(c); 307fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 308c5ed98b6ae79545284b7855a07ded32934865a6dRussell King val = omap_dma_chan_read(c, CCR); 3099043826d88467091543c1d3ab06eb4afeed34789Russell King if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) { 310fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King uint32_t sysconfig; 311fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King unsigned i; 312fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 313c5ed98b6ae79545284b7855a07ded32934865a6dRussell King sysconfig = omap_dma_glbl_read(od, OCP_SYSCONFIG); 314fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King val = sysconfig & ~DMA_SYSCONFIG_MIDLEMODE_MASK; 315fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King val |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); 316c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_glbl_write(od, OCP_SYSCONFIG, val); 317fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 318c5ed98b6ae79545284b7855a07ded32934865a6dRussell King val = omap_dma_chan_read(c, CCR); 3199043826d88467091543c1d3ab06eb4afeed34789Russell King val &= ~CCR_ENABLE; 320c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CCR, val); 321fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 322fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King /* Wait for sDMA FIFO to drain */ 323fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King for (i = 0; ; i++) { 324c5ed98b6ae79545284b7855a07ded32934865a6dRussell King val = omap_dma_chan_read(c, CCR); 3259043826d88467091543c1d3ab06eb4afeed34789Russell King if (!(val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE))) 326fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King break; 327fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 328fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King if (i > 100) 329fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King break; 330fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 331fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King udelay(5); 332fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King } 333fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 3349043826d88467091543c1d3ab06eb4afeed34789Russell King if (val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE)) 335fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King dev_err(c->vc.chan.device->dev, 336fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King "DMA drain did not complete on lch %d\n", 337fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King c->dma_ch); 338fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 339c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_glbl_write(od, OCP_SYSCONFIG, sysconfig); 340fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King } else { 3419043826d88467091543c1d3ab06eb4afeed34789Russell King val &= ~CCR_ENABLE; 342c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CCR, val); 343fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King } 344fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 345fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King mb(); 346fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 347fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King if (!__dma_omap15xx(od->plat->dma_attr) && c->cyclic) { 348c5ed98b6ae79545284b7855a07ded32934865a6dRussell King val = omap_dma_chan_read(c, CLNK_CTRL); 349fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 350fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King if (dma_omap1()) 351fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King val |= 1 << 14; /* set the STOP_LNK bit */ 352fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King else 3539043826d88467091543c1d3ab06eb4afeed34789Russell King val &= ~CLNK_CTRL_ENABLE_LNK; 354fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 355c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CLNK_CTRL, val); 356fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King } 357fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King} 358fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 3597bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d, 3607bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King unsigned idx) 3617bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 3627bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_sg *sg = d->sg + idx; 363893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King unsigned cxsa, cxei, cxfi; 364913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King 365913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King if (d->dir == DMA_DEV_TO_MEM) { 366893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King cxsa = CDSA; 367893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King cxei = CDEI; 368893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King cxfi = CDFI; 369913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King } else { 370893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King cxsa = CSSA; 371893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King cxei = CSEI; 372893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King cxfi = CSFI; 373913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King } 374913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King 375c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, cxsa, sg->addr); 376c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, cxei, 0); 377c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, cxfi, 0); 378c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CEN, sg->en); 379c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CFN, sg->fn); 380913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King 381fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King omap_dma_start(c, d); 382913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King} 383913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King 384913a2d0c6952283bc9323cb9152af87f792ff4c4Russell Kingstatic void omap_dma_start_desc(struct omap_chan *c) 385913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King{ 386913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King struct virt_dma_desc *vd = vchan_next_desc(&c->vc); 387913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King struct omap_desc *d; 388893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King unsigned cxsa, cxei, cxfi; 389b9e97822da374f52aaf99cb502f531ff2184b8f5Russell King 390913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King if (!vd) { 391913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King c->desc = NULL; 392913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King return; 393913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King } 394913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King 395913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King list_del(&vd->node); 396913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King 397913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King c->desc = d = to_omap_dma_desc(&vd->tx); 398913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King c->sgidx = 0; 399913a2d0c6952283bc9323cb9152af87f792ff4c4Russell King 40059871902703c47acc730555be41bd9cb36d3700cRussell King /* 40159871902703c47acc730555be41bd9cb36d3700cRussell King * This provides the necessary barrier to ensure data held in 40259871902703c47acc730555be41bd9cb36d3700cRussell King * DMA coherent memory is visible to the DMA engine prior to 40359871902703c47acc730555be41bd9cb36d3700cRussell King * the transfer starting. 40459871902703c47acc730555be41bd9cb36d3700cRussell King */ 40559871902703c47acc730555be41bd9cb36d3700cRussell King mb(); 40659871902703c47acc730555be41bd9cb36d3700cRussell King 407c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CCR, d->ccr); 4083ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King if (dma_omap1()) 409c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CCR2, d->ccr >> 16); 410b9e97822da374f52aaf99cb502f531ff2184b8f5Russell King 4113ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King if (d->dir == DMA_DEV_TO_MEM) { 412893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King cxsa = CSSA; 413893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King cxei = CSEI; 414893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King cxfi = CSFI; 415b9e97822da374f52aaf99cb502f531ff2184b8f5Russell King } else { 416893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King cxsa = CDSA; 417893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King cxei = CDEI; 418893e63e301e37cd3be7afb55c95eb8ef6ead304bRussell King cxfi = CDFI; 419b9e97822da374f52aaf99cb502f531ff2184b8f5Russell King } 420b9e97822da374f52aaf99cb502f531ff2184b8f5Russell King 421c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, cxsa, d->dev_addr); 422c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, cxei, 0); 423c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, cxfi, d->fi); 424c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CSDP, d->csdp); 425c5ed98b6ae79545284b7855a07ded32934865a6dRussell King omap_dma_chan_write(c, CLNK_CTRL, d->clnk_ctrl); 426b9e97822da374f52aaf99cb502f531ff2184b8f5Russell King 4277bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King omap_dma_start_sg(c, d, 0); 4287bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 4297bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 4307bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic void omap_dma_callback(int ch, u16 status, void *data) 4317bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 4327bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_chan *c = data; 4337bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_desc *d; 4347bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King unsigned long flags; 4357bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 4367bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_lock_irqsave(&c->vc.lock, flags); 4377bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King d = c->desc; 4387bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King if (d) { 4393a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King if (!c->cyclic) { 4403a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King if (++c->sgidx < d->sglen) { 4413a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King omap_dma_start_sg(c, d, c->sgidx); 4423a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King } else { 4433a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King omap_dma_start_desc(c); 4443a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King vchan_cookie_complete(&d->vd); 4453a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King } 4467bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } else { 4473a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King vchan_cyclic_callback(&d->vd); 4487bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 4497bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 4507bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_unlock_irqrestore(&c->vc.lock, flags); 4517bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 4527bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 4537bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King/* 4547bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * This callback schedules all pending channels. We could be more 4557bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * clever here by postponing allocation of the real DMA channels to 4567bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * this point, and freeing them when our virtual channel becomes idle. 4577bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * 4587bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * We would then need to deal with 'all channels in-use' 4597bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King */ 4607bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic void omap_dma_sched(unsigned long data) 4617bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 4627bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_dmadev *d = (struct omap_dmadev *)data; 4637bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King LIST_HEAD(head); 4647bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 4657bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_lock_irq(&d->lock); 4667bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King list_splice_tail_init(&d->pending, &head); 4677bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_unlock_irq(&d->lock); 4687bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 4697bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King while (!list_empty(&head)) { 4707bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_chan *c = list_first_entry(&head, 4717bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_chan, node); 4727bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 4737bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_lock_irq(&c->vc.lock); 4747bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King list_del_init(&c->node); 4757bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King omap_dma_start_desc(c); 4767bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_unlock_irq(&c->vc.lock); 4777bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 4787bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 4797bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 4806ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell Kingstatic irqreturn_t omap_dma_irq(int irq, void *devid) 4816ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King{ 4826ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King struct omap_dmadev *od = devid; 4836ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King unsigned status, channel; 4846ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 4856ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King spin_lock(&od->irq_lock); 4866ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 4876ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King status = omap_dma_glbl_read(od, IRQSTATUS_L1); 4886ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King status &= od->irq_enable_mask; 4896ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King if (status == 0) { 4906ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King spin_unlock(&od->irq_lock); 4916ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King return IRQ_NONE; 4926ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King } 4936ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 4946ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King while ((channel = ffs(status)) != 0) { 4956ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King unsigned mask, csr; 4966ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King struct omap_chan *c; 4976ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 4986ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King channel -= 1; 4996ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King mask = BIT(channel); 5006ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King status &= ~mask; 5016ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 5026ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King c = od->lch_map[channel]; 5036ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King if (c == NULL) { 5046ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King /* This should never happen */ 5056ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King dev_err(od->ddev.dev, "invalid channel %u\n", channel); 5066ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King continue; 5076ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King } 5086ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 5096ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King csr = omap_dma_get_csr(c); 5106ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King omap_dma_glbl_write(od, IRQSTATUS_L1, mask); 5116ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 5126ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King omap_dma_callback(channel, csr, c); 5136ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King } 5146ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 5156ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King spin_unlock(&od->irq_lock); 5166ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 5176ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King return IRQ_HANDLED; 5186ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King} 5196ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 5207bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic int omap_dma_alloc_chan_resources(struct dma_chan *chan) 5217bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 522596c471b69249764d8e241b004736878204daa0fRussell King struct omap_dmadev *od = to_omap_dma_dev(chan->device); 5237bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_chan *c = to_omap_dma_chan(chan); 524596c471b69249764d8e241b004736878204daa0fRussell King int ret; 525596c471b69249764d8e241b004736878204daa0fRussell King 5266ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King if (od->legacy) { 5276ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King ret = omap_request_dma(c->dma_sig, "DMA engine", 5286ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King omap_dma_callback, c, &c->dma_ch); 5296ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King } else { 5306ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King ret = omap_request_dma(c->dma_sig, "DMA engine", NULL, NULL, 5316ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King &c->dma_ch); 5326ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King } 5337bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 5346ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King dev_dbg(od->ddev.dev, "allocating channel %u for %u\n", 5356ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King c->dma_ch, c->dma_sig); 5367bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 5376ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King if (ret >= 0) { 538596c471b69249764d8e241b004736878204daa0fRussell King omap_dma_assign(od, c, c->dma_ch); 539596c471b69249764d8e241b004736878204daa0fRussell King 5406ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King if (!od->legacy) { 5416ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King unsigned val; 5426ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 5436ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King spin_lock_irq(&od->irq_lock); 5446ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King val = BIT(c->dma_ch); 5456ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King omap_dma_glbl_write(od, IRQSTATUS_L1, val); 5466ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King od->irq_enable_mask |= val; 5476ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King omap_dma_glbl_write(od, IRQENABLE_L1, od->irq_enable_mask); 5486ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 5496ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King val = omap_dma_glbl_read(od, IRQENABLE_L0); 5506ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King val &= ~BIT(c->dma_ch); 5516ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King omap_dma_glbl_write(od, IRQENABLE_L0, val); 5526ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King spin_unlock_irq(&od->irq_lock); 5536ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King } 5546ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King } 5556ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 556aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King if (dma_omap1()) { 557aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King if (__dma_omap16xx(od->plat->dma_attr)) { 558aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King c->ccr = CCR_OMAP31_DISABLE; 559aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King /* Duplicate what plat-omap/dma.c does */ 560aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King c->ccr |= c->dma_ch + 1; 561aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King } else { 562aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King c->ccr = c->dma_sig & 0x1f; 563aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King } 564aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King } else { 565aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King c->ccr = c->dma_sig & 0x1f; 566aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King c->ccr |= (c->dma_sig & ~0x1f) << 14; 567aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King } 568aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King if (od->plat->errata & DMA_ERRATA_IFRAME_BUFFERING) 569aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King c->ccr |= CCR_BUFFERING_DISABLE; 570aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King 571596c471b69249764d8e241b004736878204daa0fRussell King return ret; 5727bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 5737bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 5747bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic void omap_dma_free_chan_resources(struct dma_chan *chan) 5757bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 5766ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King struct omap_dmadev *od = to_omap_dma_dev(chan->device); 5777bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_chan *c = to_omap_dma_chan(chan); 5787bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 5796ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King if (!od->legacy) { 5806ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King spin_lock_irq(&od->irq_lock); 5816ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King od->irq_enable_mask &= ~BIT(c->dma_ch); 5826ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King omap_dma_glbl_write(od, IRQENABLE_L1, od->irq_enable_mask); 5836ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King spin_unlock_irq(&od->irq_lock); 5846ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King } 5856ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 586596c471b69249764d8e241b004736878204daa0fRussell King c->channel_base = NULL; 5876ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King od->lch_map[c->dma_ch] = NULL; 5887bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King vchan_free_chan_resources(&c->vc); 5897bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King omap_free_dma(c->dma_ch); 5907bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 5916ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King dev_dbg(od->ddev.dev, "freeing channel for %u\n", c->dma_sig); 5927bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 5937bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 5943850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell Kingstatic size_t omap_dma_sg_size(struct omap_sg *sg) 5953850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King{ 5963850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King return sg->en * sg->fn; 5973850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King} 5983850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King 5993850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell Kingstatic size_t omap_dma_desc_size(struct omap_desc *d) 6003850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King{ 6013850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King unsigned i; 6023850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King size_t size; 6033850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King 6043850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King for (size = i = 0; i < d->sglen; i++) 6053850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King size += omap_dma_sg_size(&d->sg[i]); 6063850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King 6073850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King return size * es_bytes[d->es]; 6083850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King} 6093850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King 6103850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell Kingstatic size_t omap_dma_desc_size_pos(struct omap_desc *d, dma_addr_t addr) 6113850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King{ 6123850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King unsigned i; 6133850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King size_t size, es_size = es_bytes[d->es]; 6143850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King 6153850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King for (size = i = 0; i < d->sglen; i++) { 6163850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King size_t this_size = omap_dma_sg_size(&d->sg[i]) * es_size; 6173850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King 6183850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King if (size) 6193850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King size += this_size; 6203850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King else if (addr >= d->sg[i].addr && 6213850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King addr < d->sg[i].addr + this_size) 6223850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King size += d->sg[i].addr + this_size - addr; 6233850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King } 6243850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King return size; 6253850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King} 6263850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King 627b07fd625ac9df7412bd996edbdc298eb343dd501Russell King/* 628b07fd625ac9df7412bd996edbdc298eb343dd501Russell King * OMAP 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is 629b07fd625ac9df7412bd996edbdc298eb343dd501Russell King * read before the DMA controller finished disabling the channel. 630b07fd625ac9df7412bd996edbdc298eb343dd501Russell King */ 631b07fd625ac9df7412bd996edbdc298eb343dd501Russell Kingstatic uint32_t omap_dma_chan_read_3_3(struct omap_chan *c, unsigned reg) 632b07fd625ac9df7412bd996edbdc298eb343dd501Russell King{ 633b07fd625ac9df7412bd996edbdc298eb343dd501Russell King struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); 634b07fd625ac9df7412bd996edbdc298eb343dd501Russell King uint32_t val; 635b07fd625ac9df7412bd996edbdc298eb343dd501Russell King 636b07fd625ac9df7412bd996edbdc298eb343dd501Russell King val = omap_dma_chan_read(c, reg); 637b07fd625ac9df7412bd996edbdc298eb343dd501Russell King if (val == 0 && od->plat->errata & DMA_ERRATA_3_3) 638b07fd625ac9df7412bd996edbdc298eb343dd501Russell King val = omap_dma_chan_read(c, reg); 639b07fd625ac9df7412bd996edbdc298eb343dd501Russell King 640b07fd625ac9df7412bd996edbdc298eb343dd501Russell King return val; 641b07fd625ac9df7412bd996edbdc298eb343dd501Russell King} 642b07fd625ac9df7412bd996edbdc298eb343dd501Russell King 6433997cab391b38e126f217e36ad7bdc9672c9fb4dRussell Kingstatic dma_addr_t omap_dma_get_src_pos(struct omap_chan *c) 6443997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King{ 6453997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); 646b07fd625ac9df7412bd996edbdc298eb343dd501Russell King dma_addr_t addr, cdac; 6473997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King 648b07fd625ac9df7412bd996edbdc298eb343dd501Russell King if (__dma_omap15xx(od->plat->dma_attr)) { 649c5ed98b6ae79545284b7855a07ded32934865a6dRussell King addr = omap_dma_chan_read(c, CPC); 650b07fd625ac9df7412bd996edbdc298eb343dd501Russell King } else { 651b07fd625ac9df7412bd996edbdc298eb343dd501Russell King addr = omap_dma_chan_read_3_3(c, CSAC); 652b07fd625ac9df7412bd996edbdc298eb343dd501Russell King cdac = omap_dma_chan_read_3_3(c, CDAC); 6533997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King 6543997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King /* 6553997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King * CDAC == 0 indicates that the DMA transfer on the channel has 6563997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King * not been started (no data has been transferred so far). 6573997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King * Return the programmed source start address in this case. 6583997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King */ 659b07fd625ac9df7412bd996edbdc298eb343dd501Russell King if (cdac == 0) 660c5ed98b6ae79545284b7855a07ded32934865a6dRussell King addr = omap_dma_chan_read(c, CSSA); 6613997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King } 6623997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King 6633997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King if (dma_omap1()) 664c5ed98b6ae79545284b7855a07ded32934865a6dRussell King addr |= omap_dma_chan_read(c, CSSA) & 0xffff0000; 6653997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King 6663997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King return addr; 6673997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King} 6683997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King 6693997cab391b38e126f217e36ad7bdc9672c9fb4dRussell Kingstatic dma_addr_t omap_dma_get_dst_pos(struct omap_chan *c) 6703997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King{ 6713997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device); 6723997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King dma_addr_t addr; 6733997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King 674b07fd625ac9df7412bd996edbdc298eb343dd501Russell King if (__dma_omap15xx(od->plat->dma_attr)) { 675c5ed98b6ae79545284b7855a07ded32934865a6dRussell King addr = omap_dma_chan_read(c, CPC); 676b07fd625ac9df7412bd996edbdc298eb343dd501Russell King } else { 677b07fd625ac9df7412bd996edbdc298eb343dd501Russell King addr = omap_dma_chan_read_3_3(c, CDAC); 6783997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King 6793997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King /* 680b07fd625ac9df7412bd996edbdc298eb343dd501Russell King * CDAC == 0 indicates that the DMA transfer on the channel 681b07fd625ac9df7412bd996edbdc298eb343dd501Russell King * has not been started (no data has been transferred so 682b07fd625ac9df7412bd996edbdc298eb343dd501Russell King * far). Return the programmed destination start address in 683b07fd625ac9df7412bd996edbdc298eb343dd501Russell King * this case. 6843997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King */ 6853997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King if (addr == 0) 686c5ed98b6ae79545284b7855a07ded32934865a6dRussell King addr = omap_dma_chan_read(c, CDSA); 6873997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King } 6883997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King 6893997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King if (dma_omap1()) 690c5ed98b6ae79545284b7855a07ded32934865a6dRussell King addr |= omap_dma_chan_read(c, CDSA) & 0xffff0000; 6913997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King 6923997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King return addr; 6933997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King} 6943997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King 6957bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic enum dma_status omap_dma_tx_status(struct dma_chan *chan, 6967bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King dma_cookie_t cookie, struct dma_tx_state *txstate) 6977bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 6983850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King struct omap_chan *c = to_omap_dma_chan(chan); 6993850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King struct virt_dma_desc *vd; 7003850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King enum dma_status ret; 7013850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King unsigned long flags; 7023850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King 7033850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King ret = dma_cookie_status(chan, cookie, txstate); 7047cce5083b738e3e693abe082d9958686bcb88d32Vinod Koul if (ret == DMA_COMPLETE || !txstate) 7053850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King return ret; 7063850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King 7073850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King spin_lock_irqsave(&c->vc.lock, flags); 7083850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King vd = vchan_find_desc(&c->vc, cookie); 7093850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King if (vd) { 7103850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King txstate->residue = omap_dma_desc_size(to_omap_dma_desc(&vd->tx)); 7113850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King } else if (c->desc && c->desc->vd.tx.cookie == cookie) { 7123850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King struct omap_desc *d = c->desc; 7133850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King dma_addr_t pos; 7143850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King 7153850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King if (d->dir == DMA_MEM_TO_DEV) 7163997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King pos = omap_dma_get_src_pos(c); 7173850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King else if (d->dir == DMA_DEV_TO_MEM) 7183997cab391b38e126f217e36ad7bdc9672c9fb4dRussell King pos = omap_dma_get_dst_pos(c); 7193850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King else 7203850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King pos = 0; 7213850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King 7223850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King txstate->residue = omap_dma_desc_size_pos(d, pos); 7233850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King } else { 7243850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King txstate->residue = 0; 7253850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King } 7263850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King spin_unlock_irqrestore(&c->vc.lock, flags); 7273850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King 7283850e22f5146d2ff5b66f1b7460d4720d5f1b6c7Russell King return ret; 7297bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 7307bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 7317bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic void omap_dma_issue_pending(struct dma_chan *chan) 7327bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 7337bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_chan *c = to_omap_dma_chan(chan); 7347bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King unsigned long flags; 7357bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 7367bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_lock_irqsave(&c->vc.lock, flags); 7377bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King if (vchan_issue_pending(&c->vc) && !c->desc) { 738765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi /* 739765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi * c->cyclic is used only by audio and in this case the DMA need 740765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi * to be started without delay. 741765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi */ 742765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi if (!c->cyclic) { 743765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi struct omap_dmadev *d = to_omap_dma_dev(chan->device); 744765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi spin_lock(&d->lock); 745765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi if (list_empty(&c->node)) 746765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi list_add_tail(&c->node, &d->pending); 747765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi spin_unlock(&d->lock); 748765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi tasklet_schedule(&d->task); 749765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi } else { 750765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi omap_dma_start_desc(c); 751765024697807ad1e1cac332aa891253ca4a339daPeter Ujfalusi } 7527bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 7537bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_unlock_irqrestore(&c->vc.lock, flags); 7547bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 7557bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 7567bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( 7577bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct dma_chan *chan, struct scatterlist *sgl, unsigned sglen, 7587bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King enum dma_transfer_direction dir, unsigned long tx_flags, void *context) 7597bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 76049ae0b29439446cff81c32bf01fb7b7cce195373Russell King struct omap_dmadev *od = to_omap_dma_dev(chan->device); 7617bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_chan *c = to_omap_dma_chan(chan); 7627bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King enum dma_slave_buswidth dev_width; 7637bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct scatterlist *sgent; 7647bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_desc *d; 7657bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King dma_addr_t dev_addr; 7663ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King unsigned i, j = 0, es, en, frame_bytes; 7677bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King u32 burst; 7687bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 7697bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King if (dir == DMA_DEV_TO_MEM) { 7707bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King dev_addr = c->cfg.src_addr; 7717bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King dev_width = c->cfg.src_addr_width; 7727bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King burst = c->cfg.src_maxburst; 7737bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } else if (dir == DMA_MEM_TO_DEV) { 7747bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King dev_addr = c->cfg.dst_addr; 7757bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King dev_width = c->cfg.dst_addr_width; 7767bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King burst = c->cfg.dst_maxburst; 7777bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } else { 7787bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King dev_err(chan->device->dev, "%s: bad direction?\n", __func__); 7797bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return NULL; 7807bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 7817bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 7827bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King /* Bus width translates to the element size (ES) */ 7837bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King switch (dev_width) { 7847bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King case DMA_SLAVE_BUSWIDTH_1_BYTE: 7859043826d88467091543c1d3ab06eb4afeed34789Russell King es = CSDP_DATA_TYPE_8; 7867bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King break; 7877bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King case DMA_SLAVE_BUSWIDTH_2_BYTES: 7889043826d88467091543c1d3ab06eb4afeed34789Russell King es = CSDP_DATA_TYPE_16; 7897bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King break; 7907bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King case DMA_SLAVE_BUSWIDTH_4_BYTES: 7919043826d88467091543c1d3ab06eb4afeed34789Russell King es = CSDP_DATA_TYPE_32; 7927bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King break; 7937bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King default: /* not reached */ 7947bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return NULL; 7957bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 7967bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 7977bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King /* Now allocate and setup the descriptor. */ 7987bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC); 7997bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King if (!d) 8007bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return NULL; 8017bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 8027bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King d->dir = dir; 8037bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King d->dev_addr = dev_addr; 8047bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King d->es = es; 8053ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King 806aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King d->ccr = c->ccr | CCR_SYNC_FRAME; 8073ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King if (dir == DMA_DEV_TO_MEM) 8089043826d88467091543c1d3ab06eb4afeed34789Russell King d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; 8093ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King else 8109043826d88467091543c1d3ab06eb4afeed34789Russell King d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC; 8113ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King 8129043826d88467091543c1d3ab06eb4afeed34789Russell King d->cicr = CICR_DROP_IE | CICR_BLOCK_IE; 8132f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King d->csdp = es; 814fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 8152f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King if (dma_omap1()) { 8169043826d88467091543c1d3ab06eb4afeed34789Russell King d->cicr |= CICR_TOUT_IE; 8172f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King 8182f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King if (dir == DMA_DEV_TO_MEM) 8199043826d88467091543c1d3ab06eb4afeed34789Russell King d->csdp |= CSDP_DST_PORT_EMIFF | CSDP_SRC_PORT_TIPB; 8202f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King else 8219043826d88467091543c1d3ab06eb4afeed34789Russell King d->csdp |= CSDP_DST_PORT_TIPB | CSDP_SRC_PORT_EMIFF; 8222f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King } else { 8233ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King if (dir == DMA_DEV_TO_MEM) 8249043826d88467091543c1d3ab06eb4afeed34789Russell King d->ccr |= CCR_TRIGGER_SRC; 8253ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King 8269043826d88467091543c1d3ab06eb4afeed34789Russell King d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; 8272f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King } 828965aeb4df1f2142f5a6407c6d40b7196be719582Russell King if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS) 829965aeb4df1f2142f5a6407c6d40b7196be719582Russell King d->clnk_ctrl = c->dma_ch; 8307bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 8317bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King /* 8327bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * Build our scatterlist entries: each contains the address, 8337bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * the number of elements (EN) in each frame, and the number of 8347bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * frames (FN). Number of bytes for this entry = ES * EN * FN. 8357bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * 8367bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * Burst size translates to number of elements with frame sync. 8377bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * Note: DMA engine defines burst to be the number of dev-width 8387bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * transfers. 8397bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King */ 8407bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King en = burst; 8417bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King frame_bytes = es_bytes[es] * en; 8427bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King for_each_sg(sgl, sgent, sglen, i) { 8437bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King d->sg[j].addr = sg_dma_address(sgent); 8447bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King d->sg[j].en = en; 8457bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King d->sg[j].fn = sg_dma_len(sgent) / frame_bytes; 8467bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King j++; 8477bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 8487bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 8497bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King d->sglen = j; 8507bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 8517bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return vchan_tx_prep(&c->vc, &d->vd, tx_flags); 8527bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 8537bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 8543a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell Kingstatic struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( 8553a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, 85631c1e5a1350ae8d1bc2018f5de8264266d9773e1Laurent Pinchart size_t period_len, enum dma_transfer_direction dir, unsigned long flags) 8573a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King{ 858fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King struct omap_dmadev *od = to_omap_dma_dev(chan->device); 8593a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King struct omap_chan *c = to_omap_dma_chan(chan); 8603a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King enum dma_slave_buswidth dev_width; 8613a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King struct omap_desc *d; 8623a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King dma_addr_t dev_addr; 8633ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King unsigned es; 8643a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King u32 burst; 8653a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King 8663a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King if (dir == DMA_DEV_TO_MEM) { 8673a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King dev_addr = c->cfg.src_addr; 8683a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King dev_width = c->cfg.src_addr_width; 8693a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King burst = c->cfg.src_maxburst; 8703a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King } else if (dir == DMA_MEM_TO_DEV) { 8713a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King dev_addr = c->cfg.dst_addr; 8723a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King dev_width = c->cfg.dst_addr_width; 8733a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King burst = c->cfg.dst_maxburst; 8743a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King } else { 8753a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King dev_err(chan->device->dev, "%s: bad direction?\n", __func__); 8763a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King return NULL; 8773a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King } 8783a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King 8793a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King /* Bus width translates to the element size (ES) */ 8803a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King switch (dev_width) { 8813a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King case DMA_SLAVE_BUSWIDTH_1_BYTE: 8829043826d88467091543c1d3ab06eb4afeed34789Russell King es = CSDP_DATA_TYPE_8; 8833a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King break; 8843a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King case DMA_SLAVE_BUSWIDTH_2_BYTES: 8859043826d88467091543c1d3ab06eb4afeed34789Russell King es = CSDP_DATA_TYPE_16; 8863a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King break; 8873a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King case DMA_SLAVE_BUSWIDTH_4_BYTES: 8889043826d88467091543c1d3ab06eb4afeed34789Russell King es = CSDP_DATA_TYPE_32; 8893a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King break; 8903a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King default: /* not reached */ 8913a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King return NULL; 8923a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King } 8933a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King 8943a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King /* Now allocate and setup the descriptor. */ 8953a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King d = kzalloc(sizeof(*d) + sizeof(d->sg[0]), GFP_ATOMIC); 8963a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King if (!d) 8973a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King return NULL; 8983a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King 8993a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King d->dir = dir; 9003a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King d->dev_addr = dev_addr; 9013a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King d->fi = burst; 9023a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King d->es = es; 9033a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King d->sg[0].addr = buf_addr; 9043a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King d->sg[0].en = period_len / es_bytes[es]; 9053a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King d->sg[0].fn = buf_len / period_len; 9063a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King d->sglen = 1; 9073ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King 908aa4c5b962a7a03eb6b43b3d2677c3677022c1223Russell King d->ccr = c->ccr; 9093ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King if (dir == DMA_DEV_TO_MEM) 9109043826d88467091543c1d3ab06eb4afeed34789Russell King d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT; 9113ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King else 9129043826d88467091543c1d3ab06eb4afeed34789Russell King d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC; 9133ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King 9149043826d88467091543c1d3ab06eb4afeed34789Russell King d->cicr = CICR_DROP_IE; 915fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King if (flags & DMA_PREP_INTERRUPT) 9169043826d88467091543c1d3ab06eb4afeed34789Russell King d->cicr |= CICR_FRAME_IE; 917fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King 9182f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King d->csdp = es; 9192f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King 9202f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King if (dma_omap1()) { 9219043826d88467091543c1d3ab06eb4afeed34789Russell King d->cicr |= CICR_TOUT_IE; 9222f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King 9232f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King if (dir == DMA_DEV_TO_MEM) 9249043826d88467091543c1d3ab06eb4afeed34789Russell King d->csdp |= CSDP_DST_PORT_EMIFF | CSDP_SRC_PORT_MPUI; 9252f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King else 9269043826d88467091543c1d3ab06eb4afeed34789Russell King d->csdp |= CSDP_DST_PORT_MPUI | CSDP_SRC_PORT_EMIFF; 9272f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King } else { 9283ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King if (burst) 9299043826d88467091543c1d3ab06eb4afeed34789Russell King d->ccr |= CCR_SYNC_PACKET; 9309043826d88467091543c1d3ab06eb4afeed34789Russell King else 9319043826d88467091543c1d3ab06eb4afeed34789Russell King d->ccr |= CCR_SYNC_ELEMENT; 9323ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King 9333ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King if (dir == DMA_DEV_TO_MEM) 9349043826d88467091543c1d3ab06eb4afeed34789Russell King d->ccr |= CCR_TRIGGER_SRC; 9353ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King 9369043826d88467091543c1d3ab06eb4afeed34789Russell King d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; 9373a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King 9389043826d88467091543c1d3ab06eb4afeed34789Russell King d->csdp |= CSDP_DST_BURST_64 | CSDP_SRC_BURST_64; 9392f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King } 9402f0d13bdf6440906bb52fe94681ce7927145f4d7Russell King 941965aeb4df1f2142f5a6407c6d40b7196be719582Russell King if (__dma_omap15xx(od->plat->dma_attr)) 942965aeb4df1f2142f5a6407c6d40b7196be719582Russell King d->ccr |= CCR_AUTO_INIT | CCR_REPEAT; 943965aeb4df1f2142f5a6407c6d40b7196be719582Russell King else 944965aeb4df1f2142f5a6407c6d40b7196be719582Russell King d->clnk_ctrl = c->dma_ch | CLNK_CTRL_ENABLE_LNK; 945965aeb4df1f2142f5a6407c6d40b7196be719582Russell King 9463ed4d18f39bcd8cb8d8218c0a5f89a4d81ba8730Russell King c->cyclic = true; 9473a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King 9482dde5b909e117cc95a5e31604f9bfd043e78ad9dPeter Ujfalusi return vchan_tx_prep(&c->vc, &d->vd, flags); 9493a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King} 9503a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King 9517bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic int omap_dma_slave_config(struct omap_chan *c, struct dma_slave_config *cfg) 9527bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 9537bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King if (cfg->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES || 9547bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King cfg->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES) 9557bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return -EINVAL; 9567bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 9577bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King memcpy(&c->cfg, cfg, sizeof(c->cfg)); 9587bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 9597bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return 0; 9607bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 9617bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 9627bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic int omap_dma_terminate_all(struct omap_chan *c) 9637bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 9647bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_dmadev *d = to_omap_dma_dev(c->vc.chan.device); 9657bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King unsigned long flags; 9667bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King LIST_HEAD(head); 9677bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 9687bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_lock_irqsave(&c->vc.lock, flags); 9697bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 9707bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King /* Prevent this channel being scheduled */ 9717bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_lock(&d->lock); 9727bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King list_del_init(&c->node); 9737bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_unlock(&d->lock); 9747bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 9757bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King /* 9767bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * Stop DMA activity: we assume the callback will not be called 977fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King * after omap_dma_stop() returns (even if it does, it will see 9787bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King * c->desc is NULL and exit.) 9797bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King */ 9807bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King if (c->desc) { 9817bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King c->desc = NULL; 9822dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi /* Avoid stopping the dma twice */ 9832dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi if (!c->paused) 984fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King omap_dma_stop(c); 9857bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 9867bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 9873a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King if (c->cyclic) { 9883a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King c->cyclic = false; 9892dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi c->paused = false; 9903a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King } 9913a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King 9927bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King vchan_get_all_descriptors(&c->vc, &head); 9937bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_unlock_irqrestore(&c->vc.lock, flags); 9947bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King vchan_dma_desc_free_list(&c->vc, &head); 9957bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 9967bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return 0; 9977bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 9987bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 9997bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic int omap_dma_pause(struct omap_chan *c) 10007bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 10012dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi /* Pause/Resume only allowed with cyclic mode */ 10022dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi if (!c->cyclic) 10032dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi return -EINVAL; 10042dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi 10052dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi if (!c->paused) { 1006fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King omap_dma_stop(c); 10072dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi c->paused = true; 10082dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi } 10092dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi 10102dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi return 0; 10117bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 10127bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10137bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic int omap_dma_resume(struct omap_chan *c) 10147bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 10152dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi /* Pause/Resume only allowed with cyclic mode */ 10162dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi if (!c->cyclic) 10172dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi return -EINVAL; 10182dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi 10192dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi if (c->paused) { 1020b3d09da7e1771decc6833d1fa662bf994948c8e6Peter Ujfalusi mb(); 1021b3d09da7e1771decc6833d1fa662bf994948c8e6Peter Ujfalusi 1022bfb607451786829430ecdd5bcd51c5dac03e3639Peter Ujfalusi /* Restore channel link register */ 1023bfb607451786829430ecdd5bcd51c5dac03e3639Peter Ujfalusi omap_dma_chan_write(c, CLNK_CTRL, c->desc->clnk_ctrl); 1024bfb607451786829430ecdd5bcd51c5dac03e3639Peter Ujfalusi 1025fa3ad86ae0576b2c721800cc4d46864aa6d31ffdRussell King omap_dma_start(c, c->desc); 10262dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi c->paused = false; 10272dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi } 10282dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi 10292dcdf570936168d488acf90be9b04a3d32dafce7Peter Ujfalusi return 0; 10307bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 10317bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10327bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic int omap_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, 10337bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King unsigned long arg) 10347bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 10357bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_chan *c = to_omap_dma_chan(chan); 10367bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King int ret; 10377bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10387bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King switch (cmd) { 10397bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King case DMA_SLAVE_CONFIG: 10407bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King ret = omap_dma_slave_config(c, (struct dma_slave_config *)arg); 10417bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King break; 10427bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10437bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King case DMA_TERMINATE_ALL: 10447bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King ret = omap_dma_terminate_all(c); 10457bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King break; 10467bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10477bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King case DMA_PAUSE: 10487bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King ret = omap_dma_pause(c); 10497bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King break; 10507bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10517bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King case DMA_RESUME: 10527bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King ret = omap_dma_resume(c); 10537bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King break; 10547bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10557bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King default: 10567bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King ret = -ENXIO; 10577bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King break; 10587bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 10597bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10607bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return ret; 10617bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 10627bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10637bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic int omap_dma_chan_init(struct omap_dmadev *od, int dma_sig) 10647bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 10657bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_chan *c; 10667bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10677bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King c = kzalloc(sizeof(*c), GFP_KERNEL); 10687bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King if (!c) 10697bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return -ENOMEM; 10707bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 1071596c471b69249764d8e241b004736878204daa0fRussell King c->reg_map = od->reg_map; 10727bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King c->dma_sig = dma_sig; 10737bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King c->vc.desc_free = omap_dma_desc_free; 10747bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King vchan_init(&c->vc, &od->ddev); 10757bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King INIT_LIST_HEAD(&c->node); 10767bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10777bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King od->ddev.chancnt++; 10787bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10797bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return 0; 10807bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 10817bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10827bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic void omap_dma_free(struct omap_dmadev *od) 10837bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 10847bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King tasklet_kill(&od->task); 10857bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King while (!list_empty(&od->ddev.channels)) { 10867bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_chan *c = list_first_entry(&od->ddev.channels, 10877bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_chan, vc.chan.device_node); 10887bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 10897bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King list_del(&c->vc.chan.device_node); 10907bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King tasklet_kill(&c->vc.task); 10917bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King kfree(c); 10927bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 10937bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 10947bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 109580b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi#define OMAP_DMA_BUSWIDTHS (BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \ 109680b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \ 109780b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)) 109880b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi 109980b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusistatic int omap_dma_device_slave_caps(struct dma_chan *dchan, 110080b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi struct dma_slave_caps *caps) 110180b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi{ 110280b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi caps->src_addr_widths = OMAP_DMA_BUSWIDTHS; 110380b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi caps->dstn_addr_widths = OMAP_DMA_BUSWIDTHS; 110480b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi caps->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); 110580b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi caps->cmd_pause = true; 110680b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi caps->cmd_terminate = true; 110780b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi caps->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; 110880b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi 110980b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi return 0; 111080b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi} 111180b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi 11127bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic int omap_dma_probe(struct platform_device *pdev) 11137bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 11147bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_dmadev *od; 1115596c471b69249764d8e241b004736878204daa0fRussell King struct resource *res; 11166ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King int rc, i, irq; 11177bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 1118104fce73fdbd174eb08a493eeb2920fd59e6d3f4Russell King od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL); 11197bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King if (!od) 11207bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return -ENOMEM; 11217bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 1122596c471b69249764d8e241b004736878204daa0fRussell King res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1123596c471b69249764d8e241b004736878204daa0fRussell King od->base = devm_ioremap_resource(&pdev->dev, res); 1124596c471b69249764d8e241b004736878204daa0fRussell King if (IS_ERR(od->base)) 1125596c471b69249764d8e241b004736878204daa0fRussell King return PTR_ERR(od->base); 1126596c471b69249764d8e241b004736878204daa0fRussell King 11271b416c4b41351c3eb8fc42dbb4cd8eba463c0813Russell King od->plat = omap_get_plat_info(); 11281b416c4b41351c3eb8fc42dbb4cd8eba463c0813Russell King if (!od->plat) 11291b416c4b41351c3eb8fc42dbb4cd8eba463c0813Russell King return -EPROBE_DEFER; 11301b416c4b41351c3eb8fc42dbb4cd8eba463c0813Russell King 1131596c471b69249764d8e241b004736878204daa0fRussell King od->reg_map = od->plat->reg_map; 1132596c471b69249764d8e241b004736878204daa0fRussell King 11337bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); 11343a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); 11357bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources; 11367bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King od->ddev.device_free_chan_resources = omap_dma_free_chan_resources; 11377bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King od->ddev.device_tx_status = omap_dma_tx_status; 11387bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King od->ddev.device_issue_pending = omap_dma_issue_pending; 11397bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King od->ddev.device_prep_slave_sg = omap_dma_prep_slave_sg; 11403a774ea91a5d05e7af58db6ae1ba298263c4a3d3Russell King od->ddev.device_prep_dma_cyclic = omap_dma_prep_dma_cyclic; 11417bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King od->ddev.device_control = omap_dma_control; 114280b0e0abfbcf9897ee263a79bc4cbdcfeca72431Peter Ujfalusi od->ddev.device_slave_caps = omap_dma_device_slave_caps; 11437bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King od->ddev.dev = &pdev->dev; 11447bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King INIT_LIST_HEAD(&od->ddev.channels); 11457bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King INIT_LIST_HEAD(&od->pending); 11467bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King spin_lock_init(&od->lock); 11476ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King spin_lock_init(&od->irq_lock); 11487bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 11497bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King tasklet_init(&od->task, omap_dma_sched, (unsigned long)od); 11507bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 11517bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King for (i = 0; i < 127; i++) { 11527bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King rc = omap_dma_chan_init(od, i); 11537bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King if (rc) { 11547bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King omap_dma_free(od); 11557bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return rc; 11567bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 11577bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 11587bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 11596ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King irq = platform_get_irq(pdev, 1); 11606ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King if (irq <= 0) { 11616ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King dev_info(&pdev->dev, "failed to get L1 IRQ: %d\n", irq); 11626ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King od->legacy = true; 11636ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King } else { 11646ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King /* Disable all interrupts */ 11656ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King od->irq_enable_mask = 0; 11666ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King omap_dma_glbl_write(od, IRQENABLE_L1, 0); 11676ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 11686ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King rc = devm_request_irq(&pdev->dev, irq, omap_dma_irq, 11696ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King IRQF_SHARED, "omap-dma-engine", od); 11706ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King if (rc) 11716ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King return rc; 11726ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King } 11736ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 11747bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King rc = dma_async_device_register(&od->ddev); 11757bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King if (rc) { 11767bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King pr_warn("OMAP-DMA: failed to register slave DMA engine device: %d\n", 11777bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King rc); 11787bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King omap_dma_free(od); 11798d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter return rc; 11808d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter } 11818d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter 11828d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter platform_set_drvdata(pdev, od); 11838d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter 11848d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter if (pdev->dev.of_node) { 11858d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter omap_dma_info.dma_cap = od->ddev.cap_mask; 11868d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter 11878d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter /* Device-tree DMA controller registration */ 11888d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter rc = of_dma_controller_register(pdev->dev.of_node, 11898d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter of_dma_simple_xlate, &omap_dma_info); 11908d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter if (rc) { 11918d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter pr_warn("OMAP-DMA: failed to register DMA controller\n"); 11928d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter dma_async_device_unregister(&od->ddev); 11938d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter omap_dma_free(od); 11948d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter } 11957bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 11967bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 11977bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King dev_info(&pdev->dev, "OMAP DMA engine driver\n"); 11987bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 11997bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return rc; 12007bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 12017bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 12027bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic int omap_dma_remove(struct platform_device *pdev) 12037bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 12047bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_dmadev *od = platform_get_drvdata(pdev); 12057bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 12068d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter if (pdev->dev.of_node) 12078d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter of_dma_controller_free(pdev->dev.of_node); 12088d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter 12097bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King dma_async_device_unregister(&od->ddev); 12106ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 12116ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King if (!od->legacy) { 12126ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King /* Disable all interrupts */ 12136ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King omap_dma_glbl_write(od, IRQENABLE_L0, 0); 12146ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King } 12156ddeb6d844596cac13c4a3665c0bd61f074a81a7Russell King 12167bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King omap_dma_free(od); 12177bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 12187bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return 0; 12197bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 12207bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 12218d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunterstatic const struct of_device_id omap_dma_match[] = { 12228d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter { .compatible = "ti,omap2420-sdma", }, 12238d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter { .compatible = "ti,omap2430-sdma", }, 12248d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter { .compatible = "ti,omap3430-sdma", }, 12258d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter { .compatible = "ti,omap3630-sdma", }, 12268d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter { .compatible = "ti,omap4430-sdma", }, 12278d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter {}, 12288d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter}; 12298d30662aac256eb61bc2f1d9cf1191825ef96328Jon HunterMODULE_DEVICE_TABLE(of, omap_dma_match); 12308d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter 12317bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic struct platform_driver omap_dma_driver = { 12327bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King .probe = omap_dma_probe, 12337bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King .remove = omap_dma_remove, 12347bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King .driver = { 12357bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King .name = "omap-dma-engine", 12367bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King .owner = THIS_MODULE, 12378d30662aac256eb61bc2f1d9cf1191825ef96328Jon Hunter .of_match_table = of_match_ptr(omap_dma_match), 12387bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King }, 12397bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King}; 12407bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 12417bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingbool omap_dma_filter_fn(struct dma_chan *chan, void *param) 12427bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 12437bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King if (chan->device->dev->driver == &omap_dma_driver.driver) { 12447bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King struct omap_chan *c = to_omap_dma_chan(chan); 12457bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King unsigned req = *(unsigned *)param; 12467bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 12477bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return req == c->dma_sig; 12487bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King } 12497bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King return false; 12507bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 12517bedaa5537604f34d1d63c5ec7891e559d2a61edRussell KingEXPORT_SYMBOL_GPL(omap_dma_filter_fn); 12527bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 12537bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic int omap_dma_init(void) 12547bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 1255be1f94812c2cc0aaf696d39fe23104763ea52b5bTony Lindgren return platform_driver_register(&omap_dma_driver); 12567bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 12577bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingsubsys_initcall(omap_dma_init); 12587bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 12597bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingstatic void __exit omap_dma_exit(void) 12607bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King{ 12617bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King platform_driver_unregister(&omap_dma_driver); 12627bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King} 12637bedaa5537604f34d1d63c5ec7891e559d2a61edRussell Kingmodule_exit(omap_dma_exit); 12647bedaa5537604f34d1d63c5ec7891e559d2a61edRussell King 12657bedaa5537604f34d1d63c5ec7891e559d2a61edRussell KingMODULE_AUTHOR("Russell King"); 12667bedaa5537604f34d1d63c5ec7891e559d2a61edRussell KingMODULE_LICENSE("GPL"); 1267