| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From 2aea13a107090d05e968d7d2aa3f72380a3f1b4c Mon Sep 17 00:00:00 2001 |
| 2 | From: Joakim Zhang <qiangqing.zhang@nxp.com> |
| 3 | Date: Fri, 12 Jul 2019 08:02:44 +0000 |
| 4 | Subject: [PATCH] can: flexcan: add CAN FD mode support |
| 5 | |
| 6 | This patch intends to add CAN FD mode support in driver, it means that |
| 7 | payload size can extend up to 64 bytes. |
| 8 | |
| 9 | Bit timing always set in CBT register other than CTRL1 register when |
| 10 | CANFD supports BRS, it will extend the range of all CAN bit timing |
| 11 | variables (PRESDIV, PROPSEG, PSEG1, PSEG2 and RJW), which will improve |
| 12 | the bit timing accuracy. |
| 13 | |
| 14 | Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com> |
| 15 | Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> |
| 16 | --- |
| 17 | drivers/net/can/flexcan.c | 247 ++++++++++++++++++++++++++++++++++++++++------ |
| 18 | 1 file changed, 218 insertions(+), 29 deletions(-) |
| 19 | |
| 20 | --- a/drivers/net/can/flexcan.c |
| 21 | +++ b/drivers/net/can/flexcan.c |
| 22 | @@ -52,6 +52,7 @@ |
| 23 | #define FLEXCAN_MCR_IRMQ BIT(16) |
| 24 | #define FLEXCAN_MCR_LPRIO_EN BIT(13) |
| 25 | #define FLEXCAN_MCR_AEN BIT(12) |
| 26 | +#define FLEXCAN_MCR_FDEN BIT(11) |
| 27 | /* MCR_MAXMB: maximum used MBs is MAXMB + 1 */ |
| 28 | #define FLEXCAN_MCR_MAXMB(x) ((x) & 0x7f) |
| 29 | #define FLEXCAN_MCR_IDAM_A (0x0 << 8) |
| 30 | @@ -137,6 +138,26 @@ |
| 31 | FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT | \ |
| 32 | FLEXCAN_ESR_WAK_INT) |
| 33 | |
| 34 | +/* FLEXCAN Bit Timing register (CBT) bits */ |
| 35 | +#define FLEXCAN_CBT_BTF BIT(31) |
| 36 | +#define FLEXCAN_CBT_EPRESDIV(x) (((x) & 0x3ff) << 21) |
| 37 | +#define FLEXCAN_CBT_ERJW(x) (((x) & 0x0f) << 16) |
| 38 | +#define FLEXCAN_CBT_EPROPSEG(x) (((x) & 0x3f) << 10) |
| 39 | +#define FLEXCAN_CBT_EPSEG1(x) (((x) & 0x1f) << 5) |
| 40 | +#define FLEXCAN_CBT_EPSEG2(x) ((x) & 0x1f) |
| 41 | + |
| 42 | +/* FLEXCAN FD control register (FDCTRL) bits */ |
| 43 | +#define FLEXCAN_FDCTRL_FDRATE BIT(31) |
| 44 | +#define FLEXCAN_FDCTRL_MBDSR1(x) (((x) & 0x3) << 19) |
| 45 | +#define FLEXCAN_FDCTRL_MBDSR0(x) (((x) & 0x3) << 16) |
| 46 | + |
| 47 | +/* FLEXCAN FD Bit Timing register (FDCBT) bits */ |
| 48 | +#define FLEXCAN_FDCBT_FPRESDIV(x) (((x) & 0x3ff) << 20) |
| 49 | +#define FLEXCAN_FDCBT_FRJW(x) (((x) & 0x07) << 16) |
| 50 | +#define FLEXCAN_FDCBT_FPROPSEG(x) (((x) & 0x1f) << 10) |
| 51 | +#define FLEXCAN_FDCBT_FPSEG1(x) (((x) & 0x07) << 5) |
| 52 | +#define FLEXCAN_FDCBT_FPSEG2(x) ((x) & 0x07) |
| 53 | + |
| 54 | /* FLEXCAN interrupt flag register (IFLAG) bits */ |
| 55 | /* Errata ERR005829 step7: Reserve first valid MB */ |
| 56 | #define FLEXCAN_TX_MB_RESERVED_OFF_FIFO 8 |
| 57 | @@ -161,6 +182,9 @@ |
| 58 | #define FLEXCAN_MB_CODE_TX_DATA (0xc << 24) |
| 59 | #define FLEXCAN_MB_CODE_TX_TANSWER (0xe << 24) |
| 60 | |
| 61 | +#define FLEXCAN_MB_CNT_EDL BIT(31) |
| 62 | +#define FLEXCAN_MB_CNT_BRS BIT(30) |
| 63 | +#define FLEXCAN_MB_CNT_ESI BIT(29) |
| 64 | #define FLEXCAN_MB_CNT_SRR BIT(22) |
| 65 | #define FLEXCAN_MB_CNT_IDE BIT(21) |
| 66 | #define FLEXCAN_MB_CNT_RTR BIT(20) |
| 67 | @@ -192,6 +216,7 @@ |
| 68 | #define FLEXCAN_QUIRK_BROKEN_PERR_STATE BIT(6) /* No interrupt for error passive */ |
| 69 | #define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN BIT(7) /* default to BE register access */ |
| 70 | #define FLEXCAN_QUIRK_SETUP_STOP_MODE BIT(8) /* Setup stop mode to support wakeup */ |
| 71 | +#define FLEXCAN_QUIRK_TIMESTAMP_SUPPORT_FD BIT(9) /* Use timestamp then support can fd mode */ |
| 72 | |
| 73 | /* Structure of the message buffer */ |
| 74 | struct flexcan_mb { |
| 75 | @@ -225,7 +250,8 @@ struct flexcan_regs { |
| 76 | u32 crcr; /* 0x44 */ |
| 77 | u32 rxfgmask; /* 0x48 */ |
| 78 | u32 rxfir; /* 0x4c */ |
| 79 | - u32 _reserved3[12]; /* 0x50 */ |
| 80 | + u32 cbt; /* 0x50 */ |
| 81 | + u32 _reserved3[11]; /* 0x54 */ |
| 82 | u8 mb[2][512]; /* 0x80 */ |
| 83 | /* FIFO-mode: |
| 84 | * MB |
| 85 | @@ -250,6 +276,10 @@ struct flexcan_regs { |
| 86 | u32 rerrdr; /* 0xaf4 */ |
| 87 | u32 rerrsynr; /* 0xaf8 */ |
| 88 | u32 errsr; /* 0xafc */ |
| 89 | + u32 _reserved7[64]; /* 0xb00 */ |
| 90 | + u32 fdctrl; /* 0xc00 */ |
| 91 | + u32 fdcbt; /* 0xc04 */ |
| 92 | + u32 fdcrc; /* 0xc08 */ |
| 93 | }; |
| 94 | |
| 95 | struct flexcan_devtype_data { |
| 96 | @@ -336,6 +366,30 @@ static const struct can_bittiming_const |
| 97 | .brp_inc = 1, |
| 98 | }; |
| 99 | |
| 100 | +static const struct can_bittiming_const flexcan_fd_bittiming_const = { |
| 101 | + .name = DRV_NAME, |
| 102 | + .tseg1_min = 2, |
| 103 | + .tseg1_max = 96, |
| 104 | + .tseg2_min = 2, |
| 105 | + .tseg2_max = 32, |
| 106 | + .sjw_max = 16, |
| 107 | + .brp_min = 1, |
| 108 | + .brp_max = 1024, |
| 109 | + .brp_inc = 1, |
| 110 | +}; |
| 111 | + |
| 112 | +static const struct can_bittiming_const flexcan_fd_data_bittiming_const = { |
| 113 | + .name = DRV_NAME, |
| 114 | + .tseg1_min = 2, |
| 115 | + .tseg1_max = 39, |
| 116 | + .tseg2_min = 2, |
| 117 | + .tseg2_max = 8, |
| 118 | + .sjw_max = 4, |
| 119 | + .brp_min = 1, |
| 120 | + .brp_max = 1024, |
| 121 | + .brp_inc = 1, |
| 122 | +}; |
| 123 | + |
| 124 | /* FlexCAN module is essentially modelled as a little-endian IP in most |
| 125 | * SoCs, i.e the registers as well as the message buffer areas are |
| 126 | * implemented in a little-endian fashion. |
| 127 | @@ -638,7 +692,7 @@ static netdev_tx_t flexcan_start_xmit(st |
| 128 | struct canfd_frame *cfd = (struct canfd_frame *)skb->data; |
| 129 | u32 can_id; |
| 130 | u32 data; |
| 131 | - u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cfd->len << 16); |
| 132 | + u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ((can_len2dlc(cfd->len)) << 16); |
| 133 | int i; |
| 134 | |
| 135 | if (can_dropped_invalid_skb(dev, skb)) |
| 136 | @@ -656,6 +710,9 @@ static netdev_tx_t flexcan_start_xmit(st |
| 137 | if (cfd->can_id & CAN_RTR_FLAG) |
| 138 | ctrl |= FLEXCAN_MB_CNT_RTR; |
| 139 | |
| 140 | + if (can_is_canfd_skb(skb)) |
| 141 | + ctrl |= FLEXCAN_MB_CNT_EDL; |
| 142 | + |
| 143 | for (i = 0; i < cfd->len; i += sizeof(u32)) { |
| 144 | data = be32_to_cpup((__be32 *)&cfd->data[i]); |
| 145 | priv->write(data, &priv->tx_mb->data[i / sizeof(u32)]); |
| 146 | @@ -866,7 +923,10 @@ static struct sk_buff *flexcan_mailbox_r |
| 147 | reg_ctrl = priv->read(&mb->can_ctrl); |
| 148 | } |
| 149 | |
| 150 | - skb = alloc_can_skb(offload->dev, (struct can_frame **)&cfd); |
| 151 | + if (reg_ctrl & FLEXCAN_MB_CNT_EDL) |
| 152 | + skb = alloc_canfd_skb(offload->dev, &cfd); |
| 153 | + else |
| 154 | + skb = alloc_can_skb(offload->dev, (struct can_frame **)&cfd); |
| 155 | if (unlikely(!skb)) { |
| 156 | skb = ERR_PTR(-ENOMEM); |
| 157 | goto mark_as_read; |
| 158 | @@ -881,9 +941,17 @@ static struct sk_buff *flexcan_mailbox_r |
| 159 | else |
| 160 | cfd->can_id = (reg_id >> 18) & CAN_SFF_MASK; |
| 161 | |
| 162 | - if (reg_ctrl & FLEXCAN_MB_CNT_RTR) |
| 163 | - cfd->can_id |= CAN_RTR_FLAG; |
| 164 | - cfd->len = get_can_dlc((reg_ctrl >> 16) & 0xf); |
| 165 | + if (reg_ctrl & FLEXCAN_MB_CNT_EDL) { |
| 166 | + cfd->len = can_dlc2len(get_canfd_dlc((reg_ctrl >> 16) & 0xf)); |
| 167 | + } else { |
| 168 | + cfd->len = get_can_dlc((reg_ctrl >> 16) & 0xf); |
| 169 | + |
| 170 | + if (reg_ctrl & FLEXCAN_MB_CNT_RTR) |
| 171 | + cfd->can_id |= CAN_RTR_FLAG; |
| 172 | + } |
| 173 | + |
| 174 | + if (reg_ctrl & FLEXCAN_MB_CNT_ESI) |
| 175 | + cfd->flags |= CANFD_ESI; |
| 176 | |
| 177 | for (i = 0; i < cfd->len; i += sizeof(u32)) { |
| 178 | __be32 data = cpu_to_be32(priv->read(&mb->data[i / sizeof(u32)])); |
| 179 | @@ -1028,27 +1096,14 @@ static irqreturn_t flexcan_irq(int irq, |
| 180 | |
| 181 | static void flexcan_set_bittiming(struct net_device *dev) |
| 182 | { |
| 183 | - const struct flexcan_priv *priv = netdev_priv(dev); |
| 184 | - const struct can_bittiming *bt = &priv->can.bittiming; |
| 185 | + struct flexcan_priv *priv = netdev_priv(dev); |
| 186 | + struct can_bittiming *bt = &priv->can.bittiming; |
| 187 | + struct can_bittiming *dbt = &priv->can.data_bittiming; |
| 188 | struct flexcan_regs __iomem *regs = priv->regs; |
| 189 | - u32 reg; |
| 190 | + u32 reg, reg_cbt, reg_fdcbt; |
| 191 | |
| 192 | reg = priv->read(®s->ctrl); |
| 193 | - reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) | |
| 194 | - FLEXCAN_CTRL_RJW(0x3) | |
| 195 | - FLEXCAN_CTRL_PSEG1(0x7) | |
| 196 | - FLEXCAN_CTRL_PSEG2(0x7) | |
| 197 | - FLEXCAN_CTRL_PROPSEG(0x7) | |
| 198 | - FLEXCAN_CTRL_LPB | |
| 199 | - FLEXCAN_CTRL_SMP | |
| 200 | - FLEXCAN_CTRL_LOM); |
| 201 | - |
| 202 | - reg |= FLEXCAN_CTRL_PRESDIV(bt->brp - 1) | |
| 203 | - FLEXCAN_CTRL_PSEG1(bt->phase_seg1 - 1) | |
| 204 | - FLEXCAN_CTRL_PSEG2(bt->phase_seg2 - 1) | |
| 205 | - FLEXCAN_CTRL_RJW(bt->sjw - 1) | |
| 206 | - FLEXCAN_CTRL_PROPSEG(bt->prop_seg - 1); |
| 207 | - |
| 208 | + reg &= ~(FLEXCAN_CTRL_LPB | FLEXCAN_CTRL_SMP | FLEXCAN_CTRL_LOM); |
| 209 | if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) |
| 210 | reg |= FLEXCAN_CTRL_LPB; |
| 211 | if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) |
| 212 | @@ -1059,9 +1114,102 @@ static void flexcan_set_bittiming(struct |
| 213 | netdev_dbg(dev, "writing ctrl=0x%08x\n", reg); |
| 214 | priv->write(reg, ®s->ctrl); |
| 215 | |
| 216 | - /* print chip status */ |
| 217 | - netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__, |
| 218 | - priv->read(®s->mcr), priv->read(®s->ctrl)); |
| 219 | + if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) { |
| 220 | + reg_cbt = priv->read(®s->cbt); |
| 221 | + reg_cbt &= ~(FLEXCAN_CBT_EPRESDIV(0x3ff) | |
| 222 | + FLEXCAN_CBT_EPSEG1(0x1f) | |
| 223 | + FLEXCAN_CBT_EPSEG2(0x1f) | |
| 224 | + FLEXCAN_CBT_ERJW(0x1f) | |
| 225 | + FLEXCAN_CBT_EPROPSEG(0x3f) | |
| 226 | + FLEXCAN_CBT_BTF); |
| 227 | + |
| 228 | + /* CBT[EPSEG1] is 5 bit long and CBT[EPROPSEG] is 6 bit long. |
| 229 | + * The can_calc_bittiming tries to divide the tseg1 equally |
| 230 | + * between phase_seg1 and prop_seg, which may not fit in CBT |
| 231 | + * register. Therefore, if phase_seg1 is more than possible |
| 232 | + * value, increase prop_seg and decrease phase_seg1 |
| 233 | + */ |
| 234 | + if (bt->phase_seg1 > 0x20) { |
| 235 | + bt->prop_seg += (bt->phase_seg1 - 0x20); |
| 236 | + bt->phase_seg1 = 0x20; |
| 237 | + } |
| 238 | + |
| 239 | + reg_cbt = FLEXCAN_CBT_EPRESDIV(bt->brp - 1) | |
| 240 | + FLEXCAN_CBT_EPSEG1(bt->phase_seg1 - 1) | |
| 241 | + FLEXCAN_CBT_EPSEG2(bt->phase_seg2 - 1) | |
| 242 | + FLEXCAN_CBT_ERJW(bt->sjw - 1) | |
| 243 | + FLEXCAN_CBT_EPROPSEG(bt->prop_seg - 1) | |
| 244 | + FLEXCAN_CBT_BTF; |
| 245 | + priv->write(reg_cbt, ®s->cbt); |
| 246 | + |
| 247 | + netdev_dbg(dev, "bt: prediv %d seg1 %d seg2 %d rjw %d propseg %d\n", |
| 248 | + bt->brp - 1, bt->phase_seg1 - 1, bt->phase_seg2 - 1, |
| 249 | + bt->sjw - 1, bt->prop_seg - 1); |
| 250 | + |
| 251 | + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { |
| 252 | + reg_fdcbt = priv->read(®s->fdcbt); |
| 253 | + reg_fdcbt &= ~(FLEXCAN_FDCBT_FPRESDIV(0x3ff) | |
| 254 | + FLEXCAN_FDCBT_FPSEG1(0x07) | |
| 255 | + FLEXCAN_FDCBT_FPSEG2(0x07) | |
| 256 | + FLEXCAN_FDCBT_FRJW(0x07) | |
| 257 | + FLEXCAN_FDCBT_FPROPSEG(0x1f)); |
| 258 | + |
| 259 | + /* FDCBT[FPSEG1] is 3 bit long and FDCBT[FPROPSEG] is 5 bit long. |
| 260 | + * The can_calc_bittiming tries to divide the tseg1 equally |
| 261 | + * between phase_seg1 and prop_seg, which may not fit in FDCBT |
| 262 | + * register. Therefore, if phase_seg1 is more than possible |
| 263 | + * value, increase prop_seg and decrease phase_seg1 |
| 264 | + */ |
| 265 | + if (dbt->phase_seg1 > 0x8) { |
| 266 | + dbt->prop_seg += (dbt->phase_seg1 - 0x8); |
| 267 | + dbt->phase_seg1 = 0x8; |
| 268 | + } |
| 269 | + |
| 270 | + reg_fdcbt = FLEXCAN_FDCBT_FPRESDIV(dbt->brp - 1) | |
| 271 | + FLEXCAN_FDCBT_FPSEG1(dbt->phase_seg1 - 1) | |
| 272 | + FLEXCAN_FDCBT_FPSEG2(dbt->phase_seg2 - 1) | |
| 273 | + FLEXCAN_FDCBT_FRJW(dbt->sjw - 1) | |
| 274 | + FLEXCAN_FDCBT_FPROPSEG(dbt->prop_seg); |
| 275 | + priv->write(reg_fdcbt, ®s->fdcbt); |
| 276 | + |
| 277 | + if (bt->brp != dbt->brp) |
| 278 | + netdev_warn(dev, "Warning!! data brp = %d and brp = %d don't match.\n" |
| 279 | + "flexcan may not work. consider using different bitrate or data bitrate\n", |
| 280 | + dbt->brp, bt->brp); |
| 281 | + |
| 282 | + netdev_dbg(dev, "fdbt: prediv %d seg1 %d seg2 %d rjw %d propseg %d\n", |
| 283 | + dbt->brp - 1, dbt->phase_seg1 - 1, dbt->phase_seg2 - 1, |
| 284 | + dbt->sjw - 1, dbt->prop_seg); |
| 285 | + |
| 286 | + netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x cbt=0x%08x fdcbt=0x%08x\n", |
| 287 | + __func__, priv->read(®s->mcr), |
| 288 | + priv->read(®s->ctrl), |
| 289 | + priv->read(®s->cbt), |
| 290 | + priv->read(®s->fdcbt)); |
| 291 | + } |
| 292 | + } else { |
| 293 | + reg = priv->read(®s->ctrl); |
| 294 | + reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) | |
| 295 | + FLEXCAN_CTRL_RJW(0x3) | |
| 296 | + FLEXCAN_CTRL_PSEG1(0x7) | |
| 297 | + FLEXCAN_CTRL_PSEG2(0x7) | |
| 298 | + FLEXCAN_CTRL_PROPSEG(0x7)); |
| 299 | + |
| 300 | + reg |= FLEXCAN_CTRL_PRESDIV(bt->brp - 1) | |
| 301 | + FLEXCAN_CTRL_PSEG1(bt->phase_seg1 - 1) | |
| 302 | + FLEXCAN_CTRL_PSEG2(bt->phase_seg2 - 1) | |
| 303 | + FLEXCAN_CTRL_RJW(bt->sjw - 1) | |
| 304 | + FLEXCAN_CTRL_PROPSEG(bt->prop_seg - 1); |
| 305 | + priv->write(reg, ®s->ctrl); |
| 306 | + |
| 307 | + netdev_dbg(dev, "bt: prediv %d seg1 %d seg2 %d rjw %d propseg %d\n", |
| 308 | + bt->brp - 1, bt->phase_seg1 - 1, bt->phase_seg2 - 1, |
| 309 | + bt->sjw - 1, bt->prop_seg - 1); |
| 310 | + |
| 311 | + /* print chip status */ |
| 312 | + netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__, |
| 313 | + priv->read(®s->mcr), priv->read(®s->ctrl)); |
| 314 | + } |
| 315 | } |
| 316 | |
| 317 | /* flexcan_chip_start |
| 318 | @@ -1073,7 +1221,7 @@ static int flexcan_chip_start(struct net |
| 319 | { |
| 320 | struct flexcan_priv *priv = netdev_priv(dev); |
| 321 | struct flexcan_regs __iomem *regs = priv->regs; |
| 322 | - u32 reg_mcr, reg_ctrl, reg_ctrl2, reg_mecr; |
| 323 | + u32 reg_mcr, reg_ctrl, reg_ctrl2, reg_mecr, reg_fdctrl; |
| 324 | u64 reg_imask; |
| 325 | int err, i; |
| 326 | struct flexcan_mb __iomem *mb; |
| 327 | @@ -1172,6 +1320,26 @@ static int flexcan_chip_start(struct net |
| 328 | netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); |
| 329 | priv->write(reg_ctrl, ®s->ctrl); |
| 330 | |
| 331 | + /* FDCTRL */ |
| 332 | + if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) { |
| 333 | + reg_fdctrl = priv->read(®s->fdctrl) & ~FLEXCAN_FDCTRL_FDRATE; |
| 334 | + reg_fdctrl &= ~(FLEXCAN_FDCTRL_MBDSR1(0x3) | FLEXCAN_FDCTRL_MBDSR0(0x3)); |
| 335 | + reg_mcr = priv->read(®s->mcr) & ~FLEXCAN_MCR_FDEN; |
| 336 | + |
| 337 | + /* support BRS when set CAN FD mode |
| 338 | + * 64 bytes payload per MB and 7 MBs per RAM block by default |
| 339 | + * enable CAN FD mode |
| 340 | + */ |
| 341 | + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { |
| 342 | + reg_fdctrl |= FLEXCAN_FDCTRL_FDRATE; |
| 343 | + reg_fdctrl |= FLEXCAN_FDCTRL_MBDSR1(0x3) | FLEXCAN_FDCTRL_MBDSR0(0x3); |
| 344 | + reg_mcr |= FLEXCAN_MCR_FDEN; |
| 345 | + } |
| 346 | + |
| 347 | + priv->write(reg_fdctrl, ®s->fdctrl); |
| 348 | + priv->write(reg_mcr, ®s->mcr); |
| 349 | + } |
| 350 | + |
| 351 | if ((priv->devtype_data->quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS)) { |
| 352 | reg_ctrl2 = priv->read(®s->ctrl2); |
| 353 | reg_ctrl2 |= FLEXCAN_CTRL2_EACEN | FLEXCAN_CTRL2_RRS; |
| 354 | @@ -1312,6 +1480,12 @@ static int flexcan_open(struct net_devic |
| 355 | struct flexcan_priv *priv = netdev_priv(dev); |
| 356 | int err; |
| 357 | |
| 358 | + if ((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) && |
| 359 | + (priv->can.ctrlmode & CAN_CTRLMODE_FD)) { |
| 360 | + netdev_err(dev, "three samples mode and fd mode can't be used together\n"); |
| 361 | + return -EINVAL; |
| 362 | + } |
| 363 | + |
| 364 | err = pm_runtime_get_sync(priv->dev); |
| 365 | if (err < 0) { |
| 366 | pm_runtime_put_noidle(priv->dev); |
| 367 | @@ -1330,7 +1504,10 @@ static int flexcan_open(struct net_devic |
| 368 | if (err) |
| 369 | goto out_transceiver_disable; |
| 370 | |
| 371 | - priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN; |
| 372 | + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) |
| 373 | + priv->mb_size = sizeof(struct flexcan_mb) + CANFD_MAX_DLEN; |
| 374 | + else |
| 375 | + priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN; |
| 376 | priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) + |
| 377 | (sizeof(priv->regs->mb[1]) / priv->mb_size); |
| 378 | |
| 379 | @@ -1682,6 +1859,18 @@ static int flexcan_probe(struct platform |
| 380 | priv->devtype_data = devtype_data; |
| 381 | priv->reg_xceiver = reg_xceiver; |
| 382 | |
| 383 | + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_TIMESTAMP_SUPPORT_FD) { |
| 384 | + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { |
| 385 | + priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD; |
| 386 | + priv->can.bittiming_const = &flexcan_fd_bittiming_const; |
| 387 | + priv->can.data_bittiming_const = &flexcan_fd_data_bittiming_const; |
| 388 | + } else { |
| 389 | + dev_err(&pdev->dev, "can fd mode can't work on fifo mode\n"); |
| 390 | + err = -EINVAL; |
| 391 | + goto failed_register; |
| 392 | + } |
| 393 | + } |
| 394 | + |
| 395 | pm_runtime_get_noresume(&pdev->dev); |
| 396 | pm_runtime_set_active(&pdev->dev); |
| 397 | pm_runtime_enable(&pdev->dev); |