adt7310.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * ADT7310/ADT7310 digital temperature sensor driver
  4. *
  5. * Copyright 2012-2013 Analog Devices Inc.
  6. * Author: Lars-Peter Clausen <[email protected]>
  7. */
  8. #include <linux/module.h>
  9. #include <linux/init.h>
  10. #include <linux/regmap.h>
  11. #include <linux/spi/spi.h>
  12. #include <asm/unaligned.h>
  13. #include "adt7x10.h"
  14. #define ADT7310_STATUS 0
  15. #define ADT7310_CONFIG 1
  16. #define ADT7310_TEMPERATURE 2
  17. #define ADT7310_ID 3
  18. #define ADT7310_T_CRIT 4
  19. #define ADT7310_T_HYST 5
  20. #define ADT7310_T_ALARM_HIGH 6
  21. #define ADT7310_T_ALARM_LOW 7
  22. static const u8 adt7310_reg_table[] = {
  23. [ADT7X10_TEMPERATURE] = ADT7310_TEMPERATURE,
  24. [ADT7X10_STATUS] = ADT7310_STATUS,
  25. [ADT7X10_CONFIG] = ADT7310_CONFIG,
  26. [ADT7X10_T_ALARM_HIGH] = ADT7310_T_ALARM_HIGH,
  27. [ADT7X10_T_ALARM_LOW] = ADT7310_T_ALARM_LOW,
  28. [ADT7X10_T_CRIT] = ADT7310_T_CRIT,
  29. [ADT7X10_T_HYST] = ADT7310_T_HYST,
  30. [ADT7X10_ID] = ADT7310_ID,
  31. };
  32. #define ADT7310_CMD_REG_OFFSET 3
  33. #define ADT7310_CMD_READ 0x40
  34. #define AD7310_COMMAND(reg) (adt7310_reg_table[(reg)] << ADT7310_CMD_REG_OFFSET)
  35. static int adt7310_spi_read_word(struct spi_device *spi, u8 reg)
  36. {
  37. return spi_w8r16be(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ);
  38. }
  39. static int adt7310_spi_write_word(struct spi_device *spi, u8 reg, u16 data)
  40. {
  41. u8 buf[3];
  42. buf[0] = AD7310_COMMAND(reg);
  43. put_unaligned_be16(data, &buf[1]);
  44. return spi_write(spi, buf, sizeof(buf));
  45. }
  46. static int adt7310_spi_read_byte(struct spi_device *spi, u8 reg)
  47. {
  48. return spi_w8r8(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ);
  49. }
  50. static int adt7310_spi_write_byte(struct spi_device *spi, u8 reg, u8 data)
  51. {
  52. u8 buf[2];
  53. buf[0] = AD7310_COMMAND(reg);
  54. buf[1] = data;
  55. return spi_write(spi, buf, sizeof(buf));
  56. }
  57. static bool adt7310_regmap_is_volatile(struct device *dev, unsigned int reg)
  58. {
  59. switch (reg) {
  60. case ADT7X10_TEMPERATURE:
  61. case ADT7X10_STATUS:
  62. return true;
  63. default:
  64. return false;
  65. }
  66. }
  67. static int adt7310_reg_read(void *context, unsigned int reg, unsigned int *val)
  68. {
  69. struct spi_device *spi = context;
  70. int regval;
  71. switch (reg) {
  72. case ADT7X10_TEMPERATURE:
  73. case ADT7X10_T_ALARM_HIGH:
  74. case ADT7X10_T_ALARM_LOW:
  75. case ADT7X10_T_CRIT:
  76. regval = adt7310_spi_read_word(spi, reg);
  77. break;
  78. default:
  79. regval = adt7310_spi_read_byte(spi, reg);
  80. break;
  81. }
  82. if (regval < 0)
  83. return regval;
  84. *val = regval;
  85. return 0;
  86. }
  87. static int adt7310_reg_write(void *context, unsigned int reg, unsigned int val)
  88. {
  89. struct spi_device *spi = context;
  90. int ret;
  91. switch (reg) {
  92. case ADT7X10_TEMPERATURE:
  93. case ADT7X10_T_ALARM_HIGH:
  94. case ADT7X10_T_ALARM_LOW:
  95. case ADT7X10_T_CRIT:
  96. ret = adt7310_spi_write_word(spi, reg, val);
  97. break;
  98. default:
  99. ret = adt7310_spi_write_byte(spi, reg, val);
  100. break;
  101. }
  102. return ret;
  103. }
  104. static const struct regmap_config adt7310_regmap_config = {
  105. .reg_bits = 8,
  106. .val_bits = 16,
  107. .cache_type = REGCACHE_RBTREE,
  108. .volatile_reg = adt7310_regmap_is_volatile,
  109. .reg_read = adt7310_reg_read,
  110. .reg_write = adt7310_reg_write,
  111. };
  112. static int adt7310_spi_probe(struct spi_device *spi)
  113. {
  114. struct regmap *regmap;
  115. regmap = devm_regmap_init(&spi->dev, NULL, spi, &adt7310_regmap_config);
  116. if (IS_ERR(regmap))
  117. return PTR_ERR(regmap);
  118. return adt7x10_probe(&spi->dev, spi_get_device_id(spi)->name, spi->irq,
  119. regmap);
  120. }
  121. static const struct spi_device_id adt7310_id[] = {
  122. { "adt7310", 0 },
  123. { "adt7320", 0 },
  124. {}
  125. };
  126. MODULE_DEVICE_TABLE(spi, adt7310_id);
  127. static struct spi_driver adt7310_driver = {
  128. .driver = {
  129. .name = "adt7310",
  130. .pm = pm_sleep_ptr(&adt7x10_dev_pm_ops),
  131. },
  132. .probe = adt7310_spi_probe,
  133. .id_table = adt7310_id,
  134. };
  135. module_spi_driver(adt7310_driver);
  136. MODULE_AUTHOR("Lars-Peter Clausen <[email protected]>");
  137. MODULE_DESCRIPTION("ADT7310/ADT7320 driver");
  138. MODULE_LICENSE("GPL");