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 391da177e4SLinus Torvalds static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs) 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_regs(dev, regs); 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds input_report_rel(dev, REL_X, dx); 571da177e4SLinus Torvalds input_report_rel(dev, REL_Y, -dy); 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds input_report_key(dev, BTN_LEFT, b & 0x40); 601da177e4SLinus Torvalds input_report_key(dev, BTN_MIDDLE, b & 0x20); 611da177e4SLinus Torvalds input_report_key(dev, BTN_RIGHT, b & 0x10); 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds input_sync(dev); 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds return IRQ_HANDLED; 661da177e4SLinus Torvalds } 671da177e4SLinus Torvalds 682e5b636bSDmitry Torokhov 691da177e4SLinus Torvalds static int __init rpcmouse_init(void) 701da177e4SLinus Torvalds { 712e5b636bSDmitry Torokhov if (!(rpcmouse_dev = input_allocate_device())) 722e5b636bSDmitry Torokhov return -ENOMEM; 732e5b636bSDmitry Torokhov 742e5b636bSDmitry Torokhov rpcmouse_dev->name = "Acorn RiscPC Mouse"; 752e5b636bSDmitry Torokhov rpcmouse_dev->phys = "rpcmouse/input0"; 762e5b636bSDmitry Torokhov rpcmouse_dev->id.bustype = BUS_HOST; 772e5b636bSDmitry Torokhov rpcmouse_dev->id.vendor = 0x0005; 782e5b636bSDmitry Torokhov rpcmouse_dev->id.product = 0x0001; 792e5b636bSDmitry Torokhov rpcmouse_dev->id.version = 0x0100; 802e5b636bSDmitry Torokhov 812e5b636bSDmitry Torokhov rpcmouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); 822e5b636bSDmitry Torokhov rpcmouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); 832e5b636bSDmitry Torokhov rpcmouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); 841da177e4SLinus Torvalds 851da177e4SLinus Torvalds rpcmouse_lastx = (short) iomd_readl(IOMD_MOUSEX); 861da177e4SLinus Torvalds rpcmouse_lasty = (short) iomd_readl(IOMD_MOUSEY); 871da177e4SLinus Torvalds 88*dace1453SThomas Gleixner if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, IRQF_SHARED, "rpcmouse", rpcmouse_dev)) { 891da177e4SLinus Torvalds printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n"); 902e5b636bSDmitry Torokhov input_free_device(rpcmouse_dev); 912e5b636bSDmitry Torokhov return -EBUSY; 921da177e4SLinus Torvalds } 931da177e4SLinus Torvalds 942e5b636bSDmitry Torokhov input_register_device(rpcmouse_dev); 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds return 0; 971da177e4SLinus Torvalds } 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds static void __exit rpcmouse_exit(void) 1001da177e4SLinus Torvalds { 1012e5b636bSDmitry Torokhov free_irq(IRQ_VSYNCPULSE, rpcmouse_dev); 1022e5b636bSDmitry Torokhov input_unregister_device(rpcmouse_dev); 1031da177e4SLinus Torvalds } 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds module_init(rpcmouse_init); 1061da177e4SLinus Torvalds module_exit(rpcmouse_exit); 107