diff options
Diffstat (limited to 'extras/recipes-kernel/linux/linux-davinci/omapl138/0001-uio_pruss1-Core-driver-addition.patch')
-rwxr-xr-x | extras/recipes-kernel/linux/linux-davinci/omapl138/0001-uio_pruss1-Core-driver-addition.patch | 334 |
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 @@ | |||
1 | From: Melissa Watkins <m-watkins@ti.com> | ||
2 | Date: Wed, 24 Nov 2010 02:59:34 -0600 | ||
3 | Subject: [PATCH 1/3] uio_pruss1: Core driver addition | ||
4 | |||
5 | This patch adds the uio_pru driver and updates the uio Makefile | ||
6 | and Kconfig files to support this driver. The uio_pru driver provides | ||
7 | a framework for handling the PRU in the user space and is responsible | ||
8 | for the device setup and the primary interrupt handling. | ||
9 | |||
10 | Signed-off-by: Amit Chatterjee <amit.chatterjee@ti.com> | ||
11 | Signed-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 | |||
19 | diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig | ||
20 | index 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 | ||
38 | diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile | ||
39 | index 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 | ||
47 | diff --git a/drivers/uio/uio_pru.c b/drivers/uio/uio_pru.c | ||
48 | new file mode 100644 | ||
49 | index 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 | -- | ||
333 | 1.7.0.4 | ||
334 | |||