Line data Source code
1 : /* $OpenBSD: maxim6690.c,v 1.16 2007/10/20 22:06:43 cnst Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2005 Theo de Raadt
5 : *
6 : * Permission to use, copy, modify, and distribute this software for any
7 : * purpose with or without fee is hereby granted, provided that the above
8 : * copyright notice and this permission notice appear in all copies.
9 : *
10 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 : */
18 :
19 : #include <sys/param.h>
20 : #include <sys/systm.h>
21 : #include <sys/device.h>
22 : #include <sys/sensors.h>
23 :
24 : #include <dev/i2c/i2cvar.h>
25 :
26 : /* Maxim MAX6642/90 registers */
27 : #define MAX6690_INT_TEMP 0x00
28 : #define MAX6690_EXT_TEMP 0x01
29 : #define MAX6690_INT_TEMP2 0x11
30 : #define MAX6690_EXT_TEMP2 0x10
31 : #define MAX6690_STATUS 0x02
32 : #define MAX6690_DEVID 0xfe
33 : #define MAX6690_REVISION 0xff /* absent on MAX6642 */
34 :
35 : #define MAX6642_TEMP_INVALID 0xff /* sensor disconnected */
36 : #define MAX6690_TEMP_INVALID 0x80 /* sensor disconnected */
37 : #define MAX6690_TEMP_INVALID2 0x7f /* open-circuit without pull-up */
38 : #define LM90_TEMP_INVALID 0x7f /* sensor disconnected */
39 :
40 : #define MAX6642_TEMP2_MASK 0xc0 /* significant bits */
41 : #define MAX6690_TEMP2_MASK 0xe0 /* significant bits */
42 : #define LM90_TEMP2_MASK 0xe0 /* significant bits */
43 :
44 : /* Sensors */
45 : #define MAXTMP_INT 0
46 : #define MAXTMP_EXT 1
47 : #define MAXTMP_NUM_SENSORS 2
48 :
49 : struct maxtmp_softc {
50 : struct device sc_dev;
51 : i2c_tag_t sc_tag;
52 : i2c_addr_t sc_addr;
53 :
54 : u_int8_t sc_temp_invalid[2];
55 : u_int8_t sc_temp2_mask;
56 :
57 : struct ksensor sc_sensor[MAXTMP_NUM_SENSORS];
58 : struct ksensordev sc_sensordev;
59 : };
60 :
61 : int maxtmp_match(struct device *, void *, void *);
62 : void maxtmp_attach(struct device *, struct device *, void *);
63 : void maxtmp_refresh(void *);
64 :
65 : struct cfattach maxtmp_ca = {
66 : sizeof(struct maxtmp_softc), maxtmp_match, maxtmp_attach
67 : };
68 :
69 : struct cfdriver maxtmp_cd = {
70 : NULL, "maxtmp", DV_DULL
71 : };
72 :
73 : int
74 0 : maxtmp_match(struct device *parent, void *match, void *aux)
75 : {
76 0 : struct i2c_attach_args *ia = aux;
77 :
78 0 : if (strcmp(ia->ia_name, "max6642") == 0 ||
79 0 : strcmp(ia->ia_name, "max6690") == 0 ||
80 0 : strcmp(ia->ia_name, "max6657") == 0 ||
81 0 : strcmp(ia->ia_name, "max6658") == 0 ||
82 0 : strcmp(ia->ia_name, "max6659") == 0 ||
83 0 : strcmp(ia->ia_name, "lm63") == 0 ||
84 0 : strcmp(ia->ia_name, "lm86") == 0 ||
85 0 : strcmp(ia->ia_name, "lm89") == 0 ||
86 0 : strcmp(ia->ia_name, "lm89-1") == 0 ||
87 0 : strcmp(ia->ia_name, "lm90") == 0 ||
88 0 : strcmp(ia->ia_name, "lm99") == 0 ||
89 0 : strcmp(ia->ia_name, "lm99-1") == 0)
90 0 : return (1);
91 0 : return (0);
92 0 : }
93 :
94 : void
95 0 : maxtmp_attach(struct device *parent, struct device *self, void *aux)
96 : {
97 0 : struct maxtmp_softc *sc = (struct maxtmp_softc *)self;
98 0 : struct i2c_attach_args *ia = aux;
99 : int i;
100 :
101 0 : sc->sc_tag = ia->ia_tag;
102 0 : sc->sc_addr = ia->ia_addr;
103 :
104 0 : if (strcmp(ia->ia_name, "max6642") == 0) {
105 0 : sc->sc_temp_invalid[0] = MAX6642_TEMP_INVALID;
106 0 : sc->sc_temp_invalid[1] = MAX6642_TEMP_INVALID;
107 0 : sc->sc_temp2_mask = MAX6642_TEMP2_MASK;
108 0 : } else if (strcmp(ia->ia_name, "max6690") == 0 ||
109 0 : strcmp(ia->ia_name, "max6657") == 0 ||
110 0 : strcmp(ia->ia_name, "max6658") == 0 ||
111 0 : strcmp(ia->ia_name, "max6659") == 0) {
112 0 : sc->sc_temp_invalid[0] = MAX6690_TEMP_INVALID;
113 0 : sc->sc_temp_invalid[1] = MAX6690_TEMP_INVALID2;
114 0 : sc->sc_temp2_mask = MAX6690_TEMP2_MASK;
115 0 : } else {
116 0 : sc->sc_temp_invalid[0] = LM90_TEMP_INVALID;
117 0 : sc->sc_temp_invalid[1] = LM90_TEMP_INVALID;
118 0 : sc->sc_temp2_mask = LM90_TEMP2_MASK;
119 : }
120 0 : printf(": %s", ia->ia_name);
121 :
122 : /* Initialize sensor data. */
123 0 : strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
124 : sizeof(sc->sc_sensordev.xname));
125 :
126 0 : sc->sc_sensor[MAXTMP_INT].type = SENSOR_TEMP;
127 0 : strlcpy(sc->sc_sensor[MAXTMP_INT].desc, "Internal",
128 : sizeof(sc->sc_sensor[MAXTMP_INT].desc));
129 :
130 0 : sc->sc_sensor[MAXTMP_EXT].type = SENSOR_TEMP;
131 0 : strlcpy(sc->sc_sensor[MAXTMP_EXT].desc, "External",
132 : sizeof(sc->sc_sensor[MAXTMP_EXT].desc));
133 :
134 0 : if (sensor_task_register(sc, maxtmp_refresh, 5) == NULL) {
135 0 : printf(", unable to register update task\n");
136 0 : return;
137 : }
138 :
139 0 : for (i = 0; i < MAXTMP_NUM_SENSORS; i++)
140 0 : sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
141 0 : sensordev_install(&sc->sc_sensordev);
142 :
143 0 : printf("\n");
144 0 : }
145 :
146 : void maxtmp_readport(struct maxtmp_softc *, u_int8_t, u_int8_t, int);
147 :
148 : void
149 0 : maxtmp_readport(struct maxtmp_softc *sc, u_int8_t cmd1, u_int8_t cmd2,
150 : int index)
151 : {
152 0 : u_int8_t data, data2;
153 :
154 0 : if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
155 0 : sc->sc_addr, &cmd1, sizeof cmd1, &data, sizeof data, 0))
156 : goto invalid;
157 0 : if (data == sc->sc_temp_invalid[0] || data == sc->sc_temp_invalid[1])
158 : goto invalid;
159 0 : if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
160 0 : sc->sc_addr, &cmd2, sizeof cmd2, &data2, sizeof data2, 0))
161 : goto invalid;
162 :
163 : /* Set any meaningless bits to zero. */
164 0 : data2 &= sc->sc_temp2_mask;
165 :
166 0 : sc->sc_sensor[index].value = 273150000 +
167 0 : 1000000 * data + (data2 >> 5) * 1000000 / 8;
168 0 : return;
169 :
170 : invalid:
171 0 : sc->sc_sensor[index].flags |= SENSOR_FINVALID;
172 0 : }
173 :
174 : void
175 0 : maxtmp_refresh(void *arg)
176 : {
177 0 : struct maxtmp_softc *sc = arg;
178 :
179 0 : iic_acquire_bus(sc->sc_tag, 0);
180 :
181 0 : maxtmp_readport(sc, MAX6690_INT_TEMP, MAX6690_INT_TEMP2, MAXTMP_INT);
182 0 : maxtmp_readport(sc, MAX6690_EXT_TEMP, MAX6690_EXT_TEMP2, MAXTMP_EXT);
183 :
184 0 : iic_release_bus(sc->sc_tag, 0);
185 0 : }
|