2 * Copyright (C) 2007 Google, Inc.
3 * Copyright (C) 2012 Intel, Inc.
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <linux/module.h>
17 #include <linux/interrupt.h>
18 #include <linux/types.h>
19 #include <linux/input.h>
20 #include <linux/kernel.h>
21 #include <linux/platform_device.h>
22 #include <linux/slab.h>
23 #include <linux/irq.h>
33 PAGE_EVBITS
= 0x10000,
34 PAGE_ABSDATA
= 0x20000 | EV_ABS
,
38 struct input_dev
*input
;
44 static irqreturn_t
events_interrupt(int irq
, void *dev_id
)
46 struct event_dev
*edev
= dev_id
;
47 unsigned type
, code
, value
;
49 type
= __raw_readl(edev
->addr
+ REG_READ
);
50 code
= __raw_readl(edev
->addr
+ REG_READ
);
51 value
= __raw_readl(edev
->addr
+ REG_READ
);
53 input_event(edev
->input
, type
, code
, value
);
54 input_sync(edev
->input
);
58 static void events_import_bits(struct event_dev
*edev
,
59 unsigned long bits
[], unsigned type
, size_t count
)
61 void __iomem
*addr
= edev
->addr
;
66 __raw_writel(PAGE_EVBITS
| type
, addr
+ REG_SET_PAGE
);
68 size
= __raw_readl(addr
+ REG_LEN
) * 8;
73 for (i
= 0; i
< count
; i
+= 8) {
74 val
= __raw_readb(addr
++);
75 for (j
= 0; j
< 8; j
++)
81 static void events_import_abs_params(struct event_dev
*edev
)
83 struct input_dev
*input_dev
= edev
->input
;
84 void __iomem
*addr
= edev
->addr
;
89 __raw_writel(PAGE_ABSDATA
, addr
+ REG_SET_PAGE
);
91 count
= __raw_readl(addr
+ REG_LEN
) / sizeof(val
);
95 for (i
= 0; i
< count
; i
++) {
96 if (!test_bit(i
, input_dev
->absbit
))
99 for (j
= 0; j
< ARRAY_SIZE(val
); j
++) {
100 int offset
= (i
* ARRAY_SIZE(val
) + j
) * sizeof(u32
);
101 val
[j
] = __raw_readl(edev
->addr
+ REG_DATA
+ offset
);
104 input_set_abs_params(input_dev
, i
,
105 val
[0], val
[1], val
[2], val
[3]);
109 static int events_probe(struct platform_device
*pdev
)
111 struct input_dev
*input_dev
;
112 struct event_dev
*edev
;
113 struct resource
*res
;
114 unsigned keymapnamelen
;
120 irq
= platform_get_irq(pdev
, 0);
124 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
128 addr
= devm_ioremap(&pdev
->dev
, res
->start
, 4096);
132 __raw_writel(PAGE_NAME
, addr
+ REG_SET_PAGE
);
133 keymapnamelen
= __raw_readl(addr
+ REG_LEN
);
135 edev
= devm_kzalloc(&pdev
->dev
,
136 sizeof(struct event_dev
) + keymapnamelen
+ 1,
141 input_dev
= devm_input_allocate_device(&pdev
->dev
);
145 edev
->input
= input_dev
;
149 for (i
= 0; i
< keymapnamelen
; i
++)
150 edev
->name
[i
] = __raw_readb(edev
->addr
+ REG_DATA
+ i
);
152 pr_debug("events_probe() keymap=%s\n", edev
->name
);
154 input_dev
->name
= edev
->name
;
155 input_dev
->id
.bustype
= BUS_HOST
;
157 events_import_bits(edev
, input_dev
->evbit
, EV_SYN
, EV_MAX
);
158 events_import_bits(edev
, input_dev
->keybit
, EV_KEY
, KEY_MAX
);
159 events_import_bits(edev
, input_dev
->relbit
, EV_REL
, REL_MAX
);
160 events_import_bits(edev
, input_dev
->absbit
, EV_ABS
, ABS_MAX
);
161 events_import_bits(edev
, input_dev
->mscbit
, EV_MSC
, MSC_MAX
);
162 events_import_bits(edev
, input_dev
->ledbit
, EV_LED
, LED_MAX
);
163 events_import_bits(edev
, input_dev
->sndbit
, EV_SND
, SND_MAX
);
164 events_import_bits(edev
, input_dev
->ffbit
, EV_FF
, FF_MAX
);
165 events_import_bits(edev
, input_dev
->swbit
, EV_SW
, SW_MAX
);
167 events_import_abs_params(edev
);
169 error
= devm_request_irq(&pdev
->dev
, edev
->irq
, events_interrupt
, 0,
170 "goldfish-events-keypad", edev
);
174 error
= input_register_device(input_dev
);
181 static struct platform_driver events_driver
= {
182 .probe
= events_probe
,
184 .name
= "goldfish_events",
188 module_platform_driver(events_driver
);
190 MODULE_AUTHOR("Brian Swetland");
191 MODULE_DESCRIPTION("Goldfish Event Device");
192 MODULE_LICENSE("GPL");