1 /* 2 * SiFive Platform DMA emulation 3 * 4 * Copyright (c) 2020 Wind River Systems, Inc. 5 * 6 * Author: 7 * Bin Meng <bin.meng@windriver.com> 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 or 12 * (at your option) version 3 of the License. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, see <http://www.gnu.org/licenses/>. 21 */ 22 23 #include "qemu/osdep.h" 24 #include "qemu/bitops.h" 25 #include "qemu/log.h" 26 #include "qapi/error.h" 27 #include "hw/irq.h" 28 #include "hw/qdev-properties.h" 29 #include "hw/sysbus.h" 30 #include "migration/vmstate.h" 31 #include "sysemu/dma.h" 32 #include "hw/dma/sifive_pdma.h" 33 34 #define DMA_CONTROL 0x000 35 #define CONTROL_CLAIM BIT(0) 36 #define CONTROL_RUN BIT(1) 37 #define CONTROL_DONE_IE BIT(14) 38 #define CONTROL_ERR_IE BIT(15) 39 #define CONTROL_DONE BIT(30) 40 #define CONTROL_ERR BIT(31) 41 42 #define DMA_NEXT_CONFIG 0x004 43 #define CONFIG_REPEAT BIT(2) 44 #define CONFIG_ORDER BIT(3) 45 #define CONFIG_WRSZ_SHIFT 24 46 #define CONFIG_RDSZ_SHIFT 28 47 #define CONFIG_SZ_MASK 0xf 48 49 #define DMA_NEXT_BYTES 0x008 50 #define DMA_NEXT_DST 0x010 51 #define DMA_NEXT_SRC 0x018 52 #define DMA_EXEC_CONFIG 0x104 53 #define DMA_EXEC_BYTES 0x108 54 #define DMA_EXEC_DST 0x110 55 #define DMA_EXEC_SRC 0x118 56 57 /* 58 * FU540/FU740 docs are incorrect with NextConfig.wsize/rsize reset values. 59 * The reset values tested on Unleashed/Unmatched boards are 6 instead of 0. 60 */ 61 #define CONFIG_WRSZ_DEFAULT 6 62 #define CONFIG_RDSZ_DEFAULT 6 63 64 enum dma_chan_state { 65 DMA_CHAN_STATE_IDLE, 66 DMA_CHAN_STATE_STARTED, 67 DMA_CHAN_STATE_ERROR, 68 DMA_CHAN_STATE_DONE 69 }; 70 71 static void sifive_pdma_run(SiFivePDMAState *s, int ch) 72 { 73 uint64_t bytes = s->chan[ch].next_bytes; 74 uint64_t dst = s->chan[ch].next_dst; 75 uint64_t src = s->chan[ch].next_src; 76 uint32_t config = s->chan[ch].next_config; 77 int wsize, rsize, size, remainder; 78 uint8_t buf[64]; 79 int n; 80 81 /* do nothing if bytes to transfer is zero */ 82 if (!bytes) { 83 goto done; 84 } 85 86 /* 87 * The manual does not describe how the hardware behaviors when 88 * config.wsize and config.rsize are given different values. 89 * A common case is memory to memory DMA, and in this case they 90 * are normally the same. Abort if this expectation fails. 91 */ 92 wsize = (config >> CONFIG_WRSZ_SHIFT) & CONFIG_SZ_MASK; 93 rsize = (config >> CONFIG_RDSZ_SHIFT) & CONFIG_SZ_MASK; 94 if (wsize != rsize) { 95 goto error; 96 } 97 98 /* 99 * Calculate the transaction size 100 * 101 * size field is base 2 logarithm of DMA transaction size, 102 * but there is an upper limit of 64 bytes per transaction. 103 */ 104 size = wsize; 105 if (size > 6) { 106 size = 6; 107 } 108 size = 1 << size; 109 remainder = bytes % size; 110 111 /* indicate a DMA transfer is started */ 112 s->chan[ch].state = DMA_CHAN_STATE_STARTED; 113 s->chan[ch].control &= ~CONTROL_DONE; 114 s->chan[ch].control &= ~CONTROL_ERR; 115 116 /* load the next_ registers into their exec_ counterparts */ 117 s->chan[ch].exec_config = config; 118 s->chan[ch].exec_bytes = bytes; 119 s->chan[ch].exec_dst = dst; 120 s->chan[ch].exec_src = src; 121 122 for (n = 0; n < bytes / size; n++) { 123 cpu_physical_memory_read(s->chan[ch].exec_src, buf, size); 124 cpu_physical_memory_write(s->chan[ch].exec_dst, buf, size); 125 s->chan[ch].exec_src += size; 126 s->chan[ch].exec_dst += size; 127 s->chan[ch].exec_bytes -= size; 128 } 129 130 if (remainder) { 131 cpu_physical_memory_read(s->chan[ch].exec_src, buf, remainder); 132 cpu_physical_memory_write(s->chan[ch].exec_dst, buf, remainder); 133 s->chan[ch].exec_src += remainder; 134 s->chan[ch].exec_dst += remainder; 135 s->chan[ch].exec_bytes -= remainder; 136 } 137 138 /* reload exec_ registers if repeat is required */ 139 if (s->chan[ch].next_config & CONFIG_REPEAT) { 140 s->chan[ch].exec_bytes = bytes; 141 s->chan[ch].exec_dst = dst; 142 s->chan[ch].exec_src = src; 143 } 144 145 done: 146 /* indicate a DMA transfer is done */ 147 s->chan[ch].state = DMA_CHAN_STATE_DONE; 148 s->chan[ch].control &= ~CONTROL_RUN; 149 s->chan[ch].control |= CONTROL_DONE; 150 return; 151 152 error: 153 s->chan[ch].state = DMA_CHAN_STATE_ERROR; 154 s->chan[ch].control |= CONTROL_ERR; 155 return; 156 } 157 158 static inline void sifive_pdma_update_irq(SiFivePDMAState *s, int ch) 159 { 160 bool done_ie, err_ie; 161 162 done_ie = !!(s->chan[ch].control & CONTROL_DONE_IE); 163 err_ie = !!(s->chan[ch].control & CONTROL_ERR_IE); 164 165 if (done_ie && (s->chan[ch].control & CONTROL_DONE)) { 166 qemu_irq_raise(s->irq[ch * 2]); 167 } else { 168 qemu_irq_lower(s->irq[ch * 2]); 169 } 170 171 if (err_ie && (s->chan[ch].control & CONTROL_ERR)) { 172 qemu_irq_raise(s->irq[ch * 2 + 1]); 173 } else { 174 qemu_irq_lower(s->irq[ch * 2 + 1]); 175 } 176 177 s->chan[ch].state = DMA_CHAN_STATE_IDLE; 178 } 179 180 static uint64_t sifive_pdma_read(void *opaque, hwaddr offset, unsigned size) 181 { 182 SiFivePDMAState *s = opaque; 183 int ch = SIFIVE_PDMA_CHAN_NO(offset); 184 uint64_t val = 0; 185 186 if (ch >= SIFIVE_PDMA_CHANS) { 187 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n", 188 __func__, ch); 189 return 0; 190 } 191 192 offset &= 0xfff; 193 switch (offset) { 194 case DMA_CONTROL: 195 val = s->chan[ch].control; 196 break; 197 case DMA_NEXT_CONFIG: 198 val = s->chan[ch].next_config; 199 break; 200 case DMA_NEXT_BYTES: 201 val = s->chan[ch].next_bytes; 202 break; 203 case DMA_NEXT_DST: 204 val = s->chan[ch].next_dst; 205 break; 206 case DMA_NEXT_SRC: 207 val = s->chan[ch].next_src; 208 break; 209 case DMA_EXEC_CONFIG: 210 val = s->chan[ch].exec_config; 211 break; 212 case DMA_EXEC_BYTES: 213 val = s->chan[ch].exec_bytes; 214 break; 215 case DMA_EXEC_DST: 216 val = s->chan[ch].exec_dst; 217 break; 218 case DMA_EXEC_SRC: 219 val = s->chan[ch].exec_src; 220 break; 221 default: 222 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", 223 __func__, offset); 224 break; 225 } 226 227 return val; 228 } 229 230 static void sifive_pdma_write(void *opaque, hwaddr offset, 231 uint64_t value, unsigned size) 232 { 233 SiFivePDMAState *s = opaque; 234 int ch = SIFIVE_PDMA_CHAN_NO(offset); 235 bool claimed; 236 237 if (ch >= SIFIVE_PDMA_CHANS) { 238 qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n", 239 __func__, ch); 240 return; 241 } 242 243 offset &= 0xfff; 244 switch (offset) { 245 case DMA_CONTROL: 246 claimed = !!s->chan[ch].control & CONTROL_CLAIM; 247 248 if (!claimed && (value & CONTROL_CLAIM)) { 249 /* reset Next* registers */ 250 s->chan[ch].next_config = (CONFIG_RDSZ_DEFAULT << CONFIG_RDSZ_SHIFT) | 251 (CONFIG_WRSZ_DEFAULT << CONFIG_WRSZ_SHIFT); 252 s->chan[ch].next_bytes = 0; 253 s->chan[ch].next_dst = 0; 254 s->chan[ch].next_src = 0; 255 } 256 257 s->chan[ch].control = value; 258 259 /* 260 * If channel was not claimed before run bit is set, 261 * DMA won't run. 262 */ 263 if (!claimed) { 264 s->chan[ch].control &= ~CONTROL_RUN; 265 return; 266 } 267 268 if (value & CONTROL_RUN) { 269 sifive_pdma_run(s, ch); 270 } 271 272 sifive_pdma_update_irq(s, ch); 273 break; 274 case DMA_NEXT_CONFIG: 275 s->chan[ch].next_config = value; 276 break; 277 case DMA_NEXT_BYTES: 278 s->chan[ch].next_bytes = value; 279 break; 280 case DMA_NEXT_DST: 281 s->chan[ch].next_dst = value; 282 break; 283 case DMA_NEXT_SRC: 284 s->chan[ch].next_src = value; 285 break; 286 case DMA_EXEC_CONFIG: 287 case DMA_EXEC_BYTES: 288 case DMA_EXEC_DST: 289 case DMA_EXEC_SRC: 290 /* these are read-only registers */ 291 break; 292 default: 293 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", 294 __func__, offset); 295 break; 296 } 297 } 298 299 static const MemoryRegionOps sifive_pdma_ops = { 300 .read = sifive_pdma_read, 301 .write = sifive_pdma_write, 302 .endianness = DEVICE_LITTLE_ENDIAN, 303 /* there are 32-bit and 64-bit wide registers */ 304 .impl = { 305 .min_access_size = 4, 306 .max_access_size = 8, 307 } 308 }; 309 310 static void sifive_pdma_realize(DeviceState *dev, Error **errp) 311 { 312 SiFivePDMAState *s = SIFIVE_PDMA(dev); 313 int i; 314 315 memory_region_init_io(&s->iomem, OBJECT(dev), &sifive_pdma_ops, s, 316 TYPE_SIFIVE_PDMA, SIFIVE_PDMA_REG_SIZE); 317 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); 318 319 for (i = 0; i < SIFIVE_PDMA_IRQS; i++) { 320 sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); 321 } 322 } 323 324 static void sifive_pdma_class_init(ObjectClass *klass, void *data) 325 { 326 DeviceClass *dc = DEVICE_CLASS(klass); 327 328 dc->desc = "SiFive Platform DMA controller"; 329 dc->realize = sifive_pdma_realize; 330 } 331 332 static const TypeInfo sifive_pdma_info = { 333 .name = TYPE_SIFIVE_PDMA, 334 .parent = TYPE_SYS_BUS_DEVICE, 335 .instance_size = sizeof(SiFivePDMAState), 336 .class_init = sifive_pdma_class_init, 337 }; 338 339 static void sifive_pdma_register_types(void) 340 { 341 type_register_static(&sifive_pdma_info); 342 } 343 344 type_init(sifive_pdma_register_types) 345