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