1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Azoteq IQS620A/621/622/624/625 Keys and Switches |
4 | * |
5 | * Copyright (C) 2019 Jeff LaBundy <jeff@labundy.com> |
6 | */ |
7 | |
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> |
18 | |
19 | enum { |
20 | IQS62X_SW_HALL_N, |
21 | IQS62X_SW_HALL_S, |
22 | }; |
23 | |
24 | static const char * const iqs62x_switch_names[] = { |
25 | [IQS62X_SW_HALL_N] = "hall-switch-north" , |
26 | [IQS62X_SW_HALL_S] = "hall-switch-south" , |
27 | }; |
28 | |
29 | struct iqs62x_switch_desc { |
30 | enum iqs62x_event_flag flag; |
31 | unsigned int code; |
32 | bool enabled; |
33 | }; |
34 | |
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; |
42 | u8 interval; |
43 | }; |
44 | |
45 | static int iqs62x_keys_parse_prop(struct platform_device *pdev, |
46 | struct iqs62x_keys_private *iqs62x_keys) |
47 | { |
48 | struct fwnode_handle *child; |
49 | unsigned int val; |
50 | int ret, i; |
51 | |
52 | ret = device_property_count_u32(dev: &pdev->dev, propname: "linux,keycodes" ); |
53 | if (ret > IQS62X_NUM_KEYS) { |
54 | dev_err(&pdev->dev, "Too many keycodes present\n" ); |
55 | return -EINVAL; |
56 | } else if (ret < 0) { |
57 | dev_err(&pdev->dev, "Failed to count keycodes: %d\n" , ret); |
58 | return ret; |
59 | } |
60 | iqs62x_keys->keycodemax = ret; |
61 | |
62 | ret = device_property_read_u32_array(dev: &pdev->dev, propname: "linux,keycodes" , |
63 | val: iqs62x_keys->keycode, |
64 | nval: iqs62x_keys->keycodemax); |
65 | if (ret) { |
66 | dev_err(&pdev->dev, "Failed to read keycodes: %d\n" , ret); |
67 | return ret; |
68 | } |
69 | |
70 | for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) { |
71 | child = device_get_named_child_node(dev: &pdev->dev, |
72 | childname: iqs62x_switch_names[i]); |
73 | if (!child) |
74 | continue; |
75 | |
76 | ret = fwnode_property_read_u32(fwnode: child, propname: "linux,code" , val: &val); |
77 | if (ret) { |
78 | dev_err(&pdev->dev, "Failed to read switch code: %d\n" , |
79 | ret); |
80 | fwnode_handle_put(fwnode: child); |
81 | return ret; |
82 | } |
83 | iqs62x_keys->switches[i].code = val; |
84 | iqs62x_keys->switches[i].enabled = true; |
85 | |
86 | if (fwnode_property_present(fwnode: child, propname: "azoteq,use-prox" )) |
87 | iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ? |
88 | IQS62X_EVENT_HALL_N_P : |
89 | IQS62X_EVENT_HALL_S_P); |
90 | else |
91 | iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ? |
92 | IQS62X_EVENT_HALL_N_T : |
93 | IQS62X_EVENT_HALL_S_T); |
94 | |
95 | fwnode_handle_put(fwnode: child); |
96 | } |
97 | |
98 | return 0; |
99 | } |
100 | |
101 | static int iqs62x_keys_init(struct iqs62x_keys_private *iqs62x_keys) |
102 | { |
103 | struct iqs62x_core *iqs62x = iqs62x_keys->iqs62x; |
104 | enum iqs62x_event_flag flag; |
105 | unsigned int event_reg, val; |
106 | unsigned int event_mask = 0; |
107 | int ret, i; |
108 | |
109 | switch (iqs62x->dev_desc->prod_num) { |
110 | case IQS620_PROD_NUM: |
111 | case IQS621_PROD_NUM: |
112 | case IQS622_PROD_NUM: |
113 | event_reg = IQS620_GLBL_EVENT_MASK; |
114 | |
115 | /* |
116 | * Discreet button, hysteresis and SAR UI flags represent keys |
117 | * and are unmasked if mapped to a valid keycode. |
118 | */ |
119 | for (i = 0; i < iqs62x_keys->keycodemax; i++) { |
120 | if (iqs62x_keys->keycode[i] == KEY_RESERVED) |
121 | continue; |
122 | |
123 | if (iqs62x_events[i].reg == IQS62X_EVENT_PROX) |
124 | event_mask |= iqs62x->dev_desc->prox_mask; |
125 | else if (iqs62x_events[i].reg == IQS62X_EVENT_HYST) |
126 | event_mask |= (iqs62x->dev_desc->hyst_mask | |
127 | iqs62x->dev_desc->sar_mask); |
128 | } |
129 | |
130 | ret = regmap_read(map: iqs62x->regmap, reg: iqs62x->dev_desc->hall_flags, |
131 | val: &val); |
132 | if (ret) |
133 | return ret; |
134 | |
135 | /* |
136 | * Hall UI flags represent switches and are unmasked if their |
137 | * corresponding child nodes are present. |
138 | */ |
139 | for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) { |
140 | if (!(iqs62x_keys->switches[i].enabled)) |
141 | continue; |
142 | |
143 | flag = iqs62x_keys->switches[i].flag; |
144 | |
145 | if (iqs62x_events[flag].reg != IQS62X_EVENT_HALL) |
146 | continue; |
147 | |
148 | event_mask |= iqs62x->dev_desc->hall_mask; |
149 | |
150 | input_report_switch(dev: iqs62x_keys->input, |
151 | code: iqs62x_keys->switches[i].code, |
152 | value: (val & iqs62x_events[flag].mask) == |
153 | iqs62x_events[flag].val); |
154 | } |
155 | |
156 | input_sync(dev: iqs62x_keys->input); |
157 | break; |
158 | |
159 | case IQS624_PROD_NUM: |
160 | event_reg = IQS624_HALL_UI; |
161 | |
162 | /* |
163 | * Interval change events represent keys and are unmasked if |
164 | * either wheel movement flag is mapped to a valid keycode. |
165 | */ |
166 | if (iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_UP] != KEY_RESERVED) |
167 | event_mask |= IQS624_HALL_UI_INT_EVENT; |
168 | |
169 | if (iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_DN] != KEY_RESERVED) |
170 | event_mask |= IQS624_HALL_UI_INT_EVENT; |
171 | |
172 | ret = regmap_read(map: iqs62x->regmap, reg: iqs62x->dev_desc->interval, |
173 | val: &val); |
174 | if (ret) |
175 | return ret; |
176 | |
177 | iqs62x_keys->interval = val; |
178 | break; |
179 | |
180 | default: |
181 | return 0; |
182 | } |
183 | |
184 | return regmap_update_bits(map: iqs62x->regmap, reg: event_reg, mask: event_mask, val: 0); |
185 | } |
186 | |
187 | static int iqs62x_keys_notifier(struct notifier_block *notifier, |
188 | unsigned long event_flags, void *context) |
189 | { |
190 | struct iqs62x_event_data *event_data = context; |
191 | struct iqs62x_keys_private *iqs62x_keys; |
192 | int ret, i; |
193 | |
194 | iqs62x_keys = container_of(notifier, struct iqs62x_keys_private, |
195 | notifier); |
196 | |
197 | if (event_flags & BIT(IQS62X_EVENT_SYS_RESET)) { |
198 | ret = iqs62x_keys_init(iqs62x_keys); |
199 | if (ret) { |
200 | dev_err(iqs62x_keys->input->dev.parent, |
201 | "Failed to re-initialize device: %d\n" , ret); |
202 | return NOTIFY_BAD; |
203 | } |
204 | |
205 | return NOTIFY_OK; |
206 | } |
207 | |
208 | for (i = 0; i < iqs62x_keys->keycodemax; i++) { |
209 | if (iqs62x_events[i].reg == IQS62X_EVENT_WHEEL && |
210 | event_data->interval == iqs62x_keys->interval) |
211 | continue; |
212 | |
213 | input_report_key(dev: iqs62x_keys->input, code: iqs62x_keys->keycode[i], |
214 | value: event_flags & BIT(i)); |
215 | } |
216 | |
217 | for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) |
218 | if (iqs62x_keys->switches[i].enabled) |
219 | input_report_switch(dev: iqs62x_keys->input, |
220 | code: iqs62x_keys->switches[i].code, |
221 | value: event_flags & |
222 | BIT(iqs62x_keys->switches[i].flag)); |
223 | |
224 | input_sync(dev: iqs62x_keys->input); |
225 | |
226 | if (event_data->interval == iqs62x_keys->interval) |
227 | return NOTIFY_OK; |
228 | |
229 | /* |
230 | * Each frame contains at most one wheel event (up or down), in which |
231 | * case a complementary release cycle is emulated. |
232 | */ |
233 | if (event_flags & BIT(IQS62X_EVENT_WHEEL_UP)) { |
234 | input_report_key(dev: iqs62x_keys->input, |
235 | code: iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_UP], |
236 | value: 0); |
237 | input_sync(dev: iqs62x_keys->input); |
238 | } else if (event_flags & BIT(IQS62X_EVENT_WHEEL_DN)) { |
239 | input_report_key(dev: iqs62x_keys->input, |
240 | code: iqs62x_keys->keycode[IQS62X_EVENT_WHEEL_DN], |
241 | value: 0); |
242 | input_sync(dev: iqs62x_keys->input); |
243 | } |
244 | |
245 | iqs62x_keys->interval = event_data->interval; |
246 | |
247 | return NOTIFY_OK; |
248 | } |
249 | |
250 | static int iqs62x_keys_probe(struct platform_device *pdev) |
251 | { |
252 | struct iqs62x_core *iqs62x = dev_get_drvdata(dev: pdev->dev.parent); |
253 | struct iqs62x_keys_private *iqs62x_keys; |
254 | struct input_dev *input; |
255 | int ret, i; |
256 | |
257 | iqs62x_keys = devm_kzalloc(dev: &pdev->dev, size: sizeof(*iqs62x_keys), |
258 | GFP_KERNEL); |
259 | if (!iqs62x_keys) |
260 | return -ENOMEM; |
261 | |
262 | platform_set_drvdata(pdev, data: iqs62x_keys); |
263 | |
264 | ret = iqs62x_keys_parse_prop(pdev, iqs62x_keys); |
265 | if (ret) |
266 | return ret; |
267 | |
268 | input = devm_input_allocate_device(&pdev->dev); |
269 | if (!input) |
270 | return -ENOMEM; |
271 | |
272 | input->keycodemax = iqs62x_keys->keycodemax; |
273 | input->keycode = iqs62x_keys->keycode; |
274 | input->keycodesize = sizeof(*iqs62x_keys->keycode); |
275 | |
276 | input->name = iqs62x->dev_desc->dev_name; |
277 | input->id.bustype = BUS_I2C; |
278 | |
279 | for (i = 0; i < iqs62x_keys->keycodemax; i++) |
280 | if (iqs62x_keys->keycode[i] != KEY_RESERVED) |
281 | input_set_capability(dev: input, EV_KEY, |
282 | code: iqs62x_keys->keycode[i]); |
283 | |
284 | for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) |
285 | if (iqs62x_keys->switches[i].enabled) |
286 | input_set_capability(dev: input, EV_SW, |
287 | code: iqs62x_keys->switches[i].code); |
288 | |
289 | iqs62x_keys->iqs62x = iqs62x; |
290 | iqs62x_keys->input = input; |
291 | |
292 | ret = iqs62x_keys_init(iqs62x_keys); |
293 | if (ret) { |
294 | dev_err(&pdev->dev, "Failed to initialize device: %d\n" , ret); |
295 | return ret; |
296 | } |
297 | |
298 | ret = input_register_device(iqs62x_keys->input); |
299 | if (ret) { |
300 | dev_err(&pdev->dev, "Failed to register device: %d\n" , ret); |
301 | return ret; |
302 | } |
303 | |
304 | iqs62x_keys->notifier.notifier_call = iqs62x_keys_notifier; |
305 | ret = blocking_notifier_chain_register(nh: &iqs62x_keys->iqs62x->nh, |
306 | nb: &iqs62x_keys->notifier); |
307 | if (ret) |
308 | dev_err(&pdev->dev, "Failed to register notifier: %d\n" , ret); |
309 | |
310 | return ret; |
311 | } |
312 | |
313 | static void iqs62x_keys_remove(struct platform_device *pdev) |
314 | { |
315 | struct iqs62x_keys_private *iqs62x_keys = platform_get_drvdata(pdev); |
316 | int ret; |
317 | |
318 | ret = blocking_notifier_chain_unregister(nh: &iqs62x_keys->iqs62x->nh, |
319 | nb: &iqs62x_keys->notifier); |
320 | if (ret) |
321 | dev_err(&pdev->dev, "Failed to unregister notifier: %d\n" , ret); |
322 | } |
323 | |
324 | static struct platform_driver iqs62x_keys_platform_driver = { |
325 | .driver = { |
326 | .name = "iqs62x-keys" , |
327 | }, |
328 | .probe = iqs62x_keys_probe, |
329 | .remove_new = iqs62x_keys_remove, |
330 | }; |
331 | module_platform_driver(iqs62x_keys_platform_driver); |
332 | |
333 | MODULE_AUTHOR("Jeff LaBundy <jeff@labundy.com>" ); |
334 | MODULE_DESCRIPTION("Azoteq IQS620A/621/622/624/625 Keys and Switches" ); |
335 | MODULE_LICENSE("GPL" ); |
336 | MODULE_ALIAS("platform:iqs62x-keys" ); |
337 | |