ad741x.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* $OpenBSD: ad741x.c,v 1.14 2008/04/17 19:01:48 deraadt Exp $ */
  2. /*
  3. * Copyright (c) 2005 Theo de Raadt
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #include <sys/param.h>
  18. #include <sys/systm.h>
  19. #include <sys/device.h>
  20. #include <sys/sensors.h>
  21. #include <dev/i2c/i2cvar.h>
  22. /* AD741x registers */
  23. #define AD741X_TEMP 0x00
  24. #define AD741X_CONFIG 0x01
  25. #define AD741X_THYST 0x02
  26. #define AD741X_TOTI 0x03
  27. #define AD741X_ADC 0x04
  28. #define AD741X_CONFIG2 0x05
  29. #define AD741X_CONFMASK 0xe0
  30. /* Sensors */
  31. #define ADC_TEMP 0
  32. #define ADC_ADC0 1
  33. #define ADC_ADC1 2
  34. #define ADC_ADC2 3
  35. #define ADC_ADC3 4
  36. #define ADC_MAX_SENSORS 5
  37. struct adc_softc {
  38. struct device sc_dev;
  39. i2c_tag_t sc_tag;
  40. i2c_addr_t sc_addr;
  41. int sc_chip;
  42. u_int8_t sc_config;
  43. struct ksensor sc_sensor[ADC_MAX_SENSORS];
  44. struct ksensordev sc_sensordev;
  45. };
  46. int adc_match(struct device *, void *, void *);
  47. void adc_attach(struct device *, struct device *, void *);
  48. void adc_refresh(void *);
  49. struct cfattach adc_ca = {
  50. sizeof(struct adc_softc), adc_match, adc_attach
  51. };
  52. struct cfdriver adc_cd = {
  53. NULL, "adc", DV_DULL
  54. };
  55. int
  56. adc_match(struct device *parent, void *match, void *aux)
  57. {
  58. struct i2c_attach_args *ia = aux;
  59. if (strcmp(ia->ia_name, "ad7417") == 0 ||
  60. strcmp(ia->ia_name, "ad7418") == 0)
  61. return (1);
  62. return (0);
  63. }
  64. void
  65. adc_attach(struct device *parent, struct device *self, void *aux)
  66. {
  67. struct adc_softc *sc = (struct adc_softc *)self;
  68. struct i2c_attach_args *ia = aux;
  69. u_int8_t cmd, data;
  70. int nsens = 0, i;
  71. sc->sc_tag = ia->ia_tag;
  72. sc->sc_addr = ia->ia_addr;
  73. printf(": %s", ia->ia_name);
  74. sc->sc_chip = 0;
  75. if (strcmp(ia->ia_name, "ad7417") == 0)
  76. sc->sc_chip = 7417;
  77. if (strcmp(ia->ia_name, "ad7418") == 0)
  78. sc->sc_chip = 7418;
  79. if (sc->sc_chip != 0) {
  80. cmd = AD741X_CONFIG2;
  81. data = 0;
  82. if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  83. sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
  84. printf(", config2 reset failed\n");
  85. return;
  86. }
  87. }
  88. cmd = AD741X_CONFIG;
  89. if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  90. sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
  91. printf(", config reset failed\n");
  92. return;
  93. }
  94. data &= 0xfe;
  95. if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  96. sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
  97. printf(", config reset failed\n");
  98. return;
  99. }
  100. sc->sc_config = data;
  101. /* Initialize sensor data. */
  102. strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
  103. sizeof(sc->sc_sensordev.xname));
  104. sc->sc_sensor[ADC_TEMP].type = SENSOR_TEMP;
  105. strlcpy(sc->sc_sensor[ADC_TEMP].desc, "Internal",
  106. sizeof(sc->sc_sensor[ADC_TEMP].desc));
  107. nsens = 1;
  108. if (sc->sc_chip == 7417 || sc->sc_chip == 7418) {
  109. sc->sc_sensor[ADC_ADC0].type = SENSOR_INTEGER;
  110. nsens++;
  111. }
  112. if (sc->sc_chip == 7417 || sc->sc_chip == 7418) {
  113. sc->sc_sensor[ADC_ADC1].type = SENSOR_INTEGER;
  114. sc->sc_sensor[ADC_ADC2].type = SENSOR_INTEGER;
  115. sc->sc_sensor[ADC_ADC3].type = SENSOR_INTEGER;
  116. nsens += 3;
  117. }
  118. if (sensor_task_register(sc, adc_refresh, 5) == NULL) {
  119. printf(", unable to register update task\n");
  120. return;
  121. }
  122. sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[0]);
  123. if (sc->sc_chip == 7417 || sc->sc_chip == 7418)
  124. sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[1]);
  125. if (sc->sc_chip == 7417)
  126. for (i = 2; i < nsens; i++)
  127. sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
  128. sensordev_install(&sc->sc_sensordev);
  129. printf("\n");
  130. }
  131. void
  132. adc_refresh(void *arg)
  133. {
  134. struct adc_softc *sc = arg;
  135. u_int8_t cmd, reg;
  136. u_int16_t data;
  137. int i;
  138. iic_acquire_bus(sc->sc_tag, 0);
  139. reg = (sc->sc_config & AD741X_CONFMASK) | (0 << 5);
  140. if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  141. sc->sc_addr, &cmd, sizeof cmd, &reg, sizeof reg, 0))
  142. goto done;
  143. delay(1000);
  144. cmd = AD741X_TEMP;
  145. if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  146. sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
  147. goto done;
  148. sc->sc_sensor[ADC_TEMP].value = 273150000 +
  149. (betoh16(data) >> 6) * 250000;
  150. if (sc->sc_chip == 0)
  151. goto done;
  152. if (sc->sc_chip == 7418) {
  153. reg = (reg & AD741X_CONFMASK) | (4 << 5);
  154. if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  155. sc->sc_addr, &cmd, sizeof cmd, &reg, sizeof reg, 0))
  156. goto done;
  157. delay(1000);
  158. cmd = AD741X_ADC;
  159. if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  160. sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
  161. goto done;
  162. sc->sc_sensor[ADC_ADC0].value = betoh16(data) >> 6;
  163. goto done;
  164. }
  165. for (i = 0; i < 4; i++) {
  166. reg = (reg & AD741X_CONFMASK) | (i << 5);
  167. if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  168. sc->sc_addr, &cmd, sizeof cmd, &reg, sizeof reg, 0))
  169. goto done;
  170. delay(1000);
  171. cmd = AD741X_ADC;
  172. if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  173. sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
  174. goto done;
  175. sc->sc_sensor[ADC_ADC0 + i].value = betoh16(data) >> 6;
  176. }
  177. done:
  178. iic_release_bus(sc->sc_tag, 0);
  179. }