Linux Input/HID development
 help / color / mirror / Atom feed
* Re: [PATCH v2 4/9] mfd: Add driver for Asus Transformer embedded controller
From: Lee Jones @ 2026-03-06  9:18 UTC (permalink / raw)
  To: Svyatoslav Ryhel
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Dmitry Torokhov,
	Pavel Machek, Arnd Bergmann, Greg Kroah-Hartman,
	Sebastian Reichel, Michał Mirosław, Ion Agorria,
	devicetree, linux-kernel, linux-input, linux-leds, linux-pm
In-Reply-To: <20260209104407.116426-5-clamor95@gmail.com>

On Mon, 09 Feb 2026, Svyatoslav Ryhel wrote:

> From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
> 
> Support Nuvoton NPCE795-based ECs as used in Asus Transformer TF201,
> TF300T, TF300TG, TF300TL and TF700T pad and dock, as well as TF101 dock
> and TF600T, P1801-T and TF701T pad. This is a glue driver handling
> detection and common operations for EC's functions.
> 
> Co-developed-by: Svyatoslav Ryhel <clamor95@gmail.com>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
> ---
>  drivers/mfd/Kconfig         |  15 ++
>  drivers/mfd/Makefile        |   1 +
>  drivers/mfd/asus-ec.c       | 467 ++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/asus-ec.h | 138 +++++++++++
>  4 files changed, 621 insertions(+)
>  create mode 100644 drivers/mfd/asus-ec.c
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 7192c9d1d268..312fd15eec6a 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -137,6 +137,21 @@ config MFD_AAT2870_CORE
>  	  additional drivers must be enabled in order to use the
>  	  functionality of the device.
>  
> +config MFD_ASUSEC

MFD_ASUS_EC

> +	tristate "ASUS Transformer's embedded controller"
> +	depends on I2C && OF
> +	select SYSFS
> +	select ASUS_DOCKRAM
> +	help
> +	  Support ECs found in ASUS Transformer's Pad and Mobile Dock.
> +
> +	  This provides shared glue for functional part drivers:
> +	    asus-ec-kbc, asus-ec-keys, leds-asus-ec, asus-ec-battery
> +	    and asus-ec-charger.

Why the additional tabbing?  What example did you take that from?

> +	  This driver can also be built as a module. If so, the module
> +	  will be called asus-ec.
> +
>  config MFD_AT91_USART
>  	tristate "AT91 USART Driver"
>  	select MFD_CORE
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index e75e8045c28a..b676922601ba 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -10,6 +10,7 @@ obj-$(CONFIG_MFD_88PM805)	+= 88pm805.o 88pm80x.o
>  obj-$(CONFIG_MFD_88PM886_PMIC)	+= 88pm886.o
>  obj-$(CONFIG_MFD_ACT8945A)	+= act8945a.o
>  obj-$(CONFIG_MFD_SM501)		+= sm501.o
> +obj-$(CONFIG_MFD_ASUSEC)	+= asus-ec.o
>  obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835-pm.o
>  obj-$(CONFIG_MFD_BCM590XX)	+= bcm590xx.o
>  obj-$(CONFIG_MFD_BD9571MWV)	+= bd9571mwv.o
> diff --git a/drivers/mfd/asus-ec.c b/drivers/mfd/asus-ec.c
> new file mode 100644
> index 000000000000..e151c1506aa2
> --- /dev/null
> +++ b/drivers/mfd/asus-ec.c
> @@ -0,0 +1,467 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * ASUS EC driver

Copyright?  Author?

> + */
> +
> +#include <linux/array_size.h>
> +#include <linux/debugfs.h>
> +#include <linux/delay.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/mfd/asus-ec.h>
> +#include <linux/mfd/core.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/property.h>
> +#include <linux/string.h>
> +#include <linux/sysfs.h>
> +#include <linux/types.h>

Alphabetical.

Are you sure all of these are in use?

> +#define ASUSEC_RSP_BUFFER_SIZE		8
> +
> +struct asus_ec_chip_data {
> +	const char *name;
> +	const struct mfd_cell *mfd_devices;
> +	unsigned int num_devices;
> +};
> +
> +struct asus_ec_data {
> +	struct asusec_info info;
> +	struct mutex ecreq_lock; /* prevent simultaneous access */

We know what mutexes do.

If you're going to provide a comment, state WHAT is is protecting.

Or just omit the comment altogether.

> +	struct gpio_desc *ecreq;
> +	struct i2c_client *self;

"client"

Why are you storing this?

> +	const struct asus_ec_chip_data *data;
> +	u8 ec_data[DOCKRAM_ENTRY_BUFSIZE];
> +	bool clr_fmode;
> +	bool logging_disabled;
> +};
> +
> +#define to_ec_data(ec) \
> +	container_of(ec, struct asus_ec_data, info)
> +
> +static void asus_ec_remove_notifier(struct device *dev, void *res)
> +{
> +	struct asusec_info *ec = dev_get_drvdata(dev->parent);
> +	struct notifier_block **nb = res;
> +
> +	blocking_notifier_chain_unregister(&ec->notify_list, *nb);
> +}
> +
> +/**
> + * devm_asus_ec_register_notifier - Managed registration of notifier to an
> + *				    ASUS EC blocking notifier chain.
> + * @pdev: Device requesting the notifier (used for resource management).
> + * @nb: Notifier block to be registered.
> + *
> + * Register a notifier to the ASUS EC blocking notifier chain. The notifier
> + * will be automatically unregistered when the requesting device is detached.
> + *
> + * Return: 0 on success or a negative error code on failure.
> + */
> +int devm_asus_ec_register_notifier(struct platform_device *pdev,
> +				   struct notifier_block *nb)
> +{
> +	struct asusec_info *ec = dev_get_drvdata(pdev->dev.parent);
> +	struct notifier_block **res;
> +	int ret;
> +
> +	res = devres_alloc(asus_ec_remove_notifier, sizeof(*res), GFP_KERNEL);
> +	if (!res)
> +		return -ENOMEM;
> +
> +	*res = nb;
> +	ret = blocking_notifier_chain_register(&ec->notify_list, nb);
> +	if (ret) {
> +		devres_free(res);
> +		return ret;
> +	}
> +
> +	devres_add(&pdev->dev, res);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(devm_asus_ec_register_notifier);
> +
> +static int asus_ec_signal_request(const struct asusec_info *ec)
> +{
> +	struct asus_ec_data *priv = to_ec_data(ec);
> +
> +	guard(mutex)(&priv->ecreq_lock);
> +
> +	dev_dbg(&priv->self->dev, "EC request\n");
> +
> +	gpiod_set_value_cansleep(priv->ecreq, 1);
> +	msleep(50);
> +
> +	gpiod_set_value_cansleep(priv->ecreq, 0);
> +	msleep(200);
> +
> +	return 0;
> +}
> +
> +static int asus_ec_write(struct asus_ec_data *priv, u16 data)
> +{
> +	int ret = i2c_smbus_write_word_data(priv->self, ASUSEC_WRITE_BUF, data);
> +
> +	dev_dbg(&priv->self->dev, "EC write: %04x, ret = %d\n", data, ret);
> +	return ret;
> +}
> +
> +static int asus_ec_read(struct asus_ec_data *priv, bool in_irq)
> +{
> +	int ret = i2c_smbus_read_i2c_block_data(priv->self, ASUSEC_READ_BUF,
> +						sizeof(priv->ec_data),
> +						priv->ec_data);
> +
> +	dev_dbg(&priv->self->dev, "EC read: %*ph, ret = %d%s\n",
> +		sizeof(priv->ec_data), priv->ec_data,
> +		ret, in_irq ? "; in irq" : "");
> +
> +	return ret;
> +}

Remove both of these functions and use the i2c_smbus_*() API instead.

> +
> +/**
> + * asus_ec_i2c_command - Send a 16-bit command to the ASUS EC.
> + * @ec: Pointer to the shared ASUS EC structure.
> + * @data: The 16-bit command (word) to be sent.
> + *
> + * Return: 0 on success or a negative error code on failure.
> + */
> +int asus_ec_i2c_command(const struct asusec_info *ec, u16 data)
> +{
> +	return asus_ec_write(to_ec_data(ec), data);
> +}
> +EXPORT_SYMBOL_GPL(asus_ec_i2c_command);

Why is this needed?  Why not share 'client' with the leave drivers and
let them make their own calls to i2c_smbus_write_word_data()?

> +static void asus_ec_clear_buffer(struct asus_ec_data *priv)
> +{
> +	int retry = ASUSEC_RSP_BUFFER_SIZE;
> +
> +	while (retry--) {

Why is the amount of retries related to the buffer size?

> +		if (asus_ec_read(priv, false) < 0)
> +			continue;
> +
> +		if (priv->ec_data[1] & ASUSEC_OBF_MASK)

No magic numbers.  Define the 1.

> +			continue;
> +
> +		break;
> +	}
> +}
> +
> +static int asus_ec_log_info(struct asus_ec_data *priv, unsigned int reg,
> +			    const char *name, char **out)
> +{
> +	char buf[DOCKRAM_ENTRY_BUFSIZE];
> +	int ret;
> +
> +	ret = asus_dockram_read(priv->info.dockram, reg, buf);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (!priv->logging_disabled)
> +		dev_info(&priv->self->dev, "%-14s: %.*s\n", name, buf[0], buf + 1);
> +
> +	if (out)
> +		*out = kstrndup(buf + 1, buf[0], GFP_KERNEL);
> +
> +	return 0;
> +}

The driver is written now.  You can remove this over-engineered debugging
facility.

> +static int asus_ec_reset(struct asus_ec_data *priv)
> +{
> +	int retry, ret;
> +
> +	for (retry = 0; retry < 3; retry++) {

Why 3?

Why are you using for() here and while() above?

> +		ret = asus_ec_write(priv, 0);

Add a comment to explain how this works.

Or, better still, define the value.

> +		if (!ret)
> +			return 0;
> +
> +		msleep(300);

Why 300?

> +	}
> +
> +	return ret;
> +}
> +
> +static int asus_ec_magic_debug(struct asus_ec_data *priv)

What does this do?  More comments throughout please.

> +{
> +	u64 flag;
> +	int ret;
> +
> +	ret = asus_ec_get_ctl(&priv->info, &flag);
> +	if (ret < 0)
> +		return ret;
> +
> +	flag &= ASUSEC_CTL_SUSB_MODE;
> +	dev_info(&priv->self->dev, "EC FW behaviour: %s\n",
> +		 flag ? "susb on when receive ec_req" : "susb on when system wakeup");
> +
> +	return 0;
> +}
> +
> +static int asus_ec_set_factory_mode(struct asus_ec_data *priv, bool on)
> +{
> +	dev_info(&priv->self->dev, "Entering %s mode.\n", on ? "factory" : "normal");

Remove all of the debugging prints now.

> +	return asus_ec_update_ctl(&priv->info, ASUSEC_CTL_FACTORY_MODE,
> +				  on ? ASUSEC_CTL_FACTORY_MODE : 0);
> +}
> +
> +static void asus_ec_handle_smi(struct asus_ec_data *priv, unsigned int code);

No forward declarations.

> +static irqreturn_t asus_ec_interrupt(int irq, void *dev_id)
> +{
> +	struct asus_ec_data *priv = dev_id;
> +	unsigned long notify_action;
> +	int ret;
> +
> +	ret = asus_ec_read(priv, true);
> +	if (ret <= 0 || !(priv->ec_data[1] & ASUSEC_OBF_MASK))
> +		return IRQ_NONE;
> +
> +	notify_action = priv->ec_data[1];
> +	if (notify_action & ASUSEC_SMI_MASK) {
> +		unsigned int code = priv->ec_data[2];
> +
> +		asus_ec_handle_smi(priv, code);
> +
> +		notify_action |= code << 8;
> +		dev_dbg(&priv->self->dev, "SMI code: 0x%02x\n", code);
> +	}
> +
> +	blocking_notifier_call_chain(&priv->info.notify_list,
> +				     notify_action, priv->ec_data);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int asus_ec_detect(struct asus_ec_data *priv)
> +{
> +	char *model = NULL;
> +	int ret;
> +
> +	ret = asus_ec_reset(priv);
> +	if (ret)
> +		goto err_exit;
> +
> +	asus_ec_clear_buffer(priv);
> +
> +	ret = asus_ec_log_info(priv, ASUSEC_DOCKRAM_INFO_MODEL, "model", &model);
> +	if (ret)
> +		goto err_exit;
> +
> +	ret = asus_ec_log_info(priv, ASUSEC_DOCKRAM_INFO_FW, "FW version", NULL);
> +	if (ret)
> +		goto err_exit;
> +
> +	ret = asus_ec_log_info(priv, ASUSEC_DOCKRAM_INFO_CFGFMT, "Config format", NULL);
> +	if (ret)
> +		goto err_exit;
> +
> +	ret = asus_ec_log_info(priv, ASUSEC_DOCKRAM_INFO_HW, "HW version", NULL);
> +	if (ret)
> +		goto err_exit;
> +
> +	priv->logging_disabled = true;
> +
> +	ret = asus_ec_magic_debug(priv);
> +	if (ret)
> +		goto err_exit;
> +
> +	priv->info.model = model;
> +	priv->info.name = priv->data->name;
> +
> +	if (priv->clr_fmode)
> +		asus_ec_set_factory_mode(priv, false);
> +
> +err_exit:
> +	if (ret)
> +		dev_err(&priv->self->dev, "failed to access EC: %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static void asus_ec_handle_smi(struct asus_ec_data *priv, unsigned int code)
> +{
> +	dev_dbg(&priv->self->dev, "SMI interrupt: 0x%02x\n", code);
> +
> +	switch (code) {
> +	case ASUSEC_SMI_HANDSHAKE:
> +	case ASUSEC_SMI_RESET:
> +		asus_ec_detect(priv);
> +		break;
> +	}
> +}
> +
> +static int ec_request_set(void *ec, u64 val)
> +{
> +	if (val)
> +		asus_ec_signal_request(ec);
> +
> +	return 0;
> +}
> +
> +DEFINE_DEBUGFS_ATTRIBUTE(ec_request_fops, NULL, ec_request_set, "%llu\n");
> +
> +static int ec_irq_set(void *ec, u64 val)
> +{
> +	struct asus_ec_data *priv = to_ec_data(ec);
> +
> +	if (val)
> +		irq_wake_thread(priv->self->irq, priv);
> +
> +	return 0;
> +}
> +
> +DEFINE_DEBUGFS_ATTRIBUTE(ec_irq_fops, NULL, ec_irq_set, "%llu\n");

Document these.

> +static void asus_ec_debugfs_remove(void *debugfs_root)
> +{
> +	debugfs_remove_recursive(debugfs_root);
> +}
> +
> +static void devm_asus_ec_debugfs_init(struct device *dev)
> +{
> +	struct asusec_info *ec = dev_get_drvdata(dev);
> +	struct asus_ec_data *priv = to_ec_data(ec);
> +	struct dentry *debugfs_root;
> +	char *name = devm_kasprintf(dev, GFP_KERNEL, "asus-ec-%s",
> +				    priv->data->name);
> +
> +	debugfs_root = debugfs_create_dir(name, NULL);
> +
> +	debugfs_create_file("ec_irq", 0200, debugfs_root, ec, &ec_irq_fops);
> +	debugfs_create_file("ec_request", 0200, debugfs_root, ec, &ec_request_fops);
> +
> +	asus_dockram_debugfs_init(priv->info.dockram, debugfs_root);
> +
> +	devm_add_action_or_reset(dev, asus_ec_debugfs_remove, debugfs_root);
> +}
> +
> +static int asus_ec_probe(struct i2c_client *client)
> +{
> +	struct device *dev = &client->dev;
> +	struct asus_ec_data *priv;

Call this "ddata".

> +	int ret;
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->data = device_get_match_data(dev);
> +	if (!priv->data)
> +		return -ENODEV;
> +
> +	i2c_set_clientdata(client, priv);
> +	priv->self = client;
> +
> +	priv->info.dockram = devm_asus_dockram_get(dev);
> +	if (IS_ERR(priv->info.dockram))
> +		return dev_err_probe(dev, PTR_ERR(priv->info.dockram),
> +				     "failed to get dockram\n");
> +
> +	priv->ecreq = devm_gpiod_get(dev, "request", GPIOD_OUT_LOW);
> +	if (IS_ERR(priv->ecreq))
> +		return dev_err_probe(dev, PTR_ERR(priv->ecreq),
> +				     "failed to get request GPIO\n");
> +
> +	BLOCKING_INIT_NOTIFIER_HEAD(&priv->info.notify_list);
> +	mutex_init(&priv->ecreq_lock);
> +
> +	priv->clr_fmode = device_property_read_bool(dev, "asus,clear-factory-mode");
> +
> +	asus_ec_signal_request(&priv->info);
> +
> +	ret = asus_ec_detect(priv);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "failed to detect EC version\n");
> +
> +	ret = devm_request_threaded_irq(dev, client->irq, NULL,
> +					&asus_ec_interrupt,
> +					IRQF_ONESHOT | IRQF_SHARED,
> +					client->name, priv);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "failed to register IRQ\n");
> +
> +	/* Parent I2C controller uses DMA, ASUS EC and child devices do not */
> +	client->dev.coherent_dma_mask = 0;
> +	client->dev.dma_mask = &client->dev.coherent_dma_mask;
> +
> +	devm_asus_ec_debugfs_init(dev);
> +
> +	return devm_mfd_add_devices(dev, 0, priv->data->mfd_devices,
> +				    priv->data->num_devices, NULL, 0, NULL);
> +}
> +
> +static const struct mfd_cell asus_ec_pad_mfd_devices[] = {
> +	{
> +		.name = "asus-ec-battery",
> +		.id = 0,
> +		.of_compatible = "asus,ec-battery",
> +	}, {
> +		.name = "asus-ec-charger",
> +		.id = 0,
> +		.of_compatible = "asus,ec-charger",
> +	}, {
> +		.name = "asus-ec-led",
> +		.id = 0,
> +		.of_compatible = "asus,ec-led",
> +	},
> +};
> +
> +static const struct mfd_cell asus_ec_dock_mfd_devices[] = {
> +	{
> +		.name = "asus-ec-battery",
> +		.id = 1,
> +		.of_compatible = "asus,ec-battery",
> +	}, {
> +		.name = "asus-ec-charger",
> +		.id = 1,
> +		.of_compatible = "asus,ec-charger",
> +	}, {
> +		.name = "asus-ec-led",
> +		.id = 1,
> +		.of_compatible = "asus,ec-led",
> +	}, {
> +		.name = "asus-ec-keys",
> +		.of_compatible = "asus,ec-keys",
> +	}, {
> +		.name = "asus-ec-kbc",
> +		.of_compatible = "asus,ec-kbc",
> +	},
> +};
> +
> +static const struct asus_ec_chip_data asus_ec_pad_data = {
> +	.name = "pad",
> +	.mfd_devices = asus_ec_pad_mfd_devices,
> +	.num_devices = ARRAY_SIZE(asus_ec_pad_mfd_devices),
> +};
> +
> +static const struct asus_ec_chip_data asus_ec_dock_data = {
> +	.name = "dock",
> +	.mfd_devices = asus_ec_dock_mfd_devices,
> +	.num_devices = ARRAY_SIZE(asus_ec_dock_mfd_devices),
> +};
> +
> +static const struct of_device_id asus_ec_match[] = {
> +	{ .compatible = "asus,ec-pad", .data = &asus_ec_pad_data },

Passing MFD data through a different registration mechanism is not
allowed.  Use identifiers to match in instead.

git grep "\.data =.*void" -- drivers/mfd

> +	{ .compatible = "asus,ec-dock", .data = &asus_ec_dock_data },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, asus_ec_match);
> +
> +static struct i2c_driver asus_ec_driver = {
> +	.driver	= {
> +		.name = "asus-ec",
> +		.of_match_table = asus_ec_match,
> +	},
> +	.probe = asus_ec_probe,
> +};
> +module_i2c_driver(asus_ec_driver);
> +
> +MODULE_AUTHOR("Michał Mirosław <mirq-linux@rere.qmqm.pl>");
> +MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>");
> +MODULE_DESCRIPTION("ASUS Transformer's EC driver");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/mfd/asus-ec.h b/include/linux/mfd/asus-ec.h
> index 6a36313b9ebd..6a06b125ba30 100644
> --- a/include/linux/mfd/asus-ec.h
> +++ b/include/linux/mfd/asus-ec.h
> @@ -2,16 +2,78 @@
>  #ifndef __MISC_ASUS_EC_H
>  #define __MISC_ASUS_EC_H
>  
> +#include <linux/notifier.h>
> +#include <linux/platform_device.h>
> +#include <linux/workqueue.h>
> +
>  struct i2c_client;
>  
> +struct asusec_info {
> +	const char *model;
> +	const char *name;
> +	struct i2c_client *dockram;
> +	struct workqueue_struct *wq;
> +	struct blocking_notifier_head notify_list;
> +};
> +
>  #define DOCKRAM_ENTRIES			0x100
>  #define DOCKRAM_ENTRY_SIZE		32
>  #define DOCKRAM_ENTRY_BUFSIZE		(DOCKRAM_ENTRY_SIZE + 1)
>  
> +/* interrupt sources */
> +#define ASUSEC_OBF_MASK			BIT(0)
> +#define ASUSEC_KEY_MASK			BIT(2)
> +#define ASUSEC_KBC_MASK			BIT(3)
> +#define ASUSEC_AUX_MASK			BIT(5)
> +#define ASUSEC_SCI_MASK			BIT(6)
> +#define ASUSEC_SMI_MASK			BIT(7)
> +
> +/* SMI notification codes */
> +#define ASUSEC_SMI_POWER_NOTIFY		0x31	/* [un]plugging USB cable */
> +#define ASUSEC_SMI_HANDSHAKE		0x50	/* response to ec_req edge */
> +#define ASUSEC_SMI_WAKE			0x53
> +#define ASUSEC_SMI_RESET		0x5f
> +#define ASUSEC_SMI_ADAPTER_EVENT	0x60	/* [un]plugging charger to dock */
> +#define ASUSEC_SMI_BACKLIGHT_ON		0x63
> +#define ASUSEC_SMI_AUDIO_DOCK_IN	0x70
> +
> +#define ASUSEC_SMI_ACTION(code)		(ASUSEC_SMI_MASK | ASUSEC_OBF_MASK | \
> +					(ASUSEC_SMI_##code << 8))
> +
>  /* control register [0x0A] layout */
>  #define ASUSEC_CTL_SIZE			8
>  
> +/*
> + * EC reports power from 40-pin connector in the LSB of the control
> + * register.  The following values have been observed (xor 0x02):
> + *
> + * PAD-ec no-plug  0x40 / PAD-ec DOCK     0x20 / DOCK-ec no-plug 0x40
> + * PAD-ec AC       0x25 / PAD-ec DOCK+AC  0x24 / DOCK-ec AC      0x25
> + * PAD-ec USB      0x45 / PAD-ec DOCK+USB 0x24 / DOCK-ec USB     0x41
> + */
> +
> +#define ASUSEC_CTL_DIRECT_POWER_SOURCE	BIT_ULL(0)
> +#define ASUSEC_STAT_CHARGING		BIT_ULL(2)
> +#define ASUSEC_CTL_FULL_POWER_SOURCE	BIT_ULL(5)
> +#define ASUSEC_CTL_SUSB_MODE		BIT_ULL(11)
> +#define ASUSEC_CMD_SUSPEND_S3		BIT_ULL(41)
> +#define ASUSEC_CTL_TEST_DISCHARGE	BIT_ULL(43)
> +#define ASUSEC_CMD_SUSPEND_INHIBIT	BIT_ULL(45)
> +#define ASUSEC_CTL_FACTORY_MODE		BIT_ULL(46)
> +#define ASUSEC_CTL_KEEP_AWAKE		BIT_ULL(47)
> +#define ASUSEC_CTL_USB_CHARGE		BIT_ULL(50)
> +#define ASUSEC_CMD_SWITCH_HDMI		BIT_ULL(70)
> +#define ASUSEC_CMD_WIN_SHUTDOWN		BIT_ULL(76)
> +
> +#define ASUSEC_DOCKRAM_INFO_MODEL	0x01
> +#define ASUSEC_DOCKRAM_INFO_FW		0x02
> +#define ASUSEC_DOCKRAM_INFO_CFGFMT	0x03
> +#define ASUSEC_DOCKRAM_INFO_HW		0x04
>  #define ASUSEC_DOCKRAM_CONTROL		0x0a
> +#define ASUSEC_DOCKRAM_BATT_CTL		0x14
> +
> +#define ASUSEC_WRITE_BUF		0x64
> +#define ASUSEC_READ_BUF			0x6A
>  
>  /* dockram comm */
>  int asus_dockram_read(struct i2c_client *client, int reg, char *buf);
> @@ -21,4 +83,80 @@ int asus_dockram_access_ctl(struct i2c_client *client,
>  struct i2c_client *devm_asus_dockram_get(struct device *parent);
>  void asus_dockram_debugfs_init(struct i2c_client *client,
>  			       struct dentry *debugfs_root);
> +
> +/* EC public API */
> +
> +/**
> + * cell_to_ec - Request the shared ASUS EC structure via a subdevice's pdev.
> + * @pdev: EC subdevice pdev requesting access to the shared ASUS EC structure.
> + *
> + * Returns a pointer to the asusec_info structure.
> + */
> +static inline struct asusec_info *cell_to_ec(struct platform_device *pdev)
> +{
> +	return dev_get_drvdata(pdev->dev.parent);
> +}
> +
> +/**
> + * asus_ec_get_ctl - Read from the DockRAM control register.
> + * @ec:  Pointer to the shared ASUS EC structure.
> + * @out: Pointer to the variable where the register value will be stored.
> + *
> + * Performs a control register read and stores the value in @out.
> + *
> + * Return: 0 on success, or a negative errno code on failure.
> + */
> +static inline int asus_ec_get_ctl(const struct asusec_info *ec, u64 *out)
> +{
> +	return asus_dockram_access_ctl(ec->dockram, out, 0, 0);
> +}
> +
> +/**
> + * asus_ec_update_ctl - Update the DockRAM control register.
> + * @ec:   Pointer to the shared ASUS EC structure.
> + * @mask: Bitmask of bits to be cleared.
> + * @xor:  Bitmask of bits to be toggled or set (via XOR).
> + *
> + * Performs a read-modify-write update on the control register using
> + * the provided @mask and @xor values.
> + *
> + * Return: 0 on success, or a negative errno code on failure.
> + */
> +static inline int asus_ec_update_ctl(const struct asusec_info *ec,
> +				     u64 mask, u64 xor)
> +{
> +	return asus_dockram_access_ctl(ec->dockram, NULL, mask, xor);
> +}
> +
> +/**
> + * asus_ec_set_ctl_bits - Sets bits of the DockRAM control register.
> + * @ec:   Pointer to the shared ASUS EC structure.
> + * @mask: Bitmask of bits to be set.
> + *
> + * Sets bits of the control register using the provided @mask value.
> + *
> + * Return: 0 on success, or a negative errno code on failure.
> + */
> +static inline int asus_ec_set_ctl_bits(const struct asusec_info *ec, u64 mask)
> +{
> +	return asus_dockram_access_ctl(ec->dockram, NULL, mask, mask);
> +}
> +
> +/**
> + * asus_ec_clear_ctl_bits - Clears bits of the DockRAM control register.
> + * @ec:   Pointer to the shared ASUS EC structure.
> + * @mask: Bitmask of bits to be cleared.
> + *
> + * Clears bits of the control register using the provided @mask value.
> + *
> + * Return: 0 on success, or a negative errno code on failure.
> + */
> +static inline int asus_ec_clear_ctl_bits(const struct asusec_info *ec, u64 mask)
> +{
> +	return asus_dockram_access_ctl(ec->dockram, NULL, mask, 0);
> +}

This is all abstraction for he sake of abstraction.

> +int asus_ec_i2c_command(const struct asusec_info *ec, u16 data);
> +int devm_asus_ec_register_notifier(struct platform_device *dev,
> +				   struct notifier_block *nb);
>  #endif /* __MISC_ASUS_EC_H */
> -- 
> 2.51.0
> 
> 

-- 
Lee Jones [李琼斯]

^ permalink raw reply

* Re: [PATCH 1/1] dt-bindings: input: touchscreen: edt-ft5x06: add edt,edt-ft5x06 for legacy platforms
From: Krzysztof Kozlowski @ 2026-03-06  8:41 UTC (permalink / raw)
  To: Frank Li
  Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Yedaya Katsman, Joel Selvaraj, Jens Reidel,
	open list:INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN)...,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list, imx
In-Reply-To: <20260305223731.4088953-1-Frank.Li@nxp.com>

On Thu, Mar 05, 2026 at 05:37:29PM -0500, Frank Li wrote:
> The compatible string "edt,edt-ft5x06" has been used for more than a decade
> on older platforms such as i.MX6 and OMAP. However, it is currently missing
> from the binding documentation.
> 
> Add it to the binding to document existing usage and fix the following
> CHECK_DTBS warnings.
>   arch/arm/boot/dts/nxp/imx/imx6dl-nit6xlite.dtb: /soc/bus@2100000/i2c@21a8000/touchscreen@38: failed to match any schema with compatible: ['edt,edt-ft5x06'
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
>  .../devicetree/bindings/input/touchscreen/edt-ft5x06.yaml        | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
> index 6f90522de8c0a..213451f823369 100644
> --- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
> +++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
> @@ -38,6 +38,7 @@ properties:
>        - edt,edt-ft5306
>        - edt,edt-ft5406
>        - edt,edt-ft5506
> +      - edt,edt-ft5x06 # Deprecated, not use for new platform.

Then document it as deprecated one.

OTOH, this above is clearly not correct because we also have
"edt,edt-ft5506", "edt,edt-ft5x06". Just use git grep.

I don't understand, though, what is the point of documenting it if there
is no ABI implemented (nothing in the driver) and it cannot work.

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: input: touchscreen: sitronix,st1232: Add wakeup-source
From: Krzysztof Kozlowski @ 2026-03-06  8:18 UTC (permalink / raw)
  To: phucduc.bui
  Cc: dmitry.torokhov, robh, krzk+dt, conor+dt, geert+renesas,
	magnus.damm, javier.carrasco, hechtb, wsa+renesas, linux-input,
	devicetree, linux-renesas-soc, linux-kernel
In-Reply-To: <20260305113512.227269-2-phucduc.bui@gmail.com>

On Thu, Mar 05, 2026 at 06:35:11PM +0700, phucduc.bui@gmail.com wrote:
> From: bui duc phuc <phucduc.bui@gmail.com>
> 
> Document the 'wakeup-source' property for Sitronix ST1232 touchscreen
> controllers to allow the device to wake the system from suspend.
> 
> Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
> ---
>  .../bindings/input/touchscreen/sitronix,st1232.yaml          | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/sitronix,st1232.yaml b/Documentation/devicetree/bindings/input/touchscreen/sitronix,st1232.yaml
> index 978afaa4fcef..672544e5a26e 100644
> --- a/Documentation/devicetree/bindings/input/touchscreen/sitronix,st1232.yaml
> +++ b/Documentation/devicetree/bindings/input/touchscreen/sitronix,st1232.yaml
> @@ -32,6 +32,10 @@ properties:
>      description: A phandle to the reset GPIO
>      maxItems: 1
>  
> +  wakeup-source:
> +    description: Device can be used as a wakeup source.

Drop description

> +    type: boolean

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH][next] HID: hid-lenovo-go-s: Fix spelling mistake "configuratiion" -> "configuration"
From: Derek John Clark @ 2026-03-06  5:59 UTC (permalink / raw)
  To: Colin Ian King
  Cc: Mark Pearson, Jiri Kosina, Benjamin Tissoires, linux-input,
	kernel-janitors, linux-kernel
In-Reply-To: <20260227231606.421263-1-colin.i.king@gmail.com>

On Fri, Feb 27, 2026 at 3:17 PM Colin Ian King <colin.i.king@gmail.com> wrote:
>
> There is a spelling mistake in a dev_err_probe message. Fix it.
>
> Signed-off-by: Colin Ian King <colin.i.king@gmail.com>
> ---
>  drivers/hid/hid-lenovo-go-s.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c
> index cacc5bd5ed2b..dbb88492fbba 100644
> --- a/drivers/hid/hid-lenovo-go-s.c
> +++ b/drivers/hid/hid-lenovo-go-s.c
> @@ -1401,7 +1401,7 @@ static int hid_gos_cfg_probe(struct hid_device *hdev,
>         ret = devm_device_add_group(gos_cdev_rgb.led_cdev.dev, &rgb_attr_group);
>         if (ret) {
>                 dev_err_probe(&hdev->dev, ret,
> -                             "Failed to create RGB configuratiion attributes\n");
> +                             "Failed to create RGB configuration attributes\n");
>                 return ret;
>         }
>
> --
> 2.51.0
>

Reviewed-by: Derek J. Clark <derekjohn.clark@gmail.com>

^ permalink raw reply

* Re: [PATCH] HID: hid-lenovo-go: Remove unneeded semicolon
From: Derek John Clark @ 2026-03-06  5:59 UTC (permalink / raw)
  To: Chen Ni; +Cc: mpearson-lenovo, jikos, bentiss, linux-input, linux-kernel
In-Reply-To: <20260228033936.285945-1-nichen@iscas.ac.cn>

On Fri, Feb 27, 2026 at 7:41 PM Chen Ni <nichen@iscas.ac.cn> wrote:
>
> Remove unnecessary semicolons after switch statements and function
> bodies. Most issues were reported by Coccinelle/coccicheck using the
> semantic patch at scripts/coccinelle/misc/semicolon.cocci. Additional
> instances found during manual code review were also fixed.
>
> Signed-off-by: Chen Ni <nichen@iscas.ac.cn>
> ---
>  drivers/hid/hid-lenovo-go.c | 52 ++++++++++++++++++-------------------
>  1 file changed, 26 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/hid/hid-lenovo-go.c b/drivers/hid/hid-lenovo-go.c
> index 6972d13802e2..77e3823447e5 100644
> --- a/drivers/hid/hid-lenovo-go.c
> +++ b/drivers/hid/hid-lenovo-go.c
> @@ -455,7 +455,7 @@ static int hid_go_feature_status_event(struct command_report *cmd_rep)
>                         return 0;
>                 default:
>                         return -EINVAL;
> -               };
> +               }
>         case FEATURE_IMU_BYPASS:
>                 switch (cmd_rep->device_type) {
>                 case LEFT_CONTROLLER:
> @@ -466,7 +466,7 @@ static int hid_go_feature_status_event(struct command_report *cmd_rep)
>                         return 0;
>                 default:
>                         return -EINVAL;
> -               };
> +               }
>                 break;
>         case FEATURE_LIGHT_ENABLE:
>                 drvdata.rgb_en = cmd_rep->data[0];
> @@ -481,7 +481,7 @@ static int hid_go_feature_status_event(struct command_report *cmd_rep)
>                         return 0;
>                 default:
>                         return -EINVAL;
> -               };
> +               }
>                 break;
>         case FEATURE_TOUCHPAD_ENABLE:
>                 drvdata.tp_en = cmd_rep->data[0];
> @@ -515,7 +515,7 @@ static int hid_go_motor_event(struct command_report *cmd_rep)
>                         return 0;
>                 default:
>                         return -EINVAL;
> -               };
> +               }
>                 break;
>         case RUMBLE_MODE:
>                 switch (cmd_rep->device_type) {
> @@ -527,7 +527,7 @@ static int hid_go_motor_event(struct command_report *cmd_rep)
>                         return 0;
>                 default:
>                         return -EINVAL;
> -               };
> +               }
>         case TP_VIBRATION_ENABLE:
>                 drvdata.tp_vibration_en = cmd_rep->data[0];
>                 return 0;
> @@ -625,7 +625,7 @@ static int hid_go_os_mode_cfg_event(struct command_report *cmd_rep)
>                 return 0;
>         default:
>                 return -EINVAL;
> -       };
> +       }
>  }
>
>  static int hid_go_set_event_return(struct command_report *cmd_rep)
> @@ -699,14 +699,14 @@ static int hid_go_raw_event(struct hid_device *hdev, struct hid_report *report,
>                 default:
>                         ret = -EINVAL;
>                         break;
> -               };
> +               }
>                 break;
>         case OS_MODE_DATA:
>                 ret = hid_go_os_mode_cfg_event(cmd_rep);
>                 break;
>         default:
>                 goto passthrough;
> -       };
> +       }
>         dev_dbg(&hdev->dev, "Rx data as raw input report: [%*ph]\n",
>                 GO_PACKET_SIZE, data);
>
> @@ -925,7 +925,7 @@ static ssize_t feature_status_store(struct device *dev,
>                 break;
>         default:
>                 return -EINVAL;
> -       };
> +       }
>
>         if (ret < 0)
>                 return ret;
> @@ -1013,7 +1013,7 @@ static ssize_t feature_status_show(struct device *dev,
>                         break;
>                 default:
>                         return -EINVAL;
> -               };
> +               }
>                 count = sysfs_emit(buf, "%u\n", i);
>                 break;
>         case FEATURE_FPS_SWITCH_STATUS:
> @@ -1032,7 +1032,7 @@ static ssize_t feature_status_show(struct device *dev,
>                 break;
>         default:
>                 return -EINVAL;
> -       };
> +       }
>
>         return count;
>  }
> @@ -1070,7 +1070,7 @@ static ssize_t feature_status_options(struct device *dev,
>                 break;
>         default:
>                 return -EINVAL;
> -       };
> +       }
>
>         if (count)
>                 buf[count - 1] = '\n';
> @@ -1111,7 +1111,7 @@ static ssize_t motor_config_store(struct device *dev,
>                 ret = sysfs_match_string(intensity_text, buf);
>                 val = ret;
>                 break;
> -       };
> +       }
>
>         if (ret < 0)
>                 return ret;
> @@ -1161,7 +1161,7 @@ static ssize_t motor_config_show(struct device *dev,
>                         break;
>                 default:
>                         return -EINVAL;
> -               };
> +               }
>                 if (i >= ARRAY_SIZE(enabled_status_text))
>                         return -EINVAL;
>
> @@ -1177,7 +1177,7 @@ static ssize_t motor_config_show(struct device *dev,
>                         break;
>                 default:
>                         return -EINVAL;
> -               };
> +               }
>                 if (i >= ARRAY_SIZE(rumble_mode_text))
>                         return -EINVAL;
>
> @@ -1197,7 +1197,7 @@ static ssize_t motor_config_show(struct device *dev,
>
>                 count = sysfs_emit(buf, "%s\n", intensity_text[i]);
>                 break;
> -       };
> +       }
>
>         return count;
>  }
> @@ -1232,7 +1232,7 @@ static ssize_t motor_config_options(struct device *dev,
>                                                enabled_status_text[i]);
>                 }
>                 break;
> -       };
> +       }
>
>         if (count)
>                 buf[count - 1] = '\n';
> @@ -1333,7 +1333,7 @@ static ssize_t device_status_show(struct device *dev,
>                 break;
>         default:
>                 return -EINVAL;
> -       };
> +       }
>
>         if (i >= ARRAY_SIZE(cal_status_text))
>                 return -EINVAL;
> @@ -1459,7 +1459,7 @@ static int rgb_attr_show(void)
>         index = drvdata.rgb_profile + 3;
>
>         return rgb_cfg_call(drvdata.hdev, GET_RGB_CFG, index, 0, 0);
> -};
> +}
>
>  static ssize_t rgb_effect_store(struct device *dev,
>                                 struct device_attribute *attr, const char *buf,
> @@ -1489,7 +1489,7 @@ static ssize_t rgb_effect_store(struct device *dev,
>
>         drvdata.rgb_effect = effect;
>         return count;
> -};
> +}
>
>  static ssize_t rgb_effect_show(struct device *dev,
>                                struct device_attribute *attr, char *buf)
> @@ -1552,7 +1552,7 @@ static ssize_t rgb_speed_store(struct device *dev,
>         drvdata.rgb_speed = val;
>
>         return count;
> -};
> +}
>
>  static ssize_t rgb_speed_show(struct device *dev, struct device_attribute *attr,
>                               char *buf)
> @@ -1594,7 +1594,7 @@ static ssize_t rgb_mode_store(struct device *dev, struct device_attribute *attr,
>         drvdata.rgb_mode = val;
>
>         return count;
> -};
> +}
>
>  static ssize_t rgb_mode_show(struct device *dev, struct device_attribute *attr,
>                              char *buf)
> @@ -1609,7 +1609,7 @@ static ssize_t rgb_mode_show(struct device *dev, struct device_attribute *attr,
>                 return -EINVAL;
>
>         return sysfs_emit(buf, "%s\n", rgb_mode_text[drvdata.rgb_mode]);
> -};
> +}
>
>  static ssize_t rgb_mode_index_show(struct device *dev,
>                                    struct device_attribute *attr, char *buf)
> @@ -1649,7 +1649,7 @@ static ssize_t rgb_profile_store(struct device *dev,
>         drvdata.rgb_profile = val;
>
>         return count;
> -};
> +}
>
>  static ssize_t rgb_profile_show(struct device *dev,
>                                 struct device_attribute *attr, char *buf)
> @@ -1665,7 +1665,7 @@ static ssize_t rgb_profile_show(struct device *dev,
>                 return -EINVAL;
>
>         return sysfs_emit(buf, "%hhu\n", drvdata.rgb_profile);
> -};
> +}
>
>  static ssize_t rgb_profile_range_show(struct device *dev,
>                                       struct device_attribute *attr, char *buf)
> @@ -1704,7 +1704,7 @@ static void hid_go_brightness_set(struct led_classdev *led_cdev,
>                 break;
>         default:
>                 dev_err(led_cdev->dev, "Failed to write RGB profile: %i\n", ret);
> -       };
> +       }
>  }
>
>  #define LEGO_DEVICE_ATTR_RW(_name, _attrname, _dtype, _rtype, _group)         \
> --
> 2.25.1
>

Reviewed-by: Derek J. Clark <derekjohn.clark@gmail.com>

^ permalink raw reply

* Re: [PATCH] HID: hid-lenovo-go-s: Remove unneeded semicolon
From: Derek John Clark @ 2026-03-06  5:58 UTC (permalink / raw)
  To: Chen Ni; +Cc: mpearson-lenovo, jikos, bentiss, linux-input, linux-kernel
In-Reply-To: <20260228034343.286005-1-nichen@iscas.ac.cn>

On Fri, Feb 27, 2026 at 7:44 PM Chen Ni <nichen@iscas.ac.cn> wrote:
>
> Remove unnecessary semicolons reported by Coccinelle/coccicheck and the
> semantic patch at scripts/coccinelle/misc/semicolon.cocci.
>
> Signed-off-by: Chen Ni <nichen@iscas.ac.cn>
> ---
>  drivers/hid/hid-lenovo-go-s.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c
> index cacc5bd5ed2b..d1eb067509f6 100644
> --- a/drivers/hid/hid-lenovo-go-s.c
> +++ b/drivers/hid/hid-lenovo-go-s.c
> @@ -1102,7 +1102,7 @@ static void hid_gos_brightness_set(struct led_classdev *led_cdev,
>         default:
>                 dev_err(led_cdev->dev, "Failed to write RGB profile: %i\n",
>                         ret);
> -       };
> +       }
>  }
>
>  #define LEGOS_DEVICE_ATTR_RW(_name, _attrname, _rtype, _group)                 \
> --
> 2.25.1
>

Reviewed-by: Derek J. Clark <derekjohn.clark@gmail.com>

^ permalink raw reply

* Re: [PATCH 3/3] HID: hid-lenovo-go-s: Fix positive promotion bug
From: Derek John Clark @ 2026-03-06  5:57 UTC (permalink / raw)
  To: Ethan Tidmore
  Cc: Mark Pearson, Jiri Kosina, Benjamin Tissoires, Mario Limonciello,
	linux-input, linux-kernel
In-Reply-To: <20260227205444.1083103-4-ethantidmore06@gmail.com>

On Fri, Feb 27, 2026 at 12:55 PM Ethan Tidmore <ethantidmore06@gmail.com> wrote:
>
> The function mcu_property_out() returns type int and returns negative
> error codes. The variable count is assigned from it and checked with
> (count < 0) but this check would always be false because count can
> never be less than zero as it is size_t.
>
> Change count to ssize_t.
>
> Detected by Smatch:
> drivers/hid/hid-lenovo-go-s.c:583 gamepad_property_show() warn:
> unsigned 'count' is never less than zero.
>
> drivers/hid/hid-lenovo-go-s.c:583 gamepad_property_show() warn:
> error code type promoted to positive: 'count'
>
> Fixes: 14651777fd675 ("HID: hid-lenovo-go-s: Add Feature Status Attributes")
> Signed-off-by: Ethan Tidmore <ethantidmore06@gmail.com>
> ---
>  drivers/hid/hid-lenovo-go-s.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c
> index a24737170f83..4596c18037a9 100644
> --- a/drivers/hid/hid-lenovo-go-s.c
> +++ b/drivers/hid/hid-lenovo-go-s.c
> @@ -573,7 +573,7 @@ static ssize_t gamepad_property_show(struct device *dev,
>                                      struct device_attribute *attr, char *buf,
>                                      enum feature_status_index index)
>  {
> -       size_t count = 0;
> +       ssize_t count = 0;
>         u8 i;
>
>         count = mcu_property_out(drvdata.hdev, GET_GAMEPAD_CFG, index, 0, 0);
> --
> 2.53.0
>

Reviewed-by: Derek J. Clark <derekjohn.clark@gmail.com>

^ permalink raw reply

* Re: [PATCH 2/3] HID: hid-lenovo-go-s: Remove impossible condition
From: Derek John Clark @ 2026-03-06  5:57 UTC (permalink / raw)
  To: Ethan Tidmore
  Cc: Mark Pearson, Jiri Kosina, Benjamin Tissoires, Mario Limonciello,
	linux-input, linux-kernel
In-Reply-To: <20260227205444.1083103-3-ethantidmore06@gmail.com>

On Fri, Feb 27, 2026 at 12:55 PM Ethan Tidmore <ethantidmore06@gmail.com> wrote:
>
> The variable val is of type u8, so it can only be 0-255.
>
> Remove this condition.
>
> Detected by Smatch:
> drivers/hid/hid-lenovo-go-s.c:508 gamepad_property_store() warn:
> impossible condition '(val > 255) => (0-255 > 255)'
>
> Signed-off-by: Ethan Tidmore <ethantidmore06@gmail.com>
> ---
>  drivers/hid/hid-lenovo-go-s.c | 3 ---
>  1 file changed, 3 deletions(-)
>
> diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c
> index 0ef98ba68d86..a24737170f83 100644
> --- a/drivers/hid/hid-lenovo-go-s.c
> +++ b/drivers/hid/hid-lenovo-go-s.c
> @@ -504,9 +504,6 @@ static ssize_t gamepad_property_store(struct device *dev,
>                 ret = kstrtou8(buf, 10, &val);
>                 if (ret)
>                         return ret;
> -
> -               if (val < 0 || val > 255)
> -                       return -EINVAL;
>                 break;
>         case FEATURE_IMU_ENABLE:
>                 ret = sysfs_match_string(feature_enabled_text, buf);
> --
> 2.53.0
>

Reviewed-by: Derek J. Clark <derekjohn.clark@gmail.com>

^ permalink raw reply

* Re: [PATCH 1/3] HID: hid-lenovo-go-s: Fix signedness bug
From: Derek John Clark @ 2026-03-06  5:57 UTC (permalink / raw)
  To: Ethan Tidmore
  Cc: Mark Pearson, Jiri Kosina, Benjamin Tissoires, Mario Limonciello,
	linux-input, linux-kernel
In-Reply-To: <20260227205444.1083103-2-ethantidmore06@gmail.com>

On Fri, Feb 27, 2026 at 12:55 PM Ethan Tidmore <ethantidmore06@gmail.com> wrote:
>
> The function get_endpoint_address() returns type u8 but in its error
> path returns -ENODEV. Also, every variable that is assigned from this
> function is type int.
>
> Change return type to int from u8.
>
> Detected by Smatch:
> drivers/hid/hid-lenovo-go-s.c:391 get_endpoint_address() warn:
> signedness bug returning '(-19)'
>
> Fixes: 4325fdab5dbbf ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Series HID Driver")
> Signed-off-by: Ethan Tidmore <ethantidmore06@gmail.com>
> ---
>  drivers/hid/hid-lenovo-go-s.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c
> index cacc5bd5ed2b..0ef98ba68d86 100644
> --- a/drivers/hid/hid-lenovo-go-s.c
> +++ b/drivers/hid/hid-lenovo-go-s.c
> @@ -377,7 +377,7 @@ static int hid_gos_set_event_return(struct command_report *cmd_rep)
>         return 0;
>  }
>
> -static u8 get_endpoint_address(struct hid_device *hdev)
> +static int get_endpoint_address(struct hid_device *hdev)
>  {
>         struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
>         struct usb_host_endpoint *ep;
> --
> 2.53.0
>
Hmm, odd that I did this correctly in the Go driver.
Thanks.

Reviewed-by: Derek J. Clark <derekjohn.clark@gmail.com>

^ permalink raw reply

* Re: [PATCH 3/9] dt-bindings: input: mtk-pmic-keys: add MT6392 binding definition
From: Rob Herring (Arm) @ 2026-03-06  0:29 UTC (permalink / raw)
  To: Luca Leonardo Scorcia
  Cc: Louis-Alexis Eyraud, AngeloGioacchino Del Regno, linux-input,
	Matthias Brugger, Sen Chu, Liam Girdwood, Sean Wang,
	Alexandre Belloni, Julien Massot, linux-arm-kernel, Eddie Huang,
	linux-kernel, Conor Dooley, Gary Bisson, Lee Jones,
	Krzysztof Kozlowski, Fabien Parent, Val Packett, Macpaul Lin,
	linux-rtc, devicetree, Dmitry Torokhov, linux-mediatek,
	Mark Brown, linux-pm, Chen Zhong
In-Reply-To: <056cbc09fcbb4a2845cece69209a2a564d993ac5.1771865015.git.l.scorcia@gmail.com>


On Mon, 23 Feb 2026 17:12:42 +0000, Luca Leonardo Scorcia wrote:
> From: Fabien Parent <parent.f@gmail.com>
> 
> Add the binding documentation of the mtk-pmic-keys for the MT6392 PMICs.
> 
> Signed-off-by: Fabien Parent <parent.f@gmail.com>
> Signed-off-by: Val Packett <val@packett.cool>
> Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
> ---
>  Documentation/devicetree/bindings/input/mediatek,pmic-keys.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring (Arm) <robh@kernel.org>


^ permalink raw reply

* Re: [PATCH 2/9] dt-bindings: regulator: add support for MT6392
From: Rob Herring (Arm) @ 2026-03-06  0:28 UTC (permalink / raw)
  To: Luca Leonardo Scorcia
  Cc: Mark Brown, Chen Zhong, Macpaul Lin, linux-pm,
	Krzysztof Kozlowski, Lee Jones, linux-kernel, Dmitry Torokhov,
	Louis-Alexis Eyraud, devicetree, linux-mediatek, Julien Massot,
	Liam Girdwood, Alexandre Belloni, Fabien Parent, linux-input,
	linux-rtc, Matthias Brugger, Val Packett, Sen Chu, Conor Dooley,
	linux-arm-kernel, AngeloGioacchino Del Regno, Gary Bisson,
	Eddie Huang, Sean Wang
In-Reply-To: <b7664f4d9a7b038b0603b6bba79cfab4e18cbdd6.1771865015.git.l.scorcia@gmail.com>


On Mon, 23 Feb 2026 17:12:41 +0000, Luca Leonardo Scorcia wrote:
> From: Fabien Parent <parent.f@gmail.com>
> 
> Add binding documentation of the regulator for MT6392 SoCs.
> 
> Signed-off-by: Fabien Parent <parent.f@gmail.com>
> Signed-off-by: Val Packett <val@packett.cool>
> Signed-off-by: Luca Leonardo Scorcia <l.scorcia@gmail.com>
> ---
>  Documentation/devicetree/bindings/mfd/mediatek,mt6397.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring (Arm) <robh@kernel.org>


^ permalink raw reply

* Re: [PATCH v3 7/9] dt-bindings: mfd: motorola-cpcap: document Mapphone and Mot CPCAP
From: Rob Herring (Arm) @ 2026-03-05 23:58 UTC (permalink / raw)
  To: Svyatoslav Ryhel
  Cc: Liam Girdwood, Conor Dooley, Pavel Machek, David Lechner,
	linux-leds, Tony Lindgren, linux-input, Mark Brown, Lee Jones,
	Dmitry Torokhov, linux-kernel, Krzysztof Kozlowski, devicetree
In-Reply-To: <20260223063858.12208-8-clamor95@gmail.com>


On Mon, 23 Feb 2026 08:38:56 +0200, Svyatoslav Ryhel wrote:
> Add compatibles for Mapphone and Mot CPCAP subdevice compositions. Both
> variations cannot use st,6556002 fallback since they may be based on
> different controllers.
> 
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
>  .../devicetree/bindings/mfd/motorola,cpcap.yaml       | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


^ permalink raw reply

* Re: [PATCH v3 6/9] dt-bindings: mfd: motorola-cpcap: convert to DT schema
From: Rob Herring (Arm) @ 2026-03-05 23:57 UTC (permalink / raw)
  To: Svyatoslav Ryhel
  Cc: David Lechner, Liam Girdwood, Dmitry Torokhov, devicetree,
	Pavel Machek, Conor Dooley, Lee Jones, linux-input,
	Krzysztof Kozlowski, Mark Brown, linux-leds, linux-kernel,
	Tony Lindgren
In-Reply-To: <20260223063858.12208-7-clamor95@gmail.com>


On Mon, 23 Feb 2026 08:38:55 +0200, Svyatoslav Ryhel wrote:
> Convert devicetree bindings for the Motorola CPCAP MFD from TXT to YAML.
> 
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
>  .../bindings/mfd/motorola,cpcap.yaml          | 411 ++++++++++++++++++
>  .../bindings/mfd/motorola-cpcap.txt           |  78 ----
>  2 files changed, 411 insertions(+), 78 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
>  delete mode 100644 Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


^ permalink raw reply

* Re: [PATCH 2/3] dt-bindings: mfd: convert fsl-imx25-tsadc.txt to yaml format
From: Rob Herring (Arm) @ 2026-03-05 23:44 UTC (permalink / raw)
  To: Frank Li
  Cc: Sascha Hauer, linux-arm-kernel, devicetree, Dmitry Torokhov, imx,
	Conor Dooley, Krzysztof Kozlowski, Pengutronix Kernel Team,
	Fabio Estevam, linux-input, linux-kernel, Lee Jones
In-Reply-To: <20260211-yaml_mfd-v1-2-05cb48bc6f09@nxp.com>


On Wed, 11 Feb 2026 16:41:05 -0500, Frank Li wrote:
> Convert fsl-imx25-tsadc.txt to yaml format.
> 
> Addtional changes:
> - Add ranges.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
>  .../devicetree/bindings/mfd/fsl,imx25-tsadc.yaml   | 97 ++++++++++++++++++++++
>  .../devicetree/bindings/mfd/fsl-imx25-tsadc.txt    | 47 -----------
>  2 files changed, 97 insertions(+), 47 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


^ permalink raw reply

* Re: [PATCH 1/3] dt-bindings: input: touchscreen: convert fsl-mx25-tcq.txt to yaml
From: Rob Herring (Arm) @ 2026-03-05 23:43 UTC (permalink / raw)
  To: Frank Li
  Cc: Dmitry Torokhov, Fabio Estevam, Lee Jones, linux-input,
	Sascha Hauer, devicetree, imx, Krzysztof Kozlowski,
	Pengutronix Kernel Team, Conor Dooley, linux-kernel,
	linux-arm-kernel
In-Reply-To: <20260211-yaml_mfd-v1-1-05cb48bc6f09@nxp.com>


On Wed, 11 Feb 2026 16:41:04 -0500, Frank Li wrote:
> Convert fsl-mx25-tcq.txt to yaml.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
>  .../bindings/input/touchscreen/fsl,imx25-tcq.yaml  | 69 ++++++++++++++++++++++
>  .../bindings/input/touchscreen/fsl-mx25-tcq.txt    | 34 -----------
>  2 files changed, 69 insertions(+), 34 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


^ permalink raw reply

* [PATCH 1/1] dt-bindings: input: touchscreen: edt-ft5x06: add edt,edt-ft5x06 for legacy platforms
From: Frank Li @ 2026-03-05 22:37 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Yedaya Katsman, Frank Li, Joel Selvaraj, Jens Reidel,
	open list:INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN)...,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list
  Cc: imx

The compatible string "edt,edt-ft5x06" has been used for more than a decade
on older platforms such as i.MX6 and OMAP. However, it is currently missing
from the binding documentation.

Add it to the binding to document existing usage and fix the following
CHECK_DTBS warnings.
  arch/arm/boot/dts/nxp/imx/imx6dl-nit6xlite.dtb: /soc/bus@2100000/i2c@21a8000/touchscreen@38: failed to match any schema with compatible: ['edt,edt-ft5x06'

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 .../devicetree/bindings/input/touchscreen/edt-ft5x06.yaml        | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
index 6f90522de8c0a..213451f823369 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.yaml
@@ -38,6 +38,7 @@ properties:
       - edt,edt-ft5306
       - edt,edt-ft5406
       - edt,edt-ft5506
+      - edt,edt-ft5x06 # Deprecated, not use for new platform.
       - evervision,ev-ft5726
       - focaltech,ft3518
       - focaltech,ft5426
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v4 0/4] input: add GPIO-based charlieplex keypad
From: Hugo Villeneuve @ 2026-03-05 19:23 UTC (permalink / raw)
  To: Hugo Villeneuve
  Cc: robin, andy, geert, robh, krzk+dt, conor+dt, dmitry.torokhov,
	hvilleneuve, mkorpershoek, matthias.bgg,
	angelogioacchino.delregno, lee, alexander.sverdlin, marek.vasut,
	akurz, devicetree, linux-kernel, linux-input, linux-arm-kernel,
	linux-mediatek
In-Reply-To: <20260305192101.2125660-1-hugo@hugovil.com>

On Thu,  5 Mar 2026 14:20:46 -0500
Hugo Villeneuve <hugo@hugovil.com> wrote:

> From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
> 
> Hello,
> this patch series add a new GPIO charlieplex keypad driver.
> 
> The first two patches simply commonize two properties that are present in
> a few bindings, so that the actual patches for the charlieplex keypad driver
> can reuse them instead of also redefining them.
> 
> I have tested the driver on a custom board with a Solidrun RZ/G2LC SOM
> with three charlieplex keyboards, all connected thru a single PCAL6416 I2C GPIO
> expander.
> 
> Link: [v1] https://lore.kernel.org/all/20260203155023.536103-1-hugo@hugovil.com/
> Link: [v2] https://lore.kernel.org/all/20260213171431.2228814-1-hugo@hugovil.com/
> Link: [v3] https://lore.kernel.org/all/20260225155409.612478-1-hugo@hugovil.com/
> 
> Changes for v4:
> - Fix indentation in comments (Andy)
> - Add missing includes (Andy)
> - Remove OF dependency (Andy/Dmitry)
> - Uniformize return code variables to "err" (Andy/Dmitry)
> - Change signed iterator to unsigned and move within loop (Andy)
> - Remove unused platform_set_drvdata() (Andy)
> - Fixed typo in cover letter PCAL6416 (Geert)
> - Changed name in bindings example (Geert)
> - Added pull resistors to bindings doc and example (Geert)
> - Add debounce-delay-ms common property
> - Add settling-time-us common property

Please ignore the last two lines that were already mentioned for V3.

Hugo.


> 
> Changes for v3:
> - Add ASCII diagram in bindings, and reference to it in example
> - Reorder properties alphabetically
> - Add patch to define common input settling-time-us property
> - Add patch to define common input debounce-delay-ms property
> 
> Changes for v2:
> - Fix yamllint error for example
> - Remove unused debug variable (nkeys)
> - Remove support for custom linux,no-autorepeat DT property
> - Remove support for custom gpio-activelow DT property
> 
> Thank you.
> 
> Hugo Villeneuve (4):
>   dt-bindings: input: add debounce-delay-ms common property
>   dt-bindings: input: add settling-time-us common property
>   dt-bindings: input: add GPIO charlieplex keypad
>   Input: charlieplex_keypad: add GPIO charlieplex keypad
> 
>  .../bindings/auxdisplay/holtek,ht16k33.yaml   |   5 +-
>  .../bindings/input/cirrus,ep9307-keypad.yaml  |   7 +-
>  .../input/gpio-charlieplex-keypad.yaml        | 108 +++++++++
>  .../bindings/input/gpio-matrix-keypad.yaml    |   5 +-
>  .../devicetree/bindings/input/input.yaml      |  16 ++
>  .../input/mediatek,mt6779-keypad.yaml         |   1 +
>  .../devicetree/bindings/mfd/fsl,mc13xxx.yaml  |   2 -
>  MAINTAINERS                                   |   7 +
>  drivers/input/keyboard/Kconfig                |  14 ++
>  drivers/input/keyboard/Makefile               |   1 +
>  drivers/input/keyboard/charlieplex_keypad.c   | 214 ++++++++++++++++++
>  11 files changed, 368 insertions(+), 12 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/input/gpio-charlieplex-keypad.yaml
>  create mode 100644 drivers/input/keyboard/charlieplex_keypad.c
> 
> 
> base-commit: 3bf5404fc93825ddde89992acad095a297ed9a31
> -- 
> 2.47.3
> 
> 


-- 
Hugo Villeneuve

^ permalink raw reply

* [PATCH v4 4/4] Input: charlieplex_keypad: add GPIO charlieplex keypad
From: Hugo Villeneuve @ 2026-03-05 19:20 UTC (permalink / raw)
  To: robin, andy, geert, robh, krzk+dt, conor+dt, dmitry.torokhov,
	hvilleneuve, mkorpershoek, matthias.bgg,
	angelogioacchino.delregno, lee, alexander.sverdlin, marek.vasut,
	akurz
  Cc: devicetree, linux-kernel, linux-input, linux-arm-kernel,
	linux-mediatek, hugo
In-Reply-To: <20260305192101.2125660-1-hugo@hugovil.com>

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

Add support for GPIO-based charlieplex keypad, allowing to control
N^2-N keys using N GPIO lines.

Reuse matrix keypad keymap to simplify, even if there is no concept
of rows and columns in this type of keyboard.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 MAINTAINERS                                 |   7 +
 drivers/input/keyboard/Kconfig              |  14 ++
 drivers/input/keyboard/Makefile             |   1 +
 drivers/input/keyboard/charlieplex_keypad.c | 214 ++++++++++++++++++++
 4 files changed, 236 insertions(+)
 create mode 100644 drivers/input/keyboard/charlieplex_keypad.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 9ed6d11a77466..0b2d71f32b400 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5765,6 +5765,13 @@ S:	Maintained
 F:	Documentation/hwmon/powerz.rst
 F:	drivers/hwmon/powerz.c
 
+CHARLIEPLEX KEYPAD DRIVER
+M:	Hugo Villeneuve <hvilleneuve@dimonoff.com>
+S:	Supported
+W:	http://www.mosaic-industries.com/embedded-systems/microcontroller-projects/electronic-circuits/matrix-keypad-scan-decode
+F:	Documentation/devicetree/bindings/input/gpio-charlieplex-keypad.yaml
+F:	drivers/input/keyboard/charlieplex_keypad.c
+
 CHECKPATCH
 M:	Andy Whitcroft <apw@canonical.com>
 M:	Joe Perches <joe@perches.com>
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 2ff4fef322c24..ae54b4b7e2d8a 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -289,6 +289,20 @@ config KEYBOARD_MATRIX
 	  To compile this driver as a module, choose M here: the
 	  module will be called matrix_keypad.
 
+config KEYBOARD_CHARLIEPLEX
+	tristate "GPIO driven chearlieplex keypad support"
+	depends on GPIOLIB || COMPILE_TEST
+	select INPUT_MATRIXKMAP
+	help
+	  Enable support for GPIO driven charlieplex keypad. A charlieplex
+	  keypad allows to use fewer GPIO lines to interface to key switches.
+	  For example, an N lines charlieplex keypad can be used to interface
+	  to N^2-N different key switches. However, this type of keypad
+	  cannot detect more than one key press at a time.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called charlieplex_keypad.
+
 config KEYBOARD_HIL_OLD
 	tristate "HP HIL keyboard support (simple driver)"
 	depends on GSC || HP300
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 2d906e14f3e27..40b5cf5d374d2 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_KEYBOARD_LOCOMO)		+= locomokbd.o
 obj-$(CONFIG_KEYBOARD_LPC32XX)		+= lpc32xx-keys.o
 obj-$(CONFIG_KEYBOARD_MAPLE)		+= maple_keyb.o
 obj-$(CONFIG_KEYBOARD_MATRIX)		+= matrix_keypad.o
+obj-$(CONFIG_KEYBOARD_CHARLIEPLEX)	+= charlieplex_keypad.o
 obj-$(CONFIG_KEYBOARD_MAX7359)		+= max7359_keypad.o
 obj-$(CONFIG_KEYBOARD_MAX7360)		+= max7360-keypad.o
 obj-$(CONFIG_KEYBOARD_MPR121)		+= mpr121_touchkey.o
diff --git a/drivers/input/keyboard/charlieplex_keypad.c b/drivers/input/keyboard/charlieplex_keypad.c
new file mode 100644
index 0000000000000..53d6060e83fe9
--- /dev/null
+++ b/drivers/input/keyboard/charlieplex_keypad.c
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * GPIO driven charlieplex keypad driver
+ *
+ * Copyright (c) 2025 Hugo Villeneuve <hvilleneuve@dimonoff.com>
+ *
+ * Based on matrix_keyboard.c
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/dev_printk.h>
+#include <linux/device/devres.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/types.h>
+
+struct charlieplex_keypad {
+	struct input_dev *input_dev;
+	struct gpio_descs *line_gpios;
+	unsigned int nlines;
+	unsigned int settling_time_us;
+	unsigned int debounce_threshold;
+	unsigned int debounce_count;
+	int debounce_code;
+	int current_code;
+};
+
+static void charlieplex_keypad_report_key(struct input_dev *input)
+{
+	struct charlieplex_keypad *keypad = input_get_drvdata(input);
+	const unsigned short *keycodes = input->keycode;
+
+	if (keypad->current_code > 0) {
+		input_event(input, EV_MSC, MSC_SCAN, keypad->current_code);
+		input_report_key(input, keycodes[keypad->current_code], 0);
+	}
+
+	if (keypad->debounce_code) {
+		input_event(input, EV_MSC, MSC_SCAN, keypad->debounce_code);
+		input_report_key(input, keycodes[keypad->debounce_code], 1);
+	}
+
+	input_sync(input);
+	keypad->current_code = keypad->debounce_code;
+}
+
+static void charlieplex_keypad_check_switch_change(struct input_dev *input,
+						   int code)
+{
+	struct charlieplex_keypad *keypad = input_get_drvdata(input);
+
+	if (code != keypad->debounce_code) {
+		keypad->debounce_count = 0;
+		keypad->debounce_code = code;
+	} else if (keypad->debounce_count < keypad->debounce_threshold) {
+		keypad->debounce_count++;
+
+		if (keypad->debounce_count >= keypad->debounce_threshold &&
+		    keypad->debounce_code != keypad->current_code)
+			charlieplex_keypad_report_key(input);
+	}
+}
+
+static void charlieplex_keypad_poll(struct input_dev *input)
+{
+	struct charlieplex_keypad *keypad = input_get_drvdata(input);
+	int oline;
+	int code;
+
+	for (code = 0, oline = 0; oline < keypad->nlines; oline++) {
+		DECLARE_BITMAP(values, MATRIX_MAX_ROWS);
+		int iline;
+		int err;
+
+		/* Activate only one line as output at a time. */
+		gpiod_direction_output(keypad->line_gpios->desc[oline], 1);
+
+		if (keypad->settling_time_us)
+			fsleep(keypad->settling_time_us);
+
+		/* Read input on all other lines. */
+		err = gpiod_get_array_value_cansleep(keypad->line_gpios->ndescs,
+						     keypad->line_gpios->desc,
+						     keypad->line_gpios->info, values);
+		if (err)
+			return;
+
+		for (iline = 0; iline < keypad->nlines; iline++) {
+			if (iline == oline)
+				continue; /* Do not read active output line. */
+
+			/* Check if GPIO is asserted. */
+			if (test_bit(iline, values)) {
+				code = MATRIX_SCAN_CODE(oline, iline,
+							get_count_order(keypad->nlines));
+				/*
+				 * Exit loop immediately since we cannot detect
+				 * more than one key press at a time.
+				 */
+				break;
+			}
+		}
+
+		gpiod_direction_input(keypad->line_gpios->desc[oline]);
+
+		if (code)
+			break;
+	}
+
+	charlieplex_keypad_check_switch_change(input, code);
+}
+
+static int charlieplex_keypad_init_gpio(struct platform_device *pdev,
+					struct charlieplex_keypad *keypad)
+{
+	keypad->line_gpios = devm_gpiod_get_array(&pdev->dev, "line", GPIOD_IN);
+	if (IS_ERR(keypad->line_gpios))
+		return PTR_ERR(keypad->line_gpios);
+
+	keypad->nlines = keypad->line_gpios->ndescs;
+
+	if (keypad->nlines > MATRIX_MAX_ROWS)
+		return -EINVAL;
+
+	for (unsigned int i = 0; i < keypad->nlines; i++)
+		gpiod_set_consumer_name(keypad->line_gpios->desc[i], "charlieplex_kbd_line");
+
+	return 0;
+}
+
+static int charlieplex_keypad_probe(struct platform_device *pdev)
+{
+	struct charlieplex_keypad *keypad;
+	unsigned int debounce_interval_ms;
+	unsigned int poll_interval_ms;
+	struct input_dev *input_dev;
+	int err;
+
+	keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL);
+	if (!keypad)
+		return -ENOMEM;
+
+	input_dev = devm_input_allocate_device(&pdev->dev);
+	if (!input_dev)
+		return -ENOMEM;
+
+	keypad->input_dev = input_dev;
+
+	device_property_read_u32(&pdev->dev, "poll-interval", &poll_interval_ms);
+	device_property_read_u32(&pdev->dev, "debounce-delay-ms", &debounce_interval_ms);
+	device_property_read_u32(&pdev->dev, "settling-time-us", &keypad->settling_time_us);
+
+	keypad->current_code = -1;
+	keypad->debounce_code = -1;
+	keypad->debounce_threshold = DIV_ROUND_UP(debounce_interval_ms, poll_interval_ms);
+
+	err = charlieplex_keypad_init_gpio(pdev, keypad);
+	if (err)
+		return err;
+
+	input_dev->name		= pdev->name;
+	input_dev->id.bustype	= BUS_HOST;
+
+	err = matrix_keypad_build_keymap(NULL, NULL, keypad->nlines,
+					 keypad->nlines, NULL, input_dev);
+	if (err)
+		dev_err_probe(&pdev->dev, -ENOMEM, "failed to build keymap\n");
+
+	if (device_property_read_bool(&pdev->dev, "autorepeat"))
+		__set_bit(EV_REP, input_dev->evbit);
+
+	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+
+	err = input_setup_polling(input_dev, charlieplex_keypad_poll);
+	if (err)
+		dev_err_probe(&pdev->dev, err, "unable to set up polling\n");
+
+	input_set_poll_interval(input_dev, poll_interval_ms);
+
+	input_set_drvdata(input_dev, keypad);
+
+	err = input_register_device(keypad->input_dev);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static const struct of_device_id charlieplex_keypad_dt_match[] = {
+	{ .compatible = "gpio-charlieplex-keypad" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, charlieplex_keypad_dt_match);
+
+static struct platform_driver charlieplex_keypad_driver = {
+	.probe		= charlieplex_keypad_probe,
+	.driver		= {
+		.name	= "charlieplex-keypad",
+		.of_match_table = charlieplex_keypad_dt_match,
+	},
+};
+module_platform_driver(charlieplex_keypad_driver);
+
+MODULE_AUTHOR("Hugo Villeneuve <hvilleneuve@dimonoff.com>");
+MODULE_DESCRIPTION("GPIO driven charlieplex keypad driver");
+MODULE_LICENSE("GPL");
-- 
2.47.3


^ permalink raw reply related

* [PATCH v4 0/4] input: add GPIO-based charlieplex keypad
From: Hugo Villeneuve @ 2026-03-05 19:20 UTC (permalink / raw)
  To: robin, andy, geert, robh, krzk+dt, conor+dt, dmitry.torokhov,
	hvilleneuve, mkorpershoek, matthias.bgg,
	angelogioacchino.delregno, lee, alexander.sverdlin, marek.vasut,
	akurz
  Cc: devicetree, linux-kernel, linux-input, linux-arm-kernel,
	linux-mediatek, hugo

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

Hello,
this patch series add a new GPIO charlieplex keypad driver.

The first two patches simply commonize two properties that are present in
a few bindings, so that the actual patches for the charlieplex keypad driver
can reuse them instead of also redefining them.

I have tested the driver on a custom board with a Solidrun RZ/G2LC SOM
with three charlieplex keyboards, all connected thru a single PCAL6416 I2C GPIO
expander.

Link: [v1] https://lore.kernel.org/all/20260203155023.536103-1-hugo@hugovil.com/
Link: [v2] https://lore.kernel.org/all/20260213171431.2228814-1-hugo@hugovil.com/
Link: [v3] https://lore.kernel.org/all/20260225155409.612478-1-hugo@hugovil.com/

Changes for v4:
- Fix indentation in comments (Andy)
- Add missing includes (Andy)
- Remove OF dependency (Andy/Dmitry)
- Uniformize return code variables to "err" (Andy/Dmitry)
- Change signed iterator to unsigned and move within loop (Andy)
- Remove unused platform_set_drvdata() (Andy)
- Fixed typo in cover letter PCAL6416 (Geert)
- Changed name in bindings example (Geert)
- Added pull resistors to bindings doc and example (Geert)
- Add debounce-delay-ms common property
- Add settling-time-us common property

Changes for v3:
- Add ASCII diagram in bindings, and reference to it in example
- Reorder properties alphabetically
- Add patch to define common input settling-time-us property
- Add patch to define common input debounce-delay-ms property

Changes for v2:
- Fix yamllint error for example
- Remove unused debug variable (nkeys)
- Remove support for custom linux,no-autorepeat DT property
- Remove support for custom gpio-activelow DT property

Thank you.

Hugo Villeneuve (4):
  dt-bindings: input: add debounce-delay-ms common property
  dt-bindings: input: add settling-time-us common property
  dt-bindings: input: add GPIO charlieplex keypad
  Input: charlieplex_keypad: add GPIO charlieplex keypad

 .../bindings/auxdisplay/holtek,ht16k33.yaml   |   5 +-
 .../bindings/input/cirrus,ep9307-keypad.yaml  |   7 +-
 .../input/gpio-charlieplex-keypad.yaml        | 108 +++++++++
 .../bindings/input/gpio-matrix-keypad.yaml    |   5 +-
 .../devicetree/bindings/input/input.yaml      |  16 ++
 .../input/mediatek,mt6779-keypad.yaml         |   1 +
 .../devicetree/bindings/mfd/fsl,mc13xxx.yaml  |   2 -
 MAINTAINERS                                   |   7 +
 drivers/input/keyboard/Kconfig                |  14 ++
 drivers/input/keyboard/Makefile               |   1 +
 drivers/input/keyboard/charlieplex_keypad.c   | 214 ++++++++++++++++++
 11 files changed, 368 insertions(+), 12 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/input/gpio-charlieplex-keypad.yaml
 create mode 100644 drivers/input/keyboard/charlieplex_keypad.c


base-commit: 3bf5404fc93825ddde89992acad095a297ed9a31
-- 
2.47.3


^ permalink raw reply

* [PATCH v4 1/4] dt-bindings: input: add debounce-delay-ms common property
From: Hugo Villeneuve @ 2026-03-05 19:20 UTC (permalink / raw)
  To: robin, andy, geert, robh, krzk+dt, conor+dt, dmitry.torokhov,
	hvilleneuve, mkorpershoek, matthias.bgg,
	angelogioacchino.delregno, lee, alexander.sverdlin, marek.vasut,
	akurz
  Cc: devicetree, linux-kernel, linux-input, linux-arm-kernel,
	linux-mediatek, hugo
In-Reply-To: <20260305192101.2125660-1-hugo@hugovil.com>

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

A few bindings are already defining a debounce-delay-ms property, so
add it to the input binding to reduce redundant redefines.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 .../devicetree/bindings/auxdisplay/holtek,ht16k33.yaml    | 5 ++---
 .../devicetree/bindings/input/cirrus,ep9307-keypad.yaml   | 7 +++----
 .../devicetree/bindings/input/gpio-matrix-keypad.yaml     | 5 ++---
 Documentation/devicetree/bindings/input/input.yaml        | 8 ++++++++
 .../devicetree/bindings/input/mediatek,mt6779-keypad.yaml | 1 +
 Documentation/devicetree/bindings/mfd/fsl,mc13xxx.yaml    | 2 --
 6 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml b/Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml
index b90eec2077b4b..c46a2471f8b10 100644
--- a/Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml
+++ b/Documentation/devicetree/bindings/auxdisplay/holtek,ht16k33.yaml
@@ -10,6 +10,7 @@ maintainers:
   - Robin van der Gracht <robin@protonic.nl>
 
 allOf:
+  - $ref: /schemas/input/input.yaml#
   - $ref: /schemas/input/matrix-keymap.yaml#
 
 properties:
@@ -33,9 +34,7 @@ properties:
   interrupts:
     maxItems: 1
 
-  debounce-delay-ms:
-    maxItems: 1
-    description: Debouncing interval time in milliseconds
+  debounce-delay-ms: true
 
   linux,keymap: true
 
diff --git a/Documentation/devicetree/bindings/input/cirrus,ep9307-keypad.yaml b/Documentation/devicetree/bindings/input/cirrus,ep9307-keypad.yaml
index a0d2460c55ab6..25b8b29c87d70 100644
--- a/Documentation/devicetree/bindings/input/cirrus,ep9307-keypad.yaml
+++ b/Documentation/devicetree/bindings/input/cirrus,ep9307-keypad.yaml
@@ -10,6 +10,7 @@ maintainers:
   - Alexander Sverdlin <alexander.sverdlin@gmail.com>
 
 allOf:
+  - $ref: input.yaml#
   - $ref: /schemas/input/matrix-keymap.yaml#
 
 description:
@@ -37,10 +38,8 @@ properties:
   clocks:
     maxItems: 1
 
-  debounce-delay-ms:
-    description: |
-          Time in microseconds that key must be pressed or
-          released for state change interrupt to trigger.
+  # Time for state change interrupt to trigger
+  debounce-delay-ms: true
 
   cirrus,prescale:
     description: row/column counter pre-scaler load value
diff --git a/Documentation/devicetree/bindings/input/gpio-matrix-keypad.yaml b/Documentation/devicetree/bindings/input/gpio-matrix-keypad.yaml
index ebfff9e42a365..69df24a5ae701 100644
--- a/Documentation/devicetree/bindings/input/gpio-matrix-keypad.yaml
+++ b/Documentation/devicetree/bindings/input/gpio-matrix-keypad.yaml
@@ -18,6 +18,7 @@ description:
   report the event using GPIO interrupts to the cpu.
 
 allOf:
+  - $ref: input.yaml#
   - $ref: /schemas/input/matrix-keymap.yaml#
 
 properties:
@@ -46,9 +47,7 @@ properties:
       Force GPIO polarity to active low.
       In the absence of this property GPIOs are treated as active high.
 
-  debounce-delay-ms:
-    description: Debounce interval in milliseconds.
-    default: 0
+  debounce-delay-ms: true
 
   col-scan-delay-us:
     description:
diff --git a/Documentation/devicetree/bindings/input/input.yaml b/Documentation/devicetree/bindings/input/input.yaml
index 94f7942189e8c..502e0b7eb500a 100644
--- a/Documentation/devicetree/bindings/input/input.yaml
+++ b/Documentation/devicetree/bindings/input/input.yaml
@@ -14,6 +14,14 @@ properties:
     description: Enable autorepeat when key is pressed and held down.
     type: boolean
 
+  debounce-delay-ms:
+    description:
+      Debounce delay in milliseconds. This is the time during which the key
+      press or release signal must remain stable before it is considered valid.
+    minimum: 0
+    maximum: 999
+    default: 0
+
   linux,keycodes:
     description:
       Specifies an array of numeric keycode values to be used for reporting
diff --git a/Documentation/devicetree/bindings/input/mediatek,mt6779-keypad.yaml b/Documentation/devicetree/bindings/input/mediatek,mt6779-keypad.yaml
index e365413732e7b..914dd3283df33 100644
--- a/Documentation/devicetree/bindings/input/mediatek,mt6779-keypad.yaml
+++ b/Documentation/devicetree/bindings/input/mediatek,mt6779-keypad.yaml
@@ -10,6 +10,7 @@ maintainers:
   - Mattijs Korpershoek <mkorpershoek@kernel.org>
 
 allOf:
+  - $ref: input.yaml#
   - $ref: /schemas/input/matrix-keymap.yaml#
 
 description: |
diff --git a/Documentation/devicetree/bindings/mfd/fsl,mc13xxx.yaml b/Documentation/devicetree/bindings/mfd/fsl,mc13xxx.yaml
index d2886f2686a8d..542ba51144243 100644
--- a/Documentation/devicetree/bindings/mfd/fsl,mc13xxx.yaml
+++ b/Documentation/devicetree/bindings/mfd/fsl,mc13xxx.yaml
@@ -76,8 +76,6 @@ properties:
           debounce-delay-ms:
             enum: [0, 30, 150, 750]
             default: 30
-            description:
-              Sets the debouncing delay in milliseconds.
 
           active-low:
             description: Set active when pin is pulled low.
-- 
2.47.3


^ permalink raw reply related

* [PATCH v4 3/4] dt-bindings: input: add GPIO charlieplex keypad
From: Hugo Villeneuve @ 2026-03-05 19:20 UTC (permalink / raw)
  To: robin, andy, geert, robh, krzk+dt, conor+dt, dmitry.torokhov,
	hvilleneuve, mkorpershoek, matthias.bgg,
	angelogioacchino.delregno, lee, alexander.sverdlin, marek.vasut,
	akurz
  Cc: devicetree, linux-kernel, linux-input, linux-arm-kernel,
	linux-mediatek, hugo
In-Reply-To: <20260305192101.2125660-1-hugo@hugovil.com>

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

Add DT bindings for GPIO charlieplex keypad.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
 .../input/gpio-charlieplex-keypad.yaml        | 108 ++++++++++++++++++
 1 file changed, 108 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/gpio-charlieplex-keypad.yaml

diff --git a/Documentation/devicetree/bindings/input/gpio-charlieplex-keypad.yaml b/Documentation/devicetree/bindings/input/gpio-charlieplex-keypad.yaml
new file mode 100644
index 0000000000000..c085de6dab854
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/gpio-charlieplex-keypad.yaml
@@ -0,0 +1,108 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/input/gpio-charlieplex-keypad.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: GPIO charlieplex keypad
+
+maintainers:
+  - Hugo Villeneuve <hvilleneuve@dimonoff.com>
+
+description: |
+  The charlieplex keypad supports N^2)-N different key combinations (where N is
+  the number of I/O lines). Key presses and releases are detected by configuring
+  only one line as output at a time, and reading other line states. This process
+  is repeated for each line. Diodes are required to ensure current flows in only
+  one direction between any pair of pins, as well as pull-up or pull-down
+  resistors on all I/O lines.
+  This mechanism doesn't allow to detect simultaneous key presses.
+
+  Wiring example for 3 lines keyboard with 6 switches and 3 diodes (pull-up/down
+  resistors not shown but needed on L0, L1 and L2):
+
+  L0  --+---------------------+----------------------+
+        |                     |                      |
+  L1  -------+-----------+---------------------+     |
+        |    |           |    |                |     |
+  L2  -------------+----------------+-----+    |     |
+        |    |     |     |    |     |     |    |     |
+        |    |     |     |    |     |     |    |     |
+        |  S1 \  S2 \    |  S3 \  S4 \    |  S5 \  S6 \
+        |    |     |     |    |     |     |    |     |
+        |    +--+--+     |    +--+--+     |    +--+--+
+        |       |        |       |        |       |
+        |    D1 v        |    D2 v        |    D3 v
+        |       - (k)    |       - (k)    |       - (k)
+        |       |        |       |        |       |
+        +-------+        +-------+        +-------+
+
+  L: GPIO line
+  S: switch
+  D: diode (k indicates cathode)
+
+allOf:
+  - $ref: input.yaml#
+  - $ref: /schemas/input/matrix-keymap.yaml#
+
+properties:
+  compatible:
+    const: gpio-charlieplex-keypad
+
+  autorepeat: true
+
+  debounce-delay-ms:
+    default: 5
+
+  line-gpios:
+    description:
+      List of GPIOs used as lines. The gpio specifier for this property
+      depends on the gpio controller to which these lines are connected.
+
+  linux,keymap: true
+
+  poll-interval: true
+
+  settling-time-us: true
+
+  wakeup-source: true
+
+required:
+  - compatible
+  - line-gpios
+  - linux,keymap
+  - poll-interval
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/input/input.h>
+
+    keyboard {
+        compatible = "gpio-charlieplex-keypad";
+        debounce-delay-ms = <20>;
+        poll-interval = <5>;
+        settling-time-us = <2>;
+
+        line-gpios = <&gpio2 25 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)
+                      &gpio2 26 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)
+                      &gpio2 27 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>;
+
+        /* MATRIX_KEY(output, input, key-code) */
+        linux,keymap = <
+            /*
+             * According to wiring diagram above, if L1 is configured as
+             * output and HIGH, and we detect a HIGH level on input L0,
+             * then it means S1 is pressed: MATRIX_KEY(L1, L0, KEY...)
+             */
+            MATRIX_KEY(1, 0, KEY_F1) /* S1 */
+            MATRIX_KEY(2, 0, KEY_F2) /* S2 */
+            MATRIX_KEY(0, 1, KEY_F3) /* S3 */
+            MATRIX_KEY(2, 1, KEY_F4) /* S4 */
+            MATRIX_KEY(1, 2, KEY_F5) /* S5 */
+            MATRIX_KEY(0, 2, KEY_F6) /* S6 */
+        >;
+    };
-- 
2.47.3


^ permalink raw reply related

* [PATCH v4 2/4] dt-bindings: input: add settling-time-us common property
From: Hugo Villeneuve @ 2026-03-05 19:20 UTC (permalink / raw)
  To: robin, andy, geert, robh, krzk+dt, conor+dt, dmitry.torokhov,
	hvilleneuve, mkorpershoek, matthias.bgg,
	angelogioacchino.delregno, lee, alexander.sverdlin, marek.vasut,
	akurz
  Cc: devicetree, linux-kernel, linux-input, linux-arm-kernel,
	linux-mediatek, hugo
In-Reply-To: <20260305192101.2125660-1-hugo@hugovil.com>

From: Hugo Villeneuve <hvilleneuve@dimonoff.com>

Add common property that can be reused by other bindings.

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
---
Note: a similar property is used by gpio-matrix-keypad.yaml:
  col-scan-delay-us
---
 Documentation/devicetree/bindings/input/input.yaml | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/input.yaml b/Documentation/devicetree/bindings/input/input.yaml
index 502e0b7eb500a..14652d324e2ca 100644
--- a/Documentation/devicetree/bindings/input/input.yaml
+++ b/Documentation/devicetree/bindings/input/input.yaml
@@ -66,6 +66,14 @@ properties:
       reset automatically. Device with key pressed reset feature can specify
       this property.
 
+  settling-time-us:
+    description:
+      Delay, in microseconds, when activating an output line/col/row GPIO
+      before we can reliably read other input GPIOs that maybe affected by this
+      output. This can be the case for an output with a RC circuit that affects
+      ramp-up/down times.
+    default: 0
+
 dependencies:
   linux,input-type: [ "linux,code" ]
 
-- 
2.47.3


^ permalink raw reply related

* Re: [6.18.] ThinkPad T14 Gen 2 AMD (LEN2073) - Synaptics touchpad remains PS/2, intertouch=1 ineffective, lost sync events
From: Rácz Máté @ 2026-03-05 18:07 UTC (permalink / raw)
  To: linux-input, linux-i2c
In-Reply-To: <CANkKV91Zfp_Bn_koM=Tb5vHQbog2Ja72C819aL-49kQ6PWA_Ow@mail.gmail.com>

Hello,

I did some additional checks on my system with kernel 6.18.13-200.fc43.x86_64:

1. Kernel configuration (relevant parts):

$ grep -i "RMI\|SMBus" /boot/config-$(uname -r)
CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y
CONFIG_RMI4_CORE=m
CONFIG_RMI4_I2C=m
CONFIG_RMI4_SMB=m
CONFIG_HID_RMI=m
CONFIG_I2C_HID=y
CONFIG_I2C_HID_ACPI=m

2. dmesg output (filtered):

[ 1.615300] psmouse serio1: synaptics: Trying to set up SMBus access
[ 1.618151] psmouse serio1: synaptics: SMbus companion is not ready yet
[ 17.949336] psmouse serio1: TouchPad at isa0060/serio1/input0 lost
sync at byte 1
[ 17.962506] psmouse serio1: issuing reconnect request
(repeats multiple times)

3. libinput reports:

$ sudo libinput list-devices | grep -i SynPS
Device: SynPS/2 Synaptics TouchPad

Interpretation:

- The touchpad is recognized as a SynPS/2 device, i.e., fallback PS/2 mode.
- SMBus/RMI4 driver stack does not get loaded, despite the kernel
config enabling modules.
- The "SMBus companion is not ready yet" messages indicate that
psmouse attempts SMBus access but cannot reach the device.
- I2C controllers are functional, yet the touchpad does not enumerate
as an I2C HID device.

Workarounds:

- Using psmouse.proto=imps avoids lost sync events, confirming
fallback to generic PS/2 handling.

Observation regarding previous reports:

- Unlike the 2021 report on ThinkPad P14s Gen 2 (AMD), I do not see
any "bad SMBus base address" messages in dmesg.
- The kernel attempts SMBus access, but fails because the RMI4/hid-rmi
stack does not initialize. The device simply falls back to PS/2 mode.
- Therefore, this does not appear to be the same base address issue as
the earlier P14s case.

Conclusion:

- Behavior strongly suggests a missing DMI quirk or regression in the
SMBus detection logic in combination with i2c_piix4 on this Lenovo
ThinkPad T14 Gen 2 (AMD) with LEN2073 touchpad.
- This is reproducible on multiple 6.18.x kernel versions on Fedora 43
stock kernels.

I can provide full dmesg, libinput outputs, and acpidump if required.

Best regards,
Mate Racz

Rácz Máté <raczm0812@gmail.com> ezt írta (időpont: 2026. márc. 4., Sze, 16:02):
>
> This might be related to the earlier report from 2021:
>
> https://lore.kernel.org/linux-input/3d6f7f74-3214-4c03-b352-a2a0d27ea42b@amd.com/
>
> and a similar report from 2025:
>
> https://lore.kernel.org/linux-input/b2d0af40-876e-4a2d-99a2-236b583e9497@gmail.com/
>
> The 2021 report describes incorrect SMBus address detection with
> i2c_piix4 on ThinkPad P14s Gen 2 (AMD), resulting in RMI4/SMBus not
> functioning correctly and the device remaining in PS/2 mode.
>
> On my system (LEN2073), the behaviour appears very similar:
> - intertouch has no effect
> - "SMBus companion is not ready yet" in dmesg
> - device stays in PS/2 mode
>
> It seems possible that the same underlying piix4 SMBus detection
> issue is still present.

^ permalink raw reply

* [PATCH 2/2] arm: dts: renesas: r8a7740-armadillo800eva: Add wakeup-source to st1232
From: phucduc.bui @ 2026-03-05 11:35 UTC (permalink / raw)
  To: dmitry.torokhov, robh, krzk+dt, conor+dt, geert+renesas,
	magnus.damm
  Cc: javier.carrasco, hechtb, wsa+renesas, linux-input, devicetree,
	linux-renesas-soc, linux-kernel, phucduc.bui
In-Reply-To: <20260305113512.227269-1-phucduc.bui@gmail.com>

From: bui duc phuc <phucduc.bui@gmail.com>

Add the wakeup-source property to the ST1232 touchscreen node
in the device tree so that the touchscreen interrupt can wake
the system from suspend when the panel is touched.

Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
---
 arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts
index 04d24b6d8056..d47a6cc3e756 100644
--- a/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts
+++ b/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts
@@ -228,6 +228,7 @@ touchscreen@55 {
 		pinctrl-0 = <&st1232_pins>;
 		pinctrl-names = "default";
 		gpios = <&pfc 166 GPIO_ACTIVE_LOW>;
+		wakeup-source;
 	};
 };
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH 1/2] dt-bindings: input: touchscreen: sitronix,st1232: Add wakeup-source
From: phucduc.bui @ 2026-03-05 11:35 UTC (permalink / raw)
  To: dmitry.torokhov, robh, krzk+dt, conor+dt, geert+renesas,
	magnus.damm
  Cc: javier.carrasco, hechtb, wsa+renesas, linux-input, devicetree,
	linux-renesas-soc, linux-kernel, phucduc.bui
In-Reply-To: <20260305113512.227269-1-phucduc.bui@gmail.com>

From: bui duc phuc <phucduc.bui@gmail.com>

Document the 'wakeup-source' property for Sitronix ST1232 touchscreen
controllers to allow the device to wake the system from suspend.

Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
---
 .../bindings/input/touchscreen/sitronix,st1232.yaml          | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/touchscreen/sitronix,st1232.yaml b/Documentation/devicetree/bindings/input/touchscreen/sitronix,st1232.yaml
index 978afaa4fcef..672544e5a26e 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/sitronix,st1232.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/sitronix,st1232.yaml
@@ -32,6 +32,10 @@ properties:
     description: A phandle to the reset GPIO
     maxItems: 1
 
+  wakeup-source:
+    description: Device can be used as a wakeup source.
+    type: boolean
+
 required:
   - compatible
   - reg
@@ -51,6 +55,7 @@ examples:
                     reg = <0x55>;
                     interrupts = <2 0>;
                     gpios = <&gpio1 166 0>;
+                    wakeup-source;
 
                     touch-overlay {
                             segment-0 {
-- 
2.43.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox