[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20251124102837.106973-8-biju.das.jz@bp.renesas.com>
Date: Mon, 24 Nov 2025 10:28:32 +0000
From: Biju <biju.das.au@...il.com>
To: Marc Kleine-Budde <mkl@...gutronix.de>,
Vincent Mailhol <mailhol@...nel.org>,
Geert Uytterhoeven <geert+renesas@...der.be>,
Magnus Damm <magnus.damm@...il.com>,
Philipp Zabel <p.zabel@...gutronix.de>
Cc: Biju Das <biju.das.jz@...renesas.com>,
linux-can@...r.kernel.org,
linux-renesas-soc@...r.kernel.org,
linux-kernel@...r.kernel.org,
Prabhakar Mahadev Lad <prabhakar.mahadev-lad.rj@...renesas.com>,
Biju Das <biju.das.au@...il.com>
Subject: [PATCH v3 7/7] can: rcar_canfd: Add suspend/resume support
From: Geert Uytterhoeven <geert+renesas@...der.be>
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@...der.be>
Tested-by: Biju Das <biju.das.jz@...renesas.com>
Signed-off-by: Biju Das <biju.das.jz@...renesas.com>
---
v2->v3:
* No change.
v1->v2:
* Collected tag
* Fixed the typo in error path of rcar_canfd_resume().
---
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 5a555b01ffbb..4a653d8978ba 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -2278,11 +2278,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_global_init() 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
Powered by blists - more mailing lists