Re: [PATCH v6 4/4] Input: Add TouchNetix aXiom I2C Touchscreen support

From: Andrew Thomas

Date: Fri Mar 13 2026 - 13:16:35 EST


On Tue, Mar 03, 2026 at 11:41:22PM +0100, Marco Felsch wrote:
>This adds the initial support for the TouchNetix AX54A touchcontroller
>which is part of TouchNetix's aXiom touchscreen controller family.
>
>The TouchNetix aXiom family provides two physical interfaces: SPI and
>I2C. This patch covers only the I2C interface.
>
>Apart the input event handling the driver supports firmware updates too.
>One firmware interface handles the touchcontroller firmware (AXFW)
>update the other handles the touchcontroller configuration (TH2CFGBIN)
>update.
>
>Signed-off-by: Marco Felsch <m.felsch@xxxxxxxxxxxxxx>
>---
> .../testing/sysfs-driver-input-touchnetix-axiom | 80 +
> drivers/input/touchscreen/Kconfig | 17 +
> drivers/input/touchscreen/Makefile | 1 +
> drivers/input/touchscreen/touchnetix_axiom.c | 3084 ++++++++++++++++++++
> 4 files changed, 3182 insertions(+)
>
>diff --git a/Documentation/ABI/testing/sysfs-driver-input-touchnetix-axiom b/Documentation/ABI/testing/sysfs-driver-input-touchnetix-axiom
>new file mode 100644
>index 0000000000000000000000000000000000000000..8262673630557bf1e595a97ec23e66c1c5370f71
>--- /dev/null
>+++ b/Documentation/ABI/testing/sysfs-driver-input-touchnetix-axiom
>@@ -0,0 +1,80 @@
>+What: /sys/bus/i2c/devices/xxx/fw_major
>+Date: Jan 2026
>+Contact: linux-input@xxxxxxxxxxxxxxx
>+Description:
>+ Reports the firmware major version provided by the touchscreen.
>+
>+ Access: Read
>+
>+ Valid values: Represented as string
>+
>+What: /sys/bus/i2c/devices/xxx/fw_minor
>+Date: Jan 2026
>+Contact: linux-input@xxxxxxxxxxxxxxx
>+Description:
>+ Reports the firmware minor version provided by the touchscreen.
>+
>+ Access: Read
>+
>+ Valid values: Represented as string
>+
>+What: /sys/bus/i2c/devices/xxx/fw_rc
>+Date: Jan 2026
>+Contact: linux-input@xxxxxxxxxxxxxxx
>+Description:
>+ Reports the firmware release canidate version provided by the touchscreen.
>+
>+ Access: Read
>+
>+ Valid values: Represented as string
>+
>+What: /sys/bus/i2c/devices/xxx/fw_status
>+Date: Jan 2026
>+Contact: linux-input@xxxxxxxxxxxxxxx
>+Description:
>+ Reports the firmware status provided by the touchscreen. It may
>+ be either "release" or "engineering".
>+
>+ Access: Read
>+
>+ Valid values: Represented as string
>+
>+What: /sys/bus/i2c/devices/xxx/fw_variant
>+Date: Jan 2026
>+Contact: linux-input@xxxxxxxxxxxxxxx
>+Description:
>+ Reports the firmware variant provided by the touchscreen. It may
>+ be either: "0d", "2d", "3d", "force", "xl" or "unknown".
>+
>+ Access: Read
>+
>+ Valid values: Represented as string
>+
>+What: /sys/bus/i2c/devices/xxx/device_id
>+Date: Jan 2026
>+Contact: linux-input@xxxxxxxxxxxxxxx
>+Description:
>+ Reports the touchscreen device id, for example: "54" for the AX54A.
>+
>+ Access: Read
>+
>+ Valid values: Represented as string
>+
>+What: /sys/bus/i2c/devices/xxx/device_state
>+Date: Jan 2026
>+Contact: linux-input@xxxxxxxxxxxxxxx
>+Description:
>+ Reports the touchscreen device current runtime state. The
>+ following values are reported:
>+
>+ discovery: Device is in discovery mode.
>+ tcp: Device is in touch-control-protocol (tcp) mode. This is
>+ the normal working mode.
>+ th2cfg-update: Device is in configuration update mode.
>+ bootloader: Device is in bootloader mode, used for firmware
>+ updates.
>+ unknown: Device mode is unknown.
>+
>+ Access: Read
>+
>+ Valid values: Represented as string
>diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
>index 196905162945d59e775c3e0bff6540a82842229a..9263dd79dab7e518e27af35364fcebbff0ba706e 100644
>--- a/drivers/input/touchscreen/Kconfig
>+++ b/drivers/input/touchscreen/Kconfig
>@@ -806,6 +806,23 @@ config TOUCHSCREEN_MIGOR
> To compile this driver as a module, choose M here: the
> module will be called migor_ts.
>
>+config TOUCHSCREEN_TOUCHNETIX_AXIOM
>+ tristate "TouchNetix aXiom based touchscreen controllers"
>+ # We need to call into panel code so if DRM=m, this can't be 'y'
>+ depends on DRM || !DRM
>+ depends on I2C
>+ select CRC16
>+ select CRC32
>+ select REGMAP_I2C
>+ help
>+ Say Y here if you have a axiom touchscreen connected to
>+ your system.
>+
>+ If unsure, say N.
>+
>+ To compile this driver as a module, choose M here: the
>+ module will be called touchnetix_axiom.
>+
> config TOUCHSCREEN_TOUCHRIGHT
> tristate "Touchright serial touchscreen"
> select SERIO
>diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
>index 97a025c6a3770fb80255246eb63c11688ebd79eb..0591cb304784699bf2a8bda204461ac5f4532bb1 100644
>--- a/drivers/input/touchscreen/Makefile
>+++ b/drivers/input/touchscreen/Makefile
>@@ -88,6 +88,7 @@ obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o
> obj-$(CONFIG_TOUCHSCREEN_SURFACE3_SPI) += surface3_spi.o
> obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
> obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
>+obj-$(CONFIG_TOUCHSCREEN_TOUCHNETIX_AXIOM) += touchnetix_axiom.o
> obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
> obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
> obj-$(CONFIG_TOUCHSCREEN_TS4800) += ts4800-ts.o
>diff --git a/drivers/input/touchscreen/touchnetix_axiom.c b/drivers/input/touchscreen/touchnetix_axiom.c
>new file mode 100644
>index 0000000000000000000000000000000000000000..d909b108ee24dfc5a56b0ba735cb8a7882612d34
>--- /dev/null
>+++ b/drivers/input/touchscreen/touchnetix_axiom.c
>@@ -0,0 +1,3084 @@
>+// SPDX-License-Identifier: GPL-2.0-only
>+/*
>+ * TouchNetix aXiom Touchscreen Driver
>+ *
>+ * Copyright (C) 2024 Pengutronix
>+ *
>+ * Marco Felsch <kernel@xxxxxxxxxxxxxx>
>+ */
>+
>+#include <drm/drm_panel.h>
>+#include <linux/bitfield.h>
>+#include <linux/bits.h>
>+#include <linux/completion.h>
>+#include <linux/crc16.h>
>+#include <linux/crc32.h>
>+#include <linux/delay.h>

...

>+static int axiom_u02_enter_bootloader(struct axiom_data *ts)
>+{
>+ struct axiom_u02_rev1_system_manager_msg msg = { };
>+ struct device *dev = ts->dev;
>+ unsigned int val;
>+ int error;
>+
>+ if (!axiom_driver_supports_usage(ts, AXIOM_U02))
>+ return -EINVAL;
>+
>+ /*
>+ * Enter the bootloader mode requires 3 consecutive messages so we can't
>+ * check for the response.
>+ * TODO: Check if it's required to add a delay between the consecutive
>+ * CMD_ENTERBOOTLOADER cmds.
>+ */
>+ msg.command = cpu_to_le16(AXIOM_U02_REV1_CMD_ENTERBOOTLOADER);
>+ msg.parameters[0] = cpu_to_le16(AXIOM_U02_REV1_PARAM0_ENTERBOOLOADER_KEY1);
>+ error = axiom_u02_send_msg(ts, &msg, false);

As mentioned before the delay between commands is too short and the next command is sent
before u02 is ready, which means the driver fails to put axiom into the bootloader.
Have you tested with an i2c speed of 400KHz?
All you need is to put true in above to wait for the bootloader command.
error = axiom_u02_send_msg(ts, &msg, true);

Just dont do it for the last command.

I am not too sure why you are having issues with this, this is how we do it for all our devices.

>+ if (error) {
>+ dev_err(dev, "Failed to send bootloader-key1: %d\n", error);
>+ return error;
>+ }
>+
>+ msg.parameters[0] = cpu_to_le16(AXIOM_U02_REV1_PARAM0_ENTERBOOLOADER_KEY2);
>+ error = axiom_u02_send_msg(ts, &msg, false);

Here also.

>+ if (error) {
>+ dev_err(dev, "Failed to send bootloader-key2: %d\n", error);
>+ return error;
>+ }
>+
>+ msg.parameters[0] = cpu_to_le16(AXIOM_U02_REV1_PARAM0_ENTERBOOLOADER_KEY3);
>+ error = axiom_u02_send_msg(ts, &msg, false);
>+ if (error) {
>+ dev_err(dev, "Failed to send bootloader-key3: %d\n", error);
>+ return error;
>+ }
>+
>+ /* Sleep before the first read to give the device time */
>+ fsleep(250 * USEC_PER_MSEC);
>+
>+ /* Wait till the device reports it is in bootloader mode */
>+ error = regmap_read_poll_timeout(ts->regmap,
>+ AXIOM_U31_REV1_DEVICE_ID_HIGH_REG, val,
>+ FIELD_GET(AXIOM_U31_REV1_MODE_MASK, val) ==
>+ AXIOM_U31_REV1_MODE_BLP,
>+ 250 * USEC_PER_MSEC, USEC_PER_SEC);
>+ if (error)
>+ return error;
>+
>+ return 0;
>+}
>+

...


Other than the above comments I have no issues with the driver.
We can support more usages in a later patch.

Many Thanks,
Andrew