mirror of
https://github.com/openwrt/openwrt.git
synced 2025-01-10 06:52:53 +00:00
216 lines
6.9 KiB
Diff
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)
|