1 /* 2 * Raspberry Pi emulation (c) 2012 Gregory Estrade 3 * This code is licensed under the GNU GPLv2 and later. 4 */ 5 6 #include "qemu/osdep.h" 7 #include "qapi/error.h" 8 #include "hw/dma/bcm2835_dma.h" 9 #include "hw/irq.h" 10 #include "migration/vmstate.h" 11 #include "qemu/log.h" 12 #include "qemu/module.h" 13 14 /* DMA CS Control and Status bits */ 15 #define BCM2708_DMA_ACTIVE (1 << 0) 16 #define BCM2708_DMA_END (1 << 1) /* GE */ 17 #define BCM2708_DMA_INT (1 << 2) 18 #define BCM2708_DMA_ISPAUSED (1 << 4) /* Pause requested or not active */ 19 #define BCM2708_DMA_ISHELD (1 << 5) /* Is held by DREQ flow control */ 20 #define BCM2708_DMA_ERR (1 << 8) 21 #define BCM2708_DMA_ABORT (1 << 30) /* stop current CB, go to next, WO */ 22 #define BCM2708_DMA_RESET (1 << 31) /* WO, self clearing */ 23 24 /* DMA control block "info" field bits */ 25 #define BCM2708_DMA_INT_EN (1 << 0) 26 #define BCM2708_DMA_TDMODE (1 << 1) 27 #define BCM2708_DMA_WAIT_RESP (1 << 3) 28 #define BCM2708_DMA_D_INC (1 << 4) 29 #define BCM2708_DMA_D_WIDTH (1 << 5) 30 #define BCM2708_DMA_D_DREQ (1 << 6) 31 #define BCM2708_DMA_D_IGNORE (1 << 7) 32 #define BCM2708_DMA_S_INC (1 << 8) 33 #define BCM2708_DMA_S_WIDTH (1 << 9) 34 #define BCM2708_DMA_S_DREQ (1 << 10) 35 #define BCM2708_DMA_S_IGNORE (1 << 11) 36 37 /* Register offsets */ 38 #define BCM2708_DMA_CS 0x00 /* Control and Status */ 39 #define BCM2708_DMA_ADDR 0x04 /* Control block address */ 40 /* the current control block appears in the following registers - read only */ 41 #define BCM2708_DMA_INFO 0x08 42 #define BCM2708_DMA_SOURCE_AD 0x0c 43 #define BCM2708_DMA_DEST_AD 0x10 44 #define BCM2708_DMA_TXFR_LEN 0x14 45 #define BCM2708_DMA_STRIDE 0x18 46 #define BCM2708_DMA_NEXTCB 0x1C 47 #define BCM2708_DMA_DEBUG 0x20 48 49 #define BCM2708_DMA_INT_STATUS 0xfe0 /* Interrupt status of each channel */ 50 #define BCM2708_DMA_ENABLE 0xff0 /* Global enable bits for each channel */ 51 52 #define BCM2708_DMA_CS_RW_MASK 0x30ff0001 /* All RW bits in DMA_CS */ 53 54 static void bcm2835_dma_update(BCM2835DMAState *s, unsigned c) 55 { 56 BCM2835DMAChan *ch = &s->chan[c]; 57 uint32_t data, xlen, ylen; 58 int16_t dst_stride, src_stride; 59 60 if (!(s->enable & (1 << c))) { 61 return; 62 } 63 64 while ((s->enable & (1 << c)) && (ch->conblk_ad != 0)) { 65 /* CB fetch */ 66 ch->ti = ldl_le_phys(&s->dma_as, ch->conblk_ad); 67 ch->source_ad = ldl_le_phys(&s->dma_as, ch->conblk_ad + 4); 68 ch->dest_ad = ldl_le_phys(&s->dma_as, ch->conblk_ad + 8); 69 ch->txfr_len = ldl_le_phys(&s->dma_as, ch->conblk_ad + 12); 70 ch->stride = ldl_le_phys(&s->dma_as, ch->conblk_ad + 16); 71 ch->nextconbk = ldl_le_phys(&s->dma_as, ch->conblk_ad + 20); 72 73 if (ch->ti & BCM2708_DMA_TDMODE) { 74 /* 2D transfer mode */ 75 ylen = (ch->txfr_len >> 16) & 0x3fff; 76 xlen = ch->txfr_len & 0xffff; 77 dst_stride = ch->stride >> 16; 78 src_stride = ch->stride & 0xffff; 79 } else { 80 ylen = 1; 81 xlen = ch->txfr_len; 82 dst_stride = 0; 83 src_stride = 0; 84 } 85 86 while (ylen != 0) { 87 /* Normal transfer mode */ 88 while (xlen != 0) { 89 if (ch->ti & BCM2708_DMA_S_IGNORE) { 90 /* Ignore reads */ 91 data = 0; 92 } else { 93 data = ldl_le_phys(&s->dma_as, ch->source_ad); 94 } 95 if (ch->ti & BCM2708_DMA_S_INC) { 96 ch->source_ad += 4; 97 } 98 99 if (ch->ti & BCM2708_DMA_D_IGNORE) { 100 /* Ignore writes */ 101 } else { 102 stl_le_phys(&s->dma_as, ch->dest_ad, data); 103 } 104 if (ch->ti & BCM2708_DMA_D_INC) { 105 ch->dest_ad += 4; 106 } 107 108 /* update remaining transfer length */ 109 xlen -= 4; 110 if (ch->ti & BCM2708_DMA_TDMODE) { 111 ch->txfr_len = (ylen << 16) | xlen; 112 } else { 113 ch->txfr_len = xlen; 114 } 115 } 116 117 if (--ylen != 0) { 118 ch->source_ad += src_stride; 119 ch->dest_ad += dst_stride; 120 } 121 } 122 ch->cs |= BCM2708_DMA_END; 123 if (ch->ti & BCM2708_DMA_INT_EN) { 124 ch->cs |= BCM2708_DMA_INT; 125 s->int_status |= (1 << c); 126 qemu_set_irq(ch->irq, 1); 127 } 128 129 /* Process next CB */ 130 ch->conblk_ad = ch->nextconbk; 131 } 132 133 ch->cs &= ~BCM2708_DMA_ACTIVE; 134 ch->cs |= BCM2708_DMA_ISPAUSED; 135 } 136 137 static void bcm2835_dma_chan_reset(BCM2835DMAChan *ch) 138 { 139 ch->cs = 0; 140 ch->conblk_ad = 0; 141 } 142 143 static uint64_t bcm2835_dma_read(BCM2835DMAState *s, hwaddr offset, 144 unsigned size, unsigned c) 145 { 146 BCM2835DMAChan *ch; 147 uint32_t res = 0; 148 149 assert(size == 4); 150 assert(c < BCM2835_DMA_NCHANS); 151 152 ch = &s->chan[c]; 153 154 switch (offset) { 155 case BCM2708_DMA_CS: 156 res = ch->cs; 157 break; 158 case BCM2708_DMA_ADDR: 159 res = ch->conblk_ad; 160 break; 161 case BCM2708_DMA_INFO: 162 res = ch->ti; 163 break; 164 case BCM2708_DMA_SOURCE_AD: 165 res = ch->source_ad; 166 break; 167 case BCM2708_DMA_DEST_AD: 168 res = ch->dest_ad; 169 break; 170 case BCM2708_DMA_TXFR_LEN: 171 res = ch->txfr_len; 172 break; 173 case BCM2708_DMA_STRIDE: 174 res = ch->stride; 175 break; 176 case BCM2708_DMA_NEXTCB: 177 res = ch->nextconbk; 178 break; 179 case BCM2708_DMA_DEBUG: 180 res = ch->debug; 181 break; 182 default: 183 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", 184 __func__, offset); 185 break; 186 } 187 return res; 188 } 189 190 static void bcm2835_dma_write(BCM2835DMAState *s, hwaddr offset, 191 uint64_t value, unsigned size, unsigned c) 192 { 193 BCM2835DMAChan *ch; 194 uint32_t oldcs; 195 196 assert(size == 4); 197 assert(c < BCM2835_DMA_NCHANS); 198 199 ch = &s->chan[c]; 200 201 switch (offset) { 202 case BCM2708_DMA_CS: 203 oldcs = ch->cs; 204 if (value & BCM2708_DMA_RESET) { 205 bcm2835_dma_chan_reset(ch); 206 } 207 if (value & BCM2708_DMA_ABORT) { 208 /* abort is a no-op, since we always run to completion */ 209 } 210 if (value & BCM2708_DMA_END) { 211 ch->cs &= ~BCM2708_DMA_END; 212 } 213 if (value & BCM2708_DMA_INT) { 214 ch->cs &= ~BCM2708_DMA_INT; 215 s->int_status &= ~(1 << c); 216 qemu_set_irq(ch->irq, 0); 217 } 218 ch->cs &= ~BCM2708_DMA_CS_RW_MASK; 219 ch->cs |= (value & BCM2708_DMA_CS_RW_MASK); 220 if (!(oldcs & BCM2708_DMA_ACTIVE) && (ch->cs & BCM2708_DMA_ACTIVE)) { 221 bcm2835_dma_update(s, c); 222 } 223 break; 224 case BCM2708_DMA_ADDR: 225 ch->conblk_ad = value; 226 break; 227 case BCM2708_DMA_DEBUG: 228 ch->debug = value; 229 break; 230 default: 231 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", 232 __func__, offset); 233 break; 234 } 235 } 236 237 static uint64_t bcm2835_dma0_read(void *opaque, hwaddr offset, unsigned size) 238 { 239 BCM2835DMAState *s = opaque; 240 241 if (offset < 0xf00) { 242 return bcm2835_dma_read(s, (offset & 0xff), size, (offset >> 8) & 0xf); 243 } else { 244 switch (offset) { 245 case BCM2708_DMA_INT_STATUS: 246 return s->int_status; 247 case BCM2708_DMA_ENABLE: 248 return s->enable; 249 default: 250 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", 251 __func__, offset); 252 return 0; 253 } 254 } 255 } 256 257 static uint64_t bcm2835_dma15_read(void *opaque, hwaddr offset, unsigned size) 258 { 259 return bcm2835_dma_read(opaque, (offset & 0xff), size, 15); 260 } 261 262 static void bcm2835_dma0_write(void *opaque, hwaddr offset, uint64_t value, 263 unsigned size) 264 { 265 BCM2835DMAState *s = opaque; 266 267 if (offset < 0xf00) { 268 bcm2835_dma_write(s, (offset & 0xff), value, size, (offset >> 8) & 0xf); 269 } else { 270 switch (offset) { 271 case BCM2708_DMA_INT_STATUS: 272 break; 273 case BCM2708_DMA_ENABLE: 274 s->enable = (value & 0xffff); 275 break; 276 default: 277 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n", 278 __func__, offset); 279 } 280 } 281 282 } 283 284 static void bcm2835_dma15_write(void *opaque, hwaddr offset, uint64_t value, 285 unsigned size) 286 { 287 bcm2835_dma_write(opaque, (offset & 0xff), value, size, 15); 288 } 289 290 static const MemoryRegionOps bcm2835_dma0_ops = { 291 .read = bcm2835_dma0_read, 292 .write = bcm2835_dma0_write, 293 .endianness = DEVICE_NATIVE_ENDIAN, 294 .valid.min_access_size = 4, 295 .valid.max_access_size = 4, 296 }; 297 298 static const MemoryRegionOps bcm2835_dma15_ops = { 299 .read = bcm2835_dma15_read, 300 .write = bcm2835_dma15_write, 301 .endianness = DEVICE_NATIVE_ENDIAN, 302 .valid.min_access_size = 4, 303 .valid.max_access_size = 4, 304 }; 305 306 static const VMStateDescription vmstate_bcm2835_dma_chan = { 307 .name = TYPE_BCM2835_DMA "-chan", 308 .version_id = 1, 309 .minimum_version_id = 1, 310 .fields = (VMStateField[]) { 311 VMSTATE_UINT32(cs, BCM2835DMAChan), 312 VMSTATE_UINT32(conblk_ad, BCM2835DMAChan), 313 VMSTATE_UINT32(ti, BCM2835DMAChan), 314 VMSTATE_UINT32(source_ad, BCM2835DMAChan), 315 VMSTATE_UINT32(dest_ad, BCM2835DMAChan), 316 VMSTATE_UINT32(txfr_len, BCM2835DMAChan), 317 VMSTATE_UINT32(stride, BCM2835DMAChan), 318 VMSTATE_UINT32(nextconbk, BCM2835DMAChan), 319 VMSTATE_UINT32(debug, BCM2835DMAChan), 320 VMSTATE_END_OF_LIST() 321 } 322 }; 323 324 static const VMStateDescription vmstate_bcm2835_dma = { 325 .name = TYPE_BCM2835_DMA, 326 .version_id = 1, 327 .minimum_version_id = 1, 328 .fields = (VMStateField[]) { 329 VMSTATE_STRUCT_ARRAY(chan, BCM2835DMAState, BCM2835_DMA_NCHANS, 1, 330 vmstate_bcm2835_dma_chan, BCM2835DMAChan), 331 VMSTATE_UINT32(int_status, BCM2835DMAState), 332 VMSTATE_UINT32(enable, BCM2835DMAState), 333 VMSTATE_END_OF_LIST() 334 } 335 }; 336 337 static void bcm2835_dma_init(Object *obj) 338 { 339 BCM2835DMAState *s = BCM2835_DMA(obj); 340 int n; 341 342 /* DMA channels 0-14 occupy a contiguous block of IO memory, along 343 * with the global enable and interrupt status bits. Channel 15 344 * has the same register map, but is mapped at a discontiguous 345 * address in a separate IO block. 346 */ 347 memory_region_init_io(&s->iomem0, OBJECT(s), &bcm2835_dma0_ops, s, 348 TYPE_BCM2835_DMA, 0x1000); 349 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem0); 350 351 memory_region_init_io(&s->iomem15, OBJECT(s), &bcm2835_dma15_ops, s, 352 TYPE_BCM2835_DMA "-chan15", 0x100); 353 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem15); 354 355 for (n = 0; n < 16; n++) { 356 sysbus_init_irq(SYS_BUS_DEVICE(s), &s->chan[n].irq); 357 } 358 } 359 360 static void bcm2835_dma_reset(DeviceState *dev) 361 { 362 BCM2835DMAState *s = BCM2835_DMA(dev); 363 int n; 364 365 s->enable = 0xffff; 366 s->int_status = 0; 367 for (n = 0; n < BCM2835_DMA_NCHANS; n++) { 368 bcm2835_dma_chan_reset(&s->chan[n]); 369 } 370 } 371 372 static void bcm2835_dma_realize(DeviceState *dev, Error **errp) 373 { 374 BCM2835DMAState *s = BCM2835_DMA(dev); 375 Error *err = NULL; 376 Object *obj; 377 378 obj = object_property_get_link(OBJECT(dev), "dma-mr", &err); 379 if (obj == NULL) { 380 error_setg(errp, "%s: required dma-mr link not found: %s", 381 __func__, error_get_pretty(err)); 382 return; 383 } 384 385 s->dma_mr = MEMORY_REGION(obj); 386 address_space_init(&s->dma_as, s->dma_mr, TYPE_BCM2835_DMA "-memory"); 387 388 bcm2835_dma_reset(dev); 389 } 390 391 static void bcm2835_dma_class_init(ObjectClass *klass, void *data) 392 { 393 DeviceClass *dc = DEVICE_CLASS(klass); 394 395 dc->realize = bcm2835_dma_realize; 396 dc->reset = bcm2835_dma_reset; 397 dc->vmsd = &vmstate_bcm2835_dma; 398 } 399 400 static TypeInfo bcm2835_dma_info = { 401 .name = TYPE_BCM2835_DMA, 402 .parent = TYPE_SYS_BUS_DEVICE, 403 .instance_size = sizeof(BCM2835DMAState), 404 .class_init = bcm2835_dma_class_init, 405 .instance_init = bcm2835_dma_init, 406 }; 407 408 static void bcm2835_dma_register_types(void) 409 { 410 type_register_static(&bcm2835_dma_info); 411 } 412 413 type_init(bcm2835_dma_register_types) 414