* [PATCH 0/6] can: rcar_canfd: Add suspend/resume support
@ 2025-08-22 9:50 Geert Uytterhoeven
2025-08-22 9:50 ` [PATCH 1/6] can: rcar_canfd: Invert reset assert order Geert Uytterhoeven
` (5 more replies)
0 siblings, 6 replies; 13+ messages in thread
From: Geert Uytterhoeven @ 2025-08-22 9:50 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Biju Das
Cc: linux-can, linux-renesas-soc, Geert Uytterhoeven
Hi all,
This patch series adds proper suspend/resume support to the Renesas
R-Car CAN-FD controller driver, after the customary cleanuops and fixes.
It aims to fix CAN-FD operation after resume from s2ram on systems where
PSCI powers down the SoC.
The last patch is marked RFC, as it causes a regression on R-Car Gen4.
More details can be found in that patch.
This has been tested on Ebisu-4D (R-Car E3) and White Hawk (R-Car V4H).
Thanks for your comments!
Geert Uytterhoeven (6):
can: rcar_canfd: Invert reset assert order
can: rcar_canfd: Invert global vs. channel teardown
can: rcar_canfd: Extract rcar_canfd_global_{,de}init()
can: rcar_canfd: Invert CAN clock and close_candev() order
can: rcar_canfd: Convert to DEFINE_SIMPLE_DEV_PM_OPS()
[RFC] can: rcar_canfd: Add suspend/resume support
drivers/net/can/rcar/rcar_canfd.c | 225 ++++++++++++++++++++----------
1 file changed, 152 insertions(+), 73 deletions(-)
--
2.43.0
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/6] can: rcar_canfd: Invert reset assert order
2025-08-22 9:50 [PATCH 0/6] can: rcar_canfd: Add suspend/resume support Geert Uytterhoeven
@ 2025-08-22 9:50 ` Geert Uytterhoeven
2025-08-22 14:24 ` Biju Das
2025-08-22 9:50 ` [PATCH 2/6] can: rcar_canfd: Invert global vs. channel teardown Geert Uytterhoeven
` (4 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Geert Uytterhoeven @ 2025-08-22 9:50 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Biju Das
Cc: linux-can, linux-renesas-soc, Geert Uytterhoeven
The two resets are asserted during cleanup in the same order as they
were deasserted during probe. Invert the order to restore symmetry.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/net/can/rcar/rcar_canfd.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index b3c8c592fb0e04ed..6f013f87f25c1494 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -2182,8 +2182,8 @@ static int rcar_canfd_probe(struct platform_device *pdev)
fail_clk:
clk_disable_unprepare(gpriv->clkp);
fail_reset:
- reset_control_assert(gpriv->rstc1);
reset_control_assert(gpriv->rstc2);
+ reset_control_assert(gpriv->rstc1);
fail_dev:
return err;
}
@@ -2204,8 +2204,8 @@ static void rcar_canfd_remove(struct platform_device *pdev)
/* Enter global sleep mode */
rcar_canfd_set_bit(gpriv->base, RCANFD_GCTR, RCANFD_GCTR_GSLPR);
clk_disable_unprepare(gpriv->clkp);
- reset_control_assert(gpriv->rstc1);
reset_control_assert(gpriv->rstc2);
+ reset_control_assert(gpriv->rstc1);
}
static int __maybe_unused rcar_canfd_suspend(struct device *dev)
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/6] can: rcar_canfd: Invert global vs. channel teardown
2025-08-22 9:50 [PATCH 0/6] can: rcar_canfd: Add suspend/resume support Geert Uytterhoeven
2025-08-22 9:50 ` [PATCH 1/6] can: rcar_canfd: Invert reset assert order Geert Uytterhoeven
@ 2025-08-22 9:50 ` Geert Uytterhoeven
2025-08-22 14:21 ` Biju Das
2025-08-22 9:50 ` [PATCH 3/6] can: rcar_canfd: Extract rcar_canfd_global_{,de}init() Geert Uytterhoeven
` (3 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Geert Uytterhoeven @ 2025-08-22 9:50 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Biju Das
Cc: linux-can, linux-renesas-soc, Geert Uytterhoeven
Global state is initialized and torn down before per-channel state.
Invert the order to restore symmetry.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/net/can/rcar/rcar_canfd.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index 6f013f87f25c1494..341bc25df32a8973 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -2193,14 +2193,14 @@ static void rcar_canfd_remove(struct platform_device *pdev)
struct rcar_canfd_global *gpriv = platform_get_drvdata(pdev);
u32 ch;
- rcar_canfd_reset_controller(gpriv);
- rcar_canfd_disable_global_interrupts(gpriv);
-
for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
rcar_canfd_disable_channel_interrupts(gpriv->ch[ch]);
rcar_canfd_channel_remove(gpriv, ch);
}
+ rcar_canfd_disable_global_interrupts(gpriv);
+ rcar_canfd_reset_controller(gpriv);
+
/* Enter global sleep mode */
rcar_canfd_set_bit(gpriv->base, RCANFD_GCTR, RCANFD_GCTR_GSLPR);
clk_disable_unprepare(gpriv->clkp);
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/6] can: rcar_canfd: Extract rcar_canfd_global_{,de}init()
2025-08-22 9:50 [PATCH 0/6] can: rcar_canfd: Add suspend/resume support Geert Uytterhoeven
2025-08-22 9:50 ` [PATCH 1/6] can: rcar_canfd: Invert reset assert order Geert Uytterhoeven
2025-08-22 9:50 ` [PATCH 2/6] can: rcar_canfd: Invert global vs. channel teardown Geert Uytterhoeven
@ 2025-08-22 9:50 ` Geert Uytterhoeven
2025-08-22 9:50 ` [PATCH 4/6] can: rcar_canfd: Invert CAN clock and close_candev() order Geert Uytterhoeven
` (2 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Geert Uytterhoeven @ 2025-08-22 9:50 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Biju Das
Cc: linux-can, linux-renesas-soc, Geert Uytterhoeven
Extract the code to (de)initialize global state into separate functions,
for future reuse.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/net/can/rcar/rcar_canfd.c | 160 +++++++++++++++++-------------
1 file changed, 93 insertions(+), 67 deletions(-)
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index 341bc25df32a8973..38c1b327f6b1d540 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -1950,22 +1950,110 @@ static void rcar_canfd_channel_remove(struct rcar_canfd_global *gpriv, u32 ch)
}
}
+static int rcar_canfd_global_init(struct rcar_canfd_global *gpriv)
+{
+ struct device *dev = &gpriv->pdev->dev;
+ u32 rule_entry = 0;
+ u32 ch, sts;
+ int err;
+
+ err = reset_control_reset(gpriv->rstc1);
+ if (err)
+ return err;
+
+ err = reset_control_reset(gpriv->rstc2);
+ if (err)
+ goto fail_reset1;
+
+ /* Enable peripheral clock for register access */
+ err = clk_prepare_enable(gpriv->clkp);
+ if (err) {
+ dev_err(dev, "failed to enable peripheral clock: %pe\n",
+ ERR_PTR(err));
+ goto fail_reset2;
+ }
+
+ err = rcar_canfd_reset_controller(gpriv);
+ if (err) {
+ dev_err(dev, "reset controller failed: %pe\n", ERR_PTR(err));
+ goto fail_clk;
+ }
+
+ /* Controller in Global reset & Channel reset mode */
+ rcar_canfd_configure_controller(gpriv);
+
+ /* Configure per channel attributes */
+ for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+ /* Configure Channel's Rx fifo */
+ rcar_canfd_configure_rx(gpriv, ch);
+
+ /* Configure Channel's Tx (Common) fifo */
+ rcar_canfd_configure_tx(gpriv, ch);
+
+ /* Configure receive rules */
+ rcar_canfd_configure_afl_rules(gpriv, ch, rule_entry);
+ rule_entry += RCANFD_CHANNEL_NUMRULES;
+ }
+
+ /* Configure common interrupts */
+ rcar_canfd_enable_global_interrupts(gpriv);
+
+ /* Start Global operation mode */
+ rcar_canfd_update_bit(gpriv->base, RCANFD_GCTR, RCANFD_GCTR_GMDC_MASK,
+ RCANFD_GCTR_GMDC_GOPM);
+
+ /* Verify mode change */
+ err = readl_poll_timeout((gpriv->base + RCANFD_GSTS), sts,
+ !(sts & RCANFD_GSTS_GNOPM), 2, 500000);
+ if (err) {
+ dev_err(dev, "global operational mode failed\n");
+ goto fail_mode;
+ }
+
+ return 0;
+
+fail_mode:
+ rcar_canfd_disable_global_interrupts(gpriv);
+fail_clk:
+ clk_disable_unprepare(gpriv->clkp);
+fail_reset2:
+ reset_control_assert(gpriv->rstc2);
+fail_reset1:
+ reset_control_assert(gpriv->rstc1);
+ return err;
+}
+
+static void rcar_canfd_global_deinit(struct rcar_canfd_global *gpriv, bool full)
+{
+ rcar_canfd_disable_global_interrupts(gpriv);
+
+ if (full) {
+ rcar_canfd_reset_controller(gpriv);
+
+ /* Enter global sleep mode */
+ rcar_canfd_set_bit(gpriv->base, RCANFD_GCTR, RCANFD_GCTR_GSLPR);
+ }
+
+ clk_disable_unprepare(gpriv->clkp);
+ reset_control_assert(gpriv->rstc2);
+ reset_control_assert(gpriv->rstc1);
+}
+
static int rcar_canfd_probe(struct platform_device *pdev)
{
struct phy *transceivers[RCANFD_NUM_CHANNELS] = { NULL, };
const struct rcar_canfd_hw_info *info;
struct device *dev = &pdev->dev;
void __iomem *addr;
- u32 sts, ch, fcan_freq;
struct rcar_canfd_global *gpriv;
struct device_node *of_child;
unsigned long channels_mask = 0;
int err, ch_irq, g_irq;
int g_err_irq, g_recc_irq;
- u32 rule_entry = 0;
bool fdmode = true; /* CAN FD only mode - default */
char name[9] = "channelX";
struct clk *clk_ram;
+ u32 ch, fcan_freq;
int i;
info = of_device_get_match_data(dev);
@@ -2107,59 +2195,9 @@ static int rcar_canfd_probe(struct platform_device *pdev)
}
}
- err = reset_control_reset(gpriv->rstc1);
+ err = rcar_canfd_global_init(gpriv);
if (err)
- goto fail_dev;
- err = reset_control_reset(gpriv->rstc2);
- if (err) {
- reset_control_assert(gpriv->rstc1);
- goto fail_dev;
- }
-
- /* Enable peripheral clock for register access */
- err = clk_prepare_enable(gpriv->clkp);
- if (err) {
- dev_err(dev, "failed to enable peripheral clock: %pe\n",
- ERR_PTR(err));
- goto fail_reset;
- }
-
- err = rcar_canfd_reset_controller(gpriv);
- if (err) {
- dev_err(dev, "reset controller failed: %pe\n", ERR_PTR(err));
- goto fail_clk;
- }
-
- /* Controller in Global reset & Channel reset mode */
- rcar_canfd_configure_controller(gpriv);
-
- /* Configure per channel attributes */
- for_each_set_bit(ch, &gpriv->channels_mask, info->max_channels) {
- /* Configure Channel's Rx fifo */
- rcar_canfd_configure_rx(gpriv, ch);
-
- /* Configure Channel's Tx (Common) fifo */
- rcar_canfd_configure_tx(gpriv, ch);
-
- /* Configure receive rules */
- rcar_canfd_configure_afl_rules(gpriv, ch, rule_entry);
- rule_entry += RCANFD_CHANNEL_NUMRULES;
- }
-
- /* Configure common interrupts */
- rcar_canfd_enable_global_interrupts(gpriv);
-
- /* Start Global operation mode */
- rcar_canfd_update_bit(gpriv->base, RCANFD_GCTR, RCANFD_GCTR_GMDC_MASK,
- RCANFD_GCTR_GMDC_GOPM);
-
- /* Verify mode change */
- err = readl_poll_timeout((gpriv->base + RCANFD_GSTS), sts,
- !(sts & RCANFD_GSTS_GNOPM), 2, 500000);
- if (err) {
- dev_err(dev, "global operational mode failed\n");
goto fail_mode;
- }
for_each_set_bit(ch, &gpriv->channels_mask, info->max_channels) {
err = rcar_canfd_channel_probe(gpriv, ch, fcan_freq,
@@ -2178,12 +2216,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
for_each_set_bit(ch, &gpriv->channels_mask, info->max_channels)
rcar_canfd_channel_remove(gpriv, ch);
fail_mode:
- rcar_canfd_disable_global_interrupts(gpriv);
-fail_clk:
- clk_disable_unprepare(gpriv->clkp);
-fail_reset:
- reset_control_assert(gpriv->rstc2);
- reset_control_assert(gpriv->rstc1);
+ rcar_canfd_global_deinit(gpriv, false);
fail_dev:
return err;
}
@@ -2198,14 +2231,7 @@ static void rcar_canfd_remove(struct platform_device *pdev)
rcar_canfd_channel_remove(gpriv, ch);
}
- rcar_canfd_disable_global_interrupts(gpriv);
- rcar_canfd_reset_controller(gpriv);
-
- /* Enter global sleep mode */
- rcar_canfd_set_bit(gpriv->base, RCANFD_GCTR, RCANFD_GCTR_GSLPR);
- clk_disable_unprepare(gpriv->clkp);
- reset_control_assert(gpriv->rstc2);
- reset_control_assert(gpriv->rstc1);
+ rcar_canfd_global_deinit(gpriv, true);
}
static int __maybe_unused rcar_canfd_suspend(struct device *dev)
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 4/6] can: rcar_canfd: Invert CAN clock and close_candev() order
2025-08-22 9:50 [PATCH 0/6] can: rcar_canfd: Add suspend/resume support Geert Uytterhoeven
` (2 preceding siblings ...)
2025-08-22 9:50 ` [PATCH 3/6] can: rcar_canfd: Extract rcar_canfd_global_{,de}init() Geert Uytterhoeven
@ 2025-08-22 9:50 ` Geert Uytterhoeven
2025-08-22 14:26 ` Biju Das
2025-08-22 9:50 ` [PATCH 5/6] can: rcar_canfd: Convert to DEFINE_SIMPLE_DEV_PM_OPS() Geert Uytterhoeven
2025-08-22 9:50 ` [PATCH/RFC 6/6] can: rcar_canfd: Add suspend/resume support Geert Uytterhoeven
5 siblings, 1 reply; 13+ messages in thread
From: Geert Uytterhoeven @ 2025-08-22 9:50 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Biju Das
Cc: linux-can, linux-renesas-soc, Geert Uytterhoeven
The CAN clock is enabled before calling open_candev(), and disabled
before calling close_candev(). Invert the order of the latter, to
restore symmetry.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/net/can/rcar/rcar_canfd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index 38c1b327f6b1d540..de5121efdabdb6ed 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -1561,8 +1561,8 @@ static int rcar_canfd_close(struct net_device *ndev)
netif_stop_queue(ndev);
rcar_canfd_stop(ndev);
napi_disable(&priv->napi);
- clk_disable_unprepare(gpriv->can_clk);
close_candev(ndev);
+ clk_disable_unprepare(gpriv->can_clk);
phy_power_off(priv->transceiver);
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 5/6] can: rcar_canfd: Convert to DEFINE_SIMPLE_DEV_PM_OPS()
2025-08-22 9:50 [PATCH 0/6] can: rcar_canfd: Add suspend/resume support Geert Uytterhoeven
` (3 preceding siblings ...)
2025-08-22 9:50 ` [PATCH 4/6] can: rcar_canfd: Invert CAN clock and close_candev() order Geert Uytterhoeven
@ 2025-08-22 9:50 ` Geert Uytterhoeven
2025-08-22 14:27 ` Biju Das
2025-08-22 9:50 ` [PATCH/RFC 6/6] can: rcar_canfd: Add suspend/resume support Geert Uytterhoeven
5 siblings, 1 reply; 13+ messages in thread
From: Geert Uytterhoeven @ 2025-08-22 9:50 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Biju Das
Cc: linux-can, linux-renesas-soc, Geert Uytterhoeven
Convert the Renesas R-Car CAN-FD driver from SIMPLE_DEV_PM_OPS() to
DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr(). This lets us drop the
__maybe_unused annotations from its suspend and resume callbacks, and
reduces kernel size in case CONFIG_PM or CONFIG_PM_SLEEP is disabled.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/net/can/rcar/rcar_canfd.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index de5121efdabdb6ed..eedce83b91414c57 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -2234,18 +2234,18 @@ static void rcar_canfd_remove(struct platform_device *pdev)
rcar_canfd_global_deinit(gpriv, true);
}
-static int __maybe_unused rcar_canfd_suspend(struct device *dev)
+static int rcar_canfd_suspend(struct device *dev)
{
return 0;
}
-static int __maybe_unused rcar_canfd_resume(struct device *dev)
+static int rcar_canfd_resume(struct device *dev)
{
return 0;
}
-static SIMPLE_DEV_PM_OPS(rcar_canfd_pm_ops, rcar_canfd_suspend,
- rcar_canfd_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(rcar_canfd_pm_ops, rcar_canfd_suspend,
+ rcar_canfd_resume);
static const __maybe_unused struct of_device_id rcar_canfd_of_table[] = {
{ .compatible = "renesas,r8a779a0-canfd", .data = &rcar_gen4_hw_info },
@@ -2262,7 +2262,7 @@ static struct platform_driver rcar_canfd_driver = {
.driver = {
.name = RCANFD_DRV_NAME,
.of_match_table = of_match_ptr(rcar_canfd_of_table),
- .pm = &rcar_canfd_pm_ops,
+ .pm = pm_sleep_ptr(&rcar_canfd_pm_ops),
},
.probe = rcar_canfd_probe,
.remove = rcar_canfd_remove,
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH/RFC 6/6] can: rcar_canfd: Add suspend/resume support
2025-08-22 9:50 [PATCH 0/6] can: rcar_canfd: Add suspend/resume support Geert Uytterhoeven
` (4 preceding siblings ...)
2025-08-22 9:50 ` [PATCH 5/6] can: rcar_canfd: Convert to DEFINE_SIMPLE_DEV_PM_OPS() Geert Uytterhoeven
@ 2025-08-22 9:50 ` Geert Uytterhoeven
2025-08-22 13:39 ` Biju Das
5 siblings, 1 reply; 13+ messages in thread
From: Geert Uytterhoeven @ 2025-08-22 9:50 UTC (permalink / raw)
To: Marc Kleine-Budde, Vincent Mailhol, Biju Das
Cc: linux-can, linux-renesas-soc, Geert Uytterhoeven
On R-Car Gen3 using PSCI, s2ram powers down the SoC. After resume, the
CAN-FD interface no longer works. Trying to bring it up again fails:
# ip link set can0 up
RTNETLINK answers: Connection timed out
# dmesg
...
channel 0 communication state failed
Fix this by populating the (currently empty) suspend and resume
callbacks, to stop/start the individual CAN-FD channels, and
(de)initialize the CAN-FD controller.
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
While this fixes CAN-FD after resume from s2ram on R-Car E3 (Ebisu-4D),
it does introduce a regression on R-Car V4H (White Hawk): after resume
from s2idle (White Hawk does not support s2ram), CAN frames sent by
other devices are no longer received, and the other side sometimes
reports a "bus-off".
However, the underlying issue is pre-existing, and can be reproduced
without this patch: the CAN-FD controller fails in the same way after
driver unbind/rebind. So something must be missing in the
(de)initialization sequence for the R-Car Gen4 CAN-FD register layout.
Note that it keeps on working after ifdown/ifup, which does not
reinitialize the full controller.
---
drivers/net/can/rcar/rcar_canfd.c | 53 +++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index eedce83b91414c57..6b0c563e894f74b3 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -2236,11 +2236,64 @@ static void rcar_canfd_remove(struct platform_device *pdev)
static int rcar_canfd_suspend(struct device *dev)
{
+ struct rcar_canfd_global *gpriv = dev_get_drvdata(dev);
+ int err;
+ u32 ch;
+
+ for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+ struct rcar_canfd_channel *priv = gpriv->ch[ch];
+ struct net_device *ndev = priv->ndev;
+
+ if (!netif_running(ndev))
+ continue;
+
+ netif_device_detach(ndev);
+
+ err = rcar_canfd_close(ndev);
+ if (err) {
+ netdev_err(ndev, "rcar_canfd_close() failed %pe\n",
+ ERR_PTR(err));
+ return err;
+ }
+
+ priv->can.state = CAN_STATE_SLEEPING;
+ }
+
+ /* TODO Skip if wake-up (which is not yet supported) is enabled */
+ rcar_canfd_global_deinit(gpriv, false);
+
return 0;
}
static int rcar_canfd_resume(struct device *dev)
{
+ struct rcar_canfd_global *gpriv = dev_get_drvdata(dev);
+ int err;
+ u32 ch;
+
+ err = rcar_canfd_global_init(gpriv);
+ if (err) {
+ dev_err(dev, "rcar_canfd_open() failed %pe\n", ERR_PTR(err));
+ return err;
+ }
+
+ for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+ struct rcar_canfd_channel *priv = gpriv->ch[ch];
+ struct net_device *ndev = priv->ndev;
+
+ if (!netif_running(ndev))
+ continue;
+
+ err = rcar_canfd_open(ndev);
+ if (err) {
+ netdev_err(ndev, "rcar_canfd_open() failed %pe\n",
+ ERR_PTR(err));
+ return err;
+ }
+
+ netif_device_attach(ndev);
+ }
+
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* RE: [PATCH/RFC 6/6] can: rcar_canfd: Add suspend/resume support
2025-08-22 9:50 ` [PATCH/RFC 6/6] can: rcar_canfd: Add suspend/resume support Geert Uytterhoeven
@ 2025-08-22 13:39 ` Biju Das
2025-08-22 16:19 ` Biju Das
0 siblings, 1 reply; 13+ messages in thread
From: Biju Das @ 2025-08-22 13:39 UTC (permalink / raw)
To: Geert Uytterhoeven, Marc Kleine-Budde, Vincent Mailhol
Cc: linux-can@vger.kernel.org, linux-renesas-soc@vger.kernel.org
Hi Geert,
> -----Original Message-----
> From: Geert Uytterhoeven <geert+renesas@glider.be>
> Sent: 22 August 2025 10:51
> To: Marc Kleine-Budde <mkl@pengutronix.de>; Vincent Mailhol <mailhol.vincent@wanadoo.fr>; Biju Das
> <biju.das.jz@bp.renesas.com>
> Cc: linux-can@vger.kernel.org; linux-renesas-soc@vger.kernel.org; Geert Uytterhoeven
> <geert+renesas@glider.be>
> Subject: [PATCH/RFC 6/6] can: rcar_canfd: Add suspend/resume support
>
> On R-Car Gen3 using PSCI, s2ram powers down the SoC. After resume, the CAN-FD interface no longer
> works. Trying to bring it up again fails:
>
> # ip link set can0 up
> RTNETLINK answers: Connection timed out
>
> # dmesg
> ...
> channel 0 communication state failed
>
> Fix this by populating the (currently empty) suspend and resume callbacks, to stop/start the individual
> CAN-FD channels, and (de)initialize the CAN-FD controller.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> While this fixes CAN-FD after resume from s2ram on R-Car E3 (Ebisu-4D), it does introduce a regression
> on R-Car V4H (White Hawk): after resume from s2idle (White Hawk does not support s2ram), CAN frames
> sent by other devices are no longer received, and the other side sometimes reports a "bus-off".
>
> However, the underlying issue is pre-existing, and can be reproduced without this patch: the CAN-FD
> controller fails in the same way after driver unbind/rebind. So something must be missing in the
> (de)initialization sequence for the R-Car Gen4 CAN-FD register layout.
> Note that it keeps on working after ifdown/ifup, which does not reinitialize the full controller.
> ---
> drivers/net/can/rcar/rcar_canfd.c | 53 +++++++++++++++++++++++++++++++
> 1 file changed, 53 insertions(+)
>
> diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
> index eedce83b91414c57..6b0c563e894f74b3 100644
> --- a/drivers/net/can/rcar/rcar_canfd.c
> +++ b/drivers/net/can/rcar/rcar_canfd.c
> @@ -2236,11 +2236,64 @@ static void rcar_canfd_remove(struct platform_device *pdev)
>
> static int rcar_canfd_suspend(struct device *dev) {
> + struct rcar_canfd_global *gpriv = dev_get_drvdata(dev);
> + int err;
> + u32 ch;
> +
> + for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
> + struct rcar_canfd_channel *priv = gpriv->ch[ch];
> + struct net_device *ndev = priv->ndev;
> +
> + if (!netif_running(ndev))
> + continue;
> +
> + netif_device_detach(ndev);
> +
> + err = rcar_canfd_close(ndev);
> + if (err) {
> + netdev_err(ndev, "rcar_canfd_close() failed %pe\n",
> + ERR_PTR(err));
> + return err;
> + }
> +
> + priv->can.state = CAN_STATE_SLEEPING;
> + }
> +
> + /* TODO Skip if wake-up (which is not yet supported) is enabled */
> + rcar_canfd_global_deinit(gpriv, false);
> +
> return 0;
> }
>
> static int rcar_canfd_resume(struct device *dev) {
> + struct rcar_canfd_global *gpriv = dev_get_drvdata(dev);
> + int err;
> + u32 ch;
> +
> + err = rcar_canfd_global_init(gpriv);
> + if (err) {
> + dev_err(dev, "rcar_canfd_open() failed %pe\n", ERR_PTR(err));
> + return err;
> + }
> +
> + for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
> + struct rcar_canfd_channel *priv = gpriv->ch[ch];
> + struct net_device *ndev = priv->ndev;
> +
> + if (!netif_running(ndev))
> + continue;
> +
> + err = rcar_canfd_open(ndev);
> + if (err) {
> + netdev_err(ndev, "rcar_canfd_open() failed %pe\n",
> + ERR_PTR(err));
> + return err;
> + }
> +
> + netif_device_attach(ndev);
> + }
> +
> return 0;
> }
>
This patch does not work on RZ/G3E, please see the logs
Bind/Unbind:
-------------
root@smarc-rzg3e:/cip-test-scripts# cd /sys/bus/platform/drivers/rcar_canfd
n > unbindroot@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd# echo 12440000.can > unbind
root@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd# echo 12440000.can > bind
[ 67.645615] rcar_canfd 12440000.can: can_clk rate is 80000000
[ 67.655044] rcar_canfd 12440000.can: device registered (channel 1)
[ 67.661788] rcar_canfd 12440000.can: can_clk rate is 80000000
[ 67.671258] rcar_canfd 12440000.can: device registered (channel 4)
[ 67.677603] rcar_canfd 12440000.can: global operational state (canfd clk, fd mode)
root@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd# /cip-test-scripts/canfd_t_003.sh
[INFO] Testing can0<->can1 with bitrate 1000000 and dbitrate 4000000
[INFO] Bringing down can0 can1
[INFO] Bringing up can0 can1
[INFO] Testing can1 as producer and can0 as consumer
[INFO] Testing can0 as producer and can1 as consumer
[INFO] Testing can0<->can1 with bitrate 500000 and dbitrate 2000000
[INFO] Bringing down can0 can1
[INFO] Bringing up can0 can1
[INFO] Testing can1 as producer and can0 as consumer
[INFO] Testing can0 as producer and can1 as consumer
[INFO] Testing can0<->can1 with bitrate 250000 and dbitrate 1000000
[INFO] Bringing down can0 can1
[INFO] Bringing up can0 can1
[INFO] Testing can1 as producer and can0 as consumer
[INFO] Testing can0 as producer and can1 as consumer
EXIT|PASS|canfd_t_003.sh|[00:00:25] ||
G3E S2Idle:
------------
root@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd# echo s2idle > /sys/power/mem_sleep
root@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd# echo mem > /sys/power/state
[ 160.231921] PM: suspend entry (s2idle)
[ 160.236099] Filesystems sync: 0.000 seconds
[ 160.248409] Freezing user space processes
[ 160.255200] Freezing user space processes completed (elapsed 0.002 seconds)
[ 160.262354] OOM killer disabled.
[ 160.265681] Freezing remaining freezable tasks
[ 160.271723] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[ 160.279253] printk: Suspending console(s) (use no_console_suspend to debug)
[ 160.311505] sd 0:0:0:0: [sda] Synchronizing SCSI cache
[ 160.377382] renesas-gbeth 15c30000.ethernet end0: Link is Down
[ 162.226309] dwmac4: Master AXI performs fixed burst length
[ 162.227718] renesas-gbeth 15c30000.ethernet end0: No Safety Features support found
[ 162.227788] renesas-gbeth 15c30000.ethernet end0: IEEE 1588-2008 Advanced Timestamp supported
[ 162.232919] renesas-gbeth 15c30000.ethernet end0: configuring for phy/rgmii-id link mode
[ 162.252982] dwmac4: Master AXI performs fixed burst length
[ 162.254258] renesas-gbeth 15c40000.ethernet end1: No Safety Features support found
[ 162.254321] renesas-gbeth 15c40000.ethernet end1: IEEE 1588-2008 Advanced Timestamp supported
[ 162.259706] renesas-gbeth 15c40000.ethernet end1: configuring for phy/rgmii-id link mode
[ 162.307564] usb usb1: root hub lost power or was reset
[ 162.307607] usb usb2: root hub lost power or was reset
[ 164.471610] usb 2-1: reset SuperSpeed Plus Gen 2x1 USB device number 2 using xhci-renesas-hcd
[ 164.584382] OOM killer enabled.
[ 164.587540] Restarting tasks: Starting
[ 164.593757] Restarting tasks: Done
[ 164.597263] random: crng reseeded on system resumption
[ 164.602497] PM: suspend exit
root@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd# [ 164.959424] renesas-gbeth 15c30000.ethernet end0: Link is Up - 1Gbps/Full - flow control rx/tx
root@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd# /cip-test-scripts/canfd_t_003.sh
[INFO] Testing can0<->can1 with bitrate 1000000 and dbitrate 4000000
[INFO] Bringing down can0 can1
[INFO] Bringing up can0 can1
[INFO] Testing can1 as producer and can0 as consumer
[INFO] Testing can0 as producer and can1 as consumer
[INFO] Testing can0<->can1 with bitrate 500000 and dbitrate 2000000
[INFO] Bringing down can0 can1
[INFO] Bringing up can0 can1
[INFO] Testing can1 as producer and can0 as consumer
[INFO] Testing can0 as producer and can1 as consumer
[INFO] Testing can0<->can1 with bitrate 250000 and dbitrate 1000000
[INFO] Bringing down can0 can1
[INFO] Bringing up can0 can1
[INFO] Testing can1 as producer and can0 as consumer
[INFO] Testing can0 as producer and can1 as consumer
EXIT|PASS|canfd_t_003.sh|[00:00:25] ||
G3E STR:
--------
root@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd# echo deep > /sys/power/mem_sleep
root@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd# echo mem > /sys/power/state
[ 237.863858] PM: suspend entry (deep)
[ 237.867860] Filesystems sync: 0.000 seconds
[ 237.878623] Freezing user space processes
[ 237.885330] Freezing user space processes completed (elapsed 0.002 seconds)
[ 237.892455] OOM killer disabled.
[ 237.895804] Freezing remaining freezable tasks
[ 237.902064] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[ 237.909648] printk: Suspending console(s) (use no_console_suspend to debug)
NOTICE: BL2: v2.10.5(release):2.10.5/rz_soc_dev-169-g1410189b0
NOTICE: BL2: Built : 12:53:12, Jul 15 2025
NOTICE: BL2: SYS_LSI_MODE: 0x13e06
NOTICE: BL2: SYS_LSI_DEVID: 0x8679447
NOTICE: BL2: SYS_LSI_PRR: 0x0
NOTICE: BL2: Booting BL31
[ 237.943571] sd 0:0:0:0: [sda] Synchronizing SCSI cache
[ 237.992789] renesas-gbeth 15c30000.ethernet end0: Link is Down
[ 238.006388] Disabling non-boot CPUs ...
[ 238.011104] psci: CPU3 killed (polled 0 ms)
[ 238.017799] psci: CPU2 killed (polled 0 ms)
[ 238.023704] psci: CPU1 killed (polled 4 ms)
[ 238.028259] Enabling non-boot CPUs ...
[ 238.028474] Detected VIPT I-cache on CPU1
[ 238.028521] GICv3: CPU1: found redistributor 100 region 0:0x0000000014960000
[ 238.028558] CPU1: Booted secondary processor 0x0000000100 [0x412fd050]
[ 238.029374] CPU1 is up
[ 238.029470] Detected VIPT I-cache on CPU2
[ 238.029492] GICv3: CPU2: found redistributor 200 region 0:0x0000000014980000
[ 238.029513] CPU2: Booted secondary processor 0x0000000200 [0x412fd050]
[ 238.030046] CPU2 is up
[ 238.030145] Detected VIPT I-cache on CPU3
[ 238.030167] GICv3: CPU3: found redistributor 300 region 0:0x00000000149a0000
[ 238.030189] CPU3: Booted secondary processor 0x0000000300 [0x412fd050]
[ 238.030873] CPU3 is up
[ 238.047257] dwmac4: Master AXI performs fixed burst length
[ 238.048165] renesas-gbeth 15c30000.ethernet end0: No Safety Features support found
[ 238.048185] renesas-gbeth 15c30000.ethernet end0: IEEE 1588-2008 Advanced Timestamp supported
[ 238.051680] renesas-gbeth 15c30000.ethernet end0: configuring for phy/rgmii-id link mode
[ 238.069106] dwmac4: Master AXI performs fixed burst length
[ 238.070002] renesas-gbeth 15c40000.ethernet end1: No Safety Features support found
[ 238.070018] renesas-gbeth 15c40000.ethernet end1: IEEE 1588-2008 Advanced Timestamp supported
[ 238.073613] renesas-gbeth 15c40000.ethernet end1: configuring for phy/rgmii-id link mode
[ 238.119909] usb usb1: root hub lost power or was reset
[ 238.119918] usb usb2: root hub lost power or was reset
[ 240.279309] usb 2-1: reset SuperSpeed Plus Gen 2x1 USB device number 2 using xhci-renesas-hcd
[ 240.468214] OOM killer enabled.
[ 240.471358] Restarting tasks: Starting
[ 240.475721] Restarting tasks: Done
[ 240.479171] random: crng reseeded on system resumption
[ 240.484426] PM: suspend exit
root@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd# [ 240.692426] renesas-gbeth 15c30000.ethernet end0: Link is Up - 1Gbps/Full - flow control rx/tx
root@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd#
root@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd# /cip-test-scripts/canfd_t_003.sh
[INFO] Testing can0<->can1 with bitrate 1000000 and dbitrate 4000000
[INFO] Bringing down can0 can1
[INFO] Bringing up can0 can1
[INFO] Testing can1 as producer and can0 as consumer
EXIT|FAIL|canfd_t_003.sh|[00:00:04] Problems while producing data from can1 and consuming from can0||
root@smarc-rzg3e:/sys/bus/platform/drivers/rcar_canfd#
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 2/6] can: rcar_canfd: Invert global vs. channel teardown
2025-08-22 9:50 ` [PATCH 2/6] can: rcar_canfd: Invert global vs. channel teardown Geert Uytterhoeven
@ 2025-08-22 14:21 ` Biju Das
0 siblings, 0 replies; 13+ messages in thread
From: Biju Das @ 2025-08-22 14:21 UTC (permalink / raw)
To: Geert Uytterhoeven, Marc Kleine-Budde, Vincent Mailhol
Cc: linux-can@vger.kernel.org, linux-renesas-soc@vger.kernel.org
Hi Geert,
Thanks for the patch.
> -----Original Message-----
> From: Geert Uytterhoeven <geert+renesas@glider.be>
> Sent: 22 August 2025 10:51
> Subject: [PATCH 2/6] can: rcar_canfd: Invert global vs. channel teardown
>
> Global state is initialized and torn down before per-channel state.
> Invert the order to restore symmetry.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Cheers,
Biju
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 1/6] can: rcar_canfd: Invert reset assert order
2025-08-22 9:50 ` [PATCH 1/6] can: rcar_canfd: Invert reset assert order Geert Uytterhoeven
@ 2025-08-22 14:24 ` Biju Das
0 siblings, 0 replies; 13+ messages in thread
From: Biju Das @ 2025-08-22 14:24 UTC (permalink / raw)
To: Geert Uytterhoeven, Marc Kleine-Budde, Vincent Mailhol
Cc: linux-can@vger.kernel.org, linux-renesas-soc@vger.kernel.org
Hi Geert,
> -----Original Message-----
> From: Geert Uytterhoeven <geert+renesas@glider.be>
> Sent: 22 August 2025 10:51
> Subject: [PATCH 1/6] can: rcar_canfd: Invert reset assert order
>
> The two resets are asserted during cleanup in the same order as they were deasserted during probe.
> Invert the order to restore symmetry.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Cheers,
Biju
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 4/6] can: rcar_canfd: Invert CAN clock and close_candev() order
2025-08-22 9:50 ` [PATCH 4/6] can: rcar_canfd: Invert CAN clock and close_candev() order Geert Uytterhoeven
@ 2025-08-22 14:26 ` Biju Das
0 siblings, 0 replies; 13+ messages in thread
From: Biju Das @ 2025-08-22 14:26 UTC (permalink / raw)
To: Geert Uytterhoeven, Marc Kleine-Budde, Vincent Mailhol
Cc: linux-can@vger.kernel.org, linux-renesas-soc@vger.kernel.org
Hi Geert,
> -----Original Message-----
> From: Geert Uytterhoeven <geert+renesas@glider.be>
> Sent: 22 August 2025 10:51
> Subject: [PATCH 4/6] can: rcar_canfd: Invert CAN clock and close_candev() order
>
> The CAN clock is enabled before calling open_candev(), and disabled before calling close_candev().
> Invert the order of the latter, to restore symmetry.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Cheers,
Biju
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH 5/6] can: rcar_canfd: Convert to DEFINE_SIMPLE_DEV_PM_OPS()
2025-08-22 9:50 ` [PATCH 5/6] can: rcar_canfd: Convert to DEFINE_SIMPLE_DEV_PM_OPS() Geert Uytterhoeven
@ 2025-08-22 14:27 ` Biju Das
0 siblings, 0 replies; 13+ messages in thread
From: Biju Das @ 2025-08-22 14:27 UTC (permalink / raw)
To: Geert Uytterhoeven, Marc Kleine-Budde, Vincent Mailhol
Cc: linux-can@vger.kernel.org, linux-renesas-soc@vger.kernel.org
Hi Geert,
Thanks for the patch.
> -----Original Message-----
> From: Geert Uytterhoeven <geert+renesas@glider.be>
> Sent: 22 August 2025 10:51
> To: Marc Kleine-Budde <mkl@pengutronix.de>; Vincent Mailhol <mailhol.vincent@wanadoo.fr>; Biju Das
> <biju.das.jz@bp.renesas.com>
> Cc: linux-can@vger.kernel.org; linux-renesas-soc@vger.kernel.org; Geert Uytterhoeven
> <geert+renesas@glider.be>
> Subject: [PATCH 5/6] can: rcar_canfd: Convert to DEFINE_SIMPLE_DEV_PM_OPS()
>
> Convert the Renesas R-Car CAN-FD driver from SIMPLE_DEV_PM_OPS() to
> DEFINE_SIMPLE_DEV_PM_OPS() and pm_sleep_ptr(). This lets us drop the __maybe_unused annotations from
> its suspend and resume callbacks, and reduces kernel size in case CONFIG_PM or CONFIG_PM_SLEEP is
> disabled.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com>
Cheers,
Biju
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: [PATCH/RFC 6/6] can: rcar_canfd: Add suspend/resume support
2025-08-22 13:39 ` Biju Das
@ 2025-08-22 16:19 ` Biju Das
0 siblings, 0 replies; 13+ messages in thread
From: Biju Das @ 2025-08-22 16:19 UTC (permalink / raw)
To: Geert Uytterhoeven, Marc Kleine-Budde, Vincent Mailhol
Cc: linux-can@vger.kernel.org, linux-renesas-soc@vger.kernel.org
Hi Geert,
> -----Original Message-----
> From: Biju Das
> Sent: 22 August 2025 14:40
> Subject: RE: [PATCH/RFC 6/6] can: rcar_canfd: Add suspend/resume support
>
> Hi Geert,
>
>
> > -----Original Message-----
> > From: Geert Uytterhoeven <geert+renesas@glider.be>
> > Sent: 22 August 2025 10:51
> > To: Marc Kleine-Budde <mkl@pengutronix.de>; Vincent Mailhol
> > <mailhol.vincent@wanadoo.fr>; Biju Das <biju.das.jz@bp.renesas.com>
> > Cc: linux-can@vger.kernel.org; linux-renesas-soc@vger.kernel.org;
> > Geert Uytterhoeven <geert+renesas@glider.be>
> > Subject: [PATCH/RFC 6/6] can: rcar_canfd: Add suspend/resume support
> >
> > On R-Car Gen3 using PSCI, s2ram powers down the SoC. After resume,
> > the CAN-FD interface no longer works. Trying to bring it up again fails:
> >
> > # ip link set can0 up
> > RTNETLINK answers: Connection timed out
> >
> > # dmesg
> > ...
> > channel 0 communication state failed
> >
> > Fix this by populating the (currently empty) suspend and resume
> > callbacks, to stop/start the individual CAN-FD channels, and (de)initialize the CAN-FD controller.
> >
> > Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> > ---
> > While this fixes CAN-FD after resume from s2ram on R-Car E3
> > (Ebisu-4D), it does introduce a regression on R-Car V4H (White Hawk):
> > after resume from s2idle (White Hawk does not support s2ram), CAN frames sent by other devices are no
> longer received, and the other side sometimes reports a "bus-off".
> >
> > However, the underlying issue is pre-existing, and can be reproduced
> > without this patch: the CAN-FD controller fails in the same way after
> > driver unbind/rebind. So something must be missing in the (de)initialization sequence for the R-Car
> Gen4 CAN-FD register layout.
> > Note that it keeps on working after ifdown/ifup, which does not reinitialize the full controller.
> > ---
> > drivers/net/can/rcar/rcar_canfd.c | 53
> > +++++++++++++++++++++++++++++++
> > 1 file changed, 53 insertions(+)
> >
> > diff --git a/drivers/net/can/rcar/rcar_canfd.c
> > b/drivers/net/can/rcar/rcar_canfd.c
> > index eedce83b91414c57..6b0c563e894f74b3 100644
> > --- a/drivers/net/can/rcar/rcar_canfd.c
> > +++ b/drivers/net/can/rcar/rcar_canfd.c
> > @@ -2236,11 +2236,64 @@ static void rcar_canfd_remove(struct
> > platform_device *pdev)
> >
> > static int rcar_canfd_suspend(struct device *dev) {
> > + struct rcar_canfd_global *gpriv = dev_get_drvdata(dev);
> > + int err;
> > + u32 ch;
> > +
> > + for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
> > + struct rcar_canfd_channel *priv = gpriv->ch[ch];
> > + struct net_device *ndev = priv->ndev;
> > +
> > + if (!netif_running(ndev))
> > + continue;
> > +
> > + netif_device_detach(ndev);
> > +
> > + err = rcar_canfd_close(ndev);
> > + if (err) {
> > + netdev_err(ndev, "rcar_canfd_close() failed %pe\n",
> > + ERR_PTR(err));
> > + return err;
> > + }
> > +
> > + priv->can.state = CAN_STATE_SLEEPING;
> > + }
> > +
> > + /* TODO Skip if wake-up (which is not yet supported) is enabled */
> > + rcar_canfd_global_deinit(gpriv, false);
> > +
> > return 0;
> > }
> >
> > static int rcar_canfd_resume(struct device *dev) {
> > + struct rcar_canfd_global *gpriv = dev_get_drvdata(dev);
> > + int err;
> > + u32 ch;
> > +
> > + err = rcar_canfd_global_init(gpriv);
> > + if (err) {
> > + dev_err(dev, "rcar_canfd_open() failed %pe\n", ERR_PTR(err));
> > + return err;
> > + }
> > +
> > + for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
> > + struct rcar_canfd_channel *priv = gpriv->ch[ch];
> > + struct net_device *ndev = priv->ndev;
> > +
> > + if (!netif_running(ndev))
> > + continue;
> > +
> > + err = rcar_canfd_open(ndev);
> > + if (err) {
> > + netdev_err(ndev, "rcar_canfd_open() failed %pe\n",
> > + ERR_PTR(err));
> > + return err;
> > + }
> > +
> > + netif_device_attach(ndev);
> > + }
> > +
> > return 0;
> > }
> >
STR is now working on G3E based on BSP code with the following modifications[1]
[1]
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index adf73d6238a1..89a1bc73c1af 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -469,6 +469,7 @@ struct rcar_canfd_global {
struct platform_device *pdev; /* Respective platform device */
struct clk *clkp; /* Peripheral clock */
struct clk *can_clk; /* fCAN clock */
+ struct clk *clk_ram; /* Clock RAM */
unsigned long channels_mask; /* Enabled channels mask */
bool extclk; /* CANFD or Ext clock */
bool fdmode; /* CAN FD or Classical CAN only mode */
@@ -2158,7 +2159,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
gpriv->extclk = gpriv->info->external_clk;
}
- clk_ram = devm_clk_get_optional_enabled(dev, "ram_clk");
+ gpriv->clk_ram = devm_clk_get_optional_enabled(dev, "ram_clk");
if (IS_ERR(clk_ram))
return dev_err_probe(dev, PTR_ERR(clk_ram),
"cannot get enabled ram clock\n");
@@ -2262,20 +2263,15 @@ static int rcar_canfd_suspend(struct device *dev)
if (!netif_running(ndev))
continue;
+ netif_stop_queue(ndev);
+ rcar_canfd_stop(ndev);
netif_device_detach(ndev);
-
- err = rcar_canfd_close(ndev);
- if (err) {
- netdev_err(ndev, "rcar_canfd_close() failed %pe\n",
- ERR_PTR(err));
- return err;
- }
-
- priv->can.state = CAN_STATE_SLEEPING;
}
- /* TODO Skip if wake-up (which is not yet supported) is enabled */
- rcar_canfd_global_deinit(gpriv, false);
+ reset_control_assert(gpriv->rstc1);
+ reset_control_assert(gpriv->rstc2);
+ clk_disable_unprepare(gpriv->clkp);
+ clk_disable_unprepare(gpriv->clk_ram);
return 0;
}
@@ -2286,30 +2282,71 @@ static int rcar_canfd_resume(struct device *dev)
int err;
u32 ch;
+ err = reset_control_deassert(gpriv->rstc1);
+ if (err)
+ goto fail_dev;
+
+ err = reset_control_deassert(gpriv->rstc2);
+ if (err) {
+ reset_control_assert(gpriv->rstc1);
+ goto fail_dev;
+ }
+
+ /* Enable peripheral clock for register access */
+ err = clk_prepare_enable(gpriv->clkp);
+ if (err) {
+ dev_err(dev,
+ "failed to enable peripheral clock, error %d\n", err);
+ goto fail_reset;
+ }
+
+ /* Enable RAM clock */
+ err = clk_prepare_enable(gpriv->clk_ram);
+ if (err) {
+ dev_err(dev,
+ "failed to enable ram clock, error %d\n", err);
+ goto fail_reset;
+ }
+
+ err = rcar_canfd_reset_controller(gpriv);
+ if (err) {
+ dev_err(dev, "reset controller failed\n");
+ goto fail_clk;
+ }
+
err = rcar_canfd_global_init(gpriv);
if (err) {
- dev_err(dev, "rcar_canfd_open() failed %pe\n", ERR_PTR(err));
- return err;
+ dev_err(dev, "controller init failed\n");
+ goto fail_mode;
}
- for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) {
+ for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) {
struct rcar_canfd_channel *priv = gpriv->ch[ch];
struct net_device *ndev = priv->ndev;
if (!netif_running(ndev))
continue;
- err = rcar_canfd_open(ndev);
+ netif_device_attach(ndev);
+ err = rcar_canfd_start(ndev);
if (err) {
- netdev_err(ndev, "rcar_canfd_open() failed %pe\n",
- ERR_PTR(err));
+ netif_device_detach(ndev);
return err;
}
-
- netif_device_attach(ndev);
+ netif_start_queue(ndev);
}
return 0;
+
+fail_mode:
+ rcar_canfd_disable_global_interrupts(gpriv);
+fail_clk:
+ clk_disable_unprepare(gpriv->clkp);
+fail_reset:
+ reset_control_assert(gpriv->rstc1);
+ reset_control_assert(gpriv->rstc2);
+fail_dev:
+ return err;
}
[2] logs
root@smarc-rzg3e:/cip-test-scripts# [ 36.691587] PM: suspend entry (deep)
[ 36.695460] Filesystems sync: 0.000 seconds
[ 36.704009] Freezing user space processes
[ 36.709820] Freezing user space processes completed (elapsed 0.001 seconds)
[ 36.716809] OOM killer disabled.
[ 36.720049] Freezing remaining freezable tasks
[ 36.725879] Freezing remaining freezable tasks completed (elapsed 0.001 seconds)
[ 36.733327] printk: Suspending console(s) (use no_console_suspend to debug)
NOTICE: BL2: v2.10.5(release):2.10.5/rz_soc_dev-169-g1410189b0
NOTICE: BL2: Built : 12:53:12, Jul 15 2025
NOTICE: BL2: SYS_LSI_MODE: 0x13e06
NOTICE: BL2: SYS_LSI_DEVID: 0x8679447
NOTICE: BL2: SYS_LSI_PRR: 0x0
NOTICE: BL2: Booting BL31
[ 36.759719] sd 0:0:0:0: [sda] Synchronizing SCSI cache
[ 36.818341] renesas-gbeth 15c30000.ethernet end0: Link is Down
[ 36.832139] Disabling non-boot CPUs ...
[ 36.836762] psci: CPU3 killed (polled 0 ms)
[ 36.843491] psci: CPU2 killed (polled 4 ms)
[ 36.852615] psci: CPU1 killed (polled 0 ms)
[ 36.855973] Enabling non-boot CPUs ...
[ 36.856187] Detected VIPT I-cache on CPU1
[ 36.856231] GICv3: CPU1: found redistributor 100 region 0:0x0000000014960000
[ 36.856268] CPU1: Booted secondary processor 0x0000000100 [0x412fd050]
[ 36.857067] CPU1 is up
[ 36.857163] Detected VIPT I-cache on CPU2
[ 36.857185] GICv3: CPU2: found redistributor 200 region 0:0x0000000014980000
[ 36.857205] CPU2: Booted secondary processor 0x0000000200 [0x412fd050]
[ 36.857783] CPU2 is up
[ 36.857878] Detected VIPT I-cache on CPU3
[ 36.857901] GICv3: CPU3: found redistributor 300 region 0:0x00000000149a0000
[ 36.857923] CPU3: Booted secondary processor 0x0000000300 [0x412fd050]
[ 36.858631] CPU3 is up
[ 36.875320] dwmac4: Master AXI performs fixed burst length
[ 36.876219] renesas-gbeth 15c30000.ethernet end0: No Safety Features support found
[ 36.876241] renesas-gbeth 15c30000.ethernet end0: IEEE 1588-2008 Advanced Timestamp supported
[ 36.879753] renesas-gbeth 15c30000.ethernet end0: configuring for phy/rgmii-id link mode
[ 36.897118] dwmac4: Master AXI performs fixed burst length
[ 36.898009] renesas-gbeth 15c40000.ethernet end1: No Safety Features support found
[ 36.898026] renesas-gbeth 15c40000.ethernet end1: IEEE 1588-2008 Advanced Timestamp supported
[ 36.901567] renesas-gbeth 15c40000.ethernet end1: configuring for phy/rgmii-id link mode
[ 36.948005] usb usb1: root hub lost power or was reset
[ 36.948012] usb usb2: root hub lost power or was reset
[ 39.107397] usb 2-1: reset SuperSpeed Plus Gen 2x1 USB device number 2 using xhci-renesas-hcd
[ 39.294764] OOM killer enabled.
[ 39.297903] Restarting tasks: Starting
[ 39.303378] Restarting tasks: Done
[ 39.306841] random: crng reseeded on system resumption
[ 39.312209] PM: suspend exit
[ 39.502581] renesas-gbeth 15c30000.ethernet end0: Link is Up - 1Gbps/Full - flow control rx/tx
root@smarc-rzg3e:/cip-test-scripts# ./canfd_t_003.sh
[INFO] Testing can0<->can1 with bitrate 1000000 and dbitrate 4000000
[INFO] Bringing down can0 can1
[INFO] Bringing up can0 can1
[INFO] Testing can1 as producer and can0 as consumer
[ 48.400817] can: controller area network core
[ 48.405291] NET: Registered PF_CAN protocol family
[ 48.445879] can: raw protocol
[INFO] Testing can0 as producer and can1 as consumer
[INFO] Testing can0<->can1 with bitrate 500000 and dbitrate 2000000
[INFO] Bringing down can0 can1
[INFO] Bringing up can0 can1
[INFO] Testing can1 as producer and can0 as consumer
[INFO] Testing can0 as producer and can1 as consumer
[INFO] Testing can0<->can1 with bitrate 250000 and dbitrate 1000000
[INFO] Bringing down can0 can1
[INFO] Bringing up can0 can1
[INFO] Testing can1 as producer and can0 as consumer
[INFO] Testing can0 as producer and can1 as consumer
[ 69.411870] kauditd_printk_skb: 5 callbacks suppressed
[ 69.411883] audit: type=1334 audit(1755879165.759:22): prog-id=18 op=UNLOAD
[ 69.423995] audit: type=1334 audit(1755879165.759:23): prog-id=17 op=UNLOAD
[ 69.430946] audit: type=1334 audit(1755879165.759:24): prog-id=16 op=UNLOAD
EXIT|PASS|canfd_t_003.sh|[00:00:25] ||
root@smarc-rzg3e:/cip-test-scripts#
^ permalink raw reply related [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-08-22 16:19 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-22 9:50 [PATCH 0/6] can: rcar_canfd: Add suspend/resume support Geert Uytterhoeven
2025-08-22 9:50 ` [PATCH 1/6] can: rcar_canfd: Invert reset assert order Geert Uytterhoeven
2025-08-22 14:24 ` Biju Das
2025-08-22 9:50 ` [PATCH 2/6] can: rcar_canfd: Invert global vs. channel teardown Geert Uytterhoeven
2025-08-22 14:21 ` Biju Das
2025-08-22 9:50 ` [PATCH 3/6] can: rcar_canfd: Extract rcar_canfd_global_{,de}init() Geert Uytterhoeven
2025-08-22 9:50 ` [PATCH 4/6] can: rcar_canfd: Invert CAN clock and close_candev() order Geert Uytterhoeven
2025-08-22 14:26 ` Biju Das
2025-08-22 9:50 ` [PATCH 5/6] can: rcar_canfd: Convert to DEFINE_SIMPLE_DEV_PM_OPS() Geert Uytterhoeven
2025-08-22 14:27 ` Biju Das
2025-08-22 9:50 ` [PATCH/RFC 6/6] can: rcar_canfd: Add suspend/resume support Geert Uytterhoeven
2025-08-22 13:39 ` Biju Das
2025-08-22 16:19 ` Biju Das
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).