diff options
Diffstat (limited to 'drivers/input/serio/sa1111ps2.c')
-rw-r--r-- | drivers/input/serio/sa1111ps2.c | 59 |
1 files changed, 42 insertions, 17 deletions
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 44fc8b4bcd81..5ebabe3fc845 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c | |||
@@ -24,6 +24,26 @@ | |||
24 | 24 | ||
25 | #include <asm/hardware/sa1111.h> | 25 | #include <asm/hardware/sa1111.h> |
26 | 26 | ||
27 | #define PS2CR 0x0000 | ||
28 | #define PS2STAT 0x0004 | ||
29 | #define PS2DATA 0x0008 | ||
30 | #define PS2CLKDIV 0x000c | ||
31 | #define PS2PRECNT 0x0010 | ||
32 | |||
33 | #define PS2CR_ENA 0x08 | ||
34 | #define PS2CR_FKD 0x02 | ||
35 | #define PS2CR_FKC 0x01 | ||
36 | |||
37 | #define PS2STAT_STP 0x0100 | ||
38 | #define PS2STAT_TXE 0x0080 | ||
39 | #define PS2STAT_TXB 0x0040 | ||
40 | #define PS2STAT_RXF 0x0020 | ||
41 | #define PS2STAT_RXB 0x0010 | ||
42 | #define PS2STAT_ENA 0x0008 | ||
43 | #define PS2STAT_RXP 0x0004 | ||
44 | #define PS2STAT_KBD 0x0002 | ||
45 | #define PS2STAT_KBC 0x0001 | ||
46 | |||
27 | struct ps2if { | 47 | struct ps2if { |
28 | struct serio *io; | 48 | struct serio *io; |
29 | struct sa1111_dev *dev; | 49 | struct sa1111_dev *dev; |
@@ -45,22 +65,22 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id) | |||
45 | struct ps2if *ps2if = dev_id; | 65 | struct ps2if *ps2if = dev_id; |
46 | unsigned int scancode, flag, status; | 66 | unsigned int scancode, flag, status; |
47 | 67 | ||
48 | status = sa1111_readl(ps2if->base + SA1111_PS2STAT); | 68 | status = sa1111_readl(ps2if->base + PS2STAT); |
49 | while (status & PS2STAT_RXF) { | 69 | while (status & PS2STAT_RXF) { |
50 | if (status & PS2STAT_STP) | 70 | if (status & PS2STAT_STP) |
51 | sa1111_writel(PS2STAT_STP, ps2if->base + SA1111_PS2STAT); | 71 | sa1111_writel(PS2STAT_STP, ps2if->base + PS2STAT); |
52 | 72 | ||
53 | flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) | | 73 | flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) | |
54 | (status & PS2STAT_RXP ? 0 : SERIO_PARITY); | 74 | (status & PS2STAT_RXP ? 0 : SERIO_PARITY); |
55 | 75 | ||
56 | scancode = sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff; | 76 | scancode = sa1111_readl(ps2if->base + PS2DATA) & 0xff; |
57 | 77 | ||
58 | if (hweight8(scancode) & 1) | 78 | if (hweight8(scancode) & 1) |
59 | flag ^= SERIO_PARITY; | 79 | flag ^= SERIO_PARITY; |
60 | 80 | ||
61 | serio_interrupt(ps2if->io, scancode, flag); | 81 | serio_interrupt(ps2if->io, scancode, flag); |
62 | 82 | ||
63 | status = sa1111_readl(ps2if->base + SA1111_PS2STAT); | 83 | status = sa1111_readl(ps2if->base + PS2STAT); |
64 | } | 84 | } |
65 | 85 | ||
66 | return IRQ_HANDLED; | 86 | return IRQ_HANDLED; |
@@ -75,12 +95,12 @@ static irqreturn_t ps2_txint(int irq, void *dev_id) | |||
75 | unsigned int status; | 95 | unsigned int status; |
76 | 96 | ||
77 | spin_lock(&ps2if->lock); | 97 | spin_lock(&ps2if->lock); |
78 | status = sa1111_readl(ps2if->base + SA1111_PS2STAT); | 98 | status = sa1111_readl(ps2if->base + PS2STAT); |
79 | if (ps2if->head == ps2if->tail) { | 99 | if (ps2if->head == ps2if->tail) { |
80 | disable_irq_nosync(irq); | 100 | disable_irq_nosync(irq); |
81 | /* done */ | 101 | /* done */ |
82 | } else if (status & PS2STAT_TXE) { | 102 | } else if (status & PS2STAT_TXE) { |
83 | sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA); | 103 | sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + PS2DATA); |
84 | ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1); | 104 | ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1); |
85 | } | 105 | } |
86 | spin_unlock(&ps2if->lock); | 106 | spin_unlock(&ps2if->lock); |
@@ -103,8 +123,8 @@ static int ps2_write(struct serio *io, unsigned char val) | |||
103 | /* | 123 | /* |
104 | * If the TX register is empty, we can go straight out. | 124 | * If the TX register is empty, we can go straight out. |
105 | */ | 125 | */ |
106 | if (sa1111_readl(ps2if->base + SA1111_PS2STAT) & PS2STAT_TXE) { | 126 | if (sa1111_readl(ps2if->base + PS2STAT) & PS2STAT_TXE) { |
107 | sa1111_writel(val, ps2if->base + SA1111_PS2DATA); | 127 | sa1111_writel(val, ps2if->base + PS2DATA); |
108 | } else { | 128 | } else { |
109 | if (ps2if->head == ps2if->tail) | 129 | if (ps2if->head == ps2if->tail) |
110 | enable_irq(ps2if->dev->irq[1]); | 130 | enable_irq(ps2if->dev->irq[1]); |
@@ -124,13 +144,16 @@ static int ps2_open(struct serio *io) | |||
124 | struct ps2if *ps2if = io->port_data; | 144 | struct ps2if *ps2if = io->port_data; |
125 | int ret; | 145 | int ret; |
126 | 146 | ||
127 | sa1111_enable_device(ps2if->dev); | 147 | ret = sa1111_enable_device(ps2if->dev); |
148 | if (ret) | ||
149 | return ret; | ||
128 | 150 | ||
129 | ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0, | 151 | ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0, |
130 | SA1111_DRIVER_NAME(ps2if->dev), ps2if); | 152 | SA1111_DRIVER_NAME(ps2if->dev), ps2if); |
131 | if (ret) { | 153 | if (ret) { |
132 | printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n", | 154 | printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n", |
133 | ps2if->dev->irq[0], ret); | 155 | ps2if->dev->irq[0], ret); |
156 | sa1111_disable_device(ps2if->dev); | ||
134 | return ret; | 157 | return ret; |
135 | } | 158 | } |
136 | 159 | ||
@@ -140,6 +163,7 @@ static int ps2_open(struct serio *io) | |||
140 | printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n", | 163 | printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n", |
141 | ps2if->dev->irq[1], ret); | 164 | ps2if->dev->irq[1], ret); |
142 | free_irq(ps2if->dev->irq[0], ps2if); | 165 | free_irq(ps2if->dev->irq[0], ps2if); |
166 | sa1111_disable_device(ps2if->dev); | ||
143 | return ret; | 167 | return ret; |
144 | } | 168 | } |
145 | 169 | ||
@@ -147,7 +171,7 @@ static int ps2_open(struct serio *io) | |||
147 | 171 | ||
148 | enable_irq_wake(ps2if->dev->irq[0]); | 172 | enable_irq_wake(ps2if->dev->irq[0]); |
149 | 173 | ||
150 | sa1111_writel(PS2CR_ENA, ps2if->base + SA1111_PS2CR); | 174 | sa1111_writel(PS2CR_ENA, ps2if->base + PS2CR); |
151 | return 0; | 175 | return 0; |
152 | } | 176 | } |
153 | 177 | ||
@@ -155,7 +179,7 @@ static void ps2_close(struct serio *io) | |||
155 | { | 179 | { |
156 | struct ps2if *ps2if = io->port_data; | 180 | struct ps2if *ps2if = io->port_data; |
157 | 181 | ||
158 | sa1111_writel(0, ps2if->base + SA1111_PS2CR); | 182 | sa1111_writel(0, ps2if->base + PS2CR); |
159 | 183 | ||
160 | disable_irq_wake(ps2if->dev->irq[0]); | 184 | disable_irq_wake(ps2if->dev->irq[0]); |
161 | 185 | ||
@@ -175,7 +199,7 @@ static void __devinit ps2_clear_input(struct ps2if *ps2if) | |||
175 | int maxread = 100; | 199 | int maxread = 100; |
176 | 200 | ||
177 | while (maxread--) { | 201 | while (maxread--) { |
178 | if ((sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff) == 0xff) | 202 | if ((sa1111_readl(ps2if->base + PS2DATA) & 0xff) == 0xff) |
179 | break; | 203 | break; |
180 | } | 204 | } |
181 | } | 205 | } |
@@ -185,11 +209,11 @@ static unsigned int __devinit ps2_test_one(struct ps2if *ps2if, | |||
185 | { | 209 | { |
186 | unsigned int val; | 210 | unsigned int val; |
187 | 211 | ||
188 | sa1111_writel(PS2CR_ENA | mask, ps2if->base + SA1111_PS2CR); | 212 | sa1111_writel(PS2CR_ENA | mask, ps2if->base + PS2CR); |
189 | 213 | ||
190 | udelay(2); | 214 | udelay(2); |
191 | 215 | ||
192 | val = sa1111_readl(ps2if->base + SA1111_PS2STAT); | 216 | val = sa1111_readl(ps2if->base + PS2STAT); |
193 | return val & (PS2STAT_KBC | PS2STAT_KBD); | 217 | return val & (PS2STAT_KBC | PS2STAT_KBD); |
194 | } | 218 | } |
195 | 219 | ||
@@ -220,7 +244,7 @@ static int __devinit ps2_test(struct ps2if *ps2if) | |||
220 | ret = -ENODEV; | 244 | ret = -ENODEV; |
221 | } | 245 | } |
222 | 246 | ||
223 | sa1111_writel(0, ps2if->base + SA1111_PS2CR); | 247 | sa1111_writel(0, ps2if->base + PS2CR); |
224 | 248 | ||
225 | return ret; | 249 | return ret; |
226 | } | 250 | } |
@@ -274,8 +298,8 @@ static int __devinit ps2_probe(struct sa1111_dev *dev) | |||
274 | sa1111_enable_device(ps2if->dev); | 298 | sa1111_enable_device(ps2if->dev); |
275 | 299 | ||
276 | /* Incoming clock is 8MHz */ | 300 | /* Incoming clock is 8MHz */ |
277 | sa1111_writel(0, ps2if->base + SA1111_PS2CLKDIV); | 301 | sa1111_writel(0, ps2if->base + PS2CLKDIV); |
278 | sa1111_writel(127, ps2if->base + SA1111_PS2PRECNT); | 302 | sa1111_writel(127, ps2if->base + PS2PRECNT); |
279 | 303 | ||
280 | /* | 304 | /* |
281 | * Flush any pending input. | 305 | * Flush any pending input. |
@@ -330,6 +354,7 @@ static int __devexit ps2_remove(struct sa1111_dev *dev) | |||
330 | static struct sa1111_driver ps2_driver = { | 354 | static struct sa1111_driver ps2_driver = { |
331 | .drv = { | 355 | .drv = { |
332 | .name = "sa1111-ps2", | 356 | .name = "sa1111-ps2", |
357 | .owner = THIS_MODULE, | ||
333 | }, | 358 | }, |
334 | .devid = SA1111_DEVID_PS2, | 359 | .devid = SA1111_DEVID_PS2, |
335 | .probe = ps2_probe, | 360 | .probe = ps2_probe, |