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/dma-jz4730.h> 23 #include <l4/devices/hw_mmio_register_block.h> 24 25 #include <l4/sys/ipc.h> 26 #include <l4/sys/irq.h> 27 #include <l4/sys/rcv_endpoint.h> 28 #include <l4/util/util.h> 29 30 #include <pthread.h> 31 #include <pthread-l4.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_jz4730_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 enum Dma_jz4730_request_type type) 244 { 245 // Ensure an absence of address error and halt conditions globally and in this channel. 246 247 if (error() || halted()) 248 return 0; 249 250 // Ensure an absence of transaction completed and zero transfer count for this channel. 251 252 if (completed() || _regs[Dma_transfer_count]) 253 return 0; 254 255 // Disable the channel. 256 257 _regs[Dma_control_status] = _regs[Dma_control_status] & ~Dma_channel_enable; 258 259 // Set addresses. 260 261 _regs[Dma_source] = source; 262 _regs[Dma_destination] = destination; 263 264 // Set transfer count to the number of units. 265 266 unsigned int units = count < Dma_transfer_count_mask ? count : Dma_transfer_count_mask; 267 268 _regs[Dma_transfer_count] = units; 269 270 // Set auto-request for memory-to-memory transfers. Otherwise, set the 271 // indicated request type. 272 273 _regs[Dma_request_source] = type; 274 275 // Set control/status fields. 276 // Enable the channel (and peripheral). 277 278 /* NOTE: To be considered... 279 * request detection interval length (currently left as 0) 280 * increments and port widths for external transfers 281 * port width overriding (for AIC...) 282 * transfer mode (currently left as single) 283 */ 284 285 _regs[Dma_control_status] = encode_external_transfer(type) | 286 (source_increment ? Dma_source_address_incr : Dma_source_address_no_incr) | 287 (destination_increment ? Dma_dest_address_incr : Dma_dest_address_no_incr) | 288 encode_source_port_width(source_width) | 289 encode_destination_port_width(destination_width) | 290 encode_transfer_unit_size(transfer_unit_size) | 291 (Dma_trans_mode_single << Dma_trans_mode) | 292 Dma_channel_irq_enable | 293 Dma_channel_enable; 294 295 // Return the number of units to transfer. 296 297 return units; 298 } 299 300 unsigned int 301 Dma_jz4730_channel::wait() 302 { 303 // An interrupt will occur upon completion, the completion flag will be set 304 // and the transfer count will be zero. 305 306 unsigned int remaining = 0; 307 308 do 309 { 310 if (!wait_for_irq(1000000)) 311 printf("status = %x\n", (uint32_t) _regs[Dma_control_status]); 312 313 // Clearing the completion flag will clear the interrupt condition. 314 // Any remaining units must be read before clearing the condition. 315 316 else 317 { 318 remaining = _regs[Dma_transfer_count]; 319 ack_irq(); 320 break; 321 } 322 } 323 while (!error() && !halted() && !completed()); 324 325 // Reset the channel status. 326 327 _regs[Dma_control_status] = _regs[Dma_control_status] & ~(Dma_channel_enable | 328 Dma_trans_completed | Dma_address_error | 329 Dma_trans_halted); 330 _regs[Dma_transfer_count] = 0; 331 332 // Return the number of remaining units. 333 334 return remaining; 335 } 336 337 // Wait indefinitely for an interrupt request, returning true if one was delivered. 338 339 bool 340 Dma_jz4730_channel::wait_for_irq() 341 { 342 if (l4_error(l4_rcv_ep_bind_thread(_irq, pthread_l4_cap(pthread_self()), 0))) 343 return false; 344 345 return !l4_error(l4_irq_receive(_irq, L4_IPC_NEVER)) && _chip->have_interrupt(_channel); 346 } 347 348 // Wait up to the given timeout (in microseconds) for an interrupt request, 349 // returning true if one was delivered. 350 351 bool 352 Dma_jz4730_channel::wait_for_irq(unsigned int timeout) 353 { 354 if (l4_error(l4_rcv_ep_bind_thread(_irq, pthread_l4_cap(pthread_self()), 0))) 355 return false; 356 357 return !l4_error(l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(timeout)))) && _chip->have_interrupt(_channel); 358 } 359 360 // Acknowledge an interrupt condition. 361 362 void 363 Dma_jz4730_channel::ack_irq() 364 { 365 _regs[Dma_control_status] = _regs[Dma_control_status] & ~Dma_trans_completed; 366 } 367 368 // Return whether a transfer has completed. 369 370 bool 371 Dma_jz4730_channel::completed() 372 { 373 return _regs[Dma_control_status] & Dma_trans_completed ? true : false; 374 } 375 376 // Return whether an address error condition has arisen. 377 378 bool 379 Dma_jz4730_channel::error() 380 { 381 return _regs[Dma_control_status] & Dma_address_error ? true : false; 382 } 383 384 // Return whether a transfer has halted. 385 386 bool 387 Dma_jz4730_channel::halted() 388 { 389 return _regs[Dma_control_status] & Dma_trans_halted ? true : false; 390 } 391 392 393 394 // Initialise the I2C controller. 395 396 Dma_jz4730_chip::Dma_jz4730_chip(l4_addr_t start, l4_addr_t end, 397 Cpm_jz4730_chip *cpm) 398 : _start(start), _end(end), _cpm(cpm) 399 { 400 _regs = new Hw::Mmio_register_block<32>(start); 401 } 402 403 // Enable the peripheral. 404 405 void 406 Dma_jz4730_chip::enable() 407 { 408 // Make sure that the DMA clock is available. 409 410 _cpm->start_clock(Clock_dma); 411 412 // Enable the channel. 413 // NOTE: No configuration is done for channel priority mode. 414 415 _regs[Dma_control] = Dma_control_enable; 416 while (!(_regs[Dma_control] & Dma_control_enable)); 417 } 418 419 // Disable the channel. 420 421 void 422 Dma_jz4730_chip::disable() 423 { 424 _regs[Dma_control] = 0; 425 while (_regs[Dma_control] & Dma_control_enable); 426 } 427 428 // Obtain a channel object. 429 430 Dma_jz4730_channel * 431 Dma_jz4730_chip::get_channel(uint8_t channel, l4_cap_idx_t irq) 432 { 433 if (channel < 6) 434 return new Dma_jz4730_channel(this, channel, _start + 0x20 * channel, irq); 435 else 436 throw -L4_EINVAL; 437 } 438 439 // Return whether an interrupt is pending on the given channel. 440 441 bool 442 Dma_jz4730_chip::have_interrupt(uint8_t channel) 443 { 444 return _regs[Dma_irq_pending] & (1 << (Dma_irq_pending_ch0 - channel)) ? true : false; 445 } 446 447 448 449 // C language interface functions. 450 451 void *jz4730_dma_init(l4_addr_t start, l4_addr_t end, void *cpm) 452 { 453 return (void *) new Dma_jz4730_chip(start, end, static_cast<Cpm_jz4730_chip *>(cpm)); 454 } 455 456 void jz4730_dma_disable(void *dma_chip) 457 { 458 static_cast<Dma_jz4730_chip *>(dma_chip)->disable(); 459 } 460 461 void jz4730_dma_enable(void *dma_chip) 462 { 463 static_cast<Dma_jz4730_chip *>(dma_chip)->enable(); 464 } 465 466 void *jz4730_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq) 467 { 468 return static_cast<Dma_jz4730_chip *>(dma)->get_channel(channel, irq); 469 } 470 471 void jz4730_dma_set_output_polarity(void *dma_channel, enum Dma_jz4730_ext_level polarity) 472 { 473 static_cast<Dma_jz4730_channel *>(dma_channel)->set_output_polarity(polarity); 474 } 475 476 void jz4730_dma_set_end_of_process_mode(void *dma_channel, enum Dma_jz4730_ext_level mode) 477 { 478 static_cast<Dma_jz4730_channel *>(dma_channel)->set_end_of_process_mode(mode); 479 } 480 481 void jz4730_dma_set_output_mode_cycle(void *dma_channel, enum Dma_jz4730_ext_output_mode_cycle cycle) 482 { 483 static_cast<Dma_jz4730_channel *>(dma_channel)->set_output_mode_cycle(cycle); 484 } 485 486 void jz4730_dma_set_req_detect_mode(void *dma_channel, enum Dma_jz4730_ext_req_detect_mode mode) 487 { 488 static_cast<Dma_jz4730_channel *>(dma_channel)->set_req_detect_mode(mode); 489 } 490 491 unsigned int jz4730_dma_transfer(void *dma_channel, 492 uint32_t source, uint32_t destination, 493 unsigned int count, 494 int source_increment, int destination_increment, 495 uint8_t source_width, uint8_t destination_width, 496 uint8_t transfer_unit_size, 497 enum Dma_jz4730_request_type type) 498 { 499 return static_cast<Dma_jz4730_channel *>(dma_channel)->transfer(source, 500 destination, count, source_increment, destination_increment, source_width, 501 destination_width, transfer_unit_size, type); 502 } 503 504 unsigned int jz4730_dma_wait(void *dma_channel) 505 { 506 return static_cast<Dma_jz4730_channel *>(dma_channel)->wait(); 507 }