* [PATCH 6.1.y-cip 1/9] arm64: dts: renesas: rzg3e-smarc-som: Enable I3C support
2026-03-03 9:21 [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
@ 2026-03-03 9:21 ` Tommaso Merciai
2026-03-03 9:21 ` [PATCH 6.1.y-cip 2/9] clk: Provide managed helper to get and enable bulk clocks Tommaso Merciai
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Tommaso Merciai @ 2026-03-03 9:21 UTC (permalink / raw)
To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek
Cc: Biju Das, Lad Prabhakar, tomm.merciai
commit 4ef81dcac8f6e08b29c359ab147dd87a488d178c upstream.
Enable I3C on RZ/G3E SMARC SoM.
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://patch.msgid.link/9d1cf2cdb1c11f24378404142e4c8aff680c6961.1763638659.git.tommaso.merciai.xr@bp.renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
---
arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi
index 7faa44510d98..f05b9fec05f0 100644
--- a/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg3e-smarc-som.dtsi
@@ -122,6 +122,14 @@ raa215300: pmic@12 {
};
};
+&i3c {
+ pinctrl-0 = <&i3c_pins>;
+ pinctrl-names = "default";
+ i2c-scl-hz = <400000>;
+ i3c-scl-hz = <12500000>;
+ status = "okay";
+};
+
&mdio0 {
phy0: ethernet-phy@7 {
compatible = "ethernet-phy-id0022.1640",
@@ -219,6 +227,12 @@ i2c2_pins: i2c {
<RZG3E_PORT_PINMUX(3, 5, 1)>; /* SDA2 */
};
+ i3c_pins: i3c {
+ pinmux = <RZG3E_PORT_PINMUX(2, 0, 2)>, /* I3C0_SCL */
+ <RZG3E_PORT_PINMUX(2, 1, 2)>; /* I3C0_SDA */
+ drive-push-pull;
+ };
+
rtc_irq_pin: rtc-irq {
pins = "PS1";
bias-pull-up;
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 6.1.y-cip 2/9] clk: Provide managed helper to get and enable bulk clocks
2026-03-03 9:21 [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
2026-03-03 9:21 ` [PATCH 6.1.y-cip 1/9] arm64: dts: renesas: rzg3e-smarc-som: Enable I3C support Tommaso Merciai
@ 2026-03-03 9:21 ` Tommaso Merciai
2026-03-03 9:21 ` [PATCH 6.1.y-cip 3/9] clk: provide devm_clk_get_optional_enabled_with_rate() Tommaso Merciai
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Tommaso Merciai @ 2026-03-03 9:21 UTC (permalink / raw)
To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek
Cc: Biju Das, Lad Prabhakar, tomm.merciai
From: Shradha Todi <shradha.t@samsung.com>
commit 265b07df758a998f60cf5b5aec6bd72ca676655e upstream.
Provide a managed devm_clk_bulk* wrapper to get and enable all
bulk clocks in order to simplify drivers that keeps all clocks
enabled for the time of driver operation.
Suggested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Shradha Todi <shradha.t@samsung.com>
Link: https://lore.kernel.org/r/20240220084046.23786-2-shradha.t@samsung.com
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
---
drivers/clk/clk-devres.c | 40 ++++++++++++++++++++++++++++++++++++++++
include/linux/clk.h | 22 ++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index 737aa70e2cb3..90e6078fb6e1 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -182,6 +182,46 @@ int __must_check devm_clk_bulk_get_all(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all);
+static void devm_clk_bulk_release_all_enable(struct device *dev, void *res)
+{
+ struct clk_bulk_devres *devres = res;
+
+ clk_bulk_disable_unprepare(devres->num_clks, devres->clks);
+ clk_bulk_put_all(devres->num_clks, devres->clks);
+}
+
+int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
+ struct clk_bulk_data **clks)
+{
+ struct clk_bulk_devres *devres;
+ int ret;
+
+ devres = devres_alloc(devm_clk_bulk_release_all_enable,
+ sizeof(*devres), GFP_KERNEL);
+ if (!devres)
+ return -ENOMEM;
+
+ ret = clk_bulk_get_all(dev, &devres->clks);
+ if (ret > 0) {
+ *clks = devres->clks;
+ devres->num_clks = ret;
+ } else {
+ devres_free(devres);
+ return ret;
+ }
+
+ ret = clk_bulk_prepare_enable(devres->num_clks, *clks);
+ if (!ret) {
+ devres_add(dev, devres);
+ } else {
+ clk_bulk_put_all(devres->num_clks, devres->clks);
+ devres_free(devres);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all_enable);
+
static int devm_clk_match(struct device *dev, void *res, void *data)
{
struct clk **c = res;
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 06f1b292f8a0..0f44d3863de2 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -478,6 +478,22 @@ int __must_check devm_clk_bulk_get_optional(struct device *dev, int num_clks,
int __must_check devm_clk_bulk_get_all(struct device *dev,
struct clk_bulk_data **clks);
+/**
+ * devm_clk_bulk_get_all_enable - Get and enable all clocks of the consumer (managed)
+ * @dev: device for clock "consumer"
+ * @clks: pointer to the clk_bulk_data table of consumer
+ *
+ * Returns success (0) or negative errno.
+ *
+ * This helper function allows drivers to get all clocks of the
+ * consumer and enables them in one operation with management.
+ * The clks will automatically be disabled and freed when the device
+ * is unbound.
+ */
+
+int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
+ struct clk_bulk_data **clks);
+
/**
* devm_clk_get - lookup and obtain a managed reference to a clock producer.
* @dev: device for clock "consumer"
@@ -968,6 +984,12 @@ static inline int __must_check devm_clk_bulk_get_all(struct device *dev,
return 0;
}
+static inline int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
+ struct clk_bulk_data **clks)
+{
+ return 0;
+}
+
static inline struct clk *devm_get_clk_from_child(struct device *dev,
struct device_node *np, const char *con_id)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 6.1.y-cip 3/9] clk: provide devm_clk_get_optional_enabled_with_rate()
2026-03-03 9:21 [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
2026-03-03 9:21 ` [PATCH 6.1.y-cip 1/9] arm64: dts: renesas: rzg3e-smarc-som: Enable I3C support Tommaso Merciai
2026-03-03 9:21 ` [PATCH 6.1.y-cip 2/9] clk: Provide managed helper to get and enable bulk clocks Tommaso Merciai
@ 2026-03-03 9:21 ` Tommaso Merciai
2026-03-03 9:21 ` [PATCH 6.1.y-cip 4/9] clk: Provide devm_clk_bulk_get_all_enabled() helper Tommaso Merciai
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Tommaso Merciai @ 2026-03-03 9:21 UTC (permalink / raw)
To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek
Cc: Biju Das, Lad Prabhakar, tomm.merciai
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
commit 9934a1bd45b2b03f6d1204a6ae2780d3b009799f upstream.
There are clock users in the kernel that can't use
devm_clk_get_optional_enabled() as they need to set rate after getting
the clock and before enabling it. Provide a managed helper that wraps
these operations in the correct order.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Link: https://lore.kernel.org/r/20240805-clk-new-helper-v2-1-e5fdd1e1d729@linaro.org
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
---
drivers/clk/clk-devres.c | 28 ++++++++++++++++++++++++++++
include/linux/clk.h | 33 +++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+)
diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index 90e6078fb6e1..82ae1f26e634 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -99,6 +99,34 @@ struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id)
}
EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled);
+struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
+ const char *id,
+ unsigned long rate)
+{
+ struct clk *clk;
+ int ret;
+
+ clk = __devm_clk_get(dev, id, clk_get_optional, NULL,
+ clk_disable_unprepare);
+ if (IS_ERR(clk))
+ return ERR_CAST(clk);
+
+ ret = clk_set_rate(clk, rate);
+ if (ret)
+ goto out_put_clk;
+
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ goto out_put_clk;
+
+ return clk;
+
+out_put_clk:
+ devm_clk_put(dev, clk);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled_with_rate);
+
struct clk_bulk_devres {
struct clk_bulk_data *clks;
int num_clks;
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 0f44d3863de2..ca0fe17827a5 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -623,6 +623,32 @@ struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id);
*/
struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id);
+/**
+ * devm_clk_get_optional_enabled_with_rate - devm_clk_get_optional() +
+ * clk_set_rate() +
+ * clk_prepare_enable()
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ * @rate: new clock rate
+ *
+ * Context: May sleep.
+ *
+ * Return: a struct clk corresponding to the clock producer, or
+ * valid IS_ERR() condition containing errno. The implementation
+ * uses @dev and @id to determine the clock consumer, and thereby
+ * the clock producer. If no such clk is found, it returns NULL
+ * which serves as a dummy clk. That's the only difference compared
+ * to devm_clk_get_enabled().
+ *
+ * The returned clk (if valid) is prepared and enabled and rate was set.
+ *
+ * The clock will automatically be disabled, unprepared and freed
+ * when the device is unbound from the bus.
+ */
+struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
+ const char *id,
+ unsigned long rate);
+
/**
* devm_get_clk_from_child - lookup and obtain a managed reference to a
* clock producer from child node.
@@ -965,6 +991,13 @@ static inline struct clk *devm_clk_get_optional_enabled(struct device *dev,
return NULL;
}
+static inline struct clk *
+devm_clk_get_optional_enabled_with_rate(struct device *dev, const char *id,
+ unsigned long rate)
+{
+ return NULL;
+}
+
static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
struct clk_bulk_data *clks)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 6.1.y-cip 4/9] clk: Provide devm_clk_bulk_get_all_enabled() helper
2026-03-03 9:21 [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
` (2 preceding siblings ...)
2026-03-03 9:21 ` [PATCH 6.1.y-cip 3/9] clk: provide devm_clk_get_optional_enabled_with_rate() Tommaso Merciai
@ 2026-03-03 9:21 ` Tommaso Merciai
2026-03-03 9:21 ` [PATCH 6.1.y-cip 5/9] i3c: renesas: Simplify return statement in 'renesas_i3c_daa' Tommaso Merciai
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Tommaso Merciai @ 2026-03-03 9:21 UTC (permalink / raw)
To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek
Cc: Biju Das, Lad Prabhakar, tomm.merciai
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
commit 51e32e897539663957f7a0950f66b48f8896efee upstream.
Commit 265b07df758a ("clk: Provide managed helper to get and enable bulk
clocks") added devm_clk_bulk_get_all_enable() function, but missed to
return the number of clocks stored in the clk_bulk_data table referenced
by the clks argument. Without knowing the number, it's not possible to
iterate these clocks when needed, hence the argument is useless and
could have been simply removed.
Introduce devm_clk_bulk_get_all_enabled() variant, which is consistent
with devm_clk_bulk_get_all() in terms of the returned value:
> 0 if one or more clocks have been stored
= 0 if there are no clocks
< 0 if an error occurred
Moreover, the naming is consistent with devm_clk_get_enabled(), i.e. use
the past form of 'enable'.
To reduce code duplication and improve patch readability, make
devm_clk_bulk_get_all_enable() use the new helper, as suggested by
Stephen Boyd.
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
Link: https://lore.kernel.org/r/20241019-clk_bulk_ena_fix-v4-1-57f108f64e70@collabora.com
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
---
drivers/clk/clk-devres.c | 9 +++++----
include/linux/clk.h | 21 ++++++++++++++++-----
2 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index 82ae1f26e634..5368d92d9b39 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -218,8 +218,8 @@ static void devm_clk_bulk_release_all_enable(struct device *dev, void *res)
clk_bulk_put_all(devres->num_clks, devres->clks);
}
-int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
- struct clk_bulk_data **clks)
+int __must_check devm_clk_bulk_get_all_enabled(struct device *dev,
+ struct clk_bulk_data **clks)
{
struct clk_bulk_devres *devres;
int ret;
@@ -244,11 +244,12 @@ int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
} else {
clk_bulk_put_all(devres->num_clks, devres->clks);
devres_free(devres);
+ return ret;
}
- return ret;
+ return devres->num_clks;
}
-EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all_enable);
+EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all_enabled);
static int devm_clk_match(struct device *dev, void *res, void *data)
{
diff --git a/include/linux/clk.h b/include/linux/clk.h
index ca0fe17827a5..31bc215c9de8 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -479,11 +479,13 @@ int __must_check devm_clk_bulk_get_all(struct device *dev,
struct clk_bulk_data **clks);
/**
- * devm_clk_bulk_get_all_enable - Get and enable all clocks of the consumer (managed)
+ * devm_clk_bulk_get_all_enabled - Get and enable all clocks of the consumer (managed)
* @dev: device for clock "consumer"
* @clks: pointer to the clk_bulk_data table of consumer
*
- * Returns success (0) or negative errno.
+ * Returns a positive value for the number of clocks obtained while the
+ * clock references are stored in the clk_bulk_data table in @clks field.
+ * Returns 0 if there're none and a negative value if something failed.
*
* This helper function allows drivers to get all clocks of the
* consumer and enables them in one operation with management.
@@ -491,8 +493,8 @@ int __must_check devm_clk_bulk_get_all(struct device *dev,
* is unbound.
*/
-int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
- struct clk_bulk_data **clks);
+int __must_check devm_clk_bulk_get_all_enabled(struct device *dev,
+ struct clk_bulk_data **clks);
/**
* devm_clk_get - lookup and obtain a managed reference to a clock producer.
@@ -1017,7 +1019,7 @@ static inline int __must_check devm_clk_bulk_get_all(struct device *dev,
return 0;
}
-static inline int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
+static inline int __must_check devm_clk_bulk_get_all_enabled(struct device *dev,
struct clk_bulk_data **clks)
{
return 0;
@@ -1119,6 +1121,15 @@ static inline void clk_restore_context(void) {}
#endif
+/* Deprecated. Use devm_clk_bulk_get_all_enabled() */
+static inline int __must_check
+devm_clk_bulk_get_all_enable(struct device *dev, struct clk_bulk_data **clks)
+{
+ int ret = devm_clk_bulk_get_all_enabled(dev, clks);
+
+ return ret > 0 ? 0 : ret;
+}
+
/* clk_prepare_enable helps cases using clk_enable in non-atomic context. */
static inline int clk_prepare_enable(struct clk *clk)
{
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 6.1.y-cip 5/9] i3c: renesas: Simplify return statement in 'renesas_i3c_daa'
2026-03-03 9:21 [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
` (3 preceding siblings ...)
2026-03-03 9:21 ` [PATCH 6.1.y-cip 4/9] clk: Provide devm_clk_bulk_get_all_enabled() helper Tommaso Merciai
@ 2026-03-03 9:21 ` Tommaso Merciai
2026-03-03 9:21 ` [PATCH 6.1.y-cip 6/9] i3c: renesas: Switch to clk_bulk API and store clocks in private data Tommaso Merciai
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Tommaso Merciai @ 2026-03-03 9:21 UTC (permalink / raw)
To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek
Cc: Biju Das, Lad Prabhakar, tomm.merciai
From: Wolfram Sang <wsa+renesas@sang-engineering.com>
commit bc7dd24c114e37c67061f4651bbbbbc57106c617 upstream.
There was already a bail out for 'ret < 0', so we can always return
success at the end of the function.
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Closes: https://lore.kernel.org/r/aIyzJ7HOENL1qp1l@stanley.mountain
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Tested-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Link: https://lore.kernel.org/r/20250803211256.18513-2-wsa+renesas@sang-engineering.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
---
drivers/i3c/master/renesas-i3c.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 432be328a4e4..040376903a98 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -682,7 +682,7 @@ static int renesas_i3c_daa(struct i3c_master_controller *m)
i3c_master_add_i3c_dev_locked(m, i3c->addrs[pos]);
}
- return ret < 0 ? ret : 0;
+ return 0;
}
static bool renesas_i3c_supports_ccc_cmd(struct i3c_master_controller *m,
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 6.1.y-cip 6/9] i3c: renesas: Switch to clk_bulk API and store clocks in private data
2026-03-03 9:21 [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
` (4 preceding siblings ...)
2026-03-03 9:21 ` [PATCH 6.1.y-cip 5/9] i3c: renesas: Simplify return statement in 'renesas_i3c_daa' Tommaso Merciai
@ 2026-03-03 9:21 ` Tommaso Merciai
2026-03-03 9:21 ` [PATCH 6.1.y-cip 7/9] i3c: renesas: Store clock rate and reset controls in struct renesas_i3c Tommaso Merciai
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Tommaso Merciai @ 2026-03-03 9:21 UTC (permalink / raw)
To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek
Cc: Biju Das, Lad Prabhakar, tomm.merciai
commit 579c7255922a3e0ba432eb608deb7d0fed896052 upstream.
Replace individual devm_clk_get_enabled() calls with the clk_bulk API
and store the clock handles in the driver's private data structure.
All clocks required by the controller are now acquired and enabled using
devm_clk_bulk_get_all_enabled(), removing the need for per-SoC clock
handling and the renesas_i3c_config data.
The TCLK is accessed via a fixed index in the bulk clock array.
Simplify the code and prepare the driver for upcoming suspend/resume
support.
No functional change intended.
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Link: https://patch.msgid.link/1286f8600b542da55facf9920fed7c06b2b0e4d5.1767781092.git.tommaso.merciai.xr@bp.renesas.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
---
drivers/i3c/master/renesas-i3c.c | 46 +++++++++-----------------------
1 file changed, 13 insertions(+), 33 deletions(-)
diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 040376903a98..b1efe19abd74 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -199,6 +199,8 @@
#define RENESAS_I3C_MAX_DEVS 8
#define I2C_INIT_MSG -1
+#define RENESAS_I3C_TCLK_IDX 1
+
enum i3c_internal_state {
I3C_INTERNAL_STATE_DISABLED,
I3C_INTERNAL_STATE_CONTROLLER_IDLE,
@@ -260,9 +262,10 @@ struct renesas_i3c {
u8 addrs[RENESAS_I3C_MAX_DEVS];
struct renesas_i3c_xferqueue xferqueue;
void __iomem *regs;
- struct clk *tclk;
struct reset_control *tresetn;
struct reset_control *presetn;
+ struct clk_bulk_data *clks;
+ u8 num_clks;
};
struct renesas_i3c_i2c_dev_data {
@@ -275,10 +278,6 @@ struct renesas_i3c_irq_desc {
const char *desc;
};
-struct renesas_i3c_config {
- unsigned int has_pclkrw:1;
-};
-
static inline void renesas_i3c_reg_update(void __iomem *reg, u32 mask, u32 val)
{
u32 data = readl(reg);
@@ -492,7 +491,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
int od_high_ticks, od_low_ticks, i2c_total_ticks;
int ret;
- rate = clk_get_rate(i3c->tclk);
+ rate = clk_get_rate(i3c->clks[RENESAS_I3C_TCLK_IDX].clk);
if (!rate)
return -EINVAL;
@@ -1309,13 +1308,8 @@ static void renesas_i3c_reset_control_assert(void *data)
static int renesas_i3c_probe(struct platform_device *pdev)
{
struct renesas_i3c *i3c;
- struct clk *clk;
- const struct renesas_i3c_config *config = of_device_get_match_data(&pdev->dev);
int ret, i;
- if (!config)
- return -ENODATA;
-
i3c = devm_kzalloc(&pdev->dev, sizeof(*i3c), GFP_KERNEL);
if (!i3c)
return -ENOMEM;
@@ -1324,19 +1318,12 @@ static int renesas_i3c_probe(struct platform_device *pdev)
if (IS_ERR(i3c->regs))
return PTR_ERR(i3c->regs);
- clk = devm_clk_get_enabled(&pdev->dev, "pclk");
- if (IS_ERR(clk))
- return PTR_ERR(clk);
-
- if (config->has_pclkrw) {
- clk = devm_clk_get_enabled(&pdev->dev, "pclkrw");
- if (IS_ERR(clk))
- return PTR_ERR(clk);
- }
-
- i3c->tclk = devm_clk_get_enabled(&pdev->dev, "tclk");
- if (IS_ERR(i3c->tclk))
- return PTR_ERR(i3c->tclk);
+ ret = devm_clk_bulk_get_all_enabled(&pdev->dev, &i3c->clks);
+ if (ret <= RENESAS_I3C_TCLK_IDX)
+ return dev_err_probe(&pdev->dev, ret < 0 ? ret : -EINVAL,
+ "Failed to get clocks (need > %d, got %d)\n",
+ RENESAS_I3C_TCLK_IDX, ret);
+ i3c->num_clks = ret;
i3c->tresetn = devm_reset_control_get_optional_exclusive(&pdev->dev, "tresetn");
if (IS_ERR(i3c->tresetn))
@@ -1401,16 +1388,9 @@ static int renesas_i3c_remove(struct platform_device *pdev)
return 0;
}
-static const struct renesas_i3c_config empty_i3c_config = {
-};
-
-static const struct renesas_i3c_config r9a09g047_i3c_config = {
- .has_pclkrw = 1,
-};
-
static const struct of_device_id renesas_i3c_of_ids[] = {
- { .compatible = "renesas,r9a08g045-i3c", .data = &empty_i3c_config },
- { .compatible = "renesas,r9a09g047-i3c", .data = &r9a09g047_i3c_config },
+ { .compatible = "renesas,r9a08g045-i3c" },
+ { .compatible = "renesas,r9a09g047-i3c" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, renesas_i3c_of_ids);
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 6.1.y-cip 7/9] i3c: renesas: Store clock rate and reset controls in struct renesas_i3c
2026-03-03 9:21 [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
` (5 preceding siblings ...)
2026-03-03 9:21 ` [PATCH 6.1.y-cip 6/9] i3c: renesas: Switch to clk_bulk API and store clocks in private data Tommaso Merciai
@ 2026-03-03 9:21 ` Tommaso Merciai
2026-03-03 9:21 ` [PATCH 6.1.y-cip 8/9] i3c: renesas: Factor out hardware initialization to separate function Tommaso Merciai
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Tommaso Merciai @ 2026-03-03 9:21 UTC (permalink / raw)
To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek
Cc: Biju Das, Lad Prabhakar, tomm.merciai
commit ff4e4f03f0089635b3476d68f5b8833ea67adad6 upstream.
Update the struct renesas_i3c to store the clock rate, presetn and
tresetn handlers. Replace local usage of the clock rate and reset
controls with these structure fields.
Simplify the code and prepare the driver for upcoming suspend/resume
support.
No functional change intended.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Link: https://patch.msgid.link/9e1da95dd9137590c752ecd9429925afcbeb918b.1767781092.git.tommaso.merciai.xr@bp.renesas.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
[tm: Only the clock rate was stored, as the presetn and tresetn
handlers are already present.]
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
---
drivers/i3c/master/renesas-i3c.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index b1efe19abd74..12b25811bafc 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -259,6 +259,7 @@ struct renesas_i3c {
u32 free_pos;
u32 i2c_STDBR;
u32 i3c_STDBR;
+ unsigned long rate;
u8 addrs[RENESAS_I3C_MAX_DEVS];
struct renesas_i3c_xferqueue xferqueue;
void __iomem *regs;
@@ -485,22 +486,21 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
struct i3c_bus *bus = i3c_master_get_bus(m);
struct i3c_device_info info = {};
struct i2c_timings t;
- unsigned long rate;
u32 double_SBR, val;
int cks, pp_high_ticks, pp_low_ticks, i3c_total_ticks;
int od_high_ticks, od_low_ticks, i2c_total_ticks;
int ret;
- rate = clk_get_rate(i3c->clks[RENESAS_I3C_TCLK_IDX].clk);
- if (!rate)
+ i3c->rate = clk_get_rate(i3c->clks[RENESAS_I3C_TCLK_IDX].clk);
+ if (!i3c->rate)
return -EINVAL;
ret = renesas_i3c_reset(i3c);
if (ret)
return ret;
- i2c_total_ticks = DIV_ROUND_UP(rate, bus->scl_rate.i2c);
- i3c_total_ticks = DIV_ROUND_UP(rate, bus->scl_rate.i3c);
+ i2c_total_ticks = DIV_ROUND_UP(i3c->rate, bus->scl_rate.i2c);
+ i3c_total_ticks = DIV_ROUND_UP(i3c->rate, bus->scl_rate.i3c);
i2c_parse_fw_timings(&m->dev, &t, true);
@@ -513,7 +513,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
pp_high_ticks = ((i3c_total_ticks * 5) / 10);
else
pp_high_ticks = DIV_ROUND_UP(I3C_BUS_THIGH_MIXED_MAX_NS,
- NSEC_PER_SEC / rate);
+ NSEC_PER_SEC / i3c->rate);
pp_low_ticks = i3c_total_ticks - pp_high_ticks;
if ((od_low_ticks / 2) <= 0xFF && pp_low_ticks < 0x3F)
@@ -521,7 +521,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
i2c_total_ticks /= 2;
i3c_total_ticks /= 2;
- rate /= 2;
+ i3c->rate /= 2;
}
/* SCL clock period calculation in Open-drain mode */
@@ -542,8 +542,8 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
STDBR_SBRLP(pp_low_ticks) |
STDBR_SBRHP(pp_high_ticks);
- od_low_ticks -= t.scl_fall_ns / (NSEC_PER_SEC / rate) + 1;
- od_high_ticks -= t.scl_rise_ns / (NSEC_PER_SEC / rate) + 1;
+ od_low_ticks -= t.scl_fall_ns / (NSEC_PER_SEC / i3c->rate) + 1;
+ od_high_ticks -= t.scl_rise_ns / (NSEC_PER_SEC / i3c->rate) + 1;
i3c->i2c_STDBR = (double_SBR ? STDBR_DSBRPO : 0) |
STDBR_SBRLO(double_SBR, od_low_ticks) |
STDBR_SBRHO(double_SBR, od_high_ticks) |
@@ -594,13 +594,13 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
renesas_set_bit(i3c->regs, SCSTRCTL, SCSTRCTL_ACKTWE);
/* Bus condition timing */
- val = DIV_ROUND_UP(I3C_BUS_TBUF_MIXED_FM_MIN_NS, NSEC_PER_SEC / rate);
+ val = DIV_ROUND_UP(I3C_BUS_TBUF_MIXED_FM_MIN_NS, NSEC_PER_SEC / i3c->rate);
renesas_writel(i3c->regs, BFRECDT, BFRECDT_FRECYC(val));
- val = DIV_ROUND_UP(I3C_BUS_TAVAL_MIN_NS, NSEC_PER_SEC / rate);
+ val = DIV_ROUND_UP(I3C_BUS_TAVAL_MIN_NS, NSEC_PER_SEC / i3c->rate);
renesas_writel(i3c->regs, BAVLCDT, BAVLCDT_AVLCYC(val));
- val = DIV_ROUND_UP(I3C_BUS_TIDLE_MIN_NS, NSEC_PER_SEC / rate);
+ val = DIV_ROUND_UP(I3C_BUS_TIDLE_MIN_NS, NSEC_PER_SEC / i3c->rate);
renesas_writel(i3c->regs, BIDLCDT, BIDLCDT_IDLCYC(val));
ret = i3c_master_get_free_addr(m, 0);
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 6.1.y-cip 8/9] i3c: renesas: Factor out hardware initialization to separate function
2026-03-03 9:21 [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
` (6 preceding siblings ...)
2026-03-03 9:21 ` [PATCH 6.1.y-cip 7/9] i3c: renesas: Store clock rate and reset controls in struct renesas_i3c Tommaso Merciai
@ 2026-03-03 9:21 ` Tommaso Merciai
2026-03-03 9:21 ` [PATCH 6.1.y-cip 9/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Tommaso Merciai @ 2026-03-03 9:21 UTC (permalink / raw)
To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek
Cc: Biju Das, Lad Prabhakar, tomm.merciai
commit 5eb3e8763e076a47ab145c5fafcf39f1ac7c7aee upstream.
Move the hardware initialization sequence in renesas_i3c_bus_init()
into a dedicated renesas_i3c_hw_init() helper.
Simplify the code and prepare the driver for upcoming suspend/resume
support.
No functional change intended.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Link: https://patch.msgid.link/795327270a6ceb23e15513a2619a19ae4876cfba.1767781092.git.tommaso.merciai.xr@bp.renesas.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
---
drivers/i3c/master/renesas-i3c.c | 99 ++++++++++++++++++--------------
1 file changed, 55 insertions(+), 44 deletions(-)
diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index 12b25811bafc..c244df4f2fa2 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -480,13 +480,65 @@ static int renesas_i3c_reset(struct renesas_i3c *i3c)
0, 1000, false, i3c->regs, RSTCTL);
}
+static void renesas_i3c_hw_init(struct renesas_i3c *i3c)
+{
+ u32 val;
+
+ /* Disable Slave Mode */
+ renesas_writel(i3c->regs, SVCTL, 0);
+
+ /* Initialize Queue/Buffer threshold */
+ renesas_writel(i3c->regs, NQTHCTL, NQTHCTL_IBIDSSZ(6) |
+ NQTHCTL_CMDQTH(1));
+
+ /* The only supported configuration is two entries*/
+ renesas_writel(i3c->regs, NTBTHCTL0, 0);
+ /* Interrupt when there is one entry in the queue */
+ renesas_writel(i3c->regs, NRQTHCTL, 0);
+
+ /* Enable all Bus/Transfer Status Flags */
+ renesas_writel(i3c->regs, BSTE, BSTE_ALL_FLAG);
+ renesas_writel(i3c->regs, NTSTE, NTSTE_ALL_FLAG);
+
+ /* Interrupt enable settings */
+ renesas_writel(i3c->regs, BIE, BIE_NACKDIE | BIE_TENDIE);
+ renesas_writel(i3c->regs, NTIE, 0);
+
+ /* Clear Status register */
+ renesas_writel(i3c->regs, NTST, 0);
+ renesas_writel(i3c->regs, INST, 0);
+ renesas_writel(i3c->regs, BST, 0);
+
+ /* Hot-Join Acknowlege setting. */
+ renesas_set_bit(i3c->regs, BCTL, BCTL_HJACKCTL);
+
+ renesas_writel(i3c->regs, IBINCTL, IBINCTL_NRHJCTL | IBINCTL_NRMRCTL |
+ IBINCTL_NRSIRCTL);
+
+ renesas_writel(i3c->regs, SCSTLCTL, 0);
+ renesas_set_bit(i3c->regs, SCSTRCTL, SCSTRCTL_ACKTWE);
+
+ /* Bus condition timing */
+ val = DIV_ROUND_UP(I3C_BUS_TBUF_MIXED_FM_MIN_NS,
+ NSEC_PER_SEC / i3c->rate);
+ renesas_writel(i3c->regs, BFRECDT, BFRECDT_FRECYC(val));
+
+ val = DIV_ROUND_UP(I3C_BUS_TAVAL_MIN_NS,
+ NSEC_PER_SEC / i3c->rate);
+ renesas_writel(i3c->regs, BAVLCDT, BAVLCDT_AVLCYC(val));
+
+ val = DIV_ROUND_UP(I3C_BUS_TIDLE_MIN_NS,
+ NSEC_PER_SEC / i3c->rate);
+ renesas_writel(i3c->regs, BIDLCDT, BIDLCDT_IDLCYC(val));
+}
+
static int renesas_i3c_bus_init(struct i3c_master_controller *m)
{
struct renesas_i3c *i3c = to_renesas_i3c(m);
struct i3c_bus *bus = i3c_master_get_bus(m);
struct i3c_device_info info = {};
struct i2c_timings t;
- u32 double_SBR, val;
+ u32 double_SBR;
int cks, pp_high_ticks, pp_low_ticks, i3c_total_ticks;
int od_high_ticks, od_low_ticks, i2c_total_ticks;
int ret;
@@ -559,49 +611,8 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
- /* Disable Slave Mode */
- renesas_writel(i3c->regs, SVCTL, 0);
-
- /* Initialize Queue/Buffer threshold */
- renesas_writel(i3c->regs, NQTHCTL, NQTHCTL_IBIDSSZ(6) |
- NQTHCTL_CMDQTH(1));
-
- /* The only supported configuration is two entries*/
- renesas_writel(i3c->regs, NTBTHCTL0, 0);
- /* Interrupt when there is one entry in the queue */
- renesas_writel(i3c->regs, NRQTHCTL, 0);
-
- /* Enable all Bus/Transfer Status Flags */
- renesas_writel(i3c->regs, BSTE, BSTE_ALL_FLAG);
- renesas_writel(i3c->regs, NTSTE, NTSTE_ALL_FLAG);
-
- /* Interrupt enable settings */
- renesas_writel(i3c->regs, BIE, BIE_NACKDIE | BIE_TENDIE);
- renesas_writel(i3c->regs, NTIE, 0);
-
- /* Clear Status register */
- renesas_writel(i3c->regs, NTST, 0);
- renesas_writel(i3c->regs, INST, 0);
- renesas_writel(i3c->regs, BST, 0);
-
- /* Hot-Join Acknowlege setting. */
- renesas_set_bit(i3c->regs, BCTL, BCTL_HJACKCTL);
-
- renesas_writel(i3c->regs, IBINCTL, IBINCTL_NRHJCTL | IBINCTL_NRMRCTL |
- IBINCTL_NRSIRCTL);
-
- renesas_writel(i3c->regs, SCSTLCTL, 0);
- renesas_set_bit(i3c->regs, SCSTRCTL, SCSTRCTL_ACKTWE);
-
- /* Bus condition timing */
- val = DIV_ROUND_UP(I3C_BUS_TBUF_MIXED_FM_MIN_NS, NSEC_PER_SEC / i3c->rate);
- renesas_writel(i3c->regs, BFRECDT, BFRECDT_FRECYC(val));
-
- val = DIV_ROUND_UP(I3C_BUS_TAVAL_MIN_NS, NSEC_PER_SEC / i3c->rate);
- renesas_writel(i3c->regs, BAVLCDT, BAVLCDT_AVLCYC(val));
-
- val = DIV_ROUND_UP(I3C_BUS_TIDLE_MIN_NS, NSEC_PER_SEC / i3c->rate);
- renesas_writel(i3c->regs, BIDLCDT, BIDLCDT_IDLCYC(val));
+ /* I3C hw init*/
+ renesas_i3c_hw_init(i3c);
ret = i3c_master_get_free_addr(m, 0);
if (ret < 0)
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 6.1.y-cip 9/9] i3c: renesas: Add suspend/resume support
2026-03-03 9:21 [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
` (7 preceding siblings ...)
2026-03-03 9:21 ` [PATCH 6.1.y-cip 8/9] i3c: renesas: Factor out hardware initialization to separate function Tommaso Merciai
@ 2026-03-03 9:21 ` Tommaso Merciai
2026-03-05 8:38 ` [PATCH 6.1.y-cip 0/9] " Pavel Machek
2026-03-06 13:22 ` Pavel Machek
10 siblings, 0 replies; 12+ messages in thread
From: Tommaso Merciai @ 2026-03-03 9:21 UTC (permalink / raw)
To: cip-dev, Nobuhiro Iwamatsu, Pavel Machek
Cc: Biju Das, Lad Prabhakar, tomm.merciai
commit e7218986319b4e903dfb4642dcbd1087cf16aaec upstream.
The Renesas I3C controller does not retain its register state across system
suspend, requiring the driver to explicitly save and restore hardware
configuration.
Add suspend and resume NOIRQ callbacks to handle system sleep transitions.
During suspend, save the Device Address Table (DAT) entries, assert reset
lines, and disable all related clocks to allow the controller to enter a
low-power state.
On resume, re-enable clocks and reset lines in the proper order. Restore
the REFCKCTL register, master dynamic address, and all DAT entries, then
reinitialize the controller.
Store the REFCLK divider value, and the master dynamic address to restore
timing and addressing configuration after resume.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Link: https://patch.msgid.link/c469ef89e0156d37746a85bfc314232847d1185a.1767781092.git.tommaso.merciai.xr@bp.renesas.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
[tm: Moved presetn and tresetn into the renesas_i3c struct to prevent
incorrect padding, aligned with upstream work]
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
---
drivers/i3c/master/renesas-i3c.c | 93 +++++++++++++++++++++++++++++++-
1 file changed, 91 insertions(+), 2 deletions(-)
diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
index c244df4f2fa2..2086a3ff016e 100644
--- a/drivers/i3c/master/renesas-i3c.c
+++ b/drivers/i3c/master/renesas-i3c.c
@@ -257,16 +257,19 @@ struct renesas_i3c {
enum i3c_internal_state internal_state;
u16 maxdevs;
u32 free_pos;
+ u32 dyn_addr;
u32 i2c_STDBR;
u32 i3c_STDBR;
unsigned long rate;
u8 addrs[RENESAS_I3C_MAX_DEVS];
struct renesas_i3c_xferqueue xferqueue;
void __iomem *regs;
- struct reset_control *tresetn;
- struct reset_control *presetn;
+ u32 *DATBASn;
struct clk_bulk_data *clks;
+ struct reset_control *presetn;
+ struct reset_control *tresetn;
u8 num_clks;
+ u8 refclk_div;
};
struct renesas_i3c_i2c_dev_data {
@@ -610,6 +613,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
EXTBR_EBRHP(pp_high_ticks));
renesas_writel(i3c->regs, REFCKCTL, REFCKCTL_IREFCKS(cks));
+ i3c->refclk_div = cks;
/* I3C hw init*/
renesas_i3c_hw_init(i3c);
@@ -618,6 +622,7 @@ static int renesas_i3c_bus_init(struct i3c_master_controller *m)
if (ret < 0)
return ret;
+ i3c->dyn_addr = ret;
renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYAD(ret) | MSDVAD_MDYADV);
memset(&info, 0, sizeof(info));
@@ -1387,6 +1392,12 @@ static int renesas_i3c_probe(struct platform_device *pdev)
i3c->maxdevs = RENESAS_I3C_MAX_DEVS;
i3c->free_pos = GENMASK(i3c->maxdevs - 1, 0);
+ /* Allocate dynamic Device Address Table backup. */
+ i3c->DATBASn = devm_kzalloc(&pdev->dev, sizeof(u32) * i3c->maxdevs,
+ GFP_KERNEL);
+ if (!i3c->DATBASn)
+ return -ENOMEM;
+
return i3c_master_register(&i3c->base, &pdev->dev, &renesas_i3c_ops, false);
}
@@ -1399,6 +1410,83 @@ static int renesas_i3c_remove(struct platform_device *pdev)
return 0;
}
+static int renesas_i3c_suspend_noirq(struct device *dev)
+{
+ struct renesas_i3c *i3c = dev_get_drvdata(dev);
+ int i, ret;
+
+ i2c_mark_adapter_suspended(&i3c->base.i2c);
+
+ /* Store Device Address Table values. */
+ for (i = 0; i < i3c->maxdevs; i++)
+ i3c->DATBASn[i] = renesas_readl(i3c->regs, DATBAS(i));
+
+ ret = reset_control_assert(i3c->presetn);
+ if (ret)
+ goto err_mark_resumed;
+
+ ret = reset_control_assert(i3c->tresetn);
+ if (ret)
+ goto err_presetn;
+
+ clk_bulk_disable(i3c->num_clks, i3c->clks);
+
+ return 0;
+
+err_presetn:
+ reset_control_deassert(i3c->presetn);
+err_mark_resumed:
+ i2c_mark_adapter_resumed(&i3c->base.i2c);
+
+ return ret;
+}
+
+static int renesas_i3c_resume_noirq(struct device *dev)
+{
+ struct renesas_i3c *i3c = dev_get_drvdata(dev);
+ int i, ret;
+
+ ret = reset_control_deassert(i3c->presetn);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(i3c->tresetn);
+ if (ret)
+ goto err_presetn;
+
+ ret = clk_bulk_enable(i3c->num_clks, i3c->clks);
+ if (ret)
+ goto err_tresetn;
+
+ /* Re-store I3C registers value. */
+ renesas_writel(i3c->regs, REFCKCTL,
+ REFCKCTL_IREFCKS(i3c->refclk_div));
+ renesas_writel(i3c->regs, MSDVAD, MSDVAD_MDYADV |
+ MSDVAD_MDYAD(i3c->dyn_addr));
+
+ /* Restore Device Address Table values. */
+ for (i = 0; i < i3c->maxdevs; i++)
+ renesas_writel(i3c->regs, DATBAS(i), i3c->DATBASn[i]);
+
+ /* I3C hw init. */
+ renesas_i3c_hw_init(i3c);
+
+ i2c_mark_adapter_resumed(&i3c->base.i2c);
+
+ return 0;
+
+err_tresetn:
+ reset_control_assert(i3c->tresetn);
+err_presetn:
+ reset_control_assert(i3c->presetn);
+ return ret;
+}
+
+static const struct dev_pm_ops renesas_i3c_pm_ops = {
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(renesas_i3c_suspend_noirq,
+ renesas_i3c_resume_noirq)
+};
+
static const struct of_device_id renesas_i3c_of_ids[] = {
{ .compatible = "renesas,r9a08g045-i3c" },
{ .compatible = "renesas,r9a09g047-i3c" },
@@ -1412,6 +1500,7 @@ static struct platform_driver renesas_i3c = {
.driver = {
.name = "renesas-i3c",
.of_match_table = renesas_i3c_of_ids,
+ .pm = pm_sleep_ptr(&renesas_i3c_pm_ops),
},
};
module_platform_driver(renesas_i3c);
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support
2026-03-03 9:21 [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
` (8 preceding siblings ...)
2026-03-03 9:21 ` [PATCH 6.1.y-cip 9/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
@ 2026-03-05 8:38 ` Pavel Machek
2026-03-06 13:22 ` Pavel Machek
10 siblings, 0 replies; 12+ messages in thread
From: Pavel Machek @ 2026-03-05 8:38 UTC (permalink / raw)
To: Tommaso Merciai
Cc: cip-dev, Nobuhiro Iwamatsu, Pavel Machek, Biju Das, Lad Prabhakar,
tomm.merciai
[-- Attachment #1: Type: text/plain, Size: 571 bytes --]
Hi!
> This series enable I3C on RZ/G3E SoM and adds suspend/resume support to the
> Renesas I3C controller driver into linux-cip-6.1.y.
>
> The series also includes patches required to backport:
>
> - devm_clk_bulk_get_all_enabled()
>
> Into linux-cip-6.1.y, which are used by the main suspend/resume
> patch.
This looks okay to me.
Reviewed-by: Pavel Machek <pavel@nabladev.com>
I can apply the series if it passes testing and there are no other
comments.
Best regards,
Pavel
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support
2026-03-03 9:21 [PATCH 6.1.y-cip 0/9] i3c: renesas: Add suspend/resume support Tommaso Merciai
` (9 preceding siblings ...)
2026-03-05 8:38 ` [PATCH 6.1.y-cip 0/9] " Pavel Machek
@ 2026-03-06 13:22 ` Pavel Machek
10 siblings, 0 replies; 12+ messages in thread
From: Pavel Machek @ 2026-03-06 13:22 UTC (permalink / raw)
To: Tommaso Merciai
Cc: cip-dev, Nobuhiro Iwamatsu, Pavel Machek, Biju Das, Lad Prabhakar,
tomm.merciai
[-- Attachment #1: Type: text/plain, Size: 188 bytes --]
Hi!
> This series enable I3C on RZ/G3E SoM and adds suspend/resume support to the
> Renesas I3C controller driver into linux-cip-6.1.y.
Thank you, applied.
Best regards,
Pavel
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread