* [PATCH 0/5] Pine64 PinePhone keyboard support @ 2022-01-29 23:00 Samuel Holland 2022-01-29 23:00 ` [PATCH 1/5] dt-bindings: input: Add the PinePhone keyboard binding Samuel Holland ` (4 more replies) 0 siblings, 5 replies; 18+ messages in thread From: Samuel Holland @ 2022-01-29 23:00 UTC (permalink / raw) To: Dmitry Torokhov, linux-input Cc: linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang, Ondrej Jirman, Samuel Holland This series adds support for the official keyboard case for the Pine64 PinePhone and PinePhone Pro. This accessory contains a keyboard MCU and an IP5209 power bank IC. The keyboard MCU firmware[0] is free software. It exposes the keyboard scan matrix over I2C, and also provides commands for SMBus access to the IP5209. In order to keep the IP5209 driver[1] generic, this is modeled as an I2C bus child of the keyboard. [0]: https://megous.com/git/pinephone-keyboard/about/ [1]: https://lore.kernel.org/lkml/20220129222424.45707-1-samuel@sholland.org/T/ Samuel Holland (5): dt-bindings: input: Add the PinePhone keyboard binding Input: pinephone-keyboard - Add PinePhone keyboard driver Input: pinephone-keyboard - Build in the default keymap Input: pinephone-keyboard - Support the proxied I2C bus [DO NOT MERGE] arm64: dts: allwinner: pinephone: Add keyboard .../input/pine64,pinephone-keyboard.yaml | 90 ++++ MAINTAINERS | 6 + .../dts/allwinner/sun50i-a64-pinephone.dtsi | 18 + drivers/input/keyboard/Kconfig | 10 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/pinephone-keyboard.c | 449 ++++++++++++++++++ 6 files changed, 574 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml create mode 100644 drivers/input/keyboard/pinephone-keyboard.c -- 2.33.1 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1/5] dt-bindings: input: Add the PinePhone keyboard binding 2022-01-29 23:00 [PATCH 0/5] Pine64 PinePhone keyboard support Samuel Holland @ 2022-01-29 23:00 ` Samuel Holland 2022-02-11 13:23 ` Rob Herring 2022-01-29 23:00 ` [PATCH 2/5] Input: pinephone-keyboard - Add PinePhone keyboard driver Samuel Holland ` (3 subsequent siblings) 4 siblings, 1 reply; 18+ messages in thread From: Samuel Holland @ 2022-01-29 23:00 UTC (permalink / raw) To: Dmitry Torokhov, linux-input Cc: linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang, Ondrej Jirman, Samuel Holland Add devicetree support for the PinePhone keyboard case, which provides a matrix keyboard interface and a proxied I2C bus. Signed-off-by: Samuel Holland <samuel@sholland.org> --- .../input/pine64,pinephone-keyboard.yaml | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml diff --git a/Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml b/Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml new file mode 100644 index 000000000000..00f084b263f0 --- /dev/null +++ b/Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml @@ -0,0 +1,90 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/pine64,pinephone-keyboard.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Pine64 PinePhone keyboard device tree bindings + +maintainers: + - Samuel Holland <samuel@sholland.org> + +description: + A keyboard accessory is available for the Pine64 PinePhone and PinePhone Pro. + It connects via I2C, providing a raw scan matrix, a flashing interface, and a + subordinate I2C bus for communication with a battery charger IC. + +allOf: + - $ref: /schemas/input/matrix-keymap.yaml# + +properties: + compatible: + const: pine64,pinephone-keyboard + + reg: + const: 0x15 + + interrupts: + maxItems: 1 + + linux,fn-keymap: + $ref: /schemas/input/matrix-keymap.yaml#/properties/linux,keymap + description: keymap used when the Fn key is pressed + + wakeup-source: true + + i2c-bus: + $ref: /schemas/i2c/i2c-controller.yaml# + +dependencies: + linux,fn-keymap: [ 'keypad,num-columns', 'keypad,num-rows' ] + linux,keymap: [ 'keypad,num-columns', 'keypad,num-rows' ] + +required: + - compatible + - reg + - interrupts + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/input/input.h> + #include <dt-bindings/interrupt-controller/irq.h> + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + keyboard@15 { + compatible = "pine64,pinephone-keyboard"; + reg = <0x15>; + interrupt-parent = <&r_pio>; + interrupts = <0 12 IRQ_TYPE_EDGE_FALLING>; /* PL12 */ + keypad,num-rows = <6>; + keypad,num-columns = <12>; + linux,fn-keymap = <MATRIX_KEY(0, 0, KEY_FN_ESC) + MATRIX_KEY(0, 1, KEY_F1) + MATRIX_KEY(0, 2, KEY_F2) + /* ... */ + MATRIX_KEY(5, 2, KEY_FN) + MATRIX_KEY(5, 3, KEY_LEFTALT) + MATRIX_KEY(5, 5, KEY_RIGHTALT)>; + linux,keymap = <MATRIX_KEY(0, 0, KEY_ESC) + MATRIX_KEY(0, 1, KEY_1) + MATRIX_KEY(0, 2, KEY_2) + /* ... */ + MATRIX_KEY(5, 2, KEY_FN) + MATRIX_KEY(5, 3, KEY_LEFTALT) + MATRIX_KEY(5, 5, KEY_RIGHTALT)>; + + i2c-bus { + #address-cells = <1>; + #size-cells = <0>; + + charger@75 { + reg = <0x75>; + }; + }; + }; + }; -- 2.33.1 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 1/5] dt-bindings: input: Add the PinePhone keyboard binding 2022-01-29 23:00 ` [PATCH 1/5] dt-bindings: input: Add the PinePhone keyboard binding Samuel Holland @ 2022-02-11 13:23 ` Rob Herring 2022-02-14 4:41 ` Samuel Holland 0 siblings, 1 reply; 18+ messages in thread From: Rob Herring @ 2022-02-11 13:23 UTC (permalink / raw) To: Samuel Holland Cc: Dmitry Torokhov, linux-input, linux-kernel, devicetree, linux-i2c, Wolfram Sang, Ondrej Jirman On Sat, Jan 29, 2022 at 05:00:38PM -0600, Samuel Holland wrote: > Add devicetree support for the PinePhone keyboard case, which provides a > matrix keyboard interface and a proxied I2C bus. > > Signed-off-by: Samuel Holland <samuel@sholland.org> > --- > > .../input/pine64,pinephone-keyboard.yaml | 90 +++++++++++++++++++ > 1 file changed, 90 insertions(+) > create mode 100644 Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml > > diff --git a/Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml b/Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml > new file mode 100644 > index 000000000000..00f084b263f0 > --- /dev/null > +++ b/Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml > @@ -0,0 +1,90 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/input/pine64,pinephone-keyboard.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Pine64 PinePhone keyboard device tree bindings > + > +maintainers: > + - Samuel Holland <samuel@sholland.org> > + > +description: > + A keyboard accessory is available for the Pine64 PinePhone and PinePhone Pro. > + It connects via I2C, providing a raw scan matrix, a flashing interface, and a > + subordinate I2C bus for communication with a battery charger IC. > + > +allOf: > + - $ref: /schemas/input/matrix-keymap.yaml# > + > +properties: > + compatible: > + const: pine64,pinephone-keyboard > + > + reg: > + const: 0x15 > + > + interrupts: > + maxItems: 1 > + > + linux,fn-keymap: This should be handled in a common way. Not sure if there's anything existing for alternate key maps. Child nodes of alternate maps would scale better than new property name for every alternate map. Or you could make linux,keymap contain multiple maps (e.g. 2x XxY entries) Or if the map doesn't change, just put it in the driver. > + $ref: /schemas/input/matrix-keymap.yaml#/properties/linux,keymap Referencing individual properties should be avoided. > + description: keymap used when the Fn key is pressed > + > + wakeup-source: true > + > + i2c-bus: > + $ref: /schemas/i2c/i2c-controller.yaml# > + > +dependencies: > + linux,fn-keymap: [ 'keypad,num-columns', 'keypad,num-rows' ] > + linux,keymap: [ 'keypad,num-columns', 'keypad,num-rows' ] > + > +required: > + - compatible > + - reg > + - interrupts > + > +unevaluatedProperties: false > + > +examples: > + - | > + #include <dt-bindings/input/input.h> > + #include <dt-bindings/interrupt-controller/irq.h> > + > + i2c { > + #address-cells = <1>; > + #size-cells = <0>; > + > + keyboard@15 { > + compatible = "pine64,pinephone-keyboard"; > + reg = <0x15>; > + interrupt-parent = <&r_pio>; > + interrupts = <0 12 IRQ_TYPE_EDGE_FALLING>; /* PL12 */ > + keypad,num-rows = <6>; > + keypad,num-columns = <12>; > + linux,fn-keymap = <MATRIX_KEY(0, 0, KEY_FN_ESC) > + MATRIX_KEY(0, 1, KEY_F1) > + MATRIX_KEY(0, 2, KEY_F2) > + /* ... */ > + MATRIX_KEY(5, 2, KEY_FN) > + MATRIX_KEY(5, 3, KEY_LEFTALT) > + MATRIX_KEY(5, 5, KEY_RIGHTALT)>; > + linux,keymap = <MATRIX_KEY(0, 0, KEY_ESC) > + MATRIX_KEY(0, 1, KEY_1) > + MATRIX_KEY(0, 2, KEY_2) > + /* ... */ > + MATRIX_KEY(5, 2, KEY_FN) > + MATRIX_KEY(5, 3, KEY_LEFTALT) > + MATRIX_KEY(5, 5, KEY_RIGHTALT)>; > + > + i2c-bus { > + #address-cells = <1>; > + #size-cells = <0>; > + > + charger@75 { > + reg = <0x75>; > + }; > + }; > + }; > + }; > -- > 2.33.1 > > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/5] dt-bindings: input: Add the PinePhone keyboard binding 2022-02-11 13:23 ` Rob Herring @ 2022-02-14 4:41 ` Samuel Holland 0 siblings, 0 replies; 18+ messages in thread From: Samuel Holland @ 2022-02-14 4:41 UTC (permalink / raw) To: Rob Herring, Dmitry Torokhov Cc: linux-input, linux-kernel, devicetree, linux-i2c, Wolfram Sang, Ondrej Jirman, Olof Johansson On 2/11/22 7:23 AM, Rob Herring wrote: > On Sat, Jan 29, 2022 at 05:00:38PM -0600, Samuel Holland wrote: >> Add devicetree support for the PinePhone keyboard case, which provides a >> matrix keyboard interface and a proxied I2C bus. >> >> Signed-off-by: Samuel Holland <samuel@sholland.org> >> --- >> >> .../input/pine64,pinephone-keyboard.yaml | 90 +++++++++++++++++++ >> 1 file changed, 90 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml >> >> diff --git a/Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml b/Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml >> new file mode 100644 >> index 000000000000..00f084b263f0 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml >> @@ -0,0 +1,90 @@ >> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) >> +%YAML 1.2 >> +--- >> +$id: http://devicetree.org/schemas/input/pine64,pinephone-keyboard.yaml# >> +$schema: http://devicetree.org/meta-schemas/core.yaml# >> + >> +title: Pine64 PinePhone keyboard device tree bindings >> + >> +maintainers: >> + - Samuel Holland <samuel@sholland.org> >> + >> +description: >> + A keyboard accessory is available for the Pine64 PinePhone and PinePhone Pro. >> + It connects via I2C, providing a raw scan matrix, a flashing interface, and a >> + subordinate I2C bus for communication with a battery charger IC. >> + >> +allOf: >> + - $ref: /schemas/input/matrix-keymap.yaml# >> + >> +properties: >> + compatible: >> + const: pine64,pinephone-keyboard >> + >> + reg: >> + const: 0x15 >> + >> + interrupts: >> + maxItems: 1 >> + >> + linux,fn-keymap: > > This should be handled in a common way. Not sure if there's anything > existing for alternate key maps. Child nodes of alternate maps would > scale better than new property name for every alternate map. Or you > could make linux,keymap contain multiple maps (e.g. 2x XxY entries) matrix-keymap.yaml proposes doing exactly what I do here: Some users of this binding might choose to specify secondary keymaps for cases where there is a modifier key such as a Fn key. Proposed names for said properties are "linux,fn-keymap" or with another descriptive word for the modifier other from "Fn". The only other reference to linux,fn-keymap is in the nvidia,tegra20-kbc binding, even though that driver doesn't use this property. Instead, what the tegra-kbc.c code does is double the number of rows to include the Fn layer: if (kbc->keymap_data && kbc->use_fn_map) keymap_rows *= 2; (except that use_fn_map is set nowhere, so this is dead code). Using extra rows for the Fn layer seems a bit magic to me, but if it is documented, I suppose it is fine. So there is not much in the way of prior art. > Or if the map doesn't change, just put it in the driver. The keys are removable, so technically it can change, but maybe that's better handled by userspace than in the DTB? On the other hand, from Dmitry's comment, it sounds like he would prefer leaving the map out of the driver. Regards, Samuel >> + $ref: /schemas/input/matrix-keymap.yaml#/properties/linux,keymap > > Referencing individual properties should be avoided. > >> + description: keymap used when the Fn key is pressed >> + >> + wakeup-source: true >> + >> + i2c-bus: >> + $ref: /schemas/i2c/i2c-controller.yaml# >> + >> +dependencies: >> + linux,fn-keymap: [ 'keypad,num-columns', 'keypad,num-rows' ] >> + linux,keymap: [ 'keypad,num-columns', 'keypad,num-rows' ] >> + >> +required: >> + - compatible >> + - reg >> + - interrupts >> + >> +unevaluatedProperties: false >> + >> +examples: >> + - | >> + #include <dt-bindings/input/input.h> >> + #include <dt-bindings/interrupt-controller/irq.h> >> + >> + i2c { >> + #address-cells = <1>; >> + #size-cells = <0>; >> + >> + keyboard@15 { >> + compatible = "pine64,pinephone-keyboard"; >> + reg = <0x15>; >> + interrupt-parent = <&r_pio>; >> + interrupts = <0 12 IRQ_TYPE_EDGE_FALLING>; /* PL12 */ >> + keypad,num-rows = <6>; >> + keypad,num-columns = <12>; >> + linux,fn-keymap = <MATRIX_KEY(0, 0, KEY_FN_ESC) >> + MATRIX_KEY(0, 1, KEY_F1) >> + MATRIX_KEY(0, 2, KEY_F2) >> + /* ... */ >> + MATRIX_KEY(5, 2, KEY_FN) >> + MATRIX_KEY(5, 3, KEY_LEFTALT) >> + MATRIX_KEY(5, 5, KEY_RIGHTALT)>; >> + linux,keymap = <MATRIX_KEY(0, 0, KEY_ESC) >> + MATRIX_KEY(0, 1, KEY_1) >> + MATRIX_KEY(0, 2, KEY_2) >> + /* ... */ >> + MATRIX_KEY(5, 2, KEY_FN) >> + MATRIX_KEY(5, 3, KEY_LEFTALT) >> + MATRIX_KEY(5, 5, KEY_RIGHTALT)>; >> + >> + i2c-bus { >> + #address-cells = <1>; >> + #size-cells = <0>; >> + >> + charger@75 { >> + reg = <0x75>; >> + }; >> + }; >> + }; >> + }; >> -- >> 2.33.1 >> >> ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 2/5] Input: pinephone-keyboard - Add PinePhone keyboard driver 2022-01-29 23:00 [PATCH 0/5] Pine64 PinePhone keyboard support Samuel Holland 2022-01-29 23:00 ` [PATCH 1/5] dt-bindings: input: Add the PinePhone keyboard binding Samuel Holland @ 2022-01-29 23:00 ` Samuel Holland 2022-02-02 8:07 ` Ondřej Jirman 2022-02-02 11:48 ` Ondřej Jirman 2022-01-29 23:00 ` [PATCH 3/5] Input: pinephone-keyboard - Build in the default keymap Samuel Holland ` (2 subsequent siblings) 4 siblings, 2 replies; 18+ messages in thread From: Samuel Holland @ 2022-01-29 23:00 UTC (permalink / raw) To: Dmitry Torokhov, linux-input Cc: linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang, Ondrej Jirman, Samuel Holland The official Pine64 PinePhone keyboard case contains a matrix keypad and a MCU which runs a libre firmware. Add support for its I2C interface. Signed-off-by: Samuel Holland <samuel@sholland.org> --- MAINTAINERS | 6 + drivers/input/keyboard/Kconfig | 10 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/pinephone-keyboard.c | 258 ++++++++++++++++++++ 4 files changed, 275 insertions(+) create mode 100644 drivers/input/keyboard/pinephone-keyboard.c diff --git a/MAINTAINERS b/MAINTAINERS index f41088418aae..85428a707e67 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15320,6 +15320,12 @@ S: Maintained F: Documentation/devicetree/bindings/iio/chemical/plantower,pms7003.yaml F: drivers/iio/chemical/pms7003.c +PINE64 PINEPHONE KEYBOARD DRIVER +M: Samuel Holland <samuel@sholland.org> +S: Supported +F: Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml +F: drivers/input/keyboard/pinephone-keyboard.c + PLDMFW LIBRARY M: Jacob Keller <jacob.e.keller@intel.com> S: Maintained diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 0c607da9ee10..f9978da1c916 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -523,6 +523,16 @@ config KEYBOARD_OPENCORES To compile this driver as a module, choose M here; the module will be called opencores-kbd. +config KEYBOARD_PINEPHONE + tristate "Pine64 PinePhone Keyboard" + depends on I2C + select CRC8 + select INPUT_MATRIXKMAP + help + Say Y here to enable support for the keyboard in the Pine64 PinePhone + keyboard case. This driver supports the FLOSS firmware available at + https://megous.com/git/pinephone-keyboard/ + config KEYBOARD_PXA27x tristate "PXA27x/PXA3xx keypad support" depends on PXA27x || PXA3xx || ARCH_MMP diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index e3c8648f834e..84da37e3a2f5 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o +obj-$(CONFIG_KEYBOARD_PINEPHONE) += pinephone-keyboard.o obj-$(CONFIG_KEYBOARD_PMIC8XXX) += pmic8xxx-keypad.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o diff --git a/drivers/input/keyboard/pinephone-keyboard.c b/drivers/input/keyboard/pinephone-keyboard.c new file mode 100644 index 000000000000..9a071753fd91 --- /dev/null +++ b/drivers/input/keyboard/pinephone-keyboard.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org> + +#include <linux/crc8.h> +#include <linux/i2c.h> +#include <linux/input/matrix_keypad.h> +#include <linux/interrupt.h> +#include <linux/module.h> + +#define DRV_NAME "pinephone-keyboard" + +#define PPKB_CRC8_POLYNOMIAL 0x07 + +#define PPKB_DEVICE_ID_HI 0x00 +#define PPKB_DEVICE_ID_HI_VALUE 0x4b +#define PPKB_DEVICE_ID_LO 0x01 +#define PPKB_DEVICE_ID_LO_VALUE 0x42 +#define PPKB_FW_REVISION 0x02 +#define PPKB_FW_FEATURES 0x03 +#define PPKB_MATRIX_SIZE 0x06 +#define PPKB_SCAN_CRC 0x07 +#define PPKB_SCAN_DATA 0x08 +#define PPKB_SYS_CONFIG 0x20 +#define PPKB_SYS_CONFIG_DISABLE_SCAN BIT(0) + +struct pinephone_keyboard { + struct input_dev *input; + unsigned short *fn_keymap; + u8 crc_table[CRC8_TABLE_SIZE]; + u8 row_shift; + u8 rows; + u8 cols; + u8 fn_state; + u8 buf_swap; + u8 buf[]; +}; + +static int ppkb_set_scan(struct i2c_client *client, bool enable) +{ + struct device *dev = &client->dev; + int ret, val; + + ret = i2c_smbus_read_byte_data(client, PPKB_SYS_CONFIG); + if (ret < 0) { + dev_err(dev, "Failed to read config: %d\n", ret); + return ret; + } + + if (enable) + val = ret & ~PPKB_SYS_CONFIG_DISABLE_SCAN; + else + val = ret | PPKB_SYS_CONFIG_DISABLE_SCAN; + ret = i2c_smbus_write_byte_data(client, PPKB_SYS_CONFIG, val); + if (ret) { + dev_err(dev, "Failed to write config: %d\n", ret); + return ret; + } + + return 0; +} + +static void ppkb_update(struct i2c_client *client) +{ + struct pinephone_keyboard *ppkb = i2c_get_clientdata(client); + struct device *dev = &client->dev; + size_t buf_len = ppkb->cols + 1; + u8 *old_buf = ppkb->buf; + u8 *new_buf = ppkb->buf; + unsigned short *keymap; + int col, crc, ret, row; + + if (ppkb->buf_swap) + old_buf += buf_len; + else + new_buf += buf_len; + + ret = i2c_smbus_read_i2c_block_data(client, PPKB_SCAN_CRC, + buf_len, new_buf); + if (ret != buf_len) { + dev_err(dev, "Failed to read scan data: %d\n", ret); + return; + } + + crc = crc8(ppkb->crc_table, new_buf + 1, ppkb->cols, CRC8_INIT_VALUE); + if (crc != new_buf[0]) { + dev_err(dev, "Bad scan data (%02x != %02x)\n", crc, new_buf[0]); + return; + } + + ppkb->buf_swap = !ppkb->buf_swap; + + keymap = ppkb->fn_state ? ppkb->fn_keymap : ppkb->input->keycode; + for (col = 0; col < ppkb->cols; ++col) { + u8 old = *(++old_buf); + u8 new = *(++new_buf); + u8 changed = old ^ new; + + for (row = 0; row < ppkb->rows; ++row) { + int code = MATRIX_SCAN_CODE(row, col, ppkb->row_shift); + int value = new & BIT(row); + + if (!(changed & BIT(row))) + continue; + + dev_dbg(dev, "row %u col %u %sed\n", + row, col, value ? "press" : "releas"); + if (keymap[code] == KEY_FN) { + dev_dbg(dev, "FN is now %sed\n", + value ? "press" : "releas"); + keymap = value ? ppkb->fn_keymap + : ppkb->input->keycode; + ppkb->fn_state = value; + } + input_event(ppkb->input, EV_MSC, MSC_SCAN, code); + input_report_key(ppkb->input, keymap[code], value); + } + } + input_sync(ppkb->input); +} + +static int ppkb_open(struct input_dev *input) +{ + struct i2c_client *client = input_get_drvdata(input); + int ret; + + ret = ppkb_set_scan(client, true); + if (ret) + return ret; + + ppkb_update(client); + + return 0; +} + +static void ppkb_close(struct input_dev *input) +{ + struct i2c_client *client = input_get_drvdata(input); + + ppkb_set_scan(client, false); +} + +static irqreturn_t ppkb_irq_thread(int irq, void *data) +{ + struct i2c_client *client = data; + + ppkb_update(client); + + return IRQ_HANDLED; +} + +static int ppkb_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + unsigned int phys_rows, phys_cols; + unsigned int map_rows, map_cols; + struct pinephone_keyboard *ppkb; + u8 info[PPKB_MATRIX_SIZE + 1]; + int ret; + + ret = i2c_smbus_read_i2c_block_data(client, 0, sizeof(info), info); + if (ret != sizeof(info)) + return dev_err_probe(dev, ret, "Failed to read device ID\n"); + + if (info[PPKB_DEVICE_ID_HI] != PPKB_DEVICE_ID_HI_VALUE || + info[PPKB_DEVICE_ID_LO] != PPKB_DEVICE_ID_LO_VALUE) + return dev_err_probe(dev, -ENODEV, "Unexpected device ID\n"); + + dev_info(dev, "Found keyboard firmware version %d.%d features %#x\n", + info[PPKB_FW_REVISION] >> 4, + info[PPKB_FW_REVISION] & 0xf, + info[PPKB_FW_FEATURES]); + + /* Disable scan by default to save power. */ + ret = ppkb_set_scan(client, false); + if (ret) + return ret; + + ret = matrix_keypad_parse_properties(dev, &map_rows, &map_cols); + if (ret) + return ret; + + phys_rows = info[PPKB_MATRIX_SIZE] & 0xf; + phys_cols = info[PPKB_MATRIX_SIZE] >> 4; + if (map_rows != phys_rows || map_cols != phys_cols) + return dev_err_probe(dev, -EINVAL, + "Keyboard size is %ux%u, but keymap is %ux%u\n", + phys_rows, phys_cols, map_rows, map_cols); + + /* Allocate two buffers, and include space for reading the CRC. */ + ppkb = devm_kzalloc(dev, struct_size(ppkb, buf, 2 * (phys_cols + 1)), GFP_KERNEL); + if (!ppkb) + return -ENOMEM; + + i2c_set_clientdata(client, ppkb); + + crc8_populate_msb(ppkb->crc_table, PPKB_CRC8_POLYNOMIAL); + ppkb->row_shift = get_count_order(map_cols); + ppkb->rows = map_rows; + ppkb->cols = map_cols; + + ppkb->input = devm_input_allocate_device(dev); + if (!ppkb->input) + return -ENOMEM; + + input_set_drvdata(ppkb->input, client); + + ppkb->input->name = "PinePhone Keyboard"; + ppkb->input->phys = DRV_NAME "/input0"; + ppkb->input->id.bustype = BUS_I2C; + ppkb->input->open = ppkb_open; + ppkb->input->close = ppkb_close; + + __set_bit(EV_MSC, ppkb->input->evbit); + __set_bit(EV_REP, ppkb->input->evbit); + + ret = matrix_keypad_build_keymap(NULL, "linux,fn-keymap", + map_rows, map_cols, NULL, ppkb->input); + if (ret) + return dev_err_probe(dev, ret, "Failed to build FN keymap\n"); + + ppkb->fn_keymap = ppkb->input->keycode; + + ret = matrix_keypad_build_keymap(NULL, "linux,keymap", + map_rows, map_cols, NULL, ppkb->input); + if (ret) + return dev_err_probe(dev, ret, "Failed to build keymap\n"); + + ret = input_register_device(ppkb->input); + if (ret) + return dev_err_probe(dev, ret, "Failed to register input\n"); + + ret = devm_request_threaded_irq(dev, client->irq, NULL, ppkb_irq_thread, + IRQF_ONESHOT, client->name, client); + if (ret) + return dev_err_probe(dev, ret, "Failed to request IRQ\n"); + + return 0; +} + +static const struct of_device_id ppkb_of_match[] = { + { .compatible = "pine64,pinephone-keyboard" }, + { } +}; +MODULE_DEVICE_TABLE(of, ppkb_of_match); + +static struct i2c_driver ppkb_driver = { + .probe_new = ppkb_probe, + .driver = { + .name = DRV_NAME, + .of_match_table = ppkb_of_match, + }, +}; +module_i2c_driver(ppkb_driver); + +MODULE_AUTHOR("Samuel Holland <samuel@sholland.org>"); +MODULE_DESCRIPTION("Pine64 PinePhone keyboard driver"); +MODULE_LICENSE("GPL"); -- 2.33.1 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 2/5] Input: pinephone-keyboard - Add PinePhone keyboard driver 2022-01-29 23:00 ` [PATCH 2/5] Input: pinephone-keyboard - Add PinePhone keyboard driver Samuel Holland @ 2022-02-02 8:07 ` Ondřej Jirman 2022-02-02 11:48 ` Ondřej Jirman 1 sibling, 0 replies; 18+ messages in thread From: Ondřej Jirman @ 2022-02-02 8:07 UTC (permalink / raw) To: Samuel Holland Cc: Dmitry Torokhov, linux-input, linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang Hello Samuel, On Sat, Jan 29, 2022 at 05:00:39PM -0600, Samuel Holland wrote: > The official Pine64 PinePhone keyboard case contains a matrix keypad and > a MCU which runs a libre firmware. Add support for its I2C interface. > > Signed-off-by: Samuel Holland <samuel@sholland.org> > --- > [...] > + > + ppkb->buf_swap = !ppkb->buf_swap; > + > + keymap = ppkb->fn_state ? ppkb->fn_keymap : ppkb->input->keycode; > + for (col = 0; col < ppkb->cols; ++col) { > + u8 old = *(++old_buf); > + u8 new = *(++new_buf); > + u8 changed = old ^ new; > + > + for (row = 0; row < ppkb->rows; ++row) { > + int code = MATRIX_SCAN_CODE(row, col, ppkb->row_shift); > + int value = new & BIT(row); > + > + if (!(changed & BIT(row))) > + continue; > + > + dev_dbg(dev, "row %u col %u %sed\n", > + row, col, value ? "press" : "releas"); > + if (keymap[code] == KEY_FN) { > + dev_dbg(dev, "FN is now %sed\n", > + value ? "press" : "releas"); > + keymap = value ? ppkb->fn_keymap > + : ppkb->input->keycode; > + ppkb->fn_state = value; > + } > + input_event(ppkb->input, EV_MSC, MSC_SCAN, code); > + input_report_key(ppkb->input, keymap[code], value); I think there's a logic issue here with the Fn layer. Consider what happens when you press Fn press F1 and then release Fn and release F1. In that case input_report_key will report press of F1 (in fn layer) but release of '1' which is not in Fn layer, because Fn layer was de-activated before releasing the modified key. From the PoV of the user, this will probably lead to auto-repeat of F1 and spurious '1' release without preceding press event. So the userspace sees F1 as stuck and auto-repeats it. kind regards, o. > + } > + } > + input_sync(ppkb->input); > +} > + ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/5] Input: pinephone-keyboard - Add PinePhone keyboard driver 2022-01-29 23:00 ` [PATCH 2/5] Input: pinephone-keyboard - Add PinePhone keyboard driver Samuel Holland 2022-02-02 8:07 ` Ondřej Jirman @ 2022-02-02 11:48 ` Ondřej Jirman 1 sibling, 0 replies; 18+ messages in thread From: Ondřej Jirman @ 2022-02-02 11:48 UTC (permalink / raw) To: Samuel Holland Cc: Dmitry Torokhov, linux-input, linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang Hello again Samuel, On Sat, Jan 29, 2022 at 05:00:39PM -0600, Samuel Holland wrote: > The official Pine64 PinePhone keyboard case contains a matrix keypad and > a MCU which runs a libre firmware. Add support for its I2C interface. I had one bug report from a user that reminded me of something that's missing in the driver. Please add a regulator support for power supply for the keyboard. On Pinephone the keyboard needs USB-5V regulator to be enabled, because final version of the keyboard is supplied from the VBAT POGO pin and not internally from kb battery, as on the prototypes. If this regulator is not enabled the keyboard will be supplied from battery - voltage drop on a boost regulator diode, which causes very frequent brownouts of the keyboard MCU. Users don't notice, becuse MCU recovers quickly and only a key or two is missed every once in a while, but it should be fixed. And this problem probably only shows up when the phone battery is either quite discharged, or random load spikes push its voltage bellow what's necessary for the MCU to run, temporarily. kind regards, o. ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 3/5] Input: pinephone-keyboard - Build in the default keymap 2022-01-29 23:00 [PATCH 0/5] Pine64 PinePhone keyboard support Samuel Holland 2022-01-29 23:00 ` [PATCH 1/5] dt-bindings: input: Add the PinePhone keyboard binding Samuel Holland 2022-01-29 23:00 ` [PATCH 2/5] Input: pinephone-keyboard - Add PinePhone keyboard driver Samuel Holland @ 2022-01-29 23:00 ` Samuel Holland 2022-01-31 19:45 ` Dmitry Torokhov 2022-04-12 10:20 ` Jarrah 2022-01-29 23:00 ` [PATCH 4/5] Input: pinephone-keyboard - Support the proxied I2C bus Samuel Holland 2022-01-29 23:00 ` [PATCH 5/5] [DO NOT MERGE] arm64: dts: allwinner: pinephone: Add keyboard Samuel Holland 4 siblings, 2 replies; 18+ messages in thread From: Samuel Holland @ 2022-01-29 23:00 UTC (permalink / raw) To: Dmitry Torokhov, linux-input Cc: linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang, Ondrej Jirman, Samuel Holland The PinePhone keyboard comes with removable keys, but there is a default layout labeled from the factory. Use this keymap if none is provided in the devicetree. Suggested-by: Ondrej Jirman <x@xff.cz> Signed-off-by: Samuel Holland <samuel@sholland.org> --- drivers/input/keyboard/pinephone-keyboard.c | 128 +++++++++++++++++++- 1 file changed, 123 insertions(+), 5 deletions(-) diff --git a/drivers/input/keyboard/pinephone-keyboard.c b/drivers/input/keyboard/pinephone-keyboard.c index 9a071753fd91..8065bc3e101a 100644 --- a/drivers/input/keyboard/pinephone-keyboard.c +++ b/drivers/input/keyboard/pinephone-keyboard.c @@ -24,6 +24,113 @@ #define PPKB_SYS_CONFIG 0x20 #define PPKB_SYS_CONFIG_DISABLE_SCAN BIT(0) +#define PPKB_DEFAULT_KEYMAP_ROWS 6 +#define PPKB_DEFAULT_KEYMAP_COLS 12 + +static const uint32_t ppkb_default_fn_keymap[] = { + KEY(0, 0, KEY_FN_ESC), + KEY(0, 1, KEY_F1), + KEY(0, 2, KEY_F2), + KEY(0, 3, KEY_F3), + KEY(0, 4, KEY_F4), + KEY(0, 5, KEY_F5), + KEY(0, 6, KEY_F6), + KEY(0, 7, KEY_F7), + KEY(0, 8, KEY_F8), + KEY(0, 9, KEY_F9), + KEY(0, 10, KEY_F10), + KEY(0, 11, KEY_DELETE), + + KEY(2, 0, KEY_SYSRQ), + KEY(2, 10, KEY_INSERT), + + KEY(3, 0, KEY_LEFTSHIFT), + KEY(3, 8, KEY_HOME), + KEY(3, 9, KEY_UP), + KEY(3, 10, KEY_END), + + KEY(4, 1, KEY_LEFTCTRL), + KEY(4, 6, KEY_LEFT), + KEY(4, 8, KEY_RIGHT), + KEY(4, 9, KEY_DOWN), + + KEY(5, 2, KEY_FN), + KEY(5, 3, KEY_LEFTALT), + KEY(5, 5, KEY_RIGHTALT), +}; + +static const struct matrix_keymap_data ppkb_default_fn_keymap_data = { + .keymap = ppkb_default_fn_keymap, + .keymap_size = ARRAY_SIZE(ppkb_default_fn_keymap), +}; + +static const uint32_t ppkb_default_keymap[] = { + KEY(0, 0, KEY_ESC), + KEY(0, 1, KEY_1), + KEY(0, 2, KEY_2), + KEY(0, 3, KEY_3), + KEY(0, 4, KEY_4), + KEY(0, 5, KEY_5), + KEY(0, 6, KEY_6), + KEY(0, 7, KEY_7), + KEY(0, 8, KEY_8), + KEY(0, 9, KEY_9), + KEY(0, 10, KEY_0), + KEY(0, 11, KEY_BACKSPACE), + + KEY(1, 0, KEY_TAB), + KEY(1, 1, KEY_Q), + KEY(1, 2, KEY_W), + KEY(1, 3, KEY_E), + KEY(1, 4, KEY_R), + KEY(1, 5, KEY_T), + KEY(1, 6, KEY_Y), + KEY(1, 7, KEY_U), + KEY(1, 8, KEY_I), + KEY(1, 9, KEY_O), + KEY(1, 10, KEY_P), + KEY(1, 11, KEY_ENTER), + + KEY(2, 0, KEY_LEFTMETA), + KEY(2, 1, KEY_A), + KEY(2, 2, KEY_S), + KEY(2, 3, KEY_D), + KEY(2, 4, KEY_F), + KEY(2, 5, KEY_G), + KEY(2, 6, KEY_H), + KEY(2, 7, KEY_J), + KEY(2, 8, KEY_K), + KEY(2, 9, KEY_L), + KEY(2, 10, KEY_SEMICOLON), + + KEY(3, 0, KEY_LEFTSHIFT), + KEY(3, 1, KEY_Z), + KEY(3, 2, KEY_X), + KEY(3, 3, KEY_C), + KEY(3, 4, KEY_V), + KEY(3, 5, KEY_B), + KEY(3, 6, KEY_N), + KEY(3, 7, KEY_M), + KEY(3, 8, KEY_COMMA), + KEY(3, 9, KEY_DOT), + KEY(3, 10, KEY_SLASH), + + KEY(4, 1, KEY_LEFTCTRL), + KEY(4, 4, KEY_SPACE), + KEY(4, 6, KEY_APOSTROPHE), + KEY(4, 8, KEY_RIGHTBRACE), + KEY(4, 9, KEY_LEFTBRACE), + + KEY(5, 2, KEY_FN), + KEY(5, 3, KEY_LEFTALT), + KEY(5, 5, KEY_RIGHTALT), +}; + +static const struct matrix_keymap_data ppkb_default_keymap_data = { + .keymap = ppkb_default_keymap, + .keymap_size = ARRAY_SIZE(ppkb_default_keymap), +}; + struct pinephone_keyboard { struct input_dev *input; unsigned short *fn_keymap; @@ -151,6 +258,8 @@ static irqreturn_t ppkb_irq_thread(int irq, void *data) static int ppkb_probe(struct i2c_client *client) { + const struct matrix_keymap_data *fn_keymap_data = &ppkb_default_fn_keymap_data; + const struct matrix_keymap_data *keymap_data = &ppkb_default_keymap_data; struct device *dev = &client->dev; unsigned int phys_rows, phys_cols; unsigned int map_rows, map_cols; @@ -176,9 +285,18 @@ static int ppkb_probe(struct i2c_client *client) if (ret) return ret; - ret = matrix_keypad_parse_properties(dev, &map_rows, &map_cols); - if (ret) - return ret; + /* Allow the devicetree to override the default keymaps. */ + if (of_property_read_bool(dev->of_node, "linux,fn-keymap") || + of_property_read_bool(dev->of_node, "linux,keymap")) { + ret = matrix_keypad_parse_properties(dev, &map_rows, &map_cols); + if (ret) + return ret; + + fn_keymap_data = keymap_data = NULL; + } else { + map_rows = PPKB_DEFAULT_KEYMAP_ROWS; + map_cols = PPKB_DEFAULT_KEYMAP_COLS; + } phys_rows = info[PPKB_MATRIX_SIZE] & 0xf; phys_cols = info[PPKB_MATRIX_SIZE] >> 4; @@ -214,14 +332,14 @@ static int ppkb_probe(struct i2c_client *client) __set_bit(EV_MSC, ppkb->input->evbit); __set_bit(EV_REP, ppkb->input->evbit); - ret = matrix_keypad_build_keymap(NULL, "linux,fn-keymap", + ret = matrix_keypad_build_keymap(fn_keymap_data, "linux,fn-keymap", map_rows, map_cols, NULL, ppkb->input); if (ret) return dev_err_probe(dev, ret, "Failed to build FN keymap\n"); ppkb->fn_keymap = ppkb->input->keycode; - ret = matrix_keypad_build_keymap(NULL, "linux,keymap", + ret = matrix_keypad_build_keymap(keymap_data, "linux,keymap", map_rows, map_cols, NULL, ppkb->input); if (ret) return dev_err_probe(dev, ret, "Failed to build keymap\n"); -- 2.33.1 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 3/5] Input: pinephone-keyboard - Build in the default keymap 2022-01-29 23:00 ` [PATCH 3/5] Input: pinephone-keyboard - Build in the default keymap Samuel Holland @ 2022-01-31 19:45 ` Dmitry Torokhov 2022-02-02 4:58 ` Samuel Holland 2022-04-12 10:20 ` Jarrah 1 sibling, 1 reply; 18+ messages in thread From: Dmitry Torokhov @ 2022-01-31 19:45 UTC (permalink / raw) To: Samuel Holland Cc: linux-input, linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang, Ondrej Jirman Hi Samuel, On Sat, Jan 29, 2022 at 05:00:40PM -0600, Samuel Holland wrote: > The PinePhone keyboard comes with removable keys, but there is a default > layout labeled from the factory. Use this keymap if none is provided in > the devicetree. Why can't we require to have it in device tree? Thanks. -- Dmitry ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/5] Input: pinephone-keyboard - Build in the default keymap 2022-01-31 19:45 ` Dmitry Torokhov @ 2022-02-02 4:58 ` Samuel Holland 2022-05-30 7:05 ` Pavel Machek 0 siblings, 1 reply; 18+ messages in thread From: Samuel Holland @ 2022-02-02 4:58 UTC (permalink / raw) To: Dmitry Torokhov Cc: linux-input, linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang, Ondrej Jirman Hi, On 1/31/22 1:45 PM, Dmitry Torokhov wrote: > Hi Samuel, > > On Sat, Jan 29, 2022 at 05:00:40PM -0600, Samuel Holland wrote: >> The PinePhone keyboard comes with removable keys, but there is a default >> layout labeled from the factory. Use this keymap if none is provided in >> the devicetree. > > Why can't we require to have it in device tree? We can. I am okay with dropping this patch and making the properties required if that is preferred. The keyboard is supported on at least four device trees (three revisions of PinePhone, plus the PinePhone Pro), so moving the default keymap to the driver avoids duplicating that block of data in each device tree/overlay. Regards, Samuel ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/5] Input: pinephone-keyboard - Build in the default keymap 2022-02-02 4:58 ` Samuel Holland @ 2022-05-30 7:05 ` Pavel Machek 0 siblings, 0 replies; 18+ messages in thread From: Pavel Machek @ 2022-05-30 7:05 UTC (permalink / raw) To: Samuel Holland Cc: Dmitry Torokhov, linux-input, linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang, Ondrej Jirman Hi! > > On Sat, Jan 29, 2022 at 05:00:40PM -0600, Samuel Holland wrote: > >> The PinePhone keyboard comes with removable keys, but there is a default > >> layout labeled from the factory. Use this keymap if none is provided in > >> the devicetree. > > > > Why can't we require to have it in device tree? > > We can. I am okay with dropping this patch and making the properties required if > that is preferred. > > The keyboard is supported on at least four device trees (three revisions of > PinePhone, plus the PinePhone Pro), so moving the default keymap to the driver > avoids duplicating that block of data in each device tree/overlay. #include is supported on dts, so there's no need to duplicate the keymaps, etc. Best regards, Pavel -- (english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/5] Input: pinephone-keyboard - Build in the default keymap 2022-01-29 23:00 ` [PATCH 3/5] Input: pinephone-keyboard - Build in the default keymap Samuel Holland 2022-01-31 19:45 ` Dmitry Torokhov @ 2022-04-12 10:20 ` Jarrah 2022-04-12 11:34 ` Ondřej Jirman 1 sibling, 1 reply; 18+ messages in thread From: Jarrah @ 2022-04-12 10:20 UTC (permalink / raw) To: Samuel Holland, Dmitry Torokhov, linux-input Cc: linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang, Ondrej Jirman On 1/30/22 10:00, Samuel Holland wrote: > + > +static const uint32_t ppkb_default_fn_keymap[] = { > + KEY(0, 0, KEY_FN_ESC), > + KEY(0, 1, KEY_F1), > + KEY(0, 2, KEY_F2), > + KEY(0, 3, KEY_F3), > + KEY(0, 4, KEY_F4), > + KEY(0, 5, KEY_F5), > + KEY(0, 6, KEY_F6), > + KEY(0, 7, KEY_F7), > + KEY(0, 8, KEY_F8), > + KEY(0, 9, KEY_F9), > + KEY(0, 10, KEY_F10), > + KEY(0, 11, KEY_DELETE), > + > + KEY(2, 0, KEY_SYSRQ), > + KEY(2, 10, KEY_INSERT), > + The driver currently being patched into most distros supporting the keyboard exposes the symbols printed on the keyboard rather than the F* keys on the function layer. While I agree than exposing function keys on the Fn layer is more logical, in practice running this patch for a day I've found it's far more useful to have quick access to the standard set of symbols (such as | and -) than to have the function keys. Would it be possible to either set the default back to symbols or expose another layer (potentially under the "pine" key)? An alternative solution proposed on the Mobian issue for this was to add a module option, allowing these to be switched at runtime rather than compile time. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/5] Input: pinephone-keyboard - Build in the default keymap 2022-04-12 10:20 ` Jarrah @ 2022-04-12 11:34 ` Ondřej Jirman 0 siblings, 0 replies; 18+ messages in thread From: Ondřej Jirman @ 2022-04-12 11:34 UTC (permalink / raw) To: Jarrah Cc: Samuel Holland, Dmitry Torokhov, linux-input, linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang On Tue, Apr 12, 2022 at 08:20:24PM +1000, Jarrah wrote: > > On 1/30/22 10:00, Samuel Holland wrote: > > + > > +static const uint32_t ppkb_default_fn_keymap[] = { > > + KEY(0, 0, KEY_FN_ESC), > > + KEY(0, 1, KEY_F1), > > + KEY(0, 2, KEY_F2), > > + KEY(0, 3, KEY_F3), > > + KEY(0, 4, KEY_F4), > > + KEY(0, 5, KEY_F5), > > + KEY(0, 6, KEY_F6), > > + KEY(0, 7, KEY_F7), > > + KEY(0, 8, KEY_F8), > > + KEY(0, 9, KEY_F9), > > + KEY(0, 10, KEY_F10), > > + KEY(0, 11, KEY_DELETE), > > + > > + KEY(2, 0, KEY_SYSRQ), > > + KEY(2, 10, KEY_INSERT), > > + > > > The driver currently being patched into most distros supporting the keyboard > exposes the symbols printed on the keyboard rather than the F* keys on the > function layer. While I agree than exposing function keys on the Fn layer is > more logical, in practice running this patch for a day I've found it's far > more useful to have quick access to the standard set of symbols (such as | > and -) than to have the function keys. > > Would it be possible to either set the default back to symbols or expose > another layer (potentially under the "pine" key)? An alternative solution > proposed on the Mobian issue for this was to add a module option, allowing > these to be switched at runtime rather than compile time. You will not get access to all the symbols anyway, this way. You should solve this via xkb and kernel keymaps (man keymaps(5)). Normal users should not be modifying basic keymap in DT or the driver anyway. kind regards, o. ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 4/5] Input: pinephone-keyboard - Support the proxied I2C bus 2022-01-29 23:00 [PATCH 0/5] Pine64 PinePhone keyboard support Samuel Holland ` (2 preceding siblings ...) 2022-01-29 23:00 ` [PATCH 3/5] Input: pinephone-keyboard - Build in the default keymap Samuel Holland @ 2022-01-29 23:00 ` Samuel Holland 2022-01-30 2:05 ` Ondřej Jirman 2022-01-29 23:00 ` [PATCH 5/5] [DO NOT MERGE] arm64: dts: allwinner: pinephone: Add keyboard Samuel Holland 4 siblings, 1 reply; 18+ messages in thread From: Samuel Holland @ 2022-01-29 23:00 UTC (permalink / raw) To: Dmitry Torokhov, linux-input Cc: linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang, Ondrej Jirman, Samuel Holland The PinePhone keyboard case contains a battery managed by an integrated power bank IC. The power bank IC communicates over I2C, and the keyboard MCU firmware provides an interface to read and write its registers. Let's use this interface to implement a SMBus adapter, so we can reuse the driver for the power bank IC. Signed-off-by: Samuel Holland <samuel@sholland.org> --- drivers/input/keyboard/pinephone-keyboard.c | 73 +++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/drivers/input/keyboard/pinephone-keyboard.c b/drivers/input/keyboard/pinephone-keyboard.c index 8065bc3e101a..7d2e16e588a0 100644 --- a/drivers/input/keyboard/pinephone-keyboard.c +++ b/drivers/input/keyboard/pinephone-keyboard.c @@ -3,6 +3,7 @@ // Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org> #include <linux/crc8.h> +#include <linux/delay.h> #include <linux/i2c.h> #include <linux/input/matrix_keypad.h> #include <linux/interrupt.h> @@ -23,6 +24,11 @@ #define PPKB_SCAN_DATA 0x08 #define PPKB_SYS_CONFIG 0x20 #define PPKB_SYS_CONFIG_DISABLE_SCAN BIT(0) +#define PPKB_SYS_SMBUS_COMMAND 0x21 +#define PPKB_SYS_SMBUS_DATA 0x22 +#define PPKB_SYS_COMMAND 0x23 +#define PPKB_SYS_COMMAND_SMBUS_READ 0x91 +#define PPKB_SYS_COMMAND_SMBUS_WRITE 0xa1 #define PPKB_DEFAULT_KEYMAP_ROWS 6 #define PPKB_DEFAULT_KEYMAP_COLS 12 @@ -132,6 +138,7 @@ static const struct matrix_keymap_data ppkb_default_keymap_data = { }; struct pinephone_keyboard { + struct i2c_adapter adapter; struct input_dev *input; unsigned short *fn_keymap; u8 crc_table[CRC8_TABLE_SIZE]; @@ -143,6 +150,57 @@ struct pinephone_keyboard { u8 buf[]; }; +static int ppkb_adap_smbus_xfer(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, + union i2c_smbus_data *data) +{ + struct i2c_client *client = adap->algo_data; + u8 buf[3]; + int ret; + + buf[0] = command; + buf[1] = data->byte; + buf[2] = read_write == I2C_SMBUS_READ ? PPKB_SYS_COMMAND_SMBUS_READ + : PPKB_SYS_COMMAND_SMBUS_WRITE; + + ret = i2c_smbus_write_i2c_block_data(client, PPKB_SYS_SMBUS_COMMAND, + sizeof(buf), buf); + if (ret) + return ret; + + /* Read back the command status until it passes or fails. */ + do { + usleep_range(300, 500); + ret = i2c_smbus_read_byte_data(client, PPKB_SYS_COMMAND); + } while (ret == buf[2]); + if (ret < 0) + return ret; + /* Commands return 0x00 on success and 0xff on failure. */ + if (ret) + return -EIO; + + if (read_write == I2C_SMBUS_READ) { + ret = i2c_smbus_read_byte_data(client, PPKB_SYS_SMBUS_DATA); + if (ret < 0) + return ret; + + data->byte = ret; + } + + return 0; +} + +static u32 ppkg_adap_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_BYTE_DATA; +} + +static const struct i2c_algorithm ppkb_adap_algo = { + .smbus_xfer = ppkb_adap_smbus_xfer, + .functionality = ppkg_adap_functionality, +}; + static int ppkb_set_scan(struct i2c_client *client, bool enable) { struct device *dev = &client->dev; @@ -265,6 +323,7 @@ static int ppkb_probe(struct i2c_client *client) unsigned int map_rows, map_cols; struct pinephone_keyboard *ppkb; u8 info[PPKB_MATRIX_SIZE + 1]; + struct device_node *i2c_bus; int ret; ret = i2c_smbus_read_i2c_block_data(client, 0, sizeof(info), info); @@ -312,6 +371,20 @@ static int ppkb_probe(struct i2c_client *client) i2c_set_clientdata(client, ppkb); + i2c_bus = of_get_child_by_name(dev->of_node, "i2c-bus"); + if (i2c_bus) { + ppkb->adapter.owner = THIS_MODULE; + ppkb->adapter.algo = &ppkb_adap_algo; + ppkb->adapter.algo_data = client; + ppkb->adapter.dev.parent = dev; + ppkb->adapter.dev.of_node = i2c_bus; + strscpy(ppkb->adapter.name, DRV_NAME, sizeof(ppkb->adapter.name)); + + ret = devm_i2c_add_adapter(dev, &ppkb->adapter); + if (ret) + return dev_err_probe(dev, ret, "Failed to add I2C adapter\n"); + } + crc8_populate_msb(ppkb->crc_table, PPKB_CRC8_POLYNOMIAL); ppkb->row_shift = get_count_order(map_cols); ppkb->rows = map_rows; -- 2.33.1 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 4/5] Input: pinephone-keyboard - Support the proxied I2C bus 2022-01-29 23:00 ` [PATCH 4/5] Input: pinephone-keyboard - Support the proxied I2C bus Samuel Holland @ 2022-01-30 2:05 ` Ondřej Jirman 2022-01-30 2:43 ` Samuel Holland 0 siblings, 1 reply; 18+ messages in thread From: Ondřej Jirman @ 2022-01-30 2:05 UTC (permalink / raw) To: Samuel Holland Cc: Dmitry Torokhov, linux-input, linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang Hello Samuel, On Sat, Jan 29, 2022 at 05:00:41PM -0600, Samuel Holland wrote: > The PinePhone keyboard case contains a battery managed by an integrated > power bank IC. The power bank IC communicates over I2C, and the keyboard > MCU firmware provides an interface to read and write its registers. > Let's use this interface to implement a SMBus adapter, so we can reuse > the driver for the power bank IC. > > Signed-off-by: Samuel Holland <samuel@sholland.org> > --- > > drivers/input/keyboard/pinephone-keyboard.c | 73 +++++++++++++++++++++ > 1 file changed, 73 insertions(+) > > diff --git a/drivers/input/keyboard/pinephone-keyboard.c b/drivers/input/keyboard/pinephone-keyboard.c > index 8065bc3e101a..7d2e16e588a0 100644 > --- a/drivers/input/keyboard/pinephone-keyboard.c > +++ b/drivers/input/keyboard/pinephone-keyboard.c > @@ -3,6 +3,7 @@ > // Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org> > > #include <linux/crc8.h> > +#include <linux/delay.h> > #include <linux/i2c.h> > #include <linux/input/matrix_keypad.h> > #include <linux/interrupt.h> > @@ -23,6 +24,11 @@ > #define PPKB_SCAN_DATA 0x08 > #define PPKB_SYS_CONFIG 0x20 > #define PPKB_SYS_CONFIG_DISABLE_SCAN BIT(0) > +#define PPKB_SYS_SMBUS_COMMAND 0x21 > +#define PPKB_SYS_SMBUS_DATA 0x22 > +#define PPKB_SYS_COMMAND 0x23 > +#define PPKB_SYS_COMMAND_SMBUS_READ 0x91 > +#define PPKB_SYS_COMMAND_SMBUS_WRITE 0xa1 > > #define PPKB_DEFAULT_KEYMAP_ROWS 6 > #define PPKB_DEFAULT_KEYMAP_COLS 12 > @@ -132,6 +138,7 @@ static const struct matrix_keymap_data ppkb_default_keymap_data = { > }; > > struct pinephone_keyboard { > + struct i2c_adapter adapter; > struct input_dev *input; > unsigned short *fn_keymap; > u8 crc_table[CRC8_TABLE_SIZE]; > @@ -143,6 +150,57 @@ struct pinephone_keyboard { > u8 buf[]; > }; > > +static int ppkb_adap_smbus_xfer(struct i2c_adapter *adap, u16 addr, > + unsigned short flags, char read_write, > + u8 command, int size, > + union i2c_smbus_data *data) > +{ > + struct i2c_client *client = adap->algo_data; > + u8 buf[3]; > + int ret; > + > + buf[0] = command; > + buf[1] = data->byte; > + buf[2] = read_write == I2C_SMBUS_READ ? PPKB_SYS_COMMAND_SMBUS_READ > + : PPKB_SYS_COMMAND_SMBUS_WRITE; > + > + ret = i2c_smbus_write_i2c_block_data(client, PPKB_SYS_SMBUS_COMMAND, > + sizeof(buf), buf); > + if (ret) > + return ret; [1] > + /* Read back the command status until it passes or fails. */ > + do { > + usleep_range(300, 500); > + ret = i2c_smbus_read_byte_data(client, PPKB_SYS_COMMAND); > + } while (ret == buf[2]); > + if (ret < 0) > + return ret; > + /* Commands return 0x00 on success and 0xff on failure. */ > + if (ret) > + return -EIO; > + > + if (read_write == I2C_SMBUS_READ) { > + ret = i2c_smbus_read_byte_data(client, PPKB_SYS_SMBUS_DATA); > + if (ret < 0) > + return ret; Please use a single read transfer to get both command result and data. There will be less risk that some userspace app will issue another command in between command status being read as 0 and data byte being read. Otherwise if you use this in some read/modify/write operation, you may write unexpected value to PMIC. I2C register layout is designed to make this as optimal as possible in a single I2C transaction, so you only need 3 bytes to start command and 2 bytes to read the result and data, both in a single xfer. There's very high likelihood the command will complete in those 300 - 500 us anyway, because the timing is predictable. If this delay is set right, it's almost guaranteed, only two xfers will be necessary to run the command and get the result+ status. And if possible, it would be best if the bus was somehow made busy for other users, until the whole comand/result sequence completes, to eliminate the possibility of another command being issued by other bus users around [1]. Thank you and kind regards, o. > + data->byte = ret; > + } > + > + return 0; > +} > + > +static u32 ppkg_adap_functionality(struct i2c_adapter *adap) > +{ > + return I2C_FUNC_SMBUS_BYTE_DATA; > +} > + > +static const struct i2c_algorithm ppkb_adap_algo = { > + .smbus_xfer = ppkb_adap_smbus_xfer, > + .functionality = ppkg_adap_functionality, > +}; > + > static int ppkb_set_scan(struct i2c_client *client, bool enable) > { > struct device *dev = &client->dev; > @@ -265,6 +323,7 @@ static int ppkb_probe(struct i2c_client *client) > unsigned int map_rows, map_cols; > struct pinephone_keyboard *ppkb; > u8 info[PPKB_MATRIX_SIZE + 1]; > + struct device_node *i2c_bus; > int ret; > > ret = i2c_smbus_read_i2c_block_data(client, 0, sizeof(info), info); > @@ -312,6 +371,20 @@ static int ppkb_probe(struct i2c_client *client) > > i2c_set_clientdata(client, ppkb); > > + i2c_bus = of_get_child_by_name(dev->of_node, "i2c-bus"); > + if (i2c_bus) { > + ppkb->adapter.owner = THIS_MODULE; > + ppkb->adapter.algo = &ppkb_adap_algo; > + ppkb->adapter.algo_data = client; > + ppkb->adapter.dev.parent = dev; > + ppkb->adapter.dev.of_node = i2c_bus; > + strscpy(ppkb->adapter.name, DRV_NAME, sizeof(ppkb->adapter.name)); > + > + ret = devm_i2c_add_adapter(dev, &ppkb->adapter); > + if (ret) > + return dev_err_probe(dev, ret, "Failed to add I2C adapter\n"); > + } > + > crc8_populate_msb(ppkb->crc_table, PPKB_CRC8_POLYNOMIAL); > ppkb->row_shift = get_count_order(map_cols); > ppkb->rows = map_rows; > -- > 2.33.1 > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/5] Input: pinephone-keyboard - Support the proxied I2C bus 2022-01-30 2:05 ` Ondřej Jirman @ 2022-01-30 2:43 ` Samuel Holland 2022-01-30 3:00 ` Ondřej Jirman 0 siblings, 1 reply; 18+ messages in thread From: Samuel Holland @ 2022-01-30 2:43 UTC (permalink / raw) To: Ondřej Jirman, Dmitry Torokhov, linux-input, linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang On 1/29/22 8:05 PM, Ondřej Jirman wrote: > Hello Samuel, > > On Sat, Jan 29, 2022 at 05:00:41PM -0600, Samuel Holland wrote: >> The PinePhone keyboard case contains a battery managed by an integrated >> power bank IC. The power bank IC communicates over I2C, and the keyboard >> MCU firmware provides an interface to read and write its registers. >> Let's use this interface to implement a SMBus adapter, so we can reuse >> the driver for the power bank IC. >> >> Signed-off-by: Samuel Holland <samuel@sholland.org> >> --- >> >> drivers/input/keyboard/pinephone-keyboard.c | 73 +++++++++++++++++++++ >> 1 file changed, 73 insertions(+) >> >> diff --git a/drivers/input/keyboard/pinephone-keyboard.c b/drivers/input/keyboard/pinephone-keyboard.c >> index 8065bc3e101a..7d2e16e588a0 100644 >> --- a/drivers/input/keyboard/pinephone-keyboard.c >> +++ b/drivers/input/keyboard/pinephone-keyboard.c >> @@ -3,6 +3,7 @@ >> // Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org> >> >> #include <linux/crc8.h> >> +#include <linux/delay.h> >> #include <linux/i2c.h> >> #include <linux/input/matrix_keypad.h> >> #include <linux/interrupt.h> >> @@ -23,6 +24,11 @@ >> #define PPKB_SCAN_DATA 0x08 >> #define PPKB_SYS_CONFIG 0x20 >> #define PPKB_SYS_CONFIG_DISABLE_SCAN BIT(0) >> +#define PPKB_SYS_SMBUS_COMMAND 0x21 >> +#define PPKB_SYS_SMBUS_DATA 0x22 >> +#define PPKB_SYS_COMMAND 0x23 >> +#define PPKB_SYS_COMMAND_SMBUS_READ 0x91 >> +#define PPKB_SYS_COMMAND_SMBUS_WRITE 0xa1 >> >> #define PPKB_DEFAULT_KEYMAP_ROWS 6 >> #define PPKB_DEFAULT_KEYMAP_COLS 12 >> @@ -132,6 +138,7 @@ static const struct matrix_keymap_data ppkb_default_keymap_data = { >> }; >> >> struct pinephone_keyboard { >> + struct i2c_adapter adapter; >> struct input_dev *input; >> unsigned short *fn_keymap; >> u8 crc_table[CRC8_TABLE_SIZE]; >> @@ -143,6 +150,57 @@ struct pinephone_keyboard { >> u8 buf[]; >> }; >> >> +static int ppkb_adap_smbus_xfer(struct i2c_adapter *adap, u16 addr, >> + unsigned short flags, char read_write, >> + u8 command, int size, >> + union i2c_smbus_data *data) >> +{ >> + struct i2c_client *client = adap->algo_data; >> + u8 buf[3]; >> + int ret; >> + >> + buf[0] = command; >> + buf[1] = data->byte; >> + buf[2] = read_write == I2C_SMBUS_READ ? PPKB_SYS_COMMAND_SMBUS_READ >> + : PPKB_SYS_COMMAND_SMBUS_WRITE; >> + >> + ret = i2c_smbus_write_i2c_block_data(client, PPKB_SYS_SMBUS_COMMAND, >> + sizeof(buf), buf); >> + if (ret) >> + return ret; > > [1] > >> + /* Read back the command status until it passes or fails. */ >> + do { >> + usleep_range(300, 500); >> + ret = i2c_smbus_read_byte_data(client, PPKB_SYS_COMMAND); >> + } while (ret == buf[2]); >> + if (ret < 0) >> + return ret; >> + /* Commands return 0x00 on success and 0xff on failure. */ >> + if (ret) >> + return -EIO; >> + >> + if (read_write == I2C_SMBUS_READ) { >> + ret = i2c_smbus_read_byte_data(client, PPKB_SYS_SMBUS_DATA); >> + if (ret < 0) >> + return ret; > > Please use a single read transfer to get both command result and data. > There will be less risk that some userspace app will issue another command > in between command status being read as 0 and data byte being read. > > Otherwise if you use this in some read/modify/write operation, you > may write unexpected value to PMIC. I2C register layout is designed > to make this as optimal as possible in a single I2C transaction, so > you only need 3 bytes to start command and 2 bytes to read the result > and data, both in a single xfer. There's very high likelihood the command > will complete in those 300 - 500 us anyway, because the timing is > predictable. If this delay is set right, it's almost guaranteed, > only two xfers will be necessary to run the command and get the result+ > status. I did this originally, but it causes a different race condition: since the data is read first, the command can complete between when the data is read and when the result is read. If this happens, the command will be seen as complete, but the data will be garbage. This caused occasional read errors for the charger's power supply properties, because I2C reads sometimes returned nonsensical values for those bytes. > And if possible, it would be best if the bus was somehow made busy for > other users, until the whole comand/result sequence completes, to eliminate > the possibility of another command being issued by other bus users > around [1]. Yes, I can add a call to i2c_lock_bus() here. Regards, Samuel > Thank you and kind regards, > o. > >> + data->byte = ret; >> + } >> + >> + return 0; >> +} >> + >> +static u32 ppkg_adap_functionality(struct i2c_adapter *adap) >> +{ >> + return I2C_FUNC_SMBUS_BYTE_DATA; >> +} >> + >> +static const struct i2c_algorithm ppkb_adap_algo = { >> + .smbus_xfer = ppkb_adap_smbus_xfer, >> + .functionality = ppkg_adap_functionality, >> +}; >> + >> static int ppkb_set_scan(struct i2c_client *client, bool enable) >> { >> struct device *dev = &client->dev; >> @@ -265,6 +323,7 @@ static int ppkb_probe(struct i2c_client *client) >> unsigned int map_rows, map_cols; >> struct pinephone_keyboard *ppkb; >> u8 info[PPKB_MATRIX_SIZE + 1]; >> + struct device_node *i2c_bus; >> int ret; >> >> ret = i2c_smbus_read_i2c_block_data(client, 0, sizeof(info), info); >> @@ -312,6 +371,20 @@ static int ppkb_probe(struct i2c_client *client) >> >> i2c_set_clientdata(client, ppkb); >> >> + i2c_bus = of_get_child_by_name(dev->of_node, "i2c-bus"); >> + if (i2c_bus) { >> + ppkb->adapter.owner = THIS_MODULE; >> + ppkb->adapter.algo = &ppkb_adap_algo; >> + ppkb->adapter.algo_data = client; >> + ppkb->adapter.dev.parent = dev; >> + ppkb->adapter.dev.of_node = i2c_bus; >> + strscpy(ppkb->adapter.name, DRV_NAME, sizeof(ppkb->adapter.name)); >> + >> + ret = devm_i2c_add_adapter(dev, &ppkb->adapter); >> + if (ret) >> + return dev_err_probe(dev, ret, "Failed to add I2C adapter\n"); >> + } >> + >> crc8_populate_msb(ppkb->crc_table, PPKB_CRC8_POLYNOMIAL); >> ppkb->row_shift = get_count_order(map_cols); >> ppkb->rows = map_rows; >> -- >> 2.33.1 >> ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/5] Input: pinephone-keyboard - Support the proxied I2C bus 2022-01-30 2:43 ` Samuel Holland @ 2022-01-30 3:00 ` Ondřej Jirman 0 siblings, 0 replies; 18+ messages in thread From: Ondřej Jirman @ 2022-01-30 3:00 UTC (permalink / raw) To: Samuel Holland Cc: Dmitry Torokhov, linux-input, linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang On Sat, Jan 29, 2022 at 08:43:30PM -0600, Samuel Holland wrote: > On 1/29/22 8:05 PM, Ondřej Jirman wrote: > > > > Please use a single read transfer to get both command result and data. > > There will be less risk that some userspace app will issue another command > > in between command status being read as 0 and data byte being read. > > > > Otherwise if you use this in some read/modify/write operation, you > > may write unexpected value to PMIC. I2C register layout is designed > > to make this as optimal as possible in a single I2C transaction, so > > you only need 3 bytes to start command and 2 bytes to read the result > > and data, both in a single xfer. There's very high likelihood the command > > will complete in those 300 - 500 us anyway, because the timing is > > predictable. If this delay is set right, it's almost guaranteed, > > only two xfers will be necessary to run the command and get the result+ > > status. > > I did this originally, but it causes a different race condition: since the data > is read first, the command can complete between when the data is read and when > the result is read. If this happens, the command will be seen as complete, but > the data will be garbage. > > This caused occasional read errors for the charger's power supply properties, > because I2C reads sometimes returned nonsensical values for those bytes. Oh, well. :) I guess the firmware would need to wait for any ongoing I2C tranfer to finish before setting the command status to 0, for this to work. Another lesson learned. :( > > And if possible, it would be best if the bus was somehow made busy for > > other users, until the whole comand/result sequence completes, to eliminate > > the possibility of another command being issued by other bus users > > around [1]. > > Yes, I can add a call to i2c_lock_bus() here. Perfect. thank you, o. > Regards, > Samuel ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 5/5] [DO NOT MERGE] arm64: dts: allwinner: pinephone: Add keyboard 2022-01-29 23:00 [PATCH 0/5] Pine64 PinePhone keyboard support Samuel Holland ` (3 preceding siblings ...) 2022-01-29 23:00 ` [PATCH 4/5] Input: pinephone-keyboard - Support the proxied I2C bus Samuel Holland @ 2022-01-29 23:00 ` Samuel Holland 4 siblings, 0 replies; 18+ messages in thread From: Samuel Holland @ 2022-01-29 23:00 UTC (permalink / raw) To: Dmitry Torokhov, linux-input Cc: linux-kernel, Rob Herring, devicetree, linux-i2c, Wolfram Sang, Ondrej Jirman, Samuel Holland The official PinePhone keyboard accessory connects to the phone's POGO pins for I2C and interrupts. It has an Injoinic IP5209 power bank IC connected to the keyboard's internal I2C bus. Signed-off-by: Samuel Holland <samuel@sholland.org> --- .../dts/allwinner/sun50i-a64-pinephone.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi index 87847116ab6d..2fa1bdf8aa63 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinephone.dtsi @@ -208,6 +208,24 @@ accelerometer@68 { /* Connected to pogo pins (external spring based pinheader for user addons) */ &i2c2 { status = "okay"; + + keyboard@15 { + compatible = "pine64,pinephone-keyboard"; + reg = <0x15>; + interrupt-parent = <&r_pio>; + interrupts = <0 12 IRQ_TYPE_EDGE_FALLING>; /* PL12 */ + wakeup-source; + + i2c-bus { + #address-cells = <1>; + #size-cells = <0>; + + charger@75 { + compatible = "injoinic,ip5209"; + reg = <0x75>; + }; + }; + }; }; &lradc { -- 2.33.1 ^ permalink raw reply related [flat|nested] 18+ messages in thread
end of thread, other threads:[~2022-05-30 7:06 UTC | newest] Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-01-29 23:00 [PATCH 0/5] Pine64 PinePhone keyboard support Samuel Holland 2022-01-29 23:00 ` [PATCH 1/5] dt-bindings: input: Add the PinePhone keyboard binding Samuel Holland 2022-02-11 13:23 ` Rob Herring 2022-02-14 4:41 ` Samuel Holland 2022-01-29 23:00 ` [PATCH 2/5] Input: pinephone-keyboard - Add PinePhone keyboard driver Samuel Holland 2022-02-02 8:07 ` Ondřej Jirman 2022-02-02 11:48 ` Ondřej Jirman 2022-01-29 23:00 ` [PATCH 3/5] Input: pinephone-keyboard - Build in the default keymap Samuel Holland 2022-01-31 19:45 ` Dmitry Torokhov 2022-02-02 4:58 ` Samuel Holland 2022-05-30 7:05 ` Pavel Machek 2022-04-12 10:20 ` Jarrah 2022-04-12 11:34 ` Ondřej Jirman 2022-01-29 23:00 ` [PATCH 4/5] Input: pinephone-keyboard - Support the proxied I2C bus Samuel Holland 2022-01-30 2:05 ` Ondřej Jirman 2022-01-30 2:43 ` Samuel Holland 2022-01-30 3:00 ` Ondřej Jirman 2022-01-29 23:00 ` [PATCH 5/5] [DO NOT MERGE] arm64: dts: allwinner: pinephone: Add keyboard Samuel Holland
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).