1 /* $OpenBSD: gpiodcf.c,v 1.5 2015/06/07 20:11:52 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Marc Balmer <mbalmer@openbsd.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/param.h> 20 #include <sys/systm.h> 21 #include <sys/kernel.h> 22 #include <sys/conf.h> 23 #include <sys/file.h> 24 #include <sys/select.h> 25 #include <sys/proc.h> 26 #include <sys/vnode.h> 27 #include <sys/device.h> 28 #include <sys/poll.h> 29 #include <sys/time.h> 30 #include <sys/sensors.h> 31 #include <sys/gpio.h> 32 33 #include <dev/gpio/gpiovar.h> 34 35 #ifdef GPIODCF_DEBUG 36 #define DPRINTFN(n, x) do { if (gpiodcfdebug > (n)) printf x; } while (0) 37 int gpiodcfdebug = 0; 38 #else 39 #define DPRINTFN(n, x) 40 #endif 41 #define DPRINTF(x) DPRINTFN(0, x) 42 43 #define DPERIOD1 ((long) 5 * 60) /* degrade OK -> WARN */ 44 #define DPERIOD2 ((long) 15 * 60) /* degrade WARN -> CRIT */ 45 46 /* max. skew of received time diff vs. measured time diff in percent. */ 47 #define MAX_SKEW 5 48 49 #define GPIODCF_NPINS 1 50 #define GPIODCF_PIN_DATA 0 51 52 struct gpiodcf_softc { 53 struct device sc_dev; /* base device */ 54 void *sc_gpio; 55 struct gpio_pinmap sc_map; 56 int __map[GPIODCF_NPINS]; 57 u_char sc_dying; /* disconnecting */ 58 int sc_data; 59 60 struct timeout sc_to; 61 62 struct timeout sc_bv_to; /* bit-value detect */ 63 struct timeout sc_db_to; /* debounce */ 64 struct timeout sc_mg_to; /* minute-gap detect */ 65 struct timeout sc_sl_to; /* signal-loss detect */ 66 struct timeout sc_it_to; /* invalidate time */ 67 68 int sc_sync; /* 1 during sync */ 69 u_int64_t sc_mask; /* 64 bit mask */ 70 u_int64_t sc_tbits; /* Time bits */ 71 int sc_minute; 72 int sc_level; 73 time_t sc_last_mg; 74 time_t sc_current; /* current time */ 75 time_t sc_next; /* time to become valid next */ 76 time_t sc_last; 77 int sc_nrecv; /* consecutive valid times */ 78 struct timeval sc_last_tv; /* uptime of last valid time */ 79 struct ksensor sc_sensor; 80 #ifdef GPIODCF_DEBUG 81 struct ksensor sc_skew; /* recv vs local skew */ 82 #endif 83 struct ksensordev sc_sensordev; 84 }; 85 86 /* 87 * timeouts being used in hz: 88 * t_bv bit value detection (150ms) 89 * t_sync sync (950ms) 90 * t_mg minute gap detection (1500ms) 91 * t_mgsync resync after a minute gap (450ms) 92 * t_sl detect signal loss (3sec) 93 * t_wait wait (5sec) 94 * t_warn degrade sensor status to warning (5min) 95 * t_crit degrade sensor status to critical (15min) 96 */ 97 static int t_bv, t_sync, t_mg, t_sl, t_mgsync, t_wait, t_warn, t_crit; 98 99 void gpiodcf_intr(void *); 100 void gpiodcf_probe(void *); 101 void gpiodcf_bv_probe(void *); 102 void gpiodcf_mg_probe(void *); 103 void gpiodcf_sl_probe(void *); 104 void gpiodcf_invalidate(void *); 105 106 int gpiodcf_match(struct device *, void *, void *); 107 void gpiodcf_attach(struct device *, struct device *, void *); 108 int gpiodcf_detach(struct device *, int); 109 int gpiodcf_activate(struct device *, int); 110 111 int gpiodcf_signal(struct gpiodcf_softc *); 112 113 struct cfdriver gpiodcf_cd = { 114 NULL, "gpiodcf", DV_DULL 115 }; 116 117 const struct cfattach gpiodcf_ca = { 118 sizeof(struct gpiodcf_softc), 119 gpiodcf_match, 120 gpiodcf_attach, 121 gpiodcf_detach, 122 gpiodcf_activate 123 }; 124 125 int 126 gpiodcf_match(struct device *parent, void *match, void *aux) 127 { 128 struct cfdata *cf = match; 129 struct gpio_attach_args *ga = aux; 130 131 if (ga->ga_offset == -1) 132 return 0; 133 134 return (strcmp(cf->cf_driver->cd_name, "gpiodcf") == 0); 135 } 136 137 void 138 gpiodcf_attach(struct device *parent, struct device *self, void *aux) 139 { 140 struct gpiodcf_softc *sc = (struct gpiodcf_softc *)self; 141 struct gpio_attach_args *ga = aux; 142 struct timeval t; 143 int caps; 144 145 if (gpio_npins(ga->ga_mask) != GPIODCF_NPINS) { 146 printf(": invalid pin mask\n"); 147 return; 148 } 149 sc->sc_gpio = ga->ga_gpio; 150 sc->sc_map.pm_map = sc->__map; 151 if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask, 152 &sc->sc_map)) { 153 printf(": can't map pins\n"); 154 return; 155 } 156 157 caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIODCF_PIN_DATA); 158 if (!(caps & GPIO_PIN_INPUT)) { 159 printf(": data pin is unable to receive input\n"); 160 goto fishy; 161 } 162 printf(": DATA[%d]", sc->sc_map.pm_map[GPIODCF_PIN_DATA]); 163 sc->sc_data = GPIO_PIN_INPUT; 164 gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIODCF_PIN_DATA, sc->sc_data); 165 printf("\n"); 166 167 strlcpy(sc->sc_sensor.desc, "DCF77", sizeof(sc->sc_sensor.desc)); 168 169 timeout_set(&sc->sc_to, gpiodcf_probe, sc); 170 timeout_set(&sc->sc_bv_to, gpiodcf_bv_probe, sc); 171 timeout_set(&sc->sc_mg_to, gpiodcf_mg_probe, sc); 172 timeout_set(&sc->sc_sl_to, gpiodcf_sl_probe, sc); 173 timeout_set(&sc->sc_it_to, gpiodcf_invalidate, sc); 174 175 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 176 sizeof(sc->sc_sensordev.xname)); 177 178 sc->sc_sensor.type = SENSOR_TIMEDELTA; 179 sc->sc_sensor.status = SENSOR_S_UNKNOWN; 180 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor); 181 182 #ifdef GPIODCF_DEBUG 183 sc->sc_skew.type = SENSOR_TIMEDELTA; 184 sc->sc_skew.status = SENSOR_S_UNKNOWN; 185 strlcpy(sc->sc_skew.desc, "local clock skew", 186 sizeof(sc->sc_skew.desc)); 187 sensor_attach(&sc->sc_sensordev, &sc->sc_skew); 188 #endif 189 sensordev_install(&sc->sc_sensordev); 190 191 sc->sc_level = 0; 192 sc->sc_minute = 0; 193 sc->sc_last_mg = 0L; 194 195 sc->sc_sync = 1; 196 197 sc->sc_current = 0L; 198 sc->sc_next = 0L; 199 sc->sc_nrecv = 0; 200 sc->sc_last = 0L; 201 sc->sc_last_tv.tv_sec = 0L; 202 203 /* convert timevals to hz */ 204 t.tv_sec = 0L; 205 t.tv_usec = 150000L; 206 t_bv = tvtohz(&t); 207 208 t.tv_usec = 450000L; 209 t_mgsync = tvtohz(&t); 210 211 t.tv_usec = 950000L; 212 t_sync = tvtohz(&t); 213 214 t.tv_sec = 1L; 215 t.tv_usec = 500000L; 216 t_mg = tvtohz(&t); 217 218 t.tv_sec = 3L; 219 t.tv_usec = 0L; 220 t_sl = tvtohz(&t); 221 222 t.tv_sec = 5L; 223 t_wait = tvtohz(&t); 224 225 t.tv_sec = DPERIOD1; 226 t_warn = tvtohz(&t); 227 228 t.tv_sec = DPERIOD2; 229 t_crit = tvtohz(&t); 230 231 /* Give the receiver some slack to stabilize */ 232 timeout_add(&sc->sc_to, t_wait); 233 234 /* Detect signal loss */ 235 timeout_add(&sc->sc_sl_to, t_wait + t_sl); 236 237 DPRINTF(("synchronizing\n")); 238 return; 239 240 fishy: 241 DPRINTF(("gpiodcf_attach failed\n")); 242 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); 243 sc->sc_dying = 1; 244 } 245 246 int 247 gpiodcf_detach(struct device *self, int flags) 248 { 249 struct gpiodcf_softc *sc = (struct gpiodcf_softc *)self; 250 251 sc->sc_dying = 1; 252 253 timeout_del(&sc->sc_to); 254 timeout_del(&sc->sc_bv_to); 255 timeout_del(&sc->sc_mg_to); 256 timeout_del(&sc->sc_sl_to); 257 timeout_del(&sc->sc_it_to); 258 259 /* Unregister the clock with the kernel */ 260 sensordev_deinstall(&sc->sc_sensordev); 261 262 /* Finally unmap the GPIO pin */ 263 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); 264 265 return 0; 266 } 267 268 /* 269 * return 1 during high-power-, 0 during low-power-emission 270 * If bit 0 is set, the transmitter emits at full power. 271 * During the low-power emission we decode a zero bit. 272 */ 273 int 274 gpiodcf_signal(struct gpiodcf_softc *sc) 275 { 276 return (gpio_pin_read(sc->sc_gpio, &sc->sc_map, GPIODCF_PIN_DATA) == 277 GPIO_PIN_HIGH ? 1 : 0); 278 } 279 280 /* gpiodcf_probe runs in a process context. */ 281 void 282 gpiodcf_probe(void *xsc) 283 { 284 struct gpiodcf_softc *sc = xsc; 285 struct timespec now; 286 int data; 287 288 if (sc->sc_dying) 289 return; 290 291 data = gpiodcf_signal(sc); 292 if (data == -1) 293 return; 294 295 if (data) { 296 sc->sc_level = 1; 297 timeout_add(&sc->sc_to, 1); 298 return; 299 } 300 301 if (sc->sc_level == 0) 302 return; 303 304 /* the beginning of a second */ 305 sc->sc_level = 0; 306 if (sc->sc_minute == 1) { 307 if (sc->sc_sync) { 308 DPRINTF(("start collecting bits\n")); 309 sc->sc_sync = 0; 310 } else { 311 /* provide the timedelta */ 312 microtime(&sc->sc_sensor.tv); 313 nanotime(&now); 314 sc->sc_current = sc->sc_next; 315 sc->sc_sensor.value = (int64_t)(now.tv_sec - 316 sc->sc_current) * 1000000000LL + now.tv_nsec; 317 318 sc->sc_sensor.status = SENSOR_S_OK; 319 320 /* 321 * if no valid time information is received 322 * during the next 5 minutes, the sensor state 323 * will be degraded to SENSOR_S_WARN 324 */ 325 timeout_add(&sc->sc_it_to, t_warn); 326 } 327 sc->sc_minute = 0; 328 } 329 330 timeout_add(&sc->sc_to, t_sync); /* resync in 950 ms */ 331 332 /* no clock and bit detection during sync */ 333 if (!sc->sc_sync) { 334 /* detect bit value */ 335 timeout_add(&sc->sc_bv_to, t_bv); 336 } 337 timeout_add(&sc->sc_mg_to, t_mg); /* detect minute gap */ 338 timeout_add(&sc->sc_sl_to, t_sl); /* detect signal loss */ 339 } 340 341 /* detect the bit value */ 342 void 343 gpiodcf_bv_probe(void *xsc) 344 { 345 struct gpiodcf_softc *sc = xsc; 346 int data; 347 348 if (sc->sc_dying) 349 return; 350 351 data = gpiodcf_signal(sc); 352 if (data == -1) { 353 DPRINTF(("bit detection failed\n")); 354 return; 355 } 356 357 DPRINTFN(1, (data ? "0" : "1")); 358 if (!(data)) 359 sc->sc_tbits |= sc->sc_mask; 360 sc->sc_mask <<= 1; 361 } 362 363 /* detect the minute gap */ 364 void 365 gpiodcf_mg_probe(void *xsc) 366 { 367 struct gpiodcf_softc *sc = xsc; 368 struct clock_ymdhms ymdhm; 369 struct timeval monotime; 370 int tdiff_recv, tdiff_local; 371 int skew; 372 int minute_bits, hour_bits, day_bits; 373 int month_bits, year_bits, wday; 374 int p1, p2, p3; 375 int p1_bit, p2_bit, p3_bit; 376 int r_bit, a1_bit, a2_bit, z1_bit, z2_bit; 377 int s_bit, m_bit; 378 u_int32_t parity = 0x6996; 379 380 if (sc->sc_sync) { 381 sc->sc_minute = 1; 382 goto cleanbits; 383 } 384 385 if (time_second - sc->sc_last_mg < 57) { 386 DPRINTF(("\nunexpected gap, resync\n")); 387 sc->sc_sync = sc->sc_minute = 1; 388 goto cleanbits; 389 } 390 391 /* extract bits w/o parity */ 392 m_bit = sc->sc_tbits & 1; 393 r_bit = sc->sc_tbits >> 15 & 1; 394 a1_bit = sc->sc_tbits >> 16 & 1; 395 z1_bit = sc->sc_tbits >> 17 & 1; 396 z2_bit = sc->sc_tbits >> 18 & 1; 397 a2_bit = sc->sc_tbits >> 19 & 1; 398 s_bit = sc->sc_tbits >> 20 & 1; 399 p1_bit = sc->sc_tbits >> 28 & 1; 400 p2_bit = sc->sc_tbits >> 35 & 1; 401 p3_bit = sc->sc_tbits >> 58 & 1; 402 403 minute_bits = sc->sc_tbits >> 21 & 0x7f; 404 hour_bits = sc->sc_tbits >> 29 & 0x3f; 405 day_bits = sc->sc_tbits >> 36 & 0x3f; 406 wday = (sc->sc_tbits >> 42) & 0x07; 407 month_bits = sc->sc_tbits >> 45 & 0x1f; 408 year_bits = sc->sc_tbits >> 50 & 0xff; 409 410 /* validate time information */ 411 p1 = (parity >> (minute_bits & 0x0f) & 1) ^ 412 (parity >> (minute_bits >> 4) & 1); 413 414 p2 = (parity >> (hour_bits & 0x0f) & 1) ^ 415 (parity >> (hour_bits >> 4) & 1); 416 417 p3 = (parity >> (day_bits & 0x0f) & 1) ^ 418 (parity >> (day_bits >> 4) & 1) ^ 419 ((parity >> wday) & 1) ^ (parity >> (month_bits & 0x0f) & 1) ^ 420 (parity >> (month_bits >> 4) & 1) ^ 421 (parity >> (year_bits & 0x0f) & 1) ^ 422 (parity >> (year_bits >> 4) & 1); 423 424 if (m_bit == 0 && s_bit == 1 && p1 == p1_bit && p2 == p2_bit && 425 p3 == p3_bit && (z1_bit ^ z2_bit)) { 426 427 /* Decode time */ 428 if ((ymdhm.dt_year = 2000 + FROMBCD(year_bits)) > 2037) { 429 DPRINTF(("year out of range, resync\n")); 430 sc->sc_sync = 1; 431 goto cleanbits; 432 } 433 ymdhm.dt_min = FROMBCD(minute_bits); 434 ymdhm.dt_hour = FROMBCD(hour_bits); 435 ymdhm.dt_day = FROMBCD(day_bits); 436 ymdhm.dt_mon = FROMBCD(month_bits); 437 ymdhm.dt_sec = 0; 438 439 sc->sc_next = clock_ymdhms_to_secs(&ymdhm); 440 getmicrouptime(&monotime); 441 442 /* convert to coordinated universal time */ 443 sc->sc_next -= z1_bit ? 7200 : 3600; 444 445 DPRINTF(("\n%02d.%02d.%04d %02d:%02d:00 %s", 446 ymdhm.dt_day, ymdhm.dt_mon, ymdhm.dt_year, 447 ymdhm.dt_hour, ymdhm.dt_min, z1_bit ? "CEST" : "CET")); 448 DPRINTF((r_bit ? ", call bit" : "")); 449 DPRINTF((a1_bit ? ", dst chg ann." : "")); 450 DPRINTF((a2_bit ? ", leap sec ann." : "")); 451 DPRINTF(("\n")); 452 453 if (sc->sc_last) { 454 tdiff_recv = sc->sc_next - sc->sc_last; 455 tdiff_local = monotime.tv_sec - sc->sc_last_tv.tv_sec; 456 skew = abs(tdiff_local - tdiff_recv); 457 #ifdef GPIODCF_DEBUG 458 if (sc->sc_skew.status == SENSOR_S_UNKNOWN) 459 sc->sc_skew.status = SENSOR_S_CRIT; 460 sc->sc_skew.value = skew * 1000000000LL; 461 getmicrotime(&sc->sc_skew.tv); 462 #endif 463 DPRINTF(("local = %d, recv = %d, skew = %d\n", 464 tdiff_local, tdiff_recv, skew)); 465 466 if (skew && skew * 100LL / tdiff_local > MAX_SKEW) { 467 DPRINTF(("skew out of tolerated range\n")); 468 goto cleanbits; 469 } else { 470 if (sc->sc_nrecv < 2) { 471 sc->sc_nrecv++; 472 DPRINTF(("got frame %d\n", 473 sc->sc_nrecv)); 474 } else { 475 DPRINTF(("data is valid\n")); 476 sc->sc_minute = 1; 477 } 478 } 479 } else { 480 DPRINTF(("received the first frame\n")); 481 sc->sc_nrecv = 1; 482 } 483 484 /* record the time received and when it was received */ 485 sc->sc_last = sc->sc_next; 486 sc->sc_last_tv.tv_sec = monotime.tv_sec; 487 } else { 488 DPRINTF(("\nparity error, resync\n")); 489 sc->sc_sync = sc->sc_minute = 1; 490 } 491 492 cleanbits: 493 timeout_add(&sc->sc_to, t_mgsync); /* re-sync in 450 ms */ 494 sc->sc_last_mg = time_second; 495 sc->sc_tbits = 0LL; 496 sc->sc_mask = 1LL; 497 } 498 499 /* detect signal loss */ 500 void 501 gpiodcf_sl_probe(void *xsc) 502 { 503 struct gpiodcf_softc *sc = xsc; 504 505 if (sc->sc_dying) 506 return; 507 508 DPRINTF(("no signal\n")); 509 sc->sc_sync = 1; 510 timeout_add(&sc->sc_to, t_wait); 511 timeout_add(&sc->sc_sl_to, t_wait + t_sl); 512 } 513 514 /* invalidate timedelta (called in an interrupt context) */ 515 void 516 gpiodcf_invalidate(void *xsc) 517 { 518 struct gpiodcf_softc *sc = xsc; 519 520 if (sc->sc_dying) 521 return; 522 523 if (sc->sc_sensor.status == SENSOR_S_OK) { 524 sc->sc_sensor.status = SENSOR_S_WARN; 525 /* 526 * further degrade in 15 minutes if we dont receive any new 527 * time information 528 */ 529 timeout_add(&sc->sc_it_to, t_crit); 530 } else { 531 sc->sc_sensor.status = SENSOR_S_CRIT; 532 sc->sc_nrecv = 0; 533 } 534 } 535 536 int 537 gpiodcf_activate(struct device *self, int act) 538 { 539 struct gpiodcf_softc *sc = (struct gpiodcf_softc *)self; 540 541 switch (act) { 542 case DVACT_DEACTIVATE: 543 sc->sc_dying = 1; 544 break; 545 } 546 return 0; 547 } 548