root/dev/i2c/ad741x.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. adc_match
  2. adc_attach
  3. adc_refresh

    1 /*      $OpenBSD: ad741x.c,v 1.12 2007/06/24 05:34:35 dlg Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2005 Theo de Raadt
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 #include <sys/param.h>
   20 #include <sys/systm.h>
   21 #include <sys/device.h>
   22 #include <sys/sensors.h>
   23 
   24 #include <dev/i2c/i2cvar.h>
   25 
   26 /* AD741x registers */
   27 #define AD741X_TEMP     0x00
   28 #define AD741X_CONFIG   0x01
   29 #define AD741X_THYST    0x02
   30 #define AD741X_TOTI     0x03
   31 #define AD741X_ADC      0x04
   32 #define AD741X_CONFIG2  0x05
   33 
   34 #define AD741X_CONFMASK 0xe0
   35 
   36 /* Sensors */
   37 #define ADC_TEMP                0
   38 #define ADC_ADC0                1
   39 #define ADC_ADC1                2
   40 #define ADC_ADC2                3
   41 #define ADC_ADC3                4
   42 #define ADC_MAX_SENSORS         5
   43 
   44 struct adc_softc {
   45         struct device   sc_dev;
   46         i2c_tag_t       sc_tag;
   47         i2c_addr_t      sc_addr;
   48         int             sc_chip;
   49         u_int8_t        sc_config;
   50 
   51         struct ksensor sc_sensor[ADC_MAX_SENSORS];
   52         struct ksensordev sc_sensordev;
   53 };
   54 
   55 int     adc_match(struct device *, void *, void *);
   56 void    adc_attach(struct device *, struct device *, void *);
   57 int     adc_check(struct i2c_attach_args *, u_int8_t *, u_int8_t *);
   58 void    adc_refresh(void *);
   59 
   60 struct cfattach adc_ca = {
   61         sizeof(struct adc_softc), adc_match, adc_attach
   62 };
   63 
   64 struct cfdriver adc_cd = {
   65         NULL, "adc", DV_DULL
   66 };
   67 
   68 int
   69 adc_match(struct device *parent, void *match, void *aux)
   70 {
   71         struct i2c_attach_args *ia = aux;
   72 
   73         if (strcmp(ia->ia_name, "ad7417") == 0 ||
   74             strcmp(ia->ia_name, "ad7418") == 0)
   75                 return (1);
   76         return (0);
   77 }
   78 
   79 void
   80 adc_attach(struct device *parent, struct device *self, void *aux)
   81 {
   82         struct adc_softc *sc = (struct adc_softc *)self;
   83         struct i2c_attach_args *ia = aux;
   84         u_int8_t cmd, data;
   85         int nsens = 0, i;
   86 
   87         sc->sc_tag = ia->ia_tag;
   88         sc->sc_addr = ia->ia_addr;
   89 
   90         printf(": %s", ia->ia_name);
   91 
   92         sc->sc_chip = 0;
   93         if (strcmp(ia->ia_name, "ad7417") == 0)
   94                 sc->sc_chip = 7417;
   95         if (strcmp(ia->ia_name, "ad7418") == 0)
   96                 sc->sc_chip = 7418;
   97 
   98         if (sc->sc_chip != 0) {
   99                 cmd = AD741X_CONFIG2;
  100                 data = 0;
  101                 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  102                     sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
  103                         printf(", config2 reset failed\n");
  104                         return;
  105                 }
  106         }
  107 
  108         cmd = AD741X_CONFIG;
  109         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  110             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
  111                 printf(", config reset failed\n");
  112                 return;
  113         }
  114         data &= 0xfe;
  115         if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  116             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
  117                 printf(", config reset failed\n");
  118                 return;
  119         }
  120         sc->sc_config = data;
  121 
  122         /* Initialize sensor data. */
  123         strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
  124             sizeof(sc->sc_sensordev.xname));
  125 
  126         sc->sc_sensor[ADC_TEMP].type = SENSOR_TEMP;
  127         strlcpy(sc->sc_sensor[ADC_TEMP].desc, "Internal",
  128             sizeof(sc->sc_sensor[ADC_TEMP].desc));
  129         nsens = 1;
  130 
  131         if (sc->sc_chip == 7417 || sc->sc_chip == 7418) {
  132                 sc->sc_sensor[ADC_ADC0].type = SENSOR_INTEGER;
  133                 nsens++;
  134         }
  135         if (sc->sc_chip == 7417 || sc->sc_chip == 7418) {
  136                 sc->sc_sensor[ADC_ADC1].type = SENSOR_INTEGER;
  137                 sc->sc_sensor[ADC_ADC2].type = SENSOR_INTEGER;
  138                 sc->sc_sensor[ADC_ADC3].type = SENSOR_INTEGER;
  139                 nsens += 3;
  140         }
  141 
  142         if (sensor_task_register(sc, adc_refresh, 5) == NULL) {
  143                 printf(", unable to register update task\n");
  144                 return;
  145         }
  146 
  147         sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[0]);
  148         if (sc->sc_chip == 7417 || sc->sc_chip == 7418)
  149                 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[1]);
  150         if (sc->sc_chip == 7417)
  151                 for (i = 2; i < nsens; i++)
  152                         sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
  153         sensordev_install(&sc->sc_sensordev);
  154 
  155         printf("\n");
  156 }
  157 
  158 void
  159 adc_refresh(void *arg)
  160 {
  161         struct adc_softc *sc = arg;
  162         u_int8_t cmd, data[2], reg;
  163         int i;
  164 
  165         iic_acquire_bus(sc->sc_tag, 0);
  166 
  167         reg = (sc->sc_config & AD741X_CONFMASK) | (0 << 5);
  168         if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  169             sc->sc_addr, &cmd, sizeof cmd, &reg, sizeof reg, 0))
  170                 goto done;
  171         delay(1000);
  172         cmd = AD741X_TEMP;
  173         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  174             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
  175                 goto done;
  176         sc->sc_sensor[ADC_TEMP].value = 273150000 +
  177             ((data[0] << 8 | data[1]) >> 6) * 250000;
  178 
  179         if (sc->sc_chip == 0)
  180                 goto done;
  181 
  182         if (sc->sc_chip == 7418) {
  183                 reg = (reg & AD741X_CONFMASK) | (4 << 5);
  184                 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  185                     sc->sc_addr, &cmd, sizeof cmd, &reg, sizeof reg, 0))
  186                         goto done;
  187                 delay(1000);
  188                 cmd = AD741X_ADC;
  189                 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  190                     sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
  191                         goto done;
  192                 sc->sc_sensor[ADC_ADC0].value =
  193                     (data[0] << 8 | data[1]) >> 6;
  194                 goto done;
  195         }
  196 
  197         for (i = 0; i < 4; i++) {
  198                 reg = (reg & AD741X_CONFMASK) | (i << 5);
  199                 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  200                     sc->sc_addr, &cmd, sizeof cmd, &reg, sizeof reg, 0))
  201                         goto done;
  202                 delay(1000);
  203                 cmd = AD741X_ADC;
  204                 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  205                     sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
  206                         goto done;
  207                 sc->sc_sensor[ADC_ADC0 + i].value =
  208                     (data[0] << 8 | data[1]) >> 6;
  209         }
  210 
  211 done:
  212         iic_release_bus(sc->sc_tag, 0);
  213 }

/* [<][>][^][v][top][bottom][index][help] */