| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From 57d3edbdcfee9b677452744bba5c4f08b476872a Mon Sep 17 00:00:00 2001 |
| 2 | From: Marc Kleine-Budde <mkl@pengutronix.de> |
| 3 | Date: Fri, 1 Mar 2019 15:38:05 +0100 |
| 4 | Subject: [PATCH] can: flexcan: flexcan_irq(): add support for TX mailbox in |
| 5 | iflag1 |
| 6 | |
| 7 | The flexcan IP core has up to 64 mailboxes, each one has a corresponding |
| 8 | interrupt bit in the iflag1 or iflag2 registers and a mask bit in the |
| 9 | imask1 or imask2 registers. |
| 10 | |
| 11 | The driver will always use the last mailbox for TX, which falls into the iflag2 |
| 12 | register. |
| 13 | |
| 14 | To support CANFD the payload size has to increase to 64 bytes and the number of |
| 15 | mailboxes will decrease so much that the TX mailbox will be handled in the |
| 16 | iflag1 register. |
| 17 | |
| 18 | This patch add support to handle the TX mailbox independent whether it's |
| 19 | in iflag1 or iflag2 by introducing th flexcan_read_reg_iflag_tx() |
| 20 | function, similar to flexcan_read_reg_iflag_rx(), for the read path. |
| 21 | |
| 22 | For the write path the function flexcan_write64() is added. |
| 23 | |
| 24 | Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> |
| 25 | --- |
| 26 | drivers/net/can/flexcan.c | 17 +++++++++++++++-- |
| 27 | 1 file changed, 15 insertions(+), 2 deletions(-) |
| 28 | |
| 29 | --- a/drivers/net/can/flexcan.c |
| 30 | +++ b/drivers/net/can/flexcan.c |
| 31 | @@ -798,11 +798,24 @@ static inline u64 flexcan_read64_mask(st |
| 32 | return reg & mask; |
| 33 | } |
| 34 | |
| 35 | +static inline void flexcan_write64(struct flexcan_priv *priv, u64 val, void __iomem *addr) |
| 36 | +{ |
| 37 | + if (upper_32_bits(val)) |
| 38 | + priv->write(upper_32_bits(val), addr - 4); |
| 39 | + if (lower_32_bits(val)) |
| 40 | + priv->write(lower_32_bits(val), addr); |
| 41 | +} |
| 42 | + |
| 43 | static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv) |
| 44 | { |
| 45 | return flexcan_read64_mask(priv, &priv->regs->iflag1, priv->rx_mask); |
| 46 | } |
| 47 | |
| 48 | +static inline u64 flexcan_read_reg_iflag_tx(struct flexcan_priv *priv) |
| 49 | +{ |
| 50 | + return flexcan_read64_mask(priv, &priv->regs->iflag1, priv->tx_mask); |
| 51 | +} |
| 52 | + |
| 53 | static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *offload) |
| 54 | { |
| 55 | return container_of(offload, struct flexcan_priv, offload); |
| 56 | @@ -939,7 +952,7 @@ static irqreturn_t flexcan_irq(int irq, |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | - reg_iflag_tx = (u64)priv->read(®s->iflag2) << 32; |
| 61 | + reg_iflag_tx = flexcan_read_reg_iflag_tx(priv); |
| 62 | |
| 63 | /* transmission complete interrupt */ |
| 64 | if (reg_iflag_tx & priv->tx_mask) { |
| 65 | @@ -954,7 +967,7 @@ static irqreturn_t flexcan_irq(int irq, |
| 66 | /* after sending a RTR frame MB is in RX mode */ |
| 67 | priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, |
| 68 | &priv->tx_mb->can_ctrl); |
| 69 | - priv->write(priv->tx_mask >> 32, ®s->iflag2); |
| 70 | + flexcan_write64(priv, priv->tx_mask, ®s->iflag1); |
| 71 | netif_wake_queue(dev); |
| 72 | } |
| 73 | |