can: flexcan: add low power enter/exit acknowledgment helper
authorJoakim Zhang <qiangqing.zhang@nxp.com>
Wed, 4 Dec 2019 11:36:11 +0000 (11:36 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 31 Dec 2019 15:46:05 +0000 (16:46 +0100)
[ Upstream commit b7603d080ffcf8689ec91ca300caf84d8dbed317 ]

The MCR[LPMACK] read-only bit indicates that FlexCAN is in a lower-power
mode (Disabled mode, Doze mode, Stop mode).

The CPU can poll this bit to know when FlexCAN has actually entered low
power mode. The low power enter/exit acknowledgment helper will reduce
code duplication for disabled mode, doze mode and stop mode.

Tested-by: Sean Nyekjaer <sean@geanix.com>
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/can/flexcan.c

index 99b3492..e5c207a 100644 (file)
@@ -389,6 +389,34 @@ static struct flexcan_mb __iomem *flexcan_get_mb(const struct flexcan_priv *priv
                (&priv->regs->mb[bank][priv->mb_size * mb_index]);
 }
 
+static int flexcan_low_power_enter_ack(struct flexcan_priv *priv)
+{
+       struct flexcan_regs __iomem *regs = priv->regs;
+       unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
+
+       while (timeout-- && !(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+               udelay(10);
+
+       if (!(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int flexcan_low_power_exit_ack(struct flexcan_priv *priv)
+{
+       struct flexcan_regs __iomem *regs = priv->regs;
+       unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
+
+       while (timeout-- && (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+               udelay(10);
+
+       if (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
 static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enable)
 {
        struct flexcan_regs __iomem *regs = priv->regs;
@@ -493,39 +521,25 @@ static inline int flexcan_transceiver_disable(const struct flexcan_priv *priv)
 static int flexcan_chip_enable(struct flexcan_priv *priv)
 {
        struct flexcan_regs __iomem *regs = priv->regs;
-       unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
        u32 reg;
 
        reg = priv->read(&regs->mcr);
        reg &= ~FLEXCAN_MCR_MDIS;
        priv->write(reg, &regs->mcr);
 
-       while (timeout-- && (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               udelay(10);
-
-       if (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
-               return -ETIMEDOUT;
-
-       return 0;
+       return flexcan_low_power_exit_ack(priv);
 }
 
 static int flexcan_chip_disable(struct flexcan_priv *priv)
 {
        struct flexcan_regs __iomem *regs = priv->regs;
-       unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
        u32 reg;
 
        reg = priv->read(&regs->mcr);
        reg |= FLEXCAN_MCR_MDIS;
        priv->write(reg, &regs->mcr);
 
-       while (timeout-- && !(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               udelay(10);
-
-       if (!(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               return -ETIMEDOUT;
-
-       return 0;
+       return flexcan_low_power_enter_ack(priv);
 }
 
 static int flexcan_chip_freeze(struct flexcan_priv *priv)