xref: /netbsd-src/sys/dev/onewire/onewire.c (revision 76c7fc5f6b13ed0b1508e6b313e88e59977ed78e)
1 /*	$NetBSD: onewire.c,v 1.17 2019/10/25 16:25:14 martin Exp $	*/
2 /*	$OpenBSD: onewire.c,v 1.1 2006/03/04 16:27:03 grange Exp $	*/
3 
4 /*
5  * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/cdefs.h>
21 __KERNEL_RCSID(0, "$NetBSD: onewire.c,v 1.17 2019/10/25 16:25:14 martin Exp $");
22 
23 /*
24  * 1-Wire bus driver.
25  */
26 
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/conf.h>
30 #include <sys/device.h>
31 #include <sys/kernel.h>
32 #include <sys/kthread.h>
33 #include <sys/kmem.h>
34 #include <sys/proc.h>
35 #include <sys/queue.h>
36 #include <sys/module.h>
37 
38 #include <dev/onewire/onewirereg.h>
39 #include <dev/onewire/onewirevar.h>
40 
41 #ifdef ONEWIRE_DEBUG
42 #define DPRINTF(x) printf x
43 #else
44 #define DPRINTF(x)
45 #endif
46 
47 int	onewire_maxdevs = 8;
48 int	onewire_scantime = 10;	/* was 3 seconds - too often */
49 
50 struct onewire_softc {
51 	device_t			sc_dev;
52 	struct onewire_bus *		sc_bus;
53 	kmutex_t			sc_lock;
54 	kcondvar_t			sc_scancv;
55 	struct lwp *			sc_thread;
56 	TAILQ_HEAD(, onewire_device)	sc_devs;
57 	int				sc_dying;
58 };
59 
60 struct onewire_device {
61 	TAILQ_ENTRY(onewire_device)	d_list;
62 	device_t			d_dev;
63 	u_int64_t			d_rom;
64 	bool				d_present;
65 };
66 
67 static int	onewire_match(device_t, cfdata_t, void *);
68 static void	onewire_attach(device_t, device_t, void *);
69 static int	onewire_detach(device_t, int);
70 static int	onewire_activate(device_t, enum devact);
71 int		onewire_print(void *, const char *);
72 
73 static void	onewire_thread(void *);
74 static void	onewire_scan(struct onewire_softc *);
75 
76 CFATTACH_DECL_NEW(onewire, sizeof(struct onewire_softc),
77 	onewire_match, onewire_attach, onewire_detach, onewire_activate);
78 
79 extern struct cfdriver onewire_cd;
80 
81 static int
82 onewire_match(device_t parent, cfdata_t cf, void *aux)
83 {
84 	return 1;
85 }
86 
87 static void
88 onewire_attach(device_t parent, device_t self, void *aux)
89 {
90 	struct onewire_softc *sc = device_private(self);
91 	struct onewirebus_attach_args *oba = aux;
92 
93 	sc->sc_dev = self;
94 	sc->sc_bus = oba->oba_bus;
95 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
96 	cv_init(&sc->sc_scancv, "owscan");
97 	TAILQ_INIT(&sc->sc_devs);
98 
99 	aprint_normal("\n");
100 
101 	if (kthread_create(PRI_NONE, KTHREAD_MUSTJOIN | KTHREAD_MPSAFE, NULL,
102 	    onewire_thread, sc, &sc->sc_thread, "%s", device_xname(self)) != 0) {
103 		aprint_error_dev(self, "can't create kernel thread\n");
104 		/* Normally the kthread destroys these. */
105 		mutex_destroy(&sc->sc_lock);
106 		cv_destroy(&sc->sc_scancv);
107 	}
108 }
109 
110 static int
111 onewire_detach(device_t self, int flags)
112 {
113 	struct onewire_softc *sc = device_private(self);
114 	int rv;
115 
116 	if (sc->sc_thread != NULL) {
117 		mutex_enter(&sc->sc_lock);
118 		sc->sc_dying = 1;
119 		cv_broadcast(&sc->sc_scancv);
120 		mutex_exit(&sc->sc_lock);
121 		/* Must no longer touch sc_lock nor sc_scancv. */
122 		kthread_join(sc->sc_thread);
123 	}
124 
125 	//rv = config_detach_children(self, flags);
126 	rv = 0;  /* XXX riz */
127 
128 	return rv;
129 }
130 
131 static int
132 onewire_activate(device_t self, enum devact act)
133 {
134 	struct onewire_softc *sc = device_private(self);
135 
136 	switch (act) {
137 	case DVACT_DEACTIVATE:
138 		sc->sc_dying = 1;
139 		return 0;
140 	default:
141 		return EOPNOTSUPP;
142 	}
143 }
144 
145 int
146 onewire_print(void *aux, const char *pnp)
147 {
148 	struct onewire_attach_args *oa = aux;
149 	const char *famname;
150 
151 	if (pnp == NULL)
152 		aprint_normal(" ");
153 
154 	famname = onewire_famname(ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
155 	if (famname == NULL)
156 		aprint_normal("family 0x%02x",
157 		    (uint)ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
158 	else
159 		aprint_normal("\"%s\"", famname);
160 	aprint_normal(" sn %012" PRIx64, ONEWIRE_ROM_SN(oa->oa_rom));
161 
162 	if (pnp != NULL)
163 		aprint_normal(" at %s", pnp);
164 
165 	return UNCONF;
166 }
167 
168 int
169 onewirebus_print(void *aux, const char *pnp)
170 {
171 	if (pnp != NULL)
172 		aprint_normal("onewire at %s", pnp);
173 
174 	return UNCONF;
175 }
176 
177 void
178 onewire_lock(void *arg)
179 {
180 	struct onewire_softc *sc = arg;
181 
182 	mutex_enter(&sc->sc_lock);
183 }
184 
185 void
186 onewire_unlock(void *arg)
187 {
188 	struct onewire_softc *sc = arg;
189 
190 	mutex_exit(&sc->sc_lock);
191 }
192 
193 int
194 onewire_reset(void *arg)
195 {
196 	struct onewire_softc *sc = arg;
197 	struct onewire_bus *bus = sc->sc_bus;
198 
199 	KASSERT(mutex_owned(&sc->sc_lock));
200 
201 	return bus->bus_reset(bus->bus_cookie);
202 }
203 
204 int
205 onewire_bit(void *arg, int value)
206 {
207 	struct onewire_softc *sc = arg;
208 	struct onewire_bus *bus = sc->sc_bus;
209 
210 	KASSERT(mutex_owned(&sc->sc_lock));
211 
212 	return bus->bus_bit(bus->bus_cookie, value);
213 }
214 
215 int
216 onewire_read_byte(void *arg)
217 {
218 	struct onewire_softc *sc = arg;
219 	struct onewire_bus *bus = sc->sc_bus;
220 	uint8_t value = 0;
221 	int i;
222 
223 	KASSERT(mutex_owned(&sc->sc_lock));
224 
225 	if (bus->bus_read_byte != NULL)
226 		return bus->bus_read_byte(bus->bus_cookie);
227 
228 	for (i = 0; i < 8; i++)
229 		value |= (bus->bus_bit(bus->bus_cookie, 1) << i);
230 
231 	return value;
232 }
233 
234 void
235 onewire_write_byte(void *arg, int value)
236 {
237 	struct onewire_softc *sc = arg;
238 	struct onewire_bus *bus = sc->sc_bus;
239 	int i;
240 
241 	KASSERT(mutex_owned(&sc->sc_lock));
242 
243 	if (bus->bus_write_byte != NULL)
244 		return bus->bus_write_byte(bus->bus_cookie, value);
245 
246 	for (i = 0; i < 8; i++)
247 		bus->bus_bit(bus->bus_cookie, (value >> i) & 0x1);
248 }
249 
250 int
251 onewire_triplet(void *arg, int dir)
252 {
253 	struct onewire_softc *sc = arg;
254 	struct onewire_bus *bus = sc->sc_bus;
255 	int rv;
256 
257 	KASSERT(mutex_owned(&sc->sc_lock));
258 
259 	if (bus->bus_triplet != NULL)
260 		return bus->bus_triplet(bus->bus_cookie, dir);
261 
262 	rv = bus->bus_bit(bus->bus_cookie, 1);
263 	rv <<= 1;
264 	rv |= bus->bus_bit(bus->bus_cookie, 1);
265 
266 	switch (rv) {
267 	case 0x0:
268 		bus->bus_bit(bus->bus_cookie, dir);
269 		break;
270 	case 0x1:
271 		bus->bus_bit(bus->bus_cookie, 0);
272 		break;
273 	default:
274 		bus->bus_bit(bus->bus_cookie, 1);
275 	}
276 
277 	return rv;
278 }
279 
280 void
281 onewire_read_block(void *arg, void *buf, int len)
282 {
283 	struct onewire_softc *sc = arg;
284 	uint8_t *p = buf;
285 
286 	KASSERT(mutex_owned(&sc->sc_lock));
287 
288 	while (len--)
289 		*p++ = onewire_read_byte(sc);
290 }
291 
292 void
293 onewire_write_block(void *arg, const void *buf, int len)
294 {
295 	struct onewire_softc *sc = arg;
296 	const uint8_t *p = buf;
297 
298 	KASSERT(mutex_owned(&sc->sc_lock));
299 
300 	while (len--)
301 		onewire_write_byte(sc, *p++);
302 }
303 
304 void
305 onewire_matchrom(void *arg, u_int64_t rom)
306 {
307 	struct onewire_softc *sc = arg;
308 	int i;
309 
310 	KASSERT(mutex_owned(&sc->sc_lock));
311 
312 	onewire_write_byte(sc, ONEWIRE_CMD_MATCH_ROM);
313 	for (i = 0; i < 8; i++)
314 		onewire_write_byte(sc, (rom >> (i * 8)) & 0xff);
315 }
316 
317 static void
318 onewire_thread(void *arg)
319 {
320 	struct onewire_softc *sc = arg;
321 
322 	mutex_enter(&sc->sc_lock);
323 	while (!sc->sc_dying) {
324 		onewire_scan(sc);
325 		(void)cv_timedwait(&sc->sc_scancv, &sc->sc_lock,
326 		    onewire_scantime * hz);
327 	}
328 	mutex_exit(&sc->sc_lock);
329 
330 	/* Caller has set sc_dying and will no longer touch these. */
331 	cv_destroy(&sc->sc_scancv);
332 	mutex_destroy(&sc->sc_lock);
333 	kthread_exit(0);
334 }
335 
336 static void
337 onewire_scan(struct onewire_softc *sc)
338 {
339 	struct onewire_device *d, *next, *nd;
340 	struct onewire_attach_args oa;
341 	int search = 1, count = 0, present;
342 	int dir, rv;
343 	uint64_t mask, rom = 0, lastrom;
344 	uint8_t data[8];
345 	int i, i0 = -1, lastd = -1;
346 
347 	TAILQ_FOREACH(d, &sc->sc_devs, d_list) {
348 		d->d_present = false;
349 		KASSERT(d->d_dev != NULL);
350 	}
351 
352 	KASSERT(mutex_owned(&sc->sc_lock));
353 	KASSERT(curlwp == sc->sc_thread);
354 
355 	while (search && count++ < onewire_maxdevs) {
356 		/*
357 		 * Reset the bus. If there's no presence pulse
358 		 * don't search for any devices.
359 		 */
360 		if (onewire_reset(sc) != 0) {
361 			DPRINTF(("%s: scan: no presence pulse\n",
362 			    device_xname(sc->sc_dev)));
363 			break;
364 		}
365 
366 		/*
367 		 * Start new search. Go through the previous path to
368 		 * the point we made a decision last time and make an
369 		 * opposite decision. If we didn't make any decision
370 		 * stop searching.
371 		 */
372 		search = 0;
373 		lastrom = rom;
374 		rom = 0;
375 		onewire_write_byte(sc, ONEWIRE_CMD_SEARCH_ROM);
376 		for (i = 0,i0 = -1; i < 64; i++) {
377 			dir = (lastrom >> i) & 0x1;
378 			if (i == lastd)
379 				dir = 1;
380 			else if (i > lastd)
381 				dir = 0;
382 			rv = onewire_triplet(sc, dir);
383 			switch (rv) {
384 			case 0x0:
385 				if (i != lastd) {
386 					if (dir == 0)
387 						i0 = i;
388 					search = 1;
389 				}
390 				mask = dir;
391 				break;
392 			case 0x1:
393 				mask = 0;
394 				break;
395 			case 0x2:
396 				mask = 1;
397 				break;
398 			default:
399 				DPRINTF(("%s: scan: triplet error 0x%x, "
400 				    "step %d\n",
401 				    device_xname(sc->sc_dev), rv, i));
402 				return;
403 			}
404 			rom |= (mask << i);
405 		}
406 		lastd = i0;
407 
408 		if (rom == 0)
409 			continue;
410 
411 		/*
412 		 * The last byte of the ROM code contains a CRC calculated
413 		 * from the first 7 bytes. Re-calculate it to make sure
414 		 * we found a valid device.
415 		 */
416 		for (i = 0; i < 8; i++)
417 			data[i] = (rom >> (i * 8)) & 0xff;
418 		if (onewire_crc(data, 7) != data[7])
419 			continue;
420 
421 		/*
422 		 * Go through the list of attached devices to see if we
423 		 * found a new one.
424 		 */
425 		present = 0;
426 	 	TAILQ_FOREACH(d, &sc->sc_devs, d_list) {
427 			if (d->d_rom == rom) {
428 				d->d_present = true;
429 				present = 1;
430 				break;
431 			}
432 		}
433 		if (!present) {
434 			nd = kmem_alloc(sizeof(*nd), KM_SLEEP);
435 			nd->d_dev = NULL;
436 			nd->d_rom = rom;
437 			nd->d_present = true;
438 			TAILQ_INSERT_TAIL(&sc->sc_devs, nd, d_list);
439 		}
440 
441 		/*
442 		 * Yield processor, but continue to hold the lock
443 		 * so that scan is not interrupted.
444 		 */
445 		kpause("owscan", false, 1, NULL);
446 	}
447 
448 	/*
449 	 * Detach disappeared devices, and attach new devices.  Drop the
450 	 * lock when doing this in order to prevent lock order reversal
451 	 * against sysmon.  This is safe because nothing other than this
452 	 * kthread modifies our device list.
453 	 */
454 	for (d = TAILQ_FIRST(&sc->sc_devs); d != NULL; d = next) {
455 		next = TAILQ_NEXT(d, d_list);
456 		if (!d->d_present) {
457 			mutex_exit(&sc->sc_lock);
458 
459 			KERNEL_LOCK(1, NULL); /* XXXSMP */
460 			config_detach(d->d_dev, DETACH_FORCE);
461 			d->d_dev = NULL;
462 			KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
463 
464 			mutex_enter(&sc->sc_lock);
465 		} else if (d->d_dev == NULL) {
466 			memset(&oa, 0, sizeof(oa));
467 			oa.oa_onewire = sc;
468 			oa.oa_rom = d->d_rom;
469 			mutex_exit(&sc->sc_lock);
470 
471 			KERNEL_LOCK(1, NULL); /* XXXSMP */
472 			d->d_dev = config_found(sc->sc_dev, &oa, onewire_print);
473 			KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
474 
475 			mutex_enter(&sc->sc_lock);
476 		}
477 		if (d->d_dev == NULL) {
478 			TAILQ_REMOVE(&sc->sc_devs, d, d_list);
479 			kmem_free(d, sizeof(*d));
480 		}
481 	}
482 }
483 
484 MODULE(MODULE_CLASS_DRIVER, onewire, NULL);
485 
486 #ifdef _MODULE
487 #include "ioconf.c"
488 #endif
489 
490 static int
491 onewire_modcmd(modcmd_t cmd, void *opaque)
492 {
493 	int error;
494 
495 	error = 0;
496 	switch (cmd) {
497 	case MODULE_CMD_INIT:
498 #ifdef _MODULE
499 		error = config_init_component(cfdriver_ioconf_onewire,
500 		    cfattach_ioconf_onewire, cfdata_ioconf_onewire);
501 		if (error)
502 			aprint_error("%s: unable to init component\n",
503 			    onewire_cd.cd_name);
504 #endif
505 		break;
506 	case MODULE_CMD_FINI:
507 #ifdef _MODULE
508 		config_fini_component(cfdriver_ioconf_onewire,
509 		    cfattach_ioconf_onewire, cfdata_ioconf_onewire);
510 #endif
511 		break;
512 	default:
513 		error = ENOTTY;
514 	}
515 	return error;
516 }
517