pio_rp1.c
1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2024 Raspberry Pi Ltd. 4 * All rights reserved. 5 */ 6 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <malloc.h> 10 #include <stdio.h> 11 #include <string.h> 12 #include <unistd.h> 13 14 #define PIOLIB_INTERNALS 15 16 #include "pio_platform.h" 17 18 #define pio_encode_delay _pio_encode_delay 19 #define pio_encode_sideset _pio_encode_sideset 20 #define pio_encode_sideset_opt _pio_encode_sideset_opt 21 #define pio_encode_jmp _pio_encode_jmp 22 #define pio_encode_jmp_not_x _pio_encode_jmp_not_x 23 #define pio_encode_jmp_x_dec _pio_encode_jmp_x_dec 24 #define pio_encode_jmp_not_y _pio_encode_jmp_not_y 25 #define pio_encode_jmp_y_dec _pio_encode_jmp_y_dec 26 #define pio_encode_jmp_x_ne_y _pio_encode_jmp_x_ne_y 27 #define pio_encode_jmp_pin _pio_encode_jmp_pin 28 #define pio_encode_jmp_not_osre _pio_encode_jmp_not_osre 29 #define pio_encode_wait_gpio _pio_encode_wait_gpio 30 #define pio_encode_wait_pin _pio_encode_wait_pin 31 #define pio_encode_wait_irq _pio_encode_wait_irq 32 #define pio_encode_in _pio_encode_in 33 #define pio_encode_out _pio_encode_out 34 #define pio_encode_push _pio_encode_push 35 #define pio_encode_pull _pio_encode_pull 36 #define pio_encode_mov _pio_encode_mov 37 #define pio_encode_mov_not _pio_encode_mov_not 38 #define pio_encode_mov_reverse _pio_encode_mov_reverse 39 #define pio_encode_irq_set _pio_encode_irq_set 40 #define pio_encode_irq_wait _pio_encode_irq_wait 41 #define pio_encode_irq_clear _pio_encode_irq_clear 42 #define pio_encode_set _pio_encode_set 43 #define pio_encode_nop _pio_encode_nop 44 #include "hardware/pio_instructions.h" 45 #undef pio_encode_delay 46 #undef pio_encode_sideset 47 #undef pio_encode_sideset_opt 48 #undef pio_encode_jmp 49 #undef pio_encode_jmp_not_x 50 #undef pio_encode_jmp_x_dec 51 #undef pio_encode_jmp_not_y 52 #undef pio_encode_jmp_y_dec 53 #undef pio_encode_jmp_x_ne_y 54 #undef pio_encode_jmp_pin 55 #undef pio_encode_jmp_not_osre 56 #undef pio_encode_wait_gpio 57 #undef pio_encode_wait_pin 58 #undef pio_encode_wait_irq 59 #undef pio_encode_in 60 #undef pio_encode_out 61 #undef pio_encode_push 62 #undef pio_encode_pull 63 #undef pio_encode_mov 64 #undef pio_encode_mov_not 65 #undef pio_encode_mov_reverse 66 #undef pio_encode_irq_set 67 #undef pio_encode_irq_wait 68 #undef pio_encode_irq_clear 69 #undef pio_encode_set 70 #undef pio_encode_nop 71 72 #include "hardware/gpio.h" 73 #include "hardware/pio.h" 74 #include "hardware/regs/proc_pio.h" 75 #include "piolib.h" 76 #include "piolib_priv.h" 77 #include "rp1_pio_if.h" 78 79 typedef struct rp1_pio_handle { 80 struct pio_instance base; 81 const char *devname; 82 int fd; 83 } * RP1_PIO; 84 85 #define smc_to_rp1(_config, _c) \ 86 rp1_pio_sm_config *_c = (rp1_pio_sm_config *)_config 87 88 #define GPIOS_MASK ((1 << RP1_PIO_GPIO_COUNT) - 1) 89 90 STATIC_ASSERT(sizeof(rp1_pio_sm_config) <= sizeof(pio_sm_config)); 91 92 static inline void check_sm_param(__unused uint sm) { 93 valid_params_if(PIO, sm < RP1_PIO_SM_COUNT); 94 } 95 96 static inline void check_sm_mask(__unused uint mask) { 97 valid_params_if(PIO, mask < (1u << RP1_PIO_SM_COUNT)); 98 } 99 100 static pio_sm_config rp1_pio_get_default_sm_config(PIO pio) { 101 pio_sm_config c = {{0}}; 102 sm_config_set_clkdiv_int_frac(&c, 1, 0); 103 sm_config_set_wrap(&c, 0, 31); 104 sm_config_set_in_shift(&c, true, false, 32); 105 sm_config_set_out_shift(&c, true, false, 32); 106 return c; 107 } 108 109 static uint rp1_pio_encode_delay(PIO pio, uint cycles) { 110 return _pio_encode_delay(cycles); 111 } 112 113 static uint rp1_pio_encode_sideset(PIO pio, uint sideset_bit_count, 114 uint value) { 115 return _pio_encode_sideset(sideset_bit_count, value); 116 } 117 118 static uint rp1_pio_encode_sideset_opt(PIO pio, uint sideset_bit_count, 119 uint value) { 120 return _pio_encode_sideset_opt(sideset_bit_count, value); 121 } 122 123 static uint rp1_pio_encode_jmp(PIO pio, uint addr) { 124 return _pio_encode_jmp(addr); 125 } 126 127 static uint rp1_pio_encode_jmp_not_x(PIO pio, uint addr) { 128 return _pio_encode_jmp_not_x(addr); 129 } 130 131 static uint rp1_pio_encode_jmp_x_dec(PIO pio, uint addr) { 132 return _pio_encode_jmp_x_dec(addr); 133 } 134 135 static uint rp1_pio_encode_jmp_not_y(PIO pio, uint addr) { 136 return _pio_encode_jmp_not_y(addr); 137 } 138 139 static uint rp1_pio_encode_jmp_y_dec(PIO pio, uint addr) { 140 return _pio_encode_jmp_y_dec(addr); 141 } 142 143 static uint rp1_pio_encode_jmp_x_ne_y(PIO pio, uint addr) { 144 return _pio_encode_jmp_x_ne_y(addr); 145 } 146 147 static uint rp1_pio_encode_jmp_pin(PIO pio, uint addr) { 148 return _pio_encode_jmp_pin(addr); 149 } 150 151 static uint rp1_pio_encode_jmp_not_osre(PIO pio, uint addr) { 152 return _pio_encode_jmp_not_osre(addr); 153 } 154 155 static uint rp1_pio_encode_wait_gpio(PIO pio, bool polarity, uint gpio) { 156 return _pio_encode_wait_gpio(polarity, gpio); 157 } 158 159 static uint rp1_pio_encode_wait_pin(PIO pio, bool polarity, uint pin) { 160 return _pio_encode_wait_pin(polarity, pin); 161 } 162 163 static uint rp1_pio_encode_wait_irq(PIO pio, bool polarity, bool relative, 164 uint irq) { 165 return _pio_encode_wait_irq(polarity, relative, irq); 166 } 167 168 static uint rp1_pio_encode_in(PIO pio, enum pio_src_dest src, uint count) { 169 return _pio_encode_in(src, count); 170 } 171 172 static uint rp1_pio_encode_out(PIO pio, enum pio_src_dest dest, uint count) { 173 return _pio_encode_out(dest, count); 174 } 175 176 static uint rp1_pio_encode_push(PIO pio, bool if_full, bool block) { 177 return _pio_encode_push(if_full, block); 178 } 179 180 static uint rp1_pio_encode_pull(PIO pio, bool if_empty, bool block) { 181 return _pio_encode_pull(if_empty, block); 182 } 183 184 static uint rp1_pio_encode_mov(PIO pio, enum pio_src_dest dest, 185 enum pio_src_dest src) { 186 return _pio_encode_mov(dest, src); 187 } 188 189 static uint rp1_pio_encode_mov_not(PIO pio, enum pio_src_dest dest, 190 enum pio_src_dest src) { 191 return _pio_encode_mov_not(dest, src); 192 } 193 194 static uint rp1_pio_encode_mov_reverse(PIO pio, enum pio_src_dest dest, 195 enum pio_src_dest src) { 196 return _pio_encode_mov_reverse(dest, src); 197 } 198 199 static uint rp1_pio_encode_irq_set(PIO pio, bool relative, uint irq) { 200 return _pio_encode_irq_set(relative, irq); 201 } 202 203 static uint rp1_pio_encode_irq_wait(PIO pio, bool relative, uint irq) { 204 return _pio_encode_irq_wait(relative, irq); 205 } 206 207 static uint rp1_pio_encode_irq_clear(PIO pio, bool relative, uint irq) { 208 return _pio_encode_irq_clear(relative, irq); 209 } 210 211 static uint rp1_pio_encode_set(PIO pio, enum pio_src_dest dest, uint value) { 212 return _pio_encode_set(dest, value); 213 } 214 215 static uint rp1_pio_encode_nop(PIO pio) { return _pio_encode_nop(); } 216 217 static int rp1_ioctl(PIO pio, int request, void *args) { 218 RP1_PIO rp = (RP1_PIO)pio; 219 int err = ioctl(rp->fd, request, args); 220 switch (err) { 221 case -EREMOTEIO: 222 case -ETIMEDOUT: 223 pio_panic("Error communicating with RP1"); 224 break; 225 default: 226 break; 227 } 228 return err; 229 } 230 231 static int rp1_pio_sm_config_xfer(PIO pio, uint sm, uint dir, uint buf_size, 232 uint buf_count) { 233 struct rp1_pio_sm_config_xfer_args args = { 234 .sm = sm, .dir = dir, .buf_size = buf_size, .buf_count = buf_count}; 235 int err; 236 check_sm_param(sm); 237 err = rp1_ioctl(pio, PIO_IOC_SM_CONFIG_XFER, &args); 238 return (err > 0); 239 } 240 241 static int rp1_pio_sm_xfer_data(PIO pio, uint sm, uint dir, uint data_bytes, 242 void *data) { 243 struct rp1_pio_sm_xfer_data_args args = { 244 .sm = sm, .dir = dir, .data_bytes = data_bytes, .data = data}; 245 int err; 246 check_sm_param(sm); 247 err = rp1_ioctl(pio, PIO_IOC_SM_XFER_DATA, &args); 248 return (err > 0); 249 } 250 251 static bool rp1_pio_can_add_program_at_offset(PIO pio, 252 const pio_program_t *program, 253 uint offset) { 254 struct rp1_pio_add_program_args args = {.num_instrs = program->length, 255 .origin = program->origin}; 256 int err; 257 valid_params_if(PIO, offset < RP1_PIO_INSTRUCTION_COUNT || 258 offset == PIO_ORIGIN_ANY); 259 valid_params_if(PIO, program->length <= RP1_PIO_INSTRUCTION_COUNT); 260 valid_params_if(PIO, 261 offset + program->length <= RP1_PIO_INSTRUCTION_COUNT || 262 offset == PIO_ORIGIN_ANY); 263 if (program->origin >= 0 && (uint)program->origin != offset) 264 return false; 265 if (offset != PIO_ORIGIN_ANY) 266 args.origin = offset; 267 memcpy(args.instrs, program->instructions, 268 program->length * sizeof(uint16_t)); 269 err = rp1_ioctl(pio, PIO_IOC_CAN_ADD_PROGRAM, &args); 270 return (err > 0); 271 } 272 273 static uint rp1_pio_add_program_at_offset(PIO pio, const pio_program_t *program, 274 uint offset) { 275 struct rp1_pio_add_program_args args = {.num_instrs = program->length, 276 .origin = program->origin}; 277 valid_params_if(PIO, offset < RP1_PIO_INSTRUCTION_COUNT || 278 offset == PIO_ORIGIN_ANY); 279 valid_params_if(PIO, program->length <= RP1_PIO_INSTRUCTION_COUNT); 280 valid_params_if(PIO, 281 offset + program->length <= RP1_PIO_INSTRUCTION_COUNT || 282 offset == PIO_ORIGIN_ANY); 283 if (offset != PIO_ORIGIN_ANY) 284 args.origin = offset; 285 memcpy(args.instrs, program->instructions, 286 program->length * sizeof(uint16_t)); 287 return rp1_ioctl(pio, PIO_IOC_ADD_PROGRAM, &args); 288 } 289 290 static bool rp1_pio_remove_program(PIO pio, const pio_program_t *program, 291 uint offset) { 292 struct rp1_pio_remove_program_args args = {.num_instrs = program->length, 293 .origin = offset}; 294 valid_params_if(PIO, offset < RP1_PIO_INSTRUCTION_COUNT); 295 valid_params_if(PIO, offset + program->length <= RP1_PIO_INSTRUCTION_COUNT); 296 return !rp1_ioctl(pio, PIO_IOC_REMOVE_PROGRAM, &args); 297 } 298 299 static bool rp1_pio_clear_instruction_memory(PIO pio) { 300 return !rp1_ioctl(pio, PIO_IOC_CLEAR_INSTR_MEM, NULL); 301 } 302 303 static bool rp1_pio_sm_claim(PIO pio, uint sm) { 304 struct rp1_pio_sm_claim_args args = {.mask = (1 << sm)}; 305 check_sm_param(sm); 306 return (rp1_ioctl(pio, PIO_IOC_SM_CLAIM, &args) >= 0); 307 } 308 309 static bool rp1_pio_sm_claim_mask(PIO pio, uint mask) { 310 struct rp1_pio_sm_claim_args args = {.mask = mask}; 311 valid_params_if(PIO, !!mask); 312 check_sm_mask(mask); 313 return (rp1_ioctl(pio, PIO_IOC_SM_CLAIM, &args) >= 0); 314 } 315 316 static bool rp1_pio_sm_unclaim(PIO pio, uint sm) { 317 struct rp1_pio_sm_claim_args args = {.mask = (1 << sm)}; 318 check_sm_param(sm); 319 return !rp1_ioctl(pio, PIO_IOC_SM_UNCLAIM, &args); 320 } 321 322 static int rp1_pio_sm_claim_unused(PIO pio, bool required) { 323 struct rp1_pio_sm_claim_args args = {.mask = 0}; 324 int sm = rp1_ioctl(pio, PIO_IOC_SM_CLAIM, &args); 325 if (sm < 0 && required) 326 pio_panic("No PIO state machines are available"); 327 return sm; 328 } 329 330 static bool rp1_pio_sm_is_claimed(PIO pio, uint sm) { 331 struct rp1_pio_sm_claim_args args = {.mask = (1 << sm)}; 332 check_sm_param(sm); 333 int err = rp1_ioctl(pio, PIO_IOC_SM_IS_CLAIMED, &args); 334 return (err > 0); 335 } 336 337 static void rp1_pio_sm_init(PIO pio, uint sm, uint initial_pc, 338 const pio_sm_config *config) { 339 smc_to_rp1(config, c); 340 struct rp1_pio_sm_init_args args = { 341 .sm = sm, .initial_pc = initial_pc, .config = *c}; 342 valid_params_if(PIO, initial_pc < RP1_PIO_INSTRUCTION_COUNT); 343 344 (void)rp1_ioctl(pio, PIO_IOC_SM_INIT, &args); 345 } 346 347 static void rp1_pio_sm_set_config(PIO pio, uint sm, 348 const pio_sm_config *config) { 349 smc_to_rp1(config, c); 350 struct rp1_pio_sm_init_args args = {.sm = sm, .config = *c}; 351 352 check_sm_param(sm); 353 (void)rp1_ioctl(pio, PIO_IOC_SM_SET_CONFIG, &args); 354 } 355 356 static void rp1_pio_sm_exec(PIO pio, uint sm, uint instr, bool blocking) { 357 struct rp1_pio_sm_exec_args args = { 358 .sm = sm, .instr = instr, .blocking = blocking}; 359 360 check_sm_param(sm); 361 (void)rp1_ioctl(pio, PIO_IOC_SM_EXEC, &args); 362 } 363 364 static void rp1_pio_sm_clear_fifos(PIO pio, uint sm) { 365 struct rp1_pio_sm_clear_fifos_args args = {.sm = sm}; 366 367 check_sm_param(sm); 368 (void)rp1_ioctl(pio, PIO_IOC_SM_CLEAR_FIFOS, &args); 369 } 370 371 static void rp1_pio_calculate_clkdiv_from_float(float div, uint16_t *div_int, 372 uint8_t *div_frac) { 373 valid_params_if(PIO, div >= 1 && div <= 65536); 374 *div_int = (uint16_t)div; 375 if (*div_int == 0) { 376 *div_frac = 0; 377 } else { 378 *div_frac = (uint8_t)((div - (float)*div_int) * (1u << 8u)); 379 } 380 } 381 382 static void rp1_pio_sm_set_clkdiv_int_frac(PIO pio, uint sm, uint16_t div_int, 383 uint8_t div_frac) { 384 struct rp1_pio_sm_set_clkdiv_args args = { 385 .sm = sm, .div_int = div_int, .div_frac = div_frac}; 386 387 check_sm_param(sm); 388 invalid_params_if(PIO, div_int == 0 && div_frac != 0); 389 (void)rp1_ioctl(pio, PIO_IOC_SM_SET_CLKDIV, &args); 390 } 391 392 static void rp1_pio_sm_set_clkdiv(PIO pio, uint sm, float div) { 393 uint16_t div_int; 394 uint8_t div_frac; 395 396 check_sm_param(sm); 397 rp1_pio_calculate_clkdiv_from_float(div, &div_int, &div_frac); 398 rp1_pio_sm_set_clkdiv_int_frac(pio, sm, div_int, div_frac); 399 } 400 401 static void rp1_pio_sm_set_pins(PIO pio, uint sm, uint32_t pin_values) { 402 struct rp1_pio_sm_set_pins_args args = { 403 .sm = sm, .values = pin_values, .mask = GPIOS_MASK}; 404 405 check_sm_param(sm); 406 (void)rp1_ioctl(pio, PIO_IOC_SM_SET_PINS, &args); 407 } 408 409 static void rp1_pio_sm_set_pins_with_mask(PIO pio, uint sm, uint32_t pin_values, 410 uint32_t pin_mask) { 411 struct rp1_pio_sm_set_pins_args args = { 412 .sm = sm, .values = pin_values, .mask = pin_mask}; 413 414 check_sm_param(sm); 415 (void)rp1_ioctl(pio, PIO_IOC_SM_SET_PINS, &args); 416 } 417 418 static void rp1_pio_sm_set_pindirs_with_mask(PIO pio, uint sm, 419 uint32_t pin_dirs, 420 uint32_t pin_mask) { 421 struct rp1_pio_sm_set_pindirs_args args = { 422 .sm = sm, .dirs = pin_dirs, .mask = pin_mask}; 423 424 check_sm_param(sm); 425 valid_params_if(PIO, (pin_dirs & GPIOS_MASK) == pin_dirs); 426 valid_params_if(PIO, (pin_mask & pin_mask) == pin_mask); 427 (void)rp1_ioctl(pio, PIO_IOC_SM_SET_PINDIRS, &args); 428 } 429 430 static void rp1_pio_sm_set_consecutive_pindirs(PIO pio, uint sm, uint pin_base, 431 uint pin_count, bool is_out) { 432 uint32_t mask = ((1 << pin_count) - 1) << pin_base; 433 struct rp1_pio_sm_set_pindirs_args args = { 434 .sm = sm, .dirs = is_out ? mask : 0, .mask = mask}; 435 436 check_sm_param(sm); 437 valid_params_if(PIO, pin_base < RP1_PIO_GPIO_COUNT && 438 pin_count < RP1_PIO_GPIO_COUNT && 439 (pin_base + pin_count) < RP1_PIO_GPIO_COUNT); 440 (void)rp1_ioctl(pio, PIO_IOC_SM_SET_PINDIRS, &args); 441 } 442 443 static void rp1_pio_sm_set_enabled(PIO pio, uint sm, bool enabled) { 444 struct rp1_pio_sm_set_enabled_args args = {.mask = (1 << sm), 445 .enable = enabled}; 446 check_sm_param(sm); 447 (void)rp1_ioctl(pio, PIO_IOC_SM_SET_ENABLED, &args); 448 } 449 450 static void rp1_pio_sm_set_enabled_mask(PIO pio, uint32_t mask, bool enabled) { 451 struct rp1_pio_sm_set_enabled_args args = {.mask = (uint16_t)mask, 452 .enable = enabled}; 453 check_sm_mask(mask); 454 (void)rp1_ioctl(pio, PIO_IOC_SM_SET_ENABLED, &args); 455 } 456 457 static void rp1_pio_sm_restart(PIO pio, uint sm) { 458 struct rp1_pio_sm_restart_args args = {.mask = (1 << sm)}; 459 check_sm_param(sm); 460 (void)rp1_ioctl(pio, PIO_IOC_SM_RESTART, &args); 461 } 462 463 static void rp1_pio_sm_restart_mask(PIO pio, uint32_t mask) { 464 struct rp1_pio_sm_restart_args args = {.mask = (uint16_t)mask}; 465 check_sm_mask(mask); 466 (void)rp1_ioctl(pio, PIO_IOC_SM_RESTART, &args); 467 } 468 469 static void rp1_pio_sm_clkdiv_restart(PIO pio, uint sm) { 470 struct rp1_pio_sm_restart_args args = {.mask = (1 << sm)}; 471 check_sm_param(sm); 472 (void)rp1_ioctl(pio, PIO_IOC_SM_CLKDIV_RESTART, &args); 473 } 474 475 static void rp1_pio_sm_clkdiv_restart_mask(PIO pio, uint32_t mask) { 476 struct rp1_pio_sm_restart_args args = {.mask = (uint16_t)mask}; 477 478 check_sm_mask(mask); 479 (void)rp1_ioctl(pio, PIO_IOC_SM_CLKDIV_RESTART, &args); 480 } 481 482 static void rp1_pio_sm_enable_sync(PIO pio, uint32_t mask) { 483 struct rp1_pio_sm_enable_sync_args args = {.mask = (uint16_t)mask}; 484 485 check_sm_mask(mask); 486 (void)rp1_ioctl(pio, PIO_IOC_SM_ENABLE_SYNC, &args); 487 } 488 489 static void rp1_pio_sm_put(PIO pio, uint sm, uint32_t data, bool blocking) { 490 struct rp1_pio_sm_put_args args = { 491 .sm = (uint16_t)sm, .blocking = blocking, .data = data}; 492 493 check_sm_param(sm); 494 (void)rp1_ioctl(pio, PIO_IOC_SM_PUT, &args); 495 } 496 497 static uint32_t rp1_pio_sm_get(PIO pio, uint sm, bool blocking) { 498 struct rp1_pio_sm_get_args args = {.sm = (uint16_t)sm, 499 .blocking = blocking}; 500 501 check_sm_param(sm); 502 (void)rp1_ioctl(pio, PIO_IOC_SM_GET, &args); 503 return args.data; 504 } 505 506 static void rp1_pio_sm_set_dmactrl(PIO pio, uint sm, bool is_tx, 507 uint32_t ctrl) { 508 struct rp1_pio_sm_set_dmactrl_args args = { 509 .sm = sm, .is_tx = is_tx, .ctrl = ctrl}; 510 511 check_sm_param(sm); 512 (void)rp1_ioctl(pio, PIO_IOC_SM_SET_DMACTRL, &args); 513 } 514 515 static bool rp1_pio_sm_is_rx_fifo_empty(PIO pio, uint sm) { 516 struct rp1_pio_sm_fifo_state_args args = {.sm = sm, .tx = false}; 517 518 check_sm_param(sm); 519 (void)rp1_ioctl(pio, PIO_IOC_SM_FIFO_STATE, &args); 520 return args.empty; 521 } 522 523 static bool rp1_pio_sm_is_rx_fifo_full(PIO pio, uint sm) { 524 struct rp1_pio_sm_fifo_state_args args = {.sm = sm, .tx = false}; 525 526 check_sm_param(sm); 527 (void)rp1_ioctl(pio, PIO_IOC_SM_FIFO_STATE, &args); 528 return args.full; 529 } 530 531 static uint rp1_pio_sm_get_rx_fifo_level(PIO pio, uint sm) { 532 struct rp1_pio_sm_fifo_state_args args = {.sm = sm, .tx = false}; 533 534 check_sm_param(sm); 535 (void)rp1_ioctl(pio, PIO_IOC_SM_FIFO_STATE, &args); 536 return args.level; 537 } 538 539 static bool rp1_pio_sm_is_tx_fifo_empty(PIO pio, uint sm) { 540 struct rp1_pio_sm_fifo_state_args args = {.sm = sm, .tx = true}; 541 542 check_sm_param(sm); 543 (void)rp1_ioctl(pio, PIO_IOC_SM_FIFO_STATE, &args); 544 return args.empty; 545 } 546 547 static bool rp1_pio_sm_is_tx_fifo_full(PIO pio, uint sm) { 548 struct rp1_pio_sm_fifo_state_args args = {.sm = sm, .tx = true}; 549 550 check_sm_param(sm); 551 (void)rp1_ioctl(pio, PIO_IOC_SM_FIFO_STATE, &args); 552 return args.full; 553 } 554 555 static uint rp1_pio_sm_get_tx_fifo_level(PIO pio, uint sm) { 556 struct rp1_pio_sm_fifo_state_args args = {.sm = sm, .tx = true}; 557 558 check_sm_param(sm); 559 (void)rp1_ioctl(pio, PIO_IOC_SM_FIFO_STATE, &args); 560 return args.level; 561 } 562 563 static void rp1_pio_sm_drain_tx_fifo(PIO pio, uint sm) { 564 struct rp1_pio_sm_clear_fifos_args args = {.sm = sm}; 565 566 check_sm_param(sm); 567 (void)rp1_ioctl(pio, PIO_IOC_SM_DRAIN_TX, &args); 568 } 569 570 static void rp1_smc_set_out_pins(PIO pio, pio_sm_config *config, uint out_base, 571 uint out_count) { 572 smc_to_rp1(config, c); 573 valid_params_if(PIO, out_base < RP1_PIO_GPIO_COUNT); 574 valid_params_if(PIO, out_count <= RP1_PIO_GPIO_COUNT); 575 c->pinctrl = (c->pinctrl & ~(PROC_PIO_SM0_PINCTRL_OUT_BASE_BITS | 576 PROC_PIO_SM0_PINCTRL_OUT_COUNT_BITS)) | 577 (out_base << PROC_PIO_SM0_PINCTRL_OUT_BASE_LSB) | 578 (out_count << PROC_PIO_SM0_PINCTRL_OUT_COUNT_LSB); 579 } 580 581 static void rp1_smc_set_set_pins(PIO pio, pio_sm_config *config, uint set_base, 582 uint set_count) { 583 smc_to_rp1(config, c); 584 valid_params_if(PIO, set_base < RP1_PIO_GPIO_COUNT); 585 valid_params_if(PIO, set_count <= 5); 586 c->pinctrl = (c->pinctrl & ~(PROC_PIO_SM0_PINCTRL_SET_BASE_BITS | 587 PROC_PIO_SM0_PINCTRL_SET_COUNT_BITS)) | 588 (set_base << PROC_PIO_SM0_PINCTRL_SET_BASE_LSB) | 589 (set_count << PROC_PIO_SM0_PINCTRL_SET_COUNT_LSB); 590 } 591 592 static void rp1_smc_set_in_pins(PIO pio, pio_sm_config *config, uint in_base) { 593 smc_to_rp1(config, c); 594 valid_params_if(PIO, in_base < RP1_PIO_GPIO_COUNT); 595 c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_IN_BASE_BITS) | 596 (in_base << PROC_PIO_SM0_PINCTRL_IN_BASE_LSB); 597 } 598 599 static void rp1_smc_set_sideset_pins(PIO pio, pio_sm_config *config, 600 uint sideset_base) { 601 smc_to_rp1(config, c); 602 valid_params_if(PIO, sideset_base < RP1_PIO_GPIO_COUNT); 603 c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_SIDESET_BASE_BITS) | 604 (sideset_base << PROC_PIO_SM0_PINCTRL_SIDESET_BASE_LSB); 605 } 606 607 static void rp1_smc_set_sideset(PIO pio, pio_sm_config *config, uint bit_count, 608 bool optional, bool pindirs) { 609 smc_to_rp1(config, c); 610 valid_params_if(PIO, bit_count <= 5); 611 valid_params_if(PIO, !optional || bit_count >= 1); 612 c->pinctrl = (c->pinctrl & ~PROC_PIO_SM0_PINCTRL_SIDESET_COUNT_BITS) | 613 (bit_count << PROC_PIO_SM0_PINCTRL_SIDESET_COUNT_LSB); 614 615 c->execctrl = 616 (c->execctrl & ~(PROC_PIO_SM0_EXECCTRL_SIDE_EN_BITS | 617 PROC_PIO_SM0_EXECCTRL_SIDE_PINDIR_BITS)) | 618 (bool_to_bit(optional) << PROC_PIO_SM0_EXECCTRL_SIDE_EN_LSB) | 619 (bool_to_bit(pindirs) << PROC_PIO_SM0_EXECCTRL_SIDE_PINDIR_LSB); 620 } 621 622 static void rp1_smc_set_clkdiv_int_frac(PIO pio, pio_sm_config *config, 623 uint16_t div_int, uint8_t div_frac) { 624 smc_to_rp1(config, c); 625 invalid_params_if(PIO, div_int == 0 && div_frac != 0); 626 c->clkdiv = (((uint)div_frac) << PROC_PIO_SM0_CLKDIV_FRAC_LSB) | 627 (((uint)div_int) << PROC_PIO_SM0_CLKDIV_INT_LSB); 628 } 629 630 static void rp1_smc_set_clkdiv(PIO pio, pio_sm_config *config, float div) { 631 uint16_t div_int; 632 uint8_t div_frac; 633 rp1_pio_calculate_clkdiv_from_float(div, &div_int, &div_frac); 634 sm_config_set_clkdiv_int_frac(config, div_int, div_frac); 635 } 636 637 static void rp1_smc_set_wrap(PIO pio, pio_sm_config *config, uint wrap_target, 638 uint wrap) { 639 smc_to_rp1(config, c); 640 valid_params_if(PIO, wrap < RP1_PIO_INSTRUCTION_COUNT); 641 valid_params_if(PIO, wrap_target < RP1_PIO_INSTRUCTION_COUNT); 642 c->execctrl = (c->execctrl & ~(PROC_PIO_SM0_EXECCTRL_WRAP_TOP_BITS | 643 PROC_PIO_SM0_EXECCTRL_WRAP_BOTTOM_BITS)) | 644 (wrap_target << PROC_PIO_SM0_EXECCTRL_WRAP_BOTTOM_LSB) | 645 (wrap << PROC_PIO_SM0_EXECCTRL_WRAP_TOP_LSB); 646 } 647 648 static void rp1_smc_set_jmp_pin(PIO pio, pio_sm_config *config, uint pin) { 649 smc_to_rp1(config, c); 650 valid_params_if(PIO, pin < RP1_PIO_GPIO_COUNT); 651 c->execctrl = (c->execctrl & ~PROC_PIO_SM0_EXECCTRL_JMP_PIN_BITS) | 652 (pin << PROC_PIO_SM0_EXECCTRL_JMP_PIN_LSB); 653 } 654 655 static void rp1_smc_set_in_shift(PIO pio, pio_sm_config *config, 656 bool shift_right, bool autopush, 657 uint push_threshold) { 658 smc_to_rp1(config, c); 659 valid_params_if(PIO, push_threshold <= 32); 660 c->shiftctrl = 661 (c->shiftctrl & ~(PROC_PIO_SM0_SHIFTCTRL_IN_SHIFTDIR_BITS | 662 PROC_PIO_SM0_SHIFTCTRL_AUTOPUSH_BITS | 663 PROC_PIO_SM0_SHIFTCTRL_PUSH_THRESH_BITS)) | 664 (bool_to_bit(shift_right) << PROC_PIO_SM0_SHIFTCTRL_IN_SHIFTDIR_LSB) | 665 (bool_to_bit(autopush) << PROC_PIO_SM0_SHIFTCTRL_AUTOPUSH_LSB) | 666 ((push_threshold & 0x1fu) << PROC_PIO_SM0_SHIFTCTRL_PUSH_THRESH_LSB); 667 } 668 669 static void rp1_smc_set_out_shift(PIO pio, pio_sm_config *config, 670 bool shift_right, bool autopull, 671 uint pull_threshold) { 672 smc_to_rp1(config, c); 673 valid_params_if(PIO, pull_threshold <= 32); 674 c->shiftctrl = 675 (c->shiftctrl & ~(PROC_PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_BITS | 676 PROC_PIO_SM0_SHIFTCTRL_AUTOPULL_BITS | 677 PROC_PIO_SM0_SHIFTCTRL_PULL_THRESH_BITS)) | 678 (bool_to_bit(shift_right) << PROC_PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_LSB) | 679 (bool_to_bit(autopull) << PROC_PIO_SM0_SHIFTCTRL_AUTOPULL_LSB) | 680 ((pull_threshold & 0x1fu) << PROC_PIO_SM0_SHIFTCTRL_PULL_THRESH_LSB); 681 } 682 683 static void rp1_smc_set_fifo_join(PIO pio, pio_sm_config *config, 684 enum pio_fifo_join join) { 685 smc_to_rp1(config, c); 686 valid_params_if(PIO, join == PIO_FIFO_JOIN_NONE || 687 join == PIO_FIFO_JOIN_TX || 688 join == PIO_FIFO_JOIN_RX); 689 c->shiftctrl = 690 (c->shiftctrl & (uint) ~(PROC_PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS | 691 PROC_PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS)) | 692 (((uint)join) << PROC_PIO_SM0_SHIFTCTRL_FJOIN_TX_LSB); 693 } 694 695 static void rp1_smc_set_out_special(PIO pio, pio_sm_config *config, bool sticky, 696 bool has_enable_pin, 697 uint enable_pin_index) { 698 smc_to_rp1(config, c); 699 c->execctrl = 700 (c->execctrl & (uint) ~(PROC_PIO_SM0_EXECCTRL_OUT_STICKY_BITS | 701 PROC_PIO_SM0_EXECCTRL_INLINE_OUT_EN_BITS | 702 PROC_PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS)) | 703 (bool_to_bit(sticky) << PROC_PIO_SM0_EXECCTRL_OUT_STICKY_LSB) | 704 (bool_to_bit(has_enable_pin) 705 << PROC_PIO_SM0_EXECCTRL_INLINE_OUT_EN_LSB) | 706 ((enable_pin_index << PROC_PIO_SM0_EXECCTRL_OUT_EN_SEL_LSB) & 707 PROC_PIO_SM0_EXECCTRL_OUT_EN_SEL_BITS); 708 } 709 710 static void rp1_smc_set_mov_status(PIO pio, pio_sm_config *config, 711 enum pio_mov_status_type status_sel, 712 uint status_n) { 713 smc_to_rp1(config, c); 714 valid_params_if(PIO, status_sel == STATUS_TX_LESSTHAN || 715 status_sel == STATUS_RX_LESSTHAN); 716 c->execctrl = 717 (c->execctrl & ~(PROC_PIO_SM0_EXECCTRL_STATUS_SEL_BITS | 718 PROC_PIO_SM0_EXECCTRL_STATUS_N_BITS)) | 719 ((((uint)status_sel) << PROC_PIO_SM0_EXECCTRL_STATUS_SEL_LSB) & 720 PROC_PIO_SM0_EXECCTRL_STATUS_SEL_BITS) | 721 ((status_n << PROC_PIO_SM0_EXECCTRL_STATUS_N_LSB) & 722 PROC_PIO_SM0_EXECCTRL_STATUS_N_BITS); 723 } 724 725 static uint32_t rp1_clock_get_hz(PIO pio, enum clock_index clk_index) { 726 const uint32_t MHZ = 1000000; 727 728 switch (clk_index) { 729 case clk_sys: 730 return 200 * MHZ; 731 default: 732 break; 733 } 734 return PIO_ORIGIN_ANY; 735 } 736 737 static void rp1_gpio_init(PIO pio, uint gpio) { 738 struct rp1_gpio_init_args args = {.gpio = gpio}; 739 740 valid_params_if(PIO, gpio < RP1_PIO_GPIO_COUNT); 741 (void)rp1_ioctl(pio, PIO_IOC_GPIO_INIT, &args); 742 } 743 744 static void rp1_gpio_set_function(PIO pio, uint gpio, enum gpio_function fn) { 745 struct rp1_gpio_set_function_args args = {.gpio = gpio, .fn = fn}; 746 747 valid_params_if(PIO, gpio < RP1_PIO_GPIO_COUNT); 748 (void)rp1_ioctl(pio, PIO_IOC_GPIO_SET_FUNCTION, &args); 749 } 750 751 static void rp1_gpio_set_pulls(PIO pio, uint gpio, bool up, bool down) { 752 struct rp1_gpio_set_pulls_args args = { 753 .gpio = gpio, .up = up, .down = down}; 754 755 valid_params_if(PIO, gpio < RP1_PIO_GPIO_COUNT); 756 (void)rp1_ioctl(pio, PIO_IOC_GPIO_SET_PULLS, &args); 757 } 758 759 static void rp1_gpio_set_outover(PIO pio, uint gpio, uint value) { 760 struct rp1_gpio_set_args args = {.gpio = gpio, .value = value}; 761 762 valid_params_if(PIO, gpio < RP1_PIO_GPIO_COUNT); 763 (void)rp1_ioctl(pio, PIO_IOC_GPIO_SET_OUTOVER, &args); 764 } 765 766 static void rp1_gpio_set_inover(PIO pio, uint gpio, uint value) { 767 struct rp1_gpio_set_args args = {.gpio = gpio, .value = value}; 768 769 valid_params_if(PIO, gpio < RP1_PIO_GPIO_COUNT); 770 (void)rp1_ioctl(pio, PIO_IOC_GPIO_SET_INOVER, &args); 771 } 772 773 static void rp1_gpio_set_oeover(PIO pio, uint gpio, uint value) { 774 struct rp1_gpio_set_args args = {.gpio = gpio, .value = value}; 775 776 valid_params_if(PIO, gpio < RP1_PIO_GPIO_COUNT); 777 (void)rp1_ioctl(pio, PIO_IOC_GPIO_SET_OEOVER, &args); 778 } 779 780 static void rp1_gpio_set_input_enabled(PIO pio, uint gpio, bool enabled) { 781 struct rp1_gpio_set_args args = {.gpio = gpio, .value = enabled}; 782 783 valid_params_if(PIO, gpio < RP1_PIO_GPIO_COUNT); 784 (void)rp1_ioctl(pio, PIO_IOC_GPIO_SET_INPUT_ENABLED, &args); 785 } 786 787 static void rp1_gpio_set_drive_strength(PIO pio, uint gpio, 788 enum gpio_drive_strength drive) { 789 struct rp1_gpio_set_args args = {.gpio = gpio, .value = drive}; 790 791 valid_params_if(PIO, gpio < RP1_PIO_GPIO_COUNT); 792 (void)rp1_ioctl(pio, PIO_IOC_GPIO_SET_DRIVE_STRENGTH, &args); 793 } 794 795 static void rp1_pio_gpio_init(PIO pio, uint pin) { 796 valid_params_if(PIO, pin < RP1_PIO_GPIO_COUNT); 797 rp1_gpio_set_function(pio, pin, (enum gpio_function)RP1_GPIO_FUNC_PIO); 798 } 799 800 PIO rp1_create_instance(PIO_CHIP_T *chip, uint index) { 801 char pathbuf[20]; 802 RP1_PIO pio = NULL; 803 804 sprintf(pathbuf, "/dev/pio%u", index); 805 806 if (access(pathbuf, F_OK) != 0) 807 return NULL; 808 809 pio = (RP1_PIO)calloc(1, sizeof(*pio)); 810 if (!pio) 811 return PIO_ERR(-ENOMEM); 812 813 pio->base.chip = chip; 814 pio->fd = -1; 815 pio->devname = strdup(pathbuf); 816 817 rp1_pio_clear_instruction_memory(&pio->base); 818 819 return &pio->base; 820 } 821 822 int rp1_open_instance(PIO pio) { 823 RP1_PIO rp = (RP1_PIO)pio; 824 int fd; 825 826 fd = open(rp->devname, O_RDWR, O_CLOEXEC); 827 if (fd < 0) 828 return -errno; 829 rp->fd = fd; 830 return 0; 831 } 832 833 void rp1_close_instance(PIO pio) { 834 RP1_PIO rp = (RP1_PIO)pio; 835 close(rp->fd); 836 } 837 838 static const PIO_CHIP_T rp1_pio_chip = { 839 .name = "rp1", 840 .compatible = "raspberrypi,rp1-pio", 841 .instr_count = RP1_PIO_INSTRUCTION_COUNT, 842 .sm_count = RP1_PIO_SM_COUNT, 843 .fifo_depth = 8, 844 845 .create_instance = rp1_create_instance, 846 .open_instance = rp1_open_instance, 847 .close_instance = rp1_close_instance, 848 849 .pio_sm_config_xfer = rp1_pio_sm_config_xfer, 850 .pio_sm_xfer_data = rp1_pio_sm_xfer_data, 851 852 .pio_can_add_program_at_offset = rp1_pio_can_add_program_at_offset, 853 .pio_add_program_at_offset = rp1_pio_add_program_at_offset, 854 .pio_remove_program = rp1_pio_remove_program, 855 .pio_clear_instruction_memory = rp1_pio_clear_instruction_memory, 856 .pio_encode_delay = rp1_pio_encode_delay, 857 .pio_encode_sideset = rp1_pio_encode_sideset, 858 .pio_encode_sideset_opt = rp1_pio_encode_sideset_opt, 859 .pio_encode_jmp = rp1_pio_encode_jmp, 860 .pio_encode_jmp_not_x = rp1_pio_encode_jmp_not_x, 861 .pio_encode_jmp_x_dec = rp1_pio_encode_jmp_x_dec, 862 .pio_encode_jmp_not_y = rp1_pio_encode_jmp_not_y, 863 .pio_encode_jmp_y_dec = rp1_pio_encode_jmp_y_dec, 864 .pio_encode_jmp_x_ne_y = rp1_pio_encode_jmp_x_ne_y, 865 .pio_encode_jmp_pin = rp1_pio_encode_jmp_pin, 866 .pio_encode_jmp_not_osre = rp1_pio_encode_jmp_not_osre, 867 .pio_encode_wait_gpio = rp1_pio_encode_wait_gpio, 868 .pio_encode_wait_pin = rp1_pio_encode_wait_pin, 869 .pio_encode_wait_irq = rp1_pio_encode_wait_irq, 870 .pio_encode_in = rp1_pio_encode_in, 871 .pio_encode_out = rp1_pio_encode_out, 872 .pio_encode_push = rp1_pio_encode_push, 873 .pio_encode_pull = rp1_pio_encode_pull, 874 .pio_encode_mov = rp1_pio_encode_mov, 875 .pio_encode_mov_not = rp1_pio_encode_mov_not, 876 .pio_encode_mov_reverse = rp1_pio_encode_mov_reverse, 877 .pio_encode_irq_set = rp1_pio_encode_irq_set, 878 .pio_encode_irq_wait = rp1_pio_encode_irq_wait, 879 .pio_encode_irq_clear = rp1_pio_encode_irq_clear, 880 .pio_encode_set = rp1_pio_encode_set, 881 .pio_encode_nop = rp1_pio_encode_nop, 882 883 .pio_sm_claim = rp1_pio_sm_claim, 884 .pio_sm_claim_mask = rp1_pio_sm_claim_mask, 885 .pio_sm_claim_unused = rp1_pio_sm_claim_unused, 886 .pio_sm_unclaim = rp1_pio_sm_unclaim, 887 .pio_sm_is_claimed = rp1_pio_sm_is_claimed, 888 889 .pio_sm_init = rp1_pio_sm_init, 890 .pio_sm_set_config = rp1_pio_sm_set_config, 891 .pio_sm_exec = rp1_pio_sm_exec, 892 .pio_sm_clear_fifos = rp1_pio_sm_clear_fifos, 893 .pio_sm_set_clkdiv_int_frac = &rp1_pio_sm_set_clkdiv_int_frac, 894 .pio_sm_set_clkdiv = rp1_pio_sm_set_clkdiv, 895 .pio_sm_set_pins = rp1_pio_sm_set_pins, 896 .pio_sm_set_pins_with_mask = rp1_pio_sm_set_pins_with_mask, 897 .pio_sm_set_pindirs_with_mask = rp1_pio_sm_set_pindirs_with_mask, 898 .pio_sm_set_consecutive_pindirs = rp1_pio_sm_set_consecutive_pindirs, 899 .pio_sm_set_enabled = rp1_pio_sm_set_enabled, 900 .pio_sm_set_enabled_mask = rp1_pio_sm_set_enabled_mask, 901 .pio_sm_restart = rp1_pio_sm_restart, 902 .pio_sm_restart_mask = rp1_pio_sm_restart_mask, 903 .pio_sm_clkdiv_restart = rp1_pio_sm_clkdiv_restart, 904 .pio_sm_clkdiv_restart_mask = rp1_pio_sm_clkdiv_restart_mask, 905 .pio_sm_enable_sync = rp1_pio_sm_enable_sync, 906 .pio_sm_put = rp1_pio_sm_put, 907 .pio_sm_get = rp1_pio_sm_get, 908 .pio_sm_set_dmactrl = rp1_pio_sm_set_dmactrl, 909 .pio_sm_is_rx_fifo_empty = rp1_pio_sm_is_rx_fifo_empty, 910 .pio_sm_is_rx_fifo_full = rp1_pio_sm_is_rx_fifo_full, 911 .pio_sm_get_rx_fifo_level = rp1_pio_sm_get_rx_fifo_level, 912 .pio_sm_is_tx_fifo_empty = rp1_pio_sm_is_tx_fifo_empty, 913 .pio_sm_is_tx_fifo_full = rp1_pio_sm_is_tx_fifo_full, 914 .pio_sm_get_tx_fifo_level = rp1_pio_sm_get_tx_fifo_level, 915 .pio_sm_drain_tx_fifo = rp1_pio_sm_drain_tx_fifo, 916 917 .pio_get_default_sm_config = rp1_pio_get_default_sm_config, 918 .smc_set_out_pins = rp1_smc_set_out_pins, 919 .smc_set_set_pins = rp1_smc_set_set_pins, 920 .smc_set_in_pins = rp1_smc_set_in_pins, 921 .smc_set_sideset_pins = rp1_smc_set_sideset_pins, 922 .smc_set_sideset = rp1_smc_set_sideset, 923 .smc_set_clkdiv_int_frac = rp1_smc_set_clkdiv_int_frac, 924 .smc_set_clkdiv = rp1_smc_set_clkdiv, 925 .smc_set_wrap = rp1_smc_set_wrap, 926 .smc_set_jmp_pin = rp1_smc_set_jmp_pin, 927 .smc_set_in_shift = rp1_smc_set_in_shift, 928 .smc_set_out_shift = rp1_smc_set_out_shift, 929 .smc_set_fifo_join = rp1_smc_set_fifo_join, 930 .smc_set_out_special = rp1_smc_set_out_special, 931 .smc_set_mov_status = rp1_smc_set_mov_status, 932 933 .clock_get_hz = rp1_clock_get_hz, 934 935 .pio_gpio_init = rp1_pio_gpio_init, 936 .gpio_init = rp1_gpio_init, 937 .gpio_set_function = rp1_gpio_set_function, 938 .gpio_set_pulls = rp1_gpio_set_pulls, 939 .gpio_set_outover = rp1_gpio_set_outover, 940 .gpio_set_inover = rp1_gpio_set_inover, 941 .gpio_set_oeover = rp1_gpio_set_oeover, 942 .gpio_set_input_enabled = rp1_gpio_set_input_enabled, 943 .gpio_set_drive_strength = rp1_gpio_set_drive_strength, 944 }; 945 946 DECLARE_PIO_CHIP(rp1_pio_chip);