/ src / piolib / pio_rp1.c
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);