devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] remoteproc: add CSRatlas7 remoteproc driver
@ 2015-09-15  5:37 Barry Song
       [not found] ` <1442295429-19137-1-git-send-email-21cnbao-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 4+ messages in thread
From: Barry Song @ 2015-09-15  5:37 UTC (permalink / raw)
  To: ohad-Ix1uc/W3ht7QT0dZR+AlfA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: workgroup.linux-kQvG35nSl+M, Barry Song

From: Barry Song <Baohua.Song-kQvG35nSl+M@public.gmane.org>

The first two patches make remoteproc support non-slave remote processors.
the last one adds CSRatlas7 support.

Wei Chen (3):
  drivers:remoteproc:support predefined vq notifyid
  drivers:remoteproc:support always on remote processor
  remoteproc: add CSRatlas7 remoteproc driver

 .../bindings/remoteproc/sirf,remoteproc.txt        |  33 ++
 drivers/remoteproc/Kconfig                         |  13 +
 drivers/remoteproc/Makefile                        |   1 +
 drivers/remoteproc/remoteproc_core.c               |  21 +-
 drivers/remoteproc/remoteproc_virtio.c             |   8 +
 drivers/remoteproc/sirf_remoteproc.c               | 467 +++++++++++++++++++++
 include/linux/remoteproc.h                         |   4 +-
 7 files changed, 541 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/remoteproc/sirf,remoteproc.txt
 create mode 100644 drivers/remoteproc/sirf_remoteproc.c

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 1/3] drivers:remoteproc:support predefined vq notifyid
       [not found] ` <1442295429-19137-1-git-send-email-21cnbao-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2015-09-15  5:37   ` Barry Song
  2015-09-15  5:37   ` [PATCH 2/3] drivers:remoteproc:support always on remote processor Barry Song
  2015-09-15  5:37   ` [PATCH 3/3] remoteproc: add CSRatlas7 remoteproc driver Barry Song
  2 siblings, 0 replies; 4+ messages in thread
From: Barry Song @ 2015-09-15  5:37 UTC (permalink / raw)
  To: ohad-Ix1uc/W3ht7QT0dZR+AlfA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: workgroup.linux-kQvG35nSl+M, Wei Chen, Barry Song

From: Wei Chen <Wei.Chen-kQvG35nSl+M@public.gmane.org>

In current rproc use scenario, the vq notifyid
will be allocated by Linux, and write back this
notifyid to RSC table to tell DSP.

But in some scenarios, we might meet the DSP
predefined the vq notifyid. In these scenarios,
the rproc have to read predefined vq notifyid
from RSC table, and then request a same notifyid
in Linux side.

Signed-off-by: Wei Chen <Wei.Chen-kQvG35nSl+M@public.gmane.org>
Signed-off-by: Barry Song <Baohua.Song-kQvG35nSl+M@public.gmane.org>
---
 drivers/remoteproc/remoteproc_core.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 8b3130f..8f82417 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -206,7 +206,7 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
 	struct fw_rsc_vdev *rsc;
 	dma_addr_t dma;
 	void *va;
-	int ret, size, notifyid;
+	int ret, size, notifyid, pre_nid;
 
 	/* actual size of vring (in bytes) */
 	size = PAGE_ALIGN(vring_size(rvring->len, rvring->align));
@@ -222,11 +222,16 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
 	}
 
 	/*
+	 * read predefined notifyids (via resource table)
+	 */
+	rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
+	pre_nid = rsc->vring[i].notifyid;
+
+	/*
 	 * Assign an rproc-wide unique index for this vring
 	 * TODO: assign a notifyid for rvdev updates as well
-	 * TODO: support predefined notifyids (via resource table)
 	 */
-	ret = idr_alloc(&rproc->notifyids, rvring, 0, 0, GFP_KERNEL);
+	ret = idr_alloc(&rproc->notifyids, rvring, pre_nid, 0, GFP_KERNEL);
 	if (ret < 0) {
 		dev_err(dev, "idr_alloc failed: %d\n", ret);
 		dma_free_coherent(dev->parent, size, va, dma);
@@ -247,9 +252,10 @@ int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
 	 * set up the iommu. In this case the device address (da) will
 	 * hold the physical address and not the device address.
 	 */
-	rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
 	rsc->vring[i].da = dma;
-	rsc->vring[i].notifyid = notifyid;
+	/* If notifyid is not predefined, write back to rsc */
+	if (!pre_nid)
+		rsc->vring[i].notifyid = notifyid;
 	return 0;
 }
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 2/3] drivers:remoteproc:support always on remote processor
       [not found] ` <1442295429-19137-1-git-send-email-21cnbao-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2015-09-15  5:37   ` [PATCH 1/3] drivers:remoteproc:support predefined vq notifyid Barry Song
@ 2015-09-15  5:37   ` Barry Song
  2015-09-15  5:37   ` [PATCH 3/3] remoteproc: add CSRatlas7 remoteproc driver Barry Song
  2 siblings, 0 replies; 4+ messages in thread
From: Barry Song @ 2015-09-15  5:37 UTC (permalink / raw)
  To: ohad-Ix1uc/W3ht7QT0dZR+AlfA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: workgroup.linux-kQvG35nSl+M, Wei Chen, Barry Song

From: Wei Chen <Wei.Chen-kQvG35nSl+M@public.gmane.org>

In current rproc use scenarios, the Linux side controls
the lifecycle of the remote processors, just like boot,
start, shutdown.

But in some scenarios, we require the remote processors
to be powered and booted before Linux bring up. In
additional, we might have require the remote processors
could not be shutdown, if it would be shutdown, the Linux
should be shutdown too.

In above scenarios, we have make remoteproc to support
always on remote processor. This kind of remote processor
control its lifecycle by itself.

Signed-off-by: Wei Chen <Wei.Chen-kQvG35nSl+M@public.gmane.org>
Signed-off-by: Barry Song <Baohua.Song-kQvG35nSl+M@public.gmane.org>
---
 drivers/remoteproc/remoteproc_core.c   | 5 +++++
 drivers/remoteproc/remoteproc_virtio.c | 8 ++++++++
 include/linux/remoteproc.h             | 4 +++-
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 8f82417..2307a26 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -917,6 +917,10 @@ static void rproc_fw_config_virtio(const struct firmware *fw, void *context)
 
 	rproc->table_csum = crc32(0, table, tablesz);
 
+	if (rproc->state == RPROC_ALWAYS_ON) {
+		rproc->table_ptr = table;
+		goto handl_res;
+	}
 	/*
 	 * Create a copy of the resource table. When a virtio device starts
 	 * and calls vring_new_virtqueue() the address of the allocated vring
@@ -929,6 +933,7 @@ static void rproc_fw_config_virtio(const struct firmware *fw, void *context)
 
 	rproc->table_ptr = rproc->cached_table;
 
+handl_res:
 	/* count the number of notify-ids */
 	rproc->max_notifyid = -1;
 	ret = rproc_handle_resources(rproc, tablesz,
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index e1a1023..2eba600 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -138,9 +138,13 @@ static void rproc_virtio_del_vqs(struct virtio_device *vdev)
 {
 	struct rproc *rproc = vdev_to_rproc(vdev);
 
+	if (rproc->state == RPROC_ALWAYS_ON)
+		goto del_vqs;
+
 	/* power down the remote processor before deleting vqs */
 	rproc_shutdown(rproc);
 
+del_vqs:
 	__rproc_virtio_del_vqs(vdev);
 }
 
@@ -160,6 +164,10 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		}
 	}
 
+	/* always on rproc */
+	if (rproc->state == RPROC_ALWAYS_ON)
+		return 0;
+
 	/* now that the vqs are all set, boot the remote processor */
 	ret = rproc_boot(rproc);
 	if (ret) {
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 9c4e138..9d783eb 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -346,6 +346,7 @@ struct rproc_ops {
  *			a message.
  * @RPROC_RUNNING:	device is up and running
  * @RPROC_CRASHED:	device has crashed; need to start recovery
+ * @RPROC_ALWAYS_ON:	device is always on, doesn't need to power on/off.
  * @RPROC_LAST:		just keep this one at the end
  *
  * Please note that the values of these states are used as indices
@@ -359,7 +360,8 @@ enum rproc_state {
 	RPROC_SUSPENDED	= 1,
 	RPROC_RUNNING	= 2,
 	RPROC_CRASHED	= 3,
-	RPROC_LAST	= 4,
+	RPROC_ALWAYS_ON = 4,
+	RPROC_LAST	= 5,
 };
 
 /**
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 3/3] remoteproc: add CSRatlas7 remoteproc driver
       [not found] ` <1442295429-19137-1-git-send-email-21cnbao-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2015-09-15  5:37   ` [PATCH 1/3] drivers:remoteproc:support predefined vq notifyid Barry Song
  2015-09-15  5:37   ` [PATCH 2/3] drivers:remoteproc:support always on remote processor Barry Song
@ 2015-09-15  5:37   ` Barry Song
  2 siblings, 0 replies; 4+ messages in thread
From: Barry Song @ 2015-09-15  5:37 UTC (permalink / raw)
  To: ohad-Ix1uc/W3ht7QT0dZR+AlfA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: workgroup.linux-kQvG35nSl+M, Wei Chen, Barry Song

From: Wei Chen <Wei.Chen-kQvG35nSl+M@public.gmane.org>

In CSRaltas7, Cortex-A7 uses this proc to communicate with Cortex-M3.
But M3 doesn't have to be a slave, it can boot indenpently or depend
on Linux to load firmware for it.

we reserve a memory for data and resource descriptors in DRAM.

Signed-off-by: Wei Chen <Wei.Chen-kQvG35nSl+M@public.gmane.org>
Signed-off-by: Barry Song <Baohua.Song-kQvG35nSl+M@public.gmane.org>
---
 .../bindings/remoteproc/sirf,remoteproc.txt        |  33 ++
 drivers/remoteproc/Kconfig                         |  13 +
 drivers/remoteproc/Makefile                        |   1 +
 drivers/remoteproc/sirf_remoteproc.c               | 467 +++++++++++++++++++++
 4 files changed, 514 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/remoteproc/sirf,remoteproc.txt
 create mode 100644 drivers/remoteproc/sirf_remoteproc.c

diff --git a/Documentation/devicetree/bindings/remoteproc/sirf,remoteproc.txt b/Documentation/devicetree/bindings/remoteproc/sirf,remoteproc.txt
new file mode 100644
index 0000000..409fb40
--- /dev/null
+++ b/Documentation/devicetree/bindings/remoteproc/sirf,remoteproc.txt
@@ -0,0 +1,33 @@
+SIRF Atlas7 Remote processor Device Binding
+------------------------------------------------
+1) Main node
+	Required properties :
+
+	- compatible : "sirf,atlas7-rproc"
+
+	- reg : register address of remoteproc device
+
+	- interrupts: the irq number this rproc need to handle.
+
+	- hwlocks: the hwlocks this rproc to used to protect data
+	  between two processors.
+
+	- memory-region: the memory region, which is used to store virtual
+	  device info, fifo buffers and share memory between two processors.
+
+	- firmware: the firmware file that will be loaded to remote processor.
+
+Please refer to ../reserved-memory/reserved-memory.txt for details of the
+memory-region bindings.
+Please refer to ../hwlock/hwlock.txt for details of the hwlock bindings.
+
+2) Example:
+			ns_m3_rproc@0 {
+				compatible = "sirf,atlas7-rproc";
+				reg = <0x13240108 0x4>,
+					<0x13240208 0x4>;
+				interrupts = <0 123 0>;
+				hwlocks = <&hwlock 0>, <&hwlock 1>;
+				memory-region = <&ipc_mem0>;
+				firmware = "RTOSDemo.bin";
+			};
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 28c711f..aeabbfa 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -77,4 +77,17 @@ config DA8XX_REMOTEPROC
 	  It's safe to say n here if you're not interested in multimedia
 	  offloading.
 
+config SIRF_REMOTEPROC
+	tristate "CSR atals7 remoteproc support"
+	depends on ARCH_ATLAS7
+	select REMOTEPROC
+	select RPMSG
+	default y
+	help
+	  Say y or m here to support CSR Atlas7 Inter-Processors
+	  Communication driver via remote processor framework.
+
+	  This can be either built-in or a loadable module.
+	  If unsure say N.
+
 endmenu
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 81b04d1..8cc4790 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_OMAP_REMOTEPROC)		+= omap_remoteproc.o
 obj-$(CONFIG_STE_MODEM_RPROC)	 	+= ste_modem_rproc.o
 obj-$(CONFIG_WKUP_M3_RPROC)		+= wkup_m3_rproc.o
 obj-$(CONFIG_DA8XX_REMOTEPROC)		+= da8xx_remoteproc.o
+obj-$(CONFIG_SIRF_REMOTEPROC)	+= sirf_remoteproc.o
diff --git a/drivers/remoteproc/sirf_remoteproc.c b/drivers/remoteproc/sirf_remoteproc.c
new file mode 100644
index 0000000..cb7568d
--- /dev/null
+++ b/drivers/remoteproc/sirf_remoteproc.c
@@ -0,0 +1,467 @@
+/*
+ * SIRF Remote processor machine-specific module
+ *
+ * Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/hwspinlock.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+#include <linux/remoteproc.h>
+
+#include "remoteproc_internal.h"
+
+struct fifo_buffer {
+	struct hwspinlock *lock;
+	unsigned char *buffer;
+	u32 w_pos;
+	u32 r_pos;
+	u32 size;
+	u32 *count; /* pointer to shared memory */
+};
+
+static int fifo_write(struct fifo_buffer *fifo,
+		const void *data, u32 len)
+{
+	int err;
+	u32 overflow, count;
+	ulong flags;
+
+	err = hwspin_lock_timeout_irqsave(fifo->lock, 100, &flags);
+	if (err) {
+		pr_err("%s, Get hwspinlock failed!err= %d\n",
+			__func__, err);
+		WARN_ON(err);
+		return -EBUSY;
+	}
+
+	if (len > fifo->size) {
+		err = -EFBIG;
+		goto err_exit;
+	}
+
+	count = *fifo->count;
+	overflow = len > (fifo->size - count);
+	if (overflow) {
+		/* previous data hasn't been read, FIFO busy */
+		err = -EBUSY;
+		goto err_exit;
+	}
+
+	/* copy data to fifo buffer */
+	memcpy(fifo->buffer + fifo->w_pos, data, len);
+	/* update fifo position */
+	fifo->w_pos = (fifo->w_pos + len) % fifo->size;
+	*fifo->count = count + len;
+
+	hwspin_unlock_irqrestore(fifo->lock, &flags);
+	err = 0;
+
+err_exit:
+	return err;
+}
+
+static int fifo_read(struct fifo_buffer *fifo,
+		void *data, u32 len)
+{
+	int err;
+	u32 count;
+
+	err = hwspin_lock_timeout(fifo->lock, 100);
+	if (err) {
+		pr_err("%s, Get hwspinlock failed!err= %d\n",
+			__func__, err);
+			WARN_ON(err);
+		return err;
+	}
+
+	count = *fifo->count;
+	if (!count) {
+		err = -ENOSPC;
+		goto err_exit;
+	}
+
+	if (len > count)
+		len = count;
+
+	/* copy data from fifo buffer */
+	memcpy(data, fifo->buffer + fifo->r_pos, len);
+	/* update fifo position */
+	fifo->r_pos = (fifo->r_pos + len) % fifo->size;
+	*fifo->count = count - len;
+
+	err = 0;
+
+err_exit:
+	hwspin_unlock(fifo->lock);
+
+	return err;
+}
+
+static int fifo_init(struct fifo_buffer *fifo, void *buffer,
+			int size, int hwlock_id)
+{
+
+	fifo->lock = hwspin_lock_request_specific(hwlock_id);
+	if (!fifo->lock) {
+		pr_err("%s:Could not request specific hwspin lock!\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	fifo->count = (u32 *)buffer;
+	fifo->buffer = (unsigned char *)(buffer + sizeof(u32));
+	fifo->w_pos = 0;
+	fifo->r_pos = 0;
+	fifo->size = size - sizeof(u32);
+	*fifo->count = 0;
+
+	return 0;
+}
+
+/* FIFO shared memory has been divide into 2 logical channels */
+#define FIFO_LOGIC_CHN_0	0
+#define FIFO_LOGIC_CHN_1	1
+
+#define RPROC_DEF_FIFO_SIZE	0x1000
+
+/**
+ * struct sirf_rproc - SIRF remote processor instance state
+ * @rproc: rproc handle
+ * @rsc_dma: the dma address of the resource memory, include fifo.
+ * @rsc_size: resource memory size.
+ * @table_ptr: the virtual address of rproc resource table area.
+ * @table_len: the length of rproc resource table.
+ * @fifo_rx_lock: lock for fifo receive data.
+ * @fifo_tx_lock: lock for fifo send data.
+ * @tx_avail_wq: wait queue of send data when fifo is busy.
+ * @fifo_avail: fifo status for send data.
+ *		fifo can send data when fifo_avail is true.
+ * @fifo_msg_rx: memory address for fifo arrived data.
+ * @fifo_msg_tx: memory address for fifo send data.
+ * @fifo_iomemmem: iomem address for fifo register.
+ * @irq: the irq number of fifo allocated in backend OS.
+ * @irq_gen_count: generate IRQ counter for statistic
+ * @irq_get_count: arrive IRQ counter for statistic
+ */
+struct sirf_rproc {
+	struct rproc *rproc;
+	void *rsc_dma;
+	size_t rsc_size;
+	struct resource_table *table_ptr;
+	u32 table_len;
+	void __iomem *set_reg;
+	void __iomem *clr_reg;
+	struct fifo_buffer w_fifo;
+	struct fifo_buffer r_fifo;
+	u32 w_fifo_hwlock;
+	u32 r_fifo_hwlock;
+	int irq;
+};
+
+/* Interrupt handler for IRQs from remote processor */
+static irqreturn_t sirf_rproc_ipc_isr(int irq, void *data)
+{
+	struct rproc *rproc = (struct rproc *)data;
+	struct sirf_rproc *srproc = (struct sirf_rproc *)rproc->priv;
+	u32 notifyid;
+	int err;
+
+	/* clear interrupt */
+	readl(srproc->clr_reg);
+
+	do {
+		err = fifo_read(&srproc->r_fifo, &notifyid, sizeof(notifyid));
+		if (err)
+			break;
+		rproc_vq_interrupt(rproc, notifyid);
+	} while (1);
+
+	return IRQ_HANDLED;
+}
+
+static void sirf_rproc_kick(struct rproc *rproc, int notify_id)
+{
+	struct sirf_rproc *srproc = rproc->priv;
+	int ret;
+
+	ret = fifo_write(&srproc->w_fifo, &notify_id, sizeof(notify_id));
+	if (ret) {
+		dev_err(&rproc->dev,
+			"%s could not completed, err=%d\n",
+			__func__, ret);
+		WARN_ON(1);
+	}
+
+	/*
+	 * Trigger interrupt to ask remote side to get new added data
+	 * or handle the data already in the FIFO as fast as possible.
+	 */
+	smp_mb();
+
+	writel(0x01, srproc->set_reg);
+}
+
+static const struct of_device_id sirf_rproc_dt_ids[] = {
+	{ .compatible = "sirf,atlas7-rproc", },
+	{},
+};
+
+static struct rproc_ops sirf_rproc_ops = {
+	.kick = sirf_rproc_kick,
+};
+
+static struct resource_table *
+srproc_fw_find_rsc_table(struct rproc *rproc,
+				const struct firmware *fw,
+				int *tablesz)
+{
+	struct sirf_rproc *srproc = (struct sirf_rproc *)rproc->priv;
+
+	*tablesz = srproc->table_len;
+	return srproc->table_ptr;
+}
+
+struct rproc_fw_ops sirf_rproc_fw_ops = {
+	.find_rsc_table = srproc_fw_find_rsc_table,
+};
+
+static int sirf_rproc_parse_memory(struct platform_device *pdev,
+				struct sirf_rproc *srproc)
+{
+	struct device_node *m_node;
+	struct resource res;
+	void *rsc_addr;
+	size_t rsc_size;
+	int ret;
+
+	m_node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
+	if (!m_node)
+		return -ENODEV;
+
+	ret = of_address_to_resource(m_node, 0, &res);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Convert address to resource failed! ret=%d\n",
+			ret);
+		return ret;
+	}
+
+	rsc_addr = (void *)__phys_to_virt(res.start);
+	rsc_size = res.end - res.start + 1;
+
+	/* create a coherent mapping */
+	srproc->rsc_dma = dma_common_contiguous_remap(virt_to_page(rsc_addr),
+				rsc_size, VM_IO,
+				pgprot_dmacoherent(PAGE_KERNEL),
+				NULL);
+	if (!srproc->rsc_dma)
+		return -ENOMEM;
+
+	srproc->rsc_size = rsc_size;
+
+	return 0;
+}
+
+static int sirf_rproc_parse_args(struct platform_device *pdev,
+				struct sirf_rproc *srproc)
+{
+	void *tx_buffer, *rx_buffer;
+	struct resource *res;
+	int ret;
+
+	/* retrieve trigger interrupt io base */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	srproc->set_reg = devm_ioremap_resource(&pdev->dev, res);
+	if (!srproc->set_reg) {
+		dev_err(&pdev->dev,
+			"Unable to map rproc trigger interrupt registers!\n");
+		return -ENOMEM;
+	}
+
+	/* retrieve clear interrupt io base */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	srproc->clr_reg = devm_ioremap_resource(&pdev->dev, res);
+	if (!srproc->clr_reg) {
+		dev_err(&pdev->dev,
+			"Unable to map rproc clear interrupt registers!\n");
+		return -ENOMEM;
+	}
+
+	ret = of_irq_get(pdev->dev.of_node, 0);
+	if (ret == -EPROBE_DEFER) {
+		dev_err(&pdev->dev,
+			"Unable to find IRQ number. ret=%d\n", ret);
+		return ret;
+	}
+	srproc->irq = ret;
+
+	/* Request hwlocks for rproc */
+	srproc->w_fifo_hwlock = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
+	if (srproc->w_fifo_hwlock < 0) {
+		ret = srproc->w_fifo_hwlock;
+		dev_err(&pdev->dev,
+			"Unable to get hwlock for write fifo. ret=%d\n", ret);
+		goto failed;
+	}
+
+	srproc->r_fifo_hwlock = of_hwspin_lock_get_id(pdev->dev.of_node, 1);
+	if (srproc->r_fifo_hwlock < 0) {
+		ret = srproc->r_fifo_hwlock;
+		dev_err(&pdev->dev,
+			"Unable to get hwlock for read fifo. ret=%d\n", ret);
+		goto failed;
+	}
+
+	/* Parse share memory information */
+	ret = sirf_rproc_parse_memory(pdev, srproc);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Unable to setup ipc share memory info. ret=%d\n",
+			ret);
+		goto failed;
+	}
+	srproc->table_ptr = srproc->rsc_dma;
+
+	/* check resource table size */
+	if (RPROC_DEF_FIFO_SIZE * 2 >= srproc->rsc_size) {
+		dev_err(&pdev->dev,
+			"There is no memory left for resource table!\n");
+		ret = -EINVAL;
+		goto free_rsc;
+	}
+
+	if (srproc->table_ptr->ver != 1) {
+		dev_err(&pdev->dev,
+			"unsupported fw ver: %d\n",
+			srproc->table_ptr->ver);
+		ret = -EINVAL;
+		goto free_rsc;
+	}
+
+	srproc->table_len = srproc->rsc_size - RPROC_DEF_FIFO_SIZE * 2;
+	tx_buffer = srproc->rsc_dma + srproc->table_len +
+		RPROC_DEF_FIFO_SIZE * FIFO_LOGIC_CHN_0;
+	rx_buffer = srproc->rsc_dma + srproc->table_len +
+		RPROC_DEF_FIFO_SIZE * FIFO_LOGIC_CHN_1;
+
+	ret = fifo_init(&srproc->w_fifo, tx_buffer,
+			RPROC_DEF_FIFO_SIZE, srproc->w_fifo_hwlock);
+	if (ret)
+		goto free_rsc;
+
+	ret = fifo_init(&srproc->r_fifo, rx_buffer,
+			RPROC_DEF_FIFO_SIZE, srproc->r_fifo_hwlock);
+	if (ret)
+		goto free_rsc;
+
+	return 0;
+
+free_rsc:
+	dma_common_free_remap(srproc->rsc_dma,
+			srproc->rsc_size, VM_IO);
+	srproc->table_ptr = NULL;
+	srproc->rsc_dma = NULL;
+
+failed:
+	return ret;
+}
+
+static int sirf_rproc_remove(struct platform_device *pdev)
+{
+	struct rproc *rproc = platform_get_drvdata(pdev);
+	struct sirf_rproc *srproc = rproc->priv;
+
+	dma_common_free_remap(srproc->rsc_dma,
+				srproc->rsc_size, VM_IO);
+
+	rproc->table_ptr = 0;
+
+	rproc_del(rproc);
+	rproc_put(rproc);
+
+	return 0;
+}
+
+static int sirf_rproc_probe(struct platform_device *pdev)
+{
+	struct sirf_rproc *srproc;
+	struct rproc *rproc;
+	const char *fw;
+	int ret;
+
+	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret);
+		return ret;
+	}
+
+	ret = of_property_read_string(pdev->dev.of_node, "firmware", &fw);
+	if (ret)
+		fw = NULL; /* Set to NULL, rproc core will use default name */
+
+	rproc = rproc_alloc(&pdev->dev, dev_name(&pdev->dev), &sirf_rproc_ops,
+				fw, sizeof(*srproc));
+	if (!rproc)
+		return -ENOMEM;
+
+	srproc = rproc->priv;
+	srproc->rproc = rproc;
+	/* Setup sirf rproc firmware ops */
+	rproc->fw_ops = &sirf_rproc_fw_ops;
+	/* This rproc is always on */
+	rproc->state = RPROC_ALWAYS_ON;
+
+	ret = sirf_rproc_parse_args(pdev, srproc);
+	if (ret)
+		goto free_rproc;
+
+	ret = devm_request_threaded_irq(&rproc->dev, srproc->irq,
+				NULL, sirf_rproc_ipc_isr,
+				IRQF_ONESHOT,
+				dev_name(&pdev->dev), rproc);
+	if (ret) {
+		dev_err(&rproc->dev,
+			"request_threaded_irq %d error: %d\n",
+			srproc->irq, ret);
+		goto free_rproc;
+	}
+
+	ret = rproc_add(rproc);
+	if (ret) {
+		dev_err(&rproc->dev, "rproc_add failed: %d\n", ret);
+		goto free_rproc;
+	}
+
+	platform_set_drvdata(pdev, rproc);
+
+	return 0;
+
+free_rproc:
+	rproc_put(rproc);
+
+	return ret;
+}
+
+static struct platform_driver sirf_rproc_driver = {
+	.probe = sirf_rproc_probe,
+	.remove = sirf_rproc_remove,
+	.driver = {
+		.name = "sirfsoc_remoteproc",
+		.of_match_table = of_match_ptr(sirf_rproc_dt_ids),
+	},
+};
+module_platform_driver(sirf_rproc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("SIRF Remote Processor driver");
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2015-09-15  5:37 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-15  5:37 [PATCH 0/3] remoteproc: add CSRatlas7 remoteproc driver Barry Song
     [not found] ` <1442295429-19137-1-git-send-email-21cnbao-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2015-09-15  5:37   ` [PATCH 1/3] drivers:remoteproc:support predefined vq notifyid Barry Song
2015-09-15  5:37   ` [PATCH 2/3] drivers:remoteproc:support always on remote processor Barry Song
2015-09-15  5:37   ` [PATCH 3/3] remoteproc: add CSRatlas7 remoteproc driver Barry Song

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).