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
ds2482_verify_sysctl(SYSCTLFN_ARGS)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
ds2482_set_pullup(i2c_tag_t tag,i2c_addr_t addr,bool activepullup,bool strongpullup,int debuglevel)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
ds2482_wait_with_status(i2c_tag_t tag,i2c_addr_t addr,uint8_t * status,unsigned int d,bool set_pointer,int debuglevel)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
ds2482_cmd(i2c_tag_t tag,i2c_addr_t addr,uint8_t * cmd,uint8_t * cmdarg,uint8_t * obuf,size_t obuflen,bool activepullup,bool strongpullup,int debuglevel)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
ds2482_cmdr(struct ds2482ow_sc * sc,uint8_t cmd,uint8_t cmdarg,uint8_t * buf,size_t blen)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
ds2482_set_channel(struct ds2482ow_sc * sc,int channel)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
ds2482_poke(i2c_tag_t tag,i2c_addr_t addr,bool matchdebug)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
ds2482_match(device_t parent,cfdata_t match,void * aux)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
ds2482_attach(device_t parent,device_t self,void * aux)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
ds2482_generic_action(struct ds2482_instance * sci,uint8_t cmd,uint8_t cmdarg,uint8_t * buf,size_t blen)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
ds2482_ow_reset(void * arg)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
ds2482_ow_read_bit(void * arg)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
ds2482_ow_write_bit(void * arg,int value)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
ds2482_ow_read_byte(void * arg)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
ds2482_ow_write_byte(void * arg,int value)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
ds2482_ow_triplet(void * arg,int dir)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
ds2482_detach(device_t self,int flags)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
ds2482ow_modcmd(modcmd_t cmd,void * opaque)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