summaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-davinci/omapl138/0001-uio_pruss1-Core-driver-addition.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-davinci/omapl138/0001-uio_pruss1-Core-driver-addition.patch')
-rwxr-xr-xextras/recipes-kernel/linux/linux-davinci/omapl138/0001-uio_pruss1-Core-driver-addition.patch334
1 files changed, 334 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-davinci/omapl138/0001-uio_pruss1-Core-driver-addition.patch b/extras/recipes-kernel/linux/linux-davinci/omapl138/0001-uio_pruss1-Core-driver-addition.patch
new file mode 100755
index 00000000..389097f8
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-davinci/omapl138/0001-uio_pruss1-Core-driver-addition.patch
@@ -0,0 +1,334 @@
1From: Melissa Watkins <m-watkins@ti.com>
2Date: Wed, 24 Nov 2010 02:59:34 -0600
3Subject: [PATCH 1/3] uio_pruss1: Core driver addition
4
5This patch adds the uio_pru driver and updates the uio Makefile
6 and Kconfig files to support this driver. The uio_pru driver provides
7a framework for handling the PRU in the user space and is responsible
8for the device setup and the primary interrupt handling.
9
10Signed-off-by: Amit Chatterjee <amit.chatterjee@ti.com>
11Signed-off-by: Melissa Watkins <m-watkins@ti.com>
12---
13 drivers/uio/Kconfig | 10 ++
14 drivers/uio/Makefile | 1 +
15 drivers/uio/uio_pru.c | 279 +++++++++++++++++++++++++++++++++++++++++++++++++
16 3 files changed, 290 insertions(+), 0 deletions(-)
17 create mode 100644 drivers/uio/uio_pru.c
18
19diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
20index 8aa1955..8ae8280 100644
21--- a/drivers/uio/Kconfig
22+++ b/drivers/uio/Kconfig
23@@ -94,4 +94,14 @@ config UIO_PCI_GENERIC
24 primarily, for virtualization scenarios.
25 If you compile this as a module, it will be called uio_pci_generic.
26
27+config UIO_PRUSS
28+ tristate "Texas Instruments PRUSS driver"
29+ depends on ARCH_DAVINCI_DA850
30+ default n
31+ help
32+ PRUSS driver for OMAPL13X/DA8XX/AM17XX/AM18XX devices
33+ PRUSS driver requires user space components
34+ To compile this driver as a module, choose M here: the module
35+ will be called uio_pruss.
36+
37 endif
38diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
39index 73b2e75..e6d8adb 100644
40--- a/drivers/uio/Makefile
41+++ b/drivers/uio/Makefile
42@@ -6,3 +6,4 @@ obj-$(CONFIG_UIO_SMX) += uio_smx.o
43 obj-$(CONFIG_UIO_AEC) += uio_aec.o
44 obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
45 obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
46+obj-$(CONFIG_UIO_PRUSS) += uio_pru.o
47diff --git a/drivers/uio/uio_pru.c b/drivers/uio/uio_pru.c
48new file mode 100644
49index 0000000..82dc35e
50--- /dev/null
51+++ b/drivers/uio/uio_pru.c
52@@ -0,0 +1,279 @@
53+/*
54+ * UIO TI Programmable Real-Time Unit (PRU) driver.
55+ *
56+ * (C) 2010 Amit Chatterjee <amit.chatterjee@ti.com>
57+ *
58+ * Copyright (C) {YEAR} Texas Instruments Incorporated - http://www.ti.com/
59+ *
60+ * This program is free software; you can redistribute it and/or
61+ * modify it under the terms of the GNU General Public License as
62+ * published by the Free Software Foundation version 2.
63+ *
64+ * This program is distributed .as is. WITHOUT ANY WARRANTY of any
65+ * kind, whether express or implied; without even the implied warranty
66+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
67+ * GNU General Public License for more details.
68+ */
69+
70+#include <linux/device.h>
71+#include <linux/module.h>
72+#include <linux/platform_device.h>
73+#include <linux/uio_driver.h>
74+#include <linux/io.h>
75+#include <linux/clk.h>
76+#include <linux/dma-mapping.h>
77+
78+#define DRV_NAME "pruss"
79+#define DRV_VERSION "0.01"
80+
81+/*
82+0x01C30000 - 0x01C301FF Data RAM 0
83+0x01C30200 - 0x01C31FFF Reserved
84+0x01C32000 - 0x01C321FF Data RAM 1
85+0x01C32200 - 0x01C33FFF Reserved
86+0x01C34000 - 0x01C36FFF INTC Registers
87+0x01C37000 - 0x01C373FF PRU0 Control Registers
88+0x01C37400 - 0x01C377FF PRU0 Debug Registers
89+0x01C37800 - 0x01C37BFF PRU1 Control Registers
90+0x01C37C00 - 0x01C37FFF PRU1 Debug Registers
91+0x01C38000 - 0x01C38FFF PRU0 Instruction RAM
92+0x01C39000 - 0x01C3BFFF Reserved
93+0x01C3C000 - 0x01C3CFFF PRU1 Instruction RAM
94+0x01C3D000 - 0x01C3FFFF Reserved
95+*/
96+/*
97+ * 3 PRU_EVTOUT0 PRUSS Interrupt
98+ * 4 PRU_EVTOUT1 PRUSS Interrupt
99+ * 5 PRU_EVTOUT2 PRUSS Interrupt
100+ * 6 PRU_EVTOUT3 PRUSS Interrupt
101+ * 7 PRU_EVTOUT4 PRUSS Interrupt
102+ * 8 PRU_EVTOUT5 PRUSS Interrupt
103+ * 9 PRU_EVTOUT6 PRUSS Interrupt
104+ * 10 PRU_EVTOUT7 PRUSS Interrupt
105+*/
106+
107+#define PRUSS_INSTANCE (8)
108+
109+static struct clk *pruss_clk = NULL, *ecap0_clk = NULL;
110+static struct uio_info *info[PRUSS_INSTANCE];
111+static void *ddr_virt_addr;
112+static dma_addr_t ddr_phy_addr;
113+
114+
115+
116+static irqreturn_t pruss_handler(int irq, struct uio_info *dev_info)
117+{
118+ return IRQ_HANDLED;
119+}
120+
121+static int __devinit pruss_probe(struct platform_device *dev)
122+{
123+ int ret = -ENODEV;
124+ int count = 0;
125+ struct resource *regs_pruram, *regs_l3ram, *regs_ddr;
126+ char *string;
127+
128+ /* Power on PRU in case its not done as part of boot-loader */
129+ pruss_clk = clk_get(&dev->dev, "pruss");
130+ if (IS_ERR(pruss_clk)) {
131+ dev_err(&dev->dev, "no pruss clock available\n");
132+ ret = PTR_ERR(pruss_clk);
133+ pruss_clk = NULL;
134+ return ret;
135+ } else {
136+ clk_enable (pruss_clk);
137+ }
138+
139+ ecap0_clk = clk_get(&dev->dev, "ecap0");
140+ if (IS_ERR(ecap0_clk)) {
141+ dev_err(&dev->dev, "no ecap0 clock available\n");
142+ ret = PTR_ERR(ecap0_clk);
143+ ecap0_clk = NULL;
144+ return ret;
145+ } else {
146+ clk_enable(ecap0_clk);
147+ }
148+
149+
150+
151+ for (count = 0; count < PRUSS_INSTANCE; count++) {
152+ info[count] = (struct uio_info *)kzalloc(sizeof(struct uio_info), GFP_KERNEL);
153+ if (!info[count])
154+ return -ENOMEM;
155+
156+ }
157+
158+ regs_pruram = platform_get_resource(dev, IORESOURCE_MEM, 0);
159+ if (!regs_pruram) {
160+ dev_err(&dev->dev, "No memory resource specified\n");
161+ goto out_free;
162+ }
163+
164+ regs_l3ram = platform_get_resource(dev, IORESOURCE_MEM, 1);
165+ if (!regs_l3ram) {
166+ dev_err(&dev->dev, "No memory resource specified\n");
167+ goto out_free;
168+ }
169+
170+ regs_ddr = platform_get_resource(dev, IORESOURCE_MEM, 2);
171+ if (!regs_ddr) {
172+ dev_err(&dev->dev, "No memory resource specified\n");
173+ goto out_free;
174+ }
175+ ddr_virt_addr = dma_alloc_coherent(&dev->dev, regs_ddr->end-regs_ddr->start+1, &ddr_phy_addr, GFP_KERNEL|GFP_DMA);
176+
177+
178+ for (count = 0; count < PRUSS_INSTANCE; count++) {
179+ info[count]->mem[0].addr = regs_pruram->start;
180+ if (!info[count]->mem[0].addr) {
181+ dev_err(&dev->dev, "Invalid memory resource\n");
182+ break;
183+ }
184+
185+ info[count]->mem[0].size = regs_pruram->end - regs_pruram->start + 1;
186+ info[count]->mem[0].internal_addr = ioremap(regs_pruram->start, info[count]->mem[0].size);
187+
188+ if (!info[count]->mem[0].internal_addr) {
189+ dev_err(&dev->dev, "Can't remap memory address range\n");
190+ break;
191+ }
192+ info[count]->mem[0].memtype = UIO_MEM_PHYS;
193+
194+
195+ info[count]->mem[1].addr = regs_l3ram->start;
196+ if (!info[count]->mem[1].addr) {
197+ dev_err(&dev->dev, "Invalid memory resource\n");
198+ break;
199+ }
200+
201+ info[count]->mem[1].size = regs_l3ram->end - regs_l3ram->start + 1;
202+ info[count]->mem[1].internal_addr = ioremap(regs_l3ram->start, info[count]->mem[1].size);
203+
204+ if (!info[count]->mem[1].internal_addr) {
205+ dev_err(&dev->dev, "Can't remap memory address range\n");
206+ break;
207+ }
208+ info[count]->mem[1].memtype = UIO_MEM_PHYS;
209+
210+
211+ info[count]->mem[2].size = regs_ddr->end - regs_ddr->start + 1;
212+ if (!(info[count]->mem[2].size-1)) {
213+ dev_err(&dev->dev, "Invalid memory resource\n");
214+ break;
215+ }
216+
217+
218+ info[count]->mem[2].internal_addr = ddr_virt_addr;
219+
220+ if (!info[count]->mem[2].internal_addr) {
221+ dev_err(&dev->dev, "Can't remap memory address range\n");
222+ break;
223+ }
224+ info[count]->mem[2].addr = ddr_phy_addr;
225+ info[count]->mem[2].memtype = UIO_MEM_PHYS;
226+
227+
228+ string = kzalloc(20, GFP_KERNEL);
229+ sprintf(string, "pruss_evt%d", count);
230+ info[count]->name = string;
231+ info[count]->version = "0.01";
232+
233+ /* Register PRUSS IRQ lines */
234+ info[count]->irq = IRQ_DA8XX_EVTOUT0+count;
235+
236+ info[count]->irq_flags = IRQF_SHARED;
237+ info[count]->handler = pruss_handler;
238+
239+ ret = uio_register_device(&dev->dev, info[count]);
240+
241+ if (ret < 0)
242+ break;
243+ }
244+
245+ platform_set_drvdata(dev, info);
246+
247+ if (ret < 0) {
248+ if (ddr_virt_addr)
249+ dma_free_coherent(&dev->dev, regs_ddr->end - regs_ddr->start + 1, ddr_virt_addr, ddr_phy_addr);
250+ while (count--) {
251+ uio_unregister_device(info[count]);
252+ if (info[count]->name)
253+ kfree(info[count]->name);
254+ iounmap(info[count]->mem[0].internal_addr);
255+ }
256+ } else {
257+ return 0;
258+ }
259+
260+out_free:
261+ for (count = 0; count < PRUSS_INSTANCE; count++) {
262+ if (info[count])
263+ kfree(info[count]);
264+ }
265+
266+ if (pruss_clk != NULL)
267+ clk_put(pruss_clk);
268+ if (ecap0_clk != NULL)
269+ clk_put(ecap0_clk);
270+
271+ return ret;
272+}
273+
274+static int __devexit pruss_remove(struct platform_device *dev)
275+{
276+ int count = 0;
277+ struct uio_info **info;
278+
279+ info = (struct uio_info **)platform_get_drvdata(dev);
280+
281+ for (count = 0; count < PRUSS_INSTANCE; count++) {
282+ uio_unregister_device(info[count]);
283+ if (info[count]->name)
284+ kfree(info[count]->name);
285+
286+ }
287+ iounmap(info[0]->mem[0].internal_addr);
288+ iounmap(info[0]->mem[1].internal_addr);
289+ if (ddr_virt_addr)
290+ dma_free_coherent(&dev->dev, info[0]->mem[2].size, info[0]->mem[2].internal_addr, info[0]->mem[2].addr);
291+
292+ for (count = 0; count < PRUSS_INSTANCE; count++) {
293+ if (info[count])
294+ kfree(info[count]);
295+ }
296+
297+ platform_set_drvdata(dev, NULL);
298+
299+ if (pruss_clk != NULL)
300+ clk_put(pruss_clk);
301+ if (ecap0_clk != NULL)
302+ clk_put(ecap0_clk);
303+
304+
305+ return 0;
306+}
307+
308+static struct platform_driver pruss_driver = {
309+ .probe = pruss_probe,
310+ .remove = __devexit_p(pruss_remove),
311+ .driver = {
312+ .name = DRV_NAME,
313+ .owner = THIS_MODULE,
314+ },
315+};
316+
317+static int __init pruss_init_module(void)
318+{
319+ return platform_driver_register(&pruss_driver);
320+}
321+module_init(pruss_init_module);
322+
323+static void __exit pruss_exit_module(void)
324+{
325+ platform_driver_unregister(&pruss_driver);
326+}
327+module_exit(pruss_exit_module);
328+
329+MODULE_LICENSE("GPL v2");
330+MODULE_VERSION(DRV_VERSION);
331+MODULE_AUTHOR("Amit Chatterjee <amit.chatterjee@ti.com>");
332--
3331.7.0.4
334