RE: [PATCH v2 4/4] net: can: flexcan: can FD Format (FDF) changes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: linux-can-owner@xxxxxxxxxxxxxxx <linux-can-owner@xxxxxxxxxxxxxxx>
> On Behalf Of Pankaj Bansal
> Sent: 2019年5月28日 17:55
> To: Wolfgang Grandegger <wg@xxxxxxxxxxxxxx>; Marc Kleine-Budde
> <mkl@xxxxxxxxxxxxxx>
> Cc: linux-can@xxxxxxxxxxxxxxx
> Subject: [PATCH v2 4/4] net: can: flexcan: can FD Format (FDF) changes
> 
> The new version of flexcan support CAN FD mode. The salient features of this
> version are:
> - Full implementation of the CAN with Flexible Data Rate (CAN FD) protocol
>   specification and CAN protocol specification, Version 2.0 B
> 	• Standard data frames
> 	• Extended data frames
> 	• Zero to sixty four bytes data length
> 	• Programmable bit rate
> 	• Content-related addressing
> - Flexible mailboxes configurable to store 0 to 8, 16, 32 or 64 bytes
>   data length
> - Compliant with the ISO 11898-1 standard
> - Transceiver Delay Compensation feature when transmitting CAN FD messages
>   at faster data rates
> 
> Signed-off-by: Pankaj Bansal <pankaj.bansal@xxxxxxx>
> ---
> 
> Notes:
>     V2:
>     - Fix the overflow when setting CAN bittimings in CBT and FDCBT Registers
> 
>  drivers/net/can/flexcan.c | 264 +++++++++++++++++++++++++++++++-----
>  1 file changed, 227 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index
> 26e65d3d1c3a..37d4fe6533e8 100644
> --- 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,29 @@
>  	 FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT | \
>  	 FLEXCAN_ESR_WAK_INT)
> 
> +/* FLEXCAN CAN 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 CAN FD control Register (FDCTRL) bits */
> +#define FLEXCAN_FDCTRL_FDRATE		BIT(31)
> +#define FLEXCAN_FDCTRL_MBDSR1(x)	(((x) & 0x03) << 19)
> +#define FLEXCAN_FDCTRL_MBDSR0(x)	(((x) & 0x03) << 16)
> +#define FLEXCAN_FDCTRL_TDCEN		BIT(15)
> +#define FLEXCAN_FDCTRL_TDCFAIL		BIT(14)
> +#define FLEXCAN_FDCTRL_TDCOFF(x)	(((x) & 0x1f) << 8)
> +
> +/* FLEXCAN CAN FD Bit Timing Register (FDCBT) bits */
> +#define FLEXCAN_FDCBT_FPRESDIV(x)	(((x) & 0x3ff) << 20)
> +#define FLEXCAN_FDCBT_FRJW(x)		(((x) & 0x03) << 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 +185,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)
> @@ -172,15 +199,16 @@
>  /* FLEXCAN hardware feature flags
>   *
>   * Below is some version info we got:
> - *    SOC   Version   IP-Version  Glitch- [TR]WRN_INT IRQ Err Memory
> err RTR re-
> - *                                Filter? connected?  Passive detection
> ception in MB
> - *   MX25  FlexCAN2  03.00.00.00     no        no        no
> no        no
> - *   MX28  FlexCAN2  03.00.04.00    yes       yes        no
> no        no
> - *   MX35  FlexCAN2  03.00.00.00     no        no        no
> no        no
> - *   MX53  FlexCAN2  03.00.00.00    yes        no        no
> no        no
> - *   MX6s  FlexCAN3  10.00.12.00    yes       yes        no
> no       yes
> - *   VF610 FlexCAN3  ?               no       yes        no
> yes       yes?
> - * LS1021A FlexCAN2  03.00.04.00     no       yes        no
> no       yes
> + *    SOC   Version   IP-Version  Glitch- [TR]WRN_INT IRQ Err Memory
> err RTR rece-     FD Mode
> + *                                Filter? connected?  Passive detection
> ption in MB   Supported?
> + *   MX25  FlexCAN2  03.00.00.00     no        no        no
> no        no           no
> + *   MX28  FlexCAN2  03.00.04.00    yes       yes        no
> no        no           no
> + *   MX35  FlexCAN2  03.00.00.00     no        no        no
> no        no           no
> + *   MX53  FlexCAN2  03.00.00.00    yes        no        no
> no        no           no
> + *   MX6s  FlexCAN3  10.00.12.00    yes       yes        no
> no       yes           no
> + *   VF610 FlexCAN3  ?               no       yes        no
> yes       yes?          no
> + * LS1021A FlexCAN2  03.00.04.00     no       yes        no
> no       yes           no
> + * LX2160A FlexCAN3  03.00.23.00     no       yes        no
> no       yes          yes
>   *
>   * Some SOCs do not have the RX_WARN & TX_WARN interrupt line
> connected.
>   */
> @@ -192,6 +220,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_USE_FD		BIT(9)
> 
>  /* Structure of the message buffer */
>  struct flexcan_mb {
> @@ -225,7 +254,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 +280,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 {
> @@ -324,6 +358,12 @@ static const struct flexcan_devtype_data
> fsl_ls1021a_r2_devtype_data = {
>  		FLEXCAN_QUIRK_USE_OFF_TIMESTAMP,
>  };
> 
> +static const struct flexcan_devtype_data fsl_lx2160a_r1_devtype_data = {
> +	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG |
> FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
> +		FLEXCAN_QUIRK_DISABLE_MECR |
> FLEXCAN_QUIRK_BROKEN_PERR_STATE |
> +		FLEXCAN_QUIRK_USE_OFF_TIMESTAMP |
> FLEXCAN_QUIRK_USE_FD, };
> +
>  static const struct can_bittiming_const flexcan_bittiming_const = {
>  	.name = DRV_NAME,
>  	.tseg1_min = 4,
> @@ -336,6 +376,30 @@ static const struct can_bittiming_const
> flexcan_bittiming_const = {
>  	.brp_inc = 1,
>  };
> 
> +static const struct can_bittiming_const extended_flexcan_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_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.
> @@ -626,8 +690,16 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff
> *skb, struct net_device *de
>  		can_id = (cfd->can_id & CAN_SFF_MASK) << 18;
>  	}
> 
> -	if (!can_is_canfd_skb(skb) && (cfd->can_id & CAN_RTR_FLAG))
> -		ctrl |= FLEXCAN_MB_CNT_RTR;
> +	if (can_is_canfd_skb(skb)) {
> +		ctrl |= FLEXCAN_MB_CNT_EDL;
> +		if (cfd->flags & CANFD_BRS)
> +			ctrl |= FLEXCAN_MB_CNT_BRS;
> +		if (cfd->flags & CANFD_ESI)
> +			ctrl |= FLEXCAN_MB_CNT_ESI;
> +	} else {
> +		if (cfd->can_id & CAN_RTR_FLAG)
> +			ctrl |= FLEXCAN_MB_CNT_RTR;
> +	}
> 
>  	for (i = 0; i < can_len2dlc(cfd->len); i += sizeof(u32)) {
>  		data = be32_to_cpup((__be32 *)&cfd->data[i]); @@ -981,36
> +1053,131 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
> 
>  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 *data_bt = &priv->can.data_bittiming;
>  	struct flexcan_regs __iomem *regs = priv->regs;
> -	u32 reg;
> +	u32 reg_ctrl, reg_mcr, reg_cbt, reg_fdcbt, reg_fdctrl;
> 
> -	reg = priv->read(&regs->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_mcr = priv->read(&regs->mcr);
> +	reg_ctrl = priv->read(&regs->ctrl);
> +
> +	reg_ctrl &= ~(FLEXCAN_CTRL_LPB |
> +		      FLEXCAN_CTRL_SMP |
> +		      FLEXCAN_CTRL_LOM);
> 
>  	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
> -		reg |= FLEXCAN_CTRL_LPB;
> +		reg_ctrl |= FLEXCAN_CTRL_LPB;
>  	if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
> -		reg |= FLEXCAN_CTRL_LOM;
> +		reg_ctrl |= FLEXCAN_CTRL_LOM;
>  	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
> -		reg |= FLEXCAN_CTRL_SMP;
> +		reg_ctrl |= FLEXCAN_CTRL_SMP;
> +
> +	if (reg_mcr & FLEXCAN_MCR_FDEN) {
> +		reg_cbt = priv->read(&regs->cbt);
> +		reg_fdcbt = priv->read(&regs->fdcbt);
> +		reg_fdctrl = priv->read(&regs->fdctrl);
> +
> +		reg_cbt |= FLEXCAN_CBT_BTF;
> +		reg_cbt &= ~(FLEXCAN_CBT_EPRESDIV(0x3ff) |
> +			     FLEXCAN_CBT_ERJW(0x0f) |
> +			     FLEXCAN_CBT_EPROPSEG(0x3f) |
> +			     FLEXCAN_CBT_EPSEG1(0x1f) |
> +			     FLEXCAN_CBT_EPSEG2(0x1f));
> +
> +		/* 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;
> +		}
> 
> -	netdev_dbg(dev, "writing ctrl=0x%08x\n", reg);
> -	priv->write(reg, &regs->ctrl);
> +		reg_cbt |= FLEXCAN_CBT_EPRESDIV(bt->brp - 1) |
> +			   FLEXCAN_CBT_ERJW(bt->sjw - 1) |
> +			   FLEXCAN_CBT_EPROPSEG(bt->prop_seg - 1) |
> +			   FLEXCAN_CBT_EPSEG1(bt->phase_seg1 - 1) |
> +			   FLEXCAN_CBT_EPSEG2(bt->phase_seg2 - 1);
> +
> +		reg_fdcbt &= ~(FLEXCAN_FDCBT_FPRESDIV(0x3ff) |
> +			       FLEXCAN_FDCBT_FRJW(0x03) |
> +			       FLEXCAN_CBT_EPROPSEG(0x1f) |
> +			       FLEXCAN_FDCBT_FPSEG1(0x07) |
> +			       FLEXCAN_FDCBT_FPSEG2(0x07));
> +
> +		/* 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 (data_bt->phase_seg1 > 0x8) {
> +			data_bt->prop_seg += (data_bt->phase_seg1 - 0x8);
> +			data_bt->phase_seg1 = 0x8;
> +		}
> +
> +		reg_fdcbt |= FLEXCAN_FDCBT_FPRESDIV(data_bt->brp - 1) |
> +			     FLEXCAN_FDCBT_FRJW(data_bt->sjw - 1) |
> +			     FLEXCAN_FDCBT_FPROPSEG(data_bt->prop_seg) |
> +			     FLEXCAN_FDCBT_FPSEG1(data_bt->phase_seg1 - 1) |
> +			     FLEXCAN_FDCBT_FPSEG2(data_bt->phase_seg2 - 1);
> +
> +		if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
> +			u32 tdcoff;
> +			/* No TDC is needed for data bit rates up to 2.5 MBit/s
> +			 * refer
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.c
> an-cia.org%2Ffileadmin%2Fresources%2Fdocuments%2Fproceedings%2F2013
> _hartwich_v2.pdf&amp;data=02%7C01%7Cqiangqing.zhang%40nxp.com%7C0
> 70afb27ad23478de53508d6e352a25f%7C686ea1d3bc2b4c6fa92cd99c5c301
> 635%7C0%7C0%7C636946341388299767&amp;sdata=4gHJvh9QZuIhE7TGvx
> arFejLAEWvNLqdq8aUlHxoDcQ%3D&amp;reserved=0
> +			 */
> +			if (reg_ctrl & FLEXCAN_CTRL_LPB ||
> +			    data_bt->bitrate <= 2500000)
> +				reg_fdctrl &= ~FLEXCAN_FDCTRL_TDCEN;
> +			else
> +				reg_fdctrl |= FLEXCAN_FDCTRL_TDCEN;
> +
> +			reg_fdctrl |= (FLEXCAN_FDCTRL_FDRATE |
> +				       FLEXCAN_FDCTRL_TDCFAIL);
> +
> +			/* offset should be within the can FD bit timings */
> +			tdcoff = (data_bt->phase_seg1 + data_bt->prop_seg) *
> +				  data_bt->brp;

[Joakim Zhang]
One more caught, should this be tdcoff = (data_bt->phase_seg1 + data_bt->prop_seg  + 1  ) * data_bt->brp;

> +			reg_fdctrl |= FLEXCAN_FDCTRL_TDCOFF(tdcoff);
> +			reg_fdctrl |= FLEXCAN_FDCTRL_MBDSR0(3) |
> +				      FLEXCAN_FDCTRL_MBDSR1(3);
> +
> +			if (data_bt->brp != bt->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",
> +					    data_bt->brp, bt->brp);
> +		} else {
> +			reg_fdctrl |= FLEXCAN_FDCTRL_MBDSR0(0) |
> +				      FLEXCAN_FDCTRL_MBDSR1(0);
> +			reg_fdctrl &= ~FLEXCAN_FDCTRL_FDRATE;
> +		}
> +		netdev_dbg(dev, "writing fdctrl=0x%08x", reg_fdctrl);
> +		netdev_dbg(dev, "writing cbt=0x%08x\n", reg_cbt);
> +		netdev_dbg(dev, "writing fdcbt=0x%08x\n", reg_fdcbt);
> +		priv->write(reg_fdctrl, &regs->fdctrl);
> +		priv->write(reg_cbt, &regs->cbt);
> +		priv->write(reg_fdcbt, &regs->fdcbt);
> +	} else {
> +		reg_ctrl &= ~(FLEXCAN_CTRL_PRESDIV(0xff) |
> +			FLEXCAN_CTRL_RJW(0x3) |
> +			FLEXCAN_CTRL_PSEG1(0x7) |
> +			FLEXCAN_CTRL_PSEG2(0x7) |
> +			FLEXCAN_CTRL_PROPSEG(0x7));
> +
> +		reg_ctrl |= 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);
> +	}
> +
> +	netdev_dbg(dev, "writing ctrl=0x%08x\n", reg_ctrl);
> +	priv->write(reg_ctrl, &regs->ctrl);
> 
>  	/* print chip status */
>  	netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__, @@
> -1049,6 +1216,7 @@ static int flexcan_chip_start(struct net_device *dev)
>  	 * enable individual RX masking
>  	 * choose format C
>  	 * set max mailbox number
> +	 * enable FD mode
>  	 */
>  	reg_mcr = priv->read(&regs->mcr);
>  	reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
> @@ -1083,6 +1251,8 @@ static int flexcan_chip_start(struct net_device *dev)
>  		reg_mcr &= ~FLEXCAN_MCR_SRX_DIS;
>  	else
>  		reg_mcr |= FLEXCAN_MCR_SRX_DIS;
> +	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_FD)
> +		reg_mcr |= FLEXCAN_MCR_FDEN;
> 
>  	netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
>  	priv->write(reg_mcr, &regs->mcr);
> @@ -1257,7 +1427,14 @@ static int flexcan_open(struct net_device *dev)
>  	if (err)
>  		goto out_close;
> 
> -	priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
> +	if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
> +		priv->offload.fd_enable = true;
> +		priv->mb_size = sizeof(struct flexcan_mb) + CANFD_MAX_DLEN;
> +	} else {
> +		priv->offload.fd_enable = false;
> +		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);
> 
> @@ -1272,7 +1449,6 @@ static int flexcan_open(struct net_device *dev)
> 
>  	priv->reg_imask_default = FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
> 
> -	priv->offload.fd_enable = false;
>  	priv->offload.mailbox_read = flexcan_mailbox_read;
> 
>  	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
> { @@ -1495,6 +1671,7 @@ static const struct of_device_id flexcan_of_match[]
> = {
>  	{ .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
>  	{ .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, },
>  	{ .compatible = "fsl,ls1021ar2-flexcan", .data =
> &fsl_ls1021a_r2_devtype_data, },
> +	{ .compatible = "fsl,lx2160ar1-flexcan", .data =
> +&fsl_lx2160a_r1_devtype_data, },
>  	{ /* sentinel */ },
>  };
>  MODULE_DEVICE_TABLE(of, flexcan_of_match); @@ -1588,6 +1765,13 @@
> static int flexcan_probe(struct platform_device *pdev)
>  		priv->write = flexcan_write_le;
>  	}
> 
> +	if ((devtype_data->quirks & FLEXCAN_QUIRK_USE_FD) &&
> +	    !(devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)) {
> +		dev_err(&pdev->dev, "can't use FIFO with FD mode\n");
> +		err = -ENODEV;
> +		goto failed_register;
> +	}
> +
>  	priv->dev = &pdev->dev;
>  	priv->can.clock.freq = clock_freq;
>  	priv->can.bittiming_const = &flexcan_bittiming_const; @@ -1603,6
> +1787,12 @@ static int flexcan_probe(struct platform_device *pdev)
>  	priv->devtype_data = devtype_data;
>  	priv->reg_xceiver = reg_xceiver;
> 
> +	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_FD) {
> +		priv->can.bittiming_const = &extended_flexcan_bittiming_const;
> +		priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
> +		priv->can.data_bittiming_const = &flexcan_data_bittiming_const;
> +	}
> +
>  	pm_runtime_get_noresume(&pdev->dev);
>  	pm_runtime_set_active(&pdev->dev);
>  	pm_runtime_enable(&pdev->dev);
> --
> 2.17.1





[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux