* 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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox