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 <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2021-10-19 14:38:52 +02:00 committed by Christopher Friedt
commit 267a83e94b

View file

@ -747,19 +747,28 @@ static const struct can_driver_api mcux_flexcan_driver_api = {
#endif #endif
.register_state_change_isr = mcux_flexcan_register_state_change_isr, .register_state_change_isr = mcux_flexcan_register_state_change_isr,
.get_core_clock = mcux_flexcan_get_core_clock, .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 = { .timing_min = {
.sjw = 0x1, .sjw = 0x01,
.prop_seg = 0x01, .prop_seg = 0x01,
.phase_seg1 = 0x01, .phase_seg1 = 0x01,
.phase_seg2 = 0x01, .phase_seg2 = 0x02,
.prescaler = 0x01 .prescaler = 0x01
}, },
.timing_max = { .timing_max = {
.sjw = 0x03, .sjw = 0x04,
.prop_seg = 0x07, .prop_seg = 0x08,
.phase_seg1 = 0x07, .phase_seg1 = 0x08,
.phase_seg2 = 0x07, .phase_seg2 = 0x08,
.prescaler = 0xFF .prescaler = 0x100
} }
}; };