xref: /linux/drivers/input/mouse/rpcmouse.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  *  Acorn RiscPC mouse driver for Linux/ARM
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  *  Copyright (c) 2000-2002 Vojtech Pavlik
5*1da177e4SLinus Torvalds  *  Copyright (C) 1996-2002 Russell King
6*1da177e4SLinus Torvalds  *
7*1da177e4SLinus Torvalds  */
8*1da177e4SLinus Torvalds 
9*1da177e4SLinus Torvalds /*
10*1da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify it
11*1da177e4SLinus Torvalds  * under the terms of the GNU General Public License version 2 as published by
12*1da177e4SLinus Torvalds  * the Free Software Foundation.
13*1da177e4SLinus Torvalds  *
14*1da177e4SLinus Torvalds  * This handles the Acorn RiscPCs mouse.  We basically have a couple of
15*1da177e4SLinus Torvalds  * hardware registers that track the sensor count for the X-Y movement and
16*1da177e4SLinus Torvalds  * another register holding the button state.  On every VSYNC interrupt we read
17*1da177e4SLinus Torvalds  * the complete state and then work out if something has changed.
18*1da177e4SLinus Torvalds  */
19*1da177e4SLinus Torvalds 
20*1da177e4SLinus Torvalds #include <linux/module.h>
21*1da177e4SLinus Torvalds #include <linux/sched.h>
22*1da177e4SLinus Torvalds #include <linux/ptrace.h>
23*1da177e4SLinus Torvalds #include <linux/interrupt.h>
24*1da177e4SLinus Torvalds #include <linux/init.h>
25*1da177e4SLinus Torvalds #include <linux/input.h>
26*1da177e4SLinus Torvalds 
27*1da177e4SLinus Torvalds #include <asm/hardware.h>
28*1da177e4SLinus Torvalds #include <asm/irq.h>
29*1da177e4SLinus Torvalds #include <asm/io.h>
30*1da177e4SLinus Torvalds #include <asm/hardware/iomd.h>
31*1da177e4SLinus Torvalds 
32*1da177e4SLinus Torvalds MODULE_AUTHOR("Vojtech Pavlik, Russell King");
33*1da177e4SLinus Torvalds MODULE_DESCRIPTION("Acorn RiscPC mouse driver");
34*1da177e4SLinus Torvalds MODULE_LICENSE("GPL");
35*1da177e4SLinus Torvalds 
36*1da177e4SLinus Torvalds static short rpcmouse_lastx, rpcmouse_lasty;
37*1da177e4SLinus Torvalds 
38*1da177e4SLinus Torvalds static struct input_dev rpcmouse_dev = {
39*1da177e4SLinus Torvalds 	.evbit	= { BIT(EV_KEY) | BIT(EV_REL) },
40*1da177e4SLinus Torvalds 	.keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
41*1da177e4SLinus Torvalds 	.relbit	= { BIT(REL_X) | BIT(REL_Y) },
42*1da177e4SLinus Torvalds 	.name	= "Acorn RiscPC Mouse",
43*1da177e4SLinus Torvalds 	.phys	= "rpcmouse/input0",
44*1da177e4SLinus Torvalds 	.id	= {
45*1da177e4SLinus Torvalds 		.bustype = BUS_HOST,
46*1da177e4SLinus Torvalds 		.vendor  = 0x0005,
47*1da177e4SLinus Torvalds 		.product = 0x0001,
48*1da177e4SLinus Torvalds 		.version = 0x0100,
49*1da177e4SLinus Torvalds 	},
50*1da177e4SLinus Torvalds };
51*1da177e4SLinus Torvalds 
52*1da177e4SLinus Torvalds static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
53*1da177e4SLinus Torvalds {
54*1da177e4SLinus Torvalds 	struct input_dev *dev = dev_id;
55*1da177e4SLinus Torvalds 	short x, y, dx, dy, b;
56*1da177e4SLinus Torvalds 
57*1da177e4SLinus Torvalds 	x = (short) iomd_readl(IOMD_MOUSEX);
58*1da177e4SLinus Torvalds 	y = (short) iomd_readl(IOMD_MOUSEY);
59*1da177e4SLinus Torvalds 	b = (short) (__raw_readl(0xe0310000) ^ 0x70);
60*1da177e4SLinus Torvalds 
61*1da177e4SLinus Torvalds 	dx = x - rpcmouse_lastx;
62*1da177e4SLinus Torvalds 	dy = y - rpcmouse_lasty;
63*1da177e4SLinus Torvalds 
64*1da177e4SLinus Torvalds 	rpcmouse_lastx = x;
65*1da177e4SLinus Torvalds 	rpcmouse_lasty = y;
66*1da177e4SLinus Torvalds 
67*1da177e4SLinus Torvalds 	input_regs(dev, regs);
68*1da177e4SLinus Torvalds 
69*1da177e4SLinus Torvalds 	input_report_rel(dev, REL_X, dx);
70*1da177e4SLinus Torvalds 	input_report_rel(dev, REL_Y, -dy);
71*1da177e4SLinus Torvalds 
72*1da177e4SLinus Torvalds 	input_report_key(dev, BTN_LEFT,   b & 0x40);
73*1da177e4SLinus Torvalds 	input_report_key(dev, BTN_MIDDLE, b & 0x20);
74*1da177e4SLinus Torvalds 	input_report_key(dev, BTN_RIGHT,  b & 0x10);
75*1da177e4SLinus Torvalds 
76*1da177e4SLinus Torvalds 	input_sync(dev);
77*1da177e4SLinus Torvalds 
78*1da177e4SLinus Torvalds 	return IRQ_HANDLED;
79*1da177e4SLinus Torvalds }
80*1da177e4SLinus Torvalds 
81*1da177e4SLinus Torvalds static int __init rpcmouse_init(void)
82*1da177e4SLinus Torvalds {
83*1da177e4SLinus Torvalds 	init_input_dev(&rpcmouse_dev);
84*1da177e4SLinus Torvalds 
85*1da177e4SLinus Torvalds 	rpcmouse_lastx = (short) iomd_readl(IOMD_MOUSEX);
86*1da177e4SLinus Torvalds 	rpcmouse_lasty = (short) iomd_readl(IOMD_MOUSEY);
87*1da177e4SLinus Torvalds 
88*1da177e4SLinus Torvalds 	if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, SA_SHIRQ, "rpcmouse", &rpcmouse_dev)) {
89*1da177e4SLinus Torvalds 		printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n");
90*1da177e4SLinus Torvalds 		return -1;
91*1da177e4SLinus Torvalds 	}
92*1da177e4SLinus Torvalds 
93*1da177e4SLinus Torvalds 	input_register_device(&rpcmouse_dev);
94*1da177e4SLinus Torvalds 
95*1da177e4SLinus Torvalds 	printk(KERN_INFO "input: Acorn RiscPC mouse\n");
96*1da177e4SLinus Torvalds 
97*1da177e4SLinus Torvalds 	return 0;
98*1da177e4SLinus Torvalds }
99*1da177e4SLinus Torvalds 
100*1da177e4SLinus Torvalds static void __exit rpcmouse_exit(void)
101*1da177e4SLinus Torvalds {
102*1da177e4SLinus Torvalds 	input_unregister_device(&rpcmouse_dev);
103*1da177e4SLinus Torvalds 	free_irq(IRQ_VSYNCPULSE, &rpcmouse_dev);
104*1da177e4SLinus Torvalds }
105*1da177e4SLinus Torvalds 
106*1da177e4SLinus Torvalds module_init(rpcmouse_init);
107*1da177e4SLinus Torvalds module_exit(rpcmouse_exit);
108