tcan4x5x-regmap.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // tcan4x5x - Texas Instruments TCAN4x5x Family CAN controller driver
  4. //
  5. // Copyright (c) 2020 Pengutronix,
  6. // Marc Kleine-Budde <kernel@pengutronix.de>
  7. // Copyright (c) 2018-2019 Texas Instruments Incorporated
  8. // http://www.ti.com/
  9. #include "tcan4x5x.h"
  10. #define TCAN4X5X_SPI_INSTRUCTION_WRITE (0x61 << 24)
  11. #define TCAN4X5X_SPI_INSTRUCTION_READ (0x41 << 24)
  12. #define TCAN4X5X_MAX_REGISTER 0x87fc
  13. static int tcan4x5x_regmap_gather_write(void *context,
  14. const void *reg, size_t reg_len,
  15. const void *val, size_t val_len)
  16. {
  17. struct spi_device *spi = context;
  18. struct tcan4x5x_priv *priv = spi_get_drvdata(spi);
  19. struct tcan4x5x_map_buf *buf_tx = &priv->map_buf_tx;
  20. struct spi_transfer xfer[] = {
  21. {
  22. .tx_buf = buf_tx,
  23. .len = sizeof(buf_tx->cmd) + val_len,
  24. },
  25. };
  26. memcpy(&buf_tx->cmd, reg, sizeof(buf_tx->cmd.cmd) +
  27. sizeof(buf_tx->cmd.addr));
  28. tcan4x5x_spi_cmd_set_len(&buf_tx->cmd, val_len);
  29. memcpy(buf_tx->data, val, val_len);
  30. return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
  31. }
  32. static int tcan4x5x_regmap_write(void *context, const void *data, size_t count)
  33. {
  34. return tcan4x5x_regmap_gather_write(context, data, sizeof(__be32),
  35. data + sizeof(__be32),
  36. count - sizeof(__be32));
  37. }
  38. static int tcan4x5x_regmap_read(void *context,
  39. const void *reg_buf, size_t reg_len,
  40. void *val_buf, size_t val_len)
  41. {
  42. struct spi_device *spi = context;
  43. struct tcan4x5x_priv *priv = spi_get_drvdata(spi);
  44. struct tcan4x5x_map_buf *buf_rx = &priv->map_buf_rx;
  45. struct tcan4x5x_map_buf *buf_tx = &priv->map_buf_tx;
  46. struct spi_transfer xfer[2] = {
  47. {
  48. .tx_buf = buf_tx,
  49. }
  50. };
  51. struct spi_message msg;
  52. int err;
  53. spi_message_init(&msg);
  54. spi_message_add_tail(&xfer[0], &msg);
  55. memcpy(&buf_tx->cmd, reg_buf, sizeof(buf_tx->cmd.cmd) +
  56. sizeof(buf_tx->cmd.addr));
  57. tcan4x5x_spi_cmd_set_len(&buf_tx->cmd, val_len);
  58. if (spi->controller->flags & SPI_CONTROLLER_HALF_DUPLEX) {
  59. xfer[0].len = sizeof(buf_tx->cmd);
  60. xfer[1].rx_buf = val_buf;
  61. xfer[1].len = val_len;
  62. spi_message_add_tail(&xfer[1], &msg);
  63. } else {
  64. xfer[0].rx_buf = buf_rx;
  65. xfer[0].len = sizeof(buf_tx->cmd) + val_len;
  66. if (TCAN4X5X_SANITIZE_SPI)
  67. memset(buf_tx->data, 0x0, val_len);
  68. }
  69. err = spi_sync(spi, &msg);
  70. if (err)
  71. return err;
  72. if (!(spi->controller->flags & SPI_CONTROLLER_HALF_DUPLEX))
  73. memcpy(val_buf, buf_rx->data, val_len);
  74. return 0;
  75. }
  76. static const struct regmap_range tcan4x5x_reg_table_wr_range[] = {
  77. /* Device ID and SPI Registers */
  78. regmap_reg_range(0x000c, 0x0010),
  79. /* Device configuration registers and Interrupt Flags*/
  80. regmap_reg_range(0x0800, 0x080c),
  81. regmap_reg_range(0x0820, 0x0820),
  82. regmap_reg_range(0x0830, 0x0830),
  83. /* M_CAN */
  84. regmap_reg_range(0x100c, 0x102c),
  85. regmap_reg_range(0x1048, 0x1048),
  86. regmap_reg_range(0x1050, 0x105c),
  87. regmap_reg_range(0x1080, 0x1088),
  88. regmap_reg_range(0x1090, 0x1090),
  89. regmap_reg_range(0x1098, 0x10a0),
  90. regmap_reg_range(0x10a8, 0x10b0),
  91. regmap_reg_range(0x10b8, 0x10c0),
  92. regmap_reg_range(0x10c8, 0x10c8),
  93. regmap_reg_range(0x10d0, 0x10d4),
  94. regmap_reg_range(0x10e0, 0x10e4),
  95. regmap_reg_range(0x10f0, 0x10f0),
  96. regmap_reg_range(0x10f8, 0x10f8),
  97. /* MRAM */
  98. regmap_reg_range(0x8000, 0x87fc),
  99. };
  100. static const struct regmap_range tcan4x5x_reg_table_rd_range[] = {
  101. regmap_reg_range(0x0000, 0x0010), /* Device ID and SPI Registers */
  102. regmap_reg_range(0x0800, 0x0830), /* Device configuration registers and Interrupt Flags*/
  103. regmap_reg_range(0x1000, 0x10fc), /* M_CAN */
  104. regmap_reg_range(0x8000, 0x87fc), /* MRAM */
  105. };
  106. static const struct regmap_access_table tcan4x5x_reg_table_wr = {
  107. .yes_ranges = tcan4x5x_reg_table_wr_range,
  108. .n_yes_ranges = ARRAY_SIZE(tcan4x5x_reg_table_wr_range),
  109. };
  110. static const struct regmap_access_table tcan4x5x_reg_table_rd = {
  111. .yes_ranges = tcan4x5x_reg_table_rd_range,
  112. .n_yes_ranges = ARRAY_SIZE(tcan4x5x_reg_table_rd_range),
  113. };
  114. static const struct regmap_config tcan4x5x_regmap = {
  115. .reg_bits = 24,
  116. .reg_stride = 4,
  117. .pad_bits = 8,
  118. .val_bits = 32,
  119. .wr_table = &tcan4x5x_reg_table_wr,
  120. .rd_table = &tcan4x5x_reg_table_rd,
  121. .max_register = TCAN4X5X_MAX_REGISTER,
  122. .cache_type = REGCACHE_NONE,
  123. .read_flag_mask = (__force unsigned long)
  124. cpu_to_be32(TCAN4X5X_SPI_INSTRUCTION_READ),
  125. .write_flag_mask = (__force unsigned long)
  126. cpu_to_be32(TCAN4X5X_SPI_INSTRUCTION_WRITE),
  127. };
  128. static const struct regmap_bus tcan4x5x_bus = {
  129. .write = tcan4x5x_regmap_write,
  130. .gather_write = tcan4x5x_regmap_gather_write,
  131. .read = tcan4x5x_regmap_read,
  132. .reg_format_endian_default = REGMAP_ENDIAN_BIG,
  133. .val_format_endian_default = REGMAP_ENDIAN_BIG,
  134. .max_raw_read = 256,
  135. .max_raw_write = 256,
  136. };
  137. int tcan4x5x_regmap_init(struct tcan4x5x_priv *priv)
  138. {
  139. priv->regmap = devm_regmap_init(&priv->spi->dev, &tcan4x5x_bus,
  140. priv->spi, &tcan4x5x_regmap);
  141. return PTR_ERR_OR_ZERO(priv->regmap);
  142. }