mcp251xfd-regmap.c 16 KB

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