1 /* 2 * DMA support for the JZ4730. 3 * 4 * Copyright (C) 2021, 2024 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <l4/devices/cpm-jz4730.h> 23 #include <l4/devices/dma-jz4730.h> 24 #include <l4/devices/hw_mmio_register_block.h> 25 26 #include <l4/sys/ipc.h> 27 #include <l4/sys/irq.h> 28 #include <l4/sys/rcv_endpoint.h> 29 #include <l4/util/util.h> 30 31 #include <systypes/thread.h> 32 33 #include <stdio.h> 34 35 36 37 enum Global_regs 38 { 39 Dma_irq_pending = 0xf8, // IRQP 40 Dma_control = 0xfc, // DMAC 41 }; 42 43 enum Channel_regs 44 { 45 Dma_source = 0x00, // DSA 46 Dma_destination = 0x04, // DDA 47 Dma_transfer_count = 0x08, // DTC 48 Dma_request_source = 0x0c, // DRT 49 Dma_control_status = 0x10, // DCS 50 }; 51 52 enum Dma_irq_pending_shifts : unsigned 53 { 54 Dma_irq_pending_ch0 = 15, 55 Dma_irq_pending_ch1 = 14, 56 Dma_irq_pending_ch2 = 13, 57 Dma_irq_pending_ch3 = 12, 58 Dma_irq_pending_ch4 = 11, 59 Dma_irq_pending_ch5 = 10, 60 }; 61 62 enum Dma_control_bits : unsigned 63 { 64 Dma_control_priority_mode = 0x100, // PM 65 Dma_control_halt_occurred = 0x008, // HLT 66 Dma_control_address_error = 0x004, // AR 67 Dma_control_enable = 0x001, // DMAE 68 }; 69 70 enum Dma_control_priority_modes : unsigned 71 { 72 Dma_priority_mode_01234567 = 0, 73 Dma_priority_mode_02314675 = 1, 74 Dma_priority_mode_20136457 = 2, 75 Dma_priority_mode_round_robin = 3, 76 }; 77 78 enum Dma_transfer_count_bits : unsigned 79 { 80 Dma_transfer_count_mask = 0x00ffffff, 81 }; 82 83 enum Dma_request_source_bits : unsigned 84 { 85 Dma_request_type_mask = 0x0000001f, 86 }; 87 88 enum Dma_control_status_shifts : unsigned 89 { 90 Dma_ext_output_polarity = 31, 91 Dma_ext_output_mode_cycle = 30, 92 Dma_ext_req_detect_mode = 28, 93 Dma_ext_end_of_process_mode = 27, 94 Dma_req_detect_int_length = 16, 95 Dma_source_port_width = 14, 96 Dma_dest_port_width = 12, 97 Dma_trans_unit_size = 8, 98 Dma_trans_mode = 7, 99 }; 100 101 enum Dma_control_status_bits : unsigned 102 { 103 Dma_source_address_incr = 0x00800000, 104 Dma_source_address_no_incr = 0x00000000, 105 Dma_dest_address_incr = 0x00400000, 106 Dma_dest_address_no_incr = 0x00000000, 107 108 Dma_trans_unit_size_32_bit = 0x00000000, 109 Dma_trans_unit_size_8_bit = 0x00000100, 110 Dma_trans_unit_size_16_bit = 0x00000200, 111 Dma_trans_unit_size_16_byte = 0x00000300, 112 Dma_trans_unit_size_32_byte = 0x00000400, 113 114 Dma_address_error = 0x00000010, 115 Dma_trans_completed = 0x00000008, 116 Dma_trans_halted = 0x00000004, 117 Dma_channel_irq_enable = 0x00000002, 118 Dma_channel_enable = 0x00000001, 119 }; 120 121 enum Dma_port_width_values : unsigned 122 { 123 Dma_port_width_32_bit = 0, 124 Dma_port_width_8_bit = 1, 125 Dma_port_width_16_bit = 2, 126 }; 127 128 enum Dma_trans_mode_values : unsigned 129 { 130 Dma_trans_mode_single = 0, 131 Dma_trans_mode_block = 1, 132 }; 133 134 135 136 // Initialise a channel. 137 138 Dma_jz4730_channel::Dma_jz4730_channel(Dma_chip *chip, uint8_t channel, 139 l4_addr_t start, l4_cap_idx_t irq) 140 : _chip(chip), _channel(channel), _irq(irq) 141 { 142 _regs = new Hw::Mmio_register_block<32>(start); 143 } 144 145 // Encode flags for an external transfer. 146 147 uint32_t 148 Dma_jz4730_channel::encode_external_transfer(enum Dma_jz4730_request_type type) 149 { 150 int external = (type == Dma_request_external) ? 1 : 0; 151 152 return 153 ((external ? (int) _ext_output_polarity : 0) << Dma_ext_output_polarity) | 154 ((external ? (int) _ext_output_mode_cycle : 0) << Dma_ext_output_mode_cycle) | 155 ((external ? (int) _ext_req_detect_mode : 0) << Dma_ext_req_detect_mode) | 156 ((external ? (int) _ext_end_of_process_mode : 0) << Dma_ext_end_of_process_mode); 157 } 158 159 // Return the closest interval length greater than or equal to the number of 160 // units given encoded in the request detection interval length field of the 161 // control/status register. 162 163 uint32_t 164 Dma_jz4730_channel::encode_req_detect_int_length(uint8_t units) 165 { 166 static uint8_t lengths[] = {0, 2, 4, 8, 12, 16, 20, 24, 28, 32, 48, 60, 64, 124, 128, 200}; 167 int i; 168 169 if (!units) 170 return 0; 171 172 for (i = 0; i <= 15; i++) 173 { 174 if (lengths[i] >= units) 175 break; 176 } 177 178 return i << Dma_req_detect_int_length; 179 } 180 181 // Encode the appropriate source port width. 182 183 uint32_t 184 Dma_jz4730_channel::encode_source_port_width(uint8_t width) 185 { 186 switch (width) 187 { 188 case 1: 189 return Dma_port_width_8_bit << Dma_source_port_width; 190 191 default: 192 return Dma_port_width_32_bit << Dma_source_port_width; 193 } 194 } 195 196 // Encode the appropriate destination port width for the given request type. 197 198 uint32_t 199 Dma_jz4730_channel::encode_destination_port_width(uint8_t width) 200 { 201 switch (width) 202 { 203 case 1: 204 return Dma_port_width_8_bit << Dma_dest_port_width; 205 206 default: 207 return Dma_port_width_32_bit << Dma_dest_port_width; 208 } 209 } 210 211 // Encode the transfer unit size. 212 213 uint32_t 214 Dma_jz4730_channel::encode_transfer_unit_size(uint8_t size) 215 { 216 switch (size) 217 { 218 case 1: 219 return Dma_trans_unit_size_8_bit; 220 221 case 2: 222 return Dma_trans_unit_size_16_bit; 223 224 case 16: 225 return Dma_trans_unit_size_16_byte; 226 227 case 32: 228 return Dma_trans_unit_size_32_byte; 229 230 default: 231 return Dma_trans_unit_size_32_bit; 232 } 233 } 234 235 // Transfer data between memory locations. 236 237 unsigned int 238 Dma_jz4730_channel::transfer(uint32_t source, uint32_t destination, 239 unsigned int count, 240 bool source_increment, bool destination_increment, 241 uint8_t source_width, uint8_t destination_width, 242 uint8_t transfer_unit_size, 243 int type, 244 l4_addr_t desc_vaddr, 245 l4re_dma_space_dma_addr_t desc_paddr) 246 { 247 // Descriptor-based transfers are not supported. 248 249 (void) desc_vaddr; (void) desc_paddr; 250 251 // Ensure an absence of address error and halt conditions globally and in this channel. 252 253 if (error() || halted()) 254 { 255 printf("Cleared:%s%s\n", error() ? " error" : "", halted() ? " halted" : ""); 256 clear_errors(); 257 } 258 259 // Ensure an absence of transaction completed and zero transfer count for this channel. 260 261 if (completed() || _regs[Dma_transfer_count]) 262 return 0; 263 264 // Disable the channel. 265 266 _regs[Dma_control_status] = _regs[Dma_control_status] & ~Dma_channel_enable; 267 268 // Set addresses. 269 270 _regs[Dma_source] = source; 271 _regs[Dma_destination] = destination; 272 273 // Set transfer count to the number of units. 274 275 unsigned int units = count < Dma_transfer_count_mask ? count : Dma_transfer_count_mask; 276 277 _regs[Dma_transfer_count] = units; 278 279 // Set auto-request for memory-to-memory transfers. Otherwise, set the 280 // indicated request type. 281 282 _regs[Dma_request_source] = type; 283 284 // Set control/status fields. 285 // Enable the channel (and peripheral). 286 287 /* NOTE: To be considered... 288 * request detection interval length (currently left as 0) 289 * increments and port widths for external transfers 290 * port width overriding (for AIC...) 291 * transfer mode (currently left as single) 292 */ 293 294 _regs[Dma_control_status] = encode_external_transfer((enum Dma_jz4730_request_type) type) | 295 (source_increment ? Dma_source_address_incr : Dma_source_address_no_incr) | 296 (destination_increment ? Dma_dest_address_incr : Dma_dest_address_no_incr) | 297 encode_source_port_width(source_width) | 298 encode_destination_port_width(destination_width) | 299 encode_transfer_unit_size(transfer_unit_size) | 300 (Dma_trans_mode_single << Dma_trans_mode) | 301 Dma_channel_irq_enable | 302 Dma_channel_enable; 303 304 // Return the number of units to transfer. 305 306 return units; 307 } 308 309 unsigned int 310 Dma_jz4730_channel::wait() 311 { 312 // An interrupt will occur upon completion, the completion flag will be set 313 // and the transfer count will be zero. 314 315 unsigned int remaining = 0; 316 317 do 318 { 319 if (!wait_for_irq(1000000)) 320 printf("status = %x\n", (uint32_t) _regs[Dma_control_status]); 321 322 // Clearing the completion flag will clear the interrupt condition. 323 // Any remaining units must be read before clearing the condition. 324 325 else 326 { 327 remaining = _regs[Dma_transfer_count]; 328 ack_irq(); 329 break; 330 } 331 } 332 while (!error() && !halted() && !completed()); 333 334 // Reset the channel status. 335 336 _regs[Dma_control_status] = _regs[Dma_control_status] & ~(Dma_channel_enable | 337 Dma_trans_completed | Dma_address_error | 338 Dma_trans_halted); 339 _regs[Dma_transfer_count] = 0; 340 341 // Return the number of remaining units. 342 343 return remaining; 344 } 345 346 // Wait indefinitely for an interrupt request, returning true if one was delivered. 347 348 bool 349 Dma_jz4730_channel::wait_for_irq() 350 { 351 if (l4_is_valid_cap(_irq)) 352 { 353 if (l4_error(l4_rcv_ep_bind_thread(_irq, get_current_thread(), 0))) 354 return false; 355 356 return !l4_error(l4_irq_receive(_irq, L4_IPC_NEVER)) && _chip->have_interrupt(_channel); 357 } 358 else 359 return true; 360 } 361 362 // Wait up to the given timeout (in microseconds) for an interrupt request, 363 // returning true if one was delivered. 364 365 bool 366 Dma_jz4730_channel::wait_for_irq(unsigned int timeout) 367 { 368 if (l4_error(l4_rcv_ep_bind_thread(_irq, get_current_thread(), 0))) 369 return false; 370 371 return !l4_error(l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(timeout)))) && _chip->have_interrupt(_channel); 372 } 373 374 // Acknowledge an interrupt condition. 375 376 void 377 Dma_jz4730_channel::ack_irq() 378 { 379 _regs[Dma_control_status] = _regs[Dma_control_status] & ~Dma_trans_completed; 380 } 381 382 // Clear error conditions. 383 384 void 385 Dma_jz4730_channel::clear_errors() 386 { 387 _regs[Dma_control_status] = _regs[Dma_control_status] & ~(Dma_address_error | Dma_trans_halted); 388 } 389 390 // Return whether a transfer has completed. 391 392 bool 393 Dma_jz4730_channel::completed() 394 { 395 return _regs[Dma_control_status] & Dma_trans_completed ? true : false; 396 } 397 398 // Return whether an address error condition has arisen. 399 400 bool 401 Dma_jz4730_channel::error() 402 { 403 return _regs[Dma_control_status] & Dma_address_error ? true : false; 404 } 405 406 // Return whether a transfer has halted. 407 408 bool 409 Dma_jz4730_channel::halted() 410 { 411 return _regs[Dma_control_status] & Dma_trans_halted ? true : false; 412 } 413 414 415 416 // Initialise the I2C controller. 417 418 Dma_jz4730_chip::Dma_jz4730_chip(l4_addr_t start, l4_addr_t end, 419 Cpm_chip *cpm) 420 : _start(start), _end(end), _cpm(cpm) 421 { 422 _regs = new Hw::Mmio_register_block<32>(start); 423 } 424 425 // Enable the peripheral. 426 427 void 428 Dma_jz4730_chip::enable() 429 { 430 // Make sure that the DMA clock is available. 431 432 _cpm->start_clock(Clock_dma); 433 434 // Enable the channel. 435 // NOTE: No configuration is done for channel priority mode. 436 437 _regs[Dma_control] = Dma_control_enable; 438 while (!(_regs[Dma_control] & Dma_control_enable)); 439 } 440 441 // Disable the channel. 442 443 void 444 Dma_jz4730_chip::disable() 445 { 446 _regs[Dma_control] = 0; 447 while (_regs[Dma_control] & Dma_control_enable); 448 } 449 450 // Obtain a channel object. 451 452 Dma_channel * 453 Dma_jz4730_chip::get_channel(uint8_t channel, l4_cap_idx_t irq) 454 { 455 if (channel < 6) 456 return new Dma_jz4730_channel(this, channel, _start + 0x20 * channel, irq); 457 else 458 throw -L4_EINVAL; 459 } 460 461 // Return whether an interrupt is pending on the given channel. 462 463 bool 464 Dma_jz4730_chip::have_interrupt(uint8_t channel) 465 { 466 return _regs[Dma_irq_pending] & (1 << (Dma_irq_pending_ch0 - channel)) ? true : false; 467 } 468 469 Dma_chip *jz4730_dma_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm) 470 { 471 return new Dma_jz4730_chip(start, end, cpm); 472 } 473 474 475 476 // C language interface functions. 477 478 void *jz4730_dma_init(l4_addr_t start, l4_addr_t end, void *cpm) 479 { 480 return (void *) jz4730_dma_chip(start, end, static_cast<Cpm_chip *>(cpm)); 481 } 482 483 void jz4730_dma_disable(void *dma_chip) 484 { 485 static_cast<Dma_chip *>(dma_chip)->disable(); 486 } 487 488 void jz4730_dma_enable(void *dma_chip) 489 { 490 static_cast<Dma_chip *>(dma_chip)->enable(); 491 } 492 493 void *jz4730_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq) 494 { 495 return static_cast<Dma_chip *>(dma)->get_channel(channel, irq); 496 } 497 498 void jz4730_dma_set_output_polarity(void *dma_channel, enum Dma_jz4730_ext_level polarity) 499 { 500 static_cast<Dma_jz4730_channel *>(dma_channel)->set_output_polarity(polarity); 501 } 502 503 void jz4730_dma_set_end_of_process_mode(void *dma_channel, enum Dma_jz4730_ext_level mode) 504 { 505 static_cast<Dma_jz4730_channel *>(dma_channel)->set_end_of_process_mode(mode); 506 } 507 508 void jz4730_dma_set_output_mode_cycle(void *dma_channel, enum Dma_jz4730_ext_output_mode_cycle cycle) 509 { 510 static_cast<Dma_jz4730_channel *>(dma_channel)->set_output_mode_cycle(cycle); 511 } 512 513 void jz4730_dma_set_req_detect_mode(void *dma_channel, enum Dma_jz4730_ext_req_detect_mode mode) 514 { 515 static_cast<Dma_jz4730_channel *>(dma_channel)->set_req_detect_mode(mode); 516 } 517 518 unsigned int jz4730_dma_transfer(void *dma_channel, 519 uint32_t source, uint32_t destination, 520 unsigned int count, 521 int source_increment, int destination_increment, 522 uint8_t source_width, uint8_t destination_width, 523 uint8_t transfer_unit_size, 524 enum Dma_jz4730_request_type type) 525 { 526 return static_cast<Dma_jz4730_channel *>(dma_channel)->transfer(source, 527 destination, count, source_increment, destination_increment, source_width, 528 destination_width, transfer_unit_size, type); 529 } 530 531 unsigned int jz4730_dma_wait(void *dma_channel) 532 { 533 return static_cast<Dma_jz4730_channel *>(dma_channel)->wait(); 534 }