Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 // (C) 2017-2018 Synopsys, Inc. (www.synopsys.com)
0003 
0004 /*
0005  * Synopsys DesignWare AXI DMA Controller driver.
0006  *
0007  * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
0008  */
0009 
0010 #ifndef _AXI_DMA_PLATFORM_H
0011 #define _AXI_DMA_PLATFORM_H
0012 
0013 #include <linux/bitops.h>
0014 #include <linux/clk.h>
0015 #include <linux/device.h>
0016 #include <linux/dmaengine.h>
0017 #include <linux/types.h>
0018 
0019 #include "../virt-dma.h"
0020 
0021 #define DMAC_MAX_CHANNELS   16
0022 #define DMAC_MAX_MASTERS    2
0023 #define DMAC_MAX_BLK_SIZE   0x200000
0024 
0025 struct dw_axi_dma_hcfg {
0026     u32 nr_channels;
0027     u32 nr_masters;
0028     u32 m_data_width;
0029     u32 block_size[DMAC_MAX_CHANNELS];
0030     u32 priority[DMAC_MAX_CHANNELS];
0031     /* maximum supported axi burst length */
0032     u32 axi_rw_burst_len;
0033     /* Register map for DMAX_NUM_CHANNELS <= 8 */
0034     bool    reg_map_8_channels;
0035     bool    restrict_axi_burst_len;
0036 };
0037 
0038 struct axi_dma_chan {
0039     struct axi_dma_chip     *chip;
0040     void __iomem            *chan_regs;
0041     u8              id;
0042     u8              hw_handshake_num;
0043     atomic_t            descs_allocated;
0044 
0045     struct dma_pool         *desc_pool;
0046     struct virt_dma_chan        vc;
0047 
0048     struct axi_dma_desc     *desc;
0049     struct dma_slave_config     config;
0050     enum dma_transfer_direction direction;
0051     bool                cyclic;
0052     /* these other elements are all protected by vc.lock */
0053     bool                is_paused;
0054 };
0055 
0056 struct dw_axi_dma {
0057     struct dma_device   dma;
0058     struct dw_axi_dma_hcfg  *hdata;
0059     struct device_dma_parameters    dma_parms;
0060 
0061     /* channels */
0062     struct axi_dma_chan *chan;
0063 };
0064 
0065 struct axi_dma_chip {
0066     struct device       *dev;
0067     int         irq;
0068     void __iomem        *regs;
0069     void __iomem        *apb_regs;
0070     struct clk      *core_clk;
0071     struct clk      *cfgr_clk;
0072     struct dw_axi_dma   *dw;
0073 };
0074 
0075 /* LLI == Linked List Item */
0076 struct __packed axi_dma_lli {
0077     __le64      sar;
0078     __le64      dar;
0079     __le32      block_ts_lo;
0080     __le32      block_ts_hi;
0081     __le64      llp;
0082     __le32      ctl_lo;
0083     __le32      ctl_hi;
0084     __le32      sstat;
0085     __le32      dstat;
0086     __le32      status_lo;
0087     __le32      status_hi;
0088     __le32      reserved_lo;
0089     __le32      reserved_hi;
0090 };
0091 
0092 struct axi_dma_hw_desc {
0093     struct axi_dma_lli  *lli;
0094     dma_addr_t      llp;
0095     u32         len;
0096 };
0097 
0098 struct axi_dma_desc {
0099     struct axi_dma_hw_desc  *hw_desc;
0100 
0101     struct virt_dma_desc        vd;
0102     struct axi_dma_chan     *chan;
0103     u32             completed_blocks;
0104     u32             length;
0105     u32             period_len;
0106 };
0107 
0108 struct axi_dma_chan_config {
0109     u8 dst_multblk_type;
0110     u8 src_multblk_type;
0111     u8 dst_per;
0112     u8 src_per;
0113     u8 tt_fc;
0114     u8 prior;
0115     u8 hs_sel_dst;
0116     u8 hs_sel_src;
0117 };
0118 
0119 static inline struct device *dchan2dev(struct dma_chan *dchan)
0120 {
0121     return &dchan->dev->device;
0122 }
0123 
0124 static inline struct device *chan2dev(struct axi_dma_chan *chan)
0125 {
0126     return &chan->vc.chan.dev->device;
0127 }
0128 
0129 static inline struct axi_dma_desc *vd_to_axi_desc(struct virt_dma_desc *vd)
0130 {
0131     return container_of(vd, struct axi_dma_desc, vd);
0132 }
0133 
0134 static inline struct axi_dma_chan *vc_to_axi_dma_chan(struct virt_dma_chan *vc)
0135 {
0136     return container_of(vc, struct axi_dma_chan, vc);
0137 }
0138 
0139 static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
0140 {
0141     return vc_to_axi_dma_chan(to_virt_chan(dchan));
0142 }
0143 
0144 
0145 #define COMMON_REG_LEN      0x100
0146 #define CHAN_REG_LEN        0x100
0147 
0148 /* Common registers offset */
0149 #define DMAC_ID         0x000 /* R DMAC ID */
0150 #define DMAC_COMPVER        0x008 /* R DMAC Component Version */
0151 #define DMAC_CFG        0x010 /* R/W DMAC Configuration */
0152 #define DMAC_CHEN       0x018 /* R/W DMAC Channel Enable */
0153 #define DMAC_CHEN_L     0x018 /* R/W DMAC Channel Enable 00-31 */
0154 #define DMAC_CHEN_H     0x01C /* R/W DMAC Channel Enable 32-63 */
0155 #define DMAC_CHSUSPREG      0x020 /* R/W DMAC Channel Suspend */
0156 #define DMAC_CHABORTREG     0x028 /* R/W DMAC Channel Abort */
0157 #define DMAC_INTSTATUS      0x030 /* R DMAC Interrupt Status */
0158 #define DMAC_COMMON_INTCLEAR    0x038 /* W DMAC Interrupt Clear */
0159 #define DMAC_COMMON_INTSTATUS_ENA 0x040 /* R DMAC Interrupt Status Enable */
0160 #define DMAC_COMMON_INTSIGNAL_ENA 0x048 /* R/W DMAC Interrupt Signal Enable */
0161 #define DMAC_COMMON_INTSTATUS   0x050 /* R DMAC Interrupt Status */
0162 #define DMAC_RESET      0x058 /* R DMAC Reset Register1 */
0163 
0164 /* DMA channel registers offset */
0165 #define CH_SAR          0x000 /* R/W Chan Source Address */
0166 #define CH_DAR          0x008 /* R/W Chan Destination Address */
0167 #define CH_BLOCK_TS     0x010 /* R/W Chan Block Transfer Size */
0168 #define CH_CTL          0x018 /* R/W Chan Control */
0169 #define CH_CTL_L        0x018 /* R/W Chan Control 00-31 */
0170 #define CH_CTL_H        0x01C /* R/W Chan Control 32-63 */
0171 #define CH_CFG          0x020 /* R/W Chan Configuration */
0172 #define CH_CFG_L        0x020 /* R/W Chan Configuration 00-31 */
0173 #define CH_CFG_H        0x024 /* R/W Chan Configuration 32-63 */
0174 #define CH_LLP          0x028 /* R/W Chan Linked List Pointer */
0175 #define CH_STATUS       0x030 /* R Chan Status */
0176 #define CH_SWHSSRC      0x038 /* R/W Chan SW Handshake Source */
0177 #define CH_SWHSDST      0x040 /* R/W Chan SW Handshake Destination */
0178 #define CH_BLK_TFR_RESUMEREQ    0x048 /* W Chan Block Transfer Resume Req */
0179 #define CH_AXI_ID       0x050 /* R/W Chan AXI ID */
0180 #define CH_AXI_QOS      0x058 /* R/W Chan AXI QOS */
0181 #define CH_SSTAT        0x060 /* R Chan Source Status */
0182 #define CH_DSTAT        0x068 /* R Chan Destination Status */
0183 #define CH_SSTATAR      0x070 /* R/W Chan Source Status Fetch Addr */
0184 #define CH_DSTATAR      0x078 /* R/W Chan Destination Status Fetch Addr */
0185 #define CH_INTSTATUS_ENA    0x080 /* R/W Chan Interrupt Status Enable */
0186 #define CH_INTSTATUS        0x088 /* R/W Chan Interrupt Status */
0187 #define CH_INTSIGNAL_ENA    0x090 /* R/W Chan Interrupt Signal Enable */
0188 #define CH_INTCLEAR     0x098 /* W Chan Interrupt Clear */
0189 
0190 /* These Apb registers are used by Intel KeemBay SoC */
0191 #define DMAC_APB_CFG        0x000 /* DMAC Apb Configuration Register */
0192 #define DMAC_APB_STAT       0x004 /* DMAC Apb Status Register */
0193 #define DMAC_APB_DEBUG_STAT_0   0x008 /* DMAC Apb Debug Status Register 0 */
0194 #define DMAC_APB_DEBUG_STAT_1   0x00C /* DMAC Apb Debug Status Register 1 */
0195 #define DMAC_APB_HW_HS_SEL_0    0x010 /* DMAC Apb HW HS register 0 */
0196 #define DMAC_APB_HW_HS_SEL_1    0x014 /* DMAC Apb HW HS register 1 */
0197 #define DMAC_APB_LPI        0x018 /* DMAC Apb Low Power Interface Reg */
0198 #define DMAC_APB_BYTE_WR_CH_EN  0x01C /* DMAC Apb Byte Write Enable */
0199 #define DMAC_APB_HALFWORD_WR_CH_EN  0x020 /* DMAC Halfword write enables */
0200 
0201 #define UNUSED_CHANNEL      0x3F /* Set unused DMA channel to 0x3F */
0202 #define DMA_APB_HS_SEL_BIT_SIZE 0x08 /* HW handshake bits per channel */
0203 #define DMA_APB_HS_SEL_MASK 0xFF /* HW handshake select masks */
0204 #define MAX_BLOCK_SIZE      0x1000 /* 1024 blocks * 4 bytes data width */
0205 #define DMA_REG_MAP_CH_REF  0x08 /* Channel count to choose register map */
0206 
0207 /* DMAC_CFG */
0208 #define DMAC_EN_POS         0
0209 #define DMAC_EN_MASK            BIT(DMAC_EN_POS)
0210 
0211 #define INT_EN_POS          1
0212 #define INT_EN_MASK         BIT(INT_EN_POS)
0213 
0214 /* DMAC_CHEN */
0215 #define DMAC_CHAN_EN_SHIFT      0
0216 #define DMAC_CHAN_EN_WE_SHIFT       8
0217 
0218 #define DMAC_CHAN_SUSP_SHIFT        16
0219 #define DMAC_CHAN_SUSP_WE_SHIFT     24
0220 
0221 /* DMAC_CHEN2 */
0222 #define DMAC_CHAN_EN2_WE_SHIFT      16
0223 
0224 /* DMAC_CHSUSP */
0225 #define DMAC_CHAN_SUSP2_SHIFT       0
0226 #define DMAC_CHAN_SUSP2_WE_SHIFT    16
0227 
0228 /* CH_CTL_H */
0229 #define CH_CTL_H_ARLEN_EN       BIT(6)
0230 #define CH_CTL_H_ARLEN_POS      7
0231 #define CH_CTL_H_AWLEN_EN       BIT(15)
0232 #define CH_CTL_H_AWLEN_POS      16
0233 
0234 enum {
0235     DWAXIDMAC_ARWLEN_1      = 0,
0236     DWAXIDMAC_ARWLEN_2      = 1,
0237     DWAXIDMAC_ARWLEN_4      = 3,
0238     DWAXIDMAC_ARWLEN_8      = 7,
0239     DWAXIDMAC_ARWLEN_16     = 15,
0240     DWAXIDMAC_ARWLEN_32     = 31,
0241     DWAXIDMAC_ARWLEN_64     = 63,
0242     DWAXIDMAC_ARWLEN_128        = 127,
0243     DWAXIDMAC_ARWLEN_256        = 255,
0244     DWAXIDMAC_ARWLEN_MIN        = DWAXIDMAC_ARWLEN_1,
0245     DWAXIDMAC_ARWLEN_MAX        = DWAXIDMAC_ARWLEN_256
0246 };
0247 
0248 #define CH_CTL_H_LLI_LAST       BIT(30)
0249 #define CH_CTL_H_LLI_VALID      BIT(31)
0250 
0251 /* CH_CTL_L */
0252 #define CH_CTL_L_LAST_WRITE_EN      BIT(30)
0253 
0254 #define CH_CTL_L_DST_MSIZE_POS      18
0255 #define CH_CTL_L_SRC_MSIZE_POS      14
0256 
0257 enum {
0258     DWAXIDMAC_BURST_TRANS_LEN_1 = 0,
0259     DWAXIDMAC_BURST_TRANS_LEN_4,
0260     DWAXIDMAC_BURST_TRANS_LEN_8,
0261     DWAXIDMAC_BURST_TRANS_LEN_16,
0262     DWAXIDMAC_BURST_TRANS_LEN_32,
0263     DWAXIDMAC_BURST_TRANS_LEN_64,
0264     DWAXIDMAC_BURST_TRANS_LEN_128,
0265     DWAXIDMAC_BURST_TRANS_LEN_256,
0266     DWAXIDMAC_BURST_TRANS_LEN_512,
0267     DWAXIDMAC_BURST_TRANS_LEN_1024
0268 };
0269 
0270 #define CH_CTL_L_DST_WIDTH_POS      11
0271 #define CH_CTL_L_SRC_WIDTH_POS      8
0272 
0273 #define CH_CTL_L_DST_INC_POS        6
0274 #define CH_CTL_L_SRC_INC_POS        4
0275 enum {
0276     DWAXIDMAC_CH_CTL_L_INC      = 0,
0277     DWAXIDMAC_CH_CTL_L_NOINC
0278 };
0279 
0280 #define CH_CTL_L_DST_MAST       BIT(2)
0281 #define CH_CTL_L_SRC_MAST       BIT(0)
0282 
0283 /* CH_CFG_H */
0284 #define CH_CFG_H_PRIORITY_POS       17
0285 #define CH_CFG_H_DST_PER_POS        12
0286 #define CH_CFG_H_SRC_PER_POS        7
0287 #define CH_CFG_H_HS_SEL_DST_POS     4
0288 #define CH_CFG_H_HS_SEL_SRC_POS     3
0289 enum {
0290     DWAXIDMAC_HS_SEL_HW     = 0,
0291     DWAXIDMAC_HS_SEL_SW
0292 };
0293 
0294 #define CH_CFG_H_TT_FC_POS      0
0295 enum {
0296     DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC = 0,
0297     DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC,
0298     DWAXIDMAC_TT_FC_PER_TO_MEM_DMAC,
0299     DWAXIDMAC_TT_FC_PER_TO_PER_DMAC,
0300     DWAXIDMAC_TT_FC_PER_TO_MEM_SRC,
0301     DWAXIDMAC_TT_FC_PER_TO_PER_SRC,
0302     DWAXIDMAC_TT_FC_MEM_TO_PER_DST,
0303     DWAXIDMAC_TT_FC_PER_TO_PER_DST
0304 };
0305 
0306 /* CH_CFG_L */
0307 #define CH_CFG_L_DST_MULTBLK_TYPE_POS   2
0308 #define CH_CFG_L_SRC_MULTBLK_TYPE_POS   0
0309 enum {
0310     DWAXIDMAC_MBLK_TYPE_CONTIGUOUS  = 0,
0311     DWAXIDMAC_MBLK_TYPE_RELOAD,
0312     DWAXIDMAC_MBLK_TYPE_SHADOW_REG,
0313     DWAXIDMAC_MBLK_TYPE_LL
0314 };
0315 
0316 /* CH_CFG2 */
0317 #define CH_CFG2_L_SRC_PER_POS       4
0318 #define CH_CFG2_L_DST_PER_POS       11
0319 
0320 #define CH_CFG2_H_TT_FC_POS     0
0321 #define CH_CFG2_H_HS_SEL_SRC_POS    3
0322 #define CH_CFG2_H_HS_SEL_DST_POS    4
0323 #define CH_CFG2_H_PRIORITY_POS      20
0324 
0325 /**
0326  * DW AXI DMA channel interrupts
0327  *
0328  * @DWAXIDMAC_IRQ_NONE: Bitmask of no one interrupt
0329  * @DWAXIDMAC_IRQ_BLOCK_TRF: Block transfer complete
0330  * @DWAXIDMAC_IRQ_DMA_TRF: Dma transfer complete
0331  * @DWAXIDMAC_IRQ_SRC_TRAN: Source transaction complete
0332  * @DWAXIDMAC_IRQ_DST_TRAN: Destination transaction complete
0333  * @DWAXIDMAC_IRQ_SRC_DEC_ERR: Source decode error
0334  * @DWAXIDMAC_IRQ_DST_DEC_ERR: Destination decode error
0335  * @DWAXIDMAC_IRQ_SRC_SLV_ERR: Source slave error
0336  * @DWAXIDMAC_IRQ_DST_SLV_ERR: Destination slave error
0337  * @DWAXIDMAC_IRQ_LLI_RD_DEC_ERR: LLI read decode error
0338  * @DWAXIDMAC_IRQ_LLI_WR_DEC_ERR: LLI write decode error
0339  * @DWAXIDMAC_IRQ_LLI_RD_SLV_ERR: LLI read slave error
0340  * @DWAXIDMAC_IRQ_LLI_WR_SLV_ERR: LLI write slave error
0341  * @DWAXIDMAC_IRQ_INVALID_ERR: LLI invalid error or Shadow register error
0342  * @DWAXIDMAC_IRQ_MULTIBLKTYPE_ERR: Slave Interface Multiblock type error
0343  * @DWAXIDMAC_IRQ_DEC_ERR: Slave Interface decode error
0344  * @DWAXIDMAC_IRQ_WR2RO_ERR: Slave Interface write to read only error
0345  * @DWAXIDMAC_IRQ_RD2RWO_ERR: Slave Interface read to write only error
0346  * @DWAXIDMAC_IRQ_WRONCHEN_ERR: Slave Interface write to channel error
0347  * @DWAXIDMAC_IRQ_SHADOWREG_ERR: Slave Interface shadow reg error
0348  * @DWAXIDMAC_IRQ_WRONHOLD_ERR: Slave Interface hold error
0349  * @DWAXIDMAC_IRQ_LOCK_CLEARED: Lock Cleared Status
0350  * @DWAXIDMAC_IRQ_SRC_SUSPENDED: Source Suspended Status
0351  * @DWAXIDMAC_IRQ_SUSPENDED: Channel Suspended Status
0352  * @DWAXIDMAC_IRQ_DISABLED: Channel Disabled Status
0353  * @DWAXIDMAC_IRQ_ABORTED: Channel Aborted Status
0354  * @DWAXIDMAC_IRQ_ALL_ERR: Bitmask of all error interrupts
0355  * @DWAXIDMAC_IRQ_ALL: Bitmask of all interrupts
0356  */
0357 enum {
0358     DWAXIDMAC_IRQ_NONE      = 0,
0359     DWAXIDMAC_IRQ_BLOCK_TRF     = BIT(0),
0360     DWAXIDMAC_IRQ_DMA_TRF       = BIT(1),
0361     DWAXIDMAC_IRQ_SRC_TRAN      = BIT(3),
0362     DWAXIDMAC_IRQ_DST_TRAN      = BIT(4),
0363     DWAXIDMAC_IRQ_SRC_DEC_ERR   = BIT(5),
0364     DWAXIDMAC_IRQ_DST_DEC_ERR   = BIT(6),
0365     DWAXIDMAC_IRQ_SRC_SLV_ERR   = BIT(7),
0366     DWAXIDMAC_IRQ_DST_SLV_ERR   = BIT(8),
0367     DWAXIDMAC_IRQ_LLI_RD_DEC_ERR    = BIT(9),
0368     DWAXIDMAC_IRQ_LLI_WR_DEC_ERR    = BIT(10),
0369     DWAXIDMAC_IRQ_LLI_RD_SLV_ERR    = BIT(11),
0370     DWAXIDMAC_IRQ_LLI_WR_SLV_ERR    = BIT(12),
0371     DWAXIDMAC_IRQ_INVALID_ERR   = BIT(13),
0372     DWAXIDMAC_IRQ_MULTIBLKTYPE_ERR  = BIT(14),
0373     DWAXIDMAC_IRQ_DEC_ERR       = BIT(16),
0374     DWAXIDMAC_IRQ_WR2RO_ERR     = BIT(17),
0375     DWAXIDMAC_IRQ_RD2RWO_ERR    = BIT(18),
0376     DWAXIDMAC_IRQ_WRONCHEN_ERR  = BIT(19),
0377     DWAXIDMAC_IRQ_SHADOWREG_ERR = BIT(20),
0378     DWAXIDMAC_IRQ_WRONHOLD_ERR  = BIT(21),
0379     DWAXIDMAC_IRQ_LOCK_CLEARED  = BIT(27),
0380     DWAXIDMAC_IRQ_SRC_SUSPENDED = BIT(28),
0381     DWAXIDMAC_IRQ_SUSPENDED     = BIT(29),
0382     DWAXIDMAC_IRQ_DISABLED      = BIT(30),
0383     DWAXIDMAC_IRQ_ABORTED       = BIT(31),
0384     DWAXIDMAC_IRQ_ALL_ERR       = (GENMASK(21, 16) | GENMASK(14, 5)),
0385     DWAXIDMAC_IRQ_ALL       = GENMASK(31, 0)
0386 };
0387 
0388 enum {
0389     DWAXIDMAC_TRANS_WIDTH_8     = 0,
0390     DWAXIDMAC_TRANS_WIDTH_16,
0391     DWAXIDMAC_TRANS_WIDTH_32,
0392     DWAXIDMAC_TRANS_WIDTH_64,
0393     DWAXIDMAC_TRANS_WIDTH_128,
0394     DWAXIDMAC_TRANS_WIDTH_256,
0395     DWAXIDMAC_TRANS_WIDTH_512,
0396     DWAXIDMAC_TRANS_WIDTH_MAX   = DWAXIDMAC_TRANS_WIDTH_512
0397 };
0398 
0399 #endif /* _AXI_DMA_PLATFORM_H */