openwrt/target/linux/bcm27xx/patches-6.6/950-1359-misc-rp1-pio-Add-FIFO.patch
John Audia f4c5d0e77e bcm27xx: patches: cherry-pick for RP1 kmods
Cherry-pick patches to support building RP1 modules.

Signed-off-by: John Audia <therealgraysky@proton.me>
Link: https://github.com/openwrt/openwrt/pull/17233
Signed-off-by: Robert Marko <robimarko@gmail.com>
(cherry picked from commit 613dd79d5e)
2024-12-28 14:11:52 +01:00

216 lines
6.9 KiB
Diff

From dd2394360860d15146c96635796a75b05bb32b61 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.com>
Date: Tue, 19 Nov 2024 09:25:34 +0000
Subject: [PATCH] misc: rp1-pio: Add FIFO-related methods
Add support for querying the FIFO status and clearing the TX FIFO.
Signed-off-by: Phil Elwell <phil@raspberrypi.com>
---
drivers/misc/rp1-fw-pio.h | 3 ++
drivers/misc/rp1-pio.c | 24 +++++++++
include/linux/pio_rp1.h | 89 ++++++++++++++++++++++++++++++++++
include/uapi/misc/rp1_pio_if.h | 13 ++++-
4 files changed, 128 insertions(+), 1 deletion(-)
--- a/drivers/misc/rp1-fw-pio.h
+++ b/drivers/misc/rp1-fw-pio.h
@@ -47,6 +47,9 @@ enum rp1_pio_ops {
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
};
--- a/drivers/misc/rp1-pio.c
+++ b/drivers/misc/rp1-pio.c
@@ -479,6 +479,28 @@ int rp1_pio_sm_set_dmactrl(struct rp1_pi
}
EXPORT_SYMBOL_GPL(rp1_pio_sm_set_dmactrl);
+int rp1_pio_sm_fifo_state(struct rp1_pio_client *client, void *param)
+{
+ struct rp1_pio_sm_fifo_state_args *args = param;
+ const int level_offset = offsetof(struct rp1_pio_sm_fifo_state_args, level);
+ int ret;
+
+ ret = rp1_pio_message_resp(client->pio, PIO_SM_FIFO_STATE, args, sizeof(*args),
+ &args->level, NULL, sizeof(*args) - level_offset);
+ if (ret >= 0)
+ return level_offset + ret;
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rp1_pio_sm_fifo_state);
+
+int rp1_pio_sm_drain_tx(struct rp1_pio_client *client, void *param)
+{
+ struct rp1_pio_sm_clear_fifos_args *args = param;
+
+ return rp1_pio_message(client->pio, PIO_SM_DRAIN_TX, args, sizeof(*args));
+}
+EXPORT_SYMBOL_GPL(rp1_pio_sm_drain_tx);
+
int rp1_pio_gpio_init(struct rp1_pio_client *client, void *param)
{
struct rp1_gpio_init_args *args = param;
@@ -851,6 +873,8 @@ struct handler_info {
HANDLER(SM_PUT, sm_put),
HANDLER(SM_GET, sm_get),
HANDLER(SM_SET_DMACTRL, sm_set_dmactrl),
+ HANDLER(SM_FIFO_STATE, sm_fifo_state),
+ HANDLER(SM_DRAIN_TX, sm_drain_tx),
HANDLER(GPIO_INIT, gpio_init),
HANDLER(GPIO_SET_FUNCTION, gpio_set_function),
--- a/include/linux/pio_rp1.h
+++ b/include/linux/pio_rp1.h
@@ -200,6 +200,8 @@ int rp1_pio_sm_enable_sync(struct rp1_pi
int rp1_pio_sm_put(struct rp1_pio_client *client, void *param);
int rp1_pio_sm_get(struct rp1_pio_client *client, void *param);
int rp1_pio_sm_set_dmactrl(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_fifo_state(struct rp1_pio_client *client, void *param);
+int rp1_pio_sm_drain_tx(struct rp1_pio_client *client, void *param);
int rp1_pio_gpio_init(struct rp1_pio_client *client, void *param);
int rp1_pio_gpio_set_function(struct rp1_pio_client *client, void *param);
int rp1_pio_gpio_set_pulls(struct rp1_pio_client *client, void *param);
@@ -551,6 +553,15 @@ static inline int pio_sm_set_dmactrl(str
return rp1_pio_sm_set_dmactrl(client, &args);
};
+static inline int pio_sm_drain_tx_fifo(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_clear_fifos_args args = { .sm = sm };
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ return rp1_pio_sm_drain_tx(client, &args);
+};
+
static inline int pio_sm_put(struct rp1_pio_client *client, uint sm, uint32_t data)
{
struct rp1_pio_sm_put_args args = { .sm = (uint16_t)sm, .blocking = false, .data = data };
@@ -587,6 +598,84 @@ static inline uint32_t pio_sm_get_blocki
return args.data;
}
+static inline int pio_sm_is_rx_fifo_empty(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_fifo_state_args args = { .sm = sm, .tx = false };
+ int ret;
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ ret = rp1_pio_sm_fifo_state(client, &args);
+ if (ret == sizeof(args))
+ ret = args.empty;
+ return ret;
+};
+
+static inline int pio_sm_is_rx_fifo_full(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_fifo_state_args args = { .sm = sm, .tx = false };
+ int ret;
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ ret = rp1_pio_sm_fifo_state(client, &args);
+ if (ret == sizeof(args))
+ ret = args.full;
+ return ret;
+};
+
+static inline int pio_sm_rx_fifo_level(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_fifo_state_args args = { .sm = sm, .tx = false };
+ int ret;
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ ret = rp1_pio_sm_fifo_state(client, &args);
+ if (ret == sizeof(args))
+ ret = args.level;
+ return ret;
+};
+
+static inline int pio_sm_is_tx_fifo_empty(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_fifo_state_args args = { .sm = sm, .tx = true };
+ int ret;
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ ret = rp1_pio_sm_fifo_state(client, &args);
+ if (ret == sizeof(args))
+ ret = args.empty;
+ return ret;
+};
+
+static inline int pio_sm_is_tx_fifo_full(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_fifo_state_args args = { .sm = sm, .tx = true };
+ int ret;
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ ret = rp1_pio_sm_fifo_state(client, &args);
+ if (ret == sizeof(args))
+ ret = args.full;
+ return ret;
+};
+
+static inline int pio_sm_tx_fifo_level(struct rp1_pio_client *client, uint sm)
+{
+ struct rp1_pio_sm_fifo_state_args args = { .sm = sm, .tx = true };
+ int ret;
+
+ if (bad_params_if(client, sm >= NUM_PIO_STATE_MACHINES))
+ return -EINVAL;
+ ret = rp1_pio_sm_fifo_state(client, &args);
+ if (ret == sizeof(args))
+ ret = args.level;
+ return ret;
+};
+
static inline void sm_config_set_out_pins(pio_sm_config *c, uint out_base, uint out_count)
{
if (bad_params_if(NULL, out_base >= RP1_PIO_GPIO_COUNT ||
--- a/include/uapi/misc/rp1_pio_if.h
+++ b/include/uapi/misc/rp1_pio_if.h
@@ -114,7 +114,7 @@ struct rp1_pio_sm_get_args {
uint16_t sm;
uint8_t blocking;
uint8_t rsvd;
- uint32_t data; /* IN/OUT */
+ uint32_t data; /* OUT */
};
struct rp1_pio_sm_set_dmactrl_args {
@@ -124,6 +124,15 @@ struct rp1_pio_sm_set_dmactrl_args {
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;
};
@@ -195,6 +204,8 @@ struct rp1_access_hw_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)