1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Driver for buttons on GPIO lines not capable of generating interrupts |
4 | * |
5 | * Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org> |
6 | * Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com> |
7 | * |
8 | * This file was based on: /drivers/input/misc/cobalt_btns.c |
9 | * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> |
10 | * |
11 | * also was based on: /drivers/input/keyboard/gpio_keys.c |
12 | * Copyright 2005 Phil Blundell |
13 | */ |
14 | |
15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> |
17 | #include <linux/slab.h> |
18 | #include <linux/input.h> |
19 | #include <linux/ioport.h> |
20 | #include <linux/platform_device.h> |
21 | #include <linux/gpio.h> |
22 | #include <linux/gpio/consumer.h> |
23 | #include <linux/gpio_keys.h> |
24 | #include <linux/property.h> |
25 | |
26 | #define DRV_NAME "gpio-keys-polled" |
27 | |
28 | struct gpio_keys_button_data { |
29 | struct gpio_desc *gpiod; |
30 | int last_state; |
31 | int count; |
32 | int threshold; |
33 | }; |
34 | |
35 | struct gpio_keys_polled_dev { |
36 | struct input_dev *input; |
37 | struct device *dev; |
38 | const struct gpio_keys_platform_data *pdata; |
39 | unsigned long rel_axis_seen[BITS_TO_LONGS(REL_CNT)]; |
40 | unsigned long abs_axis_seen[BITS_TO_LONGS(ABS_CNT)]; |
41 | struct gpio_keys_button_data data[]; |
42 | }; |
43 | |
44 | static void gpio_keys_button_event(struct input_dev *input, |
45 | const struct gpio_keys_button *button, |
46 | int state) |
47 | { |
48 | struct gpio_keys_polled_dev *bdev = input_get_drvdata(dev: input); |
49 | unsigned int type = button->type ?: EV_KEY; |
50 | |
51 | if (type == EV_REL) { |
52 | if (state) { |
53 | input_event(dev: input, type, code: button->code, value: button->value); |
54 | __set_bit(button->code, bdev->rel_axis_seen); |
55 | } |
56 | } else if (type == EV_ABS) { |
57 | if (state) { |
58 | input_event(dev: input, type, code: button->code, value: button->value); |
59 | __set_bit(button->code, bdev->abs_axis_seen); |
60 | } |
61 | } else { |
62 | input_event(dev: input, type, code: button->code, value: state); |
63 | input_sync(dev: input); |
64 | } |
65 | } |
66 | |
67 | static void gpio_keys_polled_check_state(struct input_dev *input, |
68 | const struct gpio_keys_button *button, |
69 | struct gpio_keys_button_data *bdata) |
70 | { |
71 | int state; |
72 | |
73 | state = gpiod_get_value_cansleep(desc: bdata->gpiod); |
74 | if (state < 0) { |
75 | dev_err(input->dev.parent, |
76 | "failed to get gpio state: %d\n" , state); |
77 | } else { |
78 | gpio_keys_button_event(input, button, state); |
79 | |
80 | if (state != bdata->last_state) { |
81 | bdata->count = 0; |
82 | bdata->last_state = state; |
83 | } |
84 | } |
85 | } |
86 | |
87 | static void gpio_keys_polled_poll(struct input_dev *input) |
88 | { |
89 | struct gpio_keys_polled_dev *bdev = input_get_drvdata(dev: input); |
90 | const struct gpio_keys_platform_data *pdata = bdev->pdata; |
91 | int i; |
92 | |
93 | memset(bdev->rel_axis_seen, 0, sizeof(bdev->rel_axis_seen)); |
94 | memset(bdev->abs_axis_seen, 0, sizeof(bdev->abs_axis_seen)); |
95 | |
96 | for (i = 0; i < pdata->nbuttons; i++) { |
97 | struct gpio_keys_button_data *bdata = &bdev->data[i]; |
98 | |
99 | if (bdata->count < bdata->threshold) { |
100 | bdata->count++; |
101 | gpio_keys_button_event(input, button: &pdata->buttons[i], |
102 | state: bdata->last_state); |
103 | } else { |
104 | gpio_keys_polled_check_state(input, button: &pdata->buttons[i], |
105 | bdata); |
106 | } |
107 | } |
108 | |
109 | for_each_set_bit(i, input->relbit, REL_CNT) { |
110 | if (!test_bit(i, bdev->rel_axis_seen)) |
111 | input_event(dev: input, EV_REL, code: i, value: 0); |
112 | } |
113 | |
114 | for_each_set_bit(i, input->absbit, ABS_CNT) { |
115 | if (!test_bit(i, bdev->abs_axis_seen)) |
116 | input_event(dev: input, EV_ABS, code: i, value: 0); |
117 | } |
118 | |
119 | input_sync(dev: input); |
120 | } |
121 | |
122 | static int gpio_keys_polled_open(struct input_dev *input) |
123 | { |
124 | struct gpio_keys_polled_dev *bdev = input_get_drvdata(dev: input); |
125 | const struct gpio_keys_platform_data *pdata = bdev->pdata; |
126 | |
127 | if (pdata->enable) |
128 | pdata->enable(bdev->dev); |
129 | |
130 | return 0; |
131 | } |
132 | |
133 | static void gpio_keys_polled_close(struct input_dev *input) |
134 | { |
135 | struct gpio_keys_polled_dev *bdev = input_get_drvdata(dev: input); |
136 | const struct gpio_keys_platform_data *pdata = bdev->pdata; |
137 | |
138 | if (pdata->disable) |
139 | pdata->disable(bdev->dev); |
140 | } |
141 | |
142 | static struct gpio_keys_platform_data * |
143 | gpio_keys_polled_get_devtree_pdata(struct device *dev) |
144 | { |
145 | struct gpio_keys_platform_data *pdata; |
146 | struct gpio_keys_button *button; |
147 | struct fwnode_handle *child; |
148 | int nbuttons; |
149 | |
150 | nbuttons = device_get_child_node_count(dev); |
151 | if (nbuttons == 0) |
152 | return ERR_PTR(error: -EINVAL); |
153 | |
154 | pdata = devm_kzalloc(dev, size: sizeof(*pdata) + nbuttons * sizeof(*button), |
155 | GFP_KERNEL); |
156 | if (!pdata) |
157 | return ERR_PTR(error: -ENOMEM); |
158 | |
159 | button = (struct gpio_keys_button *)(pdata + 1); |
160 | |
161 | pdata->buttons = button; |
162 | pdata->nbuttons = nbuttons; |
163 | |
164 | pdata->rep = device_property_present(dev, propname: "autorepeat" ); |
165 | device_property_read_u32(dev, propname: "poll-interval" , val: &pdata->poll_interval); |
166 | |
167 | device_property_read_string(dev, propname: "label" , val: &pdata->name); |
168 | |
169 | device_for_each_child_node(dev, child) { |
170 | if (fwnode_property_read_u32(fwnode: child, propname: "linux,code" , |
171 | val: &button->code)) { |
172 | dev_err(dev, "button without keycode\n" ); |
173 | fwnode_handle_put(fwnode: child); |
174 | return ERR_PTR(error: -EINVAL); |
175 | } |
176 | |
177 | fwnode_property_read_string(fwnode: child, propname: "label" , val: &button->desc); |
178 | |
179 | if (fwnode_property_read_u32(fwnode: child, propname: "linux,input-type" , |
180 | val: &button->type)) |
181 | button->type = EV_KEY; |
182 | |
183 | if (fwnode_property_read_u32(fwnode: child, propname: "linux,input-value" , |
184 | val: (u32 *)&button->value)) |
185 | button->value = 1; |
186 | |
187 | button->wakeup = |
188 | fwnode_property_read_bool(fwnode: child, propname: "wakeup-source" ) || |
189 | /* legacy name */ |
190 | fwnode_property_read_bool(fwnode: child, propname: "gpio-key,wakeup" ); |
191 | |
192 | if (fwnode_property_read_u32(fwnode: child, propname: "debounce-interval" , |
193 | val: &button->debounce_interval)) |
194 | button->debounce_interval = 5; |
195 | |
196 | button++; |
197 | } |
198 | |
199 | return pdata; |
200 | } |
201 | |
202 | static void gpio_keys_polled_set_abs_params(struct input_dev *input, |
203 | const struct gpio_keys_platform_data *pdata, unsigned int code) |
204 | { |
205 | int i, min = 0, max = 0; |
206 | |
207 | for (i = 0; i < pdata->nbuttons; i++) { |
208 | const struct gpio_keys_button *button = &pdata->buttons[i]; |
209 | |
210 | if (button->type != EV_ABS || button->code != code) |
211 | continue; |
212 | |
213 | if (button->value < min) |
214 | min = button->value; |
215 | if (button->value > max) |
216 | max = button->value; |
217 | } |
218 | |
219 | input_set_abs_params(dev: input, axis: code, min, max, fuzz: 0, flat: 0); |
220 | } |
221 | |
222 | static const struct of_device_id gpio_keys_polled_of_match[] = { |
223 | { .compatible = "gpio-keys-polled" , }, |
224 | { }, |
225 | }; |
226 | MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match); |
227 | |
228 | static int gpio_keys_polled_probe(struct platform_device *pdev) |
229 | { |
230 | struct device *dev = &pdev->dev; |
231 | struct fwnode_handle *child = NULL; |
232 | const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); |
233 | struct gpio_keys_polled_dev *bdev; |
234 | struct input_dev *input; |
235 | int error; |
236 | int i; |
237 | |
238 | if (!pdata) { |
239 | pdata = gpio_keys_polled_get_devtree_pdata(dev); |
240 | if (IS_ERR(ptr: pdata)) |
241 | return PTR_ERR(ptr: pdata); |
242 | } |
243 | |
244 | if (!pdata->poll_interval) { |
245 | dev_err(dev, "missing poll_interval value\n" ); |
246 | return -EINVAL; |
247 | } |
248 | |
249 | bdev = devm_kzalloc(dev, struct_size(bdev, data, pdata->nbuttons), |
250 | GFP_KERNEL); |
251 | if (!bdev) { |
252 | dev_err(dev, "no memory for private data\n" ); |
253 | return -ENOMEM; |
254 | } |
255 | |
256 | input = devm_input_allocate_device(dev); |
257 | if (!input) { |
258 | dev_err(dev, "no memory for input device\n" ); |
259 | return -ENOMEM; |
260 | } |
261 | |
262 | input_set_drvdata(dev: input, data: bdev); |
263 | |
264 | input->name = pdata->name ?: pdev->name; |
265 | input->phys = DRV_NAME"/input0" ; |
266 | |
267 | input->id.bustype = BUS_HOST; |
268 | input->id.vendor = 0x0001; |
269 | input->id.product = 0x0001; |
270 | input->id.version = 0x0100; |
271 | |
272 | input->open = gpio_keys_polled_open; |
273 | input->close = gpio_keys_polled_close; |
274 | |
275 | __set_bit(EV_KEY, input->evbit); |
276 | if (pdata->rep) |
277 | __set_bit(EV_REP, input->evbit); |
278 | |
279 | for (i = 0; i < pdata->nbuttons; i++) { |
280 | const struct gpio_keys_button *button = &pdata->buttons[i]; |
281 | struct gpio_keys_button_data *bdata = &bdev->data[i]; |
282 | unsigned int type = button->type ?: EV_KEY; |
283 | |
284 | if (button->wakeup) { |
285 | dev_err(dev, DRV_NAME " does not support wakeup\n" ); |
286 | fwnode_handle_put(fwnode: child); |
287 | return -EINVAL; |
288 | } |
289 | |
290 | if (!dev_get_platdata(dev)) { |
291 | /* No legacy static platform data */ |
292 | child = device_get_next_child_node(dev, child); |
293 | if (!child) { |
294 | dev_err(dev, "missing child device node\n" ); |
295 | return -EINVAL; |
296 | } |
297 | |
298 | bdata->gpiod = devm_fwnode_gpiod_get(dev, fwnode: child, |
299 | NULL, flags: GPIOD_IN, |
300 | label: button->desc); |
301 | if (IS_ERR(ptr: bdata->gpiod)) { |
302 | fwnode_handle_put(fwnode: child); |
303 | return dev_err_probe(dev, err: PTR_ERR(ptr: bdata->gpiod), |
304 | fmt: "failed to get gpio\n" ); |
305 | } |
306 | } else if (gpio_is_valid(number: button->gpio)) { |
307 | /* |
308 | * Legacy GPIO number so request the GPIO here and |
309 | * convert it to descriptor. |
310 | */ |
311 | unsigned flags = GPIOF_IN; |
312 | |
313 | if (button->active_low) |
314 | flags |= GPIOF_ACTIVE_LOW; |
315 | |
316 | error = devm_gpio_request_one(dev, gpio: button->gpio, |
317 | flags, label: button->desc ? : DRV_NAME); |
318 | if (error) { |
319 | dev_err(dev, |
320 | "unable to claim gpio %u, err=%d\n" , |
321 | button->gpio, error); |
322 | return error; |
323 | } |
324 | |
325 | bdata->gpiod = gpio_to_desc(gpio: button->gpio); |
326 | if (!bdata->gpiod) { |
327 | dev_err(dev, |
328 | "unable to convert gpio %u to descriptor\n" , |
329 | button->gpio); |
330 | return -EINVAL; |
331 | } |
332 | } |
333 | |
334 | bdata->last_state = -1; |
335 | bdata->threshold = DIV_ROUND_UP(button->debounce_interval, |
336 | pdata->poll_interval); |
337 | |
338 | input_set_capability(dev: input, type, code: button->code); |
339 | if (type == EV_ABS) |
340 | gpio_keys_polled_set_abs_params(input, pdata, |
341 | code: button->code); |
342 | } |
343 | |
344 | fwnode_handle_put(fwnode: child); |
345 | |
346 | bdev->input = input; |
347 | bdev->dev = dev; |
348 | bdev->pdata = pdata; |
349 | |
350 | error = input_setup_polling(dev: input, poll_fn: gpio_keys_polled_poll); |
351 | if (error) { |
352 | dev_err(dev, "unable to set up polling, err=%d\n" , error); |
353 | return error; |
354 | } |
355 | |
356 | input_set_poll_interval(dev: input, interval: pdata->poll_interval); |
357 | |
358 | error = input_register_device(input); |
359 | if (error) { |
360 | dev_err(dev, "unable to register polled device, err=%d\n" , |
361 | error); |
362 | return error; |
363 | } |
364 | |
365 | /* report initial state of the buttons */ |
366 | for (i = 0; i < pdata->nbuttons; i++) |
367 | gpio_keys_polled_check_state(input, button: &pdata->buttons[i], |
368 | bdata: &bdev->data[i]); |
369 | |
370 | input_sync(dev: input); |
371 | |
372 | return 0; |
373 | } |
374 | |
375 | static struct platform_driver gpio_keys_polled_driver = { |
376 | .probe = gpio_keys_polled_probe, |
377 | .driver = { |
378 | .name = DRV_NAME, |
379 | .of_match_table = gpio_keys_polled_of_match, |
380 | }, |
381 | }; |
382 | module_platform_driver(gpio_keys_polled_driver); |
383 | |
384 | MODULE_LICENSE("GPL v2" ); |
385 | MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>" ); |
386 | MODULE_DESCRIPTION("Polled GPIO Buttons driver" ); |
387 | MODULE_ALIAS("platform:" DRV_NAME); |
388 | |