linux/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// mcp251xfd - Microchip MCP251xFD Family CAN controller driver
   4//
   5// Copyright (c) 2019, 2020 Pengutronix,
   6//                          Marc Kleine-Budde <kernel@pengutronix.de>
   7//
   8
   9#include "mcp251xfd.h"
  10
  11#include <asm/unaligned.h>
  12
  13static const struct regmap_config mcp251xfd_regmap_crc;
  14
  15static int
  16mcp251xfd_regmap_nocrc_write(void *context, const void *data, size_t count)
  17{
  18        struct spi_device *spi = context;
  19
  20        return spi_write(spi, data, count);
  21}
  22
  23static int
  24mcp251xfd_regmap_nocrc_gather_write(void *context,
  25                                    const void *reg, size_t reg_len,
  26                                    const void *val, size_t val_len)
  27{
  28        struct spi_device *spi = context;
  29        struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
  30        struct mcp251xfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx;
  31        struct spi_transfer xfer[] = {
  32                {
  33                        .tx_buf = buf_tx,
  34                        .len = sizeof(buf_tx->cmd) + val_len,
  35                },
  36        };
  37
  38        BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16));
  39
  40        if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
  41            reg_len != sizeof(buf_tx->cmd.cmd))
  42                return -EINVAL;
  43
  44        memcpy(&buf_tx->cmd, reg, sizeof(buf_tx->cmd));
  45        memcpy(buf_tx->data, val, val_len);
  46
  47        return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
  48}
  49
  50static inline bool mcp251xfd_update_bits_read_reg(unsigned int reg)
  51{
  52        switch (reg) {
  53        case MCP251XFD_REG_INT:
  54        case MCP251XFD_REG_TEFCON:
  55        case MCP251XFD_REG_FIFOCON(MCP251XFD_RX_FIFO(0)):
  56        case MCP251XFD_REG_FLTCON(0):
  57        case MCP251XFD_REG_ECCSTAT:
  58        case MCP251XFD_REG_CRC:
  59                return false;
  60        case MCP251XFD_REG_CON:
  61        case MCP251XFD_REG_FIFOSTA(MCP251XFD_RX_FIFO(0)):
  62        case MCP251XFD_REG_OSC:
  63        case MCP251XFD_REG_ECCCON:
  64                return true;
  65        default:
  66                WARN(1, "Status of reg 0x%04x unknown.\n", reg);
  67        }
  68
  69        return true;
  70}
  71
  72static int
  73mcp251xfd_regmap_nocrc_update_bits(void *context, unsigned int reg,
  74                                   unsigned int mask, unsigned int val)
  75{
  76        struct spi_device *spi = context;
  77        struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
  78        struct mcp251xfd_map_buf_nocrc *buf_rx = priv->map_buf_nocrc_rx;
  79        struct mcp251xfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx;
  80        __le32 orig_le32 = 0, mask_le32, val_le32, tmp_le32;
  81        u8 first_byte, last_byte, len;
  82        int err;
  83
  84        BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16));
  85        BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16));
  86
  87        if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
  88            mask == 0)
  89                return -EINVAL;
  90
  91        first_byte = mcp251xfd_first_byte_set(mask);
  92        last_byte = mcp251xfd_last_byte_set(mask);
  93        len = last_byte - first_byte + 1;
  94
  95        if (mcp251xfd_update_bits_read_reg(reg)) {
  96                struct spi_transfer xfer[2] = { };
  97                struct spi_message msg;
  98
  99                spi_message_init(&msg);
 100                spi_message_add_tail(&xfer[0], &msg);
 101
 102                if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) {
 103                        xfer[0].tx_buf = buf_tx;
 104                        xfer[0].len = sizeof(buf_tx->cmd);
 105
 106                        xfer[1].rx_buf = buf_rx->data;
 107                        xfer[1].len = len;
 108                        spi_message_add_tail(&xfer[1], &msg);
 109                } else {
 110                        xfer[0].tx_buf = buf_tx;
 111                        xfer[0].rx_buf = buf_rx;
 112                        xfer[0].len = sizeof(buf_tx->cmd) + len;
 113
 114                        if (MCP251XFD_SANITIZE_SPI)
 115                                memset(buf_tx->data, 0x0, len);
 116                }
 117
 118                mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, reg + first_byte);
 119                err = spi_sync(spi, &msg);
 120                if (err)
 121                        return err;
 122
 123                memcpy(&orig_le32, buf_rx->data, len);
 124        }
 125
 126        mask_le32 = cpu_to_le32(mask >> BITS_PER_BYTE * first_byte);
 127        val_le32 = cpu_to_le32(val >> BITS_PER_BYTE * first_byte);
 128
 129        tmp_le32 = orig_le32 & ~mask_le32;
 130        tmp_le32 |= val_le32 & mask_le32;
 131
 132        mcp251xfd_spi_cmd_write_nocrc(&buf_tx->cmd, reg + first_byte);
 133        memcpy(buf_tx->data, &tmp_le32, len);
 134
 135        return spi_write(spi, buf_tx, sizeof(buf_tx->cmd) + len);
 136}
 137
 138static int
 139mcp251xfd_regmap_nocrc_read(void *context,
 140                            const void *reg, size_t reg_len,
 141                            void *val_buf, size_t val_len)
 142{
 143        struct spi_device *spi = context;
 144        struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
 145        struct mcp251xfd_map_buf_nocrc *buf_rx = priv->map_buf_nocrc_rx;
 146        struct mcp251xfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx;
 147        struct spi_transfer xfer[2] = { };
 148        struct spi_message msg;
 149        int err;
 150
 151        BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16));
 152        BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16));
 153
 154        if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
 155            reg_len != sizeof(buf_tx->cmd.cmd))
 156                return -EINVAL;
 157
 158        spi_message_init(&msg);
 159        spi_message_add_tail(&xfer[0], &msg);
 160
 161        if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) {
 162                xfer[0].tx_buf = reg;
 163                xfer[0].len = sizeof(buf_tx->cmd);
 164
 165                xfer[1].rx_buf = val_buf;
 166                xfer[1].len = val_len;
 167                spi_message_add_tail(&xfer[1], &msg);
 168        } else {
 169                xfer[0].tx_buf = buf_tx;
 170                xfer[0].rx_buf = buf_rx;
 171                xfer[0].len = sizeof(buf_tx->cmd) + val_len;
 172
 173                memcpy(&buf_tx->cmd, reg, sizeof(buf_tx->cmd));
 174                if (MCP251XFD_SANITIZE_SPI)
 175                        memset(buf_tx->data, 0x0, val_len);
 176        }
 177
 178        err = spi_sync(spi, &msg);
 179        if (err)
 180                return err;
 181
 182        if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX))
 183                memcpy(val_buf, buf_rx->data, val_len);
 184
 185        return 0;
 186}
 187
 188static int
 189mcp251xfd_regmap_crc_gather_write(void *context,
 190                                  const void *reg_p, size_t reg_len,
 191                                  const void *val, size_t val_len)
 192{
 193        struct spi_device *spi = context;
 194        struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
 195        struct mcp251xfd_map_buf_crc *buf_tx = priv->map_buf_crc_tx;
 196        struct spi_transfer xfer[] = {
 197                {
 198                        .tx_buf = buf_tx,
 199                        .len = sizeof(buf_tx->cmd) + val_len +
 200                                sizeof(buf_tx->crc),
 201                },
 202        };
 203        u16 reg = *(u16 *)reg_p;
 204        u16 crc;
 205
 206        BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16) + sizeof(u8));
 207
 208        if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
 209            reg_len != sizeof(buf_tx->cmd.cmd) +
 210            mcp251xfd_regmap_crc.pad_bits / BITS_PER_BYTE)
 211                return -EINVAL;
 212
 213        mcp251xfd_spi_cmd_write_crc(&buf_tx->cmd, reg, val_len);
 214        memcpy(buf_tx->data, val, val_len);
 215
 216        crc = mcp251xfd_crc16_compute(buf_tx, sizeof(buf_tx->cmd) + val_len);
 217        put_unaligned_be16(crc, buf_tx->data + val_len);
 218
 219        return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
 220}
 221
 222static int
 223mcp251xfd_regmap_crc_write(void *context,
 224                           const void *data, size_t count)
 225{
 226        const size_t data_offset = sizeof(__be16) +
 227                mcp251xfd_regmap_crc.pad_bits / BITS_PER_BYTE;
 228
 229        return mcp251xfd_regmap_crc_gather_write(context,
 230                                                 data, data_offset,
 231                                                 data + data_offset,
 232                                                 count - data_offset);
 233}
 234
 235static int
 236mcp251xfd_regmap_crc_read_check_crc(const struct mcp251xfd_map_buf_crc * const buf_rx,
 237                                    const struct mcp251xfd_map_buf_crc * const buf_tx,
 238                                    unsigned int data_len)
 239{
 240        u16 crc_received, crc_calculated;
 241
 242        crc_received = get_unaligned_be16(buf_rx->data + data_len);
 243        crc_calculated = mcp251xfd_crc16_compute2(&buf_tx->cmd,
 244                                                  sizeof(buf_tx->cmd),
 245                                                  buf_rx->data,
 246                                                  data_len);
 247        if (crc_received != crc_calculated)
 248                return -EBADMSG;
 249
 250        return 0;
 251}
 252
 253
 254static int
 255mcp251xfd_regmap_crc_read_one(struct mcp251xfd_priv *priv,
 256                              struct spi_message *msg, unsigned int data_len)
 257{
 258        const struct mcp251xfd_map_buf_crc *buf_rx = priv->map_buf_crc_rx;
 259        const struct mcp251xfd_map_buf_crc *buf_tx = priv->map_buf_crc_tx;
 260        int err;
 261
 262        BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16) + sizeof(u8));
 263        BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16) + sizeof(u8));
 264
 265        err = spi_sync(priv->spi, msg);
 266        if (err)
 267                return err;
 268
 269        return mcp251xfd_regmap_crc_read_check_crc(buf_rx, buf_tx, data_len);
 270}
 271
 272static int
 273mcp251xfd_regmap_crc_read(void *context,
 274                          const void *reg_p, size_t reg_len,
 275                          void *val_buf, size_t val_len)
 276{
 277        struct spi_device *spi = context;
 278        struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
 279        struct mcp251xfd_map_buf_crc *buf_rx = priv->map_buf_crc_rx;
 280        struct mcp251xfd_map_buf_crc *buf_tx = priv->map_buf_crc_tx;
 281        struct spi_transfer xfer[2] = { };
 282        struct spi_message msg;
 283        u16 reg = *(u16 *)reg_p;
 284        int i, err;
 285
 286        BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16) + sizeof(u8));
 287        BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16) + sizeof(u8));
 288
 289        if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
 290            reg_len != sizeof(buf_tx->cmd.cmd) +
 291            mcp251xfd_regmap_crc.pad_bits / BITS_PER_BYTE)
 292                return -EINVAL;
 293
 294        spi_message_init(&msg);
 295        spi_message_add_tail(&xfer[0], &msg);
 296
 297        if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) {
 298                xfer[0].tx_buf = buf_tx;
 299                xfer[0].len = sizeof(buf_tx->cmd);
 300
 301                xfer[1].rx_buf = buf_rx->data;
 302                xfer[1].len = val_len + sizeof(buf_tx->crc);
 303                spi_message_add_tail(&xfer[1], &msg);
 304        } else {
 305                xfer[0].tx_buf = buf_tx;
 306                xfer[0].rx_buf = buf_rx;
 307                xfer[0].len = sizeof(buf_tx->cmd) + val_len +
 308                        sizeof(buf_tx->crc);
 309
 310                if (MCP251XFD_SANITIZE_SPI)
 311                        memset(buf_tx->data, 0x0, val_len +
 312                               sizeof(buf_tx->crc));
 313        }
 314
 315        mcp251xfd_spi_cmd_read_crc(&buf_tx->cmd, reg, val_len);
 316
 317        for (i = 0; i < MCP251XFD_READ_CRC_RETRIES_MAX; i++) {
 318                err = mcp251xfd_regmap_crc_read_one(priv, &msg, val_len);
 319                if (!err)
 320                        goto out;
 321                if (err != -EBADMSG)
 322                        return err;
 323
 324                /* MCP251XFD_REG_TBC is the time base counter
 325                 * register. It increments once per SYS clock tick,
 326                 * which is 20 or 40 MHz.
 327                 *
 328                 * Observation shows that if the lowest byte (which is
 329                 * transferred first on the SPI bus) of that register
 330                 * is 0x00 or 0x80 the calculated CRC doesn't always
 331                 * match the transferred one.
 332                 *
 333                 * If the highest bit in the lowest byte is flipped
 334                 * the transferred CRC matches the calculated one. We
 335                 * assume for now the CRC calculation in the chip
 336                 * works on wrong data and the transferred data is
 337                 * correct.
 338                 */
 339                if (reg == MCP251XFD_REG_TBC &&
 340                    (buf_rx->data[0] == 0x0 || buf_rx->data[0] == 0x80)) {
 341                        /* Flip highest bit in lowest byte of le32 */
 342                        buf_rx->data[0] ^= 0x80;
 343
 344                        /* re-check CRC */
 345                        err = mcp251xfd_regmap_crc_read_check_crc(buf_rx,
 346                                                                  buf_tx,
 347                                                                  val_len);
 348                        if (!err) {
 349                                /* If CRC is now correct, assume
 350                                 * transferred data was OK, flip bit
 351                                 * back to original value.
 352                                 */
 353                                buf_rx->data[0] ^= 0x80;
 354                                goto out;
 355                        }
 356                }
 357
 358                /* MCP251XFD_REG_OSC is the first ever reg we read from.
 359                 *
 360                 * The chip may be in deep sleep and this SPI transfer
 361                 * (i.e. the assertion of the CS) will wake the chip
 362                 * up. This takes about 3ms. The CRC of this transfer
 363                 * is wrong.
 364                 *
 365                 * Or there isn't a chip at all, in this case the CRC
 366                 * will be wrong, too.
 367                 *
 368                 * In both cases ignore the CRC and copy the read data
 369                 * to the caller. It will take care of both cases.
 370                 *
 371                 */
 372                if (reg == MCP251XFD_REG_OSC) {
 373                        err = 0;
 374                        goto out;
 375                }
 376
 377                netdev_info(priv->ndev,
 378                            "CRC read error at address 0x%04x (length=%zd, data=%*ph, CRC=0x%04x) retrying.\n",
 379                            reg, val_len, (int)val_len, buf_rx->data,
 380                            get_unaligned_be16(buf_rx->data + val_len));
 381        }
 382
 383        if (err) {
 384                netdev_err(priv->ndev,
 385                           "CRC read error at address 0x%04x (length=%zd, data=%*ph, CRC=0x%04x).\n",
 386                           reg, val_len, (int)val_len, buf_rx->data,
 387                           get_unaligned_be16(buf_rx->data + val_len));
 388
 389                return err;
 390        }
 391 out:
 392        memcpy(val_buf, buf_rx->data, val_len);
 393
 394        return 0;
 395}
 396
 397static const struct regmap_range mcp251xfd_reg_table_yes_range[] = {
 398        regmap_reg_range(0x000, 0x2ec), /* CAN FD Controller Module SFR */
 399        regmap_reg_range(0x400, 0xbfc), /* RAM */
 400        regmap_reg_range(0xe00, 0xe14), /* MCP2517/18FD SFR */
 401};
 402
 403static const struct regmap_access_table mcp251xfd_reg_table = {
 404        .yes_ranges = mcp251xfd_reg_table_yes_range,
 405        .n_yes_ranges = ARRAY_SIZE(mcp251xfd_reg_table_yes_range),
 406};
 407
 408static const struct regmap_config mcp251xfd_regmap_nocrc = {
 409        .name = "nocrc",
 410        .reg_bits = 16,
 411        .reg_stride = 4,
 412        .pad_bits = 0,
 413        .val_bits = 32,
 414        .max_register = 0xffc,
 415        .wr_table = &mcp251xfd_reg_table,
 416        .rd_table = &mcp251xfd_reg_table,
 417        .cache_type = REGCACHE_NONE,
 418        .read_flag_mask = (__force unsigned long)
 419                cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_READ),
 420        .write_flag_mask = (__force unsigned long)
 421                cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_WRITE),
 422};
 423
 424static const struct regmap_bus mcp251xfd_bus_nocrc = {
 425        .write = mcp251xfd_regmap_nocrc_write,
 426        .gather_write = mcp251xfd_regmap_nocrc_gather_write,
 427        .reg_update_bits = mcp251xfd_regmap_nocrc_update_bits,
 428        .read = mcp251xfd_regmap_nocrc_read,
 429        .reg_format_endian_default = REGMAP_ENDIAN_BIG,
 430        .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
 431        .max_raw_read = sizeof_field(struct mcp251xfd_map_buf_nocrc, data),
 432        .max_raw_write = sizeof_field(struct mcp251xfd_map_buf_nocrc, data),
 433};
 434
 435static const struct regmap_config mcp251xfd_regmap_crc = {
 436        .name = "crc",
 437        .reg_bits = 16,
 438        .reg_stride = 4,
 439        .pad_bits = 16,         /* keep data bits aligned */
 440        .val_bits = 32,
 441        .max_register = 0xffc,
 442        .wr_table = &mcp251xfd_reg_table,
 443        .rd_table = &mcp251xfd_reg_table,
 444        .cache_type = REGCACHE_NONE,
 445};
 446
 447static const struct regmap_bus mcp251xfd_bus_crc = {
 448        .write = mcp251xfd_regmap_crc_write,
 449        .gather_write = mcp251xfd_regmap_crc_gather_write,
 450        .read = mcp251xfd_regmap_crc_read,
 451        .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
 452        .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
 453        .max_raw_read = sizeof_field(struct mcp251xfd_map_buf_crc, data),
 454        .max_raw_write = sizeof_field(struct mcp251xfd_map_buf_crc, data),
 455};
 456
 457static inline bool
 458mcp251xfd_regmap_use_nocrc(struct mcp251xfd_priv *priv)
 459{
 460        return (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG)) ||
 461                (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX));
 462}
 463
 464static inline bool
 465mcp251xfd_regmap_use_crc(struct mcp251xfd_priv *priv)
 466{
 467        return (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) ||
 468                (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX);
 469}
 470
 471static int
 472mcp251xfd_regmap_init_nocrc(struct mcp251xfd_priv *priv)
 473{
 474        if (!priv->map_nocrc) {
 475                struct regmap *map;
 476
 477                map = devm_regmap_init(&priv->spi->dev, &mcp251xfd_bus_nocrc,
 478                                       priv->spi, &mcp251xfd_regmap_nocrc);
 479                if (IS_ERR(map))
 480                        return PTR_ERR(map);
 481
 482                priv->map_nocrc = map;
 483        }
 484
 485        if (!priv->map_buf_nocrc_rx) {
 486                priv->map_buf_nocrc_rx =
 487                        devm_kzalloc(&priv->spi->dev,
 488                                     sizeof(*priv->map_buf_nocrc_rx),
 489                                     GFP_KERNEL);
 490                if (!priv->map_buf_nocrc_rx)
 491                        return -ENOMEM;
 492        }
 493
 494        if (!priv->map_buf_nocrc_tx) {
 495                priv->map_buf_nocrc_tx =
 496                        devm_kzalloc(&priv->spi->dev,
 497                                     sizeof(*priv->map_buf_nocrc_tx),
 498                                     GFP_KERNEL);
 499                if (!priv->map_buf_nocrc_tx)
 500                        return -ENOMEM;
 501        }
 502
 503        if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG))
 504                priv->map_reg = priv->map_nocrc;
 505
 506        if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX))
 507                priv->map_rx = priv->map_nocrc;
 508
 509        return 0;
 510}
 511
 512static void mcp251xfd_regmap_destroy_nocrc(struct mcp251xfd_priv *priv)
 513{
 514        if (priv->map_buf_nocrc_rx) {
 515                devm_kfree(&priv->spi->dev, priv->map_buf_nocrc_rx);
 516                priv->map_buf_nocrc_rx = NULL;
 517        }
 518        if (priv->map_buf_nocrc_tx) {
 519                devm_kfree(&priv->spi->dev, priv->map_buf_nocrc_tx);
 520                priv->map_buf_nocrc_tx = NULL;
 521        }
 522}
 523
 524static int
 525mcp251xfd_regmap_init_crc(struct mcp251xfd_priv *priv)
 526{
 527        if (!priv->map_crc) {
 528                struct regmap *map;
 529
 530                map = devm_regmap_init(&priv->spi->dev, &mcp251xfd_bus_crc,
 531                                       priv->spi, &mcp251xfd_regmap_crc);
 532                if (IS_ERR(map))
 533                        return PTR_ERR(map);
 534
 535                priv->map_crc = map;
 536        }
 537
 538        if (!priv->map_buf_crc_rx) {
 539                priv->map_buf_crc_rx =
 540                        devm_kzalloc(&priv->spi->dev,
 541                                     sizeof(*priv->map_buf_crc_rx),
 542                                     GFP_KERNEL);
 543                if (!priv->map_buf_crc_rx)
 544                        return -ENOMEM;
 545        }
 546
 547        if (!priv->map_buf_crc_tx) {
 548                priv->map_buf_crc_tx =
 549                        devm_kzalloc(&priv->spi->dev,
 550                                     sizeof(*priv->map_buf_crc_tx),
 551                                     GFP_KERNEL);
 552                if (!priv->map_buf_crc_tx)
 553                        return -ENOMEM;
 554        }
 555
 556        if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG)
 557                priv->map_reg = priv->map_crc;
 558
 559        if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX)
 560                priv->map_rx = priv->map_crc;
 561
 562        return 0;
 563}
 564
 565static void mcp251xfd_regmap_destroy_crc(struct mcp251xfd_priv *priv)
 566{
 567        if (priv->map_buf_crc_rx) {
 568                devm_kfree(&priv->spi->dev, priv->map_buf_crc_rx);
 569                priv->map_buf_crc_rx = NULL;
 570        }
 571        if (priv->map_buf_crc_tx) {
 572                devm_kfree(&priv->spi->dev, priv->map_buf_crc_tx);
 573                priv->map_buf_crc_tx = NULL;
 574        }
 575}
 576
 577int mcp251xfd_regmap_init(struct mcp251xfd_priv *priv)
 578{
 579        int err;
 580
 581        if (mcp251xfd_regmap_use_nocrc(priv)) {
 582                err = mcp251xfd_regmap_init_nocrc(priv);
 583
 584                if (err)
 585                        return err;
 586        } else {
 587                mcp251xfd_regmap_destroy_nocrc(priv);
 588        }
 589
 590        if (mcp251xfd_regmap_use_crc(priv)) {
 591                err = mcp251xfd_regmap_init_crc(priv);
 592
 593                if (err)
 594                        return err;
 595        } else {
 596                mcp251xfd_regmap_destroy_crc(priv);
 597        }
 598
 599        return 0;
 600}
 601