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