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>
25 #include <linux/acpi.h>
34 PAGE_EVBITS
= 0x10000,
35 PAGE_ABSDATA
= 0x20000 | EV_ABS
,
39 struct input_dev
*input
;
45 static irqreturn_t
events_interrupt(int irq
, void *dev_id
)
47 struct event_dev
*edev
= dev_id
;
48 unsigned int type
, code
, value
;
50 type
= __raw_readl(edev
->addr
+ REG_READ
);
51 code
= __raw_readl(edev
->addr
+ REG_READ
);
52 value
= __raw_readl(edev
->addr
+ REG_READ
);
54 input_event(edev
->input
, type
, code
, value
);
55 input_sync(edev
->input
);
59 static void events_import_bits(struct event_dev
*edev
,
60 unsigned long bits
[], unsigned int type
, size_t count
)
62 void __iomem
*addr
= edev
->addr
;
67 __raw_writel(PAGE_EVBITS
| type
, addr
+ REG_SET_PAGE
);
69 size
= __raw_readl(addr
+ REG_LEN
) * 8;
74 for (i
= 0; i
< count
; i
+= 8) {
75 val
= __raw_readb(addr
++);
76 for (j
= 0; j
< 8; j
++)
82 static void events_import_abs_params(struct event_dev
*edev
)
84 struct input_dev
*input_dev
= edev
->input
;
85 void __iomem
*addr
= edev
->addr
;
90 __raw_writel(PAGE_ABSDATA
, addr
+ REG_SET_PAGE
);
92 count
= __raw_readl(addr
+ REG_LEN
) / sizeof(val
);
96 for (i
= 0; i
< count
; i
++) {
97 if (!test_bit(i
, input_dev
->absbit
))
100 for (j
= 0; j
< ARRAY_SIZE(val
); j
++) {
101 int offset
= (i
* ARRAY_SIZE(val
) + j
) * sizeof(u32
);
103 val
[j
] = __raw_readl(edev
->addr
+ REG_DATA
+ offset
);
106 input_set_abs_params(input_dev
, i
,
107 val
[0], val
[1], val
[2], val
[3]);
111 static int events_probe(struct platform_device
*pdev
)
113 struct input_dev
*input_dev
;
114 struct event_dev
*edev
;
115 struct resource
*res
;
116 unsigned int keymapnamelen
;
122 irq
= platform_get_irq(pdev
, 0);
126 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
130 addr
= devm_ioremap(&pdev
->dev
, res
->start
, 4096);
134 __raw_writel(PAGE_NAME
, addr
+ REG_SET_PAGE
);
135 keymapnamelen
= __raw_readl(addr
+ REG_LEN
);
137 edev
= devm_kzalloc(&pdev
->dev
,
138 sizeof(struct event_dev
) + keymapnamelen
+ 1,
143 input_dev
= devm_input_allocate_device(&pdev
->dev
);
147 edev
->input
= input_dev
;
151 for (i
= 0; i
< keymapnamelen
; i
++)
152 edev
->name
[i
] = __raw_readb(edev
->addr
+ REG_DATA
+ i
);
154 pr_debug("%s: keymap=%s\n", __func__
, edev
->name
);
156 input_dev
->name
= edev
->name
;
157 input_dev
->id
.bustype
= BUS_HOST
;
159 events_import_bits(edev
, input_dev
->evbit
, EV_SYN
, EV_MAX
);
160 events_import_bits(edev
, input_dev
->keybit
, EV_KEY
, KEY_MAX
);
161 events_import_bits(edev
, input_dev
->relbit
, EV_REL
, REL_MAX
);
162 events_import_bits(edev
, input_dev
->absbit
, EV_ABS
, ABS_MAX
);
163 events_import_bits(edev
, input_dev
->mscbit
, EV_MSC
, MSC_MAX
);
164 events_import_bits(edev
, input_dev
->ledbit
, EV_LED
, LED_MAX
);
165 events_import_bits(edev
, input_dev
->sndbit
, EV_SND
, SND_MAX
);
166 events_import_bits(edev
, input_dev
->ffbit
, EV_FF
, FF_MAX
);
167 events_import_bits(edev
, input_dev
->swbit
, EV_SW
, SW_MAX
);
169 events_import_abs_params(edev
);
171 error
= devm_request_irq(&pdev
->dev
, edev
->irq
, events_interrupt
, 0,
172 "goldfish-events-keypad", edev
);
176 error
= input_register_device(input_dev
);
183 static const struct of_device_id goldfish_events_of_match
[] = {
184 { .compatible
= "google,goldfish-events-keypad", },
187 MODULE_DEVICE_TABLE(of
, goldfish_events_of_match
);
190 static const struct acpi_device_id goldfish_events_acpi_match
[] = {
194 MODULE_DEVICE_TABLE(acpi
, goldfish_events_acpi_match
);
197 static struct platform_driver events_driver
= {
198 .probe
= events_probe
,
200 .name
= "goldfish_events",
201 .of_match_table
= goldfish_events_of_match
,
202 .acpi_match_table
= ACPI_PTR(goldfish_events_acpi_match
),
206 module_platform_driver(events_driver
);
208 MODULE_AUTHOR("Brian Swetland");
209 MODULE_DESCRIPTION("Goldfish Event Device");
210 MODULE_LICENSE("GPL");