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/platform_device.h>
12 #include <linux/input.h>
13 #include <linux/mfd/adp5520.h>
14 #include <linux/slab.h>
15 #include <linux/device.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 adp5520_keys_probe(struct platform_device
*pdev
)
74 struct adp5520_keys_platform_data
*pdata
= dev_get_platdata(&pdev
->dev
);
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
= devm_kzalloc(&pdev
->dev
, sizeof(*dev
), GFP_KERNEL
);
95 dev_err(&pdev
->dev
, "failed to alloc memory\n");
99 input
= devm_input_allocate_device(&pdev
->dev
);
103 dev
->master
= pdev
->dev
.parent
;
106 input
->name
= pdev
->name
;
107 input
->phys
= "adp5520-keys/input0";
108 input
->dev
.parent
= &pdev
->dev
;
110 input
->id
.bustype
= BUS_I2C
;
111 input
->id
.vendor
= 0x0001;
112 input
->id
.product
= 0x5520;
113 input
->id
.version
= 0x0001;
115 input
->keycodesize
= sizeof(dev
->keycode
[0]);
116 input
->keycodemax
= pdata
->keymapsize
;
117 input
->keycode
= dev
->keycode
;
119 memcpy(dev
->keycode
, pdata
->keymap
,
120 pdata
->keymapsize
* input
->keycodesize
);
122 /* setup input device */
123 __set_bit(EV_KEY
, input
->evbit
);
126 __set_bit(EV_REP
, input
->evbit
);
128 for (i
= 0; i
< input
->keycodemax
; i
++)
129 __set_bit(dev
->keycode
[i
], input
->keybit
);
130 __clear_bit(KEY_RESERVED
, input
->keybit
);
132 ret
= input_register_device(input
);
134 dev_err(&pdev
->dev
, "unable to register input device\n");
138 en_mask
= pdata
->rows_en_mask
| pdata
->cols_en_mask
;
140 ret
= adp5520_set_bits(dev
->master
, ADP5520_GPIO_CFG_1
, en_mask
);
142 if (en_mask
& ADP5520_COL_C3
)
143 ctl_mask
|= ADP5520_C3_MODE
;
145 if (en_mask
& ADP5520_ROW_R3
)
146 ctl_mask
|= ADP5520_R3_MODE
;
149 ret
|= adp5520_set_bits(dev
->master
, ADP5520_LED_CONTROL
,
152 ret
|= adp5520_set_bits(dev
->master
, ADP5520_GPIO_PULLUP
,
153 pdata
->rows_en_mask
);
156 dev_err(&pdev
->dev
, "failed to write\n");
160 dev
->notifier
.notifier_call
= adp5520_keys_notifier
;
161 ret
= adp5520_register_notifier(dev
->master
, &dev
->notifier
,
162 ADP5520_KP_IEN
| ADP5520_KR_IEN
);
164 dev_err(&pdev
->dev
, "failed to register notifier\n");
168 platform_set_drvdata(pdev
, dev
);
172 static int adp5520_keys_remove(struct platform_device
*pdev
)
174 struct adp5520_keys
*dev
= platform_get_drvdata(pdev
);
176 adp5520_unregister_notifier(dev
->master
, &dev
->notifier
,
177 ADP5520_KP_IEN
| ADP5520_KR_IEN
);
182 static struct platform_driver adp5520_keys_driver
= {
184 .name
= "adp5520-keys",
186 .probe
= adp5520_keys_probe
,
187 .remove
= adp5520_keys_remove
,
189 module_platform_driver(adp5520_keys_driver
);
191 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
192 MODULE_DESCRIPTION("Keys ADP5520 Driver");
193 MODULE_LICENSE("GPL");
194 MODULE_ALIAS("platform:adp5520-keys");