18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for the Synopsys DesignWare AHB DMA Controller 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2005-2007 Atmel Corporation 68c2ecf20Sopenharmony_ci * Copyright (C) 2010-2011 ST Microelectronics 78c2ecf20Sopenharmony_ci * Copyright (C) 2016 Intel Corporation 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/bitops.h> 118c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 128c2ecf20Sopenharmony_ci#include <linux/dmaengine.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/io-64-nonatomic-hi-lo.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "internal.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define DW_DMA_MAX_NR_REQUESTS 16 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* flow controller */ 218c2ecf20Sopenharmony_cienum dw_dma_fc { 228c2ecf20Sopenharmony_ci DW_DMA_FC_D_M2M, 238c2ecf20Sopenharmony_ci DW_DMA_FC_D_M2P, 248c2ecf20Sopenharmony_ci DW_DMA_FC_D_P2M, 258c2ecf20Sopenharmony_ci DW_DMA_FC_D_P2P, 268c2ecf20Sopenharmony_ci DW_DMA_FC_P_P2M, 278c2ecf20Sopenharmony_ci DW_DMA_FC_SP_P2P, 288c2ecf20Sopenharmony_ci DW_DMA_FC_P_M2P, 298c2ecf20Sopenharmony_ci DW_DMA_FC_DP_P2P, 308c2ecf20Sopenharmony_ci}; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci * Redefine this macro to handle differences between 32- and 64-bit 348c2ecf20Sopenharmony_ci * addressing, big vs. little endian, etc. 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_ci#define DW_REG(name) u32 name; u32 __pad_##name 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* Hardware register definitions. */ 398c2ecf20Sopenharmony_cistruct dw_dma_chan_regs { 408c2ecf20Sopenharmony_ci DW_REG(SAR); /* Source Address Register */ 418c2ecf20Sopenharmony_ci DW_REG(DAR); /* Destination Address Register */ 428c2ecf20Sopenharmony_ci DW_REG(LLP); /* Linked List Pointer */ 438c2ecf20Sopenharmony_ci u32 CTL_LO; /* Control Register Low */ 448c2ecf20Sopenharmony_ci u32 CTL_HI; /* Control Register High */ 458c2ecf20Sopenharmony_ci DW_REG(SSTAT); 468c2ecf20Sopenharmony_ci DW_REG(DSTAT); 478c2ecf20Sopenharmony_ci DW_REG(SSTATAR); 488c2ecf20Sopenharmony_ci DW_REG(DSTATAR); 498c2ecf20Sopenharmony_ci u32 CFG_LO; /* Configuration Register Low */ 508c2ecf20Sopenharmony_ci u32 CFG_HI; /* Configuration Register High */ 518c2ecf20Sopenharmony_ci DW_REG(SGR); 528c2ecf20Sopenharmony_ci DW_REG(DSR); 538c2ecf20Sopenharmony_ci}; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistruct dw_dma_irq_regs { 568c2ecf20Sopenharmony_ci DW_REG(XFER); 578c2ecf20Sopenharmony_ci DW_REG(BLOCK); 588c2ecf20Sopenharmony_ci DW_REG(SRC_TRAN); 598c2ecf20Sopenharmony_ci DW_REG(DST_TRAN); 608c2ecf20Sopenharmony_ci DW_REG(ERROR); 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistruct dw_dma_regs { 648c2ecf20Sopenharmony_ci /* per-channel registers */ 658c2ecf20Sopenharmony_ci struct dw_dma_chan_regs CHAN[DW_DMA_MAX_NR_CHANNELS]; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* irq handling */ 688c2ecf20Sopenharmony_ci struct dw_dma_irq_regs RAW; /* r */ 698c2ecf20Sopenharmony_ci struct dw_dma_irq_regs STATUS; /* r (raw & mask) */ 708c2ecf20Sopenharmony_ci struct dw_dma_irq_regs MASK; /* rw (set = irq enabled) */ 718c2ecf20Sopenharmony_ci struct dw_dma_irq_regs CLEAR; /* w (ack, affects "raw") */ 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci DW_REG(STATUS_INT); /* r */ 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci /* software handshaking */ 768c2ecf20Sopenharmony_ci DW_REG(REQ_SRC); 778c2ecf20Sopenharmony_ci DW_REG(REQ_DST); 788c2ecf20Sopenharmony_ci DW_REG(SGL_REQ_SRC); 798c2ecf20Sopenharmony_ci DW_REG(SGL_REQ_DST); 808c2ecf20Sopenharmony_ci DW_REG(LAST_SRC); 818c2ecf20Sopenharmony_ci DW_REG(LAST_DST); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* miscellaneous */ 848c2ecf20Sopenharmony_ci DW_REG(CFG); 858c2ecf20Sopenharmony_ci DW_REG(CH_EN); 868c2ecf20Sopenharmony_ci DW_REG(ID); 878c2ecf20Sopenharmony_ci DW_REG(TEST); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci /* iDMA 32-bit support */ 908c2ecf20Sopenharmony_ci DW_REG(CLASS_PRIORITY0); 918c2ecf20Sopenharmony_ci DW_REG(CLASS_PRIORITY1); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* optional encoded params, 0x3c8..0x3f7 */ 948c2ecf20Sopenharmony_ci u32 __reserved; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci /* per-channel configuration registers */ 978c2ecf20Sopenharmony_ci u32 DWC_PARAMS[DW_DMA_MAX_NR_CHANNELS]; 988c2ecf20Sopenharmony_ci u32 MULTI_BLK_TYPE; 998c2ecf20Sopenharmony_ci u32 MAX_BLK_SIZE; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci /* top-level parameters */ 1028c2ecf20Sopenharmony_ci u32 DW_PARAMS; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci /* component ID */ 1058c2ecf20Sopenharmony_ci u32 COMP_TYPE; 1068c2ecf20Sopenharmony_ci u32 COMP_VERSION; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* iDMA 32-bit support */ 1098c2ecf20Sopenharmony_ci DW_REG(FIFO_PARTITION0); 1108c2ecf20Sopenharmony_ci DW_REG(FIFO_PARTITION1); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci DW_REG(SAI_ERR); 1138c2ecf20Sopenharmony_ci DW_REG(GLOBAL_CFG); 1148c2ecf20Sopenharmony_ci}; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci/* Bitfields in DW_PARAMS */ 1178c2ecf20Sopenharmony_ci#define DW_PARAMS_NR_CHAN 8 /* number of channels */ 1188c2ecf20Sopenharmony_ci#define DW_PARAMS_NR_MASTER 11 /* number of AHB masters */ 1198c2ecf20Sopenharmony_ci#define DW_PARAMS_DATA_WIDTH(n) (15 + 2 * (n)) 1208c2ecf20Sopenharmony_ci#define DW_PARAMS_DATA_WIDTH1 15 /* master 1 data width */ 1218c2ecf20Sopenharmony_ci#define DW_PARAMS_DATA_WIDTH2 17 /* master 2 data width */ 1228c2ecf20Sopenharmony_ci#define DW_PARAMS_DATA_WIDTH3 19 /* master 3 data width */ 1238c2ecf20Sopenharmony_ci#define DW_PARAMS_DATA_WIDTH4 21 /* master 4 data width */ 1248c2ecf20Sopenharmony_ci#define DW_PARAMS_EN 28 /* encoded parameters */ 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci/* Bitfields in DWC_PARAMS */ 1278c2ecf20Sopenharmony_ci#define DWC_PARAMS_MBLK_EN 11 /* multi block transfer */ 1288c2ecf20Sopenharmony_ci#define DWC_PARAMS_HC_LLP 13 /* set LLP register to zero */ 1298c2ecf20Sopenharmony_ci#define DWC_PARAMS_MSIZE 16 /* max group transaction size */ 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci/* bursts size */ 1328c2ecf20Sopenharmony_cienum dw_dma_msize { 1338c2ecf20Sopenharmony_ci DW_DMA_MSIZE_1, 1348c2ecf20Sopenharmony_ci DW_DMA_MSIZE_4, 1358c2ecf20Sopenharmony_ci DW_DMA_MSIZE_8, 1368c2ecf20Sopenharmony_ci DW_DMA_MSIZE_16, 1378c2ecf20Sopenharmony_ci DW_DMA_MSIZE_32, 1388c2ecf20Sopenharmony_ci DW_DMA_MSIZE_64, 1398c2ecf20Sopenharmony_ci DW_DMA_MSIZE_128, 1408c2ecf20Sopenharmony_ci DW_DMA_MSIZE_256, 1418c2ecf20Sopenharmony_ci}; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci/* Bitfields in LLP */ 1448c2ecf20Sopenharmony_ci#define DWC_LLP_LMS(x) ((x) & 3) /* list master select */ 1458c2ecf20Sopenharmony_ci#define DWC_LLP_LOC(x) ((x) & ~3) /* next lli */ 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci/* Bitfields in CTL_LO */ 1488c2ecf20Sopenharmony_ci#define DWC_CTLL_INT_EN (1 << 0) /* irqs enabled? */ 1498c2ecf20Sopenharmony_ci#define DWC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */ 1508c2ecf20Sopenharmony_ci#define DWC_CTLL_SRC_WIDTH(n) ((n)<<4) 1518c2ecf20Sopenharmony_ci#define DWC_CTLL_DST_INC (0<<7) /* DAR update/not */ 1528c2ecf20Sopenharmony_ci#define DWC_CTLL_DST_DEC (1<<7) 1538c2ecf20Sopenharmony_ci#define DWC_CTLL_DST_FIX (2<<7) 1548c2ecf20Sopenharmony_ci#define DWC_CTLL_SRC_INC (0<<9) /* SAR update/not */ 1558c2ecf20Sopenharmony_ci#define DWC_CTLL_SRC_DEC (1<<9) 1568c2ecf20Sopenharmony_ci#define DWC_CTLL_SRC_FIX (2<<9) 1578c2ecf20Sopenharmony_ci#define DWC_CTLL_DST_MSIZE(n) ((n)<<11) /* burst, #elements */ 1588c2ecf20Sopenharmony_ci#define DWC_CTLL_SRC_MSIZE(n) ((n)<<14) 1598c2ecf20Sopenharmony_ci#define DWC_CTLL_S_GATH_EN (1 << 17) /* src gather, !FIX */ 1608c2ecf20Sopenharmony_ci#define DWC_CTLL_D_SCAT_EN (1 << 18) /* dst scatter, !FIX */ 1618c2ecf20Sopenharmony_ci#define DWC_CTLL_FC(n) ((n) << 20) 1628c2ecf20Sopenharmony_ci#define DWC_CTLL_FC_M2M (0 << 20) /* mem-to-mem */ 1638c2ecf20Sopenharmony_ci#define DWC_CTLL_FC_M2P (1 << 20) /* mem-to-periph */ 1648c2ecf20Sopenharmony_ci#define DWC_CTLL_FC_P2M (2 << 20) /* periph-to-mem */ 1658c2ecf20Sopenharmony_ci#define DWC_CTLL_FC_P2P (3 << 20) /* periph-to-periph */ 1668c2ecf20Sopenharmony_ci/* plus 4 transfer types for peripheral-as-flow-controller */ 1678c2ecf20Sopenharmony_ci#define DWC_CTLL_DMS(n) ((n)<<23) /* dst master select */ 1688c2ecf20Sopenharmony_ci#define DWC_CTLL_SMS(n) ((n)<<25) /* src master select */ 1698c2ecf20Sopenharmony_ci#define DWC_CTLL_LLP_D_EN (1 << 27) /* dest block chain */ 1708c2ecf20Sopenharmony_ci#define DWC_CTLL_LLP_S_EN (1 << 28) /* src block chain */ 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci/* Bitfields in CTL_HI */ 1738c2ecf20Sopenharmony_ci#define DWC_CTLH_BLOCK_TS_MASK GENMASK(11, 0) 1748c2ecf20Sopenharmony_ci#define DWC_CTLH_BLOCK_TS(x) ((x) & DWC_CTLH_BLOCK_TS_MASK) 1758c2ecf20Sopenharmony_ci#define DWC_CTLH_DONE (1 << 12) 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci/* Bitfields in CFG_LO */ 1788c2ecf20Sopenharmony_ci#define DWC_CFGL_CH_PRIOR_MASK (0x7 << 5) /* priority mask */ 1798c2ecf20Sopenharmony_ci#define DWC_CFGL_CH_PRIOR(x) ((x) << 5) /* priority */ 1808c2ecf20Sopenharmony_ci#define DWC_CFGL_CH_SUSP (1 << 8) /* pause xfer */ 1818c2ecf20Sopenharmony_ci#define DWC_CFGL_FIFO_EMPTY (1 << 9) /* pause xfer */ 1828c2ecf20Sopenharmony_ci#define DWC_CFGL_HS_DST (1 << 10) /* handshake w/dst */ 1838c2ecf20Sopenharmony_ci#define DWC_CFGL_HS_SRC (1 << 11) /* handshake w/src */ 1848c2ecf20Sopenharmony_ci#define DWC_CFGL_LOCK_CH_XFER (0 << 12) /* scope of LOCK_CH */ 1858c2ecf20Sopenharmony_ci#define DWC_CFGL_LOCK_CH_BLOCK (1 << 12) 1868c2ecf20Sopenharmony_ci#define DWC_CFGL_LOCK_CH_XACT (2 << 12) 1878c2ecf20Sopenharmony_ci#define DWC_CFGL_LOCK_BUS_XFER (0 << 14) /* scope of LOCK_BUS */ 1888c2ecf20Sopenharmony_ci#define DWC_CFGL_LOCK_BUS_BLOCK (1 << 14) 1898c2ecf20Sopenharmony_ci#define DWC_CFGL_LOCK_BUS_XACT (2 << 14) 1908c2ecf20Sopenharmony_ci#define DWC_CFGL_LOCK_CH (1 << 15) /* channel lockout */ 1918c2ecf20Sopenharmony_ci#define DWC_CFGL_LOCK_BUS (1 << 16) /* busmaster lockout */ 1928c2ecf20Sopenharmony_ci#define DWC_CFGL_HS_DST_POL (1 << 18) /* dst handshake active low */ 1938c2ecf20Sopenharmony_ci#define DWC_CFGL_HS_SRC_POL (1 << 19) /* src handshake active low */ 1948c2ecf20Sopenharmony_ci#define DWC_CFGL_MAX_BURST(x) ((x) << 20) 1958c2ecf20Sopenharmony_ci#define DWC_CFGL_RELOAD_SAR (1 << 30) 1968c2ecf20Sopenharmony_ci#define DWC_CFGL_RELOAD_DAR (1 << 31) 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci/* Bitfields in CFG_HI */ 1998c2ecf20Sopenharmony_ci#define DWC_CFGH_FCMODE (1 << 0) 2008c2ecf20Sopenharmony_ci#define DWC_CFGH_FIFO_MODE (1 << 1) 2018c2ecf20Sopenharmony_ci#define DWC_CFGH_PROTCTL(x) ((x) << 2) 2028c2ecf20Sopenharmony_ci#define DWC_CFGH_PROTCTL_DATA (0 << 2) /* data access - always set */ 2038c2ecf20Sopenharmony_ci#define DWC_CFGH_PROTCTL_PRIV (1 << 2) /* privileged -> AHB HPROT[1] */ 2048c2ecf20Sopenharmony_ci#define DWC_CFGH_PROTCTL_BUFFER (2 << 2) /* bufferable -> AHB HPROT[2] */ 2058c2ecf20Sopenharmony_ci#define DWC_CFGH_PROTCTL_CACHE (4 << 2) /* cacheable -> AHB HPROT[3] */ 2068c2ecf20Sopenharmony_ci#define DWC_CFGH_DS_UPD_EN (1 << 5) 2078c2ecf20Sopenharmony_ci#define DWC_CFGH_SS_UPD_EN (1 << 6) 2088c2ecf20Sopenharmony_ci#define DWC_CFGH_SRC_PER(x) ((x) << 7) 2098c2ecf20Sopenharmony_ci#define DWC_CFGH_DST_PER(x) ((x) << 11) 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci/* Bitfields in SGR */ 2128c2ecf20Sopenharmony_ci#define DWC_SGR_SGI(x) ((x) << 0) 2138c2ecf20Sopenharmony_ci#define DWC_SGR_SGC(x) ((x) << 20) 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci/* Bitfields in DSR */ 2168c2ecf20Sopenharmony_ci#define DWC_DSR_DSI(x) ((x) << 0) 2178c2ecf20Sopenharmony_ci#define DWC_DSR_DSC(x) ((x) << 20) 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci/* Bitfields in CFG */ 2208c2ecf20Sopenharmony_ci#define DW_CFG_DMA_EN (1 << 0) 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci/* iDMA 32-bit support */ 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci/* bursts size */ 2258c2ecf20Sopenharmony_cienum idma32_msize { 2268c2ecf20Sopenharmony_ci IDMA32_MSIZE_1, 2278c2ecf20Sopenharmony_ci IDMA32_MSIZE_2, 2288c2ecf20Sopenharmony_ci IDMA32_MSIZE_4, 2298c2ecf20Sopenharmony_ci IDMA32_MSIZE_8, 2308c2ecf20Sopenharmony_ci IDMA32_MSIZE_16, 2318c2ecf20Sopenharmony_ci IDMA32_MSIZE_32, 2328c2ecf20Sopenharmony_ci}; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci/* Bitfields in CTL_HI */ 2358c2ecf20Sopenharmony_ci#define IDMA32C_CTLH_BLOCK_TS_MASK GENMASK(16, 0) 2368c2ecf20Sopenharmony_ci#define IDMA32C_CTLH_BLOCK_TS(x) ((x) & IDMA32C_CTLH_BLOCK_TS_MASK) 2378c2ecf20Sopenharmony_ci#define IDMA32C_CTLH_DONE (1 << 17) 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci/* Bitfields in CFG_LO */ 2408c2ecf20Sopenharmony_ci#define IDMA32C_CFGL_DST_BURST_ALIGN (1 << 0) /* dst burst align */ 2418c2ecf20Sopenharmony_ci#define IDMA32C_CFGL_SRC_BURST_ALIGN (1 << 1) /* src burst align */ 2428c2ecf20Sopenharmony_ci#define IDMA32C_CFGL_CH_DRAIN (1 << 10) /* drain FIFO */ 2438c2ecf20Sopenharmony_ci#define IDMA32C_CFGL_DST_OPT_BL (1 << 20) /* optimize dst burst length */ 2448c2ecf20Sopenharmony_ci#define IDMA32C_CFGL_SRC_OPT_BL (1 << 21) /* optimize src burst length */ 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci/* Bitfields in CFG_HI */ 2478c2ecf20Sopenharmony_ci#define IDMA32C_CFGH_SRC_PER(x) ((x) << 0) 2488c2ecf20Sopenharmony_ci#define IDMA32C_CFGH_DST_PER(x) ((x) << 4) 2498c2ecf20Sopenharmony_ci#define IDMA32C_CFGH_RD_ISSUE_THD(x) ((x) << 8) 2508c2ecf20Sopenharmony_ci#define IDMA32C_CFGH_RW_ISSUE_THD(x) ((x) << 18) 2518c2ecf20Sopenharmony_ci#define IDMA32C_CFGH_SRC_PER_EXT(x) ((x) << 28) /* src peripheral extension */ 2528c2ecf20Sopenharmony_ci#define IDMA32C_CFGH_DST_PER_EXT(x) ((x) << 30) /* dst peripheral extension */ 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci/* Bitfields in FIFO_PARTITION */ 2558c2ecf20Sopenharmony_ci#define IDMA32C_FP_PSIZE_CH0(x) ((x) << 0) 2568c2ecf20Sopenharmony_ci#define IDMA32C_FP_PSIZE_CH1(x) ((x) << 13) 2578c2ecf20Sopenharmony_ci#define IDMA32C_FP_UPDATE (1 << 26) 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_cienum dw_dmac_flags { 2608c2ecf20Sopenharmony_ci DW_DMA_IS_CYCLIC = 0, 2618c2ecf20Sopenharmony_ci DW_DMA_IS_SOFT_LLP = 1, 2628c2ecf20Sopenharmony_ci DW_DMA_IS_PAUSED = 2, 2638c2ecf20Sopenharmony_ci DW_DMA_IS_INITIALIZED = 3, 2648c2ecf20Sopenharmony_ci}; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistruct dw_dma_chan { 2678c2ecf20Sopenharmony_ci struct dma_chan chan; 2688c2ecf20Sopenharmony_ci void __iomem *ch_regs; 2698c2ecf20Sopenharmony_ci u8 mask; 2708c2ecf20Sopenharmony_ci u8 priority; 2718c2ecf20Sopenharmony_ci enum dma_transfer_direction direction; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* software emulation of the LLP transfers */ 2748c2ecf20Sopenharmony_ci struct list_head *tx_node_active; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci spinlock_t lock; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci /* these other elements are all protected by lock */ 2798c2ecf20Sopenharmony_ci unsigned long flags; 2808c2ecf20Sopenharmony_ci struct list_head active_list; 2818c2ecf20Sopenharmony_ci struct list_head queue; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci unsigned int descs_allocated; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci /* hardware configuration */ 2868c2ecf20Sopenharmony_ci unsigned int block_size; 2878c2ecf20Sopenharmony_ci bool nollp; 2888c2ecf20Sopenharmony_ci u32 max_burst; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci /* custom slave configuration */ 2918c2ecf20Sopenharmony_ci struct dw_dma_slave dws; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* configuration passed via .device_config */ 2948c2ecf20Sopenharmony_ci struct dma_slave_config dma_sconfig; 2958c2ecf20Sopenharmony_ci}; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic inline struct dw_dma_chan_regs __iomem * 2988c2ecf20Sopenharmony_ci__dwc_regs(struct dw_dma_chan *dwc) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci return dwc->ch_regs; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci#define channel_readl(dwc, name) \ 3048c2ecf20Sopenharmony_ci readl(&(__dwc_regs(dwc)->name)) 3058c2ecf20Sopenharmony_ci#define channel_writel(dwc, name, val) \ 3068c2ecf20Sopenharmony_ci writel((val), &(__dwc_regs(dwc)->name)) 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci return container_of(chan, struct dw_dma_chan, chan); 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistruct dw_dma { 3148c2ecf20Sopenharmony_ci struct dma_device dma; 3158c2ecf20Sopenharmony_ci char name[20]; 3168c2ecf20Sopenharmony_ci void __iomem *regs; 3178c2ecf20Sopenharmony_ci struct dma_pool *desc_pool; 3188c2ecf20Sopenharmony_ci struct tasklet_struct tasklet; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci /* channels */ 3218c2ecf20Sopenharmony_ci struct dw_dma_chan *chan; 3228c2ecf20Sopenharmony_ci u8 all_chan_mask; 3238c2ecf20Sopenharmony_ci u8 in_use; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* Channel operations */ 3268c2ecf20Sopenharmony_ci void (*initialize_chan)(struct dw_dma_chan *dwc); 3278c2ecf20Sopenharmony_ci void (*suspend_chan)(struct dw_dma_chan *dwc, bool drain); 3288c2ecf20Sopenharmony_ci void (*resume_chan)(struct dw_dma_chan *dwc, bool drain); 3298c2ecf20Sopenharmony_ci u32 (*prepare_ctllo)(struct dw_dma_chan *dwc); 3308c2ecf20Sopenharmony_ci void (*encode_maxburst)(struct dw_dma_chan *dwc, u32 *maxburst); 3318c2ecf20Sopenharmony_ci u32 (*bytes2block)(struct dw_dma_chan *dwc, size_t bytes, 3328c2ecf20Sopenharmony_ci unsigned int width, size_t *len); 3338c2ecf20Sopenharmony_ci size_t (*block2bytes)(struct dw_dma_chan *dwc, u32 block, u32 width); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* Device operations */ 3368c2ecf20Sopenharmony_ci void (*set_device_name)(struct dw_dma *dw, int id); 3378c2ecf20Sopenharmony_ci void (*disable)(struct dw_dma *dw); 3388c2ecf20Sopenharmony_ci void (*enable)(struct dw_dma *dw); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci /* platform data */ 3418c2ecf20Sopenharmony_ci struct dw_dma_platform_data *pdata; 3428c2ecf20Sopenharmony_ci}; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci return dw->regs; 3478c2ecf20Sopenharmony_ci} 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci#define dma_readl(dw, name) \ 3508c2ecf20Sopenharmony_ci readl(&(__dw_regs(dw)->name)) 3518c2ecf20Sopenharmony_ci#define dma_writel(dw, name, val) \ 3528c2ecf20Sopenharmony_ci writel((val), &(__dw_regs(dw)->name)) 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci#define idma32_readq(dw, name) \ 3558c2ecf20Sopenharmony_ci hi_lo_readq(&(__dw_regs(dw)->name)) 3568c2ecf20Sopenharmony_ci#define idma32_writeq(dw, name, val) \ 3578c2ecf20Sopenharmony_ci hi_lo_writeq((val), &(__dw_regs(dw)->name)) 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci#define channel_set_bit(dw, reg, mask) \ 3608c2ecf20Sopenharmony_ci dma_writel(dw, reg, ((mask) << 8) | (mask)) 3618c2ecf20Sopenharmony_ci#define channel_clear_bit(dw, reg, mask) \ 3628c2ecf20Sopenharmony_ci dma_writel(dw, reg, ((mask) << 8) | 0) 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic inline struct dw_dma *to_dw_dma(struct dma_device *ddev) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci return container_of(ddev, struct dw_dma, dma); 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci/* LLI == Linked List Item; a.k.a. DMA block descriptor */ 3708c2ecf20Sopenharmony_cistruct dw_lli { 3718c2ecf20Sopenharmony_ci /* values that are not changed by hardware */ 3728c2ecf20Sopenharmony_ci __le32 sar; 3738c2ecf20Sopenharmony_ci __le32 dar; 3748c2ecf20Sopenharmony_ci __le32 llp; /* chain to next lli */ 3758c2ecf20Sopenharmony_ci __le32 ctllo; 3768c2ecf20Sopenharmony_ci /* values that may get written back: */ 3778c2ecf20Sopenharmony_ci __le32 ctlhi; 3788c2ecf20Sopenharmony_ci /* sstat and dstat can snapshot peripheral register state. 3798c2ecf20Sopenharmony_ci * silicon config may discard either or both... 3808c2ecf20Sopenharmony_ci */ 3818c2ecf20Sopenharmony_ci __le32 sstat; 3828c2ecf20Sopenharmony_ci __le32 dstat; 3838c2ecf20Sopenharmony_ci}; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_cistruct dw_desc { 3868c2ecf20Sopenharmony_ci /* FIRST values the hardware uses */ 3878c2ecf20Sopenharmony_ci struct dw_lli lli; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci#define lli_set(d, reg, v) ((d)->lli.reg |= cpu_to_le32(v)) 3908c2ecf20Sopenharmony_ci#define lli_clear(d, reg, v) ((d)->lli.reg &= ~cpu_to_le32(v)) 3918c2ecf20Sopenharmony_ci#define lli_read(d, reg) le32_to_cpu((d)->lli.reg) 3928c2ecf20Sopenharmony_ci#define lli_write(d, reg, v) ((d)->lli.reg = cpu_to_le32(v)) 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* THEN values for driver housekeeping */ 3958c2ecf20Sopenharmony_ci struct list_head desc_node; 3968c2ecf20Sopenharmony_ci struct list_head tx_list; 3978c2ecf20Sopenharmony_ci struct dma_async_tx_descriptor txd; 3988c2ecf20Sopenharmony_ci size_t len; 3998c2ecf20Sopenharmony_ci size_t total_len; 4008c2ecf20Sopenharmony_ci u32 residue; 4018c2ecf20Sopenharmony_ci}; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci#define to_dw_desc(h) list_entry(h, struct dw_desc, desc_node) 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cistatic inline struct dw_desc * 4068c2ecf20Sopenharmony_citxd_to_dw_desc(struct dma_async_tx_descriptor *txd) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci return container_of(txd, struct dw_desc, txd); 4098c2ecf20Sopenharmony_ci} 410