1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright 2025 Bootlin
4 *
5 * Author: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
6 */
7
8 #include <linux/bitfield.h>
9 #include <linux/bitops.h>
10 #include <linux/dev_printk.h>
11 #include <linux/device/devres.h>
12 #include <linux/err.h>
13 #include <linux/init.h>
14 #include <linux/input.h>
15 #include <linux/input/matrix_keypad.h>
16 #include <linux/interrupt.h>
17 #include <linux/mfd/max7360.h>
18 #include <linux/minmax.h>
19 #include <linux/module.h>
20 #include <linux/property.h>
21 #include <linux/platform_device.h>
22 #include <linux/pm_wakeirq.h>
23 #include <linux/regmap.h>
24
25 struct max7360_keypad {
26 struct input_dev *input;
27 unsigned int rows;
28 unsigned int cols;
29 unsigned int debounce_ms;
30 int irq;
31 struct regmap *regmap;
32 unsigned short keycodes[MAX7360_MAX_KEY_ROWS * MAX7360_MAX_KEY_COLS];
33 };
34
max7360_keypad_irq(int irq,void * data)35 static irqreturn_t max7360_keypad_irq(int irq, void *data)
36 {
37 struct max7360_keypad *max7360_keypad = data;
38 struct device *dev = max7360_keypad->input->dev.parent;
39 unsigned int val;
40 unsigned int row, col;
41 unsigned int release;
42 unsigned int code;
43 int error;
44
45 error = regmap_read(max7360_keypad->regmap, MAX7360_REG_KEYFIFO, &val);
46 if (error) {
47 dev_err(dev, "Failed to read MAX7360 FIFO");
48 return IRQ_NONE;
49 }
50
51 /* FIFO overflow: ignore it and get next event. */
52 if (val == MAX7360_FIFO_OVERFLOW) {
53 dev_warn(dev, "max7360 FIFO overflow");
54 error = regmap_read_poll_timeout(max7360_keypad->regmap, MAX7360_REG_KEYFIFO,
55 val, val != MAX7360_FIFO_OVERFLOW, 0, 1000);
56 if (error) {
57 dev_err(dev, "Failed to empty MAX7360 FIFO");
58 return IRQ_NONE;
59 }
60 }
61
62 if (val == MAX7360_FIFO_EMPTY) {
63 dev_dbg(dev, "Got a spurious interrupt");
64
65 return IRQ_NONE;
66 }
67
68 row = FIELD_GET(MAX7360_FIFO_ROW, val);
69 col = FIELD_GET(MAX7360_FIFO_COL, val);
70 release = val & MAX7360_FIFO_RELEASE;
71
72 code = MATRIX_SCAN_CODE(row, col, get_count_order(max7360_keypad->cols));
73
74 dev_dbg(dev, "key[%d:%d] %s\n", row, col, release ? "release" : "press");
75
76 input_event(max7360_keypad->input, EV_MSC, MSC_SCAN, code);
77 input_report_key(max7360_keypad->input, max7360_keypad->keycodes[code], !release);
78 input_sync(max7360_keypad->input);
79
80 return IRQ_HANDLED;
81 }
82
max7360_keypad_open(struct input_dev * pdev)83 static int max7360_keypad_open(struct input_dev *pdev)
84 {
85 struct max7360_keypad *max7360_keypad = input_get_drvdata(pdev);
86 struct device *dev = max7360_keypad->input->dev.parent;
87 int error;
88
89 /* Somebody is using the device: get out of sleep. */
90 error = regmap_write_bits(max7360_keypad->regmap, MAX7360_REG_CONFIG,
91 MAX7360_CFG_SLEEP, MAX7360_CFG_SLEEP);
92 if (error)
93 dev_err(dev, "Failed to write max7360 configuration: %d\n", error);
94
95 return error;
96 }
97
max7360_keypad_close(struct input_dev * pdev)98 static void max7360_keypad_close(struct input_dev *pdev)
99 {
100 struct max7360_keypad *max7360_keypad = input_get_drvdata(pdev);
101 struct device *dev = max7360_keypad->input->dev.parent;
102 int error;
103
104 /* Nobody is using the device anymore: go to sleep. */
105 error = regmap_write_bits(max7360_keypad->regmap, MAX7360_REG_CONFIG, MAX7360_CFG_SLEEP, 0);
106 if (error)
107 dev_err(dev, "Failed to write max7360 configuration: %d\n", error);
108 }
109
max7360_keypad_hw_init(struct max7360_keypad * max7360_keypad)110 static int max7360_keypad_hw_init(struct max7360_keypad *max7360_keypad)
111 {
112 struct device *dev = max7360_keypad->input->dev.parent;
113 unsigned int val;
114 int error;
115
116 val = max7360_keypad->debounce_ms - MAX7360_DEBOUNCE_MIN;
117 error = regmap_write_bits(max7360_keypad->regmap, MAX7360_REG_DEBOUNCE,
118 MAX7360_DEBOUNCE,
119 FIELD_PREP(MAX7360_DEBOUNCE, val));
120 if (error)
121 return dev_err_probe(dev, error,
122 "Failed to write max7360 debounce configuration\n");
123
124 error = regmap_write_bits(max7360_keypad->regmap, MAX7360_REG_INTERRUPT,
125 MAX7360_INTERRUPT_TIME_MASK,
126 FIELD_PREP(MAX7360_INTERRUPT_TIME_MASK, 1));
127 if (error)
128 return dev_err_probe(dev, error,
129 "Failed to write max7360 keypad interrupt configuration\n");
130
131 return 0;
132 }
133
max7360_keypad_build_keymap(struct max7360_keypad * max7360_keypad)134 static int max7360_keypad_build_keymap(struct max7360_keypad *max7360_keypad)
135 {
136 struct input_dev *input_dev = max7360_keypad->input;
137 struct device *dev = input_dev->dev.parent->parent;
138 struct matrix_keymap_data keymap_data;
139 const char *propname = "linux,keymap";
140 unsigned int max_keys;
141 int error;
142 int size;
143
144 size = device_property_count_u32(dev, propname);
145 if (size <= 0) {
146 dev_err(dev, "missing or malformed property %s: %d\n", propname, size);
147 return size < 0 ? size : -EINVAL;
148 }
149
150 max_keys = max7360_keypad->cols * max7360_keypad->rows;
151 if (size > max_keys) {
152 dev_err(dev, "%s size overflow (%d vs max %u)\n", propname, size, max_keys);
153 return -EINVAL;
154 }
155
156 u32 *keys __free(kfree) = kmalloc_array(size, sizeof(*keys), GFP_KERNEL);
157 if (!keys)
158 return -ENOMEM;
159
160 error = device_property_read_u32_array(dev, propname, keys, size);
161 if (error) {
162 dev_err(dev, "failed to read %s property: %d\n", propname, error);
163 return error;
164 }
165
166 keymap_data.keymap = keys;
167 keymap_data.keymap_size = size;
168 error = matrix_keypad_build_keymap(&keymap_data, NULL,
169 max7360_keypad->rows, max7360_keypad->cols,
170 max7360_keypad->keycodes, max7360_keypad->input);
171 if (error)
172 return error;
173
174 return 0;
175 }
176
max7360_keypad_parse_fw(struct device * dev,struct max7360_keypad * max7360_keypad,bool * autorepeat)177 static int max7360_keypad_parse_fw(struct device *dev,
178 struct max7360_keypad *max7360_keypad,
179 bool *autorepeat)
180 {
181 int error;
182
183 error = matrix_keypad_parse_properties(dev->parent, &max7360_keypad->rows,
184 &max7360_keypad->cols);
185 if (error)
186 return error;
187
188 if (!max7360_keypad->rows || !max7360_keypad->cols ||
189 max7360_keypad->rows > MAX7360_MAX_KEY_ROWS ||
190 max7360_keypad->cols > MAX7360_MAX_KEY_COLS) {
191 dev_err(dev, "Invalid number of columns or rows (%ux%u)\n",
192 max7360_keypad->cols, max7360_keypad->rows);
193 return -EINVAL;
194 }
195
196 *autorepeat = device_property_read_bool(dev->parent, "autorepeat");
197
198 max7360_keypad->debounce_ms = MAX7360_DEBOUNCE_MIN;
199 error = device_property_read_u32(dev->parent, "keypad-debounce-delay-ms",
200 &max7360_keypad->debounce_ms);
201 if (error == -EINVAL) {
202 dev_info(dev, "Using default keypad-debounce-delay-ms: %u\n",
203 max7360_keypad->debounce_ms);
204 } else if (error < 0) {
205 dev_err(dev, "Failed to read keypad-debounce-delay-ms property\n");
206 return error;
207 }
208
209 if (!in_range(max7360_keypad->debounce_ms, MAX7360_DEBOUNCE_MIN,
210 MAX7360_DEBOUNCE_MAX - MAX7360_DEBOUNCE_MIN + 1)) {
211 dev_err(dev, "Invalid keypad-debounce-delay-ms: %u, should be between %u and %u.\n",
212 max7360_keypad->debounce_ms, MAX7360_DEBOUNCE_MIN, MAX7360_DEBOUNCE_MAX);
213 return -EINVAL;
214 }
215
216 return 0;
217 }
218
max7360_keypad_probe(struct platform_device * pdev)219 static int max7360_keypad_probe(struct platform_device *pdev)
220 {
221 struct max7360_keypad *max7360_keypad;
222 struct device *dev = &pdev->dev;
223 struct input_dev *input;
224 struct regmap *regmap;
225 bool autorepeat;
226 int error;
227 int irq;
228
229 regmap = dev_get_regmap(dev->parent, NULL);
230 if (!regmap)
231 return dev_err_probe(dev, -ENODEV, "Could not get parent regmap\n");
232
233 irq = fwnode_irq_get_byname(dev_fwnode(dev->parent), "intk");
234 if (irq < 0)
235 return dev_err_probe(dev, irq, "Failed to get IRQ\n");
236
237 max7360_keypad = devm_kzalloc(dev, sizeof(*max7360_keypad), GFP_KERNEL);
238 if (!max7360_keypad)
239 return -ENOMEM;
240
241 max7360_keypad->regmap = regmap;
242
243 error = max7360_keypad_parse_fw(dev, max7360_keypad, &autorepeat);
244 if (error)
245 return error;
246
247 input = devm_input_allocate_device(dev);
248 if (!input)
249 return -ENOMEM;
250
251 max7360_keypad->input = input;
252
253 input->id.bustype = BUS_I2C;
254 input->name = pdev->name;
255 input->open = max7360_keypad_open;
256 input->close = max7360_keypad_close;
257
258 error = max7360_keypad_build_keymap(max7360_keypad);
259 if (error)
260 return dev_err_probe(dev, error, "Failed to build keymap\n");
261
262 input_set_capability(input, EV_MSC, MSC_SCAN);
263 if (autorepeat)
264 __set_bit(EV_REP, input->evbit);
265
266 input_set_drvdata(input, max7360_keypad);
267
268 error = devm_request_threaded_irq(dev, irq, NULL, max7360_keypad_irq,
269 IRQF_ONESHOT,
270 "max7360-keypad", max7360_keypad);
271 if (error)
272 return dev_err_probe(dev, error, "Failed to register interrupt\n");
273
274 error = input_register_device(input);
275 if (error)
276 return dev_err_probe(dev, error, "Could not register input device\n");
277
278 error = max7360_keypad_hw_init(max7360_keypad);
279 if (error)
280 return dev_err_probe(dev, error, "Failed to initialize max7360 keypad\n");
281
282 device_init_wakeup(dev, true);
283 error = dev_pm_set_wake_irq(dev, irq);
284 if (error)
285 dev_warn(dev, "Failed to set up wakeup irq: %d\n", error);
286
287 return 0;
288 }
289
max7360_keypad_remove(struct platform_device * pdev)290 static void max7360_keypad_remove(struct platform_device *pdev)
291 {
292 dev_pm_clear_wake_irq(&pdev->dev);
293 device_init_wakeup(&pdev->dev, false);
294 }
295
296 static struct platform_driver max7360_keypad_driver = {
297 .driver = {
298 .name = "max7360-keypad",
299 },
300 .probe = max7360_keypad_probe,
301 .remove = max7360_keypad_remove,
302 };
303 module_platform_driver(max7360_keypad_driver);
304
305 MODULE_DESCRIPTION("MAX7360 Keypad driver");
306 MODULE_AUTHOR("Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>");
307 MODULE_LICENSE("GPL");
308