[PATCH 5.18 014/112] can: mcp251xfd: mcp251xfd_regmap_crc_read(): update workaround broken CRC on TBC register

From: Greg Kroah-Hartman
Date: Mon Jul 11 2022 - 05:26:05 EST

From: Thomas Kopp <thomas.kopp@xxxxxxxxxxxxx>

commit e3d4ee7d5f7f5256dfe89219afcc7a2d553b731f upstream.

The mcp251xfd compatible chips have an erratum ([1], [2]), where the
received CRC doesn't match the calculated CRC. In commit
c7eb923c3caf ("can: mcp251xfd: mcp251xfd_regmap_crc_read(): work
around broken CRC on TBC register") the following workaround was

- If a CRC read error on the TBC register is detected and the first
byte is 0x00 or 0x80, the most significant bit of the first 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.

New investigations and simulations indicate that the CRC send by the
device is calculated on correct data, and the data is incorrectly
received by the SPI host controller.

Use flipped instead of original data and update workaround description
in mcp251xfd_regmap_crc_read().

[1] mcp2517fd: DS80000792C: "Incorrect CRC for certain READ_CRC commands"
[2] mcp2518fd: DS80000789C: "Incorrect CRC for certain READ_CRC commands"

Link: https://lore.kernel.org/all/DM4PR11MB53901D49578FE265B239E55AFB7C9@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Fixes: c7eb923c3caf ("can: mcp251xfd: mcp251xfd_regmap_crc_read(): work around broken CRC on TBC register")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Thomas Kopp <thomas.kopp@xxxxxxxxxxxxx>
[mkl: split into 2 patches, update patch description and documentation]
Signed-off-by: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)

--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
@@ -343,9 +343,8 @@ mcp251xfd_regmap_crc_read(void *context,
* 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.
+ * assume for now the CRC operates on the correct
+ * data.
if (reg == MCP251XFD_REG_TBC &&
((buf_rx->data[0] & 0xf8) == 0x0 ||
@@ -359,10 +358,8 @@ mcp251xfd_regmap_crc_read(void *context,
if (!err) {
/* If CRC is now correct, assume
- * transferred data was OK, flip bit
- * back to original value.
+ * flipped data is OK.
- buf_rx->data[0] ^= 0x80;
goto out;