1 /* 2 * xlnx_dpdma.c 3 * 4 * Copyright (C) 2015 : GreenSocs Ltd 5 * http://www.greensocs.com/ , email: info@greensocs.com 6 * 7 * Developed by : 8 * Frederic Konrad <fred.konrad@greensocs.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation, either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License along 21 * with this program; if not, see <http://www.gnu.org/licenses/>. 22 * 23 */ 24 25 #include "qemu/osdep.h" 26 #include "qemu/log.h" 27 #include "hw/dma/xlnx_dpdma.h" 28 29 #ifndef DEBUG_DPDMA 30 #define DEBUG_DPDMA 0 31 #endif 32 33 #define DPRINTF(fmt, ...) do { \ 34 if (DEBUG_DPDMA) { \ 35 qemu_log("xlnx_dpdma: " fmt , ## __VA_ARGS__); \ 36 } \ 37 } while (0) 38 39 /* 40 * Registers offset for DPDMA. 41 */ 42 #define DPDMA_ERR_CTRL (0x0000) 43 #define DPDMA_ISR (0x0004 >> 2) 44 #define DPDMA_IMR (0x0008 >> 2) 45 #define DPDMA_IEN (0x000C >> 2) 46 #define DPDMA_IDS (0x0010 >> 2) 47 #define DPDMA_EISR (0x0014 >> 2) 48 #define DPDMA_EIMR (0x0018 >> 2) 49 #define DPDMA_EIEN (0x001C >> 2) 50 #define DPDMA_EIDS (0x0020 >> 2) 51 #define DPDMA_CNTL (0x0100 >> 2) 52 53 #define DPDMA_GBL (0x0104 >> 2) 54 #define DPDMA_GBL_TRG_CH(n) (1 << n) 55 #define DPDMA_GBL_RTRG_CH(n) (1 << 6 << n) 56 57 #define DPDMA_ALC0_CNTL (0x0108 >> 2) 58 #define DPDMA_ALC0_STATUS (0x010C >> 2) 59 #define DPDMA_ALC0_MAX (0x0110 >> 2) 60 #define DPDMA_ALC0_MIN (0x0114 >> 2) 61 #define DPDMA_ALC0_ACC (0x0118 >> 2) 62 #define DPDMA_ALC0_ACC_TRAN (0x011C >> 2) 63 #define DPDMA_ALC1_CNTL (0x0120 >> 2) 64 #define DPDMA_ALC1_STATUS (0x0124 >> 2) 65 #define DPDMA_ALC1_MAX (0x0128 >> 2) 66 #define DPDMA_ALC1_MIN (0x012C >> 2) 67 #define DPDMA_ALC1_ACC (0x0130 >> 2) 68 #define DPDMA_ALC1_ACC_TRAN (0x0134 >> 2) 69 70 #define DPDMA_DSCR_STRT_ADDRE_CH(n) ((0x0200 + n * 0x100) >> 2) 71 #define DPDMA_DSCR_STRT_ADDR_CH(n) ((0x0204 + n * 0x100) >> 2) 72 #define DPDMA_DSCR_NEXT_ADDRE_CH(n) ((0x0208 + n * 0x100) >> 2) 73 #define DPDMA_DSCR_NEXT_ADDR_CH(n) ((0x020C + n * 0x100) >> 2) 74 #define DPDMA_PYLD_CUR_ADDRE_CH(n) ((0x0210 + n * 0x100) >> 2) 75 #define DPDMA_PYLD_CUR_ADDR_CH(n) ((0x0214 + n * 0x100) >> 2) 76 77 #define DPDMA_CNTL_CH(n) ((0x0218 + n * 0x100) >> 2) 78 #define DPDMA_CNTL_CH_EN (1) 79 #define DPDMA_CNTL_CH_PAUSED (1 << 1) 80 81 #define DPDMA_STATUS_CH(n) ((0x021C + n * 0x100) >> 2) 82 #define DPDMA_STATUS_BURST_TYPE (1 << 4) 83 #define DPDMA_STATUS_MODE (1 << 5) 84 #define DPDMA_STATUS_EN_CRC (1 << 6) 85 #define DPDMA_STATUS_LAST_DSCR (1 << 7) 86 #define DPDMA_STATUS_LDSCR_FRAME (1 << 8) 87 #define DPDMA_STATUS_IGNR_DONE (1 << 9) 88 #define DPDMA_STATUS_DSCR_DONE (1 << 10) 89 #define DPDMA_STATUS_EN_DSCR_UP (1 << 11) 90 #define DPDMA_STATUS_EN_DSCR_INTR (1 << 12) 91 #define DPDMA_STATUS_PREAMBLE_OFF (13) 92 93 #define DPDMA_VDO_CH(n) ((0x0220 + n * 0x100) >> 2) 94 #define DPDMA_PYLD_SZ_CH(n) ((0x0224 + n * 0x100) >> 2) 95 #define DPDMA_DSCR_ID_CH(n) ((0x0228 + n * 0x100) >> 2) 96 97 /* 98 * Descriptor control field. 99 */ 100 #define CONTROL_PREAMBLE_VALUE 0xA5 101 102 #define DSCR_CTRL_PREAMBLE 0xFF 103 #define DSCR_CTRL_EN_DSCR_DONE_INTR (1 << 8) 104 #define DSCR_CTRL_EN_DSCR_UPDATE (1 << 9) 105 #define DSCR_CTRL_IGNORE_DONE (1 << 10) 106 #define DSCR_CTRL_AXI_BURST_TYPE (1 << 11) 107 #define DSCR_CTRL_AXCACHE (0x0F << 12) 108 #define DSCR_CTRL_AXPROT (0x2 << 16) 109 #define DSCR_CTRL_DESCRIPTOR_MODE (1 << 18) 110 #define DSCR_CTRL_LAST_DESCRIPTOR (1 << 19) 111 #define DSCR_CTRL_ENABLE_CRC (1 << 20) 112 #define DSCR_CTRL_LAST_DESCRIPTOR_OF_FRAME (1 << 21) 113 114 /* 115 * Descriptor timestamp field. 116 */ 117 #define STATUS_DONE (1 << 31) 118 119 #define DPDMA_FRAG_MAX_SZ (4096) 120 121 enum DPDMABurstType { 122 DPDMA_INCR = 0, 123 DPDMA_FIXED = 1 124 }; 125 126 enum DPDMAMode { 127 DPDMA_CONTIGOUS = 0, 128 DPDMA_FRAGMENTED = 1 129 }; 130 131 struct DPDMADescriptor { 132 uint32_t control; 133 uint32_t descriptor_id; 134 /* transfer size in byte. */ 135 uint32_t xfer_size; 136 uint32_t line_size_stride; 137 uint32_t timestamp_lsb; 138 uint32_t timestamp_msb; 139 /* contains extension for both descriptor and source. */ 140 uint32_t address_extension; 141 uint32_t next_descriptor; 142 uint32_t source_address; 143 uint32_t address_extension_23; 144 uint32_t address_extension_45; 145 uint32_t source_address2; 146 uint32_t source_address3; 147 uint32_t source_address4; 148 uint32_t source_address5; 149 uint32_t crc; 150 }; 151 152 typedef enum DPDMABurstType DPDMABurstType; 153 typedef enum DPDMAMode DPDMAMode; 154 typedef struct DPDMADescriptor DPDMADescriptor; 155 156 static bool xlnx_dpdma_desc_is_last(DPDMADescriptor *desc) 157 { 158 return ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR) != 0); 159 } 160 161 static bool xlnx_dpdma_desc_is_last_of_frame(DPDMADescriptor *desc) 162 { 163 return ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR_OF_FRAME) != 0); 164 } 165 166 static uint64_t xlnx_dpdma_desc_get_source_address(DPDMADescriptor *desc, 167 uint8_t frag) 168 { 169 uint64_t addr = 0; 170 assert(frag < 5); 171 172 switch (frag) { 173 case 0: 174 addr = desc->source_address 175 + (extract32(desc->address_extension, 16, 12) << 20); 176 break; 177 case 1: 178 addr = desc->source_address2 179 + (extract32(desc->address_extension_23, 0, 12) << 8); 180 break; 181 case 2: 182 addr = desc->source_address3 183 + (extract32(desc->address_extension_23, 16, 12) << 20); 184 break; 185 case 3: 186 addr = desc->source_address4 187 + (extract32(desc->address_extension_45, 0, 12) << 8); 188 break; 189 case 4: 190 addr = desc->source_address5 191 + (extract32(desc->address_extension_45, 16, 12) << 20); 192 break; 193 default: 194 addr = 0; 195 break; 196 } 197 198 return addr; 199 } 200 201 static uint32_t xlnx_dpdma_desc_get_transfer_size(DPDMADescriptor *desc) 202 { 203 return desc->xfer_size; 204 } 205 206 static uint32_t xlnx_dpdma_desc_get_line_size(DPDMADescriptor *desc) 207 { 208 return extract32(desc->line_size_stride, 0, 18); 209 } 210 211 static uint32_t xlnx_dpdma_desc_get_line_stride(DPDMADescriptor *desc) 212 { 213 return extract32(desc->line_size_stride, 18, 14) * 16; 214 } 215 216 static inline bool xlnx_dpdma_desc_crc_enabled(DPDMADescriptor *desc) 217 { 218 return (desc->control & DSCR_CTRL_ENABLE_CRC) != 0; 219 } 220 221 static inline bool xlnx_dpdma_desc_check_crc(DPDMADescriptor *desc) 222 { 223 uint32_t *p = (uint32_t *)desc; 224 uint32_t crc = 0; 225 uint8_t i; 226 227 /* 228 * CRC is calculated on the whole descriptor except the last 32bits word 229 * using 32bits addition. 230 */ 231 for (i = 0; i < 15; i++) { 232 crc += p[i]; 233 } 234 235 return crc == desc->crc; 236 } 237 238 static inline bool xlnx_dpdma_desc_completion_interrupt(DPDMADescriptor *desc) 239 { 240 return (desc->control & DSCR_CTRL_EN_DSCR_DONE_INTR) != 0; 241 } 242 243 static inline bool xlnx_dpdma_desc_is_valid(DPDMADescriptor *desc) 244 { 245 return (desc->control & DSCR_CTRL_PREAMBLE) == CONTROL_PREAMBLE_VALUE; 246 } 247 248 static inline bool xlnx_dpdma_desc_is_contiguous(DPDMADescriptor *desc) 249 { 250 return (desc->control & DSCR_CTRL_DESCRIPTOR_MODE) == 0; 251 } 252 253 static inline bool xlnx_dpdma_desc_update_enabled(DPDMADescriptor *desc) 254 { 255 return (desc->control & DSCR_CTRL_EN_DSCR_UPDATE) != 0; 256 } 257 258 static inline void xlnx_dpdma_desc_set_done(DPDMADescriptor *desc) 259 { 260 desc->timestamp_msb |= STATUS_DONE; 261 } 262 263 static inline bool xlnx_dpdma_desc_is_already_done(DPDMADescriptor *desc) 264 { 265 return (desc->timestamp_msb & STATUS_DONE) != 0; 266 } 267 268 static inline bool xlnx_dpdma_desc_ignore_done_bit(DPDMADescriptor *desc) 269 { 270 return (desc->control & DSCR_CTRL_IGNORE_DONE) != 0; 271 } 272 273 static const VMStateDescription vmstate_xlnx_dpdma = { 274 .name = TYPE_XLNX_DPDMA, 275 .version_id = 1, 276 .fields = (VMStateField[]) { 277 VMSTATE_UINT32_ARRAY(registers, XlnxDPDMAState, 278 XLNX_DPDMA_REG_ARRAY_SIZE), 279 VMSTATE_BOOL_ARRAY(operation_finished, XlnxDPDMAState, 6), 280 VMSTATE_END_OF_LIST() 281 } 282 }; 283 284 static void xlnx_dpdma_update_irq(XlnxDPDMAState *s) 285 { 286 bool flags; 287 288 flags = ((s->registers[DPDMA_ISR] & (~s->registers[DPDMA_IMR])) 289 || (s->registers[DPDMA_EISR] & (~s->registers[DPDMA_EIMR]))); 290 qemu_set_irq(s->irq, flags); 291 } 292 293 static uint64_t xlnx_dpdma_descriptor_start_address(XlnxDPDMAState *s, 294 uint8_t channel) 295 { 296 return (s->registers[DPDMA_DSCR_STRT_ADDRE_CH(channel)] << 16) 297 + s->registers[DPDMA_DSCR_STRT_ADDR_CH(channel)]; 298 } 299 300 static uint64_t xlnx_dpdma_descriptor_next_address(XlnxDPDMAState *s, 301 uint8_t channel) 302 { 303 return ((uint64_t)s->registers[DPDMA_DSCR_NEXT_ADDRE_CH(channel)] << 32) 304 + s->registers[DPDMA_DSCR_NEXT_ADDR_CH(channel)]; 305 } 306 307 static bool xlnx_dpdma_is_channel_enabled(XlnxDPDMAState *s, 308 uint8_t channel) 309 { 310 return (s->registers[DPDMA_CNTL_CH(channel)] & DPDMA_CNTL_CH_EN) != 0; 311 } 312 313 static bool xlnx_dpdma_is_channel_paused(XlnxDPDMAState *s, 314 uint8_t channel) 315 { 316 return (s->registers[DPDMA_CNTL_CH(channel)] & DPDMA_CNTL_CH_PAUSED) != 0; 317 } 318 319 static inline bool xlnx_dpdma_is_channel_retriggered(XlnxDPDMAState *s, 320 uint8_t channel) 321 { 322 /* Clear the retriggered bit after reading it. */ 323 bool channel_is_retriggered = s->registers[DPDMA_GBL] 324 & DPDMA_GBL_RTRG_CH(channel); 325 s->registers[DPDMA_GBL] &= ~DPDMA_GBL_RTRG_CH(channel); 326 return channel_is_retriggered; 327 } 328 329 static inline bool xlnx_dpdma_is_channel_triggered(XlnxDPDMAState *s, 330 uint8_t channel) 331 { 332 return s->registers[DPDMA_GBL] & DPDMA_GBL_TRG_CH(channel); 333 } 334 335 static void xlnx_dpdma_update_desc_info(XlnxDPDMAState *s, uint8_t channel, 336 DPDMADescriptor *desc) 337 { 338 s->registers[DPDMA_DSCR_NEXT_ADDRE_CH(channel)] = 339 extract32(desc->address_extension, 0, 16); 340 s->registers[DPDMA_DSCR_NEXT_ADDR_CH(channel)] = desc->next_descriptor; 341 s->registers[DPDMA_PYLD_CUR_ADDRE_CH(channel)] = 342 extract32(desc->address_extension, 16, 16); 343 s->registers[DPDMA_PYLD_CUR_ADDR_CH(channel)] = desc->source_address; 344 s->registers[DPDMA_VDO_CH(channel)] = 345 extract32(desc->line_size_stride, 18, 14) 346 + (extract32(desc->line_size_stride, 0, 18) 347 << 14); 348 s->registers[DPDMA_PYLD_SZ_CH(channel)] = desc->xfer_size; 349 s->registers[DPDMA_DSCR_ID_CH(channel)] = desc->descriptor_id; 350 351 /* Compute the status register with the descriptor information. */ 352 s->registers[DPDMA_STATUS_CH(channel)] = 353 extract32(desc->control, 0, 8) << 13; 354 if ((desc->control & DSCR_CTRL_EN_DSCR_DONE_INTR) != 0) { 355 s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_EN_DSCR_INTR; 356 } 357 if ((desc->control & DSCR_CTRL_EN_DSCR_UPDATE) != 0) { 358 s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_EN_DSCR_UP; 359 } 360 if ((desc->timestamp_msb & STATUS_DONE) != 0) { 361 s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_DSCR_DONE; 362 } 363 if ((desc->control & DSCR_CTRL_IGNORE_DONE) != 0) { 364 s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_IGNR_DONE; 365 } 366 if ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR_OF_FRAME) != 0) { 367 s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_LDSCR_FRAME; 368 } 369 if ((desc->control & DSCR_CTRL_LAST_DESCRIPTOR) != 0) { 370 s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_LAST_DSCR; 371 } 372 if ((desc->control & DSCR_CTRL_ENABLE_CRC) != 0) { 373 s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_EN_CRC; 374 } 375 if ((desc->control & DSCR_CTRL_DESCRIPTOR_MODE) != 0) { 376 s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_MODE; 377 } 378 if ((desc->control & DSCR_CTRL_AXI_BURST_TYPE) != 0) { 379 s->registers[DPDMA_STATUS_CH(channel)] |= DPDMA_STATUS_BURST_TYPE; 380 } 381 } 382 383 static void xlnx_dpdma_dump_descriptor(DPDMADescriptor *desc) 384 { 385 if (DEBUG_DPDMA) { 386 qemu_log("DUMP DESCRIPTOR:\n"); 387 qemu_hexdump((char *)desc, stdout, "", sizeof(DPDMADescriptor)); 388 } 389 } 390 391 static uint64_t xlnx_dpdma_read(void *opaque, hwaddr offset, 392 unsigned size) 393 { 394 XlnxDPDMAState *s = XLNX_DPDMA(opaque); 395 396 DPRINTF("read @%" HWADDR_PRIx "\n", offset); 397 offset = offset >> 2; 398 399 switch (offset) { 400 /* 401 * Trying to read a write only register. 402 */ 403 case DPDMA_GBL: 404 return 0; 405 default: 406 assert(offset <= (0xFFC >> 2)); 407 return s->registers[offset]; 408 } 409 return 0; 410 } 411 412 static void xlnx_dpdma_write(void *opaque, hwaddr offset, 413 uint64_t value, unsigned size) 414 { 415 XlnxDPDMAState *s = XLNX_DPDMA(opaque); 416 417 DPRINTF("write @%" HWADDR_PRIx " = %" PRIx64 "\n", offset, value); 418 offset = offset >> 2; 419 420 switch (offset) { 421 case DPDMA_ISR: 422 s->registers[DPDMA_ISR] &= ~value; 423 xlnx_dpdma_update_irq(s); 424 break; 425 case DPDMA_IEN: 426 s->registers[DPDMA_IMR] &= ~value; 427 break; 428 case DPDMA_IDS: 429 s->registers[DPDMA_IMR] |= value; 430 break; 431 case DPDMA_EISR: 432 s->registers[DPDMA_EISR] &= ~value; 433 xlnx_dpdma_update_irq(s); 434 break; 435 case DPDMA_EIEN: 436 s->registers[DPDMA_EIMR] &= ~value; 437 break; 438 case DPDMA_EIDS: 439 s->registers[DPDMA_EIMR] |= value; 440 break; 441 case DPDMA_IMR: 442 case DPDMA_EIMR: 443 case DPDMA_DSCR_NEXT_ADDRE_CH(0): 444 case DPDMA_DSCR_NEXT_ADDRE_CH(1): 445 case DPDMA_DSCR_NEXT_ADDRE_CH(2): 446 case DPDMA_DSCR_NEXT_ADDRE_CH(3): 447 case DPDMA_DSCR_NEXT_ADDRE_CH(4): 448 case DPDMA_DSCR_NEXT_ADDRE_CH(5): 449 case DPDMA_DSCR_NEXT_ADDR_CH(0): 450 case DPDMA_DSCR_NEXT_ADDR_CH(1): 451 case DPDMA_DSCR_NEXT_ADDR_CH(2): 452 case DPDMA_DSCR_NEXT_ADDR_CH(3): 453 case DPDMA_DSCR_NEXT_ADDR_CH(4): 454 case DPDMA_DSCR_NEXT_ADDR_CH(5): 455 case DPDMA_PYLD_CUR_ADDRE_CH(0): 456 case DPDMA_PYLD_CUR_ADDRE_CH(1): 457 case DPDMA_PYLD_CUR_ADDRE_CH(2): 458 case DPDMA_PYLD_CUR_ADDRE_CH(3): 459 case DPDMA_PYLD_CUR_ADDRE_CH(4): 460 case DPDMA_PYLD_CUR_ADDRE_CH(5): 461 case DPDMA_PYLD_CUR_ADDR_CH(0): 462 case DPDMA_PYLD_CUR_ADDR_CH(1): 463 case DPDMA_PYLD_CUR_ADDR_CH(2): 464 case DPDMA_PYLD_CUR_ADDR_CH(3): 465 case DPDMA_PYLD_CUR_ADDR_CH(4): 466 case DPDMA_PYLD_CUR_ADDR_CH(5): 467 case DPDMA_STATUS_CH(0): 468 case DPDMA_STATUS_CH(1): 469 case DPDMA_STATUS_CH(2): 470 case DPDMA_STATUS_CH(3): 471 case DPDMA_STATUS_CH(4): 472 case DPDMA_STATUS_CH(5): 473 case DPDMA_VDO_CH(0): 474 case DPDMA_VDO_CH(1): 475 case DPDMA_VDO_CH(2): 476 case DPDMA_VDO_CH(3): 477 case DPDMA_VDO_CH(4): 478 case DPDMA_VDO_CH(5): 479 case DPDMA_PYLD_SZ_CH(0): 480 case DPDMA_PYLD_SZ_CH(1): 481 case DPDMA_PYLD_SZ_CH(2): 482 case DPDMA_PYLD_SZ_CH(3): 483 case DPDMA_PYLD_SZ_CH(4): 484 case DPDMA_PYLD_SZ_CH(5): 485 case DPDMA_DSCR_ID_CH(0): 486 case DPDMA_DSCR_ID_CH(1): 487 case DPDMA_DSCR_ID_CH(2): 488 case DPDMA_DSCR_ID_CH(3): 489 case DPDMA_DSCR_ID_CH(4): 490 case DPDMA_DSCR_ID_CH(5): 491 /* 492 * Trying to write to a read only register.. 493 */ 494 break; 495 case DPDMA_GBL: 496 /* 497 * This is a write only register so it's read as zero in the read 498 * callback. 499 * We store the value anyway so we can know if the channel is 500 * enabled. 501 */ 502 s->registers[offset] |= value & 0x00000FFF; 503 break; 504 case DPDMA_DSCR_STRT_ADDRE_CH(0): 505 case DPDMA_DSCR_STRT_ADDRE_CH(1): 506 case DPDMA_DSCR_STRT_ADDRE_CH(2): 507 case DPDMA_DSCR_STRT_ADDRE_CH(3): 508 case DPDMA_DSCR_STRT_ADDRE_CH(4): 509 case DPDMA_DSCR_STRT_ADDRE_CH(5): 510 value &= 0x0000FFFF; 511 s->registers[offset] = value; 512 break; 513 case DPDMA_CNTL_CH(0): 514 s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(0); 515 value &= 0x3FFFFFFF; 516 s->registers[offset] = value; 517 break; 518 case DPDMA_CNTL_CH(1): 519 s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(1); 520 value &= 0x3FFFFFFF; 521 s->registers[offset] = value; 522 break; 523 case DPDMA_CNTL_CH(2): 524 s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(2); 525 value &= 0x3FFFFFFF; 526 s->registers[offset] = value; 527 break; 528 case DPDMA_CNTL_CH(3): 529 s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(3); 530 value &= 0x3FFFFFFF; 531 s->registers[offset] = value; 532 break; 533 case DPDMA_CNTL_CH(4): 534 s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(4); 535 value &= 0x3FFFFFFF; 536 s->registers[offset] = value; 537 break; 538 case DPDMA_CNTL_CH(5): 539 s->registers[DPDMA_GBL] &= ~DPDMA_GBL_TRG_CH(5); 540 value &= 0x3FFFFFFF; 541 s->registers[offset] = value; 542 break; 543 default: 544 assert(offset <= (0xFFC >> 2)); 545 s->registers[offset] = value; 546 break; 547 } 548 } 549 550 static const MemoryRegionOps dma_ops = { 551 .read = xlnx_dpdma_read, 552 .write = xlnx_dpdma_write, 553 .endianness = DEVICE_NATIVE_ENDIAN, 554 .valid = { 555 .min_access_size = 4, 556 .max_access_size = 4, 557 }, 558 .impl = { 559 .min_access_size = 4, 560 .max_access_size = 4, 561 }, 562 }; 563 564 static void xlnx_dpdma_init(Object *obj) 565 { 566 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 567 XlnxDPDMAState *s = XLNX_DPDMA(obj); 568 569 memory_region_init_io(&s->iomem, obj, &dma_ops, s, 570 TYPE_XLNX_DPDMA, 0x1000); 571 sysbus_init_mmio(sbd, &s->iomem); 572 sysbus_init_irq(sbd, &s->irq); 573 } 574 575 static void xlnx_dpdma_reset(DeviceState *dev) 576 { 577 XlnxDPDMAState *s = XLNX_DPDMA(dev); 578 size_t i; 579 580 memset(s->registers, 0, sizeof(s->registers)); 581 s->registers[DPDMA_IMR] = 0x07FFFFFF; 582 s->registers[DPDMA_EIMR] = 0xFFFFFFFF; 583 s->registers[DPDMA_ALC0_MIN] = 0x0000FFFF; 584 s->registers[DPDMA_ALC1_MIN] = 0x0000FFFF; 585 586 for (i = 0; i < 6; i++) { 587 s->data[i] = NULL; 588 s->operation_finished[i] = true; 589 } 590 } 591 592 static void xlnx_dpdma_class_init(ObjectClass *oc, void *data) 593 { 594 DeviceClass *dc = DEVICE_CLASS(oc); 595 596 dc->vmsd = &vmstate_xlnx_dpdma; 597 dc->reset = xlnx_dpdma_reset; 598 } 599 600 static const TypeInfo xlnx_dpdma_info = { 601 .name = TYPE_XLNX_DPDMA, 602 .parent = TYPE_SYS_BUS_DEVICE, 603 .instance_size = sizeof(XlnxDPDMAState), 604 .instance_init = xlnx_dpdma_init, 605 .class_init = xlnx_dpdma_class_init, 606 }; 607 608 static void xlnx_dpdma_register_types(void) 609 { 610 type_register_static(&xlnx_dpdma_info); 611 } 612 613 size_t xlnx_dpdma_start_operation(XlnxDPDMAState *s, uint8_t channel, 614 bool one_desc) 615 { 616 uint64_t desc_addr; 617 uint64_t source_addr[6]; 618 DPDMADescriptor desc; 619 bool done = false; 620 size_t ptr = 0; 621 622 assert(channel <= 5); 623 624 DPRINTF("start dpdma channel 0x%" PRIX8 "\n", channel); 625 626 if (!xlnx_dpdma_is_channel_triggered(s, channel)) { 627 DPRINTF("Channel isn't triggered..\n"); 628 return 0; 629 } 630 631 if (!xlnx_dpdma_is_channel_enabled(s, channel)) { 632 DPRINTF("Channel isn't enabled..\n"); 633 return 0; 634 } 635 636 if (xlnx_dpdma_is_channel_paused(s, channel)) { 637 DPRINTF("Channel is paused..\n"); 638 return 0; 639 } 640 641 do { 642 if ((s->operation_finished[channel]) 643 || xlnx_dpdma_is_channel_retriggered(s, channel)) { 644 desc_addr = xlnx_dpdma_descriptor_start_address(s, channel); 645 s->operation_finished[channel] = false; 646 } else { 647 desc_addr = xlnx_dpdma_descriptor_next_address(s, channel); 648 } 649 650 if (dma_memory_read(&address_space_memory, desc_addr, &desc, 651 sizeof(DPDMADescriptor))) { 652 s->registers[DPDMA_EISR] |= ((1 << 1) << channel); 653 xlnx_dpdma_update_irq(s); 654 s->operation_finished[channel] = true; 655 DPRINTF("Can't get the descriptor.\n"); 656 break; 657 } 658 659 xlnx_dpdma_update_desc_info(s, channel, &desc); 660 661 #ifdef DEBUG_DPDMA 662 xlnx_dpdma_dump_descriptor(&desc); 663 #endif 664 665 DPRINTF("location of the descriptor: %" PRIx64 "\n", desc_addr); 666 if (!xlnx_dpdma_desc_is_valid(&desc)) { 667 s->registers[DPDMA_EISR] |= ((1 << 7) << channel); 668 xlnx_dpdma_update_irq(s); 669 s->operation_finished[channel] = true; 670 DPRINTF("Invalid descriptor..\n"); 671 break; 672 } 673 674 if (xlnx_dpdma_desc_crc_enabled(&desc) 675 && !xlnx_dpdma_desc_check_crc(&desc)) { 676 s->registers[DPDMA_EISR] |= ((1 << 13) << channel); 677 xlnx_dpdma_update_irq(s); 678 s->operation_finished[channel] = true; 679 DPRINTF("Bad CRC for descriptor..\n"); 680 break; 681 } 682 683 if (xlnx_dpdma_desc_is_already_done(&desc) 684 && !xlnx_dpdma_desc_ignore_done_bit(&desc)) { 685 /* We are trying to process an already processed descriptor. */ 686 s->registers[DPDMA_EISR] |= ((1 << 25) << channel); 687 xlnx_dpdma_update_irq(s); 688 s->operation_finished[channel] = true; 689 DPRINTF("Already processed descriptor..\n"); 690 break; 691 } 692 693 done = xlnx_dpdma_desc_is_last(&desc) 694 || xlnx_dpdma_desc_is_last_of_frame(&desc); 695 696 s->operation_finished[channel] = done; 697 if (s->data[channel]) { 698 int64_t transfer_len = xlnx_dpdma_desc_get_transfer_size(&desc); 699 uint32_t line_size = xlnx_dpdma_desc_get_line_size(&desc); 700 uint32_t line_stride = xlnx_dpdma_desc_get_line_stride(&desc); 701 if (xlnx_dpdma_desc_is_contiguous(&desc)) { 702 source_addr[0] = xlnx_dpdma_desc_get_source_address(&desc, 0); 703 while (transfer_len != 0) { 704 if (dma_memory_read(&address_space_memory, 705 source_addr[0], 706 &s->data[channel][ptr], 707 line_size)) { 708 s->registers[DPDMA_ISR] |= ((1 << 12) << channel); 709 xlnx_dpdma_update_irq(s); 710 DPRINTF("Can't get data.\n"); 711 break; 712 } 713 ptr += line_size; 714 transfer_len -= line_size; 715 source_addr[0] += line_stride; 716 } 717 } else { 718 DPRINTF("Source address:\n"); 719 int frag; 720 for (frag = 0; frag < 5; frag++) { 721 source_addr[frag] = 722 xlnx_dpdma_desc_get_source_address(&desc, frag); 723 DPRINTF("Fragment %u: %" PRIx64 "\n", frag + 1, 724 source_addr[frag]); 725 } 726 727 frag = 0; 728 while ((transfer_len < 0) && (frag < 5)) { 729 size_t fragment_len = DPDMA_FRAG_MAX_SZ 730 - (source_addr[frag] % DPDMA_FRAG_MAX_SZ); 731 732 if (dma_memory_read(&address_space_memory, 733 source_addr[frag], 734 &(s->data[channel][ptr]), 735 fragment_len)) { 736 s->registers[DPDMA_ISR] |= ((1 << 12) << channel); 737 xlnx_dpdma_update_irq(s); 738 DPRINTF("Can't get data.\n"); 739 break; 740 } 741 ptr += fragment_len; 742 transfer_len -= fragment_len; 743 frag += 1; 744 } 745 } 746 } 747 748 if (xlnx_dpdma_desc_update_enabled(&desc)) { 749 /* The descriptor need to be updated when it's completed. */ 750 DPRINTF("update the descriptor with the done flag set.\n"); 751 xlnx_dpdma_desc_set_done(&desc); 752 dma_memory_write(&address_space_memory, desc_addr, &desc, 753 sizeof(DPDMADescriptor)); 754 } 755 756 if (xlnx_dpdma_desc_completion_interrupt(&desc)) { 757 DPRINTF("completion interrupt enabled!\n"); 758 s->registers[DPDMA_ISR] |= (1 << channel); 759 xlnx_dpdma_update_irq(s); 760 } 761 762 } while (!done && !one_desc); 763 764 return ptr; 765 } 766 767 void xlnx_dpdma_set_host_data_location(XlnxDPDMAState *s, uint8_t channel, 768 void *p) 769 { 770 if (!s) { 771 qemu_log_mask(LOG_UNIMP, "DPDMA client not attached to valid DPDMA" 772 " instance\n"); 773 return; 774 } 775 776 assert(channel <= 5); 777 s->data[channel] = p; 778 } 779 780 void xlnx_dpdma_trigger_vsync_irq(XlnxDPDMAState *s) 781 { 782 s->registers[DPDMA_ISR] |= (1 << 27); 783 xlnx_dpdma_update_irq(s); 784 } 785 786 type_init(xlnx_dpdma_register_types) 787