1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
4
5#include <linux/crc8.h>
6#include <linux/delay.h>
7#include <linux/err.h>
8#include <linux/i2c.h>
9#include <linux/input.h>
10#include <linux/input/matrix_keypad.h>
11#include <linux/interrupt.h>
12#include <linux/module.h>
13#include <linux/mod_devicetable.h>
14#include <linux/of.h>
15#include <linux/regulator/consumer.h>
16#include <linux/types.h>
17
18#define DRV_NAME "pinephone-keyboard"
19
20#define PPKB_CRC8_POLYNOMIAL 0x07
21
22#define PPKB_DEVICE_ID_HI 0x00
23#define PPKB_DEVICE_ID_HI_VALUE 'K'
24#define PPKB_DEVICE_ID_LO 0x01
25#define PPKB_DEVICE_ID_LO_VALUE 'B'
26#define PPKB_FW_REVISION 0x02
27#define PPKB_FW_FEATURES 0x03
28#define PPKB_MATRIX_SIZE 0x06
29#define PPKB_SCAN_CRC 0x07
30#define PPKB_SCAN_DATA 0x08
31#define PPKB_SYS_CONFIG 0x20
32#define PPKB_SYS_CONFIG_DISABLE_SCAN BIT(0)
33#define PPKB_SYS_SMBUS_COMMAND 0x21
34#define PPKB_SYS_SMBUS_DATA 0x22
35#define PPKB_SYS_COMMAND 0x23
36#define PPKB_SYS_COMMAND_SMBUS_READ 0x91
37#define PPKB_SYS_COMMAND_SMBUS_WRITE 0xa1
38
39#define PPKB_ROWS 6
40#define PPKB_COLS 12
41
42/* Size of the scan buffer, including the CRC byte at the beginning. */
43#define PPKB_BUF_LEN (1 + PPKB_COLS)
44
45static const uint32_t ppkb_keymap[] = {
46 KEY(0, 0, KEY_ESC),
47 KEY(0, 1, KEY_1),
48 KEY(0, 2, KEY_2),
49 KEY(0, 3, KEY_3),
50 KEY(0, 4, KEY_4),
51 KEY(0, 5, KEY_5),
52 KEY(0, 6, KEY_6),
53 KEY(0, 7, KEY_7),
54 KEY(0, 8, KEY_8),
55 KEY(0, 9, KEY_9),
56 KEY(0, 10, KEY_0),
57 KEY(0, 11, KEY_BACKSPACE),
58
59 KEY(1, 0, KEY_TAB),
60 KEY(1, 1, KEY_Q),
61 KEY(1, 2, KEY_W),
62 KEY(1, 3, KEY_E),
63 KEY(1, 4, KEY_R),
64 KEY(1, 5, KEY_T),
65 KEY(1, 6, KEY_Y),
66 KEY(1, 7, KEY_U),
67 KEY(1, 8, KEY_I),
68 KEY(1, 9, KEY_O),
69 KEY(1, 10, KEY_P),
70 KEY(1, 11, KEY_ENTER),
71
72 KEY(2, 0, KEY_LEFTMETA),
73 KEY(2, 1, KEY_A),
74 KEY(2, 2, KEY_S),
75 KEY(2, 3, KEY_D),
76 KEY(2, 4, KEY_F),
77 KEY(2, 5, KEY_G),
78 KEY(2, 6, KEY_H),
79 KEY(2, 7, KEY_J),
80 KEY(2, 8, KEY_K),
81 KEY(2, 9, KEY_L),
82 KEY(2, 10, KEY_SEMICOLON),
83
84 KEY(3, 0, KEY_LEFTSHIFT),
85 KEY(3, 1, KEY_Z),
86 KEY(3, 2, KEY_X),
87 KEY(3, 3, KEY_C),
88 KEY(3, 4, KEY_V),
89 KEY(3, 5, KEY_B),
90 KEY(3, 6, KEY_N),
91 KEY(3, 7, KEY_M),
92 KEY(3, 8, KEY_COMMA),
93 KEY(3, 9, KEY_DOT),
94 KEY(3, 10, KEY_SLASH),
95
96 KEY(4, 1, KEY_LEFTCTRL),
97 KEY(4, 4, KEY_SPACE),
98 KEY(4, 6, KEY_APOSTROPHE),
99 KEY(4, 8, KEY_RIGHTBRACE),
100 KEY(4, 9, KEY_LEFTBRACE),
101
102 KEY(5, 2, KEY_FN),
103 KEY(5, 3, KEY_LEFTALT),
104 KEY(5, 5, KEY_RIGHTALT),
105
106 /* FN layer */
107 KEY(PPKB_ROWS + 0, 0, KEY_FN_ESC),
108 KEY(PPKB_ROWS + 0, 1, KEY_F1),
109 KEY(PPKB_ROWS + 0, 2, KEY_F2),
110 KEY(PPKB_ROWS + 0, 3, KEY_F3),
111 KEY(PPKB_ROWS + 0, 4, KEY_F4),
112 KEY(PPKB_ROWS + 0, 5, KEY_F5),
113 KEY(PPKB_ROWS + 0, 6, KEY_F6),
114 KEY(PPKB_ROWS + 0, 7, KEY_F7),
115 KEY(PPKB_ROWS + 0, 8, KEY_F8),
116 KEY(PPKB_ROWS + 0, 9, KEY_F9),
117 KEY(PPKB_ROWS + 0, 10, KEY_F10),
118 KEY(PPKB_ROWS + 0, 11, KEY_DELETE),
119
120 KEY(PPKB_ROWS + 1, 10, KEY_PAGEUP),
121
122 KEY(PPKB_ROWS + 2, 0, KEY_SYSRQ),
123 KEY(PPKB_ROWS + 2, 9, KEY_PAGEDOWN),
124 KEY(PPKB_ROWS + 2, 10, KEY_INSERT),
125
126 KEY(PPKB_ROWS + 3, 0, KEY_LEFTSHIFT),
127 KEY(PPKB_ROWS + 3, 8, KEY_HOME),
128 KEY(PPKB_ROWS + 3, 9, KEY_UP),
129 KEY(PPKB_ROWS + 3, 10, KEY_END),
130
131 KEY(PPKB_ROWS + 4, 1, KEY_LEFTCTRL),
132 KEY(PPKB_ROWS + 4, 6, KEY_LEFT),
133 KEY(PPKB_ROWS + 4, 8, KEY_RIGHT),
134 KEY(PPKB_ROWS + 4, 9, KEY_DOWN),
135
136 KEY(PPKB_ROWS + 5, 3, KEY_LEFTALT),
137 KEY(PPKB_ROWS + 5, 5, KEY_RIGHTALT),
138};
139
140static const struct matrix_keymap_data ppkb_keymap_data = {
141 .keymap = ppkb_keymap,
142 .keymap_size = ARRAY_SIZE(ppkb_keymap),
143};
144
145struct pinephone_keyboard {
146 struct i2c_adapter adapter;
147 struct input_dev *input;
148 u8 buf[2][PPKB_BUF_LEN];
149 u8 crc_table[CRC8_TABLE_SIZE];
150 u8 fn_state[PPKB_COLS];
151 bool buf_swap;
152 bool fn_pressed;
153};
154
155static int ppkb_adap_smbus_xfer(struct i2c_adapter *adap, u16 addr,
156 unsigned short flags, char read_write,
157 u8 command, int size,
158 union i2c_smbus_data *data)
159{
160 struct i2c_client *client = adap->algo_data;
161 u8 buf[3];
162 int ret;
163
164 buf[0] = command;
165 buf[1] = data->byte;
166 buf[2] = read_write == I2C_SMBUS_READ ? PPKB_SYS_COMMAND_SMBUS_READ
167 : PPKB_SYS_COMMAND_SMBUS_WRITE;
168
169 ret = i2c_smbus_write_i2c_block_data(client, PPKB_SYS_SMBUS_COMMAND,
170 length: sizeof(buf), values: buf);
171 if (ret)
172 return ret;
173
174 /* Read back the command status until it passes or fails. */
175 do {
176 usleep_range(min: 300, max: 500);
177 ret = i2c_smbus_read_byte_data(client, PPKB_SYS_COMMAND);
178 } while (ret == buf[2]);
179 if (ret < 0)
180 return ret;
181 /* Commands return 0x00 on success and 0xff on failure. */
182 if (ret)
183 return -EIO;
184
185 if (read_write == I2C_SMBUS_READ) {
186 ret = i2c_smbus_read_byte_data(client, PPKB_SYS_SMBUS_DATA);
187 if (ret < 0)
188 return ret;
189
190 data->byte = ret;
191 }
192
193 return 0;
194}
195
196static u32 ppkg_adap_functionality(struct i2c_adapter *adap)
197{
198 return I2C_FUNC_SMBUS_BYTE_DATA;
199}
200
201static const struct i2c_algorithm ppkb_adap_algo = {
202 .smbus_xfer = ppkb_adap_smbus_xfer,
203 .functionality = ppkg_adap_functionality,
204};
205
206static void ppkb_update(struct i2c_client *client)
207{
208 struct pinephone_keyboard *ppkb = i2c_get_clientdata(client);
209 unsigned short *keymap = ppkb->input->keycode;
210 int row_shift = get_count_order(PPKB_COLS);
211 u8 *old_buf = ppkb->buf[!ppkb->buf_swap];
212 u8 *new_buf = ppkb->buf[ppkb->buf_swap];
213 int col, crc, ret, row;
214 struct device *dev = &client->dev;
215
216 ret = i2c_smbus_read_i2c_block_data(client, PPKB_SCAN_CRC,
217 PPKB_BUF_LEN, values: new_buf);
218 if (ret != PPKB_BUF_LEN) {
219 dev_err(dev, "Failed to read scan data: %d\n", ret);
220 return;
221 }
222
223 crc = crc8(table: ppkb->crc_table, pdata: &new_buf[1], PPKB_COLS, CRC8_INIT_VALUE);
224 if (crc != new_buf[0]) {
225 dev_err(dev, "Bad scan data (%02x != %02x)\n", crc, new_buf[0]);
226 return;
227 }
228
229 ppkb->buf_swap = !ppkb->buf_swap;
230
231 for (col = 0; col < PPKB_COLS; ++col) {
232 u8 old = old_buf[1 + col];
233 u8 new = new_buf[1 + col];
234 u8 changed = old ^ new;
235
236 if (!changed)
237 continue;
238
239 for (row = 0; row < PPKB_ROWS; ++row) {
240 u8 mask = BIT(row);
241 u8 value = new & mask;
242 unsigned short code;
243 bool fn_state;
244
245 if (!(changed & mask))
246 continue;
247
248 /*
249 * Save off the FN key state when the key was pressed,
250 * and use that to determine the code during a release.
251 */
252 fn_state = value ? ppkb->fn_pressed : ppkb->fn_state[col] & mask;
253 if (fn_state)
254 ppkb->fn_state[col] ^= mask;
255
256 /* The FN layer is a second set of rows. */
257 code = MATRIX_SCAN_CODE(fn_state ? PPKB_ROWS + row : row,
258 col, row_shift);
259 input_event(dev: ppkb->input, EV_MSC, MSC_SCAN, value: code);
260 input_report_key(dev: ppkb->input, code: keymap[code], value);
261 if (keymap[code] == KEY_FN)
262 ppkb->fn_pressed = value;
263 }
264 }
265 input_sync(dev: ppkb->input);
266}
267
268static irqreturn_t ppkb_irq_thread(int irq, void *data)
269{
270 struct i2c_client *client = data;
271
272 ppkb_update(client);
273
274 return IRQ_HANDLED;
275}
276
277static int ppkb_set_scan(struct i2c_client *client, bool enable)
278{
279 struct device *dev = &client->dev;
280 int ret, val;
281
282 ret = i2c_smbus_read_byte_data(client, PPKB_SYS_CONFIG);
283 if (ret < 0) {
284 dev_err(dev, "Failed to read config: %d\n", ret);
285 return ret;
286 }
287
288 if (enable)
289 val = ret & ~PPKB_SYS_CONFIG_DISABLE_SCAN;
290 else
291 val = ret | PPKB_SYS_CONFIG_DISABLE_SCAN;
292
293 ret = i2c_smbus_write_byte_data(client, PPKB_SYS_CONFIG, value: val);
294 if (ret) {
295 dev_err(dev, "Failed to write config: %d\n", ret);
296 return ret;
297 }
298
299 return 0;
300}
301
302static int ppkb_open(struct input_dev *input)
303{
304 struct i2c_client *client = input_get_drvdata(dev: input);
305 int error;
306
307 error = ppkb_set_scan(client, enable: true);
308 if (error)
309 return error;
310
311 return 0;
312}
313
314static void ppkb_close(struct input_dev *input)
315{
316 struct i2c_client *client = input_get_drvdata(dev: input);
317
318 ppkb_set_scan(client, enable: false);
319}
320
321static int ppkb_probe(struct i2c_client *client)
322{
323 struct device *dev = &client->dev;
324 unsigned int phys_rows, phys_cols;
325 struct pinephone_keyboard *ppkb;
326 u8 info[PPKB_MATRIX_SIZE + 1];
327 struct device_node *i2c_bus;
328 int ret;
329 int error;
330
331 error = devm_regulator_get_enable(dev, id: "vbat");
332 if (error) {
333 dev_err(dev, "Failed to get VBAT supply: %d\n", error);
334 return error;
335 }
336
337 ret = i2c_smbus_read_i2c_block_data(client, command: 0, length: sizeof(info), values: info);
338 if (ret != sizeof(info)) {
339 error = ret < 0 ? ret : -EIO;
340 dev_err(dev, "Failed to read device ID: %d\n", error);
341 return error;
342 }
343
344 if (info[PPKB_DEVICE_ID_HI] != PPKB_DEVICE_ID_HI_VALUE ||
345 info[PPKB_DEVICE_ID_LO] != PPKB_DEVICE_ID_LO_VALUE) {
346 dev_warn(dev, "Unexpected device ID: %#02x %#02x\n",
347 info[PPKB_DEVICE_ID_HI], info[PPKB_DEVICE_ID_LO]);
348 return -ENODEV;
349 }
350
351 dev_info(dev, "Found firmware version %d.%d features %#x\n",
352 info[PPKB_FW_REVISION] >> 4,
353 info[PPKB_FW_REVISION] & 0xf,
354 info[PPKB_FW_FEATURES]);
355
356 phys_rows = info[PPKB_MATRIX_SIZE] & 0xf;
357 phys_cols = info[PPKB_MATRIX_SIZE] >> 4;
358 if (phys_rows != PPKB_ROWS || phys_cols != PPKB_COLS) {
359 dev_err(dev, "Unexpected keyboard size %ux%u\n",
360 phys_rows, phys_cols);
361 return -EINVAL;
362 }
363
364 /* Disable scan by default to save power. */
365 error = ppkb_set_scan(client, enable: false);
366 if (error)
367 return error;
368
369 ppkb = devm_kzalloc(dev, size: sizeof(*ppkb), GFP_KERNEL);
370 if (!ppkb)
371 return -ENOMEM;
372
373 i2c_set_clientdata(client, data: ppkb);
374
375 i2c_bus = of_get_child_by_name(node: dev->of_node, name: "i2c");
376 if (i2c_bus) {
377 ppkb->adapter.owner = THIS_MODULE;
378 ppkb->adapter.algo = &ppkb_adap_algo;
379 ppkb->adapter.algo_data = client;
380 ppkb->adapter.dev.parent = dev;
381 ppkb->adapter.dev.of_node = i2c_bus;
382 strscpy(ppkb->adapter.name, DRV_NAME, sizeof(ppkb->adapter.name));
383
384 error = devm_i2c_add_adapter(dev, adapter: &ppkb->adapter);
385 if (error) {
386 dev_err(dev, "Failed to add I2C adapter: %d\n", error);
387 return error;
388 }
389 }
390
391 crc8_populate_msb(table: ppkb->crc_table, PPKB_CRC8_POLYNOMIAL);
392
393 ppkb->input = devm_input_allocate_device(dev);
394 if (!ppkb->input)
395 return -ENOMEM;
396
397 input_set_drvdata(dev: ppkb->input, data: client);
398
399 ppkb->input->name = "PinePhone Keyboard";
400 ppkb->input->phys = DRV_NAME "/input0";
401 ppkb->input->id.bustype = BUS_I2C;
402 ppkb->input->open = ppkb_open;
403 ppkb->input->close = ppkb_close;
404
405 input_set_capability(dev: ppkb->input, EV_MSC, MSC_SCAN);
406 __set_bit(EV_REP, ppkb->input->evbit);
407
408 error = matrix_keypad_build_keymap(keymap_data: &ppkb_keymap_data, NULL,
409 rows: 2 * PPKB_ROWS, PPKB_COLS, NULL,
410 input_dev: ppkb->input);
411 if (error) {
412 dev_err(dev, "Failed to build keymap: %d\n", error);
413 return error;
414 }
415
416 error = input_register_device(ppkb->input);
417 if (error) {
418 dev_err(dev, "Failed to register input: %d\n", error);
419 return error;
420 }
421
422 error = devm_request_threaded_irq(dev, irq: client->irq,
423 NULL, thread_fn: ppkb_irq_thread,
424 IRQF_ONESHOT, devname: client->name, dev_id: client);
425 if (error) {
426 dev_err(dev, "Failed to request IRQ: %d\n", error);
427 return error;
428 }
429
430 return 0;
431}
432
433static const struct of_device_id ppkb_of_match[] = {
434 { .compatible = "pine64,pinephone-keyboard" },
435 { }
436};
437MODULE_DEVICE_TABLE(of, ppkb_of_match);
438
439static struct i2c_driver ppkb_driver = {
440 .probe = ppkb_probe,
441 .driver = {
442 .name = DRV_NAME,
443 .of_match_table = ppkb_of_match,
444 },
445};
446module_i2c_driver(ppkb_driver);
447
448MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>");
449MODULE_DESCRIPTION("Pine64 PinePhone keyboard driver");
450MODULE_LICENSE("GPL");
451

source code of linux/drivers/input/keyboard/pinephone-keyboard.c