Skip to content

Commit

Permalink
can: flexcan: add low power enter/exit acknowledgment helper
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Joakim Zhang authored and Marc Kleine-Budde committed Dec 8, 2019
1 parent e707180 commit b7603d0
Showing 1 changed file with 30 additions and 16 deletions.
46 changes: 30 additions & 16 deletions drivers/net/can/flexcan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -506,39 +534,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)
Expand Down

0 comments on commit b7603d0

Please sign in to comment.