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@xxxxxxxxx> > > Sent: 22 August 2025 10:51 > > To: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx>; Vincent Mailhol > > <mailhol.vincent@xxxxxxxxxx>; Biju Das <biju.das.jz@xxxxxxxxxxxxxx> > > Cc: linux-can@xxxxxxxxxxxxxxx; linux-renesas-soc@xxxxxxxxxxxxxxx; > > Geert Uytterhoeven <geert+renesas@xxxxxxxxx> > > 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@xxxxxxxxx> > > --- > > 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#