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/ptrace.h> 221da177e4SLinus Torvalds #include <linux/interrupt.h> 231da177e4SLinus Torvalds #include <linux/init.h> 241da177e4SLinus Torvalds #include <linux/input.h> 251da177e4SLinus Torvalds 26*a09e64fbSRussell King #include <mach/hardware.h> 271da177e4SLinus Torvalds #include <asm/irq.h> 281da177e4SLinus Torvalds #include <asm/io.h> 291da177e4SLinus Torvalds #include <asm/hardware/iomd.h> 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds MODULE_AUTHOR("Vojtech Pavlik, Russell King"); 321da177e4SLinus Torvalds MODULE_DESCRIPTION("Acorn RiscPC mouse driver"); 331da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds static short rpcmouse_lastx, rpcmouse_lasty; 362e5b636bSDmitry Torokhov static struct input_dev *rpcmouse_dev; 371da177e4SLinus Torvalds 387d12e780SDavid Howells static irqreturn_t rpcmouse_irq(int irq, void *dev_id) 391da177e4SLinus Torvalds { 401da177e4SLinus Torvalds struct input_dev *dev = dev_id; 411da177e4SLinus Torvalds short x, y, dx, dy, b; 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds x = (short) iomd_readl(IOMD_MOUSEX); 441da177e4SLinus Torvalds y = (short) iomd_readl(IOMD_MOUSEY); 451da177e4SLinus Torvalds b = (short) (__raw_readl(0xe0310000) ^ 0x70); 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds dx = x - rpcmouse_lastx; 481da177e4SLinus Torvalds dy = y - rpcmouse_lasty; 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds rpcmouse_lastx = x; 511da177e4SLinus Torvalds rpcmouse_lasty = y; 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds input_report_rel(dev, REL_X, dx); 541da177e4SLinus Torvalds input_report_rel(dev, REL_Y, -dy); 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds input_report_key(dev, BTN_LEFT, b & 0x40); 571da177e4SLinus Torvalds input_report_key(dev, BTN_MIDDLE, b & 0x20); 581da177e4SLinus Torvalds input_report_key(dev, BTN_RIGHT, b & 0x10); 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds input_sync(dev); 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds return IRQ_HANDLED; 631da177e4SLinus Torvalds } 641da177e4SLinus Torvalds 652e5b636bSDmitry Torokhov 661da177e4SLinus Torvalds static int __init rpcmouse_init(void) 671da177e4SLinus Torvalds { 6872155615SDmitry Torokhov int err; 6972155615SDmitry Torokhov 7072155615SDmitry Torokhov rpcmouse_dev = input_allocate_device(); 7172155615SDmitry Torokhov if (!rpcmouse_dev) 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 817b19ada2SJiri Slaby rpcmouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); 827b19ada2SJiri Slaby rpcmouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | 837b19ada2SJiri Slaby BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); 847b19ada2SJiri Slaby rpcmouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(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"); 9172155615SDmitry Torokhov err = -EBUSY; 9272155615SDmitry Torokhov goto err_free_dev; 931da177e4SLinus Torvalds } 941da177e4SLinus Torvalds 9572155615SDmitry Torokhov err = input_register_device(rpcmouse_dev); 9672155615SDmitry Torokhov if (err) 9772155615SDmitry Torokhov goto err_free_irq; 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds return 0; 10072155615SDmitry Torokhov 10172155615SDmitry Torokhov err_free_irq: 10272155615SDmitry Torokhov free_irq(IRQ_VSYNCPULSE, rpcmouse_dev); 10372155615SDmitry Torokhov err_free_dev: 10472155615SDmitry Torokhov input_free_device(rpcmouse_dev); 10572155615SDmitry Torokhov 10672155615SDmitry 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