goodix_berlin_spi.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Goodix Berlin Touchscreen Driver
  4. *
  5. * Copyright (C) 2020 - 2021 Goodix, Inc.
  6. * Copyright (C) 2023 Linaro Ltd.
  7. *
  8. * Based on goodix_ts_berlin driver.
  9. */
  10. #include <linux/unaligned.h>
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/regmap.h>
  14. #include <linux/spi/spi.h>
  15. #include <linux/input.h>
  16. #include "goodix_berlin.h"
  17. #define GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN 1
  18. #define GOODIX_BERLIN_REGISTER_WIDTH 4
  19. #define GOODIX_BERLIN_SPI_READ_DUMMY_LEN 3
  20. #define GOODIX_BERLIN_SPI_READ_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \
  21. GOODIX_BERLIN_REGISTER_WIDTH + \
  22. GOODIX_BERLIN_SPI_READ_DUMMY_LEN)
  23. #define GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \
  24. GOODIX_BERLIN_REGISTER_WIDTH)
  25. #define GOODIX_BERLIN_SPI_WRITE_FLAG 0xF0
  26. #define GOODIX_BERLIN_SPI_READ_FLAG 0xF1
  27. static int goodix_berlin_spi_read(void *context, const void *reg_buf,
  28. size_t reg_size, void *val_buf,
  29. size_t val_size)
  30. {
  31. struct spi_device *spi = context;
  32. struct spi_transfer xfers;
  33. struct spi_message spi_msg;
  34. const u32 *reg = reg_buf; /* reg is stored as native u32 at start of buffer */
  35. int error;
  36. if (reg_size != GOODIX_BERLIN_REGISTER_WIDTH)
  37. return -EINVAL;
  38. u8 *buf __free(kfree) =
  39. kzalloc(GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size,
  40. GFP_KERNEL);
  41. if (!buf)
  42. return -ENOMEM;
  43. spi_message_init(&spi_msg);
  44. memset(&xfers, 0, sizeof(xfers));
  45. /* buffer format: 0xF1 + addr(4bytes) + dummy(3bytes) + data */
  46. buf[0] = GOODIX_BERLIN_SPI_READ_FLAG;
  47. put_unaligned_be32(*reg, buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN);
  48. memset(buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + GOODIX_BERLIN_REGISTER_WIDTH,
  49. 0xff, GOODIX_BERLIN_SPI_READ_DUMMY_LEN);
  50. xfers.tx_buf = buf;
  51. xfers.rx_buf = buf;
  52. xfers.len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size;
  53. xfers.cs_change = 0;
  54. spi_message_add_tail(&xfers, &spi_msg);
  55. error = spi_sync(spi, &spi_msg);
  56. if (error < 0) {
  57. dev_err(&spi->dev, "spi transfer error, %d", error);
  58. return error;
  59. }
  60. memcpy(val_buf, buf + GOODIX_BERLIN_SPI_READ_PREFIX_LEN, val_size);
  61. return error;
  62. }
  63. static int goodix_berlin_spi_write(void *context, const void *data,
  64. size_t count)
  65. {
  66. unsigned int len = count - GOODIX_BERLIN_REGISTER_WIDTH;
  67. struct spi_device *spi = context;
  68. struct spi_transfer xfers;
  69. struct spi_message spi_msg;
  70. const u32 *reg = data; /* reg is stored as native u32 at start of buffer */
  71. int error;
  72. u8 *buf __free(kfree) =
  73. kzalloc(GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN + len, GFP_KERNEL);
  74. if (!buf)
  75. return -ENOMEM;
  76. spi_message_init(&spi_msg);
  77. memset(&xfers, 0, sizeof(xfers));
  78. buf[0] = GOODIX_BERLIN_SPI_WRITE_FLAG;
  79. put_unaligned_be32(*reg, buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN);
  80. memcpy(buf + GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN,
  81. data + GOODIX_BERLIN_REGISTER_WIDTH, len);
  82. xfers.tx_buf = buf;
  83. xfers.len = GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN + len;
  84. xfers.cs_change = 0;
  85. spi_message_add_tail(&xfers, &spi_msg);
  86. error = spi_sync(spi, &spi_msg);
  87. if (error < 0) {
  88. dev_err(&spi->dev, "spi transfer error, %d", error);
  89. return error;
  90. }
  91. return 0;
  92. }
  93. static const struct regmap_config goodix_berlin_spi_regmap_conf = {
  94. .reg_bits = 32,
  95. .val_bits = 8,
  96. .read = goodix_berlin_spi_read,
  97. .write = goodix_berlin_spi_write,
  98. };
  99. /* vendor & product left unassigned here, should probably be updated from fw info */
  100. static const struct input_id goodix_berlin_spi_input_id = {
  101. .bustype = BUS_SPI,
  102. };
  103. static int goodix_berlin_spi_probe(struct spi_device *spi)
  104. {
  105. struct regmap_config regmap_config;
  106. struct regmap *regmap;
  107. size_t max_size;
  108. int error = 0;
  109. spi->mode = SPI_MODE_0;
  110. spi->bits_per_word = 8;
  111. error = spi_setup(spi);
  112. if (error)
  113. return error;
  114. max_size = spi_max_transfer_size(spi);
  115. regmap_config = goodix_berlin_spi_regmap_conf;
  116. regmap_config.max_raw_read = max_size - GOODIX_BERLIN_SPI_READ_PREFIX_LEN;
  117. regmap_config.max_raw_write = max_size - GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN;
  118. regmap = devm_regmap_init(&spi->dev, NULL, spi, &regmap_config);
  119. if (IS_ERR(regmap))
  120. return PTR_ERR(regmap);
  121. error = goodix_berlin_probe(&spi->dev, spi->irq,
  122. &goodix_berlin_spi_input_id, regmap);
  123. if (error)
  124. return error;
  125. return 0;
  126. }
  127. static const struct spi_device_id goodix_berlin_spi_ids[] = {
  128. { "gt9916" },
  129. { },
  130. };
  131. MODULE_DEVICE_TABLE(spi, goodix_berlin_spi_ids);
  132. static const struct of_device_id goodix_berlin_spi_of_match[] = {
  133. { .compatible = "goodix,gt9916", },
  134. { }
  135. };
  136. MODULE_DEVICE_TABLE(of, goodix_berlin_spi_of_match);
  137. static struct spi_driver goodix_berlin_spi_driver = {
  138. .driver = {
  139. .name = "goodix-berlin-spi",
  140. .of_match_table = goodix_berlin_spi_of_match,
  141. .pm = pm_sleep_ptr(&goodix_berlin_pm_ops),
  142. .dev_groups = goodix_berlin_groups,
  143. },
  144. .probe = goodix_berlin_spi_probe,
  145. .id_table = goodix_berlin_spi_ids,
  146. };
  147. module_spi_driver(goodix_berlin_spi_driver);
  148. MODULE_LICENSE("GPL");
  149. MODULE_DESCRIPTION("Goodix Berlin SPI Touchscreen driver");
  150. MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");