Author: wookey
Date: 2008-04-29 16:51:01 +0100 (Tue, 29 Apr 2008)
New Revision: 474
Modified:
balloon/trunk/kernel/2.6.22.2/balloon3-minipug.patch
Log:
Updated minipug driver that works with udev (using classes rather than
platform driver as that didn't work - further investigation required
sometime)
Modified: balloon/trunk/kernel/2.6.22.2/balloon3-minipug.patch
===================================================================
--- balloon/trunk/kernel/2.6.22.2/balloon3-minipug.patch 2008-04-29 15:24:57 UTC (rev 473)
+++ balloon/trunk/kernel/2.6.22.2/balloon3-minipug.patch 2008-04-29 15:51:01 UTC (rev 474)
@@ -1,7 +1,7 @@
Index: linux-2.6.22.2/drivers/char/Kconfig
===================================================================
---- linux-2.6.22.2.orig/drivers/char/Kconfig 2008-03-27 15:17:27.000000000 +0000
-+++ linux-2.6.22.2/drivers/char/Kconfig 2008-03-27 15:17:27.000000000 +0000
+--- linux-2.6.22.2.orig/drivers/char/Kconfig 2008-04-29 09:52:26.000000000 +0100
++++ linux-2.6.22.2/drivers/char/Kconfig 2008-04-29 09:52:26.000000000 +0100
@@ -1092,6 +1092,12 @@
Balloon2, 8 or 16 bit on Balloon3. You normally want this
unless you are using the bus lines for something else.
@@ -17,8 +17,8 @@
Index: linux-2.6.22.2/drivers/char/Makefile
===================================================================
---- linux-2.6.22.2.orig/drivers/char/Makefile 2008-03-27 15:17:27.000000000 +0000
-+++ linux-2.6.22.2/drivers/char/Makefile 2008-03-27 15:17:27.000000000 +0000
+--- linux-2.6.22.2.orig/drivers/char/Makefile 2008-04-29 09:52:26.000000000 +0100
++++ linux-2.6.22.2/drivers/char/Makefile 2008-04-29 09:52:26.000000000 +0100
@@ -105,6 +105,7 @@
obj-$(CONFIG_TCG_TPM) += tpm/
@@ -30,8 +30,8 @@
Index: linux-2.6.22.2/drivers/char/minipug.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22.2/drivers/char/minipug.c 2008-03-27 15:23:34.000000000 +0000
-@@ -0,0 +1,640 @@
++++ linux-2.6.22.2/drivers/char/minipug.c 2008-04-29 13:42:15.000000000 +0100
+@@ -0,0 +1,729 @@
+/*
+ * linux/drivers/char/minipug.c
+ *
@@ -59,8 +59,26 @@
+#include <linux/vmalloc.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
++#include "linux/cdev.h"
+#include "samosa.h"
+
++// uncomment to use a minipug class model.
++// This is needed at the moment for udev as
++// the add uevent seems to be missing the MAJOR
++// and MINOR fields if done via platform devices.
++#define MINIPUG_CLASS
++
++// uncomment for fixed node major numbering
++// #define MINIPUG_MAJOR 200
++
++#ifdef MINIPUG_MAJOR
++static int major = MINIPUG_MAJOR;
++#else
++static int major = 0;
++module_param(major, int, 0);
++MODULE_PARM_DESC(major, "Major device number");
++#endif
++
+static spinlock_t minipug_lock;
+
+#define dprintk(x...)
@@ -363,7 +381,6 @@
+ mmap: minipug_mmap,
+};
+
-+#define MINIPUG_MAJOR 200
+
+struct minipug_info minipug[2]={
+ {display: 0},
@@ -538,76 +555,39 @@
+}
+
+/* driver initialisation */
++static int __init minipug_probe ( struct platform_device *pdev) {
+
-+static int __init minipug_probe ( struct platform_device *pdev) {
++#ifndef CONFIG_BALLOON2_BUILD_TCL_PIKEY2
+ // if smart media present - cpld cannot be so declare invalid
-+#ifndef CONFIG_BALLOON2_BUILD_TCL_PIKEY2
+ if (balloon_samosa_sm_present()) {
+ printk("%s: samosa bus not present\n",__FUNCTION__);
+ return -ENODEV;
+ }
+#endif
+
-+ // check that the displays are ready
-+ if (!minipug_ready(0)) {
-+ printk("%s: minipug0 not ready\n",__FUNCTION__);
++ if (!minipug_ready(pdev->id)) {
++ printk("%s: minipug %d not ready\n",__FUNCTION__,pdev->id);
+ return -ENODEV;
+ }
+
-+ if (!minipug_ready(1)) {
-+ printk("%s: minipug1 not ready\n",__FUNCTION__);
-+ return -ENODEV;
-+ }
-+
-+ minipug[0].buffer=(unsigned char *)vmalloc_user(BUFFER_SIZE);
-+ if (!minipug[0].buffer) {
-+ printk("%s: minipug0 not enough memory\n",__FUNCTION__);
++ minipug[pdev->id].buffer=(unsigned char *)vmalloc_user(BUFFER_SIZE);
++ if (!minipug[pdev->id].buffer) {
++ printk("%s: minipug %d not enough memory\n",__FUNCTION__,pdev->id);
+ return -ENOMEM;
+ }
+
-+ minipug[1].buffer=(unsigned char *)vmalloc_user(BUFFER_SIZE);
-+ if (!minipug[1].buffer) {
-+ kfree(minipug[0].buffer);
-+ printk("%s: minipug1 not enough memory\n",__FUNCTION__);
-+ return -ENOMEM;
-+ }
-+
-+ spin_lock_init(&minipug_lock);
-+
-+ register_chrdev(MINIPUG_MAJOR,"minipug",&minipug_fops);
-+// register_chrdev_region(mp_dev,2,"minipug");
-+
-+ active_display=0;
-+ minipug[0].bpp=DISPLAY_BPP0;
++ active_display=pdev->id;
++ minipug[active_display].bpp=DISPLAY_BPP0;
+ minipug_setup();
+
-+ active_display=1;
-+ minipug[1].bpp=DISPLAY_BPP1;
-+ minipug_setup();
++ printk("Minipug %d display support installed\n",pdev->id);
+
-+ // create proc access to displays
-+ proc_minipug = create_proc_entry(PROC_MINIPUG,S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, &proc_root);
-+ if (proc_minipug)
-+ proc_minipug->proc_fops = &proc_minipug_operations;
-+
-+ printk("Minipug display support installed\n");
-+
+ return 0;
+}
+
+static int __exit minipug_remove (struct platform_device *_dev)
+{
-+ // remove proc entry
-+ remove_proc_entry(PROC_MINIPUG,&proc_root);
-+
-+ // remove dev entries
-+// unregister_chrdev_region(mp_dev,2);
-+ unregister_chrdev(MINIPUG_MAJOR,"minipug");
-+
-+ // free memory
-+ vfree(minipug[0].buffer);
-+ vfree(minipug[1].buffer);
-+
++ vfree(minipug[_dev->id].buffer);
+ platform_set_drvdata(_dev,NULL);
+ return 0;
+}
@@ -636,6 +616,7 @@
+{
+}
+
++// driver definition
+static struct platform_driver minipug_driver = {
+ .probe = minipug_probe,
+ .shutdown = minipug_shutdown,
@@ -648,21 +629,130 @@
+ },
+};
+
-+static struct platform_device minipug_device = {
-+ .name = "minipug",
-+ .id = 0,
++// character device
++static struct cdev minipug_cdev = {
++ .kobj = {.name = "minipug", },
++ .owner = THIS_MODULE,
+};
+
++static dev_t dev;
++#ifdef MINIPUG_CLASS
++static struct class *minipug_class;
++#else
++static struct platform_device *minipug_device[2];
++#endif
++
+static int __init minipug_init(void)
+{
-+ platform_device_register(&minipug_device);
++ int ret;
++
++ // general initialisation
++ spin_lock_init(&minipug_lock);
++
++ // register a range of device nodes
++ if (major) {
++ dev = MKDEV(major,0);
++ ret = register_chrdev_region(dev, 2, "minipug");
++ }
++ else {
++ ret = alloc_chrdev_region(&dev, 0, 2, "minipug");
++ major = MAJOR(dev);
++ }
++
++ if (ret)
++ goto error;
++
++ // create a character device handler
++ cdev_init(&minipug_cdev,&minipug_fops);
++ // add character device with 2 entries
++ ret = cdev_add(&minipug_cdev, dev, 2);
++ if (ret) {
++ kobject_put(&minipug_cdev.kobj);
++ goto error_region;
++ }
++
++#ifdef MINIPUG_CLASS
++ // explicitly create 2 devices via a minipug class
++ // this seems necessary to avoid the problem of platform devices
++ // not sending MAJOR and MINOR fields so udev is unable to
++ // create the device nodes.
++ minipug_class = class_create(THIS_MODULE, "minipug");
++ if (IS_ERR(minipug_class)) {
++ printk(KERN_ERR "Error creating minipug class.\n");
++ cdev_del(&minipug_cdev);
++ ret = PTR_ERR(minipug_class);
++ goto error_region;
++ }
++ // create the actual devices
++ device_create(minipug_class, NULL, MKDEV(major, 0), "minipug0");
++ device_create(minipug_class, NULL, MKDEV(major, 1), "minipug1");
++#else
++#if 1
++ minipug_device[0] = platform_device_alloc("minipug", 0);
++ // this is a hack to permit uevents
++ minipug_device[0]->dev.uevent_suppress = 0;
++ minipug_device[1] = platform_device_alloc("minipug", 1);
++ // this is a hack to permit uevents
++ minipug_device[1]->dev.uevent_suppress = 0;
++#else
++ // this seems a way not to have to hack platform_device_alloc
++ // it needs a release function and also doesnt pass MAJOR or MINOR
++ minipug_device[0] = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
++ minipug_device[0]->name = "minipug";
++ minipug_device[0]->id = 0;
++// minipug_device[0].release = minipug_release;
++
++ minipug_device[1] = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
++ minipug_device[1]->name = "minipug";
++ minipug_device[1]->id = 1;
++// minipug_device[1].release = minipug_release;
++#endif
++
++// both the versions below work fine
++#if 1
++ platform_device_register(minipug_device[0]);
++ platform_device_register(minipug_device[1]);
++#else
++ platform_add_devices(minipug_device, ARRAY_SIZE(minipug_device));
++#endif
++#endif
++
++ // create proc access to displays
++ proc_minipug = create_proc_entry(PROC_MINIPUG,S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, &proc_root);
++ if (proc_minipug)
++ proc_minipug->proc_fops = &proc_minipug_operations;
++
++ // register the driver
+ return platform_driver_register(&minipug_driver);
++
++error_region:
++ unregister_chrdev_region(dev, 2);
++error:
++ return ret;
+}
+
+static void __exit minipug_exit(void)
+{
++ // remove proc entry
++ remove_proc_entry(PROC_MINIPUG,&proc_root);
++#ifdef MINIPUG_CLASS
++ // remove devices
++ device_destroy(minipug_class, MKDEV(major, 0));
++ device_destroy(minipug_class, MKDEV(major, 1));
++ // remove class
++ class_destroy(minipug_class);
++#else
++ platform_device_unregister(minipug_device[0]);
++ kfree(minipug_device[0]);
++ platform_device_unregister(minipug_device[1]);
++ kfree(minipug_device[1]);
++#endif
++ // remove driver
+ platform_driver_unregister(&minipug_driver);
-+ platform_device_unregister(&minipug_device);
++ // remove character device
++ cdev_del(&minipug_cdev);
++ // unregister region
++ unregister_chrdev_region(dev, 2);
+}
+
+module_init(minipug_init);
@@ -671,4 +761,3 @@
+MODULE_AUTHOR("Nick Bane <
nick@cecomputing.co.uk>");
+MODULE_DESCRIPTION("Minipug display interface via samosa bus on Balloon");
+MODULE_LICENSE("GPL");
-+