1 /* $NetBSD: ds2482ow.c,v 1.2 2024/11/06 15:49:36 riastradh Exp $ */ 2 3 /* 4 * Copyright (c) 2024 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: ds2482ow.c,v 1.2 2024/11/06 15:49:36 riastradh Exp $"); 21 22 /* 23 * Driver for the DS2482-100 and DS2482-800 I2C to Onewire bridge 24 */ 25 26 #include <sys/param.h> 27 28 #include <sys/device.h> 29 #include <sys/kernel.h> 30 #include <sys/module.h> 31 #include <sys/mutex.h> 32 #include <sys/sysctl.h> 33 #include <sys/systm.h> 34 35 #include <dev/i2c/ds2482owreg.h> 36 #include <dev/i2c/ds2482owvar.h> 37 #include <dev/i2c/i2cvar.h> 38 #include <dev/onewire/onewirevar.h> 39 40 #define DS2482_ONEWIRE_SINGLE_BIT_READ 0xF7 /* Artifical */ 41 #define DS2482_ONEWIRE_SINGLE_BIT_WRITE 0xF8 /* Artifical */ 42 43 static int ds2482_poke(i2c_tag_t, i2c_addr_t, bool); 44 static int ds2482_match(device_t, cfdata_t, void *); 45 static void ds2482_attach(device_t, device_t, void *); 46 static int ds2482_detach(device_t, int); 47 static int ds2482_verify_sysctl(SYSCTLFN_ARGS); 48 49 static int ds2482_ow_reset(void *); 50 static int ds2482_ow_read_bit(void *); 51 static void ds2482_ow_write_bit(void *, int); 52 static int ds2482_ow_read_byte(void *); 53 static void ds2482_ow_write_byte(void *, int); 54 static int ds2482_ow_triplet(void *, int); 55 56 #define DS2482_DEBUG 57 58 #ifdef DS2482_DEBUG 59 #define DPRINTF(s, l, x) \ 60 do { \ 61 if (l <= s->sc_ds2482debug) \ 62 aprint_normal x; \ 63 } while (/*CONSTCOND*/0) 64 #else 65 #define DPRINTF(s, l, x) __nothing 66 #endif 67 68 #ifdef DS2482_DEBUG 69 #define DPRINTF2(dl, l, x) \ 70 do { \ 71 if (l <= dl) \ 72 aprint_normal x; \ 73 } while (/*CONSTCOND*/0) 74 #else 75 #define DPRINTF2(dl, l, x) __nothing 76 #endif 77 78 CFATTACH_DECL_NEW(ds2482ow, sizeof(struct ds2482ow_sc), 79 ds2482_match, ds2482_attach, ds2482_detach, NULL); 80 81 #define DS2482_QUICK_DELAY 18 82 #define DS2482_SLOW_DELAY 35 83 84 int 85 ds2482_verify_sysctl(SYSCTLFN_ARGS) 86 { 87 int error, t; 88 struct sysctlnode node; 89 90 node = *rnode; 91 t = *(int *)rnode->sysctl_data; 92 node.sysctl_data = &t; 93 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 94 if (error || newp == NULL) 95 return error; 96 97 if (t < 0) 98 return EINVAL; 99 100 *(int *)rnode->sysctl_data = t; 101 102 return 0; 103 } 104 105 static int 106 ds2482_set_pullup(i2c_tag_t tag, i2c_addr_t addr, bool activepullup, 107 bool strongpullup, int debuglevel) 108 { 109 int error; 110 uint8_t cmd = DS2482_WRITE_CONFIG; 111 uint8_t pu = 0; 112 uint8_t pux; 113 114 if (activepullup) 115 pu = pu | DS2482_CONFIG_APU; 116 if (strongpullup) 117 pu = pu | DS2482_CONFIG_SPU; 118 119 /* 120 * The Write Config command wants the top bits of the config 121 * buffer to be the ones complement of the lower bits. 122 */ 123 124 pux = ~(pu << 4); 125 pux = pux & 0xf0; 126 pu = pu | pux; 127 128 error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &cmd, 1, &pu, 1, 129 0); 130 DPRINTF2(debuglevel, 4, ("ds2482_set_pullup: pu: %02x; error: %x %d\n", 131 pu, error, error)); 132 133 return error; 134 } 135 136 static int 137 ds2482_wait_with_status(i2c_tag_t tag, i2c_addr_t addr, uint8_t *status, 138 unsigned int d, bool set_pointer, int debuglevel) 139 { 140 int error = 0; 141 uint8_t xcmd, xbuf; 142 143 DPRINTF2(debuglevel, 5, ("ds2482_wait_with_status: start\n")); 144 145 xcmd = DS2482_SET_READ_POINTER; 146 xbuf = DS2482_REGISTER_STATUS; 147 if (set_pointer) { 148 error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &xcmd, 1, 149 &xbuf, 1, 0); 150 } 151 if (!error) { 152 error = iic_exec(tag, I2C_OP_READ, addr, NULL, 0, status, 1, 153 0); 154 if ((*status & DS2482_STATUS_1WB) && !error) { 155 do { 156 delay(d); 157 error = iic_exec(tag, I2C_OP_READ, addr, 158 NULL, 0, status, 1, 0); 159 } while ((*status & DS2482_STATUS_1WB) && !error); 160 } 161 } 162 163 DPRINTF2(debuglevel, 5, 164 ("ds2482_wait_with_status: end ; status: %02x %d ; error: %x %d\n", 165 *status, *status, error, error)); 166 167 return error; 168 } 169 170 static int 171 ds2482_cmd(i2c_tag_t tag, i2c_addr_t addr, uint8_t *cmd, 172 uint8_t *cmdarg, uint8_t *obuf, size_t obuflen, bool activepullup, 173 bool strongpullup, int debuglevel) 174 { 175 int error; 176 uint8_t xcmd; 177 uint8_t xbuf; 178 179 switch (*cmd) { 180 /* 181 * The datasheet says that none of these are effected 182 * by what sort of pullup is set and only the Write 183 * Config command needs to happen when idle. 184 */ 185 case DS2482_SET_READ_POINTER: 186 case DS2482_WRITE_CONFIG: 187 case DS2482_SELECT_CHANNEL: 188 KASSERT(cmdarg != NULL); 189 190 error = 0; 191 if (*cmd == DS2482_WRITE_CONFIG) { 192 error = ds2482_wait_with_status(tag, addr, &xbuf, 193 DS2482_QUICK_DELAY, /*set_pointer*/true, 194 debuglevel); 195 } 196 if (!error) { 197 error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, 198 cmd, 1, cmdarg, 1, 0); 199 } 200 DPRINTF2(debuglevel, 4, 201 ("ds2482_cmd: cmd: %02x ; error: %x %d\n", 202 *cmd, error, error)); 203 break; 204 205 case DS2482_DEVICE_RESET: 206 case DS2482_ONEWIRE_RESET: 207 /* 208 * Device reset resets everything, including pullup 209 * configuration settings, but that doesn't matter as 210 * we will always set the config before doing anything 211 * that actions on the 1-Wire bus. 212 * 213 * The data sheet warns about using the strong pull up 214 * feature with a 1-Wire reset, so we will simply not 215 * allow that combination. 216 * 217 * The data sheet does not mention if the 1-Wire reset 218 * effects just a single channel all channels. It 219 * seems likely that it is the currently active 220 * channel, and the driver works on that assumption. 221 */ 222 error = 0; 223 if (*cmd == DS2482_ONEWIRE_RESET) { 224 error = ds2482_wait_with_status(tag, addr, &xbuf, 225 DS2482_QUICK_DELAY, /*set_pointer*/true, 226 debuglevel); 227 if (!error) { 228 error = ds2482_set_pullup(tag, addr, 229 activepullup, /*strongpullup*/false, 230 debuglevel); 231 } 232 } 233 if (!error) { 234 error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, 235 cmd, 1, NULL, 0, 0); 236 } 237 DPRINTF2(debuglevel, 4, 238 ("ds2482_cmd: cmd: %02x ; error: %x %d\n", 239 *cmd, error, error)); 240 if (*cmd == DS2482_DEVICE_RESET) 241 delay(1); 242 if (*cmd == DS2482_ONEWIRE_RESET) 243 delay(1300); 244 break; 245 246 case DS2482_ONEWIRE_SINGLE_BIT_WRITE: 247 KASSERT(cmdarg != NULL); 248 249 DPRINTF2(debuglevel, 4, 250 ("ds2482_cmd: DS2482_ONEWIRE_SINGLE_BIT_WRITE:" 251 " cmdarg: %02x %d\n", *cmdarg, *cmdarg)); 252 253 xcmd = DS2482_SET_READ_POINTER; 254 xbuf = DS2482_REGISTER_STATUS; 255 error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &xcmd, 1, 256 &xbuf, 1, 0); 257 if (!error) { 258 error = ds2482_wait_with_status(tag, addr, &xbuf, 259 DS2482_QUICK_DELAY, /*set_pointer*/false, 260 debuglevel); 261 } 262 if (!error) { 263 xcmd = DS2482_ONEWIRE_SINGLE_BIT; 264 xbuf = DS2482_ONEWIRE_BIT_ZERO; 265 if (*cmdarg & 0x01) 266 xbuf = DS2482_ONEWIRE_BIT_ONE; 267 error = ds2482_set_pullup(tag, addr, 268 activepullup, strongpullup, debuglevel); 269 if (!error) { 270 error = iic_exec(tag, I2C_OP_WRITE, addr, 271 &xcmd, 1, &xbuf, 1, 0); 272 } 273 if (!error) { 274 xbuf = 0xff; 275 error = ds2482_wait_with_status(tag, addr, 276 &xbuf, DS2482_SLOW_DELAY, 277 /*set_pointer*/false, debuglevel); 278 } 279 } 280 break; 281 282 case DS2482_ONEWIRE_SINGLE_BIT_READ: 283 KASSERT(obuf != NULL); 284 KASSERT(obuflen == 1); 285 286 DPRINTF2(debuglevel, 4, 287 ("ds2482_cmd: DS2482_ONEWIRE_SINGLE_BIT_READ\n")); 288 289 xcmd = DS2482_SET_READ_POINTER; 290 xbuf = DS2482_REGISTER_STATUS; 291 error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &xcmd, 1, 292 &xbuf, 1, 0); 293 if (!error) { 294 error = ds2482_wait_with_status(tag, addr, &xbuf, 295 DS2482_QUICK_DELAY, /*set_pointer*/false, 296 debuglevel); 297 } 298 if (!error) { 299 xcmd = DS2482_ONEWIRE_SINGLE_BIT; 300 xbuf = DS2482_ONEWIRE_BIT_ONE; 301 error = ds2482_set_pullup(tag, addr, 302 activepullup, strongpullup, debuglevel); 303 if (!error) { 304 error = iic_exec(tag, I2C_OP_WRITE, addr, 305 &xcmd, 1, &xbuf, 1, 0); 306 } 307 if (!error) { 308 xbuf = 0xff; 309 error = ds2482_wait_with_status(tag, addr, 310 &xbuf, DS2482_SLOW_DELAY, 311 /*set_pointer*/false, debuglevel); 312 if (!error) { 313 *obuf = (xbuf & DS2482_STATUS_SBR) >> 314 DS2482_STATUS_SBR_SHIFT; 315 } 316 } 317 } 318 break; 319 320 case DS2482_ONEWIRE_WRITE_BYTE: 321 KASSERT(cmdarg != NULL); 322 323 DPRINTF2(debuglevel, 4, 324 ("ds2482_cmd: DS2482_ONEWIRE_WRITE_BYTE:" 325 " cmdarg: %02x %d\n", *cmdarg, *cmdarg)); 326 327 xcmd = DS2482_SET_READ_POINTER; 328 xbuf = DS2482_REGISTER_STATUS; 329 error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &xcmd, 1, 330 &xbuf, 1, 0); 331 if (!error) { 332 error = ds2482_wait_with_status(tag, addr, &xbuf, 333 DS2482_QUICK_DELAY, /*set_pointer*/false, 334 debuglevel); 335 } 336 if (!error) { 337 error = ds2482_set_pullup(tag, addr, 338 activepullup, strongpullup, debuglevel); 339 if (!error) { 340 error = iic_exec(tag, I2C_OP_WRITE, addr, 341 cmd, 1, cmdarg, 1, 0); 342 } 343 if (!error) { 344 xbuf = 0xff; 345 error = ds2482_wait_with_status(tag, addr, 346 &xbuf, DS2482_SLOW_DELAY, 347 /*set_pointer*/false, debuglevel); 348 } 349 } 350 break; 351 352 case DS2482_ONEWIRE_READ_BYTE: 353 KASSERT(obuf != NULL); 354 KASSERT(obuflen == 1); 355 356 DPRINTF2(debuglevel, 4, 357 ("ds2482_cmd: DS2482_ONEWIRE_READ_BYTE\n")); 358 359 xcmd = DS2482_SET_READ_POINTER; 360 xbuf = DS2482_REGISTER_STATUS; 361 error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &xcmd, 1, 362 &xbuf, 1, 0); 363 if (!error) { 364 error = ds2482_wait_with_status(tag, addr, &xbuf, 365 DS2482_QUICK_DELAY, /*set_pointer*/false, 366 debuglevel); 367 } 368 if (!error) { 369 error = ds2482_set_pullup(tag, addr, 370 activepullup, strongpullup, debuglevel); 371 if (!error) { 372 error = iic_exec(tag, I2C_OP_WRITE, addr, 373 cmd, 1, NULL, 0, 0); 374 } 375 if (!error) { 376 xbuf = 0xff; 377 error = ds2482_wait_with_status(tag, addr, 378 &xbuf, DS2482_SLOW_DELAY, 379 /*set_pointer*/false, debuglevel); 380 if (!error) { 381 xcmd = DS2482_SET_READ_POINTER; 382 xbuf = DS2482_REGISTER_DATA; 383 error = iic_exec(tag, 384 I2C_OP_WRITE_WITH_STOP, addr, 385 &xcmd, 1, &xbuf, 1, 0); 386 if (!error) { 387 xbuf = 0xff; 388 error = iic_exec(tag, 389 I2C_OP_READ_WITH_STOP, 390 addr, NULL, 0, 391 &xbuf, 1, 0); 392 if (!error) { 393 *obuf = xbuf; 394 } 395 } 396 } 397 } 398 } 399 break; 400 401 case DS2482_ONEWIRE_TRIPLET: 402 KASSERT(cmdarg != NULL); 403 KASSERT(obuf != NULL); 404 KASSERT(obuflen == 1); 405 406 DPRINTF2(debuglevel, 4, 407 ("ds2482_cmd: DS2482_ONEWIRE_TRIPLET: cmdarg: %02x %d\n", 408 *cmdarg, *cmdarg)); 409 410 xcmd = DS2482_SET_READ_POINTER; 411 xbuf = DS2482_REGISTER_STATUS; 412 error = iic_exec(tag, I2C_OP_WRITE_WITH_STOP, addr, &xcmd, 1, 413 &xbuf, 1, 0); 414 if (!error) { 415 error = ds2482_wait_with_status(tag, addr, &xbuf, 416 DS2482_QUICK_DELAY, /*set_pointer*/false, 417 debuglevel); 418 } 419 if (!error) { 420 xbuf = DS2482_TRIPLET_DIR_ZERO; 421 if (*cmdarg & 0x01) { 422 xbuf = DS2482_TRIPLET_DIR_ONE; 423 } 424 error = ds2482_set_pullup(tag, addr, 425 activepullup, strongpullup, debuglevel); 426 if (!error) { 427 error = iic_exec(tag, I2C_OP_WRITE, addr, 428 cmd, 1, &xbuf, 1, 0); 429 } 430 if (!error) { 431 xbuf = 0xff; 432 error = ds2482_wait_with_status(tag, addr, 433 &xbuf, DS2482_SLOW_DELAY, 434 /*set_pointer*/false, debuglevel); 435 if (!error) { 436 /* 437 * This is undocumented 438 * anywhere I could find, but 439 * what has to be returned is 440 * 0x01 is the triplet path was 441 * taken, 0x02 is the 442 * Not-triplet path was taken, 443 * and 0x00 is neither was 444 * taken. The DIR bit in the 445 * status of the DS2482 may 446 * help with this some, but 447 * what is below seems to work. 448 */ 449 *obuf = 0; 450 if (xbuf & DS2482_STATUS_TSB) { 451 *obuf = 0x01; 452 } else { 453 if (xbuf & DS2482_STATUS_SBR) { 454 *obuf = 0x02; 455 } 456 } 457 } 458 } 459 } 460 break; 461 462 default: 463 error = EINVAL; 464 break; 465 } 466 467 return error; 468 } 469 470 static int 471 ds2482_cmdr(struct ds2482ow_sc *sc, uint8_t cmd, uint8_t cmdarg, 472 uint8_t *buf, size_t blen) 473 { 474 475 DPRINTF(sc, 3, ("%s: ds2482_cmdr: cmd: %02x\n", 476 device_xname(sc->sc_dev), cmd)); 477 return ds2482_cmd(sc->sc_tag, sc->sc_addr, &cmd, &cmdarg, buf, blen, 478 sc->sc_activepullup, sc->sc_strongpullup, sc->sc_ds2482debug); 479 } 480 481 static const uint8_t ds2482_channels[] = { 482 DS2482_CHANNEL_IO0, 483 DS2482_CHANNEL_IO1, 484 DS2482_CHANNEL_IO2, 485 DS2482_CHANNEL_IO3, 486 DS2482_CHANNEL_IO4, 487 DS2482_CHANNEL_IO5, 488 DS2482_CHANNEL_IO6, 489 DS2482_CHANNEL_IO7 490 }; 491 492 static int 493 ds2482_set_channel(struct ds2482ow_sc *sc, int channel) 494 { 495 int error = 0; 496 497 KASSERT(channel >= 0 && channel < DS2482_NUM_INSTANCES); 498 499 if (sc->sc_is_800) { 500 error = ds2482_cmdr(sc, DS2482_SELECT_CHANNEL, 501 ds2482_channels[channel], NULL, 0); 502 } 503 504 return error; 505 } 506 507 static int 508 ds2482_poke(i2c_tag_t tag, i2c_addr_t addr, bool matchdebug) 509 { 510 uint8_t reg = DS2482_SET_READ_POINTER; 511 uint8_t rbuf = DS2482_REGISTER_STATUS; 512 uint8_t obuf; 513 int error; 514 515 error = ds2482_cmd(tag, addr, ®, &rbuf, &obuf, 1, 516 /*activepullup*/false, /*strongpullup*/false, 0); 517 if (matchdebug) { 518 printf("poke X 1: %d\n", error); 519 } 520 return error; 521 } 522 523 static int 524 ds2482_match(device_t parent, cfdata_t match, void *aux) 525 { 526 struct i2c_attach_args *ia = aux; 527 int error, match_result; 528 const bool matchdebug = false; 529 530 if (iic_use_direct_match(ia, match, NULL, &match_result)) 531 return match_result; 532 533 /* indirect config - check for configured address */ 534 if (!(ia->ia_addr >= DS2482_LOWEST_ADDR && 535 ia->ia_addr <= DS2482_HIGHEST_ADDR)) 536 return 0; 537 538 /* 539 * Check to see if something is really at this i2c address. This will 540 * keep phantom devices from appearing 541 */ 542 if (iic_acquire_bus(ia->ia_tag, 0) != 0) { 543 if (matchdebug) 544 printf("in match acquire bus failed\n"); 545 return 0; 546 } 547 548 error = ds2482_poke(ia->ia_tag, ia->ia_addr, matchdebug); 549 iic_release_bus(ia->ia_tag, 0); 550 551 return error == 0 ? I2C_MATCH_ADDRESS_AND_PROBE : 0; 552 } 553 554 static void 555 ds2482_attach(device_t parent, device_t self, void *aux) 556 { 557 struct ds2482ow_sc *sc; 558 struct i2c_attach_args *ia; 559 int error, i, num_channels = 1; 560 struct onewirebus_attach_args oba; 561 const struct sysctlnode *cnode; 562 int sysctlroot_num, pullup_num; 563 564 ia = aux; 565 sc = device_private(self); 566 567 sc->sc_dev = self; 568 sc->sc_tag = ia->ia_tag; 569 sc->sc_addr = ia->ia_addr; 570 sc->sc_ds2482debug = 0; 571 sc->sc_activepullup = false; 572 sc->sc_strongpullup = false; 573 sc->sc_is_800 = false; 574 575 aprint_normal("\n"); 576 577 mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE); 578 579 if ((error = sysctl_createv(&sc->sc_ds2482log, 0, NULL, &cnode, 580 0, CTLTYPE_NODE, device_xname(sc->sc_dev), 581 SYSCTL_DESCR("DS2482 controls"), NULL, 0, NULL, 0, CTL_HW, 582 CTL_CREATE, CTL_EOL)) != 0) 583 goto out; 584 585 sysctlroot_num = cnode->sysctl_num; 586 587 #ifdef DS2482_DEBUG 588 if ((error = sysctl_createv(&sc->sc_ds2482log, 0, NULL, &cnode, 589 CTLFLAG_READWRITE, CTLTYPE_INT, "debug", 590 SYSCTL_DESCR("Debug level"), ds2482_verify_sysctl, 0, 591 &sc->sc_ds2482debug, 0, CTL_HW, sysctlroot_num, CTL_CREATE, 592 CTL_EOL)) != 0) 593 goto out; 594 #endif 595 596 if ((error = sysctl_createv(&sc->sc_ds2482log, 0, NULL, &cnode, 597 0, CTLTYPE_NODE, "pullup", 598 SYSCTL_DESCR("Pullup controls"), NULL, 0, NULL, 0, CTL_HW, 599 sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0) 600 goto out; 601 602 pullup_num = cnode->sysctl_num; 603 604 if ((error = sysctl_createv(&sc->sc_ds2482log, 0, NULL, &cnode, 605 CTLFLAG_READWRITE, CTLTYPE_BOOL, "active", 606 SYSCTL_DESCR("Active pullup"), NULL, 0, &sc->sc_activepullup, 607 0, CTL_HW, sysctlroot_num, pullup_num, CTL_CREATE, CTL_EOL)) != 0) 608 goto out; 609 610 if ((error = sysctl_createv(&sc->sc_ds2482log, 0, NULL, &cnode, 611 CTLFLAG_READWRITE, CTLTYPE_BOOL, "strong", 612 SYSCTL_DESCR("Strong pullup"), NULL, 0, &sc->sc_strongpullup, 613 0, CTL_HW, sysctlroot_num, pullup_num, CTL_CREATE, CTL_EOL)) != 0) 614 goto out; 615 616 error = iic_acquire_bus(sc->sc_tag, 0); 617 if (error) { 618 aprint_error_dev(self, "Could not acquire iic bus: %d\n", 619 error); 620 goto out; 621 } 622 623 error = ds2482_cmdr(sc, DS2482_DEVICE_RESET, 0, NULL, 0); 624 if (error != 0) 625 aprint_error_dev(self, "Reset failed: %d\n", error); 626 627 if (!error) { 628 int xerror; 629 xerror = ds2482_cmdr(sc, DS2482_SELECT_CHANNEL, 630 DS2482_CHANNEL_IO0, NULL, 0); 631 if (!xerror) 632 sc->sc_is_800 = true; 633 } 634 635 iic_release_bus(sc->sc_tag, 0); 636 637 if (error != 0) { 638 aprint_error_dev(self, "Unable to setup device\n"); 639 goto out; 640 } 641 642 if (sc->sc_is_800) { 643 num_channels = DS2482_NUM_INSTANCES; 644 } 645 646 aprint_normal_dev(self, "Maxim DS2482-%s I2C to 1-Wire bridge," 647 " Channels available: %d\n", 648 sc->sc_is_800 ? "800" : "100", 649 num_channels); 650 651 for (i = 0; i < num_channels; i++) { 652 sc->sc_instances[i].sc_i_channel = i; 653 sc->sc_instances[i].sc = sc; 654 sc->sc_instances[i].sc_i_ow_bus.bus_cookie = 655 &sc->sc_instances[i]; 656 sc->sc_instances[i].sc_i_ow_bus.bus_reset = ds2482_ow_reset; 657 sc->sc_instances[i].sc_i_ow_bus.bus_read_bit = 658 ds2482_ow_read_bit; 659 sc->sc_instances[i].sc_i_ow_bus.bus_write_bit = 660 ds2482_ow_write_bit; 661 sc->sc_instances[i].sc_i_ow_bus.bus_read_byte = 662 ds2482_ow_read_byte; 663 sc->sc_instances[i].sc_i_ow_bus.bus_write_byte = 664 ds2482_ow_write_byte; 665 sc->sc_instances[i].sc_i_ow_bus.bus_triplet = 666 ds2482_ow_triplet; 667 668 memset(&oba, 0, sizeof(oba)); 669 oba.oba_bus = &sc->sc_instances[i].sc_i_ow_bus; 670 sc->sc_instances[i].sc_i_ow_dev = 671 config_found(self, &oba, onewirebus_print, CFARGS_NONE); 672 } 673 674 out: 675 return; 676 } 677 678 /* 679 * Hmmm... except in the case of reset, there really doesn't seem to 680 * be any way with the onewire(4) API to indicate an error condition. 681 */ 682 683 static int 684 ds2482_generic_action(struct ds2482_instance *sci, uint8_t cmd, uint8_t cmdarg, 685 uint8_t *buf, size_t blen) 686 { 687 struct ds2482ow_sc *sc = sci->sc; 688 int rv; 689 690 mutex_enter(&sc->sc_mutex); 691 rv = iic_acquire_bus(sc->sc_tag, 0); 692 if (!rv) { 693 rv = ds2482_set_channel(sc, sci->sc_i_channel); 694 if (!rv) 695 rv = ds2482_cmdr(sc, cmd, cmdarg, buf, blen); 696 } 697 iic_release_bus(sc->sc_tag, 0); 698 mutex_exit(&sc->sc_mutex); 699 700 return rv; 701 } 702 703 static int 704 ds2482_ow_reset(void *arg) 705 { 706 struct ds2482_instance *sci = arg; 707 struct ds2482ow_sc *sc = sci->sc; 708 int rv; 709 710 rv = ds2482_generic_action(sci, DS2482_ONEWIRE_RESET, 0, NULL, 0); 711 712 DPRINTF(sc, 3, ("%s: ds2482_ow_reset: channel: %d ; rv: %x %d\n", 713 device_xname(sc->sc_dev), sci->sc_i_channel, rv, rv)); 714 715 return rv; 716 } 717 718 static int 719 ds2482_ow_read_bit(void *arg) 720 { 721 struct ds2482_instance *sci = arg; 722 struct ds2482ow_sc *sc = sci->sc; 723 int rv; 724 uint8_t buf = 0x55; 725 726 rv = ds2482_generic_action(sci, DS2482_ONEWIRE_SINGLE_BIT_READ, 0, 727 &buf, 1); 728 729 DPRINTF(sc, 3, 730 ("%s: ds2482_read_bit: channel: %d ; rv: %x %d ; buf: %02x %d\n", 731 device_xname(sc->sc_dev), sci->sc_i_channel, rv, rv, buf, buf)); 732 733 return (int)buf; 734 } 735 736 static void 737 ds2482_ow_write_bit(void *arg, int value) 738 { 739 struct ds2482_instance *sci = arg; 740 struct ds2482ow_sc *sc = sci->sc; 741 int rv; 742 743 rv = ds2482_generic_action(sci, DS2482_ONEWIRE_SINGLE_BIT_WRITE, 744 (uint8_t)value, NULL, 0); 745 746 DPRINTF(sc, 3, ("%s: ds2482_write_bit: channel: %d ;" 747 " rv: %x %d ; value: %02x %d\n", 748 device_xname(sc->sc_dev), sci->sc_i_channel, 749 rv, rv, (uint8_t)value, (uint8_t)value)); 750 } 751 752 static int 753 ds2482_ow_read_byte(void *arg) 754 { 755 struct ds2482_instance *sci = arg; 756 uint8_t buf = 0x55; 757 struct ds2482ow_sc *sc = sci->sc; 758 int rv; 759 760 rv = ds2482_generic_action(sci, DS2482_ONEWIRE_READ_BYTE, 0, &buf, 1); 761 762 DPRINTF(sc, 3, 763 ("%s: ds2482_read_byte: channel: %d ; rv: %x %d ; buf: %02x %d\n", 764 device_xname(sc->sc_dev), sci->sc_i_channel, rv, rv, buf, buf)); 765 766 return (int)buf; 767 } 768 769 static void 770 ds2482_ow_write_byte(void *arg, int value) 771 { 772 struct ds2482_instance *sci = arg; 773 struct ds2482ow_sc *sc = sci->sc; 774 int rv; 775 776 rv = ds2482_generic_action(sci, DS2482_ONEWIRE_WRITE_BYTE, 777 (uint8_t)value, NULL, 0); 778 779 DPRINTF(sc, 3, ("%s: ds2482_write_byte: channel: %d ;" 780 " rv: %x %d ; value: %02x %d\n", 781 device_xname(sc->sc_dev), sci->sc_i_channel, 782 rv, rv, (uint8_t)value, (uint8_t)value)); 783 } 784 785 static int 786 ds2482_ow_triplet(void *arg, int dir) 787 { 788 struct ds2482_instance *sci = arg; 789 uint8_t buf = 0x55; 790 struct ds2482ow_sc *sc = sci->sc; 791 int rv; 792 793 rv = ds2482_generic_action(sci, DS2482_ONEWIRE_TRIPLET, (uint8_t)dir, 794 &buf, 1); 795 796 DPRINTF(sc, 3, ("%s: ds2482_triplet: channel: %d ;" 797 " rv: %x %d ; dir: %x %d ; buf: %02x %d\n", 798 device_xname(sc->sc_dev), sci->sc_i_channel, rv, rv, 799 dir, dir, (uint8_t)buf, (uint8_t)buf)); 800 801 return (int)buf; 802 } 803 804 static int 805 ds2482_detach(device_t self, int flags) 806 { 807 struct ds2482ow_sc *sc; 808 809 sc = device_private(self); 810 811 /* Remove the sysctl tree */ 812 sysctl_teardown(&sc->sc_ds2482log); 813 814 /* Remove the mutex */ 815 mutex_destroy(&sc->sc_mutex); 816 817 return 0; 818 } 819 820 MODULE(MODULE_CLASS_DRIVER, ds2482ow, "iic,onewire"); 821 822 #ifdef _MODULE 823 #include "ioconf.c" 824 #endif 825 826 static int 827 ds2482ow_modcmd(modcmd_t cmd, void *opaque) 828 { 829 830 switch (cmd) { 831 case MODULE_CMD_INIT: 832 #ifdef _MODULE 833 return config_init_component(cfdriver_ioconf_ds2482ow, 834 cfattach_ioconf_ds2482ow, cfdata_ioconf_ds2482ow); 835 #else 836 return 0; 837 #endif 838 case MODULE_CMD_FINI: 839 #ifdef _MODULE 840 return config_fini_component(cfdriver_ioconf_ds2482ow, 841 cfattach_ioconf_ds2482ow, cfdata_ioconf_ds2482ow); 842 #else 843 return 0; 844 #endif 845 default: 846 return ENOTTY; 847 } 848 } 849