adt7462.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /* $OpenBSD: adt7462.c,v 1.6 2008/04/23 11:11:14 deraadt Exp $ */
  2. /*
  3. * Copyright (c) 2008 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. #define ADT7462_TEMPL 0x88
  23. #define ADT7462_TEMPH 0x89
  24. #define ADT7462_TEMP1L 0x8a
  25. #define ADT7462_TEMP1H 0x8b
  26. #define ADT7462_TEMP2L 0x8c
  27. #define ADT7462_TEMP2H 0x8d
  28. #define ADT7462_TEMP3L 0x8e
  29. #define ADT7462_TEMP3H 0x8f
  30. #define ADT7262_TACH1L 0x98
  31. #define ADT7262_TACH1H 0x99
  32. #define ADT7262_TACH2L 0x9a
  33. #define ADT7262_TACH2H 0x9b
  34. #define ADT7262_TACH3L 0x9c
  35. #define ADT7262_TACH3H 0x9d
  36. #define ADT7262_TACH4L 0x9e
  37. #define ADT7262_TACH4H 0x9f
  38. #define ADT7262_TACH5L 0xa2
  39. #define ADT7262_TACH5H 0xa3
  40. #define ADT7262_TACH6L 0xa4
  41. #define ADT7262_TACH6H 0xa5
  42. #define ADT7262_TACH7L 0xa6
  43. #define ADT7262_TACH7H 0xa7
  44. #define ADT7262_TACH8L 0xa8
  45. #define ADT7262_TACH8H 0xa9
  46. /* Sensors */
  47. #define ADTFSM_TEMP0 0
  48. #define ADTFSM_TEMP1 1
  49. #define ADTFSM_TEMP2 2
  50. #define ADTFSM_TEMP3 3
  51. #define ADTFSM_TACH1 4
  52. #define ADTFSM_TACH2 5
  53. #define ADTFSM_TACH3 6
  54. #define ADTFSM_TACH4 7
  55. #define ADTFSM_TACH5 8
  56. #define ADTFSM_TACH6 9
  57. #define ADTFSM_TACH7 10
  58. #define ADTFSM_TACH8 11
  59. #define ADTFSM_NUM_SENSORS 12
  60. struct adtfsm_softc {
  61. struct device sc_dev;
  62. i2c_tag_t sc_tag;
  63. i2c_addr_t sc_addr;
  64. int sc_fanmul;
  65. struct ksensor sc_sensor[ADTFSM_NUM_SENSORS];
  66. struct ksensordev sc_sensordev;
  67. };
  68. int adtfsm_match(struct device *, void *, void *);
  69. void adtfsm_attach(struct device *, struct device *, void *);
  70. void adtfsm_refresh(void *);
  71. struct cfattach adtfsm_ca = {
  72. sizeof(struct adtfsm_softc), adtfsm_match, adtfsm_attach
  73. };
  74. struct cfdriver adtfsm_cd = {
  75. NULL, "adtfsm", DV_DULL
  76. };
  77. int
  78. adtfsm_match(struct device *parent, void *match, void *aux)
  79. {
  80. struct i2c_attach_args *ia = aux;
  81. if (strcmp(ia->ia_name, "adt7462") == 0)
  82. return (1);
  83. return (0);
  84. }
  85. void
  86. adtfsm_attach(struct device *parent, struct device *self, void *aux)
  87. {
  88. struct adtfsm_softc *sc = (struct adtfsm_softc *)self;
  89. struct i2c_attach_args *ia = aux;
  90. int i;
  91. sc->sc_tag = ia->ia_tag;
  92. sc->sc_addr = ia->ia_addr;
  93. /* Initialize sensor data. */
  94. strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
  95. sizeof(sc->sc_sensordev.xname));
  96. for (i = ADTFSM_TEMP0; i <= ADTFSM_TEMP3; i++) {
  97. sc->sc_sensor[i].type = SENSOR_TEMP;
  98. sc->sc_sensor[i].flags |= SENSOR_FINVALID;
  99. }
  100. strlcpy(sc->sc_sensor[0].desc, "Internal",
  101. sizeof(sc->sc_sensor[0].desc));
  102. for (i = 1; i < 4; i++)
  103. strlcpy(sc->sc_sensor[i].desc, "External",
  104. sizeof(sc->sc_sensor[i].desc));
  105. for (i = ADTFSM_TACH1; i <= ADTFSM_TACH8; i++) {
  106. sc->sc_sensor[i].type = SENSOR_FANRPM;
  107. sc->sc_sensor[i].flags |= SENSOR_FINVALID;
  108. }
  109. if (sensor_task_register(sc, adtfsm_refresh, 5) == NULL) {
  110. printf(", unable to register update task\n");
  111. return;
  112. }
  113. for (i = 0; i < ADTFSM_NUM_SENSORS; i++)
  114. sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
  115. sensordev_install(&sc->sc_sensordev);
  116. printf("\n");
  117. }
  118. void
  119. adtfsm_refresh(void *arg)
  120. {
  121. struct adtfsm_softc *sc = arg;
  122. u_int8_t cmdh, cmdl, datah = 0x01, datal = 0x02;
  123. struct ksensor *ks;
  124. u_short ut;
  125. short t;
  126. int i;
  127. iic_acquire_bus(sc->sc_tag, 0);
  128. for (i = 0; i <= ADTFSM_TEMP3 - ADTFSM_TEMP0; i++) {
  129. cmdl = ADT7462_TEMPL + i * 2;
  130. cmdh = ADT7462_TEMPH + i * 2;
  131. ks = &sc->sc_sensor[ADTFSM_TEMP0 + i];
  132. if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  133. sc->sc_addr, &cmdl, sizeof cmdl, &datal,
  134. sizeof datal, 0) == 0 &&
  135. iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  136. sc->sc_addr, &cmdh, sizeof cmdh, &datah,
  137. sizeof datah, 0) == 0) {
  138. t = (((datah << 8) | datal) >> 6) - (64 << 2);
  139. ks->value = 273150000 + t * 250000;
  140. ks->flags &= ~SENSOR_FINVALID;
  141. } else
  142. ks->flags |= SENSOR_FINVALID;
  143. }
  144. for (i = 0; i <= ADTFSM_TACH8 - ADTFSM_TACH1; i++) {
  145. cmdl = ADT7262_TACH1L + i * 2;
  146. cmdh = ADT7262_TACH1H + i * 2;
  147. ks = &sc->sc_sensor[ADTFSM_TACH1 + i];
  148. if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  149. sc->sc_addr, &cmdl, sizeof cmdl, &datal,
  150. sizeof datal, 0) == 0 &&
  151. iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  152. sc->sc_addr, &cmdh, sizeof cmdh, &datah,
  153. sizeof datah, 0) == 0) {
  154. ut = ((datah << 8) | datal);
  155. if (ut == 0x0000 || ut == 0xffff)
  156. ks->flags |= SENSOR_FINVALID;
  157. else {
  158. ks->value = 90000 * 60 / ut;
  159. ks->flags &= ~SENSOR_FINVALID;
  160. }
  161. } else
  162. ks->flags |= SENSOR_FINVALID;
  163. }
  164. iic_release_bus(sc->sc_tag, 0);
  165. }