xref: /netbsd-src/sys/dev/i2c/ds2482ow.c (revision 79011e4db3dc025aa46bb15faf80ab85217cf011)
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, &reg, &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