Linux Input/HID development
 help / color / mirror / Atom feed
* Re: [PATCH AUTOSEL 7.0-5.10] HID: mcp2221: fix OOB write in mcp2221_raw_event()
From: sashiko-bot @ 2026-05-20 11:56 UTC (permalink / raw)
  To: Sasha Levin; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260520111944.3424570-25-sashal@kernel.org>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

New issues:
- [High] The patch introduces `mcp->rxbuf_size` to prevent Out-of-Bounds (OOB) writes but fails to initialize it in `mcp_smbus_xfer()` for block operations.

Pre-existing issues:
- [High] The `mcp->rxbuf` pointer is never cleared after an I2C/SMBus transfer completes or times out, leaving a dangling pointer that can be exploited.
- [High] The `mcp2221_raw_event()` handler ignores the `size` parameter provided by the HID subsystem, leading to out-of-bounds reads on the kernel heap.
- [High] A data race exists between the I2C transfer context and the HID raw event context, which accesses `rxbuf` state variables without synchronization.
--

commit 161d8d13687380796daedd1f35b98269619cd589
Author: Florian Pradines <florian.pradines@gmail.com>

HID: mcp2221: fix OOB write in mcp2221_raw_event()

mcp2221_raw_event() copies device-supplied data into mcp->rxbuf at offset
rxbuf_idx without verifying that the copy fits within the destination buffer.
A device responding with up to 60 bytes to a small I2C/SMBus read can overflow
this buffer. This patch adds an rxbuf_size field to struct mcp2221 and checks
rxbuf_idx + data[3] <= rxbuf_size before performing the copy.

> diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c
> index ef3b5c77c38e3..badd4958bc12c 100644
> --- a/drivers/hid/hid-mcp2221.c
> +++ b/drivers/hid/hid-mcp2221.c
[ ... ]
> @@ -323,12 +324,14 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp,
>  		mcp->txbuf[3] = (u8)(msg->addr << 1);
>  		total_len = msg->len;
>  		mcp->rxbuf = msg->buf;
> +		mcp->rxbuf_size = msg->len;
>  	} else {
>  		mcp->txbuf[1] = smbus_len;
>  		mcp->txbuf[2] = 0;
>  		mcp->txbuf[3] = (u8)(smbus_addr << 1);
>  		total_len = smbus_len;
>  		mcp->rxbuf = smbus_buf;
> +		mcp->rxbuf_size = smbus_len;

[Severity: High]
Does this overlook updating mcp->rxbuf_size for block operations in
mcp_smbus_xfer()?

In mcp_smbus_xfer(), mcp->rxbuf is manually assigned for block reads without
updating mcp->rxbuf_size:

drivers/hid/hid-mcp2221.c:mcp_smbus_xfer() {
...
	case I2C_SMBUS_BLOCK_DATA:
		if (read_write == I2C_SMBUS_READ) {
...
			mcp->rxbuf_idx = 0;
			mcp->rxbuf = data->block;
...
}

If rxbuf_size is 0, the new bounds check in mcp2221_raw_event() will always
fail, breaking legitimate SMBus block reads. If rxbuf_size holds a large stale
value from a prior transfer, the check might pass and still allow an overflow
on the data->block stack buffer.

>  	}
>  
>  	ret = mcp_send_data_req_status(mcp, mcp->txbuf, 4);
[ ... ]
> @@ -912,6 +915,10 @@ static int mcp2221_raw_event(struct hid_device *hdev,
>  					mcp->status = -EINVAL;
>  					break;
>  				}
> +				if (mcp->rxbuf_idx + data[3] > mcp->rxbuf_size) {
> +					mcp->status = -EINVAL;
> +					break;
> +				}

[Severity: High]
This is a pre-existing issue, but does mcp2221_raw_event() ignore the size
parameter provided by the HID subsystem?

The driver unconditionally accesses data bytes like data[3], and later copies
data[3] bytes starting from &data[4], without verifying the actual length of
the received HID report buffer. If a malicious device provides a small report
size, could reading or copying these bytes result in out-of-bounds reads on
the kernel heap?


[Severity: High]
This isn't a bug introduced by this patch, but is there a data race between
the I2C transfer context and the HID raw event context?

While mcp_i2c_smbus_read() and mcp_smbus_xfer() update mcp->rxbuf,
mcp->rxbuf_size, and mcp->rxbuf_idx while holding mcp->lock,
mcp2221_raw_event() runs asynchronously in the HID input report context and
accesses these variables without acquiring the lock.

If a stray or malicious USB report arrives concurrently with a new I2C read
request, could the state become desynchronized and lead to an out-of-bounds
write?

>  				buf = mcp->rxbuf;

[Severity: High]
This is a pre-existing issue, but is the mcp->rxbuf pointer left dangling
after a transfer completes or times out?

During transfers, mcp->rxbuf points to a caller-provided buffer which is often
allocated on the kernel stack. When a transfer times out, the stack frame is
popped, but mcp->rxbuf still points to the now-invalid stack address.

If a delayed or spurious USB report arrives later, could mcp2221_raw_event()
copy device-controlled data into this stale pointer and corrupt the kernel
stack?

>  				memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]);
>  				mcp->rxbuf_idx = mcp->rxbuf_idx + data[3];
>  				mcp->status = 0;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260520111944.3424570-25-sashal@kernel.org?part=1

^ permalink raw reply

* Re: [PATCH AUTOSEL 7.0-5.15] HID: ft260: validate i2c input report length
From: sashiko-bot @ 2026-05-20 11:57 UTC (permalink / raw)
  To: Sasha Levin; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260520111944.3424570-54-sashal@kernel.org>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

Pre-existing issues:
- [High] memcpy reads beyond the bounds of the statically sized array 'data[2]', which will trigger a FORTIFY_SOURCE panic for payloads > 2 bytes.
- [High] A race condition in the probe function leads to a NULL pointer dereference in `ft260_raw_event` if an input report is received early.
- [High] A race condition exists between the HID raw event handler and the I2C read timeout path, leading to a Use-After-Free or kernel stack corruption.
- [High] The probe function incorrectly returns 0 (success) when intentionally rejecting the UART interface, rendering it unusable.
--

commit 4ff190a6df13fab19cc5a93ba01ca6de278d20bd
Author: Michael Zaidman <michael.zaidman@gmail.com>

HID: ft260: validate i2c input report length

This commit adds checks to ft260_raw_event to prevent out-of-bounds reads
from malicious or malfunctioning devices. It rejects reports shorter than the
2-byte header and validates the length field against the actual HID report
capacity.

> diff --git a/drivers/hid/hid-ft260.c b/drivers/hid/hid-ft260.c
> index 333341e80b0ec..70e2eedb465af 100644
> --- a/drivers/hid/hid-ft260.c
> +++ b/drivers/hid/hid-ft260.c
> @@ -1068,10 +1068,22 @@ static int ft260_raw_event(struct hid_device *hdev, struct hid_report *report,
>  	struct ft260_device *dev = hid_get_drvdata(hdev);

[Severity: High]
This is a pre-existing issue, but can this result in a NULL pointer
dereference during device initialization?

If hid_hw_start() is called in ft260_probe() before hid_set_drvdata() is
initialized, the device might send an input report immediately (e.g., from
a pending interrupt). This would trigger ft260_raw_event(), leaving dev as
NULL and causing a panic when dev->read_buf is accessed below.

>  	struct ft260_i2c_input_report *xfer = (void *)data;
>  
> +	if (size < offsetof(struct ft260_i2c_input_report, data)) {
> +		hid_err(hdev, "short report %d\n", size);
> +		return -1;
> +	}
> +
>  	if (xfer->report >= FT260_I2C_REPORT_MIN &&
>  	    xfer->report <= FT260_I2C_REPORT_MAX) {
> -		ft260_dbg("i2c resp: rep %#02x len %d\n", xfer->report,
> -			  xfer->length);
> +		ft260_dbg("i2c resp: rep %#02x len %d size %d\n",
> +			  xfer->report, xfer->length, size);
> +
> +		if (xfer->length > size -
> +		    offsetof(struct ft260_i2c_input_report, data)) {
> +			hid_err(hdev, "report %#02x: length %d exceeds HID report size\n",
> +				xfer->report, xfer->length);
> +			return -1;
> +		}
>  
>  		if ((dev->read_buf == NULL) ||

[Severity: High]
This is a pre-existing issue, but does this check safely prevent a
use-after-free or stack corruption?

In ft260_i2c_read(), the driver blocks on wait_for_completion_timeout(). If a
timeout occurs, it sets dev->read_buf = NULL and returns, destroying the
caller-provided buffer which may be a stack frame.

If ft260_raw_event() checks dev->read_buf != NULL and is preempted while the
timeout path returns, wouldn't the subsequent memcpy() write hardware payload
data into freed memory or a popped stack frame?

>  		    (xfer->length > dev->read_len - dev->read_idx)) {


There is another pre-existing issue right below the diff in ft260_raw_event():

drivers/hid/hid-ft260.c:ft260_raw_event() {
	[ ... ]
		if ((dev->read_buf == NULL) ||
		    (xfer->length > dev->read_len - dev->read_idx)) {
			hid_err(hdev, "unexpected report %#02x, length %d\n",
				xfer->report, xfer->length);
			return -1;
		}

		memcpy(&dev->read_buf[dev->read_idx], &xfer->data,
		       xfer->length);
	[ ... ]
}

[Severity: High]
This isn't a bug introduced by this patch, but will this memcpy() trigger a
FORTIFY_SOURCE panic for payloads larger than 2 bytes?

The ft260_i2c_input_report structure defines the data payload as a fixed-size
array:

struct ft260_i2c_input_report {
	u8 report;
	u8 length;
	u8 data[2];
} __packed;

If xfer->length is greater than 2, the compiler statically knows the source
object size is exactly 2 bytes. Under CONFIG_FORTIFY_SOURCE=y, wouldn't this
trigger a mandatory kernel panic at runtime for a buffer overread? Could the
data field be changed to a flexible array member?


There is also a pre-existing issue in the probe function:

drivers/hid/hid-ft260.c:ft260_probe() {
	[ ... ]
	ret = ft260_is_interface_enabled(hdev);
	if (ret <= 0)
		goto err_hid_close;
	[ ... ]
err_hid_close:
	hid_hw_close(hdev);
err_hid_stop:
	hid_hw_stop(hdev);
	return ret;
}

[Severity: High]
This isn't a bug introduced by this patch, but does the probe function
incorrectly handle a rejected UART interface?

When ft260_is_interface_enabled() encounters the UART interface, it leaves
the return code as 0. The driver jumps to the error path, stops the hardware,
and returns 0 instead of an error code like -ENODEV.

Returning 0 informs the kernel driver core that hid-ft260 successfully bound
to the device interface. Doesn't this hijack the UART interface and leave it
in a disabled state, permanently preventing generic HID drivers (like
hid-generic) from claiming it?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260520111944.3424570-54-sashal@kernel.org?part=1

^ permalink raw reply

* Re: [PATCH AUTOSEL 7.0-5.10] HID: elan: Add support for ELAN SB974D touchpad
From: sashiko-bot @ 2026-05-20 12:24 UTC (permalink / raw)
  To: Sasha Levin; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260520111944.3424570-28-sashal@kernel.org>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] The driver fails to restore the device to multitouch mode after a system suspend/resume cycle.
- [High] In USB mode, if more than two fingers are active, the driver assigns identical coordinates to all fingers after the first one.
--

commit d5ae02b47586e24db0bca9c6a7b552b9fc7ef6e4
Author: Damien Dejean <damiendejean@google.com>

HID: elan: Add support for ELAN SB974D touchpad

This commit adds support for the ELAN SB974D touchpad by registering its
device ID in the supported devices list so the driver can parse its
vendor-specific formats.

> diff --git a/drivers/hid/hid-elan.c b/drivers/hid/hid-elan.c
> index 76d93fc48f6a2..0190ad567ce4d 100644
> --- a/drivers/hid/hid-elan.c
> +++ b/drivers/hid/hid-elan.c
> @@ -513,6 +513,7 @@ static const struct hid_device_id elan_devices[] = {
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER),
>  	  .driver_data = ELAN_HAS_LED },
>  	{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_TOSHIBA_CLICK_L9W) },
> +	{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_SB974D) },

[Severity: High]
This is a pre-existing issue, but does the driver fail to restore the device
to multitouch mode after a system suspend/resume cycle?

The ELAN touchpads require a vendor-specific initialization command
(elan_start_multitouch) to disable mouse emulation and enable multitouch
mode. This sequence is currently only executed during the initial elan_probe.

The hid_driver struct for elan_driver does not provide resume or reset_resume
callbacks. When the system suspends and the device loses power (both in USB
and I2C modes), it reverts to its default mouse emulation mode.

Upon resume, the core HID drivers call hid_driver_reset_resume(), which acts
as a no-op since the callback is missing and returns success without rebinding.

Does this leave the touchpad permanently in a degraded state after a
suspend/resume cycle?

[Severity: High]
This is a pre-existing issue, but in USB mode, if more than two fingers are
active, does the driver assign identical coordinates to all fingers after the
first one?

Looking at elan_usb_report_input(), when parsing the ELAN_MT_SECOND_FINGER
packet, the driver iterates over ELAN_MAX_FINGERS to dispatch slot updates
based on the active touch bits in prev_report[2].

For the first active bit found, it correctly uses coordinates from
prev_report + 3. For all subsequent active bits, the else branch executes:

    elan_report_mt_slot(drvdata, data + 1, i);

Because data + 1 is passed directly each time without incrementing any offset,
are the exact same coordinates and pressure values assigned to all fingers
after the first?

>  	{ }
>  };
>  MODULE_DEVICE_TABLE(hid, elan_devices);

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260520111944.3424570-28-sashal@kernel.org?part=1

^ permalink raw reply

* Re: [PATCH v3 0/4] HID: Proper fix for OOM in hid-core
From: Lee Jones @ 2026-05-20 12:46 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Greg Kroah-Hartman, Jiri Kosina, Filipe Laíns,
	Bastien Nocera, Ping Cheng, Jason Gerecke, Viresh Kumar,
	Johan Hovold, Alex Elder, Icenowy Zheng, linux-input,
	linux-kernel, greybus-dev, linux-staging, linux-usb, stable
In-Reply-To: <agxswzzCNMcxRN1n@beelink>

On Tue, 19 May 2026, Benjamin Tissoires wrote:

> On May 19 2026, Greg Kroah-Hartman wrote:
> > On Tue, May 19, 2026 at 02:46:13PM +0200, Benjamin Tissoires wrote:
> > > On May 19 2026, Lee Jones wrote:
> > > > On Tue, 12 May 2026, Lee Jones wrote:
> > > > 
> > > > > On Wed, 06 May 2026, Lee Jones wrote:
> > > > > 
> > > > > > On Mon, 04 May 2026, Benjamin Tissoires wrote:
> > > > > > 
> > > > > > > Commit 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing
> > > > > > > bogus memset()") enforced the provided data to be at least the size of
> > > > > > > the declared buffer in the report descriptor to prevent a buffer
> > > > > > > overflow.
> > > > > > > 
> > > > > > > We only had corner cases of malicious devices exposing the OOM because
> > > > > > > in most cases, the buffer provided by the transport layer needs to be
> > > > > > > allocated at probe time and is large enough to handle all the possible
> > > > > > > reports.
> > > > > > > 
> > > > > > > However, the patch from above, which enforces the spec a little bit more
> > > > > > > introduced both regressions for devices not following the spec (not
> > > > > > > necesserally malicious), but also a stream of errors for those devices.
> > > > > > > 
> > > > > > > Let's revert to the old behavior by giving more information to HID core
> > > > > > > to be able to decide whether it can or not memset the rest of the buffer
> > > > > > > to 0 and continue the processing.
> > > > > > > 
> > > > > > > Note that the first commit makes an API change, but the callers are
> > > > > > > relatively limited, so it should be fine on its own. The second patch
> > > > > > > can't really make the same kind of API change because we have too many
> > > > > > > callers in various subsystems. We can switch them one by one to the safe
> > > > > > > approach when needed.
> > > > > > > 
> > > > > > > The last 2 patches are small cleanups I initially put together with the
> > > > > > > 2 first patches, but they can be applied on their own and don't need to
> > > > > > > be pulled in stable like the first 2.
> > > > > > > 
> > > > > > > Cheers,
> > > > > > > Benjamin
> > > > > > > 
> > > > > > > Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
> > > > > > > ---
> > > > > > > Changes in v3:
> > > > > > > - fixed ghib -> ghid in greybus
> > > > > > > - fixed i386 size_t debug size reported by kernel-bot
> > > > > > > - Link to v2: https://lore.kernel.org/r/20260416-wip-fix-core-v2-0-be92570e5627@kernel.org
> > > > > > > 
> > > > > > > Changes in v2:
> > > > > > > - added a small blurb explaining the difference between the safe and the
> > > > > > >   non safe version of hid_safe_input_report
> > > > > > > - Link to v1: https://lore.kernel.org/r/20260415-wip-fix-core-v1-0-ed3c4c823175@kernel.org
> > > > > > > 
> > > > > > > ---
> > > > > > > Benjamin Tissoires (4):
> > > > > > >       HID: pass the buffer size to hid_report_raw_event
> > > > > > >       HID: core: introduce hid_safe_input_report()
> > > > > > >       HID: multitouch: use __free(kfree) to clean up temporary buffers
> > > > > > >       HID: wacom: use __free(kfree) to clean up temporary buffers
> > > > > > > 
> > > > > > >  drivers/hid/bpf/hid_bpf_dispatch.c |  6 ++--
> > > > > > >  drivers/hid/hid-core.c             | 67 ++++++++++++++++++++++++++++++--------
> > > > > > >  drivers/hid/hid-gfrm.c             |  4 +--
> > > > > > >  drivers/hid/hid-logitech-hidpp.c   |  2 +-
> > > > > > >  drivers/hid/hid-multitouch.c       | 18 ++++------
> > > > > > >  drivers/hid/hid-primax.c           |  2 +-
> > > > > > >  drivers/hid/hid-vivaldi-common.c   |  2 +-
> > > > > > >  drivers/hid/i2c-hid/i2c-hid-core.c |  7 ++--
> > > > > > >  drivers/hid/usbhid/hid-core.c      | 11 ++++---
> > > > > > >  drivers/hid/wacom_sys.c            | 46 +++++++++-----------------
> > > > > > >  drivers/staging/greybus/hid.c      |  2 +-
> > > > > > >  include/linux/hid.h                |  6 ++--
> > > > > > >  include/linux/hid_bpf.h            | 14 +++++---
> > > > > > >  13 files changed, 109 insertions(+), 78 deletions(-)
> > > > > > 
> > > > > > What's the plan for this set Benjamin? -rcs or -next?
> > > > > 
> > > > > Are there any updates on this set please?
> > > > > 
> > > > > FYI, this set is still important to us.
> > > > > 
> > > > > Ideally, if all is well, it would go into the -rcs for v7.1.
> > > > 
> > > > I'm still actively tracking these.
> > > > 
> > > > It looks like Mark has been reverting them from -next and I'm getting
> > > > complaints from the Stable folks that they are causing build errors.
> > > > 
> > > >   drivers/hid/hid-core.c: In function 'hid_safe_input_report':
> > > >   drivers/hid/hid-core.c:2195:16: error: too many arguments to function '__hid_input_report'
> > > >     2195 |         return __hid_input_report(hid, type, data, bufsize, size, interrupt, 0,
> > > > 
> > > > Are you folks still working on this set?
> > > 
> > > Well, everything is in Linus' tree:
> > > 
> > > not yet in a released rc (taken yesterday by Linus directly):
> > > 
> > > 4d3a2a466b8d HID: core: Fix size_t specifier in hid_report_raw_event()
> > > 
> > > Already in 7.1-rc4:
> > > 
> > > 206342541fc8 HID: core: introduce hid_safe_input_report()
> > > 2c85c61d1332 HID: pass the buffer size to hid_report_raw_event
> > > 
> > > Not sure why the patches don't apply to stable, but from an upstream
> > > subsystem point of view, everything is in order.
> > 
> > We dropped them from stable because of the build breakage :(
> > 
> 
> If that was just the i386 size_t issue, then it has been fixed in Linus'
> tree. Could you try retaking them? Please?

Thanks for following-up on this, I really appreciate it.

It looks as though these are no longer reverted from today's -next. \o/

-- 
Lee Jones

^ permalink raw reply

* Re: (subset) [PATCH 1/9] dt-bindings: mfd: mediatek: mt6397: Add rtc for MT6359
From: Lee Jones @ 2026-05-20 14:40 UTC (permalink / raw)
  To: Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Dmitry Torokhov, Chen Zhong,
	Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
	Louis-Alexis Eyraud
  Cc: kernel, linux-pm, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-input, linux-iio
In-Reply-To: <20260429-mediatek-genio-mt6365-cleanup-v1-1-6f43838be92f@collabora.com>

On Wed, 29 Apr 2026 11:44:14 +0200, Louis-Alexis Eyraud wrote:
> The rtc block of MT6359 PMIC is compatible with the one found in MT6358
> but this compatibility was never expressed in the dt-bindings, so add
> the missing compatible string for the rtc subnode.

Applied, thanks!

[1/9] dt-bindings: mfd: mediatek: mt6397: Add rtc for MT6359
      commit: 4edf75f835bad0b7e7ac022594b129f9dbf8698c

--
Lee Jones [李琼斯]


^ permalink raw reply

* Re: (subset) [PATCH 2/9] dt-bindings: mfd: mediatek: mt6397: Add MT6365 PMIC support
From: Lee Jones @ 2026-05-20 14:41 UTC (permalink / raw)
  To: Sen Chu, Sean Wang, Macpaul Lin, Lee Jones, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, Dmitry Torokhov, Chen Zhong,
	Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
	Louis-Alexis Eyraud
  Cc: kernel, linux-pm, devicetree, linux-kernel, linux-arm-kernel,
	linux-mediatek, linux-input, linux-iio
In-Reply-To: <20260429-mediatek-genio-mt6365-cleanup-v1-2-6f43838be92f@collabora.com>

On Wed, 29 Apr 2026 11:44:15 +0200, Louis-Alexis Eyraud wrote:
> MT6365 PMIC is compatible with MT6359, so add the compatible strings
> for the main and sub devices (regulator, rtc, audio codec).

Applied, thanks!

[2/9] dt-bindings: mfd: mediatek: mt6397: Add MT6365 PMIC support
      commit: 5a7c6466133eee4370995ad5ccf4c377011a381e

--
Lee Jones [李琼斯]


^ permalink raw reply

* Re: [PATCH v2] input: zforce_ts: Remove error print for devm_add_action_or_reset()
From: Waqar Hameed @ 2026-05-20 14:55 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: kernel, linux-input, linux-kernel
In-Reply-To: <pndfrbqj2u6.a.out@axis.com>

On Fri, Oct 10, 2025 at 15:36 +0200 Waqar Hameed <waqar.hameed@axis.com> wrote:

> On Tue, Aug 05, 2025 at 11:33 +0200 Waqar Hameed <waqar.hameed@axis.com> wrote:

[...]

> Friendly ping incoming!

Friendly ping 2 incoming!

This will be the last ping for the original patch [1]. I'll interpret
the silence as a NACK (though it would preferable to get an explicit
one...). All other patches in the previous patch series has been merged
[2].

[1] https://lore.kernel.org/lkml/pndbjoum7td.a.out@axis.com/
[2] https://lore.kernel.org/all/pnd7c0s6ji2.fsf@axis.com/

^ permalink raw reply

* Re: [PATCH v5 5/9] mfd: mt6397: Add support for MT6392 PMIC
From: Lee Jones @ 2026-05-20 15:00 UTC (permalink / raw)
  To: Luca Leonardo Scorcia
  Cc: linux-mediatek, Fabien Parent, Val Packett,
	AngeloGioacchino Del Regno, Dmitry Torokhov, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sen Chu, Sean Wang,
	Macpaul Lin, Matthias Brugger, Linus Walleij, Liam Girdwood,
	Mark Brown, Gary Bisson, Louis-Alexis Eyraud, Julien Massot,
	Akari Tsuyukusa, Chen Zhong, linux-input, devicetree,
	linux-kernel, linux-pm, linux-arm-kernel, linux-gpio
In-Reply-To: <20260420213529.1645560-6-l.scorcia@gmail.com>

On Mon, 20 Apr 2026, Luca Leonardo Scorcia wrote:

> From: Fabien Parent <parent.f@gmail.com>
> 
> Align the MT6397 PMIC driver to other MFD drivers by passing only an
> identifier through mt6397_of_match[*].data and add support for the MT6392
> PMIC.
> 
> 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>
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> ---
>  drivers/mfd/mt6397-core.c            | 118 +++++--
>  drivers/mfd/mt6397-irq.c             |   8 +
>  include/linux/mfd/mt6392/core.h      |  42 +++
>  include/linux/mfd/mt6392/registers.h | 487 +++++++++++++++++++++++++++
>  include/linux/mfd/mt6397/core.h      |   1 +
>  5 files changed, 630 insertions(+), 26 deletions(-)
>  create mode 100644 include/linux/mfd/mt6392/core.h
>  create mode 100644 include/linux/mfd/mt6392/registers.h
> 
> diff --git "a/drivers/mfd/mt6397-core.c" "b/drivers/mfd/mt6397-core.c"
> index 1bdacda9a933..5c5c24517c00 100644
> --- "a/drivers/mfd/mt6397-core.c"
> +++ "b/drivers/mfd/mt6397-core.c"
> @@ -18,6 +18,7 @@
>  #include <linux/mfd/mt6357/core.h>
>  #include <linux/mfd/mt6358/core.h>
>  #include <linux/mfd/mt6359/core.h>
> +#include <linux/mfd/mt6392/core.h>
>  #include <linux/mfd/mt6397/core.h>
>  #include <linux/mfd/mt6323/registers.h>
>  #include <linux/mfd/mt6328/registers.h>
> @@ -25,8 +26,20 @@
>  #include <linux/mfd/mt6357/registers.h>
>  #include <linux/mfd/mt6358/registers.h>
>  #include <linux/mfd/mt6359/registers.h>
> +#include <linux/mfd/mt6392/registers.h>
>  #include <linux/mfd/mt6397/registers.h>
>  
> +enum mfd_match_data {
> +	MATCH_DATA_MT6323 = 23,
> +	MATCH_DATA_MT6328 = 28,
> +	MATCH_DATA_MT6331 = 31,
> +	MATCH_DATA_MT6357 = 57,
> +	MATCH_DATA_MT6358 = 58,
> +	MATCH_DATA_MT6359 = 59,
> +	MATCH_DATA_MT6392 = 92,
> +	MATCH_DATA_MT6397 = 97,
> +};
> +
>  #define MT6323_RTC_BASE		0x8000
>  #define MT6323_RTC_SIZE		0x40
>  
> @@ -39,6 +52,9 @@
>  #define MT6358_RTC_BASE		0x0588
>  #define MT6358_RTC_SIZE		0x3c
>  
> +#define MT6392_RTC_BASE		0x8000
> +#define MT6392_RTC_SIZE		0x3e
> +
>  #define MT6397_RTC_BASE		0xe000
>  #define MT6397_RTC_SIZE		0x3e
>  
> @@ -65,6 +81,11 @@ static const struct resource mt6358_rtc_resources[] = {
>  	DEFINE_RES_IRQ(MT6358_IRQ_RTC),
>  };
>  
> +static const struct resource mt6392_rtc_resources[] = {
> +	DEFINE_RES_MEM(MT6392_RTC_BASE, MT6392_RTC_SIZE),
> +	DEFINE_RES_IRQ(MT6392_IRQ_RTC),
> +};
> +
>  static const struct resource mt6397_rtc_resources[] = {
>  	DEFINE_RES_MEM(MT6397_RTC_BASE, MT6397_RTC_SIZE),
>  	DEFINE_RES_IRQ(MT6397_IRQ_RTC),
> @@ -114,6 +135,11 @@ static const struct resource mt6331_keys_resources[] = {
>  	DEFINE_RES_IRQ_NAMED(MT6331_IRQ_STATUS_HOMEKEY, "homekey"),
>  };
>  
> +static const struct resource mt6392_keys_resources[] = {
> +	DEFINE_RES_IRQ_NAMED(MT6392_IRQ_PWRKEY, "powerkey"),
> +	DEFINE_RES_IRQ_NAMED(MT6392_IRQ_FCHRKEY, "homekey"),

What does FCHRKEY mean?  Is that a datasheet name?

> +};
> +
>  static const struct resource mt6397_keys_resources[] = {
>  	DEFINE_RES_IRQ_NAMED(MT6397_IRQ_PWRKEY, "powerkey"),
>  	DEFINE_RES_IRQ_NAMED(MT6397_IRQ_HOMEKEY, "homekey"),
> @@ -253,6 +279,25 @@ static const struct mfd_cell mt6359_devs[] = {
>  	},
>  };
>  
> +static const struct mfd_cell mt6392_devs[] = {
> +	{
> +		.name = "mt6392-rtc",
> +		.num_resources = ARRAY_SIZE(mt6392_rtc_resources),
> +		.resources = mt6392_rtc_resources,
> +		.of_compatible = "mediatek,mt6392-rtc",
> +	}, {
> +		.name = "mt6392-regulator",
> +	}, {
> +		.name = "mt6392-pinctrl",
> +		.of_compatible = "mediatek,mt6392-pinctrl",
> +	}, {
> +		.name = "mt6392-keys",
> +		.num_resources = ARRAY_SIZE(mt6392_keys_resources),
> +		.resources = mt6392_keys_resources,
> +		.of_compatible = "mediatek,mt6392-keys"
> +	},

MFD_CELL_*() for each.

> +};
> +
>  static const struct mfd_cell mt6397_devs[] = {
>  	{
>  		.name = "mt6397-rtc",
> @@ -335,6 +380,14 @@ static const struct chip_data mt6359_core = {
>  	.irq_init = mt6358_irq_init,
>  };
>  
> +static const struct chip_data mt6392_core = {
> +	.cid_addr = MT6392_CID,
> +	.cid_shift = 0,
> +	.cells = mt6392_devs,
> +	.cell_size = ARRAY_SIZE(mt6392_devs),
> +	.irq_init = mt6397_irq_init,
> +};
> +
>  static const struct chip_data mt6397_core = {
>  	.cid_addr = MT6397_CID,
>  	.cid_shift = 0,
> @@ -349,6 +402,7 @@ static int mt6397_probe(struct platform_device *pdev)
>  	unsigned int id = 0;
>  	struct mt6397_chip *pmic;
>  	const struct chip_data *pmic_core;
> +	enum mfd_match_data device_data;
>  
>  	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
>  	if (!pmic)
> @@ -364,9 +418,36 @@ static int mt6397_probe(struct platform_device *pdev)
>  	if (!pmic->regmap)
>  		return -ENODEV;
>  
> -	pmic_core = of_device_get_match_data(&pdev->dev);
> -	if (!pmic_core)
> +	device_data = (unsigned int)(uintptr_t)of_device_get_match_data(&pdev->dev);

We should be using generic match data variants now like device_get_match_data().

device_data should be chip_id or something.

> +	switch (device_data) {
> +	case MATCH_DATA_MT6323:

Pick some better nomenclature.

Ignore the fact that we're using these values in match data.

Do they have real differences, ideally ones which can be read from h/w?

> +		pmic_core = &mt6323_core;
> +		break;
> +	case MATCH_DATA_MT6328:
> +		pmic_core = &mt6328_core;
> +		break;
> +	case MATCH_DATA_MT6331:
> +		pmic_core = &mt6331_mt6332_core;
> +		break;
> +	case MATCH_DATA_MT6357:
> +		pmic_core = &mt6357_core;
> +		break;
> +	case MATCH_DATA_MT6358:
> +		pmic_core = &mt6358_core;
> +		break;
> +	case MATCH_DATA_MT6359:
> +		pmic_core = &mt6359_core;
> +		break;
> +	case MATCH_DATA_MT6392:
> +		pmic_core = &mt6392_core;
> +		break;
> +	case MATCH_DATA_MT6397:
> +		pmic_core = &mt6397_core;
> +		break;
> +	default:
> +		dev_err(&pdev->dev, "Unknown device match data %u\n", device_data);

The user doesn't care about your match data.

"Device not supported"

>  		return -ENODEV;
> +	}
>  
>  	ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id);
>  	if (ret) {
> @@ -398,30 +479,15 @@ static int mt6397_probe(struct platform_device *pdev)
>  }
>  
>  static const struct of_device_id mt6397_of_match[] = {
> -	{
> -		.compatible = "mediatek,mt6323",
> -		.data = &mt6323_core,
> -	}, {
> -		.compatible = "mediatek,mt6328",
> -		.data = &mt6328_core,
> -	}, {
> -		.compatible = "mediatek,mt6331",
> -		.data = &mt6331_mt6332_core,
> -	}, {
> -		.compatible = "mediatek,mt6357",
> -		.data = &mt6357_core,
> -	}, {
> -		.compatible = "mediatek,mt6358",
> -		.data = &mt6358_core,
> -	}, {
> -		.compatible = "mediatek,mt6359",
> -		.data = &mt6359_core,
> -	}, {
> -		.compatible = "mediatek,mt6397",
> -		.data = &mt6397_core,
> -	}, {
> -		/* sentinel */
> -	}
> +	{ .compatible = "mediatek,mt6323", .data = (void *)MATCH_DATA_MT6323, },
> +	{ .compatible = "mediatek,mt6328", .data = (void *)MATCH_DATA_MT6328, },
> +	{ .compatible = "mediatek,mt6331", .data = (void *)MATCH_DATA_MT6331, },
> +	{ .compatible = "mediatek,mt6357", .data = (void *)MATCH_DATA_MT6357, },
> +	{ .compatible = "mediatek,mt6358", .data = (void *)MATCH_DATA_MT6358, },
> +	{ .compatible = "mediatek,mt6359", .data = (void *)MATCH_DATA_MT6359, },
> +	{ .compatible = "mediatek,mt6392", .data = (void *)MATCH_DATA_MT6392, },
> +	{ .compatible = "mediatek,mt6397", .data = (void *)MATCH_DATA_MT6397, },

This is much better.

Maybe we can get rid of the bespoke 'struct chip_data' now?

> +	{ /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, mt6397_of_match);
>  
> diff --git "a/drivers/mfd/mt6397-irq.c" "b/drivers/mfd/mt6397-irq.c"
> index 5d2e5459f744..80ea5b92d232 100644
> --- "a/drivers/mfd/mt6397-irq.c"
> +++ "b/drivers/mfd/mt6397-irq.c"
> @@ -15,6 +15,8 @@
>  #include <linux/mfd/mt6328/registers.h>
>  #include <linux/mfd/mt6331/core.h>
>  #include <linux/mfd/mt6331/registers.h>
> +#include <linux/mfd/mt6392/core.h>
> +#include <linux/mfd/mt6392/registers.h>
>  #include <linux/mfd/mt6397/core.h>
>  #include <linux/mfd/mt6397/registers.h>
>  
> @@ -203,6 +205,12 @@ int mt6397_irq_init(struct mt6397_chip *chip)
>  		chip->int_status[0] = MT6397_INT_STATUS0;
>  		chip->int_status[1] = MT6397_INT_STATUS1;
>  		break;
> +	case MT6392_CHIP_ID:
> +		chip->int_con[0] = MT6392_INT_CON0;
> +		chip->int_con[1] = MT6392_INT_CON1;
> +		chip->int_status[0] = MT6392_INT_STATUS0;
> +		chip->int_status[1] = MT6392_INT_STATUS1;
> +		break;
>  
>  	default:
>  		dev_err(chip->dev, "unsupported chip: 0x%x\n", chip->chip_id);
> diff --git "a/include/linux/mfd/mt6392/core.h" "b/include/linux/mfd/mt6392/core.h"
> new file mode 100644
> index 000000000000..4780dab4da92
> --- /dev/null
> +++ "b/include/linux/mfd/mt6392/core.h"
> @@ -0,0 +1,42 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2020 MediaTek Inc.

This needs an update.

> + * Author: Chen Zhong <chen.zhong@mediatek.com>
> + */
> +
> +#ifndef __MFD_MT6392_CORE_H__
> +#define __MFD_MT6392_CORE_H__
> +
> +enum mt6392_irq_numbers {
> +	MT6392_IRQ_SPKL_AB = 0,
> +	MT6392_IRQ_SPKL,
> +	MT6392_IRQ_BAT_L,
> +	MT6392_IRQ_BAT_H,
> +	MT6392_IRQ_WATCHDOG,
> +	MT6392_IRQ_PWRKEY,
> +	MT6392_IRQ_THR_L,
> +	MT6392_IRQ_THR_H,
> +	MT6392_IRQ_VBATON_UNDET,
> +	MT6392_IRQ_BVALID_DET,
> +	MT6392_IRQ_CHRDET,
> +	MT6392_IRQ_OV,
> +	MT6392_IRQ_LDO = 16,
> +	MT6392_IRQ_FCHRKEY,
> +	MT6392_IRQ_RELEASE_PWRKEY,
> +	MT6392_IRQ_RELEASE_FCHRKEY,
> +	MT6392_IRQ_RTC,
> +	MT6392_IRQ_VPROC,
> +	MT6392_IRQ_VSYS,
> +	MT6392_IRQ_VCORE,
> +	MT6392_IRQ_TYPE_C_CC,
> +	MT6392_IRQ_TYPEC_H_MAX,
> +	MT6392_IRQ_TYPEC_H_MIN,
> +	MT6392_IRQ_TYPEC_L_MAX,
> +	MT6392_IRQ_TYPEC_L_MIN,
> +	MT6392_IRQ_THR_MAX,
> +	MT6392_IRQ_THR_MIN,
> +	MT6392_IRQ_NAG_C_DLTV,
> +	MT6392_IRQ_NR,
> +};
> +
> +#endif /* __MFD_MT6392_CORE_H__ */
> diff --git "a/include/linux/mfd/mt6392/registers.h" "b/include/linux/mfd/mt6392/registers.h"
> new file mode 100644
> index 000000000000..4f3a6db830d1
> --- /dev/null
> +++ "b/include/linux/mfd/mt6392/registers.h"
> @@ -0,0 +1,487 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2020 MediaTek Inc.

Same and throughout.

> + * Author: Chen Zhong <chen.zhong@mediatek.com>
> + */
> +
> +#ifndef __MFD_MT6392_REGISTERS_H__
> +#define __MFD_MT6392_REGISTERS_H__
> +
> +/* PMIC Registers */
> +#define MT6392_CHR_CON0                         0x0000
> +#define MT6392_CHR_CON1                         0x0002
> +#define MT6392_CHR_CON2                         0x0004
> +#define MT6392_CHR_CON3                         0x0006
> +#define MT6392_CHR_CON4                         0x0008
> +#define MT6392_CHR_CON5                         0x000A
> +#define MT6392_CHR_CON6                         0x000C
> +#define MT6392_CHR_CON7                         0x000E
> +#define MT6392_CHR_CON8                         0x0010
> +#define MT6392_CHR_CON9                         0x0012
> +#define MT6392_CHR_CON10                        0x0014
> +#define MT6392_CHR_CON11                        0x0016
> +#define MT6392_CHR_CON12                        0x0018
> +#define MT6392_CHR_CON13                        0x001A
> +#define MT6392_CHR_CON14                        0x001C
> +#define MT6392_CHR_CON15                        0x001E
> +#define MT6392_CHR_CON16                        0x0020
> +#define MT6392_CHR_CON17                        0x0022
> +#define MT6392_CHR_CON18                        0x0024
> +#define MT6392_CHR_CON19                        0x0026
> +#define MT6392_CHR_CON20                        0x0028
> +#define MT6392_CHR_CON21                        0x002A
> +#define MT6392_CHR_CON22                        0x002C
> +#define MT6392_CHR_CON23                        0x002E
> +#define MT6392_CHR_CON24                        0x0030
> +#define MT6392_CHR_CON25                        0x0032
> +#define MT6392_CHR_CON26                        0x0034
> +#define MT6392_CHR_CON27                        0x0036
> +#define MT6392_CHR_CON28                        0x0038
> +#define MT6392_CHR_CON29                        0x003A
> +#define MT6392_STRUP_CON0                       0x003C
> +#define MT6392_STRUP_CON2                       0x003E
> +#define MT6392_STRUP_CON3                       0x0040
> +#define MT6392_STRUP_CON4                       0x0042
> +#define MT6392_STRUP_CON5                       0x0044
> +#define MT6392_STRUP_CON6                       0x0046
> +#define MT6392_STRUP_CON7                       0x0048
> +#define MT6392_STRUP_CON8                       0x004A
> +#define MT6392_STRUP_CON9                       0x004C
> +#define MT6392_STRUP_CON10                      0x004E
> +#define MT6392_STRUP_CON11                      0x0050
> +#define MT6392_SPK_CON0                         0x0052
> +#define MT6392_SPK_CON1                         0x0054
> +#define MT6392_SPK_CON2                         0x0056
> +#define MT6392_SPK_CON6                         0x005E
> +#define MT6392_SPK_CON7                         0x0060
> +#define MT6392_SPK_CON8                         0x0062
> +#define MT6392_SPK_CON9                         0x0064
> +#define MT6392_SPK_CON10                        0x0066
> +#define MT6392_SPK_CON11                        0x0068
> +#define MT6392_SPK_CON12                        0x006A
> +#define MT6392_STRUP_CON12                      0x006E
> +#define MT6392_STRUP_CON13                      0x0070
> +#define MT6392_STRUP_CON14                      0x0072
> +#define MT6392_STRUP_CON15                      0x0074
> +#define MT6392_STRUP_CON16                      0x0076
> +#define MT6392_STRUP_CON17                      0x0078
> +#define MT6392_STRUP_CON18                      0x007A
> +#define MT6392_STRUP_CON19                      0x007C
> +#define MT6392_STRUP_CON20                      0x007E
> +#define MT6392_CID                              0x0100
> +#define MT6392_TOP_CKPDN0                       0x0102
> +#define MT6392_TOP_CKPDN0_SET                   0x0104
> +#define MT6392_TOP_CKPDN0_CLR                   0x0106
> +#define MT6392_TOP_CKPDN1                       0x0108
> +#define MT6392_TOP_CKPDN1_SET                   0x010A
> +#define MT6392_TOP_CKPDN1_CLR                   0x010C
> +#define MT6392_TOP_CKPDN2                       0x010E
> +#define MT6392_TOP_CKPDN2_SET                   0x0110
> +#define MT6392_TOP_CKPDN2_CLR                   0x0112
> +#define MT6392_TOP_RST_CON                      0x0114
> +#define MT6392_TOP_RST_CON_SET                  0x0116
> +#define MT6392_TOP_RST_CON_CLR                  0x0118
> +#define MT6392_TOP_RST_MISC                     0x011A
> +#define MT6392_TOP_RST_MISC_SET                 0x011C
> +#define MT6392_TOP_RST_MISC_CLR                 0x011E
> +#define MT6392_TOP_CKCON0                       0x0120
> +#define MT6392_TOP_CKCON0_SET                   0x0122
> +#define MT6392_TOP_CKCON0_CLR                   0x0124
> +#define MT6392_TOP_CKCON1                       0x0126
> +#define MT6392_TOP_CKCON1_SET                   0x0128
> +#define MT6392_TOP_CKCON1_CLR                   0x012A
> +#define MT6392_TOP_CKTST0                       0x012C
> +#define MT6392_TOP_CKTST1                       0x012E
> +#define MT6392_TOP_CKTST2                       0x0130
> +#define MT6392_TEST_OUT                         0x0132
> +#define MT6392_TEST_CON0                        0x0134
> +#define MT6392_TEST_CON1                        0x0136
> +#define MT6392_EN_STATUS0                       0x0138
> +#define MT6392_EN_STATUS1                       0x013A
> +#define MT6392_OCSTATUS0                        0x013C
> +#define MT6392_OCSTATUS1                        0x013E
> +#define MT6392_PGSTATUS                         0x0140
> +#define MT6392_CHRSTATUS                        0x0142
> +#define MT6392_TDSEL_CON                        0x0144
> +#define MT6392_RDSEL_CON                        0x0146
> +#define MT6392_SMT_CON0                         0x0148
> +#define MT6392_SMT_CON1                         0x014A
> +#define MT6392_DRV_CON0                         0x0152
> +#define MT6392_DRV_CON1                         0x0154
> +#define MT6392_INT_CON0                         0x0160
> +#define MT6392_INT_CON0_SET                     0x0162
> +#define MT6392_INT_CON0_CLR                     0x0164
> +#define MT6392_INT_CON1                         0x0166
> +#define MT6392_INT_CON1_SET                     0x0168
> +#define MT6392_INT_CON1_CLR                     0x016A
> +#define MT6392_INT_MISC_CON                     0x016C
> +#define MT6392_INT_MISC_CON_SET                 0x016E
> +#define MT6392_INT_MISC_CON_CLR                 0x0170
> +#define MT6392_INT_STATUS0                      0x0172
> +#define MT6392_INT_STATUS1                      0x0174
> +#define MT6392_OC_GEAR_0                        0x0176
> +#define MT6392_OC_GEAR_1                        0x0178
> +#define MT6392_OC_GEAR_2                        0x017A
> +#define MT6392_OC_CTL_VPROC                     0x017C
> +#define MT6392_OC_CTL_VSYS                      0x017E
> +#define MT6392_OC_CTL_VCORE                     0x0180
> +#define MT6392_FQMTR_CON0                       0x0182
> +#define MT6392_FQMTR_CON1                       0x0184
> +#define MT6392_FQMTR_CON2                       0x0186
> +#define MT6392_RG_SPI_CON                       0x0188
> +#define MT6392_DEW_DIO_EN                       0x018A
> +#define MT6392_DEW_READ_TEST                    0x018C
> +#define MT6392_DEW_WRITE_TEST                   0x018E
> +#define MT6392_DEW_CRC_SWRST                    0x0190
> +#define MT6392_DEW_CRC_EN                       0x0192
> +#define MT6392_DEW_CRC_VAL                      0x0194
> +#define MT6392_DEW_DBG_MON_SEL                  0x0196
> +#define MT6392_DEW_CIPHER_KEY_SEL               0x0198
> +#define MT6392_DEW_CIPHER_IV_SEL                0x019A
> +#define MT6392_DEW_CIPHER_EN                    0x019C
> +#define MT6392_DEW_CIPHER_RDY                   0x019E
> +#define MT6392_DEW_CIPHER_MODE                  0x01A0
> +#define MT6392_DEW_CIPHER_SWRST                 0x01A2
> +#define MT6392_DEW_RDDMY_NO                     0x01A4
> +#define MT6392_DEW_RDATA_DLY_SEL                0x01A6
> +#define MT6392_CLK_TRIM_CON0                    0x01A8
> +#define MT6392_BUCK_CON0                        0x0200
> +#define MT6392_BUCK_CON1                        0x0202
> +#define MT6392_BUCK_CON2                        0x0204
> +#define MT6392_BUCK_CON3                        0x0206
> +#define MT6392_BUCK_CON4                        0x0208
> +#define MT6392_BUCK_CON5                        0x020A
> +#define MT6392_VPROC_CON0                       0x020C
> +#define MT6392_VPROC_CON1                       0x020E
> +#define MT6392_VPROC_CON2                       0x0210
> +#define MT6392_VPROC_CON3                       0x0212
> +#define MT6392_VPROC_CON4                       0x0214
> +#define MT6392_VPROC_CON5                       0x0216
> +#define MT6392_VPROC_CON7                       0x021A
> +#define MT6392_VPROC_CON8                       0x021C
> +#define MT6392_VPROC_CON9                       0x021E
> +#define MT6392_VPROC_CON10                      0x0220
> +#define MT6392_VPROC_CON11                      0x0222
> +#define MT6392_VPROC_CON12                      0x0224
> +#define MT6392_VPROC_CON13                      0x0226
> +#define MT6392_VPROC_CON14                      0x0228
> +#define MT6392_VPROC_CON15                      0x022A
> +#define MT6392_VPROC_CON18                      0x0230
> +#define MT6392_VSYS_CON0                        0x0232
> +#define MT6392_VSYS_CON1                        0x0234
> +#define MT6392_VSYS_CON2                        0x0236
> +#define MT6392_VSYS_CON3                        0x0238
> +#define MT6392_VSYS_CON4                        0x023A
> +#define MT6392_VSYS_CON5                        0x023C
> +#define MT6392_VSYS_CON7                        0x0240
> +#define MT6392_VSYS_CON8                        0x0242
> +#define MT6392_VSYS_CON9                        0x0244
> +#define MT6392_VSYS_CON10                       0x0246
> +#define MT6392_VSYS_CON11                       0x0248
> +#define MT6392_VSYS_CON12                       0x024A
> +#define MT6392_VSYS_CON13                       0x024C
> +#define MT6392_VSYS_CON14                       0x024E
> +#define MT6392_VSYS_CON15                       0x0250
> +#define MT6392_VSYS_CON18                       0x0256
> +#define MT6392_BUCK_OC_CON0                     0x0258
> +#define MT6392_BUCK_OC_CON1                     0x025A
> +#define MT6392_BUCK_OC_CON2                     0x025C
> +#define MT6392_BUCK_OC_CON3                     0x025E
> +#define MT6392_BUCK_OC_CON4                     0x0260
> +#define MT6392_BUCK_OC_VPROC_CON0               0x0262
> +#define MT6392_BUCK_OC_VCORE_CON0               0x0264
> +#define MT6392_BUCK_OC_VSYS_CON0                0x0266
> +#define MT6392_BUCK_ANA_MON_CON0                0x0268
> +#define MT6392_BUCK_EFUSE_OC_CON0               0x026A
> +#define MT6392_VCORE_CON0                       0x0300
> +#define MT6392_VCORE_CON1                       0x0302
> +#define MT6392_VCORE_CON2                       0x0304
> +#define MT6392_VCORE_CON3                       0x0306
> +#define MT6392_VCORE_CON4                       0x0308
> +#define MT6392_VCORE_CON5                       0x030A
> +#define MT6392_VCORE_CON7                       0x030E
> +#define MT6392_VCORE_CON8                       0x0310
> +#define MT6392_VCORE_CON9                       0x0312
> +#define MT6392_VCORE_CON10                      0x0314
> +#define MT6392_VCORE_CON11                      0x0316
> +#define MT6392_VCORE_CON12                      0x0318
> +#define MT6392_VCORE_CON13                      0x031A
> +#define MT6392_VCORE_CON14                      0x031C
> +#define MT6392_VCORE_CON15                      0x031E
> +#define MT6392_VCORE_CON18                      0x0324
> +#define MT6392_BUCK_K_CON0                      0x032A
> +#define MT6392_BUCK_K_CON1                      0x032C
> +#define MT6392_BUCK_K_CON2                      0x032E
> +#define MT6392_ANALDO_CON0                      0x0400
> +#define MT6392_ANALDO_CON1                      0x0402
> +#define MT6392_ANALDO_CON2                      0x0404
> +#define MT6392_ANALDO_CON3                      0x0406
> +#define MT6392_ANALDO_CON4                      0x0408
> +#define MT6392_ANALDO_CON6                      0x040C
> +#define MT6392_ANALDO_CON7                      0x040E
> +#define MT6392_ANALDO_CON8                      0x0410
> +#define MT6392_ANALDO_CON10                     0x0412
> +#define MT6392_ANALDO_CON15                     0x0414
> +#define MT6392_ANALDO_CON16                     0x0416
> +#define MT6392_ANALDO_CON17                     0x0418
> +#define MT6392_ANALDO_CON21                     0x0420
> +#define MT6392_ANALDO_CON22                     0x0422
> +#define MT6392_ANALDO_CON23                     0x0424
> +#define MT6392_ANALDO_CON24                     0x0426
> +#define MT6392_ANALDO_CON25                     0x0428
> +#define MT6392_ANALDO_CON26                     0x042A
> +#define MT6392_ANALDO_CON27                     0x042C
> +#define MT6392_ANALDO_CON28                     0x042E
> +#define MT6392_ANALDO_CON29                     0x0430
> +#define MT6392_DIGLDO_CON0                      0x0500
> +#define MT6392_DIGLDO_CON2                      0x0502
> +#define MT6392_DIGLDO_CON3                      0x0504
> +#define MT6392_DIGLDO_CON5                      0x0506
> +#define MT6392_DIGLDO_CON6                      0x0508
> +#define MT6392_DIGLDO_CON7                      0x050A
> +#define MT6392_DIGLDO_CON8                      0x050C
> +#define MT6392_DIGLDO_CON10                     0x0510
> +#define MT6392_DIGLDO_CON11                     0x0512
> +#define MT6392_DIGLDO_CON12                     0x0514
> +#define MT6392_DIGLDO_CON15                     0x051A
> +#define MT6392_DIGLDO_CON20                     0x0524
> +#define MT6392_DIGLDO_CON21                     0x0526
> +#define MT6392_DIGLDO_CON23                     0x0528
> +#define MT6392_DIGLDO_CON24                     0x052A
> +#define MT6392_DIGLDO_CON26                     0x052C
> +#define MT6392_DIGLDO_CON27                     0x052E
> +#define MT6392_DIGLDO_CON28                     0x0530
> +#define MT6392_DIGLDO_CON29                     0x0532
> +#define MT6392_DIGLDO_CON30                     0x0534
> +#define MT6392_DIGLDO_CON31                     0x0536
> +#define MT6392_DIGLDO_CON32                     0x0538
> +#define MT6392_DIGLDO_CON33                     0x053A
> +#define MT6392_DIGLDO_CON36                     0x0540
> +#define MT6392_DIGLDO_CON41                     0x0546
> +#define MT6392_DIGLDO_CON44                     0x054C
> +#define MT6392_DIGLDO_CON47                     0x0552
> +#define MT6392_DIGLDO_CON48                     0x0554
> +#define MT6392_DIGLDO_CON49                     0x0556
> +#define MT6392_DIGLDO_CON50                     0x0558
> +#define MT6392_DIGLDO_CON51                     0x055A
> +#define MT6392_DIGLDO_CON52                     0x055C
> +#define MT6392_DIGLDO_CON53                     0x055E
> +#define MT6392_DIGLDO_CON54                     0x0560
> +#define MT6392_DIGLDO_CON55                     0x0562
> +#define MT6392_DIGLDO_CON56                     0x0564
> +#define MT6392_DIGLDO_CON57                     0x0566
> +#define MT6392_DIGLDO_CON58                     0x0568
> +#define MT6392_DIGLDO_CON59                     0x056A
> +#define MT6392_DIGLDO_CON60                     0x056C
> +#define MT6392_DIGLDO_CON61                     0x056E
> +#define MT6392_DIGLDO_CON62                     0x0570
> +#define MT6392_DIGLDO_CON63                     0x0572
> +#define MT6392_EFUSE_CON0                       0x0600
> +#define MT6392_EFUSE_CON1                       0x0602
> +#define MT6392_EFUSE_CON2                       0x0604
> +#define MT6392_EFUSE_CON3                       0x0606
> +#define MT6392_EFUSE_CON4                       0x0608
> +#define MT6392_EFUSE_CON5                       0x060A
> +#define MT6392_EFUSE_CON6                       0x060C
> +#define MT6392_EFUSE_VAL_0_15                   0x060E
> +#define MT6392_EFUSE_VAL_16_31                  0x0610
> +#define MT6392_EFUSE_VAL_32_47                  0x0612
> +#define MT6392_EFUSE_VAL_48_63                  0x0614
> +#define MT6392_EFUSE_VAL_64_79                  0x0616
> +#define MT6392_EFUSE_VAL_80_95                  0x0618
> +#define MT6392_EFUSE_VAL_96_111                 0x061A
> +#define MT6392_EFUSE_VAL_112_127                0x061C
> +#define MT6392_EFUSE_VAL_128_143                0x061E
> +#define MT6392_EFUSE_VAL_144_159                0x0620
> +#define MT6392_EFUSE_VAL_160_175                0x0622
> +#define MT6392_EFUSE_VAL_176_191                0x0624
> +#define MT6392_EFUSE_VAL_192_207                0x0626
> +#define MT6392_EFUSE_VAL_208_223                0x0628
> +#define MT6392_EFUSE_VAL_224_239                0x062A
> +#define MT6392_EFUSE_VAL_240_255                0x062C
> +#define MT6392_EFUSE_VAL_256_271                0x062E
> +#define MT6392_EFUSE_VAL_272_287                0x0630
> +#define MT6392_EFUSE_VAL_288_303                0x0632
> +#define MT6392_EFUSE_VAL_304_319                0x0634
> +#define MT6392_EFUSE_VAL_320_335                0x0636
> +#define MT6392_EFUSE_VAL_336_351                0x0638
> +#define MT6392_EFUSE_VAL_352_367                0x063A
> +#define MT6392_EFUSE_VAL_368_383                0x063C
> +#define MT6392_EFUSE_VAL_384_399                0x063E
> +#define MT6392_EFUSE_VAL_400_415                0x0640
> +#define MT6392_EFUSE_VAL_416_431                0x0642
> +#define MT6392_RTC_MIX_CON0                     0x0644
> +#define MT6392_RTC_MIX_CON1                     0x0646
> +#define MT6392_EFUSE_VAL_432_447                0x0648
> +#define MT6392_EFUSE_VAL_448_463                0x064A
> +#define MT6392_EFUSE_VAL_464_479                0x064C
> +#define MT6392_EFUSE_VAL_480_495                0x064E
> +#define MT6392_EFUSE_VAL_496_511                0x0650
> +#define MT6392_EFUSE_DOUT_0_15                  0x0652
> +#define MT6392_EFUSE_DOUT_16_31                 0x0654
> +#define MT6392_EFUSE_DOUT_32_47                 0x0656
> +#define MT6392_EFUSE_DOUT_48_63                 0x0658
> +#define MT6392_EFUSE_DOUT_64_79                 0x065A
> +#define MT6392_EFUSE_DOUT_80_95                 0x065C
> +#define MT6392_EFUSE_DOUT_96_111                0x065E
> +#define MT6392_EFUSE_DOUT_112_127               0x0660
> +#define MT6392_EFUSE_DOUT_128_143               0x0662
> +#define MT6392_EFUSE_DOUT_144_159               0x0664
> +#define MT6392_EFUSE_DOUT_160_175               0x0666
> +#define MT6392_EFUSE_DOUT_176_191               0x0668
> +#define MT6392_EFUSE_DOUT_192_207               0x066A
> +#define MT6392_EFUSE_DOUT_208_223               0x066C
> +#define MT6392_EFUSE_DOUT_224_239               0x066E
> +#define MT6392_EFUSE_DOUT_240_255               0x0670
> +#define MT6392_EFUSE_DOUT_256_271               0x0672
> +#define MT6392_EFUSE_DOUT_272_287               0x0674
> +#define MT6392_EFUSE_DOUT_288_303               0x0676
> +#define MT6392_EFUSE_DOUT_304_319               0x0678
> +#define MT6392_EFUSE_DOUT_320_335               0x067A
> +#define MT6392_EFUSE_DOUT_336_351               0x067C
> +#define MT6392_EFUSE_DOUT_352_367               0x067E
> +#define MT6392_EFUSE_DOUT_368_383               0x0680
> +#define MT6392_EFUSE_DOUT_384_399               0x0682
> +#define MT6392_EFUSE_DOUT_400_415               0x0684
> +#define MT6392_EFUSE_DOUT_416_431               0x0686
> +#define MT6392_EFUSE_DOUT_432_447               0x0688
> +#define MT6392_EFUSE_DOUT_448_463               0x068A
> +#define MT6392_EFUSE_DOUT_464_479               0x068C
> +#define MT6392_EFUSE_DOUT_480_495               0x068E
> +#define MT6392_EFUSE_DOUT_496_511               0x0690
> +#define MT6392_EFUSE_CON7                       0x0692
> +#define MT6392_EFUSE_CON8                       0x0694
> +#define MT6392_EFUSE_CON9                       0x0696
> +#define MT6392_AUXADC_ADC0                      0x0700
> +#define MT6392_AUXADC_ADC1                      0x0702
> +#define MT6392_AUXADC_ADC2                      0x0704
> +#define MT6392_AUXADC_ADC3                      0x0706
> +#define MT6392_AUXADC_ADC4                      0x0708
> +#define MT6392_AUXADC_ADC5                      0x070A
> +#define MT6392_AUXADC_ADC6                      0x070C
> +#define MT6392_AUXADC_ADC7                      0x070E
> +#define MT6392_AUXADC_ADC8                      0x0710
> +#define MT6392_AUXADC_ADC9                      0x0712
> +#define MT6392_AUXADC_ADC10                     0x0714
> +#define MT6392_AUXADC_ADC11                     0x0716
> +#define MT6392_AUXADC_ADC12                     0x0718
> +#define MT6392_AUXADC_ADC13                     0x071A
> +#define MT6392_AUXADC_ADC14                     0x071C
> +#define MT6392_AUXADC_ADC15                     0x071E
> +#define MT6392_AUXADC_ADC16                     0x0720
> +#define MT6392_AUXADC_ADC17                     0x0722
> +#define MT6392_AUXADC_ADC18                     0x0724
> +#define MT6392_AUXADC_ADC19                     0x0726
> +#define MT6392_AUXADC_ADC20                     0x0728
> +#define MT6392_AUXADC_ADC21                     0x072A
> +#define MT6392_AUXADC_ADC22                     0x072C
> +#define MT6392_AUXADC_STA0                      0x072E
> +#define MT6392_AUXADC_STA1                      0x0730
> +#define MT6392_AUXADC_RQST0                     0x0732
> +#define MT6392_AUXADC_RQST0_SET                 0x0734
> +#define MT6392_AUXADC_RQST0_CLR                 0x0736
> +#define MT6392_AUXADC_CON0                      0x0738
> +#define MT6392_AUXADC_CON0_SET                  0x073A
> +#define MT6392_AUXADC_CON0_CLR                  0x073C
> +#define MT6392_AUXADC_CON1                      0x073E
> +#define MT6392_AUXADC_CON2                      0x0740
> +#define MT6392_AUXADC_CON3                      0x0742
> +#define MT6392_AUXADC_CON4                      0x0744
> +#define MT6392_AUXADC_CON5                      0x0746
> +#define MT6392_AUXADC_CON6                      0x0748
> +#define MT6392_AUXADC_CON7                      0x074A
> +#define MT6392_AUXADC_CON8                      0x074C
> +#define MT6392_AUXADC_CON9                      0x074E
> +#define MT6392_AUXADC_CON10                     0x0750
> +#define MT6392_AUXADC_CON11                     0x0752
> +#define MT6392_AUXADC_CON12                     0x0754
> +#define MT6392_AUXADC_CON13                     0x0756
> +#define MT6392_AUXADC_CON14                     0x0758
> +#define MT6392_AUXADC_CON15                     0x075A
> +#define MT6392_AUXADC_CON16                     0x075C
> +#define MT6392_AUXADC_AUTORPT0                  0x075E
> +#define MT6392_AUXADC_LBAT0                     0x0760
> +#define MT6392_AUXADC_LBAT1                     0x0762
> +#define MT6392_AUXADC_LBAT2                     0x0764
> +#define MT6392_AUXADC_LBAT3                     0x0766
> +#define MT6392_AUXADC_LBAT4                     0x0768
> +#define MT6392_AUXADC_LBAT5                     0x076A
> +#define MT6392_AUXADC_LBAT6                     0x076C
> +#define MT6392_AUXADC_THR0                      0x076E
> +#define MT6392_AUXADC_THR1                      0x0770
> +#define MT6392_AUXADC_THR2                      0x0772
> +#define MT6392_AUXADC_THR3                      0x0774
> +#define MT6392_AUXADC_THR4                      0x0776
> +#define MT6392_AUXADC_THR5                      0x0778
> +#define MT6392_AUXADC_THR6                      0x077A
> +#define MT6392_AUXADC_EFUSE0                    0x077C
> +#define MT6392_AUXADC_EFUSE1                    0x077E
> +#define MT6392_AUXADC_EFUSE2                    0x0780
> +#define MT6392_AUXADC_EFUSE3                    0x0782
> +#define MT6392_AUXADC_EFUSE4                    0x0784
> +#define MT6392_AUXADC_EFUSE5                    0x0786
> +#define MT6392_AUXADC_NAG_0                     0x0788
> +#define MT6392_AUXADC_NAG_1                     0x078A
> +#define MT6392_AUXADC_NAG_2                     0x078C
> +#define MT6392_AUXADC_NAG_3                     0x078E
> +#define MT6392_AUXADC_NAG_4                     0x0790
> +#define MT6392_AUXADC_NAG_5                     0x0792
> +#define MT6392_AUXADC_NAG_6                     0x0794
> +#define MT6392_AUXADC_NAG_7                     0x0796
> +#define MT6392_AUXADC_NAG_8                     0x0798
> +#define MT6392_AUXADC_TYPEC_H_1                 0x079A
> +#define MT6392_AUXADC_TYPEC_H_2                 0x079C
> +#define MT6392_AUXADC_TYPEC_H_3                 0x079E
> +#define MT6392_AUXADC_TYPEC_H_4                 0x07A0
> +#define MT6392_AUXADC_TYPEC_H_5                 0x07A2
> +#define MT6392_AUXADC_TYPEC_H_6                 0x07A4
> +#define MT6392_AUXADC_TYPEC_H_7                 0x07A6
> +#define MT6392_AUXADC_TYPEC_L_1                 0x07A8
> +#define MT6392_AUXADC_TYPEC_L_2                 0x07AA
> +#define MT6392_AUXADC_TYPEC_L_3                 0x07AC
> +#define MT6392_AUXADC_TYPEC_L_4                 0x07AE
> +#define MT6392_AUXADC_TYPEC_L_5                 0x07B0
> +#define MT6392_AUXADC_TYPEC_L_6                 0x07B2
> +#define MT6392_AUXADC_TYPEC_L_7                 0x07B4
> +#define MT6392_AUXADC_NAG_9                     0x07B6
> +#define MT6392_TYPE_C_PHY_RG_0                  0x0800
> +#define MT6392_TYPE_C_PHY_RG_CC_RESERVE_CSR     0x0802
> +#define MT6392_TYPE_C_VCMP_CTRL                 0x0804
> +#define MT6392_TYPE_C_CTRL                      0x0806
> +#define MT6392_TYPE_C_CC_SW_CTRL                0x080a
> +#define MT6392_TYPE_C_CC_VOL_PERIODIC_MEAS_VAL  0x080c
> +#define MT6392_TYPE_C_CC_VOL_DEBOUNCE_CNT_VAL   0x080e
> +#define MT6392_TYPE_C_DRP_SRC_CNT_VAL_0         0x0810
> +#define MT6392_TYPE_C_DRP_SNK_CNT_VAL_0         0x0814
> +#define MT6392_TYPE_C_DRP_TRY_CNT_VAL_0         0x0818
> +#define MT6392_TYPE_C_CC_SRC_DEFAULT_DAC_VAL    0x0820
> +#define MT6392_TYPE_C_CC_SRC_15_DAC_VAL         0x0822
> +#define MT6392_TYPE_C_CC_SRC_30_DAC_VAL         0x0824
> +#define MT6392_TYPE_C_CC_SNK_DAC_VAL_0          0x0828
> +#define MT6392_TYPE_C_CC_SNK_DAC_VAL_1          0x082a
> +#define MT6392_TYPE_C_INTR_EN_0                 0x0830
> +#define MT6392_TYPE_C_INTR_EN_2                 0x0834
> +#define MT6392_TYPE_C_INTR_0                    0x0838
> +#define MT6392_TYPE_C_INTR_2                    0x083C
> +#define MT6392_TYPE_C_CC_STATUS                 0x0840
> +#define MT6392_TYPE_C_PWR_STATUS                0x0842
> +#define MT6392_TYPE_C_PHY_RG_CC1_RESISTENCE_0   0x0844
> +#define MT6392_TYPE_C_PHY_RG_CC1_RESISTENCE_1   0x0846
> +#define MT6392_TYPE_C_PHY_RG_CC2_RESISTENCE_0   0x0848
> +#define MT6392_TYPE_C_PHY_RG_CC2_RESISTENCE_1   0x084a
> +#define MT6392_TYPE_C_CC_SW_FORCE_MODE_ENABLE_0 0x0860
> +#define MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_0    0x0864
> +#define MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_1    0x0866
> +#define MT6392_TYPE_C_CC_SW_FORCE_MODE_ENABLE_1 0x0868
> +#define MT6392_TYPE_C_CC_SW_FORCE_MODE_VAL_2    0x086c
> +#define MT6392_TYPE_C_CC_DAC_CALI_CTRL          0x0870
> +#define MT6392_TYPE_C_CC_DAC_CALI_RESULT        0x0872
> +#define MT6392_TYPE_C_DEBUG_PORT_SELECT_0       0x0880
> +#define MT6392_TYPE_C_DEBUG_PORT_SELECT_1       0x0882
> +#define MT6392_TYPE_C_DEBUG_MODE_SELECT         0x0884
> +#define MT6392_TYPE_C_DEBUG_OUT_READ_0          0x0888
> +#define MT6392_TYPE_C_DEBUG_OUT_READ_1          0x088a
> +#define MT6392_TYPE_C_SW_DEBUG_PORT_0           0x088c
> +#define MT6392_TYPE_C_SW_DEBUG_PORT_1           0x088e
> +
> +#endif /* __MFD_MT6392_REGISTERS_H__ */
> diff --git "a/include/linux/mfd/mt6397/core.h" "b/include/linux/mfd/mt6397/core.h"
> index 340fc72e22aa..3729a6856c13 100644
> --- "a/include/linux/mfd/mt6397/core.h"
> +++ "b/include/linux/mfd/mt6397/core.h"
> @@ -20,6 +20,7 @@ enum chip_id {
>  	MT6359_CHIP_ID = 0x59,
>  	MT6366_CHIP_ID = 0x66,
>  	MT6391_CHIP_ID = 0x91,
> +	MT6392_CHIP_ID = 0x92,

This looks like a duplicated struct.

Can't we use this instead of the made-up 'mfd_match_data'?

>  	MT6397_CHIP_ID = 0x97,
>  };
>  
> -- 
> 2.43.0

-- 
Lee Jones

^ permalink raw reply

* Re: [PATCH v5 5/6] mfd: motorola-cpcap: diverge configuration per-board
From: Lee Jones @ 2026-05-20 15:07 UTC (permalink / raw)
  To: Svyatoslav Ryhel
  Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Pavel Machek, David Lechner, Tony Lindgren, linux-input,
	devicetree, linux-kernel, linux-leds
In-Reply-To: <20260510110804.33045-6-clamor95@gmail.com>

On Sun, 10 May 2026, Svyatoslav Ryhel wrote:

> MFD have rigid subdevice structure which does not allow flexible dynamic
> subdevice linking. Address this by diverging CPCAP subdevice composition
> to take into account board specific configuration.
> 
> Create a common default subdevice composition, rename existing subdevice
> composition into cpcap_mapphone_mfd_devices since it targets mainly
> Mapphone board.
> 
> Removed st,6556002 as it is no longer applicable to all cases and
> duplicates motorola,cpcap, which is used as the default composition.
> 
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
>  drivers/mfd/motorola-cpcap.c       | 142 ++++++++++++++++-------------
>  include/linux/mfd/motorola-cpcap.h |   6 ++
>  2 files changed, 87 insertions(+), 61 deletions(-)

Looking much better, thanks.

Nit: A patch-level changelog really is much more helpful to reviewers.

> diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c
> index d8243b956f87..f5a7fdd89dd5 100644
> --- a/drivers/mfd/motorola-cpcap.c
> +++ b/drivers/mfd/motorola-cpcap.c
> @@ -12,6 +12,7 @@
>  #include <linux/kernel.h>
>  #include <linux/module.h>
>  #include <linux/mod_devicetable.h>
> +#include <linux/property.h>
>  #include <linux/regmap.h>
>  #include <linux/sysfs.h>
>  
> @@ -30,6 +31,7 @@ struct cpcap_ddata {
>  	struct regmap_irq_chip_data *irqdata[CPCAP_NR_IRQ_CHIPS];
>  	const struct regmap_config *regmap_conf;
>  	struct regmap *regmap;
> +	enum cpcap_variant variant;
>  };
>  
>  static int cpcap_sense_irq(struct regmap *regmap, int irq)
> @@ -195,20 +197,6 @@ static int cpcap_init_irq(struct cpcap_ddata *cpcap)
>  	return 0;
>  }
>  
> -static const struct of_device_id cpcap_of_match[] = {
> -	{ .compatible = "motorola,cpcap", },
> -	{ .compatible = "st,6556002", },
> -	{},
> -};
> -MODULE_DEVICE_TABLE(of, cpcap_of_match);
> -
> -static const struct spi_device_id cpcap_spi_ids[] = {
> -	{ .name = "cpcap", },
> -	{ .name = "6556002", },
> -	{},
> -};
> -MODULE_DEVICE_TABLE(spi, cpcap_spi_ids);
> -
>  static const struct regmap_config cpcap_regmap_config = {
>  	.reg_bits = 16,
>  	.reg_stride = 4,
> @@ -241,62 +229,76 @@ static int cpcap_resume(struct device *dev)
>  
>  static DEFINE_SIMPLE_DEV_PM_OPS(cpcap_pm, cpcap_suspend, cpcap_resume);
>  
> -static const struct mfd_cell cpcap_mfd_devices[] = {
> -	{
> -		.name          = "cpcap_adc",
> -		.of_compatible = "motorola,mapphone-cpcap-adc",
> -	}, {
> -		.name          = "cpcap_battery",
> -		.of_compatible = "motorola,cpcap-battery",
> -	}, {
> -		.name          = "cpcap-charger",
> -		.of_compatible = "motorola,mapphone-cpcap-charger",
> -	}, {
> -		.name          = "cpcap-regulator",
> -		.of_compatible = "motorola,mapphone-cpcap-regulator",
> -	}, {
> -		.name          = "cpcap-rtc",
> -		.of_compatible = "motorola,cpcap-rtc",
> -	}, {
> -		.name          = "cpcap-pwrbutton",
> -		.of_compatible = "motorola,cpcap-pwrbutton",
> -	}, {
> -		.name          = "cpcap-usb-phy",
> -		.of_compatible = "motorola,mapphone-cpcap-usb-phy",
> -	}, {
> -		.name          = "cpcap-led",
> -		.id            = 0,
> -		.of_compatible = "motorola,cpcap-led-red",
> -	}, {
> -		.name          = "cpcap-led",
> -		.id            = 1,
> -		.of_compatible = "motorola,cpcap-led-green",
> -	}, {
> -		.name          = "cpcap-led",
> -		.id            = 2,
> -		.of_compatible = "motorola,cpcap-led-blue",
> -	}, {
> -		.name          = "cpcap-led",
> -		.id            = 3,
> -		.of_compatible = "motorola,cpcap-led-adl",
> -	}, {
> -		.name          = "cpcap-led",
> -		.id            = 4,
> -		.of_compatible = "motorola,cpcap-led-cp",
> -	}, {
> -		.name          = "cpcap-codec",
> -	}
> +static const struct mfd_cell cpcap_default_mfd_devices[] = {
> +	MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,cpcap-adc"),
> +	MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0,
> +		    "motorola,cpcap-battery"),
> +	MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0,
> +		    "motorola,cpcap-regulator"),
> +	MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> +	MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0,
> +		    "motorola,cpcap-pwrbutton"),
> +	MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0,
> +		    "motorola,cpcap-usb-phy"),
> +	MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> +	MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> +	MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> +	MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> +	MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> +	MFD_CELL_NAME("cpcap-codec"),
> +};

Nit: I wouldn't complain if you wanted to have all of these on a single
line for neatness.

> +static const struct mfd_cell cpcap_mapphone_mfd_devices[] = {
> +	MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0,
> +		    "motorola,mapphone-cpcap-adc"),
> +	MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0,
> +		    "motorola,cpcap-battery"),
> +	MFD_CELL_OF("cpcap-charger", NULL, NULL, 0, 0,
> +		    "motorola,mapphone-cpcap-charger"),
> +	MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0,
> +		    "motorola,mapphone-cpcap-regulator"),
> +	MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> +	MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0,
> +		    "motorola,cpcap-pwrbutton"),
> +	MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0,
> +		    "motorola,mapphone-cpcap-usb-phy"),
> +	MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> +	MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> +	MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> +	MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> +	MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> +	MFD_CELL_NAME("cpcap-codec"),
>  };

A lot of these are duplicated, right?

I would have a comment set, then the differences in separate containers.

>  static int cpcap_probe(struct spi_device *spi)
>  {
>  	struct cpcap_ddata *cpcap;
> +	const struct mfd_cell *cells;
> +	unsigned int num_cells;
>  	int ret;
>  
>  	cpcap = devm_kzalloc(&spi->dev, sizeof(*cpcap), GFP_KERNEL);
>  	if (!cpcap)
>  		return -ENOMEM;
>  
> +	cpcap->variant = (enum cpcap_variant)spi_get_device_match_data(spi);
> +	if (!cpcap->variant)
> +		return -ENODEV;

Isn't this covered in the 'default' below?


> +	switch (cpcap->variant) {
> +	case CPCAP_DEFAULT:
> +		cells = cpcap_default_mfd_devices;
> +		num_cells = ARRAY_SIZE(cpcap_default_mfd_devices);
> +		break;
> +	case CPCAP_MAPPHONE:
> +		cells = cpcap_mapphone_mfd_devices;
> +		num_cells = ARRAY_SIZE(cpcap_mapphone_mfd_devices);
> +		break;
> +	default:
> +		return dev_err_probe(&spi->dev, -EINVAL,
> +				     "Unknown device %d\n", cpcap->variant);

This should be -ENODEV.

> +	}
> +
>  	cpcap->spi = spi;
>  	spi_set_drvdata(spi, cpcap);
>  
> @@ -331,10 +333,28 @@ static int cpcap_probe(struct spi_device *spi)
>  	spi->dev.coherent_dma_mask = 0;
>  	spi->dev.dma_mask = &spi->dev.coherent_dma_mask;
>  
> -	return devm_mfd_add_devices(&spi->dev, 0, cpcap_mfd_devices,
> -				    ARRAY_SIZE(cpcap_mfd_devices), NULL, 0, NULL);
> +	return devm_mfd_add_devices(&spi->dev, 0, cells, num_cells, NULL, 0, NULL);
>  }
>  
> +static const struct of_device_id cpcap_of_match[] = {
> +	{
> +		.compatible = "motorola,cpcap",
> +		.data = (void *)CPCAP_DEFAULT

Single line should be fine.

> +	}, {
> +		.compatible = "motorola,mapphone-cpcap",
> +		.data = (void *)CPCAP_MAPPHONE
> +	},
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, cpcap_of_match);
> +
> +static const struct spi_device_id cpcap_spi_ids[] = {
> +	{ "cpcap", CPCAP_DEFAULT },
> +	{ "mapphone-cpcap", CPCAP_MAPPHONE },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(spi, cpcap_spi_ids);
> +
>  static struct spi_driver cpcap_driver = {
>  	.driver = {
>  		.name = "cpcap-core",
> diff --git a/include/linux/mfd/motorola-cpcap.h b/include/linux/mfd/motorola-cpcap.h
> index 981e5777deb7..1a85b06272c8 100644
> --- a/include/linux/mfd/motorola-cpcap.h
> +++ b/include/linux/mfd/motorola-cpcap.h
> @@ -25,6 +25,12 @@
>  #define CPCAP_REVISION_2_0	0x10
>  #define CPCAP_REVISION_2_1	0x11
>  
> +enum cpcap_variant {
> +	CPCAP_DEFAULT = 1,
> +	CPCAP_MAPPHONE,
> +	CPCAP_MAX
> +};
> +
>  /* CPCAP registers */
>  #define CPCAP_REG_INT1		0x0000	/* Interrupt 1 */
>  #define CPCAP_REG_INT2		0x0004	/* Interrupt 2 */
> -- 
> 2.51.0
> 

-- 
Lee Jones

^ permalink raw reply

* Re: [PATCH v5 5/6] mfd: motorola-cpcap: diverge configuration per-board
From: Svyatoslav Ryhel @ 2026-05-20 15:29 UTC (permalink / raw)
  To: Lee Jones
  Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Pavel Machek, David Lechner, Tony Lindgren, linux-input,
	devicetree, linux-kernel, linux-leds
In-Reply-To: <20260520150758.GG2767592@google.com>

ср, 20 трав. 2026 р. о 18:08 Lee Jones <lee@kernel.org> пише:
>
> On Sun, 10 May 2026, Svyatoslav Ryhel wrote:
>
> > MFD have rigid subdevice structure which does not allow flexible dynamic
> > subdevice linking. Address this by diverging CPCAP subdevice composition
> > to take into account board specific configuration.
> >
> > Create a common default subdevice composition, rename existing subdevice
> > composition into cpcap_mapphone_mfd_devices since it targets mainly
> > Mapphone board.
> >
> > Removed st,6556002 as it is no longer applicable to all cases and
> > duplicates motorola,cpcap, which is used as the default composition.
> >
> > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > ---
> >  drivers/mfd/motorola-cpcap.c       | 142 ++++++++++++++++-------------
> >  include/linux/mfd/motorola-cpcap.h |   6 ++
> >  2 files changed, 87 insertions(+), 61 deletions(-)
>
> Looking much better, thanks.
>
> Nit: A patch-level changelog really is much more helpful to reviewers.
>

Noted, but I will not guarantee that I will do patch-level changelogs, sorry.

> > diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c
> > index d8243b956f87..f5a7fdd89dd5 100644
> > --- a/drivers/mfd/motorola-cpcap.c
> > +++ b/drivers/mfd/motorola-cpcap.c
> > @@ -12,6 +12,7 @@
> >  #include <linux/kernel.h>
> >  #include <linux/module.h>
> >  #include <linux/mod_devicetable.h>
> > +#include <linux/property.h>
> >  #include <linux/regmap.h>
> >  #include <linux/sysfs.h>
> >
> > @@ -30,6 +31,7 @@ struct cpcap_ddata {
> >       struct regmap_irq_chip_data *irqdata[CPCAP_NR_IRQ_CHIPS];
> >       const struct regmap_config *regmap_conf;
> >       struct regmap *regmap;
> > +     enum cpcap_variant variant;
> >  };
> >
> >  static int cpcap_sense_irq(struct regmap *regmap, int irq)
> > @@ -195,20 +197,6 @@ static int cpcap_init_irq(struct cpcap_ddata *cpcap)
> >       return 0;
> >  }
> >
> > -static const struct of_device_id cpcap_of_match[] = {
> > -     { .compatible = "motorola,cpcap", },
> > -     { .compatible = "st,6556002", },
> > -     {},
> > -};
> > -MODULE_DEVICE_TABLE(of, cpcap_of_match);
> > -
> > -static const struct spi_device_id cpcap_spi_ids[] = {
> > -     { .name = "cpcap", },
> > -     { .name = "6556002", },
> > -     {},
> > -};
> > -MODULE_DEVICE_TABLE(spi, cpcap_spi_ids);
> > -
> >  static const struct regmap_config cpcap_regmap_config = {
> >       .reg_bits = 16,
> >       .reg_stride = 4,
> > @@ -241,62 +229,76 @@ static int cpcap_resume(struct device *dev)
> >
> >  static DEFINE_SIMPLE_DEV_PM_OPS(cpcap_pm, cpcap_suspend, cpcap_resume);
> >
> > -static const struct mfd_cell cpcap_mfd_devices[] = {
> > -     {
> > -             .name          = "cpcap_adc",
> > -             .of_compatible = "motorola,mapphone-cpcap-adc",
> > -     }, {
> > -             .name          = "cpcap_battery",
> > -             .of_compatible = "motorola,cpcap-battery",
> > -     }, {
> > -             .name          = "cpcap-charger",
> > -             .of_compatible = "motorola,mapphone-cpcap-charger",
> > -     }, {
> > -             .name          = "cpcap-regulator",
> > -             .of_compatible = "motorola,mapphone-cpcap-regulator",
> > -     }, {
> > -             .name          = "cpcap-rtc",
> > -             .of_compatible = "motorola,cpcap-rtc",
> > -     }, {
> > -             .name          = "cpcap-pwrbutton",
> > -             .of_compatible = "motorola,cpcap-pwrbutton",
> > -     }, {
> > -             .name          = "cpcap-usb-phy",
> > -             .of_compatible = "motorola,mapphone-cpcap-usb-phy",
> > -     }, {
> > -             .name          = "cpcap-led",
> > -             .id            = 0,
> > -             .of_compatible = "motorola,cpcap-led-red",
> > -     }, {
> > -             .name          = "cpcap-led",
> > -             .id            = 1,
> > -             .of_compatible = "motorola,cpcap-led-green",
> > -     }, {
> > -             .name          = "cpcap-led",
> > -             .id            = 2,
> > -             .of_compatible = "motorola,cpcap-led-blue",
> > -     }, {
> > -             .name          = "cpcap-led",
> > -             .id            = 3,
> > -             .of_compatible = "motorola,cpcap-led-adl",
> > -     }, {
> > -             .name          = "cpcap-led",
> > -             .id            = 4,
> > -             .of_compatible = "motorola,cpcap-led-cp",
> > -     }, {
> > -             .name          = "cpcap-codec",
> > -     }
> > +static const struct mfd_cell cpcap_default_mfd_devices[] = {
> > +     MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,cpcap-adc"),
> > +     MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0,
> > +                 "motorola,cpcap-battery"),
> > +     MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0,
> > +                 "motorola,cpcap-regulator"),
> > +     MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> > +     MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0,
> > +                 "motorola,cpcap-pwrbutton"),
> > +     MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0,
> > +                 "motorola,cpcap-usb-phy"),
> > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> > +     MFD_CELL_NAME("cpcap-codec"),
> > +};
>
> Nit: I wouldn't complain if you wanted to have all of these on a single
> line for neatness.
>

Noted

> > +static const struct mfd_cell cpcap_mapphone_mfd_devices[] = {
> > +     MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0,
> > +                 "motorola,mapphone-cpcap-adc"),
> > +     MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0,
> > +                 "motorola,cpcap-battery"),
> > +     MFD_CELL_OF("cpcap-charger", NULL, NULL, 0, 0,
> > +                 "motorola,mapphone-cpcap-charger"),
> > +     MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0,
> > +                 "motorola,mapphone-cpcap-regulator"),
> > +     MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> > +     MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0,
> > +                 "motorola,cpcap-pwrbutton"),
> > +     MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0,
> > +                 "motorola,mapphone-cpcap-usb-phy"),
> > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> > +     MFD_CELL_NAME("cpcap-codec"),
> >  };
>
> A lot of these are duplicated, right?
>
> I would have a comment set, then the differences in separate containers.

It may be impossible to predict a generic setup since some devices may
require unique compatibles, other may not have LEDs, third may be
partially incompatible with existing cells. In other mfd cases
creating a generic bundle might be good, but in this case I would
suggest better to keep these separate entirely per-device. They will
not take much space, nor add confusion with these macros.

>
> >  static int cpcap_probe(struct spi_device *spi)
> >  {
> >       struct cpcap_ddata *cpcap;
> > +     const struct mfd_cell *cells;
> > +     unsigned int num_cells;
> >       int ret;
> >
> >       cpcap = devm_kzalloc(&spi->dev, sizeof(*cpcap), GFP_KERNEL);
> >       if (!cpcap)
> >               return -ENOMEM;
> >
> > +     cpcap->variant = (enum cpcap_variant)spi_get_device_match_data(spi);
> > +     if (!cpcap->variant)
> > +             return -ENODEV;
>
> Isn't this covered in the 'default' below?
>

This is for case cpcap->variant = 0, it should never happen, but check
will not cause harm

>
> > +     switch (cpcap->variant) {
> > +     case CPCAP_DEFAULT:
> > +             cells = cpcap_default_mfd_devices;
> > +             num_cells = ARRAY_SIZE(cpcap_default_mfd_devices);
> > +             break;
> > +     case CPCAP_MAPPHONE:
> > +             cells = cpcap_mapphone_mfd_devices;
> > +             num_cells = ARRAY_SIZE(cpcap_mapphone_mfd_devices);
> > +             break;
> > +     default:
> > +             return dev_err_probe(&spi->dev, -EINVAL,
> > +                                  "Unknown device %d\n", cpcap->variant);
>
> This should be -ENODEV.
>

hm, match is ENODEV cause it looks for device, here driver checks
id/variant, so shouldn't it be EINVAL? I assume error message should
be "Unknown device version" or "Unknown device ID"

> > +     }
> > +
> >       cpcap->spi = spi;
> >       spi_set_drvdata(spi, cpcap);
> >
> > @@ -331,10 +333,28 @@ static int cpcap_probe(struct spi_device *spi)
> >       spi->dev.coherent_dma_mask = 0;
> >       spi->dev.dma_mask = &spi->dev.coherent_dma_mask;
> >
> > -     return devm_mfd_add_devices(&spi->dev, 0, cpcap_mfd_devices,
> > -                                 ARRAY_SIZE(cpcap_mfd_devices), NULL, 0, NULL);
> > +     return devm_mfd_add_devices(&spi->dev, 0, cells, num_cells, NULL, 0, NULL);
> >  }
> >
> > +static const struct of_device_id cpcap_of_match[] = {
> > +     {
> > +             .compatible = "motorola,cpcap",
> > +             .data = (void *)CPCAP_DEFAULT
>
> Single line should be fine.
>

Noted

> > +     }, {
> > +             .compatible = "motorola,mapphone-cpcap",
> > +             .data = (void *)CPCAP_MAPPHONE
> > +     },
> > +     { /* sentinel */ }
> > +};
> > +MODULE_DEVICE_TABLE(of, cpcap_of_match);
> > +
> > +static const struct spi_device_id cpcap_spi_ids[] = {
> > +     { "cpcap", CPCAP_DEFAULT },
> > +     { "mapphone-cpcap", CPCAP_MAPPHONE },
> > +     { /* sentinel */ }
> > +};
> > +MODULE_DEVICE_TABLE(spi, cpcap_spi_ids);
> > +
> >  static struct spi_driver cpcap_driver = {
> >       .driver = {
> >               .name = "cpcap-core",
> > diff --git a/include/linux/mfd/motorola-cpcap.h b/include/linux/mfd/motorola-cpcap.h
> > index 981e5777deb7..1a85b06272c8 100644
> > --- a/include/linux/mfd/motorola-cpcap.h
> > +++ b/include/linux/mfd/motorola-cpcap.h
> > @@ -25,6 +25,12 @@
> >  #define CPCAP_REVISION_2_0   0x10
> >  #define CPCAP_REVISION_2_1   0x11
> >
> > +enum cpcap_variant {
> > +     CPCAP_DEFAULT = 1,
> > +     CPCAP_MAPPHONE,
> > +     CPCAP_MAX
> > +};
> > +
> >  /* CPCAP registers */
> >  #define CPCAP_REG_INT1               0x0000  /* Interrupt 1 */
> >  #define CPCAP_REG_INT2               0x0004  /* Interrupt 2 */
> > --
> > 2.51.0
> >
>
> --
> Lee Jones

^ permalink raw reply

* Re: [PATCH v5 5/6] mfd: motorola-cpcap: diverge configuration per-board
From: Lee Jones @ 2026-05-20 16:05 UTC (permalink / raw)
  To: Svyatoslav Ryhel
  Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Pavel Machek, David Lechner, Tony Lindgren, linux-input,
	devicetree, linux-kernel, linux-leds
In-Reply-To: <CAPVz0n0t4PXfmgWYQ1vSTFwfg=+g4oGU+-dwgnBVKxUoUwHGqw@mail.gmail.com>

On Wed, 20 May 2026, Svyatoslav Ryhel wrote:

> ср, 20 трав. 2026 р. о 18:08 Lee Jones <lee@kernel.org> пише:
> >
> > On Sun, 10 May 2026, Svyatoslav Ryhel wrote:
> >
> > > MFD have rigid subdevice structure which does not allow flexible dynamic
> > > subdevice linking. Address this by diverging CPCAP subdevice composition
> > > to take into account board specific configuration.
> > >
> > > Create a common default subdevice composition, rename existing subdevice
> > > composition into cpcap_mapphone_mfd_devices since it targets mainly
> > > Mapphone board.
> > >
> > > Removed st,6556002 as it is no longer applicable to all cases and
> > > duplicates motorola,cpcap, which is used as the default composition.
> > >
> > > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > > ---
> > >  drivers/mfd/motorola-cpcap.c       | 142 ++++++++++++++++-------------
> > >  include/linux/mfd/motorola-cpcap.h |   6 ++
> > >  2 files changed, 87 insertions(+), 61 deletions(-)
> >
> > Looking much better, thanks.
> >
> > Nit: A patch-level changelog really is much more helpful to reviewers.
> >
> 
> Noted, but I will not guarantee that I will do patch-level changelogs, sorry.

That's fine.  All I can do is ask.

Note that, helping out reviewers usually ends up helping you too.

[...]

> > > +static const struct mfd_cell cpcap_default_mfd_devices[] = {
> > > +     MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,cpcap-adc"),
> > > +     MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0,
> > > +                 "motorola,cpcap-battery"),
> > > +     MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0,
> > > +                 "motorola,cpcap-regulator"),
> > > +     MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> > > +     MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0,
> > > +                 "motorola,cpcap-pwrbutton"),
> > > +     MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0,
> > > +                 "motorola,cpcap-usb-phy"),
> > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> > > +     MFD_CELL_NAME("cpcap-codec"),
> > > +};
> >
> > Nit: I wouldn't complain if you wanted to have all of these on a single
> > line for neatness.
> >
> 
> Noted
> 
> > > +static const struct mfd_cell cpcap_mapphone_mfd_devices[] = {
> > > +     MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0,
> > > +                 "motorola,mapphone-cpcap-adc"),
> > > +     MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0,
> > > +                 "motorola,cpcap-battery"),
> > > +     MFD_CELL_OF("cpcap-charger", NULL, NULL, 0, 0,
> > > +                 "motorola,mapphone-cpcap-charger"),
> > > +     MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0,
> > > +                 "motorola,mapphone-cpcap-regulator"),
> > > +     MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> > > +     MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0,
> > > +                 "motorola,cpcap-pwrbutton"),
> > > +     MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0,
> > > +                 "motorola,mapphone-cpcap-usb-phy"),
> > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> > > +     MFD_CELL_NAME("cpcap-codec"),
> > >  };
> >
> > A lot of these are duplicated, right?
> >
> > I would have a comment set, then the differences in separate containers.
> 
> It may be impossible to predict a generic setup since some devices may
> require unique compatibles, other may not have LEDs, third may be
> partially incompatible with existing cells. In other mfd cases
> creating a generic bundle might be good, but in this case I would
> suggest better to keep these separate entirely per-device. They will
> not take much space, nor add confusion with these macros.

I'm not sure we're understanding each other.  Let me give you an example:

static const struct mfd_cell cpcap_common_devices[] = {
     MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0, "motorola,cpcap-battery"),
     MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
     MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0, "motorola,cpcap-pwrbutton"),
     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
     MFD_CELL_NAME("cpcap-codec"),
};

static const struct mfd_cell cpcap_default_devices[] = {
     MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,cpcap-adc"),
     MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0, "motorola,cpcap-regulator"),
     MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0, "motorola,cpcap-usb-phy"),
};

static const struct mfd_cell cpcap_mapphone_devices[] = {
     MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-adc"),
     MFD_CELL_OF("cpcap-charger", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-charger"),
     MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-regulator"),
     MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-usb-phy"),
};

This way, it's super easy to read / maintain the common and unique devices.

The only potential drawback would be 2 calls to mfd_add_devices() but
that's common practice.

Also notice that I droped the "_mfd" parts, which you should too.

> > >  static int cpcap_probe(struct spi_device *spi)
> > >  {
> > >       struct cpcap_ddata *cpcap;
> > > +     const struct mfd_cell *cells;
> > > +     unsigned int num_cells;
> > >       int ret;
> > >
> > >       cpcap = devm_kzalloc(&spi->dev, sizeof(*cpcap), GFP_KERNEL);
> > >       if (!cpcap)
> > >               return -ENOMEM;
> > >
> > > +     cpcap->variant = (enum cpcap_variant)spi_get_device_match_data(spi);
> > > +     if (!cpcap->variant)
> > > +             return -ENODEV;
> >
> > Isn't this covered in the 'default' below?
> >
> 
> This is for case cpcap->variant = 0, it should never happen, but check
> will not cause harm

The 'default' branch in the switch below will pick that up too.  This
check is superfluous.

> > > +     switch (cpcap->variant) {
> > > +     case CPCAP_DEFAULT:
> > > +             cells = cpcap_default_mfd_devices;
> > > +             num_cells = ARRAY_SIZE(cpcap_default_mfd_devices);
> > > +             break;
> > > +     case CPCAP_MAPPHONE:
> > > +             cells = cpcap_mapphone_mfd_devices;
> > > +             num_cells = ARRAY_SIZE(cpcap_mapphone_mfd_devices);
> > > +             break;
> > > +     default:
> > > +             return dev_err_probe(&spi->dev, -EINVAL,
> > > +                                  "Unknown device %d\n", cpcap->variant);
> >
> > This should be -ENODEV.
> >
> 
> hm, match is ENODEV cause it looks for device, here driver checks
> id/variant, so shouldn't it be EINVAL? I assume error message should
> be "Unknown device version" or "Unknown device ID"

All of your supported devices are represented in this switch statement.
Any other request, regardless of the reason should results in
"Unsupported device" and a -ENODEV - same as your check for
!cpcap->variant above.

-- 
Lee Jones

^ permalink raw reply

* [PATCH v14 0/2] Firmware Support for USB-HID Devices and CP2112
From: Danny Kaehn @ 2026-05-20 16:13 UTC (permalink / raw)
  To: Benjamin Tissoires, Andy Shevchenko, Danny Kaehn, Andi Shyti,
	Conor Dooley
  Cc: Jiri Kosina, linux-input, Dmitry Torokhov, Ethan Twardy,
	linux-i2c, linux-kernel, Leo Huang, Arun D Patil, Willie Thai,
	Ting-Kai Chen, Bartosz Golaszewski

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 v14:
- Drop DT binding patch (merged upstream) (remove DT mailing lists and
  maintainers from email chain)
- Refactor logic in cp2112_probe() to reduce extra duplicate
  dev_fwnode() calls by retrieving and storing the CP2112's fwnode once
- Update comment on cp2112_child_acpi_cell_addrs enum to explain why
  values are explicitly defined
- Edit commit message for 1/2 per Andy's comments (lowercase letters in
  description; _ADR "equal to" Zero, etc..
- Edit commit message for 2/2 to use lowercase letters
- Link to v13: https://lore.kernel.org/r/20260127-cp2112-dt-v13-0-6448ddd4bf22@plexus.com

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 (2):
      HID: cp2112: Add fwnode support
      HID: cp2112: Configure I2C bus speed from firmware

 drivers/hid/hid-cp2112.c | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
---
base-commit: 70eda68668d1476b459b64e69b8f36659fa9dfa8
change-id: 20240605-cp2112-dt-7cdc95448e8a

Best regards,
-- 
Danny Kaehn <danny.kaehn@plexus.com>


^ permalink raw reply

* [PATCH v14 1/2] HID: cp2112: Add fwnode support
From: Danny Kaehn @ 2026-05-20 16:13 UTC (permalink / raw)
  To: Benjamin Tissoires, Andy Shevchenko, Danny Kaehn, Andi Shyti,
	Conor Dooley
  Cc: Jiri Kosina, linux-input, Dmitry Torokhov, Ethan Twardy,
	linux-i2c, linux-kernel, Leo Huang, Arun D Patil, Willie Thai,
	Ting-Kai Chen, Bartosz Golaszewski
In-Reply-To: <20260520-cp2112-dt-v14-0-b1b4b6734b6f@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 equal to Zero
and the gpio_chip will use the child with _ADR equal to 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 | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index 803b883ae875..e960fc988058 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -29,6 +29,18 @@
 #include <linux/usb/ch9.h>
 #include "hid-ids.h"
 
+/**
+ * enum cp2112_child_acpi_cell_addrs - Child ACPI addresses for CP2112 sub-functions
+ * Note that the enum values are explicitly defined, as this defines the interface
+ * between ACPI and Linux
+ * @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 +1220,10 @@ 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 *cp2112_fwnode;
+	struct fwnode_handle *child;
 	struct gpio_irq_chip *girq;
+	u32 addr;
 	int ret;
 
 	dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL);
@@ -1226,6 +1241,28 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		return ret;
 	}
 
+	cp2112_fwnode = dev_fwnode(&hdev->dev);
+	if (is_acpi_device_node(cp2112_fwnode)) {
+		fwnode_for_each_child_node(cp2112_fwnode, 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 if (is_of_node(cp2112_fwnode)) {
+		child = fwnode_get_named_child_node(cp2112_fwnode, "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 v14 2/2] HID: cp2112: Configure I2C bus speed from firmware
From: Danny Kaehn @ 2026-05-20 16:13 UTC (permalink / raw)
  To: Benjamin Tissoires, Andy Shevchenko, Danny Kaehn, Andi Shyti,
	Conor Dooley
  Cc: Jiri Kosina, linux-input, Dmitry Torokhov, Ethan Twardy,
	linux-i2c, linux-kernel, Leo Huang, Arun D Patil, Willie Thai,
	Ting-Kai Chen, Bartosz Golaszewski
In-Reply-To: <20260520-cp2112-dt-v14-0-b1b4b6734b6f@plexus.com>

Now that the I2C adapter on the CP2112 can have an associated firmware
node, set the bus speed based on firmware configuration

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Danny Kaehn <danny.kaehn@plexus.com>
---
 drivers/hid/hid-cp2112.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index e960fc988058..04379db93571 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -1223,6 +1223,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	struct fwnode_handle *cp2112_fwnode;
 	struct fwnode_handle *child;
 	struct gpio_irq_chip *girq;
+	struct i2c_timings timings;
 	u32 addr;
 	int ret;
 
@@ -1308,6 +1309,9 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		goto err_power_normal;
 	}
 
+	i2c_parse_fw_timings(&dev->adap.dev, &timings, true);
+
+	config.clock_speed = cpu_to_be32(timings.bus_freq_hz);
 	config.retry_time = cpu_to_be16(1);
 
 	ret = cp2112_hid_output(hdev, (u8 *)&config, sizeof(config),

-- 
2.25.1


^ permalink raw reply related

* Re: [PATCH v5 5/6] mfd: motorola-cpcap: diverge configuration per-board
From: Svyatoslav Ryhel @ 2026-05-20 16:30 UTC (permalink / raw)
  To: Lee Jones
  Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Pavel Machek, David Lechner, Tony Lindgren, linux-input,
	devicetree, linux-kernel, linux-leds
In-Reply-To: <20260520160548.GK2767592@google.com>

ср, 20 трав. 2026 р. о 19:05 Lee Jones <lee@kernel.org> пише:
>
> On Wed, 20 May 2026, Svyatoslav Ryhel wrote:
>
> > ср, 20 трав. 2026 р. о 18:08 Lee Jones <lee@kernel.org> пише:
> > >
> > > On Sun, 10 May 2026, Svyatoslav Ryhel wrote:
> > >
> > > > MFD have rigid subdevice structure which does not allow flexible dynamic
> > > > subdevice linking. Address this by diverging CPCAP subdevice composition
> > > > to take into account board specific configuration.
> > > >
> > > > Create a common default subdevice composition, rename existing subdevice
> > > > composition into cpcap_mapphone_mfd_devices since it targets mainly
> > > > Mapphone board.
> > > >
> > > > Removed st,6556002 as it is no longer applicable to all cases and
> > > > duplicates motorola,cpcap, which is used as the default composition.
> > > >
> > > > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > > > ---
> > > >  drivers/mfd/motorola-cpcap.c       | 142 ++++++++++++++++-------------
> > > >  include/linux/mfd/motorola-cpcap.h |   6 ++
> > > >  2 files changed, 87 insertions(+), 61 deletions(-)
> > >
> > > Looking much better, thanks.
> > >
> > > Nit: A patch-level changelog really is much more helpful to reviewers.
> > >
> >
> > Noted, but I will not guarantee that I will do patch-level changelogs, sorry.
>
> That's fine.  All I can do is ask.
>
> Note that, helping out reviewers usually ends up helping you too.
>
> [...]
>
> > > > +static const struct mfd_cell cpcap_default_mfd_devices[] = {
> > > > +     MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,cpcap-adc"),
> > > > +     MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0,
> > > > +                 "motorola,cpcap-battery"),
> > > > +     MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0,
> > > > +                 "motorola,cpcap-regulator"),
> > > > +     MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> > > > +     MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0,
> > > > +                 "motorola,cpcap-pwrbutton"),
> > > > +     MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0,
> > > > +                 "motorola,cpcap-usb-phy"),
> > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> > > > +     MFD_CELL_NAME("cpcap-codec"),
> > > > +};
> > >
> > > Nit: I wouldn't complain if you wanted to have all of these on a single
> > > line for neatness.
> > >
> >
> > Noted
> >
> > > > +static const struct mfd_cell cpcap_mapphone_mfd_devices[] = {
> > > > +     MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0,
> > > > +                 "motorola,mapphone-cpcap-adc"),
> > > > +     MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0,
> > > > +                 "motorola,cpcap-battery"),
> > > > +     MFD_CELL_OF("cpcap-charger", NULL, NULL, 0, 0,
> > > > +                 "motorola,mapphone-cpcap-charger"),
> > > > +     MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0,
> > > > +                 "motorola,mapphone-cpcap-regulator"),
> > > > +     MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> > > > +     MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0,
> > > > +                 "motorola,cpcap-pwrbutton"),
> > > > +     MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0,
> > > > +                 "motorola,mapphone-cpcap-usb-phy"),
> > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> > > > +     MFD_CELL_NAME("cpcap-codec"),
> > > >  };
> > >
> > > A lot of these are duplicated, right?
> > >
> > > I would have a comment set, then the differences in separate containers.
> >
> > It may be impossible to predict a generic setup since some devices may
> > require unique compatibles, other may not have LEDs, third may be
> > partially incompatible with existing cells. In other mfd cases
> > creating a generic bundle might be good, but in this case I would
> > suggest better to keep these separate entirely per-device. They will
> > not take much space, nor add confusion with these macros.
>
> I'm not sure we're understanding each other.  Let me give you an example:
>
> static const struct mfd_cell cpcap_common_devices[] = {
>      MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0, "motorola,cpcap-battery"),
>      MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
>      MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0, "motorola,cpcap-pwrbutton"),
>      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
>      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
>      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
>      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
>      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
>      MFD_CELL_NAME("cpcap-codec"),
> };
>
> static const struct mfd_cell cpcap_default_devices[] = {
>      MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,cpcap-adc"),
>      MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0, "motorola,cpcap-regulator"),
>      MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0, "motorola,cpcap-usb-phy"),
> };
>
> static const struct mfd_cell cpcap_mapphone_devices[] = {
>      MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-adc"),
>      MFD_CELL_OF("cpcap-charger", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-charger"),
>      MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-regulator"),
>      MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-usb-phy"),
> };
>
> This way, it's super easy to read / maintain the common and unique devices.
>
> The only potential drawback would be 2 calls to mfd_add_devices() but
> that's common practice.
>
> Also notice that I droped the "_mfd" parts, which you should too.
>

What if next added device does not have cpcap-battery, cpcap-led-adl,
cpcap-pwrbutton, uses external codec and would require cpcap-watchdog
which is not yet present. This will cause issues. Even Mot introduces
in the last patch of this patchset has slightly different composition.

> > > >  static int cpcap_probe(struct spi_device *spi)
> > > >  {
> > > >       struct cpcap_ddata *cpcap;
> > > > +     const struct mfd_cell *cells;
> > > > +     unsigned int num_cells;
> > > >       int ret;
> > > >
> > > >       cpcap = devm_kzalloc(&spi->dev, sizeof(*cpcap), GFP_KERNEL);
> > > >       if (!cpcap)
> > > >               return -ENOMEM;
> > > >
> > > > +     cpcap->variant = (enum cpcap_variant)spi_get_device_match_data(spi);
> > > > +     if (!cpcap->variant)
> > > > +             return -ENODEV;
> > >
> > > Isn't this covered in the 'default' below?
> > >
> >
> > This is for case cpcap->variant = 0, it should never happen, but check
> > will not cause harm
>
> The 'default' branch in the switch below will pick that up too.  This
> check is superfluous.
>

Noted

> > > > +     switch (cpcap->variant) {
> > > > +     case CPCAP_DEFAULT:
> > > > +             cells = cpcap_default_mfd_devices;
> > > > +             num_cells = ARRAY_SIZE(cpcap_default_mfd_devices);
> > > > +             break;
> > > > +     case CPCAP_MAPPHONE:
> > > > +             cells = cpcap_mapphone_mfd_devices;
> > > > +             num_cells = ARRAY_SIZE(cpcap_mapphone_mfd_devices);
> > > > +             break;
> > > > +     default:
> > > > +             return dev_err_probe(&spi->dev, -EINVAL,
> > > > +                                  "Unknown device %d\n", cpcap->variant);
> > >
> > > This should be -ENODEV.
> > >
> >
> > hm, match is ENODEV cause it looks for device, here driver checks
> > id/variant, so shouldn't it be EINVAL? I assume error message should
> > be "Unknown device version" or "Unknown device ID"
>
> All of your supported devices are represented in this switch statement.
> Any other request, regardless of the reason should results in
> "Unsupported device" and a -ENODEV - same as your check for
> !cpcap->variant above.
>

Noted

> --
> Lee Jones

^ permalink raw reply

* Re: [PATCH v14 1/2] HID: cp2112: Add fwnode support
From: sashiko-bot @ 2026-05-20 17:02 UTC (permalink / raw)
  To: Danny Kaehn; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260520-cp2112-dt-v14-1-b1b4b6734b6f@plexus.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Premature release of firmware node references results in use-after-free vulnerabilities when assigning the I2C adapter and GPIO chip firmware nodes.
--

commit 3dfaf368e855835bf23009205c4b93a2a070aae1
Author: Danny Kaehn <danny.kaehn@plexus.com>

HID: cp2112: Add fwnode support

This commit adds firmware node support to describe the CP2112's I2C and
GPIO interfaces. It differentiates between ACPI and DeviceTree bindings,
mapping the child nodes to the respective adapter and gpio_chip devices.

> diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
> index 803b883ae8750..e960fc988058f 100644
> --- a/drivers/hid/hid-cp2112.c
> +++ b/drivers/hid/hid-cp2112.c
[ ... ]
> @@ -1226,6 +1241,28 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
>  		return ret;
>  	}
>  
> +	cp2112_fwnode = dev_fwnode(&hdev->dev);
> +	if (is_acpi_device_node(cp2112_fwnode)) {
> +		fwnode_for_each_child_node(cp2112_fwnode, 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;
> +			}

[Severity: High]
Does this code leave dangling pointers in the device structures?

The fwnode_for_each_child_node() macro automatically drops the reference to
the child node when advancing to the next node or exiting the loop.

Because device_set_node() and direct pointer assignments do not increment
the reference count, the nodes assigned here could be prematurely freed
resulting in a use-after-free.

> +		}
> +	} else if (is_of_node(cp2112_fwnode)) {
> +		child = fwnode_get_named_child_node(cp2112_fwnode, "i2c");
> +		device_set_node(&dev->adap.dev, child);
> +		fwnode_handle_put(child);

[Severity: High]
Are we releasing the firmware node prematurely here?

fwnode_get_named_child_node() returns a node with an incremented reference
count. However, since device_set_node() does not take its own reference on
the child node, dropping the reference immediately after could leave
dev->adap.dev with a dangling pointer if the node is later removed.

> +	}
> +
>  	ret = hid_parse(hdev);
>  	if (ret) {
>  		hid_err(hdev, "parse failed\n");

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260520-cp2112-dt-v14-0-b1b4b6734b6f@plexus.com?part=1

^ permalink raw reply

* Re: [PATCH v5 5/6] mfd: motorola-cpcap: diverge configuration per-board
From: Lee Jones @ 2026-05-20 17:02 UTC (permalink / raw)
  To: Svyatoslav Ryhel
  Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Pavel Machek, David Lechner, Tony Lindgren, linux-input,
	devicetree, linux-kernel, linux-leds
In-Reply-To: <CAPVz0n2s32uYP76R9VNtWYnHrDQJKK+qC1uRRdkaX1ekF15Pww@mail.gmail.com>

On Wed, 20 May 2026, Svyatoslav Ryhel wrote:

> ср, 20 трав. 2026 р. о 19:05 Lee Jones <lee@kernel.org> пише:
> >
> > On Wed, 20 May 2026, Svyatoslav Ryhel wrote:
> >
> > > ср, 20 трав. 2026 р. о 18:08 Lee Jones <lee@kernel.org> пише:
> > > >
> > > > On Sun, 10 May 2026, Svyatoslav Ryhel wrote:
> > > >
> > > > > MFD have rigid subdevice structure which does not allow flexible dynamic
> > > > > subdevice linking. Address this by diverging CPCAP subdevice composition
> > > > > to take into account board specific configuration.
> > > > >
> > > > > Create a common default subdevice composition, rename existing subdevice
> > > > > composition into cpcap_mapphone_mfd_devices since it targets mainly
> > > > > Mapphone board.
> > > > >
> > > > > Removed st,6556002 as it is no longer applicable to all cases and
> > > > > duplicates motorola,cpcap, which is used as the default composition.
> > > > >
> > > > > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > > > > ---
> > > > >  drivers/mfd/motorola-cpcap.c       | 142 ++++++++++++++++-------------
> > > > >  include/linux/mfd/motorola-cpcap.h |   6 ++
> > > > >  2 files changed, 87 insertions(+), 61 deletions(-)
> > > >
> > > > Looking much better, thanks.
> > > >
> > > > Nit: A patch-level changelog really is much more helpful to reviewers.
> > > >
> > >
> > > Noted, but I will not guarantee that I will do patch-level changelogs, sorry.
> >
> > That's fine.  All I can do is ask.
> >
> > Note that, helping out reviewers usually ends up helping you too.
> >
> > [...]
> >
> > > > > +static const struct mfd_cell cpcap_default_mfd_devices[] = {
> > > > > +     MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,cpcap-adc"),
> > > > > +     MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0,
> > > > > +                 "motorola,cpcap-battery"),
> > > > > +     MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0,
> > > > > +                 "motorola,cpcap-regulator"),
> > > > > +     MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> > > > > +     MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0,
> > > > > +                 "motorola,cpcap-pwrbutton"),
> > > > > +     MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0,
> > > > > +                 "motorola,cpcap-usb-phy"),
> > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> > > > > +     MFD_CELL_NAME("cpcap-codec"),
> > > > > +};
> > > >
> > > > Nit: I wouldn't complain if you wanted to have all of these on a single
> > > > line for neatness.
> > > >
> > >
> > > Noted
> > >
> > > > > +static const struct mfd_cell cpcap_mapphone_mfd_devices[] = {
> > > > > +     MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0,
> > > > > +                 "motorola,mapphone-cpcap-adc"),
> > > > > +     MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0,
> > > > > +                 "motorola,cpcap-battery"),
> > > > > +     MFD_CELL_OF("cpcap-charger", NULL, NULL, 0, 0,
> > > > > +                 "motorola,mapphone-cpcap-charger"),
> > > > > +     MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0,
> > > > > +                 "motorola,mapphone-cpcap-regulator"),
> > > > > +     MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> > > > > +     MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0,
> > > > > +                 "motorola,cpcap-pwrbutton"),
> > > > > +     MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0,
> > > > > +                 "motorola,mapphone-cpcap-usb-phy"),
> > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> > > > > +     MFD_CELL_NAME("cpcap-codec"),
> > > > >  };
> > > >
> > > > A lot of these are duplicated, right?
> > > >
> > > > I would have a comment set, then the differences in separate containers.
> > >
> > > It may be impossible to predict a generic setup since some devices may
> > > require unique compatibles, other may not have LEDs, third may be
> > > partially incompatible with existing cells. In other mfd cases
> > > creating a generic bundle might be good, but in this case I would
> > > suggest better to keep these separate entirely per-device. They will
> > > not take much space, nor add confusion with these macros.
> >
> > I'm not sure we're understanding each other.  Let me give you an example:
> >
> > static const struct mfd_cell cpcap_common_devices[] = {
> >      MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0, "motorola,cpcap-battery"),
> >      MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> >      MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0, "motorola,cpcap-pwrbutton"),
> >      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> >      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> >      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> >      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> >      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> >      MFD_CELL_NAME("cpcap-codec"),
> > };
> >
> > static const struct mfd_cell cpcap_default_devices[] = {
> >      MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,cpcap-adc"),
> >      MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0, "motorola,cpcap-regulator"),
> >      MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0, "motorola,cpcap-usb-phy"),
> > };
> >
> > static const struct mfd_cell cpcap_mapphone_devices[] = {
> >      MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-adc"),
> >      MFD_CELL_OF("cpcap-charger", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-charger"),
> >      MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-regulator"),
> >      MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-usb-phy"),
> > };
> >
> > This way, it's super easy to read / maintain the common and unique devices.
> >
> > The only potential drawback would be 2 calls to mfd_add_devices() but
> > that's common practice.
> >
> > Also notice that I droped the "_mfd" parts, which you should too.
> >
> 
> What if next added device does not have cpcap-battery, cpcap-led-adl,
> cpcap-pwrbutton, uses external codec and would require cpcap-watchdog
> which is not yet present. This will cause issues. Even Mot introduces
> in the last patch of this patchset has slightly different composition.

We usually just code-up what we have _today_.

If new devices come in with different requirements, it takes 5 mins to rejig.

-- 
Lee Jones

^ permalink raw reply

* [syzbot] [input?] possible deadlock in tasklet_action_common (2)
From: syzbot @ 2026-05-20 17:05 UTC (permalink / raw)
  To: dmitry.torokhov, linux-input, linux-kernel, syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    e98d21c170b0 Add linux-next specific files for 20260508
git tree:       linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=1354bfce580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=59b98218d9b2edf4
dashboard link: https://syzkaller.appspot.com/bug?extid=b5d7ab56d43de3fd5aac
compiler:       Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8

Unfortunately, I don't have any reproducer for this issue yet.

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/66f2a00ee290/disk-e98d21c1.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/6b982257ce9e/vmlinux-e98d21c1.xz
kernel image: https://storage.googleapis.com/syzbot-assets/a73fbea43e1a/bzImage-e98d21c1.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+b5d7ab56d43de3fd5aac@syzkaller.appspotmail.com

======================================================
WARNING: possible circular locking dependency detected
syzkaller #0 Tainted: G             L     
------------------------------------------------------
syz.2.4328/32663 is trying to acquire lock:
ffff8880b8724168 (tasklet_sync_callback.cb_lock){+...}-{3:3}, at: spin_lock include/linux/spinlock_rt.h:45 [inline]
ffff8880b8724168 (tasklet_sync_callback.cb_lock){+...}-{3:3}, at: tasklet_lock_callback kernel/softirq.c:881 [inline]
ffff8880b8724168 (tasklet_sync_callback.cb_lock){+...}-{3:3}, at: tasklet_action_common+0xc5/0x610 kernel/softirq.c:931

but task is already holding lock:
ffff888058598270 (&dev->event_lock#2){+.+.}-{3:3}, at: spin_lock include/linux/spinlock_rt.h:45 [inline]
ffff888058598270 (&dev->event_lock#2){+.+.}-{3:3}, at: class_spinlock_irqsave_constructor include/linux/spinlock.h:619 [inline]
ffff888058598270 (&dev->event_lock#2){+.+.}-{3:3}, at: input_inject_event+0xa4/0x320 drivers/input/input.c:419

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #1 (&dev->event_lock#2){+.+.}-{3:3}:
       rt_spin_lock+0x83/0x400 kernel/locking/spinlock_rt.c:56
       spin_lock include/linux/spinlock_rt.h:45 [inline]
       class_spinlock_irqsave_constructor include/linux/spinlock.h:619 [inline]
       input_inject_event+0xa4/0x320 drivers/input/input.c:419
       led_trigger_event+0x13b/0x220 drivers/leds/led-triggers.c:420
       kbd_propagate_led_state drivers/tty/vt/keyboard.c:1118 [inline]
       kbd_bh+0x1b4/0x2c0 drivers/tty/vt/keyboard.c:1297
       tasklet_action_common+0x31c/0x610 kernel/softirq.c:942
       handle_softirqs+0x1de/0x6d0 kernel/softirq.c:626
       __do_softirq kernel/softirq.c:660 [inline]
       run_ktimerd+0x69/0x100 kernel/softirq.c:1155
       smpboot_thread_fn+0x541/0xa50 kernel/smpboot.c:160
       kthread+0x388/0x470 kernel/kthread.c:436
       ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
       ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

-> #0 (tasklet_sync_callback.cb_lock){+...}-{3:3}:
       check_prev_add kernel/locking/lockdep.c:3167 [inline]
       check_prevs_add kernel/locking/lockdep.c:3286 [inline]
       validate_chain kernel/locking/lockdep.c:3910 [inline]
       __lock_acquire+0x15a5/0x2d10 kernel/locking/lockdep.c:5239
       lock_acquire+0x106/0x350 kernel/locking/lockdep.c:5870
       rt_spin_lock+0x83/0x400 kernel/locking/spinlock_rt.c:56
       spin_lock include/linux/spinlock_rt.h:45 [inline]
       tasklet_lock_callback kernel/softirq.c:881 [inline]
       tasklet_action_common+0xc5/0x610 kernel/softirq.c:931
       handle_softirqs+0x1de/0x6d0 kernel/softirq.c:626
       __do_softirq kernel/softirq.c:660 [inline]
       __local_bh_enable_ip+0x170/0x2b0 kernel/softirq.c:302
       local_bh_enable include/linux/bottom_half.h:33 [inline]
       __alloc_skb+0x1aa/0x7d0 net/core/skbuff.c:697
       alloc_skb include/linux/skbuff.h:1381 [inline]
       hidp_send_message+0xb5/0x230 net/bluetooth/hidp/core.c:111
       hidp_send_intr_message net/bluetooth/hidp/core.c:143 [inline]
       hidp_input_event+0x2a4/0x380 net/bluetooth/hidp/core.c:175
       input_event_dispose+0x80/0x6b0 drivers/input/input.c:322
       input_inject_event+0x1d7/0x320 drivers/input/input.c:424
       kbd_led_trigger_activate+0xbc/0x100 drivers/tty/vt/keyboard.c:1074
       led_trigger_set+0x53b/0x960 drivers/leds/led-triggers.c:220
       led_match_default_trigger drivers/leds/led-triggers.c:277 [inline]
       led_trigger_set_default+0x266/0x2a0 drivers/leds/led-triggers.c:300
       led_classdev_register_ext+0x787/0x9c0 drivers/leds/led-class.c:581
       led_classdev_register include/linux/leds.h:274 [inline]
       input_leds_connect+0x517/0x790 drivers/input/input-leds.c:145
       input_attach_handler drivers/input/input.c:1011 [inline]
       input_register_device+0xce0/0x1140 drivers/input/input.c:2395
       hidp_session_dev_add net/bluetooth/hidp/core.c:861 [inline]
       hidp_session_probe+0x1a5/0x8a0 net/bluetooth/hidp/core.c:1139
       l2cap_register_user+0xc2/0x1d0 net/bluetooth/l2cap_core.c:1725
       hidp_connection_add+0x158b/0x1a20 net/bluetooth/hidp/core.c:1411
       do_hidp_sock_ioctl net/bluetooth/hidp/sock.c:81 [inline]
       hidp_sock_ioctl+0x403/0x650 net/bluetooth/hidp/sock.c:128
       sock_do_ioctl+0x101/0x320 net/socket.c:1328
       sock_ioctl+0x5c9/0x7f0 net/socket.c:1449
       vfs_ioctl fs/ioctl.c:51 [inline]
       __do_sys_ioctl fs/ioctl.c:597 [inline]
       __se_sys_ioctl+0xff/0x170 fs/ioctl.c:583
       do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
       do_syscall_64+0x15f/0xf80 arch/x86/entry/syscall_64.c:94
       entry_SYSCALL_64_after_hwframe+0x77/0x7f

other info that might help us debug this:

 Possible unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  lock(&dev->event_lock#2);
                               lock(tasklet_sync_callback.cb_lock);
                               lock(&dev->event_lock#2);
  lock(tasklet_sync_callback.cb_lock);

 *** DEADLOCK ***

10 locks held by syz.2.4328/32663:
 #0: ffff88805ebb3370 (&conn->lock#2){+.+.}-{4:4}, at: l2cap_register_user+0x35/0x1d0 net/bluetooth/l2cap_core.c:1712
 #1: ffffffff8f73d960 (hidp_session_sem){++++}-{4:4}, at: hidp_session_probe+0x98/0x8a0 net/bluetooth/hidp/core.c:1129
 #2: ffffffff8f006e58 (input_mutex){+.+.}-{4:4}, at: class_mutex_intr_constructor include/linux/mutex.h:255 [inline]
 #2: ffffffff8f006e58 (input_mutex){+.+.}-{4:4}, at: input_register_device+0xa56/0x1140 drivers/input/input.c:2391
 #3: ffff8880125ea860 (&led_cdev->led_access){+.+.}-{4:4}, at: led_classdev_register_ext+0x484/0x9c0 drivers/leds/led-class.c:539
 #4: ffffffff8e9c4400 (triggers_list_lock){++++}-{4:4}, at: led_trigger_set_default+0x77/0x2a0 drivers/leds/led-triggers.c:297
 #5: ffff8880125ea788 (&led_cdev->trigger_lock){+.+.}-{4:4}, at: led_trigger_set_default+0x87/0x2a0 drivers/leds/led-triggers.c:298
 #6: ffff888058598270 (&dev->event_lock#2){+.+.}-{3:3}, at: spin_lock include/linux/spinlock_rt.h:45 [inline]
 #6: ffff888058598270 (&dev->event_lock#2){+.+.}-{3:3}, at: class_spinlock_irqsave_constructor include/linux/spinlock.h:619 [inline]
 #6: ffff888058598270 (&dev->event_lock#2){+.+.}-{3:3}, at: input_inject_event+0xa4/0x320 drivers/input/input.c:419
 #7: ffffffff8e1c8240 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire include/linux/rcupdate.h:300 [inline]
 #7: ffffffff8e1c8240 (rcu_read_lock){....}-{1:3}, at: rcu_read_lock include/linux/rcupdate.h:838 [inline]
 #7: ffffffff8e1c8240 (rcu_read_lock){....}-{1:3}, at: __rt_spin_lock kernel/locking/spinlock_rt.c:50 [inline]
 #7: ffffffff8e1c8240 (rcu_read_lock){....}-{1:3}, at: rt_spin_lock+0x1e0/0x400 kernel/locking/spinlock_rt.c:57
 #8: ffffffff8e1c8240 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire include/linux/rcupdate.h:300 [inline]
 #8: ffffffff8e1c8240 (rcu_read_lock){....}-{1:3}, at: rcu_read_lock include/linux/rcupdate.h:838 [inline]
 #8: ffffffff8e1c8240 (rcu_read_lock){....}-{1:3}, at: class_rcu_constructor include/linux/rcupdate.h:1181 [inline]
 #8: ffffffff8e1c8240 (rcu_read_lock){....}-{1:3}, at: input_inject_event+0xb0/0x320 drivers/input/input.c:420
 #9: ffffffff8e1c8240 (rcu_read_lock){....}-{1:3}, at: __local_bh_disable_ip+0x3c/0x420 kernel/softirq.c:163

stack backtrace:
CPU: 1 UID: 0 PID: 32663 Comm: syz.2.4328 Tainted: G             L      syzkaller #0 PREEMPT_{RT,(full)} 
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
Call Trace:
 <TASK>
 dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
 print_circular_bug+0x2e1/0x300 kernel/locking/lockdep.c:2045
 check_noncircular+0x12e/0x150 kernel/locking/lockdep.c:2177
 check_prev_add kernel/locking/lockdep.c:3167 [inline]
 check_prevs_add kernel/locking/lockdep.c:3286 [inline]
 validate_chain kernel/locking/lockdep.c:3910 [inline]
 __lock_acquire+0x15a5/0x2d10 kernel/locking/lockdep.c:5239
 lock_acquire+0x106/0x350 kernel/locking/lockdep.c:5870
 rt_spin_lock+0x83/0x400 kernel/locking/spinlock_rt.c:56
 spin_lock include/linux/spinlock_rt.h:45 [inline]
 tasklet_lock_callback kernel/softirq.c:881 [inline]
 tasklet_action_common+0xc5/0x610 kernel/softirq.c:931
 handle_softirqs+0x1de/0x6d0 kernel/softirq.c:626
 __do_softirq kernel/softirq.c:660 [inline]
 __local_bh_enable_ip+0x170/0x2b0 kernel/softirq.c:302
 local_bh_enable include/linux/bottom_half.h:33 [inline]
 __alloc_skb+0x1aa/0x7d0 net/core/skbuff.c:697
 alloc_skb include/linux/skbuff.h:1381 [inline]
 hidp_send_message+0xb5/0x230 net/bluetooth/hidp/core.c:111
 hidp_send_intr_message net/bluetooth/hidp/core.c:143 [inline]
 hidp_input_event+0x2a4/0x380 net/bluetooth/hidp/core.c:175
 input_event_dispose+0x80/0x6b0 drivers/input/input.c:322
 input_inject_event+0x1d7/0x320 drivers/input/input.c:424
 kbd_led_trigger_activate+0xbc/0x100 drivers/tty/vt/keyboard.c:1074
 led_trigger_set+0x53b/0x960 drivers/leds/led-triggers.c:220
 led_match_default_trigger drivers/leds/led-triggers.c:277 [inline]
 led_trigger_set_default+0x266/0x2a0 drivers/leds/led-triggers.c:300
 led_classdev_register_ext+0x787/0x9c0 drivers/leds/led-class.c:581
 led_classdev_register include/linux/leds.h:274 [inline]
 input_leds_connect+0x517/0x790 drivers/input/input-leds.c:145
 input_attach_handler drivers/input/input.c:1011 [inline]
 input_register_device+0xce0/0x1140 drivers/input/input.c:2395
 hidp_session_dev_add net/bluetooth/hidp/core.c:861 [inline]
 hidp_session_probe+0x1a5/0x8a0 net/bluetooth/hidp/core.c:1139
 l2cap_register_user+0xc2/0x1d0 net/bluetooth/l2cap_core.c:1725
 hidp_connection_add+0x158b/0x1a20 net/bluetooth/hidp/core.c:1411
 do_hidp_sock_ioctl net/bluetooth/hidp/sock.c:81 [inline]
 hidp_sock_ioctl+0x403/0x650 net/bluetooth/hidp/sock.c:128
 sock_do_ioctl+0x101/0x320 net/socket.c:1328
 sock_ioctl+0x5c9/0x7f0 net/socket.c:1449
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:597 [inline]
 __se_sys_ioctl+0xff/0x170 fs/ioctl.c:583
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x15f/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fcb5e6cce59
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fcb5c905028 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007fcb5e946090 RCX: 00007fcb5e6cce59
RDX: 00002000000000c0 RSI: 00000000400448c8 RDI: 0000000000000009
RBP: 00007fcb5e762d6f R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fcb5e946128 R14: 00007fcb5e946090 R15: 00007ffddb8adae8
 </TASK>


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

^ permalink raw reply

* Re: [PATCH v5 5/6] mfd: motorola-cpcap: diverge configuration per-board
From: Svyatoslav Ryhel @ 2026-05-20 17:25 UTC (permalink / raw)
  To: Lee Jones
  Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Pavel Machek, David Lechner, Tony Lindgren, linux-input,
	devicetree, linux-kernel, linux-leds
In-Reply-To: <20260520170234.GN2767592@google.com>

ср, 20 трав. 2026 р. о 20:02 Lee Jones <lee@kernel.org> пише:
>
> On Wed, 20 May 2026, Svyatoslav Ryhel wrote:
>
> > ср, 20 трав. 2026 р. о 19:05 Lee Jones <lee@kernel.org> пише:
> > >
> > > On Wed, 20 May 2026, Svyatoslav Ryhel wrote:
> > >
> > > > ср, 20 трав. 2026 р. о 18:08 Lee Jones <lee@kernel.org> пише:
> > > > >
> > > > > On Sun, 10 May 2026, Svyatoslav Ryhel wrote:
> > > > >
> > > > > > MFD have rigid subdevice structure which does not allow flexible dynamic
> > > > > > subdevice linking. Address this by diverging CPCAP subdevice composition
> > > > > > to take into account board specific configuration.
> > > > > >
> > > > > > Create a common default subdevice composition, rename existing subdevice
> > > > > > composition into cpcap_mapphone_mfd_devices since it targets mainly
> > > > > > Mapphone board.
> > > > > >
> > > > > > Removed st,6556002 as it is no longer applicable to all cases and
> > > > > > duplicates motorola,cpcap, which is used as the default composition.
> > > > > >
> > > > > > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > > > > > ---
> > > > > >  drivers/mfd/motorola-cpcap.c       | 142 ++++++++++++++++-------------
> > > > > >  include/linux/mfd/motorola-cpcap.h |   6 ++
> > > > > >  2 files changed, 87 insertions(+), 61 deletions(-)
> > > > >
> > > > > Looking much better, thanks.
> > > > >
> > > > > Nit: A patch-level changelog really is much more helpful to reviewers.
> > > > >
> > > >
> > > > Noted, but I will not guarantee that I will do patch-level changelogs, sorry.
> > >
> > > That's fine.  All I can do is ask.
> > >
> > > Note that, helping out reviewers usually ends up helping you too.
> > >
> > > [...]
> > >
> > > > > > +static const struct mfd_cell cpcap_default_mfd_devices[] = {
> > > > > > +     MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,cpcap-adc"),
> > > > > > +     MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0,
> > > > > > +                 "motorola,cpcap-battery"),
> > > > > > +     MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0,
> > > > > > +                 "motorola,cpcap-regulator"),
> > > > > > +     MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> > > > > > +     MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0,
> > > > > > +                 "motorola,cpcap-pwrbutton"),
> > > > > > +     MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0,
> > > > > > +                 "motorola,cpcap-usb-phy"),
> > > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> > > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> > > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> > > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> > > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> > > > > > +     MFD_CELL_NAME("cpcap-codec"),
> > > > > > +};
> > > > >
> > > > > Nit: I wouldn't complain if you wanted to have all of these on a single
> > > > > line for neatness.
> > > > >
> > > >
> > > > Noted
> > > >
> > > > > > +static const struct mfd_cell cpcap_mapphone_mfd_devices[] = {
> > > > > > +     MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0,
> > > > > > +                 "motorola,mapphone-cpcap-adc"),
> > > > > > +     MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0,
> > > > > > +                 "motorola,cpcap-battery"),
> > > > > > +     MFD_CELL_OF("cpcap-charger", NULL, NULL, 0, 0,
> > > > > > +                 "motorola,mapphone-cpcap-charger"),
> > > > > > +     MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0,
> > > > > > +                 "motorola,mapphone-cpcap-regulator"),
> > > > > > +     MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> > > > > > +     MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0,
> > > > > > +                 "motorola,cpcap-pwrbutton"),
> > > > > > +     MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0,
> > > > > > +                 "motorola,mapphone-cpcap-usb-phy"),
> > > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> > > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> > > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> > > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> > > > > > +     MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> > > > > > +     MFD_CELL_NAME("cpcap-codec"),
> > > > > >  };
> > > > >
> > > > > A lot of these are duplicated, right?
> > > > >
> > > > > I would have a comment set, then the differences in separate containers.
> > > >
> > > > It may be impossible to predict a generic setup since some devices may
> > > > require unique compatibles, other may not have LEDs, third may be
> > > > partially incompatible with existing cells. In other mfd cases
> > > > creating a generic bundle might be good, but in this case I would
> > > > suggest better to keep these separate entirely per-device. They will
> > > > not take much space, nor add confusion with these macros.
> > >
> > > I'm not sure we're understanding each other.  Let me give you an example:
> > >
> > > static const struct mfd_cell cpcap_common_devices[] = {
> > >      MFD_CELL_OF("cpcap_battery", NULL, NULL, 0, 0, "motorola,cpcap-battery"),
> > >      MFD_CELL_OF("cpcap-rtc", NULL, NULL, 0, 0, "motorola,cpcap-rtc"),
> > >      MFD_CELL_OF("cpcap-pwrbutton", NULL, NULL, 0, 0, "motorola,cpcap-pwrbutton"),
> > >      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 0, "motorola,cpcap-led-red"),
> > >      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 1, "motorola,cpcap-led-green"),
> > >      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 2, "motorola,cpcap-led-blue"),
> > >      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 3, "motorola,cpcap-led-adl"),
> > >      MFD_CELL_OF("cpcap-led", NULL, NULL, 0, 4, "motorola,cpcap-led-cp"),
> > >      MFD_CELL_NAME("cpcap-codec"),
> > > };
> > >
> > > static const struct mfd_cell cpcap_default_devices[] = {
> > >      MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,cpcap-adc"),
> > >      MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0, "motorola,cpcap-regulator"),
> > >      MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0, "motorola,cpcap-usb-phy"),
> > > };
> > >
> > > static const struct mfd_cell cpcap_mapphone_devices[] = {
> > >      MFD_CELL_OF("cpcap_adc", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-adc"),
> > >      MFD_CELL_OF("cpcap-charger", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-charger"),
> > >      MFD_CELL_OF("cpcap-regulator", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-regulator"),
> > >      MFD_CELL_OF("cpcap-usb-phy", NULL, NULL, 0, 0, "motorola,mapphone-cpcap-usb-phy"),
> > > };
> > >
> > > This way, it's super easy to read / maintain the common and unique devices.
> > >
> > > The only potential drawback would be 2 calls to mfd_add_devices() but
> > > that's common practice.
> > >
> > > Also notice that I droped the "_mfd" parts, which you should too.
> > >
> >
> > What if next added device does not have cpcap-battery, cpcap-led-adl,
> > cpcap-pwrbutton, uses external codec and would require cpcap-watchdog
> > which is not yet present. This will cause issues. Even Mot introduces
> > in the last patch of this patchset has slightly different composition.
>
> We usually just code-up what we have _today_.
>
> If new devices come in with different requirements, it takes 5 mins to rejig.
>

Ok, but I will take into account Mot commit when factoring out common.

> --
> Lee Jones

^ permalink raw reply

* Re: [PATCH v14 2/2] HID: cp2112: Configure I2C bus speed from firmware
From: sashiko-bot @ 2026-05-20 17:44 UTC (permalink / raw)
  To: Danny Kaehn; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260520-cp2112-dt-v14-2-b1b4b6734b6f@plexus.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [Medium] The driver silently overwrites custom hardware I2C clock speeds with a 100kHz default for devices without firmware nodes.

Pre-existing issues:
- [High] Firmware nodes are attached to device structures without holding a reference, leading to a dangling pointer and use-after-free.
- [High] The delayed work `gpio_poll_worker` is not canceled in the probe error path, leading to a use-after-free if the probe fails.
--

commit 07ff467e4d8df706a7a27476591cd82570fb8287
Author: Danny Kaehn <danny.kaehn@plexus.com>

    HID: cp2112: Configure I2C bus speed from firmware
    
    Now that the I2C adapter on the CP2112 can have an associated firmware
    node, set the bus speed based on firmware configuration.

> diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
> index e960fc988058f..04379db93571b 100644
> --- a/drivers/hid/hid-cp2112.c
> +++ b/drivers/hid/hid-cp2112.c
[ ... ]
> @@ -1308,6 +1309,9 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
>  		goto err_power_normal;
>  	}
>  
> +	i2c_parse_fw_timings(&dev->adap.dev, &timings, true);
> +

[Severity: High]
This isn't a bug introduced by this patch, but does this new call dereference
a dangling pointer?

Earlier in cp2112_probe(), the reference to the child firmware node is
dropped either explicitly via fwnode_handle_put(child) in the OF path, or
implicitly when the fwnode_for_each_child_node loop iterates or completes
in the ACPI path:

	} else if (is_of_node(cp2112_fwnode)) {
		child = fwnode_get_named_child_node(cp2112_fwnode, "i2c");
		device_set_node(&dev->adap.dev, child);
		fwnode_handle_put(child);
	}

device_set_node(&dev->adap.dev, child) assigns the pointer without taking
its own reference, leaving dev->adap.dev.fwnode as a dangling pointer.

This newly added i2c_parse_fw_timings() call dereferences this released
fwnode via device_property_read_u32().

Could this lead to a use-after-free?

> +	config.clock_speed = cpu_to_be32(timings.bus_freq_hz);

[Severity: Medium]
Since use_defaults is set to true, does this overwrite custom hardware I2C
clock speeds with a 100kHz default for devices without firmware nodes?

Before this patch, it looks like cp2112_probe() read the current SMBus
configuration from the device, only modified retry_time, and wrote it back.
This preserved the device's original configured clock speed (which might be
set to 400kHz in the EEPROM).

By calling i2c_parse_fw_timings() with an uninitialized local timings
struct and use_defaults = true, timings.bus_freq_hz will be
unconditionally set to 100kHz if the device lacks a firmware property.

Is it intended to silently downgrade the speed and override user-configured
EEPROM settings?

[Severity: High]
This is a pre-existing issue, but is there a missing cancellation of the
delayed work in the probe error path?

If sysfs_create_group() fails during probe, the code jumps to the
err_gpiochip_remove label, which calls gpiochip_remove(&dev->gc) and
returns:

	ret = sysfs_create_group(&hdev->dev.kobj, &cp2112_attr_group);
	if (ret < 0) {
		...
		goto err_gpiochip_remove;
	}
	...
err_gpiochip_remove:
	gpiochip_remove(&dev->gc);
err_free_i2c:

Because gpiochip_add_data() was already called, an IRQ consumer could have
concurrently requested a GPIO line, triggering cp2112_gpio_irq_startup()
and queuing dev->gpio_poll_worker.

Unlike cp2112_remove(), the error path lacks a call to
cancel_delayed_work_sync(&dev->gpio_poll_worker).

Could this mean the queued work will execute on freed memory?

>  	config.retry_time = cpu_to_be16(1);
>  
>  	ret = cp2112_hid_output(hdev, (u8 *)&config, sizeof(config),

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260520-cp2112-dt-v14-0-b1b4b6734b6f@plexus.com?part=2

^ permalink raw reply

* [PATCH v6 0/6] mfd: cpcap: convert documentation to schema and add Mot board support
From: Svyatoslav Ryhel @ 2026-05-20 18:21 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Lee Jones, Pavel Machek, Svyatoslav Ryhel
  Cc: linux-input, devicetree, linux-kernel, linux-leds

The initial goal was only to add support for the CPCAP used in the Mot
Tegra20 board; however, since the documentation was already partially
converted, I decided to complete the conversion to schema too.

The CPCAP regulator, leds, rtc, pwrbutton and core files were converted
from TXT to YAML while preserving the original structure. Mot board
compatibility was added to the regulator and core schema. Since these
were one-line patches, they were not separated into dedicated commits;
however, the commit message notes this for both cases.

Finally, the CPCAP MFD was slightly refactored to improve support for
multiple subcell compositions.

---
Changes in v2:
- fixed code style
- rtc conversion was picked, so patch dropped
- added audio ports description into mfd schema
- splitted schema conversion and compatible addition
- minor style improvements and typo fixes

Changes in v3:
- added regulator node names list into pattern
- filled spi_device_id with driver data
- ADC patches were picked, so changes dropped

Changes in v4:
- dropped regulator patches (applied)

Changes in v5:
- switched to MFD_CELL_* macros
- switched to use determinator of model
- switched to spi_get_device_match_data

Changes in v6:
- removed address-cells and size-cells from main node
- changed macros formatting and OF matches
- factored out common devices and made device addition staged
- dropped cpcap->variant check for 0
- EINVAL > ENODEV in variant checking switch
---

Svyatoslav Ryhel (6):
  dt-bindings: leds: leds-cpcap: convert to DT schema
  dt-bindings: input: cpcap-pwrbutton: convert to DT schema
  dt-bindings: mfd: motorola-cpcap: convert to DT schema
  dt-bindings: mfd: motorola-cpcap: document Mapphone and Mot CPCAP
  mfd: motorola-cpcap: diverge configuration per-board
  mfd: motorola-cpcap: add support for Mot CPCAP composition

 .../bindings/input/cpcap-pwrbutton.txt        |  20 -
 .../input/motorola,cpcap-pwrbutton.yaml       |  32 ++
 .../devicetree/bindings/leds/leds-cpcap.txt   |  29 --
 .../bindings/leds/motorola,cpcap-leds.yaml    |  42 ++
 .../bindings/mfd/motorola,cpcap.yaml          | 408 ++++++++++++++++++
 .../bindings/mfd/motorola-cpcap.txt           |  78 ----
 drivers/mfd/motorola-cpcap.c                  | 143 +++---
 include/linux/mfd/motorola-cpcap.h            |   7 +
 8 files changed, 571 insertions(+), 188 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt
 create mode 100644 Documentation/devicetree/bindings/input/motorola,cpcap-pwrbutton.yaml
 delete mode 100644 Documentation/devicetree/bindings/leds/leds-cpcap.txt
 create mode 100644 Documentation/devicetree/bindings/leds/motorola,cpcap-leds.yaml
 create mode 100644 Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
 delete mode 100644 Documentation/devicetree/bindings/mfd/motorola-cpcap.txt

-- 
2.51.0


^ permalink raw reply

* [PATCH v6 1/6] dt-bindings: leds: leds-cpcap: convert to DT schema
From: Svyatoslav Ryhel @ 2026-05-20 18:21 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Lee Jones, Pavel Machek, Svyatoslav Ryhel
  Cc: linux-input, devicetree, linux-kernel, linux-leds
In-Reply-To: <20260520182124.117863-1-clamor95@gmail.com>

Convert LEDs devicetree bindings for the Motorola CPCAP MFD from TXT to
YAML format. This patch does not change any functionality; the bindings
remain the same.

Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
 .../devicetree/bindings/leds/leds-cpcap.txt   | 29 -------------
 .../bindings/leds/motorola,cpcap-leds.yaml    | 42 +++++++++++++++++++
 2 files changed, 42 insertions(+), 29 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/leds/leds-cpcap.txt
 create mode 100644 Documentation/devicetree/bindings/leds/motorola,cpcap-leds.yaml

diff --git a/Documentation/devicetree/bindings/leds/leds-cpcap.txt b/Documentation/devicetree/bindings/leds/leds-cpcap.txt
deleted file mode 100644
index ebf7cdc7f70c..000000000000
--- a/Documentation/devicetree/bindings/leds/leds-cpcap.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-Motorola CPCAP PMIC LEDs
-------------------------
-
-This module is part of the CPCAP. For more details about the whole
-chip see Documentation/devicetree/bindings/mfd/motorola-cpcap.txt.
-
-Requires node properties:
-- compatible: should be one of
-   * "motorola,cpcap-led-mdl"		(Main Display Lighting)
-   * "motorola,cpcap-led-kl"		(Keyboard Lighting)
-   * "motorola,cpcap-led-adl"		(Aux Display Lighting)
-   * "motorola,cpcap-led-red"		(Red Triode)
-   * "motorola,cpcap-led-green"		(Green Triode)
-   * "motorola,cpcap-led-blue"		(Blue Triode)
-   * "motorola,cpcap-led-cf"		(Camera Flash)
-   * "motorola,cpcap-led-bt"		(Bluetooth)
-   * "motorola,cpcap-led-cp"		(Camera Privacy LED)
-- label: see Documentation/devicetree/bindings/leds/common.txt
-- vdd-supply: A phandle to the regulator powering the LED
-
-Example:
-
-&cpcap {
-	cpcap_led_red: red-led {
-		compatible = "motorola,cpcap-led-red";
-		label = "cpcap:red";
-		vdd-supply = <&sw5>;
-	};
-};
diff --git a/Documentation/devicetree/bindings/leds/motorola,cpcap-leds.yaml b/Documentation/devicetree/bindings/leds/motorola,cpcap-leds.yaml
new file mode 100644
index 000000000000..c8e7b88a05cc
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/motorola,cpcap-leds.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/motorola,cpcap-leds.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Motorola CPCAP PMIC LEDs
+
+maintainers:
+  - Svyatoslav Ryhel <clamor95@gmail.com>
+
+description:
+  This module is part of the Motorola CPCAP MFD device. For more details
+  see Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml. LEDs are
+  represented as sub-nodes of the PMIC node on the device tree.
+
+allOf:
+  - $ref: /schemas/leds/common.yaml#
+
+properties:
+  compatible:
+    enum:
+      - motorola,cpcap-led-adl # Display Lighting
+      - motorola,cpcap-led-blue # Blue Triode
+      - motorola,cpcap-led-bt # Bluetooth
+      - motorola,cpcap-led-cf # Camera Flash
+      - motorola,cpcap-led-cp # Camera Privacy LED
+      - motorola,cpcap-led-green # Green Triode
+      - motorola,cpcap-led-kl # Keyboard Lighting
+      - motorola,cpcap-led-mdl # Main Display Lighting
+      - motorola,cpcap-led-red # Red Triode
+
+  vdd-supply: true
+
+required:
+  - compatible
+  - label
+  - vdd-supply
+
+unevaluatedProperties: false
+
+...
-- 
2.51.0


^ permalink raw reply related

* [PATCH v6 2/6] dt-bindings: input: cpcap-pwrbutton: convert to DT schema
From: Svyatoslav Ryhel @ 2026-05-20 18:21 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Lee Jones, Pavel Machek, Svyatoslav Ryhel
  Cc: linux-input, devicetree, linux-kernel, linux-leds
In-Reply-To: <20260520182124.117863-1-clamor95@gmail.com>

Convert power button devicetree bindings for the Motorola CPCAP MFD from
TXT to YAML format. This patch does not change any functionality; the
bindings remain the same.

Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
 .../bindings/input/cpcap-pwrbutton.txt        | 20 ------------
 .../input/motorola,cpcap-pwrbutton.yaml       | 32 +++++++++++++++++++
 2 files changed, 32 insertions(+), 20 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt
 create mode 100644 Documentation/devicetree/bindings/input/motorola,cpcap-pwrbutton.yaml

diff --git a/Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt b/Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt
deleted file mode 100644
index 0dd0076daf71..000000000000
--- a/Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Motorola CPCAP on key
-
-This module is part of the CPCAP. For more details about the whole
-chip see Documentation/devicetree/bindings/mfd/motorola-cpcap.txt.
-
-This module provides a simple power button event via an Interrupt.
-
-Required properties:
-- compatible: should be one of the following
-   - "motorola,cpcap-pwrbutton"
-- interrupts: irq specifier for CPCAP's ON IRQ
-
-Example:
-
-&cpcap {
-	cpcap_pwrbutton: pwrbutton {
-		compatible = "motorola,cpcap-pwrbutton";
-		interrupts = <23 IRQ_TYPE_NONE>;
-	};
-};
diff --git a/Documentation/devicetree/bindings/input/motorola,cpcap-pwrbutton.yaml b/Documentation/devicetree/bindings/input/motorola,cpcap-pwrbutton.yaml
new file mode 100644
index 000000000000..77a3e5a47d1a
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/motorola,cpcap-pwrbutton.yaml
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/motorola,cpcap-pwrbutton.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Motorola CPCAP PMIC power key
+
+maintainers:
+  - Svyatoslav Ryhel <clamor95@gmail.com>
+
+description:
+  This module is part of the Motorola CPCAP MFD device. For more details
+  see Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml. The
+  power key is represented as a sub-node of the PMIC node on the device
+  tree.
+
+properties:
+  compatible:
+    const: motorola,cpcap-pwrbutton
+
+  interrupts:
+    items:
+      - description: CPCAP's ON interrupt
+
+required:
+  - compatible
+  - interrupts
+
+additionalProperties: false
+
+...
-- 
2.51.0


^ permalink raw reply related

* [PATCH v6 3/6] dt-bindings: mfd: motorola-cpcap: convert to DT schema
From: Svyatoslav Ryhel @ 2026-05-20 18:21 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Lee Jones, Pavel Machek, Svyatoslav Ryhel
  Cc: linux-input, devicetree, linux-kernel, linux-leds
In-Reply-To: <20260520182124.117863-1-clamor95@gmail.com>

Convert devicetree bindings for the Motorola CPCAP MFD from TXT to YAML.

Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
 .../bindings/mfd/motorola,cpcap.yaml          | 403 ++++++++++++++++++
 .../bindings/mfd/motorola-cpcap.txt           |  78 ----
 2 files changed, 403 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..76705ea56805
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
@@ -0,0 +1,403 @@
+# 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:
+    items:
+      - const: motorola,cpcap
+      - const: st,6556002
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  interrupt-controller: true
+
+  "#interrupt-cells":
+    const: 2
+
+  spi-max-frequency:
+    maximum: 9600000
+
+  spi-cs-high: true
+  spi-cpol: true
+  spi-cpha: 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
+
+      VAUDIO-supply:
+        description:
+          Codec power supply, usually VAUDIO regulator of CPCAP.
+
+      ports:
+        $ref: /schemas/graph.yaml#/properties/ports
+
+        properties:
+          port@0:
+            $ref: /schemas/graph.yaml#/properties/port
+            description: port connected to the Stereo HiFi DAC
+
+          port@1:
+            $ref: /schemas/graph.yaml#/properties/port
+            description: port connected to the Voice DAC
+
+        required:
+          - port@0
+          - port@1
+
+    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
+  - interrupt-controller
+  - "#interrupt-cells"
+  - spi-max-frequency
+
+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", "st,6556002";
+            reg = <0>; /* cs0 */
+
+            interrupt-parent = <&gpio1>;
+            interrupts = <7 IRQ_TYPE_EDGE_RISING>;
+
+            interrupt-controller;
+            #interrupt-cells = <2>;
+
+            spi-max-frequency = <3000000>;
+            spi-cs-high;
+
+            spi-cpol;
+            spi-cpha;
+
+            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";
+
+                VAUDIO-supply = <&vdd_audio>;
+
+                #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,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;
+                    };
+
+                    vdd_audio: 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 related

* [PATCH v6 4/6] dt-bindings: mfd: motorola-cpcap: document Mapphone and Mot CPCAP
From: Svyatoslav Ryhel @ 2026-05-20 18:21 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Lee Jones, Pavel Machek, Svyatoslav Ryhel
  Cc: linux-input, devicetree, linux-kernel, linux-leds
In-Reply-To: <20260520182124.117863-1-clamor95@gmail.com>

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>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
 .../devicetree/bindings/mfd/motorola,cpcap.yaml       | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml b/Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
index 76705ea56805..da7abe2ec912 100644
--- a/Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
+++ b/Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
@@ -14,9 +14,14 @@ allOf:
 
 properties:
   compatible:
-    items:
-      - const: motorola,cpcap
-      - const: st,6556002
+    oneOf:
+      - enum:
+          - motorola,mapphone-cpcap
+          - motorola,mot-cpcap
+
+      - items:
+          - const: motorola,cpcap
+          - const: st,6556002
 
   reg:
     maxItems: 1
-- 
2.51.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