am2315.c revision 1.7 1 1.7 pgoyette /* $NetBSD: am2315.c,v 1.7 2022/03/30 00:06:50 pgoyette Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (c) 2017 Brad Spencer <brad (at) anduin.eldar.org>
5 1.1 christos *
6 1.1 christos * Permission to use, copy, modify, and distribute this software for any
7 1.1 christos * purpose with or without fee is hereby granted, provided that the above
8 1.1 christos * copyright notice and this permission notice appear in all copies.
9 1.1 christos *
10 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 1.1 christos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 1.1 christos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 1.1 christos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 1.1 christos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 1.1 christos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 1.1 christos * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 1.1 christos */
18 1.1 christos
19 1.1 christos #include <sys/cdefs.h>
20 1.7 pgoyette __KERNEL_RCSID(0, "$NetBSD: am2315.c,v 1.7 2022/03/30 00:06:50 pgoyette Exp $");
21 1.1 christos
22 1.1 christos /*
23 1.1 christos * Driver for the Aosong AM2315
24 1.1 christos */
25 1.1 christos
26 1.1 christos #include <sys/param.h>
27 1.1 christos #include <sys/systm.h>
28 1.1 christos #include <sys/kernel.h>
29 1.1 christos #include <sys/device.h>
30 1.1 christos #include <sys/module.h>
31 1.1 christos #include <sys/sysctl.h>
32 1.1 christos #include <sys/condvar.h>
33 1.1 christos #include <sys/mutex.h>
34 1.1 christos #include <sys/time.h>
35 1.1 christos
36 1.1 christos #include <dev/sysmon/sysmonvar.h>
37 1.1 christos #include <dev/i2c/i2cvar.h>
38 1.1 christos #include <dev/i2c/am2315reg.h>
39 1.1 christos #include <dev/i2c/am2315var.h>
40 1.1 christos
41 1.1 christos static uint16_t am2315_crc(uint8_t *, size_t);
42 1.1 christos static int am2315_poke(struct am2315_sc *);
43 1.1 christos static int am2315_poke_m(i2c_tag_t, i2c_addr_t, const char *, bool);
44 1.1 christos static int am2315_match(device_t, cfdata_t, void *);
45 1.1 christos static void am2315_attach(device_t, device_t, void *);
46 1.1 christos static int am2315_detach(device_t, int);
47 1.1 christos static void am2315_refresh(struct sysmon_envsys *, envsys_data_t *);
48 1.1 christos static int am2315_verify_sysctl(SYSCTLFN_ARGS);
49 1.1 christos
50 1.1 christos #define AM2315_DEBUG
51 1.1 christos #ifdef AM2315_DEBUG
52 1.1 christos #define DPRINTF(s, l, x) \
53 1.1 christos do { \
54 1.1 christos if (l <= s->sc_am2315debug) \
55 1.1 christos printf x; \
56 1.1 christos } while (/*CONSTCOND*/0)
57 1.1 christos #else
58 1.1 christos #define DPRINTF(s, l, x)
59 1.1 christos #endif
60 1.1 christos
61 1.1 christos CFATTACH_DECL_NEW(am2315temp, sizeof(struct am2315_sc),
62 1.1 christos am2315_match, am2315_attach, am2315_detach, NULL);
63 1.1 christos
64 1.1 christos static struct am2315_sensor am2315_sensors[] = {
65 1.1 christos {
66 1.1 christos .desc = "humidity",
67 1.1 christos .type = ENVSYS_SRELHUMIDITY,
68 1.1 christos },
69 1.1 christos {
70 1.1 christos .desc = "temperature",
71 1.1 christos .type = ENVSYS_STEMP,
72 1.1 christos }
73 1.1 christos };
74 1.1 christos
75 1.1 christos static uint16_t
76 1.1 christos am2315_crc(uint8_t *data, size_t len)
77 1.1 christos {
78 1.1 christos uint16_t crc = 0xffff;
79 1.1 christos
80 1.1 christos for (size_t j = 0; j < len; j++) {
81 1.1 christos crc ^= data[j];
82 1.1 christos for (size_t i = 0; i < 8; i++) {
83 1.1 christos if (crc & 0x01) {
84 1.1 christos crc >>= 1;
85 1.1 christos crc ^= 0xA001;
86 1.1 christos } else {
87 1.1 christos crc >>= 1;
88 1.1 christos }
89 1.1 christos }
90 1.1 christos }
91 1.1 christos
92 1.1 christos return crc;
93 1.1 christos }
94 1.1 christos
95 1.1 christos int
96 1.1 christos am2315_verify_sysctl(SYSCTLFN_ARGS)
97 1.1 christos {
98 1.1 christos int error, t;
99 1.1 christos struct sysctlnode node;
100 1.1 christos
101 1.1 christos node = *rnode;
102 1.1 christos t = *(int *)rnode->sysctl_data;
103 1.1 christos node.sysctl_data = &t;
104 1.1 christos error = sysctl_lookup(SYSCTLFN_CALL(&node));
105 1.1 christos if (error || newp == NULL)
106 1.1 christos return error;
107 1.1 christos
108 1.1 christos if (t < 0)
109 1.1 christos return EINVAL;
110 1.1 christos
111 1.1 christos *(int *) rnode->sysctl_data = t;
112 1.1 christos
113 1.1 christos return 0;
114 1.1 christos }
115 1.1 christos
116 1.1 christos static int
117 1.1 christos am2315_cmd(i2c_tag_t tag, i2c_addr_t addr, uint8_t dir, uint8_t cmd,
118 1.1 christos uint8_t clen, uint8_t *buf, size_t blen)
119 1.1 christos {
120 1.1 christos uint8_t command[] = { dir, cmd, clen };
121 1.1 christos if (buf)
122 1.1 christos memset(buf, 0xff, blen);
123 1.1 christos uint8_t reg = dir == AM2315_READ_REGISTERS ?
124 1.1 christos I2C_OP_READ_WITH_STOP : I2C_OP_WRITE_WITH_STOP;
125 1.1 christos
126 1.1 christos return iic_exec(tag, reg, addr, command,
127 1.1 christos __arraycount(command), buf, blen, 0);
128 1.1 christos }
129 1.1 christos
130 1.1 christos static int
131 1.1 christos am2315_read_regs(struct am2315_sc *sc, uint8_t cmd, uint8_t clen, uint8_t *buf,
132 1.1 christos size_t blen)
133 1.1 christos {
134 1.1 christos return am2315_cmd(sc->sc_tag, sc->sc_addr, AM2315_READ_REGISTERS,
135 1.1 christos cmd, clen, buf, blen);
136 1.1 christos }
137 1.1 christos
138 1.1 christos static int
139 1.1 christos am2315_poke(struct am2315_sc *sc)
140 1.1 christos {
141 1.1 christos return am2315_poke_m(sc->sc_tag, sc->sc_addr, device_xname(sc->sc_dev),
142 1.1 christos sc->sc_am2315debug >= 2);
143 1.1 christos }
144 1.1 christos
145 1.1 christos static int
146 1.1 christos am2315_poke_m(i2c_tag_t tag, i2c_addr_t addr, const char *name, bool debug)
147 1.1 christos {
148 1.1 christos uint8_t buf[5];
149 1.1 christos int error;
150 1.1 christos
151 1.1 christos error = am2315_cmd(tag, addr, AM2315_WRITE_REGISTERS,
152 1.1 christos AM2315_REGISTER_HIGH_USER1, 1, NULL, 0);
153 1.1 christos if (debug)
154 1.1 christos printf("%s: poke 1: %d\n", name, error);
155 1.1 christos
156 1.2 christos if (error)
157 1.1 christos delay(2800);
158 1.1 christos
159 1.1 christos error = am2315_cmd(tag, addr, AM2315_READ_REGISTERS,
160 1.1 christos AM2315_REGISTER_STATUS, 1, buf, __arraycount(buf));
161 1.1 christos if (debug)
162 1.2 christos printf("%s: poke 2: %d %02x %02x %02x %02x%02x\n", name, error,
163 1.2 christos buf[0], buf[1], buf[2], buf[3], buf[4]);
164 1.1 christos
165 1.2 christos if (error)
166 1.1 christos delay(2800);
167 1.1 christos return error;
168 1.1 christos }
169 1.1 christos
170 1.1 christos static int
171 1.1 christos am2315_match(device_t parent, cfdata_t match, void *aux)
172 1.1 christos {
173 1.3 thorpej struct i2c_attach_args *ia = aux;
174 1.3 thorpej int match_result;
175 1.1 christos
176 1.3 thorpej if (iic_use_direct_match(ia, match, NULL, &match_result))
177 1.3 thorpej return match_result;
178 1.1 christos
179 1.3 thorpej /* indirect config - check for standard address */
180 1.3 thorpej if (ia->ia_addr == AM2315_TYPICAL_ADDR)
181 1.3 thorpej return I2C_MATCH_ADDRESS_ONLY;
182 1.1 christos
183 1.3 thorpej return 0;
184 1.1 christos }
185 1.1 christos
186 1.1 christos static void
187 1.1 christos am2315_attach(device_t parent, device_t self, void *aux)
188 1.1 christos {
189 1.1 christos struct am2315_sc *sc = device_private(self);
190 1.1 christos struct i2c_attach_args *ia = aux;
191 1.1 christos uint8_t buf[11];
192 1.1 christos int error;
193 1.1 christos uint16_t crc, readcrc, model;
194 1.1 christos uint8_t chipver;
195 1.1 christos uint32_t id;
196 1.1 christos bool modelgood, chipvergood, idgood;
197 1.1 christos
198 1.1 christos sc->sc_dev = self;
199 1.1 christos sc->sc_tag = ia->ia_tag;
200 1.1 christos sc->sc_addr = ia->ia_addr;
201 1.1 christos sc->sc_am2315debug = 0;
202 1.1 christos sc->sc_readcount = 2;
203 1.1 christos sc->sc_readticks = 100;
204 1.1 christos sc->sc_sme = NULL;
205 1.1 christos
206 1.1 christos aprint_normal("\n");
207 1.1 christos
208 1.1 christos mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE);
209 1.1 christos mutex_init(&sc->sc_waitmutex, MUTEX_DEFAULT, IPL_NONE);
210 1.1 christos cv_init(&sc->sc_condwait, "am2315wait");
211 1.1 christos
212 1.1 christos sc->sc_numsensors = __arraycount(am2315_sensors);
213 1.1 christos
214 1.1 christos if ((sc->sc_sme = sysmon_envsys_create()) == NULL) {
215 1.1 christos aprint_error_dev(self, "unable to create sysmon structure\n");
216 1.1 christos return;
217 1.1 christos }
218 1.1 christos
219 1.1 christos /* XXX: sysctl's not destroyed on failure */
220 1.1 christos const struct sysctlnode *cnode;
221 1.1 christos int sysctlroot_num;
222 1.1 christos if ((error = sysctl_createv(&sc->sc_am2315log, 0, NULL, &cnode, 0,
223 1.1 christos CTLTYPE_NODE, device_xname(self),
224 1.1 christos SYSCTL_DESCR("am2315 controls"), NULL, 0, NULL, 0, CTL_HW,
225 1.1 christos CTL_CREATE, CTL_EOL)) != 0)
226 1.1 christos goto badsysctl;
227 1.1 christos sysctlroot_num = cnode->sysctl_num;
228 1.1 christos
229 1.1 christos #ifdef AM2315_DEBUG
230 1.1 christos if ((error = sysctl_createv(&sc->sc_am2315log, 0, NULL, &cnode,
231 1.1 christos CTLFLAG_READWRITE, CTLTYPE_INT, "debug",
232 1.1 christos SYSCTL_DESCR("Debug level"), am2315_verify_sysctl, 0,
233 1.1 christos &sc->sc_am2315debug, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
234 1.1 christos CTL_EOL)) != 0)
235 1.1 christos goto badsysctl;
236 1.1 christos
237 1.1 christos #endif
238 1.1 christos
239 1.1 christos if ((error = sysctl_createv(&sc->sc_am2315log, 0, NULL, &cnode,
240 1.1 christos CTLFLAG_READWRITE, CTLTYPE_INT, "readcount",
241 1.1 christos SYSCTL_DESCR("Number of times to read the sensor"),
242 1.1 christos am2315_verify_sysctl, 0, &sc->sc_readcount, 0, CTL_HW,
243 1.1 christos sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
244 1.1 christos goto badsysctl;
245 1.1 christos
246 1.1 christos if ((error = sysctl_createv(&sc->sc_am2315log, 0, NULL, &cnode,
247 1.1 christos CTLFLAG_READWRITE, CTLTYPE_INT, "readticks",
248 1.1 christos SYSCTL_DESCR("Number of ticks between reads"),
249 1.1 christos am2315_verify_sysctl, 0, &sc->sc_readticks, 0, CTL_HW,
250 1.1 christos sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
251 1.1 christos goto badsysctl;
252 1.1 christos
253 1.1 christos if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) {
254 1.1 christos aprint_error_dev(self,
255 1.1 christos "Could not acquire iic bus: %d\n", error);
256 1.1 christos return;
257 1.1 christos }
258 1.1 christos am2315_poke(sc);
259 1.1 christos
260 1.1 christos #define DUMP(a) \
261 1.1 christos DPRINTF(sc, 2, ("%s: read cmd+len+%s+crcl+crch values: %02x %02x " \
262 1.1 christos "%02x%02x %02x%02x -- %02x%02x%02x%02x%02x -- %04x %04x\n", a, \
263 1.1 christos device_xname(self), buf[0], buf[1], buf[2], buf[3], \
264 1.1 christos buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], \
265 1.1 christos buf[10], crc, readcrc))
266 1.1 christos
267 1.1 christos error = am2315_read_regs(sc, AM2315_REGISTER_HIGH_MODEL, 2, buf, 6);
268 1.1 christos if (error)
269 1.1 christos aprint_error_dev(sc->sc_dev, "read model: %d\n", error);
270 1.1 christos readcrc = buf[5] << 8 | buf[4];
271 1.1 christos crc = am2315_crc(buf, 4);
272 1.1 christos DUMP("modh+modl");
273 1.1 christos model = buf[2] << 8 | buf[3];
274 1.1 christos modelgood = buf[0] == AM2315_READ_REGISTERS && buf[1] == 2
275 1.1 christos && crc == readcrc;
276 1.1 christos
277 1.1 christos error = am2315_read_regs(sc, AM2315_REGISTER_VERSION, 1, buf, 5);
278 1.2 christos if (error)
279 1.1 christos aprint_error_dev(self, "read chipver: %d\n", error);
280 1.1 christos readcrc = buf[4] << 8 | buf[3];
281 1.1 christos crc = am2315_crc(buf, 3);
282 1.1 christos DUMP("ver");
283 1.1 christos chipver = buf[2];
284 1.1 christos chipvergood = buf[0] == AM2315_READ_REGISTERS && buf[1] == 1
285 1.1 christos && crc == readcrc;
286 1.1 christos
287 1.1 christos error = am2315_read_regs(sc, AM2315_REGISTER_ID_PT_24_31, 2, buf, 6);
288 1.2 christos if (error)
289 1.1 christos aprint_error_dev(self, "read id 1: %d\n", error);
290 1.1 christos readcrc = buf[5] << 8 | buf[4];
291 1.1 christos crc = am2315_crc(buf, 4);
292 1.1 christos DUMP("id1+id2");
293 1.1 christos id = buf[2] << 8 | buf[3];
294 1.1 christos idgood = buf[0] == AM2315_READ_REGISTERS && buf[1] == 2
295 1.1 christos && crc == readcrc;
296 1.1 christos
297 1.1 christos error = am2315_read_regs(sc, AM2315_REGISTER_ID_PT_8_15, 2, buf, 6);
298 1.2 christos if (error)
299 1.1 christos aprint_error_dev(self, "read id 2: %d\n", error);
300 1.1 christos readcrc = buf[5] << 8 | buf[4];
301 1.1 christos crc = am2315_crc(buf, 4);
302 1.1 christos DUMP("id3+id4");
303 1.1 christos id = id << 8 | buf[2];
304 1.1 christos id = id << 8 | buf[3];
305 1.1 christos idgood = buf[0] == AM2315_READ_REGISTERS && buf[1] == 2
306 1.1 christos && crc == readcrc && idgood;
307 1.1 christos
308 1.1 christos iic_release_bus(sc->sc_tag, 0);
309 1.1 christos
310 1.1 christos for (int i = 0; i < sc->sc_numsensors; i++) {
311 1.1 christos strlcpy(sc->sc_sensors[i].desc, am2315_sensors[i].desc,
312 1.1 christos sizeof(sc->sc_sensors[i].desc));
313 1.1 christos
314 1.1 christos sc->sc_sensors[i].units = am2315_sensors[i].type;
315 1.1 christos sc->sc_sensors[i].state = ENVSYS_SINVALID;
316 1.1 christos
317 1.1 christos DPRINTF(sc, 2, ("am2315_attach: registering sensor %d (%s)\n",
318 1.1 christos i, sc->sc_sensors[i].desc));
319 1.1 christos
320 1.1 christos error = sysmon_envsys_sensor_attach(sc->sc_sme,
321 1.1 christos &sc->sc_sensors[i]);
322 1.1 christos if (error) {
323 1.1 christos aprint_error_dev(self, "unable to attach sensor %d\n",
324 1.1 christos error);
325 1.1 christos goto badregister;
326 1.1 christos }
327 1.1 christos }
328 1.1 christos
329 1.1 christos sc->sc_sme->sme_name = device_xname(sc->sc_dev);
330 1.1 christos sc->sc_sme->sme_cookie = sc;
331 1.1 christos sc->sc_sme->sme_refresh = am2315_refresh;
332 1.1 christos
333 1.1 christos DPRINTF(sc, 2, ("am2315_attach: registering with envsys\n"));
334 1.1 christos
335 1.1 christos error = sysmon_envsys_register(sc->sc_sme);
336 1.1 christos if (error) {
337 1.1 christos aprint_error_dev(self, "unable to register with sysmon %d\n",
338 1.1 christos error);
339 1.1 christos goto badregister;
340 1.1 christos }
341 1.1 christos aprint_normal_dev(self, "Aosong AM2315, Model: %04x%s Version: %02x%s"
342 1.1 christos " ID: %08x%s",
343 1.1 christos model, (modelgood ? "," : "(inaccurate),"),
344 1.1 christos chipver, (chipvergood ? "," : "(inaccurate),"),
345 1.1 christos id, (idgood ? "\n" : "(inaccurate)\n"));
346 1.1 christos return;
347 1.1 christos
348 1.1 christos badsysctl:
349 1.1 christos aprint_error_dev(self, ": can't setup sysctl tree (%d)\n", error);
350 1.1 christos return;
351 1.1 christos badregister:
352 1.1 christos sysmon_envsys_destroy(sc->sc_sme);
353 1.1 christos sc->sc_sme = NULL;
354 1.1 christos }
355 1.1 christos
356 1.1 christos static void
357 1.1 christos am2315_refresh(struct sysmon_envsys * sme, envsys_data_t * edata)
358 1.1 christos {
359 1.1 christos struct am2315_sc *sc;
360 1.1 christos uint8_t buf[11], thecommand;
361 1.1 christos uint16_t crc, readcrc;
362 1.1 christos int error, rv;
363 1.1 christos uint32_t val32;
364 1.1 christos bool istempneg = false;
365 1.1 christos
366 1.1 christos sc = sme->sme_cookie;
367 1.1 christos edata->state = ENVSYS_SINVALID;
368 1.1 christos
369 1.1 christos mutex_enter(&sc->sc_mutex);
370 1.1 christos error = iic_acquire_bus(sc->sc_tag, 0);
371 1.2 christos if (error) {
372 1.1 christos DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %d\n",
373 1.1 christos device_xname(sc->sc_dev), error));
374 1.1 christos goto out;
375 1.1 christos }
376 1.1 christos
377 1.1 christos switch (edata->sensor) {
378 1.1 christos case AM2315_HUMIDITY_SENSOR:
379 1.1 christos thecommand = AM2315_REGISTER_HIGH_RH;
380 1.1 christos break;
381 1.1 christos case AM2315_TEMP_SENSOR:
382 1.1 christos thecommand = AM2315_REGISTER_HIGH_TEMP;
383 1.1 christos break;
384 1.1 christos default:
385 1.1 christos DPRINTF(sc, 2, ("%s: bad sensor %d\n",
386 1.1 christos device_xname(sc->sc_dev), edata->sensor));
387 1.1 christos goto out;
388 1.1 christos }
389 1.1 christos
390 1.1 christos for (int count = 0; ;) {
391 1.1 christos am2315_poke(sc);
392 1.1 christos
393 1.1 christos if ((error = am2315_read_regs(sc, thecommand, 2, buf, 6)) != 0)
394 1.2 christos DPRINTF(sc, 2, ("%s: Read sensor %d error: %d\n",
395 1.2 christos device_xname(sc->sc_dev),edata->sensor, error));
396 1.1 christos
397 1.1 christos readcrc = buf[5] << 8 | buf[4];
398 1.1 christos crc = am2315_crc(buf, 4);
399 1.1 christos
400 1.1 christos DPRINTF(sc, 2, ("%s: read cmd+len+dh+dl+crch+crcl values: %02x"
401 1.1 christos " %02x %02x%02x %02x%02x -- %04x %04x -- %d\n",
402 1.1 christos device_xname(sc->sc_dev), buf[0], buf[1], buf[2],
403 1.1 christos buf[3], buf[4], buf[5], crc, readcrc, count));
404 1.1 christos if (++count == sc->sc_readcount)
405 1.1 christos break;
406 1.1 christos mutex_enter(&sc->sc_waitmutex);
407 1.1 christos rv = cv_timedwait(&sc->sc_condwait, &sc->sc_waitmutex,
408 1.1 christos sc->sc_readticks);
409 1.1 christos DPRINTF(sc, 2, ("%s: wait rv: %d\n", device_xname(sc->sc_dev),
410 1.1 christos rv));
411 1.1 christos mutex_exit(&sc->sc_waitmutex);
412 1.1 christos }
413 1.1 christos
414 1.1 christos iic_release_bus(sc->sc_tag, 0);
415 1.1 christos
416 1.1 christos if (buf[0] != AM2315_READ_REGISTERS || buf[1] != 2 ||
417 1.1 christos crc != readcrc) {
418 1.1 christos DPRINTF(sc, 2, ("%s: Invalid sensor data for %d\n",
419 1.1 christos device_xname(sc->sc_dev), edata->sensor));
420 1.1 christos goto out;
421 1.1 christos }
422 1.1 christos
423 1.1 christos switch (edata->sensor) {
424 1.1 christos case AM2315_HUMIDITY_SENSOR:
425 1.1 christos val32 = buf[2] << 8 | buf[3];
426 1.1 christos val32 = val32 * 100000;
427 1.1 christos DPRINTF(sc, 2, ("%s: read translated values RH: %x\n",
428 1.1 christos device_xname(sc->sc_dev), val32));
429 1.1 christos edata->value_cur = val32;
430 1.1 christos edata->state = ENVSYS_SVALID;
431 1.1 christos break;
432 1.1 christos case AM2315_TEMP_SENSOR:
433 1.1 christos istempneg = (buf[2] & AM2315_TEMP_NEGATIVE);
434 1.1 christos buf[2] = buf[2] & (~AM2315_TEMP_NEGATIVE);
435 1.1 christos val32 = buf[2] << 8 | buf[3];
436 1.1 christos if (istempneg) {
437 1.1 christos val32 = 273150000 - (val32 * 100000);
438 1.1 christos } else {
439 1.1 christos val32 = (val32 * 100000) + 273150000;
440 1.1 christos }
441 1.1 christos DPRINTF(sc, 2, ("%s: read translated values TEMP: %x\n",
442 1.1 christos device_xname(sc->sc_dev), val32));
443 1.1 christos edata->value_cur = val32;
444 1.1 christos edata->state = ENVSYS_SVALID;
445 1.1 christos break;
446 1.1 christos default:
447 1.1 christos panic("bad sensor %d\n", edata->sensor);
448 1.1 christos }
449 1.1 christos out:
450 1.1 christos mutex_exit(&sc->sc_mutex);
451 1.1 christos }
452 1.1 christos
453 1.1 christos static int
454 1.1 christos am2315_detach(device_t self, int flags)
455 1.1 christos {
456 1.1 christos struct am2315_sc *sc = device_private(self);
457 1.1 christos
458 1.1 christos mutex_enter(&sc->sc_mutex);
459 1.1 christos
460 1.1 christos /* Remove the sensors */
461 1.6 mlelstv if (sc->sc_sme != NULL)
462 1.1 christos sysmon_envsys_unregister(sc->sc_sme);
463 1.1 christos mutex_exit(&sc->sc_mutex);
464 1.1 christos
465 1.1 christos /* Destroy the wait cond */
466 1.1 christos cv_destroy(&sc->sc_condwait);
467 1.1 christos
468 1.1 christos /* Remove the sysctl tree */
469 1.1 christos sysctl_teardown(&sc->sc_am2315log);
470 1.1 christos
471 1.1 christos /* Remove the mutex */
472 1.1 christos mutex_destroy(&sc->sc_waitmutex);
473 1.1 christos mutex_destroy(&sc->sc_mutex);
474 1.1 christos
475 1.1 christos return 0;
476 1.1 christos }
477 1.1 christos
478 1.7 pgoyette MODULE(MODULE_CLASS_DRIVER, am2315temp, "iic,sysmon_envsys");
479 1.1 christos
480 1.1 christos #ifdef _MODULE
481 1.1 christos #include "ioconf.c"
482 1.1 christos #endif
483 1.1 christos
484 1.1 christos static int
485 1.1 christos am2315temp_modcmd(modcmd_t cmd, void *opaque)
486 1.1 christos {
487 1.1 christos switch (cmd) {
488 1.1 christos case MODULE_CMD_INIT:
489 1.1 christos #ifdef _MODULE
490 1.1 christos return config_init_component(cfdriver_ioconf_am2315temp,
491 1.1 christos cfattach_ioconf_am2315temp, cfdata_ioconf_am2315temp);
492 1.1 christos #else
493 1.1 christos return 0;
494 1.1 christos #endif
495 1.1 christos case MODULE_CMD_FINI:
496 1.1 christos #ifdef _MODULE
497 1.1 christos return config_fini_component(cfdriver_ioconf_am2315temp,
498 1.1 christos cfattach_ioconf_am2315temp, cfdata_ioconf_am2315temp);
499 1.1 christos #else
500 1.1 christos return 0;
501 1.1 christos #endif
502 1.1 christos default:
503 1.1 christos return ENOTTY;
504 1.1 christos }
505 1.1 christos }
506