On Wed, Apr 7, 2021 at 1:01 AM Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx> wrote: > > 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@xxxxxxxxxxxxxx > Cc: Manivannan Sadhasivam <mani@xxxxxxxxxx> > Cc: Thomas Kopp <thomas.kopp@xxxxxxxxxxxxx> > Signed-off-by: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx> > --- > .../net/can/spi/mcp251xfd/mcp251xfd-regmap.c | 34 +++++++++++++++++++ > 1 file changed, 34 insertions(+) > > diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c > index 35557ac43c03..297491516a26 100644 > --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c > +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c > @@ -321,6 +321,40 @@ mcp251xfd_regmap_crc_read(void *context, > if (err != -EBADMSG) > return err; > > + /* 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. > + * > + * 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. > + */ > + if (reg == MCP251XFD_REG_TBC && > + (buf_rx->data[0] == 0x0 || buf_rx->data[0] == 0x80)) { > + /* Flip highest bit in lowest byte of le32 */ > + buf_rx->data[0] ^= 0x80; > + > + /* re-check CRC */ > + err = mcp251xfd_regmap_crc_read_check_crc(buf_rx, > + buf_tx, > + val_len); > + if (!err) { > + /* If CRC is now correct, assume > + * transferred data was OK, flip bit > + * back to original value. > + */ > + buf_rx->data[0] ^= 0x80; > + goto out; > + } > + } > + > /* MCP251XFD_REG_OSC is the first ever reg we read from. > * > * The chip may be in deep sleep and this SPI transfer > -- > 2.30.2 > > Hello Marc, I am encountering similar error with the 5.10 raspberrypi kernel on RPi 4 with MCP2518FD: mcp251xfd spi0.0 can0: CRC read error at address 0x0010 (length=4, data=00 ad 58 67, CRC=0xbbfd) retrying Would it be possible for you to pull these patches into a v5.10 branch in your linux-rpi repo [1]? Thanks, Drew [1] https://github.com/marckleinebudde/linux-rpi