~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/input/serio/sa1111ps2.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  linux/drivers/input/serio/sa1111ps2.c
 
3
 *
 
4
 *  Copyright (C) 2002 Russell King
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License.
 
9
 */
 
10
#include <linux/module.h>
 
11
#include <linux/init.h>
 
12
#include <linux/input.h>
 
13
#include <linux/serio.h>
 
14
#include <linux/errno.h>
 
15
#include <linux/interrupt.h>
 
16
#include <linux/ioport.h>
 
17
#include <linux/delay.h>
 
18
#include <linux/device.h>
 
19
#include <linux/slab.h>
 
20
#include <linux/spinlock.h>
 
21
 
 
22
#include <asm/io.h>
 
23
#include <asm/system.h>
 
24
 
 
25
#include <asm/hardware/sa1111.h>
 
26
 
 
27
struct ps2if {
 
28
        struct serio            *io;
 
29
        struct sa1111_dev       *dev;
 
30
        void __iomem            *base;
 
31
        unsigned int            open;
 
32
        spinlock_t              lock;
 
33
        unsigned int            head;
 
34
        unsigned int            tail;
 
35
        unsigned char           buf[4];
 
36
};
 
37
 
 
38
/*
 
39
 * Read all bytes waiting in the PS2 port.  There should be
 
40
 * at the most one, but we loop for safety.  If there was a
 
41
 * framing error, we have to manually clear the status.
 
42
 */
 
43
static irqreturn_t ps2_rxint(int irq, void *dev_id)
 
44
{
 
45
        struct ps2if *ps2if = dev_id;
 
46
        unsigned int scancode, flag, status;
 
47
 
 
48
        status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
 
49
        while (status & PS2STAT_RXF) {
 
50
                if (status & PS2STAT_STP)
 
51
                        sa1111_writel(PS2STAT_STP, ps2if->base + SA1111_PS2STAT);
 
52
 
 
53
                flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) |
 
54
                       (status & PS2STAT_RXP ? 0 : SERIO_PARITY);
 
55
 
 
56
                scancode = sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff;
 
57
 
 
58
                if (hweight8(scancode) & 1)
 
59
                        flag ^= SERIO_PARITY;
 
60
 
 
61
                serio_interrupt(ps2if->io, scancode, flag);
 
62
 
 
63
                status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
 
64
        }
 
65
 
 
66
        return IRQ_HANDLED;
 
67
}
 
68
 
 
69
/*
 
70
 * Completion of ps2 write
 
71
 */
 
72
static irqreturn_t ps2_txint(int irq, void *dev_id)
 
73
{
 
74
        struct ps2if *ps2if = dev_id;
 
75
        unsigned int status;
 
76
 
 
77
        spin_lock(&ps2if->lock);
 
78
        status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
 
79
        if (ps2if->head == ps2if->tail) {
 
80
                disable_irq_nosync(irq);
 
81
                /* done */
 
82
        } else if (status & PS2STAT_TXE) {
 
83
                sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA);
 
84
                ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
 
85
        }
 
86
        spin_unlock(&ps2if->lock);
 
87
 
 
88
        return IRQ_HANDLED;
 
89
}
 
90
 
 
91
/*
 
92
 * Write a byte to the PS2 port.  We have to wait for the
 
93
 * port to indicate that the transmitter is empty.
 
94
 */
 
95
static int ps2_write(struct serio *io, unsigned char val)
 
96
{
 
97
        struct ps2if *ps2if = io->port_data;
 
98
        unsigned long flags;
 
99
        unsigned int head;
 
100
 
 
101
        spin_lock_irqsave(&ps2if->lock, flags);
 
102
 
 
103
        /*
 
104
         * If the TX register is empty, we can go straight out.
 
105
         */
 
106
        if (sa1111_readl(ps2if->base + SA1111_PS2STAT) & PS2STAT_TXE) {
 
107
                sa1111_writel(val, ps2if->base + SA1111_PS2DATA);
 
108
        } else {
 
109
                if (ps2if->head == ps2if->tail)
 
110
                        enable_irq(ps2if->dev->irq[1]);
 
111
                head = (ps2if->head + 1) & (sizeof(ps2if->buf) - 1);
 
112
                if (head != ps2if->tail) {
 
113
                        ps2if->buf[ps2if->head] = val;
 
114
                        ps2if->head = head;
 
115
                }
 
116
        }
 
117
 
 
118
        spin_unlock_irqrestore(&ps2if->lock, flags);
 
119
        return 0;
 
120
}
 
121
 
 
122
static int ps2_open(struct serio *io)
 
123
{
 
124
        struct ps2if *ps2if = io->port_data;
 
125
        int ret;
 
126
 
 
127
        sa1111_enable_device(ps2if->dev);
 
128
 
 
129
        ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0,
 
130
                          SA1111_DRIVER_NAME(ps2if->dev), ps2if);
 
131
        if (ret) {
 
132
                printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
 
133
                        ps2if->dev->irq[0], ret);
 
134
                return ret;
 
135
        }
 
136
 
 
137
        ret = request_irq(ps2if->dev->irq[1], ps2_txint, 0,
 
138
                          SA1111_DRIVER_NAME(ps2if->dev), ps2if);
 
139
        if (ret) {
 
140
                printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
 
141
                        ps2if->dev->irq[1], ret);
 
142
                free_irq(ps2if->dev->irq[0], ps2if);
 
143
                return ret;
 
144
        }
 
145
 
 
146
        ps2if->open = 1;
 
147
 
 
148
        enable_irq_wake(ps2if->dev->irq[0]);
 
149
 
 
150
        sa1111_writel(PS2CR_ENA, ps2if->base + SA1111_PS2CR);
 
151
        return 0;
 
152
}
 
153
 
 
154
static void ps2_close(struct serio *io)
 
155
{
 
156
        struct ps2if *ps2if = io->port_data;
 
157
 
 
158
        sa1111_writel(0, ps2if->base + SA1111_PS2CR);
 
159
 
 
160
        disable_irq_wake(ps2if->dev->irq[0]);
 
161
 
 
162
        ps2if->open = 0;
 
163
 
 
164
        free_irq(ps2if->dev->irq[1], ps2if);
 
165
        free_irq(ps2if->dev->irq[0], ps2if);
 
166
 
 
167
        sa1111_disable_device(ps2if->dev);
 
168
}
 
169
 
 
170
/*
 
171
 * Clear the input buffer.
 
172
 */
 
173
static void __devinit ps2_clear_input(struct ps2if *ps2if)
 
174
{
 
175
        int maxread = 100;
 
176
 
 
177
        while (maxread--) {
 
178
                if ((sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff) == 0xff)
 
179
                        break;
 
180
        }
 
181
}
 
182
 
 
183
static unsigned int __devinit ps2_test_one(struct ps2if *ps2if,
 
184
                                           unsigned int mask)
 
185
{
 
186
        unsigned int val;
 
187
 
 
188
        sa1111_writel(PS2CR_ENA | mask, ps2if->base + SA1111_PS2CR);
 
189
 
 
190
        udelay(2);
 
191
 
 
192
        val = sa1111_readl(ps2if->base + SA1111_PS2STAT);
 
193
        return val & (PS2STAT_KBC | PS2STAT_KBD);
 
194
}
 
195
 
 
196
/*
 
197
 * Test the keyboard interface.  We basically check to make sure that
 
198
 * we can drive each line to the keyboard independently of each other.
 
199
 */
 
200
static int __devinit ps2_test(struct ps2if *ps2if)
 
201
{
 
202
        unsigned int stat;
 
203
        int ret = 0;
 
204
 
 
205
        stat = ps2_test_one(ps2if, PS2CR_FKC);
 
206
        if (stat != PS2STAT_KBD) {
 
207
                printk("PS/2 interface test failed[1]: %02x\n", stat);
 
208
                ret = -ENODEV;
 
209
        }
 
210
 
 
211
        stat = ps2_test_one(ps2if, 0);
 
212
        if (stat != (PS2STAT_KBC | PS2STAT_KBD)) {
 
213
                printk("PS/2 interface test failed[2]: %02x\n", stat);
 
214
                ret = -ENODEV;
 
215
        }
 
216
 
 
217
        stat = ps2_test_one(ps2if, PS2CR_FKD);
 
218
        if (stat != PS2STAT_KBC) {
 
219
                printk("PS/2 interface test failed[3]: %02x\n", stat);
 
220
                ret = -ENODEV;
 
221
        }
 
222
 
 
223
        sa1111_writel(0, ps2if->base + SA1111_PS2CR);
 
224
 
 
225
        return ret;
 
226
}
 
227
 
 
228
/*
 
229
 * Add one device to this driver.
 
230
 */
 
231
static int __devinit ps2_probe(struct sa1111_dev *dev)
 
232
{
 
233
        struct ps2if *ps2if;
 
234
        struct serio *serio;
 
235
        int ret;
 
236
 
 
237
        ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL);
 
238
        serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
 
239
        if (!ps2if || !serio) {
 
240
                ret = -ENOMEM;
 
241
                goto free;
 
242
        }
 
243
 
 
244
 
 
245
        serio->id.type          = SERIO_8042;
 
246
        serio->write            = ps2_write;
 
247
        serio->open             = ps2_open;
 
248
        serio->close            = ps2_close;
 
249
        strlcpy(serio->name, dev_name(&dev->dev), sizeof(serio->name));
 
250
        strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
 
251
        serio->port_data        = ps2if;
 
252
        serio->dev.parent       = &dev->dev;
 
253
        ps2if->io               = serio;
 
254
        ps2if->dev              = dev;
 
255
        sa1111_set_drvdata(dev, ps2if);
 
256
 
 
257
        spin_lock_init(&ps2if->lock);
 
258
 
 
259
        /*
 
260
         * Request the physical region for this PS2 port.
 
261
         */
 
262
        if (!request_mem_region(dev->res.start,
 
263
                                dev->res.end - dev->res.start + 1,
 
264
                                SA1111_DRIVER_NAME(dev))) {
 
265
                ret = -EBUSY;
 
266
                goto free;
 
267
        }
 
268
 
 
269
        /*
 
270
         * Our parent device has already mapped the region.
 
271
         */
 
272
        ps2if->base = dev->mapbase;
 
273
 
 
274
        sa1111_enable_device(ps2if->dev);
 
275
 
 
276
        /* Incoming clock is 8MHz */
 
277
        sa1111_writel(0, ps2if->base + SA1111_PS2CLKDIV);
 
278
        sa1111_writel(127, ps2if->base + SA1111_PS2PRECNT);
 
279
 
 
280
        /*
 
281
         * Flush any pending input.
 
282
         */
 
283
        ps2_clear_input(ps2if);
 
284
 
 
285
        /*
 
286
         * Test the keyboard interface.
 
287
         */
 
288
        ret = ps2_test(ps2if);
 
289
        if (ret)
 
290
                goto out;
 
291
 
 
292
        /*
 
293
         * Flush any pending input.
 
294
         */
 
295
        ps2_clear_input(ps2if);
 
296
 
 
297
        sa1111_disable_device(ps2if->dev);
 
298
        serio_register_port(ps2if->io);
 
299
        return 0;
 
300
 
 
301
 out:
 
302
        sa1111_disable_device(ps2if->dev);
 
303
        release_mem_region(dev->res.start, resource_size(&dev->res));
 
304
 free:
 
305
        sa1111_set_drvdata(dev, NULL);
 
306
        kfree(ps2if);
 
307
        kfree(serio);
 
308
        return ret;
 
309
}
 
310
 
 
311
/*
 
312
 * Remove one device from this driver.
 
313
 */
 
314
static int __devexit ps2_remove(struct sa1111_dev *dev)
 
315
{
 
316
        struct ps2if *ps2if = sa1111_get_drvdata(dev);
 
317
 
 
318
        serio_unregister_port(ps2if->io);
 
319
        release_mem_region(dev->res.start, resource_size(&dev->res));
 
320
        sa1111_set_drvdata(dev, NULL);
 
321
 
 
322
        kfree(ps2if);
 
323
 
 
324
        return 0;
 
325
}
 
326
 
 
327
/*
 
328
 * Our device driver structure
 
329
 */
 
330
static struct sa1111_driver ps2_driver = {
 
331
        .drv = {
 
332
                .name   = "sa1111-ps2",
 
333
        },
 
334
        .devid          = SA1111_DEVID_PS2,
 
335
        .probe          = ps2_probe,
 
336
        .remove         = __devexit_p(ps2_remove),
 
337
};
 
338
 
 
339
static int __init ps2_init(void)
 
340
{
 
341
        return sa1111_driver_register(&ps2_driver);
 
342
}
 
343
 
 
344
static void __exit ps2_exit(void)
 
345
{
 
346
        sa1111_driver_unregister(&ps2_driver);
 
347
}
 
348
 
 
349
module_init(ps2_init);
 
350
module_exit(ps2_exit);
 
351
 
 
352
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
 
353
MODULE_DESCRIPTION("SA1111 PS2 controller driver");
 
354
MODULE_LICENSE("GPL");