1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Driver for the Cirrus EP93xx matrix keypad controller.
4 *
5 * Copyright (c) 2008 H Hartley Sweeten <hsweeten@visionengravers.com>
6 *
7 * Based on the pxa27x matrix keypad controller by Rodolfo Giometti.
8 *
9 */
10
11 #include <linux/bits.h>
12 #include <linux/mod_devicetable.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/property.h>
16 #include <linux/interrupt.h>
17 #include <linux/clk.h>
18 #include <linux/io.h>
19 #include <linux/input.h>
20 #include <linux/input/matrix_keypad.h>
21 #include <linux/slab.h>
22 #include <linux/soc/cirrus/ep93xx.h>
23 #include <linux/pm_wakeirq.h>
24
25 /*
26 * Keypad Interface Register offsets
27 */
28 #define KEY_INIT 0x00 /* Key Scan Initialization register */
29 #define KEY_DIAG 0x04 /* Key Scan Diagnostic register */
30 #define KEY_REG 0x08 /* Key Value Capture register */
31
32 /* Key Scan Initialization Register bit defines */
33 #define KEY_INIT_DBNC_MASK GENMASK(23, 16)
34 #define KEY_INIT_DBNC_SHIFT 16
35 #define KEY_INIT_DIS3KY BIT(15)
36 #define KEY_INIT_DIAG BIT(14)
37 #define KEY_INIT_BACK BIT(13)
38 #define KEY_INIT_T2 BIT(12)
39 #define KEY_INIT_PRSCL_MASK GENMASK(9, 0)
40 #define KEY_INIT_PRSCL_SHIFT 0
41
42 /* Key Scan Diagnostic Register bit defines */
43 #define KEY_DIAG_MASK GENMASK(5, 0)
44 #define KEY_DIAG_SHIFT 0
45
46 /* Key Value Capture Register bit defines */
47 #define KEY_REG_K BIT(15)
48 #define KEY_REG_INT BIT(14)
49 #define KEY_REG_2KEYS BIT(13)
50 #define KEY_REG_1KEY BIT(12)
51 #define KEY_REG_KEY2_MASK GENMASK(11, 6)
52 #define KEY_REG_KEY2_SHIFT 6
53 #define KEY_REG_KEY1_MASK GENMASK(5, 0)
54 #define KEY_REG_KEY1_SHIFT 0
55
56 #define EP93XX_MATRIX_ROWS (8)
57 #define EP93XX_MATRIX_COLS (8)
58
59 #define EP93XX_MATRIX_SIZE (EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS)
60
61 struct ep93xx_keypad {
62 struct input_dev *input_dev;
63 struct clk *clk;
64 unsigned int debounce;
65 u16 prescale;
66
67 void __iomem *mmio_base;
68
69 unsigned short keycodes[EP93XX_MATRIX_SIZE];
70
71 int key1;
72 int key2;
73
74 int irq;
75
76 bool enabled;
77 };
78
ep93xx_keypad_irq_handler(int irq,void * dev_id)79 static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id)
80 {
81 struct ep93xx_keypad *keypad = dev_id;
82 struct input_dev *input_dev = keypad->input_dev;
83 unsigned int status;
84 int keycode, key1, key2;
85
86 status = __raw_readl(keypad->mmio_base + KEY_REG);
87
88 keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT;
89 key1 = keypad->keycodes[keycode];
90
91 keycode = (status & KEY_REG_KEY2_MASK) >> KEY_REG_KEY2_SHIFT;
92 key2 = keypad->keycodes[keycode];
93
94 if (status & KEY_REG_2KEYS) {
95 if (keypad->key1 && key1 != keypad->key1 && key2 != keypad->key1)
96 input_report_key(input_dev, keypad->key1, 0);
97
98 if (keypad->key2 && key1 != keypad->key2 && key2 != keypad->key2)
99 input_report_key(input_dev, keypad->key2, 0);
100
101 input_report_key(input_dev, key1, 1);
102 input_report_key(input_dev, key2, 1);
103
104 keypad->key1 = key1;
105 keypad->key2 = key2;
106
107 } else if (status & KEY_REG_1KEY) {
108 if (keypad->key1 && key1 != keypad->key1)
109 input_report_key(input_dev, keypad->key1, 0);
110
111 if (keypad->key2 && key1 != keypad->key2)
112 input_report_key(input_dev, keypad->key2, 0);
113
114 input_report_key(input_dev, key1, 1);
115
116 keypad->key1 = key1;
117 keypad->key2 = 0;
118
119 } else {
120 input_report_key(input_dev, keypad->key1, 0);
121 input_report_key(input_dev, keypad->key2, 0);
122
123 keypad->key1 = keypad->key2 = 0;
124 }
125 input_sync(input_dev);
126
127 return IRQ_HANDLED;
128 }
129
ep93xx_keypad_config(struct ep93xx_keypad * keypad)130 static void ep93xx_keypad_config(struct ep93xx_keypad *keypad)
131 {
132 unsigned int val = 0;
133
134 val |= (keypad->debounce << KEY_INIT_DBNC_SHIFT) & KEY_INIT_DBNC_MASK;
135
136 val |= (keypad->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK;
137
138 __raw_writel(val, keypad->mmio_base + KEY_INIT);
139 }
140
ep93xx_keypad_open(struct input_dev * pdev)141 static int ep93xx_keypad_open(struct input_dev *pdev)
142 {
143 struct ep93xx_keypad *keypad = input_get_drvdata(pdev);
144
145 if (!keypad->enabled) {
146 ep93xx_keypad_config(keypad);
147 clk_prepare_enable(keypad->clk);
148 keypad->enabled = true;
149 }
150
151 return 0;
152 }
153
ep93xx_keypad_close(struct input_dev * pdev)154 static void ep93xx_keypad_close(struct input_dev *pdev)
155 {
156 struct ep93xx_keypad *keypad = input_get_drvdata(pdev);
157
158 if (keypad->enabled) {
159 clk_disable_unprepare(keypad->clk);
160 keypad->enabled = false;
161 }
162 }
163
164
ep93xx_keypad_suspend(struct device * dev)165 static int ep93xx_keypad_suspend(struct device *dev)
166 {
167 struct platform_device *pdev = to_platform_device(dev);
168 struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
169 struct input_dev *input_dev = keypad->input_dev;
170
171 guard(mutex)(&input_dev->mutex);
172
173 if (keypad->enabled) {
174 clk_disable(keypad->clk);
175 keypad->enabled = false;
176 }
177
178 return 0;
179 }
180
ep93xx_keypad_resume(struct device * dev)181 static int ep93xx_keypad_resume(struct device *dev)
182 {
183 struct platform_device *pdev = to_platform_device(dev);
184 struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
185 struct input_dev *input_dev = keypad->input_dev;
186
187 guard(mutex)(&input_dev->mutex);
188
189 if (input_device_enabled(input_dev)) {
190 if (!keypad->enabled) {
191 ep93xx_keypad_config(keypad);
192 clk_enable(keypad->clk);
193 keypad->enabled = true;
194 }
195 }
196
197 return 0;
198 }
199
200 static DEFINE_SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops,
201 ep93xx_keypad_suspend, ep93xx_keypad_resume);
202
ep93xx_keypad_probe(struct platform_device * pdev)203 static int ep93xx_keypad_probe(struct platform_device *pdev)
204 {
205 struct device *dev = &pdev->dev;
206 struct ep93xx_keypad *keypad;
207 struct input_dev *input_dev;
208 int err;
209
210 keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL);
211 if (!keypad)
212 return -ENOMEM;
213
214 keypad->irq = platform_get_irq(pdev, 0);
215 if (keypad->irq < 0)
216 return keypad->irq;
217
218 keypad->mmio_base = devm_platform_ioremap_resource(pdev, 0);
219 if (IS_ERR(keypad->mmio_base))
220 return PTR_ERR(keypad->mmio_base);
221
222 keypad->clk = devm_clk_get(&pdev->dev, NULL);
223 if (IS_ERR(keypad->clk))
224 return PTR_ERR(keypad->clk);
225
226 device_property_read_u32(dev, "debounce-delay-ms", &keypad->debounce);
227 device_property_read_u16(dev, "cirrus,prescale", &keypad->prescale);
228
229 input_dev = devm_input_allocate_device(&pdev->dev);
230 if (!input_dev)
231 return -ENOMEM;
232
233 keypad->input_dev = input_dev;
234
235 input_dev->name = pdev->name;
236 input_dev->id.bustype = BUS_HOST;
237 input_dev->open = ep93xx_keypad_open;
238 input_dev->close = ep93xx_keypad_close;
239
240 err = matrix_keypad_build_keymap(NULL, NULL,
241 EP93XX_MATRIX_ROWS, EP93XX_MATRIX_COLS,
242 keypad->keycodes, input_dev);
243 if (err)
244 return err;
245
246 if (device_property_read_bool(&pdev->dev, "autorepeat"))
247 __set_bit(EV_REP, input_dev->evbit);
248 input_set_drvdata(input_dev, keypad);
249
250 err = devm_request_irq(&pdev->dev, keypad->irq,
251 ep93xx_keypad_irq_handler,
252 0, pdev->name, keypad);
253 if (err)
254 return err;
255
256 err = input_register_device(input_dev);
257 if (err)
258 return err;
259
260 platform_set_drvdata(pdev, keypad);
261
262 device_init_wakeup(&pdev->dev, 1);
263 err = dev_pm_set_wake_irq(&pdev->dev, keypad->irq);
264 if (err)
265 dev_warn(&pdev->dev, "failed to set up wakeup irq: %d\n", err);
266
267 return 0;
268 }
269
ep93xx_keypad_remove(struct platform_device * pdev)270 static void ep93xx_keypad_remove(struct platform_device *pdev)
271 {
272 dev_pm_clear_wake_irq(&pdev->dev);
273 }
274
275 static const struct of_device_id ep93xx_keypad_of_ids[] = {
276 { .compatible = "cirrus,ep9307-keypad" },
277 { /* sentinel */ }
278 };
279 MODULE_DEVICE_TABLE(of, ep93xx_keypad_of_ids);
280
281 static struct platform_driver ep93xx_keypad_driver = {
282 .driver = {
283 .name = "ep93xx-keypad",
284 .pm = pm_sleep_ptr(&ep93xx_keypad_pm_ops),
285 .of_match_table = ep93xx_keypad_of_ids,
286 },
287 .probe = ep93xx_keypad_probe,
288 .remove = ep93xx_keypad_remove,
289 };
290 module_platform_driver(ep93xx_keypad_driver);
291
292 MODULE_LICENSE("GPL");
293 MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
294 MODULE_DESCRIPTION("EP93xx Matrix Keypad Controller");
295 MODULE_ALIAS("platform:ep93xx-keypad");
296