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/lm75.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  * Copyright (c) 2010 Andreas Tobler.
    3  * Copyright (c) 2013-2014 Luiz Otavio O Souza <loos@freebsd.org>
    4  * All rights reserved.
    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 "opt_platform.h"
   32 
   33 #include <sys/param.h>
   34 #include <sys/bus.h>
   35 #include <sys/endian.h>
   36 #include <sys/kernel.h>
   37 #include <sys/module.h>
   38 #include <sys/sysctl.h>
   39 #include <sys/systm.h>
   40 
   41 #include <machine/bus.h>
   42 
   43 #include <dev/iicbus/iicbus.h>
   44 #include <dev/iicbus/iiconf.h>
   45 
   46 #ifdef FDT
   47 #include <dev/ofw/openfirm.h>
   48 #include <dev/ofw/ofw_bus.h>
   49 #include <dev/ofw/ofw_bus_subr.h>
   50 #endif
   51 
   52 /* LM75 registers. */
   53 #define LM75_TEMP       0x0
   54 #define LM75_CONF       0x1
   55 #define LM75_CONF_FSHIFT        3
   56 #define LM75_CONF_FAULT         0x18
   57 #define LM75_CONF_POL           0x04
   58 #define LM75_CONF_MODE          0x02
   59 #define LM75_CONF_SHUTD         0x01
   60 #define LM75_CONF_MASK          0x1f
   61 #define LM75_THYST      0x2
   62 #define LM75_TOS        0x3
   63 
   64 /* LM75 constants. */
   65 #define LM75_TEST_PATTERN       0xa
   66 #define LM75_MIN_TEMP           -55
   67 #define LM75_MAX_TEMP           125
   68 #define TZ_ZEROC                27315
   69 #define TZ_ZEROC_DIVIDER        100
   70 
   71 enum max_resolution{
   72         BITS_9 = 1,
   73         BITS_11
   74 };
   75 
   76 /* Regular bus attachment functions */
   77 static int  lm75_probe(device_t);
   78 static int  lm75_attach(device_t);
   79 
   80 struct lm75_softc {
   81         device_t                sc_dev;
   82         struct intr_config_hook enum_hook;
   83         uint32_t                sc_addr;
   84         uint32_t                sc_conf;
   85         uint8_t                 sc_resolution;
   86         uint8_t                 sc_max_resolution;
   87         uint16_t                sc_multiplier;
   88 };
   89 
   90 /* Utility functions */
   91 static int  lm75_conf_read(struct lm75_softc *);
   92 static int  lm75_conf_write(struct lm75_softc *);
   93 static int  lm75_temp_read(struct lm75_softc *, uint8_t, int *);
   94 static int  lm75_temp_write(struct lm75_softc *, uint8_t, int);
   95 static void lm75_start(void *);
   96 static int  lm75_read(device_t, uint32_t, uint8_t, uint8_t *, size_t);
   97 static int  lm75_write(device_t, uint32_t, uint8_t *, size_t);
   98 static int  lm75_str_mode(char *);
   99 static int  lm75_str_pol(char *);
  100 static int  lm75_temp_sysctl(SYSCTL_HANDLER_ARGS);
  101 static int  lm75_faults_sysctl(SYSCTL_HANDLER_ARGS);
  102 static int  lm75_mode_sysctl(SYSCTL_HANDLER_ARGS);
  103 static int  lm75_pol_sysctl(SYSCTL_HANDLER_ARGS);
  104 static int  lm75_shutdown_sysctl(SYSCTL_HANDLER_ARGS);
  105 static int  lm75_resolution_sysctl(SYSCTL_HANDLER_ARGS);
  106 
  107 static device_method_t  lm75_methods[] = {
  108         /* Device interface */
  109         DEVMETHOD(device_probe,         lm75_probe),
  110         DEVMETHOD(device_attach,        lm75_attach),
  111 
  112         DEVMETHOD_END
  113 };
  114 
  115 static driver_t lm75_driver = {
  116         "lm75",
  117         lm75_methods,
  118         sizeof(struct lm75_softc)
  119 };
  120 
  121 #ifdef FDT
  122 static struct ofw_compat_data compat_data[] = {
  123         {"national,lm75",       BITS_9},
  124         {"ti,lm75",             BITS_9},
  125         {0,0}
  126 };
  127 #endif
  128 
  129 DRIVER_MODULE(lm75, iicbus, lm75_driver, 0, 0);
  130 
  131 static int
  132 lm75_read(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data, size_t len)
  133 {
  134         struct iic_msg msg[2] = {
  135             { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
  136             { addr, IIC_M_RD, len, data },
  137         };
  138 
  139         if (iicbus_transfer(dev, msg, nitems(msg)) != 0)
  140                 return (-1);
  141 
  142         return (0);
  143 }
  144 
  145 static int
  146 lm75_write(device_t dev, uint32_t addr, uint8_t *data, size_t len)
  147 {
  148         struct iic_msg msg[1] = {
  149             { addr, IIC_M_WR, len, data },
  150         };
  151 
  152         if (iicbus_transfer(dev, msg, nitems(msg)) != 0)
  153                 return (-1);
  154 
  155         return (0);
  156 }
  157 
  158 static int
  159 lm75_probe(device_t dev)
  160 {
  161 #ifdef FDT
  162         const struct ofw_compat_data *compat_ptr;
  163 #endif
  164         struct lm75_softc *sc;
  165 
  166         sc = device_get_softc(dev);
  167         sc->sc_max_resolution = 9;
  168 
  169 #ifdef FDT
  170         if (!ofw_bus_status_okay(dev))
  171                 return (ENXIO);
  172 
  173         compat_ptr = ofw_bus_search_compatible(dev, compat_data);
  174 
  175         switch (compat_ptr->ocd_data){
  176         case BITS_9:
  177                 sc->sc_max_resolution = 9;
  178                 break;
  179         case BITS_11:
  180                 sc->sc_max_resolution = 11;
  181                 break;
  182         default:
  183                 return (ENXIO);
  184         }
  185 #endif
  186         device_set_desc(dev, "LM75 temperature sensor");
  187 
  188         return (BUS_PROBE_GENERIC);
  189 }
  190 
  191 static int
  192 lm75_attach(device_t dev)
  193 {
  194         struct lm75_softc *sc;
  195 
  196         sc = device_get_softc(dev);
  197         sc->sc_dev = dev;
  198         sc->sc_addr = iicbus_get_addr(dev);
  199 
  200         sc->enum_hook.ich_func = lm75_start;
  201         sc->enum_hook.ich_arg = dev;
  202 
  203         switch (sc->sc_max_resolution) {
  204         case 9:
  205                 sc->sc_resolution = 9;
  206                 sc->sc_max_resolution = 9;
  207                 sc->sc_multiplier = 10;
  208                 break;
  209         case 11:
  210                 sc->sc_resolution = 11;
  211                 sc->sc_max_resolution = 11;
  212                 sc->sc_multiplier = 1000;
  213                 break;
  214         default:
  215                 return (ENXIO);
  216         }
  217 
  218         /*
  219          * We have to wait until interrupts are enabled.  Usually I2C read
  220          * and write only works when the interrupts are available.
  221          */
  222         if (config_intrhook_establish(&sc->enum_hook) != 0)
  223                 return (ENOMEM);
  224 
  225         return (0);
  226 }
  227 
  228 static int
  229 lm75_type_detect(struct lm75_softc *sc)
  230 {
  231         int i, lm75a;
  232         uint8_t buf8;
  233         uint32_t conf;
  234 
  235         /* Save the contents of the configuration register. */
  236         if (lm75_conf_read(sc) != 0)
  237                 return (-1);
  238         conf = sc->sc_conf;
  239 
  240         /*
  241          * Just write some pattern at configuration register so we can later
  242          * verify.  The test pattern should be pretty harmless.
  243          */
  244         sc->sc_conf = LM75_TEST_PATTERN;
  245         if (lm75_conf_write(sc) != 0)
  246                 return (-1);
  247 
  248         /*
  249          * Read the configuration register again and check for our test
  250          * pattern.
  251          */
  252         if (lm75_conf_read(sc) != 0)
  253                 return (-1);
  254         if (sc->sc_conf != LM75_TEST_PATTERN)
  255                 return (-1);
  256 
  257         /*
  258          * Read from nonexistent registers (0x4 ~ 0x6).
  259          * LM75A always return 0xff for nonexistent registers.
  260          * LM75 will return the last read value - our test pattern written to
  261          * configuration register.
  262          */
  263         lm75a = 0;
  264         for (i = 4; i <= 6; i++) {
  265                 if (lm75_read(sc->sc_dev, sc->sc_addr, i,
  266                     &buf8, sizeof(buf8)) < 0)
  267                         return (-1);
  268                 if (buf8 != LM75_TEST_PATTERN && buf8 != 0xff)
  269                         return (-1);
  270                 if (buf8 == 0xff)
  271                         lm75a++;
  272         }
  273         if (lm75a == 3){
  274                 sc->sc_multiplier = 1000;
  275                 sc->sc_resolution = 11;
  276                 sc->sc_max_resolution = 11;
  277         }
  278 
  279         /* Restore the configuration register. */
  280         sc->sc_conf = conf;
  281         if (lm75_conf_write(sc) != 0)
  282                 return (-1);
  283 
  284         return (0);
  285 }
  286 
  287 static void
  288 lm75_start(void *xdev)
  289 {
  290         device_t dev;
  291         struct lm75_softc *sc;
  292         struct sysctl_ctx_list *ctx;
  293         struct sysctl_oid *tree_node;
  294         struct sysctl_oid_list *tree;
  295         char *mult_format;
  296 
  297         dev = (device_t)xdev;
  298         sc = device_get_softc(dev);
  299         ctx = device_get_sysctl_ctx(dev);
  300         tree_node = device_get_sysctl_tree(dev);
  301         tree = SYSCTL_CHILDREN(tree_node);
  302 
  303         config_intrhook_disestablish(&sc->enum_hook);
  304 
  305         /*
  306          * Detect the kind of chip we are attaching to.
  307          * This may not work for LM75 clones.
  308          */
  309         if (lm75_type_detect(sc) != 0) {
  310                 device_printf(dev, "cannot detect sensor.\n");
  311 #ifndef FDT
  312                 return;
  313 #endif
  314         }
  315 
  316         device_printf(dev,"%d bit resolution sensor attached.\n",
  317                         sc->sc_resolution);
  318 
  319         if (sc->sc_multiplier == 1000)
  320                 mult_format = "IK3";
  321         else
  322                 mult_format = "IK";
  323 
  324         /* Temperature. */
  325         SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "temperature",
  326             CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, LM75_TEMP,
  327             lm75_temp_sysctl, mult_format, "Current temperature");
  328         SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "thyst",
  329             CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, LM75_THYST,
  330             lm75_temp_sysctl, mult_format, "Hysteresis temperature");
  331         SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "tos",
  332             CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, LM75_TOS,
  333             lm75_temp_sysctl, mult_format, "Overtemperature");
  334 
  335         /* Configuration parameters. */
  336         SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "faults",
  337             CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, dev, 0,
  338             lm75_faults_sysctl, "IU", "LM75 fault queue");
  339         SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "mode",
  340             CTLFLAG_RW | CTLTYPE_STRING | CTLFLAG_MPSAFE, dev, 0,
  341             lm75_mode_sysctl, "A", "LM75 mode");
  342         SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "polarity",
  343             CTLFLAG_RW | CTLTYPE_STRING | CTLFLAG_MPSAFE, dev, 0,
  344             lm75_pol_sysctl, "A", "LM75 OS polarity");
  345         SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "shutdown",
  346             CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, dev, 0,
  347             lm75_shutdown_sysctl, "IU", "LM75 shutdown");
  348         SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "resolution",
  349             CTLFLAG_RW | CTLTYPE_INT | CTLFLAG_MPSAFE, dev, 0,
  350             lm75_resolution_sysctl, "IU", "LM75 resolution");
  351 }
  352 
  353 static int
  354 lm75_conf_read(struct lm75_softc *sc)
  355 {
  356         uint8_t buf8;
  357 
  358         if (lm75_read(sc->sc_dev, sc->sc_addr, LM75_CONF,
  359             &buf8, sizeof(buf8)) < 0)
  360                 return (-1);
  361         sc->sc_conf = (uint32_t)buf8;
  362 
  363         return (0);
  364 }
  365 
  366 static int
  367 lm75_conf_write(struct lm75_softc *sc)
  368 {
  369         uint8_t buf8[2];
  370 
  371         buf8[0] = LM75_CONF;
  372         buf8[1] = (uint8_t)sc->sc_conf & LM75_CONF_MASK;
  373         if (lm75_write(sc->sc_dev, sc->sc_addr, buf8, sizeof(buf8)) < 0)
  374                 return (-1);
  375 
  376         return (0);
  377 }
  378 
  379 static int
  380 lm75_temp_read(struct lm75_softc *sc, uint8_t reg, int32_t *temp)
  381 {
  382         int32_t buf;
  383         uint8_t buf8[2];
  384         uint8_t resolution = sc->sc_resolution;
  385         uint16_t multiplier = sc->sc_multiplier;
  386 
  387         if (lm75_read(sc->sc_dev, sc->sc_addr, reg, buf8, sizeof(buf8)) < 0)
  388                 return (-1);
  389 
  390         buf = (int16_t)((buf8[0] << 8) | buf8[1]);
  391         *temp = ((buf >> (16 - resolution)) * multiplier) >> (resolution - 8);
  392 
  393         *temp += TZ_ZEROC * sc->sc_multiplier / TZ_ZEROC_DIVIDER;
  394 
  395         return (0);
  396 }
  397 
  398 static int
  399 lm75_temp_write(struct lm75_softc *sc, uint8_t reg, int32_t temp)
  400 {
  401         int32_t buf;
  402         uint8_t buf8[3], resolution = sc->sc_resolution;
  403         uint16_t multiplier = sc->sc_multiplier;
  404 
  405         temp -= TZ_ZEROC * multiplier / TZ_ZEROC_DIVIDER;
  406         if (temp > LM75_MAX_TEMP * multiplier)
  407                 temp = LM75_MAX_TEMP * multiplier;
  408         if (temp < LM75_MIN_TEMP * multiplier)
  409                 temp = LM75_MIN_TEMP * multiplier;
  410 
  411         buf = ((temp << (resolution - 8)) / multiplier) << (16 - resolution);
  412 
  413         buf8[0] = reg;
  414         buf8[1] = (buf >> 8) & 0xff;
  415         buf8[2] = buf & 0xff;
  416 
  417         if (lm75_write(sc->sc_dev, sc->sc_addr, buf8, sizeof(buf8)) < 0)
  418                 return (-1);
  419 
  420         return (0);
  421 }
  422 
  423 static int
  424 lm75_str_mode(char *buf)
  425 {
  426         int len, rtrn;
  427 
  428         rtrn = -1;
  429         len = strlen(buf);
  430         if (len > 2 && strncasecmp("interrupt", buf, len) == 0)
  431                 rtrn = 1;
  432         else if (len > 2 && strncasecmp("comparator", buf, len) == 0)
  433                 rtrn = 0;
  434 
  435         return (rtrn);
  436 }
  437 
  438 static int
  439 lm75_str_pol(char *buf)
  440 {
  441         int len, rtrn;
  442 
  443         rtrn = -1;
  444         len = strlen(buf);
  445         if (len > 1 && strncasecmp("high", buf, len) == 0)
  446                 rtrn = 1;
  447         else if (len > 1 && strncasecmp("low", buf, len) == 0)
  448                 rtrn = 0;
  449         else if (len > 8 && strncasecmp("active-high", buf, len) == 0)
  450                 rtrn = 1;
  451         else if (len > 8 && strncasecmp("active-low", buf, len) == 0)
  452                 rtrn = 0;
  453 
  454         return (rtrn);
  455 }
  456 
  457 static int
  458 lm75_temp_sysctl(SYSCTL_HANDLER_ARGS)
  459 {
  460         device_t dev;
  461         int error;
  462         int32_t temp;
  463         struct lm75_softc *sc;
  464         uint8_t reg;
  465 
  466         dev = (device_t)arg1;
  467         reg = (uint8_t)arg2;
  468         sc = device_get_softc(dev);
  469 
  470         if (lm75_temp_read(sc, reg, &temp) != 0)
  471                 return (EIO);
  472 
  473         error = sysctl_handle_int(oidp, &temp, 0, req);
  474         if (error != 0 || req->newptr == NULL)
  475                 return (error);
  476 
  477         if (lm75_temp_write(sc, reg, temp) != 0)
  478                 return (EIO);
  479 
  480         return (error);
  481 }
  482 
  483 static int
  484 lm75_faults_sysctl(SYSCTL_HANDLER_ARGS)
  485 {
  486         device_t dev;
  487         int lm75_faults[] = { 1, 2, 4, 6 };
  488         int error, faults, i, newf, tmp;
  489         struct lm75_softc *sc;
  490 
  491         dev = (device_t)arg1;
  492         sc = device_get_softc(dev);
  493         tmp = (sc->sc_conf & LM75_CONF_FAULT) >> LM75_CONF_FSHIFT;
  494         if (tmp >= nitems(lm75_faults))
  495                 tmp = nitems(lm75_faults) - 1;
  496         faults = lm75_faults[tmp];
  497 
  498         error = sysctl_handle_int(oidp, &faults, 0, req);
  499         if (error != 0 || req->newptr == NULL)
  500                 return (error);
  501 
  502         if (faults != lm75_faults[tmp]) {
  503                 newf = 0;
  504                 for (i = 0; i < nitems(lm75_faults); i++)
  505                         if (faults >= lm75_faults[i])
  506                                 newf = i;
  507                 sc->sc_conf &= ~LM75_CONF_FAULT;
  508                 sc->sc_conf |= newf << LM75_CONF_FSHIFT;
  509                 if (lm75_conf_write(sc) != 0)
  510                         return (EIO);
  511         }
  512 
  513         return (error);
  514 }
  515 
  516 static int
  517 lm75_mode_sysctl(SYSCTL_HANDLER_ARGS)
  518 {
  519         char buf[16];
  520         device_t dev;
  521         int error, mode, newm;
  522         struct lm75_softc *sc;
  523 
  524         dev = (device_t)arg1;
  525         sc = device_get_softc(dev);
  526         if (sc->sc_conf & LM75_CONF_MODE) {
  527                 mode = 1;
  528                 strlcpy(buf, "interrupt", sizeof(buf));
  529         } else {
  530                 mode = 0;
  531                 strlcpy(buf, "comparator", sizeof(buf));
  532         }
  533 
  534         error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
  535         if (error != 0 || req->newptr == NULL)
  536                 return (error);
  537 
  538         newm = lm75_str_mode(buf);
  539         if (newm != -1 && mode != newm) {
  540                 sc->sc_conf &= ~LM75_CONF_MODE;
  541                 if (newm == 1)
  542                         sc->sc_conf |= LM75_CONF_MODE;
  543                 if (lm75_conf_write(sc) != 0)
  544                         return (EIO);
  545         }
  546 
  547         return (error);
  548 }
  549 
  550 static int
  551 lm75_pol_sysctl(SYSCTL_HANDLER_ARGS)
  552 {
  553         char buf[16];
  554         device_t dev;
  555         int error, newp, pol;
  556         struct lm75_softc *sc;
  557 
  558         dev = (device_t)arg1;
  559         sc = device_get_softc(dev);
  560         if (sc->sc_conf & LM75_CONF_POL) {
  561                 pol = 1;
  562                 strlcpy(buf, "active-high", sizeof(buf));
  563         } else {
  564                 pol = 0;
  565                 strlcpy(buf, "active-low", sizeof(buf));
  566         }
  567 
  568         error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
  569         if (error != 0 || req->newptr == NULL)
  570                 return (error);
  571 
  572         newp = lm75_str_pol(buf);
  573         if (newp != -1 && pol != newp) {
  574                 sc->sc_conf &= ~LM75_CONF_POL;
  575                 if (newp == 1)
  576                         sc->sc_conf |= LM75_CONF_POL;
  577                 if (lm75_conf_write(sc) != 0)
  578                         return (EIO);
  579         }
  580 
  581         return (error);
  582 }
  583 
  584 static int
  585 lm75_shutdown_sysctl(SYSCTL_HANDLER_ARGS)
  586 {
  587         device_t dev;
  588         int error, shutdown, tmp;
  589         struct lm75_softc *sc;
  590 
  591         dev = (device_t)arg1;
  592         sc = device_get_softc(dev);
  593         tmp = shutdown = (sc->sc_conf & LM75_CONF_SHUTD) ? 1 : 0;
  594 
  595         error = sysctl_handle_int(oidp, &shutdown, 0, req);
  596         if (error != 0 || req->newptr == NULL)
  597                 return (error);
  598 
  599         if (shutdown != tmp) {
  600                 sc->sc_conf &= ~LM75_CONF_SHUTD;
  601                 if (shutdown)
  602                         sc->sc_conf |= LM75_CONF_SHUTD;
  603                 if (lm75_conf_write(sc) != 0)
  604                         return (EIO);
  605         }
  606 
  607         return (error);
  608 }
  609 
  610 static int
  611 lm75_resolution_sysctl(SYSCTL_HANDLER_ARGS)
  612 {
  613         device_t dev;
  614         int error;
  615         struct lm75_softc *sc;
  616         int resolution;
  617 
  618         dev = (device_t)arg1;
  619         sc = device_get_softc(dev);
  620         resolution = sc->sc_resolution;
  621 
  622         error = sysctl_handle_int(oidp, &resolution, 0, req);
  623         if (error != 0 || req->newptr == NULL)
  624                 return (error);
  625 
  626         if (resolution > sc->sc_max_resolution || resolution < 9)
  627                 return (EINVAL);
  628 
  629         sc->sc_resolution = (uint8_t) resolution;
  630 
  631         return (0);
  632 }

Cache object: f469823a7523750161584fcb01d24777


[ 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.