xref: /freebsd/sys/dev/iicbus/adc/ads111x.c (revision 06589d6e029c6ff64a7816d743e0a508abe6193b)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2019 Ian Lepore.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 /*
28  * Driver for Texas Instruments ADS101x and ADS111x family i2c ADC chips.
29  */
30 
31 #include <sys/cdefs.h>
32 #include "opt_platform.h"
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/bus.h>
37 #include <sys/endian.h>
38 #include <sys/kernel.h>
39 #include <sys/lock.h>
40 #include <sys/module.h>
41 #include <sys/sx.h>
42 #include <sys/sysctl.h>
43 
44 #ifdef FDT
45 #include <dev/ofw/ofw_bus.h>
46 #include <dev/ofw/ofw_bus_subr.h>
47 #endif
48 
49 #include <dev/iicbus/iiconf.h>
50 #include <dev/iicbus/iicbus.h>
51 
52 #include "iicbus_if.h"
53 
54 /*
55  * Chip registers, bit definitions, shifting and masking values.
56  */
57 #define	ADS111x_CONV			0	/* Reg 0: Latest sample (ro) */
58 
59 #define	ADS111x_CONF			1	/* Reg 1: Config (rw) */
60 #define	  ADS111x_CONF_OS_SHIFT		15	/* Operational state */
61 #define	  ADS111x_CONF_MUX_SHIFT	12	/* Input mux setting */
62 #define	  ADS111x_CONF_GAIN_SHIFT	 9	/* Programmable gain amp */
63 #define	  ADS111x_CONF_MODE_SHIFT	 8	/* Operational mode */
64 #define	  ADS111x_CONF_RATE_SHIFT	 5	/* Sample rate */
65 #define	  ADS111x_CONF_COMP_DISABLE	 3	/* Comparator disable */
66 
67 #define	ADS111x_LOTHRESH		2	/* Compare lo threshold (rw) */
68 
69 #define	ADS111x_HITHRESH		3	/* Compare hi threshold (rw) */
70 
71 /*
72  * On config write, the operational-state bit starts a measurement, on read it
73  * indicates when the measurement process is complete/idle.
74  */
75 #define	  ADS111x_CONF_MEASURE		(1u << ADS111x_CONF_OS_SHIFT)
76 #define	  ADS111x_CONF_IDLE		(1u << ADS111x_CONF_OS_SHIFT)
77 
78 /*
79  * The default values for config items that are not per-channel.  Mostly, this
80  * turns off the comparator on chips that have that feature, because this driver
81  * doesn't support it directly.  However, the user is allowed to enable the
82  * comparator and we'll leave it alone if they do.  That allows them connect the
83  * alert pin to something and use the feature without any help from this driver.
84  */
85 #define	ADS111x_CONF_DEFAULT    \
86     ((1 << ADS111x_CONF_MODE_SHIFT) | ADS111x_CONF_COMP_DISABLE)
87 #define	ADS111x_CONF_USERMASK   0x001f
88 
89 /*
90  * Per-channel defaults.  The chip only has one control register, and we load
91  * per-channel values into it every time we make a measurement on that channel.
92  * These are the default values for the control register from the datasheet, for
93  * values we maintain on a per-channel basis.
94  */
95 #define	DEFAULT_GAINIDX		2
96 #define	DEFAULT_RATEIDX		4
97 
98 /*
99  * Full-scale ranges for each available amplifier setting, in microvolts.  The
100  * ADS1x13 chips are fixed-range, the other chips contain a programmable gain
101  * amplifier, and the full scale range is based on the amplifier setting.
102  */
103 static const u_int fixedranges[8] = {
104 	2048000, 2048000, 2048000, 2048000, 2048000, 2048000, 2048000, 2048000,
105 };
106 static const u_int gainranges[8] = {
107 	6144000, 4096000, 2048000, 1024000,  512000,  256000,  256000,  256000,
108 };
109 
110 /* The highest value for the ADS101x chip is 0x7ff0, for ADS111x it's 0x7fff. */
111 #define	ADS101x_RANGEDIV	((1 << 15) - 15)
112 #define	ADS111x_RANGEDIV	((1 << 15) - 1)
113 
114 /* Samples per second; varies based on chip type. */
115 static const u_int rates101x[8] = {128, 250, 490, 920, 1600, 2400, 3300, 3300};
116 static const u_int rates111x[8] = {  8,  16,  32,  64,  128,  250,  475,  860};
117 
118 struct ads111x_channel {
119 	u_int gainidx;		/* Amplifier (full-scale range) config index */
120 	u_int rateidx;		/* Samples per second config index */
121 	bool  configured;	/* Channel has been configured */
122 };
123 
124 #define	ADS111x_MAX_CHANNELS	8
125 
126 struct ads111x_chipinfo {
127 	const char	*name;
128 	const u_int	*rangetab;
129 	const u_int	*ratetab;
130 	u_int		numchan;
131 	int		rangediv;
132 };
133 
134 static struct ads111x_chipinfo ads111x_chip_infos[] = {
135 	{ "ADS1013", fixedranges, rates101x, 1, ADS101x_RANGEDIV },
136 	{ "ADS1014", gainranges,  rates101x, 1, ADS101x_RANGEDIV },
137 	{ "ADS1015", gainranges,  rates101x, 8, ADS101x_RANGEDIV },
138 	{ "ADS1113", fixedranges, rates111x, 1, ADS111x_RANGEDIV },
139 	{ "ADS1114", gainranges,  rates111x, 1, ADS111x_RANGEDIV },
140 	{ "ADS1115", gainranges,  rates111x, 8, ADS111x_RANGEDIV },
141 };
142 
143 #ifdef FDT
144 static struct ofw_compat_data compat_data[] = {
145 	{"ti,ads1013",   (uintptr_t)&ads111x_chip_infos[0]},
146 	{"ti,ads1014",   (uintptr_t)&ads111x_chip_infos[1]},
147 	{"ti,ads1015",   (uintptr_t)&ads111x_chip_infos[2]},
148 	{"ti,ads1113",   (uintptr_t)&ads111x_chip_infos[3]},
149 	{"ti,ads1114",   (uintptr_t)&ads111x_chip_infos[4]},
150 	{"ti,ads1115",   (uintptr_t)&ads111x_chip_infos[5]},
151 	{NULL,           (uintptr_t)NULL},
152 };
153 IICBUS_FDT_PNP_INFO(compat_data);
154 #endif
155 
156 struct ads111x_softc {
157 	device_t	dev;
158 	struct sx	lock;
159 	int		addr;
160 	int		cfgword;
161 	const struct ads111x_chipinfo
162 			*chipinfo;
163 	struct ads111x_channel
164 			channels[ADS111x_MAX_CHANNELS];
165 };
166 
167 static int
ads111x_write_2(struct ads111x_softc * sc,int reg,int val)168 ads111x_write_2(struct ads111x_softc *sc, int reg, int val)
169 {
170 	uint8_t data[3];
171 	struct iic_msg msgs[1];
172 	uint8_t slaveaddr;
173 
174 	slaveaddr = iicbus_get_addr(sc->dev);
175 
176 	data[0] = reg;
177 	be16enc(&data[1], val);
178 
179 	msgs[0].slave = slaveaddr;
180 	msgs[0].flags = IIC_M_WR;
181 	msgs[0].len   = sizeof(data);
182 	msgs[0].buf   = data;
183 
184 	return (iicbus_transfer_excl(sc->dev, msgs, nitems(msgs), IIC_WAIT));
185 }
186 
187 static int
ads111x_read_2(struct ads111x_softc * sc,int reg,int * val)188 ads111x_read_2(struct ads111x_softc *sc, int reg, int *val)
189 {
190 	int err;
191 	uint8_t data[2];
192 
193 	err = iic2errno(iicdev_readfrom(sc->dev, reg, data, 2, IIC_WAIT));
194 	if (err == 0)
195 		*val = (int16_t)be16dec(data);
196 
197 	return (err);
198 }
199 
200 static int
ads111x_sample_voltage(struct ads111x_softc * sc,int channum,int * voltage)201 ads111x_sample_voltage(struct ads111x_softc *sc, int channum, int *voltage)
202 {
203 	struct ads111x_channel *chan;
204 	int err, cfgword, convword, rate, retries, waitns;
205 	int64_t fsrange;
206 
207 	chan = &sc->channels[channum];
208 
209 	/* Ask the chip to do a one-shot measurement of the given channel. */
210 	cfgword = sc->cfgword |
211 	    (1 << ADS111x_CONF_OS_SHIFT) |
212 	    (channum << ADS111x_CONF_MUX_SHIFT) |
213 	    (chan->gainidx << ADS111x_CONF_GAIN_SHIFT) |
214 	    (chan->rateidx << ADS111x_CONF_RATE_SHIFT);
215 	if ((err = ads111x_write_2(sc, ADS111x_CONF, cfgword)) != 0)
216 		return (err);
217 
218 	/*
219 	 * Calculate how long it will take to make the measurement at the
220 	 * current sampling rate (round up).  The measurement averaging time
221 	 * ranges from 300us to 125ms, so we yield the cpu while waiting.
222 	 */
223 	rate = sc->chipinfo->ratetab[chan->rateidx];
224 	waitns = (1000000000 + rate - 1) / rate;
225 	err = pause_sbt("ads111x", nstosbt(waitns), 0, C_PREL(2));
226 	if (err != 0 && err != EWOULDBLOCK)
227 		return (err);
228 
229 	/*
230 	 * In theory the measurement should be available now; we waited long
231 	 * enough.  However, the chip times its averaging intervals using an
232 	 * internal 1 MHz oscillator which likely isn't running at the same rate
233 	 * as the system clock, so we have to double-check that the measurement
234 	 * is complete before reading the result.  If it's not ready yet, yield
235 	 * the cpu again for 5% of the time we originally calculated.
236 	 *
237 	 * Unlike most i2c slaves, this device does not auto-increment the
238 	 * register number on reads, so we can't read both status and
239 	 * measurement in one operation.
240 	 */
241 	for (retries = 5; ; --retries) {
242 		if (retries == 0)
243 			return (EWOULDBLOCK);
244 		if ((err = ads111x_read_2(sc, ADS111x_CONF, &cfgword)) != 0)
245 			return (err);
246 		if (cfgword & ADS111x_CONF_IDLE)
247 			break;
248 		pause_sbt("ads111x", nstosbt(waitns / 20), 0, C_PREL(2));
249 	}
250 
251 	/* Retrieve the sample and convert it to microvolts. */
252 	if ((err = ads111x_read_2(sc, ADS111x_CONV, &convword)) != 0)
253 		return (err);
254 	fsrange = sc->chipinfo->rangetab[chan->gainidx];
255 	*voltage = (int)((convword * fsrange ) / sc->chipinfo->rangediv);
256 
257 	return (err);
258 }
259 
260 static int
ads111x_sysctl_gainidx(SYSCTL_HANDLER_ARGS)261 ads111x_sysctl_gainidx(SYSCTL_HANDLER_ARGS)
262 {
263 	struct ads111x_softc *sc;
264 	int chan, err, gainidx;
265 
266 	sc = arg1;
267 	chan = arg2;
268 
269 	gainidx = sc->channels[chan].gainidx;
270 	err = sysctl_handle_int(oidp, &gainidx, 0, req);
271 	if (err != 0 || req->newptr == NULL)
272 		return (err);
273 	if (gainidx < 0 || gainidx > 7)
274 		return (EINVAL);
275 	sx_xlock(&sc->lock);
276 	sc->channels[chan].gainidx = gainidx;
277 	sx_xunlock(&sc->lock);
278 
279 	return (err);
280 }
281 
282 static int
ads111x_sysctl_rateidx(SYSCTL_HANDLER_ARGS)283 ads111x_sysctl_rateidx(SYSCTL_HANDLER_ARGS)
284 {
285 	struct ads111x_softc *sc;
286 	int chan, err, rateidx;
287 
288 	sc = arg1;
289 	chan = arg2;
290 
291 	rateidx = sc->channels[chan].rateidx;
292 	err = sysctl_handle_int(oidp, &rateidx, 0, req);
293 	if (err != 0 || req->newptr == NULL)
294 		return (err);
295 	if (rateidx < 0 || rateidx > 7)
296 		return (EINVAL);
297 	sx_xlock(&sc->lock);
298 	sc->channels[chan].rateidx = rateidx;
299 	sx_xunlock(&sc->lock);
300 
301 	return (err);
302 }
303 
304 static int
ads111x_sysctl_voltage(SYSCTL_HANDLER_ARGS)305 ads111x_sysctl_voltage(SYSCTL_HANDLER_ARGS)
306 {
307 	struct ads111x_softc *sc;
308 	int chan, err, voltage;
309 
310 	sc = arg1;
311 	chan = arg2;
312 
313 	if (req->oldptr != NULL) {
314 		sx_xlock(&sc->lock);
315 		err = ads111x_sample_voltage(sc, chan, &voltage);
316 		sx_xunlock(&sc->lock);
317 		if (err != 0) {
318 			device_printf(sc->dev,
319 			    "conversion read failed, error %d\n", err);
320 			return (err);
321 		}
322 	}
323 	err = sysctl_handle_int(oidp, &voltage, 0, req);
324 	return (err);
325 }
326 
327 static int
ads111x_sysctl_config(SYSCTL_HANDLER_ARGS)328 ads111x_sysctl_config(SYSCTL_HANDLER_ARGS)
329 {
330 	struct ads111x_softc *sc;
331 	int config, err;
332 
333 	sc = arg1;
334 	config = sc->cfgword & ADS111x_CONF_USERMASK;
335 	err = sysctl_handle_int(oidp, &config, 0, req);
336 	if (err != 0 || req->newptr == NULL)
337 		return (err);
338 	sx_xlock(&sc->lock);
339 	sc->cfgword = config & ADS111x_CONF_USERMASK;
340 	err = ads111x_write_2(sc, ADS111x_CONF, sc->cfgword);
341 	sx_xunlock(&sc->lock);
342 
343 	return (err);
344 }
345 static int
ads111x_sysctl_lothresh(SYSCTL_HANDLER_ARGS)346 ads111x_sysctl_lothresh(SYSCTL_HANDLER_ARGS)
347 {
348 	struct ads111x_softc *sc;
349 	int thresh, err;
350 
351 	sc = arg1;
352 	if ((err = ads111x_read_2(sc, ADS111x_LOTHRESH, &thresh)) != 0)
353 		return (err);
354 	err = sysctl_handle_int(oidp, &thresh, 0, req);
355 	if (err != 0 || req->newptr == NULL)
356 		return (err);
357 	sx_xlock(&sc->lock);
358 	err = ads111x_write_2(sc, ADS111x_CONF, thresh);
359 	sx_xunlock(&sc->lock);
360 
361 	return (err);
362 }
363 
364 static int
ads111x_sysctl_hithresh(SYSCTL_HANDLER_ARGS)365 ads111x_sysctl_hithresh(SYSCTL_HANDLER_ARGS)
366 {
367 	struct ads111x_softc *sc;
368 	int thresh, err;
369 
370 	sc = arg1;
371 	if ((err = ads111x_read_2(sc, ADS111x_HITHRESH, &thresh)) != 0)
372 		return (err);
373 	err = sysctl_handle_int(oidp, &thresh, 0, req);
374 	if (err != 0 || req->newptr == NULL)
375 		return (err);
376 	sx_xlock(&sc->lock);
377 	err = ads111x_write_2(sc, ADS111x_CONF, thresh);
378 	sx_xunlock(&sc->lock);
379 
380 	return (err);
381 }
382 
383 static void
ads111x_setup_channel(struct ads111x_softc * sc,int chan,int gainidx,int rateidx)384 ads111x_setup_channel(struct ads111x_softc *sc, int chan, int gainidx, int rateidx)
385 {
386 	struct ads111x_channel *c;
387 	struct sysctl_ctx_list *ctx;
388 	struct sysctl_oid *chantree, *devtree;
389 	char chanstr[4];
390 
391 	c = &sc->channels[chan];
392 	c->gainidx = gainidx;
393 	c->rateidx = rateidx;
394 
395 	/*
396 	 *  If setting up the channel for the first time, create channel's
397 	 *  sysctl entries.  We might have already configured the channel if
398 	 *  config data for it exists in both FDT and hints.
399 	 */
400 
401 	if (c->configured)
402 		return;
403 
404 	ctx = device_get_sysctl_ctx(sc->dev);
405 	devtree = device_get_sysctl_tree(sc->dev);
406 	snprintf(chanstr, sizeof(chanstr), "%d", chan);
407 	chantree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(devtree), OID_AUTO,
408 	    chanstr, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "channel data");
409 	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chantree), OID_AUTO,
410 	    "gain_index", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT,
411 	    sc, chan, ads111x_sysctl_gainidx, "I",
412 	    "programmable gain amp setting, 0-7");
413 	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chantree), OID_AUTO,
414 	    "rate_index", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT,
415 	    sc, chan, ads111x_sysctl_rateidx, "I", "sample rate setting, 0-7");
416 	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chantree), OID_AUTO,
417 	    "voltage",
418 	    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_SKIP | CTLFLAG_NEEDGIANT, sc,
419 	    chan, ads111x_sysctl_voltage, "I", "sampled voltage in microvolts");
420 
421 	c->configured = true;
422 }
423 
424 static void
ads111x_add_channels(struct ads111x_softc * sc)425 ads111x_add_channels(struct ads111x_softc *sc)
426 {
427 	const char *name;
428 	uint32_t chan, gainidx, num_added, rateidx, unit;
429 	bool found;
430 
431 #ifdef FDT
432 	phandle_t child, node;
433 
434 	/* Configure any channels that have FDT data. */
435 	num_added = 0;
436 	node = ofw_bus_get_node(sc->dev);
437 	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
438 		if (OF_getencprop(child, "reg", &chan, sizeof(chan)) == -1)
439 			continue;
440 		if (chan >= ADS111x_MAX_CHANNELS)
441 			continue;
442 		gainidx = DEFAULT_GAINIDX;
443 		rateidx = DEFAULT_RATEIDX;
444 		OF_getencprop(child, "ti,gain", &gainidx, sizeof(gainidx));
445 		OF_getencprop(child, "ti,datarate", &rateidx, sizeof(rateidx));
446 		ads111x_setup_channel(sc, chan, gainidx, rateidx);
447 		++num_added;
448 	}
449 #else
450 	num_added = 0;
451 #endif
452 
453 	/* Configure any channels that have hint data. */
454 	name = device_get_name(sc->dev);
455 	unit = device_get_unit(sc->dev);
456 	for (chan = 0; chan < sc->chipinfo->numchan; ++chan) {
457 		char resname[16];
458 		found = false;
459 		gainidx = DEFAULT_GAINIDX;
460 		rateidx = DEFAULT_RATEIDX;
461 		snprintf(resname, sizeof(resname), "%d.gain_index", chan);
462 		if (resource_int_value(name, unit, resname, &gainidx) == 0)
463 			found = true;
464 		snprintf(resname, sizeof(resname), "%d.rate_index", chan);
465 		if (resource_int_value(name, unit, resname, &rateidx) == 0)
466 			found = true;
467 		if (found) {
468 			ads111x_setup_channel(sc, chan, gainidx, rateidx);
469 			++num_added;
470 		}
471 	}
472 
473 	/* If any channels were configured via FDT or hints, we're done. */
474 	if (num_added > 0)
475 		return;
476 
477 	/*
478 	 * No channel config; add all possible channels using default values,
479 	 * and let the user configure the ones they want on the fly via sysctl.
480 	 */
481 	for (chan = 0; chan < sc->chipinfo->numchan; ++chan) {
482 		gainidx = DEFAULT_GAINIDX;
483 		rateidx = DEFAULT_RATEIDX;
484 		ads111x_setup_channel(sc, chan, gainidx, rateidx);
485 	}
486 }
487 
488 static const struct ads111x_chipinfo *
ads111x_find_chipinfo(device_t dev)489 ads111x_find_chipinfo(device_t dev)
490 {
491 	const struct ads111x_chipinfo *info;
492 	const char *chiptype;
493 	int i;
494 
495 #ifdef FDT
496 	if (ofw_bus_status_okay(dev)) {
497 		info = (struct ads111x_chipinfo*)
498 		    ofw_bus_search_compatible(dev, compat_data)->ocd_data;
499 		if (info != NULL)
500 			return (info);
501 	}
502 #endif
503 
504 	/* For hinted devices, we must be told the chip type. */
505 	chiptype = NULL;
506 	resource_string_value(device_get_name(dev), device_get_unit(dev),
507 	    "type", &chiptype);
508 	if (chiptype != NULL) {
509 		for (i = 0; i < nitems(ads111x_chip_infos); ++i) {
510 			info = &ads111x_chip_infos[i];
511 			if (strcasecmp(chiptype, info->name) == 0)
512 				return (info);
513 		}
514 	}
515 	return (NULL);
516 }
517 
518 static int
ads111x_probe(device_t dev)519 ads111x_probe(device_t dev)
520 {
521 	const struct ads111x_chipinfo *info;
522 
523 	info = ads111x_find_chipinfo(dev);
524 	if (info != NULL) {
525 		device_set_desc(dev, info->name);
526 #ifdef FDT
527 		return (BUS_PROBE_DEFAULT);
528 #else
529 		return (BUS_PROBE_NOWILDCARD);
530 #endif
531 	}
532 
533 	return (ENXIO);
534 }
535 
536 static int
ads111x_attach(device_t dev)537 ads111x_attach(device_t dev)
538 {
539 	struct ads111x_softc *sc;
540 	struct sysctl_ctx_list *ctx;
541 	struct sysctl_oid *tree;
542 	int err;
543 
544 	sc = device_get_softc(dev);
545 	sc->dev = dev;
546 	sc->addr = iicbus_get_addr(dev);
547 	sc->cfgword = ADS111x_CONF_DEFAULT;
548 
549 	sc->chipinfo = ads111x_find_chipinfo(sc->dev);
550 	if (sc->chipinfo == NULL) {
551 		device_printf(dev,
552 		    "cannot get chipinfo (but it worked during probe)");
553 		return (ENXIO);
554 	}
555 
556 	/* Set the default chip config. */
557 	if ((err = ads111x_write_2(sc, ADS111x_CONF, sc->cfgword)) != 0) {
558 		device_printf(dev, "cannot write chip config register\n");
559 		return (err);
560 	}
561 
562 	/* Add the sysctl handler to set the chip configuration register.  */
563 	ctx = device_get_sysctl_ctx(dev);
564 	tree = device_get_sysctl_tree(dev);
565 	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
566 	    "config", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, sc, 0,
567 	    ads111x_sysctl_config, "I", "configuration register word");
568 	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
569 	    "lo_thresh", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, sc, 0,
570 	    ads111x_sysctl_lothresh, "I", "comparator low threshold");
571 	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
572 	    "hi_thresh", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, sc, 0,
573 	    ads111x_sysctl_hithresh, "I", "comparator high threshold");
574 
575 	/* Set up channels based on metadata or default config. */
576 	ads111x_add_channels(sc);
577 
578 	sx_init(&sc->lock, "ads111x");
579 
580 	return (0);
581 }
582 
583 static int
ads111x_detach(device_t dev)584 ads111x_detach(device_t dev)
585 {
586 	struct ads111x_softc *sc;
587 
588 	sc = device_get_softc(dev);
589 
590 	sx_destroy(&sc->lock);
591 	return (0);
592 }
593 
594 static device_method_t ads111x_methods[] = {
595 	DEVMETHOD(device_probe,		ads111x_probe),
596 	DEVMETHOD(device_attach,	ads111x_attach),
597 	DEVMETHOD(device_detach,	ads111x_detach),
598 
599 	DEVMETHOD_END,
600 };
601 
602 static driver_t ads111x_driver = {
603 	"ads111x",
604 	ads111x_methods,
605 	sizeof(struct ads111x_softc),
606 };
607 
608 DRIVER_MODULE(ads111x, iicbus, ads111x_driver, NULL, NULL);
609 MODULE_VERSION(ads111x, 1);
610 MODULE_DEPEND(ads111x, iicbus, 1, 1, 1);
611