mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-20 22:23:27 +00:00
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 {
|
||
|
@@ -337,6 +367,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.
|
||
|
@@ -631,7 +685,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))
|
||
|
@@ -649,6 +703,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)]);
|
||
|
@@ -859,7 +916,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;
|
||
|
@@ -874,9 +934,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)]));
|
||
|
@@ -1021,27 +1089,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)
|
||
|
@@ -1052,9 +1107,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
|
||
|
@@ -1066,7 +1214,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;
|
||
|
@@ -1163,6 +1311,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;
|
||
|
@@ -1288,6 +1456,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)
|
||
|
return err;
|
||
|
@@ -1300,7 +1474,10 @@ static int flexcan_open(struct net_devic
|
||
|
if (err)
|
||
|
goto out_close;
|
||
|
|
||
|
- 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);
|
||
|
|
||
|
@@ -1645,6 +1822,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);
|