1 1.12 brad /* $NetBSD: si70xx.c,v 1.12 2025/01/23 19:13:19 brad 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.12 brad __KERNEL_RCSID(0, "$NetBSD: si70xx.c,v 1.12 2025/01/23 19:13:19 brad Exp $"); 21 1.1 christos 22 1.1 christos /* 23 1.9 brad Driver for the Silicon Labs SI7013/SI7020/SI7021, HTU21D and SHT21 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/mutex.h> 33 1.1 christos 34 1.1 christos #include <dev/sysmon/sysmonvar.h> 35 1.1 christos #include <dev/i2c/i2cvar.h> 36 1.1 christos #include <dev/i2c/si70xxreg.h> 37 1.1 christos #include <dev/i2c/si70xxvar.h> 38 1.1 christos 39 1.1 christos 40 1.1 christos static uint8_t si70xx_crc(uint8_t *, size_t); 41 1.1 christos static int si70xx_poke(i2c_tag_t, i2c_addr_t, bool); 42 1.1 christos static int si70xx_match(device_t, cfdata_t, void *); 43 1.1 christos static void si70xx_attach(device_t, device_t, void *); 44 1.1 christos static int si70xx_detach(device_t, int); 45 1.1 christos static void si70xx_refresh(struct sysmon_envsys *, envsys_data_t *); 46 1.1 christos static int si70xx_update_status(struct si70xx_sc *); 47 1.1 christos static int si70xx_set_heateron(struct si70xx_sc *); 48 1.1 christos static int si70xx_set_resolution(struct si70xx_sc *, size_t); 49 1.1 christos static int si70xx_set_heatervalue(struct si70xx_sc *, size_t); 50 1.1 christos static int si70xx_verify_sysctl(SYSCTLFN_ARGS); 51 1.1 christos static int si70xx_verify_sysctl_resolution(SYSCTLFN_ARGS); 52 1.1 christos static int si70xx_verify_sysctl_heateron(SYSCTLFN_ARGS); 53 1.1 christos static int si70xx_verify_sysctl_heatervalue(SYSCTLFN_ARGS); 54 1.1 christos 55 1.1 christos #define SI70XX_DEBUG 56 1.1 christos #ifdef SI70XX_DEBUG 57 1.1 christos #define DPRINTF(s, l, x) \ 58 1.1 christos do { \ 59 1.1 christos if (l <= s->sc_si70xxdebug) \ 60 1.1 christos printf x; \ 61 1.1 christos } while (/*CONSTCOND*/0) 62 1.1 christos #else 63 1.1 christos #define DPRINTF(s, l, x) 64 1.1 christos #endif 65 1.1 christos 66 1.1 christos CFATTACH_DECL_NEW(si70xxtemp, sizeof(struct si70xx_sc), 67 1.1 christos si70xx_match, si70xx_attach, si70xx_detach, NULL); 68 1.1 christos 69 1.1 christos static struct si70xx_sensor si70xx_sensors[] = { 70 1.1 christos { 71 1.1 christos .desc = "humidity", 72 1.1 christos .type = ENVSYS_SRELHUMIDITY, 73 1.1 christos }, 74 1.1 christos { 75 1.1 christos .desc = "temperature", 76 1.1 christos .type = ENVSYS_STEMP, 77 1.1 christos } 78 1.1 christos }; 79 1.1 christos 80 1.1 christos static struct si70xx_resolution si70xx_resolutions[] = { 81 1.1 christos { 82 1.1 christos .text = "12bit/14bit", 83 1.1 christos .num = 0x00, 84 1.1 christos }, 85 1.1 christos { 86 1.1 christos .text = "8bit/12bit", 87 1.1 christos .num = 0x01, 88 1.1 christos }, 89 1.1 christos { 90 1.1 christos .text = "10bit/13bit", 91 1.1 christos .num = 0x80, 92 1.1 christos }, 93 1.1 christos { 94 1.1 christos .text = "11bit/11bit", 95 1.1 christos .num = 0x81, 96 1.1 christos } 97 1.1 christos }; 98 1.1 christos 99 1.1 christos static const char si70xx_resolution_names[] = 100 1.1 christos "12bit/14bit, 8bit/12bit, 10bit/13bit, 11bit/11bit"; 101 1.1 christos 102 1.1 christos static const int si70xx_heatervalues[] = { 103 1.1 christos 0xdeadbeef, 0x00, 0x01, 0x02, 0x04, 0x08, 0x0f 104 1.1 christos }; 105 1.1 christos 106 1.1 christos int 107 1.1 christos si70xx_verify_sysctl(SYSCTLFN_ARGS) 108 1.1 christos { 109 1.1 christos int error, t; 110 1.1 christos struct sysctlnode node; 111 1.1 christos 112 1.1 christos node = *rnode; 113 1.1 christos t = *(int *)rnode->sysctl_data; 114 1.1 christos node.sysctl_data = &t; 115 1.1 christos error = sysctl_lookup(SYSCTLFN_CALL(&node)); 116 1.1 christos if (error || newp == NULL) 117 1.1 christos return error; 118 1.1 christos 119 1.1 christos if (t < 0) 120 1.1 christos return EINVAL; 121 1.1 christos 122 1.1 christos *(int *)rnode->sysctl_data = t; 123 1.1 christos 124 1.1 christos return 0; 125 1.1 christos } 126 1.1 christos 127 1.1 christos int 128 1.1 christos si70xx_verify_sysctl_resolution(SYSCTLFN_ARGS) 129 1.1 christos { 130 1.1 christos char buf[SI70XX_RES_NAME]; 131 1.1 christos struct si70xx_sc *sc; 132 1.1 christos struct sysctlnode node; 133 1.1 christos int error = 0; 134 1.1 christos size_t i; 135 1.1 christos 136 1.1 christos node = *rnode; 137 1.1 christos sc = node.sysctl_data; 138 1.1 christos (void) memcpy(buf, sc->sc_resolution, SI70XX_RES_NAME); 139 1.1 christos node.sysctl_data = buf; 140 1.1 christos error = sysctl_lookup(SYSCTLFN_CALL(&node)); 141 1.1 christos if (error || newp == NULL) 142 1.1 christos return error; 143 1.1 christos 144 1.1 christos for (i = 0; i < __arraycount(si70xx_resolutions); i++) { 145 1.1 christos if (memcmp(node.sysctl_data, si70xx_resolutions[i].text, 146 1.1 christos SI70XX_RES_NAME) == 0) 147 1.1 christos break; 148 1.1 christos } 149 1.1 christos 150 1.1 christos if (i == __arraycount(si70xx_resolutions)) 151 1.1 christos return EINVAL; 152 1.1 christos (void) memcpy(sc->sc_resolution, node.sysctl_data, SI70XX_RES_NAME); 153 1.1 christos 154 1.1 christos error = si70xx_set_resolution(sc, i); 155 1.1 christos 156 1.1 christos return error; 157 1.1 christos } 158 1.1 christos 159 1.1 christos int 160 1.1 christos si70xx_verify_sysctl_heateron(SYSCTLFN_ARGS) 161 1.1 christos { 162 1.1 christos int error; 163 1.1 christos bool t; 164 1.1 christos struct si70xx_sc *sc; 165 1.1 christos struct sysctlnode node; 166 1.1 christos 167 1.1 christos node = *rnode; 168 1.1 christos sc = node.sysctl_data; 169 1.1 christos t = sc->sc_heateron; 170 1.1 christos node.sysctl_data = &t; 171 1.1 christos error = sysctl_lookup(SYSCTLFN_CALL(&node)); 172 1.1 christos if (error || newp == NULL) 173 1.1 christos return error; 174 1.1 christos 175 1.1 christos sc->sc_heateron = t; 176 1.1 christos error = si70xx_set_heateron(sc); 177 1.1 christos 178 1.1 christos return error; 179 1.1 christos } 180 1.1 christos 181 1.1 christos int 182 1.1 christos si70xx_verify_sysctl_heatervalue(SYSCTLFN_ARGS) 183 1.1 christos { 184 1.1 christos int error = 0, t; 185 1.1 christos struct si70xx_sc *sc; 186 1.1 christos struct sysctlnode node; 187 1.1 christos 188 1.1 christos node = *rnode; 189 1.1 christos sc = node.sysctl_data; 190 1.1 christos t = sc->sc_heaterval; 191 1.1 christos node.sysctl_data = &t; 192 1.1 christos error = sysctl_lookup(SYSCTLFN_CALL(&node)); 193 1.1 christos if (error || newp == NULL) 194 1.1 christos return (error); 195 1.1 christos 196 1.1 christos if (t < 1 || t >= __arraycount(si70xx_heatervalues)) 197 1.1 christos return (EINVAL); 198 1.1 christos 199 1.1 christos sc->sc_heaterval = t; 200 1.1 christos error = si70xx_set_heatervalue(sc, t); 201 1.1 christos 202 1.1 christos return error; 203 1.1 christos } 204 1.1 christos 205 1.3 christos static uint8_t 206 1.3 christos si70xx_dir(uint8_t cmd, size_t len) 207 1.1 christos { 208 1.3 christos switch (cmd) { 209 1.1 christos case SI70XX_READ_USER_REG_1: 210 1.1 christos case SI70XX_READ_HEATER_REG: 211 1.1 christos case SI70XX_READ_ID_PT1A: 212 1.1 christos case SI70XX_READ_ID_PT1B: 213 1.1 christos case SI70XX_READ_ID_PT2A: 214 1.1 christos case SI70XX_READ_ID_PT2B: 215 1.1 christos case SI70XX_READ_FW_VERA: 216 1.1 christos case SI70XX_READ_FW_VERB: 217 1.12 brad case SI70XX_MEASURE_RH_HOLD: 218 1.12 brad case SI70XX_MEASURE_TEMP_HOLD: 219 1.3 christos return I2C_OP_READ_WITH_STOP; 220 1.1 christos case SI70XX_WRITE_USER_REG_1: 221 1.1 christos case SI70XX_WRITE_HEATER_REG: 222 1.1 christos case SI70XX_RESET: 223 1.3 christos return I2C_OP_WRITE_WITH_STOP; 224 1.1 christos case SI70XX_MEASURE_RH_NOHOLD: 225 1.1 christos case SI70XX_MEASURE_TEMP_NOHOLD: 226 1.12 brad return len == 0 ? I2C_OP_WRITE : I2C_OP_READ_WITH_STOP; 227 1.1 christos default: 228 1.3 christos panic("%s: bad command %#x\n", __func__, cmd); 229 1.3 christos return 0; 230 1.1 christos } 231 1.3 christos } 232 1.3 christos 233 1.3 christos static int 234 1.3 christos si70xx_cmd(i2c_tag_t tag, i2c_addr_t addr, uint8_t *cmd, 235 1.3 christos uint8_t clen, uint8_t *buf, size_t blen) 236 1.3 christos { 237 1.3 christos uint8_t dir; 238 1.3 christos if (clen == 0) 239 1.3 christos dir = blen == 0 ? I2C_OP_READ : I2C_OP_READ_WITH_STOP; 240 1.3 christos else 241 1.3 christos dir = si70xx_dir(cmd[0], blen); 242 1.3 christos 243 1.3 christos if (dir == I2C_OP_READ || dir == I2C_OP_READ_WITH_STOP) 244 1.3 christos memset(buf, 0, blen); 245 1.1 christos 246 1.1 christos return iic_exec(tag, dir, addr, cmd, clen, buf, blen, 0); 247 1.1 christos } 248 1.1 christos 249 1.1 christos static int 250 1.1 christos si70xx_cmd0(struct si70xx_sc *sc, uint8_t *buf, size_t blen) 251 1.1 christos { 252 1.1 christos return si70xx_cmd(sc->sc_tag, sc->sc_addr, NULL, 0, buf, blen); 253 1.1 christos } 254 1.1 christos 255 1.1 christos static int 256 1.1 christos si70xx_cmd1(struct si70xx_sc *sc, uint8_t cmd, uint8_t *buf, size_t blen) 257 1.1 christos { 258 1.1 christos return si70xx_cmd(sc->sc_tag, sc->sc_addr, &cmd, 1, buf, blen); 259 1.1 christos } 260 1.1 christos 261 1.1 christos static int 262 1.1 christos si70xx_cmd2(struct si70xx_sc *sc, uint8_t cmd1, uint8_t cmd2, uint8_t *buf, 263 1.1 christos size_t blen) 264 1.1 christos { 265 1.1 christos uint8_t cmd[] = { cmd1, cmd2 }; 266 1.1 christos return si70xx_cmd(sc->sc_tag, sc->sc_addr, cmd, __arraycount(cmd), 267 1.1 christos buf, blen); 268 1.1 christos } 269 1.1 christos 270 1.1 christos static int 271 1.1 christos si70xx_set_heateron(struct si70xx_sc * sc) 272 1.1 christos { 273 1.1 christos int error; 274 1.1 christos uint8_t userregister; 275 1.1 christos 276 1.1 christos error = iic_acquire_bus(sc->sc_tag, 0); 277 1.1 christos if (error) { 278 1.1 christos DPRINTF(sc, 2, ("%s:%s: Failed to acquire bus: %d\n", 279 1.1 christos device_xname(sc->sc_dev), __func__, error)); 280 1.1 christos return error; 281 1.1 christos } 282 1.1 christos 283 1.1 christos error = si70xx_cmd1(sc, SI70XX_READ_USER_REG_1, &userregister, 1); 284 1.1 christos if (error) { 285 1.1 christos DPRINTF(sc, 2, ("%s: Failed to read user register 1: %d\n", 286 1.1 christos device_xname(sc->sc_dev), error)); 287 1.1 christos goto out; 288 1.1 christos } 289 1.1 christos 290 1.1 christos DPRINTF(sc, 2, ("%s:%s: reg 1 values before: %#x\n", 291 1.1 christos device_xname(sc->sc_dev), __func__, userregister)); 292 1.1 christos if (sc->sc_heateron) { 293 1.1 christos userregister |= SI70XX_HTRE_MASK; 294 1.1 christos } else { 295 1.1 christos userregister &= ~SI70XX_HTRE_MASK; 296 1.1 christos } 297 1.1 christos DPRINTF(sc, 2, ("%s:%s: user reg 1 values after: %#x\n", 298 1.1 christos device_xname(sc->sc_dev), __func__, userregister)); 299 1.1 christos 300 1.1 christos error = si70xx_cmd1(sc, SI70XX_WRITE_USER_REG_1, &userregister, 1); 301 1.1 christos if (error) { 302 1.1 christos DPRINTF(sc, 2, ("%s: Failed to write user register 1: %d\n", 303 1.1 christos device_xname(sc->sc_dev), error)); 304 1.1 christos } 305 1.1 christos out: 306 1.1 christos iic_release_bus(sc->sc_tag, 0); 307 1.1 christos return error; 308 1.1 christos } 309 1.1 christos 310 1.1 christos static int 311 1.1 christos si70xx_set_resolution(struct si70xx_sc * sc, size_t index) 312 1.1 christos { 313 1.1 christos int error; 314 1.1 christos uint8_t userregister; 315 1.1 christos 316 1.1 christos error = iic_acquire_bus(sc->sc_tag, 0); 317 1.1 christos if (error) { 318 1.1 christos DPRINTF(sc, 2, ("%s: Failed to acquire bus: %d\n", 319 1.1 christos device_xname(sc->sc_dev), error)); 320 1.1 christos return error; 321 1.1 christos } 322 1.1 christos 323 1.1 christos error = si70xx_cmd1(sc, SI70XX_READ_USER_REG_1, &userregister, 1); 324 1.1 christos if (error) { 325 1.1 christos DPRINTF(sc, 2, ("%s: Failed to read user register 1: %d\n", 326 1.1 christos device_xname(sc->sc_dev), error)); 327 1.1 christos goto out; 328 1.1 christos } 329 1.1 christos 330 1.1 christos DPRINTF(sc, 2, ("%s:%s: reg 1 values before: %#x\n", 331 1.1 christos device_xname(sc->sc_dev), __func__, userregister)); 332 1.1 christos userregister &= (~SI70XX_RESOLUTION_MASK); 333 1.1 christos userregister |= si70xx_resolutions[index].num; 334 1.1 christos DPRINTF(sc, 2, ("%s:%s: reg 1 values after: %#x\n", 335 1.1 christos device_xname(sc->sc_dev), __func__, userregister)); 336 1.1 christos 337 1.1 christos error = si70xx_cmd1(sc, SI70XX_WRITE_USER_REG_1, &userregister, 1); 338 1.1 christos if (error) { 339 1.1 christos DPRINTF(sc, 2, ("%s: Failed to write user register 1: %d\n", 340 1.1 christos device_xname(sc->sc_dev), error)); 341 1.1 christos } 342 1.1 christos out: 343 1.1 christos iic_release_bus(sc->sc_tag, 0); 344 1.1 christos return error; 345 1.1 christos } 346 1.1 christos 347 1.1 christos static int 348 1.1 christos si70xx_set_heatervalue(struct si70xx_sc * sc, size_t index) 349 1.1 christos { 350 1.1 christos int error; 351 1.1 christos uint8_t heaterregister; 352 1.1 christos 353 1.1 christos error = iic_acquire_bus(sc->sc_tag, 0); 354 1.1 christos if (error) { 355 1.1 christos DPRINTF(sc, 2, ("%s: Failed to acquire bus: %d\n", 356 1.1 christos device_xname(sc->sc_dev), error)); 357 1.1 christos return error; 358 1.1 christos } 359 1.1 christos error = si70xx_cmd1(sc, SI70XX_READ_HEATER_REG, &heaterregister, 1); 360 1.1 christos if (error) { 361 1.1 christos DPRINTF(sc, 2, ("%s: Failed to read heater register: %d\n", 362 1.1 christos device_xname(sc->sc_dev), error)); 363 1.1 christos goto out; 364 1.1 christos } 365 1.1 christos 366 1.1 christos DPRINTF(sc, 2, ("%s:%s: heater values before: %#x\n", 367 1.1 christos device_xname(sc->sc_dev), __func__, heaterregister)); 368 1.1 christos heaterregister &= ~SI70XX_HEATER_MASK; 369 1.1 christos heaterregister |= si70xx_heatervalues[index]; 370 1.1 christos DPRINTF(sc, 2, ("%s:%s: heater values after: %#x\n", 371 1.1 christos device_xname(sc->sc_dev), __func__, heaterregister)); 372 1.1 christos 373 1.3 christos error = si70xx_cmd1(sc, SI70XX_WRITE_HEATER_REG, &heaterregister, 1); 374 1.1 christos if (error) { 375 1.1 christos DPRINTF(sc, 2, ("%s: Failed to write heater register: %d\n", 376 1.1 christos device_xname(sc->sc_dev), error)); 377 1.1 christos } 378 1.1 christos out: 379 1.1 christos iic_release_bus(sc->sc_tag, 0); 380 1.1 christos return error; 381 1.1 christos } 382 1.1 christos 383 1.1 christos static int 384 1.1 christos si70xx_update_heater(struct si70xx_sc *sc) 385 1.1 christos { 386 1.1 christos size_t i; 387 1.1 christos int error; 388 1.1 christos uint8_t heaterregister; 389 1.1 christos 390 1.1 christos error = si70xx_cmd1(sc, SI70XX_READ_HEATER_REG, &heaterregister, 1); 391 1.1 christos if (error) { 392 1.1 christos DPRINTF(sc, 2, ("%s: Failed to read heater register: %d\n", 393 1.1 christos device_xname(sc->sc_dev), error)); 394 1.1 christos return error; 395 1.1 christos } 396 1.1 christos 397 1.1 christos DPRINTF(sc, 2, ("%s: read heater reg values: %02x\n", 398 1.1 christos device_xname(sc->sc_dev), heaterregister)); 399 1.1 christos 400 1.1 christos uint8_t heat = heaterregister & SI70XX_HEATER_MASK; 401 1.1 christos for (i = 0; i < __arraycount(si70xx_heatervalues); i++) { 402 1.1 christos if (si70xx_heatervalues[i] == heat) 403 1.1 christos break; 404 1.1 christos } 405 1.1 christos sc->sc_heaterval = i != __arraycount(si70xx_heatervalues) ? i : 0; 406 1.1 christos return 0; 407 1.1 christos } 408 1.1 christos 409 1.1 christos static int 410 1.1 christos si70xx_update_user(struct si70xx_sc *sc) 411 1.1 christos { 412 1.1 christos size_t i; 413 1.1 christos int error; 414 1.1 christos uint8_t userregister; 415 1.1 christos 416 1.1 christos error = si70xx_cmd1(sc, SI70XX_READ_USER_REG_1, &userregister, 1); 417 1.1 christos if (error) { 418 1.1 christos DPRINTF(sc, 2, ("%s: Failed to read user register 1: %d\n", 419 1.1 christos device_xname(sc->sc_dev), error)); 420 1.1 christos return error; 421 1.1 christos } 422 1.1 christos DPRINTF(sc, 2, ("%s: read user reg 1 values: %#x\n", 423 1.1 christos device_xname(sc->sc_dev), userregister)); 424 1.1 christos 425 1.1 christos uint8_t res = userregister & SI70XX_RESOLUTION_MASK; 426 1.1 christos for (i = 0; i < __arraycount(si70xx_resolutions); i++) { 427 1.1 christos if (si70xx_resolutions[i].num == res) 428 1.1 christos break; 429 1.1 christos } 430 1.1 christos 431 1.1 christos if (i != __arraycount(si70xx_resolutions)) { 432 1.1 christos memcpy(sc->sc_resolution, si70xx_resolutions[i].text, 433 1.1 christos SI70XX_RES_NAME); 434 1.1 christos } else { 435 1.1 christos snprintf(sc->sc_resolution, SI70XX_RES_NAME, "%02x", res); 436 1.1 christos } 437 1.1 christos 438 1.1 christos sc->sc_vddok = (userregister & SI70XX_VDDS_MASK) == 0; 439 1.1 christos sc->sc_heaterval = userregister & SI70XX_HTRE_MASK; 440 1.1 christos return 0; 441 1.1 christos } 442 1.1 christos 443 1.1 christos static int 444 1.1 christos si70xx_update_status(struct si70xx_sc *sc) 445 1.1 christos { 446 1.1 christos int error1 = si70xx_update_user(sc); 447 1.9 brad int error2 = 0; 448 1.9 brad if (! sc->sc_noheater) { 449 1.9 brad error2 = si70xx_update_heater(sc); 450 1.9 brad } 451 1.1 christos return error1 ? error1 : error2; 452 1.1 christos } 453 1.1 christos 454 1.1 christos static uint8_t 455 1.1 christos si70xx_crc(uint8_t * data, size_t size) 456 1.1 christos { 457 1.1 christos uint8_t crc = 0; 458 1.1 christos 459 1.1 christos for (size_t i = 0; i < size; i++) { 460 1.1 christos crc ^= data[i]; 461 1.1 christos for (size_t j = 8; j > 0; j--) { 462 1.1 christos if (crc & 0x80) 463 1.1 christos crc = (crc << 1) ^ 0x131; 464 1.1 christos else 465 1.1 christos crc <<= 1; 466 1.1 christos } 467 1.1 christos } 468 1.1 christos return crc; 469 1.1 christos } 470 1.1 christos 471 1.1 christos static int 472 1.1 christos si70xx_poke(i2c_tag_t tag, i2c_addr_t addr, bool matchdebug) 473 1.1 christos { 474 1.1 christos uint8_t reg = SI70XX_READ_USER_REG_1; 475 1.1 christos uint8_t buf; 476 1.1 christos int error; 477 1.1 christos 478 1.1 christos error = si70xx_cmd(tag, addr, ®, 1, &buf, 1); 479 1.1 christos if (matchdebug) { 480 1.1 christos printf("poke X 1: %d\n", error); 481 1.1 christos } 482 1.1 christos return error; 483 1.1 christos } 484 1.1 christos 485 1.1 christos static int 486 1.1 christos si70xx_sysctl_init(struct si70xx_sc *sc) 487 1.1 christos { 488 1.1 christos int error; 489 1.1 christos const struct sysctlnode *cnode; 490 1.1 christos int sysctlroot_num; 491 1.1 christos 492 1.1 christos if ((error = sysctl_createv(&sc->sc_si70xxlog, 0, NULL, &cnode, 493 1.1 christos 0, CTLTYPE_NODE, device_xname(sc->sc_dev), 494 1.1 christos SYSCTL_DESCR("si70xx controls"), NULL, 0, NULL, 0, CTL_HW, 495 1.1 christos CTL_CREATE, CTL_EOL)) != 0) 496 1.1 christos return error; 497 1.1 christos 498 1.1 christos sysctlroot_num = cnode->sysctl_num; 499 1.1 christos 500 1.1 christos #ifdef SI70XX_DEBUG 501 1.1 christos if ((error = sysctl_createv(&sc->sc_si70xxlog, 0, NULL, &cnode, 502 1.1 christos CTLFLAG_READWRITE, CTLTYPE_INT, "debug", 503 1.1 christos SYSCTL_DESCR("Debug level"), si70xx_verify_sysctl, 0, 504 1.1 christos &sc->sc_si70xxdebug, 0, CTL_HW, sysctlroot_num, CTL_CREATE, 505 1.1 christos CTL_EOL)) != 0) 506 1.1 christos return error; 507 1.1 christos 508 1.1 christos #endif 509 1.1 christos 510 1.1 christos if ((error = sysctl_createv(&sc->sc_si70xxlog, 0, NULL, &cnode, 511 1.12 brad CTLFLAG_READWRITE, CTLTYPE_BOOL, "clockstretch", 512 1.12 brad SYSCTL_DESCR("Use clock stretch commands for measurements"), NULL, 0, 513 1.1 christos &sc->sc_clockstretch, 0, CTL_HW, sysctlroot_num, CTL_CREATE, 514 1.1 christos CTL_EOL)) != 0) 515 1.1 christos return error; 516 1.1 christos 517 1.1 christos if ((error = sysctl_createv(&sc->sc_si70xxlog, 0, NULL, &cnode, 518 1.1 christos CTLFLAG_READWRITE, CTLTYPE_INT, "readattempts", 519 1.1 christos SYSCTL_DESCR("The number of times to attempt to read the values"), 520 1.1 christos si70xx_verify_sysctl, 0, &sc->sc_readattempts, 0, CTL_HW, 521 1.1 christos sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 522 1.1 christos return error; 523 1.1 christos 524 1.1 christos 525 1.1 christos if ((error = sysctl_createv(&sc->sc_si70xxlog, 0, NULL, &cnode, 526 1.1 christos CTLFLAG_READONLY, CTLTYPE_STRING, "resolutions", 527 1.1 christos SYSCTL_DESCR("Valid resolutions"), 0, 0, 528 1.1 christos __UNCONST(si70xx_resolution_names), 529 1.1 christos sizeof(si70xx_resolution_names) + 1, 530 1.1 christos CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 531 1.1 christos return error; 532 1.1 christos 533 1.1 christos if ((error = sysctl_createv(&sc->sc_si70xxlog, 0, NULL, &cnode, 534 1.1 christos CTLFLAG_READWRITE, CTLTYPE_STRING, "resolution", 535 1.1 christos SYSCTL_DESCR("Resolution of RH and Temp"), 536 1.1 christos si70xx_verify_sysctl_resolution, 0, (void *) sc, 537 1.1 christos SI70XX_RES_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 538 1.1 christos return error; 539 1.1 christos 540 1.1 christos if ((error = sysctl_createv(&sc->sc_si70xxlog, 0, NULL, &cnode, 541 1.1 christos CTLFLAG_READWRITE, CTLTYPE_BOOL, "ignorecrc", 542 1.1 christos SYSCTL_DESCR("Ignore the CRC byte"), NULL, 0, &sc->sc_ignorecrc, 543 1.1 christos 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 544 1.1 christos return error; 545 1.1 christos 546 1.1 christos if ((error = sysctl_createv(&sc->sc_si70xxlog, 0, NULL, &cnode, 547 1.1 christos CTLFLAG_READONLY, CTLTYPE_BOOL, "vddok", 548 1.1 christos SYSCTL_DESCR("Vdd at least 1.9v"), NULL, 0, &sc->sc_vddok, 0, 549 1.1 christos CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 550 1.1 christos return error; 551 1.1 christos 552 1.9 brad if (! sc->sc_noheater) { 553 1.9 brad if ((error = sysctl_createv(&sc->sc_si70xxlog, 0, NULL, &cnode, 554 1.9 brad CTLFLAG_READWRITE, CTLTYPE_BOOL, "heateron", 555 1.9 brad SYSCTL_DESCR("Heater on"), si70xx_verify_sysctl_heateron, 0, 556 1.9 brad (void *)sc, 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 557 1.9 brad return error; 558 1.9 brad 559 1.9 brad if ((error = sysctl_createv(&sc->sc_si70xxlog, 0, NULL, &cnode, 560 1.9 brad CTLFLAG_READWRITE, CTLTYPE_INT, "heaterstrength", 561 1.9 brad SYSCTL_DESCR("Heater strength 1 to 6"), 562 1.9 brad si70xx_verify_sysctl_heatervalue, 0, (void *)sc, 0, CTL_HW, 563 1.9 brad sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 564 1.9 brad return error; 565 1.9 brad } 566 1.1 christos 567 1.9 brad return 0; 568 1.1 christos } 569 1.1 christos 570 1.1 christos static int 571 1.1 christos si70xx_match(device_t parent, cfdata_t match, void *aux) 572 1.1 christos { 573 1.4 thorpej struct i2c_attach_args *ia = aux; 574 1.4 thorpej int error, match_result; 575 1.1 christos const bool matchdebug = false; 576 1.1 christos 577 1.4 thorpej if (iic_use_direct_match(ia, match, NULL, &match_result)) 578 1.4 thorpej return match_result; 579 1.1 christos 580 1.4 thorpej /* indirect config - check for configured address */ 581 1.4 thorpej if (ia->ia_addr != SI70XX_TYPICAL_ADDR) 582 1.4 thorpej return 0; 583 1.1 christos 584 1.1 christos /* 585 1.1 christos * Check to see if something is really at this i2c address. This will 586 1.1 christos * keep phantom devices from appearing 587 1.1 christos */ 588 1.1 christos if (iic_acquire_bus(ia->ia_tag, 0) != 0) { 589 1.1 christos if (matchdebug) 590 1.1 christos printf("in match acquire bus failed\n"); 591 1.1 christos return 0; 592 1.1 christos } 593 1.1 christos 594 1.1 christos error = si70xx_poke(ia->ia_tag, ia->ia_addr, matchdebug); 595 1.1 christos iic_release_bus(ia->ia_tag, 0); 596 1.1 christos 597 1.4 thorpej return error == 0 ? I2C_MATCH_ADDRESS_AND_PROBE : 0; 598 1.1 christos } 599 1.1 christos 600 1.1 christos static void 601 1.1 christos si70xx_attach(device_t parent, device_t self, void *aux) 602 1.1 christos { 603 1.1 christos struct si70xx_sc *sc; 604 1.1 christos struct i2c_attach_args *ia; 605 1.1 christos int error, i; 606 1.1 christos int ecount = 0; 607 1.1 christos uint8_t buf[8]; 608 1.1 christos uint8_t testcrcpt1[4]; 609 1.1 christos uint8_t testcrcpt2[4]; 610 1.1 christos uint8_t crc1 = 0, crc2 = 0; 611 1.10 brad bool validcrcpt1, validcrcpt2; 612 1.1 christos uint8_t readcrc1 = 0, readcrc2 = 0; 613 1.9 brad uint8_t fwversion = 0, model, heaterregister; 614 1.1 christos 615 1.1 christos ia = aux; 616 1.1 christos sc = device_private(self); 617 1.1 christos 618 1.1 christos sc->sc_dev = self; 619 1.1 christos sc->sc_tag = ia->ia_tag; 620 1.1 christos sc->sc_addr = ia->ia_addr; 621 1.1 christos sc->sc_si70xxdebug = 0; 622 1.12 brad sc->sc_clockstretch = false; 623 1.10 brad sc->sc_readattempts = 40; 624 1.1 christos sc->sc_ignorecrc = false; 625 1.1 christos sc->sc_sme = NULL; 626 1.9 brad sc->sc_noheater = false; 627 1.9 brad sc->sc_nofw = false; 628 1.1 christos 629 1.1 christos aprint_normal("\n"); 630 1.1 christos 631 1.1 christos mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE); 632 1.1 christos sc->sc_numsensors = __arraycount(si70xx_sensors); 633 1.1 christos 634 1.1 christos if ((sc->sc_sme = sysmon_envsys_create()) == NULL) { 635 1.1 christos aprint_error_dev(self, 636 1.1 christos "Unable to create sysmon structure\n"); 637 1.1 christos sc->sc_sme = NULL; 638 1.1 christos return; 639 1.1 christos } 640 1.1 christos 641 1.1 christos error = iic_acquire_bus(sc->sc_tag, 0); 642 1.1 christos if (error) { 643 1.1 christos aprint_error_dev(self, "Could not acquire iic bus: %d\n", 644 1.1 christos error); 645 1.1 christos goto out; 646 1.1 christos } 647 1.1 christos error = si70xx_cmd1(sc, SI70XX_RESET, NULL, 0); 648 1.1 christos if (error != 0) 649 1.1 christos aprint_error_dev(self, "Reset failed: %d\n", error); 650 1.1 christos 651 1.1 christos delay(15000); /* 15 ms max */ 652 1.1 christos 653 1.1 christos error = si70xx_cmd2(sc, SI70XX_READ_ID_PT1A, SI70XX_READ_ID_PT1B, 654 1.1 christos buf, 8); 655 1.1 christos if (error) { 656 1.1 christos aprint_error_dev(self, "Failed to read first part of ID: %d\n", 657 1.1 christos error); 658 1.1 christos ecount++; 659 1.1 christos } 660 1.1 christos testcrcpt1[0] = buf[0]; 661 1.1 christos testcrcpt1[1] = buf[2]; 662 1.1 christos testcrcpt1[2] = buf[4]; 663 1.1 christos testcrcpt1[3] = buf[6]; 664 1.1 christos readcrc1 = buf[7]; 665 1.1 christos crc1 = si70xx_crc(testcrcpt1, 4); 666 1.10 brad /* A "real" SI70xx has the CRC cover the entire first part of the 667 1.10 brad * serial number. An HTU21D has the CRC broken out into each 668 1.10 brad * part of the serial number. 669 1.10 brad */ 670 1.10 brad validcrcpt1 = (readcrc1 == crc1); 671 1.10 brad if (! validcrcpt1) { 672 1.10 brad validcrcpt1 = (si70xx_crc(&testcrcpt1[0],1) == buf[1] && 673 1.10 brad si70xx_crc(&testcrcpt1[1],1) == buf[3] && 674 1.10 brad si70xx_crc(&testcrcpt1[2],1) == buf[5] && 675 1.10 brad si70xx_crc(&testcrcpt1[3],1) == buf[7]); 676 1.10 brad DPRINTF(sc, 2, ("%s: Part 1 SN CRC was not valid for real type, " 677 1.10 brad "check clone: %d\n", device_xname(sc->sc_dev), validcrcpt1)); 678 1.10 brad } 679 1.1 christos 680 1.1 christos DPRINTF(sc, 2, ("%s: read 1 values: %02x%02x%02x%02x%02x%02x%02x%02x " 681 1.10 brad "- %02x -- %d\n", device_xname(sc->sc_dev), buf[0], buf[1], 682 1.1 christos buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], 683 1.10 brad crc1, validcrcpt1)); 684 1.1 christos 685 1.1 christos error = si70xx_cmd2(sc, SI70XX_READ_ID_PT2A, SI70XX_READ_ID_PT2B, 686 1.12 brad buf, 6); 687 1.1 christos if (error != 0) { 688 1.1 christos aprint_error_dev(self, "Failed to read second part of ID: %d\n", 689 1.1 christos error); 690 1.1 christos ecount++; 691 1.1 christos } 692 1.1 christos model = testcrcpt2[0] = buf[0]; 693 1.1 christos testcrcpt2[1] = buf[1]; 694 1.1 christos testcrcpt2[2] = buf[3]; 695 1.1 christos testcrcpt2[3] = buf[4]; 696 1.1 christos readcrc2 = buf[5]; 697 1.1 christos crc2 = si70xx_crc(testcrcpt2, 4); 698 1.10 brad /* It is even stranger for this part of the serial number. A "real" 699 1.10 brad * SI70XX will have a single CRC for the entire second part, but 700 1.10 brad * an HTU21D has a CRC for each word in this case. 701 1.10 brad * 702 1.10 brad * The datasheet actually agrees with the HTU21D case, and not the "real" 703 1.10 brad * chip. 704 1.10 brad */ 705 1.10 brad validcrcpt2 = (readcrc2 == crc2); 706 1.10 brad if (! validcrcpt2) { 707 1.10 brad validcrcpt2 = (si70xx_crc(&testcrcpt2[0],2) == buf[2] && 708 1.10 brad si70xx_crc(&testcrcpt2[2],2) == buf[5]); 709 1.10 brad DPRINTF(sc, 2, ("%s: Part 2 SN CRC was not valid for real type, " 710 1.10 brad "check clone: %d\n", device_xname(sc->sc_dev), validcrcpt2)); 711 1.10 brad } 712 1.1 christos 713 1.10 brad DPRINTF(sc, 2, ("%s: read 2 values: %02x%02x%02x%02x%02x%02x - %02x -- %d\n", 714 1.1 christos device_xname(sc->sc_dev), buf[0], buf[1], buf[2], 715 1.10 brad buf[3], buf[4], buf[5], crc2, validcrcpt2)); 716 1.1 christos 717 1.1 christos error = si70xx_cmd2(sc, SI70XX_READ_FW_VERA, SI70XX_READ_FW_VERB, 718 1.12 brad buf, 1); 719 1.1 christos 720 1.1 christos if (error) { 721 1.10 brad aprint_error_dev(self, "Failed to read firmware version: Error %d\n", 722 1.1 christos error); 723 1.9 brad sc->sc_nofw = true; 724 1.9 brad } 725 1.9 brad if (! sc->sc_nofw) { 726 1.9 brad fwversion = buf[0]; 727 1.9 brad DPRINTF(sc, 2, ("%s: read fw values: %#x\n", device_xname(sc->sc_dev), 728 1.9 brad fwversion)); 729 1.9 brad } 730 1.9 brad 731 1.9 brad error = si70xx_cmd1(sc, SI70XX_READ_HEATER_REG, &heaterregister, 1); 732 1.9 brad 733 1.9 brad if (error) { 734 1.10 brad aprint_error_dev(self, "Failed to read heater register: Error %d\n", 735 1.9 brad error); 736 1.9 brad sc->sc_noheater = true; 737 1.1 christos } 738 1.1 christos 739 1.1 christos error = si70xx_update_status(sc); 740 1.9 brad 741 1.1 christos iic_release_bus(sc->sc_tag, 0); 742 1.9 brad 743 1.9 brad if ((error = si70xx_sysctl_init(sc)) != 0) { 744 1.9 brad aprint_error_dev(self, "Can't setup sysctl tree (%d)\n", error); 745 1.9 brad goto out; 746 1.9 brad } 747 1.9 brad 748 1.1 christos if (error != 0) { 749 1.1 christos aprint_error_dev(self, "Failed to update status: %x\n", error); 750 1.1 christos aprint_error_dev(self, "Unable to setup device\n"); 751 1.1 christos goto out; 752 1.1 christos } 753 1.1 christos 754 1.1 christos for (i = 0; i < sc->sc_numsensors; i++) { 755 1.1 christos strlcpy(sc->sc_sensors[i].desc, si70xx_sensors[i].desc, 756 1.1 christos sizeof(sc->sc_sensors[i].desc)); 757 1.1 christos 758 1.1 christos sc->sc_sensors[i].units = si70xx_sensors[i].type; 759 1.1 christos sc->sc_sensors[i].state = ENVSYS_SINVALID; 760 1.1 christos 761 1.1 christos DPRINTF(sc, 2, ("%s: registering sensor %d (%s)\n", __func__, i, 762 1.1 christos sc->sc_sensors[i].desc)); 763 1.1 christos 764 1.1 christos error = sysmon_envsys_sensor_attach(sc->sc_sme, 765 1.1 christos &sc->sc_sensors[i]); 766 1.1 christos if (error) { 767 1.1 christos aprint_error_dev(self, 768 1.1 christos "Unable to attach sensor %d: %d\n", i, error); 769 1.6 jdc sc->sc_sme = NULL; 770 1.1 christos goto out; 771 1.1 christos } 772 1.1 christos } 773 1.1 christos 774 1.1 christos sc->sc_sme->sme_name = device_xname(sc->sc_dev); 775 1.1 christos sc->sc_sme->sme_cookie = sc; 776 1.1 christos sc->sc_sme->sme_refresh = si70xx_refresh; 777 1.1 christos 778 1.1 christos DPRINTF(sc, 2, ("si70xx_attach: registering with envsys\n")); 779 1.1 christos 780 1.1 christos if (sysmon_envsys_register(sc->sc_sme)) { 781 1.1 christos aprint_error_dev(self, 782 1.1 christos "unable to register with sysmon\n"); 783 1.1 christos sysmon_envsys_destroy(sc->sc_sme); 784 1.1 christos sc->sc_sme = NULL; 785 1.1 christos return; 786 1.1 christos } 787 1.1 christos 788 1.1 christos char modelstr[64]; 789 1.1 christos switch (model) { 790 1.1 christos case 0: 791 1.1 christos case 0xff: 792 1.1 christos snprintf(modelstr, sizeof(modelstr), "Engineering Sample"); 793 1.5 mrg break; 794 1.1 christos case 13: 795 1.1 christos case 20: 796 1.1 christos case 21: 797 1.1 christos snprintf(modelstr, sizeof(modelstr), "SI70%d", model); 798 1.1 christos break; 799 1.1 christos default: 800 1.9 brad snprintf(modelstr, sizeof(modelstr), "Unknown model %d (maybe an HTU21D)", model); 801 1.1 christos break; 802 1.1 christos } 803 1.1 christos 804 1.1 christos const char *fwversionstr; 805 1.1 christos switch (fwversion) { 806 1.1 christos case 0xff: 807 1.1 christos fwversionstr = "1.0"; 808 1.1 christos break; 809 1.1 christos case 0x20: 810 1.1 christos fwversionstr = "2.0"; 811 1.1 christos break; 812 1.1 christos default: 813 1.1 christos fwversionstr = "unknown"; 814 1.1 christos break; 815 1.1 christos } 816 1.1 christos 817 1.1 christos aprint_normal_dev(self, "Silicon Labs Model: %s, " 818 1.1 christos "Firmware version: %s, " 819 1.1 christos "Serial number: %02x%02x%02x%02x%02x%02x%02x%02x%s", 820 1.1 christos modelstr, fwversionstr, testcrcpt1[0], testcrcpt1[1], 821 1.1 christos testcrcpt1[2], testcrcpt1[3], testcrcpt2[0], testcrcpt2[1], 822 1.1 christos testcrcpt2[2], testcrcpt2[3], 823 1.10 brad (validcrcpt1 && validcrcpt2) ? "\n" : " (bad crc)\n"); 824 1.1 christos return; 825 1.1 christos out: 826 1.1 christos sysmon_envsys_destroy(sc->sc_sme); 827 1.1 christos sc->sc_sme = NULL; 828 1.1 christos } 829 1.1 christos 830 1.1 christos static int 831 1.1 christos si70xx_exec(struct si70xx_sc *sc, uint8_t cmd, envsys_data_t *edata) 832 1.1 christos { 833 1.1 christos int error; 834 1.1 christos int xdelay; 835 1.1 christos const char *name; 836 1.1 christos int64_t mul, offs; 837 1.1 christos uint8_t buf[3]; 838 1.1 christos 839 1.1 christos switch (cmd) { 840 1.1 christos case SI70XX_MEASURE_RH_NOHOLD: 841 1.12 brad case SI70XX_MEASURE_RH_HOLD: 842 1.1 christos /* 843 1.1 christos * The published conversion for RH is: %RH = 844 1.1 christos * ((125 * RHCODE) / 65536) - 6 845 1.1 christos * 846 1.1 christos * The sysmon infrastructure for RH wants %RH * 847 1.1 christos * 10^6 The result will fit in 32 bits, but 848 1.1 christos * the intermediate values will not. 849 1.1 christos */ 850 1.1 christos mul = 125000000; 851 1.1 christos offs = -6000000; 852 1.1 christos /* 853 1.1 christos * Conversion times for %RH in ms 854 1.1 christos * 855 1.1 christos * Typical Max 856 1.1 christos * 12-bit 10.0 12.0 857 1.1 christos * 11-bit 5.8 7.0 858 1.1 christos * 10-bit 3.7 4.5 859 1.1 christos * 8-bit 2.6 3.1 860 1.1 christos * 861 1.1 christos * A call to read %RH will also read temperature. The 862 1.1 christos * conversion time will be the amount of time above 863 1.1 christos * plus the amount of time for temperature below 864 1.1 christos */ 865 1.1 christos xdelay = 10500; 866 1.1 christos name = "RH"; 867 1.1 christos break; 868 1.1 christos case SI70XX_MEASURE_TEMP_NOHOLD: 869 1.12 brad case SI70XX_MEASURE_TEMP_HOLD: 870 1.1 christos /* 871 1.1 christos * The published conversion for temp is: 872 1.1 christos * degree C = ((175.72 * TEMPCODE) / 65536) - 873 1.1 christos * 46.85 874 1.1 christos * 875 1.1 christos * The sysmon infrastructure for temp wants 876 1.1 christos * microkelvin. This is simple, as degree C 877 1.1 christos * converts directly with K with simple 878 1.1 christos * addition. The result will fit in 32 bits, 879 1.1 christos * but the intermediate values will not. 880 1.1 christos */ 881 1.1 christos mul = 175720000; 882 1.1 christos offs = 226300000; 883 1.1 christos /* 884 1.1 christos * Conversion times for temperature in ms 885 1.1 christos * 886 1.1 christos * Typical Max 887 1.1 christos * 14-bit 7.0 10.8 888 1.1 christos * 13-bit 4.0 6.2 889 1.1 christos * 12-bit 2.4 3.8 890 1.1 christos * 11-bit 1.5 2.4 891 1.1 christos */ 892 1.1 christos xdelay = 4750; 893 1.1 christos name = "TEMP"; 894 1.1 christos break; 895 1.1 christos default: 896 1.1 christos return EINVAL; 897 1.1 christos } 898 1.1 christos 899 1.12 brad if (sc->sc_clockstretch) { 900 1.12 brad error = si70xx_cmd1(sc, cmd, buf, sizeof(buf)); 901 1.12 brad if (error) { 902 1.12 brad DPRINTF(sc, 2, ("%s: Failed to read HOLD %s %d %d\n", 903 1.12 brad device_xname(sc->sc_dev), name, 1, error)); 904 1.12 brad return error; 905 1.12 brad } 906 1.12 brad } else { 907 1.12 brad error = si70xx_cmd1(sc, cmd, NULL, 0); 908 1.12 brad if (error) { 909 1.12 brad DPRINTF(sc, 2, ("%s: Failed to read NO HOLD %s %d %d\n", 910 1.12 brad device_xname(sc->sc_dev), name, 1, error)); 911 1.12 brad return error; 912 1.12 brad } 913 1.1 christos 914 1.12 brad /* 915 1.12 brad * It will probably be at least this long... we would 916 1.12 brad * not have to do this sort of thing if clock 917 1.12 brad * stretching worked. Even this is a problem for the 918 1.12 brad * RPI without a patch to remove a [apparently] not 919 1.12 brad * needed KASSERT() 920 1.12 brad */ 921 1.12 brad delay(xdelay); 922 1.1 christos 923 1.12 brad for (int aint = 0; aint < sc->sc_readattempts; aint++) { 924 1.12 brad error = si70xx_cmd0(sc, buf, sizeof(buf)); 925 1.12 brad if (error == 0) 926 1.12 brad break; 927 1.12 brad DPRINTF(sc, 2, ("%s: Failed to read NO HOLD RH" 928 1.12 brad " %d %d\n", device_xname(sc->sc_dev), 2, error)); 929 1.12 brad delay(1000); 930 1.12 brad } 931 1.1 christos } 932 1.1 christos 933 1.1 christos DPRINTF(sc, 2, ("%s: %s values: %02x%02x%02x - %02x\n", 934 1.1 christos device_xname(sc->sc_dev), name, buf[0], buf[1], buf[2], 935 1.1 christos si70xx_crc(buf, 2))); 936 1.1 christos 937 1.1 christos uint8_t crc; 938 1.1 christos if (sc->sc_ignorecrc) { 939 1.1 christos crc = buf[2]; 940 1.1 christos } else { 941 1.1 christos crc = si70xx_crc(buf, 2); 942 1.1 christos } 943 1.1 christos 944 1.1 christos if (crc != buf[2]) { 945 1.1 christos DPRINTF(sc, 2, ("%s: Bad CRC for %s: %#x and %#x\n", 946 1.1 christos device_xname(sc->sc_dev), name, crc, buf[2])); 947 1.1 christos return EINVAL; 948 1.1 christos } 949 1.1 christos 950 1.1 christos uint16_t val16 = (buf[0] << 8) | buf[1]; 951 1.1 christos uint64_t val64 = ((mul * val16) >> 16) + offs; 952 1.1 christos DPRINTF(sc, 2, ("%s: %s calculated values: %x %#jx\n", 953 1.1 christos device_xname(sc->sc_dev), name, val16, (uintmax_t)val64)); 954 1.1 christos edata->value_cur = (uint32_t) val64; 955 1.1 christos edata->state = ENVSYS_SVALID; 956 1.1 christos return 0; 957 1.1 christos } 958 1.1 christos 959 1.1 christos static void 960 1.1 christos si70xx_refresh(struct sysmon_envsys * sme, envsys_data_t * edata) 961 1.1 christos { 962 1.1 christos struct si70xx_sc *sc; 963 1.1 christos int error; 964 1.1 christos 965 1.1 christos sc = sme->sme_cookie; 966 1.1 christos edata->state = ENVSYS_SINVALID; 967 1.1 christos 968 1.1 christos mutex_enter(&sc->sc_mutex); 969 1.1 christos error = iic_acquire_bus(sc->sc_tag, 0); 970 1.1 christos if (error) { 971 1.1 christos DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n", 972 1.1 christos device_xname(sc->sc_dev), error)); 973 1.1 christos goto out; 974 1.1 christos } 975 1.1 christos error = si70xx_update_status(sc); 976 1.1 christos if (error) { 977 1.1 christos DPRINTF(sc, 2, ("%s: Failed to update status in refresh %d\n", 978 1.1 christos device_xname(sc->sc_dev), error)); 979 1.1 christos goto out1; 980 1.1 christos } 981 1.1 christos switch (edata->sensor) { 982 1.1 christos case SI70XX_HUMIDITY_SENSOR: 983 1.12 brad if (sc->sc_clockstretch) 984 1.12 brad error = si70xx_exec(sc, SI70XX_MEASURE_RH_HOLD, edata); 985 1.12 brad else 986 1.12 brad error = si70xx_exec(sc, SI70XX_MEASURE_RH_NOHOLD, edata); 987 1.1 christos break; 988 1.1 christos 989 1.1 christos case SI70XX_TEMP_SENSOR: 990 1.12 brad if (sc->sc_clockstretch) 991 1.12 brad error = si70xx_exec(sc, SI70XX_MEASURE_TEMP_HOLD, edata); 992 1.12 brad else 993 1.12 brad error = si70xx_exec(sc, SI70XX_MEASURE_TEMP_NOHOLD, edata); 994 1.1 christos break; 995 1.1 christos default: 996 1.1 christos error = EINVAL; 997 1.1 christos break; 998 1.1 christos } 999 1.1 christos 1000 1.1 christos if (error) { 1001 1.1 christos DPRINTF(sc, 2, ("%s: Failed to get new status in refresh %d\n", 1002 1.1 christos device_xname(sc->sc_dev), error)); 1003 1.1 christos } 1004 1.1 christos out1: 1005 1.1 christos iic_release_bus(sc->sc_tag, 0); 1006 1.1 christos out: 1007 1.1 christos mutex_exit(&sc->sc_mutex); 1008 1.1 christos } 1009 1.1 christos 1010 1.1 christos static int 1011 1.1 christos si70xx_detach(device_t self, int flags) 1012 1.1 christos { 1013 1.1 christos struct si70xx_sc *sc; 1014 1.1 christos 1015 1.1 christos sc = device_private(self); 1016 1.1 christos 1017 1.1 christos mutex_enter(&sc->sc_mutex); 1018 1.1 christos 1019 1.1 christos /* Remove the sensors */ 1020 1.7 mlelstv if (sc->sc_sme != NULL) 1021 1.1 christos sysmon_envsys_unregister(sc->sc_sme); 1022 1.1 christos mutex_exit(&sc->sc_mutex); 1023 1.1 christos 1024 1.1 christos /* Remove the sysctl tree */ 1025 1.1 christos sysctl_teardown(&sc->sc_si70xxlog); 1026 1.1 christos 1027 1.1 christos /* Remove the mutex */ 1028 1.1 christos mutex_destroy(&sc->sc_mutex); 1029 1.1 christos 1030 1.1 christos return 0; 1031 1.1 christos } 1032 1.1 christos 1033 1.11 pgoyette MODULE(MODULE_CLASS_DRIVER, si70xxtemp, "iic,sysmon_envsys"); 1034 1.1 christos 1035 1.1 christos #ifdef _MODULE 1036 1.1 christos #include "ioconf.c" 1037 1.1 christos #endif 1038 1.1 christos 1039 1.1 christos static int 1040 1.1 christos si70xxtemp_modcmd(modcmd_t cmd, void *opaque) 1041 1.1 christos { 1042 1.1 christos 1043 1.1 christos switch (cmd) { 1044 1.1 christos case MODULE_CMD_INIT: 1045 1.1 christos #ifdef _MODULE 1046 1.1 christos return config_init_component(cfdriver_ioconf_si70xxtemp, 1047 1.1 christos cfattach_ioconf_si70xxtemp, cfdata_ioconf_si70xxtemp); 1048 1.1 christos #else 1049 1.1 christos return 0; 1050 1.1 christos #endif 1051 1.1 christos case MODULE_CMD_FINI: 1052 1.1 christos #ifdef _MODULE 1053 1.2 christos return config_fini_component(cfdriver_ioconf_si70xxtemp, 1054 1.1 christos cfattach_ioconf_si70xxtemp, cfdata_ioconf_si70xxtemp); 1055 1.1 christos #else 1056 1.1 christos return 0; 1057 1.1 christos #endif 1058 1.1 christos default: 1059 1.1 christos return ENOTTY; 1060 1.1 christos } 1061 1.1 christos } 1062