1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Keypad driver for Analog Devices ADP5520 MFD PMICs
5 * Copyright 2009 Analog Devices Inc.
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/platform_device.h>
11 #include <linux/input.h>
12 #include <linux/mfd/adp5520.h>
13 #include <linux/slab.h>
14 #include <linux/device.h>
17 struct input_dev
*input
;
18 struct notifier_block notifier
;
19 struct device
*master
;
20 unsigned short keycode
[ADP5520_KEYMAPSIZE
];
23 static void adp5520_keys_report_event(struct adp5520_keys
*dev
,
24 unsigned short keymask
, int value
)
28 for (i
= 0; i
< ADP5520_MAXKEYS
; i
++)
29 if (keymask
& (1 << i
))
30 input_report_key(dev
->input
, dev
->keycode
[i
], value
);
32 input_sync(dev
->input
);
35 static int adp5520_keys_notifier(struct notifier_block
*nb
,
36 unsigned long event
, void *data
)
38 struct adp5520_keys
*dev
;
39 uint8_t reg_val_lo
, reg_val_hi
;
40 unsigned short keymask
;
42 dev
= container_of(nb
, struct adp5520_keys
, notifier
);
44 if (event
& ADP5520_KP_INT
) {
45 adp5520_read(dev
->master
, ADP5520_KP_INT_STAT_1
, ®_val_lo
);
46 adp5520_read(dev
->master
, ADP5520_KP_INT_STAT_2
, ®_val_hi
);
48 keymask
= (reg_val_hi
<< 8) | reg_val_lo
;
49 /* Read twice to clear */
50 adp5520_read(dev
->master
, ADP5520_KP_INT_STAT_1
, ®_val_lo
);
51 adp5520_read(dev
->master
, ADP5520_KP_INT_STAT_2
, ®_val_hi
);
52 keymask
|= (reg_val_hi
<< 8) | reg_val_lo
;
53 adp5520_keys_report_event(dev
, keymask
, 1);
56 if (event
& ADP5520_KR_INT
) {
57 adp5520_read(dev
->master
, ADP5520_KR_INT_STAT_1
, ®_val_lo
);
58 adp5520_read(dev
->master
, ADP5520_KR_INT_STAT_2
, ®_val_hi
);
60 keymask
= (reg_val_hi
<< 8) | reg_val_lo
;
61 /* Read twice to clear */
62 adp5520_read(dev
->master
, ADP5520_KR_INT_STAT_1
, ®_val_lo
);
63 adp5520_read(dev
->master
, ADP5520_KR_INT_STAT_2
, ®_val_hi
);
64 keymask
|= (reg_val_hi
<< 8) | reg_val_lo
;
65 adp5520_keys_report_event(dev
, keymask
, 0);
71 static int adp5520_keys_probe(struct platform_device
*pdev
)
73 struct adp5520_keys_platform_data
*pdata
= dev_get_platdata(&pdev
->dev
);
74 struct input_dev
*input
;
75 struct adp5520_keys
*dev
;
77 unsigned char en_mask
, ctl_mask
= 0;
79 if (pdev
->id
!= ID_ADP5520
) {
80 dev_err(&pdev
->dev
, "only ADP5520 supports Keypad\n");
85 dev_err(&pdev
->dev
, "missing platform data\n");
89 if (!(pdata
->rows_en_mask
&& pdata
->cols_en_mask
))
92 dev
= devm_kzalloc(&pdev
->dev
, sizeof(*dev
), GFP_KERNEL
);
94 dev_err(&pdev
->dev
, "failed to alloc memory\n");
98 input
= devm_input_allocate_device(&pdev
->dev
);
102 dev
->master
= pdev
->dev
.parent
;
105 input
->name
= pdev
->name
;
106 input
->phys
= "adp5520-keys/input0";
107 input
->dev
.parent
= &pdev
->dev
;
109 input
->id
.bustype
= BUS_I2C
;
110 input
->id
.vendor
= 0x0001;
111 input
->id
.product
= 0x5520;
112 input
->id
.version
= 0x0001;
114 input
->keycodesize
= sizeof(dev
->keycode
[0]);
115 input
->keycodemax
= pdata
->keymapsize
;
116 input
->keycode
= dev
->keycode
;
118 memcpy(dev
->keycode
, pdata
->keymap
,
119 pdata
->keymapsize
* input
->keycodesize
);
121 /* setup input device */
122 __set_bit(EV_KEY
, input
->evbit
);
125 __set_bit(EV_REP
, input
->evbit
);
127 for (i
= 0; i
< input
->keycodemax
; i
++)
128 __set_bit(dev
->keycode
[i
], input
->keybit
);
129 __clear_bit(KEY_RESERVED
, input
->keybit
);
131 ret
= input_register_device(input
);
133 dev_err(&pdev
->dev
, "unable to register input device\n");
137 en_mask
= pdata
->rows_en_mask
| pdata
->cols_en_mask
;
139 ret
= adp5520_set_bits(dev
->master
, ADP5520_GPIO_CFG_1
, en_mask
);
141 if (en_mask
& ADP5520_COL_C3
)
142 ctl_mask
|= ADP5520_C3_MODE
;
144 if (en_mask
& ADP5520_ROW_R3
)
145 ctl_mask
|= ADP5520_R3_MODE
;
148 ret
|= adp5520_set_bits(dev
->master
, ADP5520_LED_CONTROL
,
151 ret
|= adp5520_set_bits(dev
->master
, ADP5520_GPIO_PULLUP
,
152 pdata
->rows_en_mask
);
155 dev_err(&pdev
->dev
, "failed to write\n");
159 dev
->notifier
.notifier_call
= adp5520_keys_notifier
;
160 ret
= adp5520_register_notifier(dev
->master
, &dev
->notifier
,
161 ADP5520_KP_IEN
| ADP5520_KR_IEN
);
163 dev_err(&pdev
->dev
, "failed to register notifier\n");
167 platform_set_drvdata(pdev
, dev
);
171 static void adp5520_keys_remove(struct platform_device
*pdev
)
173 struct adp5520_keys
*dev
= platform_get_drvdata(pdev
);
175 adp5520_unregister_notifier(dev
->master
, &dev
->notifier
,
176 ADP5520_KP_IEN
| ADP5520_KR_IEN
);
179 static struct platform_driver adp5520_keys_driver
= {
181 .name
= "adp5520-keys",
183 .probe
= adp5520_keys_probe
,
184 .remove
= adp5520_keys_remove
,
186 module_platform_driver(adp5520_keys_driver
);
188 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
189 MODULE_DESCRIPTION("Keys ADP5520 Driver");
190 MODULE_LICENSE("GPL");
191 MODULE_ALIAS("platform:adp5520-keys");