fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / input / serio / ct82c710.c
index b7fc99e..0d35018 100644 (file)
 /*
  * 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; either version 2 of the License, or 
+ * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
+ *
  * Should you need to contact me, the author, you can do so either by
  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/serio.h>
 #include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 
@@ -43,9 +44,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("82C710 C&T mouse port chip driver");
 MODULE_LICENSE("GPL");
 
-static char ct82c710_name[] = "C&T 82c710 mouse port";
-static char ct82c710_phys[16];
-
 /*
  * ct82c710 interface
  */
@@ -61,10 +59,22 @@ static char ct82c710_phys[16];
 
 #define CT82C710_IRQ          12
 
-static int ct82c710_data;
-static int ct82c710_status;
+#define CT82C710_DATA         ct82c710_iores.start
+#define CT82C710_STATUS       (ct82c710_iores.start + 1)
 
-static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs);
+static struct serio *ct82c710_port;
+static struct platform_device *ct82c710_device;
+static struct resource ct82c710_iores;
+
+/*
+ * Interrupt handler for the 82C710 mouse port. A character
+ * is waiting in the 82C710.
+ */
+
+static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id)
+{
+       return serio_interrupt(ct82c710_port, inb(CT82C710_DATA), 0);
+}
 
 /*
  * Wait for device to send output char and flush any input char.
@@ -74,10 +84,10 @@ static int ct82c170_wait(void)
 {
        int timeout = 60000;
 
-       while ((inb(ct82c710_status) & (CT82C710_RX_FULL | CT82C710_TX_IDLE | CT82C710_DEV_IDLE))
+       while ((inb(CT82C710_STATUS) & (CT82C710_RX_FULL | CT82C710_TX_IDLE | CT82C710_DEV_IDLE))
                       != (CT82C710_DEV_IDLE | CT82C710_TX_IDLE) && timeout) {
 
-               if (inb_p(ct82c710_status) & CT82C710_RX_FULL) inb_p(ct82c710_data);
+               if (inb_p(CT82C710_STATUS) & CT82C710_RX_FULL) inb_p(CT82C710_DATA);
 
                udelay(1);
                timeout--;
@@ -91,7 +101,7 @@ static void ct82c710_close(struct serio *serio)
        if (ct82c170_wait())
                printk(KERN_WARNING "ct82c710.c: Device busy in close()\n");
 
-       outb_p(inb_p(ct82c710_status) & ~(CT82C710_ENABLE | CT82C710_INTS_ON), ct82c710_status);
+       outb_p(inb_p(CT82C710_STATUS) & ~(CT82C710_ENABLE | CT82C710_INTS_ON), CT82C710_STATUS);
 
        if (ct82c170_wait())
                printk(KERN_WARNING "ct82c710.c: Device busy in close()\n");
@@ -106,21 +116,21 @@ static int ct82c710_open(struct serio *serio)
        if (request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL))
                return -1;
 
-       status = inb_p(ct82c710_status);
+       status = inb_p(CT82C710_STATUS);
 
        status |= (CT82C710_ENABLE | CT82C710_RESET);
-       outb_p(status, ct82c710_status);
+       outb_p(status, CT82C710_STATUS);
 
        status &= ~(CT82C710_RESET);
-       outb_p(status, ct82c710_status);
+       outb_p(status, CT82C710_STATUS);
 
        status |= CT82C710_INTS_ON;
-       outb_p(status, ct82c710_status);        /* Enable interrupts */
+       outb_p(status, CT82C710_STATUS);        /* Enable interrupts */
 
        while (ct82c170_wait()) {
                printk(KERN_ERR "ct82c710: Device busy in open()\n");
                status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON);
-               outb_p(status, ct82c710_status);
+               outb_p(status, CT82C710_STATUS);
                free_irq(CT82C710_IRQ, NULL);
                return -1;
        }
@@ -135,35 +145,15 @@ static int ct82c710_open(struct serio *serio)
 static int ct82c710_write(struct serio *port, unsigned char c)
 {
        if (ct82c170_wait()) return -1;
-       outb_p(c, ct82c710_data);
+       outb_p(c, CT82C710_DATA);
        return 0;
 }
 
-static struct serio ct82c710_port =
-{
-       .type   = SERIO_8042,
-       .name   = ct82c710_name,
-       .phys   = ct82c710_phys,
-       .write  = ct82c710_write,
-       .open   = ct82c710_open,
-       .close  = ct82c710_close,
-};
-
-/*
- * Interrupt handler for the 82C710 mouse port. A character
- * is waiting in the 82C710.
- */
-
-static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
-{
-       return serio_interrupt(&ct82c710_port, inb(ct82c710_data), 0, regs);
-}
-
 /*
  * See if we can find a 82C710 device. Read mouse address.
  */
 
-static int __init ct82c710_probe(void)
+static int __init ct82c710_detect(void)
 {
        outb_p(0x55, 0x2fa);                            /* Any value except 9, ff or 36 */
        outb_p(0xaa, 0x3fa);                            /* Inverse of 55 */
@@ -172,39 +162,100 @@ static int __init ct82c710_probe(void)
        outb_p(0x1b, 0x2fa);                            /* Inverse of e4 */
        outb_p(0x0f, 0x390);                            /* Write index */
        if (inb_p(0x391) != 0xe4)                       /* Config address found? */
-               return -1;                              /* No: no 82C710 here */
+               return -ENODEV;                         /* No: no 82C710 here */
 
        outb_p(0x0d, 0x390);                            /* Write index */
-       ct82c710_data = inb_p(0x391) << 2;              /* Get mouse I/O address */
-       ct82c710_status = ct82c710_data + 1;
+       ct82c710_iores.start = inb_p(0x391) << 2;       /* Get mouse I/O address */
+       ct82c710_iores.end = ct82c710_iores.start + 1;
+       ct82c710_iores.flags = IORESOURCE_IO;
        outb_p(0x0f, 0x390);
        outb_p(0x0f, 0x391);                            /* Close config mode */
 
        return 0;
 }
 
-int __init ct82c710_init(void)
+static int __devinit ct82c710_probe(struct platform_device *dev)
+{
+       ct82c710_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
+       if (!ct82c710_port)
+               return -ENOMEM;
+
+       ct82c710_port->id.type = SERIO_8042;
+       ct82c710_port->dev.parent = &dev->dev;
+       ct82c710_port->open = ct82c710_open;
+       ct82c710_port->close = ct82c710_close;
+       ct82c710_port->write = ct82c710_write;
+       strlcpy(ct82c710_port->name, "C&T 82c710 mouse port",
+               sizeof(ct82c710_port->name));
+       snprintf(ct82c710_port->phys, sizeof(ct82c710_port->phys),
+                "isa%16llx/serio0", (unsigned long long)CT82C710_DATA);
+
+       serio_register_port(ct82c710_port);
+
+       return 0;
+}
+
+static int __devexit ct82c710_remove(struct platform_device *dev)
+{
+       serio_unregister_port(ct82c710_port);
+
+       return 0;
+}
+
+static struct platform_driver ct82c710_driver = {
+       .driver         = {
+               .name   = "ct82c710",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = ct82c710_probe,
+       .remove         = __devexit_p(ct82c710_remove),
+};
+
+
+static int __init ct82c710_init(void)
 {
-       if (ct82c710_probe())
-               return -ENODEV;
+       int error;
 
-       if (request_region(ct82c710_data, 2, "ct82c710"))
-               return -EBUSY;
+       error = ct82c710_detect();
+       if (error)
+               return error;
 
-       sprintf(ct82c710_phys, "isa%04x/serio0", ct82c710_data);
+       error = platform_driver_register(&ct82c710_driver);
+       if (error)
+               return error;
 
-       serio_register_port(&ct82c710_port);
+       ct82c710_device = platform_device_alloc("ct82c710", -1);
+       if (!ct82c710_device) {
+               error = -ENOMEM;
+               goto err_unregister_driver;
+       }
+
+       error = platform_device_add_resources(ct82c710_device, &ct82c710_iores, 1);
+       if (error)
+               goto err_free_device;
+
+       error = platform_device_add(ct82c710_device);
+       if (error)
+               goto err_free_device;
 
-       printk(KERN_INFO "serio: C&T 82c710 mouse port at %#x irq %d\n",
-               ct82c710_data, CT82C710_IRQ);
+       serio_register_port(ct82c710_port);
+
+       printk(KERN_INFO "serio: C&T 82c710 mouse port at %#llx irq %d\n",
+               (unsigned long long)CT82C710_DATA, CT82C710_IRQ);
 
        return 0;
+
+ err_free_device:
+       platform_device_put(ct82c710_device);
+ err_unregister_driver:
+       platform_driver_unregister(&ct82c710_driver);
+       return error;
 }
 
-void __exit ct82c710_exit(void)
+static void __exit ct82c710_exit(void)
 {
-       serio_unregister_port(&ct82c710_port);
-       release_region(ct82c710_data, 2);
+       platform_device_unregister(ct82c710_device);
+       platform_driver_unregister(&ct82c710_driver);
 }
 
 module_init(ct82c710_init);