[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250610181542.GA2396962-robh@kernel.org>
Date: Tue, 10 Jun 2025 13:15:42 -0500
From: Rob Herring <robh@...nel.org>
To: Tomáš Juřena <jurenatomas@...il.com>
Cc: dmitry.torokhov@...il.com, krzk+dt@...nel.org, conor+dt@...nel.org,
linux-input@...r.kernel.org, devicetree@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH] Input: tca6416-keypad - Add OF support for driver
instantiation
On Tue, Jun 10, 2025 at 05:46:10PM +0200, Tomáš Juřena wrote:
> From: Tomas Jurena <jurenatomas@...il.com>
>
> Adds support for instantiating the tca6416-keypad driver via
> Device Tree. If no platform data is present, the driver can now be
> probed based on OF bindings.
>
> A corresponding Device Tree binding document is added at:
> Documentation/devicetree/bindings/input/tca6416-keypad.yaml
>
> This allows the driver to be used in systems that rely solely on the
> Device Tree for hardware description, such as embedded ARM platforms.
>
> Tested on Toradex Ixora 1.3A board and Apalis imx8 SOM.
We already have a GPIO driver for this chip. Would the
gpio-keys driver work here instead? Seems to work for
arch/arm/boot/dts/ti/omap/am3517-evm-ui.dtsi.
>
> Signed-off-by: Tomas Jurena <jurenatomas@...il.com>
> ---
> .../bindings/input/tca6416-keypad.yaml | 87 ++++++++++++++++++
Bindings should be a separate patch.
> drivers/input/keyboard/tca6416-keypad.c | 88 +++++++++++++++++--
> 2 files changed, 170 insertions(+), 5 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/input/tca6416-keypad.yaml
>
> diff --git a/Documentation/devicetree/bindings/input/tca6416-keypad.yaml b/Documentation/devicetree/bindings/input/tca6416-keypad.yaml
> new file mode 100644
> index 000000000000..f050403c4dbe
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/tca6416-keypad.yaml
> @@ -0,0 +1,87 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/input/tca6416-keypad.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: TI TCA6416 keypad
> +
> +maintainers:
> +
> +description: |
Don't need '|'
> + Texas Instruments TCA6416 IO expander as a keypad input device.
> +
> +allOf:
> + - $ref: input.yaml#
> +
> +properties:
> + compatible:
> + enum:
> + - ti,tca6416_keys
> + - ti,tca6408_keys
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + linux,gpio-keymap:
linux,keymap
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + description: |
> + Array of gpio keys provided by the driver instance. Each entry is a
> + bitfield holding configuration of the input key. The bitfield looks like
> + this:
> + +------------------------------------------------------------+
> + | Bits | 31:18 | 17 | 16:14 | 13:10 | 9:0 |
> + | Function | reserved | active_low | type | reserved | code |
> + +------------------------------------------------------------+
> + code - Linux key code
> + type - EV_KEY or EV_SW
> + active_low - Key is active in low state
> +
> + linux,keycodes:
> + minItems: 1
> + maxItems: 16
> +
> + autorepeat:
> + type: boolean
> + description: |
> + Enables the Linux input system's autorepeat feature on the input device.
> +
> + polling:
> + type: boolean
> + description: |
> + Forces driver to use polling mode instead of IRQ.
> +
> + pinmask:
> + description: |
> + Allows to disable certain keys. By default are all inputs enabled.
> +
> +required:
> + - compatible
> + - reg
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/irq.h>
> +
> + i2c {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + keypad@21 {
> + compatible = "ti,tca6416_keys";
> + reg = <0x21>;
> + interrupt-parent = <&gpio>;
> + interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
> + linux,gpio-keymap = <
> + 0x24290, // active low, EV_KEY, 0, KEY_MACRO1
> + 0x24291, // active low, EV_KEY, 1, KEY_MACRO2
> + 0x24292, // active low, EV_KEY, 2, KEY_MACRO3
> + >;
> + };
> + };
> +
> +...
> diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c
> index fbc674d7b9f0..8910498cf266 100644
> --- a/drivers/input/keyboard/tca6416-keypad.c
> +++ b/drivers/input/keyboard/tca6416-keypad.c
> @@ -17,6 +17,7 @@
> #include <linux/i2c.h>
> #include <linux/input.h>
> #include <linux/tca6416_keypad.h>
> +#include <linux/bitfield.h>
>
> #define TCA6416_INPUT 0
> #define TCA6416_OUTPUT 1
> @@ -24,6 +25,7 @@
> #define TCA6416_DIRECTION 3
>
> #define TCA6416_POLL_INTERVAL 100 /* msec */
> +#define TCA6416_MAX_IO_SIZE 16 /* maximum number of inputs */
>
> static const struct i2c_device_id tca6416_id[] = {
> { "tca6416-keys", 16, },
> @@ -173,9 +175,67 @@ static int tca6416_setup_registers(struct tca6416_keypad_chip *chip)
> return 0;
> }
>
> +/* Configuration bitmap
> + * | 31:18 | 17 | 16:14 | 13:10 | 9:0 |
> + * | reserved | active_low | type | reserved | code |
> + */
> +#define CFG_CODE GENMASK(9, 0)
> +#define CFG_TYPE GENMASK(16, 14)
> +#define CFG_ACTIVE_LOW BIT(17)
> +
> +static struct tca6416_keys_platform_data *
> +tca6416_parse_properties(struct device *dev, uint8_t io_size)
> +{
> + static const char keymap_property[] = "linux,gpio-keymap";
> + struct tca6416_keys_platform_data *pdata;
> + u32 keymap[TCA6416_MAX_IO_SIZE];
> + struct tca6416_button *buttons;
> + int ret, i;
> + u8 pin;
> +
> + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> + if (!pdata)
> + return NULL;
> +
> + ret = device_property_count_u32(dev, keymap_property);
> + if (ret <= 0)
> + return NULL;
> +
> + pdata->nbuttons = ret;
> + if (pdata->nbuttons > io_size)
> + pdata->nbuttons = io_size;
> +
> + ret = device_property_read_u32_array(dev, keymap_property, keymap,
> + pdata->nbuttons);
> + if (ret)
> + return NULL;
> +
> + buttons = devm_kcalloc(dev, pdata->nbuttons, sizeof(*buttons),
> + GFP_KERNEL);
> + if (!buttons)
> + return NULL;
> +
> + for (i = 0; i < pdata->nbuttons; i++) {
> + buttons[i].code = FIELD_GET(CFG_CODE, keymap[i]);
> + buttons[i].type = FIELD_GET(CFG_TYPE, keymap[i]);
> + buttons[i].active_low = FIELD_GET(CFG_ACTIVE_LOW, keymap[i]);
> + /* enable all inputs by default */
> + pdata->pinmask |= BIT(i);
> + }
> +
> + pdata->buttons = buttons;
> +
> + pdata->rep = device_property_read_bool(dev, "autorepeat");
> + /* we can ignore the result as by default all inputs are enabled */
> + device_property_read_u16(dev, "pinmask", &pdata->pinmask);
> + pdata->use_polling = device_property_read_bool(dev, "polling");
> +
> + return pdata;
> +}
> +
> static int tca6416_keypad_probe(struct i2c_client *client)
> {
> - const struct i2c_device_id *id = i2c_client_get_device_id(client);
> + uint8_t io_size = (uintptr_t)i2c_get_match_data(client);
> struct tca6416_keys_platform_data *pdata;
> struct tca6416_keypad_chip *chip;
> struct input_dev *input;
> @@ -190,9 +250,13 @@ static int tca6416_keypad_probe(struct i2c_client *client)
> }
>
> pdata = dev_get_platdata(&client->dev);
> - if (!pdata) {
> - dev_dbg(&client->dev, "no platform data\n");
> - return -EINVAL;
> + if (!pdata && dev_fwnode(&client->dev)) {
> + pdata = tca6416_parse_properties(&client->dev, io_size);
> + if (!pdata) {
> + dev_err(&client->dev,
> + "Failed to parse device configuration from properties\n");
> + return -EINVAL;
> + }
> }
>
> chip = devm_kzalloc(&client->dev,
> @@ -207,7 +271,7 @@ static int tca6416_keypad_probe(struct i2c_client *client)
>
> chip->client = client;
> chip->input = input;
> - chip->io_size = id->driver_data;
> + chip->io_size = io_size;
> chip->pinmask = pdata->pinmask;
> chip->use_polling = pdata->use_polling;
>
> @@ -279,9 +343,23 @@ static int tca6416_keypad_probe(struct i2c_client *client)
> return 0;
> }
>
> +static const struct of_device_id tca6416_of_match[] = {
> + {
> + .compatible = "ti,tca6416_keys",
> + .data = (void *)16,
> + },
> + {
> + .compatible = "ti,tca6408_keys",
> + .data = (void *)8,
> + },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, tca6416_of_match);
> +
> static struct i2c_driver tca6416_keypad_driver = {
> .driver = {
> .name = "tca6416-keypad",
> + .of_match_table = tca6416_of_match,
> },
> .probe = tca6416_keypad_probe,
> .id_table = tca6416_id,
> --
> 2.34.1
>
Powered by blists - more mailing lists