1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/module.h>
19#include <linux/serio.h>
20#include <linux/interrupt.h>
21#include <linux/errno.h>
22#include <linux/slab.h>
23#include <linux/init.h>
24#include <linux/list.h>
25#include <linux/io.h>
26#include <linux/of_address.h>
27#include <linux/of_device.h>
28#include <linux/of_platform.h>
29
30#define DRIVER_NAME "xilinx_ps2"
31
32
33#define XPS2_SRST_OFFSET 0x00000000
34#define XPS2_STATUS_OFFSET 0x00000004
35#define XPS2_RX_DATA_OFFSET 0x00000008
36#define XPS2_TX_DATA_OFFSET 0x0000000C
37#define XPS2_GIER_OFFSET 0x0000002C
38#define XPS2_IPISR_OFFSET 0x00000030
39#define XPS2_IPIER_OFFSET 0x00000038
40
41
42#define XPS2_SRST_RESET 0x0000000A
43
44
45#define XPS2_STATUS_RX_FULL 0x00000001
46#define XPS2_STATUS_TX_FULL 0x00000002
47
48
49
50#define XPS2_IPIXR_WDT_TOUT 0x00000001
51#define XPS2_IPIXR_TX_NOACK 0x00000002
52#define XPS2_IPIXR_TX_ACK 0x00000004
53#define XPS2_IPIXR_RX_OVF 0x00000008
54#define XPS2_IPIXR_RX_ERR 0x00000010
55#define XPS2_IPIXR_RX_FULL 0x00000020
56
57
58#define XPS2_IPIXR_TX_ALL (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_TX_ACK)
59
60
61#define XPS2_IPIXR_RX_ALL (XPS2_IPIXR_RX_OVF | XPS2_IPIXR_RX_ERR | \
62 XPS2_IPIXR_RX_FULL)
63
64
65#define XPS2_IPIXR_ALL (XPS2_IPIXR_TX_ALL | XPS2_IPIXR_RX_ALL | \
66 XPS2_IPIXR_WDT_TOUT)
67
68
69#define XPS2_GIER_GIE_MASK 0x80000000
70
71struct xps2data {
72 int irq;
73 spinlock_t lock;
74 void __iomem *base_address;
75 unsigned int flags;
76 struct serio serio;
77};
78
79
80
81
82
83
84
85
86
87
88
89
90
91static int xps2_recv(struct xps2data *drvdata, u8 *byte)
92{
93 u32 sr;
94 int status = -1;
95
96
97 sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
98 if (sr & XPS2_STATUS_RX_FULL) {
99 *byte = in_be32(drvdata->base_address + XPS2_RX_DATA_OFFSET);
100 status = 0;
101 }
102
103 return status;
104}
105
106
107
108
109static irqreturn_t xps2_interrupt(int irq, void *dev_id)
110{
111 struct xps2data *drvdata = dev_id;
112 u32 intr_sr;
113 u8 c;
114 int status;
115
116
117 intr_sr = in_be32(drvdata->base_address + XPS2_IPISR_OFFSET);
118 out_be32(drvdata->base_address + XPS2_IPISR_OFFSET, intr_sr);
119
120
121 if (intr_sr & XPS2_IPIXR_RX_OVF)
122 dev_warn(drvdata->serio.dev.parent, "receive overrun error\n");
123
124 if (intr_sr & XPS2_IPIXR_RX_ERR)
125 drvdata->flags |= SERIO_PARITY;
126
127 if (intr_sr & (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_WDT_TOUT))
128 drvdata->flags |= SERIO_TIMEOUT;
129
130 if (intr_sr & XPS2_IPIXR_RX_FULL) {
131 status = xps2_recv(drvdata, &c);
132
133
134 if (status) {
135 dev_err(drvdata->serio.dev.parent,
136 "wrong rcvd byte count (%d)\n", status);
137 } else {
138 serio_interrupt(&drvdata->serio, c, drvdata->flags);
139 drvdata->flags = 0;
140 }
141 }
142
143 return IRQ_HANDLED;
144}
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160static int sxps2_write(struct serio *pserio, unsigned char c)
161{
162 struct xps2data *drvdata = pserio->port_data;
163 unsigned long flags;
164 u32 sr;
165 int status = -1;
166
167 spin_lock_irqsave(&drvdata->lock, flags);
168
169
170 sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
171 if (!(sr & XPS2_STATUS_TX_FULL)) {
172 out_be32(drvdata->base_address + XPS2_TX_DATA_OFFSET, c);
173 status = 0;
174 }
175
176 spin_unlock_irqrestore(&drvdata->lock, flags);
177
178 return status;
179}
180
181
182
183
184
185
186
187static int sxps2_open(struct serio *pserio)
188{
189 struct xps2data *drvdata = pserio->port_data;
190 int error;
191 u8 c;
192
193 error = request_irq(drvdata->irq, &xps2_interrupt, 0,
194 DRIVER_NAME, drvdata);
195 if (error) {
196 dev_err(drvdata->serio.dev.parent,
197 "Couldn't allocate interrupt %d\n", drvdata->irq);
198 return error;
199 }
200
201
202 out_be32(drvdata->base_address + XPS2_GIER_OFFSET, XPS2_GIER_GIE_MASK);
203 out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, XPS2_IPIXR_RX_ALL);
204 (void)xps2_recv(drvdata, &c);
205
206 return 0;
207}
208
209
210
211
212
213
214
215static void sxps2_close(struct serio *pserio)
216{
217 struct xps2data *drvdata = pserio->port_data;
218
219
220 out_be32(drvdata->base_address + XPS2_GIER_OFFSET, 0x00);
221 out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0x00);
222 free_irq(drvdata->irq, drvdata);
223}
224
225
226
227
228
229
230
231
232
233
234
235static int __devinit xps2_of_probe(struct platform_device *ofdev)
236{
237 struct resource r_irq;
238 struct resource r_mem;
239 struct xps2data *drvdata;
240 struct serio *serio;
241 struct device *dev = &ofdev->dev;
242 resource_size_t remap_size, phys_addr;
243 int error;
244
245 dev_info(dev, "Device Tree Probing \'%s\'\n",
246 ofdev->dev.of_node->name);
247
248
249 error = of_address_to_resource(ofdev->dev.of_node, 0, &r_mem);
250 if (error) {
251 dev_err(dev, "invalid address\n");
252 return error;
253 }
254
255
256 if (!of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq)) {
257 dev_err(dev, "no IRQ found\n");
258 return -ENODEV;
259 }
260
261 drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL);
262 if (!drvdata) {
263 dev_err(dev, "Couldn't allocate device private record\n");
264 return -ENOMEM;
265 }
266
267 dev_set_drvdata(dev, drvdata);
268
269 spin_lock_init(&drvdata->lock);
270 drvdata->irq = r_irq.start;
271
272 phys_addr = r_mem.start;
273 remap_size = resource_size(&r_mem);
274 if (!request_mem_region(phys_addr, remap_size, DRIVER_NAME)) {
275 dev_err(dev, "Couldn't lock memory region at 0x%08llX\n",
276 (unsigned long long)phys_addr);
277 error = -EBUSY;
278 goto failed1;
279 }
280
281
282 drvdata->base_address = ioremap(phys_addr, remap_size);
283 if (drvdata->base_address == NULL) {
284 dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n",
285 (unsigned long long)phys_addr);
286 error = -EFAULT;
287 goto failed2;
288 }
289
290
291 out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0);
292
293
294
295 out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET);
296
297 dev_info(dev, "Xilinx PS2 at 0x%08llX mapped to 0x%p, irq=%d\n",
298 (unsigned long long)phys_addr, drvdata->base_address,
299 drvdata->irq);
300
301 serio = &drvdata->serio;
302 serio->id.type = SERIO_8042;
303 serio->write = sxps2_write;
304 serio->open = sxps2_open;
305 serio->close = sxps2_close;
306 serio->port_data = drvdata;
307 serio->dev.parent = dev;
308 snprintf(serio->name, sizeof(serio->name),
309 "Xilinx XPS PS/2 at %08llX", (unsigned long long)phys_addr);
310 snprintf(serio->phys, sizeof(serio->phys),
311 "xilinxps2/serio at %08llX", (unsigned long long)phys_addr);
312
313 serio_register_port(serio);
314
315 return 0;
316
317failed2:
318 release_mem_region(phys_addr, remap_size);
319failed1:
320 kfree(drvdata);
321 dev_set_drvdata(dev, NULL);
322
323 return error;
324}
325
326
327
328
329
330
331
332
333
334static int __devexit xps2_of_remove(struct platform_device *of_dev)
335{
336 struct device *dev = &of_dev->dev;
337 struct xps2data *drvdata = dev_get_drvdata(dev);
338 struct resource r_mem;
339
340 serio_unregister_port(&drvdata->serio);
341 iounmap(drvdata->base_address);
342
343
344 if (of_address_to_resource(of_dev->dev.of_node, 0, &r_mem))
345 dev_err(dev, "invalid address\n");
346 else
347 release_mem_region(r_mem.start, resource_size(&r_mem));
348
349 kfree(drvdata);
350
351 dev_set_drvdata(dev, NULL);
352
353 return 0;
354}
355
356
357static const struct of_device_id xps2_of_match[] __devinitconst = {
358 { .compatible = "xlnx,xps-ps2-1.00.a", },
359 { },
360};
361MODULE_DEVICE_TABLE(of, xps2_of_match);
362
363static struct platform_driver xps2_of_driver = {
364 .driver = {
365 .name = DRIVER_NAME,
366 .owner = THIS_MODULE,
367 .of_match_table = xps2_of_match,
368 },
369 .probe = xps2_of_probe,
370 .remove = __devexit_p(xps2_of_remove),
371};
372module_platform_driver(xps2_of_driver);
373
374MODULE_AUTHOR("Xilinx, Inc.");
375MODULE_DESCRIPTION("Xilinx XPS PS/2 driver");
376MODULE_LICENSE("GPL");
377
378