Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * DMA driver header for STMicroelectronics STi FDMA controller * * Copyright (C) 2014 STMicroelectronics * * Author: Ludovic Barre <Ludovic.barre@st.com> */ #ifndef __DMA_ST_FDMA_H #define __DMA_ST_FDMA_H #include <linux/dmaengine.h> #include <linux/dmapool.h> #include <linux/io.h> #include <linux/remoteproc/st_slim_rproc.h> #include "virt-dma.h" #define ST_FDMA_NR_DREQS 32 #define FW_NAME_SIZE 30 #define DRIVER_NAME "st-fdma" /** * struct st_fdma_generic_node - Free running/paced generic node * * @length: Length in bytes of a line in a 2D mem to mem * @sstride: Stride, in bytes, between source lines in a 2D data move * @dstride: Stride, in bytes, between destination lines in a 2D data move */ struct st_fdma_generic_node { u32 length; u32 sstride; u32 dstride; }; /** * struct st_fdma_hw_node - Node structure used by fdma hw * * @next: Pointer to next node * @control: Transfer Control Parameters * @nbytes: Number of Bytes to read * @saddr: Source address * @daddr: Destination address * * @generic: generic node for free running/paced transfert type * 2 others transfert type are possible, but not yet implemented * * The NODE structures must be aligned to a 32 byte boundary */ struct st_fdma_hw_node { u32 next; u32 control; u32 nbytes; u32 saddr; u32 daddr; union { struct st_fdma_generic_node generic; }; } __aligned(32); /* * node control parameters */ #define FDMA_NODE_CTRL_REQ_MAP_MASK GENMASK(4, 0) #define FDMA_NODE_CTRL_REQ_MAP_FREE_RUN 0x0 #define FDMA_NODE_CTRL_REQ_MAP_DREQ(n) ((n)&FDMA_NODE_CTRL_REQ_MAP_MASK) #define FDMA_NODE_CTRL_REQ_MAP_EXT FDMA_NODE_CTRL_REQ_MAP_MASK #define FDMA_NODE_CTRL_SRC_MASK GENMASK(6, 5) #define FDMA_NODE_CTRL_SRC_STATIC BIT(5) #define FDMA_NODE_CTRL_SRC_INCR BIT(6) #define FDMA_NODE_CTRL_DST_MASK GENMASK(8, 7) #define FDMA_NODE_CTRL_DST_STATIC BIT(7) #define FDMA_NODE_CTRL_DST_INCR BIT(8) #define FDMA_NODE_CTRL_SECURE BIT(15) #define FDMA_NODE_CTRL_PAUSE_EON BIT(30) #define FDMA_NODE_CTRL_INT_EON BIT(31) /** * struct st_fdma_sw_node - descriptor structure for link list * * @pdesc: Physical address of desc * @node: link used for putting this into a channel queue */ struct st_fdma_sw_node { dma_addr_t pdesc; struct st_fdma_hw_node *desc; }; #define NAME_SZ 10 struct st_fdma_driverdata { u32 id; char name[NAME_SZ]; }; struct st_fdma_desc { struct virt_dma_desc vdesc; struct st_fdma_chan *fchan; bool iscyclic; unsigned int n_nodes; struct st_fdma_sw_node node[]; }; enum st_fdma_type { ST_FDMA_TYPE_FREE_RUN, ST_FDMA_TYPE_PACED, }; struct st_fdma_cfg { struct device_node *of_node; enum st_fdma_type type; dma_addr_t dev_addr; enum dma_transfer_direction dir; int req_line; /* request line */ long req_ctrl; /* Request control */ }; struct st_fdma_chan { struct st_fdma_dev *fdev; struct dma_pool *node_pool; struct dma_slave_config scfg; struct st_fdma_cfg cfg; int dreq_line; struct virt_dma_chan vchan; struct st_fdma_desc *fdesc; enum dma_status status; }; struct st_fdma_dev { struct device *dev; const struct st_fdma_driverdata *drvdata; struct dma_device dma_device; struct st_slim_rproc *slim_rproc; int irq; struct st_fdma_chan *chans; spinlock_t dreq_lock; unsigned long dreq_mask; u32 nr_channels; char fw_name[FW_NAME_SIZE]; }; /* Peripheral Registers*/ #define FDMA_CMD_STA_OFST 0xFC0 #define FDMA_CMD_SET_OFST 0xFC4 #define FDMA_CMD_CLR_OFST 0xFC8 #define FDMA_CMD_MASK_OFST 0xFCC #define FDMA_CMD_START(ch) (0x1 << (ch << 1)) #define FDMA_CMD_PAUSE(ch) (0x2 << (ch << 1)) #define FDMA_CMD_FLUSH(ch) (0x3 << (ch << 1)) #define FDMA_INT_STA_OFST 0xFD0 #define FDMA_INT_STA_CH 0x1 #define FDMA_INT_STA_ERR 0x2 #define FDMA_INT_SET_OFST 0xFD4 #define FDMA_INT_CLR_OFST 0xFD8 #define FDMA_INT_MASK_OFST 0xFDC #define fdma_read(fdev, name) \ readl((fdev)->slim_rproc->peri + name) #define fdma_write(fdev, val, name) \ writel((val), (fdev)->slim_rproc->peri + name) /* fchan interface (dmem) */ #define FDMA_CH_CMD_OFST 0x200 #define FDMA_CH_CMD_STA_MASK GENMASK(1, 0) #define FDMA_CH_CMD_STA_IDLE (0x0) #define FDMA_CH_CMD_STA_START (0x1) #define FDMA_CH_CMD_STA_RUNNING (0x2) #define FDMA_CH_CMD_STA_PAUSED (0x3) #define FDMA_CH_CMD_ERR_MASK GENMASK(4, 2) #define FDMA_CH_CMD_ERR_INT (0x0 << 2) #define FDMA_CH_CMD_ERR_NAND (0x1 << 2) #define FDMA_CH_CMD_ERR_MCHI (0x2 << 2) #define FDMA_CH_CMD_DATA_MASK GENMASK(31, 5) #define fchan_read(fchan, name) \ readl((fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \ + (fchan)->vchan.chan.chan_id * 0x4 \ + name) #define fchan_write(fchan, val, name) \ writel((val), (fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \ + (fchan)->vchan.chan.chan_id * 0x4 \ + name) /* req interface */ #define FDMA_REQ_CTRL_OFST 0x240 #define dreq_write(fchan, val, name) \ writel((val), (fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \ + fchan->dreq_line * 0x04 \ + name) /* node interface */ #define FDMA_NODE_SZ 128 #define FDMA_PTRN_OFST 0x800 #define FDMA_CNTN_OFST 0x808 #define FDMA_SADDRN_OFST 0x80c #define FDMA_DADDRN_OFST 0x810 #define fnode_read(fchan, name) \ readl((fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \ + (fchan)->vchan.chan.chan_id * FDMA_NODE_SZ \ + name) #define fnode_write(fchan, val, name) \ writel((val), (fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \ + (fchan)->vchan.chan.chan_id * FDMA_NODE_SZ \ + name) /* * request control bits */ #define FDMA_REQ_CTRL_NUM_OPS_MASK GENMASK(31, 24) #define FDMA_REQ_CTRL_NUM_OPS(n) (FDMA_REQ_CTRL_NUM_OPS_MASK & \ ((n) << 24)) #define FDMA_REQ_CTRL_INITIATOR_MASK BIT(22) #define FDMA_REQ_CTRL_INIT0 (0x0 << 22) #define FDMA_REQ_CTRL_INIT1 (0x1 << 22) #define FDMA_REQ_CTRL_INC_ADDR_ON BIT(21) #define FDMA_REQ_CTRL_DATA_SWAP_ON BIT(17) #define FDMA_REQ_CTRL_WNR BIT(14) #define FDMA_REQ_CTRL_OPCODE_MASK GENMASK(7, 4) #define FDMA_REQ_CTRL_OPCODE_LD_ST1 (0x0 << 4) #define FDMA_REQ_CTRL_OPCODE_LD_ST2 (0x1 << 4) #define FDMA_REQ_CTRL_OPCODE_LD_ST4 (0x2 << 4) #define FDMA_REQ_CTRL_OPCODE_LD_ST8 (0x3 << 4) #define FDMA_REQ_CTRL_OPCODE_LD_ST16 (0x4 << 4) #define FDMA_REQ_CTRL_OPCODE_LD_ST32 (0x5 << 4) #define FDMA_REQ_CTRL_OPCODE_LD_ST64 (0x6 << 4) #define FDMA_REQ_CTRL_HOLDOFF_MASK GENMASK(2, 0) #define FDMA_REQ_CTRL_HOLDOFF(n) ((n) & FDMA_REQ_CTRL_HOLDOFF_MASK) /* bits used by client to configure request control */ #define FDMA_REQ_CTRL_CFG_MASK (FDMA_REQ_CTRL_HOLDOFF_MASK | \ FDMA_REQ_CTRL_DATA_SWAP_ON | \ FDMA_REQ_CTRL_INC_ADDR_ON | \ FDMA_REQ_CTRL_INITIATOR_MASK) #endif /* __DMA_ST_FDMA_H */ |