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/init.h>
23#include <linux/list.h>
24#include <linux/io.h>
25
26#include <linux/of_device.h>
27#include <linux/of_platform.h>
28
29#define DRIVER_NAME "xilinx_ps2"
30
31
32#define XPS2_SRST_OFFSET 0x00000000
33#define XPS2_STATUS_OFFSET 0x00000004
34#define XPS2_RX_DATA_OFFSET 0x00000008
35#define XPS2_TX_DATA_OFFSET 0x0000000C
36#define XPS2_GIER_OFFSET 0x0000002C
37#define XPS2_IPISR_OFFSET 0x00000030
38#define XPS2_IPIER_OFFSET 0x00000038
39
40
41#define XPS2_SRST_RESET 0x0000000A
42
43
44#define XPS2_STATUS_RX_FULL 0x00000001
45#define XPS2_STATUS_TX_FULL 0x00000002
46
47
48
49#define XPS2_IPIXR_WDT_TOUT 0x00000001
50#define XPS2_IPIXR_TX_NOACK 0x00000002
51#define XPS2_IPIXR_TX_ACK 0x00000004
52#define XPS2_IPIXR_RX_OVF 0x00000008
53#define XPS2_IPIXR_RX_ERR 0x00000010
54#define XPS2_IPIXR_RX_FULL 0x00000020
55
56
57#define XPS2_IPIXR_TX_ALL (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_TX_ACK)
58
59
60#define XPS2_IPIXR_RX_ALL (XPS2_IPIXR_RX_OVF | XPS2_IPIXR_RX_ERR | \
61 XPS2_IPIXR_RX_FULL)
62
63
64#define XPS2_IPIXR_ALL (XPS2_IPIXR_TX_ALL | XPS2_IPIXR_RX_ALL | \
65 XPS2_IPIXR_WDT_TOUT)
66
67
68#define XPS2_GIER_GIE_MASK 0x80000000
69
70struct xps2data {
71 int irq;
72 spinlock_t lock;
73 void __iomem *base_address;
74 unsigned int flags;
75 struct serio serio;
76};
77
78
79
80
81
82
83
84
85
86
87
88
89
90static int xps2_recv(struct xps2data *drvdata, u8 *byte)
91{
92 u32 sr;
93 int status = -1;
94
95
96 sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
97 if (sr & XPS2_STATUS_RX_FULL) {
98 *byte = in_be32(drvdata->base_address + XPS2_RX_DATA_OFFSET);
99 status = 0;
100 }
101
102 return status;
103}
104
105
106
107
108static irqreturn_t xps2_interrupt(int irq, void *dev_id)
109{
110 struct xps2data *drvdata = dev_id;
111 u32 intr_sr;
112 u8 c;
113 int status;
114
115
116 intr_sr = in_be32(drvdata->base_address + XPS2_IPISR_OFFSET);
117 out_be32(drvdata->base_address + XPS2_IPISR_OFFSET, intr_sr);
118
119
120 if (intr_sr & XPS2_IPIXR_RX_OVF)
121 dev_warn(drvdata->serio.dev.parent, "receive overrun error\n");
122
123 if (intr_sr & XPS2_IPIXR_RX_ERR)
124 drvdata->flags |= SERIO_PARITY;
125
126 if (intr_sr & (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_WDT_TOUT))
127 drvdata->flags |= SERIO_TIMEOUT;
128
129 if (intr_sr & XPS2_IPIXR_RX_FULL) {
130 status = xps2_recv(drvdata, &c);
131
132
133 if (status) {
134 dev_err(drvdata->serio.dev.parent,
135 "wrong rcvd byte count (%d)\n", status);
136 } else {
137 serio_interrupt(&drvdata->serio, c, drvdata->flags);
138 drvdata->flags = 0;
139 }
140 }
141
142 return IRQ_HANDLED;
143}
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159static int sxps2_write(struct serio *pserio, unsigned char c)
160{
161 struct xps2data *drvdata = pserio->port_data;
162 unsigned long flags;
163 u32 sr;
164 int status = -1;
165
166 spin_lock_irqsave(&drvdata->lock, flags);
167
168
169 sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET);
170 if (!(sr & XPS2_STATUS_TX_FULL)) {
171 out_be32(drvdata->base_address + XPS2_TX_DATA_OFFSET, c);
172 status = 0;
173 }
174
175 spin_unlock_irqrestore(&drvdata->lock, flags);
176
177 return status;
178}
179
180
181
182
183
184
185
186static int sxps2_open(struct serio *pserio)
187{
188 struct xps2data *drvdata = pserio->port_data;
189 int error;
190 u8 c;
191
192 error = request_irq(drvdata->irq, &xps2_interrupt, 0,
193 DRIVER_NAME, drvdata);
194 if (error) {
195 dev_err(drvdata->serio.dev.parent,
196 "Couldn't allocate interrupt %d\n", drvdata->irq);
197 return error;
198 }
199
200
201 out_be32(drvdata->base_address + XPS2_GIER_OFFSET, XPS2_GIER_GIE_MASK);
202 out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, XPS2_IPIXR_RX_ALL);
203 (void)xps2_recv(drvdata, &c);
204
205 return 0;
206}
207
208
209
210
211
212
213
214static void sxps2_close(struct serio *pserio)
215{
216 struct xps2data *drvdata = pserio->port_data;
217
218
219 out_be32(drvdata->base_address + XPS2_GIER_OFFSET, 0x00);
220 out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0x00);
221 free_irq(drvdata->irq, drvdata);
222}
223
224
225
226
227
228
229
230
231
232
233
234static int __devinit xps2_of_probe(struct of_device *ofdev,
235 const struct of_device_id *match)
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->node->name);
247
248
249 error = of_address_to_resource(ofdev->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->node, 0, &r_irq) == NO_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 = r_mem.end - r_mem.start + 1;
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 of_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->node, 0, &r_mem))
345 dev_err(dev, "invalid address\n");
346 else
347 release_mem_region(r_mem.start, r_mem.end - r_mem.start + 1);
348
349 kfree(drvdata);
350
351 dev_set_drvdata(dev, NULL);
352
353 return 0;
354}
355
356
357static struct of_device_id xps2_of_match[] __devinitdata = {
358 { .compatible = "xlnx,xps-ps2-1.00.a", },
359 { },
360};
361MODULE_DEVICE_TABLE(of, xps2_of_match);
362
363static struct of_platform_driver xps2_of_driver = {
364 .name = DRIVER_NAME,
365 .match_table = xps2_of_match,
366 .probe = xps2_of_probe,
367 .remove = __devexit_p(xps2_of_remove),
368};
369
370static int __init xps2_init(void)
371{
372 return of_register_platform_driver(&xps2_of_driver);
373}
374
375static void __exit xps2_cleanup(void)
376{
377 of_unregister_platform_driver(&xps2_of_driver);
378}
379
380module_init(xps2_init);
381module_exit(xps2_cleanup);
382
383MODULE_AUTHOR("Xilinx, Inc.");
384MODULE_DESCRIPTION("Xilinx XPS PS/2 driver");
385MODULE_LICENSE("GPL");
386
387