11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Acorn RiscPC mouse driver for Linux/ARM 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (c) 2000-2002 Vojtech Pavlik 51da177e4SLinus Torvalds * Copyright (C) 1996-2002 Russell King 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds */ 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds /* 101da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify it 111da177e4SLinus Torvalds * under the terms of the GNU General Public License version 2 as published by 121da177e4SLinus Torvalds * the Free Software Foundation. 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * This handles the Acorn RiscPCs mouse. We basically have a couple of 151da177e4SLinus Torvalds * hardware registers that track the sensor count for the X-Y movement and 161da177e4SLinus Torvalds * another register holding the button state. On every VSYNC interrupt we read 171da177e4SLinus Torvalds * the complete state and then work out if something has changed. 181da177e4SLinus Torvalds */ 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds #include <linux/module.h> 211da177e4SLinus Torvalds #include <linux/sched.h> 221da177e4SLinus Torvalds #include <linux/ptrace.h> 231da177e4SLinus Torvalds #include <linux/interrupt.h> 241da177e4SLinus Torvalds #include <linux/init.h> 251da177e4SLinus Torvalds #include <linux/input.h> 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include <asm/hardware.h> 281da177e4SLinus Torvalds #include <asm/irq.h> 291da177e4SLinus Torvalds #include <asm/io.h> 301da177e4SLinus Torvalds #include <asm/hardware/iomd.h> 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds MODULE_AUTHOR("Vojtech Pavlik, Russell King"); 331da177e4SLinus Torvalds MODULE_DESCRIPTION("Acorn RiscPC mouse driver"); 341da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds static short rpcmouse_lastx, rpcmouse_lasty; 372e5b636bSDmitry Torokhov static struct input_dev *rpcmouse_dev; 381da177e4SLinus Torvalds 397d12e780SDavid Howells static irqreturn_t rpcmouse_irq(int irq, void *dev_id) 401da177e4SLinus Torvalds { 411da177e4SLinus Torvalds struct input_dev *dev = dev_id; 421da177e4SLinus Torvalds short x, y, dx, dy, b; 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds x = (short) iomd_readl(IOMD_MOUSEX); 451da177e4SLinus Torvalds y = (short) iomd_readl(IOMD_MOUSEY); 461da177e4SLinus Torvalds b = (short) (__raw_readl(0xe0310000) ^ 0x70); 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds dx = x - rpcmouse_lastx; 491da177e4SLinus Torvalds dy = y - rpcmouse_lasty; 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds rpcmouse_lastx = x; 521da177e4SLinus Torvalds rpcmouse_lasty = y; 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds input_report_rel(dev, REL_X, dx); 551da177e4SLinus Torvalds input_report_rel(dev, REL_Y, -dy); 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds input_report_key(dev, BTN_LEFT, b & 0x40); 581da177e4SLinus Torvalds input_report_key(dev, BTN_MIDDLE, b & 0x20); 591da177e4SLinus Torvalds input_report_key(dev, BTN_RIGHT, b & 0x10); 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds input_sync(dev); 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds return IRQ_HANDLED; 641da177e4SLinus Torvalds } 651da177e4SLinus Torvalds 662e5b636bSDmitry Torokhov 671da177e4SLinus Torvalds static int __init rpcmouse_init(void) 681da177e4SLinus Torvalds { 69*72155615SDmitry Torokhov int err; 70*72155615SDmitry Torokhov 71*72155615SDmitry Torokhov rpcmouse_dev = input_allocate_device(); 72*72155615SDmitry Torokhov if (!rpcmouse_dev) 732e5b636bSDmitry Torokhov return -ENOMEM; 742e5b636bSDmitry Torokhov 752e5b636bSDmitry Torokhov rpcmouse_dev->name = "Acorn RiscPC Mouse"; 762e5b636bSDmitry Torokhov rpcmouse_dev->phys = "rpcmouse/input0"; 772e5b636bSDmitry Torokhov rpcmouse_dev->id.bustype = BUS_HOST; 782e5b636bSDmitry Torokhov rpcmouse_dev->id.vendor = 0x0005; 792e5b636bSDmitry Torokhov rpcmouse_dev->id.product = 0x0001; 802e5b636bSDmitry Torokhov rpcmouse_dev->id.version = 0x0100; 812e5b636bSDmitry Torokhov 822e5b636bSDmitry Torokhov rpcmouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); 832e5b636bSDmitry Torokhov rpcmouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); 842e5b636bSDmitry Torokhov rpcmouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds rpcmouse_lastx = (short) iomd_readl(IOMD_MOUSEX); 871da177e4SLinus Torvalds rpcmouse_lasty = (short) iomd_readl(IOMD_MOUSEY); 881da177e4SLinus Torvalds 89dace1453SThomas Gleixner if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, IRQF_SHARED, "rpcmouse", rpcmouse_dev)) { 901da177e4SLinus Torvalds printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n"); 91*72155615SDmitry Torokhov err = -EBUSY; 92*72155615SDmitry Torokhov goto err_free_dev; 931da177e4SLinus Torvalds } 941da177e4SLinus Torvalds 95*72155615SDmitry Torokhov err = input_register_device(rpcmouse_dev); 96*72155615SDmitry Torokhov if (err) 97*72155615SDmitry Torokhov goto err_free_irq; 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds return 0; 100*72155615SDmitry Torokhov 101*72155615SDmitry Torokhov err_free_irq: 102*72155615SDmitry Torokhov free_irq(IRQ_VSYNCPULSE, rpcmouse_dev); 103*72155615SDmitry Torokhov err_free_dev: 104*72155615SDmitry Torokhov input_free_device(rpcmouse_dev); 105*72155615SDmitry Torokhov 106*72155615SDmitry Torokhov return err; 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds static void __exit rpcmouse_exit(void) 1101da177e4SLinus Torvalds { 1112e5b636bSDmitry Torokhov free_irq(IRQ_VSYNCPULSE, rpcmouse_dev); 1122e5b636bSDmitry Torokhov input_unregister_device(rpcmouse_dev); 1131da177e4SLinus Torvalds } 1141da177e4SLinus Torvalds 1151da177e4SLinus Torvalds module_init(rpcmouse_init); 1161da177e4SLinus Torvalds module_exit(rpcmouse_exit); 117