mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
misc: Add RP1 PIO driver
Provide remote access to the PIO hardware in RP1. There is a single instance, with 4 state machines. Signed-off-by: Phil Elwell <phil@raspberrypi.com> misc: rp1-pio: Support larger data transfers Add a separate IOCTL for larger transfer with a 32-bit data_bytes field. See: https://github.com/raspberrypi/utils/issues/107 Signed-off-by: Phil Elwell <phil@raspberrypi.com> misc: rp1-pio: More logical probe sequence Sort the probe function initialisation into a more logical order. Signed-off-by: Phil Elwell <phil@raspberrypi.com> misc: rp1-pio: Minor cosmetic tweaks No functional change. Signed-off-by: Phil Elwell <phil@raspberrypi.com> misc: rp1-pio: Add in-kernel DMA support Add kernel-facing implementations of pio_sm_config_xfer and pio_xm_xfer_data. Signed-off-by: Phil Elwell <phil@raspberrypi.com> misc: rp1-pio: Handle probe errors Ensure that rp1_pio_open fails if the device failed to probe. Link: https://github.com/raspberrypi/linux/issues/6593 Signed-off-by: Phil Elwell <phil@raspberrypi.com> misc: rp1-pio: SM_CONFIG_XFER32 = larger DMA bufs Add an ioctl type - SM_CONFIG_XFER32 - that takes uints for the buf_size and buf_count values. Signed-off-by: Phil Elwell <phil@raspberrypi.com> misc/rp1-pio: Fix copy/paste error in pio_rp1.h As per the subject, there was a copy/paste error that caused pio_sm_unclaim from a driver to result in a call to pio_sm_claim. Fix it. Signed-off-by: Phil Elwell <phil@raspberrypi.com> misc: rp1-pio: Fix parameter checks wihout client Passing bad parameters to an API call without a pio pointer will cause a NULL pointer exception when the persistent error is set. Guard against that. Signed-off-by: Phil Elwell <phil@raspberrypi.com> misc: rp1-pio: Convert floats to 24.8 fixed point Floating point arithmetic is not supported in the kernel, so use fixed point instead. Signed-off-by: Phil Elwell <phil@raspberrypi.com> misc: rp1-pio: Error out on incompatible firmware If the RP1 firmware has reported an error then return that from the PIO probe function, otherwise defer the probing. Link: https://github.com/raspberrypi/linux/issues/6642 Signed-off-by: Phil Elwell <phil@raspberrypi.com> misc: rp1-pio: Demote fw probe error to warning Support for the RP1 firmware mailbox API is rolling out to Pi 5 EEPROM images. For most users, the fact that the PIO is not available is no cause for alarm. Change the message to a warning, so that it does not appear with "quiet" in cmdline.txt. Link: https://github.com/raspberrypi/linux/issues/6642 Signed-off-by: Phil Elwell <phil@raspberrypi.com> misc: rp1-pio: Don't just reuse the same DMA buf A missing pointer increment meant that not only was the same buffer being reused again and again, there was also no protection against using it simultaneously for multiple transfers. Fix that basic bug, and also move a similar increment to before the transfer is started, which feels less racy. See: https://github.com/raspberrypi/linux/issues/6919 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
This commit is contained in:
@@ -17,6 +17,14 @@ config BCM2835_SMI
|
|||||||
Driver for enabling and using Broadcom's Secondary/Slow Memory Interface.
|
Driver for enabling and using Broadcom's Secondary/Slow Memory Interface.
|
||||||
Appears as /dev/bcm2835_smi. For ioctl interface see drivers/misc/bcm2835_smi.h
|
Appears as /dev/bcm2835_smi. For ioctl interface see drivers/misc/bcm2835_smi.h
|
||||||
|
|
||||||
|
config RP1_PIO
|
||||||
|
tristate "Raspberry Pi RP1 PIO driver"
|
||||||
|
depends on FIRMWARE_RP1 || COMPILE_TEST
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Driver providing control of the Raspberry Pi PIO block, as found in
|
||||||
|
RP1.
|
||||||
|
|
||||||
config AD525X_DPOT
|
config AD525X_DPOT
|
||||||
tristate "Analog Devices Digital Potentiometers"
|
tristate "Analog Devices Digital Potentiometers"
|
||||||
depends on (I2C || SPI) && SYSFS
|
depends on (I2C || SPI) && SYSFS
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ obj-$(CONFIG_PHANTOM) += phantom.o
|
|||||||
obj-$(CONFIG_RPMB) += rpmb-core.o
|
obj-$(CONFIG_RPMB) += rpmb-core.o
|
||||||
obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o
|
obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o
|
||||||
obj-$(CONFIG_QCOM_FASTRPC) += fastrpc.o
|
obj-$(CONFIG_QCOM_FASTRPC) += fastrpc.o
|
||||||
|
obj-$(CONFIG_RP1_PIO) += rp1-pio.o
|
||||||
obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o
|
obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o
|
||||||
obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o
|
obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o
|
||||||
obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
|
obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
|
||||||
|
|||||||
56
drivers/misc/rp1-fw-pio.h
Normal file
56
drivers/misc/rp1-fw-pio.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 2023-2024 Raspberry Pi Ltd.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SOC_RP1_FIRMWARE_OPS_H__
|
||||||
|
#define __SOC_RP1_FIRMWARE_OPS_H__
|
||||||
|
|
||||||
|
#include <linux/rp1-firmware.h>
|
||||||
|
|
||||||
|
#define FOURCC_PIO RP1_FOURCC("PIO ")
|
||||||
|
|
||||||
|
enum rp1_pio_ops {
|
||||||
|
PIO_CAN_ADD_PROGRAM, // u16 num_instrs, u16 origin -> origin
|
||||||
|
PIO_ADD_PROGRAM, // u16 num_instrs, u16 origin, u16 prog[] -> rc
|
||||||
|
PIO_REMOVE_PROGRAM, // u16 num_instrs, u16 origin
|
||||||
|
PIO_CLEAR_INSTR_MEM, // -
|
||||||
|
|
||||||
|
PIO_SM_CLAIM, // u16 mask -> sm
|
||||||
|
PIO_SM_UNCLAIM, // u16 mask
|
||||||
|
PIO_SM_IS_CLAIMED, // u16 mask -> claimed
|
||||||
|
|
||||||
|
PIO_SM_INIT, // u16 sm, u16 initial_pc, u32 sm_config[4]
|
||||||
|
PIO_SM_SET_CONFIG, // u16 sm, u16 rsvd, u32 sm_config[4]
|
||||||
|
PIO_SM_EXEC, // u16 sm, u16 instr, u8 blocking, u8 rsvd
|
||||||
|
PIO_SM_CLEAR_FIFOS, // u16 sm
|
||||||
|
PIO_SM_SET_CLKDIV, // u16 sm, u16 div_int, u8 div_frac, u8 rsvd
|
||||||
|
PIO_SM_SET_PINS, // u16 sm, u16 rsvd, u32 values, u32 mask
|
||||||
|
PIO_SM_SET_PINDIRS, // u16 sm, u16 rsvd, u32 dirs, u32 mask
|
||||||
|
PIO_SM_SET_ENABLED, // u16 mask, u8 enable, u8 rsvd
|
||||||
|
PIO_SM_RESTART, // u16 mask
|
||||||
|
PIO_SM_CLKDIV_RESTART, // u16 mask
|
||||||
|
PIO_SM_ENABLE_SYNC, // u16 mask
|
||||||
|
PIO_SM_PUT, // u16 sm, u8 blocking, u8 rsvd, u32 data
|
||||||
|
PIO_SM_GET, // u16 sm, u8 blocking, u8 rsvd -> u32 data
|
||||||
|
PIO_SM_SET_DMACTRL, // u16 sm, u16 is_tx, u32 ctrl
|
||||||
|
|
||||||
|
GPIO_INIT, // u16 gpio
|
||||||
|
GPIO_SET_FUNCTION, // u16 gpio, u16 fn
|
||||||
|
GPIO_SET_PULLS, // u16 gpio, u8 up, u8 down
|
||||||
|
GPIO_SET_OUTOVER, // u16 gpio, u16 value
|
||||||
|
GPIO_SET_INOVER, // u16 gpio, u16 value
|
||||||
|
GPIO_SET_OEOVER, // u16 gpio, u16 value
|
||||||
|
GPIO_SET_INPUT_ENABLED, // u16 gpio, u16 value
|
||||||
|
GPIO_SET_DRIVE_STRENGTH, // u16 gpio, u16 value
|
||||||
|
|
||||||
|
READ_HW, // src address, len -> data bytes
|
||||||
|
WRITE_HW, // dst address, data
|
||||||
|
|
||||||
|
PIO_SM_FIFO_STATE, // u16 sm, u8 tx -> u16 level, u8 empty, u8 full
|
||||||
|
PIO_SM_DRAIN_TX, // u16 sm
|
||||||
|
|
||||||
|
PIO_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
1390
drivers/misc/rp1-pio.c
Normal file
1390
drivers/misc/rp1-pio.c
Normal file
File diff suppressed because it is too large
Load Diff
481
include/linux/pio_instructions.h
Normal file
481
include/linux/pio_instructions.h
Normal file
@@ -0,0 +1,481 @@
|
|||||||
|
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HARDWARE_PIO_INSTRUCTIONS_H
|
||||||
|
#define _HARDWARE_PIO_INSTRUCTIONS_H
|
||||||
|
|
||||||
|
/** \brief PIO instruction encoding
|
||||||
|
* \defgroup pio_instructions pio_instructions
|
||||||
|
* \ingroup hardware_pio
|
||||||
|
*
|
||||||
|
* Functions for generating PIO instruction encodings programmatically. In debug builds
|
||||||
|
*`PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS` can be set to 1 to enable validation of encoding function
|
||||||
|
* parameters.
|
||||||
|
*
|
||||||
|
* For fuller descriptions of the instructions in question see the "RP2040 Datasheet"
|
||||||
|
*/
|
||||||
|
|
||||||
|
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS, Enable/disable assertions in the PIO instructions, type=bool, default=0, group=pio_instructions
|
||||||
|
#ifndef PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS
|
||||||
|
#define PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum pio_instr_bits {
|
||||||
|
pio_instr_bits_jmp = 0x0000,
|
||||||
|
pio_instr_bits_wait = 0x2000,
|
||||||
|
pio_instr_bits_in = 0x4000,
|
||||||
|
pio_instr_bits_out = 0x6000,
|
||||||
|
pio_instr_bits_push = 0x8000,
|
||||||
|
pio_instr_bits_pull = 0x8080,
|
||||||
|
pio_instr_bits_mov = 0xa000,
|
||||||
|
pio_instr_bits_irq = 0xc000,
|
||||||
|
pio_instr_bits_set = 0xe000,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define _PIO_INVALID_IN_SRC 0x08u
|
||||||
|
#define _PIO_INVALID_OUT_DEST 0x10u
|
||||||
|
#define _PIO_INVALID_SET_DEST 0x20u
|
||||||
|
#define _PIO_INVALID_MOV_SRC 0x40u
|
||||||
|
#define _PIO_INVALID_MOV_DEST 0x80u
|
||||||
|
#else
|
||||||
|
#define _PIO_INVALID_IN_SRC 0u
|
||||||
|
#define _PIO_INVALID_OUT_DEST 0u
|
||||||
|
#define _PIO_INVALID_SET_DEST 0u
|
||||||
|
#define _PIO_INVALID_MOV_SRC 0u
|
||||||
|
#define _PIO_INVALID_MOV_DEST 0u
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! \brief Enumeration of values to pass for source/destination args for instruction encoding functions
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* \note Not all values are suitable for all functions. Validity is only checked in debug mode when
|
||||||
|
* `PARAM_ASSERTIONS_ENABLED_PIO_INSTRUCTIONS` is 1
|
||||||
|
*/
|
||||||
|
enum pio_src_dest {
|
||||||
|
pio_pins = 0u,
|
||||||
|
pio_x = 1u,
|
||||||
|
pio_y = 2u,
|
||||||
|
pio_null = 3u | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
|
||||||
|
pio_pindirs = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
|
||||||
|
pio_exec_mov = 4u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
|
||||||
|
pio_status = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_DEST,
|
||||||
|
pio_pc = 5u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC,
|
||||||
|
pio_isr = 6u | _PIO_INVALID_SET_DEST,
|
||||||
|
pio_osr = 7u | _PIO_INVALID_OUT_DEST | _PIO_INVALID_SET_DEST,
|
||||||
|
pio_exec_out = 7u | _PIO_INVALID_IN_SRC | _PIO_INVALID_SET_DEST | _PIO_INVALID_MOV_SRC | _PIO_INVALID_MOV_DEST,
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline uint _pio_major_instr_bits(uint instr) {
|
||||||
|
return instr & 0xe000u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint _pio_encode_instr_and_args(enum pio_instr_bits instr_bits, uint arg1, uint arg2) {
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, arg1 <= 0x7);
|
||||||
|
#if PARAM_ASSERTIONS_ENABLED(PIO_INSTRUCTIONS)
|
||||||
|
uint32_t major = _pio_major_instr_bits(instr_bits);
|
||||||
|
if (major == pio_instr_bits_in || major == pio_instr_bits_out) {
|
||||||
|
assert(arg2 && arg2 <= 32);
|
||||||
|
} else {
|
||||||
|
assert(arg2 <= 31);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return instr_bits | (arg1 << 5u) | (arg2 & 0x1fu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint _pio_encode_instr_and_src_dest(enum pio_instr_bits instr_bits, enum pio_src_dest dest, uint value) {
|
||||||
|
return _pio_encode_instr_and_args(instr_bits, dest & 7u, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode just the delay slot bits of an instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* \note This function does not return a valid instruction encoding; instead it returns an encoding of the delay
|
||||||
|
* slot suitable for `OR`ing with the result of an encoding function for an actual instruction. Care should be taken when
|
||||||
|
* combining the results of this function with the results of \ref pio_encode_sideset and \ref pio_encode_sideset_opt
|
||||||
|
* as they share the same bits within the instruction encoding.
|
||||||
|
*
|
||||||
|
* \param cycles the number of cycles 0-31 (or less if side set is being used)
|
||||||
|
* \return the delay slot bits to be ORed with an instruction encoding
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_delay(uint cycles) {
|
||||||
|
// note that the maximum cycles will be smaller if sideset_bit_count > 0
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, cycles <= 0x1f);
|
||||||
|
return cycles << 8u;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode just the side set bits of an instruction (in non optional side set mode)
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* \note This function does not return a valid instruction encoding; instead it returns an encoding of the side set bits
|
||||||
|
* suitable for `OR`ing with the result of an encoding function for an actual instruction. Care should be taken when
|
||||||
|
* combining the results of this function with the results of \ref pio_encode_delay as they share the same bits
|
||||||
|
* within the instruction encoding.
|
||||||
|
*
|
||||||
|
* \param sideset_bit_count number of side set bits as would be specified via `.sideset` in pioasm
|
||||||
|
* \param value the value to sideset on the pins
|
||||||
|
* \return the side set bits to be ORed with an instruction encoding
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_sideset(uint sideset_bit_count, uint value) {
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, sideset_bit_count >= 1 && sideset_bit_count <= 5);
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, value <= ((1u << sideset_bit_count) - 1));
|
||||||
|
return value << (13u - sideset_bit_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode just the side set bits of an instruction (in optional -`opt` side set mode)
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* \note This function does not return a valid instruction encoding; instead it returns an encoding of the side set bits
|
||||||
|
* suitable for `OR`ing with the result of an encoding function for an actual instruction. Care should be taken when
|
||||||
|
* combining the results of this function with the results of \ref pio_encode_delay as they share the same bits
|
||||||
|
* within the instruction encoding.
|
||||||
|
*
|
||||||
|
* \param sideset_bit_count number of side set bits as would be specified via `.sideset <n> opt` in pioasm
|
||||||
|
* \param value the value to sideset on the pins
|
||||||
|
* \return the side set bits to be ORed with an instruction encoding
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_sideset_opt(uint sideset_bit_count, uint value) {
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, sideset_bit_count >= 1 && sideset_bit_count <= 4);
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, value <= ((1u << sideset_bit_count) - 1));
|
||||||
|
return 0x1000u | value << (12u - sideset_bit_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode an unconditional JMP instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `JMP <addr>`
|
||||||
|
*
|
||||||
|
* \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_jmp(uint addr) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_jmp, 0, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a conditional JMP if scratch X zero instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `JMP !X <addr>`
|
||||||
|
*
|
||||||
|
* \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_jmp_not_x(uint addr) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_jmp, 1, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a conditional JMP if scratch X non-zero (and post-decrement X) instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `JMP X-- <addr>`
|
||||||
|
*
|
||||||
|
* \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_jmp_x_dec(uint addr) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_jmp, 2, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a conditional JMP if scratch Y zero instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `JMP !Y <addr>`
|
||||||
|
*
|
||||||
|
* \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_jmp_not_y(uint addr) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_jmp, 3, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a conditional JMP if scratch Y non-zero (and post-decrement Y) instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `JMP Y-- <addr>`
|
||||||
|
*
|
||||||
|
* \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_jmp_y_dec(uint addr) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_jmp, 4, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a conditional JMP if scratch X not equal scratch Y instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `JMP X!=Y <addr>`
|
||||||
|
*
|
||||||
|
* \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_jmp_x_ne_y(uint addr) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_jmp, 5, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a conditional JMP if input pin high instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `JMP PIN <addr>`
|
||||||
|
*
|
||||||
|
* \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_jmp_pin(uint addr) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_jmp, 6, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a conditional JMP if output shift register not empty instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `JMP !OSRE <addr>`
|
||||||
|
*
|
||||||
|
* \param addr The target address 0-31 (an absolute address within the PIO instruction memory)
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_jmp_not_osre(uint addr) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_jmp, 7, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint _pio_encode_irq(bool relative, uint irq) {
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, irq <= 7);
|
||||||
|
return (relative ? 0x10u : 0x0u) | irq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a WAIT for GPIO pin instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `WAIT <polarity> GPIO <gpio>`
|
||||||
|
*
|
||||||
|
* \param polarity true for `WAIT 1`, false for `WAIT 0`
|
||||||
|
* \param gpio The real GPIO number 0-31
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_wait_gpio(bool polarity, uint gpio) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_wait, 0u | (polarity ? 4u : 0u), gpio);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a WAIT for pin instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `WAIT <polarity> PIN <pin>`
|
||||||
|
*
|
||||||
|
* \param polarity true for `WAIT 1`, false for `WAIT 0`
|
||||||
|
* \param pin The pin number 0-31 relative to the executing SM's input pin mapping
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_wait_pin(bool polarity, uint pin) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_wait, 1u | (polarity ? 4u : 0u), pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a WAIT for IRQ instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `WAIT <polarity> IRQ <irq> <relative>`
|
||||||
|
*
|
||||||
|
* \param polarity true for `WAIT 1`, false for `WAIT 0`
|
||||||
|
* \param relative true for a `WAIT IRQ <irq> REL`, false for regular `WAIT IRQ <irq>`
|
||||||
|
* \param irq the irq number 0-7
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_wait_irq(bool polarity, bool relative, uint irq) {
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, irq <= 7);
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_wait, 2u | (polarity ? 4u : 0u), _pio_encode_irq(relative, irq));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode an IN instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `IN <src>, <count>`
|
||||||
|
*
|
||||||
|
* \param src The source to take data from
|
||||||
|
* \param count The number of bits 1-32
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_in(enum pio_src_dest src, uint count) {
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_IN_SRC));
|
||||||
|
return _pio_encode_instr_and_src_dest(pio_instr_bits_in, src, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode an OUT instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `OUT <src>, <count>`
|
||||||
|
*
|
||||||
|
* \param dest The destination to write data to
|
||||||
|
* \param count The number of bits 1-32
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_out(enum pio_src_dest dest, uint count) {
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_OUT_DEST));
|
||||||
|
return _pio_encode_instr_and_src_dest(pio_instr_bits_out, dest, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a PUSH instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `PUSH <if_full>, <block>`
|
||||||
|
*
|
||||||
|
* \param if_full true for `PUSH IF_FULL ...`, false for `PUSH ...`
|
||||||
|
* \param block true for `PUSH ... BLOCK`, false for `PUSH ...`
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_push(bool if_full, bool block) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_push, (if_full ? 2u : 0u) | (block ? 1u : 0u), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a PULL instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `PULL <if_empty>, <block>`
|
||||||
|
*
|
||||||
|
* \param if_empty true for `PULL IF_EMPTY ...`, false for `PULL ...`
|
||||||
|
* \param block true for `PULL ... BLOCK`, false for `PULL ...`
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_pull(bool if_empty, bool block) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_pull, (if_empty ? 2u : 0u) | (block ? 1u : 0u), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a MOV instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `MOV <dest>, <src>`
|
||||||
|
*
|
||||||
|
* \param dest The destination to write data to
|
||||||
|
* \param src The source to take data from
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_mov(enum pio_src_dest dest, enum pio_src_dest src) {
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
|
||||||
|
return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, src & 7u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a MOV instruction with bit invert
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `MOV <dest>, ~<src>`
|
||||||
|
*
|
||||||
|
* \param dest The destination to write inverted data to
|
||||||
|
* \param src The source to take data from
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_mov_not(enum pio_src_dest dest, enum pio_src_dest src) {
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
|
||||||
|
return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, (1u << 3u) | (src & 7u));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a MOV instruction with bit reverse
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `MOV <dest>, ::<src>`
|
||||||
|
*
|
||||||
|
* \param dest The destination to write bit reversed data to
|
||||||
|
* \param src The source to take data from
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_mov_reverse(enum pio_src_dest dest, enum pio_src_dest src) {
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_MOV_DEST));
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, !(src & _PIO_INVALID_MOV_SRC));
|
||||||
|
return _pio_encode_instr_and_src_dest(pio_instr_bits_mov, dest, (2u << 3u) | (src & 7u));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a IRQ SET instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `IRQ SET <irq> <relative>`
|
||||||
|
*
|
||||||
|
* \param relative true for a `IRQ SET <irq> REL`, false for regular `IRQ SET <irq>`
|
||||||
|
* \param irq the irq number 0-7
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_irq_set(bool relative, uint irq) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_irq, 0, _pio_encode_irq(relative, irq));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a IRQ WAIT instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `IRQ WAIT <irq> <relative>`
|
||||||
|
*
|
||||||
|
* \param relative true for a `IRQ WAIT <irq> REL`, false for regular `IRQ WAIT <irq>`
|
||||||
|
* \param irq the irq number 0-7
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_irq_wait(bool relative, uint irq) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_irq, 1, _pio_encode_irq(relative, irq));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a IRQ CLEAR instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `IRQ CLEAR <irq> <relative>`
|
||||||
|
*
|
||||||
|
* \param relative true for a `IRQ CLEAR <irq> REL`, false for regular `IRQ CLEAR <irq>`
|
||||||
|
* \param irq the irq number 0-7
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_irq_clear(bool relative, uint irq) {
|
||||||
|
return _pio_encode_instr_and_args(pio_instr_bits_irq, 2, _pio_encode_irq(relative, irq));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a SET instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `SET <dest>, <value>`
|
||||||
|
*
|
||||||
|
* \param dest The destination to apply the value to
|
||||||
|
* \param value The value 0-31
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_set(enum pio_src_dest dest, uint value) {
|
||||||
|
valid_params_if(PIO_INSTRUCTIONS, !(dest & _PIO_INVALID_SET_DEST));
|
||||||
|
return _pio_encode_instr_and_src_dest(pio_instr_bits_set, dest, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Encode a NOP instruction
|
||||||
|
* \ingroup pio_instructions
|
||||||
|
*
|
||||||
|
* This is the equivalent of `NOP` which is itself encoded as `MOV y, y`
|
||||||
|
*
|
||||||
|
* \return The instruction encoding with 0 delay and no side set value
|
||||||
|
* \see pio_encode_delay, pio_encode_sideset, pio_encode_sideset_opt
|
||||||
|
*/
|
||||||
|
static inline uint pio_encode_nop(void) {
|
||||||
|
return pio_encode_mov(pio_y, pio_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
1019
include/linux/pio_rp1.h
Normal file
1019
include/linux/pio_rp1.h
Normal file
File diff suppressed because it is too large
Load Diff
235
include/uapi/misc/rp1_pio_if.h
Normal file
235
include/uapi/misc/rp1_pio_if.h
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 + WITH Linux-syscall-note */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023-24 Raspberry Pi Ltd.
|
||||||
|
* All rights reserved.
|
||||||
|
*/
|
||||||
|
#ifndef _PIO_RP1_IF_H
|
||||||
|
#define _PIO_RP1_IF_H
|
||||||
|
|
||||||
|
#include <linux/ioctl.h>
|
||||||
|
|
||||||
|
#define RP1_PIO_INSTRUCTION_COUNT 32
|
||||||
|
#define RP1_PIO_SM_COUNT 4
|
||||||
|
#define RP1_PIO_GPIO_COUNT 28
|
||||||
|
#define RP1_GPIO_FUNC_PIO 7
|
||||||
|
|
||||||
|
#define RP1_PIO_ORIGIN_ANY ((uint16_t)(~0))
|
||||||
|
|
||||||
|
#define RP1_PIO_DIR_TO_SM 0
|
||||||
|
#define RP1_PIO_DIR_FROM_SM 1
|
||||||
|
#define RP1_PIO_DIR_COUNT 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t clkdiv;
|
||||||
|
uint32_t execctrl;
|
||||||
|
uint32_t shiftctrl;
|
||||||
|
uint32_t pinctrl;
|
||||||
|
} rp1_pio_sm_config;
|
||||||
|
|
||||||
|
struct rp1_pio_add_program_args {
|
||||||
|
uint16_t num_instrs;
|
||||||
|
uint16_t origin;
|
||||||
|
uint16_t instrs[RP1_PIO_INSTRUCTION_COUNT];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_remove_program_args {
|
||||||
|
uint16_t num_instrs;
|
||||||
|
uint16_t origin;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_claim_args {
|
||||||
|
uint16_t mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_init_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint16_t initial_pc;
|
||||||
|
rp1_pio_sm_config config;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_set_config_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint16_t rsvd;
|
||||||
|
rp1_pio_sm_config config;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_exec_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint16_t instr;
|
||||||
|
uint8_t blocking;
|
||||||
|
uint8_t rsvd;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_clear_fifos_args {
|
||||||
|
uint16_t sm;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_set_clkdiv_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint16_t div_int;
|
||||||
|
uint8_t div_frac;
|
||||||
|
uint8_t rsvd;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_set_pins_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint16_t rsvd;
|
||||||
|
uint32_t values;
|
||||||
|
uint32_t mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_set_pindirs_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint16_t rsvd;
|
||||||
|
uint32_t dirs;
|
||||||
|
uint32_t mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_set_enabled_args {
|
||||||
|
uint16_t mask;
|
||||||
|
uint8_t enable;
|
||||||
|
uint8_t rsvd;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_restart_args {
|
||||||
|
uint16_t mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_clkdiv_restart_args {
|
||||||
|
uint16_t mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_enable_sync_args {
|
||||||
|
uint16_t mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_put_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint8_t blocking;
|
||||||
|
uint8_t rsvd;
|
||||||
|
uint32_t data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_get_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint8_t blocking;
|
||||||
|
uint8_t rsvd;
|
||||||
|
uint32_t data; /* OUT */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_set_dmactrl_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint8_t is_tx;
|
||||||
|
uint8_t rsvd;
|
||||||
|
uint32_t ctrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_fifo_state_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint8_t tx;
|
||||||
|
uint8_t rsvd;
|
||||||
|
uint16_t level; /* OUT */
|
||||||
|
uint8_t empty; /* OUT */
|
||||||
|
uint8_t full; /* OUT */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_gpio_init_args {
|
||||||
|
uint16_t gpio;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_gpio_set_function_args {
|
||||||
|
uint16_t gpio;
|
||||||
|
uint16_t fn;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_gpio_set_pulls_args {
|
||||||
|
uint16_t gpio;
|
||||||
|
uint8_t up;
|
||||||
|
uint8_t down;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_gpio_set_args {
|
||||||
|
uint16_t gpio;
|
||||||
|
uint16_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_config_xfer_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint16_t dir;
|
||||||
|
uint16_t buf_size;
|
||||||
|
uint16_t buf_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_config_xfer32_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint16_t dir;
|
||||||
|
uint32_t buf_size;
|
||||||
|
uint32_t buf_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_xfer_data_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint16_t dir;
|
||||||
|
uint16_t data_bytes;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_pio_sm_xfer_data32_args {
|
||||||
|
uint16_t sm;
|
||||||
|
uint16_t dir;
|
||||||
|
uint32_t data_bytes;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rp1_access_hw_args {
|
||||||
|
uint32_t addr;
|
||||||
|
uint32_t len;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PIO_IOC_MAGIC 102
|
||||||
|
|
||||||
|
#define PIO_IOC_SM_CONFIG_XFER _IOW(PIO_IOC_MAGIC, 0, struct rp1_pio_sm_config_xfer_args)
|
||||||
|
#define PIO_IOC_SM_XFER_DATA _IOW(PIO_IOC_MAGIC, 1, struct rp1_pio_sm_xfer_data_args)
|
||||||
|
#define PIO_IOC_SM_XFER_DATA32 _IOW(PIO_IOC_MAGIC, 2, struct rp1_pio_sm_xfer_data32_args)
|
||||||
|
#define PIO_IOC_SM_CONFIG_XFER32 _IOW(PIO_IOC_MAGIC, 3, struct rp1_pio_sm_config_xfer32_args)
|
||||||
|
|
||||||
|
#define PIO_IOC_READ_HW _IOW(PIO_IOC_MAGIC, 8, struct rp1_access_hw_args)
|
||||||
|
#define PIO_IOC_WRITE_HW _IOW(PIO_IOC_MAGIC, 9, struct rp1_access_hw_args)
|
||||||
|
|
||||||
|
#define PIO_IOC_CAN_ADD_PROGRAM _IOW(PIO_IOC_MAGIC, 10, struct rp1_pio_add_program_args)
|
||||||
|
#define PIO_IOC_ADD_PROGRAM _IOW(PIO_IOC_MAGIC, 11, struct rp1_pio_add_program_args)
|
||||||
|
#define PIO_IOC_REMOVE_PROGRAM _IOW(PIO_IOC_MAGIC, 12, struct rp1_pio_remove_program_args)
|
||||||
|
#define PIO_IOC_CLEAR_INSTR_MEM _IO(PIO_IOC_MAGIC, 13)
|
||||||
|
|
||||||
|
#define PIO_IOC_SM_CLAIM _IOW(PIO_IOC_MAGIC, 20, struct rp1_pio_sm_claim_args)
|
||||||
|
#define PIO_IOC_SM_UNCLAIM _IOW(PIO_IOC_MAGIC, 21, struct rp1_pio_sm_claim_args)
|
||||||
|
#define PIO_IOC_SM_IS_CLAIMED _IOW(PIO_IOC_MAGIC, 22, struct rp1_pio_sm_claim_args)
|
||||||
|
|
||||||
|
#define PIO_IOC_SM_INIT _IOW(PIO_IOC_MAGIC, 30, struct rp1_pio_sm_init_args)
|
||||||
|
#define PIO_IOC_SM_SET_CONFIG _IOW(PIO_IOC_MAGIC, 31, struct rp1_pio_sm_set_config_args)
|
||||||
|
#define PIO_IOC_SM_EXEC _IOW(PIO_IOC_MAGIC, 32, struct rp1_pio_sm_exec_args)
|
||||||
|
#define PIO_IOC_SM_CLEAR_FIFOS _IOW(PIO_IOC_MAGIC, 33, struct rp1_pio_sm_clear_fifos_args)
|
||||||
|
#define PIO_IOC_SM_SET_CLKDIV _IOW(PIO_IOC_MAGIC, 34, struct rp1_pio_sm_set_clkdiv_args)
|
||||||
|
#define PIO_IOC_SM_SET_PINS _IOW(PIO_IOC_MAGIC, 35, struct rp1_pio_sm_set_pins_args)
|
||||||
|
#define PIO_IOC_SM_SET_PINDIRS _IOW(PIO_IOC_MAGIC, 36, struct rp1_pio_sm_set_pindirs_args)
|
||||||
|
#define PIO_IOC_SM_SET_ENABLED _IOW(PIO_IOC_MAGIC, 37, struct rp1_pio_sm_set_enabled_args)
|
||||||
|
#define PIO_IOC_SM_RESTART _IOW(PIO_IOC_MAGIC, 38, struct rp1_pio_sm_restart_args)
|
||||||
|
#define PIO_IOC_SM_CLKDIV_RESTART _IOW(PIO_IOC_MAGIC, 39, struct rp1_pio_sm_restart_args)
|
||||||
|
#define PIO_IOC_SM_ENABLE_SYNC _IOW(PIO_IOC_MAGIC, 40, struct rp1_pio_sm_enable_sync_args)
|
||||||
|
#define PIO_IOC_SM_PUT _IOW(PIO_IOC_MAGIC, 41, struct rp1_pio_sm_put_args)
|
||||||
|
#define PIO_IOC_SM_GET _IOWR(PIO_IOC_MAGIC, 42, struct rp1_pio_sm_get_args)
|
||||||
|
#define PIO_IOC_SM_SET_DMACTRL _IOW(PIO_IOC_MAGIC, 43, struct rp1_pio_sm_set_dmactrl_args)
|
||||||
|
#define PIO_IOC_SM_FIFO_STATE _IOW(PIO_IOC_MAGIC, 44, struct rp1_pio_sm_fifo_state_args)
|
||||||
|
#define PIO_IOC_SM_DRAIN_TX _IOW(PIO_IOC_MAGIC, 45, struct rp1_pio_sm_clear_fifos_args)
|
||||||
|
|
||||||
|
#define PIO_IOC_GPIO_INIT _IOW(PIO_IOC_MAGIC, 50, struct rp1_gpio_init_args)
|
||||||
|
#define PIO_IOC_GPIO_SET_FUNCTION _IOW(PIO_IOC_MAGIC, 51, struct rp1_gpio_set_function_args)
|
||||||
|
#define PIO_IOC_GPIO_SET_PULLS _IOW(PIO_IOC_MAGIC, 52, struct rp1_gpio_set_pulls_args)
|
||||||
|
#define PIO_IOC_GPIO_SET_OUTOVER _IOW(PIO_IOC_MAGIC, 53, struct rp1_gpio_set_args)
|
||||||
|
#define PIO_IOC_GPIO_SET_INOVER _IOW(PIO_IOC_MAGIC, 54, struct rp1_gpio_set_args)
|
||||||
|
#define PIO_IOC_GPIO_SET_OEOVER _IOW(PIO_IOC_MAGIC, 55, struct rp1_gpio_set_args)
|
||||||
|
#define PIO_IOC_GPIO_SET_INPUT_ENABLED _IOW(PIO_IOC_MAGIC, 56, struct rp1_gpio_set_args)
|
||||||
|
#define PIO_IOC_GPIO_SET_DRIVE_STRENGTH _IOW(PIO_IOC_MAGIC, 57, struct rp1_gpio_set_args)
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user