From mboxrd@z Thu Jan 1 00:00:00 1970
Authentication-Results: smtp.subspace.kernel.org; arc=pass header.oldest-pass=0 smtp.remote-ip=185.203.200.13
ARC-Seal: i=2; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=pass;
t=1793196216;
b=BiKGa+FfYpvGuGQk/bZIRywcfg44XZ98l0Hef7LsnjSo2LXOpnwg/iX+WHIskSVkMUY6
+V7O1pU/AFxBpZwqBmTyFEAcSx/swFbQRd+xw4zOw+jY4hoOFcLbClTXobzX/KKzIcDwM
bZ0Owf29ArVbUuYm+xoYEL50ir2QboWdzJlJV69LajcIaVjCSJ2K6cuxDoS4wFfT2Mvkd
xA1kMiRWjTFHlG4zfFa8q14jI88FL5uDsbLwaDj7Wk34d2sU6QbcNATrCn75v714BEPBi
UIMdPrAPuvWB+SVNu3MSt1aYt5dWzJ5JXc2NF4UDtWRTIxsOCvcc7u7Z1+D3HS35jCA==
ARC-Message-Signature: i=2; d=subspace.kernel.org; s=arc20261015;
a=rsa-sha256; c=relaxed/relaxed; t=1793196216;
h=DMARC-Filter:Received:DKIM-Signature:Message-ID:Subject:From:To:Cc:
Date:In-Reply-To:References:Content-Type:Content-Transfer-Encoding:
User-Agent:MIME-Version;
bh=7P6hkajrEuuwluLOAZvBDyIw6BeTtytgqv1+hRyvjaw=;
b=Lz5rt+X9VCn5cGxW14P8cY6ANLWwkb+7yZ6piQWjAlidNn8JhQmGFMXLeCE48+jQsuJ0
VMkDbcZEsPQn+i+xFh2wIJkrLQDvj2YTbQvvX1ByPrVRU2zqH7gRmV9xDYSvCuu7XtiMx
sglbTgmTxy9ukH5WjdFKks4hZKOBbf0wCVeocQOE2GLpN9tssvvM1mES0UxkAPRUv3p1N
3Vd1NFV2uMurrsbBycQw9ZHAx8jk+aVvyt9PNiKZXAXEgHau2hY981D+4xA/qNESm80g5
9PHma8/MRvCsh2d+cinBBpWr1EiC0UiTjZh5cHz21yEQpjkqMZMhznVcsUoLM6qutew==
ARC-Authentication-Results: i=2; smtp.subspace.kernel.org;
dmarc=none header.from=pengutronix.de;
spf=pass smtp.mailfrom=pengutronix.de;
dkim=pass header.d=pengutronix.de header.i=@pengutronix.de header.a=rsa-sha256 header.s=20260414 header.b=fJk0v+4g;
arc=pass header.oldest-pass=0 smtp.remote-ip=185.203.200.13
Received: from mx1.white.stw.pengutronix.de (mx1.white.stw.pengutronix.de [185.203.200.13])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256)
(No client certificate requested)
by smtp.subspace.kernel.org (Postfix) with ESMTPS id C6725606A31D;
Wed, 28 Oct 2026 14:03:32 +0000 (UTC)
DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org C6725606A31D
Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de
Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de
Authentication-Results: smtp.subspace.kernel.org;
dkim=pass (2048-bit key, unprotected) header.d=pengutronix.de header.i=@pengutronix.de header.a=rsa-sha256 header.s=20260414 header.b=fJk0v+4g
Received: from [IPv6:2a0a:edc0:0:900:1d::4e] (lupine.office.stw.pengutronix.de [IPv6:2a0a:edc0:0:900:1d::4e])
(Authenticated sender: pza@pengutronix.de)
by mx1.white.stw.pengutronix.de (Postfix) with ESMTPSA id 23858202950;
Wed, 28 Oct 2026 15:03:25 +0100 (CET)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pengutronix.de;
s=20260414; t=1793196205;
h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding:
in-reply-to:in-reply-to:references:references;
bh=7P6hkajrEuuwluLOAZvBDyIw6BeTtytgqv1+hRyvjaw=;
b=fJk0v+4ga7M4vRJu7VspWY2EHWe0tBqGwn6UYuEsrU8J7tIqos7QxaaEOtktZt6mmd9oG4
tToGGLOVQtMyd0VwsAL034DCpZd70a+KOypN3Pw8M25iIz2z6CMTQk8bTB4h6LYHH5LMI/
GpkYTVdTUUMIMXxksYKapUyLhsCfVFPcblNefrbBVwotYvdq92Ov4Ce/JGQHK1XmCBrR44
G/eCbiWnv5Tn7DiM61GMwJ00vjgr8Iwk54oCJyGMBOPdXIetaRJ6UHBr6nkfZ2YHYgHkdg
AmhyKxulPq5GBLQpez5Cjz3Oc7pwXY2FdlL23PY0g3+QMfU+obSKEAeDEeeOdQ==
ARC-Seal: i=1; s=20260414; d=pengutronix.de; t=1793196205; a=rsa-sha256;
cv=none;
b=K0EsB2LyhvUVGLcLwWVrAdslwBFmPDFzgFymzsVwxmG8GDel+Q44FM+cyA1YQyjUa70bCr
zaaw7nep7CYdZapkD/ueEfo/EKWTbn+PQYXxXfUvWZzvvP0Wkbxx4yF2ZCS09XgQTUphvh
JES9Msf+INOKkobm6Z2No4WAyj7iqFa66rW2RNVqlpzjrvaq3XEBesTgXFcGP0OKF1/YUL
kgiGY/0s9/fQGt0IZD5Kx3WViRkNRF7DGibpfUPSatdwC00jjKeyVubysf3krFdDEyRwRZ
yUSZDM/agGViiRKQScZRwUHPtwCFkYbu2ioL6xbeWyvdRS+2sr/kJpB/jrlhQw==
ARC-Authentication-Results: i=1;
ORIGINATING;
auth=pass smtp.auth=pza@pengutronix.de smtp.mailfrom=p.zabel@pengutronix.de
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=pengutronix.de;
s=20260414; t=1793196205;
h=from:from:reply-to:subject:subject:date:date:message-id:message-id:
to:to:cc:cc:mime-version:mime-version:content-type:content-type:
content-transfer-encoding:content-transfer-encoding:
in-reply-to:in-reply-to:references:references;
bh=7P6hkajrEuuwluLOAZvBDyIw6BeTtytgqv1+hRyvjaw=;
b=ZMLvYx3qz7/nxsQJFZRewAGvPfe/6T/mFhonAzwIFBSuRxFtgY87l2CKgxhdMfgYNaZgYv
Wkj87jgAjvUxznmG2qh+Zg73PuUY6yD0NXNwypWe7qor+bk4PUrOOSvVY2hissGpRXQX7J
1esXry4x+WKs81rK/YdDQXrqHCXPL8XW2K+xtGjCkV1i7JnHP2WcPSFpHbhOgk2MkUWg3G
hDqLFIp2A6Anxg6w0z9Sh1/Ybm5t0mtKU+cSezAZHHF6KvlCM3hxit8r1luB1bWEy4aKr1
p7T3ZdO1soNYx8xZ+tdNtvXfGbw952EUyt6lcmcxeJdmBYUZk+g/9/sQHPi2aw==
Message-ID: <8d57f0a1dc8a07838bf1320f9b79588196264ff5.camel@pengutronix.de>
Subject: Re: [PATCH 6/9] reset: google: Add CPM reset driver
From: Philipp Zabel
To: Brian Norris , Rob Herring ,
Krzysztof Kozlowski
, Conor Dooley , Stephen Boyd
, Brian Masney , Jerome Brunet
, Thomas Gleixner , Ulf Hansson
Cc: Peter Griffin , devicetree@vger.kernel.org,
Tudor Ambarus , =?ISO-8859-1?Q?Andr=E9?= Draszik
, linux-samsung-soc@vger.kernel.org,
linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, Radu Rendec
, linux-arm-kernel@lists.infradead.org, Mariano Marciello
, Douglas Anderson ,
linux-clk@vger.kernel.org, Jakub =?UTF-8?Q?G=C5=82owacki?=
Date: Wed, 28 Oct 2026 15:03:24 +0100
In-Reply-To: <20261026144346.6.I0b1ad34a718a9b5f667d2481041970ea45989dd3@changeid>
References: <20261026214359.3122870-1-briannorris@chromium.org>
<20261026144346.6.I0b1ad34a718a9b5f667d2481041970ea45989dd3@changeid>
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
User-Agent: Evolution 3.56.2-0+deb13u1
X-Mailing-List: linux-kernel@vger.kernel.org
List-Id:
List-Post:
List-Help:
List-Subscribe:
List-Unsubscribe:
List-Owner:
Precedence: list
MIME-Version: 1.0
On Mo, 2026-10-26 at 14:43 -0700, Brian Norris wrote:
> Google Tensor SoCs (used on Pixel phones) manage many resources
> (including resets) using a Central Power Manager (CPM) co-processor. We
> communicate with CPM using mailboxes, abstracted in the
> cpm_request_client(), etc., API.
>=20
> For posterity, I list a summary of changes made relative to the
> downstream Pixel driver:
>=20
> * Switch to auxiliary bus, as a child of a CPM device
>=20
> * Use devm more heavily
>=20
> * Avoid representing each reset as its own Device Tree node. Use a
> limited per-SoC table to describe any additional per-SoC details
> instead.
>=20
> Signed-off-by: Brian Norris
> ---
>=20
> drivers/reset/Kconfig | 1 +
> drivers/reset/Makefile | 1 +
> drivers/reset/google/Kconfig | 11 +
> drivers/reset/google/Makefile | 2 +
> drivers/reset/google/reset-cpm.c | 367 +++++++++++++++++++++++++++++++
> 5 files changed, 382 insertions(+)
> create mode 100644 drivers/reset/google/Kconfig
> create mode 100644 drivers/reset/google/Makefile
> create mode 100644 drivers/reset/google/reset-cpm.c
>=20
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index eda9c698a95f..37dbddcd620f 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -451,6 +451,7 @@ config RESET_ZYNQMP
> This enables the reset controller driver for Xilinx ZynqMP SoCs.
> =20
> source "drivers/reset/amlogic/Kconfig"
> +source "drivers/reset/google/Kconfig"
> source "drivers/reset/hisilicon/Kconfig"
> source "drivers/reset/spacemit/Kconfig"
> source "drivers/reset/starfive/Kconfig"
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 489fafd6bbe3..9754c274766c 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -1,6 +1,7 @@
> # SPDX-License-Identifier: GPL-2.0
> obj-y +=3D core.o
> obj-y +=3D amlogic/
> +obj-y +=3D google/
> obj-y +=3D hisilicon/
> obj-y +=3D spacemit/
> obj-y +=3D starfive/
> diff --git a/drivers/reset/google/Kconfig b/drivers/reset/google/Kconfig
> new file mode 100644
> index 000000000000..38431b4f9001
> --- /dev/null
> +++ b/drivers/reset/google/Kconfig
> @@ -0,0 +1,11 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config RESET_CPM
> + tristate "Google CPM Reset Controller"
> + depends on ARCH_GOOGLE || COMPILE_TEST
> + depends on GOOGLE_CPM_MBA
> + help
> + Driver support for reset controllers found on Google Tensor SoCs,
> + operating over the CPM mailbox interface. This allows peripheral
> + drivers to assert and deassert resets on LPCM hardware blocks.
> +
> + If unsure, say N.
> diff --git a/drivers/reset/google/Makefile b/drivers/reset/google/Makefil=
e
> new file mode 100644
> index 000000000000..437c19459464
> --- /dev/null
> +++ b/drivers/reset/google/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-$(CONFIG_RESET_CPM) +=3D reset-cpm.o
> diff --git a/drivers/reset/google/reset-cpm.c b/drivers/reset/google/rese=
t-cpm.c
> new file mode 100644
> index 000000000000..5f144f1ad5f2
> --- /dev/null
> +++ b/drivers/reset/google/reset-cpm.c
> @@ -0,0 +1,367 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Device driver to control Google SoC LPCM resets via CPM.
> + * Copyright 2023-2026 Google LLC
> + */
> +
> +#include
> +#include
> +#include
> +#include
> +#include
> +#include
> +#include
> +#include
> +#include
> +#include
> +#include
> +
> +#define MAILBOX_SEND_TIMEOUT_MS 3000
> +#define LPCM_CMD_SET_RST 0x4
> +
> +#define OP_ID_BITFIELD GENMASK(31, 24)
> +#define RST_ID_BITFIELD GENMASK(23, 16)
> +#define LPCM_ID_BITFIELD GENMASK(15, 8)
> +#define REQ_ID_BITFIELD GENMASK(7, 0)
> +
> +#define ASSERT_OP_ID 0
> +#define DEASSERT_OP_ID 1
> +
> +#define NO_ERROR 0
> +#define ERR_LPCM_NOT_SUPPORTED (-24)
> +#define ERR_LPCM_INVALID_ARGS (-8)
> +#define ERR_LPCM_TIMED_OUT (-13)
> +#define ERR_LPCM_GENERIC (-1)
> +
> +#define CPM_RST_LPCM_ID_MASK GENMASK(31, 16)
> +#define CPM_RST_ID_MASK GENMASK(15, 0)
> +
> +static inline unsigned long to_rstc_idx(u32 lpcm_id, u32 rst_id)
> +{
> + return FIELD_PREP(CPM_RST_LPCM_ID_MASK, lpcm_id) |
> + FIELD_PREP(CPM_RST_ID_MASK, rst_id);
> +}
> +
> +static inline u32 lpcm_from_idx(unsigned long idx)
> +{
> + return FIELD_GET(CPM_RST_LPCM_ID_MASK, idx);
> +}
> +
> +static inline u32 rst_from_idx(unsigned long idx)
> +{
> + return FIELD_GET(CPM_RST_ID_MASK, idx);
> +}
> +
> +struct cpm_reset_data {
> + u32 lpcm_id;
> + u32 nr_resets;
> + const char *name;
> +};
> +
> +struct cpm_reset_soc_data {
> + const struct cpm_reset_data *resets;
> + size_t num_resets;
> +};
> +
> +struct goog_cpm_rst_provider {
> + struct device *dev;
> + struct reset_controller_dev rcdev;
> + struct cpm_client *cpm_client;
> + struct dentry *debugfs_root;
> + struct goog_cpm_rst_debugfs_entry *dbg_entries;
> + const struct cpm_reset_soc_data *soc_data;
> +};
> +
> +#define to_provider(rc) container_of(rc, struct goog_cpm_rst_provider, r=
cdev)
This should be an inline function.
> +struct goog_cpm_rst_debugfs_entry {
> + struct goog_cpm_rst_provider *provider;
> + u32 lpcm_id;
> +};
> +
> +static int goog_cpm_rst_mba_check_ret(struct device *dev, int ret)
> +{
> + switch (ret) {
> + case NO_ERROR:
> + return 0;
> + case ERR_LPCM_NOT_SUPPORTED:
> + dev_err(dev, "the received request_id is invalid\n");
> + return -EPROTO;
-EOPNOTSUPP?
> + case ERR_LPCM_INVALID_ARGS:
> + dev_err(dev, "invalid lpcm_id or rst_id\n");
> + return -EINVAL;
> + case ERR_LPCM_TIMED_OUT:
> + dev_err(dev, "operation timed out\n");
> + return -ETIMEDOUT;
> + case ERR_LPCM_GENERIC:
> + dev_err(dev, "internal error occurred\n");
> + return -EREMOTEIO;
> + default:
> + dev_err(dev, "unknown error response from CPM\n");
> + return -EPROTO;
> + }
> +}
Is this specific to reset functionality, or should this maybe live in
CPM common code? I see that the return values in the power-domain
driver are not translated, but the clock driver contains a near-
identical copy of this function. Or maybe just printing the translated
error with "%pe" is good enough?
> +static int goog_cpm_rst_mba_resp_hdl(struct device *dev, const struct cp=
m_request *cpm_req)
> +{
> + int dst =3D cpm_req->dst_id;
> + int ret =3D cpm_req->resp_msg->payload[0];
> +
> + dev_dbg(dev, "got resp from %u, data %d.\n", dst, ret);
> +
> + return goog_cpm_rst_mba_check_ret(dev, ret);
> +}
> +
> +static int goog_cpm_rst_send_mba_mail(struct goog_cpm_rst_provider *prov=
ider,
> + u32 lpcm_id, unsigned long rst_id, int op_id)
> +{
> + struct device *dev =3D provider->dev;
> + struct cpm_payload resp_msg;
> + struct cpm_payload req_msg =3D {};
> + struct cpm_request cpm_req =3D {
> + .msg_type =3D REQUEST_MSG,
> + .req_msg =3D &req_msg,
> + .resp_msg =3D &resp_msg,
> + .dst_id =3D CPM_COMMON_LPCM_SERVICE,
> + .tout_ms =3D MAILBOX_SEND_TIMEOUT_MS,
> + };
> + int ret;
> +
> + req_msg.payload[0] =3D FIELD_PREP(REQ_ID_BITFIELD, LPCM_CMD_SET_RST) |
> + FIELD_PREP(LPCM_ID_BITFIELD, lpcm_id) |
> + FIELD_PREP(RST_ID_BITFIELD, rst_id) |
> + FIELD_PREP(OP_ID_BITFIELD, op_id);
> +
> + dev_dbg(dev, "lpcm_id %d, rst_id %lu: send mba mail: [%u, %u, %u]\n",
> + lpcm_id, rst_id, req_msg.payload[0], req_msg.payload[1],
> + req_msg.payload[2]);
> +
> + ret =3D cpm_send_message(provider->cpm_client, &cpm_req);
> + if (ret < 0) {
> + dev_err(dev,
> + "lpcm_id %d, rst_id %lu: failed to send request to CPM, ret=3D%d\n",
> + lpcm_id, rst_id, ret);
> + return ret;
> + }
> +
> + return goog_cpm_rst_mba_resp_hdl(dev, &cpm_req);
> +}
> +
> +static int goog_cpm_rst_assert(struct reset_controller_dev *rcdev,
> + unsigned long idx)
> +{
> + struct goog_cpm_rst_provider *provider =3D to_provider(rcdev);
> + u32 lpcm_id =3D lpcm_from_idx(idx);
> + u32 rst_id =3D rst_from_idx(idx);
> +
> + dev_dbg(rcdev->dev, "assert reset id=3D%u of lpcm %u\n", rst_id, lpcm_i=
d);
> + return goog_cpm_rst_send_mba_mail(provider, lpcm_id, rst_id, ASSERT_OP_=
ID);
> +}
> +
> +static int goog_cpm_rst_deassert(struct reset_controller_dev *rcdev,
> + unsigned long idx)
> +{
> + struct goog_cpm_rst_provider *provider =3D to_provider(rcdev);
> + u32 lpcm_id =3D lpcm_from_idx(idx);
> + u32 rst_id =3D rst_from_idx(idx);
> +
> + dev_dbg(rcdev->dev, "deassert reset id=3D%u of lpcm %u\n", rst_id, lpcm=
_id);
This all could be deduplicated by moving it into the _send_mba_mail()
function, using str_assert_deassert(op_id =3D=3D ASSERT_OP_ID).
> + return goog_cpm_rst_send_mba_mail(provider, lpcm_id, rst_id, DEASSERT_O=
P_ID);
> +}
> +
> +static const struct reset_control_ops goog_cpm_rst_ops =3D {
> + .assert =3D goog_cpm_rst_assert,
> + .deassert =3D goog_cpm_rst_deassert,
> +};
> +
> +static int goog_cpm_rst_debugfs_assert_set(void *data, u64 rst_id)
> +{
> + struct goog_cpm_rst_debugfs_entry *entry =3D data;
> + unsigned long idx =3D to_rstc_idx(entry->lpcm_id, rst_id);
> +
> + return goog_cpm_rst_assert(&entry->provider->rcdev, idx);
Calling into reset_control_ops like this bypasses all reference
counting in the core and breaks reset controller API promises.
> +}
> +
> +static int goog_cpm_rst_debugfs_deassert_set(void *data, u64 rst_id)
> +{
> + struct goog_cpm_rst_debugfs_entry *entry =3D data;
> + unsigned long idx =3D to_rstc_idx(entry->lpcm_id, rst_id);
> +
> + return goog_cpm_rst_deassert(&entry->provider->rcdev, idx);
> +}
> +
> +DEFINE_DEBUGFS_ATTRIBUTE(goog_cpm_rst_assert_debugfs_fops, NULL,
> + goog_cpm_rst_debugfs_assert_set, "%llu\n");
> +
> +DEFINE_DEBUGFS_ATTRIBUTE(goog_cpm_rst_deassert_debugfs_fops, NULL,
> + goog_cpm_rst_debugfs_deassert_set, "%llu\n");
> +
> +static void goog_cpm_rst_add_debugfs(struct goog_cpm_rst_debugfs_entry *=
entry,
> + struct dentry *debugfs_root,
> + const char *name)
> +{
> + struct dentry *d =3D debugfs_create_dir(name, debugfs_root);
> +
> + debugfs_create_file("assert", 0220, d, entry,
> + &goog_cpm_rst_assert_debugfs_fops);
> + debugfs_create_file("deassert", 0220, d, entry,
> + &goog_cpm_rst_deassert_debugfs_fops);
> +}
Please drop the debugfs functionality or explain what it is needed for.
> +static int goog_cpm_rst_get_nr_resets(const struct cpm_reset_soc_data *s=
oc_data, u32 lpcm_id)
> +{
> + int i;
> +
> + for (i =3D 0; i < soc_data->num_resets; i++)
> + if (soc_data->resets[i].lpcm_id =3D=3D lpcm_id)
> + return soc_data->resets[i].nr_resets;
> +
> + return -EINVAL;
> +}
> +
> +static int goog_cpm_rst_of_xlate(struct reset_controller_dev *rcdev,
> + const struct of_phandle_args *reset_spec)
> +{
> + struct goog_cpm_rst_provider *provider =3D to_provider(rcdev);
> + u32 lpcm_id, rst_id;
> + int max_resets;
> +
> + if (reset_spec->args_count !=3D 2)
> + return -EINVAL;
> +
> + lpcm_id =3D reset_spec->args[0];
> + rst_id =3D reset_spec->args[1];
> +
> + max_resets =3D goog_cpm_rst_get_nr_resets(provider->soc_data, lpcm_id);
> + if (max_resets < 0)
> + return max_resets;
> +
> + if (rst_id >=3D max_resets)
> + return -EINVAL;
> +
> + return to_rstc_idx(lpcm_id, rst_id);
> +}
> +
> +static const struct cpm_reset_data cpm_resets_lga_entries[] =3D {
> + {
> + .lpcm_id =3D LGA_LPCM_HSIO_N,
> + .nr_resets =3D 16,
> + .name =3D "hsio-n",
> + },
> + {
> + .lpcm_id =3D LGA_LPCM_HSIO_S,
> + .nr_resets =3D 5,
> + .name =3D "hsio-s",
> + },
> + {
> + .lpcm_id =3D LGA_LPCM_LSIO_S,
> + .nr_resets =3D 45,
> + .name =3D "lsio-s",
> + },
> + {
> + .lpcm_id =3D LGA_LPCM_LSIO_N,
> + .nr_resets =3D 43,
> + .name =3D "lsio-n",
> + },
> + {
> + .lpcm_id =3D LGA_LPCM_LSIO_E,
> + .nr_resets =3D 50,
> + .name =3D "lsio-e",
> + },
> +};
> +
> +static const struct cpm_reset_soc_data cpm_resets_lga =3D {
> + .resets =3D cpm_resets_lga_entries,
> + .num_resets =3D ARRAY_SIZE(cpm_resets_lga_entries),
> +};
> +
> +static const struct of_device_id cpm_rst_of_match[] =3D {
> + { .compatible =3D "google,lga-cpm", .data =3D &cpm_resets_lga },
> + { /* sentinel */ }
Please choose one style (align with goog_cpm_rst_id_table).
> +};
> +
> +static int goog_cpm_rst_probe(struct auxiliary_device *auxdev,
> + const struct auxiliary_device_id *id)
> +{
> + struct device *dev =3D &auxdev->dev;
> + struct goog_cpm_rst_provider *provider;
> + const struct of_device_id *match;
> + int i, ret;
> +
> + match =3D of_match_node(cpm_rst_of_match, dev->of_node);
> + if (!match) {
> + dev_err(dev, "no matching SoC data found\n");
This should never happen, does it warrant an error message?
> + return -ENODEV;
> + }
> +
> + provider =3D devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL);
> + if (!provider)
> + return -ENOMEM;
> +
> + provider->dev =3D dev;
This is not needed, you can just use provider->rcdev.dev.
> + provider->soc_data =3D match->data;
> +
> + provider->cpm_client =3D devm_cpm_request_client(dev, 0, NULL, NULL);
> + if (IS_ERR(provider->cpm_client))
> + return dev_err_probe(dev, PTR_ERR(provider->cpm_client),
> + "Failed to request cpm client\n");
> + auxiliary_set_drvdata(auxdev, provider);
> +
> + provider->rcdev.dev =3D dev;
> + provider->rcdev.owner =3D THIS_MODULE;
> + provider->rcdev.of_node =3D dev->of_node;
> + provider->rcdev.ops =3D &goog_cpm_rst_ops;
> + provider->rcdev.of_reset_n_cells =3D 2;
> + provider->rcdev.of_xlate =3D goog_cpm_rst_of_xlate;
> +
> + ret =3D devm_reset_controller_register(dev, &provider->rcdev);
> + if (ret < 0) {
> + dev_err(dev, "failed to register reset controller: %d\n", ret);
> + return ret;
> + }
> +
> + provider->debugfs_root =3D debugfs_create_dir(dev_name(dev), NULL);
> + if (!IS_ERR(provider->debugfs_root)) {
> + provider->dbg_entries =3D devm_kcalloc(dev, provider->soc_data->num_re=
sets,
> + sizeof(*provider->dbg_entries), GFP_KERNEL);
> + if (!provider->dbg_entries) {
> + debugfs_remove_recursive(provider->debugfs_root);
> + return -ENOMEM;
> + }
> +
> + for (i =3D 0; i < provider->soc_data->num_resets; i++) {
> + provider->dbg_entries[i].provider =3D provider;
> + provider->dbg_entries[i].lpcm_id =3D provider->soc_data->resets[i].lp=
cm_id;
> + goog_cpm_rst_add_debugfs(&provider->dbg_entries[i],
> + provider->debugfs_root,
> + provider->soc_data->resets[i].name);
> + }
> + }
> +
> + return 0;
> +}
> +
> +static void goog_cpm_rst_remove(struct auxiliary_device *auxdev)
> +{
> + struct goog_cpm_rst_provider *provider =3D auxiliary_get_drvdata(auxdev=
);
> +
> + debugfs_remove_recursive(provider->debugfs_root);
> +}
> +
> +static const struct auxiliary_device_id goog_cpm_rst_id_table[] =3D {
> + { .name =3D "google_cpm_mba.reset" },
> + {},
Please choose one style (align with cpm_rst_of_match).
> +};
> +MODULE_DEVICE_TABLE(auxiliary, goog_cpm_rst_id_table);
> +
> +static struct auxiliary_driver goog_cpm_rst_driver =3D {
> + .probe =3D goog_cpm_rst_probe,
> + .remove =3D goog_cpm_rst_remove,
> + .name =3D "google-reset-cpm",
> + .id_table =3D goog_cpm_rst_id_table,
> +};
> +
> +module_auxiliary_driver(goog_cpm_rst_driver);
> +
> +MODULE_DESCRIPTION("Google CPM Reset Driver");
> +MODULE_LICENSE("GPL");
regards
Philipp