2 * Buttons driver for iPAQ h1910/h1915
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file COPYING in the main directory of this archive for
8 * Copyright (C) 2005 Pawel Kolodziejski
9 * Copyright (C) 2003 Joshua Wise
13 #include <linux/input.h>
14 #include <linux/input_pda.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/interrupt.h>
19 #include <asm/mach/arch.h>
20 #include <asm/mach/map.h>
21 #include <asm/mach-types.h>
22 #include <asm/hardware.h>
23 #include <asm/arch/pxa-regs.h>
24 #include <asm/arch/irqs.h>
25 #include <asm/hardware/ipaq-asic3.h>
26 #include <asm/arch/h1900-gpio.h>
27 #include <asm/arch/h1900-asic.h>
29 #include <linux/soc/asic3_base.h>
30 #include <linux/platform_device.h>
32 extern struct platform_device h1900_asic3
;
33 #define asic3 &h1900_asic3.dev
34 static struct input_dev
*button_dev
;
42 static struct keys pxa_button_tab
[] = {
43 { _KEY_POWER
, GPIO_NR_H1900_POWER_BUTTON_N
, "Power button" },
44 { KEY_ENTER
, GPIO_NR_H1900_ACTION_BUTTON_N
, "Action button" },
45 { KEY_UP
, GPIO_NR_H1900_UP_BUTTON_N
, "Up button" },
46 { KEY_DOWN
, GPIO_NR_H1900_DOWN_BUTTON_N
, "Down button" },
47 { KEY_LEFT
, GPIO_NR_H1900_LEFT_BUTTON_N
, "Left button" },
48 { KEY_RIGHT
, GPIO_NR_H1900_RIGHT_BUTTON_N
, "Right button" },
58 #define BIT_RECORD 0x04
61 #define BIT_CONTACTS 0x20
62 #define BIT_CALENDAR 0x40
64 static struct kpad button_tab
[] = {
65 { BIT_RECORD
, _KEY_RECORD
, H1900_RECORD_BTN_IRQ
, "Record button" },
66 { BIT_HOME
, _KEY_HOMEPAGE
, H1900_HOME_BTN_IRQ
, "Home button" },
67 { BIT_MAIL
, _KEY_MAIL
, H1900_MAIL_BTN_IRQ
, "Mail button" },
68 { BIT_CONTACTS
, _KEY_CONTACTS
, H1900_CONTACTS_BTN_IRQ
, "Contacts button" },
69 { BIT_CALENDAR
, _KEY_CALENDAR
, H1900_CALENDAR_BTN_IRQ
, "Calendar button" },
72 static irqreturn_t
h1900_buttons_asic_handle(int irq
, void *data
, struct pt_regs
*regs
)
74 int i
, pressed
, base_irq
;
76 base_irq
= asic3_irq_base(asic3
);
77 for (i
= 0; i
< ARRAY_SIZE(button_tab
); i
++) {
78 if ((base_irq
+ button_tab
[i
].irq
) == irq
) {
79 pressed
= !(asic3_get_gpio_status_d(asic3
) & button_tab
[i
].keybit
);
81 set_irq_type(irq
, IRQT_FALLING
);
83 set_irq_type(irq
, IRQT_RISING
);
85 input_report_key(button_dev
, button_tab
[i
].keyno
, pressed
);
86 input_sync(button_dev
);
93 static irqreturn_t
h1900_buttons_handle(int irq
, void* data
, struct pt_regs
*regs
)
97 for (button
= 0; button
< ARRAY_SIZE(pxa_button_tab
); button
++)
98 if (IRQ_GPIO(pxa_button_tab
[button
].gpio
) == irq
)
101 if (likely(button
< ARRAY_SIZE(pxa_button_tab
))) {
102 down
= GPLR(pxa_button_tab
[button
].gpio
) & GPIO_bit(pxa_button_tab
[button
].gpio
) ? 0 : 1;
103 input_report_key(button_dev
, pxa_button_tab
[button
].keyno
, down
);
104 input_sync(button_dev
);
110 static int __init
h1900_buttons_probe(struct device
*dev
)
114 if (!machine_is_h1900())
117 button_dev
= input_allocate_device();
121 button_dev
->name
= "hp iPAQ h1910/h1915 buttons driver";
122 set_bit(EV_KEY
, button_dev
->evbit
);
124 base_irq
= asic3_irq_base(asic3
);
126 for (i
= 0; i
< ARRAY_SIZE(pxa_button_tab
); i
++) {
127 set_bit(pxa_button_tab
[i
].keyno
, button_dev
->keybit
);
128 request_irq(IRQ_GPIO(pxa_button_tab
[i
].gpio
), h1900_buttons_handle
, SA_SAMPLE_RANDOM
, pxa_button_tab
[i
].desc
, NULL
);
129 set_irq_type(IRQ_GPIO(pxa_button_tab
[i
].gpio
), IRQT_BOTHEDGE
);
132 for (i
= 0; i
< ARRAY_SIZE(button_tab
); i
++) {
133 set_bit(button_tab
[i
].keyno
, button_dev
->keybit
);
134 request_irq(base_irq
+ button_tab
[i
].irq
, h1900_buttons_asic_handle
, SA_SAMPLE_RANDOM
, button_tab
[i
].desc
, NULL
);
135 set_irq_type(base_irq
+ button_tab
[i
].irq
, IRQT_FALLING
);
138 input_register_device(button_dev
);
144 static int h1900_buttons_suspend(struct device
*dev
, pm_message_t state
)
148 base_irq
= asic3_irq_base(asic3
);
150 for (i
= 0; i
< ARRAY_SIZE(pxa_button_tab
); i
++) {
151 disable_irq(IRQ_GPIO(pxa_button_tab
[i
].gpio
));
154 for (i
= 0; i
< ARRAY_SIZE(button_tab
); i
++) {
155 disable_irq(base_irq
+ button_tab
[i
].irq
);
161 static int h1900_buttons_resume(struct device
*dev
)
165 base_irq
= asic3_irq_base(asic3
);
167 for (i
= 0; i
< ARRAY_SIZE(pxa_button_tab
); i
++) {
168 enable_irq(IRQ_GPIO(pxa_button_tab
[i
].gpio
));
171 for (i
= 0; i
< ARRAY_SIZE(button_tab
); i
++) {
172 enable_irq(base_irq
+ button_tab
[i
].irq
);
179 static struct device_driver h1900_buttons_driver
= {
180 .name
= "h1900-buttons",
181 .bus
= &platform_bus_type
,
182 .probe
= h1900_buttons_probe
,
184 .suspend
= h1900_buttons_suspend
,
185 .resume
= h1900_buttons_resume
,
189 static int __init
h1900_buttons_init(void)
191 if (!machine_is_h1900())
194 return driver_register(&h1900_buttons_driver
);
197 static void __exit
h1900_buttons_exit(void)
201 input_unregister_device(button_dev
);
203 for (i
= 0; i
< ARRAY_SIZE(pxa_button_tab
); i
++) {
204 free_irq(IRQ_GPIO(pxa_button_tab
[i
].gpio
), NULL
);
207 base_irq
= asic3_irq_base(asic3
);
208 for (i
= 0; i
< ARRAY_SIZE(button_tab
); i
++) {
209 free_irq(base_irq
+ button_tab
[i
].irq
, NULL
);
212 driver_unregister(&h1900_buttons_driver
);
215 module_init(h1900_buttons_init
);
216 module_exit(h1900_buttons_exit
);
218 MODULE_AUTHOR ("Joshua Wise, Pawel Kolodziejski");
219 MODULE_DESCRIPTION ("Button support for iPAQ h1910/h1915");
220 MODULE_LICENSE ("GPL");