xref: /linux/drivers/input/keyboard/ep93xx_keypad.c (revision 566ab427f827b0256d3e8ce0235d088e6a9c28bd)
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 
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 
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 
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 
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 
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 	mutex_lock(&input_dev->mutex);
172 
173 	if (keypad->enabled) {
174 		clk_disable(keypad->clk);
175 		keypad->enabled = false;
176 	}
177 
178 	mutex_unlock(&input_dev->mutex);
179 
180 	return 0;
181 }
182 
183 static int ep93xx_keypad_resume(struct device *dev)
184 {
185 	struct platform_device *pdev = to_platform_device(dev);
186 	struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
187 	struct input_dev *input_dev = keypad->input_dev;
188 
189 	mutex_lock(&input_dev->mutex);
190 
191 	if (input_device_enabled(input_dev)) {
192 		if (!keypad->enabled) {
193 			ep93xx_keypad_config(keypad);
194 			clk_enable(keypad->clk);
195 			keypad->enabled = true;
196 		}
197 	}
198 
199 	mutex_unlock(&input_dev->mutex);
200 
201 	return 0;
202 }
203 
204 static DEFINE_SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops,
205 				ep93xx_keypad_suspend, ep93xx_keypad_resume);
206 
207 static int ep93xx_keypad_probe(struct platform_device *pdev)
208 {
209 	struct device *dev = &pdev->dev;
210 	struct ep93xx_keypad *keypad;
211 	struct input_dev *input_dev;
212 	int err;
213 
214 	keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL);
215 	if (!keypad)
216 		return -ENOMEM;
217 
218 	keypad->irq = platform_get_irq(pdev, 0);
219 	if (keypad->irq < 0)
220 		return keypad->irq;
221 
222 	keypad->mmio_base = devm_platform_ioremap_resource(pdev, 0);
223 	if (IS_ERR(keypad->mmio_base))
224 		return PTR_ERR(keypad->mmio_base);
225 
226 	keypad->clk = devm_clk_get(&pdev->dev, NULL);
227 	if (IS_ERR(keypad->clk))
228 		return PTR_ERR(keypad->clk);
229 
230 	device_property_read_u32(dev, "debounce-delay-ms", &keypad->debounce);
231 	device_property_read_u16(dev, "cirrus,prescale", &keypad->prescale);
232 
233 	input_dev = devm_input_allocate_device(&pdev->dev);
234 	if (!input_dev)
235 		return -ENOMEM;
236 
237 	keypad->input_dev = input_dev;
238 
239 	input_dev->name = pdev->name;
240 	input_dev->id.bustype = BUS_HOST;
241 	input_dev->open = ep93xx_keypad_open;
242 	input_dev->close = ep93xx_keypad_close;
243 
244 	err = matrix_keypad_build_keymap(NULL, NULL,
245 					 EP93XX_MATRIX_ROWS, EP93XX_MATRIX_COLS,
246 					 keypad->keycodes, input_dev);
247 	if (err)
248 		return err;
249 
250 	if (device_property_read_bool(&pdev->dev, "autorepeat"))
251 		__set_bit(EV_REP, input_dev->evbit);
252 	input_set_drvdata(input_dev, keypad);
253 
254 	err = devm_request_irq(&pdev->dev, keypad->irq,
255 			       ep93xx_keypad_irq_handler,
256 			       0, pdev->name, keypad);
257 	if (err)
258 		return err;
259 
260 	err = input_register_device(input_dev);
261 	if (err)
262 		return err;
263 
264 	platform_set_drvdata(pdev, keypad);
265 
266 	device_init_wakeup(&pdev->dev, 1);
267 	err = dev_pm_set_wake_irq(&pdev->dev, keypad->irq);
268 	if (err)
269 		dev_warn(&pdev->dev, "failed to set up wakeup irq: %d\n", err);
270 
271 	return 0;
272 }
273 
274 static void ep93xx_keypad_remove(struct platform_device *pdev)
275 {
276 	dev_pm_clear_wake_irq(&pdev->dev);
277 }
278 
279 static const struct of_device_id ep93xx_keypad_of_ids[] = {
280 	{ .compatible = "cirrus,ep9307-keypad" },
281 	{ /* sentinel */ }
282 };
283 MODULE_DEVICE_TABLE(of, ep93xx_keypad_of_ids);
284 
285 static struct platform_driver ep93xx_keypad_driver = {
286 	.driver		= {
287 		.name	= "ep93xx-keypad",
288 		.pm	= pm_sleep_ptr(&ep93xx_keypad_pm_ops),
289 		.of_match_table = ep93xx_keypad_of_ids,
290 	},
291 	.probe		= ep93xx_keypad_probe,
292 	.remove_new	= ep93xx_keypad_remove,
293 };
294 module_platform_driver(ep93xx_keypad_driver);
295 
296 MODULE_LICENSE("GPL");
297 MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
298 MODULE_DESCRIPTION("EP93xx Matrix Keypad Controller");
299 MODULE_ALIAS("platform:ep93xx-keypad");
300