Commit | Line | Data |
---|---|---|
6af6dc2d SG |
1 | /* |
2 | * ChromeOS EC keyboard driver | |
3 | * | |
4 | * Copyright (C) 2012 Google, Inc | |
5 | * | |
6 | * This software is licensed under the terms of the GNU General Public | |
7 | * License version 2, as published by the Free Software Foundation, and | |
8 | * may be copied, distributed, and modified under those terms. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * This driver uses the Chrome OS EC byte-level message-based protocol for | |
16 | * communicating the keyboard state (which keys are pressed) from a keyboard EC | |
17 | * to the AP over some bus (such as i2c, lpc, spi). The EC does debouncing, | |
18 | * but everything else (including deghosting) is done here. The main | |
19 | * motivation for this is to keep the EC firmware as simple as possible, since | |
20 | * it cannot be easily upgraded and EC flash/IRAM space is relatively | |
21 | * expensive. | |
22 | */ | |
23 | ||
24 | #include <linux/module.h> | |
017f14e8 | 25 | #include <linux/bitops.h> |
6af6dc2d SG |
26 | #include <linux/i2c.h> |
27 | #include <linux/input.h> | |
d1fd345e | 28 | #include <linux/interrupt.h> |
6af6dc2d | 29 | #include <linux/kernel.h> |
6af6dc2d SG |
30 | #include <linux/platform_device.h> |
31 | #include <linux/slab.h> | |
32 | #include <linux/input/matrix_keypad.h> | |
33 | #include <linux/mfd/cros_ec.h> | |
34 | #include <linux/mfd/cros_ec_commands.h> | |
35 | ||
36 | /* | |
37 | * @rows: Number of rows in the keypad | |
38 | * @cols: Number of columns in the keypad | |
39 | * @row_shift: log2 or number of rows, rounded up | |
40 | * @keymap_data: Matrix keymap data used to convert to keyscan values | |
41 | * @ghost_filter: true to enable the matrix key-ghosting filter | |
017f14e8 | 42 | * @valid_keys: bitmap of existing keys for each matrix column |
64757eba | 43 | * @old_kb_state: bitmap of keys pressed last scan |
6af6dc2d SG |
44 | * @dev: Device pointer |
45 | * @idev: Input device | |
46 | * @ec: Top level ChromeOS device to use to talk to EC | |
6af6dc2d SG |
47 | */ |
48 | struct cros_ec_keyb { | |
49 | unsigned int rows; | |
50 | unsigned int cols; | |
51 | int row_shift; | |
52 | const struct matrix_keymap_data *keymap_data; | |
53 | bool ghost_filter; | |
017f14e8 | 54 | uint8_t *valid_keys; |
64757eba | 55 | uint8_t *old_kb_state; |
6af6dc2d SG |
56 | |
57 | struct device *dev; | |
58 | struct input_dev *idev; | |
59 | struct cros_ec_device *ec; | |
6af6dc2d SG |
60 | }; |
61 | ||
62 | ||
6af6dc2d SG |
63 | /* |
64 | * Returns true when there is at least one combination of pressed keys that | |
65 | * results in ghosting. | |
66 | */ | |
67 | static bool cros_ec_keyb_has_ghosting(struct cros_ec_keyb *ckdev, uint8_t *buf) | |
68 | { | |
017f14e8 TB |
69 | int col1, col2, buf1, buf2; |
70 | struct device *dev = ckdev->dev; | |
71 | uint8_t *valid_keys = ckdev->valid_keys; | |
6af6dc2d SG |
72 | |
73 | /* | |
74 | * Ghosting happens if for any pressed key X there are other keys | |
75 | * pressed both in the same row and column of X as, for instance, | |
76 | * in the following diagram: | |
77 | * | |
78 | * . . Y . g . | |
79 | * . . . . . . | |
80 | * . . . . . . | |
81 | * . . X . Z . | |
82 | * | |
83 | * In this case only X, Y, and Z are pressed, but g appears to be | |
84 | * pressed too (see Wikipedia). | |
6af6dc2d | 85 | */ |
017f14e8 TB |
86 | for (col1 = 0; col1 < ckdev->cols; col1++) { |
87 | buf1 = buf[col1] & valid_keys[col1]; | |
88 | for (col2 = col1 + 1; col2 < ckdev->cols; col2++) { | |
89 | buf2 = buf[col2] & valid_keys[col2]; | |
90 | if (hweight8(buf1 & buf2) > 1) { | |
91 | dev_dbg(dev, "ghost found at: B[%02d]:0x%02x & B[%02d]:0x%02x", | |
92 | col1, buf1, col2, buf2); | |
93 | return true; | |
94 | } | |
95 | } | |
96 | } | |
6af6dc2d SG |
97 | |
98 | return false; | |
99 | } | |
100 | ||
017f14e8 | 101 | |
6af6dc2d SG |
102 | /* |
103 | * Compares the new keyboard state to the old one and produces key | |
104 | * press/release events accordingly. The keyboard state is 13 bytes (one byte | |
105 | * per column) | |
106 | */ | |
107 | static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev, | |
108 | uint8_t *kb_state, int len) | |
109 | { | |
110 | struct input_dev *idev = ckdev->idev; | |
111 | int col, row; | |
112 | int new_state; | |
64757eba | 113 | int old_state; |
6af6dc2d SG |
114 | int num_cols; |
115 | ||
116 | num_cols = len; | |
117 | ||
118 | if (ckdev->ghost_filter && cros_ec_keyb_has_ghosting(ckdev, kb_state)) { | |
119 | /* | |
120 | * Simple-minded solution: ignore this state. The obvious | |
121 | * improvement is to only ignore changes to keys involved in | |
122 | * the ghosting, but process the other changes. | |
123 | */ | |
124 | dev_dbg(ckdev->dev, "ghosting found\n"); | |
125 | return; | |
126 | } | |
127 | ||
128 | for (col = 0; col < ckdev->cols; col++) { | |
129 | for (row = 0; row < ckdev->rows; row++) { | |
130 | int pos = MATRIX_SCAN_CODE(row, col, ckdev->row_shift); | |
131 | const unsigned short *keycodes = idev->keycode; | |
6af6dc2d | 132 | |
6af6dc2d | 133 | new_state = kb_state[col] & (1 << row); |
64757eba DA |
134 | old_state = ckdev->old_kb_state[col] & (1 << row); |
135 | if (new_state != old_state) { | |
6af6dc2d SG |
136 | dev_dbg(ckdev->dev, |
137 | "changed: [r%d c%d]: byte %02x\n", | |
138 | row, col, new_state); | |
139 | ||
64757eba DA |
140 | input_report_key(idev, keycodes[pos], |
141 | new_state); | |
6af6dc2d SG |
142 | } |
143 | } | |
64757eba | 144 | ckdev->old_kb_state[col] = kb_state[col]; |
6af6dc2d SG |
145 | } |
146 | input_sync(ckdev->idev); | |
147 | } | |
148 | ||
6af6dc2d SG |
149 | static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state) |
150 | { | |
a8411784 JMC |
151 | int ret = 0; |
152 | struct cros_ec_command *msg; | |
153 | ||
154 | msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL); | |
155 | if (!msg) | |
156 | return -ENOMEM; | |
157 | ||
158 | msg->version = 0; | |
159 | msg->command = EC_CMD_MKBP_STATE; | |
160 | msg->insize = ckdev->cols; | |
161 | msg->outsize = 0; | |
162 | ||
163 | ret = cros_ec_cmd_xfer(ckdev->ec, msg); | |
164 | if (ret < 0) { | |
165 | dev_err(ckdev->dev, "Error transferring EC message %d\n", ret); | |
166 | goto exit; | |
167 | } | |
1b84f2a4 | 168 | |
a8411784 JMC |
169 | memcpy(kb_state, msg->data, ckdev->cols); |
170 | exit: | |
171 | kfree(msg); | |
172 | return ret; | |
6af6dc2d SG |
173 | } |
174 | ||
d1fd345e | 175 | static irqreturn_t cros_ec_keyb_irq(int irq, void *data) |
6af6dc2d | 176 | { |
d1fd345e AB |
177 | struct cros_ec_keyb *ckdev = data; |
178 | struct cros_ec_device *ec = ckdev->ec; | |
6af6dc2d | 179 | int ret; |
6af6dc2d SG |
180 | uint8_t kb_state[ckdev->cols]; |
181 | ||
d1fd345e AB |
182 | if (device_may_wakeup(ec->dev)) |
183 | pm_wakeup_event(ec->dev, 0); | |
184 | ||
6af6dc2d SG |
185 | ret = cros_ec_keyb_get_state(ckdev, kb_state); |
186 | if (ret >= 0) | |
187 | cros_ec_keyb_process(ckdev, kb_state, ret); | |
d1fd345e AB |
188 | else |
189 | dev_err(ec->dev, "failed to get keyboard state: %d\n", ret); | |
6af6dc2d | 190 | |
d1fd345e AB |
191 | return IRQ_HANDLED; |
192 | } | |
193 | ||
194 | static int cros_ec_keyb_open(struct input_dev *dev) | |
195 | { | |
196 | struct cros_ec_keyb *ckdev = input_get_drvdata(dev); | |
197 | struct cros_ec_device *ec = ckdev->ec; | |
198 | ||
199 | return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq, | |
200 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | |
201 | "cros_ec_keyb", ckdev); | |
202 | } | |
203 | ||
204 | static void cros_ec_keyb_close(struct input_dev *dev) | |
205 | { | |
206 | struct cros_ec_keyb *ckdev = input_get_drvdata(dev); | |
207 | struct cros_ec_device *ec = ckdev->ec; | |
208 | ||
209 | free_irq(ec->irq, ckdev); | |
6af6dc2d SG |
210 | } |
211 | ||
017f14e8 TB |
212 | /* |
213 | * Walks keycodes flipping bit in buffer COLUMNS deep where bit is ROW. Used by | |
214 | * ghosting logic to ignore NULL or virtual keys. | |
215 | */ | |
216 | static void cros_ec_keyb_compute_valid_keys(struct cros_ec_keyb *ckdev) | |
217 | { | |
218 | int row, col; | |
219 | int row_shift = ckdev->row_shift; | |
220 | unsigned short *keymap = ckdev->idev->keycode; | |
221 | unsigned short code; | |
222 | ||
223 | BUG_ON(ckdev->idev->keycodesize != sizeof(*keymap)); | |
224 | ||
225 | for (col = 0; col < ckdev->cols; col++) { | |
226 | for (row = 0; row < ckdev->rows; row++) { | |
227 | code = keymap[MATRIX_SCAN_CODE(row, col, row_shift)]; | |
228 | if (code && (code != KEY_BATTERY)) | |
229 | ckdev->valid_keys[col] |= 1 << row; | |
230 | } | |
231 | dev_dbg(ckdev->dev, "valid_keys[%02d] = 0x%02x\n", | |
232 | col, ckdev->valid_keys[col]); | |
233 | } | |
234 | } | |
235 | ||
6af6dc2d SG |
236 | static int cros_ec_keyb_probe(struct platform_device *pdev) |
237 | { | |
238 | struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); | |
239 | struct device *dev = ec->dev; | |
240 | struct cros_ec_keyb *ckdev; | |
241 | struct input_dev *idev; | |
242 | struct device_node *np; | |
243 | int err; | |
244 | ||
245 | np = pdev->dev.of_node; | |
246 | if (!np) | |
247 | return -ENODEV; | |
248 | ||
249 | ckdev = devm_kzalloc(&pdev->dev, sizeof(*ckdev), GFP_KERNEL); | |
250 | if (!ckdev) | |
251 | return -ENOMEM; | |
252 | err = matrix_keypad_parse_of_params(&pdev->dev, &ckdev->rows, | |
253 | &ckdev->cols); | |
254 | if (err) | |
255 | return err; | |
017f14e8 TB |
256 | |
257 | ckdev->valid_keys = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL); | |
258 | if (!ckdev->valid_keys) | |
259 | return -ENOMEM; | |
260 | ||
64757eba DA |
261 | ckdev->old_kb_state = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL); |
262 | if (!ckdev->old_kb_state) | |
263 | return -ENOMEM; | |
6af6dc2d SG |
264 | |
265 | idev = devm_input_allocate_device(&pdev->dev); | |
266 | if (!idev) | |
267 | return -ENOMEM; | |
268 | ||
d1fd345e AB |
269 | if (!ec->irq) { |
270 | dev_err(dev, "no EC IRQ specified\n"); | |
271 | return -EINVAL; | |
272 | } | |
273 | ||
6af6dc2d | 274 | ckdev->ec = ec; |
6af6dc2d SG |
275 | ckdev->dev = dev; |
276 | dev_set_drvdata(&pdev->dev, ckdev); | |
277 | ||
57b33ff0 | 278 | idev->name = CROS_EC_DEV_NAME; |
6af6dc2d SG |
279 | idev->phys = ec->phys_name; |
280 | __set_bit(EV_REP, idev->evbit); | |
281 | ||
282 | idev->id.bustype = BUS_VIRTUAL; | |
283 | idev->id.version = 1; | |
284 | idev->id.product = 0; | |
285 | idev->dev.parent = &pdev->dev; | |
286 | idev->open = cros_ec_keyb_open; | |
287 | idev->close = cros_ec_keyb_close; | |
288 | ||
289 | ckdev->ghost_filter = of_property_read_bool(np, | |
290 | "google,needs-ghost-filter"); | |
291 | ||
292 | err = matrix_keypad_build_keymap(NULL, NULL, ckdev->rows, ckdev->cols, | |
293 | NULL, idev); | |
294 | if (err) { | |
295 | dev_err(dev, "cannot build key matrix\n"); | |
296 | return err; | |
297 | } | |
298 | ||
299 | ckdev->row_shift = get_count_order(ckdev->cols); | |
300 | ||
301 | input_set_capability(idev, EV_MSC, MSC_SCAN); | |
302 | input_set_drvdata(idev, ckdev); | |
303 | ckdev->idev = idev; | |
017f14e8 TB |
304 | cros_ec_keyb_compute_valid_keys(ckdev); |
305 | ||
6af6dc2d SG |
306 | err = input_register_device(ckdev->idev); |
307 | if (err) { | |
308 | dev_err(dev, "cannot register input device\n"); | |
309 | return err; | |
310 | } | |
311 | ||
312 | return 0; | |
313 | } | |
314 | ||
315 | #ifdef CONFIG_PM_SLEEP | |
03832aa8 GU |
316 | /* Clear any keys in the buffer */ |
317 | static void cros_ec_keyb_clear_keyboard(struct cros_ec_keyb *ckdev) | |
318 | { | |
319 | uint8_t old_state[ckdev->cols]; | |
320 | uint8_t new_state[ckdev->cols]; | |
321 | unsigned long duration; | |
322 | int i, ret; | |
323 | ||
324 | /* | |
325 | * Keep reading until we see that the scan state does not change. | |
326 | * That indicates that we are done. | |
327 | * | |
328 | * Assume that the EC keyscan buffer is at most 32 deep. | |
329 | */ | |
330 | duration = jiffies; | |
331 | ret = cros_ec_keyb_get_state(ckdev, new_state); | |
332 | for (i = 1; !ret && i < 32; i++) { | |
333 | memcpy(old_state, new_state, sizeof(old_state)); | |
334 | ret = cros_ec_keyb_get_state(ckdev, new_state); | |
335 | if (0 == memcmp(old_state, new_state, sizeof(old_state))) | |
336 | break; | |
337 | } | |
338 | duration = jiffies - duration; | |
339 | dev_info(ckdev->dev, "Discarded %d keyscan(s) in %dus\n", i, | |
340 | jiffies_to_usecs(duration)); | |
341 | } | |
342 | ||
6af6dc2d SG |
343 | static int cros_ec_keyb_resume(struct device *dev) |
344 | { | |
345 | struct cros_ec_keyb *ckdev = dev_get_drvdata(dev); | |
346 | ||
347 | /* | |
348 | * When the EC is not a wake source, then it could not have caused the | |
349 | * resume, so we clear the EC's key scan buffer. If the EC was a | |
350 | * wake source (e.g. the lid is open and the user might press a key to | |
351 | * wake) then the key scan buffer should be preserved. | |
352 | */ | |
ef30a406 | 353 | if (!ckdev->ec->was_wake_device) |
6af6dc2d SG |
354 | cros_ec_keyb_clear_keyboard(ckdev); |
355 | ||
356 | return 0; | |
357 | } | |
358 | ||
359 | #endif | |
360 | ||
361 | static SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume); | |
362 | ||
3f1fe73b SS |
363 | #ifdef CONFIG_OF |
364 | static const struct of_device_id cros_ec_keyb_of_match[] = { | |
365 | { .compatible = "google,cros-ec-keyb" }, | |
366 | {}, | |
367 | }; | |
368 | MODULE_DEVICE_TABLE(of, cros_ec_keyb_of_match); | |
369 | #endif | |
370 | ||
6af6dc2d SG |
371 | static struct platform_driver cros_ec_keyb_driver = { |
372 | .probe = cros_ec_keyb_probe, | |
373 | .driver = { | |
374 | .name = "cros-ec-keyb", | |
3f1fe73b | 375 | .of_match_table = of_match_ptr(cros_ec_keyb_of_match), |
6af6dc2d SG |
376 | .pm = &cros_ec_keyb_pm_ops, |
377 | }, | |
378 | }; | |
379 | ||
380 | module_platform_driver(cros_ec_keyb_driver); | |
381 | ||
382 | MODULE_LICENSE("GPL"); | |
383 | MODULE_DESCRIPTION("ChromeOS EC keyboard driver"); | |
384 | MODULE_ALIAS("platform:cros-ec-keyb"); |