74 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			74 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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);
 | |
|  	}
 | |
|  
 | 
