1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2016 Michael Zhilin <mizhka@freebsd.org> All rights reserved. 5 * Copyright (c) 2019 Ian Lepore <ian@freebsd.org> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * GPIOTHS - Temp/Humidity sensor over GPIO. 31 * 32 * This is driver for Temperature & Humidity sensor which provides digital 33 * output over single-wire protocol from embedded 8-bit microcontroller. 34 * Note that it uses a custom single-wire protocol, it is not 1-wire(tm). 35 * 36 * This driver supports the following chips: 37 * DHT11: Temp 0c to 50c +-2.0c, Humidity 20% to 90% +-5% 38 * DHT12: Temp -20c to 60c +-0.5c, Humidity 20% to 95% +-5% 39 * DHT21: Temp -40c to 80c +-0.3c, Humidity 0% to 100% +-3% 40 * DHT22: Temp -40c to 80c +-0.3c, Humidity 0% to 100% +-2% 41 * AM2301: Same as DHT21, but also supports i2c interface. 42 * AM2302: Same as DHT22, but also supports i2c interface. 43 * 44 * Temp/Humidity sensor can't be discovered automatically, please specify hints 45 * as part of loader or kernel configuration: 46 * hint.gpioths.0.at="gpiobus0" 47 * hint.gpioths.0.pins=<PIN> 48 * 49 * Or configure via FDT data. 50 */ 51 52 #include <sys/cdefs.h> 53 __FBSDID("$FreeBSD$"); 54 55 #include <sys/param.h> 56 #include <sys/kernel.h> 57 #include <sys/bus.h> 58 #include <sys/gpio.h> 59 #include <sys/module.h> 60 #include <sys/errno.h> 61 #include <sys/systm.h> 62 #include <sys/sysctl.h> 63 #include <sys/taskqueue.h> 64 65 #include <dev/gpio/gpiobusvar.h> 66 67 #ifdef FDT 68 #include <dev/ofw/ofw_bus.h> 69 #include <dev/ofw/ofw_bus_subr.h> 70 71 static struct ofw_compat_data compat_data[] = { 72 {"dht11", true}, 73 {NULL, false} 74 }; 75 OFWBUS_PNP_INFO(compat_data); 76 SIMPLEBUS_PNP_INFO(compat_data); 77 #endif /* FDT */ 78 79 #define PIN_IDX 0 /* Use the first/only configured pin. */ 80 81 #define GPIOTHS_POLLTIME 5 /* in seconds */ 82 83 #define GPIOTHS_DHT_STARTCYCLE 20000 /* 20ms = 20000us */ 84 #define GPIOTHS_DHT_TIMEOUT 1000 /* 1ms = 1000us */ 85 #define GPIOTHS_DHT_CYCLES 41 86 #define GPIOTHS_DHT_ONEBYTEMASK 0xFF 87 88 struct gpioths_softc { 89 device_t dev; 90 gpio_pin_t pin; 91 int temp; 92 int hum; 93 int fails; 94 struct timeout_task task; 95 bool detaching; 96 }; 97 98 static int 99 gpioths_probe(device_t dev) 100 { 101 int rv; 102 103 /* 104 * By default we only bid to attach if specifically added by our parent 105 * (usually via hint.gpioths.#.at=busname). On FDT systems we bid as 106 * the default driver based on being configured in the FDT data. 107 */ 108 rv = BUS_PROBE_NOWILDCARD; 109 110 #ifdef FDT 111 if (ofw_bus_status_okay(dev) && 112 ofw_bus_search_compatible(dev, compat_data)->ocd_data) 113 rv = BUS_PROBE_DEFAULT; 114 #endif 115 116 device_set_desc(dev, "DHT11/DHT22 Temperature and Humidity Sensor"); 117 118 return (rv); 119 } 120 121 static int 122 gpioths_dht_timeuntil(struct gpioths_softc *sc, bool lev, uint32_t *time) 123 { 124 bool cur_level; 125 int i; 126 127 for (i = 0; i < GPIOTHS_DHT_TIMEOUT; i++) { 128 gpio_pin_is_active(sc->pin, &cur_level); 129 if (cur_level == lev) { 130 if (time != NULL) 131 *time = i; 132 return (0); 133 } 134 DELAY(1); 135 } 136 137 /* Timeout */ 138 return (ETIMEDOUT); 139 } 140 141 static void 142 gpioths_dht_initread(struct gpioths_softc *sc) 143 { 144 145 /* 146 * According to specifications we need to drive the data line low for at 147 * least 20ms then drive it high, to wake up the chip and signal it to 148 * send a measurement. After sending this start signal, we switch the 149 * pin back to input so the device can begin talking to us. 150 */ 151 gpio_pin_setflags(sc->pin, GPIO_PIN_OUTPUT); 152 gpio_pin_set_active(sc->pin, false); 153 pause_sbt("gpioths", ustosbt(GPIOTHS_DHT_STARTCYCLE), C_PREL(2), 0); 154 gpio_pin_set_active(sc->pin, true); 155 gpio_pin_setflags(sc->pin, GPIO_PIN_INPUT); 156 } 157 158 static int 159 gpioths_dht_readbytes(struct gpioths_softc *sc) 160 { 161 uint32_t calibrations[GPIOTHS_DHT_CYCLES]; 162 uint32_t intervals[GPIOTHS_DHT_CYCLES]; 163 uint32_t err, avglen, value; 164 uint8_t crc, calc; 165 int i, negmul, offset, size, tmphi, tmplo; 166 167 gpioths_dht_initread(sc); 168 169 err = gpioths_dht_timeuntil(sc, false, NULL); 170 if (err) { 171 device_printf(sc->dev, "err(START) = %d\n", err); 172 goto error; 173 } 174 175 /* reading - 41 cycles */ 176 for (i = 0; i < GPIOTHS_DHT_CYCLES; i++) { 177 err = gpioths_dht_timeuntil(sc, true, &calibrations[i]); 178 if (err) { 179 device_printf(sc->dev, "err(CAL, %d) = %d\n", i, err); 180 goto error; 181 } 182 err = gpioths_dht_timeuntil(sc, false, &intervals[i]); 183 if (err) { 184 device_printf(sc->dev, "err(INTERVAL, %d) = %d\n", i, err); 185 goto error; 186 } 187 } 188 189 /* Calculate average data calibration cycle length */ 190 avglen = 0; 191 for (i = 1; i < GPIOTHS_DHT_CYCLES; i++) 192 avglen += calibrations[i]; 193 194 avglen = avglen / (GPIOTHS_DHT_CYCLES - 1); 195 196 /* Calculate data */ 197 value = 0; 198 offset = 1; 199 size = sizeof(value) * 8; 200 for (i = offset; i < size + offset; i++) { 201 value <<= 1; 202 if (intervals[i] > avglen) 203 value += 1; 204 } 205 206 /* Calculate CRC */ 207 crc = 0; 208 offset = sizeof(value) * 8 + 1; 209 size = sizeof(crc) * 8; 210 for (i = offset; i < size + offset; i++) { 211 crc <<= 1; 212 if (intervals[i] > avglen) 213 crc += 1; 214 } 215 216 calc = 0; 217 for (i = 0; i < sizeof(value); i++) 218 calc += (value >> (8*i)) & GPIOTHS_DHT_ONEBYTEMASK; 219 220 #ifdef GPIOTHS_DEBUG 221 /* Debug bits */ 222 for (i = 0; i < GPIOTHS_DHT_CYCLES; i++) 223 device_printf(sc->dev, "%d: %d %d\n", i, calibrations[i], 224 intervals[i]); 225 226 device_printf(sc->dev, "len=%d, data=%x, crc=%x/%x\n", avglen, value, crc, 227 calc); 228 #endif /* GPIOTHS_DEBUG */ 229 230 /* CRC check */ 231 if (calc != crc) { 232 err = -1; 233 goto error; 234 } 235 236 /* 237 * For DHT11/12, the values are split into 8 bits of integer and 8 bits 238 * of fractional tenths. On DHT11 the fraction bytes are always zero. 239 * On DHT12 the sign bit is in the high bit of the fraction byte. 240 * - DHT11: 0HHHHHHH 00000000 00TTTTTT 00000000 241 * - DHT12: 0HHHHHHH 0000hhhh 00TTTTTT s000tttt 242 * 243 * For DHT21/21, the values are are encoded in 16 bits each, with the 244 * temperature sign bit in the high bit. The values are tenths of a 245 * degree C and tenths of a percent RH. 246 * - DHT21: 000000HH HHHHHHHH s00000TT TTTTTTTT 247 * - DHT22: 000000HH HHHHHHHH s00000TT TTTTTTTT 248 * 249 * For all devices, some bits are always zero because of the range of 250 * values supported by the device. 251 * 252 * We figure out how to decode things based on the high byte of the 253 * humidity. A DHT21/22 cannot report a value greater than 3 in 254 * the upper bits of its 16-bit humidity. A DHT11/12 should not report 255 * a value lower than 20. To allow for the possibility that a device 256 * could report a value slightly out of its sensitivity range, we split 257 * the difference and say if the value is greater than 10 it must be a 258 * DHT11/12 (that would be a humidity over 256% on a DHT21/22). 259 */ 260 #define DK_OFFSET 2731 /* Offset between K and C, in decikelvins. */ 261 if ((value >> 24) > 10) { 262 /* DHT11 or DHT12 */ 263 tmphi = (value >> 8) & 0x3f; 264 tmplo = value & 0x0f; 265 negmul = (value & 0x80) ? -1 : 1; 266 sc->temp = DK_OFFSET + (negmul * (tmphi * 10 + tmplo)); 267 sc->hum = (value >> 24) & 0x7f; 268 } else { 269 /* DHT21 or DHT22 */ 270 negmul = (value & 0x8000) ? -1 : 1; 271 sc->temp = DK_OFFSET + (negmul * (value & 0x03ff)); 272 sc->hum = ((value >> 16) & 0x03ff) / 10; 273 } 274 275 sc->fails = 0; 276 277 #ifdef GPIOTHS_DEBUG 278 /* Debug bits */ 279 device_printf(dev, "fails=%d, temp=%d, hum=%d\n", sc->fails, 280 sc->temp, sc->hum); 281 #endif /* GPIOTHS_DEBUG */ 282 283 return (0); 284 error: 285 sc->fails++; 286 return (err); 287 } 288 289 static void 290 gpioths_poll(void *arg, int pending __unused) 291 { 292 struct gpioths_softc *sc; 293 294 sc = (struct gpioths_softc *)arg; 295 296 gpioths_dht_readbytes(sc); 297 if (!sc->detaching) 298 taskqueue_enqueue_timeout_sbt(taskqueue_thread, &sc->task, 299 GPIOTHS_POLLTIME * SBT_1S, 0, C_PREL(3)); 300 } 301 302 static int 303 gpioths_attach(device_t dev) 304 { 305 struct gpioths_softc *sc; 306 struct sysctl_ctx_list *ctx; 307 struct sysctl_oid *tree; 308 int err; 309 310 sc = device_get_softc(dev); 311 ctx = device_get_sysctl_ctx(dev); 312 tree = device_get_sysctl_tree(dev); 313 314 sc->dev = dev; 315 316 TIMEOUT_TASK_INIT(taskqueue_thread, &sc->task, 0, gpioths_poll, sc); 317 318 #ifdef FDT 319 /* Try to configure our pin from fdt data on fdt-based systems. */ 320 err = gpio_pin_get_by_ofw_idx(dev, ofw_bus_get_node(dev), PIN_IDX, 321 &sc->pin); 322 #else 323 err = ENOENT; 324 #endif 325 /* 326 * If we didn't get configured by fdt data and our parent is gpiobus, 327 * see if we can be configured by the bus (allows hinted attachment even 328 * on fdt-based systems). 329 */ 330 if (err != 0 && 331 strcmp("gpiobus", device_get_name(device_get_parent(dev))) == 0) 332 err = gpio_pin_get_by_child_index(dev, PIN_IDX, &sc->pin); 333 334 /* If we didn't get configured by either method, whine and punt. */ 335 if (err != 0) { 336 device_printf(sc->dev, 337 "cannot acquire gpio pin (config error)\n"); 338 return (err); 339 } 340 341 /* 342 * Ensure we have control of our pin, and preset the data line to its 343 * idle condition (high). Leave the line in input mode, relying on the 344 * external pullup to keep the line high while idle. 345 */ 346 err = gpio_pin_setflags(sc->pin, GPIO_PIN_OUTPUT); 347 if (err != 0) { 348 device_printf(dev, "gpio_pin_setflags(OUT) = %d\n", err); 349 return (err); 350 } 351 err = gpio_pin_set_active(sc->pin, true); 352 if (err != 0) { 353 device_printf(dev, "gpio_pin_set_active(false) = %d\n", err); 354 return (err); 355 } 356 err = gpio_pin_setflags(sc->pin, GPIO_PIN_INPUT); 357 if (err != 0) { 358 device_printf(dev, "gpio_pin_setflags(IN) = %d\n", err); 359 return (err); 360 } 361 362 /* 363 * Do an initial read so we have correct values for reporting before 364 * registering the sysctls that can access those values. This also 365 * schedules the periodic polling the driver does every few seconds to 366 * update the sysctl variables. 367 */ 368 gpioths_poll(sc, 0); 369 370 sysctl_add_oid(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "temperature", \ 371 CTLFLAG_RD | CTLTYPE_INT | CTLFLAG_MPSAFE, 372 &sc->temp, 0, sysctl_handle_int, "IK", "temperature", NULL); 373 374 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "humidity", 375 CTLFLAG_RD, &sc->hum, 0, "relative humidity(%)"); 376 377 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "fails", 378 CTLFLAG_RD, &sc->fails, 0, 379 "failures since last successful read"); 380 381 return (0); 382 } 383 384 static int 385 gpioths_detach(device_t dev) 386 { 387 struct gpioths_softc *sc; 388 389 sc = device_get_softc(dev); 390 gpio_pin_release(sc->pin); 391 sc->detaching = true; 392 while (taskqueue_cancel_timeout(taskqueue_thread, &sc->task, NULL) != 0) 393 taskqueue_drain_timeout(taskqueue_thread, &sc->task); 394 395 return (0); 396 } 397 398 /* Driver bits */ 399 static device_method_t gpioths_methods[] = { 400 /* Device interface */ 401 DEVMETHOD(device_probe, gpioths_probe), 402 DEVMETHOD(device_attach, gpioths_attach), 403 DEVMETHOD(device_detach, gpioths_detach), 404 405 DEVMETHOD_END 406 }; 407 408 DEFINE_CLASS_0(gpioths, gpioths_driver, gpioths_methods, sizeof(struct gpioths_softc)); 409 410 #ifdef FDT 411 DRIVER_MODULE(gpioths, simplebus, gpioths_driver, 0, 0); 412 #endif 413 414 DRIVER_MODULE(gpioths, gpiobus, gpioths_driver, 0, 0); 415 MODULE_DEPEND(gpioths, gpiobus, 1, 1, 1); 416