1875347feSMarc Kleine-Budde // SPDX-License-Identifier: GPL-2.0 2875347feSMarc Kleine-Budde // 3eb79a267SMarc Kleine-Budde // mcp251xfd - Microchip MCP251xFD Family CAN controller driver 4875347feSMarc Kleine-Budde // 5c912f19eSMarc Kleine-Budde // Copyright (c) 2019, 2020, 2021 Pengutronix, 6875347feSMarc Kleine-Budde // Marc Kleine-Budde <kernel@pengutronix.de> 7875347feSMarc Kleine-Budde // 8875347feSMarc Kleine-Budde 91f0e21a0SMarc Kleine-Budde #include "mcp251xfd.h" 10875347feSMarc Kleine-Budde 11875347feSMarc Kleine-Budde #include <asm/unaligned.h> 12875347feSMarc Kleine-Budde 13eb79a267SMarc Kleine-Budde static const struct regmap_config mcp251xfd_regmap_crc; 14875347feSMarc Kleine-Budde 15875347feSMarc Kleine-Budde static int 16eb79a267SMarc Kleine-Budde mcp251xfd_regmap_nocrc_write(void *context, const void *data, size_t count) 17875347feSMarc Kleine-Budde { 18875347feSMarc Kleine-Budde struct spi_device *spi = context; 19875347feSMarc Kleine-Budde 20875347feSMarc Kleine-Budde return spi_write(spi, data, count); 21875347feSMarc Kleine-Budde } 22875347feSMarc Kleine-Budde 23875347feSMarc Kleine-Budde static int 24eb79a267SMarc Kleine-Budde mcp251xfd_regmap_nocrc_gather_write(void *context, 25875347feSMarc Kleine-Budde const void *reg, size_t reg_len, 26875347feSMarc Kleine-Budde const void *val, size_t val_len) 27875347feSMarc Kleine-Budde { 28875347feSMarc Kleine-Budde struct spi_device *spi = context; 29eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = spi_get_drvdata(spi); 30eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx; 31875347feSMarc Kleine-Budde struct spi_transfer xfer[] = { 32875347feSMarc Kleine-Budde { 33875347feSMarc Kleine-Budde .tx_buf = buf_tx, 34875347feSMarc Kleine-Budde .len = sizeof(buf_tx->cmd) + val_len, 35875347feSMarc Kleine-Budde }, 36875347feSMarc Kleine-Budde }; 37875347feSMarc Kleine-Budde 38875347feSMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16)); 39875347feSMarc Kleine-Budde 40eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) && 41875347feSMarc Kleine-Budde reg_len != sizeof(buf_tx->cmd.cmd)) 42875347feSMarc Kleine-Budde return -EINVAL; 43875347feSMarc Kleine-Budde 44875347feSMarc Kleine-Budde memcpy(&buf_tx->cmd, reg, sizeof(buf_tx->cmd)); 45875347feSMarc Kleine-Budde memcpy(buf_tx->data, val, val_len); 46875347feSMarc Kleine-Budde 47875347feSMarc Kleine-Budde return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); 48875347feSMarc Kleine-Budde } 49875347feSMarc Kleine-Budde 50c912f19eSMarc Kleine-Budde static inline bool 51c912f19eSMarc Kleine-Budde mcp251xfd_update_bits_read_reg(const struct mcp251xfd_priv *priv, 52c912f19eSMarc Kleine-Budde unsigned int reg) 53875347feSMarc Kleine-Budde { 54c912f19eSMarc Kleine-Budde struct mcp251xfd_rx_ring *ring; 55c912f19eSMarc Kleine-Budde int n; 56c912f19eSMarc Kleine-Budde 57875347feSMarc Kleine-Budde switch (reg) { 58eb79a267SMarc Kleine-Budde case MCP251XFD_REG_INT: 59eb79a267SMarc Kleine-Budde case MCP251XFD_REG_TEFCON: 60eb79a267SMarc Kleine-Budde case MCP251XFD_REG_FLTCON(0): 61eb79a267SMarc Kleine-Budde case MCP251XFD_REG_ECCSTAT: 62eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CRC: 63875347feSMarc Kleine-Budde return false; 64eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON: 65eb79a267SMarc Kleine-Budde case MCP251XFD_REG_OSC: 66eb79a267SMarc Kleine-Budde case MCP251XFD_REG_ECCCON: 67875347feSMarc Kleine-Budde return true; 68875347feSMarc Kleine-Budde default: 69c912f19eSMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, ring, n) { 70c912f19eSMarc Kleine-Budde if (reg == MCP251XFD_REG_FIFOCON(ring->fifo_nr)) 71c912f19eSMarc Kleine-Budde return false; 72c912f19eSMarc Kleine-Budde if (reg == MCP251XFD_REG_FIFOSTA(ring->fifo_nr)) 73c912f19eSMarc Kleine-Budde return true; 74c912f19eSMarc Kleine-Budde } 75c912f19eSMarc Kleine-Budde 76875347feSMarc Kleine-Budde WARN(1, "Status of reg 0x%04x unknown.\n", reg); 77875347feSMarc Kleine-Budde } 78875347feSMarc Kleine-Budde 79875347feSMarc Kleine-Budde return true; 80875347feSMarc Kleine-Budde } 81875347feSMarc Kleine-Budde 82875347feSMarc Kleine-Budde static int 83eb79a267SMarc Kleine-Budde mcp251xfd_regmap_nocrc_update_bits(void *context, unsigned int reg, 84875347feSMarc Kleine-Budde unsigned int mask, unsigned int val) 85875347feSMarc Kleine-Budde { 86875347feSMarc Kleine-Budde struct spi_device *spi = context; 87eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = spi_get_drvdata(spi); 88eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_rx = priv->map_buf_nocrc_rx; 89eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx; 90875347feSMarc Kleine-Budde __le32 orig_le32 = 0, mask_le32, val_le32, tmp_le32; 91875347feSMarc Kleine-Budde u8 first_byte, last_byte, len; 92875347feSMarc Kleine-Budde int err; 93875347feSMarc Kleine-Budde 94875347feSMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16)); 95875347feSMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16)); 96875347feSMarc Kleine-Budde 97eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) && 98875347feSMarc Kleine-Budde mask == 0) 99875347feSMarc Kleine-Budde return -EINVAL; 100875347feSMarc Kleine-Budde 101eb79a267SMarc Kleine-Budde first_byte = mcp251xfd_first_byte_set(mask); 102eb79a267SMarc Kleine-Budde last_byte = mcp251xfd_last_byte_set(mask); 103875347feSMarc Kleine-Budde len = last_byte - first_byte + 1; 104875347feSMarc Kleine-Budde 105c912f19eSMarc Kleine-Budde if (mcp251xfd_update_bits_read_reg(priv, reg)) { 106875347feSMarc Kleine-Budde struct spi_transfer xfer[2] = { }; 107875347feSMarc Kleine-Budde struct spi_message msg; 108875347feSMarc Kleine-Budde 109875347feSMarc Kleine-Budde spi_message_init(&msg); 110875347feSMarc Kleine-Budde spi_message_add_tail(&xfer[0], &msg); 111875347feSMarc Kleine-Budde 112eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) { 113875347feSMarc Kleine-Budde xfer[0].tx_buf = buf_tx; 114875347feSMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd); 115875347feSMarc Kleine-Budde 116875347feSMarc Kleine-Budde xfer[1].rx_buf = buf_rx->data; 117875347feSMarc Kleine-Budde xfer[1].len = len; 118875347feSMarc Kleine-Budde spi_message_add_tail(&xfer[1], &msg); 119875347feSMarc Kleine-Budde } else { 120875347feSMarc Kleine-Budde xfer[0].tx_buf = buf_tx; 121875347feSMarc Kleine-Budde xfer[0].rx_buf = buf_rx; 122875347feSMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd) + len; 123875347feSMarc Kleine-Budde 124eb79a267SMarc Kleine-Budde if (MCP251XFD_SANITIZE_SPI) 125875347feSMarc Kleine-Budde memset(buf_tx->data, 0x0, len); 126875347feSMarc Kleine-Budde } 127875347feSMarc Kleine-Budde 128eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, reg + first_byte); 129875347feSMarc Kleine-Budde err = spi_sync(spi, &msg); 130875347feSMarc Kleine-Budde if (err) 131875347feSMarc Kleine-Budde return err; 132875347feSMarc Kleine-Budde 133875347feSMarc Kleine-Budde memcpy(&orig_le32, buf_rx->data, len); 134875347feSMarc Kleine-Budde } 135875347feSMarc Kleine-Budde 136875347feSMarc Kleine-Budde mask_le32 = cpu_to_le32(mask >> BITS_PER_BYTE * first_byte); 137875347feSMarc Kleine-Budde val_le32 = cpu_to_le32(val >> BITS_PER_BYTE * first_byte); 138875347feSMarc Kleine-Budde 139875347feSMarc Kleine-Budde tmp_le32 = orig_le32 & ~mask_le32; 140875347feSMarc Kleine-Budde tmp_le32 |= val_le32 & mask_le32; 141875347feSMarc Kleine-Budde 142eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_write_nocrc(&buf_tx->cmd, reg + first_byte); 143875347feSMarc Kleine-Budde memcpy(buf_tx->data, &tmp_le32, len); 144875347feSMarc Kleine-Budde 145875347feSMarc Kleine-Budde return spi_write(spi, buf_tx, sizeof(buf_tx->cmd) + len); 146875347feSMarc Kleine-Budde } 147875347feSMarc Kleine-Budde 148875347feSMarc Kleine-Budde static int 149eb79a267SMarc Kleine-Budde mcp251xfd_regmap_nocrc_read(void *context, 150875347feSMarc Kleine-Budde const void *reg, size_t reg_len, 151875347feSMarc Kleine-Budde void *val_buf, size_t val_len) 152875347feSMarc Kleine-Budde { 153875347feSMarc Kleine-Budde struct spi_device *spi = context; 154eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = spi_get_drvdata(spi); 155eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_rx = priv->map_buf_nocrc_rx; 156eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx; 157875347feSMarc Kleine-Budde struct spi_transfer xfer[2] = { }; 158875347feSMarc Kleine-Budde struct spi_message msg; 159875347feSMarc Kleine-Budde int err; 160875347feSMarc Kleine-Budde 161875347feSMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16)); 162875347feSMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16)); 163875347feSMarc Kleine-Budde 164eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) && 165875347feSMarc Kleine-Budde reg_len != sizeof(buf_tx->cmd.cmd)) 166875347feSMarc Kleine-Budde return -EINVAL; 167875347feSMarc Kleine-Budde 168875347feSMarc Kleine-Budde spi_message_init(&msg); 169875347feSMarc Kleine-Budde spi_message_add_tail(&xfer[0], &msg); 170875347feSMarc Kleine-Budde 171eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) { 172875347feSMarc Kleine-Budde xfer[0].tx_buf = reg; 173875347feSMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd); 174875347feSMarc Kleine-Budde 175875347feSMarc Kleine-Budde xfer[1].rx_buf = val_buf; 176875347feSMarc Kleine-Budde xfer[1].len = val_len; 177875347feSMarc Kleine-Budde spi_message_add_tail(&xfer[1], &msg); 178875347feSMarc Kleine-Budde } else { 179875347feSMarc Kleine-Budde xfer[0].tx_buf = buf_tx; 180875347feSMarc Kleine-Budde xfer[0].rx_buf = buf_rx; 181875347feSMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd) + val_len; 182875347feSMarc Kleine-Budde 183875347feSMarc Kleine-Budde memcpy(&buf_tx->cmd, reg, sizeof(buf_tx->cmd)); 184eb79a267SMarc Kleine-Budde if (MCP251XFD_SANITIZE_SPI) 185875347feSMarc Kleine-Budde memset(buf_tx->data, 0x0, val_len); 186da623840Skernel test robot } 187875347feSMarc Kleine-Budde 188875347feSMarc Kleine-Budde err = spi_sync(spi, &msg); 189875347feSMarc Kleine-Budde if (err) 190875347feSMarc Kleine-Budde return err; 191875347feSMarc Kleine-Budde 192eb79a267SMarc Kleine-Budde if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX)) 193875347feSMarc Kleine-Budde memcpy(val_buf, buf_rx->data, val_len); 194875347feSMarc Kleine-Budde 195875347feSMarc Kleine-Budde return 0; 196875347feSMarc Kleine-Budde } 197875347feSMarc Kleine-Budde 198875347feSMarc Kleine-Budde static int 199eb79a267SMarc Kleine-Budde mcp251xfd_regmap_crc_gather_write(void *context, 200875347feSMarc Kleine-Budde const void *reg_p, size_t reg_len, 201875347feSMarc Kleine-Budde const void *val, size_t val_len) 202875347feSMarc Kleine-Budde { 203875347feSMarc Kleine-Budde struct spi_device *spi = context; 204eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = spi_get_drvdata(spi); 205eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_crc *buf_tx = priv->map_buf_crc_tx; 206875347feSMarc Kleine-Budde struct spi_transfer xfer[] = { 207875347feSMarc Kleine-Budde { 208875347feSMarc Kleine-Budde .tx_buf = buf_tx, 209875347feSMarc Kleine-Budde .len = sizeof(buf_tx->cmd) + val_len + 210875347feSMarc Kleine-Budde sizeof(buf_tx->crc), 211875347feSMarc Kleine-Budde }, 212875347feSMarc Kleine-Budde }; 213875347feSMarc Kleine-Budde u16 reg = *(u16 *)reg_p; 214875347feSMarc Kleine-Budde u16 crc; 215875347feSMarc Kleine-Budde 216875347feSMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16) + sizeof(u8)); 217875347feSMarc Kleine-Budde 218eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) && 219875347feSMarc Kleine-Budde reg_len != sizeof(buf_tx->cmd.cmd) + 220eb79a267SMarc Kleine-Budde mcp251xfd_regmap_crc.pad_bits / BITS_PER_BYTE) 221875347feSMarc Kleine-Budde return -EINVAL; 222875347feSMarc Kleine-Budde 223eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_write_crc(&buf_tx->cmd, reg, val_len); 224875347feSMarc Kleine-Budde memcpy(buf_tx->data, val, val_len); 225875347feSMarc Kleine-Budde 226eb79a267SMarc Kleine-Budde crc = mcp251xfd_crc16_compute(buf_tx, sizeof(buf_tx->cmd) + val_len); 227875347feSMarc Kleine-Budde put_unaligned_be16(crc, buf_tx->data + val_len); 228875347feSMarc Kleine-Budde 229875347feSMarc Kleine-Budde return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); 230875347feSMarc Kleine-Budde } 231875347feSMarc Kleine-Budde 232875347feSMarc Kleine-Budde static int 233eb79a267SMarc Kleine-Budde mcp251xfd_regmap_crc_write(void *context, 234875347feSMarc Kleine-Budde const void *data, size_t count) 235875347feSMarc Kleine-Budde { 236875347feSMarc Kleine-Budde const size_t data_offset = sizeof(__be16) + 237eb79a267SMarc Kleine-Budde mcp251xfd_regmap_crc.pad_bits / BITS_PER_BYTE; 238875347feSMarc Kleine-Budde 239eb79a267SMarc Kleine-Budde return mcp251xfd_regmap_crc_gather_write(context, 240875347feSMarc Kleine-Budde data, data_offset, 241875347feSMarc Kleine-Budde data + data_offset, 242875347feSMarc Kleine-Budde count - data_offset); 243875347feSMarc Kleine-Budde } 244875347feSMarc Kleine-Budde 245875347feSMarc Kleine-Budde static int 246ef7a8c3eSMarc Kleine-Budde mcp251xfd_regmap_crc_read_check_crc(const struct mcp251xfd_map_buf_crc * const buf_rx, 247ef7a8c3eSMarc Kleine-Budde const struct mcp251xfd_map_buf_crc * const buf_tx, 248ef7a8c3eSMarc Kleine-Budde unsigned int data_len) 249875347feSMarc Kleine-Budde { 250875347feSMarc Kleine-Budde u16 crc_received, crc_calculated; 251875347feSMarc Kleine-Budde 252875347feSMarc Kleine-Budde crc_received = get_unaligned_be16(buf_rx->data + data_len); 253eb79a267SMarc Kleine-Budde crc_calculated = mcp251xfd_crc16_compute2(&buf_tx->cmd, 254875347feSMarc Kleine-Budde sizeof(buf_tx->cmd), 255875347feSMarc Kleine-Budde buf_rx->data, 256875347feSMarc Kleine-Budde data_len); 257875347feSMarc Kleine-Budde if (crc_received != crc_calculated) 258875347feSMarc Kleine-Budde return -EBADMSG; 259875347feSMarc Kleine-Budde 260875347feSMarc Kleine-Budde return 0; 261875347feSMarc Kleine-Budde } 262875347feSMarc Kleine-Budde 263ef7a8c3eSMarc Kleine-Budde static int 264ef7a8c3eSMarc Kleine-Budde mcp251xfd_regmap_crc_read_one(struct mcp251xfd_priv *priv, 265ef7a8c3eSMarc Kleine-Budde struct spi_message *msg, unsigned int data_len) 266ef7a8c3eSMarc Kleine-Budde { 267ef7a8c3eSMarc Kleine-Budde const struct mcp251xfd_map_buf_crc *buf_rx = priv->map_buf_crc_rx; 268ef7a8c3eSMarc Kleine-Budde const struct mcp251xfd_map_buf_crc *buf_tx = priv->map_buf_crc_tx; 269ef7a8c3eSMarc Kleine-Budde int err; 270ef7a8c3eSMarc Kleine-Budde 271ef7a8c3eSMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16) + sizeof(u8)); 272ef7a8c3eSMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16) + sizeof(u8)); 273ef7a8c3eSMarc Kleine-Budde 274ef7a8c3eSMarc Kleine-Budde err = spi_sync(priv->spi, msg); 275ef7a8c3eSMarc Kleine-Budde if (err) 276ef7a8c3eSMarc Kleine-Budde return err; 277ef7a8c3eSMarc Kleine-Budde 278ef7a8c3eSMarc Kleine-Budde return mcp251xfd_regmap_crc_read_check_crc(buf_rx, buf_tx, data_len); 279ef7a8c3eSMarc Kleine-Budde } 280ef7a8c3eSMarc Kleine-Budde 281875347feSMarc Kleine-Budde static int 282eb79a267SMarc Kleine-Budde mcp251xfd_regmap_crc_read(void *context, 283875347feSMarc Kleine-Budde const void *reg_p, size_t reg_len, 284875347feSMarc Kleine-Budde void *val_buf, size_t val_len) 285875347feSMarc Kleine-Budde { 286875347feSMarc Kleine-Budde struct spi_device *spi = context; 287eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = spi_get_drvdata(spi); 288eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_crc *buf_rx = priv->map_buf_crc_rx; 289eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_crc *buf_tx = priv->map_buf_crc_tx; 290875347feSMarc Kleine-Budde struct spi_transfer xfer[2] = { }; 291875347feSMarc Kleine-Budde struct spi_message msg; 292875347feSMarc Kleine-Budde u16 reg = *(u16 *)reg_p; 293875347feSMarc Kleine-Budde int i, err; 294875347feSMarc Kleine-Budde 295875347feSMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16) + sizeof(u8)); 296875347feSMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16) + sizeof(u8)); 297875347feSMarc Kleine-Budde 298eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) && 299875347feSMarc Kleine-Budde reg_len != sizeof(buf_tx->cmd.cmd) + 300eb79a267SMarc Kleine-Budde mcp251xfd_regmap_crc.pad_bits / BITS_PER_BYTE) 301875347feSMarc Kleine-Budde return -EINVAL; 302875347feSMarc Kleine-Budde 303875347feSMarc Kleine-Budde spi_message_init(&msg); 304875347feSMarc Kleine-Budde spi_message_add_tail(&xfer[0], &msg); 305875347feSMarc Kleine-Budde 306eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) { 307875347feSMarc Kleine-Budde xfer[0].tx_buf = buf_tx; 308875347feSMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd); 309875347feSMarc Kleine-Budde 310875347feSMarc Kleine-Budde xfer[1].rx_buf = buf_rx->data; 311875347feSMarc Kleine-Budde xfer[1].len = val_len + sizeof(buf_tx->crc); 312875347feSMarc Kleine-Budde spi_message_add_tail(&xfer[1], &msg); 313875347feSMarc Kleine-Budde } else { 314875347feSMarc Kleine-Budde xfer[0].tx_buf = buf_tx; 315875347feSMarc Kleine-Budde xfer[0].rx_buf = buf_rx; 316875347feSMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd) + val_len + 317875347feSMarc Kleine-Budde sizeof(buf_tx->crc); 318875347feSMarc Kleine-Budde 319eb79a267SMarc Kleine-Budde if (MCP251XFD_SANITIZE_SPI) 320875347feSMarc Kleine-Budde memset(buf_tx->data, 0x0, val_len + 321875347feSMarc Kleine-Budde sizeof(buf_tx->crc)); 322875347feSMarc Kleine-Budde } 323875347feSMarc Kleine-Budde 324eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_read_crc(&buf_tx->cmd, reg, val_len); 325875347feSMarc Kleine-Budde 326eb79a267SMarc Kleine-Budde for (i = 0; i < MCP251XFD_READ_CRC_RETRIES_MAX; i++) { 327eb79a267SMarc Kleine-Budde err = mcp251xfd_regmap_crc_read_one(priv, &msg, val_len); 328875347feSMarc Kleine-Budde if (!err) 329875347feSMarc Kleine-Budde goto out; 330875347feSMarc Kleine-Budde if (err != -EBADMSG) 331875347feSMarc Kleine-Budde return err; 332875347feSMarc Kleine-Budde 333c7eb923cSMarc Kleine-Budde /* MCP251XFD_REG_TBC is the time base counter 334c7eb923cSMarc Kleine-Budde * register. It increments once per SYS clock tick, 335c7eb923cSMarc Kleine-Budde * which is 20 or 40 MHz. 336c7eb923cSMarc Kleine-Budde * 337c7eb923cSMarc Kleine-Budde * Observation shows that if the lowest byte (which is 338c7eb923cSMarc Kleine-Budde * transferred first on the SPI bus) of that register 339c7eb923cSMarc Kleine-Budde * is 0x00 or 0x80 the calculated CRC doesn't always 340c7eb923cSMarc Kleine-Budde * match the transferred one. 341c7eb923cSMarc Kleine-Budde * 342c7eb923cSMarc Kleine-Budde * If the highest bit in the lowest byte is flipped 343c7eb923cSMarc Kleine-Budde * the transferred CRC matches the calculated one. We 344c7eb923cSMarc Kleine-Budde * assume for now the CRC calculation in the chip 345c7eb923cSMarc Kleine-Budde * works on wrong data and the transferred data is 346c7eb923cSMarc Kleine-Budde * correct. 347c7eb923cSMarc Kleine-Budde */ 348c7eb923cSMarc Kleine-Budde if (reg == MCP251XFD_REG_TBC && 349c7eb923cSMarc Kleine-Budde (buf_rx->data[0] == 0x0 || buf_rx->data[0] == 0x80)) { 350c7eb923cSMarc Kleine-Budde /* Flip highest bit in lowest byte of le32 */ 351c7eb923cSMarc Kleine-Budde buf_rx->data[0] ^= 0x80; 352c7eb923cSMarc Kleine-Budde 353c7eb923cSMarc Kleine-Budde /* re-check CRC */ 354c7eb923cSMarc Kleine-Budde err = mcp251xfd_regmap_crc_read_check_crc(buf_rx, 355c7eb923cSMarc Kleine-Budde buf_tx, 356c7eb923cSMarc Kleine-Budde val_len); 357c7eb923cSMarc Kleine-Budde if (!err) { 358c7eb923cSMarc Kleine-Budde /* If CRC is now correct, assume 359c7eb923cSMarc Kleine-Budde * transferred data was OK, flip bit 360c7eb923cSMarc Kleine-Budde * back to original value. 361c7eb923cSMarc Kleine-Budde */ 362c7eb923cSMarc Kleine-Budde buf_rx->data[0] ^= 0x80; 363c7eb923cSMarc Kleine-Budde goto out; 364c7eb923cSMarc Kleine-Budde } 365c7eb923cSMarc Kleine-Budde } 366c7eb923cSMarc Kleine-Budde 367eb79a267SMarc Kleine-Budde /* MCP251XFD_REG_OSC is the first ever reg we read from. 368875347feSMarc Kleine-Budde * 369875347feSMarc Kleine-Budde * The chip may be in deep sleep and this SPI transfer 370875347feSMarc Kleine-Budde * (i.e. the assertion of the CS) will wake the chip 371875347feSMarc Kleine-Budde * up. This takes about 3ms. The CRC of this transfer 372875347feSMarc Kleine-Budde * is wrong. 373875347feSMarc Kleine-Budde * 374875347feSMarc Kleine-Budde * Or there isn't a chip at all, in this case the CRC 375875347feSMarc Kleine-Budde * will be wrong, too. 376875347feSMarc Kleine-Budde * 377875347feSMarc Kleine-Budde * In both cases ignore the CRC and copy the read data 378875347feSMarc Kleine-Budde * to the caller. It will take care of both cases. 379875347feSMarc Kleine-Budde * 380875347feSMarc Kleine-Budde */ 38125386c9aSMarc Kleine-Budde if (reg == MCP251XFD_REG_OSC && val_len == sizeof(__le32)) { 382875347feSMarc Kleine-Budde err = 0; 383875347feSMarc Kleine-Budde goto out; 384875347feSMarc Kleine-Budde } 385875347feSMarc Kleine-Budde 386b4728920SMarc Kleine-Budde netdev_info(priv->ndev, 387875347feSMarc Kleine-Budde "CRC read error at address 0x%04x (length=%zd, data=%*ph, CRC=0x%04x) retrying.\n", 388875347feSMarc Kleine-Budde reg, val_len, (int)val_len, buf_rx->data, 389875347feSMarc Kleine-Budde get_unaligned_be16(buf_rx->data + val_len)); 390875347feSMarc Kleine-Budde } 391875347feSMarc Kleine-Budde 392875347feSMarc Kleine-Budde if (err) { 393b4728920SMarc Kleine-Budde netdev_err(priv->ndev, 394875347feSMarc Kleine-Budde "CRC read error at address 0x%04x (length=%zd, data=%*ph, CRC=0x%04x).\n", 395875347feSMarc Kleine-Budde reg, val_len, (int)val_len, buf_rx->data, 396875347feSMarc Kleine-Budde get_unaligned_be16(buf_rx->data + val_len)); 397875347feSMarc Kleine-Budde 398875347feSMarc Kleine-Budde return err; 399875347feSMarc Kleine-Budde } 400875347feSMarc Kleine-Budde out: 401875347feSMarc Kleine-Budde memcpy(val_buf, buf_rx->data, val_len); 402875347feSMarc Kleine-Budde 403875347feSMarc Kleine-Budde return 0; 404875347feSMarc Kleine-Budde } 405875347feSMarc Kleine-Budde 406eb79a267SMarc Kleine-Budde static const struct regmap_range mcp251xfd_reg_table_yes_range[] = { 407875347feSMarc Kleine-Budde regmap_reg_range(0x000, 0x2ec), /* CAN FD Controller Module SFR */ 408875347feSMarc Kleine-Budde regmap_reg_range(0x400, 0xbfc), /* RAM */ 409875347feSMarc Kleine-Budde regmap_reg_range(0xe00, 0xe14), /* MCP2517/18FD SFR */ 410875347feSMarc Kleine-Budde }; 411875347feSMarc Kleine-Budde 412eb79a267SMarc Kleine-Budde static const struct regmap_access_table mcp251xfd_reg_table = { 413eb79a267SMarc Kleine-Budde .yes_ranges = mcp251xfd_reg_table_yes_range, 414eb79a267SMarc Kleine-Budde .n_yes_ranges = ARRAY_SIZE(mcp251xfd_reg_table_yes_range), 415875347feSMarc Kleine-Budde }; 416875347feSMarc Kleine-Budde 417eb79a267SMarc Kleine-Budde static const struct regmap_config mcp251xfd_regmap_nocrc = { 418875347feSMarc Kleine-Budde .name = "nocrc", 419875347feSMarc Kleine-Budde .reg_bits = 16, 420875347feSMarc Kleine-Budde .reg_stride = 4, 421875347feSMarc Kleine-Budde .pad_bits = 0, 422875347feSMarc Kleine-Budde .val_bits = 32, 423875347feSMarc Kleine-Budde .max_register = 0xffc, 424eb79a267SMarc Kleine-Budde .wr_table = &mcp251xfd_reg_table, 425eb79a267SMarc Kleine-Budde .rd_table = &mcp251xfd_reg_table, 426875347feSMarc Kleine-Budde .cache_type = REGCACHE_NONE, 427875347feSMarc Kleine-Budde .read_flag_mask = (__force unsigned long) 428eb79a267SMarc Kleine-Budde cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_READ), 429875347feSMarc Kleine-Budde .write_flag_mask = (__force unsigned long) 430eb79a267SMarc Kleine-Budde cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_WRITE), 431875347feSMarc Kleine-Budde }; 432875347feSMarc Kleine-Budde 433eb79a267SMarc Kleine-Budde static const struct regmap_bus mcp251xfd_bus_nocrc = { 434eb79a267SMarc Kleine-Budde .write = mcp251xfd_regmap_nocrc_write, 435eb79a267SMarc Kleine-Budde .gather_write = mcp251xfd_regmap_nocrc_gather_write, 436eb79a267SMarc Kleine-Budde .reg_update_bits = mcp251xfd_regmap_nocrc_update_bits, 437eb79a267SMarc Kleine-Budde .read = mcp251xfd_regmap_nocrc_read, 438875347feSMarc Kleine-Budde .reg_format_endian_default = REGMAP_ENDIAN_BIG, 439875347feSMarc Kleine-Budde .val_format_endian_default = REGMAP_ENDIAN_LITTLE, 440eb79a267SMarc Kleine-Budde .max_raw_read = sizeof_field(struct mcp251xfd_map_buf_nocrc, data), 441eb79a267SMarc Kleine-Budde .max_raw_write = sizeof_field(struct mcp251xfd_map_buf_nocrc, data), 442875347feSMarc Kleine-Budde }; 443875347feSMarc Kleine-Budde 444eb79a267SMarc Kleine-Budde static const struct regmap_config mcp251xfd_regmap_crc = { 445875347feSMarc Kleine-Budde .name = "crc", 446875347feSMarc Kleine-Budde .reg_bits = 16, 447875347feSMarc Kleine-Budde .reg_stride = 4, 448875347feSMarc Kleine-Budde .pad_bits = 16, /* keep data bits aligned */ 449875347feSMarc Kleine-Budde .val_bits = 32, 450875347feSMarc Kleine-Budde .max_register = 0xffc, 451eb79a267SMarc Kleine-Budde .wr_table = &mcp251xfd_reg_table, 452eb79a267SMarc Kleine-Budde .rd_table = &mcp251xfd_reg_table, 453875347feSMarc Kleine-Budde .cache_type = REGCACHE_NONE, 454875347feSMarc Kleine-Budde }; 455875347feSMarc Kleine-Budde 456eb79a267SMarc Kleine-Budde static const struct regmap_bus mcp251xfd_bus_crc = { 457eb79a267SMarc Kleine-Budde .write = mcp251xfd_regmap_crc_write, 458eb79a267SMarc Kleine-Budde .gather_write = mcp251xfd_regmap_crc_gather_write, 459eb79a267SMarc Kleine-Budde .read = mcp251xfd_regmap_crc_read, 460875347feSMarc Kleine-Budde .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, 461875347feSMarc Kleine-Budde .val_format_endian_default = REGMAP_ENDIAN_LITTLE, 462eb79a267SMarc Kleine-Budde .max_raw_read = sizeof_field(struct mcp251xfd_map_buf_crc, data), 463eb79a267SMarc Kleine-Budde .max_raw_write = sizeof_field(struct mcp251xfd_map_buf_crc, data), 464875347feSMarc Kleine-Budde }; 465875347feSMarc Kleine-Budde 466875347feSMarc Kleine-Budde static inline bool 467eb79a267SMarc Kleine-Budde mcp251xfd_regmap_use_nocrc(struct mcp251xfd_priv *priv) 468875347feSMarc Kleine-Budde { 469eb79a267SMarc Kleine-Budde return (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG)) || 470eb79a267SMarc Kleine-Budde (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX)); 471875347feSMarc Kleine-Budde } 472875347feSMarc Kleine-Budde 473875347feSMarc Kleine-Budde static inline bool 474eb79a267SMarc Kleine-Budde mcp251xfd_regmap_use_crc(struct mcp251xfd_priv *priv) 475875347feSMarc Kleine-Budde { 476eb79a267SMarc Kleine-Budde return (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) || 477eb79a267SMarc Kleine-Budde (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX); 478875347feSMarc Kleine-Budde } 479875347feSMarc Kleine-Budde 480875347feSMarc Kleine-Budde static int 481eb79a267SMarc Kleine-Budde mcp251xfd_regmap_init_nocrc(struct mcp251xfd_priv *priv) 482875347feSMarc Kleine-Budde { 483875347feSMarc Kleine-Budde if (!priv->map_nocrc) { 484875347feSMarc Kleine-Budde struct regmap *map; 485875347feSMarc Kleine-Budde 486eb79a267SMarc Kleine-Budde map = devm_regmap_init(&priv->spi->dev, &mcp251xfd_bus_nocrc, 487eb79a267SMarc Kleine-Budde priv->spi, &mcp251xfd_regmap_nocrc); 488875347feSMarc Kleine-Budde if (IS_ERR(map)) 489875347feSMarc Kleine-Budde return PTR_ERR(map); 490875347feSMarc Kleine-Budde 491875347feSMarc Kleine-Budde priv->map_nocrc = map; 492875347feSMarc Kleine-Budde } 493875347feSMarc Kleine-Budde 494875347feSMarc Kleine-Budde if (!priv->map_buf_nocrc_rx) { 495875347feSMarc Kleine-Budde priv->map_buf_nocrc_rx = 496875347feSMarc Kleine-Budde devm_kzalloc(&priv->spi->dev, 497875347feSMarc Kleine-Budde sizeof(*priv->map_buf_nocrc_rx), 498875347feSMarc Kleine-Budde GFP_KERNEL); 499875347feSMarc Kleine-Budde if (!priv->map_buf_nocrc_rx) 500875347feSMarc Kleine-Budde return -ENOMEM; 501875347feSMarc Kleine-Budde } 502875347feSMarc Kleine-Budde 503875347feSMarc Kleine-Budde if (!priv->map_buf_nocrc_tx) { 504875347feSMarc Kleine-Budde priv->map_buf_nocrc_tx = 505875347feSMarc Kleine-Budde devm_kzalloc(&priv->spi->dev, 506875347feSMarc Kleine-Budde sizeof(*priv->map_buf_nocrc_tx), 507875347feSMarc Kleine-Budde GFP_KERNEL); 508875347feSMarc Kleine-Budde if (!priv->map_buf_nocrc_tx) 509875347feSMarc Kleine-Budde return -ENOMEM; 510875347feSMarc Kleine-Budde } 511875347feSMarc Kleine-Budde 512eb79a267SMarc Kleine-Budde if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG)) 513875347feSMarc Kleine-Budde priv->map_reg = priv->map_nocrc; 514875347feSMarc Kleine-Budde 515eb79a267SMarc Kleine-Budde if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX)) 516875347feSMarc Kleine-Budde priv->map_rx = priv->map_nocrc; 517875347feSMarc Kleine-Budde 518875347feSMarc Kleine-Budde return 0; 519875347feSMarc Kleine-Budde } 520875347feSMarc Kleine-Budde 521eb79a267SMarc Kleine-Budde static void mcp251xfd_regmap_destroy_nocrc(struct mcp251xfd_priv *priv) 522875347feSMarc Kleine-Budde { 523875347feSMarc Kleine-Budde if (priv->map_buf_nocrc_rx) { 524875347feSMarc Kleine-Budde devm_kfree(&priv->spi->dev, priv->map_buf_nocrc_rx); 525875347feSMarc Kleine-Budde priv->map_buf_nocrc_rx = NULL; 526875347feSMarc Kleine-Budde } 527875347feSMarc Kleine-Budde if (priv->map_buf_nocrc_tx) { 528875347feSMarc Kleine-Budde devm_kfree(&priv->spi->dev, priv->map_buf_nocrc_tx); 529875347feSMarc Kleine-Budde priv->map_buf_nocrc_tx = NULL; 530875347feSMarc Kleine-Budde } 531875347feSMarc Kleine-Budde } 532875347feSMarc Kleine-Budde 533875347feSMarc Kleine-Budde static int 534eb79a267SMarc Kleine-Budde mcp251xfd_regmap_init_crc(struct mcp251xfd_priv *priv) 535875347feSMarc Kleine-Budde { 536875347feSMarc Kleine-Budde if (!priv->map_crc) { 537875347feSMarc Kleine-Budde struct regmap *map; 538875347feSMarc Kleine-Budde 539eb79a267SMarc Kleine-Budde map = devm_regmap_init(&priv->spi->dev, &mcp251xfd_bus_crc, 540eb79a267SMarc Kleine-Budde priv->spi, &mcp251xfd_regmap_crc); 541875347feSMarc Kleine-Budde if (IS_ERR(map)) 542875347feSMarc Kleine-Budde return PTR_ERR(map); 543875347feSMarc Kleine-Budde 544875347feSMarc Kleine-Budde priv->map_crc = map; 545875347feSMarc Kleine-Budde } 546875347feSMarc Kleine-Budde 547875347feSMarc Kleine-Budde if (!priv->map_buf_crc_rx) { 548875347feSMarc Kleine-Budde priv->map_buf_crc_rx = 549875347feSMarc Kleine-Budde devm_kzalloc(&priv->spi->dev, 550875347feSMarc Kleine-Budde sizeof(*priv->map_buf_crc_rx), 551875347feSMarc Kleine-Budde GFP_KERNEL); 552875347feSMarc Kleine-Budde if (!priv->map_buf_crc_rx) 553875347feSMarc Kleine-Budde return -ENOMEM; 554875347feSMarc Kleine-Budde } 555875347feSMarc Kleine-Budde 556875347feSMarc Kleine-Budde if (!priv->map_buf_crc_tx) { 557875347feSMarc Kleine-Budde priv->map_buf_crc_tx = 558875347feSMarc Kleine-Budde devm_kzalloc(&priv->spi->dev, 559875347feSMarc Kleine-Budde sizeof(*priv->map_buf_crc_tx), 560875347feSMarc Kleine-Budde GFP_KERNEL); 561875347feSMarc Kleine-Budde if (!priv->map_buf_crc_tx) 562875347feSMarc Kleine-Budde return -ENOMEM; 563875347feSMarc Kleine-Budde } 564875347feSMarc Kleine-Budde 565eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) 566875347feSMarc Kleine-Budde priv->map_reg = priv->map_crc; 567875347feSMarc Kleine-Budde 568eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX) 569875347feSMarc Kleine-Budde priv->map_rx = priv->map_crc; 570875347feSMarc Kleine-Budde 571875347feSMarc Kleine-Budde return 0; 572875347feSMarc Kleine-Budde } 573875347feSMarc Kleine-Budde 574eb79a267SMarc Kleine-Budde static void mcp251xfd_regmap_destroy_crc(struct mcp251xfd_priv *priv) 575875347feSMarc Kleine-Budde { 576875347feSMarc Kleine-Budde if (priv->map_buf_crc_rx) { 577875347feSMarc Kleine-Budde devm_kfree(&priv->spi->dev, priv->map_buf_crc_rx); 578875347feSMarc Kleine-Budde priv->map_buf_crc_rx = NULL; 579875347feSMarc Kleine-Budde } 580875347feSMarc Kleine-Budde if (priv->map_buf_crc_tx) { 581875347feSMarc Kleine-Budde devm_kfree(&priv->spi->dev, priv->map_buf_crc_tx); 582875347feSMarc Kleine-Budde priv->map_buf_crc_tx = NULL; 583875347feSMarc Kleine-Budde } 584875347feSMarc Kleine-Budde } 585875347feSMarc Kleine-Budde 586eb79a267SMarc Kleine-Budde int mcp251xfd_regmap_init(struct mcp251xfd_priv *priv) 587875347feSMarc Kleine-Budde { 588875347feSMarc Kleine-Budde int err; 589875347feSMarc Kleine-Budde 590eb79a267SMarc Kleine-Budde if (mcp251xfd_regmap_use_nocrc(priv)) { 591eb79a267SMarc Kleine-Budde err = mcp251xfd_regmap_init_nocrc(priv); 592875347feSMarc Kleine-Budde 593875347feSMarc Kleine-Budde if (err) 594875347feSMarc Kleine-Budde return err; 595875347feSMarc Kleine-Budde } else { 596eb79a267SMarc Kleine-Budde mcp251xfd_regmap_destroy_nocrc(priv); 597875347feSMarc Kleine-Budde } 598875347feSMarc Kleine-Budde 599eb79a267SMarc Kleine-Budde if (mcp251xfd_regmap_use_crc(priv)) { 600eb79a267SMarc Kleine-Budde err = mcp251xfd_regmap_init_crc(priv); 601875347feSMarc Kleine-Budde 602875347feSMarc Kleine-Budde if (err) 603875347feSMarc Kleine-Budde return err; 604875347feSMarc Kleine-Budde } else { 605eb79a267SMarc Kleine-Budde mcp251xfd_regmap_destroy_crc(priv); 606875347feSMarc Kleine-Budde } 607875347feSMarc Kleine-Budde 608875347feSMarc Kleine-Budde return 0; 609875347feSMarc Kleine-Budde } 610