1*d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * Acorn RiscPC mouse driver for Linux/ARM 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (c) 2000-2002 Vojtech Pavlik 61da177e4SLinus Torvalds * Copyright (C) 1996-2002 Russell King 71da177e4SLinus Torvalds */ 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds /* 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * This handles the Acorn RiscPCs mouse. We basically have a couple of 121da177e4SLinus Torvalds * hardware registers that track the sensor count for the X-Y movement and 131da177e4SLinus Torvalds * another register holding the button state. On every VSYNC interrupt we read 141da177e4SLinus Torvalds * the complete state and then work out if something has changed. 151da177e4SLinus Torvalds */ 161da177e4SLinus Torvalds 171da177e4SLinus Torvalds #include <linux/module.h> 181da177e4SLinus Torvalds #include <linux/ptrace.h> 191da177e4SLinus Torvalds #include <linux/interrupt.h> 201da177e4SLinus Torvalds #include <linux/init.h> 211da177e4SLinus Torvalds #include <linux/input.h> 2299730225SRussell King #include <linux/io.h> 231da177e4SLinus Torvalds 24a09e64fbSRussell King #include <mach/hardware.h> 251da177e4SLinus Torvalds #include <asm/irq.h> 261da177e4SLinus Torvalds #include <asm/hardware/iomd.h> 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds MODULE_AUTHOR("Vojtech Pavlik, Russell King"); 291da177e4SLinus Torvalds MODULE_DESCRIPTION("Acorn RiscPC mouse driver"); 301da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds static short rpcmouse_lastx, rpcmouse_lasty; 332e5b636bSDmitry Torokhov static struct input_dev *rpcmouse_dev; 341da177e4SLinus Torvalds 357d12e780SDavid Howells static irqreturn_t rpcmouse_irq(int irq, void *dev_id) 361da177e4SLinus Torvalds { 371da177e4SLinus Torvalds struct input_dev *dev = dev_id; 381da177e4SLinus Torvalds short x, y, dx, dy, b; 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds x = (short) iomd_readl(IOMD_MOUSEX); 411da177e4SLinus Torvalds y = (short) iomd_readl(IOMD_MOUSEY); 42fe73f035SArnd Bergmann b = (short) (__raw_readl(IOMEM(0xe0310000)) ^ 0x70); 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds dx = x - rpcmouse_lastx; 451da177e4SLinus Torvalds dy = y - rpcmouse_lasty; 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds rpcmouse_lastx = x; 481da177e4SLinus Torvalds rpcmouse_lasty = y; 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds input_report_rel(dev, REL_X, dx); 511da177e4SLinus Torvalds input_report_rel(dev, REL_Y, -dy); 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds input_report_key(dev, BTN_LEFT, b & 0x40); 541da177e4SLinus Torvalds input_report_key(dev, BTN_MIDDLE, b & 0x20); 551da177e4SLinus Torvalds input_report_key(dev, BTN_RIGHT, b & 0x10); 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds input_sync(dev); 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds return IRQ_HANDLED; 601da177e4SLinus Torvalds } 611da177e4SLinus Torvalds 622e5b636bSDmitry Torokhov 631da177e4SLinus Torvalds static int __init rpcmouse_init(void) 641da177e4SLinus Torvalds { 6572155615SDmitry Torokhov int err; 6672155615SDmitry Torokhov 6772155615SDmitry Torokhov rpcmouse_dev = input_allocate_device(); 6872155615SDmitry Torokhov if (!rpcmouse_dev) 692e5b636bSDmitry Torokhov return -ENOMEM; 702e5b636bSDmitry Torokhov 712e5b636bSDmitry Torokhov rpcmouse_dev->name = "Acorn RiscPC Mouse"; 722e5b636bSDmitry Torokhov rpcmouse_dev->phys = "rpcmouse/input0"; 732e5b636bSDmitry Torokhov rpcmouse_dev->id.bustype = BUS_HOST; 742e5b636bSDmitry Torokhov rpcmouse_dev->id.vendor = 0x0005; 752e5b636bSDmitry Torokhov rpcmouse_dev->id.product = 0x0001; 762e5b636bSDmitry Torokhov rpcmouse_dev->id.version = 0x0100; 772e5b636bSDmitry Torokhov 787b19ada2SJiri Slaby rpcmouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); 797b19ada2SJiri Slaby rpcmouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | 807b19ada2SJiri Slaby BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); 817b19ada2SJiri Slaby rpcmouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds rpcmouse_lastx = (short) iomd_readl(IOMD_MOUSEX); 841da177e4SLinus Torvalds rpcmouse_lasty = (short) iomd_readl(IOMD_MOUSEY); 851da177e4SLinus Torvalds 86dace1453SThomas Gleixner if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, IRQF_SHARED, "rpcmouse", rpcmouse_dev)) { 871da177e4SLinus Torvalds printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n"); 8872155615SDmitry Torokhov err = -EBUSY; 8972155615SDmitry Torokhov goto err_free_dev; 901da177e4SLinus Torvalds } 911da177e4SLinus Torvalds 9272155615SDmitry Torokhov err = input_register_device(rpcmouse_dev); 9372155615SDmitry Torokhov if (err) 9472155615SDmitry Torokhov goto err_free_irq; 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds return 0; 9772155615SDmitry Torokhov 9872155615SDmitry Torokhov err_free_irq: 9972155615SDmitry Torokhov free_irq(IRQ_VSYNCPULSE, rpcmouse_dev); 10072155615SDmitry Torokhov err_free_dev: 10172155615SDmitry Torokhov input_free_device(rpcmouse_dev); 10272155615SDmitry Torokhov 10372155615SDmitry Torokhov return err; 1041da177e4SLinus Torvalds } 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds static void __exit rpcmouse_exit(void) 1071da177e4SLinus Torvalds { 1082e5b636bSDmitry Torokhov free_irq(IRQ_VSYNCPULSE, rpcmouse_dev); 1092e5b636bSDmitry Torokhov input_unregister_device(rpcmouse_dev); 1101da177e4SLinus Torvalds } 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds module_init(rpcmouse_init); 1131da177e4SLinus Torvalds module_exit(rpcmouse_exit); 114