aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/uio
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/uio
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/uio')
-rw-r--r--drivers/uio/Kconfig23
-rw-r--r--drivers/uio/Makefile1
-rw-r--r--drivers/uio/uio.c182
-rw-r--r--drivers/uio/uio_cif.c2
-rw-r--r--drivers/uio/uio_netx.c21
-rw-r--r--drivers/uio/uio_pci_generic.c13
-rw-r--r--drivers/uio/uio_pdrv_genirq.c4
-rw-r--r--drivers/uio/uio_pruss.c247
8 files changed, 381 insertions, 112 deletions
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 1da73ecd9799..6f3ea9bbc818 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -17,9 +17,9 @@ config UIO_CIF
17 depends on PCI 17 depends on PCI
18 help 18 help
19 Driver for Hilscher CIF DeviceNet and Profibus cards. This 19 Driver for Hilscher CIF DeviceNet and Profibus cards. This
20 driver requires a userspace component that handles all of the 20 driver requires a userspace component called cif that handles
21 heavy lifting and can be found at: 21 all of the heavy lifting and can be found at:
22 http://www.osadl.org/projects/downloads/UIO/user/cif-* 22 <http://www.osadl.org/projects/downloads/UIO/user/>
23 23
24 To compile this driver as a module, choose M here: the module 24 To compile this driver as a module, choose M here: the module
25 will be called uio_cif. 25 will be called uio_cif.
@@ -94,4 +94,21 @@ config UIO_NETX
94 To compile this driver as a module, choose M here; the module 94 To compile this driver as a module, choose M here; the module
95 will be called uio_netx. 95 will be called uio_netx.
96 96
97config UIO_PRUSS
98 tristate "Texas Instruments PRUSS driver"
99 depends on ARCH_DAVINCI_DA850
100 help
101 PRUSS driver for OMAPL138/DA850/AM18XX devices
102 PRUSS driver requires user space components, examples and user space
103 driver is available from below SVN repo - you may use anonymous login
104
105 https://gforge.ti.com/gf/project/pru_sw/
106
107 More info on API is available at below wiki
108
109 http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader
110
111 To compile this driver as a module, choose M here: the module
112 will be called uio_pruss.
113
97endif 114endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 18fd818c5b97..d4dd9a5552f8 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_UIO_AEC) += uio_aec.o
6obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o 6obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
7obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o 7obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
8obj-$(CONFIG_UIO_NETX) += uio_netx.o 8obj-$(CONFIG_UIO_NETX) += uio_netx.o
9obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index bff1afbde5a4..d2efe823c20d 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright(C) 2005, Benedikt Spranger <b.spranger@linutronix.de> 4 * Copyright(C) 2005, Benedikt Spranger <b.spranger@linutronix.de>
5 * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de> 5 * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
6 * Copyright(C) 2006, Hans J. Koch <hjk@linutronix.de> 6 * Copyright(C) 2006, Hans J. Koch <hjk@hansjkoch.de>
7 * Copyright(C) 2006, Greg Kroah-Hartman <greg@kroah.com> 7 * Copyright(C) 2006, Greg Kroah-Hartman <greg@kroah.com>
8 * 8 *
9 * Userspace IO 9 * Userspace IO
@@ -23,9 +23,10 @@
23#include <linux/sched.h> 23#include <linux/sched.h>
24#include <linux/string.h> 24#include <linux/string.h>
25#include <linux/kobject.h> 25#include <linux/kobject.h>
26#include <linux/cdev.h>
26#include <linux/uio_driver.h> 27#include <linux/uio_driver.h>
27 28
28#define UIO_MAX_DEVICES 255 29#define UIO_MAX_DEVICES (1U << MINORBITS)
29 30
30struct uio_device { 31struct uio_device {
31 struct module *owner; 32 struct module *owner;
@@ -41,15 +42,10 @@ struct uio_device {
41}; 42};
42 43
43static int uio_major; 44static int uio_major;
45static struct cdev *uio_cdev;
44static DEFINE_IDR(uio_idr); 46static DEFINE_IDR(uio_idr);
45static const struct file_operations uio_fops; 47static const struct file_operations uio_fops;
46 48
47/* UIO class infrastructure */
48static struct uio_class {
49 struct kref kref;
50 struct class *class;
51} *uio_class;
52
53/* Protect idr accesses */ 49/* Protect idr accesses */
54static DEFINE_MUTEX(minor_lock); 50static DEFINE_MUTEX(minor_lock);
55 51
@@ -232,45 +228,34 @@ static ssize_t show_name(struct device *dev,
232 struct device_attribute *attr, char *buf) 228 struct device_attribute *attr, char *buf)
233{ 229{
234 struct uio_device *idev = dev_get_drvdata(dev); 230 struct uio_device *idev = dev_get_drvdata(dev);
235 if (idev) 231 return sprintf(buf, "%s\n", idev->info->name);
236 return sprintf(buf, "%s\n", idev->info->name);
237 else
238 return -ENODEV;
239} 232}
240static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
241 233
242static ssize_t show_version(struct device *dev, 234static ssize_t show_version(struct device *dev,
243 struct device_attribute *attr, char *buf) 235 struct device_attribute *attr, char *buf)
244{ 236{
245 struct uio_device *idev = dev_get_drvdata(dev); 237 struct uio_device *idev = dev_get_drvdata(dev);
246 if (idev) 238 return sprintf(buf, "%s\n", idev->info->version);
247 return sprintf(buf, "%s\n", idev->info->version);
248 else
249 return -ENODEV;
250} 239}
251static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
252 240
253static ssize_t show_event(struct device *dev, 241static ssize_t show_event(struct device *dev,
254 struct device_attribute *attr, char *buf) 242 struct device_attribute *attr, char *buf)
255{ 243{
256 struct uio_device *idev = dev_get_drvdata(dev); 244 struct uio_device *idev = dev_get_drvdata(dev);
257 if (idev) 245 return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event));
258 return sprintf(buf, "%u\n",
259 (unsigned int)atomic_read(&idev->event));
260 else
261 return -ENODEV;
262} 246}
263static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
264 247
265static struct attribute *uio_attrs[] = { 248static struct device_attribute uio_class_attributes[] = {
266 &dev_attr_name.attr, 249 __ATTR(name, S_IRUGO, show_name, NULL),
267 &dev_attr_version.attr, 250 __ATTR(version, S_IRUGO, show_version, NULL),
268 &dev_attr_event.attr, 251 __ATTR(event, S_IRUGO, show_event, NULL),
269 NULL, 252 {}
270}; 253};
271 254
272static struct attribute_group uio_attr_grp = { 255/* UIO class infrastructure */
273 .attrs = uio_attrs, 256static struct class uio_class = {
257 .name = "uio",
258 .dev_attrs = uio_class_attributes,
274}; 259};
275 260
276/* 261/*
@@ -287,10 +272,6 @@ static int uio_dev_add_attributes(struct uio_device *idev)
287 struct uio_port *port; 272 struct uio_port *port;
288 struct uio_portio *portio; 273 struct uio_portio *portio;
289 274
290 ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp);
291 if (ret)
292 goto err_group;
293
294 for (mi = 0; mi < MAX_UIO_MAPS; mi++) { 275 for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
295 mem = &idev->info->mem[mi]; 276 mem = &idev->info->mem[mi];
296 if (mem->size == 0) 277 if (mem->size == 0)
@@ -358,8 +339,6 @@ err_map:
358 kobject_put(&map->kobj); 339 kobject_put(&map->kobj);
359 } 340 }
360 kobject_put(idev->map_dir); 341 kobject_put(idev->map_dir);
361 sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
362err_group:
363 dev_err(idev->dev, "error creating sysfs files (%d)\n", ret); 342 dev_err(idev->dev, "error creating sysfs files (%d)\n", ret);
364 return ret; 343 return ret;
365} 344}
@@ -385,8 +364,6 @@ static void uio_dev_del_attributes(struct uio_device *idev)
385 kobject_put(&port->portio->kobj); 364 kobject_put(&port->portio->kobj);
386 } 365 }
387 kobject_put(idev->portio_dir); 366 kobject_put(idev->portio_dir);
388
389 sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
390} 367}
391 368
392static int uio_get_minor(struct uio_device *idev) 369static int uio_get_minor(struct uio_device *idev)
@@ -404,7 +381,13 @@ static int uio_get_minor(struct uio_device *idev)
404 retval = -ENOMEM; 381 retval = -ENOMEM;
405 goto exit; 382 goto exit;
406 } 383 }
407 idev->minor = id & MAX_ID_MASK; 384 if (id < UIO_MAX_DEVICES) {
385 idev->minor = id;
386 } else {
387 dev_err(idev->dev, "too many uio devices\n");
388 retval = -EINVAL;
389 idr_remove(&uio_idr, id);
390 }
408exit: 391exit:
409 mutex_unlock(&minor_lock); 392 mutex_unlock(&minor_lock);
410 return retval; 393 return retval;
@@ -525,7 +508,7 @@ static unsigned int uio_poll(struct file *filep, poll_table *wait)
525 struct uio_listener *listener = filep->private_data; 508 struct uio_listener *listener = filep->private_data;
526 struct uio_device *idev = listener->dev; 509 struct uio_device *idev = listener->dev;
527 510
528 if (idev->info->irq == UIO_IRQ_NONE) 511 if (!idev->info->irq)
529 return -EIO; 512 return -EIO;
530 513
531 poll_wait(filep, &idev->wait, wait); 514 poll_wait(filep, &idev->wait, wait);
@@ -543,7 +526,7 @@ static ssize_t uio_read(struct file *filep, char __user *buf,
543 ssize_t retval; 526 ssize_t retval;
544 s32 event_count; 527 s32 event_count;
545 528
546 if (idev->info->irq == UIO_IRQ_NONE) 529 if (!idev->info->irq)
547 return -EIO; 530 return -EIO;
548 531
549 if (count != sizeof(s32)) 532 if (count != sizeof(s32))
@@ -591,7 +574,7 @@ static ssize_t uio_write(struct file *filep, const char __user *buf,
591 ssize_t retval; 574 ssize_t retval;
592 s32 irq_on; 575 s32 irq_on;
593 576
594 if (idev->info->irq == UIO_IRQ_NONE) 577 if (!idev->info->irq)
595 return -EIO; 578 return -EIO;
596 579
597 if (count != sizeof(s32)) 580 if (count != sizeof(s32))
@@ -610,14 +593,12 @@ static ssize_t uio_write(struct file *filep, const char __user *buf,
610 593
611static int uio_find_mem_index(struct vm_area_struct *vma) 594static int uio_find_mem_index(struct vm_area_struct *vma)
612{ 595{
613 int mi;
614 struct uio_device *idev = vma->vm_private_data; 596 struct uio_device *idev = vma->vm_private_data;
615 597
616 for (mi = 0; mi < MAX_UIO_MAPS; mi++) { 598 if (vma->vm_pgoff < MAX_UIO_MAPS) {
617 if (idev->info->mem[mi].size == 0) 599 if (idev->info->mem[vma->vm_pgoff].size == 0)
618 return -1; 600 return -1;
619 if (vma->vm_pgoff == mi) 601 return (int)vma->vm_pgoff;
620 return mi;
621 } 602 }
622 return -1; 603 return -1;
623} 604}
@@ -740,72 +721,77 @@ static const struct file_operations uio_fops = {
740 .mmap = uio_mmap, 721 .mmap = uio_mmap,
741 .poll = uio_poll, 722 .poll = uio_poll,
742 .fasync = uio_fasync, 723 .fasync = uio_fasync,
724 .llseek = noop_llseek,
743}; 725};
744 726
745static int uio_major_init(void) 727static int uio_major_init(void)
746{ 728{
747 uio_major = register_chrdev(0, "uio", &uio_fops); 729 static const char name[] = "uio";
748 if (uio_major < 0) 730 struct cdev *cdev = NULL;
749 return uio_major; 731 dev_t uio_dev = 0;
750 return 0; 732 int result;
733
734 result = alloc_chrdev_region(&uio_dev, 0, UIO_MAX_DEVICES, name);
735 if (result)
736 goto out;
737
738 result = -ENOMEM;
739 cdev = cdev_alloc();
740 if (!cdev)
741 goto out_unregister;
742
743 cdev->owner = THIS_MODULE;
744 cdev->ops = &uio_fops;
745 kobject_set_name(&cdev->kobj, "%s", name);
746
747 result = cdev_add(cdev, uio_dev, UIO_MAX_DEVICES);
748 if (result)
749 goto out_put;
750
751 uio_major = MAJOR(uio_dev);
752 uio_cdev = cdev;
753 result = 0;
754out:
755 return result;
756out_put:
757 kobject_put(&cdev->kobj);
758out_unregister:
759 unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES);
760 goto out;
751} 761}
752 762
753static void uio_major_cleanup(void) 763static void uio_major_cleanup(void)
754{ 764{
755 unregister_chrdev(uio_major, "uio"); 765 unregister_chrdev_region(MKDEV(uio_major, 0), UIO_MAX_DEVICES);
766 cdev_del(uio_cdev);
756} 767}
757 768
758static int init_uio_class(void) 769static int init_uio_class(void)
759{ 770{
760 int ret = 0; 771 int ret;
761
762 if (uio_class != NULL) {
763 kref_get(&uio_class->kref);
764 goto exit;
765 }
766 772
767 /* This is the first time in here, set everything up properly */ 773 /* This is the first time in here, set everything up properly */
768 ret = uio_major_init(); 774 ret = uio_major_init();
769 if (ret) 775 if (ret)
770 goto exit; 776 goto exit;
771 777
772 uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL); 778 ret = class_register(&uio_class);
773 if (!uio_class) { 779 if (ret) {
774 ret = -ENOMEM; 780 printk(KERN_ERR "class_register failed for uio\n");
775 goto err_kzalloc; 781 goto err_class_register;
776 }
777
778 kref_init(&uio_class->kref);
779 uio_class->class = class_create(THIS_MODULE, "uio");
780 if (IS_ERR(uio_class->class)) {
781 ret = IS_ERR(uio_class->class);
782 printk(KERN_ERR "class_create failed for uio\n");
783 goto err_class_create;
784 } 782 }
785 return 0; 783 return 0;
786 784
787err_class_create: 785err_class_register:
788 kfree(uio_class);
789 uio_class = NULL;
790err_kzalloc:
791 uio_major_cleanup(); 786 uio_major_cleanup();
792exit: 787exit:
793 return ret; 788 return ret;
794} 789}
795 790
796static void release_uio_class(struct kref *kref) 791static void release_uio_class(void)
797{ 792{
798 /* Ok, we cheat as we know we only have one uio_class */ 793 class_unregister(&uio_class);
799 class_destroy(uio_class->class);
800 kfree(uio_class);
801 uio_major_cleanup(); 794 uio_major_cleanup();
802 uio_class = NULL;
803}
804
805static void uio_class_destroy(void)
806{
807 if (uio_class)
808 kref_put(&uio_class->kref, release_uio_class);
809} 795}
810 796
811/** 797/**
@@ -828,10 +814,6 @@ int __uio_register_device(struct module *owner,
828 814
829 info->uio_dev = NULL; 815 info->uio_dev = NULL;
830 816
831 ret = init_uio_class();
832 if (ret)
833 return ret;
834
835 idev = kzalloc(sizeof(*idev), GFP_KERNEL); 817 idev = kzalloc(sizeof(*idev), GFP_KERNEL);
836 if (!idev) { 818 if (!idev) {
837 ret = -ENOMEM; 819 ret = -ENOMEM;
@@ -847,7 +829,7 @@ int __uio_register_device(struct module *owner,
847 if (ret) 829 if (ret)
848 goto err_get_minor; 830 goto err_get_minor;
849 831
850 idev->dev = device_create(uio_class->class, parent, 832 idev->dev = device_create(&uio_class, parent,
851 MKDEV(uio_major, idev->minor), idev, 833 MKDEV(uio_major, idev->minor), idev,
852 "uio%d", idev->minor); 834 "uio%d", idev->minor);
853 if (IS_ERR(idev->dev)) { 835 if (IS_ERR(idev->dev)) {
@@ -862,9 +844,9 @@ int __uio_register_device(struct module *owner,
862 844
863 info->uio_dev = idev; 845 info->uio_dev = idev;
864 846
865 if (idev->info->irq >= 0) { 847 if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {
866 ret = request_irq(idev->info->irq, uio_interrupt, 848 ret = request_irq(info->irq, uio_interrupt,
867 idev->info->irq_flags, idev->info->name, idev); 849 info->irq_flags, info->name, idev);
868 if (ret) 850 if (ret)
869 goto err_request_irq; 851 goto err_request_irq;
870 } 852 }
@@ -874,13 +856,12 @@ int __uio_register_device(struct module *owner,
874err_request_irq: 856err_request_irq:
875 uio_dev_del_attributes(idev); 857 uio_dev_del_attributes(idev);
876err_uio_dev_add_attributes: 858err_uio_dev_add_attributes:
877 device_destroy(uio_class->class, MKDEV(uio_major, idev->minor)); 859 device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
878err_device_create: 860err_device_create:
879 uio_free_minor(idev); 861 uio_free_minor(idev);
880err_get_minor: 862err_get_minor:
881 kfree(idev); 863 kfree(idev);
882err_kzalloc: 864err_kzalloc:
883 uio_class_destroy();
884 return ret; 865 return ret;
885} 866}
886EXPORT_SYMBOL_GPL(__uio_register_device); 867EXPORT_SYMBOL_GPL(__uio_register_device);
@@ -901,15 +882,13 @@ void uio_unregister_device(struct uio_info *info)
901 882
902 uio_free_minor(idev); 883 uio_free_minor(idev);
903 884
904 if (info->irq >= 0) 885 if (info->irq && (info->irq != UIO_IRQ_CUSTOM))
905 free_irq(info->irq, idev); 886 free_irq(info->irq, idev);
906 887
907 uio_dev_del_attributes(idev); 888 uio_dev_del_attributes(idev);
908 889
909 dev_set_drvdata(idev->dev, NULL); 890 device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
910 device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
911 kfree(idev); 891 kfree(idev);
912 uio_class_destroy();
913 892
914 return; 893 return;
915} 894}
@@ -917,11 +896,12 @@ EXPORT_SYMBOL_GPL(uio_unregister_device);
917 896
918static int __init uio_init(void) 897static int __init uio_init(void)
919{ 898{
920 return 0; 899 return init_uio_class();
921} 900}
922 901
923static void __exit uio_exit(void) 902static void __exit uio_exit(void)
924{ 903{
904 release_uio_class();
925} 905}
926 906
927module_init(uio_init) 907module_init(uio_init)
diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c
index a8ea2f19a0cc..a84a451159ed 100644
--- a/drivers/uio/uio_cif.c
+++ b/drivers/uio/uio_cif.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * UIO Hilscher CIF card driver 2 * UIO Hilscher CIF card driver
3 * 3 *
4 * (C) 2007 Hans J. Koch <hjk@linutronix.de> 4 * (C) 2007 Hans J. Koch <hjk@hansjkoch.de>
5 * Original code (C) 2005 Benedikt Spranger <b.spranger@linutronix.de> 5 * Original code (C) 2005 Benedikt Spranger <b.spranger@linutronix.de>
6 * 6 *
7 * Licensed under GPL version 2 only. 7 * Licensed under GPL version 2 only.
diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c
index 5a18e9f7b836..a879fd5741f8 100644
--- a/drivers/uio/uio_netx.c
+++ b/drivers/uio/uio_netx.c
@@ -2,7 +2,7 @@
2 * UIO driver for Hilscher NetX based fieldbus cards (cifX, comX). 2 * UIO driver for Hilscher NetX based fieldbus cards (cifX, comX).
3 * See http://www.hilscher.com for details. 3 * See http://www.hilscher.com for details.
4 * 4 *
5 * (C) 2007 Hans J. Koch <hjk@linutronix.de> 5 * (C) 2007 Hans J. Koch <hjk@hansjkoch.de>
6 * (C) 2008 Manuel Traut <manut@linutronix.de> 6 * (C) 2008 Manuel Traut <manut@linutronix.de>
7 * 7 *
8 * Licensed under GPL version 2 only. 8 * Licensed under GPL version 2 only.
@@ -18,6 +18,9 @@
18 18
19#define PCI_VENDOR_ID_HILSCHER 0x15CF 19#define PCI_VENDOR_ID_HILSCHER 0x15CF
20#define PCI_DEVICE_ID_HILSCHER_NETX 0x0000 20#define PCI_DEVICE_ID_HILSCHER_NETX 0x0000
21#define PCI_DEVICE_ID_HILSCHER_NETPLC 0x0010
22#define PCI_SUBDEVICE_ID_NETPLC_RAM 0x0000
23#define PCI_SUBDEVICE_ID_NETPLC_FLASH 0x0001
21#define PCI_SUBDEVICE_ID_NXSB_PCA 0x3235 24#define PCI_SUBDEVICE_ID_NXSB_PCA 0x3235
22#define PCI_SUBDEVICE_ID_NXPCA 0x3335 25#define PCI_SUBDEVICE_ID_NXPCA 0x3335
23 26
@@ -66,6 +69,10 @@ static int __devinit netx_pci_probe(struct pci_dev *dev,
66 bar = 0; 69 bar = 0;
67 info->name = "netx"; 70 info->name = "netx";
68 break; 71 break;
72 case PCI_DEVICE_ID_HILSCHER_NETPLC:
73 bar = 0;
74 info->name = "netplc";
75 break;
69 default: 76 default:
70 bar = 2; 77 bar = 2;
71 info->name = "netx_plx"; 78 info->name = "netx_plx";
@@ -134,6 +141,18 @@ static struct pci_device_id netx_pci_ids[] = {
134 .subdevice = 0, 141 .subdevice = 0,
135 }, 142 },
136 { 143 {
144 .vendor = PCI_VENDOR_ID_HILSCHER,
145 .device = PCI_DEVICE_ID_HILSCHER_NETPLC,
146 .subvendor = PCI_VENDOR_ID_HILSCHER,
147 .subdevice = PCI_SUBDEVICE_ID_NETPLC_RAM,
148 },
149 {
150 .vendor = PCI_VENDOR_ID_HILSCHER,
151 .device = PCI_DEVICE_ID_HILSCHER_NETPLC,
152 .subvendor = PCI_VENDOR_ID_HILSCHER,
153 .subdevice = PCI_SUBDEVICE_ID_NETPLC_FLASH,
154 },
155 {
137 .vendor = PCI_VENDOR_ID_PLX, 156 .vendor = PCI_VENDOR_ID_PLX,
138 .device = PCI_DEVICE_ID_PLX_9030, 157 .device = PCI_DEVICE_ID_PLX_9030,
139 .subvendor = PCI_VENDOR_ID_PLX, 158 .subvendor = PCI_VENDOR_ID_PLX,
diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c
index 85c9884a67fd..fc22e1e6f215 100644
--- a/drivers/uio/uio_pci_generic.c
+++ b/drivers/uio/uio_pci_generic.c
@@ -128,12 +128,6 @@ static int __devinit probe(struct pci_dev *pdev,
128 struct uio_pci_generic_dev *gdev; 128 struct uio_pci_generic_dev *gdev;
129 int err; 129 int err;
130 130
131 if (!pdev->irq) {
132 dev_warn(&pdev->dev, "No IRQ assigned to device: "
133 "no support for interrupts?\n");
134 return -ENODEV;
135 }
136
137 err = pci_enable_device(pdev); 131 err = pci_enable_device(pdev);
138 if (err) { 132 if (err) {
139 dev_err(&pdev->dev, "%s: pci_enable_device failed: %d\n", 133 dev_err(&pdev->dev, "%s: pci_enable_device failed: %d\n",
@@ -141,6 +135,13 @@ static int __devinit probe(struct pci_dev *pdev,
141 return err; 135 return err;
142 } 136 }
143 137
138 if (!pdev->irq) {
139 dev_warn(&pdev->dev, "No IRQ assigned to device: "
140 "no support for interrupts?\n");
141 pci_disable_device(pdev);
142 return -ENODEV;
143 }
144
144 err = verify_pci_2_3(pdev); 145 err = verify_pci_2_3(pdev);
145 if (err) 146 if (err)
146 goto err_verify; 147 goto err_verify;
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index 7174d518b8a6..0f424af7f109 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -189,6 +189,10 @@ static int uio_pdrv_genirq_remove(struct platform_device *pdev)
189 189
190 uio_unregister_device(priv->uioinfo); 190 uio_unregister_device(priv->uioinfo);
191 pm_runtime_disable(&pdev->dev); 191 pm_runtime_disable(&pdev->dev);
192
193 priv->uioinfo->handler = NULL;
194 priv->uioinfo->irqcontrol = NULL;
195
192 kfree(priv); 196 kfree(priv);
193 return 0; 197 return 0;
194} 198}
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
new file mode 100644
index 000000000000..e67b566e7aa3
--- /dev/null
+++ b/drivers/uio/uio_pruss.c
@@ -0,0 +1,247 @@
1/*
2 * Programmable Real-Time Unit Sub System (PRUSS) UIO driver (uio_pruss)
3 *
4 * This driver exports PRUSS host event out interrupts and PRUSS, L3 RAM,
5 * and DDR RAM to user space for applications interacting with PRUSS firmware
6 *
7 * Copyright (C) 2010-11 Texas Instruments Incorporated - http://www.ti.com/
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation version 2.
12 *
13 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
14 * kind, whether express or implied; without even the implied warranty
15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18#include <linux/device.h>
19#include <linux/module.h>
20#include <linux/moduleparam.h>
21#include <linux/platform_device.h>
22#include <linux/uio_driver.h>
23#include <linux/platform_data/uio_pruss.h>
24#include <linux/io.h>
25#include <linux/clk.h>
26#include <linux/dma-mapping.h>
27#include <linux/slab.h>
28#include <mach/sram.h>
29
30#define DRV_NAME "pruss_uio"
31#define DRV_VERSION "1.0"
32
33static int sram_pool_sz = SZ_16K;
34module_param(sram_pool_sz, int, 0);
35MODULE_PARM_DESC(sram_pool_sz, "sram pool size to allocate ");
36
37static int extram_pool_sz = SZ_256K;
38module_param(extram_pool_sz, int, 0);
39MODULE_PARM_DESC(extram_pool_sz, "external ram pool size to allocate");
40
41/*
42 * Host event IRQ numbers from PRUSS - PRUSS can generate up to 8 interrupt
43 * events to AINTC of ARM host processor - which can be used for IPC b/w PRUSS
44 * firmware and user space application, async notification from PRU firmware
45 * to user space application
46 * 3 PRU_EVTOUT0
47 * 4 PRU_EVTOUT1
48 * 5 PRU_EVTOUT2
49 * 6 PRU_EVTOUT3
50 * 7 PRU_EVTOUT4
51 * 8 PRU_EVTOUT5
52 * 9 PRU_EVTOUT6
53 * 10 PRU_EVTOUT7
54*/
55#define MAX_PRUSS_EVT 8
56
57#define PINTC_HIDISR 0x0038
58#define PINTC_HIPIR 0x0900
59#define HIPIR_NOPEND 0x80000000
60#define PINTC_HIER 0x1500
61
62struct uio_pruss_dev {
63 struct uio_info *info;
64 struct clk *pruss_clk;
65 dma_addr_t sram_paddr;
66 dma_addr_t ddr_paddr;
67 void __iomem *prussio_vaddr;
68 void *sram_vaddr;
69 void *ddr_vaddr;
70 unsigned int hostirq_start;
71 unsigned int pintc_base;
72};
73
74static irqreturn_t pruss_handler(int irq, struct uio_info *info)
75{
76 struct uio_pruss_dev *gdev = info->priv;
77 int intr_bit = (irq - gdev->hostirq_start + 2);
78 int val, intr_mask = (1 << intr_bit);
79 void __iomem *base = gdev->prussio_vaddr + gdev->pintc_base;
80 void __iomem *intren_reg = base + PINTC_HIER;
81 void __iomem *intrdis_reg = base + PINTC_HIDISR;
82 void __iomem *intrstat_reg = base + PINTC_HIPIR + (intr_bit << 2);
83
84 val = ioread32(intren_reg);
85 /* Is interrupt enabled and active ? */
86 if (!(val & intr_mask) && (ioread32(intrstat_reg) & HIPIR_NOPEND))
87 return IRQ_NONE;
88 /* Disable interrupt */
89 iowrite32(intr_bit, intrdis_reg);
90 return IRQ_HANDLED;
91}
92
93static void pruss_cleanup(struct platform_device *dev,
94 struct uio_pruss_dev *gdev)
95{
96 int cnt;
97 struct uio_info *p = gdev->info;
98
99 for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) {
100 uio_unregister_device(p);
101 kfree(p->name);
102 }
103 iounmap(gdev->prussio_vaddr);
104 if (gdev->ddr_vaddr) {
105 dma_free_coherent(&dev->dev, extram_pool_sz, gdev->ddr_vaddr,
106 gdev->ddr_paddr);
107 }
108 if (gdev->sram_vaddr)
109 sram_free(gdev->sram_vaddr, sram_pool_sz);
110 kfree(gdev->info);
111 clk_put(gdev->pruss_clk);
112 kfree(gdev);
113}
114
115static int __devinit pruss_probe(struct platform_device *dev)
116{
117 struct uio_info *p;
118 struct uio_pruss_dev *gdev;
119 struct resource *regs_prussio;
120 int ret = -ENODEV, cnt = 0, len;
121 struct uio_pruss_pdata *pdata = dev->dev.platform_data;
122
123 gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL);
124 if (!gdev)
125 return -ENOMEM;
126
127 gdev->info = kzalloc(sizeof(*p) * MAX_PRUSS_EVT, GFP_KERNEL);
128 if (!gdev->info) {
129 kfree(gdev);
130 return -ENOMEM;
131 }
132 /* Power on PRU in case its not done as part of boot-loader */
133 gdev->pruss_clk = clk_get(&dev->dev, "pruss");
134 if (IS_ERR(gdev->pruss_clk)) {
135 dev_err(&dev->dev, "Failed to get clock\n");
136 kfree(gdev->info);
137 kfree(gdev);
138 ret = PTR_ERR(gdev->pruss_clk);
139 return ret;
140 } else {
141 clk_enable(gdev->pruss_clk);
142 }
143
144 regs_prussio = platform_get_resource(dev, IORESOURCE_MEM, 0);
145 if (!regs_prussio) {
146 dev_err(&dev->dev, "No PRUSS I/O resource specified\n");
147 goto out_free;
148 }
149
150 if (!regs_prussio->start) {
151 dev_err(&dev->dev, "Invalid memory resource\n");
152 goto out_free;
153 }
154
155 gdev->sram_vaddr = sram_alloc(sram_pool_sz, &(gdev->sram_paddr));
156 if (!gdev->sram_vaddr) {
157 dev_err(&dev->dev, "Could not allocate SRAM pool\n");
158 goto out_free;
159 }
160
161 gdev->ddr_vaddr = dma_alloc_coherent(&dev->dev, extram_pool_sz,
162 &(gdev->ddr_paddr), GFP_KERNEL | GFP_DMA);
163 if (!gdev->ddr_vaddr) {
164 dev_err(&dev->dev, "Could not allocate external memory\n");
165 goto out_free;
166 }
167
168 len = resource_size(regs_prussio);
169 gdev->prussio_vaddr = ioremap(regs_prussio->start, len);
170 if (!gdev->prussio_vaddr) {
171 dev_err(&dev->dev, "Can't remap PRUSS I/O address range\n");
172 goto out_free;
173 }
174
175 gdev->pintc_base = pdata->pintc_base;
176 gdev->hostirq_start = platform_get_irq(dev, 0);
177
178 for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) {
179 p->mem[0].addr = regs_prussio->start;
180 p->mem[0].size = resource_size(regs_prussio);
181 p->mem[0].memtype = UIO_MEM_PHYS;
182
183 p->mem[1].addr = gdev->sram_paddr;
184 p->mem[1].size = sram_pool_sz;
185 p->mem[1].memtype = UIO_MEM_PHYS;
186
187 p->mem[2].addr = gdev->ddr_paddr;
188 p->mem[2].size = extram_pool_sz;
189 p->mem[2].memtype = UIO_MEM_PHYS;
190
191 p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt);
192 p->version = DRV_VERSION;
193
194 /* Register PRUSS IRQ lines */
195 p->irq = gdev->hostirq_start + cnt;
196 p->handler = pruss_handler;
197 p->priv = gdev;
198
199 ret = uio_register_device(&dev->dev, p);
200 if (ret < 0)
201 goto out_free;
202 }
203
204 platform_set_drvdata(dev, gdev);
205 return 0;
206
207out_free:
208 pruss_cleanup(dev, gdev);
209 return ret;
210}
211
212static int __devexit pruss_remove(struct platform_device *dev)
213{
214 struct uio_pruss_dev *gdev = platform_get_drvdata(dev);
215
216 pruss_cleanup(dev, gdev);
217 platform_set_drvdata(dev, NULL);
218 return 0;
219}
220
221static struct platform_driver pruss_driver = {
222 .probe = pruss_probe,
223 .remove = __devexit_p(pruss_remove),
224 .driver = {
225 .name = DRV_NAME,
226 .owner = THIS_MODULE,
227 },
228};
229
230static int __init pruss_init_module(void)
231{
232 return platform_driver_register(&pruss_driver);
233}
234
235module_init(pruss_init_module);
236
237static void __exit pruss_exit_module(void)
238{
239 platform_driver_unregister(&pruss_driver);
240}
241
242module_exit(pruss_exit_module);
243
244MODULE_LICENSE("GPL v2");
245MODULE_VERSION(DRV_VERSION);
246MODULE_AUTHOR("Amit Chatterjee <amit.chatterjee@ti.com>");
247MODULE_AUTHOR("Pratheesh Gangadhar <pratheesh@ti.com>");