Module Name: src
Committed By: phx
Date: Tue Aug 18 15:54:20 UTC 2015
Modified Files:
src/distrib/sets/lists/man: mi
src/doc: CHANGES
src/share/man/man4: Makefile
src/sys/arch/evbarm/conf: RPI
src/sys/dev/spi: files.spi
Added Files:
src/share/man/man4: mcp3kadc.4
src/sys/dev/spi: mcp3k.c
Log Message:
MI driver for the Microchip 3x0x series of SAR analog to digital converters.
To generate a diff of this commit:
cvs rdiff -u -r1.1504 -r1.1505 src/distrib/sets/lists/man/mi
cvs rdiff -u -r1.2094 -r1.2095 src/doc/CHANGES
cvs rdiff -u -r1.620 -r1.621 src/share/man/man4/Makefile
cvs rdiff -u -r0 -r1.1 src/share/man/man4/mcp3kadc.4
cvs rdiff -u -r1.63 -r1.64 src/sys/arch/evbarm/conf/RPI
cvs rdiff -u -r1.4 -r1.5 src/sys/dev/spi/files.spi
cvs rdiff -u -r0 -r1.1 src/sys/dev/spi/mcp3k.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/distrib/sets/lists/man/mi
diff -u src/distrib/sets/lists/man/mi:1.1504 src/distrib/sets/lists/man/mi:1.1505
--- src/distrib/sets/lists/man/mi:1.1504 Mon Aug 17 06:50:03 2015
+++ src/distrib/sets/lists/man/mi Tue Aug 18 15:54:20 2015
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1504 2015/08/17 06:50:03 knakahara Exp $
+# $NetBSD: mi,v 1.1505 2015/08/18 15:54:20 phx Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -1391,6 +1391,7 @@
./usr/share/man/cat4/mcclock.0 man-sys-catman .cat
./usr/share/man/cat4/mcd.0 man-sys-catman .cat
./usr/share/man/cat4/mcp23s17gpio.0 man-sys-catman .cat
+./usr/share/man/cat4/mcp3kadc.0 man-sys-catman .cat
./usr/share/man/cat4/mcp980x.0 man-sys-catman .cat
./usr/share/man/cat4/md.0 man-sys-catman .cat
./usr/share/man/cat4/mfb.0 man-sys-catman .cat
@@ -4415,6 +4416,7 @@
./usr/share/man/html4/mcclock.html man-sys-htmlman html
./usr/share/man/html4/mcd.html man-sys-htmlman html
./usr/share/man/html4/mcp23s17gpio.html man-sys-htmlman html
+./usr/share/man/html4/mcp3kadc.html man-sys-htmlman html
./usr/share/man/html4/mcp980x.html man-sys-htmlman html
./usr/share/man/html4/md.html man-sys-htmlman html
./usr/share/man/html4/mfb.html man-sys-htmlman html
@@ -7289,6 +7291,7 @@
./usr/share/man/man4/mcclock.4 man-sys-man .man
./usr/share/man/man4/mcd.4 man-sys-man .man
./usr/share/man/man4/mcp23s17gpio.4 man-sys-man .man
+./usr/share/man/man4/mcp3kadc.4 man-sys-man .man
./usr/share/man/man4/mcp980x.4 man-sys-man .man
./usr/share/man/man4/md.4 man-sys-man .man
./usr/share/man/man4/mfb.4 man-sys-man .man
Index: src/doc/CHANGES
diff -u src/doc/CHANGES:1.2094 src/doc/CHANGES:1.2095
--- src/doc/CHANGES:1.2094 Tue Aug 18 10:48:01 2015
+++ src/doc/CHANGES Tue Aug 18 15:54:20 2015
@@ -1,4 +1,4 @@
-# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.2094 $>
+# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.2095 $>
#
#
# [Note: This file does not mention every change made to the NetBSD source tree.
@@ -187,3 +187,4 @@ Changes from NetBSD 7.0 to NetBSD 8.0:
libc: Update to tzcode2015f. [christos 20150813]
gdb(1): Updated to 7.9.1. [christos 20150818]
acpi(4): Updated ACPICA to 20150717. [christos 20150818]
+ mcp3kadc(4): Driver for Microchip 3x0x SAR ADC chips. [phx 20150818]
Index: src/share/man/man4/Makefile
diff -u src/share/man/man4/Makefile:1.620 src/share/man/man4/Makefile:1.621
--- src/share/man/man4/Makefile:1.620 Wed May 13 07:28:49 2015
+++ src/share/man/man4/Makefile Tue Aug 18 15:54:20 2015
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.620 2015/05/13 07:28:49 mlelstv Exp $
+# $NetBSD: Makefile,v 1.621 2015/08/18 15:54:20 phx Exp $
# @(#)Makefile 8.1 (Berkeley) 6/18/93
MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \
@@ -127,7 +127,7 @@ MAN+= dbcool.4 g760a.4 lmenv.4 lmtemp.4
smscmon.4 spdmem.4 tps65217pmic.4
# machine-independent SPI devices
-MAN += m25p.4 mcp23s17gpio.4 tm121temp.4
+MAN += m25p.4 mcp23s17gpio.4 mcp3kadc.4 tm121temp.4
# machine-independent SD/MMC devices
MAN += sbt.4 sdhc.4 sdmmc.4
Index: src/sys/arch/evbarm/conf/RPI
diff -u src/sys/arch/evbarm/conf/RPI:1.63 src/sys/arch/evbarm/conf/RPI:1.64
--- src/sys/arch/evbarm/conf/RPI:1.63 Sat Apr 18 13:43:45 2015
+++ src/sys/arch/evbarm/conf/RPI Tue Aug 18 15:54:20 2015
@@ -1,5 +1,5 @@
#
-# $NetBSD: RPI,v 1.63 2015/04/18 13:43:45 skrll Exp $
+# $NetBSD: RPI,v 1.64 2015/08/18 15:54:20 phx Exp $
#
# RPi -- Raspberry Pi
#
@@ -144,6 +144,10 @@ iic* at i2cbus?
bcmspi* at obio?
spi* at spibus?
+# MCP3x0x ADC
+# flags selects the actual chip, refer to mcp3kadc(4)
+#mcp3kadc0 at spi? slave 0 flags 0
+
# PIFace or other boards using that chip (needs gpio)
#mcp23s17gpio0 at spi? slave 0 flags 0
#mcp23s17gpio1 at spi? slave 0 flags 1
Index: src/sys/dev/spi/files.spi
diff -u src/sys/dev/spi/files.spi:1.4 src/sys/dev/spi/files.spi:1.5
--- src/sys/dev/spi/files.spi:1.4 Sun Apr 6 17:59:39 2014
+++ src/sys/dev/spi/files.spi Tue Aug 18 15:54:20 2015
@@ -1,4 +1,4 @@
-# $NetBSD: files.spi,v 1.4 2014/04/06 17:59:39 kardel Exp $
+# $NetBSD: files.spi,v 1.5 2015/08/18 15:54:20 phx Exp $
define spibus { }
@@ -35,3 +35,8 @@ file dev/spi/mcp48x1.c mcp48x1dac
device mcp23s17gpio: gpiobus
attach mcp23s17gpio at spi
file dev/spi/mcp23s17.c mcp23s17gpio
+
+# MCP3x0x ADC
+device mcp3kadc: sysmon_envsys
+attach mcp3kadc at spi
+file dev/spi/mcp3k.c mcp3kadc
Added files:
Index: src/share/man/man4/mcp3kadc.4
diff -u /dev/null src/share/man/man4/mcp3kadc.4:1.1
--- /dev/null Tue Aug 18 15:54:20 2015
+++ src/share/man/man4/mcp3kadc.4 Tue Aug 18 15:54:20 2015
@@ -0,0 +1,94 @@
+.\" $NetBSD: mcp3kadc.4,v 1.1 2015/08/18 15:54:20 phx Exp $
+.\"
+.\" Copyright (c) 2015 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Frank Wille.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd August 18, 2015
+.Dt MCP3KADC 4
+.Os
+.Sh NAME
+.Nm mcp3kadc
+.Nd Microchip 3x0x SAR analog to digital converter
+.Sh SYNOPSIS
+.Cd "mcp3kadc* at spi? slave ? flags N"
+.Sh DESCRIPTION
+The
+.Nm
+driver reports the current voltage on the chip's ADC channels through the
+.Xr envsys 4
+API. The driver calculates these values according to the currently selected
+reference voltage (
+.Li Vref
+). It can be changed
+through the
+.Xr sysctl 8
+node
+.Li hw.mcp3kadc0.vref .
+.Pp
+The following table shows the supported chips. The type of the chip can
+be selected with the
+.Ar flags
+argument in the config file.
+.Bl -column "Designation" "Resolution" "Input Channels" "flags" -offset indent
+.It Sy "Designation" Ta Sy "Resolution" Ta Sy "Input Channels" Ta Sy "flags"
+.It Li "MCP3001" Ta "10 bits" Ta "1" Ta "0"
+.It Li "MCP3002" Ta "10 bits" Ta "2" Ta "1"
+.It Li "MCP3004" Ta "10 bits" Ta "4" Ta "2"
+.It Li "MCP3008" Ta "10 bits" Ta "8" Ta "3"
+.It Li "MCP3201" Ta "12 bits" Ta "1" Ta "4"
+.It Li "MCP3202" Ta "12 bits" Ta "2" Ta "5"
+.It Li "MCP3204" Ta "12 bits" Ta "4" Ta "6"
+.It Li "MCP3208" Ta "12 bits" Ta "8" Ta "7"
+.It Li "MCP3301" Ta "13 bits" Ta "1" Ta "8"
+.It Li "MCP3302" Ta "13 bits" Ta "4" Ta "9"
+.It Li "MCP3304" Ta "13 bits" Ta "8" Ta "10"
+.El
+.Sh SYSCTL VARIABLES
+The following
+.Xr sysctl 3
+variables are provided:
+.Bl -tag -width indent
+.It hw.mcp3kadc0.vref
+Defines the reference voltage on the chip's
+.Li Vref
+pin in millivolts (mV). It defaults to the ADC's maximum output value + 1
+in millivolts (e.g., 4096 for a 12-bit ADC).
+.El
+.Sh SEE ALSO
+.Xr spi 4 ,
+.Xr envsys 4 ,
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Nx 8.0 .
+.Sh AUTHORS
+The
+.Nm
+driver was written by
+.An Frank Wille .
Index: src/sys/dev/spi/mcp3k.c
diff -u /dev/null src/sys/dev/spi/mcp3k.c:1.1
--- /dev/null Tue Aug 18 15:54:20 2015
+++ src/sys/dev/spi/mcp3k.c Tue Aug 18 15:54:20 2015
@@ -0,0 +1,368 @@
+/* $NetBSD: mcp3k.c,v 1.1 2015/08/18 15:54:20 phx Exp $ */
+
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Frank Wille.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Microchip MCP3x0x SAR analog to digital converters.
+ * The driver supports various ADCs with different resolutions, operation
+ * modes and number of input channels.
+ * The reference voltage Vref defaults to the maximum output value in mV,
+ * but can be changed via sysctl(3).
+ *
+ * MCP3001: http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf
+ * MCP3002: http://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf
+ * MCP3004/3008: http://ww1.microchip.com/downloads/en/DeviceDoc/21295C.pdf
+ * MCP3201: http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf
+ * MCP3204/3208: http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf
+ * MCP3301: http://ww1.microchip.com/downloads/en/DeviceDoc/21700E.pdf
+ * MPC3302/3304: http://ww1.microchip.com/downloads/en/DeviceDoc/21697F.pdf
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include <dev/sysmon/sysmonvar.h>
+#include <dev/spi/spivar.h>
+
+#define M3K_MAX_SENSORS 16 /* 8 single-ended & 8 diff. */
+
+/* mcp3x0x model description */
+struct mcp3kadc_model {
+ uint32_t name;
+ uint8_t bits;
+ uint8_t channels;
+ uint8_t lead; /* leading bits to ignore */
+ uint8_t flags;
+#define M3K_SGLDIFF 0x01 /* single-ended/differential */
+#define M3K_D2D1D0 0x02 /* 3 channel select bits */
+#define M3K_MSBF 0x04 /* MSBF select bit */
+#define M3K_SIGNED 0x80 /* result is signed */
+#define M3K_CTRL_NEEDED (M3K_SGLDIFF | M3K_D2D1D0 | M3K_MSBF)
+};
+
+struct mcp3kadc_softc {
+ device_t sc_dev;
+ struct spi_handle *sc_sh;
+ int sc_model;
+ uint32_t sc_adc_max;
+ int32_t sc_vref_mv;
+
+ struct sysmon_envsys *sc_sme;
+ envsys_data_t sc_sensors[M3K_MAX_SENSORS];
+};
+
+static int mcp3kadc_match(device_t, cfdata_t, void *);
+static void mcp3kadc_attach(device_t, device_t, void *);
+static void mcp3kadc_envsys_refresh(struct sysmon_envsys *,
+ envsys_data_t *);
+static int sysctl_mcp3kadc_vref(SYSCTLFN_ARGS);
+
+CFATTACH_DECL_NEW(mcp3kadc, sizeof(struct mcp3kadc_softc),
+ mcp3kadc_match, mcp3kadc_attach, NULL, NULL);
+
+static struct mcp3kadc_model mcp3k_models[] = {
+ {
+ .name = 3001,
+ .bits = 10,
+ .channels = 1,
+ .lead = 3,
+ .flags = 0
+ },
+ {
+ .name = 3002,
+ .bits = 10,
+ .channels = 2,
+ .lead = 2,
+ .flags = M3K_SGLDIFF | M3K_MSBF
+ },
+ {
+ .name = 3004,
+ .bits = 10,
+ .channels = 4,
+ .lead = 2,
+ .flags = M3K_SGLDIFF | M3K_D2D1D0
+ },
+ {
+ .name = 3008,
+ .bits = 10,
+ .channels = 8,
+ .lead = 2,
+ .flags = M3K_SGLDIFF | M3K_D2D1D0
+ },
+ {
+ .name = 3201,
+ .bits = 12,
+ .channels = 1,
+ .lead = 3,
+ .flags = 0
+ },
+ {
+ .name = 3202,
+ .bits = 12,
+ .channels = 2,
+ .lead = 2,
+ .flags = M3K_SGLDIFF | M3K_MSBF
+ },
+ {
+ .name = 3204,
+ .bits = 12,
+ .channels = 4,
+ .lead = 2,
+ .flags = M3K_SGLDIFF | M3K_D2D1D0
+ },
+ {
+ .name = 3208,
+ .bits = 12,
+ .channels = 8,
+ .lead = 2,
+ .flags = M3K_SGLDIFF | M3K_D2D1D0
+ },
+ {
+ .name = 3301,
+ .bits = 13,
+ .channels = 1,
+ .lead = 3,
+ .flags = M3K_SIGNED
+ },
+ {
+ .name = 3302,
+ .bits = 13,
+ .channels = 4,
+ .lead = 2,
+ .flags = M3K_SIGNED | M3K_SGLDIFF | M3K_D2D1D0
+ },
+ {
+ .name = 3204,
+ .bits = 13,
+ .channels = 8,
+ .lead = 2,
+ .flags = M3K_SIGNED | M3K_SGLDIFF | M3K_D2D1D0
+ },
+};
+
+static int
+mcp3kadc_match(device_t parent, cfdata_t cf, void *aux)
+{
+ struct spi_attach_args *sa = aux;
+
+ if (strcmp(cf->cf_name, "mcp3kadc") != 0)
+ return 0;
+
+ /* configure for 1MHz */
+ if (spi_configure(sa->sa_handle, SPI_MODE_0, 1000000))
+ return 0;
+
+ return 1;
+}
+
+static void
+mcp3kadc_attach(device_t parent, device_t self, void *aux)
+{
+ const struct sysctlnode *rnode, *node;
+ struct spi_attach_args *sa;
+ struct mcp3kadc_softc *sc;
+ struct mcp3kadc_model *model;
+ int ch, i;
+
+ sa = aux;
+ sc = device_private(self);
+ sc->sc_dev = self;
+ sc->sc_sh = sa->sa_handle;
+
+ /* device flags define the model */
+ sc->sc_model = device_cfdata(sc->sc_dev)->cf_flags;
+ model = &mcp3k_models[sc->sc_model];
+
+ aprint_naive(": Analog to Digital converter\n");
+ aprint_normal(": MCP%u %u-channel %u-bit ADC\n",
+ (unsigned)model->name, (unsigned)model->channels,
+ (unsigned)model->bits);
+
+ /* set a default Vref in mV according to the chip's ADC resolution */
+ sc->sc_vref_mv = 1 << ((model->flags & M3K_SIGNED) ?
+ model->bits - 1 : model->bits);
+
+ /* remember maximum value for this ADC - also used for masking */
+ sc->sc_adc_max = (1 << model->bits) - 1;
+
+ /* attach voltage sensors to envsys */
+ sc->sc_sme = sysmon_envsys_create();
+
+ /* adc difference from two neighbouring channels */
+ for (ch = 0; ch < model->channels; ch++) {
+ KASSERT(ch < M3K_MAX_SENSORS);
+ sc->sc_sensors[ch].units = ENVSYS_SVOLTS_DC;
+ sc->sc_sensors[ch].state = ENVSYS_SINVALID;
+ if (model->channels == 1)
+ strlcpy(sc->sc_sensors[ch].desc, "adc diff ch0",
+ sizeof(sc->sc_sensors[ch].desc));
+ else
+ snprintf(sc->sc_sensors[ch].desc,
+ sizeof(sc->sc_sensors[ch].desc),
+ "adc diff ch%d-ch%d", ch, ch ^ 1);
+ sc->sc_sensors[ch].private = ch;
+ sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensors[ch]);
+ }
+
+ if (model->flags & M3K_SGLDIFF) {
+ /* adc from single ended channels */
+ for (i = 0; i < model->channels; i++, ch++) {
+ KASSERT(ch < M3K_MAX_SENSORS);
+ sc->sc_sensors[ch].units = ENVSYS_SVOLTS_DC;
+ sc->sc_sensors[ch].state = ENVSYS_SINVALID;
+ snprintf(sc->sc_sensors[ch].desc,
+ sizeof(sc->sc_sensors[ch].desc),
+ "adc single ch%d", i);
+ sc->sc_sensors[ch].private = ch;
+ sysmon_envsys_sensor_attach(sc->sc_sme,
+ &sc->sc_sensors[ch]);
+ }
+ }
+
+ sc->sc_sme->sme_name = device_xname(self);
+ sc->sc_sme->sme_refresh = mcp3kadc_envsys_refresh;
+ sc->sc_sme->sme_cookie = sc;
+ if (sysmon_envsys_register(sc->sc_sme)) {
+ aprint_error_dev(self, "unable to register with sysmon\n");
+ sysmon_envsys_destroy(sc->sc_sme);
+ }
+
+ /* create a sysctl node for adjusting the ADC's reference voltage */
+ rnode = node = NULL;
+ sysctl_createv(NULL, 0, NULL, &rnode,
+ CTLFLAG_READWRITE,
+ CTLTYPE_NODE, device_xname(sc->sc_dev), NULL,
+ NULL, 0, NULL, 0,
+ CTL_HW, CTL_CREATE, CTL_EOL);
+
+ if (rnode != NULL)
+ sysctl_createv(NULL, 0, NULL, &node,
+ CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
+ CTLTYPE_INT, "vref",
+ SYSCTL_DESCR("ADC reference voltage"),
+ sysctl_mcp3kadc_vref, 0, (void *)sc, 0,
+ CTL_HW, rnode->sysctl_num, CTL_CREATE, CTL_EOL);
+}
+
+static void
+mcp3kadc_envsys_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
+{
+ struct mcp3kadc_softc *sc;
+ struct mcp3kadc_model *model;
+ uint8_t buf[2], ctrl;
+ int32_t val, scale;
+
+ sc = sme->sme_cookie;
+ model = &mcp3k_models[sc->sc_model];
+ scale = sc->sc_adc_max + 1;
+
+ if (model->flags & M3K_CTRL_NEEDED) {
+ /* we need to send some control bits first */
+ ctrl = 1; /* start bit */
+
+ if (model->flags & M3K_SGLDIFF) {
+ /* bit set to select single-ended mode */
+ ctrl <<= 1;
+ ctrl |= edata->private >= model->channels;
+ }
+
+ if (model->flags & M3K_D2D1D0) {
+ /* 3 bits select the channel */
+ ctrl <<= 3;
+ ctrl |= edata->private & (model->channels - 1);
+ } else {
+ /* 1 bit selects between two channels */
+ ctrl <<= 1;
+ ctrl |= edata->private & 1;
+ }
+
+ if (model->flags & M3K_MSBF) {
+ /* bit select MSB first format */
+ ctrl <<= 1;
+ ctrl |= 1;
+ }
+
+ /* send control bits, receive ADC data */
+ if (spi_send_recv(sc->sc_sh, 1, &ctrl, 2, buf) != 0) {
+ edata->state = ENVSYS_SINVALID;
+ return;
+ }
+ } else {
+
+ /* just read data from the ADC */
+ if (spi_recv(sc->sc_sh, 2, buf) != 0) {
+ edata->state = ENVSYS_SINVALID;
+ return;
+ }
+ }
+
+ /* extract big-endian ADC data from buffer */
+ val = (buf[0] << 8) | buf[1];
+ val = (val >> (16 - (model->bits + model->lead))) & sc->sc_adc_max;
+
+ /* sign-extend the result, when needed */
+ if (model->flags & M3K_SIGNED) {
+ if (val & (1 << (model->bits - 1)))
+ val -= sc->sc_adc_max + 1;
+ scale >>= 1; /* MSB is the sign */
+ }
+
+ /* scale the value for Vref and convert to mV */
+ edata->value_cur = (sc->sc_vref_mv * val / scale) * 1000;
+ edata->state = ENVSYS_SVALID;
+}
+
+static int
+sysctl_mcp3kadc_vref(SYSCTLFN_ARGS)
+{
+ struct sysctlnode node;
+ struct mcp3kadc_softc *sc;
+ int32_t t;
+ int error;
+
+ node = *rnode;
+ sc = node.sysctl_data;
+
+ t = sc->sc_vref_mv;
+ node.sysctl_data = &t;
+
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL)
+ return error;
+ if (t <= 0)
+ return EINVAL;
+
+ sc->sc_vref_mv = t;
+ return 0;
+}