1 /* 2 * DMA support for the JZ4780. 3 * NOTE: This should be combined with the X1600 support. 4 * 5 * Copyright (C) 2021, 2023, 2024 Paul Boddie <paul@boddie.org.uk> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA 21 */ 22 23 #include <l4/devices/cpm-jz4780.h> 24 #include <l4/devices/dma-jz4780.h> 25 #include <l4/devices/hw_mmio_register_block.h> 26 27 #include <l4/sys/cache.h> 28 #include <l4/sys/ipc.h> 29 #include <l4/sys/irq.h> 30 #include <l4/sys/rcv_endpoint.h> 31 #include <l4/util/util.h> 32 33 #include <systypes/thread.h> 34 35 #include <stdio.h> 36 37 38 39 enum Global_regs 40 { 41 Dma_control = 0x1000, // DMAC 42 Dma_irq_pending = 0x1004, // DIRQP 43 Dma_doorbell = 0x1008, // DDB 44 Dma_doorbell_set = 0x100c, // DDS 45 Dma_channel_programmable = 0x101c, // DMACP 46 Dma_soft_irq_pending = 0x1020, // DSIRQP 47 Dma_soft_irq_mask = 0x1024, // DSIRQM 48 Dma_mcu_irq_pending = 0x1028, // DCIRQP 49 Dma_mcu_irq_mask = 0x102c, // DCIRQM 50 }; 51 52 enum Channel_regs 53 { 54 Dma_source = 0x00, // DSA 55 Dma_destination = 0x04, // DTA 56 Dma_transfer_count = 0x08, // DTC 57 Dma_request_source = 0x0c, // DRT 58 Dma_control_status = 0x10, // DCS 59 Dma_command = 0x14, // DCM 60 Dma_descriptor_address = 0x18, // DDA 61 Dma_stride = 0x1c, // DSD 62 }; 63 64 enum Dma_control_bits : unsigned 65 { 66 Dma_fast_msc_transfer = 0x80000000, // FMSC 67 Dma_fast_ssi_transfer = 0x40000000, // FSSI 68 Dma_fast_tssi_transfer = 0x20000000, // FTSSI 69 Dma_fast_uart_transfer = 0x10000000, // FUART 70 Dma_fast_aic_transfer = 0x08000000, // FAIC 71 72 Dma_intc_irq_channel_mask = 0x003e0000, // INTCC 73 Dma_intc_irq_channel_bind = 0x00010000, // INTCE 74 75 Dma_control_trans_halted = 0x00000008, // HLT 76 Dma_control_address_error = 0x00000004, // AR 77 Dma_control_special_ch01 = 0x00000002, // CH01 78 Dma_control_enable = 0x00000001, // DMAE 79 }; 80 81 enum Dma_transfer_count_bits : unsigned 82 { 83 Dma_descriptor_offset_mask = 0xff000000, // DOA (in DES3) 84 Dma_transfer_count_mask = 0x00ffffff, 85 86 Dma_descriptor_offset_shift = 24, 87 }; 88 89 enum Dma_request_source_bits : unsigned 90 { 91 Dma_request_type_mask = 0x0000003f, 92 }; 93 94 enum Dma_control_status_bits : unsigned 95 { 96 Dma_no_descriptor_transfer = 0x80000000, 97 Dma_8word_descriptor = 0x40000000, 98 Dma_4word_descriptor = 0x00000000, 99 Dma_copy_offset_mask = 0x0000ff00, 100 Dma_address_error = 0x00000010, 101 Dma_trans_completed = 0x00000008, 102 Dma_trans_halted = 0x00000004, 103 Dma_channel_enable = 0x00000001, 104 105 Dma_copy_offset_shift = 8, 106 }; 107 108 enum Dma_command_bits : unsigned 109 { 110 Dma_special_source_mask = 0x0c000000, 111 Dma_special_source_tcsm = 0x00000000, 112 Dma_special_source_bch_nemc = 0x04000000, 113 Dma_special_source_reserved_ddr = 0x08000000, 114 115 Dma_special_destination_mask = 0x03000000, 116 Dma_special_destination_tcsm = 0x00000000, 117 Dma_special_destination_bch_nemc = 0x01000000, 118 Dma_special_destination_reserved_ddr = 0x02000000, 119 120 Dma_source_address_increment = 0x00800000, 121 Dma_source_address_no_increment = 0x00000000, 122 Dma_destination_address_increment = 0x00400000, 123 Dma_destination_address_no_increment = 0x00000000, 124 125 Dma_recommended_data_unit_size_mask = 0x000f0000, 126 Dma_source_port_width_mask = 0x0000c000, 127 Dma_destination_port_width_mask = 0x00003000, 128 Dma_transfer_unit_size_mask = 0x00000f00, 129 130 Dma_trans_unit_size_32_bit = 0x00000000, 131 Dma_trans_unit_size_8_bit = 0x00000100, 132 Dma_trans_unit_size_16_bit = 0x00000200, 133 Dma_trans_unit_size_16_byte = 0x00000300, 134 Dma_trans_unit_size_32_byte = 0x00000400, 135 Dma_trans_unit_size_64_byte = 0x00000500, 136 Dma_trans_unit_size_128_byte = 0x00000600, 137 Dma_trans_unit_size_autonomous = 0x00000700, 138 139 Dma_stride_enable = 0x00000004, 140 Dma_transfer_irq_enable = 0x00000002, 141 Dma_descriptor_link_enable = 0x00000001, 142 143 Dma_recommended_data_unit_size_shift = 16, 144 Dma_source_port_width_shift = 14, 145 Dma_destination_port_width_shift = 12, 146 Dma_transfer_unit_size_shift = 8, 147 }; 148 149 enum Dma_port_width_values : unsigned 150 { 151 Dma_port_width_32_bit = 0, 152 Dma_port_width_8_bit = 1, 153 Dma_port_width_16_bit = 2, 154 }; 155 156 157 158 // Initialise a channel. 159 160 Dma_jz4780_channel::Dma_jz4780_channel(Dma_chip *chip, uint8_t channel, 161 l4_addr_t start, l4_cap_idx_t irq) 162 : _chip(chip), _channel(channel), _irq(irq) 163 { 164 _regs = new Hw::Mmio_register_block<32>(start); 165 166 // Initialise the transfer count. 167 168 _regs[Dma_transfer_count] = 0; 169 } 170 171 // Return the closest interval length greater than or equal to the number of 172 // units given encoded in the request detection interval length field of the 173 // control/status register. 174 175 uint32_t 176 Dma_jz4780_channel::encode_req_detect_int_length(uint8_t units) 177 { 178 static uint8_t lengths[] = {0, 1, 2, 3, 4, 8, 16, 32, 64, 128}; 179 int i; 180 181 if (!units) 182 return 0; 183 184 for (i = 0; i <= 9; i++) 185 { 186 if (lengths[i] >= units) 187 break; 188 } 189 190 return i << Dma_recommended_data_unit_size_shift; 191 } 192 193 // Encode the appropriate source port width for the given request type. 194 195 uint32_t 196 Dma_jz4780_channel::encode_source_port_width(uint8_t width) 197 { 198 switch (width) 199 { 200 case 1: 201 return Dma_port_width_8_bit << Dma_source_port_width_shift; 202 203 case 2: 204 return Dma_port_width_16_bit << Dma_source_port_width_shift; 205 206 default: 207 return Dma_port_width_32_bit << Dma_source_port_width_shift; 208 } 209 } 210 211 // Encode the appropriate destination port width for the given request type. 212 213 uint32_t 214 Dma_jz4780_channel::encode_destination_port_width(uint8_t width) 215 { 216 switch (width) 217 { 218 case 1: 219 return Dma_port_width_8_bit << Dma_destination_port_width_shift; 220 221 case 2: 222 return Dma_port_width_16_bit << Dma_destination_port_width_shift; 223 224 default: 225 return Dma_port_width_32_bit << Dma_destination_port_width_shift; 226 } 227 } 228 229 // Encode the transfer unit size. 230 // NOTE: This does not handle the external case. 231 232 uint32_t 233 Dma_jz4780_channel::encode_transfer_unit_size(uint8_t size) 234 { 235 switch (size) 236 { 237 case 0: 238 return Dma_trans_unit_size_autonomous; 239 240 case 1: 241 return Dma_trans_unit_size_8_bit; 242 243 case 2: 244 return Dma_trans_unit_size_16_bit; 245 246 case 16: 247 return Dma_trans_unit_size_16_byte; 248 249 case 32: 250 return Dma_trans_unit_size_32_byte; 251 252 case 64: 253 return Dma_trans_unit_size_64_byte; 254 255 case 128: 256 return Dma_trans_unit_size_128_byte; 257 258 default: 259 return Dma_trans_unit_size_32_bit; 260 } 261 } 262 263 // Transfer data between memory locations. 264 265 unsigned int 266 Dma_jz4780_channel::transfer(uint32_t source, uint32_t destination, 267 unsigned int count, 268 bool source_increment, bool destination_increment, 269 uint8_t source_width, uint8_t destination_width, 270 uint8_t transfer_unit_size, 271 int type, 272 l4_addr_t desc_vaddr, 273 l4re_dma_space_dma_addr_t desc_paddr) 274 { 275 // Ensure an absence of address error and halt conditions globally and in this channel. 276 277 if (error() || halted()) 278 { 279 printf("Cleared:%s%s\n", error() ? " error" : "", halted() ? " halted" : ""); 280 clear_errors(); 281 } 282 283 // Ensure a zero transfer count for this channel. 284 285 if (_regs[Dma_transfer_count]) 286 return 0; 287 288 // Disable the channel. 289 290 _regs[Dma_control_status] = _regs[Dma_control_status] & ~Dma_channel_enable; 291 292 // Set transfer count to the number of units. 293 294 unsigned int units = count < Dma_transfer_count_mask ? count : Dma_transfer_count_mask; 295 296 // NOTE: Request detection interval length (for autonomous mode) not considered. 297 298 uint32_t command = (source_increment ? Dma_source_address_increment : 299 Dma_source_address_no_increment) | 300 (destination_increment ? Dma_destination_address_increment : 301 Dma_destination_address_no_increment) | 302 encode_source_port_width(source_width) | 303 encode_destination_port_width(destination_width) | 304 encode_transfer_unit_size(transfer_unit_size) | 305 Dma_transfer_irq_enable; 306 307 // Populate the descriptor, largely corresponding to the population of 308 // registers when descriptors are not being used. 309 310 if (desc_vaddr) 311 { 312 struct jz4780_dma_descriptor *desc = (struct jz4780_dma_descriptor *) desc_vaddr; 313 314 // NOTE: Linking to the same descriptor. 315 316 uint32_t descriptor_offset = 0; 317 318 desc->command = command | Dma_descriptor_link_enable; 319 desc->source = source; 320 desc->destination = destination; 321 desc->transfer_count = (units & Dma_transfer_count_mask) | 322 (descriptor_offset << Dma_descriptor_offset_shift); 323 desc->request_source = (enum Dma_jz4780_request_type) type; 324 325 // NOTE: Stride not supported yet. 326 327 l4_cache_clean_data((unsigned long) desc_vaddr, 328 (unsigned long) desc_vaddr + sizeof(*desc)); 329 330 // Commit the descriptor. 331 332 _regs[Dma_descriptor_address] = desc_paddr; 333 _chip->commit_descriptor(_channel); 334 } 335 336 // Otherwise, populate the registers for a one-off transfer. 337 338 else 339 { 340 _regs[Dma_command] = command; 341 _regs[Dma_source] = source; 342 _regs[Dma_destination] = destination; 343 _regs[Dma_transfer_count] = units & Dma_transfer_count_mask; 344 _regs[Dma_request_source] = type; 345 } 346 347 // Enable the channel with descriptor transfer configured if appropriate. 348 349 _regs[Dma_control_status] = (desc_vaddr ? Dma_8word_descriptor : 350 Dma_no_descriptor_transfer) | 351 Dma_channel_enable; 352 353 // Return the number of units to transfer. 354 355 return units; 356 } 357 358 unsigned int 359 Dma_jz4780_channel::wait() 360 { 361 // An interrupt will occur upon completion, the completion flag will be set 362 // and the transfer count will be zero. 363 364 unsigned int remaining = 0; 365 366 do 367 { 368 if (!wait_for_irq(1000000)) 369 printf("status = %x\n", (uint32_t) _regs[Dma_control_status]); 370 else 371 { 372 printf("status = %x\n", (uint32_t) _regs[Dma_control_status]); 373 remaining = _regs[Dma_transfer_count]; 374 ack_irq(); 375 break; 376 } 377 } 378 while (!error() && !halted() && !completed()); 379 380 // Reset the channel status. 381 382 _regs[Dma_control_status] = _regs[Dma_control_status] & ~(Dma_channel_enable | 383 Dma_trans_completed | Dma_address_error | 384 Dma_trans_halted); 385 _regs[Dma_transfer_count] = 0; 386 387 // Return the number of remaining units. 388 389 return remaining; 390 } 391 392 // Wait indefinitely for an interrupt request, returning true if one was delivered. 393 394 bool 395 Dma_jz4780_channel::wait_for_irq() 396 { 397 if (l4_is_valid_cap(_irq)) 398 { 399 if (l4_error(l4_rcv_ep_bind_thread(_irq, get_current_thread(), 0))) 400 return false; 401 402 return !l4_error(l4_irq_receive(_irq, L4_IPC_NEVER)) && _chip->have_interrupt(_channel); 403 } 404 else 405 return true; 406 } 407 408 // Wait up to the given timeout (in microseconds) for an interrupt request, 409 // returning true if one was delivered. 410 411 bool 412 Dma_jz4780_channel::wait_for_irq(unsigned int timeout) 413 { 414 if (l4_is_valid_cap(_irq)) 415 { 416 if (l4_error(l4_rcv_ep_bind_thread(_irq, get_current_thread(), 0))) 417 return false; 418 419 return !l4_error(l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(timeout)))) && _chip->have_interrupt(_channel); 420 } 421 else 422 return true; 423 } 424 425 // Acknowledge an interrupt condition. 426 427 void 428 Dma_jz4780_channel::ack_irq() 429 { 430 _chip->ack_irq(_channel); 431 } 432 433 // Clear error conditions. 434 435 void 436 Dma_jz4780_channel::clear_errors() 437 { 438 _regs[Dma_control_status] = _regs[Dma_control_status] & ~(Dma_address_error | Dma_trans_halted); 439 _chip->clear_errors(); 440 } 441 442 // Return whether a transfer has completed. 443 444 bool 445 Dma_jz4780_channel::completed() 446 { 447 return _regs[Dma_control_status] & Dma_trans_completed ? true : false; 448 } 449 450 // Return whether an address error condition has arisen. 451 452 bool 453 Dma_jz4780_channel::error() 454 { 455 return _chip->error() || (_regs[Dma_control_status] & Dma_address_error ? true : false); 456 } 457 458 // Return whether a transfer has halted. 459 460 bool 461 Dma_jz4780_channel::halted() 462 { 463 return _chip->halted() || (_regs[Dma_control_status] & Dma_trans_halted ? true : false); 464 } 465 466 467 468 // Initialise the I2C controller. 469 470 Dma_jz4780_chip::Dma_jz4780_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm) 471 : _start(start), _end(end), _cpm(cpm) 472 { 473 _regs = new Hw::Mmio_register_block<32>(start); 474 } 475 476 // Enable the peripheral. 477 478 void 479 Dma_jz4780_chip::enable() 480 { 481 // Make sure that the DMA clock is available. 482 483 _cpm->start_clock(Clock_dma); 484 485 _regs[Dma_control] = Dma_control_enable; 486 while (!(_regs[Dma_control] & Dma_control_enable)); 487 } 488 489 // Disable the channel. 490 491 void 492 Dma_jz4780_chip::disable() 493 { 494 _regs[Dma_control] = 0; 495 while (_regs[Dma_control] & Dma_control_enable); 496 } 497 498 // Obtain a channel object. 499 500 Dma_channel * 501 Dma_jz4780_chip::get_channel(uint8_t channel, l4_cap_idx_t irq) 502 { 503 if (channel < 32) 504 return new Dma_jz4780_channel(this, channel, _start + 0x20 * channel, irq); 505 else 506 throw -L4_EINVAL; 507 } 508 509 // Return whether an interrupt is pending on the given channel. 510 511 bool 512 Dma_jz4780_chip::have_interrupt(uint8_t channel) 513 { 514 return _regs[Dma_irq_pending] & (1 << channel) ? true : false; 515 } 516 517 // Acknowledge an interrupt condition on the given channel. 518 519 void 520 Dma_jz4780_chip::ack_irq(uint8_t channel) 521 { 522 _regs[Dma_irq_pending] = _regs[Dma_irq_pending] & ~(1 << channel); 523 } 524 525 // Clear error conditions. 526 527 void 528 Dma_jz4780_chip::clear_errors() 529 { 530 _regs[Dma_control] = _regs[Dma_control] & ~(Dma_control_address_error | Dma_control_trans_halted); 531 } 532 533 // Return whether an address error condition has arisen. 534 535 bool 536 Dma_jz4780_chip::error() 537 { 538 return _regs[Dma_control] & Dma_control_address_error ? true : false; 539 } 540 541 // Return whether a transfer has halted. 542 543 bool 544 Dma_jz4780_chip::halted() 545 { 546 return _regs[Dma_control] & Dma_control_trans_halted ? true : false; 547 } 548 549 void 550 Dma_jz4780_chip::commit_descriptor(uint8_t channel) 551 { 552 _regs[Dma_doorbell_set] = (1 << channel); 553 } 554 555 Dma_chip *jz4780_dma_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm) 556 { 557 return new Dma_jz4780_chip(start, end, cpm); 558 } 559 560 561 562 // C language interface functions. 563 564 void *jz4780_dma_init(l4_addr_t start, l4_addr_t end, void *cpm) 565 { 566 return (void *) jz4780_dma_chip(start, end, static_cast<Cpm_chip *>(cpm)); 567 } 568 569 void jz4780_dma_disable(void *dma_chip) 570 { 571 static_cast<Dma_chip *>(dma_chip)->disable(); 572 } 573 574 void jz4780_dma_enable(void *dma_chip) 575 { 576 static_cast<Dma_chip *>(dma_chip)->enable(); 577 } 578 579 void *jz4780_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq) 580 { 581 return static_cast<Dma_chip *>(dma)->get_channel(channel, irq); 582 } 583 584 unsigned int jz4780_dma_transfer(void *dma_channel, 585 uint32_t source, uint32_t destination, 586 unsigned int count, 587 int source_increment, int destination_increment, 588 uint8_t source_width, uint8_t destination_width, 589 uint8_t transfer_unit_size, 590 enum Dma_jz4780_request_type type) 591 { 592 return static_cast<Dma_jz4780_channel *>(dma_channel)->transfer(source, 593 destination, count, source_increment, destination_increment, source_width, 594 destination_width, transfer_unit_size, type); 595 } 596 597 unsigned int jz4780_dma_transfer_descriptor(void *dma_channel, 598 uint32_t source, uint32_t destination, 599 unsigned int count, 600 int source_increment, int destination_increment, 601 uint8_t source_width, uint8_t destination_width, 602 uint8_t transfer_unit_size, 603 enum Dma_jz4780_request_type type, 604 l4_addr_t desc_vaddr, 605 l4re_dma_space_dma_addr_t desc_paddr) 606 { 607 return static_cast<Dma_jz4780_channel *>(dma_channel)->transfer(source, 608 destination, count, source_increment, destination_increment, source_width, 609 destination_width, transfer_unit_size, type, desc_vaddr, desc_paddr); 610 } 611 612 unsigned int jz4780_dma_wait(void *dma_channel) 613 { 614 return static_cast<Dma_jz4780_channel *>(dma_channel)->wait(); 615 }