* [PATCH v2] media: rc: fix race between unregister and urb/irq callbacks
From: Sean Young @ 2026-01-26 13:31 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter,
Bruno Prémont, Jiri Kosina, Benjamin Tissoires, Hans Verkuil,
Mauro Carvalho Chehab, Maxim Levitsky, Patrice Chotard,
Chen-Yu Tsai, Samuel Holland, David Härdeman,
Benjamin Valentin, Greg Kroah-Hartman
Cc: Haotian Zhang, dri-devel, linux-kernel, linux-input, linux-media,
linux-arm-kernel, linux-sunxi, linux-staging
Some rc device drivers have a race condition between rc_unregister_device()
and irq or urb callbacks. This is because rc_unregister_device() does two
things, it marks the device as unregistered so no new commands can be
issued and then it calls rc_free_device(). This means the driver has no
chance to cancel any pending urb callbacks or interrupts after the device
has been marked as unregistered. Those callbacks may access struct rc_dev
or its members (e.g. struct ir_raw_event_ctrl), which have been freed by
rc_free_device().
This change removes the implicit call to rc_free_device() from
rc_unregister_device(). This means that device drivers can call
rc_unregister_device() in their remove or disconnect function, then cancel
all the urbs and interrupts before explicitly calling rc_free_device().
Note this is an alternative fix for an issue found by Haotian Zhang, see
the Closes: tags.
Reported-by: Haotian Zhang <vulab@iscas.ac.cn>
Closes: https://lore.kernel.org/linux-media/20251114101432.2566-1-vulab@iscas.ac.cn/
Closes: https://lore.kernel.org/linux-media/20251114101418.2548-1-vulab@iscas.ac.cn/
Closes: https://lore.kernel.org/linux-media/20251114101346.2530-1-vulab@iscas.ac.cn/
Closes: https://lore.kernel.org/linux-media/20251114090605.2413-1-vulab@iscas.ac.cn/
Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com>
Signed-off-by: Sean Young <sean@mess.org>
---
drivers/gpu/drm/bridge/sil-sii8620.c | 1 +
drivers/hid/hid-picolcd_cir.c | 1 +
drivers/media/cec/core/cec-core.c | 2 +-
drivers/media/common/siano/smsir.c | 1 +
drivers/media/i2c/ir-kbd-i2c.c | 2 ++
drivers/media/pci/bt8xx/bttv-input.c | 3 ++-
drivers/media/pci/cx23885/cx23885-input.c | 1 +
drivers/media/pci/cx88/cx88-input.c | 3 ++-
drivers/media/pci/dm1105/dm1105.c | 1 +
drivers/media/pci/mantis/mantis_input.c | 1 +
drivers/media/pci/saa7134/saa7134-input.c | 1 +
drivers/media/pci/smipcie/smipcie-ir.c | 1 +
drivers/media/pci/ttpci/budget-ci.c | 1 +
drivers/media/rc/ati_remote.c | 6 +++---
drivers/media/rc/ene_ir.c | 2 +-
drivers/media/rc/fintek-cir.c | 3 ++-
drivers/media/rc/igorplugusb.c | 1 +
drivers/media/rc/iguanair.c | 1 +
drivers/media/rc/img-ir/img-ir-hw.c | 3 ++-
drivers/media/rc/img-ir/img-ir-raw.c | 3 ++-
drivers/media/rc/imon.c | 3 ++-
drivers/media/rc/ir-hix5hd2.c | 2 +-
drivers/media/rc/ir_toy.c | 1 +
drivers/media/rc/ite-cir.c | 2 +-
drivers/media/rc/mceusb.c | 1 +
drivers/media/rc/rc-ir-raw.c | 5 -----
drivers/media/rc/rc-loopback.c | 1 +
drivers/media/rc/rc-main.c | 6 +-----
drivers/media/rc/redrat3.c | 4 +++-
drivers/media/rc/st_rc.c | 2 +-
drivers/media/rc/streamzap.c | 7 ++++---
drivers/media/rc/sunxi-cir.c | 1 +
drivers/media/rc/ttusbir.c | 2 +-
drivers/media/rc/winbond-cir.c | 2 +-
drivers/media/rc/xbox_remote.c | 5 +++--
drivers/media/usb/au0828/au0828-input.c | 1 +
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 1 +
drivers/media/usb/dvb-usb/dvb-usb-remote.c | 6 ++++--
drivers/media/usb/em28xx/em28xx-input.c | 1 +
drivers/staging/media/av7110/av7110_ir.c | 1 +
include/media/rc-core.h | 2 --
41 files changed, 58 insertions(+), 36 deletions(-)
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index 9e48ad39e1cc9..923e2ed30624b 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.c
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -2221,6 +2221,7 @@ static void sii8620_detach(struct drm_bridge *bridge)
return;
rc_unregister_device(ctx->rc_dev);
+ rc_free_device(ctx->rc_dev);
}
static int sii8620_is_packing_required(struct sii8620 *ctx,
diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
index d6faa0e00f95a..6d4c636e1c9f7 100644
--- a/drivers/hid/hid-picolcd_cir.c
+++ b/drivers/hid/hid-picolcd_cir.c
@@ -134,5 +134,6 @@ void picolcd_exit_cir(struct picolcd_data *data)
data->rc_dev = NULL;
rc_unregister_device(rdev);
+ rc_free_device(rdev);
}
diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c
index dd6e24a0899bd..1b8a33c05b3c9 100644
--- a/drivers/media/cec/core/cec-core.c
+++ b/drivers/media/cec/core/cec-core.c
@@ -338,8 +338,8 @@ int cec_register_adapter(struct cec_adapter *adap,
res = cec_devnode_register(&adap->devnode, adap->owner);
if (res) {
#ifdef CONFIG_MEDIA_CEC_RC
- /* Note: rc_unregister also calls rc_free */
rc_unregister_device(adap->rc);
+ rc_free_device(adap->rc);
adap->rc = NULL;
#endif
return res;
diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c
index af07fed21ae12..283770d583d56 100644
--- a/drivers/media/common/siano/smsir.c
+++ b/drivers/media/common/siano/smsir.c
@@ -92,6 +92,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
void sms_ir_exit(struct smscore_device_t *coredev)
{
rc_unregister_device(coredev->ir.dev);
+ rc_free_device(coredev->ir.dev);
pr_debug("\n");
}
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 5588cdd7ec20d..6047453170043 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -355,6 +355,7 @@ static void ir_work(struct work_struct *work)
mutex_unlock(&ir->lock);
if (rc == -ENODEV) {
rc_unregister_device(ir->rc);
+ rc_free_device(ir->rc);
ir->rc = NULL;
return;
}
@@ -972,6 +973,7 @@ static void ir_remove(struct i2c_client *client)
i2c_unregister_device(ir->tx_c);
rc_unregister_device(ir->rc);
+ rc_free_device(ir->rc);
}
static const struct i2c_device_id ir_kbd_id[] = {
diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c
index 84aa269248fd3..f84fcf96eca98 100644
--- a/drivers/media/pci/bt8xx/bttv-input.c
+++ b/drivers/media/pci/bt8xx/bttv-input.c
@@ -572,8 +572,9 @@ void bttv_input_fini(struct bttv *btv)
if (btv->remote == NULL)
return;
- bttv_ir_stop(btv);
rc_unregister_device(btv->remote->dev);
+ bttv_ir_stop(btv);
+ rc_free_device(btv->remote->dev);
kfree(btv->remote);
btv->remote = NULL;
}
diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c
index d2e84c6457e0a..722329ef3fd2c 100644
--- a/drivers/media/pci/cx23885/cx23885-input.c
+++ b/drivers/media/pci/cx23885/cx23885-input.c
@@ -402,6 +402,7 @@ void cx23885_input_fini(struct cx23885_dev *dev)
if (dev->kernel_ir == NULL)
return;
rc_unregister_device(dev->kernel_ir->rc);
+ rc_free_device(dev->kernel_ir->rc);
kfree(dev->kernel_ir->phys);
kfree(dev->kernel_ir->name);
kfree(dev->kernel_ir);
diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
index b9f2c14d62b40..4757787c3f593 100644
--- a/drivers/media/pci/cx88/cx88-input.c
+++ b/drivers/media/pci/cx88/cx88-input.c
@@ -509,8 +509,9 @@ int cx88_ir_fini(struct cx88_core *core)
if (!ir)
return 0;
- cx88_ir_stop(core);
rc_unregister_device(ir->dev);
+ cx88_ir_stop(core);
+ rc_free_device(ir->dev);
kfree(ir);
/* done */
diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c
index 9e9c7c071accc..e1185aa669f48 100644
--- a/drivers/media/pci/dm1105/dm1105.c
+++ b/drivers/media/pci/dm1105/dm1105.c
@@ -763,6 +763,7 @@ static int dm1105_ir_init(struct dm1105_dev *dm1105)
static void dm1105_ir_exit(struct dm1105_dev *dm1105)
{
rc_unregister_device(dm1105->ir.dev);
+ rc_free_device(dm1105->ir.dev);
}
static int dm1105_hw_init(struct dm1105_dev *dev)
diff --git a/drivers/media/pci/mantis/mantis_input.c b/drivers/media/pci/mantis/mantis_input.c
index 34c0d979240fd..edb4cacf55d22 100644
--- a/drivers/media/pci/mantis/mantis_input.c
+++ b/drivers/media/pci/mantis/mantis_input.c
@@ -72,5 +72,6 @@ EXPORT_SYMBOL_GPL(mantis_input_init);
void mantis_input_exit(struct mantis_pci *mantis)
{
rc_unregister_device(mantis->rc);
+ rc_free_device(mantis->rc);
}
EXPORT_SYMBOL_GPL(mantis_input_exit);
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
index 468dbe8d552f8..d39537c95d9d3 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -834,6 +834,7 @@ void saa7134_input_fini(struct saa7134_dev *dev)
return;
rc_unregister_device(dev->remote->dev);
+ rc_free_device(dev->remote->dev);
kfree(dev->remote);
dev->remote = NULL;
}
diff --git a/drivers/media/pci/smipcie/smipcie-ir.c b/drivers/media/pci/smipcie/smipcie-ir.c
index c0604d9c70119..0bbe4fa2d5a84 100644
--- a/drivers/media/pci/smipcie/smipcie-ir.c
+++ b/drivers/media/pci/smipcie/smipcie-ir.c
@@ -181,5 +181,6 @@ void smi_ir_exit(struct smi_dev *dev)
rc_unregister_device(rc_dev);
smi_ir_stop(ir);
+ rc_free_device(rc_dev);
ir->rc_dev = NULL;
}
diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c
index 33f08adf4feb1..16973ac8e6a92 100644
--- a/drivers/media/pci/ttpci/budget-ci.c
+++ b/drivers/media/pci/ttpci/budget-ci.c
@@ -249,6 +249,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci)
cancel_work_sync(&budget_ci->ir.msp430_irq_bh_work);
rc_unregister_device(budget_ci->ir.dev);
+ rc_free_device(budget_ci->ir.dev);
}
static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index a733914a25742..f1fd4765651ca 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -921,7 +921,6 @@ static int ati_remote_probe(struct usb_interface *interface,
input_free_device(input_dev);
exit_unregister_device:
rc_unregister_device(rc_dev);
- rc_dev = NULL;
exit_kill_urbs:
usb_kill_urb(ati_remote->irq_urb);
usb_kill_urb(ati_remote->out_urb);
@@ -941,18 +940,19 @@ static void ati_remote_disconnect(struct usb_interface *interface)
struct ati_remote *ati_remote;
ati_remote = usb_get_intfdata(interface);
- usb_set_intfdata(interface, NULL);
if (!ati_remote) {
dev_warn(&interface->dev, "%s - null device?\n", __func__);
return;
}
+ rc_unregister_device(ati_remote->rdev);
+ usb_set_intfdata(interface, NULL);
usb_kill_urb(ati_remote->irq_urb);
usb_kill_urb(ati_remote->out_urb);
if (ati_remote->idev)
input_unregister_device(ati_remote->idev);
- rc_unregister_device(ati_remote->rdev);
ati_remote_free_buffers(ati_remote);
+ rc_free_device(ati_remote->rdev);
kfree(ati_remote);
}
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index d6c54a3bccc26..136fc4192265d 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -1090,7 +1090,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
release_region(dev->hw_io, ENE_IO_SIZE);
exit_unregister_device:
rc_unregister_device(rdev);
- rdev = NULL;
exit_free_dev_rdev:
rc_free_device(rdev);
kfree(dev);
@@ -1110,6 +1109,7 @@ static void ene_remove(struct pnp_dev *pnp_dev)
ene_rx_restore_hw_buffer(dev);
spin_unlock_irqrestore(&dev->hw_lock, flags);
+ rc_free_device(dev->rdev);
free_irq(dev->irq, dev);
release_region(dev->hw_io, ENE_IO_SIZE);
kfree(dev);
diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c
index 3fb0968efd57d..9b789097cdd4c 100644
--- a/drivers/media/rc/fintek-cir.c
+++ b/drivers/media/rc/fintek-cir.c
@@ -568,6 +568,7 @@ static void fintek_remove(struct pnp_dev *pdev)
struct fintek_dev *fintek = pnp_get_drvdata(pdev);
unsigned long flags;
+ rc_unregister_device(fintek->rdev);
spin_lock_irqsave(&fintek->fintek_lock, flags);
/* disable CIR */
fintek_disable_cir(fintek);
@@ -580,7 +581,7 @@ static void fintek_remove(struct pnp_dev *pdev)
free_irq(fintek->cir_irq, fintek);
release_region(fintek->cir_addr, fintek->cir_port_len);
- rc_unregister_device(fintek->rdev);
+ rc_free_device(fintek->rdev);
kfree(fintek);
}
diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c
index e034c93d57cf0..5ceb5ca44e235 100644
--- a/drivers/media/rc/igorplugusb.c
+++ b/drivers/media/rc/igorplugusb.c
@@ -242,6 +242,7 @@ static void igorplugusb_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
usb_unpoison_urb(ir->urb);
usb_free_urb(ir->urb);
+ rc_free_device(ir->rc);
kfree(ir->buf_in);
}
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
index 8af94246e5916..7bd6dd7254157 100644
--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -500,6 +500,7 @@ static void iguanair_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
usb_kill_urb(ir->urb_in);
usb_kill_urb(ir->urb_out);
+ rc_free_device(ir->rc);
usb_free_urb(ir->urb_in);
usb_free_urb(ir->urb_out);
usb_free_coherent(ir->udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c
index 63f6f5b36838d..f30adf4d8444d 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.c
+++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -1118,9 +1118,10 @@ void img_ir_remove_hw(struct img_ir_priv *priv)
struct rc_dev *rdev = hw->rdev;
if (!rdev)
return;
+ rc_unregister_device(rdev);
img_ir_set_decoder(priv, NULL, 0);
hw->rdev = NULL;
- rc_unregister_device(rdev);
+ rc_free_device(rdev);
#ifdef CONFIG_COMMON_CLK
if (!IS_ERR(priv->clk))
clk_notifier_unregister(priv->clk, &hw->clk_nb);
diff --git a/drivers/media/rc/img-ir/img-ir-raw.c b/drivers/media/rc/img-ir/img-ir-raw.c
index 92fb7b555a0f6..f1460d4acf3e8 100644
--- a/drivers/media/rc/img-ir/img-ir-raw.c
+++ b/drivers/media/rc/img-ir/img-ir-raw.c
@@ -136,6 +136,7 @@ void img_ir_remove_raw(struct img_ir_priv *priv)
if (!rdev)
return;
+ rc_unregister_device(rdev);
/* switch off and disable raw (edge) interrupts */
spin_lock_irq(&priv->lock);
raw->rdev = NULL;
@@ -145,7 +146,7 @@ void img_ir_remove_raw(struct img_ir_priv *priv)
img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
spin_unlock_irq(&priv->lock);
- rc_unregister_device(rdev);
+ rc_free_device(rdev);
timer_delete_sync(&raw->timer);
}
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 35b9e07003d88..48534bb52e4d0 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -2541,9 +2541,10 @@ static void imon_disconnect(struct usb_interface *interface)
if (ifnum == 0) {
ictx->dev_present_intf0 = false;
+ rc_unregister_device(ictx->rdev);
usb_kill_urb(ictx->rx_urb_intf0);
input_unregister_device(ictx->idev);
- rc_unregister_device(ictx->rdev);
+ rc_free_device(ictx->rdev);
if (ictx->display_supported) {
if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
usb_deregister_dev(interface, &imon_lcd_class);
diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c
index edc46828509c8..1b061e4a3dcfa 100644
--- a/drivers/media/rc/ir-hix5hd2.c
+++ b/drivers/media/rc/ir-hix5hd2.c
@@ -331,7 +331,6 @@ static int hix5hd2_ir_probe(struct platform_device *pdev)
regerr:
rc_unregister_device(rdev);
- rdev = NULL;
clkerr:
clk_disable_unprepare(priv->clock);
err:
@@ -346,6 +345,7 @@ static void hix5hd2_ir_remove(struct platform_device *pdev)
clk_disable_unprepare(priv->clock);
rc_unregister_device(priv->rdev);
+ rc_free_device(priv->rdev);
}
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/media/rc/ir_toy.c b/drivers/media/rc/ir_toy.c
index 533faa1175174..e79de56997a42 100644
--- a/drivers/media/rc/ir_toy.c
+++ b/drivers/media/rc/ir_toy.c
@@ -536,6 +536,7 @@ static void irtoy_disconnect(struct usb_interface *intf)
usb_free_urb(ir->urb_out);
usb_kill_urb(ir->urb_in);
usb_free_urb(ir->urb_in);
+ rc_free_device(ir->rc);
kfree(ir->in);
kfree(ir->out);
kfree(ir);
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index 2bacecb022623..23afbafb55748 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -1414,7 +1414,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
release_region(itdev->cir_addr, itdev->params->io_region_size);
exit_unregister_device:
rc_unregister_device(rdev);
- rdev = NULL;
exit_free_dev_rdev:
rc_free_device(rdev);
kfree(itdev);
@@ -1439,6 +1438,7 @@ static void ite_remove(struct pnp_dev *pdev)
release_region(dev->cir_addr, dev->params->io_region_size);
rc_unregister_device(dev->rdev);
+ rc_free_device(dev->rdev);
kfree(dev);
}
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 044767eb3a38c..a4c94fdf767ca 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -1850,6 +1850,7 @@ static void mceusb_dev_disconnect(struct usb_interface *intf)
usb_free_urb(ir->urb_in);
usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in);
usb_put_dev(dev);
+ rc_free_device(ir->rc);
kfree(ir);
}
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 5dafe11f61c6b..76c3d1307f9f1 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -648,9 +648,6 @@ int ir_raw_event_register(struct rc_dev *dev)
void ir_raw_event_free(struct rc_dev *dev)
{
- if (!dev)
- return;
-
kfree(dev->raw);
dev->raw = NULL;
}
@@ -674,8 +671,6 @@ void ir_raw_event_unregister(struct rc_dev *dev)
lirc_bpf_free(dev);
- ir_raw_event_free(dev);
-
/*
* A user can be calling bpf(BPF_PROG_{QUERY|ATTACH|DETACH}), so
* ensure that the raw member is null on unlock; this is how
diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index 8288366f891fc..a108b057b5fd5 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -263,6 +263,7 @@ static int __init loop_init(void)
static void __exit loop_exit(void)
{
rc_unregister_device(loopdev.dev);
+ rc_free_device(loopdev.dev);
}
module_init(loop_init);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index b9bf5cdcde4ae..6bdf32cb4a17d 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1611,6 +1611,7 @@ static void rc_dev_release(struct device *device)
{
struct rc_dev *dev = to_rc_dev(device);
+ ir_raw_event_free(dev);
kfree(dev);
}
@@ -1773,7 +1774,6 @@ struct rc_dev *devm_rc_allocate_device(struct device *dev,
}
rc->dev.parent = dev;
- rc->managed_alloc = true;
*dr = rc;
devres_add(dev, dr);
@@ -2042,11 +2042,7 @@ void rc_unregister_device(struct rc_dev *dev)
device_del(&dev->dev);
ida_free(&rc_ida, dev->minor);
-
- if (!dev->managed_alloc)
- rc_free_device(dev);
}
-
EXPORT_SYMBOL_GPL(rc_unregister_device);
/*
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index a49173f54a4d0..b8289327f6a20 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -1133,11 +1133,13 @@ static void redrat3_dev_disconnect(struct usb_interface *intf)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
+ struct rc_dev *rc = rr3->rc;
usb_set_intfdata(intf, NULL);
- rc_unregister_device(rr3->rc);
+ rc_unregister_device(rc);
led_classdev_unregister(&rr3->led);
redrat3_delete(rr3, udev);
+ rc_free_device(rc);
}
static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message)
diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c
index 6b70bac5f45d6..0ba06bfc9e14b 100644
--- a/drivers/media/rc/st_rc.c
+++ b/drivers/media/rc/st_rc.c
@@ -203,6 +203,7 @@ static void st_rc_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, false);
clk_disable_unprepare(rc_dev->sys_clock);
rc_unregister_device(rc_dev->rdev);
+ rc_free_device(rc_dev->rdev);
}
static int st_rc_open(struct rc_dev *rdev)
@@ -334,7 +335,6 @@ static int st_rc_probe(struct platform_device *pdev)
return ret;
rcerr:
rc_unregister_device(rdev);
- rdev = NULL;
clkerr:
clk_disable_unprepare(rc_dev->sys_clock);
err:
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index d3b48a0dd1f47..421bc655f8af4 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -388,15 +388,16 @@ static void streamzap_disconnect(struct usb_interface *interface)
struct streamzap_ir *sz = usb_get_intfdata(interface);
struct usb_device *usbdev = interface_to_usbdev(interface);
- usb_set_intfdata(interface, NULL);
-
if (!sz)
return;
- usb_kill_urb(sz->urb_in);
rc_unregister_device(sz->rdev);
+ usb_set_intfdata(interface, NULL);
+
+ usb_kill_urb(sz->urb_in);
usb_free_urb(sz->urb_in);
usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
+ rc_free_device(sz->rdev);
kfree(sz);
}
diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c
index 92ef4e7c6f69f..cb4c56bf0752a 100644
--- a/drivers/media/rc/sunxi-cir.c
+++ b/drivers/media/rc/sunxi-cir.c
@@ -371,6 +371,7 @@ static void sunxi_ir_remove(struct platform_device *pdev)
struct sunxi_ir *ir = platform_get_drvdata(pdev);
rc_unregister_device(ir->rc);
+ rc_free_device(ir->rc);
sunxi_ir_hw_exit(&pdev->dev);
}
diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c
index 560a26f3965cf..5234c1e9a58ea 100644
--- a/drivers/media/rc/ttusbir.c
+++ b/drivers/media/rc/ttusbir.c
@@ -333,7 +333,6 @@ static int ttusbir_probe(struct usb_interface *intf,
return 0;
out3:
rc_unregister_device(rc);
- rc = NULL;
out2:
led_classdev_unregister(&tt->led);
out:
@@ -373,6 +372,7 @@ static void ttusbir_disconnect(struct usb_interface *intf)
}
usb_kill_urb(tt->bulk_urb);
usb_free_urb(tt->bulk_urb);
+ rc_free_device(tt->rc);
usb_set_intfdata(intf, NULL);
kfree(tt);
}
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 25884a79985c8..14d8b58e28398 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -1132,7 +1132,6 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
release_region(data->wbase, WAKEUP_IOMEM_LEN);
exit_unregister_device:
rc_unregister_device(data->dev);
- data->dev = NULL;
exit_free_rc:
rc_free_device(data->dev);
exit_unregister_led:
@@ -1163,6 +1162,7 @@ wbcir_remove(struct pnp_dev *device)
wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
rc_unregister_device(data->dev);
+ rc_free_device(data->dev);
led_classdev_unregister(&data->led);
diff --git a/drivers/media/rc/xbox_remote.c b/drivers/media/rc/xbox_remote.c
index a1572381d0971..05e3c6db54ee6 100644
--- a/drivers/media/rc/xbox_remote.c
+++ b/drivers/media/rc/xbox_remote.c
@@ -277,14 +277,15 @@ static void xbox_remote_disconnect(struct usb_interface *interface)
struct xbox_remote *xbox_remote;
xbox_remote = usb_get_intfdata(interface);
- usb_set_intfdata(interface, NULL);
if (!xbox_remote) {
dev_warn(&interface->dev, "%s - null device?\n", __func__);
return;
}
- usb_kill_urb(xbox_remote->irq_urb);
rc_unregister_device(xbox_remote->rdev);
+ usb_set_intfdata(interface, NULL);
+ usb_kill_urb(xbox_remote->irq_urb);
+ rc_free_device(xbox_remote->rdev);
usb_free_urb(xbox_remote->irq_urb);
kfree(xbox_remote);
}
diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c
index 3d3368202cd01..283ad2c6288cd 100644
--- a/drivers/media/usb/au0828/au0828-input.c
+++ b/drivers/media/usb/au0828/au0828-input.c
@@ -357,6 +357,7 @@ void au0828_rc_unregister(struct au0828_dev *dev)
return;
rc_unregister_device(ir->rc);
+ rc_free_device(ir->rc);
/* done */
kfree(ir);
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index f1c79f351ec8d..17e8961179d14 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -187,6 +187,7 @@ static int dvb_usbv2_remote_exit(struct dvb_usb_device *d)
if (d->rc_dev) {
cancel_delayed_work_sync(&d->rc_query_work);
rc_unregister_device(d->rc_dev);
+ rc_free_device(d->rc_dev);
d->rc_dev = NULL;
}
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
index 65e2c9e2cdc99..6dc11718dfb98 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
@@ -347,10 +347,12 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d)
{
if (d->state & DVB_USB_STATE_REMOTE) {
cancel_delayed_work_sync(&d->rc_query_work);
- if (d->props.rc.mode == DVB_RC_LEGACY)
+ if (d->props.rc.mode == DVB_RC_LEGACY) {
input_unregister_device(d->input_dev);
- else
+ } else {
rc_unregister_device(d->rc_dev);
+ rc_free_device(d->rc_dev);
+ }
}
d->state &= ~DVB_USB_STATE_REMOTE;
return 0;
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index 5f3b00869bdbc..26f333b5be732 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -853,6 +853,7 @@ static int em28xx_ir_fini(struct em28xx *dev)
goto ref_put;
rc_unregister_device(ir->rc);
+ rc_free_device(ir->rc);
kfree(ir->i2c_client);
diff --git a/drivers/staging/media/av7110/av7110_ir.c b/drivers/staging/media/av7110/av7110_ir.c
index 68b3979ba5f20..fdae467fd7ab8 100644
--- a/drivers/staging/media/av7110/av7110_ir.c
+++ b/drivers/staging/media/av7110/av7110_ir.c
@@ -151,6 +151,7 @@ int av7110_ir_init(struct av7110 *av7110)
void av7110_ir_exit(struct av7110 *av7110)
{
rc_unregister_device(av7110->ir.rcdev);
+ rc_free_device(av7110->ir.rcdev);
}
//MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>, Oliver Endriss <o.endriss@gmx.de>");
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 35c7a0546f02e..7c964b5ad7926 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -81,7 +81,6 @@ struct lirc_fh {
/**
* struct rc_dev - represents a remote control device
* @dev: driver model's view of this device
- * @managed_alloc: devm_rc_allocate_device was used to create rc_dev
* @registered: set to true by rc_register_device(), false by
* rc_unregister_device
* @idle: used to keep track of RX state
@@ -156,7 +155,6 @@ struct lirc_fh {
*/
struct rc_dev {
struct device dev;
- bool managed_alloc;
bool registered;
bool idle;
bool encode_wakeup;
--
2.52.0
^ permalink raw reply related
* Re: [PATCH v12 00/11] HID: asus: Fix ASUS ROG Laptop's Keyboard backlight handling
From: Ilpo Järvinen @ 2026-01-26 14:30 UTC (permalink / raw)
To: platform-driver-x86, linux-input, Antheas Kapenekakis
Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Corentin Chary,
Luke D . Jones, Hans de Goede, Denis Benato
In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev>
On Thu, 22 Jan 2026 08:50:33 +0100, Antheas Kapenekakis wrote:
> This is a two part series which does the following:
> - Clean-up init sequence
> - Unify backlight handling to happen under asus-wmi so that all Aura
> devices have synced brightness controls and the backlight button works
> properly when it is on a USB laptop keyboard instead of one w/ WMI.
>
> For more context, see cover letter of V1. Since V5, I removed some patches
> to make this easier to merge.
>
> [...]
Thank you for your contribution, it has been applied to my local
review-ilpo-next branch. Note it will show up in the public
platform-drivers-x86/review-ilpo-next branch only once I've pushed my
local branch there, which might take a while.
The list of commits applied:
[01/11] HID: asus: simplify RGB init sequence
commit: 0cd98ed97f1cab77822f0afea2bd4dabadd12a8b
[02/11] HID: asus: initialize additional endpoints only for certain devices
commit: 3415a1beb3d876769e476cae2085bedb6b94da35
[03/11] HID: asus: use same report_id in response
commit: 629771528f76df2e6d8b1d5b9297a0c95b317676
[04/11] HID: asus: fortify keyboard handshake
commit: a96ec7a12e41a3f37784f3f69396facc659ec2d4
[05/11] HID: asus: move vendor initialization to probe
commit: 8baca948f6aad8866b4722f527d01bb4d4e22b6f
[06/11] HID: asus: early return for ROG devices
commit: ee1de467511811c71075e5750785d3c95cf45c5f
[07/11] platform/x86: asus-wmi: Add support for multiple kbd led handlers
commit: efdcbec427f15e6514388c27cf5599604c95b788
[08/11] HID: asus: listen to the asus-wmi brightness device instead of creating one
commit: ba374d424cdd3050d2e1864e7b18393cf3a4d06f
[09/11] platform/x86: asus-wmi: remove unused keyboard backlight quirk
commit: d384a3994712ddaec10ae37549c6f0b1a10e7b98
[10/11] platform/x86: asus-wmi: add keyboard brightness event handler
commit: f9a21738c6993c6720b8b82a7ead644a74497487
[11/11] HID: asus: add support for the asus-wmi brightness handler
commit: 4884d4795a5ce8077bbb5b97e4c2fd51e312087f
--
i.
^ permalink raw reply
* Re: [PATCH v1 08/10] dt-bindings: mfg: motorola-cpcap: convert to schema
From: Rob Herring @ 2026-01-26 14:37 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Krzysztof Kozlowski, Conor Dooley, Dmitry Torokhov, Lee Jones,
Pavel Machek, Liam Girdwood, Mark Brown, Alexandre Belloni,
Dixit Parmar, Tony Lindgren, linux-iio, devicetree, linux-kernel,
linux-input, linux-leds, linux-rtc
In-Reply-To: <20260125134302.45958-9-clamor95@gmail.com>
On Sun, Jan 25, 2026 at 03:43:00PM +0200, Svyatoslav Ryhel wrote:
> Convert devicetree bindings for the Motorola CPCAP MFD from TXT to YAML.
> Audio codec bindings adjusted with common ports node for port@0 and
> port@1. Added compatible for Mot board CPCAP. Other bindings remain the
> same.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
> .../bindings/mfd/motorola,cpcap.yaml | 389 ++++++++++++++++++
> .../bindings/mfd/motorola-cpcap.txt | 78 ----
> 2 files changed, 389 insertions(+), 78 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
> delete mode 100644 Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
>
> diff --git a/Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml b/Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
> new file mode 100644
> index 000000000000..f75f884c7b3e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
> @@ -0,0 +1,389 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/motorola,cpcap.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Motorola CPCAP PMIC MFD
> +
> +maintainers:
> + - Svyatoslav Ryhel <clamor95@gmail.com>
> +
> +allOf:
> + - $ref: /schemas/spi/spi-peripheral-props.yaml#
> +
> +properties:
> + compatible:
> + enum:
> + - motorola,cpcap
> + - st,6556002
> + - motorola,mapphone-cpcap
> + - motorola,mot-cpcap
Adding new compatibles should be a separate patch unless they have
already been in use.
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + interrupt-controller: true
> +
> + "#interrupt-cells":
> + const: 2
> +
> + "#address-cells":
> + const: 1
> +
> + "#size-cells":
> + const: 0
> +
> + spi-max-frequency:
> + maximum: 8000000
> +
> + spi-cs-high: true
> +
> + adc:
> + $ref: /schemas/iio/adc/motorola,cpcap-adc.yaml
> +
> + audio-codec:
> + type: object
additionalProperties: false
> +
> + properties:
> + interrupts:
> + items:
> + - description: headset detect interrupt
> + - description: microphone bias 2 detect interrupt
> +
> + interrupt-names:
> + items:
> + - const: hs
> + - const: mb2
> +
> + "#sound-dai-cells":
> + const: 1
> +
> + ports:
> + $ref: /schemas/graph.yaml#/properties/ports
> + description: The audio-codec provides two DAIs. The first one is
> + connected to the Stereo HiFi DAC and the second one is connected
> + to the Voice DAC.
You need to define each port in the schema.
> +
> + required:
> + - interrupts
> + - interrupt-names
> + - "#sound-dai-cells"
> +
> + battery:
> + $ref: /schemas/power/supply/cpcap-battery.yaml
> +
> + charger:
> + $ref: /schemas/power/supply/cpcap-charger.yaml
> +
> + key-power:
> + $ref: /schemas/input/motorola,cpcap-pwrbutton.yaml
> +
> + phy:
> + $ref: /schemas/phy/motorola,cpcap-usb-phy.yaml
> +
> + regulator:
> + $ref: /schemas/regulator/motorola,cpcap-regulator.yaml
> +
> + rtc:
> + $ref: /schemas/rtc/motorola,cpcap-rtc.yaml
> +
> +patternProperties:
> + "^led(-[a-z]+)?$":
> + $ref: /schemas/leds/motorola,cpcap-leds.yaml
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> + - "#address-cells"
> + - "#size-cells"
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/gpio/gpio.h>
> + #include <dt-bindings/interrupt-controller/irq.h>
> + #include <dt-bindings/input/linux-event-codes.h>
> +
> + spi {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + cpcap: pmic@0 {
> + compatible = "motorola,cpcap";
> + reg = <0>; /* cs0 */
> +
> + interrupt-parent = <&gpio1>;
> + interrupts = <7 IRQ_TYPE_EDGE_RISING>;
> +
> + interrupt-controller;
> + #interrupt-cells = <2>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + spi-max-frequency = <3000000>;
> + spi-cs-high;
> +
> + cpcap_adc: adc {
> + compatible = "motorola,cpcap-adc";
> +
> + interrupt-parent = <&cpcap>;
> + interrupts = <8 IRQ_TYPE_NONE>;
> + interrupt-names = "adcdone";
> +
> + #io-channel-cells = <1>;
> + };
> +
> + cpcap_audio: audio-codec {
> + interrupt-parent = <&cpcap>;
> + interrupts = <9 IRQ_TYPE_NONE>, <10 IRQ_TYPE_NONE>;
> + interrupt-names = "hs", "mb2";
> +
> + #sound-dai-cells = <1>;
> +
> + ports {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + /* HiFi */
> + port@0 {
> + reg = <0>;
> + cpcap_audio_codec0: endpoint {
> + };
> + };
> +
> + /* Voice */
> + port@1 {
> + reg = <1>;
> + cpcap_audio_codec1: endpoint {
> + };
> + };
> + };
> + };
> +
> + cpcap_battery: battery {
> + compatible = "motorola,cpcap-battery";
> +
> + interrupt-parent = <&cpcap>;
> + interrupts = <6 IRQ_TYPE_NONE>, <5 IRQ_TYPE_NONE>,
> + <3 IRQ_TYPE_NONE>, <20 IRQ_TYPE_NONE>,
> + <54 IRQ_TYPE_NONE>, <57 IRQ_TYPE_NONE>;
> + interrupt-names = "eol", "lowbph", "lowbpl",
> + "chrgcurr1", "battdetb", "cccal";
> +
> + io-channels = <&cpcap_adc 0>, <&cpcap_adc 1>,
> + <&cpcap_adc 5>, <&cpcap_adc 6>;
> + io-channel-names = "battdetb", "battp",
> + "chg_isense", "batti";
> + power-supplies = <&cpcap_charger>;
> + };
> +
> + cpcap_charger: charger {
> + compatible = "motorola,mapphone-cpcap-charger";
> +
> + interrupt-parent = <&cpcap>;
> + interrupts = <13 IRQ_TYPE_NONE>, <12 IRQ_TYPE_NONE>,
> + <29 IRQ_TYPE_NONE>, <28 IRQ_TYPE_NONE>,
> + <22 IRQ_TYPE_NONE>, <21 IRQ_TYPE_NONE>,
> + <20 IRQ_TYPE_NONE>, <19 IRQ_TYPE_NONE>,
> + <54 IRQ_TYPE_NONE>;
> + interrupt-names = "chrg_det", "rvrs_chrg", "chrg_se1b",
> + "se0conn", "rvrs_mode", "chrgcurr2",
> + "chrgcurr1", "vbusvld", "battdetb";
> +
> + mode-gpios = <&gpio3 29 GPIO_ACTIVE_LOW>,
> + <&gpio3 23 GPIO_ACTIVE_LOW>;
> +
> + io-channels = <&cpcap_adc 0>, <&cpcap_adc 1>,
> + <&cpcap_adc 2>, <&cpcap_adc 5>,
> + <&cpcap_adc 6>;
> + io-channel-names = "battdetb", "battp",
> + "vbus", "chg_isense",
> + "batti";
> + };
> +
> + key-power {
> + compatible = "motorola,cpcap-pwrbutton";
> +
> + interrupt-parent = <&cpcap>;
> + interrupts = <23 IRQ_TYPE_NONE>;
> + };
> +
> + led-red {
> + compatible = "motorola,cpcap-led-red";
> + vdd-supply = <&vdd_led>;
> + label = "status-led::red";
> + };
> +
> + led-green {
> + compatible = "motorola,cpcap-led-green";
> + vdd-supply = <&vdd_led>;
> + label = "status-led::green";
> + };
> +
> + led-blue {
> + compatible = "motorola,cpcap-led-blue";
> + vdd-supply = <&vdd_led>;
> + label = "status-led::blue";
> + };
> +
> + cpcap_usb2_phy: phy {
> + compatible = "motorola,mapphone-cpcap-usb-phy";
> +
> + pinctrl-0 = <&usb_gpio_mux_sel1>, <&usb_gpio_mux_sel2>;
> + pinctrl-1 = <&usb_ulpi_pins>;
> + pinctrl-2 = <&usb_utmi_pins>;
> + pinctrl-3 = <&uart3_pins>;
> + pinctrl-names = "default", "ulpi", "utmi", "uart";
> + #phy-cells = <0>;
> +
> + interrupts-extended =
> + <&cpcap 15 IRQ_TYPE_NONE>, <&cpcap 14 IRQ_TYPE_NONE>,
> + <&cpcap 28 IRQ_TYPE_NONE>, <&cpcap 19 IRQ_TYPE_NONE>,
> + <&cpcap 18 IRQ_TYPE_NONE>, <&cpcap 17 IRQ_TYPE_NONE>,
> + <&cpcap 16 IRQ_TYPE_NONE>, <&cpcap 49 IRQ_TYPE_NONE>,
> + <&cpcap 48 IRQ_TYPE_NONE>;
> + interrupt-names = "id_ground", "id_float", "se0conn",
> + "vbusvld", "sessvld", "sessend",
> + "se1", "dm", "dp";
> +
> + mode-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>,
> + <&gpio1 0 GPIO_ACTIVE_HIGH>;
> +
> + io-channels = <&cpcap_adc 2>, <&cpcap_adc 7>;
> + io-channel-names = "vbus", "id";
> +
> + vusb-supply = <&avdd_usb>;
> + };
> +
> + regulator {
> + compatible = "motorola,cpcap-regulator";
> +
> + regulators {
> + vdd_cpu: SW1 {
> + regulator-name = "vdd_cpu";
> + regulator-min-microvolt = <750000>;
> + regulator-max-microvolt = <1125000>;
> + regulator-enable-ramp-delay = <1500>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vdd_core: SW2 {
> + regulator-name = "vdd_core";
> + regulator-min-microvolt = <950000>;
> + regulator-max-microvolt = <1300000>;
> + regulator-enable-ramp-delay = <1500>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vdd_1v8_vio: SW3 {
> + regulator-name = "vdd_1v8_vio";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + regulator-enable-ramp-delay = <0>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vdd_aon: SW4 {
> + regulator-name = "vdd_aon";
> + regulator-min-microvolt = <950000>;
> + regulator-max-microvolt = <1300000>;
> + regulator-enable-ramp-delay = <1500>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + vdd_led: SW5 {
> + regulator-name = "vdd_led";
> + regulator-min-microvolt = <5050000>;
> + regulator-max-microvolt = <5050000>;
> + regulator-enable-ramp-delay = <1500>;
> + regulator-boot-on;
> + };
> +
> + vdd_hvio: VHVIO {
> + regulator-name = "vdd_hvio";
> + regulator-min-microvolt = <2775000>;
> + regulator-max-microvolt = <2775000>;
> + regulator-enable-ramp-delay = <1000>;
> + };
> +
> + vcore_emmc: VSDIO {
> + regulator-name = "vcore_emmc";
> + regulator-min-microvolt = <1500000>;
> + regulator-max-microvolt = <3000000>;
> + regulator-enable-ramp-delay = <1000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + avdd_dsi_csi: VCSI {
> + regulator-name = "avdd_dsi_csi";
> + regulator-min-microvolt = <1200000>;
> + regulator-max-microvolt = <1200000>;
> + regulator-enable-ramp-delay = <1000>;
> + regulator-boot-on;
> + };
> +
> + avdd_3v3_periph: VWLAN2 {
> + regulator-name = "avdd_3v3_periph";
> + regulator-min-microvolt = <2775000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-enable-ramp-delay = <1000>;
> + regulator-boot-on;
> + };
> +
> + vddio_usd: VSIMCARD {
> + regulator-name = "vddio_usd";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <2900000>;
> + regulator-enable-ramp-delay = <1000>;
> + regulator-boot-on;
> + };
> +
> + vdd_haptic: VVIB {
> + regulator-name = "vdd_haptic";
> + regulator-min-microvolt = <1300000>;
> + regulator-max-microvolt = <3000000>;
> + regulator-enable-ramp-delay = <1000>;
> + };
> +
> + avdd_usb: VUSB {
> + regulator-name = "avdd_usb";
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + regulator-enable-ramp-delay = <1000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> +
> + VAUDIO {
> + regulator-name = "vdd_audio";
> + regulator-min-microvolt = <2775000>;
> + regulator-max-microvolt = <2775000>;
> + regulator-enable-ramp-delay = <1000>;
> + regulator-always-on;
> + regulator-boot-on;
> + };
> + };
> + };
> +
> + cpcap_rtc: rtc {
> + compatible = "motorola,cpcap-rtc";
> +
> + interrupt-parent = <&cpcap>;
> + interrupts = <39 IRQ_TYPE_NONE>, <26 IRQ_TYPE_NONE>;
> + };
> + };
> + };
> +
> +...
> diff --git a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
> deleted file mode 100644
> index 18c3fc26ca93..000000000000
> --- a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
> +++ /dev/null
> @@ -1,78 +0,0 @@
> -Motorola CPCAP PMIC device tree binding
> -
> -Required properties:
> -- compatible : One or both of "motorola,cpcap" or "ste,6556002"
> -- reg : SPI chip select
> -- interrupts : The interrupt line the device is connected to
> -- interrupt-controller : Marks the device node as an interrupt controller
> -- #interrupt-cells : The number of cells to describe an IRQ, should be 2
> -- #address-cells : Child device offset number of cells, should be 1
> -- #size-cells : Child device size number of cells, should be 0
> -- spi-max-frequency : Typically set to 3000000
> -- spi-cs-high : SPI chip select direction
> -
> -Optional subnodes:
> -
> -The sub-functions of CPCAP get their own node with their own compatible values,
> -which are described in the following files:
> -
> -- Documentation/devicetree/bindings/power/supply/cpcap-battery.yaml
> -- Documentation/devicetree/bindings/power/supply/cpcap-charger.yaml
> -- Documentation/devicetree/bindings/regulator/cpcap-regulator.txt
> -- Documentation/devicetree/bindings/phy/motorola,cpcap-usb-phy.yaml
> -- Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt
> -- Documentation/devicetree/bindings/rtc/cpcap-rtc.txt
> -- Documentation/devicetree/bindings/leds/leds-cpcap.txt
> -- Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml
> -
> -The only exception is the audio codec. Instead of a compatible value its
> -node must be named "audio-codec".
> -
> -Required properties for the audio-codec subnode:
> -
> -- #sound-dai-cells = <1>;
> -- interrupts : should contain jack detection interrupts, with headset
> - detect interrupt matching "hs" and microphone bias 2
> - detect interrupt matching "mb2" in interrupt-names.
> -- interrupt-names : Contains "hs", "mb2"
> -
> -The audio-codec provides two DAIs. The first one is connected to the
> -Stereo HiFi DAC and the second one is connected to the Voice DAC.
> -
> -Example:
> -
> -&mcspi1 {
> - cpcap: pmic@0 {
> - compatible = "motorola,cpcap", "ste,6556002";
> - reg = <0>; /* cs0 */
> - interrupt-parent = <&gpio1>;
> - interrupts = <7 IRQ_TYPE_EDGE_RISING>;
> - interrupt-controller;
> - #interrupt-cells = <2>;
> - #address-cells = <1>;
> - #size-cells = <0>;
> - spi-max-frequency = <3000000>;
> - spi-cs-high;
> -
> - audio-codec {
> - #sound-dai-cells = <1>;
> - interrupts-extended = <&cpcap 9 0>, <&cpcap 10 0>;
> - interrupt-names = "hs", "mb2";
> -
> - /* HiFi */
> - port@0 {
> - endpoint {
> - remote-endpoint = <&cpu_dai1>;
> - };
> - };
> -
> - /* Voice */
> - port@1 {
> - endpoint {
> - remote-endpoint = <&cpu_dai2>;
> - };
> - };
> - };
> - };
> -};
> -
> --
> 2.51.0
>
^ permalink raw reply
* Re: [PATCH v2 0/4] Add quirks for MECHREVO Wujie 15X Pro laptop
From: Ilpo Järvinen @ 2026-01-26 14:57 UTC (permalink / raw)
To: rafael, dmitry.torokhov, Shyam-sundar.S-k, hansg, perex, tiwai,
gongqi
Cc: linux-acpi, linux-input, platform-driver-x86, linux-sound,
linux-kernel
In-Reply-To: <20260122155501.376199-1-550230171hxy@gmail.com>
On Thu, 22 Jan 2026 23:54:57 +0800, gongqi wrote:
> This series adds several quirks for the MECHREVO Wujie 15X Pro
> (AMD Ryzen AI 9 H 365) laptop to fix issues with the keyboard,
> touchpad, power management, and headset microphone.
>
> The laptop requires:
> - ACPI IRQ override for the keyboard.
> - i8042 quirks for keyboard/touchpad stability.
> - AMD PMC quirk to fix spurious IRQs during suspend.
> - Conexant codec quirk for the headset microphone.
>
> [...]
Thank you for your contribution, it has been applied to my local
review-ilpo-fixes branch. Note it will show up in the public
platform-drivers-x86/review-ilpo-fixes branch only once I've pushed my
local branch there, which might take a while.
The list of commits applied:
[1/4] ACPI: resource: Add IRQ override quirk for MECHREVO Wujie 15X Pro
(no commit info)
[2/4] Input: i8042: Add quirks for MECHREVO Wujie 15X Pro
(no commit info)
[3/4] platform/x86/amd/pmc: Add quirk for MECHREVO Wujie 15X Pro
commit: 2b4e00d8e70ca8736fda82447be6a4e323c6d1f5
[4/4] ALSA: hda/conexant: Add headset mic fix for MECHREVO Wujie 15X Pro
(no commit info)
--
i.
^ permalink raw reply
* Re: [PATCH v1] dt-bindings: input: Add TouchNetix aXiom touchscreen driver
From: Andrew Thomas @ 2026-01-26 16:28 UTC (permalink / raw)
To: Krzysztof Kozlowski, dmitry.torokhov@gmail.com
Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
Mark Satterthwaite, m.felsch@pengutronix.de,
kamel.bouhara@bootlin.com
In-Reply-To: <c6fabbcc-4a18-446c-b97e-944cfd23b87e@kernel.org>
Hi Krzysztof,
Thank you for the quick review and giving me a lot to look into straight away!
I shall resubmit my patch correctly using b4 in a separate email.
> > + The TouchNetix aXiom series are high-performance touchscreen controllers
> > + supporting various interface methods including I2C and SPI.
> > +
> > +properties:
> > + compatible:
> > + enum:
> > + - tnx,axiom-i2c
> > + - tnx,axiom-spi
>
> No, these are the same. Use only one describing the device.
>
Fixed.
> No device model? Really?
There are device models, but all devices use a very similar interface which
just changes with revision.
> > +allOf:
> > + - $ref: touchscreen.yaml#
>
> Missing ref to spi-periph.
>
> Look at other bindings instead of inventing your own.
Added.
> > +
> > + reg:
> > + maxItems: 1
> > +
> > + interrupts:
> > + maxItems: 1
> > +
> > + axiom,poll-enable:
>
> There is no such company as axiom. You just said it is tnx.
>
> > + type: boolean
> > + description: Enable aXiom polling mode instead of interrupt-driven
> > + reporting.
>
> Anyway, drop entire property. Not a DT suitable, not hardware.
Removed polling from device tree and added as a module_param.
Many Thanks,
Andrew
^ permalink raw reply
* Re: [PATCH 1/1] Adding support for aXiom touchscreen controller
From: Andrew Thomas @ 2026-01-26 16:27 UTC (permalink / raw)
To: Marco Felsch
Cc: dmitry.torokhov@gmail.com, linux-input@vger.kernel.org,
linux-kernel@vger.kernel.org, Mark Satterthwaite,
kamel.bouhara@bootlin.com, kernel@pengutronix.de
In-Reply-To: <20260122220918.uuy7rlvtcrsmfqmd@pengutronix.de>
Hi Marco,
Thank you very much for your quick review.
I have addressed many of your comments below.
> > +config TOUCHSCREEN_AXIOM_CORE
> > + tristate "TouchNetix Axiom touchscreen"
>
> Nack, the spi or i2c should select the core.
>
Changed.
> > +#define U41_COORD_SIZE (4)
> > +#define U41_Z_OFFSET (42)
>
> Align your defines.
>
Changed.
> > + input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
> > + input_set_abs_params(input_dev, ABS_MT_DISTANCE, 0, 127, 0, 0);
> > + input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 127, 0, 0);
>
> Max values are coming from the firmware.
>
I am trying to keep the initial patch as simple as possible.
This is a fixed value describedin the usage definition.
> > +
> > + input_mt_init_slots(input_dev, U41_MAX_TARGETS, INPUT_MT_DIRECT);
>
> num-targets can be configured via firmware config IIRC, so nack.
>
That is correct, all u41 can be configured separately.
As above, I wish the keep this patch as simple as possible so we can
add support for this in the future.
> > + err = ax->bus_ops->read(ax->dev, 0x0, SIZE_U31_DEVICE_INFO,
> > + ax->read_buf);
>
> No need for custom accessors, use regmap API.
>
From my understanding the the interface is the same.
Manual I2C/SPI bus handling is still required.
> > + ax->bus_ops = bus_ops;
> > + ax->irq = irq;
>
> You allocate absolute no ext. resources like regulators or reset-gpios.
>
If you think this would be needed in order for you to test this patch
we can add it.
As above, I wish the patch to a minimal support of I2C and SPI and furthur
features can be added ontop.
>
> > + switch (hdr.report_usage) {
> > + case AX_2DCTS_REPORT_ID:
> > + err = axiom_process_u41_report(ax,
> > + &report[AX_U34_PAYLOAD_BUFFER]);
>
> May I ask why you guys write in your programming manual, that the host
> needs to check the usage-revision and you completely ignore this?
As above.
all usage revisions will handle this identically.
Regards,
Andrew
^ permalink raw reply
* [PATCH 0/2] Input: add support for aXiom touchscreen controller using SPI or I2C
From: Andrew Thomas @ 2026-01-26 16:38 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Henrik Rydberg
Cc: linux-input, devicetree, linux-kernel, Andrew Thomas,
Marco Felsch
Summary of the added features:
- Add input driver support for TouchNetix aXiom touchscreen controller
using either I2C or SPI.
- Support ABS_MT touch reports in axiom_process_u41_report().
- Support both polling and interrupt mode.
- Add basic documentation and provide example device tree bindings.
- Provide the basic structure to add firmware and config download in
the future via both I2C and SPI.
Many thanks,
Andrew
Signed-off-by: Andrew Thomas <andrew.thomas@touchnetix.com>
---
Andrew Thomas (2):
dt-bindings: input: touchscreen: add TouchNetix aXiom device tree
Input: add support for aXiom touchscreen controller using SPI or I2C
.../bindings/input/touchscreen/tnx,axiom.yaml | 70 +++
.../devicetree/bindings/vendor-prefixes.yaml | 2 +
drivers/input/touchscreen/Kconfig | 25 ++
drivers/input/touchscreen/Makefile | 3 +
drivers/input/touchscreen/axiom_core.c | 473 +++++++++++++++++++++
drivers/input/touchscreen/axiom_core.h | 118 +++++
drivers/input/touchscreen/axiom_i2c.c | 150 +++++++
drivers/input/touchscreen/axiom_spi.c | 155 +++++++
8 files changed, 996 insertions(+)
---
base-commit: 7ff574599464bd0e30da88aabc7be9de1021204a
change-id: 20260126-axiom-driver-submission3-f892e1ae9ec0
Best regards,
--
Andrew Thomas <andrew.thomas@touchnetix.com>
^ permalink raw reply
* [PATCH 1/2] dt-bindings: input: touchscreen: add TouchNetix aXiom device tree
From: Andrew Thomas @ 2026-01-26 16:38 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Henrik Rydberg
Cc: linux-input, devicetree, linux-kernel, Andrew Thomas,
Marco Felsch
In-Reply-To: <20260126-axiom-driver-submission3-v1-0-d462c4a608e3@touchnetix.com>
---
.../bindings/input/touchscreen/tnx,axiom.yaml | 70 ++++++++++++++++++++++
.../devicetree/bindings/vendor-prefixes.yaml | 2 +
2 files changed, 72 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/tnx,axiom.yaml b/Documentation/devicetree/bindings/input/touchscreen/tnx,axiom.yaml
new file mode 100644
index 000000000000..7b532471c17f
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/tnx,axiom.yaml
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/tnx,axiom.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TouchNetix aXiom Touchscreen Controller
+
+maintainers:
+ - Andrew Thomas <andrew.thomas@touchnetix.com>
+
+description: |
+ The TouchNetix aXiom series are high-performance touchscreen controllers
+ supporting various interface methods including I2C and SPI.
+
+properties:
+ compatible:
+ enum:
+ - tnx,axiom
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ description: Both IRQ_TYPE_LEVEL_LOW and IRQ_TYPE_EDGE_FALLING are supported
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+allOf:
+ - $ref: touchscreen.yaml#
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ touchscreen@66 {
+ compatible = "tnx,axiom-i2c";
+ reg = <0x66>;
+ interrupt-parent = <&gpio>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ axiom,poll-enable;
+ axiom,poll-period = <15>;
+ };
+ };
+
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ touchscreen@0 {
+ compatible = "tnx,axiom-spi";
+ reg = <0>;
+ interrupt-parent = <&gpio>;
+ interrupts = <24 IRQ_TYPE_EDGE_FALLING>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index f1d1882009ba..dadfc7036ed7 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -1636,6 +1636,8 @@ patternProperties:
description: Trusted Logic Mobility
"^tmt,.*":
description: Tecon Microprocessor Technologies, LLC.
+ "^tnx,.*":
+ description: TouchNetix
"^topeet,.*":
description: Topeet
"^topic,.*":
--
2.43.0
^ permalink raw reply related
* [PATCH 2/2] Input: add support for aXiom touchscreen controller using SPI or I2C
From: Andrew Thomas @ 2026-01-26 16:38 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Henrik Rydberg
Cc: linux-input, devicetree, linux-kernel, Andrew Thomas,
Marco Felsch
In-Reply-To: <20260126-axiom-driver-submission3-v1-0-d462c4a608e3@touchnetix.com>
---
drivers/input/touchscreen/Kconfig | 25 ++
drivers/input/touchscreen/Makefile | 3 +
drivers/input/touchscreen/axiom_core.c | 473 +++++++++++++++++++++++++++++++++
drivers/input/touchscreen/axiom_core.h | 118 ++++++++
drivers/input/touchscreen/axiom_i2c.c | 150 +++++++++++
drivers/input/touchscreen/axiom_spi.c | 155 +++++++++++
6 files changed, 924 insertions(+)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 7d5b72ee07fa..d27292ccabc9 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -162,6 +162,31 @@ config TOUCHSCREEN_AUO_PIXCIR
To compile this driver as a module, choose M here: the
module will be called auo-pixcir-ts.
+config TOUCHSCREEN_AXIOM_CORE
+ tristate
+
+config TOUCHSCREEN_AXIOM_I2C
+ tristate "TouchNetix aXiom touchscreen (I2C)"
+ depends on I2C
+ select TOUCHSCREEN_AXIOM_CORE
+ help
+ Say Y here if the aXiom touchscreen is connected via
+ the I2C bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called axiom_i2c.
+
+config TOUCHSCREEN_AXIOM_SPI
+ tristate "TouchNetix aXiom touchscreen (SPI)"
+ depends on SPI
+ select TOUCHSCREEN_AXIOM_CORE
+ help
+ Say Y here if the aXiom touchscreen is connected via
+ the SPI bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called axiom_spi.
+
config TOUCHSCREEN_BU21013
tristate "BU21013 based touch panel controllers"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index ab9abd151078..9b7d572c4589 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -19,6 +19,9 @@ obj-$(CONFIG_TOUCHSCREEN_APPLE_Z2) += apple_z2.o
obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
+obj-$(CONFIG_TOUCHSCREEN_AXIOM_CORE) += axiom_core.o
+obj-$(CONFIG_TOUCHSCREEN_AXIOM_I2C) += axiom_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_AXIOM_SPI) += axiom_spi.o
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
obj-$(CONFIG_TOUCHSCREEN_BU21029) += bu21029_ts.o
obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8318) += chipone_icn8318.o
diff --git a/drivers/input/touchscreen/axiom_core.c b/drivers/input/touchscreen/axiom_core.c
new file mode 100644
index 000000000000..89a845ab90ba
--- /dev/null
+++ b/drivers/input/touchscreen/axiom_core.c
@@ -0,0 +1,473 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TouchNetix aXiom Touchscreen Driver
+ *
+ * Copyright (C) 2020-2026 TouchNetix Ltd.
+ *
+ * Author(s): Mark Satterthwaite <mark.satterthwaite@touchnetix.com>
+ * Pedro Torruella <pedro.torruella@touchnetix.com>
+ * Bart Prescott <bartp@baasheep.co.uk>
+ * Hannah Rossiter <hannah.rossiter@touchnetix.com>
+ * Andrew Thomas <andrew.thomas@touchnetix.com>
+ */
+
+#include <linux/device.h>
+#include <linux/input/mt.h>
+#include <linux/crc16.h>
+#include <linux/property.h>
+#include <linux/interrupt.h>
+#include <linux/unaligned.h>
+#include <linux/bitfield.h>
+#include "axiom_core.h"
+
+static bool poll_enable;
+module_param(poll_enable, bool, 0444);
+MODULE_PARM_DESC(poll_enable, "Enable polling mode [default 0=no]");
+
+static int poll_period = 10;
+module_param(poll_period, uint, 0444);
+MODULE_PARM_DESC(poll_period, "Polling period in ms [default = 10]");
+
+/* u31 device info masks */
+#define AX_DEV_ID_MASK GENMASK(14, 0)
+#define AX_MODE BIT(15)
+#define AX_FW_REV_MINOR_MASK GENMASK(7, 0)
+#define AX_FW_REV_MAJOR_MASK GENMASK(15, 8)
+#define AX_VARIANT_MASK GENMASK(5, 0)
+#define AX_FW_STATUS BIT(7)
+#define AX_TCP_REV_MASK GENMASK(15, 8)
+#define AX_BOOT_REV_MINOR_MASK GENMASK(7, 0)
+#define AX_BOOT_REV_MAJOR_MASK GENMASK(15, 8)
+#define AX_NUM_USAGES_MASK GENMASK(7, 0)
+#define AX_SILICON_REV_MASK GENMASK(11, 8)
+#define AX_RUNTIME_FW_PATCH_MASK GENMASK(15, 12)
+
+/* u31 usage table entry masks */
+#define AX_U31_USAGE_NUM_MASK GENMASK(7, 0)
+#define AX_U31_START_PAGE_MASK GENMASK(15, 8)
+#define AX_U31_NUM_PAGES_MASK GENMASK(7, 0)
+#define AX_U31_MAX_OFFSET_MASK GENMASK(14, 8)
+#define AX_U31_OFFSET_TYPE_BIT BIT(15)
+#define AX_U31_UIF_REV_MASK GENMASK(7, 0)
+#define AX_U31_USAGE_TYPE_MASK GENMASK(15, 8)
+
+/* u34 report masks */
+#define AX_U34_LEN_MASK GENMASK(6, 0)
+#define AX_U34_OVERFLOW BIT(7)
+#define AX_U34_USAGE_MASK GENMASK(15, 8)
+#define AX_U34_PAYLOAD_BUFFER (2)
+
+/* u41 report masks */
+#define AX_U41_PRESENT_MASK GENMASK(9, 0)
+#define U41_X_Y_OFFSET (2)
+#define U41_COORD_SIZE (4)
+#define U41_Z_OFFSET (42)
+
+static const char *const fw_variants[] = {
+ "3D",
+ "2D",
+ "FORCE",
+ "0D",
+ "XL",
+ "TOUCHPAD",
+};
+
+static int axiom_set_capabilities(struct input_dev *input_dev)
+{
+ input_dev->name = "TouchNetix aXiom Touchscreen";
+ input_dev->phys = "input/ts";
+
+ // Multi Touch
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, 65535, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, 65535, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_DISTANCE, 0, 127, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 127, 0, 0);
+
+ // each report id in u41 can be configured separately in u42,
+ // to keep it simple have all reports ids be touch.
+ input_mt_init_slots(input_dev, U41_MAX_TARGETS, INPUT_MT_DIRECT);
+
+ return 0;
+}
+
+static struct u31_usage_entry *usage_find_entry(struct axiom *ax, u16 usage)
+{
+ u16 i;
+
+ for (i = 0; i < ax->dev_info.num_usages; i++) {
+ if (ax->usage_table[i].usage_num == usage)
+ return &ax->usage_table[i];
+ }
+
+ pr_err("aXiom-core: Usage u%02x not found in usage table\n", usage);
+ return ERR_PTR(-EINVAL);
+}
+
+static void axiom_unpack_device_info(const u8 *buf,
+ struct axiom_device_info *info)
+{
+ u16 w;
+
+ w = get_unaligned_le16(buf);
+ info->device_id = FIELD_GET(AX_DEV_ID_MASK, w);
+ info->mode = !!(w & AX_MODE);
+
+ w = get_unaligned_le16(buf + 2);
+ info->runtime_fw_rev_minor = FIELD_GET(AX_FW_REV_MINOR_MASK, w);
+ info->runtime_fw_rev_major = FIELD_GET(AX_FW_REV_MAJOR_MASK, w);
+
+ w = get_unaligned_le16(buf + 4);
+ info->device_build_variant = FIELD_GET(AX_VARIANT_MASK, w);
+ info->runtime_fw_status = !!(w & AX_FW_STATUS);
+ info->tcp_revision = FIELD_GET(AX_TCP_REV_MASK, w);
+
+ w = get_unaligned_le16(buf + 6);
+ info->bootloader_fw_rev_minor = FIELD_GET(AX_BOOT_REV_MINOR_MASK, w);
+ info->bootloader_fw_rev_major = FIELD_GET(AX_BOOT_REV_MAJOR_MASK, w);
+
+ info->jedec_id = get_unaligned_le16(buf + 8);
+
+ w = get_unaligned_le16(buf + 10);
+ info->num_usages = FIELD_GET(AX_NUM_USAGES_MASK, w);
+ info->silicon_revision = FIELD_GET(AX_SILICON_REV_MASK, w);
+ info->runtime_fw_rev_patch = FIELD_GET(AX_RUNTIME_FW_PATCH_MASK, w);
+}
+
+static void axiom_unpack_usage_table(u8 *buf, struct axiom *ax)
+{
+ struct u31_usage_entry *entry;
+ u16 report_len;
+ u8 *ptr;
+ int i;
+ u16 w;
+
+ for (i = 0; i < ax->dev_info.num_usages && i < U31_MAX_USAGES; i++) {
+ entry = &ax->usage_table[i];
+ /* Calculate offset for this specific entry */
+ ptr = buf + (i * SIZE_U31_USAGE_ENTRY);
+
+ w = get_unaligned_le16(ptr);
+ entry->usage_num = FIELD_GET(AX_U31_USAGE_NUM_MASK, w);
+ entry->start_page = FIELD_GET(AX_U31_START_PAGE_MASK, w);
+
+ w = get_unaligned_le16(ptr + 2);
+ entry->num_pages = FIELD_GET(AX_U31_NUM_PAGES_MASK, w);
+ entry->max_offset = FIELD_GET(AX_U31_MAX_OFFSET_MASK, w);
+ entry->offset_type = !!(w & AX_U31_OFFSET_TYPE_BIT);
+
+ w = get_unaligned_le16(ptr + 4);
+ entry->uifrevision = FIELD_GET(AX_U31_UIF_REV_MASK, w);
+ entry->usage_type = FIELD_GET(AX_U31_USAGE_TYPE_MASK, w);
+
+ // Convert words to bytes
+ report_len = (entry->max_offset + 1) * 2;
+ if (entry->usage_type == REPORT &&
+ report_len > ax->max_report_len) {
+ ax->max_report_len = report_len;
+ }
+ }
+}
+
+static int axiom_init_dev_info(struct axiom *ax)
+{
+ struct u31_usage_entry *u;
+ const char *variant_str;
+ char silicon_rev;
+ int err;
+ int i;
+
+ /* Read page 0 of u31 */
+ err = ax->bus_ops->read(ax->dev, 0x0, SIZE_U31_DEVICE_INFO,
+ ax->read_buf);
+ if (err)
+ return -EIO;
+
+ axiom_unpack_device_info(ax->read_buf, &ax->dev_info);
+
+ silicon_rev = (char)(0x41 + ax->dev_info.silicon_revision);
+
+ if (ax->dev_info.device_build_variant < ARRAY_SIZE(fw_variants))
+ variant_str = fw_variants[ax->dev_info.device_build_variant];
+ else
+ variant_str = "UNKNOWN";
+
+ dev_info(ax->dev, "Firmware Info:\n");
+ dev_info(ax->dev, " BL Mode : %u\n", ax->dev_info.mode);
+ dev_info(ax->dev, " Device ID : %04x\n", ax->dev_info.device_id);
+ dev_info(ax->dev, " FW Revision : %u.%u.%u-%s %s\n",
+ ax->dev_info.runtime_fw_rev_major,
+ ax->dev_info.runtime_fw_rev_minor,
+ ax->dev_info.runtime_fw_rev_patch,
+ (ax->dev_info.runtime_fw_status == 0) ? "eng" : "prod",
+ variant_str);
+ dev_info(ax->dev, " BL Revision : %02x.%02x\n",
+ ax->dev_info.bootloader_fw_rev_major,
+ ax->dev_info.bootloader_fw_rev_minor);
+ dev_info(ax->dev, " Silicon : 0x%04X (Rev %c)\n",
+ ax->dev_info.jedec_id, silicon_rev);
+ dev_info(ax->dev, " Num Usages : %u\n", ax->dev_info.num_usages);
+
+ if (ax->dev_info.num_usages > U31_MAX_USAGES) {
+ dev_err(ax->dev,
+ "Num usages (%u) exceeds maximum supported (%u)\n",
+ ax->dev_info.num_usages, U31_MAX_USAGES);
+ return -EINVAL;
+ }
+
+ /* Read the second page of u31 to get the usage table */
+ err = ax->bus_ops->read(ax->dev, 0x100,
+ sizeof(ax->usage_table[0]) *
+ ax->dev_info.num_usages,
+ ax->read_buf);
+ if (err)
+ return -EIO;
+
+ axiom_unpack_usage_table(ax->read_buf, ax);
+
+ dev_info(ax->dev, "Usage Table:\n");
+ for (i = 0; i < ax->dev_info.num_usages; i++) {
+ u = &ax->usage_table[i];
+
+ dev_info(ax->dev, " Usage: u%02x Rev: %3u Page: 0x%02x00 Num Pages: %3u\n",
+ u->usage_num, u->uifrevision, u->start_page,
+ u->num_pages);
+ }
+
+ if (ax->max_report_len > AXIOM_MAX_READ_SIZE) {
+ dev_err(ax->dev,
+ "aXiom maximum report length (%u) greater than allocated buffer size (%u).",
+ ax->max_report_len, AXIOM_MAX_READ_SIZE);
+ return -EINVAL;
+ }
+
+ /* Set u34 address to allow direct access to report reading address */
+ u = usage_find_entry(ax, 0x34);
+ if (IS_ERR(u))
+ return PTR_ERR(u);
+ ax->u34_address = u->start_page << 8;
+
+ return 0;
+}
+
+static int axiom_process_u41_report(struct axiom *ax, u8 *report)
+{
+ enum u41_target_state_e state;
+ u16 target_present;
+ bool active;
+ u8 offset;
+ int i;
+ u16 x;
+ u16 y;
+ s8 z;
+
+ target_present =
+ FIELD_GET(AX_U41_PRESENT_MASK, get_unaligned_le16(&report[0]));
+
+ for (i = 0; i < U41_MAX_TARGETS; i++) {
+ active = !!((target_present >> i) & 1);
+
+ offset = U41_X_Y_OFFSET + (i * U41_COORD_SIZE);
+ x = get_unaligned_le16(&report[offset]);
+ y = get_unaligned_le16(&report[offset + 2]);
+ z = report[U41_Z_OFFSET + i];
+
+ if (!active)
+ state = target_state_not_present;
+ else if (z >= 0)
+ state = target_state_touching;
+ else if ((z > U41_PROX_LEVEL) && (z < 0))
+ state = target_state_hover;
+ else if (z == U41_PROX_LEVEL)
+ state = target_state_prox;
+ else
+ state = target_state_not_present;
+
+ dev_dbg(ax->dev, "Target %d: x=%u y=%u z=%d present=%d\n", i, x,
+ y, z, active);
+
+ switch (state) {
+ case target_state_not_present:
+ case target_state_prox:
+
+ input_mt_slot(ax->input, i);
+ input_mt_report_slot_inactive(ax->input);
+ break;
+
+ case target_state_hover:
+ case target_state_touching:
+
+ input_mt_slot(ax->input, i);
+ input_report_abs(ax->input, ABS_MT_TRACKING_ID, i);
+ input_report_abs(ax->input, ABS_MT_POSITION_X, x);
+ input_report_abs(ax->input, ABS_MT_POSITION_Y, y);
+
+ if (state == target_state_touching) {
+ input_report_abs(ax->input, ABS_MT_DISTANCE, 0);
+ input_report_abs(ax->input, ABS_MT_PRESSURE, z);
+ } else { /* Hover */
+ input_report_abs(ax->input, ABS_MT_DISTANCE, -z);
+ input_report_abs(ax->input, ABS_MT_PRESSURE, 0);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ input_mt_sync_frame(ax->input);
+ input_sync(ax->input);
+
+ return 0;
+}
+
+static int axiom_process_report(struct axiom *ax, u8 *report)
+{
+ u16 hdr_buf = get_unaligned_le16(&report[0]);
+ struct u34_report_header hdr;
+ u16 crc_report;
+ u16 crc_calc;
+ int err;
+ u8 len;
+
+ dev_dbg(ax->dev, "Payload Data %*ph\n", ax->max_report_len, report);
+
+ hdr.report_length = FIELD_GET(AX_U34_LEN_MASK, hdr_buf);
+ hdr.overflow = !!(hdr_buf & AX_U34_OVERFLOW);
+ hdr.report_usage = FIELD_GET(AX_U34_USAGE_MASK, hdr_buf);
+
+ len = hdr.report_length << 1;
+ if (hdr.report_length == 0) {
+ dev_err(ax->dev, "Zero length report discarded.\n");
+ return -EIO;
+ }
+
+ // Length is 16 bit words and remove the size of the CRC16 itself
+ crc_report = (report[len - 1] << 8) | (report[len - 2]);
+ crc_calc = crc16(0, report, (len - 2));
+
+ if (crc_calc != crc_report) {
+ dev_err(ax->dev,
+ "CRC mismatch! Expected: %04X, Calculated CRC: %04X. Report discarded.\n",
+ crc_report, crc_calc);
+ return -EIO;
+ }
+
+ switch (hdr.report_usage) {
+ case AX_2DCTS_REPORT_ID:
+ err = axiom_process_u41_report(ax,
+ &report[AX_U34_PAYLOAD_BUFFER]);
+ break;
+
+ default:
+ break;
+ }
+
+ return err;
+}
+
+static void axiom_poll(struct input_dev *input_dev)
+{
+ struct axiom *ax = input_get_drvdata(input_dev);
+ int err;
+
+ /* Read touch reports from u34 */
+ err = ax->bus_ops->read(ax->dev, ax->u34_address, ax->max_report_len,
+ ax->read_buf);
+ if (err)
+ return;
+
+ err = axiom_process_report(ax, ax->read_buf);
+ if (err)
+ dev_err(ax->dev, "Failed to process report: %d\n", err);
+}
+
+static irqreturn_t axiom_irq(int irq, void *handle)
+{
+ struct axiom *ax = handle;
+ int err;
+
+ /* Read touch reports from u34 */
+ err = ax->bus_ops->read(ax->dev, ax->u34_address, ax->max_report_len,
+ ax->read_buf);
+ if (err)
+ goto out;
+
+ err = axiom_process_report(ax, ax->read_buf);
+ if (err)
+ dev_err(ax->dev, "Failed to process report: %d\n", err);
+
+out:
+ return IRQ_HANDLED;
+}
+
+struct axiom *axiom_probe(const struct axiom_bus_ops *bus_ops,
+ struct device *dev, int irq)
+{
+ struct input_dev *input_dev;
+ struct axiom *ax;
+ int err;
+
+ ax = devm_kzalloc(dev, sizeof(*ax), GFP_KERNEL);
+ if (!ax)
+ return ERR_PTR(-ENOMEM);
+
+ input_dev = devm_input_allocate_device(dev);
+ if (!input_dev) {
+ pr_err("ERROR: aXiom-core: Failed to allocate memory for input device!\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ ax->dev = dev;
+ ax->input = input_dev;
+ ax->bus_ops = bus_ops;
+ ax->irq = irq;
+
+ dev_info(dev, "aXiom Probe\n");
+ if (poll_enable)
+ dev_info(dev, "Polling Period : %u\n", poll_period);
+ else
+ dev_info(dev, "Device IRQ : %u\n", ax->irq);
+
+ axiom_set_capabilities(input_dev);
+
+ err = axiom_init_dev_info(ax);
+ if (err) {
+ dev_err(ax->dev, "Failed to read device info, err: %d\n", err);
+ return ERR_PTR(err);
+ }
+
+ if (poll_enable) {
+ err = input_setup_polling(input_dev, axiom_poll);
+ if (err) {
+ dev_err(ax->dev, "could not set up polling mode, %d\n",
+ err);
+ return ERR_PTR(err);
+ }
+
+ input_set_poll_interval(input_dev, poll_period);
+ } else {
+ err = devm_request_threaded_irq(ax->dev, ax->irq, NULL,
+ axiom_irq,
+ IRQF_ONESHOT,
+ "axiom_irq", ax);
+ if (err)
+ return ERR_PTR(err);
+ }
+
+ err = input_register_device(input_dev);
+ if (err) {
+ dev_err(ax->dev, "Failed to register input device: %d\n", err);
+ return ERR_PTR(err);
+ }
+
+ input_set_drvdata(input_dev, ax);
+
+ return ax;
+}
+EXPORT_SYMBOL_GPL(axiom_probe);
+
+MODULE_AUTHOR("TouchNetix <support@touchnetix.com>");
+MODULE_DESCRIPTION("aXiom touchscreen core logic");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/axiom_core.h b/drivers/input/touchscreen/axiom_core.h
new file mode 100644
index 000000000000..8ca46200bede
--- /dev/null
+++ b/drivers/input/touchscreen/axiom_core.h
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * TouchNetix aXiom Touchscreen Driver
+ *
+ * Copyright (C) 2020-2026 TouchNetix Ltd.
+ *
+ * Author(s): Mark Satterthwaite <mark.satterthwaite@touchnetix.com>
+ * Pedro Torruella <pedro.torruella@touchnetix.com>
+ * Bart Prescott <bartp@baasheep.co.uk>
+ * Hannah Rossiter <hannah.rossiter@touchnetix.com>
+ * Andrew Thomas <andrew.thomas@touchnetix.com>
+ */
+
+#ifndef __AXIOM_CORE_H
+#define __AXIOM_CORE_H
+
+#include <linux/input.h>
+
+#define AX_POLLING_PERIOD_MS (10)
+
+#define AXIOM_PAGE_SIZE (256)
+// u31 has 2 pages for usage table entries. (2 * PAGE_SIZE) / U31_BYTES_PER_USAGE = 85
+#define AXIOM_MAX_READ_SIZE (2 * AXIOM_PAGE_SIZE)
+#define SIZE_U31_DEVICE_INFO (12)
+#define SIZE_U31_USAGE_ENTRY (6)
+#define U31_MAX_USAGES (85U)
+#define U41_MAX_TARGETS (10U)
+#define U41_PROX_LEVEL (-128)
+#define AXIOM_HOLDOFF_DELAY_US (40)
+
+enum ax_comms_op_e { AX_WR_OP = 0, AX_RD_OP = 1 };
+
+enum report_ids_e {
+ AX_2DCTS_REPORT_ID = 0x41,
+};
+
+enum axiom_mode_e {
+ AX_RUNTIME_STATE = 0,
+ AX_BOOTLOADER_STATE = 1,
+};
+
+enum usage_type_e {
+ UNKNOWN = 0,
+ OTHER = 1,
+ REPORT = 2,
+ REGISTER = 3,
+ REGISTER_READ_ONLY_ = 4,
+ CDU = 5,
+ CDU_READ_ONLY_ = 6,
+};
+
+struct axiom_device_info {
+ u16 device_id;
+ u8 mode;
+ u8 runtime_fw_rev_minor;
+ u8 runtime_fw_rev_major;
+ u8 device_build_variant;
+ u8 runtime_fw_status;
+ u8 tcp_revision;
+ u8 bootloader_fw_rev_minor;
+ u8 bootloader_fw_rev_major;
+ u8 jedec_id;
+ u8 num_usages;
+ u8 silicon_revision;
+ u8 runtime_fw_rev_patch;
+};
+
+struct u31_usage_entry {
+ u8 usage_num;
+ u8 start_page;
+ u8 num_pages;
+ u8 max_offset;
+ u8 offset_type;
+ u8 uifrevision;
+ u8 usage_type;
+};
+
+struct axiom_cmd_header {
+ __le16 target_address;
+ __le16 length_and_op;
+} __packed;
+
+struct axiom_bus_ops {
+ u16 bustype;
+ int (*write)(struct device *dev, u16 addr, u16 length, void *values);
+ int (*read)(struct device *dev, u16 addr, u16 length, void *values);
+};
+
+enum u41_target_state_e {
+ target_state_not_present = 0,
+ target_state_prox = 1,
+ target_state_hover = 2,
+ target_state_touching = 3,
+};
+
+struct axiom {
+ struct device *dev;
+ int irq;
+ struct input_dev *input;
+ const struct axiom_bus_ops *bus_ops;
+ struct axiom_device_info dev_info;
+ struct u31_usage_entry usage_table[U31_MAX_USAGES];
+ u16 max_report_len;
+ u16 u34_address;
+
+ u8 read_buf[AXIOM_MAX_READ_SIZE];
+};
+
+struct u34_report_header {
+ u8 report_length;
+ u8 overflow;
+ u8 report_usage;
+};
+
+struct axiom *axiom_probe(const struct axiom_bus_ops *bus_ops,
+ struct device *dev, int irq);
+
+#endif /* __AXIOM_CORE_H */
diff --git a/drivers/input/touchscreen/axiom_i2c.c b/drivers/input/touchscreen/axiom_i2c.c
new file mode 100644
index 000000000000..93b445f4ce54
--- /dev/null
+++ b/drivers/input/touchscreen/axiom_i2c.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TouchNetix aXiom Touchscreen Driver
+ *
+ * Copyright (C) 2020-2026 TouchNetix Ltd.
+ *
+ * Author(s): Mark Satterthwaite <mark.satterthwaite@touchnetix.com>
+ * Pedro Torruella <pedro.torruella@touchnetix.com>
+ * Bart Prescott <bartp@baasheep.co.uk>
+ * Hannah Rossiter <hannah.rossiter@touchnetix.com>
+ * Andrew Thomas <andrew.thomas@touchnetix.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/unaligned.h>
+#include "axiom_core.h"
+
+static int axiom_i2c_read_block_data(struct device *dev, u16 addr, u16 length,
+ void *values)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct axiom_cmd_header cmd_header;
+ u16 len_op;
+ int err;
+
+ put_unaligned_le16(addr, &cmd_header.target_address);
+ len_op = (length & 0x7FFF) | (AX_RD_OP << 15);
+ put_unaligned_le16(len_op, &cmd_header.length_and_op);
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = sizeof(cmd_header),
+ .buf = (u8 *)&cmd_header,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = values,
+ },
+ };
+
+ err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (err < 0) {
+ dev_err(dev, "I2C transfer error: %d\n", err);
+ return err;
+ }
+
+ udelay(AXIOM_HOLDOFF_DELAY_US);
+
+ return err != ARRAY_SIZE(msgs) ? -EIO : 0;
+}
+
+static int axiom_i2c_write_block_data(struct device *dev, u16 addr, u16 length,
+ void *values)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct axiom_cmd_header cmd_header;
+ u16 len_op;
+ int err;
+
+ put_unaligned_le16(addr, &cmd_header.target_address);
+ len_op = (length & 0x7FFF) | (AX_WR_OP << 15);
+ put_unaligned_le16(len_op, &cmd_header.length_and_op);
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = sizeof(cmd_header),
+ .buf = (u8 *)&cmd_header,
+ },
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = length,
+ .buf = values,
+ },
+ };
+
+ err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (err < 0) {
+ dev_err(dev, "I2C transfer error: %d\n", err);
+ return err;
+ }
+
+ udelay(AXIOM_HOLDOFF_DELAY_US);
+
+ return err != ARRAY_SIZE(msgs) ? -EIO : 0;
+}
+
+static const struct axiom_bus_ops axiom_i2c_bus_ops = {
+ .bustype = BUS_I2C,
+ .write = axiom_i2c_write_block_data,
+ .read = axiom_i2c_read_block_data,
+};
+
+static int axiom_i2c_probe(struct i2c_client *client)
+{
+ struct axiom *axiom;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "I2C functionality not Supported\n");
+ return -EIO;
+ }
+
+ axiom = axiom_probe(&axiom_i2c_bus_ops, &client->dev, client->irq);
+ if (IS_ERR(axiom))
+ return dev_err_probe(&client->dev, PTR_ERR(axiom),
+ "failed to register input device\n");
+
+ return 0;
+}
+
+static const struct i2c_device_id axiom_i2c_id_table[] = {
+ { "axiom-i2c" },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, axiom_i2c_id_table);
+
+static const struct of_device_id axiom_i2c_dt_ids[] = {
+ {
+ .compatible = "tnx,axiom-i2c",
+ .data = "axiom",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, axiom_i2c_dt_ids);
+
+static struct i2c_driver axiom_i2c_driver = {
+ .driver = {
+ .name = "axiom_i2c",
+ .of_match_table = axiom_i2c_dt_ids,
+ },
+ .id_table = axiom_i2c_id_table,
+ .probe = axiom_i2c_probe,
+};
+
+module_i2c_driver(axiom_i2c_driver);
+
+MODULE_AUTHOR("TouchNetix <support@touchnetix.com>");
+MODULE_DESCRIPTION("aXiom touchscreen I2C bus driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0.0");
diff --git a/drivers/input/touchscreen/axiom_spi.c b/drivers/input/touchscreen/axiom_spi.c
new file mode 100644
index 000000000000..a7d9d3dd66ce
--- /dev/null
+++ b/drivers/input/touchscreen/axiom_spi.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TouchNetix aXiom Touchscreen Driver
+ *
+ * Copyright (C) 2020-2026 TouchNetix Ltd.
+ *
+ * Author(s): Mark Satterthwaite <mark.satterthwaite@touchnetix.com>
+ * Pedro Torruella <pedro.torruella@touchnetix.com>
+ * Bart Prescott <bartp@baasheep.co.uk>
+ * Hannah Rossiter <hannah.rossiter@touchnetix.com>
+ * Andrew Thomas <andrew.thomas@touchnetix.com>
+ */
+
+#include <linux/of.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/input.h>
+#include <linux/unaligned.h>
+#include "axiom_core.h"
+
+#define SPI_PADDING_LEN (32)
+
+static int axiom_spi_transfer(struct device *dev, enum ax_comms_op_e op,
+ u16 addr, u16 length, void *values)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ u8 pad_buf[SPI_PADDING_LEN] = { 0 };
+ struct axiom_cmd_header cmd_header;
+ struct spi_transfer xfr_header;
+ struct spi_transfer xfr_padding;
+ struct spi_transfer xfr_payload;
+ struct spi_message msg;
+ u16 len_op;
+ int err;
+
+ put_unaligned_le16(addr, &cmd_header.target_address);
+ len_op = (length & 0x7FFF) | (AX_RD_OP << 15);
+ put_unaligned_le16(len_op, &cmd_header.length_and_op);
+
+ memset(&xfr_header, 0, sizeof(xfr_header));
+ memset(&xfr_padding, 0, sizeof(xfr_padding));
+ memset(&xfr_payload, 0, sizeof(xfr_payload));
+
+ /* Setup the SPI transfer operations */
+ xfr_header.tx_buf = &cmd_header;
+ xfr_header.len = sizeof(cmd_header);
+
+ xfr_padding.tx_buf = pad_buf;
+ xfr_padding.len = sizeof(pad_buf);
+
+ switch (op) {
+ case AX_WR_OP:
+ xfr_payload.tx_buf = values;
+ break;
+ case AX_RD_OP:
+ xfr_payload.rx_buf = values;
+ break;
+ default:
+ dev_err(dev, "%s: invalid operation: %d\n", __func__, op);
+ return -EINVAL;
+ }
+ xfr_payload.len = length;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfr_header, &msg);
+ spi_message_add_tail(&xfr_padding, &msg);
+ spi_message_add_tail(&xfr_payload, &msg);
+
+ err = spi_sync(spi, &msg);
+ if (err < 0) {
+ dev_err(&spi->dev, "Failed to SPI transfer, error: %d\n", err);
+ return err;
+ }
+
+ udelay(AXIOM_HOLDOFF_DELAY_US);
+
+ return 0;
+}
+
+static int axiom_spi_read_block_data(struct device *dev, u16 addr, u16 length,
+ void *values)
+{
+ return axiom_spi_transfer(dev, AX_RD_OP, addr, length, values);
+}
+
+static int axiom_spi_write_block_data(struct device *dev, u16 addr, u16 length,
+ void *values)
+{
+ return axiom_spi_transfer(dev, AX_WR_OP, addr, length, values);
+}
+
+static const struct axiom_bus_ops axiom_spi_bus_ops = {
+ .bustype = BUS_SPI,
+ .write = axiom_spi_write_block_data,
+ .read = axiom_spi_read_block_data,
+};
+
+static int axiom_spi_probe(struct spi_device *spi)
+{
+ struct axiom *axiom;
+ int err;
+
+ /* Set up SPI */
+ spi->bits_per_word = 8;
+ spi->mode = SPI_MODE_0;
+ spi->max_speed_hz = 4000000;
+
+ if (spi->irq == 0)
+ dev_err(&spi->dev, "No IRQ specified!\n");
+
+ err = spi_setup(spi);
+ if (err < 0) {
+ dev_err(&spi->dev, "%s: SPI setup error %d\n", __func__, err);
+ return err;
+ }
+ axiom = axiom_probe(&axiom_spi_bus_ops, &spi->dev, spi->irq);
+ if (IS_ERR(axiom))
+ return dev_err_probe(&spi->dev, PTR_ERR(axiom),
+ "failed to register input device\n");
+
+ return 0;
+}
+
+static const struct spi_device_id axiom_spi_id_table[] = {
+ { "axiom-spi" },
+ {},
+};
+MODULE_DEVICE_TABLE(spi, axiom_spi_id_table);
+
+static const struct of_device_id axiom_spi_dt_ids[] = {
+ {
+ .compatible = "tnx,axiom-spi",
+ .data = "axiom",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, axiom_spi_dt_ids);
+
+static struct spi_driver axiom_spi_driver = {
+ .id_table = axiom_spi_id_table,
+ .driver = {
+ .name = "axiom_spi",
+ .of_match_table = axiom_spi_dt_ids,
+ },
+ .probe = axiom_spi_probe,
+};
+
+module_spi_driver(axiom_spi_driver);
+
+MODULE_AUTHOR("TouchNetix <support@touchnetix.com>");
+MODULE_DESCRIPTION("aXiom touchscreen SPI bus driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0.0");
--
2.43.0
^ permalink raw reply related
* [PATCH] dt-bindings: Fix emails with spaces or missing brackets
From: Rob Herring (Arm) @ 2026-01-26 16:47 UTC (permalink / raw)
To: Guenter Roeck, Krzysztof Kozlowski, Conor Dooley, Dmitry Torokhov,
Mauro Carvalho Chehab, Alim Akhtar, Karthikeyan Mitran,
Hou Zhiqiang, Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Bjorn Helgaas, Christopher Ruehl,
Jason A. Donenfeld, Matthias Schiffer, Vincent Huang, Inki Dae,
Seung-Woo Kim, Frank Li
Cc: Krzysztof Kozlowski, linux-hwmon, devicetree, linux-kernel,
linux-input, linux-media, linux-arm-kernel, linux-samsung-soc,
linux-pci
Fix email addresses with spaces or missing brackets. A pending
dtschema meta-schema change will check for these.
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
---
Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml | 2 +-
Documentation/devicetree/bindings/input/syna,rmi4.yaml | 2 +-
.../devicetree/bindings/media/samsung,exynos5250-gsc.yaml | 2 +-
Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml b/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
index 3d14d5fc96c5..7b38f2182ffa 100644
--- a/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
+++ b/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sensirion SHTC1 Humidity and Temperature Sensor IC
maintainers:
- - Christopher Ruehl chris.ruehl@gtsys.com.hk
+ - Christopher Ruehl <chris.ruehl@gtsys.com.hk>
description: |
The SHTC1, SHTW1 and SHTC3 are digital humidity and temperature sensors
diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
index f369385ffaf0..8685ef4481f4 100644
--- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml
+++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
@@ -8,7 +8,7 @@ title: Synaptics RMI4 compliant devices
maintainers:
- Jason A. Donenfeld <Jason@zx2c4.com>
- - Matthias Schiffer <matthias.schiffer@ew.tq-group.com
+ - Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
- Vincent Huang <vincent.huang@tw.synaptics.com>
description: |
diff --git a/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml b/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml
index 878397830a4d..9196cf5dac0f 100644
--- a/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml
+++ b/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml
@@ -9,7 +9,7 @@ title: Samsung Exynos SoC G-Scaler
maintainers:
- Inki Dae <inki.dae@samsung.com>
- Krzysztof Kozlowski <krzk@kernel.org>
- - Seung-Woo Kim <sw0312.kim@samsung.com
+ - Seung-Woo Kim <sw0312.kim@samsung.com>
description:
G-Scaler is used for scaling and color space conversion on Samsung Exynos
diff --git a/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml b/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml
index d286b77921e0..8f5d33050348 100644
--- a/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mobiveil AXI PCIe Host Bridge
maintainers:
- - Frank Li <Frank Li@nxp.com>
+ - Frank Li <Frank.Li@nxp.com>
description:
Mobiveil's GPEX 4.0 is a PCIe Gen4 host bridge IP. This configurable IP
--
2.51.0
^ permalink raw reply related
* Re: [PATCH 1/2] dt-bindings: input: touchscreen: add TouchNetix aXiom device tree
From: Rob Herring (Arm) @ 2026-01-26 17:32 UTC (permalink / raw)
To: Andrew Thomas
Cc: linux-kernel, devicetree, Marco Felsch, Conor Dooley,
Dmitry Torokhov, Krzysztof Kozlowski, Henrik Rydberg, linux-input
In-Reply-To: <20260126-axiom-driver-submission3-v1-1-d462c4a608e3@touchnetix.com>
On Mon, 26 Jan 2026 16:38:23 +0000, Andrew Thomas wrote:
> ---
> .../bindings/input/touchscreen/tnx,axiom.yaml | 70 ++++++++++++++++++++++
> .../devicetree/bindings/vendor-prefixes.yaml | 2 +
> 2 files changed, 72 insertions(+)
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/input/touchscreen/tnx,axiom.example.dtb: /example-0/i2c/touchscreen@66: failed to match any schema with compatible: ['tnx,axiom-i2c']
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/input/touchscreen/tnx,axiom.example.dtb: touchscreen@66 (tnx,axiom-i2c): 'axiom,poll-enable', 'axiom,poll-period' do not match any of the regexes: '^#.*', '^(at25|bm|devbus|dmacap|dsa|exynos|fsi[ab]|gpio-fan|gpio-key|gpio|gpmc|hdmi|i2c-gpio),.*', '^(keypad|m25p|max8952|max8997|max8998|mpmc),.*', '^(pciclass|pinctrl-single|#pinctrl-single|PowerPC),.*', '^(pl022|pxa-mmc|rcar_sound|rotary-encoder|s5m8767|sdhci),.*', '^(simple-audio-card|st-plgpio|st-spics|ts|vsc8531),.*', '^100ask,.*', '^70mai,.*', '^8dev,.*', '^9tripod,.*', '^GEFanuc,.*', '^IBM,.*', '^ORCL,.*', '^SUNW,.*', '^[a-zA-Z0-9#_][a-zA-Z0-9#+\\-._@]{0,63}$', '^[a-zA-Z0-9+\\-._]*@[0-9a-zA-Z,]*$', '^abb,.*', '^abilis,.*', '^abracon,.*', '^abt,.*', '^acbel,.*', '^acelink,.*', '^acer,.*', '^acme,.*', '^actions,.*', '^actiontec,.*', '^active-semi,.*', '^ad,.*', '^adafruit,.*', '^adapteva,.*', '^adaptrum,.*', '^adh,.*', '^adi,.*', '^adieng,.*', '^admatec,.*', '^advantech,.*', '^aeroflexgaisler,.*', '^aesop,.*', '^airoha,.*', '^al,.*', '^alcatel,.*', '^aldec,.*', '^alfa-network,.*', '^algoltek,.*', '^allegro,.*', '^allegromicro,.*', '^alliedtelesis,.*', '^alliedvision,.*', '^allo,.*', '^allwinner,.*', '^alphascale,.*', '^alps,.*', '^alt,.*', '^altr,.*', '^amarula,.*', '^amazon,.*', '^amcc,.*', '^amd,.*', '^amediatech,.*', '^amlogic,.*', '^ampere,.*', '^amphenol,.*', '^ampire,.*', '^ams,.*', '^amstaos,.*', '^analogix,.*', '^anbernic,.*', '^andestech,.*', '^anlogic,.*', '^anvo,.*', '^aoly,.*', '^aosong,.*', '^apm,.*', '^apple,.*', '^aptina,.*', '^arasan,.*', '^archermind,.*', '^arcom,.*', '^arctic,.*', '^arcx,.*', '^arduino,.*', '^argon40,.*', '^ariaboard,.*', '^aries,.*', '^arm,.*', '^armadeus,.*', '^armsom,.*', '^arrow,.*', '^artesyn,.*', '^asahi-kasei,.*', '^asc,.*', '^asix,.*', '^asl-tek,.*', '^aspeed,.*', '^asrock,.*', '^asteralabs,.*', '^asus,.*', '^atheros,.*', '^atlas,.*', '^atmel,.*', '^auo,.*', '^auvidea,.*', '^avago,.*', '^avia,.*', '^avic,.*', '^avnet,.*', '^awinic,.*', '^axentia,.*', '^axiado,.*', '^axis,.*', '^azoteq,.*', '^azw,.*', '^baikal,.*', '^bananapi,.*', '^beacon,.*', '^beagle,.*', '^belling,.*', '^bestar,.*', '^bhf,.*', '^bigtreetech,.*', '^bitmain,.*', '^blaize,.*', '^bluegiga,.*', '^blutek,.*', '^boe,.*', '^bosch,.*', '^boundary,.*', '^brcm,.*', '^broadmobi,.*', '^bsh,.*', '^bst,.*', '^bticino,.*', '^buffalo,.*', '^buglabs,.*', '^bur,.*', '^bytedance,.*', '^calamp,.*', '^calao,.*', '^calaosystems,.*', '^calxeda,.*', '^cameo,.*', '^canaan,.*', '^caninos,.*', '^capella,.*', '^cascoda,.*', '^catalyst,.*', '^cavium,.*', '^cct,.*', '^cdns,.*', '^cdtech,.*', '^cellwise,.*', '^ceva,.*', '^chargebyte,.*', '^checkpoint,.*', '^chefree,.*', '^chipidea,.*', '^chipone,.*', '^chipspark,.*', '^chongzhou,.*', '^chrontel,.*', '^chrp,.*', '^chunghwa,.*', '^chuwi,.*', '^ciaa,.*', '^cirrus,.*', '^cisco,.*', '^cix,.*', '^clockwork,.*', '^cloos,.*', '^cloudengines,.*', '^cnm,.*', '^cnxt,.*', '^colorfly,.*', '^compal,.*', '^compulab,.*', '^comvetia,.*', '^congatec,.*', '^coolpi,.*', '^coreriver,.*', '^corpro,.*', '^cortina,.*', '^cosmic,.*', '^crane,.*', '^creative,.*', '^crystalfontz,.*', '^csky,.*', '^csot,.*', '^csq,.*', '^csr,.*', '^ctera,.*', '^ctu,.*', '^cubietech,.*', '^cudy,.*', '^cui,.*', '^cypress,.*', '^cyx,.*', '^cznic,.*', '^dallas,.*', '^dataimage,.*', '^davicom,.*', '^deepcomputing,.*', '^dell,.*', '^delta,.*', '^densitron,.*', '^denx,.*', '^devantech,.*', '^dfi,.*', '^dfrobot,.*', '^dh,.*', '^difrnce,.*', '^digi,.*', '^digilent,.*', '^dimonoff,.*', '^diodes,.*', '^dioo,.*', '^djn,.*', '^dlc,.*', '^dlg,.*', '^dlink,.*', '^dmo,.*', '^domintech,.*', '^dongwoon,.*', '^dptechnics,.*', '^dragino,.*', '^dream,.*', '^ds,.*', '^dserve,.*', '^dynaimage,.*', '^ea,.*', '^ebang,.*', '^ebbg,.*', '^ebs-systart,.*', '^ebv,.*', '^eckelmann,.*', '^econet,.*', '^edgeble,.*', '^edimax,.*', '^edt,.*', '^ees,.*', '^eeti,.*', '^egnite,.*', '^einfochips,.*', '^eink,.*', '^elan,.*', '^element14,.*', '^elgin,.*', '^elida,.*', '^elimo,.*', '^elpida,.*', '^embedfire,.*', '^embest,.*', '^emcraft,.*', '^emlid,.*', '^emmicro,.*', '^empire-electronix,.*', '^emtrion,.*', '^enbw,.*', '^enclustra,.*', '^endian,.*', '^endless,.*', '^ene,.*', '^energymicro,.*', '^engicam,.*', '^engleder,.*', '^epcos,.*', '^epfl,.*', '^epson,.*', '^esp,.*', '^est,.*', '^eswin,.*', '^ettus,.*', '^eukrea,.*', '^everest,.*', '^everspin,.*', '^evervision,.*', '^exar,.*', '^excito,.*', '^exegin,.*', '^ezchip,.*', '^ezurio,.*', '^facebook,.*', '^fairchild,.*', '^fairphone,.*', '^faraday,.*', '^fascontek,.*', '^fastrax,.*', '^fcs,.*', '^feixin,.*', '^feiyang,.*', '^fii,.*', '^firefly,.*', '^fitipower,.*', '^flipkart,.*', '^focaltech,.*', '^forlinx,.*', '^foursemi,.*', '^foxlink,.*', '^freebox,.*', '^freecom,.*', '^frida,.*', '^friendlyarm,.*', '^fsl,.*', '^fujitsu,.*', '^fxtec,.*', '^galaxycore,.*', '^gameforce,.*', '^gardena,.*', '^gateway,.*', '^gateworks,.*', '^gcw,.*', '^ge,.*', '^geekbuying,.*', '^gef,.*', '^gehc,.*', '^gemei,.*', '^gemtek,.*', '^genesys,.*', '^genexis,.*', '^geniatech,.*', '^giantec,.*', '^giantplus,.*', '^glinet,.*', '^globalscale,.*', '^globaltop,.*', '^gmt,.*', '^gocontroll,.*', '^goldelico,.*', '^goodix,.*', '^google,.*', '^goramo,.*', '^gplus,.*', '^grinn,.*', '^grmn,.*', '^gumstix,.*', '^gw,.*', '^hannstar,.*', '^haochuangyi,.*', '^haoyu,.*', '^hardkernel,.*', '^hce,.*', '^headacoustics,.*', '^hechuang,.*', '^hideep,.*', '^himax,.*', '^hinlink,.*', '^hirschmann,.*', '^hisi,.*', '^hisilicon,.*', '^hit,.*', '^hitex,.*', '^holt,.*', '^holtek,.*', '^honestar,.*', '^honeywell,.*', '^hoperf,.*', '^hoperun,.*', '^hp,.*', '^hpe,.*', '^hsg,.*', '^htc,.*', '^huawei,.*', '^hugsun,.*', '^huiling,.*', '^hwacom,.*', '^hxt,.*', '^hycon,.*', '^hydis,.*', '^hynitron,.*', '^hynix,.*', '^hyundai,.*', '^i2se,.*', '^ibm,.*', '^icplus,.*', '^idt,.*', '^iei,.*', '^ifi,.*', '^ifm,.*', '^ilitek,.*', '^imagis,.*', '^img,.*', '^imi,.*', '^inanbo,.*', '^incircuit,.*', '^incostartec,.*', '^indiedroid,.*', '^inet-tek,.*', '^infineon,.*', '^inforce,.*', '^ingenic,.*', '^ingrasys,.*', '^injoinic,.*', '^innocomm,.*', '^innolux,.*', '^inside-secure,.*', '^insignal,.*', '^inspur,.*', '^intel,.*', '^intercontrol,.*', '^invensense,.*', '^inventec,.*', '^inversepath,.*', '^iom,.*', '^irondevice,.*', '^isee,.*', '^isil,.*', '^issi,.*', '^ite,.*', '^itead,.*', '^itian,.*', '^ivo,.*', '^iwave,.*', '^jadard,.*', '^jasonic,.*', '^jdi,.*', '^jedec,.*', '^jenson,.*', '^jesurun,.*', '^jethome,.*', '^jianda,.*', '^jide,.*', '^joz,.*', '^jty,.*', '^jutouch,.*', '^kam,.*', '^karo,.*', '^keithkoep,.*', '^keymile,.*', '^khadas,.*', '^kiebackpeter,.*', '^kinetic,.*', '^kingdisplay,.*', '^kingnovel,.*', '^kionix,.*', '^kobo,.*', '^kobol,.*', '^koe,.*', '^kontron,.*', '^kosagi,.*', '^kvg,.*', '^kyo,.*', '^lacie,.*', '^laird,.*', '^lamobo,.*', '^lantiq,.*', '^lattice,.*', '^lckfb,.*', '^lctech,.*', '^leadtek,.*', '^leez,.*', '^lego,.*', '^lemaker,.*', '^lenovo,.*', '^lg,.*', '^lgphilips,.*', '^libretech,.*', '^licheepi,.*', '^linaro,.*', '^lincolntech,.*', '^lineartechnology,.*', '^linkease,.*', '^linksprite,.*', '^linksys,.*', '^linutronix,.*', '^linux,.*', '^linx,.*', '^liontron,.*', '^liteon,.*', '^litex,.*', '^lltc,.*', '^logicpd,.*', '^logictechno,.*', '^longcheer,.*', '^lontium,.*', '^loongmasses,.*', '^loongson,.*', '^lsi,.*', '^luckfox,.*', '^lunzn,.*', '^luxul,.*', '^lwn,.*', '^lxa,.*', '^m5stack,.*', '^macnica,.*', '^mantix,.*', '^mapleboard,.*', '^marantec,.*', '^marvell,.*', '^maxbotix,.*', '^maxim,.*', '^maxlinear,.*', '^maxtor,.*', '^mayqueen,.*', '^mbvl,.*', '^mcube,.*', '^meas,.*', '^mecer,.*', '^mediatek,.*', '^medion,.*', '^megachips,.*', '^mele,.*', '^melexis,.*', '^melfas,.*', '^mellanox,.*', '^memsensing,.*', '^memsic,.*', '^menlo,.*', '^mentor,.*', '^meraki,.*', '^merrii,.*', '^methode,.*', '^micrel,.*', '^microchip,.*', '^microcrystal,.*', '^micron,.*', '^microsoft,.*', '^microsys,.*', '^microtips,.*', '^mikroe,.*', '^mikrotik,.*', '^milianke,.*', '^milkv,.*', '^miniand,.*', '^minix,.*', '^mips,.*', '^miramems,.*', '^mitsubishi,.*', '^mitsumi,.*', '^mixel,.*', '^miyoo,.*', '^mntre,.*', '^mobileye,.*', '^modtronix,.*', '^moortec,.*', '^mosaixtech,.*', '^motorcomm,.*', '^motorola,.*', '^moxa,.*', '^mpl,.*', '^mps,.*', '^mqmaker,.*', '^mrvl,.*', '^mscc,.*', '^msi,.*', '^mstar,.*', '^mti,.*', '^multi-inno,.*', '^mundoreader,.*', '^murata,.*', '^mxic,.*', '^mxicy,.*', '^myir,.*', '^national,.*', '^neardi,.*', '^nec,.*', '^neofidelity,.*', '^neonode,.*', '^netcube,.*', '^netgear,.*', '^netlogic,.*', '^netron-dy,.*', '^netronix,.*', '^netxeon,.*', '^neweast,.*', '^newhaven,.*', '^newvision,.*', '^nexbox,.*', '^nextthing,.*', '^ni,.*', '^nicera,.*', '^nintendo,.*', '^nlt,.*', '^nokia,.*', '^nordic,.*', '^nothing,.*', '^novatech,.*', '^novatek,.*', '^novtech,.*', '^nuclei,.*', '^numonyx,.*', '^nutsboard,.*', '^nuvoton,.*', '^nvd,.*', '^nvidia,.*', '^nxp,.*', '^oceanic,.*', '^ocs,.*', '^oct,.*', '^okaya,.*', '^oki,.*', '^olimex,.*', '^olpc,.*', '^oneplus,.*', '^onie,.*', '^onion,.*', '^onnn,.*', '^ontat,.*', '^opalkelly,.*', '^openailab,.*', '^opencores,.*', '^openembed,.*', '^openpandora,.*', '^openrisc,.*', '^openwrt,.*', '^option,.*', '^oranth,.*', '^orisetech,.*', '^ortustech,.*', '^osddisplays,.*', '^osmc,.*', '^ouya,.*', '^overkiz,.*', '^ovti,.*', '^oxsemi,.*', '^ozzmaker,.*', '^panasonic,.*', '^parade,.*', '^parallax,.*', '^particle,.*', '^pda,.*', '^pegatron,.*', '^pericom,.*', '^pervasive,.*', '^phicomm,.*', '^phontech,.*', '^phytec,.*', '^picochip,.*', '^pinctrl-[0-9]+$', '^pine64,.*', '^pineriver,.*', '^pixcir,.*', '^plantower,.*', '^plathome,.*', '^plda,.*', '^plx,.*', '^ply,.*', '^pni,.*', '^pocketbook,.*', '^polaroid,.*', '^polyhex,.*', '^pool[0-3],.*', '^portwell,.*', '^poslab,.*', '^pov,.*', '^powertip,.*', '^powervr,.*', '^powkiddy,.*', '^pri,.*', '^primeview,.*', '^primux,.*', '^probox2,.*', '^prt,.*', '^pulsedlight,.*', '^purism,.*', '^puya,.*', '^qca,.*', '^qcom,.*', '^qemu,.*', '^qi,.*', '^qiaodian,.*', '^qihua,.*', '^qishenglong,.*', '^qnap,.*', '^quanta,.*', '^radxa,.*', '^raidsonic,.*', '^ralink,.*', '^ramtron,.*', '^raspberrypi,.*', '^raumfeld,.*', '^raydium,.*', '^raystar,.*', '^rda,.*', '^realtek,.*', '^relfor,.*', '^remarkable,.*', '^renesas,.*', '^rervision,.*', '^retronix,.*', '^revotics,.*', '^rex,.*', '^rfdigital,.*', '^richtek,.*', '^ricoh,.*', '^rikomagic,.*', '^riot,.*', '^riscv,.*', '^rockchip,.*', '^rocktech,.*', '^rohm,.*', '^ronbo,.*', '^ronetix,.*', '^roofull,.*', '^roseapplepi,.*', '^rve,.*', '^saef,.*', '^sakurapi,.*', '^samsung,.*', '^samtec,.*', '^sancloud,.*', '^sandisk,.*', '^satoz,.*', '^sbs,.*', '^schindler,.*', '^schneider,.*', '^schulercontrol,.*', '^sciosense,.*', '^sdmc,.*', '^seagate,.*', '^seeed,.*', '^seirobotics,.*', '^semtech,.*', '^senseair,.*', '^sensirion,.*', '^sensortek,.*', '^sercomm,.*', '^sff,.*', '^sgd,.*', '^sgmicro,.*', '^sgx,.*', '^sharp,.*', '^shift,.*', '^shimafuji,.*', '^shineworld,.*', '^shiratech,.*', '^si-en,.*', '^si-linux,.*', '^sielaff,.*', '^siemens,.*', '^sifive,.*', '^siflower,.*', '^sigma,.*', '^sii,.*', '^sil,.*', '^silabs,.*', '^silan,.*', '^silead,.*', '^silergy,.*', '^silex-insight,.*', '^siliconfile,.*', '^siliconmitus,.*', '^silvaco,.*', '^simtek,.*', '^sinlinx,.*', '^sinovoip,.*', '^sinowealth,.*', '^sipeed,.*', '^sirf,.*', '^sis,.*', '^sitronix,.*', '^skov,.*', '^skyworks,.*', '^smartfiber,.*', '^smartlabs,.*', '^smartrg,.*', '^smi,.*', '^smsc,.*', '^snps,.*', '^sochip,.*', '^socionext,.*', '^solidrun,.*', '^solomon,.*', '^somfy,.*', '^sony,.*', '^sophgo,.*', '^sourceparts,.*', '^spacemit,.*', '^spansion,.*', '^sparkfun,.*', '^spinalhdl,.*', '^sprd,.*', '^square,.*', '^ssi,.*', '^sst,.*', '^sstar,.*', '^st,.*', '^st-ericsson,.*', '^starfive,.*', '^starry,.*', '^startek,.*', '^starterkit,.*', '^ste,.*', '^stericsson,.*', '^storlink,.*', '^storm,.*', '^storopack,.*', '^summit,.*', '^sunchip,.*', '^sundance,.*', '^sunplus,.*', '^supermicro,.*', '^swir,.*', '^syna,.*', '^synaptics,.*', '^synology,.*', '^synopsys,.*', '^taos,.*', '^tbs,.*', '^tbs-biometrics,.*', '^tcg,.*', '^tcl,.*', '^tcs,.*', '^tcu,.*', '^tdo,.*', '^team-source-display,.*', '^technexion,.*', '^technologic,.*', '^techstar,.*', '^techwell,.*', '^teejet,.*', '^teltonika,.*', '^tempo,.*', '^tenda,.*', '^tenstorrent,.*', '^terasic,.*', '^tesla,.*', '^test,.*', '^tfc,.*', '^thead,.*', '^thine,.*', '^thingyjp,.*', '^thundercomm,.*', '^thwc,.*', '^ti,.*', '^tianma,.*', '^tlm,.*', '^tmt,.*', '^tnx,.*', '^topeet,.*', '^topic,.*', '^topland,.*', '^toppoly,.*', '^topwise,.*', '^toradex,.*', '^toshiba,.*', '^toumaz,.*', '^tpk,.*', '^tplink,.*', '^tpo,.*', '^tq,.*', '^transpeed,.*', '^traverse,.*', '^tronfy,.*', '^tronsmart,.*', '^truly,.*', '^tsd,.*', '^turing,.*', '^tuxedo,.*', '^tyan,.*', '^tyhx,.*', '^u-blox,.*', '^u-boot,.*', '^ubnt,.*', '^ucrobotics,.*', '^udoo,.*', '^ufispace,.*', '^ugoos,.*', '^ultrarisc,.*', '^ultratronik,.*', '^uni-t,.*', '^uniwest,.*', '^upisemi,.*', '^urt,.*', '^usi,.*', '^usr,.*', '^utoo,.*', '^v3,.*', '^vaisala,.*', '^valve,.*', '^vamrs,.*', '^variscite,.*', '^vdl,.*', '^vertexcom,.*', '^via,.*', '^vialab,.*', '^vicor,.*', '^videostrong,.*', '^virtio,.*', '^virtual,.*', '^vishay,.*', '^visionox,.*', '^vitesse,.*', '^vivante,.*', '^vivax,.*', '^vocore,.*', '^voipac,.*', '^voltafield,.*', '^vot,.*', '^vscom,.*', '^vxt,.*', '^wacom,.*', '^wanchanglong,.*', '^wand,.*', '^waveshare,.*', '^wd,.*', '^we,.*', '^welltech,.*', '^wetek,.*', '^wexler,.*', '^whwave,.*', '^wi2wi,.*', '^widora,.*', '^wiligear,.*', '^willsemi,.*', '^winbond,.*', '^wingtech,.*', '^winlink,.*', '^winsen,.*', '^winstar,.*', '^wirelesstag,.*', '^wits,.*', '^wlf,.*', '^wm,.*', '^wobo,.*', '^wolfvision,.*', '^x-powers,.*', '^xen,.*', '^xes,.*', '^xiaomi,.*', '^xicor,.*', '^xillybus,.*', '^xingbangda,.*', '^xinpeng,.*', '^xiphera,.*', '^xlnx,.*', '^xnano,.*', '^xunlong,.*', '^xylon,.*', '^yadro,.*', '^yamaha,.*', '^yes-optoelectronics,.*', '^yic,.*', '^yiming,.*', '^ylm,.*', '^yna,.*', '^yones-toptech,.*', '^ys,.*', '^ysoft,.*', '^yuridenki,.*', '^yuzukihd,.*', '^zarlink,.*', '^zealz,.*', '^zeitec,.*', '^zidoo,.*', '^zii,.*', '^zinitix,.*', '^zkmagic,.*', '^zte,.*', '^zyxel,.*'
from schema $id: http://devicetree.org/schemas/vendor-prefixes.yaml
Documentation/devicetree/bindings/input/touchscreen/tnx,axiom.example.dtb: /example-1/spi/touchscreen@0: failed to match any schema with compatible: ['tnx,axiom-spi']
doc reference errors (make refcheckdocs):
See https://patchwork.kernel.org/project/devicetree/patch/20260126-axiom-driver-submission3-v1-1-d462c4a608e3@touchnetix.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply
* Re: [PATCH] dt-bindings: Fix emails with spaces or missing brackets
From: Guenter Roeck @ 2026-01-26 17:21 UTC (permalink / raw)
To: Rob Herring (Arm), Krzysztof Kozlowski, Conor Dooley,
Dmitry Torokhov, Mauro Carvalho Chehab, Alim Akhtar,
Karthikeyan Mitran, Hou Zhiqiang, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Bjorn Helgaas,
Christopher Ruehl, Jason A. Donenfeld, Matthias Schiffer,
Vincent Huang, Inki Dae, Seung-Woo Kim, Frank Li
Cc: Krzysztof Kozlowski, linux-hwmon, devicetree, linux-kernel,
linux-input, linux-media, linux-arm-kernel, linux-samsung-soc,
linux-pci
In-Reply-To: <20260126164724.2832009-1-robh@kernel.org>
On 1/26/26 08:47, Rob Herring (Arm) wrote:
> Fix email addresses with spaces or missing brackets. A pending
> dtschema meta-schema change will check for these.
>
> Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
For hwmon:
Acked-by: Guenter Roeck <linux@roeck-us.net>
> ---
> Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml | 2 +-
> Documentation/devicetree/bindings/input/syna,rmi4.yaml | 2 +-
> .../devicetree/bindings/media/samsung,exynos5250-gsc.yaml | 2 +-
> Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml | 2 +-
> 4 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml b/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
> index 3d14d5fc96c5..7b38f2182ffa 100644
> --- a/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
> +++ b/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
> @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
> title: Sensirion SHTC1 Humidity and Temperature Sensor IC
>
> maintainers:
> - - Christopher Ruehl chris.ruehl@gtsys.com.hk
> + - Christopher Ruehl <chris.ruehl@gtsys.com.hk>
>
> description: |
> The SHTC1, SHTW1 and SHTC3 are digital humidity and temperature sensors
> diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> index f369385ffaf0..8685ef4481f4 100644
> --- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> +++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> @@ -8,7 +8,7 @@ title: Synaptics RMI4 compliant devices
>
> maintainers:
> - Jason A. Donenfeld <Jason@zx2c4.com>
> - - Matthias Schiffer <matthias.schiffer@ew.tq-group.com
> + - Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
> - Vincent Huang <vincent.huang@tw.synaptics.com>
>
> description: |
> diff --git a/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml b/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml
> index 878397830a4d..9196cf5dac0f 100644
> --- a/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml
> +++ b/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml
> @@ -9,7 +9,7 @@ title: Samsung Exynos SoC G-Scaler
> maintainers:
> - Inki Dae <inki.dae@samsung.com>
> - Krzysztof Kozlowski <krzk@kernel.org>
> - - Seung-Woo Kim <sw0312.kim@samsung.com
> + - Seung-Woo Kim <sw0312.kim@samsung.com>
>
> description:
> G-Scaler is used for scaling and color space conversion on Samsung Exynos
> diff --git a/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml b/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml
> index d286b77921e0..8f5d33050348 100644
> --- a/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml
> +++ b/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml
> @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
> title: Mobiveil AXI PCIe Host Bridge
>
> maintainers:
> - - Frank Li <Frank Li@nxp.com>
> + - Frank Li <Frank.Li@nxp.com>
>
> description:
> Mobiveil's GPEX 4.0 is a PCIe Gen4 host bridge IP. This configurable IP
^ permalink raw reply
* Re: [PATCH] dt-bindings: Fix emails with spaces or missing brackets
From: Dmitry Torokhov @ 2026-01-26 19:12 UTC (permalink / raw)
To: Guenter Roeck
Cc: Rob Herring (Arm), Krzysztof Kozlowski, Conor Dooley,
Mauro Carvalho Chehab, Alim Akhtar, Karthikeyan Mitran,
Hou Zhiqiang, Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Bjorn Helgaas, Christopher Ruehl,
Jason A. Donenfeld, Matthias Schiffer, Vincent Huang, Inki Dae,
Seung-Woo Kim, Frank Li, Krzysztof Kozlowski, linux-hwmon,
devicetree, linux-kernel, linux-input, linux-media,
linux-arm-kernel, linux-samsung-soc, linux-pci
In-Reply-To: <9a3d4ae8-b57e-450e-971b-d09fc923eee1@roeck-us.net>
On Mon, Jan 26, 2026 at 09:21:15AM -0800, Guenter Roeck wrote:
> On 1/26/26 08:47, Rob Herring (Arm) wrote:
> > Fix email addresses with spaces or missing brackets. A pending
> > dtschema meta-schema change will check for these.
> >
> > Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
>
> For hwmon:
>
> Acked-by: Guenter Roeck <linux@roeck-us.net>
For input:
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
>
> > ---
> > Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml | 2 +-
> > Documentation/devicetree/bindings/input/syna,rmi4.yaml | 2 +-
> > .../devicetree/bindings/media/samsung,exynos5250-gsc.yaml | 2 +-
> > Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml | 2 +-
> > 4 files changed, 4 insertions(+), 4 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml b/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
> > index 3d14d5fc96c5..7b38f2182ffa 100644
> > --- a/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
> > +++ b/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
> > @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
> > title: Sensirion SHTC1 Humidity and Temperature Sensor IC
> > maintainers:
> > - - Christopher Ruehl chris.ruehl@gtsys.com.hk
> > + - Christopher Ruehl <chris.ruehl@gtsys.com.hk>
> > description: |
> > The SHTC1, SHTW1 and SHTC3 are digital humidity and temperature sensors
> > diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> > index f369385ffaf0..8685ef4481f4 100644
> > --- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> > +++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> > @@ -8,7 +8,7 @@ title: Synaptics RMI4 compliant devices
> > maintainers:
> > - Jason A. Donenfeld <Jason@zx2c4.com>
> > - - Matthias Schiffer <matthias.schiffer@ew.tq-group.com
> > + - Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
> > - Vincent Huang <vincent.huang@tw.synaptics.com>
> > description: |
> > diff --git a/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml b/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml
> > index 878397830a4d..9196cf5dac0f 100644
> > --- a/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml
> > +++ b/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml
> > @@ -9,7 +9,7 @@ title: Samsung Exynos SoC G-Scaler
> > maintainers:
> > - Inki Dae <inki.dae@samsung.com>
> > - Krzysztof Kozlowski <krzk@kernel.org>
> > - - Seung-Woo Kim <sw0312.kim@samsung.com
> > + - Seung-Woo Kim <sw0312.kim@samsung.com>
> > description:
> > G-Scaler is used for scaling and color space conversion on Samsung Exynos
> > diff --git a/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml b/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml
> > index d286b77921e0..8f5d33050348 100644
> > --- a/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml
> > +++ b/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml
> > @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
> > title: Mobiveil AXI PCIe Host Bridge
> > maintainers:
> > - - Frank Li <Frank Li@nxp.com>
> > + - Frank Li <Frank.Li@nxp.com>
> > description:
> > Mobiveil's GPEX 4.0 is a PCIe Gen4 host bridge IP. This configurable IP
Thanks.
--
Dmitry
^ permalink raw reply
* Re: bcm5974 trackpad broken after USB reset
From: Henrik Rydberg @ 2026-01-26 22:20 UTC (permalink / raw)
To: Liam Mitchell; +Cc: linux-input, Henrik Rydberg
In-Reply-To: <CAOQ1CL7royHBeeY-Qr-xBhvXkWy1cJZ-tcT1kS1Dfu_z3emN6g@mail.gmail.com>
Hi Liam,
> I did a lot of experiments changing modes at different times and this
> is what I understand:
>
> 0x8 ("normal") is pause/off. If this is set, no messages of any kind
> will be received.
> This is not the same as the default/init state (sending 8 byte
> packets, HID?). Even though the first config read returns this (08 05
> 00 00 00 00 00 00), if you write the same bytes back, it will stop
> sending the default 8 byte packets. I haven't found a way to re-enable
> this default mode other than USB reset.
>
> 0x1 ("wellspring") enables multi-touch packets, how the driver has
> been working for 18 years.
>
> 0x0 (suggested above) also enables "wellspring" multi-touch packets. I
> noticed one major difference in my testing; that it seems to survive
> suspend-resume without issues, whereas if the mode was 0x1 on suspend,
> it will resume, report 0x0 in config and send default packets again.
>
> Another interesting observation is that the first packet received (60
> 02, "control response ignored") comes reliably 120-140ms after USB
> reset. Importantly, if you send 0x1 or 0x0 before this is received, it
> will be ignored. It will update the config but won't take effect. From
> this state you have to send 0x8, wait 1ms then send 0x1 (or 0x0) again
> to enable wellspring mode.
Looks like you made real progress here, great stuff! With this
information, we should be able to provide a proper fix, agreed.
> The above will be why my mouse doesn't work after reset and why adding
> msleep() in probe() fixed it.
>
> I think a more permanent fix could be to set mode on receiving that
> first packet (control response) and/or on receiving default 8 byte
> packets.
I like that, expecially if 0x08 never needs to be set, as touching that
bit would require some sort of rougher handling. It was a bit uncelar if
your experiment with the 0x00 mode went between 0x08/0x00 or 0x00/0x01.
> I looked at the history of the module and saw that the first packet
> has been ignored from the first version so I assume it works the same
> across all hardware versions.
Yes, the setup timing was never considered, and your suggestion should
be a good fix for a lot of devices.
Thanks!
Henrik
^ permalink raw reply
* Re: [PATCH] dt-bindings: Fix emails with spaces or missing brackets
From: Manivannan Sadhasivam @ 2026-01-27 4:44 UTC (permalink / raw)
To: Rob Herring (Arm)
Cc: Guenter Roeck, Krzysztof Kozlowski, Conor Dooley, Dmitry Torokhov,
Mauro Carvalho Chehab, Alim Akhtar, Karthikeyan Mitran,
Hou Zhiqiang, Lorenzo Pieralisi, Krzysztof Wilczyński,
Bjorn Helgaas, Christopher Ruehl, Jason A. Donenfeld,
Matthias Schiffer, Vincent Huang, Inki Dae, Seung-Woo Kim,
Frank Li, Krzysztof Kozlowski, linux-hwmon, devicetree,
linux-kernel, linux-input, linux-media, linux-arm-kernel,
linux-samsung-soc, linux-pci
In-Reply-To: <20260126164724.2832009-1-robh@kernel.org>
On Mon, Jan 26, 2026 at 10:47:22AM -0600, Rob Herring (Arm) wrote:
> Fix email addresses with spaces or missing brackets. A pending
> dtschema meta-schema change will check for these.
>
> Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
> ---
> Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml | 2 +-
> Documentation/devicetree/bindings/input/syna,rmi4.yaml | 2 +-
> .../devicetree/bindings/media/samsung,exynos5250-gsc.yaml | 2 +-
> Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml | 2 +-
For PCI controllers,
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
- Mani
> 4 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml b/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
> index 3d14d5fc96c5..7b38f2182ffa 100644
> --- a/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
> +++ b/Documentation/devicetree/bindings/hwmon/sensirion,shtc1.yaml
> @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
> title: Sensirion SHTC1 Humidity and Temperature Sensor IC
>
> maintainers:
> - - Christopher Ruehl chris.ruehl@gtsys.com.hk
> + - Christopher Ruehl <chris.ruehl@gtsys.com.hk>
>
> description: |
> The SHTC1, SHTW1 and SHTC3 are digital humidity and temperature sensors
> diff --git a/Documentation/devicetree/bindings/input/syna,rmi4.yaml b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> index f369385ffaf0..8685ef4481f4 100644
> --- a/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> +++ b/Documentation/devicetree/bindings/input/syna,rmi4.yaml
> @@ -8,7 +8,7 @@ title: Synaptics RMI4 compliant devices
>
> maintainers:
> - Jason A. Donenfeld <Jason@zx2c4.com>
> - - Matthias Schiffer <matthias.schiffer@ew.tq-group.com
> + - Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
> - Vincent Huang <vincent.huang@tw.synaptics.com>
>
> description: |
> diff --git a/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml b/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml
> index 878397830a4d..9196cf5dac0f 100644
> --- a/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml
> +++ b/Documentation/devicetree/bindings/media/samsung,exynos5250-gsc.yaml
> @@ -9,7 +9,7 @@ title: Samsung Exynos SoC G-Scaler
> maintainers:
> - Inki Dae <inki.dae@samsung.com>
> - Krzysztof Kozlowski <krzk@kernel.org>
> - - Seung-Woo Kim <sw0312.kim@samsung.com
> + - Seung-Woo Kim <sw0312.kim@samsung.com>
>
> description:
> G-Scaler is used for scaling and color space conversion on Samsung Exynos
> diff --git a/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml b/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml
> index d286b77921e0..8f5d33050348 100644
> --- a/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml
> +++ b/Documentation/devicetree/bindings/pci/mbvl,gpex40-pcie.yaml
> @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
> title: Mobiveil AXI PCIe Host Bridge
>
> maintainers:
> - - Frank Li <Frank Li@nxp.com>
> + - Frank Li <Frank.Li@nxp.com>
>
> description:
> Mobiveil's GPEX 4.0 is a PCIe Gen4 host bridge IP. This configurable IP
> --
> 2.51.0
>
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH v2 4/4] ALSA: hda/conexant: Add headset mic fix for MECHREVO Wujie 15X Pro
From: Takashi Iwai @ 2026-01-27 7:30 UTC (permalink / raw)
To: gongqi
Cc: rafael, dmitry.torokhov, Shyam-sundar.S-k, hansg, ilpo.jarvinen,
perex, tiwai, linux-acpi, linux-input, platform-driver-x86,
linux-sound, linux-kernel
In-Reply-To: <20260122155501.376199-5-550230171hxy@gmail.com>
On Thu, 22 Jan 2026 16:55:01 +0100,
gongqi wrote:
>
> The headset microphone on the MECHREVO Wujie 15X Pro requires the
> CXT_FIXUP_HEADSET_MIC quirk to function properly. Add the PCI SSID
> (0x1d05:0x3012) to the quirk table.
>
> Signed-off-by: gongqi <550230171hxy@gmail.com>
Applied to for-next branch of sound.git tree. Thanks.
Takashi
> ---
> sound/hda/codecs/conexant.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/sound/hda/codecs/conexant.c b/sound/hda/codecs/conexant.c
> index 5fcbc1312c697..2384e64eada36 100644
> --- a/sound/hda/codecs/conexant.c
> +++ b/sound/hda/codecs/conexant.c
> @@ -1123,6 +1123,7 @@ static const struct hda_quirk cxt5066_fixups[] = {
> SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad/Ideapad", CXT_FIXUP_LENOVO_XPAD_ACPI),
> SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
> SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
> + SND_PCI_QUIRK(0x1d05, 0x3012, "MECHREVO Wujie 15X Pro", CXT_FIXUP_HEADSET_MIC),
> HDA_CODEC_QUIRK(0x2782, 0x12c3, "Sirius Gen1", CXT_PINCFG_TOP_SPEAKER),
> HDA_CODEC_QUIRK(0x2782, 0x12c5, "Sirius Gen2", CXT_PINCFG_TOP_SPEAKER),
> {}
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH 1/2] linux/interrupt.h: allow "guard" notation to disable and reenable IRQ with valid IRQ check
From: Thomas Gleixner @ 2026-01-27 9:14 UTC (permalink / raw)
To: Marek Vasut, linux-input
Cc: Marek Vasut, Peter Zijlstra (Intel), Cheng-Yang Chou,
Dmitry Torokhov, Frank Li, Geert Uytterhoeven, Jinjie Ruan,
Krzysztof Kozlowski, Marc Zyngier, Sebastian Andrzej Siewior,
linux-kernel, linux-renesas-soc
In-Reply-To: <20260121232522.154771-1-marek.vasut+renesas@mailbox.org>
On Thu, Jan 22 2026 at 00:23, Marek Vasut wrote:
$Subject: linux/interrupt.h is not a proper prefix. Just use 'genirq:'
Also what means 'allow ....'? Subject lines should provide a concise
summary of the change, i.e. something like:
Provide conditional disable_irq guard variant
> Introduce disable_valid_irq scoped guard. This is an extension
> of disable_irq scoped guard, which disables and enables IRQs
> around a scope. The disable_valid_irq scoped guard does almost
> the same, except it handles the case where IRQ is not valid,
> in which case it does not do anything. This is meant to be used
> by for example touch controller drivers, which can do both IRQ
> driven and polling mode of operation, and this makes their code
> slighly simpler.
How many of those have this pattern? From a cursory look I found not
even one as your example is neither applicable to upstream nor to next.
> +static inline void disable_valid_irq(unsigned int irq)
> +{
> + if (irq > 0)
> + disable_irq(irq);
> +}
> +
> +static inline void enable_valid_irq(unsigned int irq)
> +{
> + if (irq > 0)
> + enable_irq(irq);
> +}
> +
> +DEFINE_LOCK_GUARD_1(disable_valid_irq, int,
'int' because it matches the function argument type of the inlines,
right?
> + disable_valid_irq(*_T->lock), enable_valid_irq(*_T->lock))
disable_valid_irq is a pretty non-intuitive name if you look at it just
by reading a usage site. It's not really improving the readability of
the code, it's in fact obscuring it as the reader has to actually look
up what the hell this means and then stumble upon a completely
undocumented lock guard define.
I'm all for using guards, but using guards just for the sake of using
guards is not a really good approach.
Thanks,
tglx
^ permalink raw reply
* [PATCH v6 0/3] TrackPoint doubletap enablement and user control
From: Vishnu Sankar @ 2026-01-27 10:39 UTC (permalink / raw)
To: mpearson-lenovo, dmitry.torokhov, hmh, hansg, corbet,
derekjohn.clark, ilpo.jarvinen
Cc: linux-input, linux-kernel, ibm-acpi-devel, linux-doc,
platform-driver-x86, vsankar, Vishnu Sankar
This patch series adds support for TrackPoint doubletap with a clear and
simple separation of responsibilities between drivers:
1. Firmware enablement (trackpoint.c):
Automatically enables doubletap on capable hardware during device
detection.
2. User control (thinkpad_acpi.c):
Provides a sysfs interface to enable or disable delivery of doubletap
events to userspace.
The approach follows the KISS principle:
- The TrackPoint driver enables hardware functionality by default.
- The thinkpad_acpi driver controls whether ACPI doubletap events are
delivered, using existing hotkey filtering infrastructure.
- No cross-driver APIs or dual filtering paths are introduced.
Changes in v6:
- Documentation: fix formatting of the doubletap_enable sysfs attribute
description (separate "Values" list)
Changes in v5:
- Rename sysfs attribute from doubletap_filter to doubletap_enable to
reflect actual behavior.
- Fix inverted logic so events are delivered only when doubletap is
enabled.
- Suppress ACPI hotkey delivery instead of injecting or filtering input
events.
- Register the sysfs attribute via hotkey_attributes[] instead of
device_create_file().
- Drop unnecessary helper wrappers and debug logging.
- Update Documentation to reflect the new naming and semantics.
Changes in v4:
- Complete redesign based on reviewer feedback.
- trackpoint.c: Simplified to only enable doubletap by default.
- trackpoint.c: Removed all sysfs attributes and global variables.
- trackpoint.c: Uses firmware ID detection with deny list.
- thinkpad_acpi.c: Added sysfs interface for kernel-level event control.
- thinkpad_acpi.c: No cross-driver dependencies.
- Documentation: Updated to reflect simplified sysfs approach.
Changes in v3:
- No changes.
Changes in v2:
- Improved commit messages.
- Removed unnecessary comments and debug messages.
- Switched to strstarts() usage.
- Simplified firmware capability detection logic.
This version addresses the remaining review feedback by correcting the
naming and logic inversion, aligning sysfs semantics with behavior, and
fully integrating with existing thinkpad_acpi hotkey handling.
Vishnu Sankar (3):
input: trackpoint - Enable doubletap by default on capable devices
platform/x86: thinkpad_acpi: Add sysfs control for TrackPoint
double-tap
Documentation: thinkpad-acpi - Document doubletap_enable attribute
.../admin-guide/laptops/thinkpad-acpi.rst | 21 +++++++++
drivers/input/mouse/trackpoint.c | 47 +++++++++++++++++++
drivers/input/mouse/trackpoint.h | 5 ++
drivers/platform/x86/lenovo/thinkpad_acpi.c | 42 ++++++++++++++---
4 files changed, 108 insertions(+), 7 deletions(-)
--
2.51.0
^ permalink raw reply
* [PATCH v6 1/3] input: trackpoint - Enable doubletap by default on capable devices
From: Vishnu Sankar @ 2026-01-27 10:39 UTC (permalink / raw)
To: mpearson-lenovo, dmitry.torokhov, hmh, hansg, corbet,
derekjohn.clark, ilpo.jarvinen
Cc: linux-input, linux-kernel, ibm-acpi-devel, linux-doc,
platform-driver-x86, vsankar, Vishnu Sankar
In-Reply-To: <20260127103907.20269-1-vishnuocv@gmail.com>
Enable doubletap functionality by default on TrackPoint devices that
support it. The feature is detected using firmware ID pattern matching
(PNP: LEN03xxx) with a deny list of incompatible devices.
This provides immediate doubletap functionality without requiring
userspace configuration. The hardware is enabled during device
detection, while event filtering continues to be handled by the
thinkpad_acpi driver as before.
Signed-off-by: Vishnu Sankar <vishnuocv@gmail.com>
Suggested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
---
Changes in v5:
- Renamed function to trackpoint_is_dt_capable()
- Simplified string comparison without sscanf()
- Removed wrapper function as suggested
- Fixed missing period in comment
Changes in v4:
- Simplified approach: removed all sysfs attributes and user interface
- Enable doubletap by default during device detection
- Removed global variables and complex attribute infrastructure
- Uses minimal firmware ID detection with deny list
- Follows KISS principle as suggested by reviewers
Changes in v3:
- No changes
Changes in v2:
- Improve commit messages
- Sysfs attributes moved to trackpoint.c
- Removed unnecessary comments
- Removed unnecessary debug messages
- Using strstarts() instead of strcmp()
- is_trackpoint_dt_capable() modified
- Removed _BIT suffix and used BIT() define
- Reverse the trackpoint_doubletap_status() logic to return error first
- Removed export functions as a result of the design change
- Changed trackpoint_dev->psmouse to parent_psmouse
- The path of trackpoint.h is not changed
---
drivers/input/mouse/trackpoint.c | 47 ++++++++++++++++++++++++++++++++
drivers/input/mouse/trackpoint.h | 5 ++++
2 files changed, 52 insertions(+)
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index 5f6643b69a2c..8319b5bb6ce5 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -393,6 +393,45 @@ static int trackpoint_reconnect(struct psmouse *psmouse)
return 0;
}
+/* List of known incapable device PNP IDs */
+static const char * const dt_incompatible_devices[] = {
+ "LEN0304",
+ "LEN0306",
+ "LEN0317",
+ "LEN031A",
+ "LEN031B",
+ "LEN031C",
+ "LEN031D",
+};
+
+/*
+ * Checks if it's a doubletap capable device.
+ * The PNP ID format is "PNP: LEN030d PNP0f13".
+ */
+static bool trackpoint_is_dt_capable(const char *pnp_id)
+{
+ size_t i;
+
+ if (!pnp_id)
+ return false;
+
+ /* Must start with "PNP: LEN03" */
+ if (!strstarts(pnp_id, "PNP: LEN03"))
+ return false;
+
+ /* Ensure enough length before comparing */
+ if (strlen(pnp_id) < 12)
+ return false;
+
+ /* Check deny-list */
+ for (i = 0; i < ARRAY_SIZE(dt_incompatible_devices); i++) {
+ if (!strncmp(pnp_id + 5,
+ dt_incompatible_devices[i], 7))
+ return false;
+ }
+ return true;
+}
+
int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
@@ -470,6 +509,14 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
psmouse->vendor, firmware_id,
(button_info & 0xf0) >> 4, button_info & 0x0f);
+ /* Enable doubletap by default on capable devices */
+ if (trackpoint_is_dt_capable(ps2dev->serio->firmware_id)) {
+ if (trackpoint_write(ps2dev, TP_DOUBLETAP, TP_DOUBLETAP_ENABLE))
+ psmouse_warn(psmouse, "Failed to enable doubletap: %d\n", error);
+ else
+ psmouse_info(psmouse, "Doubletap enabled by default!\n");
+ }
+
return 0;
}
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
index eb5412904fe0..3e03cdb39449 100644
--- a/drivers/input/mouse/trackpoint.h
+++ b/drivers/input/mouse/trackpoint.h
@@ -69,6 +69,8 @@
/* (how hard it is to drag */
/* with Z-axis pressed) */
+#define TP_DOUBLETAP 0x58 /* TrackPoint doubletap register */
+
#define TP_MINDRAG 0x59 /* Minimum amount of force needed */
/* to trigger dragging */
@@ -110,6 +112,9 @@
external device will be forced to 1 */
#define TP_MASK_EXT_TAG 0x04
+/* Doubletap register values */
+#define TP_DOUBLETAP_ENABLE 0xFF /* Enable value */
+#define TP_DOUBLETAP_DISABLE 0xFE /* Disable value */
/* Power on Self Test Results */
#define TP_POR_SUCCESS 0x3B
--
2.51.0
^ permalink raw reply related
* [PATCH v6 2/3] platform/x86: thinkpad_acpi: Add sysfs control for TrackPoint double-tap
From: Vishnu Sankar @ 2026-01-27 10:39 UTC (permalink / raw)
To: mpearson-lenovo, dmitry.torokhov, hmh, hansg, corbet,
derekjohn.clark, ilpo.jarvinen
Cc: linux-input, linux-kernel, ibm-acpi-devel, linux-doc,
platform-driver-x86, vsankar, Vishnu Sankar
In-Reply-To: <20260127103907.20269-1-vishnuocv@gmail.com>
Add a sysfs attribute to enable or disable TrackPoint double-tap hotkey
events at the kernel level.
The TrackPoint firmware enables double-tap support automatically. This
interface allows userspace to control whether double-tap events are
forwarded to userspace.
The attribute is available at:
/sys/devices/platform/thinkpad_acpi/doubletap_enable
0 - Disable double-tap hotkey events
1 - Enable double-tap hotkey events (default)
Filtering is implemented by suppressing ACPI hotkey delivery without
injecting synthetic input events.
Signed-off-by: Vishnu Sankar <vishnuocv@gmail.com>
Suggested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
---
Changes in v2:
- Updated commit message to clarify dependency on trackpoint driver
- Now handling sysfs read/write of trackpoint driver using file read/write
- Removed sysfs attribute creation of trackpoint double tap here
- Reversed the logic and return false right away
- Dropped unnecessary debug messages
- Using dev_dbg() instead of pr_xxxx()
Changes in v3:
- No changes
Changes in v4:
- Simplified approach: single sysfs attribute for user control
- Clear naming: doubletap_filter instead of doubletap_enabled
- Intuitive behavior: 0=process events, 1=filter events
- No cross-driver dependencies or complex interactions
- Minimal code changes using existing thinkpad_acpi infrastructure
Changes in v5:
- Rename doubletap_filter to doubletap_enable to match actual behavior
- Fix inverted logic so events are emitted only when doubletap is enabled
- Register sysfs attribute via hotkey_attributes[] (no device_create_file)
---
---
drivers/platform/x86/lenovo/thinkpad_acpi.c | 42 +++++++++++++++++----
1 file changed, 35 insertions(+), 7 deletions(-)
diff --git a/drivers/platform/x86/lenovo/thinkpad_acpi.c b/drivers/platform/x86/lenovo/thinkpad_acpi.c
index cc19fe520ea9..ca01323c990a 100644
--- a/drivers/platform/x86/lenovo/thinkpad_acpi.c
+++ b/drivers/platform/x86/lenovo/thinkpad_acpi.c
@@ -373,7 +373,7 @@ static struct {
u32 hotkey_poll_active:1;
u32 has_adaptive_kbd:1;
u32 kbd_lang:1;
- u32 trackpoint_doubletap:1;
+ u32 trackpoint_doubletap_enable:1;
struct quirk_entry *quirks;
} tp_features;
@@ -3018,6 +3018,31 @@ static const struct attribute_group adaptive_kbd_attr_group = {
.attrs = adaptive_kbd_attributes,
};
+/* sysfs doubletap enable --------------------------------------------- */
+static ssize_t doubletap_enable_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "%d\n", tp_features.trackpoint_doubletap_enable);
+}
+
+static ssize_t doubletap_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ bool enable;
+ int err;
+
+ err = kstrtobool(buf, &enable);
+ if (err)
+ return err;
+
+ tp_features.trackpoint_doubletap_enable = enable;
+ return count;
+}
+
+static DEVICE_ATTR_RW(doubletap_enable);
+
/* --------------------------------------------------------------------- */
static struct attribute *hotkey_attributes[] = {
@@ -3032,6 +3057,7 @@ static struct attribute *hotkey_attributes[] = {
&dev_attr_hotkey_recommended_mask.attr,
&dev_attr_hotkey_tablet_mode.attr,
&dev_attr_hotkey_radio_sw.attr,
+ &dev_attr_doubletap_enable.attr,
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
&dev_attr_hotkey_source_mask.attr,
&dev_attr_hotkey_poll_freq.attr,
@@ -3557,8 +3583,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
hotkey_poll_setup_safe(true);
- /* Enable doubletap by default */
- tp_features.trackpoint_doubletap = 1;
+ /* Enable TrackPoint doubletap event reporting by default. */
+ tp_features.trackpoint_doubletap_enable = 1;
return 0;
}
@@ -3863,9 +3889,9 @@ static bool hotkey_notify_8xxx(const u32 hkey, bool *send_acpi_ev)
{
switch (hkey) {
case TP_HKEY_EV_TRACK_DOUBLETAP:
- if (tp_features.trackpoint_doubletap)
- tpacpi_input_send_key(hkey, send_acpi_ev);
-
+ /* Only send event if doubletap is enabled */
+ if (!tp_features.trackpoint_doubletap_enable)
+ *send_acpi_ev = false;
return true;
default:
return false;
@@ -11285,7 +11311,9 @@ static bool tpacpi_driver_event(const unsigned int hkey_event)
mutex_unlock(&tpacpi_inputdev_send_mutex);
return true;
case TP_HKEY_EV_DOUBLETAP_TOGGLE:
- tp_features.trackpoint_doubletap = !tp_features.trackpoint_doubletap;
+ /* Toggle kernel-level doubletap event filtering */
+ tp_features.trackpoint_doubletap_enable =
+ !tp_features.trackpoint_doubletap_enable;
return true;
case TP_HKEY_EV_PROFILE_TOGGLE:
case TP_HKEY_EV_PROFILE_TOGGLE2:
--
2.51.0
^ permalink raw reply related
* [PATCH v6 3/3] Documentation: thinkpad-acpi - Document doubletap_enable attribute
From: Vishnu Sankar @ 2026-01-27 10:39 UTC (permalink / raw)
To: mpearson-lenovo, dmitry.torokhov, hmh, hansg, corbet,
derekjohn.clark, ilpo.jarvinen
Cc: linux-input, linux-kernel, ibm-acpi-devel, linux-doc,
platform-driver-x86, vsankar, Vishnu Sankar
In-Reply-To: <20260127103907.20269-1-vishnuocv@gmail.com>
Document the doubletap_enable sysfs attribute for ThinkPad ACPI driver.
Signed-off-by: Vishnu Sankar <vishnuocv@gmail.com>
---
Changes in v6:
- Fix formatting of doubletap_enable sysfs documentation (separate Values list)
---
.../admin-guide/laptops/thinkpad-acpi.rst | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/Documentation/admin-guide/laptops/thinkpad-acpi.rst b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
index 4ab0fef7d440..9a660724648b 100644
--- a/Documentation/admin-guide/laptops/thinkpad-acpi.rst
+++ b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
@@ -1521,6 +1521,27 @@ Currently 2 antenna types are supported as mentioned below:
The property is read-only. If the platform doesn't have support the sysfs
class is not created.
+doubletap_enable
+----------------
+
+sysfs: doubletap_enable
+
+Controls whether TrackPoint doubletap events are filtered out. Doubletap is a
+feature where quickly tapping the TrackPoint twice triggers a special function key event.
+
+The available commands are::
+
+ cat /sys/devices/platform/thinkpad_acpi/doubletap_enable
+ echo 1 | sudo tee /sys/devices/platform/thinkpad_acpi/doubletap_enable
+ echo 0 | sudo tee /sys/devices/platform/thinkpad_acpi/doubletap_enable
+
+Values:
+
+ * 1 - doubletap events are processed (default)
+ * 0 - doubletap events are filtered out (ignored)
+
+ This setting can also be toggled via the Fn+doubletap hotkey.
+
Auxmac
------
--
2.51.0
^ permalink raw reply related
* Re: [PATCH 1/2] dt-bindings: input: touchscreen: add TouchNetix aXiom device tree
From: Rob Herring @ 2026-01-27 14:16 UTC (permalink / raw)
To: Andrew Thomas
Cc: Dmitry Torokhov, Krzysztof Kozlowski, Conor Dooley,
Henrik Rydberg, linux-input, devicetree, linux-kernel,
Marco Felsch
In-Reply-To: <20260126-axiom-driver-submission3-v1-1-d462c4a608e3@touchnetix.com>
On Mon, Jan 26, 2026 at 04:38:23PM +0000, Andrew Thomas wrote:
> ---
Also needs a commit message and S-o-b.
> .../bindings/input/touchscreen/tnx,axiom.yaml | 70 ++++++++++++++++++++++
> .../devicetree/bindings/vendor-prefixes.yaml | 2 +
> 2 files changed, 72 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/tnx,axiom.yaml b/Documentation/devicetree/bindings/input/touchscreen/tnx,axiom.yaml
> new file mode 100644
> index 000000000000..7b532471c17f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/touchscreen/tnx,axiom.yaml
> @@ -0,0 +1,70 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/input/touchscreen/tnx,axiom.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: TouchNetix aXiom Touchscreen Controller
> +
> +maintainers:
> + - Andrew Thomas <andrew.thomas@touchnetix.com>
> +
> +description: |
Don't need '|' if no formatting to preserve.
> + The TouchNetix aXiom series are high-performance touchscreen controllers
> + supporting various interface methods including I2C and SPI.
> +
> +properties:
> + compatible:
> + enum:
> + - tnx,axiom
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + description: Both IRQ_TYPE_LEVEL_LOW and IRQ_TYPE_EDGE_FALLING are supported
> + maxItems: 1
> +
> +required:
> + - compatible
> + - reg
> + - interrupts
> +
> +allOf:
> + - $ref: touchscreen.yaml#
> + - $ref: /schemas/spi/spi-peripheral-props.yaml#
> +
> +unevaluatedProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/irq.h>
> +
> + i2c {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + touchscreen@66 {
> + compatible = "tnx,axiom-i2c";
> + reg = <0x66>;
> + interrupt-parent = <&gpio>;
> + interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
> + axiom,poll-enable;
> + axiom,poll-period = <15>;
> + };
> + };
> +
> + - |
> + #include <dt-bindings/interrupt-controller/irq.h>
> +
> + spi {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + touchscreen@0 {
> + compatible = "tnx,axiom-spi";
> + reg = <0>;
> + interrupt-parent = <&gpio>;
> + interrupts = <24 IRQ_TYPE_EDGE_FALLING>;
> + };
> + };
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> index f1d1882009ba..dadfc7036ed7 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> @@ -1636,6 +1636,8 @@ patternProperties:
> description: Trusted Logic Mobility
> "^tmt,.*":
> description: Tecon Microprocessor Technologies, LLC.
> + "^tnx,.*":
> + description: TouchNetix
> "^topeet,.*":
> description: Topeet
> "^topic,.*":
>
> --
> 2.43.0
>
^ permalink raw reply
* [PATCH v13 2/3] HID: cp2112: Fwnode Support
From: Danny Kaehn @ 2026-01-27 14:47 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Benjamin Tissoires,
Andy Shevchenko, Danny Kaehn, Andi Shyti, Conor Dooley
Cc: Jiri Kosina, devicetree, linux-input, Dmitry Torokhov,
Bartosz Golaszewski, Ethan Twardy, linux-i2c, linux-kernel,
Leo Huang, Arun D Patil, Willie Thai, Ting-Kai Chen
In-Reply-To: <20260127-cp2112-dt-v13-0-6448ddd4bf22@plexus.com>
Support describing the CP2112's I2C and GPIO interfaces in firmware.
Bindings between the firmware nodes and the functions of the device
are distinct between ACPI and DeviceTree.
For ACPI, the i2c_adapter will use the child with _ADR Zero and the
gpio_chip will use the child with _ADR One. For DeviceTree, the
i2c_adapter will use the child with name "i2c", but the gpio_chip
will share a firmware node with the CP2112.
Signed-off-by: Danny Kaehn <danny.kaehn@plexus.com>
---
drivers/hid/hid-cp2112.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index 803b883ae875..ea19b5cb58f9 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -29,6 +29,16 @@
#include <linux/usb/ch9.h>
#include "hid-ids.h"
+/**
+ * enum cp2112_child_acpi_cell_addrs - Child ACPI addresses for CP2112 sub-functions
+ * @CP2112_I2C_ADR: Address for I2C node
+ * @CP2112_GPIO_ADR: Address for GPIO node
+ */
+enum cp2112_child_acpi_cell_addrs {
+ CP2112_I2C_ADR = 0,
+ CP2112_GPIO_ADR = 1,
+};
+
#define CP2112_REPORT_MAX_LENGTH 64
#define CP2112_GPIO_CONFIG_LENGTH 5
#define CP2112_GPIO_GET_LENGTH 2
@@ -1208,7 +1218,9 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
struct cp2112_device *dev;
u8 buf[3];
struct cp2112_smbus_config_report config;
+ struct fwnode_handle *child;
struct gpio_irq_chip *girq;
+ u32 addr;
int ret;
dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL);
@@ -1226,6 +1238,27 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
return ret;
}
+ if (is_acpi_device_node(dev_fwnode(&hdev->dev))) {
+ device_for_each_child_node(&hdev->dev, child) {
+ ret = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), &addr);
+ if (ret)
+ continue;
+
+ switch (addr) {
+ case CP2112_I2C_ADR:
+ device_set_node(&dev->adap.dev, child);
+ break;
+ case CP2112_GPIO_ADR:
+ dev->gc.fwnode = child;
+ break;
+ }
+ }
+ } else {
+ child = device_get_named_child_node(&hdev->dev, "i2c");
+ device_set_node(&dev->adap.dev, child);
+ fwnode_handle_put(child);
+ }
+
ret = hid_parse(hdev);
if (ret) {
hid_err(hdev, "parse failed\n");
--
2.25.1
^ permalink raw reply related
* [PATCH v13 1/3] dt-bindings: i2c: Add CP2112 HID USB to SMBus Bridge
From: Danny Kaehn @ 2026-01-27 14:47 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Benjamin Tissoires,
Andy Shevchenko, Danny Kaehn, Andi Shyti, Conor Dooley
Cc: Jiri Kosina, devicetree, linux-input, Dmitry Torokhov,
Bartosz Golaszewski, Ethan Twardy, linux-i2c, linux-kernel,
Leo Huang, Arun D Patil, Willie Thai, Ting-Kai Chen
In-Reply-To: <20260127-cp2112-dt-v13-0-6448ddd4bf22@plexus.com>
This is a USB HID device which includes an I2C controller and 8 GPIO pins.
The binding allows describing the chip's gpio and i2c controller in DT,
with the i2c controller being bound to a subnode named "i2c". This is
intended to be used in configurations where the CP2112 is permanently
connected in hardware.
Signed-off-by: Danny Kaehn <danny.kaehn@plexus.com>
---
.../devicetree/bindings/i2c/silabs,cp2112.yaml | 100 +++++++++++++++++++++
1 file changed, 100 insertions(+)
diff --git a/Documentation/devicetree/bindings/i2c/silabs,cp2112.yaml b/Documentation/devicetree/bindings/i2c/silabs,cp2112.yaml
new file mode 100644
index 000000000000..a204adfe57b3
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/silabs,cp2112.yaml
@@ -0,0 +1,100 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i2c/silabs,cp2112.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: CP2112 HID USB to SMBus/I2C Bridge
+
+maintainers:
+ - Danny Kaehn <danny.kaehn@plexus.com>
+
+description:
+ The CP2112 is a USB HID device which includes an integrated I2C controller
+ and 8 GPIO pins. Its GPIO pins can each be configured as inputs, open-drain
+ outputs, or push-pull outputs.
+
+properties:
+ compatible:
+ const: usb10c4,ea90
+
+ reg:
+ maxItems: 1
+ description: The USB port number
+
+ interrupt-controller: true
+ "#interrupt-cells":
+ const: 2
+
+ gpio-controller: true
+ "#gpio-cells":
+ const: 2
+
+ gpio-line-names:
+ minItems: 1
+ maxItems: 8
+
+ i2c:
+ description: The SMBus/I2C controller node for the CP2112
+ $ref: /schemas/i2c/i2c-controller.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ clock-frequency:
+ minimum: 10000
+ default: 100000
+ maximum: 400000
+
+patternProperties:
+ "-hog(-[0-9]+)?$":
+ type: object
+
+ required:
+ - gpio-hog
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/gpio/gpio.h>
+
+ usb {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cp2112: device@1 {
+ compatible = "usb10c4,ea90";
+ reg = <1>;
+
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ #gpio-cells = <2>;
+ gpio-line-names = "CP2112_SDA", "CP2112_SCL", "TEST2",
+ "TEST3","TEST4", "TEST5", "TEST6";
+
+ fan-rst-hog {
+ gpio-hog;
+ gpios = <7 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "FAN_RST";
+ };
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ sda-gpios = <&cp2112 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ scl-gpios = <&cp2112 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+
+ temp@48 {
+ compatible = "national,lm75";
+ reg = <0x48>;
+ };
+ };
+ };
+ };
--
2.25.1
^ permalink raw reply related
* [PATCH v13 0/3] Firmware Support for USB-HID Devices and CP2112
From: Danny Kaehn @ 2026-01-27 14:47 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Benjamin Tissoires,
Andy Shevchenko, Danny Kaehn, Andi Shyti, Conor Dooley
Cc: Jiri Kosina, devicetree, linux-input, Dmitry Torokhov,
Bartosz Golaszewski, Ethan Twardy, linux-i2c, linux-kernel,
Leo Huang, Arun D Patil, Willie Thai, Ting-Kai Chen
This patchset allows USB-HID devices to have Firmware bindings through sharing
the USB fwnode with the HID driver, and adds such a binding and driver
implementation for the CP2112 USB to SMBus Bridge (which necessitated the
USB-HID change). This change allows a CP2112 permanently attached in hardware to
be described in DT and ACPI and interoperate with other drivers.
Changes in v13:
- dt-binding changes:
- drop scl-gpios and sda-gpios from binding, since they are included
from the i2c-controller schena.
- Set indentation to 4 spaces consistently for the DTS example
- Fix alignment for gpio-line-names in the example
- Use dev_fwnode in hid-cp2112.c instead of directly accessing fwnode
- Immediately release the fwnode_handle from
device_get_named_child_node() in hid-cp2112.c
- Link to v12: https://lore.kernel.org/r/20251126-cp2112-dt-v12-0-2cdba6481db3@plexus.com
Changes in v12:
- dt-binding changes:
- Drop "on the host controller" from top-level description based on
comment from Rob H.
- Correct "Properties must precede subnodes" dt_binding_check error by
moving gpio_chip-related properties above the i2c subnode in the
binding and in the example.
- Include `interrupt-controller` property in the example
- Modify hid-cp2112.c to support separate schemas for DT vs. ACPI - DT
combines gpio subnode with the CP2112's node, but will have an I2C
subnode; while ACPI will maintain separate child nodes for the GPIO
I2C devices
Changes in v11:
- Eliminate 'gpio' subnode for DT and ACPI for the CP2112 per comment
from Rob H.
- Edit hid-cp2112.c to match for ACPI index and fall back to matching by
name (instead of the other way around)
- Separate CP2112 I2C bus speed configuration into a separate patch
Changes in v10:
- Define an enumeration and mapping for CP2112 ACPI _ADRs and devicetree
child node names, and use these in the scanning of child nodes
- Address other miscellaneous
Changes in v9:
- Add _ADR-based ACPI binding of child nodes (I2C is _ADR Zero, GPIO is _ADR One)
- Use a loop-based approach for assigning child nodes within probe().
As a consequence, hid-cp2112.c no longer maintains references to the
child fwnodes during the lifetime of the device. (plese correct if this
is actually needed for this use-case)
Changes in v8:
- Apply Review tags retroactively to patches previously reviewed
Changes in v7:
- Use dev_fwnode when calling fwnod_handle_put in i2c_adapter in hid-cp2112.c
- Capitalize I2C and GPIO in commit message for patch 0003
Changes in v6:
- Fix fwnode_handle reference leaks in hid-cp21112.c
- Simplify hog node pattern in silabs,cp2112.yaml
Changes in v5:
- Use fwnode API instead of of_node api in hid-core.c and hid-cp2112.c
- Include sda-gpios and scl-gpios in silabs,cp2112.yaml
- Additional fixups to silabs,cp2112.yaml to address comments
- Remove ngpios property
- Constrain the hog pattern to a single naming scheme
- Remove unneeded properties from the gpio hog which are provided by
the parent schema
- Submit threaded interrupt bugfix separately from this patchset, as requested
Changes in v4:
- Moved silabs,cp2112.yaml to /Documentation/devicetree/bindings/i2c
Changes in v3:
- Additional fixups to silabs,cp2112.yaml to address comments
Changes in v2:
- Added more detail to silabs,cp2112.yaml dt-binding
- Moved silabs,cp2112.yaml to /Documentation/devicetree/bindings/input
- Added support for setting smbus clock-frequency from DT in hid-cp2112.c
- Added freeing of of_nodes on error paths of _probe in hid-cp2112.c
Danny Kaehn (3):
dt-bindings: i2c: Add CP2112 HID USB to SMBus Bridge
HID: usbhid: Share USB device firmware node with child HID device
HID: cp2112: Fwnode Support
.../bindings/i2c/silabs,cp2112.yaml | 113 ++++++++++++++++++
drivers/hid/hid-cp2112.c | 50 ++++++++
drivers/hid/usbhid/hid-core.c | 2 +
3 files changed, 165 insertions(+)
create mode 100644 Documentation/devicetree/bindings/i2c/silabs,cp2112.yaml
--
2.25.1
---
Danny Kaehn (3):
dt-bindings: i2c: Add CP2112 HID USB to SMBus Bridge
HID: cp2112: Fwnode Support
HID: cp2112: Configure I2C Bus Speed from Firmware
.../devicetree/bindings/i2c/silabs,cp2112.yaml | 100 +++++++++++++++++++++
drivers/hid/hid-cp2112.c | 37 ++++++++
2 files changed, 137 insertions(+)
---
base-commit: 1c772200c9dcb23a304f84a9334fe2e0d9529ab0
change-id: 20240605-cp2112-dt-7cdc95448e8a
Best regards,
--
Danny Kaehn <danny.kaehn@plexus.com>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox