2022-04-18 13:09:09

by Puranjay Mohan

[permalink] [raw]
Subject: [PATCH v2 0/6] Introduce PRU platform consumer API

This is the re-spin of the old patch series[1]. This doesn't have any
functional changes, the old series has been rebased on linux-next.

This series depends on another un-merged series in the remoteproc
tree[2]. This series and the remoteproc series form the PRUSS comsumer
API which can be used by consumer drivers to utilize the PRUs.

One example of the consumer driver is the PRU-ICSSG ethernet driver,
which depends on this series and the remoteproc series[2].

I had earlier sent all the three series, this, remoteproc, and the
ethernet driver as RFC to get comments. It can be seen here[3] to
understand the overall structure.

The Programmable Real-Time Unit and Industrial Communication Subsystem (PRU-ICSS
or simply PRUSS) on various TI SoCs consists of dual 32-bit RISC cores
(Programmable Real-Time Units, or PRUs) for program execution.

There are 3 foundation components for TI PRUSS subsystem: the PRUSS platform
driver, the PRUSS INTC driver and the PRUSS remoteproc driver.

The programmable nature of the PRUs provide flexibility to implement custom
peripheral interfaces, fast real-time responses, or specialized data handling.
Example of a PRU consumer drivers will be:
- Software UART over PRUSS
- PRU-ICSS Ethernet EMAC

In order to make usage of common PRU resources and allow the consumer drivers to
configure the PRU hardware for specific usage the PRU API is introduced.

[1] https://patchwork.kernel.org/project/linux-remoteproc/cover/[email protected]/
[2] https://patchwork.kernel.org/project/linux-remoteproc/cover/[email protected]/
[3] https://patchwork.kernel.org/project/linux-remoteproc/cover/[email protected]/

Thanks,
Puranjay Mohan

Andrew F. Davis (1):
soc: ti: pruss: Add pruss_{request,release}_mem_region() API

Suman Anna (3):
soc: ti: pruss: Add pruss_cfg_read()/update() API
soc: ti: pruss: Add helper functions to set GPI mode, MII_RT_event and
XFR
soc: ti: pruss: Add helper function to enable OCP master ports

Tero Kristo (2):
soc: ti: pruss: Add pruss_get()/put() API
soc: ti: pruss: Add helper functions to get/set PRUSS_CFG_GPMUX

drivers/soc/ti/pruss.c | 257 ++++++++++++++++++++++++++++++++++-
include/linux/pruss.h | 221 ++++++++++++++++++++++++++++++
include/linux/pruss_driver.h | 72 +++++++---
3 files changed, 526 insertions(+), 24 deletions(-)

--
2.17.1


2022-04-18 13:09:25

by Puranjay Mohan

[permalink] [raw]
Subject: [PATCH v2 3/6] soc: ti: pruss: Add pruss_cfg_read()/update() API

From: Suman Anna <[email protected]>

Add two new generic API pruss_cfg_read() and pruss_cfg_update() to
the PRUSS platform driver to allow other drivers to read and program
respectively a register within the PRUSS CFG sub-module represented
by a syscon driver. This interface provides a simple way for client
drivers without having them to include and parse the CFG syscon node
within their respective device nodes. Various useful registers and
macros for certain register bit-fields and their values have also
been added.

It is the responsibility of the client drivers to reconfigure or
reset a particular register upon any failures.

Signed-off-by: Suman Anna <[email protected]>
Co-developed-by: Grzegorz Jaszczyk <[email protected]>
Signed-off-by: Grzegorz Jaszczyk <[email protected]>
Signed-off-by: Puranjay Mohan <[email protected]>
---
drivers/soc/ti/pruss.c | 41 +++++++++++++++++
include/linux/pruss.h | 102 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 143 insertions(+)

diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c
index 95c0cbd7c52f..bf5471c4fa33 100644
--- a/drivers/soc/ti/pruss.c
+++ b/drivers/soc/ti/pruss.c
@@ -164,6 +164,47 @@ int pruss_release_mem_region(struct pruss *pruss,
}
EXPORT_SYMBOL_GPL(pruss_release_mem_region);

+/**
+ * pruss_cfg_read() - read a PRUSS CFG sub-module register
+ * @pruss: the pruss instance handle
+ * @reg: register offset within the CFG sub-module
+ * @val: pointer to return the value in
+ *
+ * Reads a given register within the PRUSS CFG sub-module and
+ * returns it through the passed-in @val pointer
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int pruss_cfg_read(struct pruss *pruss, unsigned int reg, unsigned int *val)
+{
+ if (IS_ERR_OR_NULL(pruss))
+ return -EINVAL;
+
+ return regmap_read(pruss->cfg_regmap, reg, val);
+}
+EXPORT_SYMBOL_GPL(pruss_cfg_read);
+
+/**
+ * pruss_cfg_update() - configure a PRUSS CFG sub-module register
+ * @pruss: the pruss instance handle
+ * @reg: register offset within the CFG sub-module
+ * @mask: bit mask to use for programming the @val
+ * @val: value to write
+ *
+ * Programs a given register within the PRUSS CFG sub-module
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int pruss_cfg_update(struct pruss *pruss, unsigned int reg,
+ unsigned int mask, unsigned int val)
+{
+ if (IS_ERR_OR_NULL(pruss))
+ return -EINVAL;
+
+ return regmap_update_bits(pruss->cfg_regmap, reg, mask, val);
+}
+EXPORT_SYMBOL_GPL(pruss_cfg_update);
+
static void pruss_of_free_clk_provider(void *data)
{
struct device_node *clk_mux_np = data;
diff --git a/include/linux/pruss.h b/include/linux/pruss.h
index 689ef243bcbc..eb2f974eef9c 100644
--- a/include/linux/pruss.h
+++ b/include/linux/pruss.h
@@ -10,12 +10,99 @@
#ifndef __LINUX_PRUSS_H
#define __LINUX_PRUSS_H

+#include <linux/bits.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/types.h>

#define PRU_RPROC_DRVNAME "pru-rproc"

+/*
+ * PRU_ICSS_CFG registers
+ * SYSCFG, ISRP, ISP, IESP, IECP, SCRP applicable on AMxxxx devices only
+ */
+#define PRUSS_CFG_REVID 0x00
+#define PRUSS_CFG_SYSCFG 0x04
+#define PRUSS_CFG_GPCFG(x) (0x08 + (x) * 4)
+#define PRUSS_CFG_CGR 0x10
+#define PRUSS_CFG_ISRP 0x14
+#define PRUSS_CFG_ISP 0x18
+#define PRUSS_CFG_IESP 0x1C
+#define PRUSS_CFG_IECP 0x20
+#define PRUSS_CFG_SCRP 0x24
+#define PRUSS_CFG_PMAO 0x28
+#define PRUSS_CFG_MII_RT 0x2C
+#define PRUSS_CFG_IEPCLK 0x30
+#define PRUSS_CFG_SPP 0x34
+#define PRUSS_CFG_PIN_MX 0x40
+
+/* PRUSS_GPCFG register bits */
+#define PRUSS_GPCFG_PRU_GPO_SH_SEL BIT(25)
+
+#define PRUSS_GPCFG_PRU_DIV1_SHIFT 20
+#define PRUSS_GPCFG_PRU_DIV1_MASK GENMASK(24, 20)
+
+#define PRUSS_GPCFG_PRU_DIV0_SHIFT 15
+#define PRUSS_GPCFG_PRU_DIV0_MASK GENMASK(15, 19)
+
+#define PRUSS_GPCFG_PRU_GPO_MODE BIT(14)
+#define PRUSS_GPCFG_PRU_GPO_MODE_DIRECT 0
+#define PRUSS_GPCFG_PRU_GPO_MODE_SERIAL BIT(14)
+
+#define PRUSS_GPCFG_PRU_GPI_SB BIT(13)
+
+#define PRUSS_GPCFG_PRU_GPI_DIV1_SHIFT 8
+#define PRUSS_GPCFG_PRU_GPI_DIV1_MASK GENMASK(12, 8)
+
+#define PRUSS_GPCFG_PRU_GPI_DIV0_SHIFT 3
+#define PRUSS_GPCFG_PRU_GPI_DIV0_MASK GENMASK(7, 3)
+
+#define PRUSS_GPCFG_PRU_GPI_CLK_MODE_POSITIVE 0
+#define PRUSS_GPCFG_PRU_GPI_CLK_MODE_NEGATIVE BIT(2)
+#define PRUSS_GPCFG_PRU_GPI_CLK_MODE BIT(2)
+
+#define PRUSS_GPCFG_PRU_GPI_MODE_MASK GENMASK(1, 0)
+#define PRUSS_GPCFG_PRU_GPI_MODE_SHIFT 0
+
+#define PRUSS_GPCFG_PRU_MUX_SEL_SHIFT 26
+#define PRUSS_GPCFG_PRU_MUX_SEL_MASK GENMASK(29, 26)
+
+/* PRUSS_MII_RT register bits */
+#define PRUSS_MII_RT_EVENT_EN BIT(0)
+
+/* PRUSS_SPP register bits */
+#define PRUSS_SPP_XFER_SHIFT_EN BIT(1)
+#define PRUSS_SPP_PRU1_PAD_HP_EN BIT(0)
+
+/*
+ * enum pruss_gp_mux_sel - PRUSS GPI/O Mux modes for the
+ * PRUSS_GPCFG0/1 registers
+ *
+ * NOTE: The below defines are the most common values, but there
+ * are some exceptions like on 66AK2G, where the RESERVED and MII2
+ * values are interchanged. Also, this bit-field does not exist on
+ * AM335x SoCs
+ */
+enum pruss_gp_mux_sel {
+ PRUSS_GP_MUX_SEL_GP = 0,
+ PRUSS_GP_MUX_SEL_ENDAT,
+ PRUSS_GP_MUX_SEL_RESERVED,
+ PRUSS_GP_MUX_SEL_SD,
+ PRUSS_GP_MUX_SEL_MII2,
+ PRUSS_GP_MUX_SEL_MAX,
+};
+
+/*
+ * enum pruss_gpi_mode - PRUSS GPI configuration modes, used
+ * to program the PRUSS_GPCFG0/1 registers
+ */
+enum pruss_gpi_mode {
+ PRUSS_GPI_MODE_DIRECT = 0,
+ PRUSS_GPI_MODE_PARALLEL,
+ PRUSS_GPI_MODE_28BIT_SHIFT,
+ PRUSS_GPI_MODE_MII,
+};
+
/*
* enum pruss_pru_id - PRU core identifiers
*/
@@ -73,6 +160,9 @@ int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id,
struct pruss_mem_region *region);
int pruss_release_mem_region(struct pruss *pruss,
struct pruss_mem_region *region);
+int pruss_cfg_read(struct pruss *pruss, unsigned int reg, unsigned int *val);
+int pruss_cfg_update(struct pruss *pruss, unsigned int reg,
+ unsigned int mask, unsigned int val);

#else

@@ -96,6 +186,18 @@ static inline int pruss_release_mem_region(struct pruss *pruss,
return -EOPNOTSUPP;
}

+static inline int pruss_cfg_read(struct pruss *pruss, unsigned int reg,
+ unsigned int *val)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int pruss_cfg_update(struct pruss *pruss, unsigned int reg,
+ unsigned int mask, unsigned int val)
+{
+ return -EOPNOTSUPP;
+}
+
#endif /* CONFIG_TI_PRUSS */

#if IS_ENABLED(CONFIG_PRU_REMOTEPROC)
--
2.17.1