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_error(l4_rcv_ep_bind_thread(_irq, get_current_thread(), 0))) 352 return false; 353 354 return !l4_error(l4_irq_receive(_irq, L4_IPC_NEVER)) && _chip->have_interrupt(_channel); 355 } 356 357 // Wait up to the given timeout (in microseconds) for an interrupt request, 358 // returning true if one was delivered. 359 360 bool 361 Dma_jz4730_channel::wait_for_irq(unsigned int timeout) 362 { 363 if (l4_error(l4_rcv_ep_bind_thread(_irq, get_current_thread(), 0))) 364 return false; 365 366 return !l4_error(l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(timeout)))) && _chip->have_interrupt(_channel); 367 } 368 369 // Acknowledge an interrupt condition. 370 371 void 372 Dma_jz4730_channel::ack_irq() 373 { 374 _regs[Dma_control_status] = _regs[Dma_control_status] & ~Dma_trans_completed; 375 } 376 377 // Clear error conditions. 378 379 void 380 Dma_jz4730_channel::clear_errors() 381 { 382 _regs[Dma_control_status] = _regs[Dma_control_status] & ~(Dma_address_error | Dma_trans_halted); 383 } 384 385 // Return whether a transfer has completed. 386 387 bool 388 Dma_jz4730_channel::completed() 389 { 390 return _regs[Dma_control_status] & Dma_trans_completed ? true : false; 391 } 392 393 // Return whether an address error condition has arisen. 394 395 bool 396 Dma_jz4730_channel::error() 397 { 398 return _regs[Dma_control_status] & Dma_address_error ? true : false; 399 } 400 401 // Return whether a transfer has halted. 402 403 bool 404 Dma_jz4730_channel::halted() 405 { 406 return _regs[Dma_control_status] & Dma_trans_halted ? true : false; 407 } 408 409 410 411 // Initialise the I2C controller. 412 413 Dma_jz4730_chip::Dma_jz4730_chip(l4_addr_t start, l4_addr_t end, 414 Cpm_chip *cpm) 415 : _start(start), _end(end), _cpm(cpm) 416 { 417 _regs = new Hw::Mmio_register_block<32>(start); 418 } 419 420 // Enable the peripheral. 421 422 void 423 Dma_jz4730_chip::enable() 424 { 425 // Make sure that the DMA clock is available. 426 427 _cpm->start_clock(Clock_dma); 428 429 // Enable the channel. 430 // NOTE: No configuration is done for channel priority mode. 431 432 _regs[Dma_control] = Dma_control_enable; 433 while (!(_regs[Dma_control] & Dma_control_enable)); 434 } 435 436 // Disable the channel. 437 438 void 439 Dma_jz4730_chip::disable() 440 { 441 _regs[Dma_control] = 0; 442 while (_regs[Dma_control] & Dma_control_enable); 443 } 444 445 // Obtain a channel object. 446 447 Dma_channel * 448 Dma_jz4730_chip::get_channel(uint8_t channel, l4_cap_idx_t irq) 449 { 450 if (channel < 6) 451 return new Dma_jz4730_channel(this, channel, _start + 0x20 * channel, irq); 452 else 453 throw -L4_EINVAL; 454 } 455 456 // Return whether an interrupt is pending on the given channel. 457 458 bool 459 Dma_jz4730_chip::have_interrupt(uint8_t channel) 460 { 461 return _regs[Dma_irq_pending] & (1 << (Dma_irq_pending_ch0 - channel)) ? true : false; 462 } 463 464 Dma_chip *jz4730_dma_chip(l4_addr_t start, l4_addr_t end, Cpm_chip *cpm) 465 { 466 return new Dma_jz4730_chip(start, end, cpm); 467 } 468 469 470 471 // C language interface functions. 472 473 void *jz4730_dma_init(l4_addr_t start, l4_addr_t end, void *cpm) 474 { 475 return (void *) jz4730_dma_chip(start, end, static_cast<Cpm_chip *>(cpm)); 476 } 477 478 void jz4730_dma_disable(void *dma_chip) 479 { 480 static_cast<Dma_chip *>(dma_chip)->disable(); 481 } 482 483 void jz4730_dma_enable(void *dma_chip) 484 { 485 static_cast<Dma_chip *>(dma_chip)->enable(); 486 } 487 488 void *jz4730_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq) 489 { 490 return static_cast<Dma_chip *>(dma)->get_channel(channel, irq); 491 } 492 493 void jz4730_dma_set_output_polarity(void *dma_channel, enum Dma_jz4730_ext_level polarity) 494 { 495 static_cast<Dma_jz4730_channel *>(dma_channel)->set_output_polarity(polarity); 496 } 497 498 void jz4730_dma_set_end_of_process_mode(void *dma_channel, enum Dma_jz4730_ext_level mode) 499 { 500 static_cast<Dma_jz4730_channel *>(dma_channel)->set_end_of_process_mode(mode); 501 } 502 503 void jz4730_dma_set_output_mode_cycle(void *dma_channel, enum Dma_jz4730_ext_output_mode_cycle cycle) 504 { 505 static_cast<Dma_jz4730_channel *>(dma_channel)->set_output_mode_cycle(cycle); 506 } 507 508 void jz4730_dma_set_req_detect_mode(void *dma_channel, enum Dma_jz4730_ext_req_detect_mode mode) 509 { 510 static_cast<Dma_jz4730_channel *>(dma_channel)->set_req_detect_mode(mode); 511 } 512 513 unsigned int jz4730_dma_transfer(void *dma_channel, 514 uint32_t source, uint32_t destination, 515 unsigned int count, 516 int source_increment, int destination_increment, 517 uint8_t source_width, uint8_t destination_width, 518 uint8_t transfer_unit_size, 519 enum Dma_jz4730_request_type type) 520 { 521 return static_cast<Dma_jz4730_channel *>(dma_channel)->transfer(source, 522 destination, count, source_increment, destination_increment, source_width, 523 destination_width, transfer_unit_size, type); 524 } 525 526 unsigned int jz4730_dma_wait(void *dma_channel) 527 { 528 return static_cast<Dma_jz4730_channel *>(dma_channel)->wait(); 529 }