summaryrefslogtreecommitdiffstats
path: root/drivers/net/can/flexcan.c
diff options
context:
space:
mode:
authorJoakim Zhang <qiangqing.zhang@nxp.com>2019-07-12 10:02:56 +0200
committerMarc Kleine-Budde <mkl@pengutronix.de>2020-09-22 16:55:34 +0200
commitef5f6312087e18ce55cbd067c7c12e7e7e3fb528 (patch)
tree948fcf129ee400dd00398a826093fc0f4a7cad1e /drivers/net/can/flexcan.c
parentcan: flexcan: add CAN FD BRS support (diff)
downloadlinux-ef5f6312087e18ce55cbd067c7c12e7e7e3fb528.tar.xz
linux-ef5f6312087e18ce55cbd067c7c12e7e7e3fb528.zip
can: flexcan: add Transceiver Delay Compensation support
The CAN-FD protocol allows the transmission and reception of data at a higher bit rate than the nominal rate used in the arbitration phase when the message's BRS bit is set. The TDC mechanism is effective only during the data phase of FD frames having BRS bit set. It has no effect either on non-FD frames, or on FD frames transmitted at normal bit rate. Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com> Link: https://lore.kernel.org/r/20190712075926.7357-7-qiangqing.zhang@nxp.com Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can/flexcan.c')
-rw-r--r--drivers/net/can/flexcan.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index fc0e9d5fd02b..fc98b5d521f2 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -156,6 +156,10 @@
#define FLEXCAN_FDCTRL_MBDSR_12 0x1
#define FLEXCAN_FDCTRL_MBDSR_32 0x2
#define FLEXCAN_FDCTRL_MBDSR_64 0x3
+#define FLEXCAN_FDCTRL_TDCEN BIT(15)
+#define FLEXCAN_FDCTRL_TDCFAIL BIT(14)
+#define FLEXCAN_FDCTRL_TDCOFF GENMASK(12, 8)
+#define FLEXCAN_FDCTRL_TDCVAL GENMASK(5, 0)
/* FLEXCAN FD Bit Timing register (FDCBT) bits */
#define FLEXCAN_FDCBT_FPRESDIV_MASK GENMASK(29, 20)
@@ -1220,11 +1224,24 @@ static void flexcan_set_bittiming_cbt(const struct net_device *dev)
/* FDCTRL */
reg_fdctrl = priv->read(&regs->fdctrl);
- reg_fdctrl &= ~FLEXCAN_FDCTRL_FDRATE;
+ reg_fdctrl &= ~(FLEXCAN_FDCTRL_FDRATE |
+ FIELD_PREP(FLEXCAN_FDCTRL_TDCOFF, 0x1f));
- if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
+ if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
reg_fdctrl |= FLEXCAN_FDCTRL_FDRATE;
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+ /* TDC must be disabled for Loop Back mode */
+ reg_fdctrl &= ~FLEXCAN_FDCTRL_TDCEN;
+ } else {
+ reg_fdctrl |= FLEXCAN_FDCTRL_TDCEN |
+ FIELD_PREP(FLEXCAN_FDCTRL_TDCOFF,
+ ((dbt->phase_seg1 - 1) +
+ dbt->prop_seg + 2) *
+ ((dbt->brp - 1 ) + 1));
+ }
+ }
+
netdev_dbg(dev, "writing fdctrl=0x%08x\n", reg_fdctrl);
priv->write(reg_fdctrl, &regs->fdctrl);