]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/iicbus/ads111x.c
MFC r351885, r351887
[FreeBSD/FreeBSD.git] / sys / dev / iicbus / ads111x.c
1 /*-
2  * Copyright (c) 2019 Ian Lepore.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 /*
26  * Driver for Texas Instruments ADS101x and ADS111x family i2c ADC chips.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
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
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
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
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
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
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
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
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
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
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
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, NULL, "channel data");
409         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chantree), OID_AUTO,
410             "gain_index", CTLTYPE_INT | CTLFLAG_RWTUN, sc, chan,
411             ads111x_sysctl_gainidx, "I", "programmable gain amp setting, 0-7");
412         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chantree), OID_AUTO,
413             "rate_index", CTLTYPE_INT | CTLFLAG_RWTUN, sc, chan,
414             ads111x_sysctl_rateidx, "I", "sample rate setting, 0-7");
415         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chantree), OID_AUTO,
416             "voltage", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_SKIP, sc, chan,
417             ads111x_sysctl_voltage, "I", "sampled voltage in microvolts");
418
419         c->configured = true;
420 }
421
422 static void
423 ads111x_add_channels(struct ads111x_softc *sc)
424 {
425         const char *name;
426         uint32_t chan, gainidx, num_added, rateidx, unit;
427         bool found;
428
429 #ifdef FDT
430         phandle_t child, node;
431
432         /* Configure any channels that have FDT data. */
433         num_added = 0;
434         node = ofw_bus_get_node(sc->dev);
435         for (child = OF_child(node); child != 0; child = OF_peer(child)) {
436                 if (OF_getencprop(child, "reg", &chan, sizeof(chan)) == -1)
437                         continue;
438                 if (chan >= ADS111x_MAX_CHANNELS)
439                         continue;
440                 gainidx = DEFAULT_GAINIDX;
441                 rateidx = DEFAULT_RATEIDX;
442                 OF_getencprop(child, "ti,gain", &gainidx, sizeof(gainidx));
443                 OF_getencprop(child, "ti,datarate", &rateidx, sizeof(rateidx));
444                 ads111x_setup_channel(sc, chan, gainidx, rateidx);
445                 ++num_added;
446         }
447 #else
448         num_added = 0;
449 #endif
450
451         /* Configure any channels that have hint data. */
452         name = device_get_name(sc->dev);
453         unit = device_get_unit(sc->dev);
454         for (chan = 0; chan < sc->chipinfo->numchan; ++chan) {
455                 found = false;
456                 gainidx = DEFAULT_GAINIDX;
457                 rateidx = DEFAULT_RATEIDX;
458                 if (resource_int_value(name, unit, "gain_index", &gainidx) == 0)
459                         found = true;
460                 if (resource_int_value(name, unit, "rate_index", &gainidx) == 0)
461                         found = true;
462                 if (found) {
463                         ads111x_setup_channel(sc, chan, gainidx, rateidx);
464                         ++num_added;
465                 }
466         }
467
468         /* If any channels were configured via FDT or hints, we're done. */
469         if (num_added > 0)
470                 return;
471
472         /*
473          * No channel config; add all possible channels using default values,
474          * and let the user configure the ones they want on the fly via sysctl.
475          */
476         for (chan = 0; chan < sc->chipinfo->numchan; ++chan) {
477                 gainidx = DEFAULT_GAINIDX;
478                 rateidx = DEFAULT_RATEIDX;
479                 ads111x_setup_channel(sc, chan, gainidx, rateidx);
480         }
481 }
482
483 static const struct ads111x_chipinfo *
484 ads111x_find_chipinfo(device_t dev)
485 {
486         const struct ads111x_chipinfo *info;
487         const char *chiptype;
488         int i;
489
490 #ifdef FDT
491         if (ofw_bus_status_okay(dev)) {
492                 info = (struct ads111x_chipinfo*)
493                     ofw_bus_search_compatible(dev, compat_data)->ocd_data;
494                 if (info != NULL)
495                         return (info);
496         }
497 #endif
498
499         /* For hinted devices, we must be told the chip type. */
500         chiptype = NULL;
501         resource_string_value(device_get_name(dev), device_get_unit(dev),
502             "type", &chiptype);
503         if (chiptype != NULL) {
504                 for (i = 0; i < nitems(ads111x_chip_infos); ++i) {
505                         info = &ads111x_chip_infos[i];
506                         if (strcasecmp(chiptype, info->name) == 0)
507                                 return (info);
508                 }
509         }
510         return (NULL);
511 }
512
513 static int
514 ads111x_probe(device_t dev)
515 {
516         const struct ads111x_chipinfo *info;
517
518         info = ads111x_find_chipinfo(dev);
519         if (info != NULL) {
520                 device_set_desc(dev, info->name);
521                 return (BUS_PROBE_DEFAULT);
522         }
523
524         return (ENXIO);
525 }
526
527 static int
528 ads111x_attach(device_t dev)
529 {
530         struct ads111x_softc *sc;
531         struct sysctl_ctx_list *ctx;
532         struct sysctl_oid *tree;
533         int err;
534
535         sc = device_get_softc(dev);
536         sc->dev = dev;
537         sc->addr = iicbus_get_addr(dev);
538         sc->cfgword = ADS111x_CONF_DEFAULT;
539
540         sc->chipinfo = ads111x_find_chipinfo(sc->dev);
541         if (sc->chipinfo == NULL) {
542                 device_printf(dev,
543                     "cannot get chipinfo (but it worked during probe)");
544                 return (ENXIO);
545         }
546
547         /* Set the default chip config. */
548         if ((err = ads111x_write_2(sc, ADS111x_CONF, sc->cfgword)) != 0) {
549                 device_printf(dev, "cannot write chip config register\n");
550                 return (err);
551         }
552
553         /* Add the sysctl handler to set the chip configuration register.  */
554         ctx = device_get_sysctl_ctx(dev);
555         tree = device_get_sysctl_tree(dev);
556         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
557             "config", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0,
558             ads111x_sysctl_config, "I", "configuration register word");
559         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
560             "lo_thresh", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0,
561             ads111x_sysctl_lothresh, "I", "comparator low threshold");
562         SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
563             "hi_thresh", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0,
564             ads111x_sysctl_hithresh, "I", "comparator high threshold");
565
566         /* Set up channels based on metadata or default config. */
567         ads111x_add_channels(sc);
568
569         sx_init(&sc->lock, "ads111x");
570
571         return (0);
572 }
573
574 static int
575 ads111x_detach(device_t dev)
576 {
577         struct ads111x_softc *sc;
578
579         sc = device_get_softc(dev);
580
581         sx_destroy(&sc->lock);
582         return (0);
583 }
584
585 static device_method_t ads111x_methods[] = {
586         DEVMETHOD(device_probe,         ads111x_probe),
587         DEVMETHOD(device_attach,        ads111x_attach),
588         DEVMETHOD(device_detach,        ads111x_detach),
589
590         DEVMETHOD_END,
591 };
592
593 static driver_t ads111x_driver = {
594         "ads111x",
595         ads111x_methods,
596         sizeof(struct ads111x_softc),
597 };
598 static devclass_t ads111x_devclass;
599
600 DRIVER_MODULE(ads111x, iicbus, ads111x_driver, ads111x_devclass, NULL, NULL);
601 MODULE_VERSION(ads111x, 1);
602 MODULE_DEPEND(ads111x, iicbus, 1, 1, 1);