diff options
author | Joakim Zhang <qiangqing.zhang@nxp.com> | 2019-12-04 11:36:19 +0000 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2020-09-22 16:52:50 +0200 |
commit | 1434d04349626d7b4da49b99f79d6391b9a67f16 (patch) | |
tree | c7527b1545393c7d5421733fb01cd36172fce837 /drivers/net/can/flexcan.c | |
parent | 02f71c6605e1f8259c07f16178330db766189a74 (diff) |
can: flexcan: add LPSR mode support
On the i.MX7D in LPSR mode, the controller will be powered off and the
configuration state is lost after system resume. Upcoming i.MX8QM/QXP
will also completely power off the domain, the controller state is lost
and needs restore, too. So we need to set the pinctrl state again and
re-start chip to re-configuration after resume.
For the wakeup case, it should not set pinctrl to sleep state by
pinctrl_pm_select_sleep_state.
If the interface is down before suspend, we don't need to re-configure
it as it will be configured if the interface is brought up later.
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Link: https://lore.kernel.org/r/20191204113249.3381-7-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can/flexcan.c')
-rw-r--r-- | drivers/net/can/flexcan.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index ed2ead7c21ef..35d0fa59e957 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -23,6 +23,7 @@ #include <linux/netdevice.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> @@ -1742,7 +1743,7 @@ static int __maybe_unused flexcan_suspend(struct device *device) { struct net_device *dev = dev_get_drvdata(device); struct flexcan_priv *priv = netdev_priv(dev); - int err = 0; + int err; if (netif_running(dev)) { /* if wakeup is enabled, enter stop mode @@ -1754,7 +1755,11 @@ static int __maybe_unused flexcan_suspend(struct device *device) if (err) return err; } else { - err = flexcan_chip_disable(priv); + err = flexcan_chip_stop(dev); + if (err) + return err; + + err = pinctrl_pm_select_sleep_state(device); if (err) return err; } @@ -1763,14 +1768,14 @@ static int __maybe_unused flexcan_suspend(struct device *device) } priv->can.state = CAN_STATE_SLEEPING; - return err; + return 0; } static int __maybe_unused flexcan_resume(struct device *device) { struct net_device *dev = dev_get_drvdata(device); struct flexcan_priv *priv = netdev_priv(dev); - int err = 0; + int err; priv->can.state = CAN_STATE_ERROR_ACTIVE; if (netif_running(dev)) { @@ -1782,11 +1787,17 @@ static int __maybe_unused flexcan_resume(struct device *device) if (err) return err; } else { - err = flexcan_chip_enable(priv); + err = pinctrl_pm_select_default_state(device); + if (err) + return err; + + err = flexcan_chip_start(dev); + if (err) + return err; } } - return err; + return 0; } static int __maybe_unused flexcan_runtime_suspend(struct device *device) |