1/* $NetBSD: bmx280.c,v 1.2 2023/04/16 17:16:45 brad Exp $ */ 2 3/* 4 * Copyright (c) 2022 Brad Spencer <brad@anduin.eldar.org> 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/cdefs.h> 20__KERNEL_RCSID(0, "$NetBSD: bmx280.c,v 1.2 2023/04/16 17:16:45 brad Exp $"); 21 22/* 23 * Common driver for the Bosch BMP280/BME280 temperature, humidity (sometimes) and 24 * (usually barometric) pressure sensor. Calls out to specific frontends to 25 * the move bits around. 26*/ 27 28#include <sys/param.h> 29#include <sys/systm.h> 30#include <sys/kernel.h> 31#include <sys/device.h> 32#include <sys/module.h> 33#include <sys/sysctl.h> 34#include <sys/mutex.h> 35#include <sys/proc.h> 36 37#include <dev/sysmon/sysmonvar.h> 38#include <dev/spi/spivar.h> 39#include <dev/i2c/i2cvar.h> 40#include <dev/ic/bmx280reg.h> 41#include <dev/ic/bmx280var.h> 42 43 44static void bmx280_store_raw_blob_tp(struct bmx280_sc *, uint8_t *); 45static void bmx280_store_raw_blob_h(struct bmx280_sc *, uint8_t *); 46void bmx280_attach(struct bmx280_sc *); 47static void bmx280_refresh(struct sysmon_envsys *, envsys_data_t *); 48static int bmx280_verify_sysctl(SYSCTLFN_ARGS); 49static int bmx280_verify_sysctl_osrs(SYSCTLFN_ARGS); 50static int bmx280_verify_sysctl_irr(SYSCTLFN_ARGS); 51 52#define BMX280_DEBUG 53#ifdef BMX280_DEBUG 54#define DPRINTF(s, l, x) \ 55 do { \ 56 if (l <= s->sc_bmx280debug) \ 57 printf x; \ 58 } while (/*CONSTCOND*/0) 59#else 60#define DPRINTF(s, l, x) 61#endif 62 63static struct bmx280_sensor bmx280_sensors[] = { 64 { 65 .desc = "temperature", 66 .type = ENVSYS_STEMP, 67 }, 68 { 69 .desc = "pressure", 70 .type = ENVSYS_PRESSURE, 71 }, 72 { 73 .desc = "humidity", 74 .type = ENVSYS_SRELHUMIDITY, 75 } 76}; 77 78static struct bmx280_osrs_list bmx280_osrs[] = { 79 { 80 .text = 1, 81 .mask = BMX280_OSRS_TP_VALUE_X1, 82 }, 83 { 84 .text = 2, 85 .mask = BMX280_OSRS_TP_VALUE_X2, 86 }, 87 { 88 .text = 4, 89 .mask = BMX280_OSRS_TP_VALUE_X4, 90 }, 91 { 92 .text = 8, 93 .mask = BMX280_OSRS_TP_VALUE_X8, 94 }, 95 { 96 .text = 16, 97 .mask = BMX280_OSRS_TP_VALUE_X16, 98 } 99}; 100 101static struct bmx280_irr_list bmx280_irr[] = { 102 { 103 .text = 1, 104 .mask = BMX280_FILTER_VALUE_OFF, 105 }, 106 { 107 .text = 2, 108 .mask = BMX280_FILTER_VALUE_2, 109 }, 110 { 111 .text = 5, 112 .mask = BMX280_FILTER_VALUE_5, 113 }, 114 { 115 .text = 11, 116 .mask = BMX280_FILTER_VALUE_11, 117 }, 118 { 119 .text = 22, 120 .mask = BMX280_FILTER_VALUE_22, 121 } 122}; 123 124static uint8_t 125bmx280_osrs_text_to_mask(int t) 126{ 127 int i; 128 uint8_t m = 0; 129 130 for (i = 0; i < __arraycount(bmx280_osrs); i++) { 131 if (t == bmx280_osrs[i].text) { 132 m = bmx280_osrs[i].mask; 133 break; 134 } 135 } 136 137 return m; 138} 139 140static uint8_t 141bmx280_irr_text_to_mask(int t) 142{ 143 int i; 144 uint8_t m = 0; 145 146 for (i = 0; i < __arraycount(bmx280_irr); i++) { 147 if (t == bmx280_irr[i].text) { 148 m = bmx280_irr[i].mask; 149 break; 150 } 151 } 152 153 return m; 154} 155 156int 157bmx280_verify_sysctl(SYSCTLFN_ARGS) 158{ 159 int error, t; 160 struct sysctlnode node; 161 162 node = *rnode; 163 t = *(int *)rnode->sysctl_data; 164 node.sysctl_data = &t; 165 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 166 if (error || newp == NULL) 167 return error; 168 169 if (t < 0) 170 return EINVAL; 171 172 *(int *)rnode->sysctl_data = t; 173 174 return 0; 175} 176 177int 178bmx280_verify_sysctl_osrs(SYSCTLFN_ARGS) 179{ 180 struct sysctlnode node; 181 int error = 0, t; 182 size_t i; 183 184 node = *rnode; 185 t = *(int *)rnode->sysctl_data; 186 node.sysctl_data = &t; 187 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 188 if (error || newp == NULL) 189 return error; 190 191 for (i = 0; i < __arraycount(bmx280_osrs); i++) { 192 if (t == bmx280_osrs[i].text) { 193 break; 194 } 195 } 196 197 if (i == __arraycount(bmx280_osrs)) 198 return EINVAL; 199 200 *(int *)rnode->sysctl_data = t; 201 202 return error; 203} 204 205int 206bmx280_verify_sysctl_irr(SYSCTLFN_ARGS) 207{ 208 struct sysctlnode node; 209 int error = 0, t; 210 size_t i; 211 212 node = *rnode; 213 t = *(int *)rnode->sysctl_data; 214 node.sysctl_data = &t; 215 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 216 if (error || newp == NULL) 217 return error; 218 219 for (i = 0; i < __arraycount(bmx280_irr); i++) { 220 if (t == bmx280_irr[i].text) { 221 break; 222 } 223 } 224 225 if (i == __arraycount(bmx280_irr)) 226 return EINVAL; 227 228 *(int *)rnode->sysctl_data = t; 229 230 return error; 231} 232 233/* The datasheet was pretty vague as to the byte order... 234 * in fact, down right deceptive... 235 */ 236 237static void 238bmx280_store_raw_blob_tp(struct bmx280_sc *sc, uint8_t *b) { 239 sc->sc_cal_blob.dig_T1 = (uint16_t)b[1] << 8; 240 sc->sc_cal_blob.dig_T1 = sc->sc_cal_blob.dig_T1 | (uint16_t)b[0]; 241 sc->sc_cal_blob.dig_T2 = (int16_t)b[3] << 8; 242 sc->sc_cal_blob.dig_T2 = sc->sc_cal_blob.dig_T2 | (int16_t)b[2]; 243 sc->sc_cal_blob.dig_T3 = (int16_t)b[5] << 8; 244 sc->sc_cal_blob.dig_T3 = sc->sc_cal_blob.dig_T3 | (int16_t)b[4]; 245 246 sc->sc_cal_blob.dig_P1 = (uint16_t)b[7] << 8; 247 sc->sc_cal_blob.dig_P1 = sc->sc_cal_blob.dig_P1 | (uint16_t)b[6]; 248 sc->sc_cal_blob.dig_P2 = (int16_t)b[9] << 8; 249 sc->sc_cal_blob.dig_P2 = sc->sc_cal_blob.dig_P2 | (int16_t)b[8]; 250 sc->sc_cal_blob.dig_P3 = (int16_t)b[11] << 8; 251 sc->sc_cal_blob.dig_P3 = sc->sc_cal_blob.dig_P3 | (int16_t)b[10]; 252 sc->sc_cal_blob.dig_P4 = (int16_t)b[13] << 8; 253 sc->sc_cal_blob.dig_P4 = sc->sc_cal_blob.dig_P4 | (int16_t)b[12]; 254 sc->sc_cal_blob.dig_P5 = (int16_t)b[15] << 8; 255 sc->sc_cal_blob.dig_P5 = sc->sc_cal_blob.dig_P5 | (int16_t)b[14]; 256 sc->sc_cal_blob.dig_P6 = (int16_t)b[17] << 8; 257 sc->sc_cal_blob.dig_P6 = sc->sc_cal_blob.dig_P6 | (int16_t)b[16]; 258 sc->sc_cal_blob.dig_P7 = (int16_t)b[19] << 8; 259 sc->sc_cal_blob.dig_P7 = sc->sc_cal_blob.dig_P7 | (int16_t)b[18]; 260 sc->sc_cal_blob.dig_P8 = (int16_t)b[21] << 8; 261 sc->sc_cal_blob.dig_P8 = sc->sc_cal_blob.dig_P8 | (int16_t)b[20]; 262 sc->sc_cal_blob.dig_P9 = (int16_t)b[23] << 8; 263 sc->sc_cal_blob.dig_P9 = sc->sc_cal_blob.dig_P9 | (int16_t)b[22]; 264} 265 266static void 267bmx280_store_raw_blob_h(struct bmx280_sc *sc, uint8_t *b) { 268 sc->sc_cal_blob.dig_H1 = (uint8_t)b[0]; 269 sc->sc_cal_blob.dig_H2 = (int16_t)b[2] << 8; 270 sc->sc_cal_blob.dig_H2 = sc->sc_cal_blob.dig_H2 | (int16_t)b[1]; 271 sc->sc_cal_blob.dig_H3 = (uint8_t)b[3]; 272 sc->sc_cal_blob.dig_H4 = ((int16_t)((b[4] << 4) | (b[5] & 0x0F))); 273 sc->sc_cal_blob.dig_H5 = (int16_t)b[6] << 4; 274 sc->sc_cal_blob.dig_H5 = sc->sc_cal_blob.dig_H5 | (((int16_t)b[5] & 0x00f0) >> 4); 275 sc->sc_cal_blob.dig_H6 = (int8_t)b[7]; 276} 277 278static int 279bmx280_sysctl_init(struct bmx280_sc *sc) 280{ 281 int error; 282 const struct sysctlnode *cnode; 283 int sysctlroot_num, sysctlwait_num; 284 285 sc->sc_func_attach = &bmx280_attach; 286 287 if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode, 288 0, CTLTYPE_NODE, device_xname(sc->sc_dev), 289 SYSCTL_DESCR("bmx280 controls"), NULL, 0, NULL, 0, CTL_HW, 290 CTL_CREATE, CTL_EOL)) != 0) 291 return error; 292 293 sysctlroot_num = cnode->sysctl_num; 294 295#ifdef BMX280_DEBUG 296 if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode, 297 CTLFLAG_READWRITE, CTLTYPE_INT, "debug", 298 SYSCTL_DESCR("Debug level"), bmx280_verify_sysctl, 0, 299 &sc->sc_bmx280debug, 0, CTL_HW, sysctlroot_num, CTL_CREATE, 300 CTL_EOL)) != 0) 301 return error; 302 303 /* It would be nice to have a CTLTYPE_SHORT */ 304 305 if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode, 306 CTLFLAG_READWRITE, CTLTYPE_BOOL, "dump_calibration", 307 SYSCTL_DESCR("Dumps the calibration values to the console"), 308 bmx280_verify_sysctl, 0, 309 &sc->sc_bmx280dump, 0, CTL_HW, sysctlroot_num, CTL_CREATE, 310 CTL_EOL)) != 0) 311 return error; 312#endif 313 if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode, 314 CTLFLAG_READWRITE, CTLTYPE_INT, "readattempts", 315 SYSCTL_DESCR("Read attempts"), bmx280_verify_sysctl, 0, 316 &sc->sc_readattempts, 0, CTL_HW, sysctlroot_num, CTL_CREATE, 317 CTL_EOL)) != 0) 318 return error; 319 320 if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode, 321 CTLFLAG_READWRITE, CTLTYPE_INT, "osrs_t", 322 SYSCTL_DESCR("Temperature oversample"), 323 bmx280_verify_sysctl_osrs, 0, &sc->sc_osrs_t, 324 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 325 return error; 326 327 if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode, 328 CTLFLAG_READWRITE, CTLTYPE_INT, "osrs_p", 329 SYSCTL_DESCR("Pressure oversample"), 330 bmx280_verify_sysctl_osrs, 0, &sc->sc_osrs_p, 331 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 332 return error; 333 334 if (sc->sc_has_humidity) { 335 if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode, 336 CTLFLAG_READWRITE, CTLTYPE_INT, "osrs_h", 337 SYSCTL_DESCR("Humidity oversample"), 338 bmx280_verify_sysctl_osrs, 0, &sc->sc_osrs_h, 339 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 340 return error; 341 } 342 343 if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode, 344 CTLFLAG_READWRITE, CTLTYPE_INT, "irr_samples", 345 SYSCTL_DESCR("IRR samples"), 346 bmx280_verify_sysctl_irr, 0, &sc->sc_irr_samples, 347 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 348 return error; 349 350 if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode, 351 0, CTLTYPE_NODE, "waitfactor", 352 SYSCTL_DESCR("bmx280 wait factors"), NULL, 0, NULL, 0, CTL_HW, 353 sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 354 return error; 355 sysctlwait_num = cnode->sysctl_num; 356 357 if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode, 358 CTLFLAG_READWRITE, CTLTYPE_INT, "t", 359 SYSCTL_DESCR("Temperature wait multiplier"), 360 bmx280_verify_sysctl, 0, &sc->sc_waitfactor_t, 361 0, CTL_HW, sysctlroot_num, sysctlwait_num, CTL_CREATE, CTL_EOL)) != 0) 362 return error; 363 364 if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode, 365 CTLFLAG_READWRITE, CTLTYPE_INT, "p", 366 SYSCTL_DESCR("Pressure wait multiplier"), 367 bmx280_verify_sysctl, 0, &sc->sc_waitfactor_p, 368 0, CTL_HW, sysctlroot_num, sysctlwait_num, CTL_CREATE, CTL_EOL)) != 0) 369 return error; 370 371 if (sc->sc_has_humidity) { 372 if ((error = sysctl_createv(&sc->sc_bmx280log, 0, NULL, &cnode, 373 CTLFLAG_READWRITE, CTLTYPE_INT, "h", 374 SYSCTL_DESCR("Humidity wait multiplier"), 375 bmx280_verify_sysctl, 0, &sc->sc_waitfactor_h, 376 0, CTL_HW, sysctlroot_num, sysctlwait_num, CTL_CREATE, CTL_EOL)) != 0) 377 return error; 378 } 379 380 return 0; 381} 382void 383bmx280_attach(struct bmx280_sc *sc) 384{ 385 int error, i; 386 uint8_t reg, chip_id; 387 uint8_t buf[2]; 388 389 sc->sc_bmx280dump = false; 390 sc->sc_has_humidity = false; 391 sc->sc_readattempts = 25; 392 sc->sc_osrs_t = 1; 393 sc->sc_osrs_p = 4; 394 sc->sc_osrs_h = 1; 395 sc->sc_irr_samples = 1; 396 sc->sc_previous_irr = 0xff; 397 sc->sc_waitfactor_t = 6; 398 sc->sc_waitfactor_p = 2; 399 sc->sc_waitfactor_h = 2; 400 sc->sc_sme = NULL; 401 402 aprint_normal("\n"); 403 404 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE); 405 sc->sc_numsensors = __arraycount(bmx280_sensors); 406 407 if ((sc->sc_sme = sysmon_envsys_create()) == NULL) { 408 aprint_error_dev(sc->sc_dev, 409 "Unable to create sysmon structure\n"); 410 sc->sc_sme = NULL; 411 return; 412 } 413 414 error = (*(sc->sc_func_acquire_bus))(sc); 415 if (error) { 416 aprint_error_dev(sc->sc_dev, "Could not acquire the bus: %d\n", 417 error); 418 goto out; 419 } 420 421 buf[0] = BMX280_REGISTER_RESET; 422 buf[1] = BMX280_TRIGGER_RESET; 423 error = (*(sc->sc_func_write_register))(sc, buf, 2); 424 if (error) { 425 aprint_error_dev(sc->sc_dev, "Failed to reset chip: %d\n", 426 error); 427 } 428 429 delay(30000); 430 431 reg = BMX280_REGISTER_ID; 432 error = (*(sc->sc_func_read_register))(sc, reg, &chip_id, 1); 433 if (error) { 434 aprint_error_dev(sc->sc_dev, "Failed to read ID: %d\n", 435 error); 436 } 437 438 delay(1000); 439 440 DPRINTF(sc, 2, ("%s: read ID value: %02x\n", 441 device_xname(sc->sc_dev), chip_id)); 442 443 if (chip_id == BMX280_ID_BME280) { 444 sc->sc_has_humidity = true; 445 } 446 447 uint8_t raw_blob_tp[24]; 448 reg = BMX280_REGISTER_DIG_T1; 449 error = (*(sc->sc_func_read_register))(sc, reg, raw_blob_tp, 24); 450 if (error) { 451 aprint_error_dev(sc->sc_dev, "Failed to read the calibration registers for tp: %d\n", 452 error); 453 } 454 455 if (sc->sc_bmx280debug > 0) { 456 for(int _d = 0;_d < 24;_d++) { 457 DPRINTF(sc, 0, ("%s: %d %02x\n", 458 device_xname(sc->sc_dev), _d, raw_blob_tp[_d])); 459 } 460 } 461 462 bmx280_store_raw_blob_tp(sc,raw_blob_tp); 463 464 if (sc->sc_has_humidity) { 465 uint8_t raw_blob_h[8]; 466 467 reg = BMX280_REGISTER_DIG_H1; 468 error = (*(sc->sc_func_read_register))(sc, reg, raw_blob_h, 1); 469 if (error) { 470 aprint_error_dev(sc->sc_dev, "Failed to read the calibration registers for h1: %d\n", 471 error); 472 } 473 474 reg = BMX280_REGISTER_DIG_H2; 475 error = (*(sc->sc_func_read_register))(sc, reg, &raw_blob_h[1], 7); 476 if (error) { 477 aprint_error_dev(sc->sc_dev, "Failed to read the calibration registers for h2 - h6: %d\n", 478 error); 479 } 480 481 if (sc->sc_bmx280debug > 0) { 482 for(int _d = 0;_d < 8;_d++) { 483 DPRINTF(sc, 0, ("%s: %d %02x\n", 484 device_xname(sc->sc_dev), _d, raw_blob_h[_d])); 485 } 486 } 487 488 bmx280_store_raw_blob_h(sc,raw_blob_h); 489 } 490 491 (*(sc->sc_func_release_bus))(sc); 492 493 if (error != 0) { 494 aprint_error_dev(sc->sc_dev, "Unable to setup device\n"); 495 goto out; 496 } 497 498 if ((error = bmx280_sysctl_init(sc)) != 0) { 499 aprint_error_dev(sc->sc_dev, "Can't setup sysctl tree (%d)\n", error); 500 goto out; 501 } 502 503 for (i = 0; i < sc->sc_numsensors; i++) { 504 if (sc->sc_has_humidity == false && 505 bmx280_sensors[i].type == ENVSYS_SRELHUMIDITY) { 506 break; 507 } 508 509 strlcpy(sc->sc_sensors[i].desc, bmx280_sensors[i].desc, 510 sizeof(sc->sc_sensors[i].desc)); 511 512 sc->sc_sensors[i].units = bmx280_sensors[i].type; 513 sc->sc_sensors[i].state = ENVSYS_SINVALID; 514 515 DPRINTF(sc, 2, ("%s: registering sensor %d (%s)\n", __func__, i, 516 sc->sc_sensors[i].desc)); 517 518 error = sysmon_envsys_sensor_attach(sc->sc_sme, 519 &sc->sc_sensors[i]); 520 if (error) { 521 aprint_error_dev(sc->sc_dev, 522 "Unable to attach sensor %d: %d\n", i, error); 523 goto out; 524 } 525 } 526 527 sc->sc_sme->sme_name = device_xname(sc->sc_dev); 528 sc->sc_sme->sme_cookie = sc; 529 sc->sc_sme->sme_refresh = bmx280_refresh; 530 531 DPRINTF(sc, 2, ("bmx280_attach: registering with envsys\n")); 532 533 if (sysmon_envsys_register(sc->sc_sme)) { 534 aprint_error_dev(sc->sc_dev, 535 "unable to register with sysmon\n"); 536 sysmon_envsys_destroy(sc->sc_sme); 537 sc->sc_sme = NULL; 538 return; 539 } 540 541 aprint_normal_dev(sc->sc_dev, "Bosch Sensortec %s, Chip ID: 0x%02x\n", 542 (chip_id == BMX280_ID_BMP280) ? "BMP280" : (chip_id == BMX280_ID_BME280) ? "BME280" : "Unknown chip", 543 chip_id); 544 545 return; 546out: 547 sysmon_envsys_destroy(sc->sc_sme); 548 sc->sc_sme = NULL; 549} 550 551/* The conversion algorithms are taken from the BMP280 datasheet. The 552 * same algorithms are used with the BME280. 553 * 554 * https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp280-ds001.pdf 555 * 556 * Section 3.11.3, page 21 557 * 558 */ 559 560static int32_t 561bmx280_compensate_T_int32(struct bmx280_calibration_blob *b, 562 int32_t adc_T, 563 int32_t *t_fine) 564{ 565 int32_t var1, var2, T; 566 var1 = ((((adc_T>>3) - ((int32_t)b->dig_T1<<1))) * ((int32_t)b->dig_T2)) >> 11; 567 var2 = (((((adc_T>>4) - ((int32_t)b->dig_T1)) * ((adc_T>>4) - ((int32_t)b->dig_T1))) >> 12) * 568 ((int32_t)b->dig_T3)) >> 14; 569 *t_fine = var1 + var2; 570 T = (*t_fine * 5 + 128) >> 8; 571 return T; 572} 573 574/* Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits). 575 * Output value of 24674867 represents 24674867/256 = 96386.2 Pa = 963.862 hPa 576 */ 577static uint32_t 578bmx280_compensate_P_int64(struct bmx280_calibration_blob *b, 579 int32_t adc_P, 580 int32_t t_fine) 581{ 582 int64_t var1, var2, p; 583 var1 = ((int64_t)t_fine) - 128000; 584 var2 = var1 * var1 * (int64_t)b->dig_P6; 585 var2 = var2 + ((var1*(int64_t)b->dig_P5)<<17); 586 var2 = var2 + (((int64_t)b->dig_P4)<<35); 587 var1 = ((var1 * var1 * (int64_t)b->dig_P3)>>8) + ((var1 * (int64_t)b->dig_P2)<<12); 588 var1 = (((((int64_t)1)<<47)+var1))*((int64_t)b->dig_P1)>>33; 589 if (var1 == 0) { 590 return 0; /* avoid exception caused by division by zero */ 591 } 592 p = 1048576-adc_P; 593 p = (((p<<31)-var2)*3125)/var1; 594 var1 = (((int64_t)b->dig_P9) * (p>>13) * (p>>13)) >> 25; 595 var2 = (((int64_t)b->dig_P8) * p) >> 19; 596 p = ((p + var1 + var2) >> 8) + (((int64_t)b->dig_P7)<<4); 597 return (uint32_t)p; 598} 599 600/* Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits). 601 * 602 * Output value of 47445 represents 47445/1024 = 46.333 %RH 603 */ 604static uint32_t 605bmx280_compensate_H_int32(struct bmx280_calibration_blob *b, 606 int32_t adc_H, 607 int32_t t_fine) 608{ 609 int32_t v_x1_u32r; 610 v_x1_u32r = (t_fine - ((int32_t)76800)); 611 v_x1_u32r = (((((adc_H << 14) - (((int32_t)b->dig_H4) << 20) - (((int32_t)b->dig_H5) * 612 v_x1_u32r)) + ((int32_t)16384)) >> 15) * (((((((v_x1_u32r * 613 ((int32_t)b->dig_H6)) >> 10) * (((v_x1_u32r * ((int32_t)b->dig_H3)) >> 11) + 614 ((int32_t)32768))) >> 10) + ((int32_t)2097152)) * ((int32_t)b->dig_H2) + 615 8192) >> 14)); 616 v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * 617 ((int32_t)b->dig_H1)) >> 4)); 618 v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r); 619 v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r); 620 return (uint32_t)(v_x1_u32r>>12); 621} 622 623 624static int 625bmx280_set_control_and_trigger(struct bmx280_sc *sc, 626 uint8_t osrs_t_mask, 627 uint8_t osrs_p_mask, 628 uint8_t osrs_h_mask, 629 uint8_t filter_mask) 630{ 631 uint8_t cr[6]; 632 int error; 633 int s = 0; 634 635 cr[0] = cr[1] = cr[2] = cr[3] = cr[4] = cr[5] = 0; 636 637 if (filter_mask != sc->sc_previous_irr) { 638 cr[s] = BMX280_REGISTER_CONFIG; 639 s++; 640 cr[s] = filter_mask << BMX280_CONFIG_FILTER_SHIFT; 641 s++; 642 sc->sc_previous_irr = filter_mask; 643 } 644 if (sc->sc_has_humidity) { 645 cr[s] = BMX280_REGISTER_CTRL_HUM; 646 s++; 647 cr[s] = osrs_h_mask; 648 s++; 649 } 650 cr[s] = BMX280_REGISTER_CTRL_MEAS; 651 s++; 652 cr[s] = osrs_t_mask << BMX280_CTRL_OSRS_T_SHIFT; 653 cr[s] = cr[s] | osrs_p_mask << BMX280_CTRL_OSRS_P_SHIFT; 654 cr[s] = cr[s] | BMX280_MODE_FORCED; 655 s++; 656 DPRINTF(sc, 2, ("%s: control register set up: num: %d ; %02x %02x ; %02x %02x ; %02x %02x\n", 657 device_xname(sc->sc_dev), s, cr[0], cr[1], cr[2], cr[3], cr[4], cr[5])); 658 error = (*(sc->sc_func_write_register))(sc, cr, s); 659 if (error) { 660 DPRINTF(sc, 2, ("%s: write control registers: %d\n", 661 device_xname(sc->sc_dev), error)); 662 error = EINVAL; 663 } 664 665 /* The wait needed is not well documented, so this is somewhat of a guess. 666 * There is an attempt with this to only wait as long as needed. 667 */ 668 669 int p1, p2; 670 671 p1 = (osrs_t_mask * sc->sc_waitfactor_t) + (osrs_p_mask * sc->sc_waitfactor_p); 672 if (sc->sc_has_humidity) { 673 p1 = p1 + (osrs_h_mask * sc->sc_waitfactor_h); 674 } 675 p2 = mstohz(p1); 676 if (p2 == 0) { 677 p2 = 1; 678 } 679 /* Be careful with this... the print itself will cause extra delay */ 680 DPRINTF(sc, 2, ("%s: p1: %d ; %d\n", 681 device_xname(sc->sc_dev), p1, p2)); 682 kpause("b280mea",false,p2,NULL); 683 684 return error; 685} 686 687static int 688bmx280_wait_for_data(struct bmx280_sc *sc) 689{ 690 uint8_t reg; 691 uint8_t running = 99; 692 int c = sc->sc_readattempts; 693 int error = 0, ierror; 694 695 reg = BMX280_REGISTER_STATUS; 696 do { 697 delay(1000); 698 ierror = (*(sc->sc_func_read_register))(sc, reg, &running, 1); 699 if (ierror) { 700 DPRINTF(sc, 2, ("%s: Refresh failed to read back status: %d\n", 701 device_xname(sc->sc_dev), ierror)); 702 error = EINVAL; 703 break; 704 } 705 706 DPRINTF(sc, 2, ("%s: Refresh status read back: %02x\n", 707 device_xname(sc->sc_dev), running)); 708 709 c--; 710 } while (c > 0 && (running & BMX280_STATUS_MEASURING_MASK)); 711 712 return error; 713} 714 715static int 716bmx280_read_data(struct bmx280_sc *sc, 717 int32_t *temp, 718 int32_t *press, 719 int32_t *hum, 720 bool justtemp) 721{ 722 int error = 0, ierror; 723 int rlen, rtstart, rpstart, rhstart; 724 int x_temp, x_press, x_hum; 725 uint8_t raw_press_temp_hum[8], reg; 726 727 raw_press_temp_hum[0] = raw_press_temp_hum[1] = 728 raw_press_temp_hum[2] = raw_press_temp_hum[3] = 729 raw_press_temp_hum[4] = raw_press_temp_hum[5] = 730 raw_press_temp_hum[6] = raw_press_temp_hum[7] = 0; 731 732 if (justtemp) { 733 reg = BMX280_REGISTER_TEMP_MSB; 734 rlen = 3; 735 rtstart = 0; 736 rpstart = 0; 737 rhstart = 0; 738 } else { 739 reg = BMX280_REGISTER_PRESS_MSB; 740 if (sc->sc_has_humidity == false) { 741 rlen = 6; 742 } else { 743 rlen = 8; 744 } 745 rtstart = 3; 746 rpstart = 0; 747 rhstart = 6; 748 } 749 750 DPRINTF(sc, 2, ("%s: read data: reg: %02x ; len: %d ; tstart: %d ; pstart: %d\n", 751 device_xname(sc->sc_dev), reg, rlen, rtstart, rpstart)); 752 753 ierror = (*(sc->sc_func_read_register))(sc, reg, raw_press_temp_hum, rlen); 754 if (ierror) { 755 DPRINTF(sc, 2, ("%s: failed to read pressure and temp registers: %d\n", 756 device_xname(sc->sc_dev), ierror)); 757 error = EINVAL; 758 goto out; 759 } 760 761 DPRINTF(sc, 2, ("%s: raw pressure, temp and hum: %02x %02x %02x - %02x %02x %02x - %02x %02x\n", 762 device_xname(sc->sc_dev), 763 raw_press_temp_hum[0], raw_press_temp_hum[1], raw_press_temp_hum[2], 764 raw_press_temp_hum[3], raw_press_temp_hum[4], raw_press_temp_hum[5], 765 raw_press_temp_hum[6],raw_press_temp_hum[7])); 766 767 x_temp = raw_press_temp_hum[rtstart] << 12; 768 x_temp = x_temp | (raw_press_temp_hum[rtstart + 1] << 4); 769 x_temp = x_temp | (raw_press_temp_hum[rtstart + 2] >> 4); 770 771 DPRINTF(sc, 1, ("%s: intermediate temp: %d (%04x)\n", 772 device_xname(sc->sc_dev), x_temp, x_temp)); 773 774 *temp = x_temp; 775 776 *hum = 0; 777 *press = 0; 778 779 if (justtemp == false) { 780 x_press = raw_press_temp_hum[rpstart] << 12; 781 x_press = x_press | (raw_press_temp_hum[rpstart + 1] << 4); 782 x_press = x_press | (raw_press_temp_hum[rpstart + 2] >> 4); 783 784 DPRINTF(sc, 1, ("%s: intermediate pressure: %d (%04x)\n", 785 device_xname(sc->sc_dev), x_press, x_press)); 786 *press = x_press; 787 } 788 if (sc->sc_has_humidity) { 789 x_hum = raw_press_temp_hum[rhstart] << 8; 790 x_hum = x_hum | raw_press_temp_hum[rhstart + 1]; 791 792 DPRINTF(sc, 1, ("%s: intermediate humidity: %d (%02x)\n", 793 device_xname(sc->sc_dev), x_hum, x_hum)); 794 *hum = x_hum; 795 } 796 797 out: 798 return error; 799} 800 801static void 802bmx280_refresh(struct sysmon_envsys * sme, envsys_data_t * edata) 803{ 804 struct bmx280_sc *sc; 805 sc = sme->sme_cookie; 806 int error = 0; 807 int32_t t_fine; 808 int32_t m_temp, m_press, m_hum; 809 int32_t comp_temp; 810 uint32_t comp_press; 811 uint32_t comp_hum; 812 edata->state = ENVSYS_SINVALID; 813 814 /* Ya... just do this on a refresh... */ 815 816 if (sc->sc_bmx280dump) { 817 DPRINTF(sc, 1, ("%s: dig_T1: %d %04x\n",__func__,sc->sc_cal_blob.dig_T1,sc->sc_cal_blob.dig_T1)); 818 DPRINTF(sc, 1, ("%s: dig_T2: %d %04x\n",__func__,sc->sc_cal_blob.dig_T2,sc->sc_cal_blob.dig_T2)); 819 DPRINTF(sc, 1, ("%s: dig_T3: %d %04x\n",__func__,sc->sc_cal_blob.dig_T3,sc->sc_cal_blob.dig_T3)); 820 DPRINTF(sc, 1, ("%s: dig_P1: %d %04x\n",__func__,sc->sc_cal_blob.dig_P1,sc->sc_cal_blob.dig_P1)); 821 DPRINTF(sc, 1, ("%s: dig_P2: %d %04x\n",__func__,sc->sc_cal_blob.dig_P2,sc->sc_cal_blob.dig_P2)); 822 DPRINTF(sc, 1, ("%s: dig_P3: %d %04x\n",__func__,sc->sc_cal_blob.dig_P3,sc->sc_cal_blob.dig_P3)); 823 DPRINTF(sc, 1, ("%s: dig_P4: %d %04x\n",__func__,sc->sc_cal_blob.dig_P4,sc->sc_cal_blob.dig_P4)); 824 DPRINTF(sc, 1, ("%s: dig_P5: %d %04x\n",__func__,sc->sc_cal_blob.dig_P5,sc->sc_cal_blob.dig_P5)); 825 DPRINTF(sc, 1, ("%s: dig_P6: %d %04x\n",__func__,sc->sc_cal_blob.dig_P6,sc->sc_cal_blob.dig_P6)); 826 DPRINTF(sc, 1, ("%s: dig_P7: %d %04x\n",__func__,sc->sc_cal_blob.dig_P7,sc->sc_cal_blob.dig_P7)); 827 DPRINTF(sc, 1, ("%s: dig_P8: %d %04x\n",__func__,sc->sc_cal_blob.dig_P8,sc->sc_cal_blob.dig_P8)); 828 DPRINTF(sc, 1, ("%s: dig_P9: %d %04x\n",__func__,sc->sc_cal_blob.dig_P9,sc->sc_cal_blob.dig_P9)); 829 830 if (sc->sc_has_humidity) { 831 DPRINTF(sc, 1, ("%s: dig_H1: %d %02x\n",__func__,sc->sc_cal_blob.dig_H1,sc->sc_cal_blob.dig_H1)); 832 DPRINTF(sc, 1, ("%s: dig_H2: %d %04x\n",__func__,sc->sc_cal_blob.dig_H2,sc->sc_cal_blob.dig_H2)); 833 DPRINTF(sc, 1, ("%s: dig_H3: %d %02x\n",__func__,sc->sc_cal_blob.dig_H3,sc->sc_cal_blob.dig_H3)); 834 DPRINTF(sc, 1, ("%s: dig_H4: %d %04x\n",__func__,sc->sc_cal_blob.dig_H4,sc->sc_cal_blob.dig_H4)); 835 DPRINTF(sc, 1, ("%s: dig_H5: %d %04x\n",__func__,sc->sc_cal_blob.dig_H5,sc->sc_cal_blob.dig_H5)); 836 DPRINTF(sc, 1, ("%s: dig_H6: %d %02x\n",__func__,sc->sc_cal_blob.dig_H6,sc->sc_cal_blob.dig_H6)); 837 } 838 839 sc->sc_bmx280dump = false; 840 } 841 842 mutex_enter(&sc->sc_mutex); 843 error = (*(sc->sc_func_acquire_bus))(sc); 844 if (error) { 845 DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n", 846 device_xname(sc->sc_dev), error)); 847 goto out; 848 } 849 850 if (error == 0) { 851 switch (edata->sensor) { 852 case BMX280_TEMP_SENSOR: 853 /* A temperature reading does not need pressure */ 854 855 error = bmx280_set_control_and_trigger(sc, 856 bmx280_osrs_text_to_mask(sc->sc_osrs_t), 857 0, 858 0, 859 bmx280_irr_text_to_mask(sc->sc_irr_samples)); 860 861 if (error == 0) { 862 error = bmx280_wait_for_data(sc); 863 864 if (error == 0) { 865 error = bmx280_read_data(sc, &m_temp, &m_press, &m_hum, true); 866 867 if (error == 0) { 868 comp_temp = bmx280_compensate_T_int32(&sc->sc_cal_blob, m_temp, &t_fine); 869 870 DPRINTF(sc, 1, ("%s: Refresh compensated temp: %d - t_fine: %d\n", 871 device_xname(sc->sc_dev), comp_temp, t_fine)); 872 873 /* comp_temp is in Celcius * 100. This converts it to microkelvin */ 874 875 uint32_t q; 876 877 q = (uint32_t)comp_temp; 878 q = q + 27315; 879 q = q * 10000; 880 881 DPRINTF(sc, 1, ("%s: Refresh Q: %d\n", __func__, q)); 882 883 edata->value_cur = q; 884 edata->state = ENVSYS_SVALID; 885 } 886 } 887 } 888 break; 889 case BMX280_PRESSURE_SENSOR: 890 891 /* Pressure needs the temp too */ 892 error = bmx280_set_control_and_trigger(sc, 893 bmx280_osrs_text_to_mask(sc->sc_osrs_t), 894 bmx280_osrs_text_to_mask(sc->sc_osrs_p), 895 0, 896 bmx280_irr_text_to_mask(sc->sc_irr_samples)); 897 898 if (error == 0) { 899 error = bmx280_wait_for_data(sc); 900 901 if (error == 0) { 902 error = bmx280_read_data(sc, &m_temp, &m_press, &m_hum, false); 903 904 if (error == 0) { 905 comp_temp = bmx280_compensate_T_int32(&sc->sc_cal_blob, m_temp, &t_fine); 906 907 DPRINTF(sc, 1, ("%s: Refresh compensated temp for pressure: %d - t_fine: %d\n", 908 device_xname(sc->sc_dev), comp_temp, t_fine)); 909 910 comp_press = bmx280_compensate_P_int64(&sc->sc_cal_blob, m_press, t_fine); 911 912 DPRINTF(sc, 1, ("%s: Refresh compensated pressure: %d\n", 913 device_xname(sc->sc_dev), comp_press)); 914 915 uint32_t q; 916 917 q = comp_press; 918 q = q / 256; 919 q = q * 100; 920 921 DPRINTF(sc, 1, ("%s: Refresh pressure Q: %d\n", __func__, q)); 922 923 edata->value_cur = q; 924 edata->state = ENVSYS_SVALID; 925 } 926 } 927 } 928 break; 929 930 case BMX280_HUMIDITY_SENSOR: 931 932 /* Humidity wants temperature */ 933 934 error = bmx280_set_control_and_trigger(sc, 935 bmx280_osrs_text_to_mask(sc->sc_osrs_t), 936 0, 937 bmx280_osrs_text_to_mask(sc->sc_osrs_h), 938 bmx280_irr_text_to_mask(sc->sc_irr_samples)); 939 940 if (error == 0) { 941 error = bmx280_wait_for_data(sc); 942 943 if (error == 0) { 944 error = bmx280_read_data(sc, &m_temp, &m_press, &m_hum, false); 945 946 if (error == 0) { 947 comp_temp = bmx280_compensate_T_int32(&sc->sc_cal_blob, m_temp, &t_fine); 948 949 DPRINTF(sc, 1, ("%s: Refresh compensated temp for humidity: %d - t_fine: %d\n", 950 device_xname(sc->sc_dev), comp_temp, t_fine)); 951 952 comp_hum = bmx280_compensate_H_int32(&sc->sc_cal_blob, m_hum, t_fine); 953 954 DPRINTF(sc, 2, ("%s: Refresh compensated humidity: %d\n", 955 device_xname(sc->sc_dev), comp_hum)); 956 957 uint64_t q; 958 959 q = (uint64_t)comp_hum * 1000000; 960 DPRINTF(sc, 1, ("%s: Refresh humidity Q 1: %jd\n", __func__, (uintmax_t)q)); 961 q = q / 1024; 962 963 DPRINTF(sc, 1, ("%s: Refresh humidity Q 2: %jd\n", __func__, (uintmax_t)q)); 964 965 edata->value_cur = (uint32_t) q; 966 edata->state = ENVSYS_SVALID; 967 } 968 } 969 } 970 break; 971 } 972 } 973 974 if (error) { 975 DPRINTF(sc, 2, ("%s: Failed to get new status in refresh %d\n", 976 device_xname(sc->sc_dev), error)); 977 } 978 979 (*(sc->sc_func_release_bus))(sc); 980out: 981 mutex_exit(&sc->sc_mutex); 982} 983 984MODULE(MODULE_CLASS_DRIVER, bmx280thp, NULL); 985 986#ifdef _MODULE 987CFDRIVER_DECL(bmx280thp, DV_DULL, NULL); 988#include "ioconf.c" 989#endif 990 991static int 992bmx280thp_modcmd(modcmd_t cmd, void *opaque) 993{ 994 995 switch (cmd) { 996 case MODULE_CMD_INIT: 997#ifdef _MODULE 998 return config_init_component(cfdriver_ioconf_bmx280thp, 999 cfattach_ioconf_bmx280thp, cfdata_ioconf_bmx280thp); 1000#else 1001 return 0; 1002#endif 1003 case MODULE_CMD_FINI: 1004#ifdef _MODULE 1005 return config_fini_component(cfdriver_ioconf_bmx280thp, 1006 cfattach_ioconf_bmx280thp, cfdata_ioconf_bmx280thp); 1007#else 1008 return 0; 1009#endif 1010 default: 1011 return ENOTTY; 1012 } 1013} 1014