1 /* $OpenBSD: lm87.c,v 1.21 2022/04/06 18:59:28 naddy Exp $ */
2
3 /*
4 * Copyright (c) 2005 Mark Kettenis
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 /* LM87 registers */
27 #define LM87_2_5V 0x20
28 #define LM87_VCCP1 0x21
29 #define LM87_VCC 0x22
30 #define LM87_5V 0x23
31 #define LM87_12V 0x24
32 #define LM87_VCCP2 0x25
33 #define LM87_EXT_TEMP 0x26
34 #define LM87_INT_TEMP 0x27
35 #define LM87_FAN1 0x28
36 #define LM87_FAN2 0x29
37 #define LM87_REVISION 0x3f
38 #define LM87_CONFIG1 0x40
39 #define LM87_CONFIG1_START 0x01
40 #define LM87_CONFIG1_INTCLR 0x08
41 #define LM87_CHANNEL 0x16
42 #define LM87_CHANNEL_AIN1 0x01
43 #define LM87_CHANNEL_AIN2 0x02
44 #define LM87_FANDIV 0x47
45
46 /* Sensors */
47 #define LMENV_2_5V 0
48 #define LMENV_VCCP1 1
49 #define LMENV_VCC 2
50 #define LMENV_5V 3
51 #define LMENV_12V 4
52 #define LMENV_VCCP2 5
53 #define LMENV_EXT_TEMP 6
54 #define LMENV_INT_TEMP 7
55 #define LMENV_FAN1 8
56 #define LMENV_FAN2 9
57 #define LMENV_NUM_SENSORS 10
58
59 struct lmenv_softc {
60 struct device sc_dev;
61 i2c_tag_t sc_tag;
62 i2c_addr_t sc_addr;
63
64 struct ksensor sc_sensor[LMENV_NUM_SENSORS];
65 struct ksensordev sc_sensordev;
66 int sc_fan1_div, sc_fan2_div;
67 int sc_family;
68 };
69
70 int lmenv_match(struct device *, void *, void *);
71 void lmenv_attach(struct device *, struct device *, void *);
72
73 void lmenv_refresh(void *);
74
75 const struct cfattach lmenv_ca = {
76 sizeof(struct lmenv_softc), lmenv_match, lmenv_attach
77 };
78
79 struct cfdriver lmenv_cd = {
80 NULL, "lmenv", DV_DULL
81 };
82
83 int
lmenv_match(struct device * parent,void * match,void * aux)84 lmenv_match(struct device *parent, void *match, void *aux)
85 {
86 struct i2c_attach_args *ia = aux;
87
88 if (strcmp(ia->ia_name, "lm87") == 0 ||
89 strcmp(ia->ia_name, "lm87cimt") == 0 ||
90 strcmp(ia->ia_name, "adm9240") == 0 ||
91 strcmp(ia->ia_name, "lm81") == 0 ||
92 strcmp(ia->ia_name, "ds1780") == 0)
93 return (1);
94 return (0);
95 }
96
97 void
lmenv_attach(struct device * parent,struct device * self,void * aux)98 lmenv_attach(struct device *parent, struct device *self, void *aux)
99 {
100 struct lmenv_softc *sc = (struct lmenv_softc *)self;
101 struct i2c_attach_args *ia = aux;
102 u_int8_t cmd, data, data2, channel;
103 int i;
104
105 sc->sc_tag = ia->ia_tag;
106 sc->sc_addr = ia->ia_addr;
107
108 sc->sc_family = 87;
109 if (strcmp(ia->ia_name, "lm81") == 0 ||
110 strcmp(ia->ia_name, "adm9240") == 0 ||
111 strcmp(ia->ia_name, "ds1780") == 0)
112 sc->sc_family = 81;
113
114 iic_acquire_bus(sc->sc_tag, 0);
115
116 cmd = LM87_REVISION;
117 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
118 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
119 iic_release_bus(sc->sc_tag, 0);
120 printf(": cannot read ID register\n");
121 return;
122 }
123 printf(": %s rev %x", ia->ia_name, data);
124
125 cmd = LM87_FANDIV;
126 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
127 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
128 iic_release_bus(sc->sc_tag, 0);
129 printf(", cannot read Fan Divisor register\n");
130 return;
131 }
132 sc->sc_fan1_div = 1 << ((data >> 4) & 0x03);
133 sc->sc_fan2_div = 1 << ((data >> 6) & 0x03);
134
135 if (sc->sc_family == 87) {
136 cmd = LM87_CHANNEL;
137 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
138 sc->sc_addr, &cmd, sizeof cmd, &channel,
139 sizeof channel, 0)) {
140 iic_release_bus(sc->sc_tag, 0);
141 printf(", cannot read Channel register\n");
142 return;
143 }
144 } else
145 channel = 0;
146
147 cmd = LM87_CONFIG1;
148 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
149 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
150 iic_release_bus(sc->sc_tag, 0);
151 printf(", cannot read Configuration Register 1\n");
152 return;
153 }
154
155 /*
156 * if chip is not running, try to start it.
157 * if it is stalled doing an interrupt, unstall it
158 */
159 data2 = (data | LM87_CONFIG1_START);
160 data2 = data2 & ~LM87_CONFIG1_INTCLR;
161
162 if (data != data2) {
163 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
164 sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
165 iic_release_bus(sc->sc_tag, 0);
166 printf(", cannot write Configuration Register 1\n");
167 return;
168 }
169 printf(", starting scan");
170 }
171 iic_release_bus(sc->sc_tag, 0);
172
173 /* Initialize sensor data. */
174 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
175 sizeof(sc->sc_sensordev.xname));
176
177 sc->sc_sensor[LMENV_2_5V].type = SENSOR_VOLTS_DC;
178 strlcpy(sc->sc_sensor[LMENV_2_5V].desc, "+2.5Vin",
179 sizeof(sc->sc_sensor[LMENV_2_5V].desc));
180
181 sc->sc_sensor[LMENV_VCCP1].type = SENSOR_VOLTS_DC;
182 strlcpy(sc->sc_sensor[LMENV_VCCP1].desc, "Vccp",
183 sizeof(sc->sc_sensor[LMENV_VCCP1].desc));
184
185 sc->sc_sensor[LMENV_VCC].type = SENSOR_VOLTS_DC;
186 strlcpy(sc->sc_sensor[LMENV_VCC].desc, "+Vcc",
187 sizeof(sc->sc_sensor[LMENV_VCC].desc));
188
189 sc->sc_sensor[LMENV_5V].type = SENSOR_VOLTS_DC;
190 strlcpy(sc->sc_sensor[LMENV_5V].desc, "+5Vin/Vcc",
191 sizeof(sc->sc_sensor[LMENV_5V].desc));
192
193 sc->sc_sensor[LMENV_12V].type = SENSOR_VOLTS_DC;
194 strlcpy(sc->sc_sensor[LMENV_12V].desc, "+12Vin",
195 sizeof(sc->sc_sensor[LMENV_12V].desc));
196
197 sc->sc_sensor[LMENV_VCCP2].type = SENSOR_VOLTS_DC;
198 strlcpy(sc->sc_sensor[LMENV_VCCP2].desc, "Vccp",
199 sizeof(sc->sc_sensor[LMENV_VCCP2].desc));
200
201 sc->sc_sensor[LMENV_EXT_TEMP].type = SENSOR_TEMP;
202 strlcpy(sc->sc_sensor[LMENV_EXT_TEMP].desc, "External",
203 sizeof(sc->sc_sensor[LMENV_EXT_TEMP].desc));
204 if (sc->sc_family == 81)
205 sc->sc_sensor[LMENV_EXT_TEMP].flags |= SENSOR_FINVALID;
206
207 sc->sc_sensor[LMENV_INT_TEMP].type = SENSOR_TEMP;
208 strlcpy(sc->sc_sensor[LMENV_INT_TEMP].desc, "Internal",
209 sizeof(sc->sc_sensor[LMENV_INT_TEMP].desc));
210
211 if (channel & LM87_CHANNEL_AIN1) {
212 sc->sc_sensor[LMENV_FAN1].type = SENSOR_VOLTS_DC;
213 strlcpy(sc->sc_sensor[LMENV_FAN1].desc, "AIN1",
214 sizeof(sc->sc_sensor[LMENV_FAN1].desc));
215 } else {
216 sc->sc_sensor[LMENV_FAN1].type = SENSOR_FANRPM;
217 }
218
219 if (channel & LM87_CHANNEL_AIN2) {
220 sc->sc_sensor[LMENV_FAN2].type = SENSOR_VOLTS_DC;
221 strlcpy(sc->sc_sensor[LMENV_FAN2].desc, "AIN2",
222 sizeof(sc->sc_sensor[LMENV_FAN2].desc));
223 } else {
224 sc->sc_sensor[LMENV_FAN2].type = SENSOR_FANRPM;
225 }
226
227 if (sensor_task_register(sc, lmenv_refresh, 5) == NULL) {
228 printf(", unable to register update task\n");
229 return;
230 }
231
232 for (i = 0; i < LMENV_NUM_SENSORS; i++)
233 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
234 sensordev_install(&sc->sc_sensordev);
235
236 printf("\n");
237 }
238
239 void
lmenv_refresh(void * arg)240 lmenv_refresh(void *arg)
241 {
242 struct lmenv_softc *sc = arg;
243 u_int8_t cmd, data;
244 u_int tmp;
245 int sensor;
246
247 iic_acquire_bus(sc->sc_tag, 0);
248
249 for (sensor = 0; sensor < LMENV_NUM_SENSORS; sensor++) {
250 cmd = LM87_2_5V + sensor;
251 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
252 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
253 sc->sc_sensor[sensor].flags |= SENSOR_FINVALID;
254 continue;
255 }
256
257 sc->sc_sensor[sensor].flags &= ~SENSOR_FINVALID;
258 switch (sensor) {
259 case LMENV_2_5V:
260 sc->sc_sensor[sensor].value = 2500000 * data / 192;
261 break;
262 case LMENV_5V:
263 sc->sc_sensor[sensor].value = 5000000 * data / 192;
264 break;
265 case LMENV_12V:
266 sc->sc_sensor[sensor].value = 12000000 * data / 192;
267 break;
268 case LMENV_VCCP1:
269 case LMENV_VCCP2:
270 sc->sc_sensor[sensor].value = 2700000 * data / 192;
271 break;
272 case LMENV_VCC:
273 sc->sc_sensor[sensor].value = 3300000 * data / 192;
274 break;
275 case LMENV_EXT_TEMP:
276 if (sc->sc_family == 81) {
277 sc->sc_sensor[sensor].flags |= SENSOR_FINVALID;
278 break; /* missing on LM81 */
279 }
280 /* FALLTHROUGH */
281 case LMENV_INT_TEMP:
282 if (data == 0x80)
283 sc->sc_sensor[sensor].flags |= SENSOR_FINVALID;
284 else
285 sc->sc_sensor[sensor].value =
286 (int8_t)data * 1000000 + 273150000;
287 break;
288 case LMENV_FAN1:
289 if (sc->sc_sensor[sensor].type == SENSOR_VOLTS_DC) {
290 sc->sc_sensor[sensor].value =
291 1870000 * data / 192;
292 break;
293 }
294 tmp = data * sc->sc_fan1_div;
295 if (tmp == 0)
296 sc->sc_sensor[sensor].flags |= SENSOR_FINVALID;
297 else
298 sc->sc_sensor[sensor].value = 1350000 / tmp;
299 break;
300 case LMENV_FAN2:
301 if (sc->sc_sensor[sensor].type == SENSOR_VOLTS_DC) {
302 sc->sc_sensor[sensor].value =
303 1870000 * data / 192;
304 break;
305 }
306 tmp = data * sc->sc_fan2_div;
307 if (tmp == 0)
308 sc->sc_sensor[sensor].flags |= SENSOR_FINVALID;
309 else
310 sc->sc_sensor[sensor].value = 1350000 / tmp;
311 break;
312 default:
313 sc->sc_sensor[sensor].flags |= SENSOR_FINVALID;
314 break;
315 }
316 }
317
318 iic_release_bus(sc->sc_tag, 0);
319 }
320