1 // SPDX-License-Identifier: GPL-2.0+
3 * Azoteq IQS620A/621/622/624/625 Keys and Switches
5 * Copyright (C) 2019 Jeff LaBundy <jeff@labundy.com>
8 #include <linux/device.h>
9 #include <linux/input.h>
10 #include <linux/kernel.h>
11 #include <linux/mfd/iqs62x.h>
12 #include <linux/module.h>
13 #include <linux/notifier.h>
14 #include <linux/platform_device.h>
15 #include <linux/property.h>
16 #include <linux/regmap.h>
17 #include <linux/slab.h>
24 static const char * const iqs62x_switch_names
[] = {
25 [IQS62X_SW_HALL_N
] = "hall-switch-north",
26 [IQS62X_SW_HALL_S
] = "hall-switch-south",
29 struct iqs62x_switch_desc
{
30 enum iqs62x_event_flag flag
;
35 struct iqs62x_keys_private
{
36 struct iqs62x_core
*iqs62x
;
37 struct input_dev
*input
;
38 struct notifier_block notifier
;
39 struct iqs62x_switch_desc switches
[ARRAY_SIZE(iqs62x_switch_names
)];
40 unsigned int keycode
[IQS62X_NUM_KEYS
];
41 unsigned int keycodemax
;
45 static int iqs62x_keys_parse_prop(struct platform_device
*pdev
,
46 struct iqs62x_keys_private
*iqs62x_keys
)
48 struct fwnode_handle
*child
;
52 ret
= device_property_count_u32(&pdev
->dev
, "linux,keycodes");
53 if (ret
> IQS62X_NUM_KEYS
) {
54 dev_err(&pdev
->dev
, "Too many keycodes present\n");
57 dev_err(&pdev
->dev
, "Failed to count keycodes: %d\n", ret
);
60 iqs62x_keys
->keycodemax
= ret
;
62 ret
= device_property_read_u32_array(&pdev
->dev
, "linux,keycodes",
64 iqs62x_keys
->keycodemax
);
66 dev_err(&pdev
->dev
, "Failed to read keycodes: %d\n", ret
);
70 for (i
= 0; i
< ARRAY_SIZE(iqs62x_keys
->switches
); i
++) {
71 child
= device_get_named_child_node(&pdev
->dev
,
72 iqs62x_switch_names
[i
]);
76 ret
= fwnode_property_read_u32(child
, "linux,code", &val
);
78 dev_err(&pdev
->dev
, "Failed to read switch code: %d\n",
82 iqs62x_keys
->switches
[i
].code
= val
;
83 iqs62x_keys
->switches
[i
].enabled
= true;
85 if (fwnode_property_present(child
, "azoteq,use-prox"))
86 iqs62x_keys
->switches
[i
].flag
= (i
== IQS62X_SW_HALL_N
?
87 IQS62X_EVENT_HALL_N_P
:
88 IQS62X_EVENT_HALL_S_P
);
90 iqs62x_keys
->switches
[i
].flag
= (i
== IQS62X_SW_HALL_N
?
91 IQS62X_EVENT_HALL_N_T
:
92 IQS62X_EVENT_HALL_S_T
);
98 static int iqs62x_keys_init(struct iqs62x_keys_private
*iqs62x_keys
)
100 struct iqs62x_core
*iqs62x
= iqs62x_keys
->iqs62x
;
101 enum iqs62x_event_flag flag
;
102 unsigned int event_reg
, val
;
103 unsigned int event_mask
= 0;
106 switch (iqs62x
->dev_desc
->prod_num
) {
107 case IQS620_PROD_NUM
:
108 case IQS621_PROD_NUM
:
109 case IQS622_PROD_NUM
:
110 event_reg
= IQS620_GLBL_EVENT_MASK
;
113 * Discreet button, hysteresis and SAR UI flags represent keys
114 * and are unmasked if mapped to a valid keycode.
116 for (i
= 0; i
< iqs62x_keys
->keycodemax
; i
++) {
117 if (iqs62x_keys
->keycode
[i
] == KEY_RESERVED
)
120 if (iqs62x_events
[i
].reg
== IQS62X_EVENT_PROX
)
121 event_mask
|= iqs62x
->dev_desc
->prox_mask
;
122 else if (iqs62x_events
[i
].reg
== IQS62X_EVENT_HYST
)
123 event_mask
|= (iqs62x
->dev_desc
->hyst_mask
|
124 iqs62x
->dev_desc
->sar_mask
);
127 ret
= regmap_read(iqs62x
->regmap
, iqs62x
->dev_desc
->hall_flags
,
133 * Hall UI flags represent switches and are unmasked if their
134 * corresponding child nodes are present.
136 for (i
= 0; i
< ARRAY_SIZE(iqs62x_keys
->switches
); i
++) {
137 if (!(iqs62x_keys
->switches
[i
].enabled
))
140 flag
= iqs62x_keys
->switches
[i
].flag
;
142 if (iqs62x_events
[flag
].reg
!= IQS62X_EVENT_HALL
)
145 event_mask
|= iqs62x
->dev_desc
->hall_mask
;
147 input_report_switch(iqs62x_keys
->input
,
148 iqs62x_keys
->switches
[i
].code
,
149 (val
& iqs62x_events
[flag
].mask
) ==
150 iqs62x_events
[flag
].val
);
153 input_sync(iqs62x_keys
->input
);
156 case IQS624_PROD_NUM
:
157 event_reg
= IQS624_HALL_UI
;
160 * Interval change events represent keys and are unmasked if
161 * either wheel movement flag is mapped to a valid keycode.
163 if (iqs62x_keys
->keycode
[IQS62X_EVENT_WHEEL_UP
] != KEY_RESERVED
)
164 event_mask
|= IQS624_HALL_UI_INT_EVENT
;
166 if (iqs62x_keys
->keycode
[IQS62X_EVENT_WHEEL_DN
] != KEY_RESERVED
)
167 event_mask
|= IQS624_HALL_UI_INT_EVENT
;
169 ret
= regmap_read(iqs62x
->regmap
, iqs62x
->dev_desc
->interval
,
174 iqs62x_keys
->interval
= val
;
181 return regmap_update_bits(iqs62x
->regmap
, event_reg
, event_mask
, 0);
184 static int iqs62x_keys_notifier(struct notifier_block
*notifier
,
185 unsigned long event_flags
, void *context
)
187 struct iqs62x_event_data
*event_data
= context
;
188 struct iqs62x_keys_private
*iqs62x_keys
;
191 iqs62x_keys
= container_of(notifier
, struct iqs62x_keys_private
,
194 if (event_flags
& BIT(IQS62X_EVENT_SYS_RESET
)) {
195 ret
= iqs62x_keys_init(iqs62x_keys
);
197 dev_err(iqs62x_keys
->input
->dev
.parent
,
198 "Failed to re-initialize device: %d\n", ret
);
205 for (i
= 0; i
< iqs62x_keys
->keycodemax
; i
++) {
206 if (iqs62x_events
[i
].reg
== IQS62X_EVENT_WHEEL
&&
207 event_data
->interval
== iqs62x_keys
->interval
)
210 input_report_key(iqs62x_keys
->input
, iqs62x_keys
->keycode
[i
],
211 event_flags
& BIT(i
));
214 for (i
= 0; i
< ARRAY_SIZE(iqs62x_keys
->switches
); i
++)
215 if (iqs62x_keys
->switches
[i
].enabled
)
216 input_report_switch(iqs62x_keys
->input
,
217 iqs62x_keys
->switches
[i
].code
,
219 BIT(iqs62x_keys
->switches
[i
].flag
));
221 input_sync(iqs62x_keys
->input
);
223 if (event_data
->interval
== iqs62x_keys
->interval
)
227 * Each frame contains at most one wheel event (up or down), in which
228 * case a complementary release cycle is emulated.
230 if (event_flags
& BIT(IQS62X_EVENT_WHEEL_UP
)) {
231 input_report_key(iqs62x_keys
->input
,
232 iqs62x_keys
->keycode
[IQS62X_EVENT_WHEEL_UP
],
234 input_sync(iqs62x_keys
->input
);
235 } else if (event_flags
& BIT(IQS62X_EVENT_WHEEL_DN
)) {
236 input_report_key(iqs62x_keys
->input
,
237 iqs62x_keys
->keycode
[IQS62X_EVENT_WHEEL_DN
],
239 input_sync(iqs62x_keys
->input
);
242 iqs62x_keys
->interval
= event_data
->interval
;
247 static int iqs62x_keys_probe(struct platform_device
*pdev
)
249 struct iqs62x_core
*iqs62x
= dev_get_drvdata(pdev
->dev
.parent
);
250 struct iqs62x_keys_private
*iqs62x_keys
;
251 struct input_dev
*input
;
254 iqs62x_keys
= devm_kzalloc(&pdev
->dev
, sizeof(*iqs62x_keys
),
259 platform_set_drvdata(pdev
, iqs62x_keys
);
261 ret
= iqs62x_keys_parse_prop(pdev
, iqs62x_keys
);
265 input
= devm_input_allocate_device(&pdev
->dev
);
269 input
->keycodemax
= iqs62x_keys
->keycodemax
;
270 input
->keycode
= iqs62x_keys
->keycode
;
271 input
->keycodesize
= sizeof(*iqs62x_keys
->keycode
);
273 input
->name
= iqs62x
->dev_desc
->dev_name
;
274 input
->id
.bustype
= BUS_I2C
;
276 for (i
= 0; i
< iqs62x_keys
->keycodemax
; i
++)
277 if (iqs62x_keys
->keycode
[i
] != KEY_RESERVED
)
278 input_set_capability(input
, EV_KEY
,
279 iqs62x_keys
->keycode
[i
]);
281 for (i
= 0; i
< ARRAY_SIZE(iqs62x_keys
->switches
); i
++)
282 if (iqs62x_keys
->switches
[i
].enabled
)
283 input_set_capability(input
, EV_SW
,
284 iqs62x_keys
->switches
[i
].code
);
286 iqs62x_keys
->iqs62x
= iqs62x
;
287 iqs62x_keys
->input
= input
;
289 ret
= iqs62x_keys_init(iqs62x_keys
);
291 dev_err(&pdev
->dev
, "Failed to initialize device: %d\n", ret
);
295 ret
= input_register_device(iqs62x_keys
->input
);
297 dev_err(&pdev
->dev
, "Failed to register device: %d\n", ret
);
301 iqs62x_keys
->notifier
.notifier_call
= iqs62x_keys_notifier
;
302 ret
= blocking_notifier_chain_register(&iqs62x_keys
->iqs62x
->nh
,
303 &iqs62x_keys
->notifier
);
305 dev_err(&pdev
->dev
, "Failed to register notifier: %d\n", ret
);
310 static int iqs62x_keys_remove(struct platform_device
*pdev
)
312 struct iqs62x_keys_private
*iqs62x_keys
= platform_get_drvdata(pdev
);
315 ret
= blocking_notifier_chain_unregister(&iqs62x_keys
->iqs62x
->nh
,
316 &iqs62x_keys
->notifier
);
318 dev_err(&pdev
->dev
, "Failed to unregister notifier: %d\n", ret
);
323 static struct platform_driver iqs62x_keys_platform_driver
= {
325 .name
= "iqs62x-keys",
327 .probe
= iqs62x_keys_probe
,
328 .remove
= iqs62x_keys_remove
,
330 module_platform_driver(iqs62x_keys_platform_driver
);
332 MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>");
333 MODULE_DESCRIPTION("Azoteq IQS620A/621/622/624/625 Keys and Switches");
334 MODULE_LICENSE("GPL");
335 MODULE_ALIAS("platform:iqs62x-keys");