From 0e0cd2a0d7a0efbdb70e3e829ab6236a7c4acc3c Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Sun, 10 Mar 2024 18:28:18 +0100 Subject: [PATCH] drivers: can: mcan: enable transmitter delay compensation when possible Enable Transmitter Delay Compensation whenever the data phase timing parameters allow it. Fixes: #70447 Signed-off-by: Henrik Brix Andersen (cherry picked from commit bfad7bc00e734010d059d5ba7eb4cd2187eb1c8d) --- drivers/can/can_mcan.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/can/can_mcan.c b/drivers/can/can_mcan.c index a0ae16e0889389..f1df65963f5197 100644 --- a/drivers/can/can_mcan.c +++ b/drivers/can/can_mcan.c @@ -225,8 +225,10 @@ int can_mcan_set_timing(const struct device *dev, const struct can_timing *timin #ifdef CONFIG_CAN_FD_MODE int can_mcan_set_timing_data(const struct device *dev, const struct can_timing *timing_data) { + const uint8_t tdco_max = FIELD_GET(CAN_MCAN_TDCR_TDCO, CAN_MCAN_TDCR_TDCO); struct can_mcan_data *data = dev->data; uint32_t dbtp = 0U; + uint8_t tdco; int err; if (data->started) { @@ -240,6 +242,23 @@ int can_mcan_set_timing_data(const struct device *dev, const struct can_timing * FIELD_PREP(CAN_MCAN_DBTP_DTSEG2, timing_data->phase_seg2 - 1UL) | FIELD_PREP(CAN_MCAN_DBTP_DBRP, timing_data->prescaler - 1UL); + if (timing_data->prescaler == 1U || timing_data->prescaler == 2U) { + /* TDC can only be enabled if DBRP = { 0, 1 } */ + dbtp |= CAN_MCAN_DBTP_TDC; + + /* Set TDC offset for correct location of the Secondary Sample Point (SSP) */ + tdco = CAN_CALC_TDCO(timing_data, 0U, tdco_max); + LOG_DBG("TDC enabled, using TDCO %u", tdco); + + err = can_mcan_write_reg(dev, CAN_MCAN_TDCR, FIELD_PREP(CAN_MCAN_TDCR_TDCO, tdco)); + if (err != 0) { + goto unlock; + } + } else { + LOG_DBG("TDC cannot be enabled, prescaler value %u too high", + timing_data->prescaler); + } + err = can_mcan_write_reg(dev, CAN_MCAN_DBTP, dbtp); if (err != 0) { goto unlock;