• Marc Kleine-Budde's avatar
    can: mcp251xfd: mcp251xfd_regmap_crc_read(): work around broken CRC on TBC register · c7eb923c
    Marc Kleine-Budde authored
    MCP251XFD_REG_TBC is the time base counter register. It increments
    once per SYS clock tick, which is 20 or 40 MHz. Observation shows that
    if the lowest byte (which is transferred first on the SPI bus) of that
    register is 0x00 or 0x80 the calculated CRC doesn't always match the
    transferred one.
    
    To reproduce this problem let the driver read the TBC register in a
    high frequency. This can be done by attaching only the mcp251xfd CAN
    controller to a valid terminated CAN bus and send a single CAN frame.
    As there are no other CAN controller on the bus, the sent CAN frame is
    not ACKed and the mcp251xfd repeats it. If user space enables the bus
    error reporting, each of the NACK errors is reported with a time
    stamp (which is read from the TBC register) to user space.
    
    $ ip link set can0 down
    $ ip link set can0 up type can bitrate 500000 berr-reporting on
    $ cansend can0 4FF#ff.01.00.00.00.00.00.00
    
    This leads to several error messages per second:
    
    | mcp251xfd spi0.0 can0: CRC read error at address 0x0010 (length=4, data=00 3a 86 da, CRC=0x7753) retrying.
    | mcp251xfd spi0.0 can0: CRC read error at address 0x0010 (length=4, data=80 01 b4 da, CRC=0x5830) retrying.
    | mcp251xfd spi0.0 can0: CRC read error at address 0x0010 (length=4, data=00 e9 23 db, CRC=0xa723) retrying.
    | mcp251xfd spi0.0 can0: CRC read error at address 0x0010 (length=4, data=00 8a 30 db, CRC=0x4a9c) retrying.
    | mcp251xfd spi0.0 can0: CRC read error at address 0x0010 (length=4, data=80 f3 43 db, CRC=0x66d2) retrying.
    
    If the highest bit in the lowest byte is flipped the transferred CRC
    matches the calculated one. We assume for now the CRC calculation in
    the chip works on wrong data and the transferred data is correct.
    
    This patch implements the following workaround:
    
    - If a CRC read error on the TBC register is detected and the lowest
      byte is 0x00 or 0x80, the highest bit of the lowest byte is flipped
      and the CRC is calculated again.
    - If the CRC now matches, the _original_ data is passed to the reader.
      For now we assume transferred data was OK.
    
    Link: https://lore.kernel.org/r/20210406110617.1865592-5-mkl@pengutronix.de
    Cc: Manivannan Sadhasivam <mani@kernel.org>
    Cc: Thomas Kopp <thomas.kopp@microchip.com>
    Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
    c7eb923c
mcp251xfd-regmap.c 15.8 KB