2 * Keypad driver for Analog Devices ADP5520 MFD PMICs
4 * Copyright 2009 Analog Devices Inc.
6 * Licensed under the GPL-2 or later.
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/platform_device.h>
13 #include <linux/input.h>
14 #include <linux/mfd/adp5520.h>
15 #include <linux/slab.h>
18 struct input_dev
*input
;
19 struct notifier_block notifier
;
20 struct device
*master
;
21 unsigned short keycode
[ADP5520_KEYMAPSIZE
];
24 static void adp5520_keys_report_event(struct adp5520_keys
*dev
,
25 unsigned short keymask
, int value
)
29 for (i
= 0; i
< ADP5520_MAXKEYS
; i
++)
30 if (keymask
& (1 << i
))
31 input_report_key(dev
->input
, dev
->keycode
[i
], value
);
33 input_sync(dev
->input
);
36 static int adp5520_keys_notifier(struct notifier_block
*nb
,
37 unsigned long event
, void *data
)
39 struct adp5520_keys
*dev
;
40 uint8_t reg_val_lo
, reg_val_hi
;
41 unsigned short keymask
;
43 dev
= container_of(nb
, struct adp5520_keys
, notifier
);
45 if (event
& ADP5520_KP_INT
) {
46 adp5520_read(dev
->master
, ADP5520_KP_INT_STAT_1
, ®_val_lo
);
47 adp5520_read(dev
->master
, ADP5520_KP_INT_STAT_2
, ®_val_hi
);
49 keymask
= (reg_val_hi
<< 8) | reg_val_lo
;
50 /* Read twice to clear */
51 adp5520_read(dev
->master
, ADP5520_KP_INT_STAT_1
, ®_val_lo
);
52 adp5520_read(dev
->master
, ADP5520_KP_INT_STAT_2
, ®_val_hi
);
53 keymask
|= (reg_val_hi
<< 8) | reg_val_lo
;
54 adp5520_keys_report_event(dev
, keymask
, 1);
57 if (event
& ADP5520_KR_INT
) {
58 adp5520_read(dev
->master
, ADP5520_KR_INT_STAT_1
, ®_val_lo
);
59 adp5520_read(dev
->master
, ADP5520_KR_INT_STAT_2
, ®_val_hi
);
61 keymask
= (reg_val_hi
<< 8) | reg_val_lo
;
62 /* Read twice to clear */
63 adp5520_read(dev
->master
, ADP5520_KR_INT_STAT_1
, ®_val_lo
);
64 adp5520_read(dev
->master
, ADP5520_KR_INT_STAT_2
, ®_val_hi
);
65 keymask
|= (reg_val_hi
<< 8) | reg_val_lo
;
66 adp5520_keys_report_event(dev
, keymask
, 0);
72 static int __devinit
adp5520_keys_probe(struct platform_device
*pdev
)
74 struct adp5520_keys_platform_data
*pdata
= pdev
->dev
.platform_data
;
75 struct input_dev
*input
;
76 struct adp5520_keys
*dev
;
78 unsigned char en_mask
, ctl_mask
= 0;
80 if (pdev
->id
!= ID_ADP5520
) {
81 dev_err(&pdev
->dev
, "only ADP5520 supports Keypad\n");
86 dev_err(&pdev
->dev
, "missing platform data\n");
90 if (!(pdata
->rows_en_mask
&& pdata
->cols_en_mask
))
93 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
95 dev_err(&pdev
->dev
, "failed to alloc memory\n");
99 input
= input_allocate_device();
105 dev
->master
= pdev
->dev
.parent
;
108 input
->name
= pdev
->name
;
109 input
->phys
= "adp5520-keys/input0";
110 input
->dev
.parent
= &pdev
->dev
;
112 input_set_drvdata(input
, dev
);
114 input
->id
.bustype
= BUS_I2C
;
115 input
->id
.vendor
= 0x0001;
116 input
->id
.product
= 0x5520;
117 input
->id
.version
= 0x0001;
119 input
->keycodesize
= sizeof(dev
->keycode
[0]);
120 input
->keycodemax
= pdata
->keymapsize
;
121 input
->keycode
= dev
->keycode
;
123 memcpy(dev
->keycode
, pdata
->keymap
,
124 pdata
->keymapsize
* input
->keycodesize
);
126 /* setup input device */
127 __set_bit(EV_KEY
, input
->evbit
);
130 __set_bit(EV_REP
, input
->evbit
);
132 for (i
= 0; i
< input
->keycodemax
; i
++)
133 __set_bit(dev
->keycode
[i
], input
->keybit
);
134 __clear_bit(KEY_RESERVED
, input
->keybit
);
136 ret
= input_register_device(input
);
138 dev_err(&pdev
->dev
, "unable to register input device\n");
142 en_mask
= pdata
->rows_en_mask
| pdata
->cols_en_mask
;
144 ret
= adp5520_set_bits(dev
->master
, ADP5520_GPIO_CFG_1
, en_mask
);
146 if (en_mask
& ADP5520_COL_C3
)
147 ctl_mask
|= ADP5520_C3_MODE
;
149 if (en_mask
& ADP5520_ROW_R3
)
150 ctl_mask
|= ADP5520_R3_MODE
;
153 ret
|= adp5520_set_bits(dev
->master
, ADP5520_LED_CONTROL
,
156 ret
|= adp5520_set_bits(dev
->master
, ADP5520_GPIO_PULLUP
,
157 pdata
->rows_en_mask
);
160 dev_err(&pdev
->dev
, "failed to write\n");
165 dev
->notifier
.notifier_call
= adp5520_keys_notifier
;
166 ret
= adp5520_register_notifier(dev
->master
, &dev
->notifier
,
167 ADP5520_KP_IEN
| ADP5520_KR_IEN
);
169 dev_err(&pdev
->dev
, "failed to register notifier\n");
173 platform_set_drvdata(pdev
, dev
);
177 input_unregister_device(input
);
180 input_free_device(input
);
185 static int __devexit
adp5520_keys_remove(struct platform_device
*pdev
)
187 struct adp5520_keys
*dev
= platform_get_drvdata(pdev
);
189 adp5520_unregister_notifier(dev
->master
, &dev
->notifier
,
190 ADP5520_KP_IEN
| ADP5520_KR_IEN
);
192 input_unregister_device(dev
->input
);
197 static struct platform_driver adp5520_keys_driver
= {
199 .name
= "adp5520-keys",
200 .owner
= THIS_MODULE
,
202 .probe
= adp5520_keys_probe
,
203 .remove
= __devexit_p(adp5520_keys_remove
),
206 static int __init
adp5520_keys_init(void)
208 return platform_driver_register(&adp5520_keys_driver
);
210 module_init(adp5520_keys_init
);
212 static void __exit
adp5520_keys_exit(void)
214 platform_driver_unregister(&adp5520_keys_driver
);
216 module_exit(adp5520_keys_exit
);
218 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
219 MODULE_DESCRIPTION("Keys ADP5520 Driver");
220 MODULE_LICENSE("GPL");
221 MODULE_ALIAS("platform:adp5520-keys");