All of lore.kernel.org
 help / color / mirror / Atom feed
From: Roger Quadros <rogerq@ti.com>
To: ohad@wizery.com, bjorn.andersson@linaro.org
Cc: tony@atomide.com, robh+dt@kernel.org, bcousson@baylibre.com,
	ssantosh@kernel.org, s-anna@ti.com, nsekhar@ti.com,
	t-kristo@ti.com, nsaulnier@ti.com, jreeder@ti.com,
	m-karicheri2@ti.com, woods.technical@gmail.com,
	linux-omap@vger.kernel.org, linux-remoteproc@vger.kernel.org,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	rogerq@ti.com
Subject: [PATCH 04/16] remoteproc/pru: Add PRU remoteproc driver
Date: Mon, 26 Nov 2018 09:52:37 +0200	[thread overview]
Message-ID: <1543218769-5507-5-git-send-email-rogerq@ti.com> (raw)
In-Reply-To: <1543218769-5507-1-git-send-email-rogerq@ti.com>

From: Suman Anna <s-anna@ti.com>

The Programmable Real-Time Unit Subsystem (PRUSS) consists of
dual 32-bit RISC cores (Programmable Real-Time Units, or PRUs)
for program execution. This patch adds a remoteproc platform
driver for managing the individual PRU RISC cores life cycle.

The PRU remoteproc driver uses the standard remoteproc core ELF
loader. However, the PRUs do not have a unified address space,
(has an Instruction RAM and a primary Data RAM at both 0x0) and
leverage an added .da_to_va ops to use the standard ELF loader.
This remoteproc driver does not have support for error recovery
and system suspend/resume features. Different compatibles are
used to allow providing scalability for instance-specific device
data if needed. The driver uses a default firmware-name retrieved
from device-tree, and the firmwares are expected to be present
in the standard Linux firmware search paths. They can also be
adjusted by userspace if required through the sysfs interface
provided by the remoteproc core.

The PRU remoteproc driver uses a client-driven boot methodology
- it does _not_ support auto-boot so that the PRU load and boot
is dictated by the corresponding client drivers for achieving
various usecases. This allows flexibility for the client drivers
or applications to set a firmware name (if needed) based on their
desired functionality and boot the PRU. The sysfs bind and unbind
attributes have also been suppressed so that the PRU devices cannot
be unbound and thereby shutdown a PRU from underneath a PRU client
driver.

The driver currently supports the AM335x SoC, and support for other
TI SoCs will be added in subsequent patches.

[rogerq@ti.com] Use request/release_mem_region()
[rogerq@ti.com] Strip INTC handling
Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Andrew F. Davis <afd@ti.com>
Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/remoteproc/Kconfig     |  14 ++
 drivers/remoteproc/Makefile    |   1 +
 drivers/remoteproc/pru_rproc.c | 392 +++++++++++++++++++++++++++++++++++++++++
 drivers/remoteproc/pru_rproc.h |  65 +++++++
 4 files changed, 472 insertions(+)
 create mode 100644 drivers/remoteproc/pru_rproc.c
 create mode 100644 drivers/remoteproc/pru_rproc.h

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index f0abd26..333666e 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -197,6 +197,20 @@ config ST_REMOTEPROC
 config ST_SLIM_REMOTEPROC
 	tristate
 
+config PRUSS_REMOTEPROC
+	tristate "TI PRUSS remoteproc support"
+	depends on TI_PRUSS
+	default n
+	help
+	  Support for TI PRU-ICSS remote processors via the remote processor
+	  framework.
+
+	  Currently supported on AM33xx SoCs.
+
+	  Say Y or M here to support the Programmable Realtime Unit (PRU)
+	  processors on various TI SoCs. It's safe to say N here if you're
+	  not interested in the PRU or if you are unsure.
+
 endif # REMOTEPROC
 
 endmenu
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index ce5d061..88a86cc 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -26,3 +26,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_PRUSS_REMOTEPROC)		+= pru_rproc.o
diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
new file mode 100644
index 0000000..c35f432
--- /dev/null
+++ b/drivers/remoteproc/pru_rproc.c
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PRU-ICSS remoteproc driver for various TI SoCs
+ *
+ * Copyright (C) 2014-2018 Texas Instruments Incorporated - http://www.ti.com/
+ *	Suman Anna <s-anna@ti.com>
+ *	Andrew F. Davis <afd@ti.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/remoteproc.h>
+#include <linux/pruss.h>
+
+#include "remoteproc_internal.h"
+#include "pru_rproc.h"
+
+/* PRU_ICSS_PRU_CTRL registers */
+#define PRU_CTRL_CTRL		0x0000
+#define PRU_CTRL_STS		0x0004
+#define PRU_CTRL_WAKEUP_EN	0x0008
+#define PRU_CTRL_CYCLE		0x000C
+#define PRU_CTRL_STALL		0x0010
+#define PRU_CTRL_CTBIR0		0x0020
+#define PRU_CTRL_CTBIR1		0x0024
+#define PRU_CTRL_CTPPR0		0x0028
+#define PRU_CTRL_CTPPR1		0x002C
+
+/* CTRL register bit-fields */
+#define CTRL_CTRL_SOFT_RST_N	BIT(0)
+#define CTRL_CTRL_EN		BIT(1)
+#define CTRL_CTRL_SLEEPING	BIT(2)
+#define CTRL_CTRL_CTR_EN	BIT(3)
+#define CTRL_CTRL_SINGLE_STEP	BIT(8)
+#define CTRL_CTRL_RUNSTATE	BIT(15)
+
+/**
+ * enum pru_mem - PRU core memory range identifiers
+ */
+enum pru_mem {
+	PRU_MEM_IRAM = 0,
+	PRU_MEM_CTRL,
+	PRU_MEM_DEBUG,
+	PRU_MEM_MAX,
+};
+
+/**
+ * struct pru_rproc - PRU remoteproc structure
+ * @id: id of the PRU core within the PRUSS
+ * @pruss: back-reference to parent PRUSS structure
+ * @rproc: remoteproc pointer for this PRU core
+ * @mem_regions: data for each of the PRU memory regions
+ * @dram0: PRUSS DRAM0 region
+ * @dram1: PRUSS DRAM1 region
+ * @shrdram: PRUSS SHARED RAM region
+ * @iram_da: device address of Instruction RAM for this PRU
+ * @pdram_da: device address of primary Data RAM for this PRU
+ * @sdram_da: device address of secondary Data RAM for this PRU
+ * @shrdram_da: device address of shared Data RAM
+ * @fw_name: name of firmware image used during loading
+ */
+struct pru_rproc {
+	int id;
+	struct pruss *pruss;
+	struct rproc *rproc;
+	struct pruss_mem_region mem_regions[PRU_MEM_MAX];
+	struct pruss_mem_region dram0;
+	struct pruss_mem_region dram1;
+	struct pruss_mem_region shrdram;
+	u32 iram_da;
+	u32 pdram_da;
+	u32 sdram_da;
+	u32 shrdram_da;
+	const char *fw_name;
+};
+
+static void *pru_d_da_to_va(struct pru_rproc *pru, u32 da, int len);
+
+static inline u32 pru_control_read_reg(struct pru_rproc *pru, unsigned int reg)
+{
+	return readl_relaxed(pru->mem_regions[PRU_MEM_CTRL].va + reg);
+}
+
+static inline
+void pru_control_write_reg(struct pru_rproc *pru, unsigned int reg, u32 val)
+{
+	writel_relaxed(val, pru->mem_regions[PRU_MEM_CTRL].va + reg);
+}
+
+static inline u32 pru_debug_read_reg(struct pru_rproc *pru, unsigned int reg)
+{
+	return readl_relaxed(pru->mem_regions[PRU_MEM_DEBUG].va + reg);
+}
+
+static inline
+void pru_debug_write_reg(struct pru_rproc *pru, unsigned int reg, u32 val)
+{
+	writel_relaxed(val, pru->mem_regions[PRU_MEM_DEBUG].va + reg);
+}
+
+/* start a PRU core */
+static int pru_rproc_start(struct rproc *rproc)
+{
+	struct device *dev = &rproc->dev;
+	struct pru_rproc *pru = rproc->priv;
+	u32 val;
+
+	dev_dbg(dev, "starting PRU%d: entry-point = 0x%x\n",
+		pru->id, (rproc->bootaddr >> 2));
+
+	val = CTRL_CTRL_EN | ((rproc->bootaddr >> 2) << 16);
+	pru_control_write_reg(pru, PRU_CTRL_CTRL, val);
+
+	/* TODO: INTC setup */
+
+	return 0;
+}
+
+/* stop/disable a PRU core */
+static int pru_rproc_stop(struct rproc *rproc)
+{
+	struct device *dev = &rproc->dev;
+	struct pru_rproc *pru = rproc->priv;
+	u32 val;
+
+	dev_dbg(dev, "stopping PRU%d\n", pru->id);
+
+	val = pru_control_read_reg(pru, PRU_CTRL_CTRL);
+	val &= ~CTRL_CTRL_EN;
+	pru_control_write_reg(pru, PRU_CTRL_CTRL, val);
+
+	/* TODO: INTC cleanup */
+
+	return 0;
+}
+
+/*
+ * Convert PRU device address (data spaces only) to kernel virtual address
+ *
+ * Each PRU has access to all data memories within the PRUSS, accessible at
+ * different ranges. So, look through both its primary and secondary Data
+ * RAMs as well as any shared Data RAM to convert a PRU device address to
+ * kernel virtual address. Data RAM0 is primary Data RAM for PRU0 and Data
+ * RAM1 is primary Data RAM for PRU1.
+ */
+static void *pru_d_da_to_va(struct pru_rproc *pru, u32 da, int len)
+{
+	struct pruss_mem_region dram0, dram1, shrd_ram;
+	u32 offset;
+	void *va = NULL;
+
+	if (len <= 0)
+		return NULL;
+
+	dram0 = pru->dram0;
+	dram1 = pru->dram1;
+	/* PRU1 has its local RAM addresses reversed */
+	if (pru->id == 1)
+		swap(dram0, dram1);
+	shrd_ram = pru->shrdram;
+
+	if (da >= pru->pdram_da && da + len <= pru->pdram_da + dram0.size) {
+		offset = da - pru->pdram_da;
+		va = (__force void *)(dram0.va + offset);
+	} else if (da >= pru->sdram_da &&
+		   da + len <= pru->sdram_da + dram1.size) {
+		offset = da - pru->sdram_da;
+		va = (__force void *)(dram1.va + offset);
+	} else if (da >= pru->shrdram_da &&
+		   da + len <= pru->shrdram_da + shrd_ram.size) {
+		offset = da - pru->shrdram_da;
+		va = (__force void *)(shrd_ram.va + offset);
+	}
+
+	return va;
+}
+
+/*
+ * Convert PRU device address (instruction space) to kernel virtual address
+ *
+ * A PRU does not have an unified address space. Each PRU has its very own
+ * private Instruction RAM, and its device address is identical to that of
+ * its primary Data RAM device address.
+ */
+static void *pru_i_da_to_va(struct pru_rproc *pru, u32 da, int len)
+{
+	u32 offset;
+	void *va = NULL;
+
+	if (len <= 0)
+		return NULL;
+
+	if (da >= pru->iram_da &&
+	    da + len <= pru->iram_da + pru->mem_regions[PRU_MEM_IRAM].size) {
+		offset = da - pru->iram_da;
+		va = (__force void *)(pru->mem_regions[PRU_MEM_IRAM].va +
+				      offset);
+	}
+
+	return va;
+}
+
+/* PRU-specific address translator */
+static void *pru_da_to_va(struct rproc *rproc, u64 da, int len, u32 flags)
+{
+	struct pru_rproc *pru = rproc->priv;
+	void *va;
+	u32 exec_flag;
+
+	exec_flag = ((flags & RPROC_FLAGS_ELF_SHDR) ? flags & SHF_EXECINSTR :
+		     ((flags & RPROC_FLAGS_ELF_PHDR) ? flags & PF_X : 0));
+
+	if (exec_flag)
+		va = pru_i_da_to_va(pru, da, len);
+	else
+		va = pru_d_da_to_va(pru, da, len);
+
+	return va;
+}
+
+static struct rproc_ops pru_rproc_ops = {
+	.start			= pru_rproc_start,
+	.stop			= pru_rproc_stop,
+	.da_to_va		= pru_da_to_va,
+};
+
+static int pru_rproc_set_id(struct pru_rproc *pru)
+{
+	int ret = 0;
+	u32 mask1 = 0x34000;
+	u32 mask2 = 0x38000;
+
+	if ((pru->mem_regions[0].pa & mask1) == mask1)
+		pru->id = 0;
+	else if ((pru->mem_regions[0].pa & mask2) == mask2)
+		pru->id = 1;
+	else
+		ret = -EINVAL;
+
+	return ret;
+}
+
+static int pru_rproc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct platform_device *ppdev = to_platform_device(dev->parent);
+	struct pru_rproc *pru;
+	const char *fw_name;
+	struct rproc *rproc = NULL;
+	struct resource *res;
+	int i, ret;
+	const char *mem_names[PRU_MEM_MAX] = { "iram", "control", "debug" };
+
+	if (!np) {
+		dev_err(dev, "Non-DT platform device not supported\n");
+		return -ENODEV;
+	}
+
+	ret = of_property_read_string(np, "firmware-name", &fw_name);
+	if (ret) {
+		dev_err(dev, "unable to retrieve firmware-name %d\n", ret);
+		return ret;
+	}
+
+	rproc = rproc_alloc(dev, pdev->name, &pru_rproc_ops, fw_name,
+			    sizeof(*pru));
+	if (!rproc) {
+		dev_err(dev, "rproc_alloc failed\n");
+		return -ENOMEM;
+	}
+	/* error recovery is not supported for PRUs */
+	rproc->recovery_disabled = true;
+
+	/*
+	 * rproc_add will auto-boot the processor normally, but this is
+	 * not desired with PRU client driven boot-flow methodology. A PRU
+	 * application/client driver will boot the corresponding PRU
+	 * remote-processor as part of its state machine either through
+	 * the remoteproc sysfs interface or through the equivalent kernel API
+	 */
+	rproc->auto_boot = false;
+
+	pru = rproc->priv;
+	pru->pruss = platform_get_drvdata(ppdev);
+	pru->rproc = rproc;
+	pru->fw_name = fw_name;
+
+	ret = pruss_request_mem_region(pru->pruss, PRUSS_MEM_DRAM0,
+				       &pru->dram0);
+	if (ret) {
+		dev_err(dev, "couldn't get PRUSS DRAM0: %d\n", ret);
+		return ret;
+	}
+	pruss_release_mem_region(pru->pruss, &pru->dram0);
+
+	ret = pruss_request_mem_region(pru->pruss, PRUSS_MEM_DRAM1,
+				       &pru->dram1);
+	if (ret) {
+		dev_err(dev, "couldn't get PRUSS DRAM1: %d\n", ret);
+		return ret;
+	}
+	pruss_release_mem_region(pru->pruss, &pru->dram1);
+
+	ret = pruss_request_mem_region(pru->pruss, PRUSS_MEM_SHRD_RAM2,
+				       &pru->shrdram);
+	if (ret) {
+		dev_err(dev, "couldn't get PRUSS Shared RAM: %d\n", ret);
+		return ret;
+	}
+	pruss_release_mem_region(pru->pruss, &pru->shrdram);
+
+	/* XXX: get this from match data if different in the future */
+	pru->iram_da = 0;
+	pru->pdram_da = 0;
+	pru->sdram_da = 0x2000;
+	pru->shrdram_da = 0x10000;
+
+	for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						   mem_names[i]);
+		pru->mem_regions[i].va = devm_ioremap_resource(dev, res);
+		if (IS_ERR(pru->mem_regions[i].va)) {
+			dev_err(dev, "failed to parse and map memory resource %d %s\n",
+				i, mem_names[i]);
+			ret = PTR_ERR(pru->mem_regions[i].va);
+			goto free_rproc;
+		}
+		pru->mem_regions[i].pa = res->start;
+		pru->mem_regions[i].size = resource_size(res);
+
+		dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %p\n",
+			mem_names[i], &pru->mem_regions[i].pa,
+			pru->mem_regions[i].size, pru->mem_regions[i].va);
+	}
+
+	ret = pru_rproc_set_id(pru);
+	if (ret < 0)
+		goto free_rproc;
+
+	platform_set_drvdata(pdev, rproc);
+
+	ret = rproc_add(pru->rproc);
+	if (ret) {
+		dev_err(dev, "rproc_add failed: %d\n", ret);
+		goto free_rproc;
+	}
+
+	dev_info(dev, "PRU rproc node %s probed successfully\n", np->full_name);
+
+	return 0;
+
+free_rproc:
+	rproc_free(rproc);
+	return ret;
+}
+
+static int pru_rproc_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rproc *rproc = platform_get_drvdata(pdev);
+
+	dev_info(dev, "%s: removing rproc %s\n", __func__, rproc->name);
+
+	rproc_del(rproc);
+	rproc_free(rproc);
+
+	return 0;
+}
+
+static const struct of_device_id pru_rproc_match[] = {
+	{ .compatible = "ti,am3356-pru", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pru_rproc_match);
+
+static struct platform_driver pru_rproc_driver = {
+	.driver = {
+		.name   = "pru-rproc",
+		.of_match_table = pru_rproc_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe  = pru_rproc_probe,
+	.remove = pru_rproc_remove,
+};
+module_platform_driver(pru_rproc_driver);
+
+MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");
+MODULE_DESCRIPTION("PRU-ICSS Remote Processor Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/remoteproc/pru_rproc.h b/drivers/remoteproc/pru_rproc.h
new file mode 100644
index 0000000..35240e9
--- /dev/null
+++ b/drivers/remoteproc/pru_rproc.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * PRUSS Remote Processor specific types
+ *
+ * Copyright (C) 2014-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * All rights reserved.
+ */
+
+#ifndef _PRU_REMOTEPROC_H_
+#define _PRU_REMOTEPROC_H_
+
+/**
+ * enum pruss_rsc_types - PRU specific resource types
+ *
+ * @PRUSS_RSC_INTRS: Resource holding information on PRU PINTC configuration
+ * @PRUSS_RSC_MAX: Indicates end of known/defined PRU resource types.
+ *		   This should be the last definition.
+ *
+ * Introduce new custom resource types before PRUSS_RSC_MAX.
+ */
+enum pruss_rsc_types {
+	PRUSS_RSC_INTRS	= 1,
+	PRUSS_RSC_MAX	= 2,
+};
+
+/**
+ * struct pruss_event_chnl - PRU system events _to_ channel mapping
+ * @event: number of the system event
+ * @chnl: channel number assigned to a given @event
+ *
+ * PRU system events are mapped to channels, and these channels are mapped
+ * to host interrupts. Events can be mapped to channels in a one-to-one or
+ * many-to-one ratio (multiple events per channel), and channels can be
+ * mapped to host interrupts in a one-to-one or many-to-one ratio (multiple
+ * channels per interrupt).
+ *
+ */
+struct pruss_event_chnl {
+	s8 event;
+	s8 chnl;
+};
+
+/**
+ * struct fw_rsc_custom_intrmap - custom resource to define PRU interrupts
+ * @reserved: reserved field providing padding and alignment
+ * @chnl_host_intr_map: array of PRU channels to host interrupt mappings
+ * @event_chnl_map_size: number of event_channel mappings defined in
+ *			 @event_chnl_map_addr
+ * @event_chnl_map_addr: PRU device address of pointer to array of events to
+ *			 channel mappings (struct pruss_event_chnl elements)
+ *
+ * PRU system events are mapped to channels, and these channels are mapped
+ * to host interrupts. Events can be mapped to channels in a one-to-one or
+ * many-to-one ratio (multiple events per channel), and channels can be
+ * mapped to host interrupts in a one-to-one or many-to-one ratio (multiple
+ * channels per interrupt).
+ */
+struct fw_rsc_custom_intrmap {
+	u16 reserved;
+	s8 chnl_host_intr_map[10];
+	u32 event_chnl_map_size;
+	u32 event_chnl_map_addr;
+};
+
+#endif	/* _PRU_REMOTEPROC_H_ */
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

WARNING: multiple messages have this Message-ID (diff)
From: Roger Quadros <rogerq@ti.com>
To: <ohad@wizery.com>, <bjorn.andersson@linaro.org>
Cc: <tony@atomide.com>, <robh+dt@kernel.org>, <bcousson@baylibre.com>,
	<ssantosh@kernel.org>, <s-anna@ti.com>, <nsekhar@ti.com>,
	<t-kristo@ti.com>, <nsaulnier@ti.com>, <jreeder@ti.com>,
	<m-karicheri2@ti.com>, <woods.technical@gmail.com>,
	<linux-omap@vger.kernel.org>, <linux-remoteproc@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>, <devicetree@vger.kernel.org>,
	<rogerq@ti.com>
Subject: [PATCH 04/16] remoteproc/pru: Add PRU remoteproc driver
Date: Mon, 26 Nov 2018 09:52:37 +0200	[thread overview]
Message-ID: <1543218769-5507-5-git-send-email-rogerq@ti.com> (raw)
In-Reply-To: <1543218769-5507-1-git-send-email-rogerq@ti.com>

From: Suman Anna <s-anna@ti.com>

The Programmable Real-Time Unit Subsystem (PRUSS) consists of
dual 32-bit RISC cores (Programmable Real-Time Units, or PRUs)
for program execution. This patch adds a remoteproc platform
driver for managing the individual PRU RISC cores life cycle.

The PRU remoteproc driver uses the standard remoteproc core ELF
loader. However, the PRUs do not have a unified address space,
(has an Instruction RAM and a primary Data RAM at both 0x0) and
leverage an added .da_to_va ops to use the standard ELF loader.
This remoteproc driver does not have support for error recovery
and system suspend/resume features. Different compatibles are
used to allow providing scalability for instance-specific device
data if needed. The driver uses a default firmware-name retrieved
from device-tree, and the firmwares are expected to be present
in the standard Linux firmware search paths. They can also be
adjusted by userspace if required through the sysfs interface
provided by the remoteproc core.

The PRU remoteproc driver uses a client-driven boot methodology
- it does _not_ support auto-boot so that the PRU load and boot
is dictated by the corresponding client drivers for achieving
various usecases. This allows flexibility for the client drivers
or applications to set a firmware name (if needed) based on their
desired functionality and boot the PRU. The sysfs bind and unbind
attributes have also been suppressed so that the PRU devices cannot
be unbound and thereby shutdown a PRU from underneath a PRU client
driver.

The driver currently supports the AM335x SoC, and support for other
TI SoCs will be added in subsequent patches.

[rogerq@ti.com] Use request/release_mem_region()
[rogerq@ti.com] Strip INTC handling
Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Andrew F. Davis <afd@ti.com>
Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/remoteproc/Kconfig     |  14 ++
 drivers/remoteproc/Makefile    |   1 +
 drivers/remoteproc/pru_rproc.c | 392 +++++++++++++++++++++++++++++++++++++++++
 drivers/remoteproc/pru_rproc.h |  65 +++++++
 4 files changed, 472 insertions(+)
 create mode 100644 drivers/remoteproc/pru_rproc.c
 create mode 100644 drivers/remoteproc/pru_rproc.h

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index f0abd26..333666e 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -197,6 +197,20 @@ config ST_REMOTEPROC
 config ST_SLIM_REMOTEPROC
 	tristate
 
+config PRUSS_REMOTEPROC
+	tristate "TI PRUSS remoteproc support"
+	depends on TI_PRUSS
+	default n
+	help
+	  Support for TI PRU-ICSS remote processors via the remote processor
+	  framework.
+
+	  Currently supported on AM33xx SoCs.
+
+	  Say Y or M here to support the Programmable Realtime Unit (PRU)
+	  processors on various TI SoCs. It's safe to say N here if you're
+	  not interested in the PRU or if you are unsure.
+
 endif # REMOTEPROC
 
 endmenu
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index ce5d061..88a86cc 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -26,3 +26,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_PRUSS_REMOTEPROC)		+= pru_rproc.o
diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
new file mode 100644
index 0000000..c35f432
--- /dev/null
+++ b/drivers/remoteproc/pru_rproc.c
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PRU-ICSS remoteproc driver for various TI SoCs
+ *
+ * Copyright (C) 2014-2018 Texas Instruments Incorporated - http://www.ti.com/
+ *	Suman Anna <s-anna@ti.com>
+ *	Andrew F. Davis <afd@ti.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/remoteproc.h>
+#include <linux/pruss.h>
+
+#include "remoteproc_internal.h"
+#include "pru_rproc.h"
+
+/* PRU_ICSS_PRU_CTRL registers */
+#define PRU_CTRL_CTRL		0x0000
+#define PRU_CTRL_STS		0x0004
+#define PRU_CTRL_WAKEUP_EN	0x0008
+#define PRU_CTRL_CYCLE		0x000C
+#define PRU_CTRL_STALL		0x0010
+#define PRU_CTRL_CTBIR0		0x0020
+#define PRU_CTRL_CTBIR1		0x0024
+#define PRU_CTRL_CTPPR0		0x0028
+#define PRU_CTRL_CTPPR1		0x002C
+
+/* CTRL register bit-fields */
+#define CTRL_CTRL_SOFT_RST_N	BIT(0)
+#define CTRL_CTRL_EN		BIT(1)
+#define CTRL_CTRL_SLEEPING	BIT(2)
+#define CTRL_CTRL_CTR_EN	BIT(3)
+#define CTRL_CTRL_SINGLE_STEP	BIT(8)
+#define CTRL_CTRL_RUNSTATE	BIT(15)
+
+/**
+ * enum pru_mem - PRU core memory range identifiers
+ */
+enum pru_mem {
+	PRU_MEM_IRAM = 0,
+	PRU_MEM_CTRL,
+	PRU_MEM_DEBUG,
+	PRU_MEM_MAX,
+};
+
+/**
+ * struct pru_rproc - PRU remoteproc structure
+ * @id: id of the PRU core within the PRUSS
+ * @pruss: back-reference to parent PRUSS structure
+ * @rproc: remoteproc pointer for this PRU core
+ * @mem_regions: data for each of the PRU memory regions
+ * @dram0: PRUSS DRAM0 region
+ * @dram1: PRUSS DRAM1 region
+ * @shrdram: PRUSS SHARED RAM region
+ * @iram_da: device address of Instruction RAM for this PRU
+ * @pdram_da: device address of primary Data RAM for this PRU
+ * @sdram_da: device address of secondary Data RAM for this PRU
+ * @shrdram_da: device address of shared Data RAM
+ * @fw_name: name of firmware image used during loading
+ */
+struct pru_rproc {
+	int id;
+	struct pruss *pruss;
+	struct rproc *rproc;
+	struct pruss_mem_region mem_regions[PRU_MEM_MAX];
+	struct pruss_mem_region dram0;
+	struct pruss_mem_region dram1;
+	struct pruss_mem_region shrdram;
+	u32 iram_da;
+	u32 pdram_da;
+	u32 sdram_da;
+	u32 shrdram_da;
+	const char *fw_name;
+};
+
+static void *pru_d_da_to_va(struct pru_rproc *pru, u32 da, int len);
+
+static inline u32 pru_control_read_reg(struct pru_rproc *pru, unsigned int reg)
+{
+	return readl_relaxed(pru->mem_regions[PRU_MEM_CTRL].va + reg);
+}
+
+static inline
+void pru_control_write_reg(struct pru_rproc *pru, unsigned int reg, u32 val)
+{
+	writel_relaxed(val, pru->mem_regions[PRU_MEM_CTRL].va + reg);
+}
+
+static inline u32 pru_debug_read_reg(struct pru_rproc *pru, unsigned int reg)
+{
+	return readl_relaxed(pru->mem_regions[PRU_MEM_DEBUG].va + reg);
+}
+
+static inline
+void pru_debug_write_reg(struct pru_rproc *pru, unsigned int reg, u32 val)
+{
+	writel_relaxed(val, pru->mem_regions[PRU_MEM_DEBUG].va + reg);
+}
+
+/* start a PRU core */
+static int pru_rproc_start(struct rproc *rproc)
+{
+	struct device *dev = &rproc->dev;
+	struct pru_rproc *pru = rproc->priv;
+	u32 val;
+
+	dev_dbg(dev, "starting PRU%d: entry-point = 0x%x\n",
+		pru->id, (rproc->bootaddr >> 2));
+
+	val = CTRL_CTRL_EN | ((rproc->bootaddr >> 2) << 16);
+	pru_control_write_reg(pru, PRU_CTRL_CTRL, val);
+
+	/* TODO: INTC setup */
+
+	return 0;
+}
+
+/* stop/disable a PRU core */
+static int pru_rproc_stop(struct rproc *rproc)
+{
+	struct device *dev = &rproc->dev;
+	struct pru_rproc *pru = rproc->priv;
+	u32 val;
+
+	dev_dbg(dev, "stopping PRU%d\n", pru->id);
+
+	val = pru_control_read_reg(pru, PRU_CTRL_CTRL);
+	val &= ~CTRL_CTRL_EN;
+	pru_control_write_reg(pru, PRU_CTRL_CTRL, val);
+
+	/* TODO: INTC cleanup */
+
+	return 0;
+}
+
+/*
+ * Convert PRU device address (data spaces only) to kernel virtual address
+ *
+ * Each PRU has access to all data memories within the PRUSS, accessible at
+ * different ranges. So, look through both its primary and secondary Data
+ * RAMs as well as any shared Data RAM to convert a PRU device address to
+ * kernel virtual address. Data RAM0 is primary Data RAM for PRU0 and Data
+ * RAM1 is primary Data RAM for PRU1.
+ */
+static void *pru_d_da_to_va(struct pru_rproc *pru, u32 da, int len)
+{
+	struct pruss_mem_region dram0, dram1, shrd_ram;
+	u32 offset;
+	void *va = NULL;
+
+	if (len <= 0)
+		return NULL;
+
+	dram0 = pru->dram0;
+	dram1 = pru->dram1;
+	/* PRU1 has its local RAM addresses reversed */
+	if (pru->id == 1)
+		swap(dram0, dram1);
+	shrd_ram = pru->shrdram;
+
+	if (da >= pru->pdram_da && da + len <= pru->pdram_da + dram0.size) {
+		offset = da - pru->pdram_da;
+		va = (__force void *)(dram0.va + offset);
+	} else if (da >= pru->sdram_da &&
+		   da + len <= pru->sdram_da + dram1.size) {
+		offset = da - pru->sdram_da;
+		va = (__force void *)(dram1.va + offset);
+	} else if (da >= pru->shrdram_da &&
+		   da + len <= pru->shrdram_da + shrd_ram.size) {
+		offset = da - pru->shrdram_da;
+		va = (__force void *)(shrd_ram.va + offset);
+	}
+
+	return va;
+}
+
+/*
+ * Convert PRU device address (instruction space) to kernel virtual address
+ *
+ * A PRU does not have an unified address space. Each PRU has its very own
+ * private Instruction RAM, and its device address is identical to that of
+ * its primary Data RAM device address.
+ */
+static void *pru_i_da_to_va(struct pru_rproc *pru, u32 da, int len)
+{
+	u32 offset;
+	void *va = NULL;
+
+	if (len <= 0)
+		return NULL;
+
+	if (da >= pru->iram_da &&
+	    da + len <= pru->iram_da + pru->mem_regions[PRU_MEM_IRAM].size) {
+		offset = da - pru->iram_da;
+		va = (__force void *)(pru->mem_regions[PRU_MEM_IRAM].va +
+				      offset);
+	}
+
+	return va;
+}
+
+/* PRU-specific address translator */
+static void *pru_da_to_va(struct rproc *rproc, u64 da, int len, u32 flags)
+{
+	struct pru_rproc *pru = rproc->priv;
+	void *va;
+	u32 exec_flag;
+
+	exec_flag = ((flags & RPROC_FLAGS_ELF_SHDR) ? flags & SHF_EXECINSTR :
+		     ((flags & RPROC_FLAGS_ELF_PHDR) ? flags & PF_X : 0));
+
+	if (exec_flag)
+		va = pru_i_da_to_va(pru, da, len);
+	else
+		va = pru_d_da_to_va(pru, da, len);
+
+	return va;
+}
+
+static struct rproc_ops pru_rproc_ops = {
+	.start			= pru_rproc_start,
+	.stop			= pru_rproc_stop,
+	.da_to_va		= pru_da_to_va,
+};
+
+static int pru_rproc_set_id(struct pru_rproc *pru)
+{
+	int ret = 0;
+	u32 mask1 = 0x34000;
+	u32 mask2 = 0x38000;
+
+	if ((pru->mem_regions[0].pa & mask1) == mask1)
+		pru->id = 0;
+	else if ((pru->mem_regions[0].pa & mask2) == mask2)
+		pru->id = 1;
+	else
+		ret = -EINVAL;
+
+	return ret;
+}
+
+static int pru_rproc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct platform_device *ppdev = to_platform_device(dev->parent);
+	struct pru_rproc *pru;
+	const char *fw_name;
+	struct rproc *rproc = NULL;
+	struct resource *res;
+	int i, ret;
+	const char *mem_names[PRU_MEM_MAX] = { "iram", "control", "debug" };
+
+	if (!np) {
+		dev_err(dev, "Non-DT platform device not supported\n");
+		return -ENODEV;
+	}
+
+	ret = of_property_read_string(np, "firmware-name", &fw_name);
+	if (ret) {
+		dev_err(dev, "unable to retrieve firmware-name %d\n", ret);
+		return ret;
+	}
+
+	rproc = rproc_alloc(dev, pdev->name, &pru_rproc_ops, fw_name,
+			    sizeof(*pru));
+	if (!rproc) {
+		dev_err(dev, "rproc_alloc failed\n");
+		return -ENOMEM;
+	}
+	/* error recovery is not supported for PRUs */
+	rproc->recovery_disabled = true;
+
+	/*
+	 * rproc_add will auto-boot the processor normally, but this is
+	 * not desired with PRU client driven boot-flow methodology. A PRU
+	 * application/client driver will boot the corresponding PRU
+	 * remote-processor as part of its state machine either through
+	 * the remoteproc sysfs interface or through the equivalent kernel API
+	 */
+	rproc->auto_boot = false;
+
+	pru = rproc->priv;
+	pru->pruss = platform_get_drvdata(ppdev);
+	pru->rproc = rproc;
+	pru->fw_name = fw_name;
+
+	ret = pruss_request_mem_region(pru->pruss, PRUSS_MEM_DRAM0,
+				       &pru->dram0);
+	if (ret) {
+		dev_err(dev, "couldn't get PRUSS DRAM0: %d\n", ret);
+		return ret;
+	}
+	pruss_release_mem_region(pru->pruss, &pru->dram0);
+
+	ret = pruss_request_mem_region(pru->pruss, PRUSS_MEM_DRAM1,
+				       &pru->dram1);
+	if (ret) {
+		dev_err(dev, "couldn't get PRUSS DRAM1: %d\n", ret);
+		return ret;
+	}
+	pruss_release_mem_region(pru->pruss, &pru->dram1);
+
+	ret = pruss_request_mem_region(pru->pruss, PRUSS_MEM_SHRD_RAM2,
+				       &pru->shrdram);
+	if (ret) {
+		dev_err(dev, "couldn't get PRUSS Shared RAM: %d\n", ret);
+		return ret;
+	}
+	pruss_release_mem_region(pru->pruss, &pru->shrdram);
+
+	/* XXX: get this from match data if different in the future */
+	pru->iram_da = 0;
+	pru->pdram_da = 0;
+	pru->sdram_da = 0x2000;
+	pru->shrdram_da = 0x10000;
+
+	for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						   mem_names[i]);
+		pru->mem_regions[i].va = devm_ioremap_resource(dev, res);
+		if (IS_ERR(pru->mem_regions[i].va)) {
+			dev_err(dev, "failed to parse and map memory resource %d %s\n",
+				i, mem_names[i]);
+			ret = PTR_ERR(pru->mem_regions[i].va);
+			goto free_rproc;
+		}
+		pru->mem_regions[i].pa = res->start;
+		pru->mem_regions[i].size = resource_size(res);
+
+		dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %p\n",
+			mem_names[i], &pru->mem_regions[i].pa,
+			pru->mem_regions[i].size, pru->mem_regions[i].va);
+	}
+
+	ret = pru_rproc_set_id(pru);
+	if (ret < 0)
+		goto free_rproc;
+
+	platform_set_drvdata(pdev, rproc);
+
+	ret = rproc_add(pru->rproc);
+	if (ret) {
+		dev_err(dev, "rproc_add failed: %d\n", ret);
+		goto free_rproc;
+	}
+
+	dev_info(dev, "PRU rproc node %s probed successfully\n", np->full_name);
+
+	return 0;
+
+free_rproc:
+	rproc_free(rproc);
+	return ret;
+}
+
+static int pru_rproc_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rproc *rproc = platform_get_drvdata(pdev);
+
+	dev_info(dev, "%s: removing rproc %s\n", __func__, rproc->name);
+
+	rproc_del(rproc);
+	rproc_free(rproc);
+
+	return 0;
+}
+
+static const struct of_device_id pru_rproc_match[] = {
+	{ .compatible = "ti,am3356-pru", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pru_rproc_match);
+
+static struct platform_driver pru_rproc_driver = {
+	.driver = {
+		.name   = "pru-rproc",
+		.of_match_table = pru_rproc_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe  = pru_rproc_probe,
+	.remove = pru_rproc_remove,
+};
+module_platform_driver(pru_rproc_driver);
+
+MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");
+MODULE_DESCRIPTION("PRU-ICSS Remote Processor Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/remoteproc/pru_rproc.h b/drivers/remoteproc/pru_rproc.h
new file mode 100644
index 0000000..35240e9
--- /dev/null
+++ b/drivers/remoteproc/pru_rproc.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * PRUSS Remote Processor specific types
+ *
+ * Copyright (C) 2014-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * All rights reserved.
+ */
+
+#ifndef _PRU_REMOTEPROC_H_
+#define _PRU_REMOTEPROC_H_
+
+/**
+ * enum pruss_rsc_types - PRU specific resource types
+ *
+ * @PRUSS_RSC_INTRS: Resource holding information on PRU PINTC configuration
+ * @PRUSS_RSC_MAX: Indicates end of known/defined PRU resource types.
+ *		   This should be the last definition.
+ *
+ * Introduce new custom resource types before PRUSS_RSC_MAX.
+ */
+enum pruss_rsc_types {
+	PRUSS_RSC_INTRS	= 1,
+	PRUSS_RSC_MAX	= 2,
+};
+
+/**
+ * struct pruss_event_chnl - PRU system events _to_ channel mapping
+ * @event: number of the system event
+ * @chnl: channel number assigned to a given @event
+ *
+ * PRU system events are mapped to channels, and these channels are mapped
+ * to host interrupts. Events can be mapped to channels in a one-to-one or
+ * many-to-one ratio (multiple events per channel), and channels can be
+ * mapped to host interrupts in a one-to-one or many-to-one ratio (multiple
+ * channels per interrupt).
+ *
+ */
+struct pruss_event_chnl {
+	s8 event;
+	s8 chnl;
+};
+
+/**
+ * struct fw_rsc_custom_intrmap - custom resource to define PRU interrupts
+ * @reserved: reserved field providing padding and alignment
+ * @chnl_host_intr_map: array of PRU channels to host interrupt mappings
+ * @event_chnl_map_size: number of event_channel mappings defined in
+ *			 @event_chnl_map_addr
+ * @event_chnl_map_addr: PRU device address of pointer to array of events to
+ *			 channel mappings (struct pruss_event_chnl elements)
+ *
+ * PRU system events are mapped to channels, and these channels are mapped
+ * to host interrupts. Events can be mapped to channels in a one-to-one or
+ * many-to-one ratio (multiple events per channel), and channels can be
+ * mapped to host interrupts in a one-to-one or many-to-one ratio (multiple
+ * channels per interrupt).
+ */
+struct fw_rsc_custom_intrmap {
+	u16 reserved;
+	s8 chnl_host_intr_map[10];
+	u32 event_chnl_map_size;
+	u32 event_chnl_map_addr;
+};
+
+#endif	/* _PRU_REMOTEPROC_H_ */
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


  parent reply	other threads:[~2018-11-26  7:52 UTC|newest]

Thread overview: 76+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-26  7:52 [PATCH 00/16] remoteproc: Add support for TI PRU Roger Quadros
2018-11-26  7:52 ` Roger Quadros
2018-11-26  7:52 ` [PATCH 01/16] remoteproc: Extend rproc_da_to_va() API with a flags parameter Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26 21:29   ` David Lechner
2018-11-29 10:29     ` Roger Quadros
2018-11-29 10:29       ` Roger Quadros
2018-11-29 16:12       ` David Lechner
2018-12-04 10:03         ` Roger Quadros
2018-12-04 10:03           ` Roger Quadros
2019-02-14  3:35           ` Suman Anna
2019-02-14  3:35             ` Suman Anna
2018-11-26  7:52 ` [PATCH 02/16] remoteproc: Add a rproc_set_firmware() API Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26 21:41   ` David Lechner
2018-11-29  8:51     ` Roger Quadros
2018-11-29  8:51       ` Roger Quadros
2018-11-26  7:52 ` [PATCH 03/16] remoteproc: Add support to handle device specific resource types Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26  7:52 ` Roger Quadros [this message]
2018-11-26  7:52   ` [PATCH 04/16] remoteproc/pru: Add PRU remoteproc driver Roger Quadros
2018-11-26 22:32   ` David Lechner
2018-11-29  9:26     ` Roger Quadros
2018-11-29  9:26       ` Roger Quadros
2018-11-30 21:39   ` Dimitar Dimitrov
2018-12-04  8:47     ` Roger Quadros
2018-12-04  8:47       ` Roger Quadros
2018-12-14  9:53     ` Roger Quadros
2018-12-14  9:53       ` Roger Quadros
2018-12-15 13:43       ` Dimitar Dimitrov
2018-11-26  7:52 ` [PATCH 05/16] remoteproc/pru: Add pru-specific debugfs support Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26 22:37   ` David Lechner
2018-11-29 10:17     ` Roger Quadros
2018-11-29 10:17       ` Roger Quadros
2018-12-18 15:51       ` Roger Quadros
2018-12-18 15:51         ` Roger Quadros
2018-12-19 12:38         ` Mark Brown
2018-12-19 15:43           ` Roger Quadros
2018-12-19 15:43             ` Roger Quadros
2018-12-19 15:48             ` David Lechner
2018-12-19 17:07               ` Mark Brown
2018-12-19 17:18                 ` Tony Lindgren
2018-12-20  8:45                   ` Roger Quadros
2018-12-20  8:45                     ` Roger Quadros
2018-11-26  7:52 ` [PATCH 06/16] dt-bindings: remoteproc: ti-pruss: Update bindings for supporting rpmsg Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26  7:52 ` [PATCH 07/16] remoteproc/pru: Add support for virtio rpmsg stack Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26  7:52 ` [PATCH 08/16] remoteproc/pru: Add pru_rproc_set_ctable() function Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26  7:52 ` [PATCH 09/16] remoteproc/pru: add APIs to get and put the PRU cores Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26  7:52 ` [PATCH 10/16] remoteproc/pru: add pru_rproc_get_id() API to retrieve the PRU id Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26  7:52 ` [PATCH 11/16] soc: ti: pruss: add helper functions to set GPI mode, MII_RT_event and XFR Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26  7:52 ` [PATCH 12/16] dt-bindings: remoteproc: ti-pruss: Document application node bindings Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26 23:27   ` David Lechner
2018-11-29 10:07     ` Roger Quadros
2018-11-29 10:07       ` Roger Quadros
2018-11-29 16:33       ` David Lechner
2018-11-30 11:42         ` Roger Quadros
2018-11-30 11:42           ` Roger Quadros
2018-12-11 22:06   ` Rob Herring
2018-12-17 16:03     ` Roger Quadros
2018-12-17 16:03       ` Roger Quadros
2018-11-26  7:52 ` [PATCH 13/16] remoteproc/pru: add support for configuring GPMUX based on client setup Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26  7:52 ` [PATCH 14/16] remoteproc/pru: configure firmware " Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26  7:52 ` [PATCH 15/16] remoteproc/pru: add support for parsing pru interrupt mapping from DT Roger Quadros
2018-11-26  7:52   ` Roger Quadros
2018-11-26  7:52 ` [PATCH 16/16] remoteproc/pru: Add support for INTC Interrupt map resource Roger Quadros
2018-11-26  7:52   ` Roger Quadros

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1543218769-5507-5-git-send-email-rogerq@ti.com \
    --to=rogerq@ti.com \
    --cc=bcousson@baylibre.com \
    --cc=bjorn.andersson@linaro.org \
    --cc=devicetree@vger.kernel.org \
    --cc=jreeder@ti.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=linux-remoteproc@vger.kernel.org \
    --cc=m-karicheri2@ti.com \
    --cc=nsaulnier@ti.com \
    --cc=nsekhar@ti.com \
    --cc=ohad@wizery.com \
    --cc=robh+dt@kernel.org \
    --cc=s-anna@ti.com \
    --cc=ssantosh@kernel.org \
    --cc=t-kristo@ti.com \
    --cc=tony@atomide.com \
    --cc=woods.technical@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.