xref: /netbsd-src/sys/dev/onewire/onewire.c (revision d909946ca08dceb44d7d0f22ec9488679695d976)
1 /* $NetBSD: onewire.c,v 1.16 2014/07/25 08:10:38 dholland 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.16 2014/07/25 08:10:38 dholland 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/rwlock.h>
34 #include <sys/malloc.h>
35 #include <sys/proc.h>
36 #include <sys/queue.h>
37 #include <sys/module.h>
38 
39 #include <dev/onewire/onewirereg.h>
40 #include <dev/onewire/onewirevar.h>
41 
42 #ifdef ONEWIRE_DEBUG
43 #define DPRINTF(x) printf x
44 #else
45 #define DPRINTF(x)
46 #endif
47 
48 //#define ONEWIRE_MAXDEVS		256
49 #define ONEWIRE_MAXDEVS		8
50 #define ONEWIRE_SCANTIME	3
51 
52 struct onewire_softc {
53 	device_t			sc_dev;
54 
55 	struct onewire_bus *		sc_bus;
56 	krwlock_t			sc_rwlock;
57 	struct lwp *			sc_thread;
58 	TAILQ_HEAD(, onewire_device)	sc_devs;
59 
60 	int				sc_dying;
61 };
62 
63 struct onewire_device {
64 	TAILQ_ENTRY(onewire_device)	d_list;
65 	device_t			d_dev;
66 	u_int64_t			d_rom;
67 	int				d_present;
68 };
69 
70 static int	onewire_match(device_t, cfdata_t, void *);
71 static void	onewire_attach(device_t, device_t, void *);
72 static int	onewire_detach(device_t, int);
73 static int	onewire_activate(device_t, enum devact);
74 int		onewire_print(void *, const char *);
75 
76 static void	onewire_thread(void *);
77 static void	onewire_scan(struct onewire_softc *);
78 
79 CFATTACH_DECL_NEW(onewire, sizeof(struct onewire_softc),
80 	onewire_match, onewire_attach, onewire_detach, onewire_activate);
81 
82 const struct cdevsw onewire_cdevsw = {
83 	.d_open = noopen,
84 	.d_close = noclose,
85 	.d_read = noread,
86 	.d_write = nowrite,
87 	.d_ioctl = noioctl,
88 	.d_stop = nostop,
89 	.d_tty = notty,
90 	.d_poll = nopoll,
91 	.d_mmap = nommap,
92 	.d_kqfilter = nokqfilter,
93 	.d_discard = nodiscard,
94 	.d_flag = D_OTHER
95 };
96 
97 extern struct cfdriver onewire_cd;
98 
99 static int
100 onewire_match(device_t parent, cfdata_t cf, void *aux)
101 {
102 	return 1;
103 }
104 
105 static void
106 onewire_attach(device_t parent, device_t self, void *aux)
107 {
108 	struct onewire_softc *sc = device_private(self);
109 	struct onewirebus_attach_args *oba = aux;
110 
111 	sc->sc_dev = self;
112 	sc->sc_bus = oba->oba_bus;
113 	rw_init(&sc->sc_rwlock);
114 	TAILQ_INIT(&sc->sc_devs);
115 
116 	aprint_normal("\n");
117 
118 	if (kthread_create(PRI_NONE, 0, NULL, onewire_thread, sc,
119 	    &sc->sc_thread, "%s", device_xname(self)) != 0)
120 		aprint_error_dev(self, "can't create kernel thread\n");
121 }
122 
123 static int
124 onewire_detach(device_t self, int flags)
125 {
126 	struct onewire_softc *sc = device_private(self);
127 	int rv;
128 
129 	sc->sc_dying = 1;
130 	if (sc->sc_thread != NULL) {
131 		wakeup(sc->sc_thread);
132 		tsleep(&sc->sc_dying, PWAIT, "owdt", 0);
133 	}
134 
135 	onewire_lock(sc);
136 	//rv = config_detach_children(self, flags);
137 	rv = 0;  /* XXX riz */
138 	onewire_unlock(sc);
139 	rw_destroy(&sc->sc_rwlock);
140 
141 	return rv;
142 }
143 
144 static int
145 onewire_activate(device_t self, enum devact act)
146 {
147 	struct onewire_softc *sc = device_private(self);
148 
149 	switch (act) {
150 	case DVACT_DEACTIVATE:
151 		sc->sc_dying = 1;
152 		return 0;
153 	default:
154 		return EOPNOTSUPP;
155 	}
156 }
157 
158 int
159 onewire_print(void *aux, const char *pnp)
160 {
161 	struct onewire_attach_args *oa = aux;
162 	const char *famname;
163 
164 	if (pnp == NULL)
165 		aprint_normal(" ");
166 
167 	famname = onewire_famname(ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
168 	if (famname == NULL)
169 		aprint_normal("family 0x%02x",
170 		    (uint)ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
171 	else
172 		aprint_normal("\"%s\"", famname);
173 	aprint_normal(" sn %012llx", ONEWIRE_ROM_SN(oa->oa_rom));
174 
175 	if (pnp != NULL)
176 		aprint_normal(" at %s", pnp);
177 
178 	return UNCONF;
179 }
180 
181 int
182 onewirebus_print(void *aux, const char *pnp)
183 {
184 	if (pnp != NULL)
185 		aprint_normal("onewire at %s", pnp);
186 
187 	return UNCONF;
188 }
189 
190 void
191 onewire_lock(void *arg)
192 {
193 	struct onewire_softc *sc = arg;
194 
195 	rw_enter(&sc->sc_rwlock, RW_WRITER);
196 }
197 
198 void
199 onewire_unlock(void *arg)
200 {
201 	struct onewire_softc *sc = arg;
202 
203 	rw_exit(&sc->sc_rwlock);
204 }
205 
206 int
207 onewire_reset(void *arg)
208 {
209 	struct onewire_softc *sc = arg;
210 	struct onewire_bus *bus = sc->sc_bus;
211 
212 	return bus->bus_reset(bus->bus_cookie);
213 }
214 
215 int
216 onewire_bit(void *arg, int value)
217 {
218 	struct onewire_softc *sc = arg;
219 	struct onewire_bus *bus = sc->sc_bus;
220 
221 	return bus->bus_bit(bus->bus_cookie, value);
222 }
223 
224 int
225 onewire_read_byte(void *arg)
226 {
227 	struct onewire_softc *sc = arg;
228 	struct onewire_bus *bus = sc->sc_bus;
229 	uint8_t value = 0;
230 	int i;
231 
232 	if (bus->bus_read_byte != NULL)
233 		return bus->bus_read_byte(bus->bus_cookie);
234 
235 	for (i = 0; i < 8; i++)
236 		value |= (bus->bus_bit(bus->bus_cookie, 1) << i);
237 
238 	return value;
239 }
240 
241 void
242 onewire_write_byte(void *arg, int value)
243 {
244 	struct onewire_softc *sc = arg;
245 	struct onewire_bus *bus = sc->sc_bus;
246 	int i;
247 
248 	if (bus->bus_write_byte != NULL)
249 		return bus->bus_write_byte(bus->bus_cookie, value);
250 
251 	for (i = 0; i < 8; i++)
252 		bus->bus_bit(bus->bus_cookie, (value >> i) & 0x1);
253 }
254 
255 int
256 onewire_triplet(void *arg, int dir)
257 {
258 	struct onewire_softc *sc = arg;
259 	struct onewire_bus *bus = sc->sc_bus;
260 	int rv;
261 
262 	if (bus->bus_triplet != NULL)
263 		return bus->bus_triplet(bus->bus_cookie, dir);
264 
265 	rv = bus->bus_bit(bus->bus_cookie, 1);
266 	rv <<= 1;
267 	rv |= bus->bus_bit(bus->bus_cookie, 1);
268 
269 	switch (rv) {
270 	case 0x0:
271 		bus->bus_bit(bus->bus_cookie, dir);
272 		break;
273 	case 0x1:
274 		bus->bus_bit(bus->bus_cookie, 0);
275 		break;
276 	default:
277 		bus->bus_bit(bus->bus_cookie, 1);
278 	}
279 
280 	return rv;
281 }
282 
283 void
284 onewire_read_block(void *arg, void *buf, int len)
285 {
286 	uint8_t *p = buf;
287 
288 	while (len--)
289 		*p++ = onewire_read_byte(arg);
290 }
291 
292 void
293 onewire_write_block(void *arg, const void *buf, int len)
294 {
295 	const uint8_t *p = buf;
296 
297 	while (len--)
298 		onewire_write_byte(arg, *p++);
299 }
300 
301 void
302 onewire_matchrom(void *arg, u_int64_t rom)
303 {
304 	int i;
305 
306 	onewire_write_byte(arg, ONEWIRE_CMD_MATCH_ROM);
307 	for (i = 0; i < 8; i++)
308 		onewire_write_byte(arg, (rom >> (i * 8)) & 0xff);
309 }
310 
311 static void
312 onewire_thread(void *arg)
313 {
314 	struct onewire_softc *sc = arg;
315 
316 	while (!sc->sc_dying) {
317 		onewire_scan(sc);
318 		tsleep(sc->sc_thread, PWAIT, "owidle", ONEWIRE_SCANTIME * hz);
319 	}
320 
321 	sc->sc_thread = NULL;
322 	wakeup(&sc->sc_dying);
323 	kthread_exit(0);
324 }
325 
326 static void
327 onewire_scan(struct onewire_softc *sc)
328 {
329 	struct onewire_device *d, *next, *nd;
330 	struct onewire_attach_args oa;
331 	device_t dev;
332 	int search = 1, count = 0, present;
333 	int dir, rv;
334 	uint64_t mask, rom = 0, lastrom;
335 	uint8_t data[8];
336 	int i, i0 = -1, lastd = -1;
337 
338 	TAILQ_FOREACH(d, &sc->sc_devs, d_list)
339 		d->d_present = 0;
340 
341 	while (search && count++ < ONEWIRE_MAXDEVS) {
342 		/* XXX: yield processor */
343 		tsleep(sc, PWAIT, "owscan", hz / 10);
344 
345 		/*
346 		 * Reset the bus. If there's no presence pulse
347 		 * don't search for any devices.
348 		 */
349 		onewire_lock(sc);
350 		if (onewire_reset(sc) != 0) {
351 			DPRINTF(("%s: scan: no presence pulse\n",
352 			    device_xname(sc->sc_dev)));
353 			onewire_unlock(sc);
354 			break;
355 		}
356 
357 		/*
358 		 * Start new search. Go through the previous path to
359 		 * the point we made a decision last time and make an
360 		 * opposite decision. If we didn't make any decision
361 		 * stop searching.
362 		 */
363 		search = 0;
364 		lastrom = rom;
365 		rom = 0;
366 		onewire_write_byte(sc, ONEWIRE_CMD_SEARCH_ROM);
367 		for (i = 0,i0 = -1; i < 64; i++) {
368 			dir = (lastrom >> i) & 0x1;
369 			if (i == lastd)
370 				dir = 1;
371 			else if (i > lastd)
372 				dir = 0;
373 			rv = onewire_triplet(sc, dir);
374 			switch (rv) {
375 			case 0x0:
376 				if (i != lastd) {
377 					if (dir == 0)
378 						i0 = i;
379 					search = 1;
380 				}
381 				mask = dir;
382 				break;
383 			case 0x1:
384 				mask = 0;
385 				break;
386 			case 0x2:
387 				mask = 1;
388 				break;
389 			default:
390 				DPRINTF(("%s: scan: triplet error 0x%x, "
391 				    "step %d\n",
392 				    device_xname(sc->sc_dev), rv, i));
393 				onewire_unlock(sc);
394 				return;
395 			}
396 			rom |= (mask << i);
397 		}
398 		lastd = i0;
399 		onewire_unlock(sc);
400 
401 		if (rom == 0)
402 			continue;
403 
404 		/*
405 		 * The last byte of the ROM code contains a CRC calculated
406 		 * from the first 7 bytes. Re-calculate it to make sure
407 		 * we found a valid device.
408 		 */
409 		for (i = 0; i < 8; i++)
410 			data[i] = (rom >> (i * 8)) & 0xff;
411 		if (onewire_crc(data, 7) != data[7])
412 			continue;
413 
414 		/*
415 		 * Go through the list of attached devices to see if we
416 		 * found a new one.
417 		 */
418 		present = 0;
419 	 	TAILQ_FOREACH(d, &sc->sc_devs, d_list) {
420 			if (d->d_rom == rom) {
421 				d->d_present = 1;
422 				present = 1;
423 				break;
424 			}
425 		}
426 		if (!present) {
427 			memset(&oa, 0, sizeof(oa));
428 			oa.oa_onewire = sc;
429 			oa.oa_rom = rom;
430 			if ((dev = config_found(sc->sc_dev, &oa,
431 			    onewire_print)) == NULL)
432 				continue;
433 
434 			nd = malloc(sizeof(struct onewire_device),
435 				M_DEVBUF, M_NOWAIT);
436 			if (nd == NULL)
437 				continue;
438 			nd->d_dev = dev;
439 			nd->d_rom = rom;
440 			nd->d_present = 1;
441 			TAILQ_INSERT_TAIL(&sc->sc_devs, nd, d_list);
442 		}
443 	}
444 
445 	/* Detach disappeared devices */
446 	onewire_lock(sc);
447 	for (d = TAILQ_FIRST(&sc->sc_devs);
448 	    d != NULL; d = next) {
449 		next = TAILQ_NEXT(d, d_list);
450 		if (!d->d_present) {
451 			config_detach(d->d_dev, DETACH_FORCE);
452 			TAILQ_REMOVE(&sc->sc_devs, d, d_list);
453 			free(d, M_DEVBUF);
454 		}
455 	}
456 	onewire_unlock(sc);
457 }
458 
459 MODULE(MODULE_CLASS_DRIVER, onewire, NULL);
460 
461 #ifdef _MODULE
462 #include "ioconf.c"
463 #endif
464 
465 static int
466 onewire_modcmd(modcmd_t cmd, void *opaque)
467 {
468 	int error;
469 
470 	error = 0;
471 	switch (cmd) {
472 	case MODULE_CMD_INIT:
473 #ifdef _MODULE
474 		error = config_init_component(cfdriver_ioconf_onewire,
475 		    cfattach_ioconf_onewire, cfdata_ioconf_onewire);
476 		if (error)
477 			aprint_error("%s: unable to init component\n",
478 			    onewire_cd.cd_name);
479 #endif
480 		break;
481 	case MODULE_CMD_FINI:
482 #ifdef _MODULE
483 		config_fini_component(cfdriver_ioconf_onewire,
484 		    cfattach_ioconf_onewire, cfdata_ioconf_onewire);
485 #endif
486 		break;
487 	default:
488 		error = ENOTTY;
489 	}
490 	return error;
491 }
492