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