1b466a37fSAndy Shevchenko /* SPDX-License-Identifier: GPL-2.0 */
29cade1a4SAndy Shevchenko /*
39cade1a4SAndy Shevchenko * Driver for the Synopsys DesignWare AHB DMA Controller
49cade1a4SAndy Shevchenko *
59cade1a4SAndy Shevchenko * Copyright (C) 2005-2007 Atmel Corporation
69cade1a4SAndy Shevchenko * Copyright (C) 2010-2011 ST Microelectronics
7a9f4d1b8SAndy Shevchenko * Copyright (C) 2016 Intel Corporation
89cade1a4SAndy Shevchenko */
99cade1a4SAndy Shevchenko
102d248812SAndy Shevchenko #include <linux/bitops.h>
119cade1a4SAndy Shevchenko #include <linux/interrupt.h>
129cade1a4SAndy Shevchenko #include <linux/dmaengine.h>
139cade1a4SAndy Shevchenko
14a9f4d1b8SAndy Shevchenko #include <linux/io-64-nonatomic-hi-lo.h>
15a9f4d1b8SAndy Shevchenko
16bd2c6636SEugeniy Paltsev #include "internal.h"
17bd2c6636SEugeniy Paltsev
189cade1a4SAndy Shevchenko #define DW_DMA_MAX_NR_REQUESTS 16
199cade1a4SAndy Shevchenko
209cade1a4SAndy Shevchenko /* flow controller */
219cade1a4SAndy Shevchenko enum dw_dma_fc {
229cade1a4SAndy Shevchenko DW_DMA_FC_D_M2M,
239cade1a4SAndy Shevchenko DW_DMA_FC_D_M2P,
249cade1a4SAndy Shevchenko DW_DMA_FC_D_P2M,
259cade1a4SAndy Shevchenko DW_DMA_FC_D_P2P,
269cade1a4SAndy Shevchenko DW_DMA_FC_P_P2M,
279cade1a4SAndy Shevchenko DW_DMA_FC_SP_P2P,
289cade1a4SAndy Shevchenko DW_DMA_FC_P_M2P,
299cade1a4SAndy Shevchenko DW_DMA_FC_DP_P2P,
309cade1a4SAndy Shevchenko };
319cade1a4SAndy Shevchenko
329cade1a4SAndy Shevchenko /*
339cade1a4SAndy Shevchenko * Redefine this macro to handle differences between 32- and 64-bit
349cade1a4SAndy Shevchenko * addressing, big vs. little endian, etc.
359cade1a4SAndy Shevchenko */
369cade1a4SAndy Shevchenko #define DW_REG(name) u32 name; u32 __pad_##name
379cade1a4SAndy Shevchenko
389cade1a4SAndy Shevchenko /* Hardware register definitions. */
399cade1a4SAndy Shevchenko struct dw_dma_chan_regs {
409cade1a4SAndy Shevchenko DW_REG(SAR); /* Source Address Register */
419cade1a4SAndy Shevchenko DW_REG(DAR); /* Destination Address Register */
429cade1a4SAndy Shevchenko DW_REG(LLP); /* Linked List Pointer */
439cade1a4SAndy Shevchenko u32 CTL_LO; /* Control Register Low */
449cade1a4SAndy Shevchenko u32 CTL_HI; /* Control Register High */
459cade1a4SAndy Shevchenko DW_REG(SSTAT);
469cade1a4SAndy Shevchenko DW_REG(DSTAT);
479cade1a4SAndy Shevchenko DW_REG(SSTATAR);
489cade1a4SAndy Shevchenko DW_REG(DSTATAR);
499cade1a4SAndy Shevchenko u32 CFG_LO; /* Configuration Register Low */
509cade1a4SAndy Shevchenko u32 CFG_HI; /* Configuration Register High */
519cade1a4SAndy Shevchenko DW_REG(SGR);
529cade1a4SAndy Shevchenko DW_REG(DSR);
539cade1a4SAndy Shevchenko };
549cade1a4SAndy Shevchenko
559cade1a4SAndy Shevchenko struct dw_dma_irq_regs {
569cade1a4SAndy Shevchenko DW_REG(XFER);
579cade1a4SAndy Shevchenko DW_REG(BLOCK);
589cade1a4SAndy Shevchenko DW_REG(SRC_TRAN);
599cade1a4SAndy Shevchenko DW_REG(DST_TRAN);
609cade1a4SAndy Shevchenko DW_REG(ERROR);
619cade1a4SAndy Shevchenko };
629cade1a4SAndy Shevchenko
639cade1a4SAndy Shevchenko struct dw_dma_regs {
649cade1a4SAndy Shevchenko /* per-channel registers */
659cade1a4SAndy Shevchenko struct dw_dma_chan_regs CHAN[DW_DMA_MAX_NR_CHANNELS];
669cade1a4SAndy Shevchenko
679cade1a4SAndy Shevchenko /* irq handling */
689cade1a4SAndy Shevchenko struct dw_dma_irq_regs RAW; /* r */
699cade1a4SAndy Shevchenko struct dw_dma_irq_regs STATUS; /* r (raw & mask) */
709cade1a4SAndy Shevchenko struct dw_dma_irq_regs MASK; /* rw (set = irq enabled) */
719cade1a4SAndy Shevchenko struct dw_dma_irq_regs CLEAR; /* w (ack, affects "raw") */
729cade1a4SAndy Shevchenko
739cade1a4SAndy Shevchenko DW_REG(STATUS_INT); /* r */
749cade1a4SAndy Shevchenko
759cade1a4SAndy Shevchenko /* software handshaking */
769cade1a4SAndy Shevchenko DW_REG(REQ_SRC);
779cade1a4SAndy Shevchenko DW_REG(REQ_DST);
789cade1a4SAndy Shevchenko DW_REG(SGL_REQ_SRC);
799cade1a4SAndy Shevchenko DW_REG(SGL_REQ_DST);
809cade1a4SAndy Shevchenko DW_REG(LAST_SRC);
819cade1a4SAndy Shevchenko DW_REG(LAST_DST);
829cade1a4SAndy Shevchenko
839cade1a4SAndy Shevchenko /* miscellaneous */
849cade1a4SAndy Shevchenko DW_REG(CFG);
859cade1a4SAndy Shevchenko DW_REG(CH_EN);
869cade1a4SAndy Shevchenko DW_REG(ID);
879cade1a4SAndy Shevchenko DW_REG(TEST);
889cade1a4SAndy Shevchenko
89a9f4d1b8SAndy Shevchenko /* iDMA 32-bit support */
90a9f4d1b8SAndy Shevchenko DW_REG(CLASS_PRIORITY0);
91a9f4d1b8SAndy Shevchenko DW_REG(CLASS_PRIORITY1);
929cade1a4SAndy Shevchenko
939cade1a4SAndy Shevchenko /* optional encoded params, 0x3c8..0x3f7 */
949cade1a4SAndy Shevchenko u32 __reserved;
959cade1a4SAndy Shevchenko
969cade1a4SAndy Shevchenko /* per-channel configuration registers */
979cade1a4SAndy Shevchenko u32 DWC_PARAMS[DW_DMA_MAX_NR_CHANNELS];
989cade1a4SAndy Shevchenko u32 MULTI_BLK_TYPE;
999cade1a4SAndy Shevchenko u32 MAX_BLK_SIZE;
1009cade1a4SAndy Shevchenko
1019cade1a4SAndy Shevchenko /* top-level parameters */
1029cade1a4SAndy Shevchenko u32 DW_PARAMS;
103a9f4d1b8SAndy Shevchenko
104a9f4d1b8SAndy Shevchenko /* component ID */
105a9f4d1b8SAndy Shevchenko u32 COMP_TYPE;
106a9f4d1b8SAndy Shevchenko u32 COMP_VERSION;
107a9f4d1b8SAndy Shevchenko
108a9f4d1b8SAndy Shevchenko /* iDMA 32-bit support */
109a9f4d1b8SAndy Shevchenko DW_REG(FIFO_PARTITION0);
110a9f4d1b8SAndy Shevchenko DW_REG(FIFO_PARTITION1);
111a9f4d1b8SAndy Shevchenko
112a9f4d1b8SAndy Shevchenko DW_REG(SAI_ERR);
113a9f4d1b8SAndy Shevchenko DW_REG(GLOBAL_CFG);
1149cade1a4SAndy Shevchenko };
1159cade1a4SAndy Shevchenko
1169cade1a4SAndy Shevchenko /* Bitfields in DW_PARAMS */
1179cade1a4SAndy Shevchenko #define DW_PARAMS_NR_CHAN 8 /* number of channels */
1189cade1a4SAndy Shevchenko #define DW_PARAMS_NR_MASTER 11 /* number of AHB masters */
1199cade1a4SAndy Shevchenko #define DW_PARAMS_DATA_WIDTH(n) (15 + 2 * (n))
1209cade1a4SAndy Shevchenko #define DW_PARAMS_DATA_WIDTH1 15 /* master 1 data width */
1219cade1a4SAndy Shevchenko #define DW_PARAMS_DATA_WIDTH2 17 /* master 2 data width */
1229cade1a4SAndy Shevchenko #define DW_PARAMS_DATA_WIDTH3 19 /* master 3 data width */
1239cade1a4SAndy Shevchenko #define DW_PARAMS_DATA_WIDTH4 21 /* master 4 data width */
1249cade1a4SAndy Shevchenko #define DW_PARAMS_EN 28 /* encoded parameters */
1259cade1a4SAndy Shevchenko
1269cade1a4SAndy Shevchenko /* Bitfields in DWC_PARAMS */
1279cade1a4SAndy Shevchenko #define DWC_PARAMS_MBLK_EN 11 /* multi block transfer */
128ef3e515aSSerge Semin #define DWC_PARAMS_HC_LLP 13 /* set LLP register to zero */
129*ca7f2851SSerge Semin #define DWC_PARAMS_MSIZE 16 /* max group transaction size */
1309cade1a4SAndy Shevchenko
13146e8c83cSAndy Shevchenko /* bursts size */
13246e8c83cSAndy Shevchenko enum dw_dma_msize {
13346e8c83cSAndy Shevchenko DW_DMA_MSIZE_1,
13446e8c83cSAndy Shevchenko DW_DMA_MSIZE_4,
13546e8c83cSAndy Shevchenko DW_DMA_MSIZE_8,
13646e8c83cSAndy Shevchenko DW_DMA_MSIZE_16,
13746e8c83cSAndy Shevchenko DW_DMA_MSIZE_32,
13846e8c83cSAndy Shevchenko DW_DMA_MSIZE_64,
13946e8c83cSAndy Shevchenko DW_DMA_MSIZE_128,
14046e8c83cSAndy Shevchenko DW_DMA_MSIZE_256,
14146e8c83cSAndy Shevchenko };
14246e8c83cSAndy Shevchenko
1432a0fae02SMans Rullgard /* Bitfields in LLP */
1442a0fae02SMans Rullgard #define DWC_LLP_LMS(x) ((x) & 3) /* list master select */
1452a0fae02SMans Rullgard #define DWC_LLP_LOC(x) ((x) & ~3) /* next lli */
1462a0fae02SMans Rullgard
1479cade1a4SAndy Shevchenko /* Bitfields in CTL_LO */
1489cade1a4SAndy Shevchenko #define DWC_CTLL_INT_EN (1 << 0) /* irqs enabled? */
1499cade1a4SAndy Shevchenko #define DWC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */
1509cade1a4SAndy Shevchenko #define DWC_CTLL_SRC_WIDTH(n) ((n)<<4)
1519cade1a4SAndy Shevchenko #define DWC_CTLL_DST_INC (0<<7) /* DAR update/not */
1529cade1a4SAndy Shevchenko #define DWC_CTLL_DST_DEC (1<<7)
1539cade1a4SAndy Shevchenko #define DWC_CTLL_DST_FIX (2<<7)
154c9784a46SJie Yang #define DWC_CTLL_SRC_INC (0<<9) /* SAR update/not */
1559cade1a4SAndy Shevchenko #define DWC_CTLL_SRC_DEC (1<<9)
1569cade1a4SAndy Shevchenko #define DWC_CTLL_SRC_FIX (2<<9)
1579cade1a4SAndy Shevchenko #define DWC_CTLL_DST_MSIZE(n) ((n)<<11) /* burst, #elements */
1589cade1a4SAndy Shevchenko #define DWC_CTLL_SRC_MSIZE(n) ((n)<<14)
1599cade1a4SAndy Shevchenko #define DWC_CTLL_S_GATH_EN (1 << 17) /* src gather, !FIX */
1609cade1a4SAndy Shevchenko #define DWC_CTLL_D_SCAT_EN (1 << 18) /* dst scatter, !FIX */
1619cade1a4SAndy Shevchenko #define DWC_CTLL_FC(n) ((n) << 20)
1629cade1a4SAndy Shevchenko #define DWC_CTLL_FC_M2M (0 << 20) /* mem-to-mem */
1639cade1a4SAndy Shevchenko #define DWC_CTLL_FC_M2P (1 << 20) /* mem-to-periph */
1649cade1a4SAndy Shevchenko #define DWC_CTLL_FC_P2M (2 << 20) /* periph-to-mem */
1659cade1a4SAndy Shevchenko #define DWC_CTLL_FC_P2P (3 << 20) /* periph-to-periph */
1669cade1a4SAndy Shevchenko /* plus 4 transfer types for peripheral-as-flow-controller */
1679cade1a4SAndy Shevchenko #define DWC_CTLL_DMS(n) ((n)<<23) /* dst master select */
1689cade1a4SAndy Shevchenko #define DWC_CTLL_SMS(n) ((n)<<25) /* src master select */
1699cade1a4SAndy Shevchenko #define DWC_CTLL_LLP_D_EN (1 << 27) /* dest block chain */
1709cade1a4SAndy Shevchenko #define DWC_CTLL_LLP_S_EN (1 << 28) /* src block chain */
1719cade1a4SAndy Shevchenko
1729cade1a4SAndy Shevchenko /* Bitfields in CTL_HI */
1732d248812SAndy Shevchenko #define DWC_CTLH_BLOCK_TS_MASK GENMASK(11, 0)
1742d248812SAndy Shevchenko #define DWC_CTLH_BLOCK_TS(x) ((x) & DWC_CTLH_BLOCK_TS_MASK)
1752d248812SAndy Shevchenko #define DWC_CTLH_DONE (1 << 12)
1769cade1a4SAndy Shevchenko
17746e8c83cSAndy Shevchenko /* Bitfields in CFG_LO */
1789cade1a4SAndy Shevchenko #define DWC_CFGL_CH_PRIOR_MASK (0x7 << 5) /* priority mask */
1799cade1a4SAndy Shevchenko #define DWC_CFGL_CH_PRIOR(x) ((x) << 5) /* priority */
1809cade1a4SAndy Shevchenko #define DWC_CFGL_CH_SUSP (1 << 8) /* pause xfer */
1819cade1a4SAndy Shevchenko #define DWC_CFGL_FIFO_EMPTY (1 << 9) /* pause xfer */
1829cade1a4SAndy Shevchenko #define DWC_CFGL_HS_DST (1 << 10) /* handshake w/dst */
1839cade1a4SAndy Shevchenko #define DWC_CFGL_HS_SRC (1 << 11) /* handshake w/src */
18446e8c83cSAndy Shevchenko #define DWC_CFGL_LOCK_CH_XFER (0 << 12) /* scope of LOCK_CH */
18546e8c83cSAndy Shevchenko #define DWC_CFGL_LOCK_CH_BLOCK (1 << 12)
18646e8c83cSAndy Shevchenko #define DWC_CFGL_LOCK_CH_XACT (2 << 12)
18746e8c83cSAndy Shevchenko #define DWC_CFGL_LOCK_BUS_XFER (0 << 14) /* scope of LOCK_BUS */
18846e8c83cSAndy Shevchenko #define DWC_CFGL_LOCK_BUS_BLOCK (1 << 14)
18946e8c83cSAndy Shevchenko #define DWC_CFGL_LOCK_BUS_XACT (2 << 14)
19046e8c83cSAndy Shevchenko #define DWC_CFGL_LOCK_CH (1 << 15) /* channel lockout */
19146e8c83cSAndy Shevchenko #define DWC_CFGL_LOCK_BUS (1 << 16) /* busmaster lockout */
19246e8c83cSAndy Shevchenko #define DWC_CFGL_HS_DST_POL (1 << 18) /* dst handshake active low */
19346e8c83cSAndy Shevchenko #define DWC_CFGL_HS_SRC_POL (1 << 19) /* src handshake active low */
1949cade1a4SAndy Shevchenko #define DWC_CFGL_MAX_BURST(x) ((x) << 20)
1959cade1a4SAndy Shevchenko #define DWC_CFGL_RELOAD_SAR (1 << 30)
1969cade1a4SAndy Shevchenko #define DWC_CFGL_RELOAD_DAR (1 << 31)
1979cade1a4SAndy Shevchenko
19846e8c83cSAndy Shevchenko /* Bitfields in CFG_HI */
19946e8c83cSAndy Shevchenko #define DWC_CFGH_FCMODE (1 << 0)
20046e8c83cSAndy Shevchenko #define DWC_CFGH_FIFO_MODE (1 << 1)
20146e8c83cSAndy Shevchenko #define DWC_CFGH_PROTCTL(x) ((x) << 2)
2027b0c03ecSChristian Lamparter #define DWC_CFGH_PROTCTL_DATA (0 << 2) /* data access - always set */
2037b0c03ecSChristian Lamparter #define DWC_CFGH_PROTCTL_PRIV (1 << 2) /* privileged -> AHB HPROT[1] */
2047b0c03ecSChristian Lamparter #define DWC_CFGH_PROTCTL_BUFFER (2 << 2) /* bufferable -> AHB HPROT[2] */
2057b0c03ecSChristian Lamparter #define DWC_CFGH_PROTCTL_CACHE (4 << 2) /* cacheable -> AHB HPROT[3] */
2069cade1a4SAndy Shevchenko #define DWC_CFGH_DS_UPD_EN (1 << 5)
2079cade1a4SAndy Shevchenko #define DWC_CFGH_SS_UPD_EN (1 << 6)
20846e8c83cSAndy Shevchenko #define DWC_CFGH_SRC_PER(x) ((x) << 7)
20946e8c83cSAndy Shevchenko #define DWC_CFGH_DST_PER(x) ((x) << 11)
2109cade1a4SAndy Shevchenko
2119cade1a4SAndy Shevchenko /* Bitfields in SGR */
2129cade1a4SAndy Shevchenko #define DWC_SGR_SGI(x) ((x) << 0)
2139cade1a4SAndy Shevchenko #define DWC_SGR_SGC(x) ((x) << 20)
2149cade1a4SAndy Shevchenko
2159cade1a4SAndy Shevchenko /* Bitfields in DSR */
2169cade1a4SAndy Shevchenko #define DWC_DSR_DSI(x) ((x) << 0)
2179cade1a4SAndy Shevchenko #define DWC_DSR_DSC(x) ((x) << 20)
2189cade1a4SAndy Shevchenko
2199cade1a4SAndy Shevchenko /* Bitfields in CFG */
2209cade1a4SAndy Shevchenko #define DW_CFG_DMA_EN (1 << 0)
2219cade1a4SAndy Shevchenko
222a9f4d1b8SAndy Shevchenko /* iDMA 32-bit support */
223a9f4d1b8SAndy Shevchenko
224934891b0SAndy Shevchenko /* bursts size */
225934891b0SAndy Shevchenko enum idma32_msize {
226934891b0SAndy Shevchenko IDMA32_MSIZE_1,
227934891b0SAndy Shevchenko IDMA32_MSIZE_2,
228934891b0SAndy Shevchenko IDMA32_MSIZE_4,
229934891b0SAndy Shevchenko IDMA32_MSIZE_8,
230934891b0SAndy Shevchenko IDMA32_MSIZE_16,
231934891b0SAndy Shevchenko IDMA32_MSIZE_32,
232934891b0SAndy Shevchenko };
233934891b0SAndy Shevchenko
234a9f4d1b8SAndy Shevchenko /* Bitfields in CTL_HI */
235a9f4d1b8SAndy Shevchenko #define IDMA32C_CTLH_BLOCK_TS_MASK GENMASK(16, 0)
236a9f4d1b8SAndy Shevchenko #define IDMA32C_CTLH_BLOCK_TS(x) ((x) & IDMA32C_CTLH_BLOCK_TS_MASK)
237a9f4d1b8SAndy Shevchenko #define IDMA32C_CTLH_DONE (1 << 17)
238a9f4d1b8SAndy Shevchenko
239a9f4d1b8SAndy Shevchenko /* Bitfields in CFG_LO */
240a9f4d1b8SAndy Shevchenko #define IDMA32C_CFGL_DST_BURST_ALIGN (1 << 0) /* dst burst align */
241a9f4d1b8SAndy Shevchenko #define IDMA32C_CFGL_SRC_BURST_ALIGN (1 << 1) /* src burst align */
242a9f4d1b8SAndy Shevchenko #define IDMA32C_CFGL_CH_DRAIN (1 << 10) /* drain FIFO */
243a9f4d1b8SAndy Shevchenko #define IDMA32C_CFGL_DST_OPT_BL (1 << 20) /* optimize dst burst length */
244a9f4d1b8SAndy Shevchenko #define IDMA32C_CFGL_SRC_OPT_BL (1 << 21) /* optimize src burst length */
245a9f4d1b8SAndy Shevchenko
246a9f4d1b8SAndy Shevchenko /* Bitfields in CFG_HI */
247a9f4d1b8SAndy Shevchenko #define IDMA32C_CFGH_SRC_PER(x) ((x) << 0)
248a9f4d1b8SAndy Shevchenko #define IDMA32C_CFGH_DST_PER(x) ((x) << 4)
249a9f4d1b8SAndy Shevchenko #define IDMA32C_CFGH_RD_ISSUE_THD(x) ((x) << 8)
250a9f4d1b8SAndy Shevchenko #define IDMA32C_CFGH_RW_ISSUE_THD(x) ((x) << 18)
251a9f4d1b8SAndy Shevchenko #define IDMA32C_CFGH_SRC_PER_EXT(x) ((x) << 28) /* src peripheral extension */
252a9f4d1b8SAndy Shevchenko #define IDMA32C_CFGH_DST_PER_EXT(x) ((x) << 30) /* dst peripheral extension */
253a9f4d1b8SAndy Shevchenko
254a9f4d1b8SAndy Shevchenko /* Bitfields in FIFO_PARTITION */
255a9f4d1b8SAndy Shevchenko #define IDMA32C_FP_PSIZE_CH0(x) ((x) << 0)
256a9f4d1b8SAndy Shevchenko #define IDMA32C_FP_PSIZE_CH1(x) ((x) << 13)
257a9f4d1b8SAndy Shevchenko #define IDMA32C_FP_UPDATE (1 << 26)
258a9f4d1b8SAndy Shevchenko
2599cade1a4SAndy Shevchenko enum dw_dmac_flags {
2609cade1a4SAndy Shevchenko DW_DMA_IS_CYCLIC = 0,
2619cade1a4SAndy Shevchenko DW_DMA_IS_SOFT_LLP = 1,
2625e09f98eSAndy Shevchenko DW_DMA_IS_PAUSED = 2,
263423f9cbfSAndy Shevchenko DW_DMA_IS_INITIALIZED = 3,
2649cade1a4SAndy Shevchenko };
2659cade1a4SAndy Shevchenko
2669cade1a4SAndy Shevchenko struct dw_dma_chan {
2679cade1a4SAndy Shevchenko struct dma_chan chan;
2689cade1a4SAndy Shevchenko void __iomem *ch_regs;
2699cade1a4SAndy Shevchenko u8 mask;
2709cade1a4SAndy Shevchenko u8 priority;
2719cade1a4SAndy Shevchenko enum dma_transfer_direction direction;
2729cade1a4SAndy Shevchenko
2739cade1a4SAndy Shevchenko /* software emulation of the LLP transfers */
2749cade1a4SAndy Shevchenko struct list_head *tx_node_active;
2759cade1a4SAndy Shevchenko
2769cade1a4SAndy Shevchenko spinlock_t lock;
2779cade1a4SAndy Shevchenko
2789cade1a4SAndy Shevchenko /* these other elements are all protected by lock */
2799cade1a4SAndy Shevchenko unsigned long flags;
2809cade1a4SAndy Shevchenko struct list_head active_list;
2819cade1a4SAndy Shevchenko struct list_head queue;
2829cade1a4SAndy Shevchenko
2839cade1a4SAndy Shevchenko unsigned int descs_allocated;
2849cade1a4SAndy Shevchenko
2859cade1a4SAndy Shevchenko /* hardware configuration */
2869cade1a4SAndy Shevchenko unsigned int block_size;
2879cade1a4SAndy Shevchenko bool nollp;
288*ca7f2851SSerge Semin u32 max_burst;
2899cade1a4SAndy Shevchenko
2909cade1a4SAndy Shevchenko /* custom slave configuration */
2919217a5bfSAndy Shevchenko struct dw_dma_slave dws;
2929cade1a4SAndy Shevchenko
293295d3e10SVinod Koul /* configuration passed via .device_config */
2949cade1a4SAndy Shevchenko struct dma_slave_config dma_sconfig;
2959cade1a4SAndy Shevchenko };
2969cade1a4SAndy Shevchenko
2979cade1a4SAndy Shevchenko static inline struct dw_dma_chan_regs __iomem *
__dwc_regs(struct dw_dma_chan * dwc)2989cade1a4SAndy Shevchenko __dwc_regs(struct dw_dma_chan *dwc)
2999cade1a4SAndy Shevchenko {
3009cade1a4SAndy Shevchenko return dwc->ch_regs;
3019cade1a4SAndy Shevchenko }
3029cade1a4SAndy Shevchenko
3039cade1a4SAndy Shevchenko #define channel_readl(dwc, name) \
30414bebd01SAndy Shevchenko readl(&(__dwc_regs(dwc)->name))
3059cade1a4SAndy Shevchenko #define channel_writel(dwc, name, val) \
30614bebd01SAndy Shevchenko writel((val), &(__dwc_regs(dwc)->name))
3079cade1a4SAndy Shevchenko
to_dw_dma_chan(struct dma_chan * chan)3089cade1a4SAndy Shevchenko static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
3099cade1a4SAndy Shevchenko {
3109cade1a4SAndy Shevchenko return container_of(chan, struct dw_dma_chan, chan);
3119cade1a4SAndy Shevchenko }
3129cade1a4SAndy Shevchenko
3139cade1a4SAndy Shevchenko struct dw_dma {
3149cade1a4SAndy Shevchenko struct dma_device dma;
31508d62f58SAndy Shevchenko char name[20];
3169cade1a4SAndy Shevchenko void __iomem *regs;
3179cade1a4SAndy Shevchenko struct dma_pool *desc_pool;
3189cade1a4SAndy Shevchenko struct tasklet_struct tasklet;
3199cade1a4SAndy Shevchenko
320000871ceSAndy Shevchenko /* channels */
321000871ceSAndy Shevchenko struct dw_dma_chan *chan;
3229cade1a4SAndy Shevchenko u8 all_chan_mask;
32399d9bf4eSAndy Shevchenko u8 in_use;
3249cade1a4SAndy Shevchenko
32569da8be9SAndy Shevchenko /* Channel operations */
32669da8be9SAndy Shevchenko void (*initialize_chan)(struct dw_dma_chan *dwc);
32769da8be9SAndy Shevchenko void (*suspend_chan)(struct dw_dma_chan *dwc, bool drain);
32891f0ff88SAndy Shevchenko void (*resume_chan)(struct dw_dma_chan *dwc, bool drain);
329934891b0SAndy Shevchenko u32 (*prepare_ctllo)(struct dw_dma_chan *dwc);
33069da8be9SAndy Shevchenko void (*encode_maxburst)(struct dw_dma_chan *dwc, u32 *maxburst);
33169da8be9SAndy Shevchenko u32 (*bytes2block)(struct dw_dma_chan *dwc, size_t bytes,
33269da8be9SAndy Shevchenko unsigned int width, size_t *len);
33369da8be9SAndy Shevchenko size_t (*block2bytes)(struct dw_dma_chan *dwc, u32 block, u32 width);
33469da8be9SAndy Shevchenko
33569da8be9SAndy Shevchenko /* Device operations */
33669da8be9SAndy Shevchenko void (*set_device_name)(struct dw_dma *dw, int id);
33769da8be9SAndy Shevchenko void (*disable)(struct dw_dma *dw);
33869da8be9SAndy Shevchenko void (*enable)(struct dw_dma *dw);
33969da8be9SAndy Shevchenko
340161c3d04SAndy Shevchenko /* platform data */
341161c3d04SAndy Shevchenko struct dw_dma_platform_data *pdata;
3429cade1a4SAndy Shevchenko };
3439cade1a4SAndy Shevchenko
__dw_regs(struct dw_dma * dw)3449cade1a4SAndy Shevchenko static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
3459cade1a4SAndy Shevchenko {
3469cade1a4SAndy Shevchenko return dw->regs;
3479cade1a4SAndy Shevchenko }
3489cade1a4SAndy Shevchenko
3499cade1a4SAndy Shevchenko #define dma_readl(dw, name) \
35014bebd01SAndy Shevchenko readl(&(__dw_regs(dw)->name))
3519cade1a4SAndy Shevchenko #define dma_writel(dw, name, val) \
35214bebd01SAndy Shevchenko writel((val), &(__dw_regs(dw)->name))
3539cade1a4SAndy Shevchenko
354a9f4d1b8SAndy Shevchenko #define idma32_readq(dw, name) \
355a9f4d1b8SAndy Shevchenko hi_lo_readq(&(__dw_regs(dw)->name))
356a9f4d1b8SAndy Shevchenko #define idma32_writeq(dw, name, val) \
357a9f4d1b8SAndy Shevchenko hi_lo_writeq((val), &(__dw_regs(dw)->name))
358a9f4d1b8SAndy Shevchenko
3599cade1a4SAndy Shevchenko #define channel_set_bit(dw, reg, mask) \
3609cade1a4SAndy Shevchenko dma_writel(dw, reg, ((mask) << 8) | (mask))
3619cade1a4SAndy Shevchenko #define channel_clear_bit(dw, reg, mask) \
3629cade1a4SAndy Shevchenko dma_writel(dw, reg, ((mask) << 8) | 0)
3639cade1a4SAndy Shevchenko
to_dw_dma(struct dma_device * ddev)3649cade1a4SAndy Shevchenko static inline struct dw_dma *to_dw_dma(struct dma_device *ddev)
3659cade1a4SAndy Shevchenko {
3669cade1a4SAndy Shevchenko return container_of(ddev, struct dw_dma, dma);
3679cade1a4SAndy Shevchenko }
3689cade1a4SAndy Shevchenko
3699cade1a4SAndy Shevchenko /* LLI == Linked List Item; a.k.a. DMA block descriptor */
3709cade1a4SAndy Shevchenko struct dw_lli {
3719cade1a4SAndy Shevchenko /* values that are not changed by hardware */
37214bebd01SAndy Shevchenko __le32 sar;
37314bebd01SAndy Shevchenko __le32 dar;
37414bebd01SAndy Shevchenko __le32 llp; /* chain to next lli */
37514bebd01SAndy Shevchenko __le32 ctllo;
3769cade1a4SAndy Shevchenko /* values that may get written back: */
37714bebd01SAndy Shevchenko __le32 ctlhi;
3789cade1a4SAndy Shevchenko /* sstat and dstat can snapshot peripheral register state.
3799cade1a4SAndy Shevchenko * silicon config may discard either or both...
3809cade1a4SAndy Shevchenko */
38114bebd01SAndy Shevchenko __le32 sstat;
38214bebd01SAndy Shevchenko __le32 dstat;
3839cade1a4SAndy Shevchenko };
3849cade1a4SAndy Shevchenko
3859cade1a4SAndy Shevchenko struct dw_desc {
3869cade1a4SAndy Shevchenko /* FIRST values the hardware uses */
3879cade1a4SAndy Shevchenko struct dw_lli lli;
3889cade1a4SAndy Shevchenko
389df1f3a23SMans Rullgard #define lli_set(d, reg, v) ((d)->lli.reg |= cpu_to_le32(v))
390df1f3a23SMans Rullgard #define lli_clear(d, reg, v) ((d)->lli.reg &= ~cpu_to_le32(v))
391df1f3a23SMans Rullgard #define lli_read(d, reg) le32_to_cpu((d)->lli.reg)
392df1f3a23SMans Rullgard #define lli_write(d, reg, v) ((d)->lli.reg = cpu_to_le32(v))
393df1f3a23SMans Rullgard
3949cade1a4SAndy Shevchenko /* THEN values for driver housekeeping */
3959cade1a4SAndy Shevchenko struct list_head desc_node;
3969cade1a4SAndy Shevchenko struct list_head tx_list;
3979cade1a4SAndy Shevchenko struct dma_async_tx_descriptor txd;
3989cade1a4SAndy Shevchenko size_t len;
3999cade1a4SAndy Shevchenko size_t total_len;
400b68fd097SAndy Shevchenko u32 residue;
4019cade1a4SAndy Shevchenko };
4029cade1a4SAndy Shevchenko
4039cade1a4SAndy Shevchenko #define to_dw_desc(h) list_entry(h, struct dw_desc, desc_node)
4049cade1a4SAndy Shevchenko
4059cade1a4SAndy Shevchenko static inline struct dw_desc *
txd_to_dw_desc(struct dma_async_tx_descriptor * txd)4069cade1a4SAndy Shevchenko txd_to_dw_desc(struct dma_async_tx_descriptor *txd)
4079cade1a4SAndy Shevchenko {
4089cade1a4SAndy Shevchenko return container_of(txd, struct dw_desc, txd);
4099cade1a4SAndy Shevchenko }
410