From 1efa30d0895e7e9a58a59b0880b330b38245be68 Mon Sep 17 00:00:00 2001
From: Sarangdhar Joshi <spjoshi@codeaurora.org>
Date: Fri, 26 May 2017 16:51:00 -0700
Subject: [PATCH 01/12] remoteproc: Introduce rproc_{start,stop}() functions

In the context of recovering from crash, rproc_trigger_recovery() does
rproc_shutdown() followed by rproc_boot(). The remoteproc resources are
cleaned up in rproc_shutdown() and immediately reallocated in
rproc_boot() which is an unnecessary overhead. Furthermore, we want the
memory regions to be accessible after stopping the remote processor, to
be able to extract the memory content for a coredump.

This patch factors out the code in rproc_boot() and rproc_shutdown()
path and introduces rproc_{start,stop}() in order to avoid resource
allocation overhead.

Signed-off-by: Sarangdhar Joshi <spjoshi@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/remoteproc/remoteproc_core.c | 143 ++++++++++++++++-----------
 1 file changed, 87 insertions(+), 56 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 3dabb20b8d5d..c8cb54bedd9a 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -847,6 +847,63 @@ static void rproc_resource_cleanup(struct rproc *rproc)
 		kref_put(&rvdev->refcount, rproc_vdev_release);
 }
 
+static int rproc_start(struct rproc *rproc, const struct firmware *fw)
+{
+	struct resource_table *table, *loaded_table;
+	struct device *dev = &rproc->dev;
+	int ret, tablesz;
+
+	/* look for the resource table */
+	table = rproc_find_rsc_table(rproc, fw, &tablesz);
+	if (!table) {
+		dev_err(dev, "Resouce table look up failed\n");
+		return -EINVAL;
+	}
+
+	/* load the ELF segments to memory */
+	ret = rproc_load_segments(rproc, fw);
+	if (ret) {
+		dev_err(dev, "Failed to load program segments: %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * The starting device has been given the rproc->cached_table as the
+	 * resource table. The address of the vring along with the other
+	 * allocated resources (carveouts etc) is stored in cached_table.
+	 * In order to pass this information to the remote device we must copy
+	 * this information to device memory. We also update the table_ptr so
+	 * that any subsequent changes will be applied to the loaded version.
+	 */
+	loaded_table = rproc_find_loaded_rsc_table(rproc, fw);
+	if (loaded_table) {
+		memcpy(loaded_table, rproc->cached_table, tablesz);
+		rproc->table_ptr = loaded_table;
+	}
+
+	/* power up the remote processor */
+	ret = rproc->ops->start(rproc);
+	if (ret) {
+		dev_err(dev, "can't start rproc %s: %d\n", rproc->name, ret);
+		return ret;
+	}
+
+	/* probe any subdevices for the remote processor */
+	ret = rproc_probe_subdevices(rproc);
+	if (ret) {
+		dev_err(dev, "failed to probe subdevices for %s: %d\n",
+			rproc->name, ret);
+		rproc->ops->stop(rproc);
+		return ret;
+	}
+
+	rproc->state = RPROC_RUNNING;
+
+	dev_info(dev, "remote processor %s is now up\n", rproc->name);
+
+	return 0;
+}
+
 /*
  * take a firmware and boot a remote processor with it.
  */
@@ -854,7 +911,7 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
 {
 	struct device *dev = &rproc->dev;
 	const char *name = rproc->firmware;
-	struct resource_table *table, *loaded_table;
+	struct resource_table *table;
 	int ret, tablesz;
 
 	ret = rproc_fw_sanity_check(rproc, fw);
@@ -905,50 +962,12 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
 		goto clean_up_resources;
 	}
 
-	/* load the ELF segments to memory */
-	ret = rproc_load_segments(rproc, fw);
-	if (ret) {
-		dev_err(dev, "Failed to load program segments: %d\n", ret);
+	ret = rproc_start(rproc, fw);
+	if (ret)
 		goto clean_up_resources;
-	}
-
-	/*
-	 * The starting device has been given the rproc->cached_table as the
-	 * resource table. The address of the vring along with the other
-	 * allocated resources (carveouts etc) is stored in cached_table.
-	 * In order to pass this information to the remote device we must copy
-	 * this information to device memory. We also update the table_ptr so
-	 * that any subsequent changes will be applied to the loaded version.
-	 */
-	loaded_table = rproc_find_loaded_rsc_table(rproc, fw);
-	if (loaded_table) {
-		memcpy(loaded_table, rproc->cached_table, tablesz);
-		rproc->table_ptr = loaded_table;
-	}
-
-	/* power up the remote processor */
-	ret = rproc->ops->start(rproc);
-	if (ret) {
-		dev_err(dev, "can't start rproc %s: %d\n", rproc->name, ret);
-		goto clean_up_resources;
-	}
-
-	/* probe any subdevices for the remote processor */
-	ret = rproc_probe_subdevices(rproc);
-	if (ret) {
-		dev_err(dev, "failed to probe subdevices for %s: %d\n",
-			rproc->name, ret);
-		goto stop_rproc;
-	}
-
-	rproc->state = RPROC_RUNNING;
-
-	dev_info(dev, "remote processor %s is now up\n", rproc->name);
 
 	return 0;
 
-stop_rproc:
-	rproc->ops->stop(rproc);
 clean_up_resources:
 	rproc_resource_cleanup(rproc);
 clean_up:
@@ -994,6 +1013,32 @@ static int rproc_trigger_auto_boot(struct rproc *rproc)
 	return ret;
 }
 
+static int rproc_stop(struct rproc *rproc)
+{
+	struct device *dev = &rproc->dev;
+	int ret;
+
+	/* remove any subdevices for the remote processor */
+	rproc_remove_subdevices(rproc);
+
+	/* power off the remote processor */
+	ret = rproc->ops->stop(rproc);
+	if (ret) {
+		dev_err(dev, "can't stop rproc: %d\n", ret);
+		return ret;
+	}
+
+	/* if in crash state, unlock crash handler */
+	if (rproc->state == RPROC_CRASHED)
+		complete_all(&rproc->crash_comp);
+
+	rproc->state = RPROC_OFFLINE;
+
+	dev_info(dev, "stopped remote processor %s\n", rproc->name);
+
+	return 0;
+}
+
 /**
  * rproc_trigger_recovery() - recover a remoteproc
  * @rproc: the remote processor
@@ -1163,14 +1208,9 @@ void rproc_shutdown(struct rproc *rproc)
 	if (!atomic_dec_and_test(&rproc->power))
 		goto out;
 
-	/* remove any subdevices for the remote processor */
-	rproc_remove_subdevices(rproc);
-
-	/* power off the remote processor */
-	ret = rproc->ops->stop(rproc);
+	ret = rproc_stop(rproc);
 	if (ret) {
 		atomic_inc(&rproc->power);
-		dev_err(dev, "can't stop rproc: %d\n", ret);
 		goto out;
 	}
 
@@ -1183,15 +1223,6 @@ void rproc_shutdown(struct rproc *rproc)
 	kfree(rproc->cached_table);
 	rproc->cached_table = NULL;
 	rproc->table_ptr = NULL;
-
-	/* if in crash state, unlock crash handler */
-	if (rproc->state == RPROC_CRASHED)
-		complete_all(&rproc->crash_comp);
-
-	rproc->state = RPROC_OFFLINE;
-
-	dev_info(dev, "stopped remote processor %s\n", rproc->name);
-
 out:
 	mutex_unlock(&rproc->lock);
 }

From 7e83cab824a86704cdbd7735c19d34e0ce423dc5 Mon Sep 17 00:00:00 2001
From: Sarangdhar Joshi <spjoshi@codeaurora.org>
Date: Fri, 26 May 2017 16:51:01 -0700
Subject: [PATCH 02/12] remoteproc: Modify recovery path to use
 rproc_{start,stop}()

Replace rproc_shutdown() by rproc_stop() and rproc_boot() by
rproc_start() in the recovery path, in order to avoid remoteproc
resources re-allocation overhead and to assist with extracting the
coredumps after stopping the remote processor.

Signed-off-by: Sarangdhar Joshi <spjoshi@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/remoteproc/remoteproc_core.c | 35 +++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index c8cb54bedd9a..369ba0f8429c 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1051,23 +1051,40 @@ static int rproc_stop(struct rproc *rproc)
  */
 int rproc_trigger_recovery(struct rproc *rproc)
 {
-	dev_err(&rproc->dev, "recovering %s\n", rproc->name);
+	const struct firmware *firmware_p;
+	struct device *dev = &rproc->dev;
+	int ret;
+
+	dev_err(dev, "recovering %s\n", rproc->name);
 
 	init_completion(&rproc->crash_comp);
 
-	/* shut down the remote */
-	/* TODO: make sure this works with rproc->power > 1 */
-	rproc_shutdown(rproc);
+	ret = mutex_lock_interruptible(&rproc->lock);
+	if (ret)
+		return ret;
+
+	ret = rproc_stop(rproc);
+	if (ret)
+		goto unlock_mutex;
 
 	/* wait until there is no more rproc users */
 	wait_for_completion(&rproc->crash_comp);
 
-	/*
-	 * boot the remote processor up again
-	 */
-	rproc_boot(rproc);
+	/* load firmware */
+	ret = request_firmware(&firmware_p, rproc->firmware, dev);
+	if (ret < 0) {
+		dev_err(dev, "request_firmware failed: %d\n", ret);
+		goto unlock_mutex;
+	}
 
-	return 0;
+	/* boot the remote processor up again */
+	ret = rproc_start(rproc, firmware_p);
+
+	release_firmware(firmware_p);
+
+unlock_mutex:
+	mutex_unlock(&rproc->lock);
+	return ret;
 }
 
 /**

From ca91ab5f112bdcea9516c7ce8f46f4139df69b4a Mon Sep 17 00:00:00 2001
From: Colin Ian King <colin.king@canonical.com>
Date: Mon, 29 May 2017 07:23:52 +0100
Subject: [PATCH 03/12] remoteproc: fix spelling mistake: "Resouce" ->
 "Resource"

Trivial fix to spelling mistake in dev_err message

Signed-off-by: Colin Ian King <colin.king@canonical.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/remoteproc/remoteproc_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 369ba0f8429c..564061dcc019 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -856,7 +856,7 @@ static int rproc_start(struct rproc *rproc, const struct firmware *fw)
 	/* look for the resource table */
 	table = rproc_find_rsc_table(rproc, fw, &tablesz);
 	if (!table) {
-		dev_err(dev, "Resouce table look up failed\n");
+		dev_err(dev, "Resource table look up failed\n");
 		return -EINVAL;
 	}
 

From c51e882cd711abfa11e29f46cd7a73ce41ba1cf4 Mon Sep 17 00:00:00 2001
From: Suman Anna <s-anna@ti.com>
Date: Thu, 18 May 2017 17:08:59 -0500
Subject: [PATCH 04/12] remoteproc/davinci: Update Kconfig to depend on DMA_CMA

The davinci remoteproc driver requires a CMA pool for allocating
memory for virtio vrings/buffers and other sections of the firmware
image. The allocations are done using the DMA API. The CMA option is
currently selected automatically on systems with MMU when davinci
remoteproc is enabled, switch this to a saner depends on dependency
convention. The dependency is also updated to use the DMA_CMA kconfig
symbol that is used for CMA allocations using the DMA API, the CMA
dependency is inherited implicitly.

Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/remoteproc/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index faad69a1a597..0aafb0d0e9fd 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -52,7 +52,7 @@ config DA8XX_REMOTEPROC
 	tristate "DA8xx/OMAP-L13x remoteproc support"
 	depends on ARCH_DAVINCI_DA8XX
 	depends on REMOTEPROC
-	select CMA if MMU
+	depends on DMA_CMA
 	select RPMSG_VIRTIO
 	help
 	  Say y here to support DA8xx/OMAP-L13x remote processors via the

From 470ac62fe557b905324ccecb3a20ad686672d22e Mon Sep 17 00:00:00 2001
From: Suman Anna <s-anna@ti.com>
Date: Thu, 18 May 2017 17:09:00 -0500
Subject: [PATCH 05/12] remoteproc/davinci: simplify the reset function

The reset_assert() function is used to make sure the DSP remote
processor is in a reset state regardless of its previous state.
The driver relies on davinci_clk_reset_{assert,deassert}()
functions for reset management which take in a clock parameter.
The assert_reset() performs a clk_get()/clk_put() cycle to
acquire the clock handle to use with this function. This is
totally unnecessary and the code can be simplified to use
the clock acquired during probe and directly use the reset
functions, so simplify this logic.

Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/remoteproc/da8xx_remoteproc.c | 23 +++--------------------
 1 file changed, 3 insertions(+), 20 deletions(-)

diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c
index 3814de28599c..fcd3cecb4967 100644
--- a/drivers/remoteproc/da8xx_remoteproc.c
+++ b/drivers/remoteproc/da8xx_remoteproc.c
@@ -157,22 +157,6 @@ static const struct rproc_ops da8xx_rproc_ops = {
 	.kick = da8xx_rproc_kick,
 };
 
-static int reset_assert(struct device *dev)
-{
-	struct clk *dsp_clk;
-
-	dsp_clk = clk_get(dev, NULL);
-	if (IS_ERR(dsp_clk)) {
-		dev_err(dev, "clk_get error: %ld\n", PTR_ERR(dsp_clk));
-		return PTR_ERR(dsp_clk);
-	}
-
-	davinci_clk_reset_assert(dsp_clk);
-	clk_put(dsp_clk);
-
-	return 0;
-}
-
 static int da8xx_rproc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -223,6 +207,7 @@ static int da8xx_rproc_probe(struct platform_device *pdev)
 
 	drproc = rproc->priv;
 	drproc->rproc = rproc;
+	drproc->dsp_clk = dsp_clk;
 	rproc->has_iommu = false;
 
 	platform_set_drvdata(pdev, rproc);
@@ -241,7 +226,7 @@ static int da8xx_rproc_probe(struct platform_device *pdev)
 	 * *not* in reset, but da8xx_rproc_start() needs the DSP to be
 	 * held in reset at the time it is called.
 	 */
-	ret = reset_assert(dev);
+	ret = davinci_clk_reset_assert(drproc->dsp_clk);
 	if (ret)
 		goto free_rproc;
 
@@ -250,7 +235,6 @@ static int da8xx_rproc_probe(struct platform_device *pdev)
 	drproc->ack_fxn = irq_data->chip->irq_ack;
 	drproc->irq_data = irq_data;
 	drproc->irq = irq;
-	drproc->dsp_clk = dsp_clk;
 
 	ret = rproc_add(rproc);
 	if (ret) {
@@ -268,7 +252,6 @@ free_rproc:
 
 static int da8xx_rproc_remove(struct platform_device *pdev)
 {
-	struct device *dev = &pdev->dev;
 	struct rproc *rproc = platform_get_drvdata(pdev);
 	struct da8xx_rproc *drproc = (struct da8xx_rproc *)rproc->priv;
 
@@ -280,7 +263,7 @@ static int da8xx_rproc_remove(struct platform_device *pdev)
 	 * Without the reset, the DSP can lockup permanently when it
 	 * begins executing garbage.
 	 */
-	reset_assert(dev);
+	davinci_clk_reset_assert(drproc->dsp_clk);
 
 	/*
 	 * The devm subsystem might end up releasing things before

From a63c70d4dc93628147b76b4081838f913c0dbe6e Mon Sep 17 00:00:00 2001
From: Suman Anna <s-anna@ti.com>
Date: Thu, 18 May 2017 17:09:01 -0500
Subject: [PATCH 06/12] remoteproc/davinci: fix unbalanced reset between start
 and stop ops

The davinci remoteproc driver is currently de-asserting the reset in
its rproc .start() ops, but is not asserting the reset in its .stop()
ops. This leaves the remote processor to not boot properly when using
the sysfs 'state' variable between multiple start and stop operations.
On the other hand, a reset is being asserted unconditionally in the
driver remove function to alleviate some of these issues.

Move this reset assertion logic into the .stop() ops implementation
to fix the sysfs state-machine and the unbalanced reset. The logic
from remove is still effective since .stop() ops will be invoked
during the remove due to the enabled 'auto-boot' support. The probe
already has support for asserting the reset in case the DSP is not
in reset for some reason.

Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/remoteproc/da8xx_remoteproc.c | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c
index fcd3cecb4967..99539cec1329 100644
--- a/drivers/remoteproc/da8xx_remoteproc.c
+++ b/drivers/remoteproc/da8xx_remoteproc.c
@@ -137,6 +137,7 @@ static int da8xx_rproc_stop(struct rproc *rproc)
 {
 	struct da8xx_rproc *drproc = rproc->priv;
 
+	davinci_clk_reset_assert(drproc->dsp_clk);
 	clk_disable(drproc->dsp_clk);
 
 	return 0;
@@ -255,16 +256,6 @@ static int da8xx_rproc_remove(struct platform_device *pdev)
 	struct rproc *rproc = platform_get_drvdata(pdev);
 	struct da8xx_rproc *drproc = (struct da8xx_rproc *)rproc->priv;
 
-	/*
-	 * It's important to place the DSP in reset before going away,
-	 * since a subsequent insmod of this module may enable the DSP's
-	 * clock before its program/boot-address has been loaded and
-	 * before this module's probe has had a chance to reset the DSP.
-	 * Without the reset, the DSP can lockup permanently when it
-	 * begins executing garbage.
-	 */
-	davinci_clk_reset_assert(drproc->dsp_clk);
-
 	/*
 	 * The devm subsystem might end up releasing things before
 	 * freeing the irq, thus allowing an interrupt to sneak in while

From fd7c7041a4c0b284fab2509aed4dc1151b4ca700 Mon Sep 17 00:00:00 2001
From: Suman Anna <s-anna@ti.com>
Date: Tue, 13 Jun 2017 18:45:11 -0500
Subject: [PATCH 07/12] dt-bindings: remoteproc: Add Keystone DSP remoteproc
 binding

Add the device tree bindings document for the Texas Instrument's
Keystone 2 DSP remoteproc devices.

Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Sam Nelson <sam.nelson@ti.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 .../bindings/remoteproc/ti,keystone-rproc.txt | 133 ++++++++++++++++++
 1 file changed, 133 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/remoteproc/ti,keystone-rproc.txt

diff --git a/Documentation/devicetree/bindings/remoteproc/ti,keystone-rproc.txt b/Documentation/devicetree/bindings/remoteproc/ti,keystone-rproc.txt
new file mode 100644
index 000000000000..2aac1aa4123d
--- /dev/null
+++ b/Documentation/devicetree/bindings/remoteproc/ti,keystone-rproc.txt
@@ -0,0 +1,133 @@
+TI Keystone DSP devices
+=======================
+
+The TI Keystone 2 family of SoCs usually have one or more (upto 8) TI DSP Core
+sub-systems that are used to offload some of the processor-intensive tasks or
+algorithms, for achieving various system level goals.
+
+These processor sub-systems usually contain additional sub-modules like L1
+and/or L2 caches/SRAMs, an Interrupt Controller, an external memory controller,
+a dedicated local power/sleep controller etc. The DSP processor core in
+Keystone 2 SoCs is usually a TMS320C66x CorePac processor.
+
+DSP Device Node:
+================
+Each DSP Core sub-system is represented as a single DT node, and should also
+have an alias with the stem 'rproc' defined. Each node has a number of required
+or optional properties that enable the OS running on the host processor (ARM
+CorePac) to perform the device management of the remote processor and to
+communicate with the remote processor.
+
+Required properties:
+--------------------
+The following are the mandatory properties:
+
+- compatible:		Should be one of the following,
+			    "ti,k2hk-dsp" for DSPs on Keystone 2 66AK2H/K SoCs
+			    "ti,k2l-dsp" for DSPs on Keystone 2 66AK2L SoCs
+			    "ti,k2e-dsp" for DSPs on Keystone 2 66AK2E SoCs
+
+- reg:			Should contain an entry for each value in 'reg-names'.
+			Each entry should have the memory region's start address
+			and the size of the region, the representation matching
+			the parent node's '#address-cells' and '#size-cells' values.
+
+- reg-names:		Should contain strings with the following names, each
+			representing a specific internal memory region, and
+			should be defined in this order,
+			     "l2sram", "l1pram", "l1dram"
+
+- clocks: 		Should contain the device's input clock, and should be
+			defined as per the bindings in,
+			Documentation/devicetree/bindings/clock/keystone-gate.txt
+
+- ti,syscon-dev:	Should be a pair of the phandle to the Keystone Device
+			State Control node, and the register offset of the DSP
+			boot address register within that node's address space.
+
+- resets:		Should contain the phandle to the reset controller node
+			managing the resets for this device, and a reset
+			specifier. Please refer to the following reset bindings
+			for the reset argument specifier as per SoC,
+			Documentation/devicetree/bindings/reset/ti-syscon-reset.txt
+			    for 66AK2HK/66AK2L/66AK2E SoCs
+
+- interrupt-parent:	Should contain a phandle to the Keystone 2 IRQ controller
+			IP node that is used by the ARM CorePac processor to
+			receive interrupts from the DSP remote processors. See
+			Documentation/devicetree/bindings/interrupt-controller/ti,keystone-irq.txt
+			for details.
+
+- interrupts: 		Should contain an entry for each value in 'interrupt-names'.
+			Each entry should have the interrupt source number used by
+			the remote processor to the host processor. The values should
+			follow the interrupt-specifier format as dictated by the
+			'interrupt-parent' node. The purpose of each is as per the
+			description in the 'interrupt-names' property.
+
+- interrupt-names:	Should contain strings with the following names, each
+			representing a specific interrupt,
+			    "vring" - interrupt for virtio based IPC
+			    "exception" - interrupt for exception notification
+
+- kick-gpios: 		Should specify the gpio device needed for the virtio IPC
+			stack. This will be used to interrupt the remote processor.
+			The gpio device to be used is as per the bindings in,
+			Documentation/devicetree/bindings/gpio/gpio-dsp-keystone.txt
+
+Optional properties:
+--------------------
+
+- memory-region:	phandle to the reserved memory node to be associated
+			with the remoteproc device. The reserved memory node
+			can be a CMA memory node, and should be defined as
+			per the bindings in
+			Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
+
+
+Example:
+--------
+	/* 66AK2H/K DSP aliases */
+	aliases {
+		rproc0 = &dsp0;
+		rproc1 = &dsp1;
+		rproc2 = &dsp2;
+		rproc3 = &dsp3;
+		rproc4 = &dsp4;
+		rproc5 = &dsp5;
+		rproc6 = &dsp6;
+		rproc7 = &dsp7;
+	};
+
+	/* 66AK2H/K DSP memory node */
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		dsp_common_memory: dsp-common-memory@81f800000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00000008 0x1f800000 0x00000000 0x800000>;
+			reusable;
+		};
+	};
+
+	/* 66AK2H/K DSP node */
+	soc {
+		dsp0: dsp@10800000 {
+			compatible = "ti,k2hk-dsp";
+			reg = <0x10800000 0x00100000>,
+			      <0x10e00000 0x00008000>,
+			      <0x10f00000 0x00008000>;
+			reg-names = "l2sram", "l1pram", "l1dram";
+			clocks = <&clkgem0>;
+			ti,syscon-dev = <&devctrl 0x40>;
+			resets = <&pscrst 0>;
+			interrupt-parent = <&kirq0>;
+			interrupts = <0 8>;
+			interrupt-names = "vring", "exception";
+			kick-gpios = <&dspgpio0 27 0>;
+			memory-region = <&dsp_common_memory>;
+		};
+
+	};

From e88bb8f7a12c1325e312c214f157109d56b06f76 Mon Sep 17 00:00:00 2001
From: Suman Anna <s-anna@ti.com>
Date: Tue, 13 Jun 2017 18:45:12 -0500
Subject: [PATCH 08/12] remoteproc/keystone: Add a remoteproc driver for
 Keystone 2 DSPs

The Texas Instrument's Keystone 2 family of SoCs has 1 or more
TMS320C66x DSP Core Subsystems (C66x CorePacs). Each subsystem has
a C66x Fixed/Floating-Point DSP Core, with 32KB of L1P and L1D SRAMs,
that can be configured and partitioned as either RAM and/or Cache,
and 1 MB of L2 SRAM. The CorePac also includes an Internal DMA (IDMA),
External Memory Controller (EMC), Extended Memory Controller (XMC)
with a Memory Protection and Address Extension (MPAX) unit, a Bandwidth
Management (BWM) unit, an Interrupt Controller (INTC) and a Powerdown
Controller (PDC).

A new remoteproc module is added to perform the device management of
these DSP devices. The driver expects the firmware names to be of the
form "keystone-dsp<X>-fw", where X is the corresponding DSP number, and
uses the standard remoteproc core ELF loader. The support is limited
to images only using the DSP internal memories at the moment. This
remoteproc driver is also designed to work with virtio, and uses the
IPC Generation registers for performing the virtio signalling and
getting notified of exceptions.

The driver currently supports the 66AK2H/66AK2K, 66AK2L and 66AK2E
SoCs.

Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Sam Nelson <sam.nelson@ti.com>
Signed-off-by: Andrew F. Davis <afd@ti.com>
Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/remoteproc/Kconfig               |  13 +
 drivers/remoteproc/Makefile              |   1 +
 drivers/remoteproc/keystone_remoteproc.c | 515 +++++++++++++++++++++++
 3 files changed, 529 insertions(+)
 create mode 100644 drivers/remoteproc/keystone_remoteproc.c

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 0aafb0d0e9fd..b950e6cd4ba2 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -71,6 +71,19 @@ config DA8XX_REMOTEPROC
 	  It's safe to say n here if you're not interested in multimedia
 	  offloading.
 
+config KEYSTONE_REMOTEPROC
+	tristate "Keystone Remoteproc support"
+	depends on ARCH_KEYSTONE
+	depends on RESET_CONTROLLER
+	depends on REMOTEPROC
+	select RPMSG_VIRTIO
+	help
+	  Say Y here here to support Keystone remote processors (DSP)
+	  via the remote processor framework.
+
+	  It's safe to say N here if you're not interested in the Keystone
+	  DSPs or just want to use a bare minimum kernel.
+
 config QCOM_ADSP_PIL
 	tristate "Qualcomm ADSP Peripheral Image Loader"
 	depends on OF && ARCH_QCOM
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index ffc5e430df27..f1ce5fc8a2f3 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -11,6 +11,7 @@ remoteproc-y				+= remoteproc_elf_loader.o
 obj-$(CONFIG_OMAP_REMOTEPROC)		+= omap_remoteproc.o
 obj-$(CONFIG_WKUP_M3_RPROC)		+= wkup_m3_rproc.o
 obj-$(CONFIG_DA8XX_REMOTEPROC)		+= da8xx_remoteproc.o
+obj-$(CONFIG_KEYSTONE_REMOTEPROC)	+= keystone_remoteproc.o
 obj-$(CONFIG_QCOM_ADSP_PIL)		+= qcom_adsp_pil.o
 obj-$(CONFIG_QCOM_RPROC_COMMON)		+= qcom_common.o
 obj-$(CONFIG_QCOM_Q6V5_PIL)		+= qcom_q6v5_pil.o
diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c
new file mode 100644
index 000000000000..6e09ef76f7c7
--- /dev/null
+++ b/drivers/remoteproc/keystone_remoteproc.c
@@ -0,0 +1,515 @@
+/*
+ * TI Keystone DSP remoteproc driver
+ *
+ * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/workqueue.h>
+#include <linux/of_address.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/remoteproc.h>
+#include <linux/reset.h>
+
+#include "remoteproc_internal.h"
+
+#define KEYSTONE_RPROC_LOCAL_ADDRESS_MASK	(SZ_16M - 1)
+
+/**
+ * struct keystone_rproc_mem - internal memory structure
+ * @cpu_addr: MPU virtual address of the memory region
+ * @bus_addr: Bus address used to access the memory region
+ * @dev_addr: Device address of the memory region from DSP view
+ * @size: Size of the memory region
+ */
+struct keystone_rproc_mem {
+	void __iomem *cpu_addr;
+	phys_addr_t bus_addr;
+	u32 dev_addr;
+	size_t size;
+};
+
+/**
+ * struct keystone_rproc - keystone remote processor driver structure
+ * @dev: cached device pointer
+ * @rproc: remoteproc device handle
+ * @mem: internal memory regions data
+ * @num_mems: number of internal memory regions
+ * @dev_ctrl: device control regmap handle
+ * @reset: reset control handle
+ * @boot_offset: boot register offset in @dev_ctrl regmap
+ * @irq_ring: irq entry for vring
+ * @irq_fault: irq entry for exception
+ * @kick_gpio: gpio used for virtio kicks
+ * @workqueue: workqueue for processing virtio interrupts
+ */
+struct keystone_rproc {
+	struct device *dev;
+	struct rproc *rproc;
+	struct keystone_rproc_mem *mem;
+	int num_mems;
+	struct regmap *dev_ctrl;
+	struct reset_control *reset;
+	u32 boot_offset;
+	int irq_ring;
+	int irq_fault;
+	int kick_gpio;
+	struct work_struct workqueue;
+};
+
+/* Put the DSP processor into reset */
+static void keystone_rproc_dsp_reset(struct keystone_rproc *ksproc)
+{
+	reset_control_assert(ksproc->reset);
+}
+
+/* Configure the boot address and boot the DSP processor */
+static int keystone_rproc_dsp_boot(struct keystone_rproc *ksproc, u32 boot_addr)
+{
+	int ret;
+
+	if (boot_addr & (SZ_1K - 1)) {
+		dev_err(ksproc->dev, "invalid boot address 0x%x, must be aligned on a 1KB boundary\n",
+			boot_addr);
+		return -EINVAL;
+	}
+
+	ret = regmap_write(ksproc->dev_ctrl, ksproc->boot_offset, boot_addr);
+	if (ret) {
+		dev_err(ksproc->dev, "regmap_write of boot address failed, status = %d\n",
+			ret);
+		return ret;
+	}
+
+	reset_control_deassert(ksproc->reset);
+
+	return 0;
+}
+
+/*
+ * Process the remoteproc exceptions
+ *
+ * The exception reporting on Keystone DSP remote processors is very simple
+ * compared to the equivalent processors on the OMAP family, it is notified
+ * through a software-designed specific interrupt source in the IPC interrupt
+ * generation register.
+ *
+ * This function just invokes the rproc_report_crash to report the exception
+ * to the remoteproc driver core, to trigger a recovery.
+ */
+static irqreturn_t keystone_rproc_exception_interrupt(int irq, void *dev_id)
+{
+	struct keystone_rproc *ksproc = dev_id;
+
+	rproc_report_crash(ksproc->rproc, RPROC_FATAL_ERROR);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Main virtqueue message workqueue function
+ *
+ * This function is executed upon scheduling of the keystone remoteproc
+ * driver's workqueue. The workqueue is scheduled by the vring ISR handler.
+ *
+ * There is no payload message indicating the virtqueue index as is the
+ * case with mailbox-based implementations on OMAP family. As such, this
+ * handler processes both the Tx and Rx virtqueue indices on every invocation.
+ * The rproc_vq_interrupt function can detect if there are new unprocessed
+ * messages or not (returns IRQ_NONE vs IRQ_HANDLED), but there is no need
+ * to check for these return values. The index 0 triggering will process all
+ * pending Rx buffers, and the index 1 triggering will process all newly
+ * available Tx buffers and will wakeup any potentially blocked senders.
+ *
+ * NOTE:
+ * 1. A payload could be added by using some of the source bits in the
+ *    IPC interrupt generation registers, but this would need additional
+ *    changes to the overall IPC stack, and currently there are no benefits
+ *    of adapting that approach.
+ * 2. The current logic is based on an inherent design assumption of supporting
+ *    only 2 vrings, but this can be changed if needed.
+ */
+static void handle_event(struct work_struct *work)
+{
+	struct keystone_rproc *ksproc =
+		container_of(work, struct keystone_rproc, workqueue);
+
+	rproc_vq_interrupt(ksproc->rproc, 0);
+	rproc_vq_interrupt(ksproc->rproc, 1);
+}
+
+/*
+ * Interrupt handler for processing vring kicks from remote processor
+ */
+static irqreturn_t keystone_rproc_vring_interrupt(int irq, void *dev_id)
+{
+	struct keystone_rproc *ksproc = dev_id;
+
+	schedule_work(&ksproc->workqueue);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Power up the DSP remote processor.
+ *
+ * This function will be invoked only after the firmware for this rproc
+ * was loaded, parsed successfully, and all of its resource requirements
+ * were met.
+ */
+static int keystone_rproc_start(struct rproc *rproc)
+{
+	struct keystone_rproc *ksproc = rproc->priv;
+	int ret;
+
+	INIT_WORK(&ksproc->workqueue, handle_event);
+
+	ret = request_irq(ksproc->irq_ring, keystone_rproc_vring_interrupt, 0,
+			  dev_name(ksproc->dev), ksproc);
+	if (ret) {
+		dev_err(ksproc->dev, "failed to enable vring interrupt, ret = %d\n",
+			ret);
+		goto out;
+	}
+
+	ret = request_irq(ksproc->irq_fault, keystone_rproc_exception_interrupt,
+			  0, dev_name(ksproc->dev), ksproc);
+	if (ret) {
+		dev_err(ksproc->dev, "failed to enable exception interrupt, ret = %d\n",
+			ret);
+		goto free_vring_irq;
+	}
+
+	ret = keystone_rproc_dsp_boot(ksproc, rproc->bootaddr);
+	if (ret)
+		goto free_exc_irq;
+
+	return 0;
+
+free_exc_irq:
+	free_irq(ksproc->irq_fault, ksproc);
+free_vring_irq:
+	free_irq(ksproc->irq_ring, ksproc);
+	flush_work(&ksproc->workqueue);
+out:
+	return ret;
+}
+
+/*
+ * Stop the DSP remote processor.
+ *
+ * This function puts the DSP processor into reset, and finishes processing
+ * of any pending messages.
+ */
+static int keystone_rproc_stop(struct rproc *rproc)
+{
+	struct keystone_rproc *ksproc = rproc->priv;
+
+	keystone_rproc_dsp_reset(ksproc);
+	free_irq(ksproc->irq_fault, ksproc);
+	free_irq(ksproc->irq_ring, ksproc);
+	flush_work(&ksproc->workqueue);
+
+	return 0;
+}
+
+/*
+ * Kick the remote processor to notify about pending unprocessed messages.
+ * The vqid usage is not used and is inconsequential, as the kick is performed
+ * through a simulated GPIO (a bit in an IPC interrupt-triggering register),
+ * the remote processor is expected to process both its Tx and Rx virtqueues.
+ */
+static void keystone_rproc_kick(struct rproc *rproc, int vqid)
+{
+	struct keystone_rproc *ksproc = rproc->priv;
+
+	if (WARN_ON(ksproc->kick_gpio < 0))
+		return;
+
+	gpio_set_value(ksproc->kick_gpio, 1);
+}
+
+/*
+ * Custom function to translate a DSP device address (internal RAMs only) to a
+ * kernel virtual address.  The DSPs can access their RAMs at either an internal
+ * address visible only from a DSP, or at the SoC-level bus address. Both these
+ * addresses need to be looked through for translation. The translated addresses
+ * 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)
+{
+	struct keystone_rproc *ksproc = rproc->priv;
+	void __iomem *va = NULL;
+	phys_addr_t bus_addr;
+	u32 dev_addr, offset;
+	size_t size;
+	int i;
+
+	if (len <= 0)
+		return NULL;
+
+	for (i = 0; i < ksproc->num_mems; i++) {
+		bus_addr = ksproc->mem[i].bus_addr;
+		dev_addr = ksproc->mem[i].dev_addr;
+		size = ksproc->mem[i].size;
+
+		if (da < KEYSTONE_RPROC_LOCAL_ADDRESS_MASK) {
+			/* handle DSP-view addresses */
+			if ((da >= dev_addr) &&
+			    ((da + len) <= (dev_addr + size))) {
+				offset = da - dev_addr;
+				va = ksproc->mem[i].cpu_addr + offset;
+				break;
+			}
+		} else {
+			/* handle SoC-view addresses */
+			if ((da >= bus_addr) &&
+			    (da + len) <= (bus_addr + size)) {
+				offset = da - bus_addr;
+				va = ksproc->mem[i].cpu_addr + offset;
+				break;
+			}
+		}
+	}
+
+	return (__force void *)va;
+}
+
+static const struct rproc_ops keystone_rproc_ops = {
+	.start		= keystone_rproc_start,
+	.stop		= keystone_rproc_stop,
+	.kick		= keystone_rproc_kick,
+	.da_to_va	= keystone_rproc_da_to_va,
+};
+
+static int keystone_rproc_of_get_memories(struct platform_device *pdev,
+					  struct keystone_rproc *ksproc)
+{
+	static const char * const mem_names[] = {"l2sram", "l1pram", "l1dram"};
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	int num_mems = 0;
+	int i;
+
+	num_mems = ARRAY_SIZE(mem_names);
+	ksproc->mem = devm_kcalloc(ksproc->dev, num_mems,
+				   sizeof(*ksproc->mem), GFP_KERNEL);
+	if (!ksproc->mem)
+		return -ENOMEM;
+
+	for (i = 0; i < num_mems; i++) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						   mem_names[i]);
+		ksproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res);
+		if (IS_ERR(ksproc->mem[i].cpu_addr)) {
+			dev_err(dev, "failed to parse and map %s memory\n",
+				mem_names[i]);
+			return PTR_ERR(ksproc->mem[i].cpu_addr);
+		}
+		ksproc->mem[i].bus_addr = res->start;
+		ksproc->mem[i].dev_addr =
+				res->start & KEYSTONE_RPROC_LOCAL_ADDRESS_MASK;
+		ksproc->mem[i].size = resource_size(res);
+
+		/* zero out memories to start in a pristine state */
+		memset((__force void *)ksproc->mem[i].cpu_addr, 0,
+		       ksproc->mem[i].size);
+	}
+	ksproc->num_mems = num_mems;
+
+	return 0;
+}
+
+static int keystone_rproc_of_get_dev_syscon(struct platform_device *pdev,
+					    struct keystone_rproc *ksproc)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	if (!of_property_read_bool(np, "ti,syscon-dev")) {
+		dev_err(dev, "ti,syscon-dev property is absent\n");
+		return -EINVAL;
+	}
+
+	ksproc->dev_ctrl =
+		syscon_regmap_lookup_by_phandle(np, "ti,syscon-dev");
+	if (IS_ERR(ksproc->dev_ctrl)) {
+		ret = PTR_ERR(ksproc->dev_ctrl);
+		return ret;
+	}
+
+	if (of_property_read_u32_index(np, "ti,syscon-dev", 1,
+				       &ksproc->boot_offset)) {
+		dev_err(dev, "couldn't read the boot register offset\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int keystone_rproc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct keystone_rproc *ksproc;
+	struct rproc *rproc;
+	int dsp_id;
+	char *fw_name = NULL;
+	char *template = "keystone-dsp%d-fw";
+	int name_len = 0;
+	int ret = 0;
+
+	if (!np) {
+		dev_err(dev, "only DT-based devices are supported\n");
+		return -ENODEV;
+	}
+
+	dsp_id = of_alias_get_id(np, "rproc");
+	if (dsp_id < 0) {
+		dev_warn(dev, "device does not have an alias id\n");
+		return dsp_id;
+	}
+
+	/* construct a custom default fw name - subject to change in future */
+	name_len = strlen(template); /* assuming a single digit alias */
+	fw_name = devm_kzalloc(dev, name_len, GFP_KERNEL);
+	if (!fw_name)
+		return -ENOMEM;
+	snprintf(fw_name, name_len, template, dsp_id);
+
+	rproc = rproc_alloc(dev, dev_name(dev), &keystone_rproc_ops, fw_name,
+			    sizeof(*ksproc));
+	if (!rproc)
+		return -ENOMEM;
+
+	rproc->has_iommu = false;
+	ksproc = rproc->priv;
+	ksproc->rproc = rproc;
+	ksproc->dev = dev;
+
+	ret = keystone_rproc_of_get_dev_syscon(pdev, ksproc);
+	if (ret)
+		goto free_rproc;
+
+	ksproc->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(ksproc->reset)) {
+		ret = PTR_ERR(ksproc->reset);
+		goto free_rproc;
+	}
+
+	/* enable clock for accessing DSP internal memories */
+	pm_runtime_enable(dev);
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		dev_err(dev, "failed to enable clock, status = %d\n", ret);
+		pm_runtime_put_noidle(dev);
+		goto disable_rpm;
+	}
+
+	ret = keystone_rproc_of_get_memories(pdev, ksproc);
+	if (ret)
+		goto disable_clk;
+
+	ksproc->irq_ring = platform_get_irq_byname(pdev, "vring");
+	if (ksproc->irq_ring < 0) {
+		ret = ksproc->irq_ring;
+		dev_err(dev, "failed to get vring interrupt, status = %d\n",
+			ret);
+		goto disable_clk;
+	}
+
+	ksproc->irq_fault = platform_get_irq_byname(pdev, "exception");
+	if (ksproc->irq_fault < 0) {
+		ret = ksproc->irq_fault;
+		dev_err(dev, "failed to get exception interrupt, status = %d\n",
+			ret);
+		goto disable_clk;
+	}
+
+	ksproc->kick_gpio = of_get_named_gpio_flags(np, "kick-gpios", 0, NULL);
+	if (ksproc->kick_gpio < 0) {
+		ret = ksproc->kick_gpio;
+		dev_err(dev, "failed to get gpio for virtio kicks, status = %d\n",
+			ret);
+		goto disable_clk;
+	}
+
+	if (of_reserved_mem_device_init(dev))
+		dev_warn(dev, "device does not have specific CMA pool\n");
+
+	ret = rproc_add(rproc);
+	if (ret) {
+		dev_err(dev, "failed to add register device with remoteproc core, status = %d\n",
+			ret);
+		goto release_mem;
+	}
+
+	platform_set_drvdata(pdev, ksproc);
+
+	return 0;
+
+release_mem:
+	of_reserved_mem_device_release(dev);
+disable_clk:
+	pm_runtime_put_sync(dev);
+disable_rpm:
+	pm_runtime_disable(dev);
+free_rproc:
+	rproc_free(rproc);
+	return ret;
+}
+
+static int keystone_rproc_remove(struct platform_device *pdev)
+{
+	struct keystone_rproc *ksproc = platform_get_drvdata(pdev);
+
+	rproc_del(ksproc->rproc);
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	rproc_free(ksproc->rproc);
+	of_reserved_mem_device_release(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id keystone_rproc_of_match[] = {
+	{ .compatible = "ti,k2hk-dsp", },
+	{ .compatible = "ti,k2l-dsp", },
+	{ .compatible = "ti,k2e-dsp", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, keystone_rproc_of_match);
+
+static struct platform_driver keystone_rproc_driver = {
+	.probe	= keystone_rproc_probe,
+	.remove	= keystone_rproc_remove,
+	.driver	= {
+		.name = "keystone-rproc",
+		.of_match_table = keystone_rproc_of_match,
+	},
+};
+
+module_platform_driver(keystone_rproc_driver);
+
+MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI Keystone DSP Remoteproc driver");

From 11d2a2ffa881c971bab065d6e38c33849f35e7bc Mon Sep 17 00:00:00 2001
From: "Andrew F. Davis" <afd@ti.com>
Date: Tue, 13 Jun 2017 18:45:13 -0500
Subject: [PATCH 09/12] remoteproc/keystone: Ensure the DSPs are in reset in
 probe

The DSPs are expected to be in reset when the driver probes a device.
If the DSPs are out of reset in probe, the system may crash when the
firmware is being loaded. So, add a check to make sure the DSP resets
are asserted, and if not, throw a eye-catchy warning and assert the
resets specifically.

Signed-off-by: Andrew F. Davis <afd@ti.com>
[s-anna@ti.com: replace warning with a WARN]
Signed-off-by: Suman Anna <s-anna@ti.com>
Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/remoteproc/keystone_remoteproc.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c
index 6e09ef76f7c7..5f776bfd674a 100644
--- a/drivers/remoteproc/keystone_remoteproc.c
+++ b/drivers/remoteproc/keystone_remoteproc.c
@@ -456,6 +456,16 @@ static int keystone_rproc_probe(struct platform_device *pdev)
 	if (of_reserved_mem_device_init(dev))
 		dev_warn(dev, "device does not have specific CMA pool\n");
 
+	/* ensure the DSP is in reset before loading firmware */
+	ret = reset_control_status(ksproc->reset);
+	if (ret < 0) {
+		dev_err(dev, "failed to get reset status, status = %d\n", ret);
+		goto release_mem;
+	} else if (ret == 0) {
+		WARN(1, "device is not in reset\n");
+		keystone_rproc_dsp_reset(ksproc);
+	}
+
 	ret = rproc_add(rproc);
 	if (ret) {
 		dev_err(dev, "failed to add register device with remoteproc core, status = %d\n",

From 384700d4653e7ad6d774bf2f217aaca1bcbe62e8 Mon Sep 17 00:00:00 2001
From: Suman Anna <s-anna@ti.com>
Date: Tue, 27 Jun 2017 17:46:08 -0500
Subject: [PATCH 10/12] remoteproc: Drop VIRTUALIZATION dependency from
 REMOTEPROC

A dependency to VIRTUALIZATION has been added to REMOTEPROC in v3.10
kernel in commit b9777859ec01 ("remoteproc: fix kconfig dependencies
for VIRTIO") to resolve Kconfig warnings due to the inclusion of the
virtio configuration file from the ARM's KVM config file. The KVM
config was fixed properly in the subsequent release in commit
8bd4ffd6b3a9 ("ARM: kvm: don't include drivers/virtio/Kconfig").
So, drop this unneeded VIRTUALIZATION dependency from REMOTEPROC.

Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/remoteproc/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index b950e6cd4ba2..ea344fbf378a 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -6,7 +6,6 @@ config REMOTEPROC
 	select CRC32
 	select FW_LOADER
 	select VIRTIO
-	select VIRTUALIZATION
 	help
 	  Support for remote processors (such as DSP coprocessors). These
 	  are mainly used on embedded systems.

From e3f37c5ed70ca3902ab84762763e18abb742f627 Mon Sep 17 00:00:00 2001
From: Suman Anna <s-anna@ti.com>
Date: Tue, 27 Jun 2017 17:46:09 -0500
Subject: [PATCH 11/12] remoteproc: Drop redundant REMOTEPROC dependency from
 driver Kconfigs

All the remoteproc platform driver Kconfig symbols are defined and
included under an if REMOTEPROC condition, so the dependency on
REMOTEPROC is implicit and they do not need an explicit 'depends
on REMOTEPROC' line. So, clean these up.

Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/remoteproc/Kconfig | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index ea344fbf378a..945c1574f896 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -17,7 +17,6 @@ config OMAP_REMOTEPROC
 	depends on HAS_DMA
 	depends on ARCH_OMAP4 || SOC_OMAP5
 	depends on OMAP_IOMMU
-	depends on REMOTEPROC
 	select MAILBOX
 	select OMAP2PLUS_MBOX
 	select RPMSG_VIRTIO
@@ -37,7 +36,6 @@ config OMAP_REMOTEPROC
 config WKUP_M3_RPROC
 	tristate "AMx3xx Wakeup M3 remoteproc support"
 	depends on SOC_AM33XX || SOC_AM43XX
-	depends on REMOTEPROC
 	help
 	  Say y here to support Wakeup M3 remote processor on TI AM33xx
 	  and AM43xx family of SoCs.
@@ -50,7 +48,6 @@ config WKUP_M3_RPROC
 config DA8XX_REMOTEPROC
 	tristate "DA8xx/OMAP-L13x remoteproc support"
 	depends on ARCH_DAVINCI_DA8XX
-	depends on REMOTEPROC
 	depends on DMA_CMA
 	select RPMSG_VIRTIO
 	help
@@ -74,7 +71,6 @@ config KEYSTONE_REMOTEPROC
 	tristate "Keystone Remoteproc support"
 	depends on ARCH_KEYSTONE
 	depends on RESET_CONTROLLER
-	depends on REMOTEPROC
 	select RPMSG_VIRTIO
 	help
 	  Say Y here here to support Keystone remote processors (DSP)
@@ -86,7 +82,6 @@ config KEYSTONE_REMOTEPROC
 config QCOM_ADSP_PIL
 	tristate "Qualcomm ADSP Peripheral Image Loader"
 	depends on OF && ARCH_QCOM
-	depends on REMOTEPROC
 	depends on QCOM_SMEM
 	depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
 	select MFD_SYSCON
@@ -104,7 +99,6 @@ config QCOM_Q6V5_PIL
 	tristate "Qualcomm Hexagon V5 Peripherial Image Loader"
 	depends on OF && ARCH_QCOM
 	depends on QCOM_SMEM
-	depends on REMOTEPROC
 	depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
 	select MFD_SYSCON
 	select QCOM_RPROC_COMMON
@@ -118,7 +112,6 @@ config QCOM_WCNSS_PIL
 	depends on OF && ARCH_QCOM
 	depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
 	depends on QCOM_SMEM
-	depends on REMOTEPROC
 	select QCOM_MDT_LOADER
 	select QCOM_RPROC_COMMON
 	select QCOM_SCM
@@ -129,7 +122,6 @@ config QCOM_WCNSS_PIL
 config ST_REMOTEPROC
 	tristate "ST remoteproc support"
 	depends on ARCH_STI
-	depends on REMOTEPROC
 	select MAILBOX
 	select STI_MBOX
 	select RPMSG_VIRTIO
@@ -140,7 +132,6 @@ config ST_REMOTEPROC
 
 config ST_SLIM_REMOTEPROC
 	tristate
-	depends on REMOTEPROC
 
 endif # REMOTEPROC
 

From b0af7b7dbedd45367f8f1d91049c30b251ad528f Mon Sep 17 00:00:00 2001
From: Suman Anna <s-anna@ti.com>
Date: Tue, 27 Jun 2017 17:46:10 -0500
Subject: [PATCH 12/12] remoteproc/keystone: Fix circular dependencies for ARM
 configs

Drop the dependency on RESET_CONTROLLER for the Keystone remoteproc
driver to resolve some circular dependencies around different choices
for RESET_CONTROLLER on common ARM configs. This dependency is
inherent as the RESET_CONTROLLER will be enabled due to the enabled
ARCH_HAS_RESET_CONTROLLER for ARCH_KEYSTONE.

Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/remoteproc/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 945c1574f896..8891a8e50f12 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -70,7 +70,6 @@ config DA8XX_REMOTEPROC
 config KEYSTONE_REMOTEPROC
 	tristate "Keystone Remoteproc support"
 	depends on ARCH_KEYSTONE
-	depends on RESET_CONTROLLER
 	select RPMSG_VIRTIO
 	help
 	  Say Y here here to support Keystone remote processors (DSP)