1 /* 2 * Perform SPI communication using the JZ4780/X1600 SPI peripheral. 3 * 4 * Copyright (C) 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/byteorder.h> 23 #include <l4/devices/dma.h> 24 #include <l4/devices/spi-jz4780.h> 25 #include <l4/sys/err.h> 26 #include <string.h> 27 28 29 30 /* Register definitions. */ 31 32 enum Regs 33 { 34 Ssi_data = 0x00, // SSIDR 35 Ssi_control0 = 0x04, // SSICR0 36 Ssi_control1 = 0x08, // SSICR1 37 Ssi_status = 0x0c, // SSISR 38 Ssi_interval_time = 0x10, // SSIITR 39 Ssi_char_per_frame = 0x14, // SSIICR 40 Ssi_clock = 0x18, // SSICGR 41 Ssi_recv_counter = 0x1c, // SSIRCNT 42 43 /* Register block offset. */ 44 45 Ssi_block_offset = 0x1000, 46 }; 47 48 enum Ssi_data_bits : unsigned 49 { 50 Ssi_data_gpc_set = 0x10000, 51 Ssi_data_gpc_unset = 0x00000, 52 }; 53 54 enum Ssi_control0_bits : unsigned 55 { 56 Ssi_trans_endian_mask = 0xc0000, 57 Ssi_trans_endian_msbyte_msbit = 0x00000, 58 Ssi_trans_endian_msbyte_lsbit = 0x40000, 59 Ssi_trans_endian_lsbyte_lsbit = 0x80000, 60 Ssi_trans_endian_lsbyte_msbit = 0xc0000, 61 62 Ssi_recv_endian_mask = 0x30000, 63 Ssi_recv_endian_msbyte_msbit = 0x00000, 64 Ssi_recv_endian_msbyte_lsbit = 0x10000, 65 Ssi_recv_endian_lsbyte_lsbit = 0x20000, 66 Ssi_recv_endian_lsbyte_msbit = 0x30000, 67 68 Ssi_enable = 0x08000, 69 Ssi_enable_trans_half_empty = 0x04000, 70 Ssi_enable_recv_half_full = 0x02000, 71 Ssi_enable_trans_error = 0x01000, 72 Ssi_enable_recv_error = 0x00800, 73 Ssi_loopback = 0x00400, 74 Ssi_recv_finish_control = 0x00200, 75 Ssi_recv_finished = 0x00100, 76 Ssi_enable_auto_clear_underrun = 0x00080, 77 Ssi_select_pin_is_ce2 = 0x00040, 78 Ssi_use_recv_count = 0x00010, 79 Ssi_old_fifo_empty_mode = 0x00008, 80 Ssi_trans_flush = 0x00004, 81 Ssi_recv_flush = 0x00002, 82 Ssi_disable_recv = 0x00001, 83 }; 84 85 enum Ssi_control1_bits : unsigned 86 { 87 Ssi_active_mask = 0xc0000000, 88 Ssi_active_ce_low = 0x00000000, 89 Ssi_active_ce_high = 0x40000000, 90 Ssi_active_ce2_low = 0x00000000, 91 Ssi_active_ce2_high = 0x80000000, 92 93 Ssi_clock_start_delay_mask = 0x30000000, 94 Ssi_clock_start_delay_default = 0x00000000, 95 Ssi_clock_start_delay_plus_1 = 0x10000000, 96 Ssi_clock_start_delay_plus_2 = 0x20000000, 97 Ssi_clock_start_delay_plus_3 = 0x30000000, 98 99 Ssi_clock_stop_delay_mask = 0x0c000000, 100 Ssi_clock_stop_delay_default = 0x00000000, 101 Ssi_clock_stop_delay_plus_1 = 0x04000000, 102 Ssi_clock_stop_delay_plus_2 = 0x08000000, 103 Ssi_clock_stop_delay_plus_3 = 0x0c000000, 104 105 /* X1600... */ 106 107 Ssi_gpc_level_from_gpc_bit = 0x00000000, 108 Ssi_gpc_level_from_gpc_level = 0x02000000, 109 110 /* Common... */ 111 112 Ssi_interval_assert_ce_or_ce2 = 0x01000000, 113 Ssi_trans_empty_unfinished = 0x00800000, 114 115 Ssi_format_mask = 0x00300000, 116 Ssi_format_spi = 0x00000000, 117 Ssi_format_ssp = 0x00100000, 118 Ssi_format_microwire1 = 0x00200000, 119 Ssi_format_microwire2 = 0x00300000, 120 121 Ssi_trans_threshold_mask = 0x000f0000, 122 Ssi_command_length_mask = 0x0000f000, 123 Ssi_recv_threshold_mask = 0x00000f00, 124 Ssi_char_length_mask = 0x000000f8, 125 126 /* X1600... */ 127 128 Ssi_gpc_level = 0x00000004, // see Ssi_gpc_level_from_gpc_level 129 130 /* Common... */ 131 132 Spi_clock_assert_sample = 0x00000000, // phase #0 133 Spi_clock_assert_drive = 0x00000002, // phase #1 134 Spi_clock_idle_low_level = 0x00000000, // polarity #0 135 Spi_clock_idle_high_level = 0x00000001, // polarity #1 136 }; 137 138 enum Ssi_control1_shifts : unsigned 139 { 140 Ssi_trans_threshold_shift = 16, 141 Ssi_command_length_shift = 12, 142 Ssi_recv_threshold_shift = 8, 143 Ssi_char_length_shift = 3, 144 }; 145 146 enum Ssi_control1_limits : unsigned 147 { 148 Ssi_trans_threshold_limit = 15, 149 Ssi_command_length_limit = 15, 150 Ssi_recv_threshold_limit = 15, 151 Ssi_char_length_limit = 30, 152 }; 153 154 enum Ssi_status_bits : unsigned 155 { 156 Ssi_trans_char_count_mask = 0x00ff0000, 157 Ssi_recv_char_count_mask = 0x0000ff00, 158 Ssi_trans_ended = 0x00000080, 159 Ssi_trans_busy = 0x00000040, 160 Ssi_trans_fifo_full = 0x00000020, 161 Ssi_recv_fifo_empty = 0x00000010, 162 Ssi_trans_fifo_half_empty = 0x00000008, 163 Ssi_recv_fifo_half_full = 0x00000004, 164 Ssi_trans_underrun = 0x00000002, 165 Ssi_recv_overrun = 0x00000001, 166 }; 167 168 enum Ssi_status_shifts : unsigned 169 { 170 Ssi_trans_char_count_shift = 16, 171 Ssi_recv_char_count_shift = 8, 172 }; 173 174 enum Ssi_status_limits : unsigned 175 { 176 Ssi_trans_char_count_limit = 0xff, 177 Ssi_recv_char_count_limit = 0xff, 178 }; 179 180 enum Ssi_interval_time_bits : unsigned 181 { 182 Ssi_interval_clock_mask = 0x8000, 183 Ssi_interval_clock_bit_clock = 0x0000, 184 Ssi_interval_clock_32k_clock = 0x8000, 185 Ssi_interval_time_mask = 0x3fff, 186 }; 187 188 enum Ssi_char_per_frame_bits : unsigned 189 { 190 Ssi_char_per_frame_mask = 0x7, 191 }; 192 193 enum Ssi_clock_bits : unsigned 194 { 195 Ssi_clock_frequency_mask = 0xff, 196 }; 197 198 enum Ssi_recv_counter_bits : unsigned 199 { 200 Ssi_recv_counter_mask = 0xffff, 201 }; 202 203 204 205 /* Initialise a channel. */ 206 207 Spi_jz4780_channel::Spi_jz4780_channel(l4_addr_t spi_start, l4_addr_t start, 208 enum Clock_identifiers clock, 209 Cpm_jz4780_chip *cpm, 210 Dma_jz4780_channel *dma, 211 enum Dma_jz4780_request_type request_type, 212 uint64_t frequency) 213 : _spi_start(spi_start), _clock(clock), _cpm(cpm), _dma(dma), 214 _request_type(request_type), _frequency(frequency) 215 { 216 _regs = new Hw::Mmio_register_block<32>(start); 217 _cpm->start_clock(clock); 218 219 /* Disable the channel while configuring: send MSB first, big endian wire 220 representation. Disable reception. */ 221 222 _regs[Ssi_control0] = Ssi_trans_endian_msbyte_msbit | 223 Ssi_select_pin_is_ce2 | 224 Ssi_disable_recv; 225 226 /* Set default transfer properties. */ 227 228 configure_transfer(8); 229 230 /* Select "normal" mode. */ 231 232 _regs[Ssi_interval_time] = 0; 233 234 /* Limit the frequency to half that of the device clock. */ 235 236 if (_frequency >= _cpm->get_frequency(_clock)) 237 _frequency = _cpm->get_frequency(_clock) / 2; 238 239 /* SSI_CLK = DEV_CLK / (2 * (divider + 1)) */ 240 241 uint32_t divider = _cpm->get_frequency(_clock) / (_frequency * 2) - 1; 242 243 _regs[Ssi_clock] = divider < Ssi_clock_frequency_mask ? divider : Ssi_clock_frequency_mask; 244 245 /* Enable the channel. */ 246 247 _regs[Ssi_control0] = _regs[Ssi_control0] | Ssi_enable; 248 } 249 250 /* NOTE: More transfer characteristics should be configurable. */ 251 252 void Spi_jz4780_channel::configure_transfer(uint8_t char_size) 253 { 254 uint32_t char_length; 255 256 if (char_size < 2) 257 char_length = 0; 258 else 259 { 260 char_length = char_size - 2; 261 262 if (char_size > Ssi_char_length_limit) 263 char_length = Ssi_char_length_limit; 264 } 265 266 /* Clear the status. */ 267 268 _regs[Ssi_control0] = _regs[Ssi_control0] | Ssi_trans_flush | Ssi_recv_flush; 269 _regs[Ssi_status] = 0; 270 271 /* Indicate the desired character size. 272 273 Use active low device selection, SPI format with active low clock, with 274 data driven on the falling (asserted) clock and sampled on the rising 275 clock 276 277 The unfinished flag prevents the transaction from finishing if the FIFO is 278 empty. It is not used here since it appears to prevent any meaningful 279 testing of the busy and end flags. */ 280 281 _regs[Ssi_control1] = (char_length << Ssi_char_length_shift) | 282 ((Ssi_trans_threshold_limit / 2) << Ssi_trans_threshold_shift) | 283 Ssi_format_spi | Ssi_active_ce2_low | 284 Spi_clock_assert_drive | Spi_clock_idle_high_level; 285 } 286 287 /* Transfer the given number of bytes from a buffer. */ 288 289 uint32_t 290 Spi_jz4780_channel::send(uint32_t bytes, const uint8_t data[]) 291 { 292 return send_units(bytes, data, 1, 8, false); 293 } 294 295 /* Transfer the given number of bytes from a buffer together with control 296 values. Return the number of bytes transferred. */ 297 298 uint32_t 299 Spi_jz4780_channel::send_dc(uint32_t bytes, const uint8_t data[], 300 const int dc[], uint8_t char_size, bool big_endian) 301 { 302 configure_transfer(char_size); 303 304 uint32_t transferred, char_unit; 305 uint8_t char_unit_size = ((char_size ? char_size - 1 : 0) / 8) + 1; 306 uint32_t char_mask = (1 << char_size) - 1; 307 308 for (transferred = 0, char_unit = 0; transferred < bytes; 309 transferred += char_unit_size, char_unit++) 310 { 311 uint32_t value = get_stored_value(&data[transferred], char_unit_size, big_endian); 312 313 /* Relocate the data/command level to bit 16. */ 314 315 uint32_t command = dc[char_unit] ? Ssi_data_gpc_set : Ssi_data_gpc_unset; 316 317 /* Combine the character with the data/command bit. */ 318 319 _regs[Ssi_data] = (value & char_mask) | command; 320 } 321 322 wait_busy(); 323 324 return transferred; 325 } 326 327 /* Transfer the given number of bytes from a buffer using the given unit size in 328 bytes and character size in bits. The bytes are stored in a big endian 329 arrangement. Return the number of bytes transferred. */ 330 331 uint32_t 332 Spi_jz4780_channel::send_units(uint32_t bytes, const uint8_t data[], 333 uint8_t unit_size, uint8_t char_size, 334 bool big_endian) 335 { 336 configure_transfer(char_size); 337 338 uint32_t transferred; 339 uint32_t char_mask = (1 << char_size) - 1; 340 341 for (transferred = 0; transferred < bytes; transferred += unit_size) 342 { 343 uint32_t value = get_stored_value(&data[transferred], unit_size, big_endian); 344 345 /* Relocate any command bit to bit 16 for byte characters. */ 346 347 uint32_t command = (char_size < 16) && (value & (1 << char_size)) 348 ? Ssi_data_gpc_set : Ssi_data_gpc_unset; 349 350 /* Combine the character portion of the unit with the command. */ 351 352 _regs[Ssi_data] = (value & char_mask) | command; 353 } 354 355 wait_busy(); 356 357 return transferred; 358 } 359 360 /* Transfer the given number of bytes from a DMA region using the given 361 unit size in bytes and character size in bits. Return the number of bytes 362 transferred. */ 363 364 uint32_t 365 Spi_jz4780_channel::transfer(l4_addr_t vaddr, 366 l4re_dma_space_dma_addr_t paddr, 367 uint32_t count, uint8_t unit_size, 368 uint8_t char_size, 369 l4_addr_t desc_vaddr, 370 l4re_dma_space_dma_addr_t desc_paddr) 371 { 372 /* Employ a non-DMA transfer if no usable physical address is provided. 373 Assume little endian byte ordering in line with the native value 374 representation. */ 375 376 if (!paddr) 377 return send_units(count, (const uint8_t *) vaddr, unit_size, char_size, 378 false); 379 380 /* Configure and initiate a DMA transfer with optional descriptor. */ 381 382 configure_transfer(char_size); 383 384 uint32_t transferred = 0; 385 uint32_t unit_count = count / unit_size; 386 uint32_t to_transfer = _dma->transfer(paddr, _spi_start + Ssi_data, 387 unit_count, true, false, 388 unit_size, unit_size, unit_size, 389 _request_type, desc_vaddr, desc_paddr); 390 391 /* Wait if not using a descriptor, which could be configured in a cycle to 392 cause an endless, repeating transfer, perhaps updating a display, for 393 example. */ 394 395 if (to_transfer && !desc_vaddr) 396 { 397 transferred = to_transfer ? (unit_count - _dma->wait()) * unit_size : 0; 398 wait_busy(); 399 } 400 else 401 transferred = to_transfer * unit_size; 402 403 return transferred; 404 } 405 406 /* Wait for the busy condition to clear or for a limited period. */ 407 408 void 409 Spi_jz4780_channel::wait_busy() 410 { 411 for (unsigned int i = 0; i < (1 << 20) && (_regs[Ssi_status] & Ssi_trans_busy); i++); 412 } 413 414 415 416 /* Initialise the peripheral abstraction. */ 417 418 Spi_jz4780_chip::Spi_jz4780_chip(l4_addr_t spi_start, l4_addr_t start, 419 l4_addr_t end, Cpm_jz4780_chip *cpm) 420 : _spi_start(spi_start), _start(start), _end(end), _cpm(cpm) 421 { 422 } 423 424 Spi_jz4780_channel * 425 Spi_jz4780_chip::get_channel(uint8_t channel, Dma_jz4780_channel *dma, 426 uint64_t frequency) 427 { 428 // NOTE: Only sending is supported. 429 430 enum Dma_jz4780_request_type request_types[] = {Dma_request_ssi0_out, Dma_request_ssi1_out}; 431 enum Clock_identifiers clocks[] = {Clock_ssi0, Clock_ssi1}; 432 433 if (channel < 2) 434 return new Spi_jz4780_channel(_spi_start + channel * Ssi_block_offset, 435 _start + channel * Ssi_block_offset, 436 clocks[channel], 437 _cpm, dma, request_types[channel], frequency); 438 else 439 throw -L4_EINVAL; 440 } 441 442 443 444 /* C language interface. */ 445 446 void *jz4780_spi_init(l4_addr_t spi_start, l4_addr_t start, l4_addr_t end, void *cpm) 447 { 448 return new Spi_jz4780_chip(spi_start, start, end, static_cast<Cpm_jz4780_chip *>(cpm)); 449 } 450 451 void *jz4780_spi_get_channel(void *spi, uint8_t channel, void *dma, uint64_t frequency) 452 { 453 return static_cast<Spi_jz4780_chip *>(spi)->get_channel(channel, 454 static_cast<Dma_jz4780_channel *>(dma), frequency); 455 } 456 457 uint32_t jz4780_spi_send(void *channel, uint32_t bytes, const uint8_t data[]) 458 { 459 return static_cast<Spi_jz4780_channel *>(channel)->send(bytes, data); 460 } 461 462 uint32_t jz4780_spi_send_dc(void *channel, uint32_t bytes, const uint8_t data[], 463 const int dc[], uint8_t char_size, int big_endian) 464 { 465 return static_cast<Spi_jz4780_channel *>(channel)->send_dc(bytes, data, dc, 466 char_size, big_endian); 467 } 468 469 uint32_t jz4780_spi_send_units(void *channel, uint32_t bytes, const uint8_t data[], 470 uint8_t unit_size, uint8_t char_size, int big_endian) 471 { 472 return static_cast<Spi_jz4780_channel *>(channel)->send_units(bytes, data, 473 unit_size, char_size, big_endian); 474 } 475 476 uint32_t jz4780_spi_transfer(void *channel, l4_addr_t vaddr, 477 l4re_dma_space_dma_addr_t paddr, 478 uint32_t count, uint8_t unit_size, 479 uint8_t char_size) 480 { 481 return static_cast<Spi_jz4780_channel *>(channel)->transfer(vaddr, paddr, 482 count, unit_size, char_size); 483 } 484 485 uint32_t jz4780_spi_transfer_descriptor(void *channel, l4_addr_t vaddr, 486 l4re_dma_space_dma_addr_t paddr, 487 uint32_t count, uint8_t unit_size, 488 uint8_t char_size, l4_addr_t desc_vaddr, 489 l4re_dma_space_dma_addr_t desc_paddr) 490 { 491 return static_cast<Spi_jz4780_channel *>(channel)->transfer(vaddr, paddr, 492 count, unit_size, char_size, desc_vaddr, desc_paddr); 493 }