OSDN Git Service

can: flexcan: introduce struct flexcan_priv::tx_mask and make use of it
authorMarc Kleine-Budde <mkl@pengutronix.de>
Fri, 1 Mar 2019 12:54:19 +0000 (13:54 +0100)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Mon, 11 Nov 2019 20:58:11 +0000 (21:58 +0100)
The current driver uses FLEXCAN_IFLAG2_MB() to generate the mask to check for
the TX complete interrupt. This works well, as 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 introduces a tx_mask in the struct flexcan_priv (similar to rx_mask)
and makes use of it. The actual support to handle the TX mailbox in iflag1 will
be added in the next patches.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/flexcan.c

index c3fdd47..c284357 100644 (file)
 #define FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP   0
 #define FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST      (FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP + 1)
 #define FLEXCAN_IFLAG_MB(x)            BIT_ULL(x)
-#define FLEXCAN_IFLAG2_MB(x)           BIT((x) & 0x1f)
 #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7)
 #define FLEXCAN_IFLAG_RX_FIFO_WARN     BIT(6)
 #define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE        BIT(5)
@@ -279,6 +278,7 @@ struct flexcan_priv {
        u8 clk_src;     /* clock source of CAN Protocol Engine */
 
        u64 rx_mask;
+       u64 tx_mask;
        u32 reg_ctrl_default;
 
        struct clk *clk_ipg;
@@ -890,7 +890,8 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
        struct flexcan_priv *priv = netdev_priv(dev);
        struct flexcan_regs __iomem *regs = priv->regs;
        irqreturn_t handled = IRQ_NONE;
-       u32 reg_iflag2, reg_esr;
+       u64 reg_iflag_tx;
+       u32 reg_esr;
        enum can_state last_state = priv->can.state;
 
        /* reception interrupt */
@@ -924,10 +925,10 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
                }
        }
 
-       reg_iflag2 = priv->read(&regs->iflag2);
+       reg_iflag_tx = (u64)priv->read(&regs->iflag2) << 32;
 
        /* transmission complete interrupt */
-       if (reg_iflag2 & FLEXCAN_IFLAG2_MB(priv->tx_mb_idx)) {
+       if (reg_iflag_tx & priv->tx_mask) {
                u32 reg_ctrl = priv->read(&priv->tx_mb->can_ctrl);
 
                handled = IRQ_HANDLED;
@@ -939,7 +940,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
                /* after sending a RTR frame MB is in RX mode */
                priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
                            &priv->tx_mb->can_ctrl);
-               priv->write(FLEXCAN_IFLAG2_MB(priv->tx_mb_idx), &regs->iflag2);
+               priv->write(priv->tx_mask >> 32, &regs->iflag2);
                netif_wake_queue(dev);
        }
 
@@ -1226,7 +1227,7 @@ static int flexcan_chip_start(struct net_device *dev)
        /* enable interrupts atomically */
        disable_irq(dev->irq);
        priv->write(priv->reg_ctrl_default, &regs->ctrl);
-       reg_imask = priv->rx_mask | FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
+       reg_imask = priv->rx_mask | priv->tx_mask;
        priv->write(upper_32_bits(reg_imask), &regs->imask2);
        priv->write(lower_32_bits(reg_imask), &regs->imask1);
        enable_irq(dev->irq);
@@ -1296,6 +1297,7 @@ static int flexcan_open(struct net_device *dev)
                        flexcan_get_mb(priv, FLEXCAN_TX_MB_RESERVED_OFF_FIFO);
        priv->tx_mb_idx = priv->mb_count - 1;
        priv->tx_mb = flexcan_get_mb(priv, priv->tx_mb_idx);
+       priv->tx_mask = FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
 
        priv->offload.mailbox_read = flexcan_mailbox_read;