From ad7e288ab2dad6f8a4625852f2bf69fa3da6cb5b Mon Sep 17 00:00:00 2001 From: Henrik Brix Andersen Date: Tue, 19 Oct 2021 14:38:52 +0200 Subject: [PATCH] drivers: can: flexcan: fix timing parameter limits Fix the limits for the timing parameter calculations. The lower limit for the phase_seg2 value is wrongly specified as 1 to 7, but 1U is substracted before writing it to the CTRL1:PSEG2 register field. This results in register field values between 0 and 6, but 0 is an invalid value for the PSEG2 register field. The upper limits for several of the timing parameters are wrong as well, but this does not result in invalid register field values being calculated. It can, however, result in not being able to meet CAN timing requirements. The confusion in specifying the limits likely stems from the timing calculations and timing limits using the "physical" values, whereas the registers fields all use the "physical" value minus 1. When the datasheet says "The valid programmable values are 1-7", the corresponding limits should be set to 2 to 8 to take the "minus 1" into account. Fixes: #39541 Signed-off-by: Henrik Brix Andersen --- drivers/can/can_mcux_flexcan.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/can/can_mcux_flexcan.c b/drivers/can/can_mcux_flexcan.c index 0a1c5172c7231..a54c7f23850b4 100644 --- a/drivers/can/can_mcux_flexcan.c +++ b/drivers/can/can_mcux_flexcan.c @@ -747,19 +747,28 @@ static const struct can_driver_api mcux_flexcan_driver_api = { #endif .register_state_change_isr = mcux_flexcan_register_state_change_isr, .get_core_clock = mcux_flexcan_get_core_clock, + /* + * FlexCAN timing limits are specified in the "FLEXCANx_CTRL1 field + * descriptions" table in the SoC reference manual. + * + * Note that the values here are the "physical" timing limits, whereas + * the register field limits are physical values minus 1 (which is + * handled by the flexcan_config_t field assignments elsewhere in this + * driver). + */ .timing_min = { - .sjw = 0x1, + .sjw = 0x01, .prop_seg = 0x01, .phase_seg1 = 0x01, - .phase_seg2 = 0x01, + .phase_seg2 = 0x02, .prescaler = 0x01 }, .timing_max = { - .sjw = 0x03, - .prop_seg = 0x07, - .phase_seg1 = 0x07, - .phase_seg2 = 0x07, - .prescaler = 0xFF + .sjw = 0x04, + .prop_seg = 0x08, + .phase_seg1 = 0x08, + .phase_seg2 = 0x08, + .prescaler = 0x100 } };