11f0e21a0SMarc Kleine-Budde // SPDX-License-Identifier: GPL-2.0
21f0e21a0SMarc Kleine-Budde //
3eb79a267SMarc Kleine-Budde // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
41f0e21a0SMarc Kleine-Budde //
5c912f19eSMarc Kleine-Budde // Copyright (c) 2019, 2020, 2021 Pengutronix,
61f0e21a0SMarc Kleine-Budde // Marc Kleine-Budde <kernel@pengutronix.de>
71f0e21a0SMarc Kleine-Budde //
81f0e21a0SMarc Kleine-Budde
91f0e21a0SMarc Kleine-Budde #include "mcp251xfd.h"
101f0e21a0SMarc Kleine-Budde
111f0e21a0SMarc Kleine-Budde #include <asm/unaligned.h>
121f0e21a0SMarc Kleine-Budde
13eb79a267SMarc Kleine-Budde static const struct regmap_config mcp251xfd_regmap_crc;
141f0e21a0SMarc Kleine-Budde
151f0e21a0SMarc Kleine-Budde static int
mcp251xfd_regmap_nocrc_write(void * context,const void * data,size_t count)16eb79a267SMarc Kleine-Budde mcp251xfd_regmap_nocrc_write(void *context, const void *data, size_t count)
171f0e21a0SMarc Kleine-Budde {
181f0e21a0SMarc Kleine-Budde struct spi_device *spi = context;
191f0e21a0SMarc Kleine-Budde
201f0e21a0SMarc Kleine-Budde return spi_write(spi, data, count);
211f0e21a0SMarc Kleine-Budde }
221f0e21a0SMarc Kleine-Budde
231f0e21a0SMarc Kleine-Budde static int
mcp251xfd_regmap_nocrc_gather_write(void * context,const void * reg,size_t reg_len,const void * val,size_t val_len)24eb79a267SMarc Kleine-Budde mcp251xfd_regmap_nocrc_gather_write(void *context,
251f0e21a0SMarc Kleine-Budde const void *reg, size_t reg_len,
261f0e21a0SMarc Kleine-Budde const void *val, size_t val_len)
271f0e21a0SMarc Kleine-Budde {
281f0e21a0SMarc 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;
311f0e21a0SMarc Kleine-Budde struct spi_transfer xfer[] = {
321f0e21a0SMarc Kleine-Budde {
331f0e21a0SMarc Kleine-Budde .tx_buf = buf_tx,
341f0e21a0SMarc Kleine-Budde .len = sizeof(buf_tx->cmd) + val_len,
351f0e21a0SMarc Kleine-Budde },
361f0e21a0SMarc Kleine-Budde };
371f0e21a0SMarc Kleine-Budde
381f0e21a0SMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16));
391f0e21a0SMarc Kleine-Budde
40eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
411f0e21a0SMarc Kleine-Budde reg_len != sizeof(buf_tx->cmd.cmd))
421f0e21a0SMarc Kleine-Budde return -EINVAL;
431f0e21a0SMarc Kleine-Budde
441f0e21a0SMarc Kleine-Budde memcpy(&buf_tx->cmd, reg, sizeof(buf_tx->cmd));
451f0e21a0SMarc Kleine-Budde memcpy(buf_tx->data, val, val_len);
461f0e21a0SMarc Kleine-Budde
471f0e21a0SMarc Kleine-Budde return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
481f0e21a0SMarc Kleine-Budde }
491f0e21a0SMarc Kleine-Budde
50c912f19eSMarc Kleine-Budde static inline bool
mcp251xfd_update_bits_read_reg(const struct mcp251xfd_priv * priv,unsigned int reg)51c912f19eSMarc Kleine-Budde mcp251xfd_update_bits_read_reg(const struct mcp251xfd_priv *priv,
52c912f19eSMarc Kleine-Budde unsigned int reg)
531f0e21a0SMarc Kleine-Budde {
54c912f19eSMarc Kleine-Budde struct mcp251xfd_rx_ring *ring;
55c912f19eSMarc Kleine-Budde int n;
56c912f19eSMarc Kleine-Budde
571f0e21a0SMarc 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:
631f0e21a0SMarc 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:
671f0e21a0SMarc Kleine-Budde return true;
681f0e21a0SMarc 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
761f0e21a0SMarc Kleine-Budde WARN(1, "Status of reg 0x%04x unknown.\n", reg);
771f0e21a0SMarc Kleine-Budde }
781f0e21a0SMarc Kleine-Budde
791f0e21a0SMarc Kleine-Budde return true;
801f0e21a0SMarc Kleine-Budde }
811f0e21a0SMarc Kleine-Budde
821f0e21a0SMarc Kleine-Budde static int
mcp251xfd_regmap_nocrc_update_bits(void * context,unsigned int reg,unsigned int mask,unsigned int val)83eb79a267SMarc Kleine-Budde mcp251xfd_regmap_nocrc_update_bits(void *context, unsigned int reg,
841f0e21a0SMarc Kleine-Budde unsigned int mask, unsigned int val)
851f0e21a0SMarc Kleine-Budde {
861f0e21a0SMarc 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;
901f0e21a0SMarc Kleine-Budde __le32 orig_le32 = 0, mask_le32, val_le32, tmp_le32;
911f0e21a0SMarc Kleine-Budde u8 first_byte, last_byte, len;
921f0e21a0SMarc Kleine-Budde int err;
931f0e21a0SMarc Kleine-Budde
941f0e21a0SMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16));
951f0e21a0SMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16));
961f0e21a0SMarc Kleine-Budde
97eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
981f0e21a0SMarc Kleine-Budde mask == 0)
991f0e21a0SMarc Kleine-Budde return -EINVAL;
1001f0e21a0SMarc Kleine-Budde
101eb79a267SMarc Kleine-Budde first_byte = mcp251xfd_first_byte_set(mask);
102eb79a267SMarc Kleine-Budde last_byte = mcp251xfd_last_byte_set(mask);
1031f0e21a0SMarc Kleine-Budde len = last_byte - first_byte + 1;
1041f0e21a0SMarc Kleine-Budde
105c912f19eSMarc Kleine-Budde if (mcp251xfd_update_bits_read_reg(priv, reg)) {
1061f0e21a0SMarc Kleine-Budde struct spi_transfer xfer[2] = { };
1071f0e21a0SMarc Kleine-Budde struct spi_message msg;
1081f0e21a0SMarc Kleine-Budde
1091f0e21a0SMarc Kleine-Budde spi_message_init(&msg);
1101f0e21a0SMarc Kleine-Budde spi_message_add_tail(&xfer[0], &msg);
1111f0e21a0SMarc Kleine-Budde
112eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) {
1131f0e21a0SMarc Kleine-Budde xfer[0].tx_buf = buf_tx;
1141f0e21a0SMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd);
1151f0e21a0SMarc Kleine-Budde
1161f0e21a0SMarc Kleine-Budde xfer[1].rx_buf = buf_rx->data;
1171f0e21a0SMarc Kleine-Budde xfer[1].len = len;
1181f0e21a0SMarc Kleine-Budde spi_message_add_tail(&xfer[1], &msg);
1191f0e21a0SMarc Kleine-Budde } else {
1201f0e21a0SMarc Kleine-Budde xfer[0].tx_buf = buf_tx;
1211f0e21a0SMarc Kleine-Budde xfer[0].rx_buf = buf_rx;
1221f0e21a0SMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd) + len;
1231f0e21a0SMarc Kleine-Budde
124eb79a267SMarc Kleine-Budde if (MCP251XFD_SANITIZE_SPI)
1251f0e21a0SMarc Kleine-Budde memset(buf_tx->data, 0x0, len);
1261f0e21a0SMarc Kleine-Budde }
1271f0e21a0SMarc Kleine-Budde
128eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, reg + first_byte);
1291f0e21a0SMarc Kleine-Budde err = spi_sync(spi, &msg);
1301f0e21a0SMarc Kleine-Budde if (err)
1311f0e21a0SMarc Kleine-Budde return err;
1321f0e21a0SMarc Kleine-Budde
1331f0e21a0SMarc Kleine-Budde memcpy(&orig_le32, buf_rx->data, len);
1341f0e21a0SMarc Kleine-Budde }
1351f0e21a0SMarc Kleine-Budde
1361f0e21a0SMarc Kleine-Budde mask_le32 = cpu_to_le32(mask >> BITS_PER_BYTE * first_byte);
1371f0e21a0SMarc Kleine-Budde val_le32 = cpu_to_le32(val >> BITS_PER_BYTE * first_byte);
1381f0e21a0SMarc Kleine-Budde
1391f0e21a0SMarc Kleine-Budde tmp_le32 = orig_le32 & ~mask_le32;
1401f0e21a0SMarc Kleine-Budde tmp_le32 |= val_le32 & mask_le32;
1411f0e21a0SMarc Kleine-Budde
142eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_write_nocrc(&buf_tx->cmd, reg + first_byte);
1431f0e21a0SMarc Kleine-Budde memcpy(buf_tx->data, &tmp_le32, len);
1441f0e21a0SMarc Kleine-Budde
1451f0e21a0SMarc Kleine-Budde return spi_write(spi, buf_tx, sizeof(buf_tx->cmd) + len);
1461f0e21a0SMarc Kleine-Budde }
1471f0e21a0SMarc Kleine-Budde
1481f0e21a0SMarc Kleine-Budde static int
mcp251xfd_regmap_nocrc_read(void * context,const void * reg,size_t reg_len,void * val_buf,size_t val_len)149eb79a267SMarc Kleine-Budde mcp251xfd_regmap_nocrc_read(void *context,
1501f0e21a0SMarc Kleine-Budde const void *reg, size_t reg_len,
1511f0e21a0SMarc Kleine-Budde void *val_buf, size_t val_len)
1521f0e21a0SMarc Kleine-Budde {
1531f0e21a0SMarc 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;
1571f0e21a0SMarc Kleine-Budde struct spi_transfer xfer[2] = { };
1581f0e21a0SMarc Kleine-Budde struct spi_message msg;
1591f0e21a0SMarc Kleine-Budde int err;
1601f0e21a0SMarc Kleine-Budde
1611f0e21a0SMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16));
1621f0e21a0SMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16));
1631f0e21a0SMarc Kleine-Budde
164eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
1651f0e21a0SMarc Kleine-Budde reg_len != sizeof(buf_tx->cmd.cmd))
1661f0e21a0SMarc Kleine-Budde return -EINVAL;
1671f0e21a0SMarc Kleine-Budde
1681f0e21a0SMarc Kleine-Budde spi_message_init(&msg);
1691f0e21a0SMarc Kleine-Budde spi_message_add_tail(&xfer[0], &msg);
1701f0e21a0SMarc Kleine-Budde
171eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) {
1721f0e21a0SMarc Kleine-Budde xfer[0].tx_buf = reg;
1731f0e21a0SMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd);
1741f0e21a0SMarc Kleine-Budde
1751f0e21a0SMarc Kleine-Budde xfer[1].rx_buf = val_buf;
1761f0e21a0SMarc Kleine-Budde xfer[1].len = val_len;
1771f0e21a0SMarc Kleine-Budde spi_message_add_tail(&xfer[1], &msg);
1781f0e21a0SMarc Kleine-Budde } else {
1791f0e21a0SMarc Kleine-Budde xfer[0].tx_buf = buf_tx;
1801f0e21a0SMarc Kleine-Budde xfer[0].rx_buf = buf_rx;
1811f0e21a0SMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd) + val_len;
1821f0e21a0SMarc Kleine-Budde
1831f0e21a0SMarc Kleine-Budde memcpy(&buf_tx->cmd, reg, sizeof(buf_tx->cmd));
184eb79a267SMarc Kleine-Budde if (MCP251XFD_SANITIZE_SPI)
1851f0e21a0SMarc Kleine-Budde memset(buf_tx->data, 0x0, val_len);
186da623840Skernel test robot }
1871f0e21a0SMarc Kleine-Budde
1881f0e21a0SMarc Kleine-Budde err = spi_sync(spi, &msg);
1891f0e21a0SMarc Kleine-Budde if (err)
1901f0e21a0SMarc Kleine-Budde return err;
1911f0e21a0SMarc Kleine-Budde
192eb79a267SMarc Kleine-Budde if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX))
1931f0e21a0SMarc Kleine-Budde memcpy(val_buf, buf_rx->data, val_len);
1941f0e21a0SMarc Kleine-Budde
1951f0e21a0SMarc Kleine-Budde return 0;
1961f0e21a0SMarc Kleine-Budde }
1971f0e21a0SMarc Kleine-Budde
1981f0e21a0SMarc Kleine-Budde static int
mcp251xfd_regmap_crc_gather_write(void * context,const void * reg_p,size_t reg_len,const void * val,size_t val_len)199eb79a267SMarc Kleine-Budde mcp251xfd_regmap_crc_gather_write(void *context,
2001f0e21a0SMarc Kleine-Budde const void *reg_p, size_t reg_len,
2011f0e21a0SMarc Kleine-Budde const void *val, size_t val_len)
2021f0e21a0SMarc Kleine-Budde {
2031f0e21a0SMarc 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;
2061f0e21a0SMarc Kleine-Budde struct spi_transfer xfer[] = {
2071f0e21a0SMarc Kleine-Budde {
2081f0e21a0SMarc Kleine-Budde .tx_buf = buf_tx,
2091f0e21a0SMarc Kleine-Budde .len = sizeof(buf_tx->cmd) + val_len +
2101f0e21a0SMarc Kleine-Budde sizeof(buf_tx->crc),
2111f0e21a0SMarc Kleine-Budde },
2121f0e21a0SMarc Kleine-Budde };
2131f0e21a0SMarc Kleine-Budde u16 reg = *(u16 *)reg_p;
2141f0e21a0SMarc Kleine-Budde u16 crc;
2151f0e21a0SMarc Kleine-Budde
2161f0e21a0SMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16) + sizeof(u8));
2171f0e21a0SMarc Kleine-Budde
218eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
2191f0e21a0SMarc Kleine-Budde reg_len != sizeof(buf_tx->cmd.cmd) +
220eb79a267SMarc Kleine-Budde mcp251xfd_regmap_crc.pad_bits / BITS_PER_BYTE)
2211f0e21a0SMarc Kleine-Budde return -EINVAL;
2221f0e21a0SMarc Kleine-Budde
223eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_write_crc(&buf_tx->cmd, reg, val_len);
2241f0e21a0SMarc Kleine-Budde memcpy(buf_tx->data, val, val_len);
2251f0e21a0SMarc Kleine-Budde
226eb79a267SMarc Kleine-Budde crc = mcp251xfd_crc16_compute(buf_tx, sizeof(buf_tx->cmd) + val_len);
2271f0e21a0SMarc Kleine-Budde put_unaligned_be16(crc, buf_tx->data + val_len);
2281f0e21a0SMarc Kleine-Budde
2291f0e21a0SMarc Kleine-Budde return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
2301f0e21a0SMarc Kleine-Budde }
2311f0e21a0SMarc Kleine-Budde
2321f0e21a0SMarc Kleine-Budde static int
mcp251xfd_regmap_crc_write(void * context,const void * data,size_t count)233eb79a267SMarc Kleine-Budde mcp251xfd_regmap_crc_write(void *context,
2341f0e21a0SMarc Kleine-Budde const void *data, size_t count)
2351f0e21a0SMarc Kleine-Budde {
2361f0e21a0SMarc Kleine-Budde const size_t data_offset = sizeof(__be16) +
237eb79a267SMarc Kleine-Budde mcp251xfd_regmap_crc.pad_bits / BITS_PER_BYTE;
2381f0e21a0SMarc Kleine-Budde
239eb79a267SMarc Kleine-Budde return mcp251xfd_regmap_crc_gather_write(context,
2401f0e21a0SMarc Kleine-Budde data, data_offset,
2411f0e21a0SMarc Kleine-Budde data + data_offset,
2421f0e21a0SMarc Kleine-Budde count - data_offset);
2431f0e21a0SMarc Kleine-Budde }
2441f0e21a0SMarc Kleine-Budde
2451f0e21a0SMarc Kleine-Budde static int
mcp251xfd_regmap_crc_read_check_crc(const struct mcp251xfd_map_buf_crc * const buf_rx,const struct mcp251xfd_map_buf_crc * const buf_tx,unsigned int data_len)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)
2491f0e21a0SMarc Kleine-Budde {
2501f0e21a0SMarc Kleine-Budde u16 crc_received, crc_calculated;
2511f0e21a0SMarc Kleine-Budde
2521f0e21a0SMarc Kleine-Budde crc_received = get_unaligned_be16(buf_rx->data + data_len);
253eb79a267SMarc Kleine-Budde crc_calculated = mcp251xfd_crc16_compute2(&buf_tx->cmd,
2541f0e21a0SMarc Kleine-Budde sizeof(buf_tx->cmd),
2551f0e21a0SMarc Kleine-Budde buf_rx->data,
2561f0e21a0SMarc Kleine-Budde data_len);
2571f0e21a0SMarc Kleine-Budde if (crc_received != crc_calculated)
2581f0e21a0SMarc Kleine-Budde return -EBADMSG;
2591f0e21a0SMarc Kleine-Budde
2601f0e21a0SMarc Kleine-Budde return 0;
2611f0e21a0SMarc Kleine-Budde }
2621f0e21a0SMarc Kleine-Budde
263ef7a8c3eSMarc Kleine-Budde static int
mcp251xfd_regmap_crc_read_one(struct mcp251xfd_priv * priv,struct spi_message * msg,unsigned int data_len)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
2811f0e21a0SMarc Kleine-Budde static int
mcp251xfd_regmap_crc_read(void * context,const void * reg_p,size_t reg_len,void * val_buf,size_t val_len)282eb79a267SMarc Kleine-Budde mcp251xfd_regmap_crc_read(void *context,
2831f0e21a0SMarc Kleine-Budde const void *reg_p, size_t reg_len,
2841f0e21a0SMarc Kleine-Budde void *val_buf, size_t val_len)
2851f0e21a0SMarc Kleine-Budde {
2861f0e21a0SMarc 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;
2901f0e21a0SMarc Kleine-Budde struct spi_transfer xfer[2] = { };
2911f0e21a0SMarc Kleine-Budde struct spi_message msg;
2921f0e21a0SMarc Kleine-Budde u16 reg = *(u16 *)reg_p;
2931f0e21a0SMarc Kleine-Budde int i, err;
2941f0e21a0SMarc Kleine-Budde
2951f0e21a0SMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16) + sizeof(u8));
2961f0e21a0SMarc Kleine-Budde BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16) + sizeof(u8));
2971f0e21a0SMarc Kleine-Budde
298eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
2991f0e21a0SMarc Kleine-Budde reg_len != sizeof(buf_tx->cmd.cmd) +
300eb79a267SMarc Kleine-Budde mcp251xfd_regmap_crc.pad_bits / BITS_PER_BYTE)
3011f0e21a0SMarc Kleine-Budde return -EINVAL;
3021f0e21a0SMarc Kleine-Budde
3031f0e21a0SMarc Kleine-Budde spi_message_init(&msg);
3041f0e21a0SMarc Kleine-Budde spi_message_add_tail(&xfer[0], &msg);
3051f0e21a0SMarc Kleine-Budde
306eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) {
3071f0e21a0SMarc Kleine-Budde xfer[0].tx_buf = buf_tx;
3081f0e21a0SMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd);
3091f0e21a0SMarc Kleine-Budde
3101f0e21a0SMarc Kleine-Budde xfer[1].rx_buf = buf_rx->data;
3111f0e21a0SMarc Kleine-Budde xfer[1].len = val_len + sizeof(buf_tx->crc);
3121f0e21a0SMarc Kleine-Budde spi_message_add_tail(&xfer[1], &msg);
3131f0e21a0SMarc Kleine-Budde } else {
3141f0e21a0SMarc Kleine-Budde xfer[0].tx_buf = buf_tx;
3151f0e21a0SMarc Kleine-Budde xfer[0].rx_buf = buf_rx;
3161f0e21a0SMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd) + val_len +
3171f0e21a0SMarc Kleine-Budde sizeof(buf_tx->crc);
3181f0e21a0SMarc Kleine-Budde
319eb79a267SMarc Kleine-Budde if (MCP251XFD_SANITIZE_SPI)
3201f0e21a0SMarc Kleine-Budde memset(buf_tx->data, 0x0, val_len +
3211f0e21a0SMarc Kleine-Budde sizeof(buf_tx->crc));
3221f0e21a0SMarc Kleine-Budde }
3231f0e21a0SMarc Kleine-Budde
324eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_read_crc(&buf_tx->cmd, reg, val_len);
3251f0e21a0SMarc 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);
3281f0e21a0SMarc Kleine-Budde if (!err)
3291f0e21a0SMarc Kleine-Budde goto out;
3301f0e21a0SMarc Kleine-Budde if (err != -EBADMSG)
3311f0e21a0SMarc Kleine-Budde return err;
3321f0e21a0SMarc 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 *
337406cc9cdSThomas Kopp * Observation on the mcp2518fd shows that if the
338406cc9cdSThomas Kopp * lowest byte (which is transferred first on the SPI
339406cc9cdSThomas Kopp * bus) of that register is 0x00 or 0x80 the
340406cc9cdSThomas Kopp * calculated CRC doesn't always match the transferred
341406cc9cdSThomas Kopp * one. On the mcp2517fd this problem is not limited
342406cc9cdSThomas Kopp * to the first byte being 0x00 or 0x80.
343c7eb923cSMarc Kleine-Budde *
344c7eb923cSMarc Kleine-Budde * If the highest bit in the lowest byte is flipped
345c7eb923cSMarc Kleine-Budde * the transferred CRC matches the calculated one. We
346*e3d4ee7dSThomas Kopp * assume for now the CRC operates on the correct
347*e3d4ee7dSThomas Kopp * data.
348c7eb923cSMarc Kleine-Budde */
349c7eb923cSMarc Kleine-Budde if (reg == MCP251XFD_REG_TBC &&
350406cc9cdSThomas Kopp ((buf_rx->data[0] & 0xf8) == 0x0 ||
351406cc9cdSThomas Kopp (buf_rx->data[0] & 0xf8) == 0x80)) {
352c7eb923cSMarc Kleine-Budde /* Flip highest bit in lowest byte of le32 */
353c7eb923cSMarc Kleine-Budde buf_rx->data[0] ^= 0x80;
354c7eb923cSMarc Kleine-Budde
355c7eb923cSMarc Kleine-Budde /* re-check CRC */
356c7eb923cSMarc Kleine-Budde err = mcp251xfd_regmap_crc_read_check_crc(buf_rx,
357c7eb923cSMarc Kleine-Budde buf_tx,
358c7eb923cSMarc Kleine-Budde val_len);
359c7eb923cSMarc Kleine-Budde if (!err) {
360c7eb923cSMarc Kleine-Budde /* If CRC is now correct, assume
361*e3d4ee7dSThomas Kopp * flipped data is OK.
362c7eb923cSMarc Kleine-Budde */
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.
3681f0e21a0SMarc Kleine-Budde *
3691f0e21a0SMarc Kleine-Budde * The chip may be in deep sleep and this SPI transfer
3701f0e21a0SMarc Kleine-Budde * (i.e. the assertion of the CS) will wake the chip
3711f0e21a0SMarc Kleine-Budde * up. This takes about 3ms. The CRC of this transfer
3721f0e21a0SMarc Kleine-Budde * is wrong.
3731f0e21a0SMarc Kleine-Budde *
3741f0e21a0SMarc Kleine-Budde * Or there isn't a chip at all, in this case the CRC
3751f0e21a0SMarc Kleine-Budde * will be wrong, too.
3761f0e21a0SMarc Kleine-Budde *
3771f0e21a0SMarc Kleine-Budde * In both cases ignore the CRC and copy the read data
3781f0e21a0SMarc Kleine-Budde * to the caller. It will take care of both cases.
3791f0e21a0SMarc Kleine-Budde *
3801f0e21a0SMarc Kleine-Budde */
38125386c9aSMarc Kleine-Budde if (reg == MCP251XFD_REG_OSC && val_len == sizeof(__le32)) {
3821f0e21a0SMarc Kleine-Budde err = 0;
3831f0e21a0SMarc Kleine-Budde goto out;
3841f0e21a0SMarc Kleine-Budde }
3851f0e21a0SMarc Kleine-Budde
386b4728920SMarc Kleine-Budde netdev_info(priv->ndev,
3871f0e21a0SMarc Kleine-Budde "CRC read error at address 0x%04x (length=%zd, data=%*ph, CRC=0x%04x) retrying.\n",
3881f0e21a0SMarc Kleine-Budde reg, val_len, (int)val_len, buf_rx->data,
3891f0e21a0SMarc Kleine-Budde get_unaligned_be16(buf_rx->data + val_len));
3901f0e21a0SMarc Kleine-Budde }
3911f0e21a0SMarc Kleine-Budde
3921f0e21a0SMarc Kleine-Budde if (err) {
393b4728920SMarc Kleine-Budde netdev_err(priv->ndev,
3941f0e21a0SMarc Kleine-Budde "CRC read error at address 0x%04x (length=%zd, data=%*ph, CRC=0x%04x).\n",
3951f0e21a0SMarc Kleine-Budde reg, val_len, (int)val_len, buf_rx->data,
3961f0e21a0SMarc Kleine-Budde get_unaligned_be16(buf_rx->data + val_len));
3971f0e21a0SMarc Kleine-Budde
3981f0e21a0SMarc Kleine-Budde return err;
3991f0e21a0SMarc Kleine-Budde }
4001f0e21a0SMarc Kleine-Budde out:
4011f0e21a0SMarc Kleine-Budde memcpy(val_buf, buf_rx->data, val_len);
4021f0e21a0SMarc Kleine-Budde
4031f0e21a0SMarc Kleine-Budde return 0;
4041f0e21a0SMarc Kleine-Budde }
4051f0e21a0SMarc Kleine-Budde
406eb79a267SMarc Kleine-Budde static const struct regmap_range mcp251xfd_reg_table_yes_range[] = {
4071f0e21a0SMarc Kleine-Budde regmap_reg_range(0x000, 0x2ec), /* CAN FD Controller Module SFR */
4081f0e21a0SMarc Kleine-Budde regmap_reg_range(0x400, 0xbfc), /* RAM */
4091f0e21a0SMarc Kleine-Budde regmap_reg_range(0xe00, 0xe14), /* MCP2517/18FD SFR */
4101f0e21a0SMarc Kleine-Budde };
4111f0e21a0SMarc 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),
4151f0e21a0SMarc Kleine-Budde };
4161f0e21a0SMarc Kleine-Budde
417eb79a267SMarc Kleine-Budde static const struct regmap_config mcp251xfd_regmap_nocrc = {
4181f0e21a0SMarc Kleine-Budde .name = "nocrc",
4191f0e21a0SMarc Kleine-Budde .reg_bits = 16,
4201f0e21a0SMarc Kleine-Budde .reg_stride = 4,
4211f0e21a0SMarc Kleine-Budde .pad_bits = 0,
4221f0e21a0SMarc Kleine-Budde .val_bits = 32,
4231f0e21a0SMarc Kleine-Budde .max_register = 0xffc,
424eb79a267SMarc Kleine-Budde .wr_table = &mcp251xfd_reg_table,
425eb79a267SMarc Kleine-Budde .rd_table = &mcp251xfd_reg_table,
4261f0e21a0SMarc Kleine-Budde .cache_type = REGCACHE_NONE,
4271f0e21a0SMarc Kleine-Budde .read_flag_mask = (__force unsigned long)
428eb79a267SMarc Kleine-Budde cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_READ),
4291f0e21a0SMarc Kleine-Budde .write_flag_mask = (__force unsigned long)
430eb79a267SMarc Kleine-Budde cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_WRITE),
4311f0e21a0SMarc Kleine-Budde };
4321f0e21a0SMarc 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,
4381f0e21a0SMarc Kleine-Budde .reg_format_endian_default = REGMAP_ENDIAN_BIG,
4391f0e21a0SMarc 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),
4421f0e21a0SMarc Kleine-Budde };
4431f0e21a0SMarc Kleine-Budde
444eb79a267SMarc Kleine-Budde static const struct regmap_config mcp251xfd_regmap_crc = {
4451f0e21a0SMarc Kleine-Budde .name = "crc",
4461f0e21a0SMarc Kleine-Budde .reg_bits = 16,
4471f0e21a0SMarc Kleine-Budde .reg_stride = 4,
4481f0e21a0SMarc Kleine-Budde .pad_bits = 16, /* keep data bits aligned */
4491f0e21a0SMarc Kleine-Budde .val_bits = 32,
4501f0e21a0SMarc Kleine-Budde .max_register = 0xffc,
451eb79a267SMarc Kleine-Budde .wr_table = &mcp251xfd_reg_table,
452eb79a267SMarc Kleine-Budde .rd_table = &mcp251xfd_reg_table,
4531f0e21a0SMarc Kleine-Budde .cache_type = REGCACHE_NONE,
4541f0e21a0SMarc Kleine-Budde };
4551f0e21a0SMarc 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,
4601f0e21a0SMarc Kleine-Budde .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
4611f0e21a0SMarc 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),
4641f0e21a0SMarc Kleine-Budde };
4651f0e21a0SMarc Kleine-Budde
4661f0e21a0SMarc Kleine-Budde static inline bool
mcp251xfd_regmap_use_nocrc(struct mcp251xfd_priv * priv)467eb79a267SMarc Kleine-Budde mcp251xfd_regmap_use_nocrc(struct mcp251xfd_priv *priv)
4681f0e21a0SMarc 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));
4711f0e21a0SMarc Kleine-Budde }
4721f0e21a0SMarc Kleine-Budde
4731f0e21a0SMarc Kleine-Budde static inline bool
mcp251xfd_regmap_use_crc(struct mcp251xfd_priv * priv)474eb79a267SMarc Kleine-Budde mcp251xfd_regmap_use_crc(struct mcp251xfd_priv *priv)
4751f0e21a0SMarc 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);
4781f0e21a0SMarc Kleine-Budde }
4791f0e21a0SMarc Kleine-Budde
4801f0e21a0SMarc Kleine-Budde static int
mcp251xfd_regmap_init_nocrc(struct mcp251xfd_priv * priv)481eb79a267SMarc Kleine-Budde mcp251xfd_regmap_init_nocrc(struct mcp251xfd_priv *priv)
4821f0e21a0SMarc Kleine-Budde {
4831f0e21a0SMarc Kleine-Budde if (!priv->map_nocrc) {
4841f0e21a0SMarc Kleine-Budde struct regmap *map;
4851f0e21a0SMarc Kleine-Budde
486eb79a267SMarc Kleine-Budde map = devm_regmap_init(&priv->spi->dev, &mcp251xfd_bus_nocrc,
487eb79a267SMarc Kleine-Budde priv->spi, &mcp251xfd_regmap_nocrc);
4881f0e21a0SMarc Kleine-Budde if (IS_ERR(map))
4891f0e21a0SMarc Kleine-Budde return PTR_ERR(map);
4901f0e21a0SMarc Kleine-Budde
4911f0e21a0SMarc Kleine-Budde priv->map_nocrc = map;
4921f0e21a0SMarc Kleine-Budde }
4931f0e21a0SMarc Kleine-Budde
4941f0e21a0SMarc Kleine-Budde if (!priv->map_buf_nocrc_rx) {
4951f0e21a0SMarc Kleine-Budde priv->map_buf_nocrc_rx =
4961f0e21a0SMarc Kleine-Budde devm_kzalloc(&priv->spi->dev,
4971f0e21a0SMarc Kleine-Budde sizeof(*priv->map_buf_nocrc_rx),
4981f0e21a0SMarc Kleine-Budde GFP_KERNEL);
4991f0e21a0SMarc Kleine-Budde if (!priv->map_buf_nocrc_rx)
5001f0e21a0SMarc Kleine-Budde return -ENOMEM;
5011f0e21a0SMarc Kleine-Budde }
5021f0e21a0SMarc Kleine-Budde
5031f0e21a0SMarc Kleine-Budde if (!priv->map_buf_nocrc_tx) {
5041f0e21a0SMarc Kleine-Budde priv->map_buf_nocrc_tx =
5051f0e21a0SMarc Kleine-Budde devm_kzalloc(&priv->spi->dev,
5061f0e21a0SMarc Kleine-Budde sizeof(*priv->map_buf_nocrc_tx),
5071f0e21a0SMarc Kleine-Budde GFP_KERNEL);
5081f0e21a0SMarc Kleine-Budde if (!priv->map_buf_nocrc_tx)
5091f0e21a0SMarc Kleine-Budde return -ENOMEM;
5101f0e21a0SMarc Kleine-Budde }
5111f0e21a0SMarc Kleine-Budde
512eb79a267SMarc Kleine-Budde if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG))
5131f0e21a0SMarc Kleine-Budde priv->map_reg = priv->map_nocrc;
5141f0e21a0SMarc Kleine-Budde
515eb79a267SMarc Kleine-Budde if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX))
5161f0e21a0SMarc Kleine-Budde priv->map_rx = priv->map_nocrc;
5171f0e21a0SMarc Kleine-Budde
5181f0e21a0SMarc Kleine-Budde return 0;
5191f0e21a0SMarc Kleine-Budde }
5201f0e21a0SMarc Kleine-Budde
mcp251xfd_regmap_destroy_nocrc(struct mcp251xfd_priv * priv)521eb79a267SMarc Kleine-Budde static void mcp251xfd_regmap_destroy_nocrc(struct mcp251xfd_priv *priv)
5221f0e21a0SMarc Kleine-Budde {
5231f0e21a0SMarc Kleine-Budde if (priv->map_buf_nocrc_rx) {
5241f0e21a0SMarc Kleine-Budde devm_kfree(&priv->spi->dev, priv->map_buf_nocrc_rx);
5251f0e21a0SMarc Kleine-Budde priv->map_buf_nocrc_rx = NULL;
5261f0e21a0SMarc Kleine-Budde }
5271f0e21a0SMarc Kleine-Budde if (priv->map_buf_nocrc_tx) {
5281f0e21a0SMarc Kleine-Budde devm_kfree(&priv->spi->dev, priv->map_buf_nocrc_tx);
5291f0e21a0SMarc Kleine-Budde priv->map_buf_nocrc_tx = NULL;
5301f0e21a0SMarc Kleine-Budde }
5311f0e21a0SMarc Kleine-Budde }
5321f0e21a0SMarc Kleine-Budde
5331f0e21a0SMarc Kleine-Budde static int
mcp251xfd_regmap_init_crc(struct mcp251xfd_priv * priv)534eb79a267SMarc Kleine-Budde mcp251xfd_regmap_init_crc(struct mcp251xfd_priv *priv)
5351f0e21a0SMarc Kleine-Budde {
5361f0e21a0SMarc Kleine-Budde if (!priv->map_crc) {
5371f0e21a0SMarc Kleine-Budde struct regmap *map;
5381f0e21a0SMarc Kleine-Budde
539eb79a267SMarc Kleine-Budde map = devm_regmap_init(&priv->spi->dev, &mcp251xfd_bus_crc,
540eb79a267SMarc Kleine-Budde priv->spi, &mcp251xfd_regmap_crc);
5411f0e21a0SMarc Kleine-Budde if (IS_ERR(map))
5421f0e21a0SMarc Kleine-Budde return PTR_ERR(map);
5431f0e21a0SMarc Kleine-Budde
5441f0e21a0SMarc Kleine-Budde priv->map_crc = map;
5451f0e21a0SMarc Kleine-Budde }
5461f0e21a0SMarc Kleine-Budde
5471f0e21a0SMarc Kleine-Budde if (!priv->map_buf_crc_rx) {
5481f0e21a0SMarc Kleine-Budde priv->map_buf_crc_rx =
5491f0e21a0SMarc Kleine-Budde devm_kzalloc(&priv->spi->dev,
5501f0e21a0SMarc Kleine-Budde sizeof(*priv->map_buf_crc_rx),
5511f0e21a0SMarc Kleine-Budde GFP_KERNEL);
5521f0e21a0SMarc Kleine-Budde if (!priv->map_buf_crc_rx)
5531f0e21a0SMarc Kleine-Budde return -ENOMEM;
5541f0e21a0SMarc Kleine-Budde }
5551f0e21a0SMarc Kleine-Budde
5561f0e21a0SMarc Kleine-Budde if (!priv->map_buf_crc_tx) {
5571f0e21a0SMarc Kleine-Budde priv->map_buf_crc_tx =
5581f0e21a0SMarc Kleine-Budde devm_kzalloc(&priv->spi->dev,
5591f0e21a0SMarc Kleine-Budde sizeof(*priv->map_buf_crc_tx),
5601f0e21a0SMarc Kleine-Budde GFP_KERNEL);
5611f0e21a0SMarc Kleine-Budde if (!priv->map_buf_crc_tx)
5621f0e21a0SMarc Kleine-Budde return -ENOMEM;
5631f0e21a0SMarc Kleine-Budde }
5641f0e21a0SMarc Kleine-Budde
565eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG)
5661f0e21a0SMarc Kleine-Budde priv->map_reg = priv->map_crc;
5671f0e21a0SMarc Kleine-Budde
568eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX)
5691f0e21a0SMarc Kleine-Budde priv->map_rx = priv->map_crc;
5701f0e21a0SMarc Kleine-Budde
5711f0e21a0SMarc Kleine-Budde return 0;
5721f0e21a0SMarc Kleine-Budde }
5731f0e21a0SMarc Kleine-Budde
mcp251xfd_regmap_destroy_crc(struct mcp251xfd_priv * priv)574eb79a267SMarc Kleine-Budde static void mcp251xfd_regmap_destroy_crc(struct mcp251xfd_priv *priv)
5751f0e21a0SMarc Kleine-Budde {
5761f0e21a0SMarc Kleine-Budde if (priv->map_buf_crc_rx) {
5771f0e21a0SMarc Kleine-Budde devm_kfree(&priv->spi->dev, priv->map_buf_crc_rx);
5781f0e21a0SMarc Kleine-Budde priv->map_buf_crc_rx = NULL;
5791f0e21a0SMarc Kleine-Budde }
5801f0e21a0SMarc Kleine-Budde if (priv->map_buf_crc_tx) {
5811f0e21a0SMarc Kleine-Budde devm_kfree(&priv->spi->dev, priv->map_buf_crc_tx);
5821f0e21a0SMarc Kleine-Budde priv->map_buf_crc_tx = NULL;
5831f0e21a0SMarc Kleine-Budde }
5841f0e21a0SMarc Kleine-Budde }
5851f0e21a0SMarc Kleine-Budde
mcp251xfd_regmap_init(struct mcp251xfd_priv * priv)586eb79a267SMarc Kleine-Budde int mcp251xfd_regmap_init(struct mcp251xfd_priv *priv)
5871f0e21a0SMarc Kleine-Budde {
5881f0e21a0SMarc Kleine-Budde int err;
5891f0e21a0SMarc Kleine-Budde
590eb79a267SMarc Kleine-Budde if (mcp251xfd_regmap_use_nocrc(priv)) {
591eb79a267SMarc Kleine-Budde err = mcp251xfd_regmap_init_nocrc(priv);
5921f0e21a0SMarc Kleine-Budde
5931f0e21a0SMarc Kleine-Budde if (err)
5941f0e21a0SMarc Kleine-Budde return err;
5951f0e21a0SMarc Kleine-Budde } else {
596eb79a267SMarc Kleine-Budde mcp251xfd_regmap_destroy_nocrc(priv);
5971f0e21a0SMarc Kleine-Budde }
5981f0e21a0SMarc Kleine-Budde
599eb79a267SMarc Kleine-Budde if (mcp251xfd_regmap_use_crc(priv)) {
600eb79a267SMarc Kleine-Budde err = mcp251xfd_regmap_init_crc(priv);
6011f0e21a0SMarc Kleine-Budde
6021f0e21a0SMarc Kleine-Budde if (err)
6031f0e21a0SMarc Kleine-Budde return err;
6041f0e21a0SMarc Kleine-Budde } else {
605eb79a267SMarc Kleine-Budde mcp251xfd_regmap_destroy_crc(priv);
6061f0e21a0SMarc Kleine-Budde }
6071f0e21a0SMarc Kleine-Budde
6081f0e21a0SMarc Kleine-Budde return 0;
6091f0e21a0SMarc Kleine-Budde }
610