linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/8] remoteproc: add map parameter to da_to_va
       [not found] <20180623210810.21232-1-david@lechnology.com>
@ 2018-06-23 21:08 ` David Lechner
  2018-06-23 21:08 ` [PATCH 2/8] remoteproc: add page lookup for TI PRU to ELF loader David Lechner
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2018-06-23 21:08 UTC (permalink / raw)
  To: linux-remoteproc, devicetree, linux-omap, linux-arm-kernel
  Cc: David Lechner, Ohad Ben-Cohen, Bjorn Andersson, Rob Herring,
	Mark Rutland, Benoît Cousson, Tony Lindgren, Sekhar Nori,
	Kevin Hilman, linux-kernel

This adds a new map parameter to the da_to_va callback for remoteproc
devices. This parameter will be used by devices that have more than
one memory map, such as the PRU found in TI Sitara SoCs.

On these devices, the same physical memory address can refer to two
different locations, i.e. instruction memory or data memory both start
at 0x0. So, an extra bit of information is needed in the da_to_va
callback to tell these apart.

Devices that only have a single memory map will just pass 0 for this
parameter. For now we are using 0 everywhere, but later patches will
modify this value.

Signed-off-by: David Lechner <david@lechnology.com>
---
 drivers/remoteproc/imx_rproc.c             |  2 +-
 drivers/remoteproc/keystone_remoteproc.c   |  3 ++-
 drivers/remoteproc/qcom_adsp_pil.c         |  2 +-
 drivers/remoteproc/qcom_q6v5_pil.c         |  2 +-
 drivers/remoteproc/qcom_wcnss.c            |  2 +-
 drivers/remoteproc/remoteproc_core.c       | 10 ++++++----
 drivers/remoteproc/remoteproc_elf_loader.c |  4 ++--
 drivers/remoteproc/remoteproc_internal.h   |  2 +-
 drivers/remoteproc/st_slim_rproc.c         |  2 +-
 drivers/remoteproc/wkup_m3_rproc.c         |  3 ++-
 include/linux/remoteproc.h                 |  2 +-
 11 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 54c07fd3f204..78c3502fea36 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -211,7 +211,7 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
 	return -ENOENT;
 }
 
-static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, int len, int map)
 {
 	struct imx_rproc *priv = rproc->priv;
 	void *va = NULL;
diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c
index aaac31134e39..0f87cf95ae4f 100644
--- a/drivers/remoteproc/keystone_remoteproc.c
+++ b/drivers/remoteproc/keystone_remoteproc.c
@@ -254,7 +254,8 @@ static void keystone_rproc_kick(struct rproc *rproc, int vqid)
  * can be used either by the remoteproc core for loading (when using kernel
  * remoteproc loader), or by any rpmsg bus drivers.
  */
-static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, int len,
+				     int map)
 {
 	struct keystone_rproc *ksproc = rproc->priv;
 	void __iomem *va = NULL;
diff --git a/drivers/remoteproc/qcom_adsp_pil.c b/drivers/remoteproc/qcom_adsp_pil.c
index 89a86ce07f99..25a174a06985 100644
--- a/drivers/remoteproc/qcom_adsp_pil.c
+++ b/drivers/remoteproc/qcom_adsp_pil.c
@@ -167,7 +167,7 @@ static int adsp_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, int len, int map)
 {
 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c
index 2bf8e7c49f2a..58ba7349b311 100644
--- a/drivers/remoteproc/qcom_q6v5_pil.c
+++ b/drivers/remoteproc/qcom_q6v5_pil.c
@@ -995,7 +995,7 @@ static int q6v5_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *q6v5_da_to_va(struct rproc *rproc, u64 da, int len, int map)
 {
 	struct q6v5 *qproc = rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index b0e07e9f42d5..92b05fb10557 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -295,7 +295,7 @@ static int wcnss_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *wcnss_da_to_va(struct rproc *rproc, u64 da, int len, int map)
 {
 	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index a9609d971f7f..fb9ae85a0bee 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -145,6 +145,8 @@ static void rproc_disable_iommu(struct rproc *rproc)
  * @rproc: handle of a remote processor
  * @da: remoteproc device address to translate
  * @len: length of the memory region @da is pointing to
+ * @map: indicates which memory map to use for devices with more than one
+ *       memory map or 0 for devices that only have a single memory map
  *
  * Some remote processors will ask us to allocate them physically contiguous
  * memory regions (which we call "carveouts"), and map them to specific
@@ -169,13 +171,13 @@ static void rproc_disable_iommu(struct rproc *rproc)
  * here the output of the DMA API for the carveouts, which should be more
  * correct.
  */
-void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+void *rproc_da_to_va(struct rproc *rproc, u64 da, int len, int map)
 {
 	struct rproc_mem_entry *carveout;
 	void *ptr = NULL;
 
 	if (rproc->ops->da_to_va) {
-		ptr = rproc->ops->da_to_va(rproc, da, len);
+		ptr = rproc->ops->da_to_va(rproc, da, len, map);
 		if (ptr)
 			goto out;
 	}
@@ -468,7 +470,7 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc,
 	}
 
 	/* what's the kernel address of this resource ? */
-	ptr = rproc_da_to_va(rproc, rsc->da, rsc->len);
+	ptr = rproc_da_to_va(rproc, rsc->da, rsc->len, 0);
 	if (!ptr) {
 		dev_err(dev, "erroneous trace resource entry\n");
 		return -EINVAL;
@@ -1124,7 +1126,7 @@ static void rproc_coredump(struct rproc *rproc)
 		phdr->p_flags = PF_R | PF_W | PF_X;
 		phdr->p_align = 0;
 
-		ptr = rproc_da_to_va(rproc, segment->da, segment->size);
+		ptr = rproc_da_to_va(rproc, segment->da, segment->size, 0);
 		if (!ptr) {
 			dev_err(&rproc->dev,
 				"invalid coredump segment (%pad, %zu)\n",
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index b17d72ec8603..8888d39e1b13 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -182,7 +182,7 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 		}
 
 		/* grab the kernel address for this device address */
-		ptr = rproc_da_to_va(rproc, da, memsz);
+		ptr = rproc_da_to_va(rproc, da, memsz, 0);
 		if (!ptr) {
 			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
 			ret = -EINVAL;
@@ -333,6 +333,6 @@ struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
 	if (!shdr)
 		return NULL;
 
-	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size);
+	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size, 0);
 }
 EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 7570beb035b5..92968a341f86 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -51,7 +51,7 @@ void rproc_exit_sysfs(void);
 void rproc_free_vring(struct rproc_vring *rvring);
 int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
 
-void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
+void *rproc_da_to_va(struct rproc *rproc, u64 da, int len, int map);
 int rproc_trigger_recovery(struct rproc *rproc);
 
 int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw);
diff --git a/drivers/remoteproc/st_slim_rproc.c b/drivers/remoteproc/st_slim_rproc.c
index 1ffb1f0c43d6..146badc9f061 100644
--- a/drivers/remoteproc/st_slim_rproc.c
+++ b/drivers/remoteproc/st_slim_rproc.c
@@ -178,7 +178,7 @@ static int slim_rproc_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, int len, int map)
 {
 	struct st_slim_rproc *slim_rproc = rproc->priv;
 	void *va = NULL;
diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c
index 1ada0e51fef6..12cb26ebf35b 100644
--- a/drivers/remoteproc/wkup_m3_rproc.c
+++ b/drivers/remoteproc/wkup_m3_rproc.c
@@ -88,7 +88,8 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, int len,
+				    int map)
 {
 	struct wkup_m3_rproc *wkupm3 = rproc->priv;
 	void *va = NULL;
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index dfdaede9139e..2d88e394fc99 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -343,7 +343,7 @@ struct rproc_ops {
 	int (*start)(struct rproc *rproc);
 	int (*stop)(struct rproc *rproc);
 	void (*kick)(struct rproc *rproc, int vqid);
-	void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
+	void * (*da_to_va)(struct rproc *rproc, u64 da, int len, int map);
 	int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
 	struct resource_table *(*find_loaded_rsc_table)(
 				struct rproc *rproc, const struct firmware *fw);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 2/8] remoteproc: add page lookup for TI PRU to ELF loader
       [not found] <20180623210810.21232-1-david@lechnology.com>
  2018-06-23 21:08 ` [PATCH 1/8] remoteproc: add map parameter to da_to_va David Lechner
@ 2018-06-23 21:08 ` David Lechner
  2018-06-23 21:08 ` [PATCH 3/8] ARM: OMAP2+: add pdata quirks for PRUSS reset David Lechner
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2018-06-23 21:08 UTC (permalink / raw)
  To: linux-remoteproc, devicetree, linux-omap, linux-arm-kernel
  Cc: David Lechner, Ohad Ben-Cohen, Bjorn Andersson, Rob Herring,
	Mark Rutland, Benoît Cousson, Tony Lindgren, Sekhar Nori,
	Kevin Hilman, linux-kernel

This adds a special handler to the default remoteproc ELF firmware
loader that looks up the memory map on TI PRU firmware files.

These processors have multiple memory maps that share the same address
space, so we need to know the page in addition to the physical address
in order to translate the address to a local CPU address.

Signed-off-by: David Lechner <david@lechnology.com>
---
 drivers/remoteproc/remoteproc_elf_loader.c | 117 +++++++++++++++++++--
 include/uapi/linux/elf-em.h                |   1 +
 2 files changed, 112 insertions(+), 6 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index 8888d39e1b13..f041b6fb798f 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -32,6 +32,103 @@
 
 #include "remoteproc_internal.h"
 
+#define SHT_TI_PHATTRS 0x7F000004
+#define SHT_TI_SH_PAGE 0x7F000007
+
+typedef struct {
+	Elf32_Half pha_seg_id; /* Segment id */
+	Elf32_Half pha_tag_id; /* Attribute kind id */
+	union {
+		Elf32_Off pha_offset; /* byte offset within the section */
+		Elf32_Word pha_value; /* Constant tag value */
+	} pha_un;
+} Elf32_TI_PHAttrs;
+
+/* this struct is reverse engineered, so not sure what most of the values are */
+struct ti_section_page {
+	u32 unk0;
+	u32 unk1;
+	u32 unk2;
+	u32 unk3;
+	u32 unk4;
+	u16 size;
+	u16 unk5;
+	u16 unk6;
+	u8 data[0]; /* array of size */
+};
+
+/**
+ * rproc_elf_segment_to_map() - Gets memory map for segment
+ * @id: segment id
+ * @elf_data: pointer to ELF file data
+ *
+ * Returns the memory map for the segment.
+ */
+static int rproc_elf_segment_to_map(u32 id, const u8 *elf_data)
+{
+	struct elf32_hdr *ehdr;
+	struct elf32_shdr *shdr;
+	Elf32_TI_PHAttrs *attrs = NULL;
+	int i;
+
+	ehdr = (struct elf32_hdr *)elf_data;
+	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
+
+	if (ehdr->e_machine != EM_TI_PRU)
+		return 0;
+
+	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
+		if (shdr->sh_type == SHT_TI_PHATTRS) {
+			attrs = (Elf32_TI_PHAttrs *)(elf_data + shdr->sh_offset);
+			break;
+		}
+	}
+
+	if (!attrs)
+		return 0;
+
+	/* list is terminated by tag id == 0 (PHA_NULL) */
+	for (; attrs->pha_tag_id; attrs++) {
+		if (attrs->pha_tag_id == 3 && attrs->pha_seg_id == id)
+			return attrs->pha_un.pha_value;
+	}
+
+	return 0;
+}
+
+/**
+ * rproc_elf_section_to_map() - Gets memory map for section
+ * @id: segment id
+ * @elf_data: pointer to ELF file data
+ *
+ * Returns the memory map for the section.
+ */
+static int rproc_elf_section_to_map(u32 id, const u8 *elf_data)
+{
+	struct elf32_hdr *ehdr;
+	struct elf32_shdr *shdr;
+	struct ti_section_page *map = NULL;
+	int i;
+
+	ehdr = (struct elf32_hdr *)elf_data;
+	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
+
+	if (ehdr->e_machine != EM_TI_PRU)
+		return 0;
+
+	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
+		if (shdr->sh_type == SHT_TI_SH_PAGE) {
+			map = (struct ti_section_page *)(elf_data + shdr->sh_offset);
+			break;
+		}
+	}
+
+	if (!map || id >= map->size)
+		return 0;
+
+	return map->data[id];
+}
+
 /**
  * rproc_elf_sanity_check() - Sanity Check ELF firmware image
  * @rproc: the remote processor handle
@@ -147,7 +244,7 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 	struct device *dev = &rproc->dev;
 	struct elf32_hdr *ehdr;
 	struct elf32_phdr *phdr;
-	int i, ret = 0;
+	int i, map, ret = 0;
 	const u8 *elf_data = fw->data;
 
 	ehdr = (struct elf32_hdr *)elf_data;
@@ -181,8 +278,10 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 			break;
 		}
 
+		map = rproc_elf_segment_to_map(i, elf_data);
+
 		/* grab the kernel address for this device address */
-		ptr = rproc_da_to_va(rproc, da, memsz, 0);
+		ptr = rproc_da_to_va(rproc, da, memsz, map);
 		if (!ptr) {
 			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
 			ret = -EINVAL;
@@ -209,7 +308,7 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 EXPORT_SYMBOL(rproc_elf_load_segments);
 
 static struct elf32_shdr *
-find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
+find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size, int *id)
 {
 	struct elf32_shdr *shdr;
 	int i;
@@ -261,6 +360,9 @@ find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size)
 			return NULL;
 		}
 
+		if (id)
+			*id = i;
+
 		return shdr;
 	}
 
@@ -288,7 +390,7 @@ int rproc_elf_load_rsc_table(struct rproc *rproc, const struct firmware *fw)
 
 	ehdr = (struct elf32_hdr *)elf_data;
 
-	shdr = find_table(dev, ehdr, fw->size);
+	shdr = find_table(dev, ehdr, fw->size, NULL);
 	if (!shdr)
 		return -EINVAL;
 
@@ -328,11 +430,14 @@ struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
 {
 	struct elf32_hdr *ehdr = (struct elf32_hdr *)fw->data;
 	struct elf32_shdr *shdr;
+	int id, map;
 
-	shdr = find_table(&rproc->dev, ehdr, fw->size);
+	shdr = find_table(&rproc->dev, ehdr, fw->size, &id);
 	if (!shdr)
 		return NULL;
 
-	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size, 0);
+	map = rproc_elf_section_to_map(id, fw->data);
+
+	return rproc_da_to_va(rproc, shdr->sh_addr, shdr->sh_size, map);
 }
 EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
diff --git a/include/uapi/linux/elf-em.h b/include/uapi/linux/elf-em.h
index 31aa10178335..ce114abc7a50 100644
--- a/include/uapi/linux/elf-em.h
+++ b/include/uapi/linux/elf-em.h
@@ -37,6 +37,7 @@
 #define EM_BLACKFIN     106     /* ADI Blackfin Processor */
 #define EM_ALTERA_NIOS2	113	/* Altera Nios II soft-core processor */
 #define EM_TI_C6000	140	/* TI C6X DSPs */
+#define EM_TI_PRU	144	/* TI Programmable Realtime Unit */
 #define EM_AARCH64	183	/* ARM 64 bit */
 #define EM_TILEPRO	188	/* Tilera TILEPro */
 #define EM_MICROBLAZE	189	/* Xilinx MicroBlaze */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 3/8] ARM: OMAP2+: add pdata quirks for PRUSS reset
       [not found] <20180623210810.21232-1-david@lechnology.com>
  2018-06-23 21:08 ` [PATCH 1/8] remoteproc: add map parameter to da_to_va David Lechner
  2018-06-23 21:08 ` [PATCH 2/8] remoteproc: add page lookup for TI PRU to ELF loader David Lechner
@ 2018-06-23 21:08 ` David Lechner
  2018-06-23 21:08 ` [PATCH 4/8] dt-bindings: add bindings for TI PRU as remoteproc David Lechner
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2018-06-23 21:08 UTC (permalink / raw)
  To: linux-remoteproc, devicetree, linux-omap, linux-arm-kernel
  Cc: David Lechner, Ohad Ben-Cohen, Bjorn Andersson, Rob Herring,
	Mark Rutland, Benoît Cousson, Tony Lindgren, Sekhar Nori,
	Kevin Hilman, linux-kernel

This adds platform data for the PRUSS reset on OMAP2+. This is following
the pattern used by several other platform devices on these SoCs since
there is not a proper reset controller.

Signed-off-by: David Lechner <david@lechnology.com>
---
 arch/arm/mach-omap2/pdata-quirks.c     |  9 +++++++++
 include/linux/platform_data/ti-pruss.h | 18 ++++++++++++++++++
 2 files changed, 27 insertions(+)
 create mode 100644 include/linux/platform_data/ti-pruss.h

diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 7f02743edbe4..8ea35d6cded5 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -25,6 +25,7 @@
 #include <linux/platform_data/hsmmc-omap.h>
 #include <linux/platform_data/iommu-omap.h>
 #include <linux/platform_data/ti-sysc.h>
+#include <linux/platform_data/ti-pruss.h>
 #include <linux/platform_data/wkup_m3.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
 
@@ -424,6 +425,12 @@ static struct wkup_m3_platform_data wkup_m3_data = {
 	.assert_reset = omap_device_assert_hardreset,
 	.deassert_reset = omap_device_deassert_hardreset,
 };
+
+static struct ti_pruss_platform_data pruss_data = {
+	.reset_name = "pruss",
+	.assert_reset = omap_device_assert_hardreset,
+	.deassert_reset = omap_device_deassert_hardreset,
+};
 #endif
 
 #ifdef CONFIG_SOC_OMAP5
@@ -568,6 +575,8 @@ static struct of_dev_auxdata omap_auxdata_lookup[] = {
 #ifdef CONFIG_SOC_AM33XX
 	OF_DEV_AUXDATA("ti,am3352-wkup-m3", 0x44d00000, "44d00000.wkup_m3",
 		       &wkup_m3_data),
+	OF_DEV_AUXDATA("ti,am3352-pru-rproc", 0x4a300000, "4a300000.cpu",
+		       &pruss_data),
 #endif
 #ifdef CONFIG_SOC_AM43XX
 	OF_DEV_AUXDATA("ti,am4372-wkup-m3", 0x44d00000, "44d00000.wkup_m3",
diff --git a/include/linux/platform_data/ti-pruss.h b/include/linux/platform_data/ti-pruss.h
new file mode 100644
index 000000000000..e401e621ebdf
--- /dev/null
+++ b/include/linux/platform_data/ti-pruss.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * TI PRU remote processor platform data
+ */
+
+#ifndef _LINUX_PLATFORM_DATA_TI_PRU_H
+#define _LINUX_PLATFORM_DATA_TI_PRU_H
+
+struct platform_device;
+
+struct ti_pruss_platform_data {
+	const char *reset_name;
+
+	int (*assert_reset)(struct platform_device *pdev, const char *name);
+	int (*deassert_reset)(struct platform_device *pdev, const char *name);
+};
+
+#endif /* _LINUX_PLATFORM_DATA_TI_PRU_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 4/8] dt-bindings: add bindings for TI PRU as remoteproc
       [not found] <20180623210810.21232-1-david@lechnology.com>
                   ` (2 preceding siblings ...)
  2018-06-23 21:08 ` [PATCH 3/8] ARM: OMAP2+: add pdata quirks for PRUSS reset David Lechner
@ 2018-06-23 21:08 ` David Lechner
  2018-07-03 20:59   ` Rob Herring
  2018-06-23 21:08 ` [PATCH 5/8] remoteproc: new driver for TI PRU David Lechner
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: David Lechner @ 2018-06-23 21:08 UTC (permalink / raw)
  To: linux-remoteproc, devicetree, linux-omap, linux-arm-kernel
  Cc: David Lechner, Ohad Ben-Cohen, Bjorn Andersson, Rob Herring,
	Mark Rutland, Benoît Cousson, Tony Lindgren, Sekhar Nori,
	Kevin Hilman, linux-kernel

This adds a new binding for the TI Programmable Runtime Unit (PRU)
as a remoteproc device.

Signed-off-by: David Lechner <david@lechnology.com>
---
 .../bindings/remoteproc/ti_pru_rproc.txt      | 51 +++++++++++++++++++
 1 file changed, 51 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/remoteproc/ti_pru_rproc.txt

diff --git a/Documentation/devicetree/bindings/remoteproc/ti_pru_rproc.txt b/Documentation/devicetree/bindings/remoteproc/ti_pru_rproc.txt
new file mode 100644
index 000000000000..0e80a8db46d0
--- /dev/null
+++ b/Documentation/devicetree/bindings/remoteproc/ti_pru_rproc.txt
@@ -0,0 +1,51 @@
+TI Programmable Realtime Unit (PRU)
+===================================
+
+Some TI Sitara SoCs contain a Programmable Realtime Unit subsystem with two
+processor cores that can be used for hard-realtime tasks.
+
+
+Required properties:
+--------------------
+The following are the mandatory properties:
+
+- compatible:		Should be one of the following,
+			    "ti,da850-pru-rproc" for AM18xx/OMAPL138 SoCs
+			    "ti,am3352-pru-rproc" for AM355x SoCs
+
+- reg:			Should contain the memory region for the PRUSS
+
+- interrupts: 		Should contain the interrupt number used to receive the
+			virtualqueue kick interrupts from the PRU (i.e.
+			PRU_EVTOUT0 and PRU_EVTOUT1)
+
+- interrupt-names	Should contain "pru0-vq", "pru1-vq"
+
+Optional properties:
+--------------------
+
+- power-domains:	A phandle to the power domain that powers the PRUSS
+
+- ti,hwmods:		Name of the hwmod associated to the PRUSS, which is
+			typically "pruss"
+
+Example:
+--------
+
+	// AM18xx
+	pru_rproc: cpu@30000 {
+		compatible = "ti,da850-pru-rproc";
+		reg = <0x30000 0x10000>;
+		interrupts = <3>, <4>;
+		interrupt-names = "pru0-vq", "pru1-vq";
+		power-domains = <&psc0 13>;
+	};
+
+	// AM335x
+	pru_rproc: cpu@4a300000 {
+		compatible = "ti,am3352-pru-rproc";
+		reg = <0x4a300000 0x80000>;
+		interrupts = <20>, <21>;
+		interrupt-names = "pru0-vq", "pru1-vq";
+		ti,hwmods = "pruss";
+	};
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 5/8] remoteproc: new driver for TI PRU
       [not found] <20180623210810.21232-1-david@lechnology.com>
                   ` (3 preceding siblings ...)
  2018-06-23 21:08 ` [PATCH 4/8] dt-bindings: add bindings for TI PRU as remoteproc David Lechner
@ 2018-06-23 21:08 ` David Lechner
  2018-06-29 10:14   ` Roger Quadros
  2018-06-23 21:08 ` [PATCH 6/8] ARM: davinci_all_defconfig: enable PRU remoteproc module David Lechner
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: David Lechner @ 2018-06-23 21:08 UTC (permalink / raw)
  To: linux-remoteproc, devicetree, linux-omap, linux-arm-kernel
  Cc: David Lechner, Ohad Ben-Cohen, Bjorn Andersson, Rob Herring,
	Mark Rutland, Benoît Cousson, Tony Lindgren, Sekhar Nori,
	Kevin Hilman, linux-kernel

This adds a new remoteproc driver for TI Programmable Realtime Units
(PRUs).

This has been tested working on AM1808 (LEGO MINDSTORMS EV3) using the
sample rpmsg client driver.

Signed-off-by: David Lechner <david@lechnology.com>
---
 MAINTAINERS                       |   5 +
 drivers/remoteproc/Kconfig        |   7 +
 drivers/remoteproc/Makefile       |   1 +
 drivers/remoteproc/ti_pru_rproc.c | 660 ++++++++++++++++++++++++++++++
 4 files changed, 673 insertions(+)
 create mode 100644 drivers/remoteproc/ti_pru_rproc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index edf3cf5ea691..06dea089d9ae 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14288,6 +14288,11 @@ L:	netdev@vger.kernel.org
 S:	Maintained
 F:	drivers/net/ethernet/ti/netcp*
 
+TI PRU REMOTEPROC DRIVER
+R:	David Lechner <david@lechnology.com>
+F:	Documentation/devicetree/bindings/remoteproc/ti_pru_rproc.txt
+F:	drivers/remoteproc/ti_pru_rproc.c
+
 TI TAS571X FAMILY ASoC CODEC DRIVER
 M:	Kevin Cernekee <cernekee@chromium.org>
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index cd1c168fd188..ae6e725e1755 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -158,6 +158,13 @@ config ST_REMOTEPROC
 config ST_SLIM_REMOTEPROC
 	tristate
 
+config TI_PRU_REMOTEPROC
+	tristate "TI Programmable Realtime Unit"
+	depends on ARCH_DAVINCI_DA8XX || SOC_AM33XX
+	help
+	  Say y here to support TI Programmable Runtime Units (PRUs) via the
+	  remote processor framework.
+
 endif # REMOTEPROC
 
 endmenu
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 02627ede8d4a..451efee5c8d3 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -23,3 +23,4 @@ qcom_wcnss_pil-y			+= qcom_wcnss.o
 qcom_wcnss_pil-y			+= qcom_wcnss_iris.o
 obj-$(CONFIG_ST_REMOTEPROC)		+= st_remoteproc.o
 obj-$(CONFIG_ST_SLIM_REMOTEPROC)	+= st_slim_rproc.o
+obj-$(CONFIG_TI_PRU_REMOTEPROC)		+= ti_pru_rproc.o
diff --git a/drivers/remoteproc/ti_pru_rproc.c b/drivers/remoteproc/ti_pru_rproc.c
new file mode 100644
index 000000000000..cd8302c318c9
--- /dev/null
+++ b/drivers/remoteproc/ti_pru_rproc.c
@@ -0,0 +1,660 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 David Lechner <david@lechnology.com>
+ *
+ * Remoteproc driver for TI Programmable Realtime Unit
+ */
+
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_data/ti-pruss.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/remoteproc.h>
+#include <linux/regmap.h>
+#include <linux/sizes.h>
+#include <linux/types.h>
+
+#include "remoteproc_internal.h"
+
+#define SZ_12K 0x3000
+
+/* control/status registers */
+#define TI_PRU_CS_CONTROL	0x0
+#define TI_PRU_CS_STATUS	0x4
+#define TI_PRU_CS_WAKEUP	0x8
+#define TI_PRU_CS_CYCLECNT	0xc
+
+/* control register bits */
+#define TI_PRU_CONTROL_PCRESETVAL	GENMASK(31, 16)
+#define TI_PRU_CONTROL_RUNSTATE		BIT(15)
+#define TI_PRU_CONTROL_SINGLESTEP	BIT(8)
+#define TI_PRU_CONTROL_COUNTENABLE	BIT(3)
+#define TI_PRU_CONTROL_SLEEPING		BIT(2)
+#define TI_PRU_CONTROL_ENABLE		BIT(1)
+#define TI_PRU_CONTROL_SOFTRESET	BIT(0)
+
+/* status bits */
+#define TI_PRU_STATUS_PCOUNTER		GENMASK(15, 0)
+
+/* interrupt controller registers */
+#define TI_PRU_INTC_GLBLEN		0x10
+#define TI_PRU_INTC_STATIDXSET		0x20
+#define TI_PRU_INTC_STATIDXCLR		0x24
+#define TI_PRU_INTC_ENIDXSET		0x28
+#define TI_PRU_INTC_HSTINTENIDXSET	0x34
+#define TI_PRU_INTC_CHANMAP0		0x400
+#define TI_PRU_INTC_POLARITY0		0xd00
+#define TI_PRU_INTC_TYPE0		0xd80
+#define TI_PRU_INTC_HOSTMAP0		0x800
+
+/* config registers */
+#define TI_PRU_CFG_SYSCFG		0x4
+
+/* syscfg bits */
+#define TI_PRU_SYSCFG_SUB_MWAIT			BIT(5)
+#define TI_PRU_SYSCFG_STANDBY_INIT		BIT(4)
+#define TI_PRU_SYSCFG_STANDBY_MODE_MASK		GENMASK(3, 2)
+#define TI_PRU_SYSCFG_STANDBY_MODE_SMART	(2 << 2)
+#define TI_PRU_SYSCFG_IDLE_MODE_MASK		GENMASK(1, 0)
+#define TI_PRU_SYSCFG_IDLE_MODE_SMART		(2 << 0)
+
+enum ti_pru {
+	TI_PRU0,
+	TI_PRU1,
+	NUM_TI_PRU
+};
+
+enum ti_pru_type {
+	TI_PRU_TYPE_AM18XX,
+	TI_PRU_TYPE_AM335X,
+	NUM_TI_PRU_TYPE
+};
+
+enum ti_pru_evtout {
+	TI_PRU_EVTOUT0,
+	TI_PRU_EVTOUT1,
+	TI_PRU_EVTOUT2,
+	TI_PRU_EVTOUT3,
+	TI_PRU_EVTOUT4,
+	TI_PRU_EVTOUT5,
+	TI_PRU_EVTOUT6,
+	TI_PRU_EVTOUT7,
+	NUM_TI_PRU_EVTOUT
+};
+
+struct ti_pru_mem_region {
+	off_t offset;
+	size_t size;
+};
+
+/**
+ * ti_pru_shared_info - common init info for the PRUSS
+ * @ram: shared RAM, if present
+ * @intc: interrupt controller
+ * @cfg: configuration registers, if present
+ */
+struct ti_pru_shared_info {
+	struct ti_pru_mem_region ram;
+	struct ti_pru_mem_region intc;
+	struct ti_pru_mem_region cfg;
+};
+
+/**
+ * ti_pru_info - init info each individual PRU
+ * @ram: PRU RAM
+ * @ctrl: PRU control/status registers
+ * @dbg: PRU dbg registers
+ * @inst: instruction RAM
+ * @vq_arm_to_pru_event: The index of the PRU system event interrupt used
+ *                       used by the ARM for kicking the PRU
+ * @vq_pru_to_arm_event: The index of the PRU system event interrupt used
+ *                       used by the PRU for kicking the ARM
+ */
+struct ti_pru_info {
+	struct ti_pru_mem_region ram;
+	struct ti_pru_mem_region ctrl;
+	struct ti_pru_mem_region dbg;
+	struct ti_pru_mem_region inst;
+	int vq_arm_to_pru_event;
+	int vq_pru_to_arm_event;
+};
+
+struct ti_pru_device_info {
+	struct ti_pru_shared_info shared;
+	struct ti_pru_info pru[NUM_TI_PRU];
+};
+
+static const struct ti_pru_device_info ti_pru_devices[NUM_TI_PRU_TYPE] = {
+	[TI_PRU_TYPE_AM18XX] = {
+		.shared = {
+			.intc	= { .offset = 0x4000,	.size = SZ_12K,	},
+		},
+		.pru[TI_PRU0] = {
+			.ram	= { .offset = 0x0000,	.size = SZ_512,	},
+			.ctrl	= { .offset = 0x7000,	.size = SZ_1K,	},
+			.dbg	= { .offset = 0x7400,	.size = SZ_1K,	},
+			.inst	= { .offset = 0x8000,	.size = SZ_4K,	},
+			.vq_arm_to_pru_event = 32,
+			.vq_pru_to_arm_event = 33,
+		},
+		.pru[TI_PRU1] = {
+			.ram	= { .offset = 0x2000,	.size = SZ_512,	},
+			.ctrl	= { .offset = 0x7800,	.size = SZ_1K,	},
+			.dbg	= { .offset = 0x7c00,	.size = SZ_1K,	},
+			.inst	= { .offset = 0xc000,	.size = SZ_4K,	},
+			.vq_arm_to_pru_event = 34,
+			.vq_pru_to_arm_event = 35,
+		},
+	},
+	[TI_PRU_TYPE_AM335X] = {
+		.shared = {
+			.ram	= { .offset = 0x10000,	.size = SZ_12K,	},
+			.intc	= { .offset = 0x20000,	.size = SZ_8K,	},
+			.cfg	= { .offset = 0x26000,	.size = SZ_8K,	},
+		},
+		.pru[TI_PRU0] = {
+			.ram	= { .offset = 0x00000,	.size = SZ_8K,	},
+			.ctrl	= { .offset = 0x22000,	.size = SZ_1K,	},
+			.dbg	= { .offset = 0x22400,	.size = SZ_1K,	},
+			.inst	= { .offset = 0x34000,	.size = SZ_8K,	},
+			.vq_arm_to_pru_event = 16,
+			.vq_pru_to_arm_event = 17,
+		},
+		.pru[TI_PRU1] = {
+			.ram	= { .offset = 0x02000,	.size = SZ_8K,	},
+			.ctrl	= { .offset = 0x24000,	.size = SZ_1K,	},
+			.dbg	= { .offset = 0x24400,	.size = SZ_1K,	},
+			.inst	= { .offset = 0x38000,	.size = SZ_8K,	},
+			.vq_arm_to_pru_event = 18,
+			.vq_pru_to_arm_event = 19,
+		},
+	},
+};
+
+/**
+ * ti_pru_shared_data - private platform driver data
+ * @info: init info common to both PRU cores
+ * @dev: the platform device
+ * @base: the mapped memory region of the PRUSS
+ * @intc: regmap of the interrupt controller
+ * @cfg: regmap of configuration registers
+ * @pru: per-PRU core data
+ */
+struct ti_pru_shared_data {
+	const struct ti_pru_shared_info *info;
+	struct device *dev;
+	void __iomem *base;
+	struct regmap *intc;
+	struct regmap *cfg;
+	struct rproc *pru[NUM_TI_PRU];
+};
+
+/**
+ * ti_pru_data - private data for each PRU core
+ * @info: static init info
+ * @shared: pointer to the shared data struct
+ * @ctrl: regmap of the PRU control/status register
+ * @vq_irq: interrupt used for rpmsg
+ */
+struct ti_pru_data {
+	const struct ti_pru_info *info;
+	struct ti_pru_shared_data *shared;
+	struct regmap *ctrl;
+	int vq_irq;
+};
+
+static int ti_pru_rproc_start(struct rproc *rproc)
+{
+	struct ti_pru_data *pru = rproc->priv;
+	u32 val;
+
+	val = (rproc->bootaddr >> 2) << (ffs(TI_PRU_CONTROL_PCRESETVAL) - 1);
+	val |= TI_PRU_CONTROL_ENABLE;
+
+	return regmap_write(pru->ctrl, TI_PRU_CS_CONTROL, val);
+}
+
+static int ti_pru_rproc_stop(struct rproc *rproc)
+{
+	struct ti_pru_data *pru = rproc->priv;
+	u32 mask;
+
+	mask = TI_PRU_CONTROL_ENABLE;
+
+	return regmap_write_bits(pru->ctrl, TI_PRU_CS_CONTROL, mask, 0);
+}
+
+static void ti_pru_rproc_kick(struct rproc *rproc, int vqid)
+{
+	struct ti_pru_data *pru = rproc->priv;
+	struct ti_pru_shared_data *shared = pru->shared;
+	u32 val;
+
+	val = pru->info->vq_arm_to_pru_event;
+
+	regmap_write(shared->intc, TI_PRU_INTC_STATIDXSET, val);
+}
+
+static void *ti_pru_rproc_da_to_va(struct rproc *rproc, u64 da, int len, int map)
+{
+	struct ti_pru_data *pru = rproc->priv;
+	struct ti_pru_shared_data *shared = pru->shared;
+
+	if (map == 0) {
+		if (da + len > pru->info->inst.size)
+			return ERR_PTR(-EINVAL);
+
+		return shared->base + pru->info->inst.offset + da;
+	}
+
+	if (map == 1) {
+		if (da + len > pru->info->ram.size)
+			return ERR_PTR(-EINVAL);
+
+		return shared->base + pru->info->ram.offset + da;
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+static const struct rproc_ops ti_pru_rproc_ops = {
+	.start = ti_pru_rproc_start,
+	.stop = ti_pru_rproc_stop,
+	.kick = ti_pru_rproc_kick,
+	.da_to_va = ti_pru_rproc_da_to_va,
+};
+
+static struct regmap_config ti_pru_ctrl_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0x2c,
+};
+
+static struct regmap_config ti_pru_intc_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0x1500,
+};
+
+static struct regmap_config ti_pru_cfg_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = 0x40,
+};
+
+static const struct of_device_id ti_pru_rproc_of_match[] = {
+	{
+		.compatible = "ti,da850-pru-rproc",
+		.data = &ti_pru_devices[TI_PRU_TYPE_AM18XX]
+	},
+	{
+		.compatible = "ti,am3352-pru-rproc",
+		.data = &ti_pru_devices[TI_PRU_TYPE_AM335X]
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ti_pru_rproc_of_match);
+
+static irqreturn_t ti_pru_handle_vq_irq(int irq, void *p)
+{
+	struct rproc *rproc = p;
+	struct ti_pru_data *pru = rproc->priv;
+
+	regmap_write(pru->shared->intc, TI_PRU_INTC_STATIDXCLR,
+		     pru->info->vq_pru_to_arm_event);
+
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t ti_pru_vq_irq_thread(int irq, void *p)
+{
+	struct rproc *rproc = p;
+
+	rproc_vq_interrupt(rproc, 0);
+	rproc_vq_interrupt(rproc, 1);
+
+	return IRQ_HANDLED;
+}
+
+static void ti_pru_free_rproc(void *data)
+{
+	struct rproc *rproc = data;
+
+	rproc_free(rproc);
+}
+
+static struct rproc *ti_pru_init_one_rproc(struct ti_pru_shared_data *shared,
+					   const struct ti_pru_info *info,
+					   enum ti_pru id)
+{
+	struct device *dev = shared->dev;
+	struct platform_device *pdev = to_platform_device(dev);
+	const char *name;
+	char irq_name[16];
+	struct rproc *rproc;
+	struct ti_pru_data *pru;
+	int err;
+
+	name = devm_kasprintf(dev, GFP_KERNEL, "pru%u", id);
+	if (!name)
+		return ERR_PTR(-ENOMEM);
+
+	rproc = rproc_alloc(dev, name, &ti_pru_rproc_ops, NULL, sizeof(*pru));
+	if (!rproc)
+		return ERR_PTR(-ENOMEM);
+
+	devm_add_action(dev, ti_pru_free_rproc, rproc);
+
+	/* don't auto-boot for now - bad firmware can lock up the system */
+	rproc->auto_boot = false;
+
+	pru = rproc->priv;
+	pru->info = info;
+	pru->shared = shared;
+
+	snprintf(irq_name, 16, "%s-vq", name);
+
+	pru->vq_irq = platform_get_irq_byname(pdev, irq_name);
+	if (pru->vq_irq < 0) {
+		dev_err(&rproc->dev, "failed to get vq IRQ\n");
+		return ERR_PTR(pru->vq_irq);
+	}
+
+	err = devm_request_threaded_irq(&rproc->dev, pru->vq_irq,
+					ti_pru_handle_vq_irq,
+					ti_pru_vq_irq_thread, 0, name, rproc);
+	if (err < 0) {
+		dev_err(&rproc->dev, "failed to request vq IRQ\n");
+		return ERR_PTR(err);
+	}
+
+	pru->ctrl = devm_regmap_init_mmio(&rproc->dev,
+					  shared->base + info->ctrl.offset,
+					  &ti_pru_ctrl_regmap_config);
+	if (IS_ERR(pru->ctrl)) {
+		dev_err(&rproc->dev, "failed to init ctrl regmap\n");
+		return ERR_CAST(pru->ctrl);
+	}
+
+	return rproc;
+}
+
+/**
+ * ti_pru_init_intc_polarity - configure polarity interrupt event
+ * @intc: the interrtup controller regmap
+ * @event: the source event
+ */
+static void ti_pru_init_intc_polarity(struct regmap *intc, int event)
+{
+	int offset, shift, mask;
+
+	/* 32 events per register */
+	offset = event / 32 * 4;
+	shift = event % 32;
+	mask = 1 << shift;
+
+	/* polarity is always high (1) */
+	regmap_write_bits(intc, TI_PRU_INTC_POLARITY0 + offset, mask, ~0);
+}
+
+/**
+ * ti_pru_init_intc_type - configure type of interrupt event
+ * @intc: the interrtup controller regmap
+ * @event: the source event
+ */
+static void ti_pru_init_intc_type(struct regmap *intc, int event)
+{
+	int offset, shift, mask;
+
+	/* 32 events per register */
+	offset = event / 32 * 4;
+	shift = event % 32;
+	mask = 1 << shift;
+
+	/* type is always pulse (0) */
+	regmap_write_bits(intc, TI_PRU_INTC_TYPE0 + offset, mask, 0);
+}
+
+/**
+ * ti_pru_init_intc_channel_map - configure interrupt event to channel mapping
+ * @intc: the interrtup controller regmap
+ * @event: the source event
+ * @ch: the channel to be assigned to the event
+ */
+static void ti_pru_init_intc_channel_map(struct regmap *intc, int event, int ch)
+{
+	int offset, shift, mask, val;
+
+	/* 4 channels per 32-bit register */
+	offset = event / 4 * 4;
+	shift = event % 4 * 8;
+	mask = 0xff << shift;
+	val = ch << shift;
+
+	regmap_write_bits(intc, TI_PRU_INTC_CHANMAP0 + offset, mask, val);
+}
+
+/**
+ * ti_pru_init_intc_host_map - configure interrupt channel to host mapping
+ * @intc: the interrtup controller regmap
+ * @ch: the source channel
+ * @host: the host interrupt to be assigned to the channel
+ */
+static void ti_pru_init_intc_host_map(struct regmap *intc, int ch, int host)
+{
+	int offset, shift, mask, val;
+
+	/* 4 hosts per 32-bit register */
+	offset = ch / 4 * 4;
+	shift = ch % 4 * 8;
+	mask = 0xff << shift;
+	val = host << shift;
+
+	regmap_write_bits(intc, TI_PRU_INTC_HOSTMAP0 + offset, mask, val);
+}
+
+static void ti_pru_init_intc(struct regmap *intc,
+			     const struct ti_pru_device_info *info)
+{
+	int arm_to_pru0 = info->pru[TI_PRU0].vq_arm_to_pru_event;
+	int arm_to_pru1 = info->pru[TI_PRU1].vq_arm_to_pru_event;
+	int pru0_to_arm = info->pru[TI_PRU0].vq_pru_to_arm_event;
+	int pru1_to_arm = info->pru[TI_PRU1].vq_pru_to_arm_event;
+
+	/* set polarity of system events */
+	ti_pru_init_intc_polarity(intc, arm_to_pru0);
+	ti_pru_init_intc_polarity(intc, arm_to_pru1);
+	ti_pru_init_intc_polarity(intc, pru0_to_arm);
+	ti_pru_init_intc_polarity(intc, pru1_to_arm);
+
+	/* set type of system events */
+	ti_pru_init_intc_type(intc, arm_to_pru0);
+	ti_pru_init_intc_type(intc, arm_to_pru1);
+	ti_pru_init_intc_type(intc, pru0_to_arm);
+	ti_pru_init_intc_type(intc, pru1_to_arm);
+
+	/* map system events to channels */
+	ti_pru_init_intc_channel_map(intc, arm_to_pru0, 0);
+	ti_pru_init_intc_channel_map(intc, arm_to_pru1, 1);
+	ti_pru_init_intc_channel_map(intc, pru0_to_arm, 2);
+	ti_pru_init_intc_channel_map(intc, pru1_to_arm, 3);
+
+	/* map channels to host interrupts */
+	ti_pru_init_intc_host_map(intc, 0, 0); /* ARM to PRU0 */
+	ti_pru_init_intc_host_map(intc, 1, 1); /* ARM to PRU1 */
+	ti_pru_init_intc_host_map(intc, 2, 2); /* PRU0 to ARM */
+	ti_pru_init_intc_host_map(intc, 3, 3); /* PRU1 to ARM */
+
+	/* clear system interrupts */
+	regmap_write(intc, TI_PRU_INTC_STATIDXCLR, arm_to_pru0);
+	regmap_write(intc, TI_PRU_INTC_STATIDXCLR, arm_to_pru1);
+	regmap_write(intc, TI_PRU_INTC_STATIDXCLR, pru0_to_arm);
+	regmap_write(intc, TI_PRU_INTC_STATIDXCLR, pru1_to_arm);
+
+	/* enable host interrupts for kicking */
+	regmap_write(intc, TI_PRU_INTC_HSTINTENIDXSET, 0); /* ARM to PRU0 */
+	regmap_write(intc, TI_PRU_INTC_HSTINTENIDXSET, 1); /* ARM to PRU1 */
+	regmap_write(intc, TI_PRU_INTC_HSTINTENIDXSET, 2); /* PRU0 to ARM */
+	regmap_write(intc, TI_PRU_INTC_HSTINTENIDXSET, 3); /* PRU1 to ARM */
+
+	/* enable system events for kicking */
+	regmap_write(intc, TI_PRU_INTC_ENIDXSET, arm_to_pru0);
+	regmap_write(intc, TI_PRU_INTC_ENIDXSET, arm_to_pru1);
+	regmap_write(intc, TI_PRU_INTC_ENIDXSET, pru0_to_arm);
+	regmap_write(intc, TI_PRU_INTC_ENIDXSET, pru1_to_arm);
+
+	/* enable all interrupts */
+	regmap_write_bits(intc, TI_PRU_INTC_GLBLEN, 1, 1);
+}
+
+static int ti_pru_rproc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ti_pruss_platform_data *pdata = dev_get_platdata(dev);
+	const struct of_device_id *of_id;
+	const struct ti_pru_device_info *info;
+	struct ti_pru_shared_data *shared;
+	struct resource *res;
+	int err;
+
+	of_id = of_match_device(ti_pru_rproc_of_match, dev);
+	if (!of_id || !of_id->data)
+		return -EINVAL;
+
+	info = of_id->data;
+
+	shared = devm_kzalloc(dev, sizeof(*shared), GFP_KERNEL);
+
+	platform_set_drvdata(pdev, shared);
+
+	shared->info = &info->shared;
+	shared->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	shared->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(shared->base)) {
+		dev_err(dev, "failed to ioremap resource\n");
+		return PTR_ERR(shared->base);
+	}
+
+	shared->intc = devm_regmap_init_mmio(dev,
+				shared->base + shared->info->intc.offset,
+				&ti_pru_intc_regmap_config);
+	if (IS_ERR(shared->intc)) {
+		dev_err(dev, "failed to init intc regmap\n");
+		return PTR_ERR(shared->intc);
+	}
+
+	if (shared->info->cfg.size) {
+		shared->cfg = devm_regmap_init_mmio(dev,
+			shared->base + shared->info->cfg.offset,
+			&ti_pru_cfg_regmap_config);
+		if (IS_ERR(shared->cfg)) {
+			dev_err(dev, "failed to init cfg regmap\n");
+			return PTR_ERR(shared->cfg);
+		}
+	}
+
+	shared->pru[TI_PRU0] = ti_pru_init_one_rproc(shared, &info->pru[TI_PRU0],
+						     TI_PRU0);
+	if (IS_ERR(shared->pru[TI_PRU0]))
+		return PTR_ERR(shared->pru[TI_PRU0]);
+
+	shared->pru[TI_PRU1] = ti_pru_init_one_rproc(shared, &info->pru[TI_PRU1],
+						     TI_PRU1);
+	if (IS_ERR(shared->pru[TI_PRU1]))
+		return PTR_ERR(shared->pru[TI_PRU1]);
+
+	pm_runtime_enable(dev);
+
+	err = pm_runtime_get_sync(dev);
+	if (err < 0)
+		goto err_pm_runtime_disable;
+
+	if (pdata) {
+		err = pdata->deassert_reset(pdev, pdata->reset_name);
+		if (err < 0) {
+			dev_err(dev, "Failed to reset pruss\n");
+			goto err_pm_runtime_put;
+		}
+	}
+
+	if (shared->cfg) {
+		int mask, val;
+
+		mask = TI_PRU_SYSCFG_IDLE_MODE_MASK | TI_PRU_SYSCFG_STANDBY_MODE_MASK;
+		val = TI_PRU_SYSCFG_IDLE_MODE_SMART | TI_PRU_SYSCFG_STANDBY_MODE_SMART;
+		regmap_write_bits(shared->cfg, TI_PRU_CFG_SYSCFG, mask, val);
+
+		mask = TI_PRU_SYSCFG_STANDBY_INIT;
+		val = 0;
+		regmap_write_bits(shared->cfg, TI_PRU_CFG_SYSCFG, mask, val);
+
+		err = regmap_read_poll_timeout(shared->cfg, TI_PRU_CFG_SYSCFG,
+				val, !(val & TI_PRU_SYSCFG_SUB_MWAIT), 5, 50);
+		if (err < 0) {
+			dev_err(dev, "timeout while enabling pruss\n");
+			goto err_pm_runtime_put;
+		}
+	}
+
+	ti_pru_init_intc(shared->intc, info);
+
+	err = rproc_add(shared->pru[TI_PRU0]);
+	if (err < 0)
+		goto err_assert_reset;
+
+	err = rproc_add(shared->pru[TI_PRU1]);
+	if (err < 0)
+		goto err_del_pru0;
+
+	return 0;
+
+err_del_pru0:
+	rproc_del(shared->pru[TI_PRU0]);
+err_assert_reset:
+	if (pdata)
+		pdata->assert_reset(pdev, pdata->reset_name);
+err_pm_runtime_put:
+	pm_runtime_put(dev);
+err_pm_runtime_disable:
+	pm_runtime_disable(dev);
+
+	return err;
+}
+
+static int ti_pru_rproc_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ti_pruss_platform_data *pdata = dev_get_platdata(dev);
+	struct ti_pru_shared_data *shared = platform_get_drvdata(pdev);
+
+	rproc_del(shared->pru[TI_PRU1]);
+	rproc_del(shared->pru[TI_PRU0]);
+	if (pdata)
+		pdata->assert_reset(pdev, pdata->reset_name);
+	pm_runtime_put(dev);
+	pm_runtime_disable(dev);
+
+	return 0;
+}
+
+static struct platform_driver ti_pru_rproc_driver = {
+	.probe	= ti_pru_rproc_probe,
+	.remove	= ti_pru_rproc_remove,
+	.driver	= {
+		.name = "ti-pru-rproc",
+		.of_match_table = ti_pru_rproc_of_match,
+	},
+};
+module_platform_driver(ti_pru_rproc_driver);
+
+MODULE_AUTHOR("David Lechner <david@lechnology.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Remoteproc driver for TI PRU");
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 6/8] ARM: davinci_all_defconfig: enable PRU remoteproc module
       [not found] <20180623210810.21232-1-david@lechnology.com>
                   ` (4 preceding siblings ...)
  2018-06-23 21:08 ` [PATCH 5/8] remoteproc: new driver for TI PRU David Lechner
@ 2018-06-23 21:08 ` David Lechner
  2018-06-23 21:08 ` [PATCH 7/8] ARM: dts: da850: add node for PRUSS David Lechner
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2018-06-23 21:08 UTC (permalink / raw)
  To: linux-remoteproc, devicetree, linux-omap, linux-arm-kernel
  Cc: David Lechner, Ohad Ben-Cohen, Bjorn Andersson, Rob Herring,
	Mark Rutland, Benoît Cousson, Tony Lindgren, Sekhar Nori,
	Kevin Hilman, linux-kernel

This enabled the remoteproc module for the PRU on DA8xx-type devices.

Signed-off-by: David Lechner <david@lechnology.com>
---
 arch/arm/configs/davinci_all_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
index a1b6e106b867..1bcc7c6a03ee 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -214,6 +214,8 @@ CONFIG_DMADEVICES=y
 CONFIG_TI_EDMA=y
 CONFIG_REMOTEPROC=m
 CONFIG_DA8XX_REMOTEPROC=m
+CONFIG_TI_PRU_REMOTEPROC=m
+CONFIG_RPMSG_VIRTIO=m
 CONFIG_MEMORY=y
 CONFIG_TI_AEMIF=m
 CONFIG_DA8XX_DDRCTL=y
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 7/8] ARM: dts: da850: add node for PRUSS
       [not found] <20180623210810.21232-1-david@lechnology.com>
                   ` (5 preceding siblings ...)
  2018-06-23 21:08 ` [PATCH 6/8] ARM: davinci_all_defconfig: enable PRU remoteproc module David Lechner
@ 2018-06-23 21:08 ` David Lechner
  2018-06-23 21:08 ` [PATCH 8/8] ARM: dts: am33xx: add node for PRU remoteproc David Lechner
  2018-06-29  9:58 ` New remoteproc driver for TI PRU Roger Quadros
  8 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2018-06-23 21:08 UTC (permalink / raw)
  To: linux-remoteproc, devicetree, linux-omap, linux-arm-kernel
  Cc: David Lechner, Ohad Ben-Cohen, Bjorn Andersson, Rob Herring,
	Mark Rutland, Benoît Cousson, Tony Lindgren, Sekhar Nori,
	Kevin Hilman, linux-kernel

This adds a new remoteproc node to the da850 device tree for the PRUSS.

Signed-off-by: David Lechner <david@lechnology.com>
---

Note: this requires the recent common-clk patches for power-domains

 arch/arm/boot/dts/da850.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index 3fc8b8fd816e..8b052e96fb53 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -540,6 +540,14 @@
 			clocks = <&pll0_auxclk>;
 			status = "disabled";
 		};
+		pru_rproc: cpu@30000 {
+			compatible = "ti,da850-pru-rproc";
+			reg = <0x30000 0x10000>;
+			interrupts = <3>, <4>;
+			interrupt-names = "pru0-vq", "pru1-vq";
+			power-domains = <&psc0 13>;
+			status = "disabled";
+		};
 		mmc0: mmc@40000 {
 			compatible = "ti,da830-mmc";
 			reg = <0x40000 0x1000>;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 8/8] ARM: dts: am33xx: add node for PRU remoteproc
       [not found] <20180623210810.21232-1-david@lechnology.com>
                   ` (6 preceding siblings ...)
  2018-06-23 21:08 ` [PATCH 7/8] ARM: dts: da850: add node for PRUSS David Lechner
@ 2018-06-23 21:08 ` David Lechner
  2018-06-29  9:58 ` New remoteproc driver for TI PRU Roger Quadros
  8 siblings, 0 replies; 17+ messages in thread
From: David Lechner @ 2018-06-23 21:08 UTC (permalink / raw)
  To: linux-remoteproc, devicetree, linux-omap, linux-arm-kernel
  Cc: David Lechner, Ohad Ben-Cohen, Bjorn Andersson, Rob Herring,
	Mark Rutland, Benoît Cousson, Tony Lindgren, Sekhar Nori,
	Kevin Hilman, linux-kernel

This adds a new node to am33xx.dtsi for binding the PRUSS as a
remoteproc device.

Signed-off-by: David Lechner <david@lechnology.com>
---
 arch/arm/boot/dts/am33xx.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 9cd62bc2ca35..1e7837af4689 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -924,6 +924,15 @@
 			};
 		};
 
+		pru_rproc: cpu@4a300000 {
+			compatible = "ti,am3352-pru-rproc";
+			reg = <0x4a300000 0x80000>;
+			interrupts = <20>, <21>;
+			interrupt-names = "pru0-vq", "pru1-vq";
+			ti,hwmods = "pruss";
+			status = "disabled";
+		};
+
 		elm: elm@48080000 {
 			compatible = "ti,am3352-elm";
 			reg = <0x48080000 0x2000>;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* New remoteproc driver for TI PRU
       [not found] <20180623210810.21232-1-david@lechnology.com>
                   ` (7 preceding siblings ...)
  2018-06-23 21:08 ` [PATCH 8/8] ARM: dts: am33xx: add node for PRU remoteproc David Lechner
@ 2018-06-29  9:58 ` Roger Quadros
  2018-06-29 17:44   ` David Lechner
  8 siblings, 1 reply; 17+ messages in thread
From: Roger Quadros @ 2018-06-29  9:58 UTC (permalink / raw)
  To: David Lechner, linux-remoteproc, devicetree, linux-omap,
	linux-arm-kernel
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Sekhar Nori, Kevin Hilman,
	linux-kernel, Anna, Suman, Tero Kristo

+Suman & Tero

Hi David,

On 24/06/18 00:08, David Lechner wrote:
> 
> Date: Sat, 23 Jun 2018 15:43:59 -0500
> Subject: [PATCH 0/8] New remoteproc driver for TI PRU
> 
> This series adds a new remoteproc driver for the TI Programmable Runtime Unit
> (PRU) that is present in some TI Sitara processors. This code has been tested
> working on AM1808 (LEGO MINDSTORMS EV3) and AM3358 (BeagleBone Green).

This is great. We have been working on something similar and I think it would
be great if we can collaborate to get all our needs addressed.

Our primary requirement is that it should be possible for a user (e.g. kernel driver) to
- request a specific PRU core load a specific firmware blob and boot/stop the PRU.
- configure INTC interrupt mapping based on either resource table or DT
- use request_irq to request and use an interrupt.
- request access to DRAM/SRAM
- configure gpimode/miirt/xfr (CFG space)

The work is published here

PRUSS platform bus driver (platform resets & quirks)
https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/drivers/remoteproc/pruss_soc_bus.c

PRUSS core driver (resource management e.g. SRAM/DRAM for clients)
https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/drivers/remoteproc/pruss.c

PRU Rproc driver (PRU remoteproc driver)
https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/drivers/remoteproc/pru_rproc.c

INTC driver (irqchip support for INTC)
https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/drivers/remoteproc/pruss_intc.c

Please have a look at it. I think it addresses most if not all of what your series addresses.
Maybe Suman and you can decide which driver to start with and get the missing pieces addressed.

An example of a client driver
https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/drivers/net/ethernet/ti/prueth.c
and DT node for that
https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/arch/arm/boot/dts/am335x-icev2-prueth.dts#line25

> 
> There are a couple of quirks that had to be worked around in order to get this
> working. The PRU units have multiple memory maps. Notably, both the instruction
> RAM and data RAM are at address 0x0. This caused the da_to_va callback to not
> work because the same address could refer to two different locations. To work
> around this, the first two patches add a "map" parameter to the da_to_va
> callbacks so that we have an extra bit of information to make this distinction.
> 
> Also, on AM38xx we have to use pdata for accessing a reset since there is not
> a reset controller. There are several other devices doing this, so the seems
> the best way for now.
> 
> For anyone else who would like to test, I used the rpmsg-client-sample driver.
> Just enable it in your kernel config. Then grab the appropriate firmware[1]
> and put in in /lib/firmware/. Use sysfs to start and stop the PRU:
> 
>         echo start > /sys/class/remoteproc<n>/state
>         echo stop > /sys/class/remoteproc<n>/state
> 
> [1]: firmware downloads:
> 
> AM18XX: https://github.com/ev3dev/ev3dev-pru-firmware/releases/download/mainline-kernel-testing/AM18xx-PRU-rpmsg-client-sample.zip
> AM335X: https://github.com/ev3dev/ev3dev-pru-firmware/releases/download/mainline-kernel-testing/AM335x-PRU-rpmsg-client-sample.zip
> 
> David Lechner (8):
>   remoteproc: add map parameter to da_to_va
>   remoteproc: add page lookup for TI PRU to ELF loader
>   ARM: OMAP2+: add pdata quirks for PRUSS reset
>   dt-bindings: add bindings for TI PRU as remoteproc
>   remoteproc: new driver for TI PRU
>   ARM: davinci_all_defconfig: enable PRU remoteproc module
>   ARM: dts: da850: add node for PRUSS
>   ARM: dts: am33xx: add node for PRU remoteproc
> 
>  .../bindings/remoteproc/ti_pru_rproc.txt      |  51 ++
>  MAINTAINERS                                   |   5 +
>  arch/arm/boot/dts/am33xx.dtsi                 |   9 +
>  arch/arm/boot/dts/da850.dtsi                  |   8 +
>  arch/arm/configs/davinci_all_defconfig        |   2 +
>  arch/arm/mach-omap2/pdata-quirks.c            |   9 +
>  drivers/remoteproc/Kconfig                    |   7 +
>  drivers/remoteproc/Makefile                   |   1 +
>  drivers/remoteproc/imx_rproc.c                |   2 +-
>  drivers/remoteproc/keystone_remoteproc.c      |   3 +-
>  drivers/remoteproc/qcom_adsp_pil.c            |   2 +-
>  drivers/remoteproc/qcom_q6v5_pil.c            |   2 +-
>  drivers/remoteproc/qcom_wcnss.c               |   2 +-
>  drivers/remoteproc/remoteproc_core.c          |  10 +-
>  drivers/remoteproc/remoteproc_elf_loader.c    | 117 +++-
>  drivers/remoteproc/remoteproc_internal.h      |   2 +-
>  drivers/remoteproc/st_slim_rproc.c            |   2 +-
>  drivers/remoteproc/ti_pru_rproc.c             | 660 ++++++++++++++++++
>  drivers/remoteproc/wkup_m3_rproc.c            |   3 +-
>  include/linux/platform_data/ti-pruss.h        |  18 +
>  include/linux/remoteproc.h                    |   2 +-
>  include/uapi/linux/elf-em.h                   |   1 +
>  22 files changed, 899 insertions(+), 19 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/remoteproc/ti_pru_rproc.txt
>  create mode 100644 drivers/remoteproc/ti_pru_rproc.c
>  create mode 100644 include/linux/platform_data/ti-pruss.h
> 

-- 
cheers,
-roger

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 5/8] remoteproc: new driver for TI PRU
  2018-06-23 21:08 ` [PATCH 5/8] remoteproc: new driver for TI PRU David Lechner
@ 2018-06-29 10:14   ` Roger Quadros
       [not found]     ` <CA+CtpRhQ07=3UytY7QrfnpWkY06UqHbNVq099Coez3C4H3U5yg@mail.gmail.com>
  0 siblings, 1 reply; 17+ messages in thread
From: Roger Quadros @ 2018-06-29 10:14 UTC (permalink / raw)
  To: David Lechner, linux-remoteproc, devicetree, linux-omap,
	linux-arm-kernel
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Sekhar Nori, Kevin Hilman,
	linux-kernel, Anna, Suman, Tero Kristo



On 24/06/18 00:08, David Lechner wrote:
> This adds a new remoteproc driver for TI Programmable Realtime Units
> (PRUs).
> 
> This has been tested working on AM1808 (LEGO MINDSTORMS EV3) using the
> sample rpmsg client driver.
> 
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
>  MAINTAINERS                       |   5 +
>  drivers/remoteproc/Kconfig        |   7 +
>  drivers/remoteproc/Makefile       |   1 +
>  drivers/remoteproc/ti_pru_rproc.c | 660 ++++++++++++++++++++++++++++++
>  4 files changed, 673 insertions(+)
>  create mode 100644 drivers/remoteproc/ti_pru_rproc.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index edf3cf5ea691..06dea089d9ae 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -14288,6 +14288,11 @@ L:	netdev@vger.kernel.org
>  S:	Maintained
>  F:	drivers/net/ethernet/ti/netcp*
>  
> +TI PRU REMOTEPROC DRIVER
> +R:	David Lechner <david@lechnology.com>
> +F:	Documentation/devicetree/bindings/remoteproc/ti_pru_rproc.txt
> +F:	drivers/remoteproc/ti_pru_rproc.c
> +
>  TI TAS571X FAMILY ASoC CODEC DRIVER
>  M:	Kevin Cernekee <cernekee@chromium.org>
>  L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
> diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
> index cd1c168fd188..ae6e725e1755 100644
> --- a/drivers/remoteproc/Kconfig
> +++ b/drivers/remoteproc/Kconfig
> @@ -158,6 +158,13 @@ config ST_REMOTEPROC
>  config ST_SLIM_REMOTEPROC
>  	tristate
>  
> +config TI_PRU_REMOTEPROC
> +	tristate "TI Programmable Realtime Unit"
> +	depends on ARCH_DAVINCI_DA8XX || SOC_AM33XX
> +	help
> +	  Say y here to support TI Programmable Runtime Units (PRUs) via the
> +	  remote processor framework.
> +
>  endif # REMOTEPROC
>  
>  endmenu
> diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
> index 02627ede8d4a..451efee5c8d3 100644
> --- a/drivers/remoteproc/Makefile
> +++ b/drivers/remoteproc/Makefile
> @@ -23,3 +23,4 @@ qcom_wcnss_pil-y			+= qcom_wcnss.o
>  qcom_wcnss_pil-y			+= qcom_wcnss_iris.o
>  obj-$(CONFIG_ST_REMOTEPROC)		+= st_remoteproc.o
>  obj-$(CONFIG_ST_SLIM_REMOTEPROC)	+= st_slim_rproc.o
> +obj-$(CONFIG_TI_PRU_REMOTEPROC)		+= ti_pru_rproc.o
> diff --git a/drivers/remoteproc/ti_pru_rproc.c b/drivers/remoteproc/ti_pru_rproc.c
> new file mode 100644
> index 000000000000..cd8302c318c9
> --- /dev/null
> +++ b/drivers/remoteproc/ti_pru_rproc.c
> @@ -0,0 +1,660 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018 David Lechner <david@lechnology.com>
> + *
> + * Remoteproc driver for TI Programmable Realtime Unit
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_data/ti-pruss.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/remoteproc.h>
> +#include <linux/regmap.h>
> +#include <linux/sizes.h>
> +#include <linux/types.h>
> +
> +#include "remoteproc_internal.h"
> +
> +#define SZ_12K 0x3000
> +
> +/* control/status registers */
> +#define TI_PRU_CS_CONTROL	0x0
> +#define TI_PRU_CS_STATUS	0x4
> +#define TI_PRU_CS_WAKEUP	0x8
> +#define TI_PRU_CS_CYCLECNT	0xc
> +
> +/* control register bits */
> +#define TI_PRU_CONTROL_PCRESETVAL	GENMASK(31, 16)
> +#define TI_PRU_CONTROL_RUNSTATE		BIT(15)
> +#define TI_PRU_CONTROL_SINGLESTEP	BIT(8)
> +#define TI_PRU_CONTROL_COUNTENABLE	BIT(3)
> +#define TI_PRU_CONTROL_SLEEPING		BIT(2)
> +#define TI_PRU_CONTROL_ENABLE		BIT(1)
> +#define TI_PRU_CONTROL_SOFTRESET	BIT(0)
> +
> +/* status bits */
> +#define TI_PRU_STATUS_PCOUNTER		GENMASK(15, 0)
> +
> +/* interrupt controller registers */
> +#define TI_PRU_INTC_GLBLEN		0x10
> +#define TI_PRU_INTC_STATIDXSET		0x20
> +#define TI_PRU_INTC_STATIDXCLR		0x24
> +#define TI_PRU_INTC_ENIDXSET		0x28
> +#define TI_PRU_INTC_HSTINTENIDXSET	0x34
> +#define TI_PRU_INTC_CHANMAP0		0x400
> +#define TI_PRU_INTC_POLARITY0		0xd00
> +#define TI_PRU_INTC_TYPE0		0xd80
> +#define TI_PRU_INTC_HOSTMAP0		0x800
> +
> +/* config registers */
> +#define TI_PRU_CFG_SYSCFG		0x4
> +
> +/* syscfg bits */
> +#define TI_PRU_SYSCFG_SUB_MWAIT			BIT(5)
> +#define TI_PRU_SYSCFG_STANDBY_INIT		BIT(4)
> +#define TI_PRU_SYSCFG_STANDBY_MODE_MASK		GENMASK(3, 2)
> +#define TI_PRU_SYSCFG_STANDBY_MODE_SMART	(2 << 2)
> +#define TI_PRU_SYSCFG_IDLE_MODE_MASK		GENMASK(1, 0)
> +#define TI_PRU_SYSCFG_IDLE_MODE_SMART		(2 << 0)
> +
> +enum ti_pru {
> +	TI_PRU0,
> +	TI_PRU1,
> +	NUM_TI_PRU
> +};
> +
> +enum ti_pru_type {
> +	TI_PRU_TYPE_AM18XX,
> +	TI_PRU_TYPE_AM335X,
> +	NUM_TI_PRU_TYPE
> +};
> +
> +enum ti_pru_evtout {
> +	TI_PRU_EVTOUT0,
> +	TI_PRU_EVTOUT1,
> +	TI_PRU_EVTOUT2,
> +	TI_PRU_EVTOUT3,
> +	TI_PRU_EVTOUT4,
> +	TI_PRU_EVTOUT5,
> +	TI_PRU_EVTOUT6,
> +	TI_PRU_EVTOUT7,
> +	NUM_TI_PRU_EVTOUT
> +};
> +
> +struct ti_pru_mem_region {
> +	off_t offset;
> +	size_t size;
> +};
> +
> +/**
> + * ti_pru_shared_info - common init info for the PRUSS
> + * @ram: shared RAM, if present
> + * @intc: interrupt controller
> + * @cfg: configuration registers, if present
> + */
> +struct ti_pru_shared_info {
> +	struct ti_pru_mem_region ram;
> +	struct ti_pru_mem_region intc;
> +	struct ti_pru_mem_region cfg;
> +};
> +
> +/**
> + * ti_pru_info - init info each individual PRU
> + * @ram: PRU RAM
> + * @ctrl: PRU control/status registers
> + * @dbg: PRU dbg registers
> + * @inst: instruction RAM
> + * @vq_arm_to_pru_event: The index of the PRU system event interrupt used
> + *                       used by the ARM for kicking the PRU
> + * @vq_pru_to_arm_event: The index of the PRU system event interrupt used
> + *                       used by the PRU for kicking the ARM
> + */
> +struct ti_pru_info {
> +	struct ti_pru_mem_region ram;
> +	struct ti_pru_mem_region ctrl;
> +	struct ti_pru_mem_region dbg;
> +	struct ti_pru_mem_region inst;
> +	int vq_arm_to_pru_event;
> +	int vq_pru_to_arm_event;
> +};
> +
> +struct ti_pru_device_info {
> +	struct ti_pru_shared_info shared;
> +	struct ti_pru_info pru[NUM_TI_PRU];
> +};
> +
> +static const struct ti_pru_device_info ti_pru_devices[NUM_TI_PRU_TYPE] = {
> +	[TI_PRU_TYPE_AM18XX] = {
> +		.shared = {
> +			.intc	= { .offset = 0x4000,	.size = SZ_12K,	},
> +		},
> +		.pru[TI_PRU0] = {
> +			.ram	= { .offset = 0x0000,	.size = SZ_512,	},
> +			.ctrl	= { .offset = 0x7000,	.size = SZ_1K,	},
> +			.dbg	= { .offset = 0x7400,	.size = SZ_1K,	},
> +			.inst	= { .offset = 0x8000,	.size = SZ_4K,	},
> +			.vq_arm_to_pru_event = 32,
> +			.vq_pru_to_arm_event = 33,
> +		},
> +		.pru[TI_PRU1] = {
> +			.ram	= { .offset = 0x2000,	.size = SZ_512,	},
> +			.ctrl	= { .offset = 0x7800,	.size = SZ_1K,	},
> +			.dbg	= { .offset = 0x7c00,	.size = SZ_1K,	},
> +			.inst	= { .offset = 0xc000,	.size = SZ_4K,	},
> +			.vq_arm_to_pru_event = 34,
> +			.vq_pru_to_arm_event = 35,
> +		},
> +	},
> +	[TI_PRU_TYPE_AM335X] = {
> +		.shared = {
> +			.ram	= { .offset = 0x10000,	.size = SZ_12K,	},
> +			.intc	= { .offset = 0x20000,	.size = SZ_8K,	},
> +			.cfg	= { .offset = 0x26000,	.size = SZ_8K,	},
> +		},
> +		.pru[TI_PRU0] = {
> +			.ram	= { .offset = 0x00000,	.size = SZ_8K,	},
> +			.ctrl	= { .offset = 0x22000,	.size = SZ_1K,	},
> +			.dbg	= { .offset = 0x22400,	.size = SZ_1K,	},
> +			.inst	= { .offset = 0x34000,	.size = SZ_8K,	},
> +			.vq_arm_to_pru_event = 16,
> +			.vq_pru_to_arm_event = 17,
> +		},
> +		.pru[TI_PRU1] = {
> +			.ram	= { .offset = 0x02000,	.size = SZ_8K,	},
> +			.ctrl	= { .offset = 0x24000,	.size = SZ_1K,	},
> +			.dbg	= { .offset = 0x24400,	.size = SZ_1K,	},
> +			.inst	= { .offset = 0x38000,	.size = SZ_8K,	},
> +			.vq_arm_to_pru_event = 18,
> +			.vq_pru_to_arm_event = 19,
> +		},
> +	},

All this information should really come from the DT.

> +};
> +
> +/**
> + * ti_pru_shared_data - private platform driver data
> + * @info: init info common to both PRU cores
> + * @dev: the platform device
> + * @base: the mapped memory region of the PRUSS
> + * @intc: regmap of the interrupt controller
> + * @cfg: regmap of configuration registers
> + * @pru: per-PRU core data
> + */
> +struct ti_pru_shared_data {
> +	const struct ti_pru_shared_info *info;
> +	struct device *dev;
> +	void __iomem *base;
> +	struct regmap *intc;
> +	struct regmap *cfg;
> +	struct rproc *pru[NUM_TI_PRU];
> +};
> +
> +/**
> + * ti_pru_data - private data for each PRU core
> + * @info: static init info
> + * @shared: pointer to the shared data struct
> + * @ctrl: regmap of the PRU control/status register
> + * @vq_irq: interrupt used for rpmsg
> + */
> +struct ti_pru_data {
> +	const struct ti_pru_info *info;
> +	struct ti_pru_shared_data *shared;
> +	struct regmap *ctrl;
> +	int vq_irq;
> +};
> +
> +static int ti_pru_rproc_start(struct rproc *rproc)
> +{
> +	struct ti_pru_data *pru = rproc->priv;
> +	u32 val;
> +
> +	val = (rproc->bootaddr >> 2) << (ffs(TI_PRU_CONTROL_PCRESETVAL) - 1);
> +	val |= TI_PRU_CONTROL_ENABLE;
> +
> +	return regmap_write(pru->ctrl, TI_PRU_CS_CONTROL, val);
> +}
> +
> +static int ti_pru_rproc_stop(struct rproc *rproc)
> +{
> +	struct ti_pru_data *pru = rproc->priv;
> +	u32 mask;
> +
> +	mask = TI_PRU_CONTROL_ENABLE;
> +
> +	return regmap_write_bits(pru->ctrl, TI_PRU_CS_CONTROL, mask, 0);
> +}
> +
> +static void ti_pru_rproc_kick(struct rproc *rproc, int vqid)
> +{
> +	struct ti_pru_data *pru = rproc->priv;
> +	struct ti_pru_shared_data *shared = pru->shared;
> +	u32 val;
> +
> +	val = pru->info->vq_arm_to_pru_event;
> +
> +	regmap_write(shared->intc, TI_PRU_INTC_STATIDXSET, val);
> +}
> +
> +static void *ti_pru_rproc_da_to_va(struct rproc *rproc, u64 da, int len, int map)
> +{
> +	struct ti_pru_data *pru = rproc->priv;
> +	struct ti_pru_shared_data *shared = pru->shared;
> +
> +	if (map == 0) {
> +		if (da + len > pru->info->inst.size)
> +			return ERR_PTR(-EINVAL);
> +
> +		return shared->base + pru->info->inst.offset + da;
> +	}
> +
> +	if (map == 1) {
> +		if (da + len > pru->info->ram.size)
> +			return ERR_PTR(-EINVAL);
> +
> +		return shared->base + pru->info->ram.offset + da;
> +	}
> +
> +	return ERR_PTR(-EINVAL);
> +}
> +
> +static const struct rproc_ops ti_pru_rproc_ops = {
> +	.start = ti_pru_rproc_start,
> +	.stop = ti_pru_rproc_stop,
> +	.kick = ti_pru_rproc_kick,
> +	.da_to_va = ti_pru_rproc_da_to_va,
> +};
> +
> +static struct regmap_config ti_pru_ctrl_regmap_config = {
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.max_register = 0x2c,
> +};
> +
> +static struct regmap_config ti_pru_intc_regmap_config = {
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.max_register = 0x1500,
> +};
> +
> +static struct regmap_config ti_pru_cfg_regmap_config = {
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.max_register = 0x40,
> +};
> +
> +static const struct of_device_id ti_pru_rproc_of_match[] = {
> +	{
> +		.compatible = "ti,da850-pru-rproc",
> +		.data = &ti_pru_devices[TI_PRU_TYPE_AM18XX]
> +	},
> +	{
> +		.compatible = "ti,am3352-pru-rproc",
> +		.data = &ti_pru_devices[TI_PRU_TYPE_AM335X]
> +	},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, ti_pru_rproc_of_match);
> +
> +static irqreturn_t ti_pru_handle_vq_irq(int irq, void *p)
> +{
> +	struct rproc *rproc = p;
> +	struct ti_pru_data *pru = rproc->priv;
> +
> +	regmap_write(pru->shared->intc, TI_PRU_INTC_STATIDXCLR,
> +		     pru->info->vq_pru_to_arm_event);
> +
> +	return IRQ_WAKE_THREAD;
> +}
> +
> +static irqreturn_t ti_pru_vq_irq_thread(int irq, void *p)
> +{
> +	struct rproc *rproc = p;
> +
> +	rproc_vq_interrupt(rproc, 0);
> +	rproc_vq_interrupt(rproc, 1);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void ti_pru_free_rproc(void *data)
> +{
> +	struct rproc *rproc = data;
> +
> +	rproc_free(rproc);
> +}
> +
> +static struct rproc *ti_pru_init_one_rproc(struct ti_pru_shared_data *shared,
> +					   const struct ti_pru_info *info,
> +					   enum ti_pru id)
> +{
> +	struct device *dev = shared->dev;
> +	struct platform_device *pdev = to_platform_device(dev);
> +	const char *name;
> +	char irq_name[16];
> +	struct rproc *rproc;
> +	struct ti_pru_data *pru;
> +	int err;
> +
> +	name = devm_kasprintf(dev, GFP_KERNEL, "pru%u", id);
> +	if (!name)
> +		return ERR_PTR(-ENOMEM);
> +
> +	rproc = rproc_alloc(dev, name, &ti_pru_rproc_ops, NULL, sizeof(*pru));
> +	if (!rproc)
> +		return ERR_PTR(-ENOMEM);
> +
> +	devm_add_action(dev, ti_pru_free_rproc, rproc);
> +
> +	/* don't auto-boot for now - bad firmware can lock up the system */
> +	rproc->auto_boot = false;
> +
> +	pru = rproc->priv;
> +	pru->info = info;
> +	pru->shared = shared;
> +
> +	snprintf(irq_name, 16, "%s-vq", name);
> +
> +	pru->vq_irq = platform_get_irq_byname(pdev, irq_name);
> +	if (pru->vq_irq < 0) {
> +		dev_err(&rproc->dev, "failed to get vq IRQ\n");
> +		return ERR_PTR(pru->vq_irq);
> +	}
> +
> +	err = devm_request_threaded_irq(&rproc->dev, pru->vq_irq,
> +					ti_pru_handle_vq_irq,
> +					ti_pru_vq_irq_thread, 0, name, rproc);
> +	if (err < 0) {
> +		dev_err(&rproc->dev, "failed to request vq IRQ\n");
> +		return ERR_PTR(err);
> +	}
> +
> +	pru->ctrl = devm_regmap_init_mmio(&rproc->dev,
> +					  shared->base + info->ctrl.offset,
> +					  &ti_pru_ctrl_regmap_config);
> +	if (IS_ERR(pru->ctrl)) {
> +		dev_err(&rproc->dev, "failed to init ctrl regmap\n");
> +		return ERR_CAST(pru->ctrl);
> +	}
> +
> +	return rproc;
> +}
> +
> +/**
> + * ti_pru_init_intc_polarity - configure polarity interrupt event
> + * @intc: the interrtup controller regmap
> + * @event: the source event
> + */
> +static void ti_pru_init_intc_polarity(struct regmap *intc, int event)
> +{
> +	int offset, shift, mask;
> +
> +	/* 32 events per register */
> +	offset = event / 32 * 4;
> +	shift = event % 32;
> +	mask = 1 << shift;
> +
> +	/* polarity is always high (1) */
> +	regmap_write_bits(intc, TI_PRU_INTC_POLARITY0 + offset, mask, ~0);
> +}
> +
> +/**
> + * ti_pru_init_intc_type - configure type of interrupt event
> + * @intc: the interrtup controller regmap
> + * @event: the source event
> + */
> +static void ti_pru_init_intc_type(struct regmap *intc, int event)
> +{
> +	int offset, shift, mask;
> +
> +	/* 32 events per register */
> +	offset = event / 32 * 4;
> +	shift = event % 32;
> +	mask = 1 << shift;
> +
> +	/* type is always pulse (0) */
> +	regmap_write_bits(intc, TI_PRU_INTC_TYPE0 + offset, mask, 0);
> +}
> +
> +/**
> + * ti_pru_init_intc_channel_map - configure interrupt event to channel mapping
> + * @intc: the interrtup controller regmap
> + * @event: the source event
> + * @ch: the channel to be assigned to the event
> + */
> +static void ti_pru_init_intc_channel_map(struct regmap *intc, int event, int ch)
> +{
> +	int offset, shift, mask, val;
> +
> +	/* 4 channels per 32-bit register */
> +	offset = event / 4 * 4;
> +	shift = event % 4 * 8;
> +	mask = 0xff << shift;
> +	val = ch << shift;
> +
> +	regmap_write_bits(intc, TI_PRU_INTC_CHANMAP0 + offset, mask, val);
> +}
> +
> +/**
> + * ti_pru_init_intc_host_map - configure interrupt channel to host mapping
> + * @intc: the interrtup controller regmap
> + * @ch: the source channel
> + * @host: the host interrupt to be assigned to the channel
> + */
> +static void ti_pru_init_intc_host_map(struct regmap *intc, int ch, int host)
> +{
> +	int offset, shift, mask, val;
> +
> +	/* 4 hosts per 32-bit register */
> +	offset = ch / 4 * 4;
> +	shift = ch % 4 * 8;
> +	mask = 0xff << shift;
> +	val = host << shift;
> +
> +	regmap_write_bits(intc, TI_PRU_INTC_HOSTMAP0 + offset, mask, val);
> +}
> +
> +static void ti_pru_init_intc(struct regmap *intc,
> +			     const struct ti_pru_device_info *info)
> +{
> +	int arm_to_pru0 = info->pru[TI_PRU0].vq_arm_to_pru_event;
> +	int arm_to_pru1 = info->pru[TI_PRU1].vq_arm_to_pru_event;
> +	int pru0_to_arm = info->pru[TI_PRU0].vq_pru_to_arm_event;
> +	int pru1_to_arm = info->pru[TI_PRU1].vq_pru_to_arm_event;
> +
> +	/* set polarity of system events */
> +	ti_pru_init_intc_polarity(intc, arm_to_pru0);
> +	ti_pru_init_intc_polarity(intc, arm_to_pru1);
> +	ti_pru_init_intc_polarity(intc, pru0_to_arm);
> +	ti_pru_init_intc_polarity(intc, pru1_to_arm);
> +
> +	/* set type of system events */
> +	ti_pru_init_intc_type(intc, arm_to_pru0);
> +	ti_pru_init_intc_type(intc, arm_to_pru1);
> +	ti_pru_init_intc_type(intc, pru0_to_arm);
> +	ti_pru_init_intc_type(intc, pru1_to_arm);
> +
> +	/* map system events to channels */
> +	ti_pru_init_intc_channel_map(intc, arm_to_pru0, 0);
> +	ti_pru_init_intc_channel_map(intc, arm_to_pru1, 1);
> +	ti_pru_init_intc_channel_map(intc, pru0_to_arm, 2);
> +	ti_pru_init_intc_channel_map(intc, pru1_to_arm, 3);
> +
> +	/* map channels to host interrupts */
> +	ti_pru_init_intc_host_map(intc, 0, 0); /* ARM to PRU0 */
> +	ti_pru_init_intc_host_map(intc, 1, 1); /* ARM to PRU1 */
> +	ti_pru_init_intc_host_map(intc, 2, 2); /* PRU0 to ARM */
> +	ti_pru_init_intc_host_map(intc, 3, 3); /* PRU1 to ARM */
> +
> +	/* clear system interrupts */
> +	regmap_write(intc, TI_PRU_INTC_STATIDXCLR, arm_to_pru0);
> +	regmap_write(intc, TI_PRU_INTC_STATIDXCLR, arm_to_pru1);
> +	regmap_write(intc, TI_PRU_INTC_STATIDXCLR, pru0_to_arm);
> +	regmap_write(intc, TI_PRU_INTC_STATIDXCLR, pru1_to_arm);
> +
> +	/* enable host interrupts for kicking */
> +	regmap_write(intc, TI_PRU_INTC_HSTINTENIDXSET, 0); /* ARM to PRU0 */
> +	regmap_write(intc, TI_PRU_INTC_HSTINTENIDXSET, 1); /* ARM to PRU1 */
> +	regmap_write(intc, TI_PRU_INTC_HSTINTENIDXSET, 2); /* PRU0 to ARM */
> +	regmap_write(intc, TI_PRU_INTC_HSTINTENIDXSET, 3); /* PRU1 to ARM */
> +
> +	/* enable system events for kicking */
> +	regmap_write(intc, TI_PRU_INTC_ENIDXSET, arm_to_pru0);
> +	regmap_write(intc, TI_PRU_INTC_ENIDXSET, arm_to_pru1);
> +	regmap_write(intc, TI_PRU_INTC_ENIDXSET, pru0_to_arm);
> +	regmap_write(intc, TI_PRU_INTC_ENIDXSET, pru1_to_arm);
> +
> +	/* enable all interrupts */
> +	regmap_write_bits(intc, TI_PRU_INTC_GLBLEN, 1, 1);
> +}

We already have a working irq_chip implementation for INTC.
https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/drivers/remoteproc/pruss_intc.c

I think we can leverage directly from that.

This way pru_rproc or client device nodes can easily specify a pruss_intc interrupt parent and the
SYSEVENT number as the irq. Then device drivers can simply use request_irq().

example usage here
https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/arch/arm/boot/dts/am33xx.dtsi#line986
https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/drivers/remoteproc/pru_rproc.c#line670


> +
> +static int ti_pru_rproc_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct ti_pruss_platform_data *pdata = dev_get_platdata(dev);
> +	const struct of_device_id *of_id;
> +	const struct ti_pru_device_info *info;
> +	struct ti_pru_shared_data *shared;
> +	struct resource *res;
> +	int err;
> +
> +	of_id = of_match_device(ti_pru_rproc_of_match, dev);
> +	if (!of_id || !of_id->data)
> +		return -EINVAL;
> +
> +	info = of_id->data;
> +
> +	shared = devm_kzalloc(dev, sizeof(*shared), GFP_KERNEL);
> +
> +	platform_set_drvdata(pdev, shared);
> +
> +	shared->info = &info->shared;
> +	shared->dev = dev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	shared->base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(shared->base)) {
> +		dev_err(dev, "failed to ioremap resource\n");
> +		return PTR_ERR(shared->base);
> +	}
> +
> +	shared->intc = devm_regmap_init_mmio(dev,
> +				shared->base + shared->info->intc.offset,
> +				&ti_pru_intc_regmap_config);
> +	if (IS_ERR(shared->intc)) {
> +		dev_err(dev, "failed to init intc regmap\n");
> +		return PTR_ERR(shared->intc);
> +	}
> +
> +	if (shared->info->cfg.size) {
> +		shared->cfg = devm_regmap_init_mmio(dev,
> +			shared->base + shared->info->cfg.offset,
> +			&ti_pru_cfg_regmap_config);
> +		if (IS_ERR(shared->cfg)) {
> +			dev_err(dev, "failed to init cfg regmap\n");
> +			return PTR_ERR(shared->cfg);
> +		}
> +	}
> +
> +	shared->pru[TI_PRU0] = ti_pru_init_one_rproc(shared, &info->pru[TI_PRU0],
> +						     TI_PRU0);
> +	if (IS_ERR(shared->pru[TI_PRU0]))
> +		return PTR_ERR(shared->pru[TI_PRU0]);
> +
> +	shared->pru[TI_PRU1] = ti_pru_init_one_rproc(shared, &info->pru[TI_PRU1],
> +						     TI_PRU1);
> +	if (IS_ERR(shared->pru[TI_PRU1]))
> +		return PTR_ERR(shared->pru[TI_PRU1]);
> +
> +	pm_runtime_enable(dev);
> +
> +	err = pm_runtime_get_sync(dev);
> +	if (err < 0)
> +		goto err_pm_runtime_disable;
> +
> +	if (pdata) {
> +		err = pdata->deassert_reset(pdev, pdata->reset_name);
> +		if (err < 0) {
> +			dev_err(dev, "Failed to reset pruss\n");
> +			goto err_pm_runtime_put;
> +		}
> +	}
> +
> +	if (shared->cfg) {
> +		int mask, val;
> +
> +		mask = TI_PRU_SYSCFG_IDLE_MODE_MASK | TI_PRU_SYSCFG_STANDBY_MODE_MASK;
> +		val = TI_PRU_SYSCFG_IDLE_MODE_SMART | TI_PRU_SYSCFG_STANDBY_MODE_SMART;
> +		regmap_write_bits(shared->cfg, TI_PRU_CFG_SYSCFG, mask, val);
> +
> +		mask = TI_PRU_SYSCFG_STANDBY_INIT;
> +		val = 0;
> +		regmap_write_bits(shared->cfg, TI_PRU_CFG_SYSCFG, mask, val);
> +
> +		err = regmap_read_poll_timeout(shared->cfg, TI_PRU_CFG_SYSCFG,
> +				val, !(val & TI_PRU_SYSCFG_SUB_MWAIT), 5, 50);
> +		if (err < 0) {
> +			dev_err(dev, "timeout while enabling pruss\n");
> +			goto err_pm_runtime_put;
> +		}
> +	}
> +
> +	ti_pru_init_intc(shared->intc, info);

This is using a static INTC map right?
This limits our possibility to use application based INTC mapping.
There needs to be a way to specify the INTC mapping in the DT and/or resource table.

> +
> +	err = rproc_add(shared->pru[TI_PRU0]);
> +	if (err < 0)
> +		goto err_assert_reset;
> +
> +	err = rproc_add(shared->pru[TI_PRU1]);
> +	if (err < 0)
> +		goto err_del_pru0;
> +
> +	return 0;
> +
> +err_del_pru0:
> +	rproc_del(shared->pru[TI_PRU0]);
> +err_assert_reset:
> +	if (pdata)
> +		pdata->assert_reset(pdev, pdata->reset_name);
> +err_pm_runtime_put:
> +	pm_runtime_put(dev);
> +err_pm_runtime_disable:
> +	pm_runtime_disable(dev);
> +
> +	return err;
> +}
> +
> +static int ti_pru_rproc_remove(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct ti_pruss_platform_data *pdata = dev_get_platdata(dev);
> +	struct ti_pru_shared_data *shared = platform_get_drvdata(pdev);
> +
> +	rproc_del(shared->pru[TI_PRU1]);
> +	rproc_del(shared->pru[TI_PRU0]);
> +	if (pdata)
> +		pdata->assert_reset(pdev, pdata->reset_name);
> +	pm_runtime_put(dev);
> +	pm_runtime_disable(dev);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver ti_pru_rproc_driver = {
> +	.probe	= ti_pru_rproc_probe,
> +	.remove	= ti_pru_rproc_remove,
> +	.driver	= {
> +		.name = "ti-pru-rproc",
> +		.of_match_table = ti_pru_rproc_of_match,
> +	},
> +};
> +module_platform_driver(ti_pru_rproc_driver);
> +
> +MODULE_AUTHOR("David Lechner <david@lechnology.com>");
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Remoteproc driver for TI PRU");
> 

-- 
cheers,
-roger

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: New remoteproc driver for TI PRU
  2018-06-29  9:58 ` New remoteproc driver for TI PRU Roger Quadros
@ 2018-06-29 17:44   ` David Lechner
  2018-06-30  0:17     ` Suman Anna
  2018-07-02  8:17     ` Roger Quadros
  0 siblings, 2 replies; 17+ messages in thread
From: David Lechner @ 2018-06-29 17:44 UTC (permalink / raw)
  To: Roger Quadros, linux-remoteproc, devicetree, linux-omap,
	linux-arm-kernel
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Sekhar Nori, Kevin Hilman,
	linux-kernel, Anna, Suman, Tero Kristo

On 06/29/2018 04:58 AM, Roger Quadros wrote:
> +Suman & Tero
> 
> Hi David,
> 
> On 24/06/18 00:08, David Lechner wrote:
>>
>> Date: Sat, 23 Jun 2018 15:43:59 -0500
>> Subject: [PATCH 0/8] New remoteproc driver for TI PRU
>>
>> This series adds a new remoteproc driver for the TI Programmable Runtime Unit
>> (PRU) that is present in some TI Sitara processors. This code has been tested
>> working on AM1808 (LEGO MINDSTORMS EV3) and AM3358 (BeagleBone Green).
> 
> This is great. We have been working on something similar and I think it would
> be great if we can collaborate to get all our needs addressed.

Yes, I have used the PRU with the TI kernel on BeagleBone so I've seen the TI
implementation. My primary interest is in the AM1808, which has a far simpler
PRU than other SoCs. So, I was hoping I could get away with just implementing
the basic stuff that I need and let TI add the more complex stuff later.

> 
> Our primary requirement is that it should be possible for a user (e.g. kernel driver) to
> - request a specific PRU core load a specific firmware blob and boot/stop the PRU.

For this, I was thinking of suggesting a generic remoteproc provider/consumer
binding that is similar to other subsystems. For example:

Provider node has:

	#remoteproc-cells = <1>;

And consumer has:

	remoteprocs = <&pruss 0>, <&pruss 1>;
	remoteproc-names = "pru0", "pru1";

The consumer device would be responsible for determining the firmware file
and for calling the rproc boot function.


> - configure INTC interrupt mapping based on either resource table or DT
> - use request_irq to request and use an interrupt.

I didn't consider creating a new interrupt controller in device tree, but
that makes sense. I will have to look into it some more.


> - request access to DRAM/SRAM

Can the existing device tree bindings for reserved-memory be used for this?
I would expect the consumer nodes to use this and not the PRUSS provider node.


> - configure gpimode/miirt/xfr (CFG space)

I have no idea what this stuff is. :-)

(This is what I was referring to when I said I was hoping that someone
else could add more later).


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: New remoteproc driver for TI PRU
  2018-06-29 17:44   ` David Lechner
@ 2018-06-30  0:17     ` Suman Anna
  2018-08-06 16:32       ` David Lechner
  2018-07-02  8:17     ` Roger Quadros
  1 sibling, 1 reply; 17+ messages in thread
From: Suman Anna @ 2018-06-30  0:17 UTC (permalink / raw)
  To: David Lechner, Roger Quadros, linux-remoteproc, devicetree,
	linux-omap, linux-arm-kernel
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Sekhar Nori, Kevin Hilman,
	linux-kernel, Tero Kristo

Hi David,

On 06/29/2018 12:44 PM, David Lechner wrote:
> On 06/29/2018 04:58 AM, Roger Quadros wrote:
>> +Suman & Tero
>>
>> Hi David,
>>
>> On 24/06/18 00:08, David Lechner wrote:
>>>
>>> Date: Sat, 23 Jun 2018 15:43:59 -0500
>>> Subject: [PATCH 0/8] New remoteproc driver for TI PRU
>>>
>>> This series adds a new remoteproc driver for the TI Programmable
>>> Runtime Unit
>>> (PRU) that is present in some TI Sitara processors. This code has
>>> been tested
>>> working on AM1808 (LEGO MINDSTORMS EV3) and AM3358 (BeagleBone Green).
>>
>> This is great. We have been working on something similar and I think
>> it would
>> be great if we can collaborate to get all our needs addressed.
> 
> Yes, I have used the PRU with the TI kernel on BeagleBone so I've seen
> the TI
> implementation. My primary interest is in the AM1808, which has a far
> simpler
> PRU than other SoCs. So, I was hoping I could get away with just
> implementing
> the basic stuff that I need and let TI add the more complex stuff later.

Thanks for the series. PRUSS is present on many SoCs now, and each with
their own integration quirks, both in terms of SoC connections as well
as internal sub-modules within the subsystem. We currently support
AM335x, AM437x, AM57xx, Keystone 2 based 66AK2G and a newer generation
AM65x as well. It should be relatively straight-forward to scale this
for AM1808/OMAP-L138 as well. The move to the standard Common Clock and
Reset frameworks for clocks with the Davinci chips should make it
relatively straight-forward for the architecture pieces.

I will take a look at your series in detail sometime next week, and
mostly post our series to the upstream lists as well within the next
couple of weeks so that it is easier for discussion on the upstream lists.

> 
>>
>> Our primary requirement is that it should be possible for a user (e.g.
>> kernel driver) to
>> - request a specific PRU core load a specific firmware blob and
>> boot/stop the PRU.
> 
> For this, I was thinking of suggesting a generic remoteproc
> provider/consumer
> binding that is similar to other subsystems. For example:
> 
> Provider node has:
> 
>     #remoteproc-cells = <1>;
> 
> And consumer has:
> 
>     remoteprocs = <&pruss 0>, <&pruss 1>;
>     remoteproc-names = "pru0", "pru1";

We do have an existing API in remoteproc core today,
rproc_get_by_phandle() for this, though it is not as sophisticated or
designed in a standard way that we see on some other sub-systems. One
thing that's currently missing from this is a sense of exclusive access,
as we do want to restrict access to a PRU to a single client at a time.
> 
> The consumer device would be responsible for determining the firmware file
> and for calling the rproc boot function.
> 
> 
>> - configure INTC interrupt mapping based on either resource table or DT
>> - use request_irq to request and use an interrupt.
> 
> I didn't consider creating a new interrupt controller in device tree, but
> that makes sense. I will have to look into it some more.
> 

Couple of iterations on our vendor tree all but resulted in representing
various sub-modules as child nodes - this allows to reuse different
drivers to deal with specific functionality like MDIO, UART etc. The
number of registers across all PRUSS sub-modules and SoCs are too huge
to support through a single driver.

> 
>> - request access to DRAM/SRAM
> 
> Can the existing device tree bindings for reserved-memory be used for this?

Typically, reserved-memory is used for reserving regions in DDR, not
mmio spaces. There is the SRAM driver in general to deal with on-chip
memories.

> I would expect the consumer nodes to use this and not the PRUSS provider
> node.

We will need access from both, as the remoteproc core does the loading
in general leveraging specific rproc ops from a remoteproc
implementation driver.

> 
> 
>> - configure gpimode/miirt/xfr (CFG space)
> 
> I have no idea what this stuff is. :-)

There are all the different sub-modules/register spaces dealing
specifically with internal pinmuxes, some serial/parallel GPIO pin
operations etc.

regards
Suman

> 
> (This is what I was referring to when I said I was hoping that someone
> else could add more later).
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 5/8] remoteproc: new driver for TI PRU
       [not found]     ` <CA+CtpRhQ07=3UytY7QrfnpWkY06UqHbNVq099Coez3C4H3U5yg@mail.gmail.com>
@ 2018-07-02  8:05       ` Roger Quadros
  0 siblings, 0 replies; 17+ messages in thread
From: Roger Quadros @ 2018-07-02  8:05 UTC (permalink / raw)
  To: Derald Woods
  Cc: David Lechner, linux-remoteproc, devicetree, linux-omap,
	linux-arm-kernel, Ohad Ben-Cohen, Bjorn Andersson, Rob Herring,
	Mark Rutland, Benoît Cousson, Tony Lindgren, Sekhar Nori,
	Kevin Hilman, linux-kernel, Anna, Suman, Tero Kristo

Derald,

On 30/06/18 22:02, Derald Woods wrote:
> 
> 
> On Fri, Jun 29, 2018 at 5:14 AM, Roger Quadros <rogerq@ti.com <mailto:rogerq@ti.com>> wrote:
> 
> 
> 
>     On 24/06/18 00:08, David Lechner wrote:
>     > This adds a new remoteproc driver for TI Programmable Realtime Units
>     > (PRUs).
>     >
>     > This has been tested working on AM1808 (LEGO MINDSTORMS EV3) using the
>     > sample rpmsg client driver.
>     >
>     > Signed-off-by: David Lechner <david@lechnology.com <mailto:david@lechnology.com>>
>     > ---
>     >  MAINTAINERS                       |   5 +
>     >  drivers/remoteproc/Kconfig        |   7 +
>     >  drivers/remoteproc/Makefile       |   1 +
>     >  drivers/remoteproc/ti_pru_rproc.c | 660 ++++++++++++++++++++++++++++++
>     >  4 files changed, 673 insertions(+)
>     >  create mode 100644 drivers/remoteproc/ti_pru_rproc.c

<snip>

> 
>     We already have a working irq_chip implementation for INTC.
>     https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/drivers/remoteproc/pruss_intc.c <https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/drivers/remoteproc/pruss_intc.c>
> 
>     I think we can leverage directly from that.
> 
>     This way pru_rproc or client device nodes can easily specify a pruss_intc interrupt parent and the
>     SYSEVENT number as the irq. Then device drivers can simply use request_irq().
> 
>     example usage here
>     https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/arch/arm/boot/dts/am33xx.dtsi#line986 <https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/arch/arm/boot/dts/am33xx.dtsi#line986>
>     https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/drivers/remoteproc/pru_rproc.c#line670 <https://git.ti.com/ti-linux-kernel/ti-linux-kernel/blobs/ti-linux-4.14.y/drivers/remoteproc/pru_rproc.c#line670>
> 
> 
> 
> 
> ​Is this PRU code on a path to be added to the mainline kernel?​ There is an increase in the number of available systems which would benefit from consistent PRU interfaces. If code is not mainlined, or on a mainline path, some may think it is not usable or ready for production. Is this a permanent "out-of-tree" and/or "TI-tree" development. Just wondering.
> 

Yes, we constantly upstream our work. We are currently working to get the PRU support upstream.

-- 
cheers,
-roger

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: New remoteproc driver for TI PRU
  2018-06-29 17:44   ` David Lechner
  2018-06-30  0:17     ` Suman Anna
@ 2018-07-02  8:17     ` Roger Quadros
  1 sibling, 0 replies; 17+ messages in thread
From: Roger Quadros @ 2018-07-02  8:17 UTC (permalink / raw)
  To: David Lechner, linux-remoteproc, devicetree, linux-omap,
	linux-arm-kernel
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Sekhar Nori, Kevin Hilman,
	linux-kernel, Anna, Suman, Tero Kristo

On 29/06/18 20:44, David Lechner wrote:
> On 06/29/2018 04:58 AM, Roger Quadros wrote:
>> +Suman & Tero
>>
>> Hi David,
>>
>> On 24/06/18 00:08, David Lechner wrote:
>>>
>>> Date: Sat, 23 Jun 2018 15:43:59 -0500
>>> Subject: [PATCH 0/8] New remoteproc driver for TI PRU
>>>
>>> This series adds a new remoteproc driver for the TI Programmable Runtime Unit
>>> (PRU) that is present in some TI Sitara processors. This code has been tested
>>> working on AM1808 (LEGO MINDSTORMS EV3) and AM3358 (BeagleBone Green).
>>
>> This is great. We have been working on something similar and I think it would
>> be great if we can collaborate to get all our needs addressed.
> 
> Yes, I have used the PRU with the TI kernel on BeagleBone so I've seen the TI
> implementation. My primary interest is in the AM1808, which has a far simpler
> PRU than other SoCs. So, I was hoping I could get away with just implementing
> the basic stuff that I need and let TI add the more complex stuff later.
> 

The PRUSS core is essentially the same thing on most of our SoCs. They might
be varying in amount of RAM and integrated modules though. So PRUSS core support
should be scalable across all SoCs.

It is perfectly fine to get basic support in first and add the rest as we go along.

>>
>> Our primary requirement is that it should be possible for a user (e.g. kernel driver) to
>> - request a specific PRU core load a specific firmware blob and boot/stop the PRU.
> 
> For this, I was thinking of suggesting a generic remoteproc provider/consumer
> binding that is similar to other subsystems. For example:
> 
> Provider node has:
> 
>     #remoteproc-cells = <1>;
> 
> And consumer has:
> 
>     remoteprocs = <&pruss 0>, <&pruss 1>;
>     remoteproc-names = "pru0", "pru1";
> 
> The consumer device would be responsible for determining the firmware file
> and for calling the rproc boot function.
> 
> 
>> - configure INTC interrupt mapping based on either resource table or DT
>> - use request_irq to request and use an interrupt.
> 
> I didn't consider creating a new interrupt controller in device tree, but
> that makes sense. I will have to look into it some more.
> 
> 
>> - request access to DRAM/SRAM
> 
> Can the existing device tree bindings for reserved-memory be used for this?
> I would expect the consumer nodes to use this and not the PRUSS provider node.
> 
> 
>> - configure gpimode/miirt/xfr (CFG space)
> 
> I have no idea what this stuff is. :-)
> 
> (This is what I was referring to when I said I was hoping that someone
> else could add more later).
> 

-- 
cheers,
-roger

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 4/8] dt-bindings: add bindings for TI PRU as remoteproc
  2018-06-23 21:08 ` [PATCH 4/8] dt-bindings: add bindings for TI PRU as remoteproc David Lechner
@ 2018-07-03 20:59   ` Rob Herring
  0 siblings, 0 replies; 17+ messages in thread
From: Rob Herring @ 2018-07-03 20:59 UTC (permalink / raw)
  To: David Lechner
  Cc: linux-remoteproc, devicetree, linux-omap, linux-arm-kernel,
	Ohad Ben-Cohen, Bjorn Andersson, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Sekhar Nori, Kevin Hilman,
	linux-kernel

On Sat, Jun 23, 2018 at 04:08:06PM -0500, David Lechner wrote:
> This adds a new binding for the TI Programmable Runtime Unit (PRU)
> as a remoteproc device.
> 
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
>  .../bindings/remoteproc/ti_pru_rproc.txt      | 51 +++++++++++++++++++
>  1 file changed, 51 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/remoteproc/ti_pru_rproc.txt
> 
> diff --git a/Documentation/devicetree/bindings/remoteproc/ti_pru_rproc.txt b/Documentation/devicetree/bindings/remoteproc/ti_pru_rproc.txt
> new file mode 100644
> index 000000000000..0e80a8db46d0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/remoteproc/ti_pru_rproc.txt
> @@ -0,0 +1,51 @@
> +TI Programmable Realtime Unit (PRU)
> +===================================
> +
> +Some TI Sitara SoCs contain a Programmable Realtime Unit subsystem with two
> +processor cores that can be used for hard-realtime tasks.
> +
> +
> +Required properties:
> +--------------------
> +The following are the mandatory properties:
> +
> +- compatible:		Should be one of the following,
> +			    "ti,da850-pru-rproc" for AM18xx/OMAPL138 SoCs
> +			    "ti,am3352-pru-rproc" for AM355x SoCs
> +
> +- reg:			Should contain the memory region for the PRUSS
> +
> +- interrupts: 		Should contain the interrupt number used to receive the
> +			virtualqueue kick interrupts from the PRU (i.e.
> +			PRU_EVTOUT0 and PRU_EVTOUT1)
> +
> +- interrupt-names	Should contain "pru0-vq", "pru1-vq"
> +
> +Optional properties:
> +--------------------
> +
> +- power-domains:	A phandle to the power domain that powers the PRUSS

Only for da850?

> +
> +- ti,hwmods:		Name of the hwmod associated to the PRUSS, which is
> +			typically "pruss"

Only for am3352?

typically? You should enumerate possible values.

> +
> +Example:
> +--------
> +
> +	// AM18xx
> +	pru_rproc: cpu@30000 {

cpu is reserved for cpu nodes.

> +		compatible = "ti,da850-pru-rproc";
> +		reg = <0x30000 0x10000>;
> +		interrupts = <3>, <4>;
> +		interrupt-names = "pru0-vq", "pru1-vq";
> +		power-domains = <&psc0 13>;
> +	};
> +
> +	// AM335x
> +	pru_rproc: cpu@4a300000 {
> +		compatible = "ti,am3352-pru-rproc";
> +		reg = <0x4a300000 0x80000>;
> +		interrupts = <20>, <21>;
> +		interrupt-names = "pru0-vq", "pru1-vq";
> +		ti,hwmods = "pruss";
> +	};

Really need 2 examples?

> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: New remoteproc driver for TI PRU
  2018-06-30  0:17     ` Suman Anna
@ 2018-08-06 16:32       ` David Lechner
  2018-08-07  1:39         ` Suman Anna
  0 siblings, 1 reply; 17+ messages in thread
From: David Lechner @ 2018-08-06 16:32 UTC (permalink / raw)
  To: Suman Anna, Roger Quadros, linux-remoteproc, devicetree,
	linux-omap, linux-arm-kernel
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Sekhar Nori, Kevin Hilman,
	linux-kernel, Tero Kristo

On 06/29/2018 07:17 PM, Suman Anna wrote:
> Hi David,
> 
> On 06/29/2018 12:44 PM, David Lechner wrote:
>> On 06/29/2018 04:58 AM, Roger Quadros wrote:
>>> +Suman & Tero
>>>
>>> Hi David,
>>>
>>> On 24/06/18 00:08, David Lechner wrote:
>>>>
>>>> Date: Sat, 23 Jun 2018 15:43:59 -0500
>>>> Subject: [PATCH 0/8] New remoteproc driver for TI PRU
>>>>
>>>> This series adds a new remoteproc driver for the TI Programmable
>>>> Runtime Unit
>>>> (PRU) that is present in some TI Sitara processors. This code has
>>>> been tested
>>>> working on AM1808 (LEGO MINDSTORMS EV3) and AM3358 (BeagleBone Green).
>>>
>>> This is great. We have been working on something similar and I think
>>> it would
>>> be great if we can collaborate to get all our needs addressed.
>>
>> Yes, I have used the PRU with the TI kernel on BeagleBone so I've seen
>> the TI
>> implementation. My primary interest is in the AM1808, which has a far
>> simpler
>> PRU than other SoCs. So, I was hoping I could get away with just
>> implementing
>> the basic stuff that I need and let TI add the more complex stuff later.
> 
> Thanks for the series. PRUSS is present on many SoCs now, and each with
> their own integration quirks, both in terms of SoC connections as well
> as internal sub-modules within the subsystem. We currently support
> AM335x, AM437x, AM57xx, Keystone 2 based 66AK2G and a newer generation
> AM65x as well. It should be relatively straight-forward to scale this
> for AM1808/OMAP-L138 as well. The move to the standard Common Clock and
> Reset frameworks for clocks with the Davinci chips should make it
> relatively straight-forward for the architecture pieces.
> 
> I will take a look at your series in detail sometime next week, and
> mostly post our series to the upstream lists as well within the next
> couple of weeks so that it is easier for discussion on the upstream lists.
> 

Have you had time to look at this yet? If you are too busy, I can submit
a v2 with the interrupt controller broken out into a separate driver.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: New remoteproc driver for TI PRU
  2018-08-06 16:32       ` David Lechner
@ 2018-08-07  1:39         ` Suman Anna
  0 siblings, 0 replies; 17+ messages in thread
From: Suman Anna @ 2018-08-07  1:39 UTC (permalink / raw)
  To: David Lechner, Roger Quadros, linux-remoteproc, devicetree,
	linux-omap, linux-arm-kernel
  Cc: Ohad Ben-Cohen, Bjorn Andersson, Rob Herring, Mark Rutland,
	Benoît Cousson, Tony Lindgren, Sekhar Nori, Kevin Hilman,
	linux-kernel, Tero Kristo

Hi David,

On 08/06/2018 11:32 AM, David Lechner wrote:
> On 06/29/2018 07:17 PM, Suman Anna wrote:
>> Hi David,
>>
>> On 06/29/2018 12:44 PM, David Lechner wrote:
>>> On 06/29/2018 04:58 AM, Roger Quadros wrote:
>>>> +Suman & Tero
>>>>
>>>> Hi David,
>>>>
>>>> On 24/06/18 00:08, David Lechner wrote:
>>>>>
>>>>> Date: Sat, 23 Jun 2018 15:43:59 -0500
>>>>> Subject: [PATCH 0/8] New remoteproc driver for TI PRU
>>>>>
>>>>> This series adds a new remoteproc driver for the TI Programmable
>>>>> Runtime Unit
>>>>> (PRU) that is present in some TI Sitara processors. This code has
>>>>> been tested
>>>>> working on AM1808 (LEGO MINDSTORMS EV3) and AM3358 (BeagleBone Green).
>>>>
>>>> This is great. We have been working on something similar and I think
>>>> it would
>>>> be great if we can collaborate to get all our needs addressed.
>>>
>>> Yes, I have used the PRU with the TI kernel on BeagleBone so I've seen
>>> the TI
>>> implementation. My primary interest is in the AM1808, which has a far
>>> simpler
>>> PRU than other SoCs. So, I was hoping I could get away with just
>>> implementing
>>> the basic stuff that I need and let TI add the more complex stuff later.
>>
>> Thanks for the series. PRUSS is present on many SoCs now, and each with
>> their own integration quirks, both in terms of SoC connections as well
>> as internal sub-modules within the subsystem. We currently support
>> AM335x, AM437x, AM57xx, Keystone 2 based 66AK2G and a newer generation
>> AM65x as well. It should be relatively straight-forward to scale this
>> for AM1808/OMAP-L138 as well. The move to the standard Common Clock and
>> Reset frameworks for clocks with the Davinci chips should make it
>> relatively straight-forward for the architecture pieces.
>>
>> I will take a look at your series in detail sometime next week, and
>> mostly post our series to the upstream lists as well within the next
>> couple of weeks so that it is easier for discussion on the upstream
>> lists.
>>
> 
> Have you had time to look at this yet? If you are too busy, I can submit
> a v2 with the interrupt controller broken out into a separate driver.

Yeah, I worked on it a bit around -rc4 time, but didn't get a chance to
complete the cleanup & testing before I had to shift to some other
tasks. If you are interested, I can share my branch. I will mostly get
back to this towards the latter half of next week. Anyway, I am
expecting 4.19-rc1 to be in a better shape w.r.t Davinci platform as the
genpd and CCF stuff comes in, and the pm_runtime usage for clocking in
my PRUSS drivers will fit well with those available.

regards
Suman



^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2018-08-07  1:40 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20180623210810.21232-1-david@lechnology.com>
2018-06-23 21:08 ` [PATCH 1/8] remoteproc: add map parameter to da_to_va David Lechner
2018-06-23 21:08 ` [PATCH 2/8] remoteproc: add page lookup for TI PRU to ELF loader David Lechner
2018-06-23 21:08 ` [PATCH 3/8] ARM: OMAP2+: add pdata quirks for PRUSS reset David Lechner
2018-06-23 21:08 ` [PATCH 4/8] dt-bindings: add bindings for TI PRU as remoteproc David Lechner
2018-07-03 20:59   ` Rob Herring
2018-06-23 21:08 ` [PATCH 5/8] remoteproc: new driver for TI PRU David Lechner
2018-06-29 10:14   ` Roger Quadros
     [not found]     ` <CA+CtpRhQ07=3UytY7QrfnpWkY06UqHbNVq099Coez3C4H3U5yg@mail.gmail.com>
2018-07-02  8:05       ` Roger Quadros
2018-06-23 21:08 ` [PATCH 6/8] ARM: davinci_all_defconfig: enable PRU remoteproc module David Lechner
2018-06-23 21:08 ` [PATCH 7/8] ARM: dts: da850: add node for PRUSS David Lechner
2018-06-23 21:08 ` [PATCH 8/8] ARM: dts: am33xx: add node for PRU remoteproc David Lechner
2018-06-29  9:58 ` New remoteproc driver for TI PRU Roger Quadros
2018-06-29 17:44   ` David Lechner
2018-06-30  0:17     ` Suman Anna
2018-08-06 16:32       ` David Lechner
2018-08-07  1:39         ` Suman Anna
2018-07-02  8:17     ` Roger Quadros

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).