From f580d9c8fe9894f8c0d75d859c9a631494713eb8 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 16 Dec 2024 23:01:41 +0000 Subject: [PATCH] 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 --- drivers/misc/rp1-pio.c | 43 +++++++++++++++++++++++++++++++--- include/uapi/misc/rp1_pio_if.h | 8 +++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/drivers/misc/rp1-pio.c b/drivers/misc/rp1-pio.c index fcb3376e882c35..a5469cdf156bb2 100644 --- a/drivers/misc/rp1-pio.c +++ b/drivers/misc/rp1-pio.c @@ -824,9 +824,9 @@ static int rp1_pio_sm_rx_user(struct rp1_pio_device *pio, struct dma_info *dma, return ret; } -static int rp1_pio_sm_xfer_data(struct rp1_pio_client *client, void *param) +static int rp1_pio_sm_xfer_data32(struct rp1_pio_client *client, void *param) { - struct rp1_pio_sm_xfer_data_args *args = param; + struct rp1_pio_sm_xfer_data32_args *args = param; struct rp1_pio_device *pio = client->pio; struct dma_info *dma; @@ -842,6 +842,19 @@ static int rp1_pio_sm_xfer_data(struct rp1_pio_client *client, void *param) return rp1_pio_sm_rx_user(pio, dma, args->data, args->data_bytes); } +static int rp1_pio_sm_xfer_data(struct rp1_pio_client *client, void *param) +{ + struct rp1_pio_sm_xfer_data_args *args = param; + struct rp1_pio_sm_xfer_data32_args args32; + + args32.sm = args->sm; + args32.dir = args->dir; + args32.data_bytes = args->data_bytes; + args32.data = args->data; + + return rp1_pio_sm_xfer_data32(client, &args32); +} + struct handler_info { const char *name; int (*func)(struct rp1_pio_client *client, void *param); @@ -849,6 +862,7 @@ struct handler_info { } ioctl_handlers[] = { HANDLER(SM_CONFIG_XFER, sm_config_xfer), HANDLER(SM_XFER_DATA, sm_xfer_data), + HANDLER(SM_XFER_DATA32, sm_xfer_data32), HANDLER(CAN_ADD_PROGRAM, can_add_program), HANDLER(ADD_PROGRAM, add_program), @@ -1032,13 +1046,23 @@ struct rp1_pio_sm_xfer_data_args_compat { compat_uptr_t data; }; +struct rp1_pio_sm_xfer_data32_args_compat { + uint16_t sm; + uint16_t dir; + uint32_t data_bytes; + compat_uptr_t data; +}; + struct rp1_access_hw_args_compat { uint32_t addr; uint32_t len; compat_uptr_t data; }; -#define PIO_IOC_SM_XFER_DATA_COMPAT _IOW(PIO_IOC_MAGIC, 1, struct rp1_pio_sm_xfer_data_args_compat) +#define PIO_IOC_SM_XFER_DATA_COMPAT \ + _IOW(PIO_IOC_MAGIC, 1, struct rp1_pio_sm_xfer_data_args_compat) +#define PIO_IOC_SM_XFER_DATA32_COMPAT \ + _IOW(PIO_IOC_MAGIC, 2, struct rp1_pio_sm_xfer_data32_args_compat) #define PIO_IOC_READ_HW_COMPAT _IOW(PIO_IOC_MAGIC, 8, struct rp1_access_hw_args_compat) #define PIO_IOC_WRITE_HW_COMPAT _IOW(PIO_IOC_MAGIC, 9, struct rp1_access_hw_args_compat) @@ -1061,6 +1085,19 @@ static long rp1_pio_compat_ioctl(struct file *filp, unsigned int ioctl_num, param.data = compat_ptr(compat_param.data); return rp1_pio_sm_xfer_data(client, ¶m); } + case PIO_IOC_SM_XFER_DATA32_COMPAT: + { + struct rp1_pio_sm_xfer_data32_args_compat compat_param; + struct rp1_pio_sm_xfer_data32_args param; + + if (copy_from_user(&compat_param, compat_ptr(ioctl_param), sizeof(compat_param))) + return -EFAULT; + param.sm = compat_param.sm; + param.dir = compat_param.dir; + param.data_bytes = compat_param.data_bytes; + param.data = compat_ptr(compat_param.data); + return rp1_pio_sm_xfer_data32(client, ¶m); + } case PIO_IOC_READ_HW_COMPAT: case PIO_IOC_WRITE_HW_COMPAT: diff --git a/include/uapi/misc/rp1_pio_if.h b/include/uapi/misc/rp1_pio_if.h index 5409e93c771caa..0a0d4aca11dd48 100644 --- a/include/uapi/misc/rp1_pio_if.h +++ b/include/uapi/misc/rp1_pio_if.h @@ -167,6 +167,13 @@ struct rp1_pio_sm_xfer_data_args { 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; @@ -177,6 +184,7 @@ struct rp1_access_hw_args { #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_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)