linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@suse.de>
To: linux-kernel@vger.kernel.org
Cc: Pratheesh Gangadhar <pratheesh@ti.com>,
	"Hans J. Koch" <hjk@hansjkoch.de>,
	Greg Kroah-Hartman <gregkh@suse.de>
Subject: [PATCH 40/50] UIO: add PRUSS UIO driver support
Date: Wed, 16 Mar 2011 14:11:18 -0700	[thread overview]
Message-ID: <1300309888-5028-40-git-send-email-gregkh@suse.de> (raw)
In-Reply-To: <1300309888-5028-1-git-send-email-gregkh@suse.de>

From: Pratheesh Gangadhar <pratheesh@ti.com>

This patch implements PRUSS (Programmable Real-time Unit Sub System)
UIO driver which exports SOC resources associated with PRUSS like
I/O, memories and IRQs to user space. PRUSS is dual 32-bit RISC
processors which is efficient in performing embedded tasks that
require manipulation of packed memory mapped data structures and
handling system events that have tight real time constraints. This
driver is currently supported on Texas Instruments DA850, AM18xx and
OMAP-L138 devices.
For example, PRUSS runs firmware for real-time critical industrial
communication data link layer and communicates with application stack
running in user space via shared memory and IRQs.

Signed-off-by: Pratheesh Gangadhar <pratheesh@ti.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Hans J. Koch <hjk@hansjkoch.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/uio/Kconfig                     |   17 ++
 drivers/uio/Makefile                    |    1 +
 drivers/uio/uio_pruss.c                 |  247 +++++++++++++++++++++++++++++++
 include/linux/platform_data/uio_pruss.h |   25 +++
 4 files changed, 290 insertions(+), 0 deletions(-)
 create mode 100644 drivers/uio/uio_pruss.c
 create mode 100644 include/linux/platform_data/uio_pruss.h

diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index bb44079..6f3ea9b 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -94,4 +94,21 @@ config UIO_NETX
 	  To compile this driver as a module, choose M here; the module
 	  will be called uio_netx.
 
+config UIO_PRUSS
+	tristate "Texas Instruments PRUSS driver"
+	depends on ARCH_DAVINCI_DA850
+	help
+	  PRUSS driver for OMAPL138/DA850/AM18XX devices
+	  PRUSS driver requires user space components, examples and user space
+	  driver is available from below SVN repo - you may use anonymous login
+
+	  https://gforge.ti.com/gf/project/pru_sw/
+
+	  More info on API is available at below wiki
+
+	  http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called uio_pruss.
+
 endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 18fd818..d4dd9a5 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_UIO_AEC)	+= uio_aec.o
 obj-$(CONFIG_UIO_SERCOS3)	+= uio_sercos3.o
 obj-$(CONFIG_UIO_PCI_GENERIC)	+= uio_pci_generic.o
 obj-$(CONFIG_UIO_NETX)	+= uio_netx.o
+obj-$(CONFIG_UIO_PRUSS)         += uio_pruss.o
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
new file mode 100644
index 0000000..daf6e77
--- /dev/null
+++ b/drivers/uio/uio_pruss.c
@@ -0,0 +1,247 @@
+/*
+ * Programmable Real-Time Unit Sub System (PRUSS) UIO driver (uio_pruss)
+ *
+ * This driver exports PRUSS host event out interrupts and PRUSS, L3 RAM,
+ * and DDR RAM to user space for applications interacting with PRUSS firmware
+ *
+ * Copyright (C) 2010-11 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 as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/uio_driver.h>
+#include <linux/platform_data/uio_pruss.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <mach/sram.h>
+
+#define DRV_NAME "pruss_uio"
+#define DRV_VERSION "1.0"
+
+static int sram_pool_sz = SZ_16K;
+module_param(sram_pool_sz, int, 0);
+MODULE_PARM_DESC(sram_pool_sz, "sram pool size to allocate ");
+
+static int extram_pool_sz = SZ_256K;
+module_param(extram_pool_sz, int, 0);
+MODULE_PARM_DESC(extram_pool_sz, "external ram pool size to allocate");
+
+/*
+ * Host event IRQ numbers from PRUSS - PRUSS can generate upto 8 interrupt
+ * events to AINTC of ARM host processor - which can be used for IPC b/w PRUSS
+ * firmware and user space application, async notification from PRU firmware
+ * to user space application
+ * 3	PRU_EVTOUT0
+ * 4	PRU_EVTOUT1
+ * 5	PRU_EVTOUT2
+ * 6	PRU_EVTOUT3
+ * 7	PRU_EVTOUT4
+ * 8	PRU_EVTOUT5
+ * 9	PRU_EVTOUT6
+ * 10	PRU_EVTOUT7
+*/
+#define MAX_PRUSS_EVT	8
+
+#define PINTC_HIDISR	0x0038
+#define PINTC_HIPIR	0x0900
+#define HIPIR_NOPEND	0x80000000
+#define PINTC_HIER	0x1500
+
+struct uio_pruss_dev {
+	struct uio_info *info;
+	struct clk *pruss_clk;
+	dma_addr_t sram_paddr;
+	dma_addr_t ddr_paddr;
+	void __iomem *prussio_vaddr;
+	void *sram_vaddr;
+	void *ddr_vaddr;
+	unsigned int hostirq_start;
+	unsigned int pintc_base;
+};
+
+static irqreturn_t pruss_handler(int irq, struct uio_info *info)
+{
+	struct uio_pruss_dev *gdev = info->priv;
+	int intr_bit = (irq - gdev->hostirq_start + 2);
+	int val, intr_mask = (1 << intr_bit);
+	void __iomem *base = gdev->prussio_vaddr + gdev->pintc_base;
+	void __iomem *intren_reg = base + PINTC_HIER;
+	void __iomem *intrdis_reg = base + PINTC_HIDISR;
+	void __iomem *intrstat_reg = base + PINTC_HIPIR + (intr_bit << 2);
+
+	val = ioread32(intren_reg);
+	/* Is interrupt enabled and active ? */
+	if (!(val & intr_mask) && (ioread32(intrstat_reg) & HIPIR_NOPEND))
+		return IRQ_NONE;
+	/* Disable interrupt */
+	iowrite32(intr_bit, intrdis_reg);
+	return IRQ_HANDLED;
+}
+
+static void pruss_cleanup(struct platform_device *dev,
+			struct uio_pruss_dev *gdev)
+{
+	int cnt;
+	struct uio_info *p = gdev->info;
+
+	for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) {
+		uio_unregister_device(p);
+		kfree(p->name);
+	}
+	iounmap(gdev->prussio_vaddr);
+	if (gdev->ddr_vaddr) {
+		dma_free_coherent(&dev->dev, extram_pool_sz, gdev->ddr_vaddr,
+			gdev->ddr_paddr);
+	}
+	if (gdev->sram_vaddr)
+		sram_free(gdev->sram_vaddr, sram_pool_sz);
+	kfree(gdev->info);
+	clk_put(gdev->pruss_clk);
+	kfree(gdev);
+}
+
+static int __devinit pruss_probe(struct platform_device *dev)
+{
+	struct uio_info *p;
+	struct uio_pruss_dev *gdev;
+	struct resource *regs_prussio;
+	int ret = -ENODEV, cnt = 0, len;
+	struct uio_pruss_pdata *pdata = dev->dev.platform_data;
+
+	gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL);
+	if (!gdev)
+		return -ENOMEM;
+
+	gdev->info = kzalloc(sizeof(*p) * MAX_PRUSS_EVT, GFP_KERNEL);
+	if (!gdev->info) {
+		kfree(gdev);
+		return -ENOMEM;
+	}
+	/* Power on PRU in case its not done as part of boot-loader */
+	gdev->pruss_clk = clk_get(&dev->dev, "pruss");
+	if (IS_ERR(gdev->pruss_clk)) {
+		dev_err(&dev->dev, "Failed to get clock\n");
+		kfree(gdev->info);
+		kfree(gdev);
+		ret = PTR_ERR(gdev->pruss_clk);
+		return ret;
+	} else {
+		clk_enable(gdev->pruss_clk);
+	}
+
+	regs_prussio = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!regs_prussio) {
+		dev_err(&dev->dev, "No PRUSS I/O resource specified\n");
+		goto out_free;
+	}
+
+	if (!regs_prussio->start) {
+		dev_err(&dev->dev, "Invalid memory resource\n");
+		goto out_free;
+	}
+
+	gdev->sram_vaddr = sram_alloc(sram_pool_sz, &(gdev->sram_paddr));
+	if (!gdev->sram_vaddr) {
+		dev_err(&dev->dev, "Could not allocate SRAM pool\n");
+		goto out_free;
+	}
+
+	gdev->ddr_vaddr = dma_alloc_coherent(&dev->dev, extram_pool_sz,
+				&(gdev->ddr_paddr), GFP_KERNEL | GFP_DMA);
+	if (!gdev->ddr_vaddr) {
+		dev_err(&dev->dev, "Could not allocate external memory\n");
+		goto out_free;
+	}
+
+	len = resource_size(regs_prussio);
+	gdev->prussio_vaddr = ioremap(regs_prussio->start, len);
+	if (!gdev->prussio_vaddr) {
+		dev_err(&dev->dev, "Can't remap PRUSS I/O  address range\n");
+		goto out_free;
+	}
+
+	gdev->pintc_base = pdata->pintc_base;
+	gdev->hostirq_start = platform_get_irq(dev, 0);
+
+	for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) {
+		p->mem[0].addr = regs_prussio->start;
+		p->mem[0].size = resource_size(regs_prussio);
+		p->mem[0].memtype = UIO_MEM_PHYS;
+
+		p->mem[1].addr = gdev->sram_paddr;
+		p->mem[1].size = sram_pool_sz;
+		p->mem[1].memtype = UIO_MEM_PHYS;
+
+		p->mem[2].addr = gdev->ddr_paddr;
+		p->mem[2].size = extram_pool_sz;
+		p->mem[2].memtype = UIO_MEM_PHYS;
+
+		p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt);
+		p->version = DRV_VERSION;
+
+		/* Register PRUSS IRQ lines */
+		p->irq = gdev->hostirq_start + cnt;
+		p->handler = pruss_handler;
+		p->priv = gdev;
+
+		ret = uio_register_device(&dev->dev, p);
+		if (ret < 0)
+			goto out_free;
+	}
+
+	platform_set_drvdata(dev, gdev);
+	return 0;
+
+out_free:
+	pruss_cleanup(dev, gdev);
+	return ret;
+}
+
+static int __devexit pruss_remove(struct platform_device *dev)
+{
+	struct uio_pruss_dev *gdev = platform_get_drvdata(dev);
+
+	pruss_cleanup(dev, gdev);
+	platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver pruss_driver = {
+	.probe = pruss_probe,
+	.remove = __devexit_p(pruss_remove),
+	.driver = {
+		   .name = DRV_NAME,
+		   .owner = THIS_MODULE,
+		   },
+};
+
+static int __init pruss_init_module(void)
+{
+	return platform_driver_register(&pruss_driver);
+}
+
+module_init(pruss_init_module);
+
+static void __exit pruss_exit_module(void)
+{
+	platform_driver_unregister(&pruss_driver);
+}
+
+module_exit(pruss_exit_module);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Amit Chatterjee <amit.chatterjee@ti.com>");
+MODULE_AUTHOR("Pratheesh Gangadhar <pratheesh@ti.com>");
diff --git a/include/linux/platform_data/uio_pruss.h b/include/linux/platform_data/uio_pruss.h
new file mode 100644
index 0000000..f39140a
--- /dev/null
+++ b/include/linux/platform_data/uio_pruss.h
@@ -0,0 +1,25 @@
+/*
+ * include/linux/platform_data/uio_pruss.h
+ *
+ * Platform data for uio_pruss driver
+ *
+ * Copyright (C) 2010-11 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 as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _UIO_PRUSS_H_
+#define _UIO_PRUSS_H_
+
+/* To configure the PRUSS INTC base offset for UIO driver */
+struct uio_pruss_pdata {
+	u32	pintc_base;
+};
+#endif /* _UIO_PRUSS_H_ */
-- 
1.7.4.1


  parent reply	other threads:[~2011-03-16 21:13 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-16 20:52 [GIT PATCH] driver core patches for .39 Greg KH
2011-03-16 21:10 ` [PATCH 01/50] driver-core: document restrictions on device_rename() Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 02/50] docs/sysfs: Update directory/kobject documentation Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 03/50] docs/sysfs: show() methods should use scnprintf() Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 04/50] kobject: Add missing format attribute specifications Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 05/50] Dynamic debug: Add more flags Greg Kroah-Hartman
2011-03-17 17:56     ` Jason Baron
2011-03-17 18:02       ` Greg KH
2011-03-18 10:22         ` Ingo Molnar
2011-03-18 11:19           ` Bart Van Assche
2011-03-16 21:10   ` [PATCH 06/50] firmware_classs: change val uevent's type to bool Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 07/50] sysdev: Fixup warning message Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 08/50] debugfs: remove module_exit() Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 09/50] sysdev: Do not register with sysdev when erroring on add Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 10/50] Translate Documentation/SecurityBugs into Chinese Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 11/50] pch_phub: add new device ML7213 Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 12/50] dynamic_debug: add #include <linux/sched.h> Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 13/50] memory hotplug: Allow memory blocks to span multiple memory sections Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 14/50] memory hotplug: Update phys_index to [start|end]_section_nr Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 15/50] memory hotplug: Define memory_block_size_bytes for powerpc/pseries Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 16/50] memory hotplug: Define memory_block_size_bytes for x86_64 with CONFIG_X86_UV Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 17/50] memory hotplug: sysfs probe routine should add all memory sections Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 18/50] driver core: Replace the dangerous to_root_device macro with an inline function Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 19/50] sysfs: Capitalize description of SYSFS_DEPRECATED{_V2} options Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 20/50] Fix a mistake Chinese character in Documentation/zh_CN/SubmittingPatches Greg Kroah-Hartman
2011-03-16 21:10   ` [PATCH 21/50] drivers:misc: ti-st: register with channel IDs Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 22/50] drivers:misc: ti-st: move from rfkill to sysfs Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 23/50] drivers:misc: ti-st: fix error codes Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 24/50] drivers:misc: ti-st: set right debug levels for logs Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 25/50] drivers:misc: ti-st: firmware download optimization Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 26/50] drivers:misc: ti-st: fix hci-ll on wake_ind collision Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 27/50] drivers:misc: ti-st: remove multiple gpio handling Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 28/50] kobject.h: fix build when CONFIG_HOTPLUG is disabled Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 29/50] debugfs: Fix filesystem reference counting on debugfs_remove() failure Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 30/50] Translat Documentation/SubmittingChecklist into Chinese Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 31/50] Translate linux-2.6/Documentation/magic-number.txt " Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 32/50] Driver core: convert platform_{get,set}_drvdata to static inline functions Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 33/50] firmware: Add DMI entry types to the headers Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 34/50] firmware: Basic dmi-sysfs support Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 35/50] firmware: Break out system_event_log in dmi-sysfs Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 36/50] firmware: Expose DMI type 15 System Event Log Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 37/50] firmware: Add documentation for /sys/firmware/dmi Greg Kroah-Hartman
2011-03-18 20:53     ` Valdis.Kletnieks
2011-03-18 23:50       ` [PATCH] firmware: Fix grammar in sysfs-firmware-dmi doc Mike Waychison
2011-03-16 21:11   ` [PATCH 38/50] firmware: Fix unaligned memory accesses in dmi-sysfs Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 39/50] Fix spelling mistakes in Documentation/zh_CN/SubmittingPatches Greg Kroah-Hartman
2011-03-16 21:11   ` Greg Kroah-Hartman [this message]
2011-03-16 21:11   ` [PATCH 41/50] kref: Fix typo in kref documentation Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 42/50] drivers:misc: ti-st: fix debugging code Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 43/50] efivars: move efivars globals into struct efivars Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 44/50] efivars: Make efivars bin_attributes dynamic Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 45/50] efivars: parameterize efivars Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 46/50] efivars: Split out variable registration Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 47/50] efivars: Parameterize operations Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 48/50] efivars: Expose efivars functionality to external drivers Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 49/50] efivars: Add Documentation Greg Kroah-Hartman
2011-03-16 21:11   ` [PATCH 50/50] printk: do not mangle valid userspace syslog prefixes Greg Kroah-Hartman

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=1300309888-5028-40-git-send-email-gregkh@suse.de \
    --to=gregkh@suse.de \
    --cc=hjk@hansjkoch.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pratheesh@ti.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 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).