1. Apr 08, 2021
  2. Apr 07, 2021
    • 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