The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/iicbus/ad7417.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2010 Andreas Tobler
    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,
   20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include <sys/param.h>
   32 #include <sys/bus.h>
   33 #include <sys/systm.h>
   34 #include <sys/module.h>
   35 #include <sys/callout.h>
   36 #include <sys/conf.h>
   37 #include <sys/cpu.h>
   38 #include <sys/ctype.h>
   39 #include <sys/kernel.h>
   40 #include <sys/reboot.h>
   41 #include <sys/rman.h>
   42 #include <sys/sysctl.h>
   43 #include <sys/limits.h>
   44 
   45 #include <machine/bus.h>
   46 #include <machine/md_var.h>
   47 
   48 #include <dev/iicbus/iicbus.h>
   49 #include <dev/iicbus/iiconf.h>
   50 
   51 #include <dev/ofw/openfirm.h>
   52 #include <dev/ofw/ofw_bus.h>
   53 #include <powerpc/powermac/powermac_thermal.h>
   54 
   55 /* CPU A/B sensors, temp and adc: AD7417. */
   56 
   57 #define AD7417_TEMP         0x00
   58 #define AD7417_CONFIG       0x01
   59 #define AD7417_ADC          0x04
   60 #define AD7417_CONFIG2      0x05
   61 #define AD7417_CONFMASK     0xe0
   62 
   63 uint8_t adc741x_config;
   64 
   65 struct ad7417_sensor {
   66         struct  pmac_therm therm;
   67         device_t dev;
   68         int     id;
   69         enum {
   70                 ADC7417_TEMP_SENSOR,
   71                 ADC7417_ADC_SENSOR
   72         } type;
   73 };
   74 
   75 struct write_data {
   76         uint8_t reg;
   77         uint8_t val;
   78 };
   79 
   80 struct read_data {
   81         uint8_t reg;
   82         uint16_t val;
   83 };
   84 
   85 /* Regular bus attachment functions */
   86 static int ad7417_probe(device_t);
   87 static int ad7417_attach(device_t);
   88 
   89 /* Utility functions */
   90 static int ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS);
   91 static int ad7417_write(device_t dev, uint32_t addr, uint8_t reg,
   92                         uint8_t *buf, int len);
   93 static int ad7417_read_1(device_t dev, uint32_t addr, uint8_t reg,
   94                          uint8_t *data);
   95 static int ad7417_read_2(device_t dev, uint32_t addr, uint8_t reg,
   96                          uint16_t *data);
   97 static int ad7417_write_read(device_t dev, uint32_t addr,
   98                              struct write_data out, struct read_data *in);
   99 static int ad7417_diode_read(struct ad7417_sensor *sens);
  100 static int ad7417_adc_read(struct ad7417_sensor *sens);
  101 static int ad7417_sensor_read(struct ad7417_sensor *sens);
  102 
  103 struct ad7417_softc {
  104         device_t                sc_dev;
  105         uint32_t                sc_addr;
  106         struct ad7417_sensor    *sc_sensors;
  107         int                     sc_nsensors;
  108         int                     init_done;
  109 };
  110 static device_method_t  ad7417_methods[] = {
  111         /* Device interface */
  112         DEVMETHOD(device_probe,         ad7417_probe),
  113         DEVMETHOD(device_attach,        ad7417_attach),
  114         { 0, 0 },
  115 };
  116 
  117 static driver_t ad7417_driver = {
  118         "ad7417",
  119         ad7417_methods,
  120         sizeof(struct ad7417_softc)
  121 };
  122 
  123 DRIVER_MODULE(ad7417, iicbus, ad7417_driver, 0, 0);
  124 static MALLOC_DEFINE(M_AD7417, "ad7417", "Supply-Monitor AD7417");
  125 
  126 
  127 static int
  128 ad7417_write(device_t dev, uint32_t addr, uint8_t reg, uint8_t *buff, int len)
  129 {
  130         unsigned char buf[4];
  131         int try = 0;
  132 
  133         struct iic_msg msg[] = {
  134                 { addr, IIC_M_WR, 0, buf }
  135         };
  136 
  137         msg[0].len = len + 1;
  138         buf[0] = reg;
  139         memcpy(buf + 1, buff, len);
  140 
  141         for (;;)
  142         {
  143                 if (iicbus_transfer(dev, msg, nitems(msg)) == 0)
  144                         return (0);
  145 
  146                 if (++try > 5) {
  147                         device_printf(dev, "iicbus write failed\n");
  148                         return (-1);
  149                 }
  150                 pause("ad7417_write", hz);
  151         }
  152 }
  153 
  154 static int
  155 ad7417_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data)
  156 {
  157         uint8_t buf[4];
  158         int err, try = 0;
  159 
  160         struct iic_msg msg[2] = {
  161             { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
  162             { addr, IIC_M_RD, 1, buf },
  163         };
  164 
  165         for (;;)
  166         {
  167                 err = iicbus_transfer(dev, msg, nitems(msg));
  168                 if (err != 0)
  169                         goto retry;
  170 
  171                 *data = *((uint8_t*)buf);
  172                 return (0);
  173         retry:
  174                 if (++try > 5) {
  175                         device_printf(dev, "iicbus read failed\n");
  176                         return (-1);
  177                 }
  178                 pause("ad7417_read_1", hz);
  179         }
  180 }
  181 
  182 static int
  183 ad7417_read_2(device_t dev, uint32_t addr, uint8_t reg, uint16_t *data)
  184 {
  185         uint8_t buf[4];
  186         int err, try = 0;
  187 
  188         struct iic_msg msg[2] = {
  189             { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
  190             { addr, IIC_M_RD, 2, buf },
  191         };
  192 
  193         for (;;)
  194         {
  195                 err = iicbus_transfer(dev, msg, nitems(msg));
  196                 if (err != 0)
  197                         goto retry;
  198 
  199                 *data = *((uint16_t*)buf);
  200                 return (0);
  201         retry:
  202                 if (++try > 5) {
  203                         device_printf(dev, "iicbus read failed\n");
  204                         return (-1);
  205                 }
  206                 pause("ad7417_read_2", hz);
  207         }
  208 }
  209 
  210 static int
  211 ad7417_write_read(device_t dev, uint32_t addr, struct write_data out,
  212                   struct read_data *in)
  213 {
  214         uint8_t buf[4];
  215         int err, try = 0;
  216 
  217         /* Do a combined write/read. */
  218         struct iic_msg msg[3] = {
  219             { addr, IIC_M_WR, 2, buf },
  220             { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &in->reg },
  221             { addr, IIC_M_RD, 2, buf },
  222         };
  223 
  224         /* Prepare the write msg. */
  225         buf[0] = out.reg;
  226         buf[1] = out.val & 0xff;
  227 
  228         for (;;)
  229         {
  230                 err = iicbus_transfer(dev, msg, nitems(msg));
  231                 if (err != 0)
  232                         goto retry;
  233 
  234                 in->val = *((uint16_t*)buf);
  235                 return (0);
  236         retry:
  237                 if (++try > 5) {
  238                         device_printf(dev, "iicbus write/read failed\n");
  239                         return (-1);
  240                 }
  241                 pause("ad7417_write_read", hz);
  242         }
  243 }
  244 
  245 static int
  246 ad7417_init_adc(device_t dev, uint32_t addr)
  247 {
  248         uint8_t buf;
  249         int err;
  250         struct ad7417_softc *sc;
  251 
  252         sc = device_get_softc(dev);
  253 
  254         adc741x_config = 0;
  255         /* Clear Config2 */
  256         buf = 0;
  257 
  258         err = ad7417_write(dev, addr, AD7417_CONFIG2, &buf, sizeof(buf));
  259 
  260          /* Read & cache Config1 */
  261         buf = 0;
  262         err = ad7417_write(dev, addr, AD7417_CONFIG, &buf, sizeof(buf));
  263         err = ad7417_read_1(dev, addr, AD7417_CONFIG, &buf);
  264         adc741x_config = (uint8_t)buf;
  265 
  266         /* Disable shutdown mode */
  267         adc741x_config &= 0xfe;
  268         buf = adc741x_config;
  269         err = ad7417_write(dev, addr, AD7417_CONFIG, &buf, sizeof(buf));
  270         if (err < 0)
  271                 return (-1);
  272 
  273         sc->init_done = 1;
  274 
  275         return (0);
  276 
  277 }
  278 static int
  279 ad7417_probe(device_t dev)
  280 {
  281         const char  *name, *compatible;
  282         struct ad7417_softc *sc;
  283 
  284         name = ofw_bus_get_name(dev);
  285         compatible = ofw_bus_get_compat(dev);
  286 
  287         if (!name)
  288                 return (ENXIO);
  289 
  290         if (strcmp(name, "supply-monitor") != 0 ||
  291             strcmp(compatible, "ad7417") != 0)
  292                 return (ENXIO);
  293 
  294         sc = device_get_softc(dev);
  295         sc->sc_dev = dev;
  296         sc->sc_addr = iicbus_get_addr(dev);
  297 
  298         device_set_desc(dev, "Supply-Monitor AD7417");
  299 
  300         return (0);
  301 }
  302 
  303 /*
  304  * This function returns the number of sensors. If we call it the second time
  305  * and we have allocated memory for sc->sc_sensors, we fill in the properties.
  306  */
  307 static int
  308 ad7417_fill_sensor_prop(device_t dev)
  309 {
  310         phandle_t child, node;
  311         struct ad7417_softc *sc;
  312         u_int id[10];
  313         char location[96];
  314         char type[32];
  315         int i = 0, j, len = 0, prop_len, prev_len = 0;
  316 
  317         sc = device_get_softc(dev);
  318 
  319         child = ofw_bus_get_node(dev);
  320 
  321         /* Fill the sensor location property. */
  322         prop_len = OF_getprop(child, "hwsensor-location", location,
  323                               sizeof(location));
  324         while (len < prop_len) {
  325                 if (sc->sc_sensors != NULL)
  326                         strcpy(sc->sc_sensors[i].therm.name, location + len);
  327                 prev_len = strlen(location + len) + 1;
  328                 len += prev_len;
  329                 i++;
  330         }
  331         if (sc->sc_sensors == NULL)
  332                 return (i);
  333 
  334         /* Fill the sensor type property. */
  335         len = 0;
  336         i = 0;
  337         prev_len = 0;
  338         prop_len = OF_getprop(child, "hwsensor-type", type, sizeof(type));
  339         while (len < prop_len) {
  340                 if (strcmp(type + len, "temperature") == 0)
  341                         sc->sc_sensors[i].type = ADC7417_TEMP_SENSOR;
  342                 else
  343                         sc->sc_sensors[i].type = ADC7417_ADC_SENSOR;
  344                 prev_len = strlen(type + len) + 1;
  345                 len += prev_len;
  346                 i++;
  347         }
  348 
  349         /* Fill the sensor id property. Taken from OF. */
  350         prop_len = OF_getprop(child, "hwsensor-id", id, sizeof(id));
  351         for (j = 0; j < i; j++)
  352                 sc->sc_sensors[j].id = id[j];
  353 
  354         /* Fill the sensor zone property. Taken from OF. */
  355         prop_len = OF_getprop(child, "hwsensor-zone", id, sizeof(id));
  356         for (j = 0; j < i; j++)
  357                 sc->sc_sensors[j].therm.zone = id[j];
  358 
  359         /* Some PowerMac's have the real location of the sensors on
  360            child nodes of the hwsensor-location node. Check for and
  361            fix the name if needed.
  362            This is needed to apply the below HACK with the diode.
  363         */
  364         j = 0;
  365         for (node = OF_child(child); node != 0; node = OF_peer(node)) {
  366             
  367             OF_getprop(node, "location", location, sizeof(location));
  368             strcpy(sc->sc_sensors[i].therm.name, location);
  369             j++; 
  370         }
  371 
  372         /* Finish setting up sensor properties */
  373         for (j = 0; j < i; j++) {
  374                 sc->sc_sensors[j].dev = dev;
  375         
  376                 /* HACK: Apple wired a random diode to the ADC line */
  377                 if ((strstr(sc->sc_sensors[j].therm.name, "DIODE TEMP")
  378                     != NULL)
  379                     || (strstr(sc->sc_sensors[j].therm.name, "AD1") != NULL)) {
  380                         sc->sc_sensors[j].type = ADC7417_TEMP_SENSOR;
  381                         sc->sc_sensors[j].therm.read =
  382                             (int (*)(struct pmac_therm *))(ad7417_diode_read);
  383                 } else {
  384                         sc->sc_sensors[j].therm.read =
  385                             (int (*)(struct pmac_therm *))(ad7417_sensor_read);
  386                 }
  387                         
  388                 if (sc->sc_sensors[j].type != ADC7417_TEMP_SENSOR)
  389                         continue;
  390 
  391                 /* Make up some ranges */
  392                 sc->sc_sensors[j].therm.target_temp = 500 + ZERO_C_TO_K;
  393                 sc->sc_sensors[j].therm.max_temp = 900 + ZERO_C_TO_K;
  394                 
  395                 pmac_thermal_sensor_register(&sc->sc_sensors[j].therm);
  396         }
  397 
  398         return (i);
  399 }
  400 
  401 static int
  402 ad7417_attach(device_t dev)
  403 {
  404         struct ad7417_softc *sc;
  405         struct sysctl_oid *oid, *sensroot_oid;
  406         struct sysctl_ctx_list *ctx;
  407         char sysctl_name[32];
  408         int i, j;
  409         const char *unit;
  410 
  411         sc = device_get_softc(dev);
  412 
  413         sc->sc_nsensors = 0;
  414 
  415         /* Count the actual number of sensors. */
  416         sc->sc_nsensors = ad7417_fill_sensor_prop(dev);
  417 
  418         device_printf(dev, "%d sensors detected.\n", sc->sc_nsensors);
  419 
  420         if (sc->sc_nsensors == 0)
  421                 device_printf(dev, "WARNING: No AD7417 sensors detected!\n");
  422 
  423         sc->sc_sensors = malloc (sc->sc_nsensors * sizeof(struct ad7417_sensor),
  424                                  M_AD7417, M_WAITOK | M_ZERO);
  425 
  426         ctx = device_get_sysctl_ctx(dev);
  427         sensroot_oid = SYSCTL_ADD_NODE(ctx,
  428             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "sensor",
  429             CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "AD7417 Sensor Information");
  430 
  431         /* Now we can fill the properties into the allocated struct. */
  432         sc->sc_nsensors = ad7417_fill_sensor_prop(dev);
  433 
  434         /* Add sysctls for the sensors. */
  435         for (i = 0; i < sc->sc_nsensors; i++) {
  436                 for (j = 0; j < strlen(sc->sc_sensors[i].therm.name); j++) {
  437                         sysctl_name[j] =
  438                             tolower(sc->sc_sensors[i].therm.name[j]);
  439                         if (isspace(sysctl_name[j]))
  440                                 sysctl_name[j] = '_';
  441                 }
  442                 sysctl_name[j] = 0;
  443 
  444                 oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(sensroot_oid),
  445                     OID_AUTO, sysctl_name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  446                     "Sensor Information");
  447 
  448                 if (sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR) {
  449                         unit = "temp";
  450                 } else {
  451                         unit = "volt";
  452                 }
  453                 /* I use i to pass the sensor id. */
  454                 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
  455                                 unit, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
  456                                 dev, i, ad7417_sensor_sysctl,
  457                                 sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR ?
  458                                 "IK" : "I",
  459                                 sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR ?
  460                                 "sensor unit (C)" : "sensor unit (mV)");
  461         }
  462         /* Dump sensor location, ID & type. */
  463         if (bootverbose) {
  464                 device_printf(dev, "Sensors\n");
  465                 for (i = 0; i < sc->sc_nsensors; i++) {
  466                         device_printf(dev, "Location: %s ID: %d type: %d\n",
  467                                       sc->sc_sensors[i].therm.name,
  468                                       sc->sc_sensors[i].id,
  469                                       sc->sc_sensors[i].type);
  470                 }
  471         }
  472 
  473         return (0);
  474 }
  475 
  476 static int
  477 ad7417_get_temp(device_t dev, uint32_t addr, int *temp)
  478 {
  479         uint16_t buf[2];
  480         uint16_t read;
  481         int err;
  482 
  483         err = ad7417_read_2(dev, addr, AD7417_TEMP, buf);
  484 
  485         if (err < 0)
  486                 return (-1);
  487 
  488         read = *((int16_t*)buf);
  489 
  490         /* The ADC is 10 bit, the resolution is 0.25 C.
  491            The temperature is in tenth kelvin.
  492         */
  493         *temp = (((int16_t)(read & 0xffc0)) >> 6) * 25 / 10;
  494         return (0);
  495 }
  496 
  497 static int
  498 ad7417_get_adc(device_t dev, uint32_t addr, unsigned int *value,
  499                uint8_t chan)
  500 {
  501         uint8_t tmp;
  502         int err;
  503         struct write_data config;
  504         struct read_data data;
  505 
  506         tmp = chan << 5;
  507         config.reg = AD7417_CONFIG;
  508         data.reg = AD7417_ADC;
  509         data.val = 0;
  510 
  511         err = ad7417_read_1(dev, addr, AD7417_CONFIG, &config.val);
  512 
  513         config.val = (config.val & ~AD7417_CONFMASK) | (tmp & AD7417_CONFMASK);
  514 
  515         err = ad7417_write_read(dev, addr, config, &data);
  516         if (err < 0)
  517                 return (-1);
  518 
  519         *value = ((uint32_t)data.val) >> 6;
  520 
  521         return (0);
  522 }
  523 
  524 static int
  525 ad7417_diode_read(struct ad7417_sensor *sens)
  526 {
  527         static int eeprom_read = 0;
  528         static cell_t eeprom[2][40];
  529         phandle_t eeprom_node;
  530         int rawval, diode_slope, diode_offset;
  531         int temp;
  532 
  533         if (!eeprom_read) {
  534                 eeprom_node = OF_finddevice("/u3/i2c/cpuid@a0");
  535                 OF_getprop(eeprom_node, "cpuid", eeprom[0], sizeof(eeprom[0]));
  536                 eeprom_node = OF_finddevice("/u3/i2c/cpuid@a2");
  537                 OF_getprop(eeprom_node, "cpuid", eeprom[1], sizeof(eeprom[1]));
  538                 eeprom_read = 1;
  539         }
  540 
  541         rawval = ad7417_adc_read(sens);
  542         if (rawval < 0)
  543                 return (-1);
  544 
  545         if (strstr(sens->therm.name, "CPU B") != NULL) {
  546                 diode_slope = eeprom[1][0x11] >> 16;
  547                 diode_offset = (int16_t)(eeprom[1][0x11] & 0xffff) << 12;
  548         } else {
  549                 diode_slope = eeprom[0][0x11] >> 16;
  550                 diode_offset = (int16_t)(eeprom[0][0x11] & 0xffff) << 12;
  551         }
  552 
  553         temp = (rawval*diode_slope + diode_offset) >> 2;
  554         temp = (10*(temp >> 16)) + ((10*(temp & 0xffff)) >> 16);
  555         
  556         return (temp + ZERO_C_TO_K);
  557 }
  558 
  559 static int
  560 ad7417_adc_read(struct ad7417_sensor *sens)
  561 {
  562         struct ad7417_softc *sc;
  563         uint8_t chan;
  564         int temp;
  565 
  566         sc = device_get_softc(sens->dev);
  567 
  568         switch (sens->id) {
  569         case 11:
  570         case 16:
  571                 chan = 1;
  572                 break;
  573         case 12:
  574         case 17:
  575                 chan = 2;
  576                 break;
  577         case 13:
  578         case 18:
  579                 chan = 3;
  580                 break;
  581         case 14:
  582         case 19:
  583                 chan = 4;
  584                 break;
  585         default:
  586                 chan = 1;
  587         }
  588 
  589         if (ad7417_get_adc(sc->sc_dev, sc->sc_addr, &temp, chan) < 0)
  590                 return (-1);
  591 
  592         return (temp);
  593 }
  594 
  595 
  596 static int
  597 ad7417_sensor_read(struct ad7417_sensor *sens)
  598 {
  599         struct ad7417_softc *sc;
  600         int temp;
  601 
  602         sc = device_get_softc(sens->dev);
  603 
  604         /* Init the ADC if not already done.*/
  605         if (!sc->init_done)
  606                 if (ad7417_init_adc(sc->sc_dev, sc->sc_addr) < 0)
  607                         return (-1);
  608 
  609         if (sens->type == ADC7417_TEMP_SENSOR) {
  610                 if (ad7417_get_temp(sc->sc_dev, sc->sc_addr, &temp) < 0)
  611                         return (-1);
  612                 temp += ZERO_C_TO_K;
  613         } else {
  614                 temp = ad7417_adc_read(sens);
  615         }
  616         return (temp);
  617 }
  618 
  619 static int
  620 ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS)
  621 {
  622         device_t dev;
  623         struct ad7417_softc *sc;
  624         struct ad7417_sensor *sens;
  625         int value = 0;
  626         int error;
  627 
  628         dev = arg1;
  629         sc = device_get_softc(dev);
  630         sens = &sc->sc_sensors[arg2];
  631 
  632         value = sens->therm.read(&sens->therm);
  633         if (value < 0)
  634                 return (ENXIO);
  635 
  636         error = sysctl_handle_int(oidp, &value, 0, req);
  637 
  638         return (error);
  639 }

Cache object: 822924a593e37e58cc3f348c829da2c0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.