1 /* 2 * DMA support for the X1600. 3 * 4 * Copyright (C) 2021, 2023, 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-x1600.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 <systypes/thread.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 }; 41 42 enum Channel_regs 43 { 44 Dma_source = 0x00, // DSA 45 Dma_destination = 0x04, // DTA 46 Dma_transfer_count = 0x08, // DTC 47 Dma_request_source = 0x0c, // DRT 48 Dma_control_status = 0x10, // DCS 49 Dma_command = 0x14, // DCM 50 Dma_descriptor_address = 0x18, // DDA 51 Dma_stride = 0x1c, // DSD 52 }; 53 54 enum Dma_control_bits : unsigned 55 { 56 Dma_fast_msc_transfer = 0x80000000, // FMSC 57 Dma_fast_ssi_transfer = 0x40000000, // FSSI 58 Dma_fast_tssi_transfer = 0x20000000, // FTSSI 59 Dma_fast_uart_transfer = 0x10000000, // FUART 60 Dma_fast_aic_transfer = 0x08000000, // FAIC 61 Dma_control_trans_halted = 0x00000008, // HLT 62 Dma_control_address_error = 0x00000004, // AR 63 Dma_control_enable = 0x00000001, // DMAE 64 }; 65 66 enum Dma_transfer_count_bits : unsigned 67 { 68 Dma_transfer_count_mask = 0x00ffffff, 69 }; 70 71 enum Dma_request_source_bits : unsigned 72 { 73 Dma_request_type_mask = 0x0000003f, 74 }; 75 76 enum Dma_control_status_bits : unsigned 77 { 78 Dma_no_descriptor_transfer = 0x80000000, 79 Dma_8word_descriptor = 0x40000000, 80 Dma_copy_offset_mask = 0x0000ff00, 81 Dma_address_error = 0x00000010, 82 Dma_trans_completed = 0x00000008, 83 Dma_trans_halted = 0x00000004, 84 Dma_channel_enable = 0x00000001, 85 86 Dma_copy_offset_shift = 8, 87 }; 88 89 enum Dma_command_bits : unsigned 90 { 91 Dma_source_address_increment = 0x800000, 92 Dma_source_address_no_increment = 0x000000, 93 Dma_destination_address_increment = 0x400000, 94 Dma_destination_address_no_increment = 0x000000, 95 96 Dma_source_address_increment_wrap = 0x200000, 97 Dma_destination_address_increment_wrap = 0x100000, 98 Dma_recommended_data_unit_size_mask = 0x0f0000, 99 Dma_source_port_width_mask = 0x00c000, 100 Dma_destination_port_width_mask = 0x003000, 101 Dma_transfer_unit_size_mask = 0x000f00, 102 103 Dma_trans_unit_size_32_bit = 0x000000, 104 Dma_trans_unit_size_8_bit = 0x000100, 105 Dma_trans_unit_size_16_bit = 0x000200, 106 Dma_trans_unit_size_16_byte = 0x000300, 107 Dma_trans_unit_size_32_byte = 0x000400, 108 Dma_trans_unit_size_64_byte = 0x000500, 109 Dma_trans_unit_size_128_byte = 0x000600, 110 Dma_trans_unit_size_autonomous = 0x000700, 111 Dma_trans_unit_size_external = 0x000800, 112 113 Dma_source_address_compare_index = 0x000080, 114 Dma_destination_address_compare_index = 0x000040, 115 Dma_stride_enable = 0x000004, 116 Dma_transfer_irq_enable = 0x000002, 117 Dma_descriptor_link_enable = 0x000001, 118 119 Dma_recommended_data_unit_size_shift = 16, 120 Dma_source_port_width_shift = 14, 121 Dma_destination_port_width_shift = 12, 122 Dma_transfer_unit_size_shift = 8, 123 }; 124 125 enum Dma_port_width_values : unsigned 126 { 127 Dma_port_width_32_bit = 0, 128 Dma_port_width_8_bit = 1, 129 Dma_port_width_16_bit = 2, 130 }; 131 132 133 134 // Initialise a channel. 135 136 Dma_x1600_channel::Dma_x1600_channel(Dma_x1600_chip *chip, uint8_t channel, 137 l4_addr_t start, l4_cap_idx_t irq) 138 : _chip(chip), _channel(channel), _irq(irq) 139 { 140 _regs = new Hw::Mmio_register_block<32>(start); 141 142 // Initialise the transfer count. 143 144 _regs[Dma_transfer_count] = 0; 145 } 146 147 // Return the closest interval length greater than or equal to the number of 148 // units given encoded in the request detection interval length field of the 149 // control/status register. 150 151 uint32_t 152 Dma_x1600_channel::encode_req_detect_int_length(uint8_t units) 153 { 154 static uint8_t lengths[] = {0, 1, 2, 3, 4, 8, 16, 32, 64, 128}; 155 int i; 156 157 if (!units) 158 return 0; 159 160 for (i = 0; i <= 9; i++) 161 { 162 if (lengths[i] >= units) 163 break; 164 } 165 166 return i << Dma_recommended_data_unit_size_shift; 167 } 168 169 // Encode the appropriate source port width for the given request type. 170 171 uint32_t 172 Dma_x1600_channel::encode_source_port_width(uint8_t width) 173 { 174 switch (width) 175 { 176 case 1: 177 return Dma_port_width_8_bit << Dma_source_port_width_shift; 178 179 case 2: 180 return Dma_port_width_16_bit << Dma_source_port_width_shift; 181 182 default: 183 return Dma_port_width_32_bit << Dma_source_port_width_shift; 184 } 185 } 186 187 // Encode the appropriate destination port width for the given request type. 188 189 uint32_t 190 Dma_x1600_channel::encode_destination_port_width(uint8_t width) 191 { 192 switch (width) 193 { 194 case 1: 195 return Dma_port_width_8_bit << Dma_destination_port_width_shift; 196 197 case 2: 198 return Dma_port_width_16_bit << Dma_destination_port_width_shift; 199 200 default: 201 return Dma_port_width_32_bit << Dma_destination_port_width_shift; 202 } 203 } 204 205 // Encode the transfer unit size. 206 // NOTE: This does not handle the external case. 207 208 uint32_t 209 Dma_x1600_channel::encode_transfer_unit_size(uint8_t size) 210 { 211 switch (size) 212 { 213 case 0: 214 return Dma_trans_unit_size_autonomous; 215 216 case 1: 217 return Dma_trans_unit_size_8_bit; 218 219 case 2: 220 return Dma_trans_unit_size_16_bit; 221 222 case 16: 223 return Dma_trans_unit_size_16_byte; 224 225 case 32: 226 return Dma_trans_unit_size_32_byte; 227 228 case 64: 229 return Dma_trans_unit_size_64_byte; 230 231 case 128: 232 return Dma_trans_unit_size_128_byte; 233 234 default: 235 return Dma_trans_unit_size_32_bit; 236 } 237 } 238 239 // Transfer data between memory locations, returning the number of units that 240 // should have been transferred. 241 242 unsigned int 243 Dma_x1600_channel::transfer(uint32_t source, uint32_t destination, 244 unsigned int count, 245 bool source_increment, bool destination_increment, 246 uint8_t source_width, uint8_t destination_width, 247 uint8_t transfer_unit_size, 248 enum Dma_x1600_request_type type) 249 { 250 // Ensure an absence of address error and halt conditions globally and in this channel. 251 252 if (error() || halted()) 253 return 0; 254 255 // Ensure a zero transfer count for this channel. 256 257 if (_regs[Dma_transfer_count]) 258 return 0; 259 260 // Disable the channel. 261 262 _regs[Dma_control_status] = _regs[Dma_control_status] & ~Dma_channel_enable; 263 264 // Set addresses. 265 266 _regs[Dma_source] = source; 267 _regs[Dma_destination] = destination; 268 269 // Set transfer count to the number of units. 270 271 unsigned int units = count < Dma_transfer_count_mask ? count : Dma_transfer_count_mask; 272 273 _regs[Dma_transfer_count] = units; 274 275 // Set auto-request for memory-to-memory transfers. Otherwise, set the 276 // indicated request type. 277 278 _regs[Dma_request_source] = type; 279 280 // For a descriptor, the actual fields would be populated instead of the 281 // command register, descriptor transfer would be indicated in the control/ 282 // status register along with the appropriate descriptor size indicator. 283 284 /* NOTE: To be considered... 285 * request detection interval length (for autonomous mode) 286 */ 287 288 _regs[Dma_command] = (source_increment ? Dma_source_address_increment : Dma_source_address_no_increment) | 289 (destination_increment ? Dma_destination_address_increment : Dma_destination_address_no_increment) | 290 encode_source_port_width(source_width) | 291 encode_destination_port_width(destination_width) | 292 encode_transfer_unit_size(transfer_unit_size) | 293 Dma_transfer_irq_enable; 294 295 // For a descriptor, the descriptor address would be set and the doorbell 296 // register field for the channel set. 297 298 // Enable the channel (and peripheral). 299 300 _regs[Dma_control_status] = Dma_no_descriptor_transfer | 301 Dma_channel_enable; 302 303 // Return the number of units to transfer. 304 305 return units; 306 } 307 308 // Wait for a transfer to end, returning the number of units remaining to be 309 // transferred. 310 311 unsigned int 312 Dma_x1600_channel::wait() 313 { 314 // An interrupt will occur upon completion, the completion flag will be set 315 // and the transfer count will be zero. 316 317 unsigned int remaining = 0; 318 319 do 320 { 321 if (!wait_for_irq(1000000)) 322 printf("status = %x\n", (uint32_t) _regs[Dma_control_status]); 323 else 324 { 325 remaining = _regs[Dma_transfer_count]; 326 ack_irq(); 327 break; 328 } 329 } 330 while (!error() && !halted() && !completed()); 331 332 // Reset the channel status. 333 334 _regs[Dma_control_status] = _regs[Dma_control_status] & ~(Dma_channel_enable | 335 Dma_trans_completed | Dma_address_error | 336 Dma_trans_halted); 337 _regs[Dma_transfer_count] = 0; 338 339 return remaining; 340 } 341 342 // Wait indefinitely for an interrupt request, returning true if one was delivered. 343 344 bool 345 Dma_x1600_channel::wait_for_irq() 346 { 347 if (l4_error(l4_rcv_ep_bind_thread(_irq, get_current_thread(), 0))) 348 return false; 349 350 return !l4_error(l4_irq_receive(_irq, L4_IPC_NEVER)) && _chip->have_interrupt(_channel); 351 } 352 353 // Wait up to the given timeout (in microseconds) for an interrupt request, 354 // returning true if one was delivered. 355 356 bool 357 Dma_x1600_channel::wait_for_irq(unsigned int timeout) 358 { 359 if (l4_error(l4_rcv_ep_bind_thread(_irq, get_current_thread(), 0))) 360 return false; 361 362 return !l4_error(l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(timeout)))) && _chip->have_interrupt(_channel); 363 } 364 365 // Acknowledge an interrupt condition. 366 367 void 368 Dma_x1600_channel::ack_irq() 369 { 370 _chip->ack_irq(_channel); 371 } 372 373 // Return whether a transfer has completed. 374 375 bool 376 Dma_x1600_channel::completed() 377 { 378 return _regs[Dma_control_status] & Dma_trans_completed ? true : false; 379 } 380 381 // Return whether an address error condition has arisen. 382 383 bool 384 Dma_x1600_channel::error() 385 { 386 return _chip->error() || (_regs[Dma_control_status] & Dma_address_error ? true : false); 387 } 388 389 // Return whether a transfer has halted. 390 391 bool 392 Dma_x1600_channel::halted() 393 { 394 return _chip->halted() || (_regs[Dma_control_status] & Dma_trans_halted ? true : false); 395 } 396 397 398 399 // Initialise the I2C controller. 400 401 Dma_x1600_chip::Dma_x1600_chip(l4_addr_t start, l4_addr_t end, 402 Cpm_x1600_chip *cpm) 403 : _start(start), _end(end), _cpm(cpm) 404 { 405 _regs = new Hw::Mmio_register_block<32>(start); 406 } 407 408 // Enable the peripheral. 409 410 void 411 Dma_x1600_chip::enable() 412 { 413 // Make sure that the DMA clock is available. 414 415 _cpm->start_clock(Clock_dma); 416 417 _regs[Dma_control] = Dma_control_enable; 418 while (!(_regs[Dma_control] & Dma_control_enable)); 419 } 420 421 // Disable the channel. 422 423 void 424 Dma_x1600_chip::disable() 425 { 426 _regs[Dma_control] = 0; 427 while (_regs[Dma_control] & Dma_control_enable); 428 } 429 430 // Obtain a channel object. 431 432 Dma_x1600_channel * 433 Dma_x1600_chip::get_channel(uint8_t channel, l4_cap_idx_t irq) 434 { 435 if (channel < 32) 436 return new Dma_x1600_channel(this, channel, _start + 0x20 * channel, irq); 437 else 438 throw -L4_EINVAL; 439 } 440 441 // Return whether an interrupt is pending on the given channel. 442 443 bool 444 Dma_x1600_chip::have_interrupt(uint8_t channel) 445 { 446 return _regs[Dma_irq_pending] & (1UL << channel) ? true : false; 447 } 448 449 // Acknowledge an interrupt condition on the given channel. 450 451 void 452 Dma_x1600_chip::ack_irq(uint8_t channel) 453 { 454 _regs[Dma_irq_pending] = _regs[Dma_irq_pending] & ~(1UL << channel); 455 } 456 457 // Return whether an address error condition has arisen. 458 459 bool 460 Dma_x1600_chip::error() 461 { 462 return _regs[Dma_control] & Dma_control_address_error ? true : false; 463 } 464 465 // Return whether a transfer has halted. 466 467 bool 468 Dma_x1600_chip::halted() 469 { 470 return _regs[Dma_control] & Dma_control_trans_halted ? true : false; 471 } 472 473 474 475 // C language interface functions. 476 477 void *x1600_dma_init(l4_addr_t start, l4_addr_t end, void *cpm) 478 { 479 return (void *) new Dma_x1600_chip(start, end, static_cast<Cpm_x1600_chip *>(cpm)); 480 } 481 482 void x1600_dma_disable(void *dma_chip) 483 { 484 static_cast<Dma_x1600_chip *>(dma_chip)->disable(); 485 } 486 487 void x1600_dma_enable(void *dma_chip) 488 { 489 static_cast<Dma_x1600_chip *>(dma_chip)->enable(); 490 } 491 492 void *x1600_dma_get_channel(void *dma, uint8_t channel, l4_cap_idx_t irq) 493 { 494 return static_cast<Dma_x1600_chip *>(dma)->get_channel(channel, irq); 495 } 496 497 unsigned int x1600_dma_transfer(void *dma_channel, 498 uint32_t source, uint32_t destination, 499 unsigned int count, 500 int source_increment, int destination_increment, 501 uint8_t source_width, uint8_t destination_width, 502 uint8_t transfer_unit_size, 503 enum Dma_x1600_request_type type) 504 { 505 return static_cast<Dma_x1600_channel *>(dma_channel)->transfer(source, 506 destination, count, source_increment, destination_increment, source_width, 507 destination_width, transfer_unit_size, type); 508 } 509 510 unsigned int x1600_dma_wait(void *dma_channel) 511 { 512 return static_cast<Dma_x1600_channel *>(dma_channel)->wait(); 513 }