[RESEND PATCH v6 3/6] can: flexcan: split rx/tx masks per mailbox IRQ line
Ciprian Costea <[email protected]>
| Newsgroups | org.kernel.vger.linux-can,dev.linux.lists.imx,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Ciprian Marian Costea <[email protected]> On S32G2, which has two mailbox IRQ lines (mb-0 for MBs 0-7, mb-1 for MBs 8-63), both handlers currently process the full rx_mask/tx_mask range. Introduce FLEXCAN_SECONDARY_MB_IRQ_MB0_MASK and FLEXCAN_SECONDARY_MB_IRQ_MB1_MASK to describe the split, and pass the selected mask to flexcan_do_mb() via a new mb_mask parameter. In flexcan_irq_mb(), the irq argument selects the correct mask: the primary MB IRQ uses MB0_MASK and the secondary uses MB1_MASK. For single-IRQ platforms, mb_mask is ~0ULL with no functional change. Signed-off-by: Ciprian Marian Costea <[email protected]> Reviewed-by: Vincent Mailhol <[email protected]> Reviewed-and-tested-by: Haibo Chen <[email protected]> Tested-by: Enric Balletbo i Serra <[email protected]> --- drivers/net/can/flexcan/flexcan-core.c | 39 ++++++++++++++++++-------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c index 7dde2e623def..8b70952f7f05 100644 --- a/drivers/net/can/flexcan/flexcan-core.c +++ b/drivers/net/can/flexcan/flexcan-core.c @@ -182,6 +182,12 @@ #define FLEXCAN_IFLAG_RX_FIFO_WARN BIT(6) #define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE BIT(5) +/* On platforms with FLEXCAN_QUIRK_SECONDARY_MB_IRQ, the MB IRQ lines are + * split. + */ +#define FLEXCAN_SECONDARY_MB_IRQ_MB0_MASK GENMASK_U64(7, 0) +#define FLEXCAN_SECONDARY_MB_IRQ_MB1_MASK GENMASK_U64(63, 8) + /* FLEXCAN message buffers */ #define FLEXCAN_MB_CODE_MASK (0xf << 24) #define FLEXCAN_MB_CODE_RX_BUSY_BIT (0x1 << 24) @@ -957,14 +963,16 @@ static inline void flexcan_write64(struct flexcan_priv *priv, u64 val, void __io priv->write(lower_32_bits(val), addr); } -static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv) +static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv, + u64 rx_mask) { - return flexcan_read64_mask(priv, &priv->regs->iflag1, priv->rx_mask); + return flexcan_read64_mask(priv, &priv->regs->iflag1, rx_mask); } -static inline u64 flexcan_read_reg_iflag_tx(struct flexcan_priv *priv) +static inline u64 flexcan_read_reg_iflag_tx(struct flexcan_priv *priv, + u64 tx_mask) { - return flexcan_read64_mask(priv, &priv->regs->iflag1, priv->tx_mask); + return flexcan_read64_mask(priv, &priv->regs->iflag1, tx_mask); } static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *offload) @@ -1071,12 +1079,14 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload, } /* Process mailbox (RX + TX) events */ -static irqreturn_t flexcan_do_mb(struct net_device *dev) +static irqreturn_t flexcan_do_mb(struct net_device *dev, u64 mb_mask) { struct net_device_stats *stats = &dev->stats; struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_regs __iomem *regs = priv->regs; irqreturn_t handled = IRQ_NONE; + u64 rx_mask = priv->rx_mask & mb_mask; + u64 tx_mask = priv->tx_mask & mb_mask; u64 reg_iflag_tx; /* reception interrupt */ @@ -1084,7 +1094,8 @@ static irqreturn_t flexcan_do_mb(struct net_device *dev) u64 reg_iflag_rx; int ret; - while ((reg_iflag_rx = flexcan_read_reg_iflag_rx(priv))) { + while ((reg_iflag_rx = flexcan_read_reg_iflag_rx(priv, + rx_mask))) { handled = IRQ_HANDLED; ret = can_rx_offload_irq_offload_timestamp(&priv->offload, reg_iflag_rx); @@ -1110,10 +1121,10 @@ static irqreturn_t flexcan_do_mb(struct net_device *dev) } } - reg_iflag_tx = flexcan_read_reg_iflag_tx(priv); + reg_iflag_tx = flexcan_read_reg_iflag_tx(priv, tx_mask); /* transmission complete interrupt */ - if (reg_iflag_tx & priv->tx_mask) { + if (reg_iflag_tx & tx_mask) { u32 reg_ctrl = priv->read(&priv->tx_mb->can_ctrl); handled = IRQ_HANDLED; @@ -1125,7 +1136,7 @@ static irqreturn_t flexcan_do_mb(struct net_device *dev) /* after sending a RTR frame MB is in RX mode */ priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, &priv->tx_mb->can_ctrl); - flexcan_write64(priv, priv->tx_mask, ®s->iflag1); + flexcan_write64(priv, tx_mask, ®s->iflag1); netif_wake_queue(dev); } @@ -1228,7 +1239,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) struct flexcan_priv *priv = netdev_priv(dev); irqreturn_t handled; - handled = flexcan_do_mb(dev); + handled = flexcan_do_mb(dev, ~0ULL); handled |= flexcan_do_state(dev); handled |= flexcan_do_berr(dev); @@ -1244,8 +1255,14 @@ static irqreturn_t flexcan_irq_mb(int irq, void *dev_id) struct net_device *dev = dev_id; struct flexcan_priv *priv = netdev_priv(dev); irqreturn_t handled; + u64 mb_mask = ~0ULL; + + if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SECONDARY_MB_IRQ) + mb_mask = (irq == priv->irq_secondary_mb) ? + FLEXCAN_SECONDARY_MB_IRQ_MB1_MASK : + FLEXCAN_SECONDARY_MB_IRQ_MB0_MASK; - handled = flexcan_do_mb(dev); + handled = flexcan_do_mb(dev, mb_mask); if (handled) can_rx_offload_irq_finish(&priv->offload); -- 2.43.0