| From 57d3edbdcfee9b677452744bba5c4f08b476872a Mon Sep 17 00:00:00 2001 |
| From: Marc Kleine-Budde <mkl@pengutronix.de> |
| Date: Fri, 1 Mar 2019 15:38:05 +0100 |
| Subject: [PATCH] can: flexcan: flexcan_irq(): add support for TX mailbox in |
| iflag1 |
| |
| The flexcan IP core has up to 64 mailboxes, each one has a corresponding |
| interrupt bit in the iflag1 or iflag2 registers and a mask bit in the |
| imask1 or imask2 registers. |
| |
| The driver will always use the last mailbox for TX, which falls into the iflag2 |
| register. |
| |
| To support CANFD the payload size has to increase to 64 bytes and the number of |
| mailboxes will decrease so much that the TX mailbox will be handled in the |
| iflag1 register. |
| |
| This patch add support to handle the TX mailbox independent whether it's |
| in iflag1 or iflag2 by introducing th flexcan_read_reg_iflag_tx() |
| function, similar to flexcan_read_reg_iflag_rx(), for the read path. |
| |
| For the write path the function flexcan_write64() is added. |
| |
| Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> |
| --- |
| drivers/net/can/flexcan.c | 17 +++++++++++++++-- |
| 1 file changed, 15 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/net/can/flexcan.c |
| +++ b/drivers/net/can/flexcan.c |
| @@ -798,11 +798,24 @@ static inline u64 flexcan_read64_mask(st |
| return reg & mask; |
| } |
| |
| +static inline void flexcan_write64(struct flexcan_priv *priv, u64 val, void __iomem *addr) |
| +{ |
| + if (upper_32_bits(val)) |
| + priv->write(upper_32_bits(val), addr - 4); |
| + if (lower_32_bits(val)) |
| + priv->write(lower_32_bits(val), addr); |
| +} |
| + |
| static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv) |
| { |
| return flexcan_read64_mask(priv, &priv->regs->iflag1, priv->rx_mask); |
| } |
| |
| +static inline u64 flexcan_read_reg_iflag_tx(struct flexcan_priv *priv) |
| +{ |
| + return flexcan_read64_mask(priv, &priv->regs->iflag1, priv->tx_mask); |
| +} |
| + |
| static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *offload) |
| { |
| return container_of(offload, struct flexcan_priv, offload); |
| @@ -939,7 +952,7 @@ static irqreturn_t flexcan_irq(int irq, |
| } |
| } |
| |
| - reg_iflag_tx = (u64)priv->read(®s->iflag2) << 32; |
| + reg_iflag_tx = flexcan_read_reg_iflag_tx(priv); |
| |
| /* transmission complete interrupt */ |
| if (reg_iflag_tx & priv->tx_mask) { |
| @@ -954,7 +967,7 @@ static irqreturn_t flexcan_irq(int irq, |
| /* after sending a RTR frame MB is in RX mode */ |
| priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, |
| &priv->tx_mb->can_ctrl); |
| - priv->write(priv->tx_mask >> 32, ®s->iflag2); |
| + flexcan_write64(priv, priv->tx_mask, ®s->iflag1); |
| netif_wake_queue(dev); |
| } |
| |