| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From 7b294e0cd2f7fbfb548a17b8d68d161da19e6592 Mon Sep 17 00:00:00 2001 |
| 2 | From: Joakim Zhang <qiangqing.zhang@nxp.com> |
| 3 | Date: Fri, 12 Jul 2019 08:02:56 +0000 |
| 4 | Subject: [PATCH] can: flexcan: add Transceiver Delay Compensation suopport |
| 5 | |
| 6 | The CAN FD protocol allows the transmission and reception of data at a higher |
| 7 | bit rate than the nominal rate used in the arbitration phase when the message's |
| 8 | BRS bit is set. |
| 9 | |
| 10 | The TDC mechanism is effective only during the data phase of FD frames |
| 11 | having BRS bit set. It has no effect either on non-FD frames, or on FD |
| 12 | frames transmitted at normal bit rate. |
| 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 | 19 ++++++++++++++++++- |
| 18 | 1 file changed, 18 insertions(+), 1 deletion(-) |
| 19 | |
| 20 | --- a/drivers/net/can/flexcan.c |
| 21 | +++ b/drivers/net/can/flexcan.c |
| 22 | @@ -149,8 +149,11 @@ |
| 23 | |
| 24 | /* FLEXCAN FD control register (FDCTRL) bits */ |
| 25 | #define FLEXCAN_FDCTRL_FDRATE BIT(31) |
| 26 | +#define FLEXCAN_FDCTRL_TDCEN BIT(15) |
| 27 | +#define FLEXCAN_FDCTRL_TDCFAIL BIT(14) |
| 28 | #define FLEXCAN_FDCTRL_MBDSR1(x) (((x) & 0x3) << 19) |
| 29 | #define FLEXCAN_FDCTRL_MBDSR0(x) (((x) & 0x3) << 16) |
| 30 | +#define FLEXCAN_FDCTRL_TDCOFF(x) (((x) & 0x1f) << 8) |
| 31 | |
| 32 | /* FLEXCAN FD Bit Timing register (FDCBT) bits */ |
| 33 | #define FLEXCAN_FDCBT_FPRESDIV(x) (((x) & 0x3ff) << 20) |
| 34 | @@ -1108,7 +1111,7 @@ static void flexcan_set_bittiming(struct |
| 35 | struct can_bittiming *bt = &priv->can.bittiming; |
| 36 | struct can_bittiming *dbt = &priv->can.data_bittiming; |
| 37 | struct flexcan_regs __iomem *regs = priv->regs; |
| 38 | - u32 reg, reg_cbt, reg_fdcbt; |
| 39 | + u32 reg, reg_cbt, reg_fdcbt, reg_fdctrl; |
| 40 | |
| 41 | reg = priv->read(®s->ctrl); |
| 42 | reg &= ~(FLEXCAN_CTRL_LPB | FLEXCAN_CTRL_SMP | FLEXCAN_CTRL_LOM); |
| 43 | @@ -1180,6 +1183,19 @@ static void flexcan_set_bittiming(struct |
| 44 | FLEXCAN_FDCBT_FPROPSEG(dbt->prop_seg); |
| 45 | priv->write(reg_fdcbt, ®s->fdcbt); |
| 46 | |
| 47 | + /* enable transceiver delay compensation(TDC) for fd frame. |
| 48 | + * TDC must be disabled when Loop Back mode is enabled. |
| 49 | + */ |
| 50 | + reg_fdctrl = priv->read(®s->fdctrl); |
| 51 | + if (!(reg & FLEXCAN_CTRL_LPB)) { |
| 52 | + reg_fdctrl |= FLEXCAN_FDCTRL_TDCEN; |
| 53 | + reg_fdctrl &= ~FLEXCAN_FDCTRL_TDCOFF(0x1f); |
| 54 | + /* for the TDC to work reliably, the offset has to use optimal settings */ |
| 55 | + reg_fdctrl |= FLEXCAN_FDCTRL_TDCOFF(((dbt->phase_seg1 - 1) + dbt->prop_seg + 2) * |
| 56 | + ((dbt->brp -1) + 1)); |
| 57 | + } |
| 58 | + priv->write(reg_fdctrl, ®s->fdctrl); |
| 59 | + |
| 60 | if (bt->brp != dbt->brp) |
| 61 | netdev_warn(dev, "Warning!! data brp = %d and brp = %d don't match.\n" |
| 62 | "flexcan may not work. consider using different bitrate or data bitrate\n", |
| 63 | @@ -1331,6 +1347,7 @@ static int flexcan_chip_start(struct net |
| 64 | /* FDCTRL */ |
| 65 | if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) { |
| 66 | reg_fdctrl = priv->read(®s->fdctrl) & ~FLEXCAN_FDCTRL_FDRATE; |
| 67 | + reg_fdctrl &= ~FLEXCAN_FDCTRL_TDCEN; |
| 68 | reg_fdctrl &= ~(FLEXCAN_FDCTRL_MBDSR1(0x3) | FLEXCAN_FDCTRL_MBDSR0(0x3)); |
| 69 | reg_mcr = priv->read(®s->mcr) & ~FLEXCAN_MCR_FDEN; |
| 70 | reg_ctrl2 = priv->read(®s->ctrl2) & ~FLEXCAN_CTRL2_ISOCANFDEN; |