 ec6293febc
			
		
	
	ec6293febc
	
	
	
		
			
			Ran update_kernel.sh in a fresh clone without any existing toolchains.
Manually rebased:
  pending-5.4/611-netfilter_match_bypass_default_table.patch
The upstream change affecting this patch is the revert of an earlier
kernel commit. Therefore, we just revert our corresponding changes
in [1].
Build system: x86_64
Build-tested: ipq806x/R7800
[1] 9b1b89229f ("kernel: bump 5.4 to 5.4.86")
Signed-off-by: John Audia <graysky@archlinux.us>
[adjust manually rebased patch, add explanation]
Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
		
	
		
			
				
	
	
		
			398 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			398 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 2aea13a107090d05e968d7d2aa3f72380a3f1b4c Mon Sep 17 00:00:00 2001
 | |
| From: Joakim Zhang <qiangqing.zhang@nxp.com>
 | |
| Date: Fri, 12 Jul 2019 08:02:44 +0000
 | |
| Subject: [PATCH] can: flexcan: add CAN FD mode support
 | |
| 
 | |
| This patch intends to add CAN FD mode support in driver, it means that
 | |
| payload size can extend up to 64 bytes.
 | |
| 
 | |
| Bit timing always set in CBT register other than CTRL1 register when
 | |
| CANFD supports BRS, it will extend the range of all CAN bit timing
 | |
| variables (PRESDIV, PROPSEG, PSEG1, PSEG2 and RJW), which will improve
 | |
| the bit timing accuracy.
 | |
| 
 | |
| Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
 | |
| Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
 | |
| ---
 | |
|  drivers/net/can/flexcan.c | 247 ++++++++++++++++++++++++++++++++++++++++------
 | |
|  1 file changed, 218 insertions(+), 29 deletions(-)
 | |
| 
 | |
| --- a/drivers/net/can/flexcan.c
 | |
| +++ b/drivers/net/can/flexcan.c
 | |
| @@ -52,6 +52,7 @@
 | |
|  #define FLEXCAN_MCR_IRMQ		BIT(16)
 | |
|  #define FLEXCAN_MCR_LPRIO_EN		BIT(13)
 | |
|  #define FLEXCAN_MCR_AEN			BIT(12)
 | |
| +#define FLEXCAN_MCR_FDEN		BIT(11)
 | |
|  /* MCR_MAXMB: maximum used MBs is MAXMB + 1 */
 | |
|  #define FLEXCAN_MCR_MAXMB(x)		((x) & 0x7f)
 | |
|  #define FLEXCAN_MCR_IDAM_A		(0x0 << 8)
 | |
| @@ -137,6 +138,26 @@
 | |
|  	 FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT | \
 | |
|  	 FLEXCAN_ESR_WAK_INT)
 | |
|  
 | |
| +/* FLEXCAN Bit Timing register (CBT) bits */
 | |
| +#define FLEXCAN_CBT_BTF			BIT(31)
 | |
| +#define FLEXCAN_CBT_EPRESDIV(x)		(((x) & 0x3ff) << 21)
 | |
| +#define FLEXCAN_CBT_ERJW(x)		(((x) & 0x0f) << 16)
 | |
| +#define FLEXCAN_CBT_EPROPSEG(x)		(((x) & 0x3f) << 10)
 | |
| +#define FLEXCAN_CBT_EPSEG1(x)		(((x) & 0x1f) << 5)
 | |
| +#define FLEXCAN_CBT_EPSEG2(x)		((x) & 0x1f)
 | |
| +
 | |
| +/* FLEXCAN FD control register (FDCTRL) bits */
 | |
| +#define FLEXCAN_FDCTRL_FDRATE		BIT(31)
 | |
| +#define FLEXCAN_FDCTRL_MBDSR1(x)	(((x) & 0x3) << 19)
 | |
| +#define FLEXCAN_FDCTRL_MBDSR0(x)	(((x) & 0x3) << 16)
 | |
| +
 | |
| +/* FLEXCAN FD Bit Timing register (FDCBT) bits */
 | |
| +#define FLEXCAN_FDCBT_FPRESDIV(x)	(((x) & 0x3ff) << 20)
 | |
| +#define FLEXCAN_FDCBT_FRJW(x)		(((x) & 0x07) << 16)
 | |
| +#define FLEXCAN_FDCBT_FPROPSEG(x)	(((x) & 0x1f) << 10)
 | |
| +#define FLEXCAN_FDCBT_FPSEG1(x)		(((x) & 0x07) << 5)
 | |
| +#define FLEXCAN_FDCBT_FPSEG2(x)		((x) & 0x07)
 | |
| +
 | |
|  /* FLEXCAN interrupt flag register (IFLAG) bits */
 | |
|  /* Errata ERR005829 step7: Reserve first valid MB */
 | |
|  #define FLEXCAN_TX_MB_RESERVED_OFF_FIFO		8
 | |
| @@ -161,6 +182,9 @@
 | |
|  #define FLEXCAN_MB_CODE_TX_DATA		(0xc << 24)
 | |
|  #define FLEXCAN_MB_CODE_TX_TANSWER	(0xe << 24)
 | |
|  
 | |
| +#define FLEXCAN_MB_CNT_EDL		BIT(31)
 | |
| +#define FLEXCAN_MB_CNT_BRS		BIT(30)
 | |
| +#define FLEXCAN_MB_CNT_ESI		BIT(29)
 | |
|  #define FLEXCAN_MB_CNT_SRR		BIT(22)
 | |
|  #define FLEXCAN_MB_CNT_IDE		BIT(21)
 | |
|  #define FLEXCAN_MB_CNT_RTR		BIT(20)
 | |
| @@ -192,6 +216,7 @@
 | |
|  #define FLEXCAN_QUIRK_BROKEN_PERR_STATE	BIT(6) /* No interrupt for error passive */
 | |
|  #define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN	BIT(7) /* default to BE register access */
 | |
|  #define FLEXCAN_QUIRK_SETUP_STOP_MODE		BIT(8) /* Setup stop mode to support wakeup */
 | |
| +#define FLEXCAN_QUIRK_TIMESTAMP_SUPPORT_FD	BIT(9) /* Use timestamp then support can fd mode */
 | |
|  
 | |
|  /* Structure of the message buffer */
 | |
|  struct flexcan_mb {
 | |
| @@ -225,7 +250,8 @@ struct flexcan_regs {
 | |
|  	u32 crcr;		/* 0x44 */
 | |
|  	u32 rxfgmask;		/* 0x48 */
 | |
|  	u32 rxfir;		/* 0x4c */
 | |
| -	u32 _reserved3[12];	/* 0x50 */
 | |
| +	u32 cbt;		/* 0x50 */
 | |
| +	u32 _reserved3[11];	/* 0x54 */
 | |
|  	u8 mb[2][512];		/* 0x80 */
 | |
|  	/* FIFO-mode:
 | |
|  	 *			MB
 | |
| @@ -250,6 +276,10 @@ struct flexcan_regs {
 | |
|  	u32 rerrdr;		/* 0xaf4 */
 | |
|  	u32 rerrsynr;		/* 0xaf8 */
 | |
|  	u32 errsr;		/* 0xafc */
 | |
| +	u32 _reserved7[64];	/* 0xb00 */
 | |
| +	u32 fdctrl;		/* 0xc00 */
 | |
| +	u32 fdcbt;		/* 0xc04 */
 | |
| +	u32 fdcrc;		/* 0xc08 */
 | |
|  };
 | |
|  
 | |
|  struct flexcan_devtype_data {
 | |
| @@ -336,6 +366,30 @@ static const struct can_bittiming_const
 | |
|  	.brp_inc = 1,
 | |
|  };
 | |
|  
 | |
| +static const struct can_bittiming_const flexcan_fd_bittiming_const = {
 | |
| +	.name = DRV_NAME,
 | |
| +	.tseg1_min = 2,
 | |
| +	.tseg1_max = 96,
 | |
| +	.tseg2_min = 2,
 | |
| +	.tseg2_max = 32,
 | |
| +	.sjw_max = 16,
 | |
| +	.brp_min = 1,
 | |
| +	.brp_max = 1024,
 | |
| +	.brp_inc = 1,
 | |
| +};
 | |
| +
 | |
| +static const struct can_bittiming_const flexcan_fd_data_bittiming_const = {
 | |
| +	.name = DRV_NAME,
 | |
| +	.tseg1_min = 2,
 | |
| +	.tseg1_max = 39,
 | |
| +	.tseg2_min = 2,
 | |
| +	.tseg2_max = 8,
 | |
| +	.sjw_max = 4,
 | |
| +	.brp_min = 1,
 | |
| +	.brp_max = 1024,
 | |
| +	.brp_inc = 1,
 | |
| +};
 | |
| +
 | |
|  /* FlexCAN module is essentially modelled as a little-endian IP in most
 | |
|   * SoCs, i.e the registers as well as the message buffer areas are
 | |
|   * implemented in a little-endian fashion.
 | |
| @@ -638,7 +692,7 @@ static netdev_tx_t flexcan_start_xmit(st
 | |
|  	struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
 | |
|  	u32 can_id;
 | |
|  	u32 data;
 | |
| -	u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cfd->len << 16);
 | |
| +	u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ((can_len2dlc(cfd->len)) << 16);
 | |
|  	int i;
 | |
|  
 | |
|  	if (can_dropped_invalid_skb(dev, skb))
 | |
| @@ -656,6 +710,9 @@ static netdev_tx_t flexcan_start_xmit(st
 | |
|  	if (cfd->can_id & CAN_RTR_FLAG)
 | |
|  		ctrl |= FLEXCAN_MB_CNT_RTR;
 | |
|  
 | |
| +	if (can_is_canfd_skb(skb))
 | |
| +		ctrl |= FLEXCAN_MB_CNT_EDL;
 | |
| +
 | |
|  	for (i = 0; i < cfd->len; i += sizeof(u32)) {
 | |
|  		data = be32_to_cpup((__be32 *)&cfd->data[i]);
 | |
|  		priv->write(data, &priv->tx_mb->data[i / sizeof(u32)]);
 | |
| @@ -866,7 +923,10 @@ static struct sk_buff *flexcan_mailbox_r
 | |
|  		reg_ctrl = priv->read(&mb->can_ctrl);
 | |
|  	}
 | |
|  
 | |
| -	skb = alloc_can_skb(offload->dev, (struct can_frame **)&cfd);
 | |
| +	if (reg_ctrl & FLEXCAN_MB_CNT_EDL)
 | |
| +		skb = alloc_canfd_skb(offload->dev, &cfd);
 | |
| +	else
 | |
| +		skb = alloc_can_skb(offload->dev, (struct can_frame **)&cfd);
 | |
|  	if (unlikely(!skb)) {
 | |
|  		skb = ERR_PTR(-ENOMEM);
 | |
|  		goto mark_as_read;
 | |
| @@ -881,9 +941,17 @@ static struct sk_buff *flexcan_mailbox_r
 | |
|  	else
 | |
|  		cfd->can_id = (reg_id >> 18) & CAN_SFF_MASK;
 | |
|  
 | |
| -	if (reg_ctrl & FLEXCAN_MB_CNT_RTR)
 | |
| -		cfd->can_id |= CAN_RTR_FLAG;
 | |
| -	cfd->len = get_can_dlc((reg_ctrl >> 16) & 0xf);
 | |
| +	if (reg_ctrl & FLEXCAN_MB_CNT_EDL) {
 | |
| +		cfd->len = can_dlc2len(get_canfd_dlc((reg_ctrl >> 16) & 0xf));
 | |
| +	} else {
 | |
| +		cfd->len = get_can_dlc((reg_ctrl >> 16) & 0xf);
 | |
| +
 | |
| +		if (reg_ctrl & FLEXCAN_MB_CNT_RTR)
 | |
| +			cfd->can_id |= CAN_RTR_FLAG;
 | |
| +	}
 | |
| +
 | |
| +	if (reg_ctrl & FLEXCAN_MB_CNT_ESI)
 | |
| +		cfd->flags |= CANFD_ESI;
 | |
|  
 | |
|  	for (i = 0; i < cfd->len; i += sizeof(u32)) {
 | |
|  		__be32 data = cpu_to_be32(priv->read(&mb->data[i / sizeof(u32)]));
 | |
| @@ -1028,27 +1096,14 @@ static irqreturn_t flexcan_irq(int irq,
 | |
|  
 | |
|  static void flexcan_set_bittiming(struct net_device *dev)
 | |
|  {
 | |
| -	const struct flexcan_priv *priv = netdev_priv(dev);
 | |
| -	const struct can_bittiming *bt = &priv->can.bittiming;
 | |
| +	struct flexcan_priv *priv = netdev_priv(dev);
 | |
| +	struct can_bittiming *bt = &priv->can.bittiming;
 | |
| +	struct can_bittiming *dbt = &priv->can.data_bittiming;
 | |
|  	struct flexcan_regs __iomem *regs = priv->regs;
 | |
| -	u32 reg;
 | |
| +	u32 reg, reg_cbt, reg_fdcbt;
 | |
|  
 | |
|  	reg = priv->read(®s->ctrl);
 | |
| -	reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) |
 | |
| -		 FLEXCAN_CTRL_RJW(0x3) |
 | |
| -		 FLEXCAN_CTRL_PSEG1(0x7) |
 | |
| -		 FLEXCAN_CTRL_PSEG2(0x7) |
 | |
| -		 FLEXCAN_CTRL_PROPSEG(0x7) |
 | |
| -		 FLEXCAN_CTRL_LPB |
 | |
| -		 FLEXCAN_CTRL_SMP |
 | |
| -		 FLEXCAN_CTRL_LOM);
 | |
| -
 | |
| -	reg |= FLEXCAN_CTRL_PRESDIV(bt->brp - 1) |
 | |
| -		FLEXCAN_CTRL_PSEG1(bt->phase_seg1 - 1) |
 | |
| -		FLEXCAN_CTRL_PSEG2(bt->phase_seg2 - 1) |
 | |
| -		FLEXCAN_CTRL_RJW(bt->sjw - 1) |
 | |
| -		FLEXCAN_CTRL_PROPSEG(bt->prop_seg - 1);
 | |
| -
 | |
| +	reg &= ~(FLEXCAN_CTRL_LPB | FLEXCAN_CTRL_SMP | FLEXCAN_CTRL_LOM);
 | |
|  	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
 | |
|  		reg |= FLEXCAN_CTRL_LPB;
 | |
|  	if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
 | |
| @@ -1059,9 +1114,102 @@ static void flexcan_set_bittiming(struct
 | |
|  	netdev_dbg(dev, "writing ctrl=0x%08x\n", reg);
 | |
|  	priv->write(reg, ®s->ctrl);
 | |
|  
 | |
| -	/* print chip status */
 | |
| -	netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__,
 | |
| -		   priv->read(®s->mcr), priv->read(®s->ctrl));
 | |
| +	if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
 | |
| +		reg_cbt = priv->read(®s->cbt);
 | |
| +		reg_cbt &= ~(FLEXCAN_CBT_EPRESDIV(0x3ff) |
 | |
| +			     FLEXCAN_CBT_EPSEG1(0x1f) |
 | |
| +			     FLEXCAN_CBT_EPSEG2(0x1f) |
 | |
| +			     FLEXCAN_CBT_ERJW(0x1f) |
 | |
| +			     FLEXCAN_CBT_EPROPSEG(0x3f) |
 | |
| +			     FLEXCAN_CBT_BTF);
 | |
| +
 | |
| +		/* CBT[EPSEG1] is 5 bit long and CBT[EPROPSEG] is 6 bit long.
 | |
| +		 * The can_calc_bittiming tries to divide the tseg1 equally
 | |
| +		 * between phase_seg1 and prop_seg, which may not fit in CBT
 | |
| +		 * register. Therefore, if phase_seg1 is more than possible
 | |
| +		 * value, increase prop_seg and decrease phase_seg1
 | |
| +		 */
 | |
| +		if (bt->phase_seg1 > 0x20) {
 | |
| +			bt->prop_seg += (bt->phase_seg1 - 0x20);
 | |
| +			bt->phase_seg1 = 0x20;
 | |
| +		}
 | |
| +
 | |
| +		reg_cbt = FLEXCAN_CBT_EPRESDIV(bt->brp - 1) |
 | |
| +				FLEXCAN_CBT_EPSEG1(bt->phase_seg1 - 1) |
 | |
| +				FLEXCAN_CBT_EPSEG2(bt->phase_seg2 - 1) |
 | |
| +				FLEXCAN_CBT_ERJW(bt->sjw - 1) |
 | |
| +				FLEXCAN_CBT_EPROPSEG(bt->prop_seg - 1) |
 | |
| +				FLEXCAN_CBT_BTF;
 | |
| +		priv->write(reg_cbt, ®s->cbt);
 | |
| +
 | |
| +		netdev_dbg(dev, "bt: prediv %d seg1 %d seg2 %d rjw %d propseg %d\n",
 | |
| +			   bt->brp - 1, bt->phase_seg1 - 1, bt->phase_seg2 - 1,
 | |
| +			   bt->sjw - 1, bt->prop_seg - 1);
 | |
| +
 | |
| +		if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
 | |
| +			reg_fdcbt = priv->read(®s->fdcbt);
 | |
| +			reg_fdcbt &= ~(FLEXCAN_FDCBT_FPRESDIV(0x3ff) |
 | |
| +				       FLEXCAN_FDCBT_FPSEG1(0x07) |
 | |
| +				       FLEXCAN_FDCBT_FPSEG2(0x07) |
 | |
| +				       FLEXCAN_FDCBT_FRJW(0x07) |
 | |
| +				       FLEXCAN_FDCBT_FPROPSEG(0x1f));
 | |
| +
 | |
| +			/* FDCBT[FPSEG1] is 3 bit long and FDCBT[FPROPSEG] is 5 bit long.
 | |
| +			 * The can_calc_bittiming tries to divide the tseg1 equally
 | |
| +			 * between phase_seg1 and prop_seg, which may not fit in FDCBT
 | |
| +			 * register. Therefore, if phase_seg1 is more than possible
 | |
| +			 * value, increase prop_seg and decrease phase_seg1
 | |
| +			 */
 | |
| +			if (dbt->phase_seg1 > 0x8) {
 | |
| +				dbt->prop_seg += (dbt->phase_seg1 - 0x8);
 | |
| +				dbt->phase_seg1 = 0x8;
 | |
| +			}
 | |
| +
 | |
| +			reg_fdcbt = FLEXCAN_FDCBT_FPRESDIV(dbt->brp - 1) |
 | |
| +					FLEXCAN_FDCBT_FPSEG1(dbt->phase_seg1 - 1) |
 | |
| +					FLEXCAN_FDCBT_FPSEG2(dbt->phase_seg2 - 1) |
 | |
| +					FLEXCAN_FDCBT_FRJW(dbt->sjw - 1) |
 | |
| +					FLEXCAN_FDCBT_FPROPSEG(dbt->prop_seg);
 | |
| +			priv->write(reg_fdcbt, ®s->fdcbt);
 | |
| +
 | |
| +			if (bt->brp != dbt->brp)
 | |
| +				netdev_warn(dev, "Warning!! data brp = %d and brp = %d don't match.\n"
 | |
| +					    "flexcan may not work. consider using different bitrate or data bitrate\n",
 | |
| +					    dbt->brp, bt->brp);
 | |
| +
 | |
| +			netdev_dbg(dev, "fdbt: prediv %d seg1 %d seg2 %d rjw %d propseg %d\n",
 | |
| +				   dbt->brp - 1, dbt->phase_seg1 - 1, dbt->phase_seg2 - 1,
 | |
| +				   dbt->sjw - 1, dbt->prop_seg);
 | |
| +
 | |
| +			netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x cbt=0x%08x fdcbt=0x%08x\n",
 | |
| +				   __func__, priv->read(®s->mcr),
 | |
| +				   priv->read(®s->ctrl),
 | |
| +				   priv->read(®s->cbt),
 | |
| +				   priv->read(®s->fdcbt));
 | |
| +		}
 | |
| +	} else {
 | |
| +		reg = priv->read(®s->ctrl);
 | |
| +		reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) |
 | |
| +			 FLEXCAN_CTRL_RJW(0x3) |
 | |
| +			 FLEXCAN_CTRL_PSEG1(0x7) |
 | |
| +			 FLEXCAN_CTRL_PSEG2(0x7) |
 | |
| +			 FLEXCAN_CTRL_PROPSEG(0x7));
 | |
| +
 | |
| +		reg |= FLEXCAN_CTRL_PRESDIV(bt->brp - 1) |
 | |
| +			FLEXCAN_CTRL_PSEG1(bt->phase_seg1 - 1) |
 | |
| +			FLEXCAN_CTRL_PSEG2(bt->phase_seg2 - 1) |
 | |
| +			FLEXCAN_CTRL_RJW(bt->sjw - 1) |
 | |
| +			FLEXCAN_CTRL_PROPSEG(bt->prop_seg - 1);
 | |
| +		priv->write(reg, ®s->ctrl);
 | |
| +
 | |
| +		netdev_dbg(dev, "bt: prediv %d seg1 %d seg2 %d rjw %d propseg %d\n",
 | |
| +			   bt->brp - 1, bt->phase_seg1 - 1, bt->phase_seg2 - 1,
 | |
| +			   bt->sjw - 1, bt->prop_seg - 1);
 | |
| +
 | |
| +		/* print chip status */
 | |
| +		netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__,
 | |
| +			   priv->read(®s->mcr), priv->read(®s->ctrl));
 | |
| +	}
 | |
|  }
 | |
|  
 | |
|  /* flexcan_chip_start
 | |
| @@ -1073,7 +1221,7 @@ static int flexcan_chip_start(struct net
 | |
|  {
 | |
|  	struct flexcan_priv *priv = netdev_priv(dev);
 | |
|  	struct flexcan_regs __iomem *regs = priv->regs;
 | |
| -	u32 reg_mcr, reg_ctrl, reg_ctrl2, reg_mecr;
 | |
| +	u32 reg_mcr, reg_ctrl, reg_ctrl2, reg_mecr, reg_fdctrl;
 | |
|  	u64 reg_imask;
 | |
|  	int err, i;
 | |
|  	struct flexcan_mb __iomem *mb;
 | |
| @@ -1172,6 +1320,26 @@ static int flexcan_chip_start(struct net
 | |
|  	netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
 | |
|  	priv->write(reg_ctrl, ®s->ctrl);
 | |
|  
 | |
| +	/* FDCTRL */
 | |
| +	if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
 | |
| +		reg_fdctrl = priv->read(®s->fdctrl) & ~FLEXCAN_FDCTRL_FDRATE;
 | |
| +		reg_fdctrl &= ~(FLEXCAN_FDCTRL_MBDSR1(0x3) | FLEXCAN_FDCTRL_MBDSR0(0x3));
 | |
| +		reg_mcr = priv->read(®s->mcr) & ~FLEXCAN_MCR_FDEN;
 | |
| +
 | |
| +		/* support BRS when set CAN FD mode
 | |
| +		 * 64 bytes payload per MB and 7 MBs per RAM block by default
 | |
| +		 * enable CAN FD mode
 | |
| +		 */
 | |
| +		if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
 | |
| +			reg_fdctrl |= FLEXCAN_FDCTRL_FDRATE;
 | |
| +			reg_fdctrl |= FLEXCAN_FDCTRL_MBDSR1(0x3) | FLEXCAN_FDCTRL_MBDSR0(0x3);
 | |
| +			reg_mcr |= FLEXCAN_MCR_FDEN;
 | |
| +		}
 | |
| +
 | |
| +		priv->write(reg_fdctrl, ®s->fdctrl);
 | |
| +		priv->write(reg_mcr, ®s->mcr);
 | |
| +	}
 | |
| +
 | |
|  	if ((priv->devtype_data->quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS)) {
 | |
|  		reg_ctrl2 = priv->read(®s->ctrl2);
 | |
|  		reg_ctrl2 |= FLEXCAN_CTRL2_EACEN | FLEXCAN_CTRL2_RRS;
 | |
| @@ -1312,6 +1480,12 @@ static int flexcan_open(struct net_devic
 | |
|  	struct flexcan_priv *priv = netdev_priv(dev);
 | |
|  	int err;
 | |
|  
 | |
| +	if ((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) &&
 | |
| +	    (priv->can.ctrlmode & CAN_CTRLMODE_FD)) {
 | |
| +		netdev_err(dev, "three samples mode and fd mode can't be used together\n");
 | |
| +		return -EINVAL;
 | |
| +	}
 | |
| +
 | |
|  	err = pm_runtime_get_sync(priv->dev);
 | |
|  	if (err < 0) {
 | |
|  		pm_runtime_put_noidle(priv->dev);
 | |
| @@ -1330,7 +1504,10 @@ static int flexcan_open(struct net_devic
 | |
|  	if (err)
 | |
|  		goto out_transceiver_disable;
 | |
|  
 | |
| -	priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
 | |
| +	if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
 | |
| +		priv->mb_size = sizeof(struct flexcan_mb) + CANFD_MAX_DLEN;
 | |
| +	else
 | |
| +		priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
 | |
|  	priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) +
 | |
|  			 (sizeof(priv->regs->mb[1]) / priv->mb_size);
 | |
|  
 | |
| @@ -1682,6 +1859,18 @@ static int flexcan_probe(struct platform
 | |
|  	priv->devtype_data = devtype_data;
 | |
|  	priv->reg_xceiver = reg_xceiver;
 | |
|  
 | |
| +	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_TIMESTAMP_SUPPORT_FD) {
 | |
| +		if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
 | |
| +			priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
 | |
| +			priv->can.bittiming_const = &flexcan_fd_bittiming_const;
 | |
| +			priv->can.data_bittiming_const = &flexcan_fd_data_bittiming_const;
 | |
| +		} else {
 | |
| +			dev_err(&pdev->dev, "can fd mode can't work on fifo mode\n");
 | |
| +			err = -EINVAL;
 | |
| +			goto failed_register;
 | |
| +		}
 | |
| +	}
 | |
| +
 | |
|  	pm_runtime_get_noresume(&pdev->dev);
 | |
|  	pm_runtime_set_active(&pdev->dev);
 | |
|  	pm_runtime_enable(&pdev->dev);
 |