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