[U-Boot] [PATCH 06/10] remoteproc: pru_rproc: Add support for am33xx

Greg Leonberg greg.leonberg at sunhillo.com
Wed Jul 27 21:27:53 CEST 2022


In order to support the am33xx pru_rproc, the KConfig needed to have the
depends updated to support either ARCH_K3 or ARCH_OMAP2PLUS. The Makefile
needed to be tweaked because when building for am33xx, the SPL will not fit
into SRAM if the pru_rproc driver is built into it.

The pru_rproc struct udevice_id was modified in line with how it is in the
Linux kernel driver to add support for other devices via checking the .data
structure contents during the probe for flags and platform-specific data.
Additionally, the memory address reading from the DT "reg" property was
modified to use the "reg-names" property similar to how it is done in the
Linux kernel driver.

Signed-off-by: Greg Leonberg <greg.leonberg at sunhillo.com>
---
 drivers/remoteproc/Kconfig     |   6 +-
 drivers/remoteproc/Makefile    |   6 ++
 drivers/remoteproc/pru_rproc.c | 173 +++++++++++++++++++++++++++++------------
 3 files changed, 132 insertions(+), 53 deletions(-)

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index d9aa17a..beb42bf 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -83,14 +83,14 @@ config REMOTEPROC_TI_POWER
 	  found on certain TI keystone and OMAP generation SoCs.
 
 config REMOTEPROC_TI_PRU
-	bool "Support for TI's K3 based PRU remoteproc driver"
+	bool "Support for TI's PRU remoteproc driver"
 	select REMOTEPROC
 	depends on DM
 	depends on TI_PRUSS
-	depends on ARCH_K3
+	depends on ARCH_K3 || ARCH_OMAP2PLUS
 	depends on OF_CONTROL
 	help
-	  Say 'y' here to add support for TI' K3 remoteproc driver.
+	  Say 'y' here to add support for TI pru remoteproc driver.
 
 config REMOTEPROC_TI_IPU
 	bool "Support for TI's K3 based IPU remoteproc driver"
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index fbe9c17..0639acc 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -14,5 +14,11 @@ obj-$(CONFIG_REMOTEPROC_TI_K3_ARM64) += ti_k3_arm64_rproc.o
 obj-$(CONFIG_REMOTEPROC_TI_K3_DSP) += ti_k3_dsp_rproc.o
 obj-$(CONFIG_REMOTEPROC_TI_K3_R5F) += ti_k3_r5f_rproc.o
 obj-$(CONFIG_REMOTEPROC_TI_POWER) += ti_power_proc.o
+ifndef CONFIG_AM33XX
 obj-$(CONFIG_REMOTEPROC_TI_PRU) += pru_rproc.o
+else
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_REMOTEPROC_TI_PRU) += pru_rproc.o
+endif
+endif
 obj-$(CONFIG_REMOTEPROC_TI_IPU) += ipu_rproc.o
diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
index 657d8e3..296a9c9 100644
--- a/drivers/remoteproc/pru_rproc.c
+++ b/drivers/remoteproc/pru_rproc.c
@@ -44,23 +44,60 @@
 #define RPROC_FLAGS_ELF_PHDR	BIT(0 + RPROC_FLAGS_SHIFT)
 #define RPROC_FLAGS_ELF_SHDR	BIT(1 + RPROC_FLAGS_SHIFT)
 
+/* PRU/RTU Core IRAM address masks */
+#define PRU0_IRAM_ADDR_MASK	0x34000
+#define PRU1_IRAM_ADDR_MASK	0x38000
+#define RTU0_IRAM_ADDR_MASK	0x4000
+#define RTU1_IRAM_ADDR_MASK	0x6000
+#define TX_PRU0_IRAM_ADDR_MASK	0xa000
+#define TX_PRU1_IRAM_ADDR_MASK	0xc000
+
 /**
- * enum pru_mem - PRU core memory range identifiers
+ * enum pru_iomem - PRU core memory range identifiers
  */
-enum pru_mem {
+enum pru_iomem {
 	PRU_MEM_IRAM = 0,
 	PRU_MEM_CTRL,
 	PRU_MEM_DEBUG,
 	PRU_MEM_MAX,
 };
 
-struct pru_privdata {
-	phys_addr_t pru_iram;
-	phys_addr_t pru_ctrl;
-	phys_addr_t pru_debug;
-	fdt_size_t pru_iramsz;
-	fdt_size_t pru_ctrlsz;
-	fdt_size_t pru_debugsz;
+/**
+ * enum pru_type - PRU core type identifier
+ */
+enum pru_type {
+	PRU_TYPE_PRU = 0,
+	PRU_TYPE_RTU,
+	PRU_TYPE_TX_PRU,
+	PRU_TYPE_MAX,
+};
+
+/**
+ * struct pru_private_data - device data for a PRU core
+ * @mask1: address mask1 used to identify PRU core id
+ * @mask2: address mask2 used to identify PRU core id
+ * @type: type of the PRU core (PRU, RTU, Tx_PRU)
+ * @is_k3: flag used to identify the need for special load & event handling
+ */
+struct pru_private_data {
+	u32 mask1;
+	u32 mask2;
+	enum pru_type type;
+	unsigned int is_k3 : 1;
+};
+
+/**
+ * struct pru_mem_region - PRU memory region structure
+ * @pa: physical (bus) address of the PRU memory region
+ * @size: size of the PRU memory region
+ */
+struct pru_mem_region {
+	phys_addr_t pa;
+	fdt_size_t size;
+};
+
+struct pru {
+	struct pru_mem_region mem_regions[3];
 	const char *fw_name;
 	u32 iram_da;
 	u32 pdram_da;
@@ -69,21 +106,22 @@ struct pru_privdata {
 	u32 bootaddr;
 	int id;
 	struct pruss *prusspriv;
+	const struct pru_private_data *data;
 };
 
-static inline u32 pru_control_read_reg(struct pru_privdata *pru, unsigned int reg)
+static inline u32 pru_control_read_reg(struct pru *pru, unsigned int reg)
 {
-	return readl(pru->pru_ctrl + reg);
+	return readl(pru->mem_regions[PRU_MEM_CTRL].pa + reg);
 }
 
 static inline
-void pru_control_write_reg(struct pru_privdata *pru, unsigned int reg, u32 val)
+void pru_control_write_reg(struct pru *pru, unsigned int reg, u32 val)
 {
-	writel(val, pru->pru_ctrl + reg);
+	writel(val, pru->mem_regions[PRU_MEM_CTRL].pa + reg);
 }
 
 static inline
-void pru_control_set_reg(struct pru_privdata *pru, unsigned int reg,
+void pru_control_set_reg(struct pru *pru, unsigned int reg,
 			 u32 mask, u32 set)
 {
 	u32 val;
@@ -100,7 +138,7 @@ void pru_control_set_reg(struct pru_privdata *pru, unsigned int reg,
  * @c: constant table index to set
  * @addr: physical address to set it to
  */
-static int pru_rproc_set_ctable(struct pru_privdata *pru, enum pru_ctable_idx c, u32 addr)
+static int pru_rproc_set_ctable(struct pru *pru, enum pru_ctable_idx c, u32 addr)
 {
 	unsigned int reg;
 	u32 mask, set;
@@ -131,7 +169,7 @@ static int pru_rproc_set_ctable(struct pru_privdata *pru, enum pru_ctable_idx c,
  */
 static int pru_start(struct udevice *dev)
 {
-	struct pru_privdata *priv;
+	struct pru *priv;
 	int val = 0;
 
 	priv = dev_get_priv(dev);
@@ -139,7 +177,7 @@ static int pru_start(struct udevice *dev)
 	pru_rproc_set_ctable(priv, PRU_C28, 0x100 << 8);
 
 	val = CTRL_CTRL_EN | ((priv->bootaddr >> 2) << 16);
-	writel(val, priv->pru_ctrl + PRU_CTRL_CTRL);
+	writel(val, priv->mem_regions[PRU_MEM_CTRL].pa + PRU_CTRL_CTRL);
 
 	return 0;
 }
@@ -152,14 +190,14 @@ static int pru_start(struct udevice *dev)
  */
 static int pru_stop(struct udevice *dev)
 {
-	struct pru_privdata *priv;
+	struct pru *priv;
 	int val = 0;
 
 	priv = dev_get_priv(dev);
 
-	val = readl(priv->pru_ctrl + PRU_CTRL_CTRL);
+	val = readl(priv->mem_regions[PRU_MEM_CTRL].pa + PRU_CTRL_CTRL);
 	val &= ~CTRL_CTRL_EN;
-	writel(val, priv->pru_ctrl + PRU_CTRL_CTRL);
+	writel(val, priv->mem_regions[PRU_MEM_CTRL].pa + PRU_CTRL_CTRL);
 
 	return 0;
 }
@@ -184,7 +222,7 @@ static int pru_init(struct udevice *dev)
  * kernel virtual address. Data RAM0 is primary Data RAM for PRU0 and Data
  * RAM1 is primary Data RAM for PRU1.
  */
-static void *pru_d_da_to_pa(struct pru_privdata *priv, u32 da, int len)
+static void *pru_d_da_to_pa(struct pru *priv, u32 da, int len)
 {
 	u32 offset;
 	void *pa = NULL;
@@ -233,7 +271,7 @@ static void *pru_d_da_to_pa(struct pru_privdata *priv, u32 da, int len)
  * private Instruction RAM, and its device address is identical to that of
  * its primary Data RAM device address.
  */
-static void *pru_i_da_to_pa(struct pru_privdata *priv, u32 da, int len)
+static void *pru_i_da_to_pa(struct pru *priv, u32 da, int len)
 {
 	u32 offset;
 	void *pa = NULL;
@@ -242,16 +280,17 @@ static void *pru_i_da_to_pa(struct pru_privdata *priv, u32 da, int len)
 		return NULL;
 
 	if (da >= priv->iram_da &&
-	    da + len <= priv->iram_da + priv->pru_iramsz) {
+	    da + len <= priv->iram_da + priv->mem_regions[PRU_MEM_IRAM].size) {
 		offset = da - priv->iram_da;
-		pa = (__force void *)(priv->pru_iram + offset);
+		pa = (__force void *)(priv->mem_regions[PRU_MEM_IRAM].pa +
+				      offset);
 	}
 
 	return pa;
 }
 
 /* PRU-specific address translator */
-static void *pru_da_to_pa(struct pru_privdata *priv, u64 da, int len, u32 flags)
+static void *pru_da_to_pa(struct pru *priv, u64 da, int len, u32 flags)
 {
 	void *pa;
 	u32 exec_flag;
@@ -322,7 +361,7 @@ static int pru_rproc_memcpy(void *dest, void *src, size_t count)
  */
 static int pru_load(struct udevice *dev, ulong addr, ulong size)
 {
-	struct pru_privdata *priv;
+	struct pru *priv;
 	Elf32_Ehdr *ehdr;
 	Elf32_Phdr *phdr;
 	int i, ret = 0;
@@ -355,7 +394,7 @@ static int pru_load(struct udevice *dev, ulong addr, ulong size)
 
 		if (offset + filesz > size) {
 			dev_dbg(dev, "truncated fw: need 0x%x avail 0x%zx\n",
-				offset + filesz, size);
+				offset + filesz, (size_t)size);
 			ret = -EINVAL;
 			break;
 		}
@@ -374,7 +413,7 @@ static int pru_load(struct udevice *dev, ulong addr, ulong size)
 			continue;
 
 		ret = pru_rproc_memcpy(ptr,
-				       (void *)addr + phdr->p_offset, filesz);
+					(void *)addr + phdr->p_offset, filesz);
 		if (ret) {
 			dev_dbg(dev, "PRU custom memory copy failed for da 0x%x memsz 0x%x\n",
 				da, memsz);
@@ -394,17 +433,10 @@ static const struct dm_rproc_ops pru_ops = {
 	.load = pru_load,
 };
 
-static void pru_set_id(struct pru_privdata *priv, struct udevice *dev)
+static void pru_set_id(struct pru *priv, struct udevice *dev)
 {
-	u32 mask2 = 0x38000;
-
-	if (device_is_compatible(dev, "ti,am654-rtu"))
-		mask2 = 0x6000;
-
-	if (device_is_compatible(dev, "ti,am654-tx-pru"))
-		mask2 = 0xc000;
-
-	if ((priv->pru_iram & mask2) == mask2)
+	if ((priv->mem_regions[PRU_MEM_IRAM].pa & priv->data->mask2) ==
+	     priv->data->mask2)
 		priv->id = 1;
 	else
 		priv->id = 0;
@@ -418,21 +450,23 @@ static void pru_set_id(struct pru_privdata *priv, struct udevice *dev)
  */
 static int pru_probe(struct udevice *dev)
 {
-	struct pru_privdata *priv;
-	int lenp;
+	struct pru *priv;
+	int lenp, i, idx;
 	ofnode node;
+	const struct pru_private_data *data;
+	const char *mem_names[PRU_MEM_MAX] = { "iram", "control", "debug" };
 
 	node = dev_ofnode(dev);
 
 	priv = dev_get_priv(dev);
 	priv->prusspriv = dev_get_priv(dev->parent);
 
-	priv->pru_iram = devfdt_get_addr_size_index(dev, PRU_MEM_IRAM,
-						    &priv->pru_iramsz);
-	priv->pru_ctrl = devfdt_get_addr_size_index(dev, PRU_MEM_CTRL,
-						    &priv->pru_ctrlsz);
-	priv->pru_debug = devfdt_get_addr_size_index(dev, PRU_MEM_DEBUG,
-						     &priv->pru_debugsz);
+	for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
+		idx = ofnode_stringlist_search(node, "reg-names", mem_names[i]);
+		priv->mem_regions[i].pa = ofnode_get_addr_size_index(node, idx,
+						    &priv->mem_regions[i].size);
+	}
+
 
 	priv->fw_name = ofnode_get_property(node, "firmware-name", &lenp);
 
@@ -441,15 +475,54 @@ static int pru_probe(struct udevice *dev)
 	priv->sdram_da = 0x2000;
 	priv->shrdram_da = 0x10000;
 
+	data = (const struct pru_private_data *)dev_get_driver_data(dev);
+	if (!data) {
+		dev_err(dev, "Non-DT platform devices not supported\n");
+		return -ENODEV;
+	}
+	priv->data = data;
+
 	pru_set_id(priv, dev);
 
 	return 0;
 }
 
+static const struct pru_private_data pru_data = {
+	.mask1 = PRU0_IRAM_ADDR_MASK,
+	.mask2 = PRU1_IRAM_ADDR_MASK,
+	.type = PRU_TYPE_PRU,
+};
+
+static const struct pru_private_data k3_pru_data = {
+	.mask1 = PRU0_IRAM_ADDR_MASK,
+	.mask2 = PRU1_IRAM_ADDR_MASK,
+	.type = PRU_TYPE_PRU,
+	.is_k3 = 1,
+};
+
+static const struct pru_private_data k3_rtu_data = {
+	.mask1 = RTU0_IRAM_ADDR_MASK,
+	.mask2 = RTU1_IRAM_ADDR_MASK,
+	.type = PRU_TYPE_RTU,
+	.is_k3 = 1,
+};
+
+static const struct pru_private_data k3_tx_pru_data = {
+	.mask1 = TX_PRU0_IRAM_ADDR_MASK,
+	.mask2 = TX_PRU1_IRAM_ADDR_MASK,
+	.type = PRU_TYPE_TX_PRU,
+	.is_k3 = 1,
+};
+
 static const struct udevice_id pru_ids[] = {
-	{ .compatible = "ti,am654-pru"},
-	{ .compatible = "ti,am654-rtu"},
-	{ .compatible = "ti,am654-tx-pru" },
+	{	.compatible = "ti,am654-pru",
+		.data = (unsigned long)&k3_pru_data, },
+	{	.compatible = "ti,am654-rtu",
+		.data = (unsigned long)&k3_rtu_data, },
+	{	.compatible = "ti,am654-tx-pru",
+		.data = (unsigned long)&k3_tx_pru_data, },
+	{	.compatible = "ti,am3356-pru",
+		.data = (unsigned long)&pru_data, },
 	{}
 };
 
@@ -459,5 +532,5 @@ U_BOOT_DRIVER(pru) = {
 	.id = UCLASS_REMOTEPROC,
 	.ops = &pru_ops,
 	.probe = pru_probe,
-	.priv_auto_alloc_size = sizeof(struct pru_privdata),
+	.priv_auto_alloc_size = sizeof(struct pru),
 };
-- 
1.8.3.1



More information about the U-Boot mailing list