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