linux/drivers/hwmon/ltc4245.c
<<
>>
Prefs
   1/*
   2 * Driver for Linear Technology LTC4245 I2C Multiple Supply Hot Swap Controller
   3 *
   4 * Copyright (C) 2008 Ira W. Snyder <iws@ovro.caltech.edu>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; version 2 of the License.
   9 *
  10 * This driver is based on the ds1621 and ina209 drivers.
  11 *
  12 * Datasheet:
  13 * http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1140,P19392,D13517
  14 */
  15
  16#include <linux/kernel.h>
  17#include <linux/module.h>
  18#include <linux/init.h>
  19#include <linux/err.h>
  20#include <linux/slab.h>
  21#include <linux/i2c.h>
  22#include <linux/hwmon.h>
  23#include <linux/hwmon-sysfs.h>
  24#include <linux/i2c/ltc4245.h>
  25
  26/* Here are names of the chip's registers (a.k.a. commands) */
  27enum ltc4245_cmd {
  28        LTC4245_STATUS                  = 0x00, /* readonly */
  29        LTC4245_ALERT                   = 0x01,
  30        LTC4245_CONTROL                 = 0x02,
  31        LTC4245_ON                      = 0x03,
  32        LTC4245_FAULT1                  = 0x04,
  33        LTC4245_FAULT2                  = 0x05,
  34        LTC4245_GPIO                    = 0x06,
  35        LTC4245_ADCADR                  = 0x07,
  36
  37        LTC4245_12VIN                   = 0x10,
  38        LTC4245_12VSENSE                = 0x11,
  39        LTC4245_12VOUT                  = 0x12,
  40        LTC4245_5VIN                    = 0x13,
  41        LTC4245_5VSENSE                 = 0x14,
  42        LTC4245_5VOUT                   = 0x15,
  43        LTC4245_3VIN                    = 0x16,
  44        LTC4245_3VSENSE                 = 0x17,
  45        LTC4245_3VOUT                   = 0x18,
  46        LTC4245_VEEIN                   = 0x19,
  47        LTC4245_VEESENSE                = 0x1a,
  48        LTC4245_VEEOUT                  = 0x1b,
  49        LTC4245_GPIOADC                 = 0x1c,
  50};
  51
  52struct ltc4245_data {
  53        struct device *hwmon_dev;
  54
  55        struct mutex update_lock;
  56        bool valid;
  57        unsigned long last_updated; /* in jiffies */
  58
  59        /* Control registers */
  60        u8 cregs[0x08];
  61
  62        /* Voltage registers */
  63        u8 vregs[0x0d];
  64
  65        /* GPIO ADC registers */
  66        bool use_extra_gpios;
  67        int gpios[3];
  68};
  69
  70/*
  71 * Update the readings from the GPIO pins. If the driver has been configured to
  72 * sample all GPIO's as analog voltages, a round-robin sampling method is used.
  73 * Otherwise, only the configured GPIO pin is sampled.
  74 *
  75 * LOCKING: must hold data->update_lock
  76 */
  77static void ltc4245_update_gpios(struct device *dev)
  78{
  79        struct i2c_client *client = to_i2c_client(dev);
  80        struct ltc4245_data *data = i2c_get_clientdata(client);
  81        u8 gpio_curr, gpio_next, gpio_reg;
  82        int i;
  83
  84        /* no extra gpio support, we're basically done */
  85        if (!data->use_extra_gpios) {
  86                data->gpios[0] = data->vregs[LTC4245_GPIOADC - 0x10];
  87                return;
  88        }
  89
  90        /*
  91         * If the last reading was too long ago, then we mark all old GPIO
  92         * readings as stale by setting them to -EAGAIN
  93         */
  94        if (time_after(jiffies, data->last_updated + 5 * HZ)) {
  95                dev_dbg(&client->dev, "Marking GPIOs invalid\n");
  96                for (i = 0; i < ARRAY_SIZE(data->gpios); i++)
  97                        data->gpios[i] = -EAGAIN;
  98        }
  99
 100        /*
 101         * Get the current GPIO pin
 102         *
 103         * The datasheet calls these GPIO[1-3], but we'll calculate the zero
 104         * based array index instead, and call them GPIO[0-2]. This is much
 105         * easier to think about.
 106         */
 107        gpio_curr = (data->cregs[LTC4245_GPIO] & 0xc0) >> 6;
 108        if (gpio_curr > 0)
 109                gpio_curr -= 1;
 110
 111        /* Read the GPIO voltage from the GPIOADC register */
 112        data->gpios[gpio_curr] = data->vregs[LTC4245_GPIOADC - 0x10];
 113
 114        /* Find the next GPIO pin to read */
 115        gpio_next = (gpio_curr + 1) % ARRAY_SIZE(data->gpios);
 116
 117        /*
 118         * Calculate the correct setting for the GPIO register so it will
 119         * sample the next GPIO pin
 120         */
 121        gpio_reg = (data->cregs[LTC4245_GPIO] & 0x3f) | ((gpio_next + 1) << 6);
 122
 123        /* Update the GPIO register */
 124        i2c_smbus_write_byte_data(client, LTC4245_GPIO, gpio_reg);
 125
 126        /* Update saved data */
 127        data->cregs[LTC4245_GPIO] = gpio_reg;
 128}
 129
 130static struct ltc4245_data *ltc4245_update_device(struct device *dev)
 131{
 132        struct i2c_client *client = to_i2c_client(dev);
 133        struct ltc4245_data *data = i2c_get_clientdata(client);
 134        s32 val;
 135        int i;
 136
 137        mutex_lock(&data->update_lock);
 138
 139        if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
 140
 141                dev_dbg(&client->dev, "Starting ltc4245 update\n");
 142
 143                /* Read control registers -- 0x00 to 0x07 */
 144                for (i = 0; i < ARRAY_SIZE(data->cregs); i++) {
 145                        val = i2c_smbus_read_byte_data(client, i);
 146                        if (unlikely(val < 0))
 147                                data->cregs[i] = 0;
 148                        else
 149                                data->cregs[i] = val;
 150                }
 151
 152                /* Read voltage registers -- 0x10 to 0x1c */
 153                for (i = 0; i < ARRAY_SIZE(data->vregs); i++) {
 154                        val = i2c_smbus_read_byte_data(client, i+0x10);
 155                        if (unlikely(val < 0))
 156                                data->vregs[i] = 0;
 157                        else
 158                                data->vregs[i] = val;
 159                }
 160
 161                /* Update GPIO readings */
 162                ltc4245_update_gpios(dev);
 163
 164                data->last_updated = jiffies;
 165                data->valid = 1;
 166        }
 167
 168        mutex_unlock(&data->update_lock);
 169
 170        return data;
 171}
 172
 173/* Return the voltage from the given register in millivolts */
 174static int ltc4245_get_voltage(struct device *dev, u8 reg)
 175{
 176        struct ltc4245_data *data = ltc4245_update_device(dev);
 177        const u8 regval = data->vregs[reg - 0x10];
 178        u32 voltage = 0;
 179
 180        switch (reg) {
 181        case LTC4245_12VIN:
 182        case LTC4245_12VOUT:
 183                voltage = regval * 55;
 184                break;
 185        case LTC4245_5VIN:
 186        case LTC4245_5VOUT:
 187                voltage = regval * 22;
 188                break;
 189        case LTC4245_3VIN:
 190        case LTC4245_3VOUT:
 191                voltage = regval * 15;
 192                break;
 193        case LTC4245_VEEIN:
 194        case LTC4245_VEEOUT:
 195                voltage = regval * -55;
 196                break;
 197        case LTC4245_GPIOADC:
 198                voltage = regval * 10;
 199                break;
 200        default:
 201                /* If we get here, the developer messed up */
 202                WARN_ON_ONCE(1);
 203                break;
 204        }
 205
 206        return voltage;
 207}
 208
 209/* Return the current in the given sense register in milliAmperes */
 210static unsigned int ltc4245_get_current(struct device *dev, u8 reg)
 211{
 212        struct ltc4245_data *data = ltc4245_update_device(dev);
 213        const u8 regval = data->vregs[reg - 0x10];
 214        unsigned int voltage;
 215        unsigned int curr;
 216
 217        /*
 218         * The strange looking conversions that follow are fixed-point
 219         * math, since we cannot do floating point in the kernel.
 220         *
 221         * Step 1: convert sense register to microVolts
 222         * Step 2: convert voltage to milliAmperes
 223         *
 224         * If you play around with the V=IR equation, you come up with
 225         * the following: X uV / Y mOhm == Z mA
 226         *
 227         * With the resistors that are fractions of a milliOhm, we multiply
 228         * the voltage and resistance by 10, to shift the decimal point.
 229         * Now we can use the normal division operator again.
 230         */
 231
 232        switch (reg) {
 233        case LTC4245_12VSENSE:
 234                voltage = regval * 250; /* voltage in uV */
 235                curr = voltage / 50; /* sense resistor 50 mOhm */
 236                break;
 237        case LTC4245_5VSENSE:
 238                voltage = regval * 125; /* voltage in uV */
 239                curr = (voltage * 10) / 35; /* sense resistor 3.5 mOhm */
 240                break;
 241        case LTC4245_3VSENSE:
 242                voltage = regval * 125; /* voltage in uV */
 243                curr = (voltage * 10) / 25; /* sense resistor 2.5 mOhm */
 244                break;
 245        case LTC4245_VEESENSE:
 246                voltage = regval * 250; /* voltage in uV */
 247                curr = voltage / 100; /* sense resistor 100 mOhm */
 248                break;
 249        default:
 250                /* If we get here, the developer messed up */
 251                WARN_ON_ONCE(1);
 252                curr = 0;
 253                break;
 254        }
 255
 256        return curr;
 257}
 258
 259static ssize_t ltc4245_show_voltage(struct device *dev,
 260                                    struct device_attribute *da,
 261                                    char *buf)
 262{
 263        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 264        const int voltage = ltc4245_get_voltage(dev, attr->index);
 265
 266        return snprintf(buf, PAGE_SIZE, "%d\n", voltage);
 267}
 268
 269static ssize_t ltc4245_show_current(struct device *dev,
 270                                    struct device_attribute *da,
 271                                    char *buf)
 272{
 273        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 274        const unsigned int curr = ltc4245_get_current(dev, attr->index);
 275
 276        return snprintf(buf, PAGE_SIZE, "%u\n", curr);
 277}
 278
 279static ssize_t ltc4245_show_power(struct device *dev,
 280                                  struct device_attribute *da,
 281                                  char *buf)
 282{
 283        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 284        const unsigned int curr = ltc4245_get_current(dev, attr->index);
 285        const int output_voltage = ltc4245_get_voltage(dev, attr->index+1);
 286
 287        /* current in mA * voltage in mV == power in uW */
 288        const unsigned int power = abs(output_voltage * curr);
 289
 290        return snprintf(buf, PAGE_SIZE, "%u\n", power);
 291}
 292
 293static ssize_t ltc4245_show_alarm(struct device *dev,
 294                                          struct device_attribute *da,
 295                                          char *buf)
 296{
 297        struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
 298        struct ltc4245_data *data = ltc4245_update_device(dev);
 299        const u8 reg = data->cregs[attr->index];
 300        const u32 mask = attr->nr;
 301
 302        return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0);
 303}
 304
 305static ssize_t ltc4245_show_gpio(struct device *dev,
 306                                 struct device_attribute *da,
 307                                 char *buf)
 308{
 309        struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 310        struct ltc4245_data *data = ltc4245_update_device(dev);
 311        int val = data->gpios[attr->index];
 312
 313        /* handle stale GPIO's */
 314        if (val < 0)
 315                return val;
 316
 317        /* Convert to millivolts and print */
 318        return snprintf(buf, PAGE_SIZE, "%u\n", val * 10);
 319}
 320
 321/*
 322 * These macros are used below in constructing device attribute objects
 323 * for use with sysfs_create_group() to make a sysfs device file
 324 * for each register.
 325 */
 326
 327#define LTC4245_VOLTAGE(name, ltc4245_cmd_idx) \
 328        static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
 329        ltc4245_show_voltage, NULL, ltc4245_cmd_idx)
 330
 331#define LTC4245_CURRENT(name, ltc4245_cmd_idx) \
 332        static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
 333        ltc4245_show_current, NULL, ltc4245_cmd_idx)
 334
 335#define LTC4245_POWER(name, ltc4245_cmd_idx) \
 336        static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
 337        ltc4245_show_power, NULL, ltc4245_cmd_idx)
 338
 339#define LTC4245_ALARM(name, mask, reg) \
 340        static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \
 341        ltc4245_show_alarm, NULL, (mask), reg)
 342
 343#define LTC4245_GPIO_VOLTAGE(name, gpio_num) \
 344        static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
 345        ltc4245_show_gpio, NULL, gpio_num)
 346
 347/* Construct a sensor_device_attribute structure for each register */
 348
 349/* Input voltages */
 350LTC4245_VOLTAGE(in1_input,                      LTC4245_12VIN);
 351LTC4245_VOLTAGE(in2_input,                      LTC4245_5VIN);
 352LTC4245_VOLTAGE(in3_input,                      LTC4245_3VIN);
 353LTC4245_VOLTAGE(in4_input,                      LTC4245_VEEIN);
 354
 355/* Input undervoltage alarms */
 356LTC4245_ALARM(in1_min_alarm,    (1 << 0),       LTC4245_FAULT1);
 357LTC4245_ALARM(in2_min_alarm,    (1 << 1),       LTC4245_FAULT1);
 358LTC4245_ALARM(in3_min_alarm,    (1 << 2),       LTC4245_FAULT1);
 359LTC4245_ALARM(in4_min_alarm,    (1 << 3),       LTC4245_FAULT1);
 360
 361/* Currents (via sense resistor) */
 362LTC4245_CURRENT(curr1_input,                    LTC4245_12VSENSE);
 363LTC4245_CURRENT(curr2_input,                    LTC4245_5VSENSE);
 364LTC4245_CURRENT(curr3_input,                    LTC4245_3VSENSE);
 365LTC4245_CURRENT(curr4_input,                    LTC4245_VEESENSE);
 366
 367/* Overcurrent alarms */
 368LTC4245_ALARM(curr1_max_alarm,  (1 << 4),       LTC4245_FAULT1);
 369LTC4245_ALARM(curr2_max_alarm,  (1 << 5),       LTC4245_FAULT1);
 370LTC4245_ALARM(curr3_max_alarm,  (1 << 6),       LTC4245_FAULT1);
 371LTC4245_ALARM(curr4_max_alarm,  (1 << 7),       LTC4245_FAULT1);
 372
 373/* Output voltages */
 374LTC4245_VOLTAGE(in5_input,                      LTC4245_12VOUT);
 375LTC4245_VOLTAGE(in6_input,                      LTC4245_5VOUT);
 376LTC4245_VOLTAGE(in7_input,                      LTC4245_3VOUT);
 377LTC4245_VOLTAGE(in8_input,                      LTC4245_VEEOUT);
 378
 379/* Power Bad alarms */
 380LTC4245_ALARM(in5_min_alarm,    (1 << 0),       LTC4245_FAULT2);
 381LTC4245_ALARM(in6_min_alarm,    (1 << 1),       LTC4245_FAULT2);
 382LTC4245_ALARM(in7_min_alarm,    (1 << 2),       LTC4245_FAULT2);
 383LTC4245_ALARM(in8_min_alarm,    (1 << 3),       LTC4245_FAULT2);
 384
 385/* GPIO voltages */
 386LTC4245_GPIO_VOLTAGE(in9_input,                 0);
 387LTC4245_GPIO_VOLTAGE(in10_input,                1);
 388LTC4245_GPIO_VOLTAGE(in11_input,                2);
 389
 390/* Power Consumption (virtual) */
 391LTC4245_POWER(power1_input,                     LTC4245_12VSENSE);
S_1<c4245.c#L391" iame="L300k5l545.c#L391" iame=" hre  struct (#L338" i"> 390307">383"> 383curr3_input,                 ef">ltc4235_show_alarm(struct 3a hre39"L274" class="line" name="L274"> 2743 class="l3ne" name="L294"> 2943     3      href="+code=PAGE_SIZE" class="sref">PAGE_SIZE,  365 * Finally,on/ltc4245             0);
/*emb39"t=2i="drabov245.c#L32,e_attribute" cl3ss="s39"line" name="L365"> 3f="+code=s="line" name="L297"> 293 3       href="drivers/hwmoarsaycas required/a>, > 3="+code=ic#L298" id="L298" class=3line"39E" class="sref">LTC4245_VOLTAGE" class="sref">LTC4245_GPIO_VOLTAGE(<4ame="L2994> 299        const <4 href4"+codehwmon/lstruct                        e="L344">td">ltc4245_">data = td">ltc4245_"    [] = vice_attribute" class="sref">device_4index" cl4ss="sref">index];
)
ltc4w_gpio(struct  300   4    c4nst LTC4245_POWERLrive.               >)
ltc4w_gpio(struct 403t )
ltc4w_gpio(struct #L338" i"> 390307">34" cla404t )
ltc4w_gpio(struct  2743 class="l3ne"4 href40294"> 2943     3      href="+code=PA4href="dri4ers/hwmon/ltc4245.c#L3054 id="4305" class="liLTC4245_ALARM(LTC42rive.               >)
ltc4w_gpio(struct LTC4245_ALARM(LTC42rive.               >)
ltc4w_gpio(struct  294ef="+408t LTC4245_ALARM(LTC42rive.               >)
ltc4w_gpio(struct da,
<LTC4245_ALARM(LTC42rive.               >)
ltc4w_gpio(struct  419" id="L359" class="line" name="L359"> 34n/ltc42454c#L310" id="L310" class=4line"41drivers/hwmon 3605.c#L296" id="L2line" name=rive.               >)
ltc4w_gpio(struct LTC4245_CURRENTLTCrive.               >)
ltc4w_gpio(struct val = LTC4245_CURRENT<5.c#L296" id="L2ss="sref">Lrive.               >)
ltc4w_gpio(struct ->LTC4245_CURRENT<5.c#L296" id="L2ss="sref">Lrive.               >)
ltc4w_gpio(struct  2943     3      href="+code=PA4 */ltc4w_gpio(struct LTC4245_ALARM(LTC4245_Arive.               >)
ltc4w_gpio(struct LTC4245_ALARM(LTC4245_Arive.               >)
ltc4w_gpio(struct  418da,
<LTC4245_ALARM(LTC4245_Arive.               >)
ltc4w_gpio(struct (buf, PAGE_SIZE4 )
ltc4w_gpio(struct  * 10);
LTC4245_VO5.c#L296" id="L2="lass="srive.               >)
ltc4w_gpio(struct LTC4245_5.c#L296" id="L2=" class=rive.               >)
ltc4w_gpio(struct  322LTC4245_5.c#L296" id="L2=" class=rive.               >)
ltc4w_gpio(struct  2943     3      href="+code=PA4fs_create4group() to make a sysfs 4evice4205" class="li)
ltc4w_gpio(struct LTC4245_ALARM(LTC42rive.               >)
ltc4w_gpio(struct  326
4a hre428t LTC4245_ALARM(LTC42rive.               >)
ltc4w_gpio(struct ltc4245_cmd_idx)4\
da,
<LTC4245_ALARM(LTC42rive.               >)
ltc4w_gpio(struct , \
 329        5.c#L296" id="L2="ss="linrive.               >)
ltc4w_gpio(struct  330
4a hre43 id="L371" class="line" name="L371"> 3714 class="s4ef">ltc4245_cmd_idx)4\
 385.c#L296" id="L2lass="line" rive.               >)
ltc4w_gpio(struct , \
LTC4245_POWERLrive.               >)
ltc4w_gpio(struct  333        LTC4245_CURRENT<5.c#L296" id="L2uct ltc4w_gpio(struct  334<4a>
ltc4w_gpio(struct ltc4245_cmd_idx)4\
S_IRUGO, \
(struct  337      4 4338
reg) \
<4 href4"drivehwmon/lstruct                        e="L344" href307  ">data =   "    [] = vice_attribute" class="sref">device_4/a>, \
 386 38e="L.               >)
ltc4w_gpio(struct  387 387e="L.               >)
ltc4w_gpio(struct  342<4a>
(struct gpio_num)4\
S_IR4GO  ="commef="d               e="L344">td""comm7" class="line"e="L344">td""commef="d= vice_attribute" class="sref">device_4/8ef="dri4class="sref">gpio_numdata = td"307  ">data = td">ltc4245_"    "_gpio(struct  346
4* Construct a sensor_dev4ce_at45hwmon/ltc4245.c#L329" id="L329" class="l4tages */<4span>
  ="commef="d               e="L344" href"comm7" class="line"e="L344" href"commef="d= vice_attribute" class="sref">device_4C4245_12V4N);
data =   ">data =   "    "_gpio(struct (struct 3a hre39"L274" class="line"4c4s="line4/a>);
 343        struce="L344">data = name, device_4Cid="L3454ref="drivers/hwmon/ltc4245.c#L45e=dev" class=struct sensor_device_attribute *attri2c_get_clilase * 303}
(struct 3a hre39"L274" class="line"4c9ef="dri4ref="drivers/hwmon/ltc4245.c#L45ef">da,
<10        strucress="line" name="res04" >(struct 3a hre39"L274" class="line"4/a>);
 349 388
  "TAGE" class="sref">LTC4245_GPIO_VOLTAGE(<4      attr>td""comm7" class="line"e="L344">td""commef="=>(struct 3a hre39"L274" class="line"4
<4 href="drivers/hwmon/ltc4245.c463t index];
device_4NSE);4 317        /ef="+code=rendardn307  "ass="comment">/=>(struct 3a hre39"L274" class="line"4 34 3ress="line" name="res04" >(struct 3a hre39"L274" class="line"4/        4 href="drivers/hwmon/ltc4245.c4605" class="li  return  388iweos" c="L31"dri="drextra  hre support,/ef="+codeitos" cla307  "TAGE" class="sref">LTC4245_GPIO_VOLTAGE(<4 9ef="dri4f="drivers/hwmon/ltc42454c#L36469t index];
 *data = device_4>);
attr>);
index];
device_4>);
        struc.c#Lerref="drivers/hwm.c#Lerrcode"               tc4245.c#L304" id="L304" ame="L317"> 317        /ef="+code hre 307  "ass="comment">/=>(struct 3a hre39"L274" class="line"4/a>        struc5td""comm7" class="line"e="L344">td""commef="=>(struct 3a hre39"L274" class="line"4 <<47),        3ress="line" name="res04" >(struct 3a hre39"L274" class="line"4ges */
);
);
(struct (struct 3a hre39"L274" class="line"4g9ef="dri4/a> 34span>
data = name, );
device_4/a>);
sensor_device_attribute *attri2c_get_clilase *device_4/<<4ref="drivers/hwmon/ltc4245.c#L484ef="drivers/struct  303}
(struct 3a hre39"L274" class="line"43 2943     3      href="+code=PA4(1 <&l4; 3),       index];
 *data = 3     3      href="+code=PA4(45_5VOUT45"> 385        struc54n9_in4845.c#L377" id="L377" class="line" name="4f="+code=4n10_input" class="sref">4n10_i489t td""comm7" class="line"e="L344">td""commef="=>(struct 3a hre39"L274" class="line"4rs/hwmon/4tc4245.c#L388" id="L388"4class4"line"  return in41_inpu return );
data = name, )4
device_4" name="L407">#L338" i"> 390307">343"> 3494ef="drivers/struct attr.c#Lget_plate *(struct 3a hre39"L274" class="line"4r 2743 class="l3ne"4name=4L294">#ifdeflass="sref">attrCONFIG_OF245.c#L304" id=CONFIG_OFinpu return PAGE_SIZE4  303}
attrclilass="line" name="clilas    245_update_device 303(struct 3a hre39"L274" class="line"4365 *4Finally,on/ltc4245      4     40);
 294 4945.c#L377" id="L377" class="line" name="43="+code=4c#L298" id="L298" class=4line"499t  388LTC4245_GPIO_VOLTAGE(<5ame="L2995> 299        const <5 href500ef="drivers/">index];
name, index];
 3pevice_attribute" clpde=attr"245_update_devicedata = (struct 3a hre39"L274" class="line"5ass="line5 name="L300"> 300   5    c50 id="L371" class="line" name="L371"> 3715a3s="line5 503t attrCONFIG_OF245.c#L304" id=CONFIG_OFinpu return #L338" i"> 390307">35" cla504t  388LTC4245_GPIO_VOLTAGE(<5a5s="line5 > 2743 class="l3ne"5 href505ef="drivers/">index];
 303 317        /,/               f="+code=SENSOR_DEVICE_ATTR)=name" class="sref">name, PAGE_SIZE5 id="5305" class="li href="+="line" name="L313"> 3true="L303"> 303(struct 3a hre39"L274" class="line"5a7s="line5 inally,on/ltc4245      5f="+c50);
 295ef="+5045.c#L377" id="L377" class="line" name="5a9ef="dri5e#L298" id="L298" class=5ass="5ref">da,
<="line" name="L313"> 3false="L303"> 303(struct 3a hre39"L274" class="line"509" id="L509" class="line" name="L509"> 51line"  return         struce="L344"probe="L303"> 303(struct val = }
name, device_505s="line5a href="drivers/hwmon/lt54245.515ef="drivers/struct attrclilass="line" name="clilas    245_update_device(struct 3a hre39"L274" class="line"506s="line5
sensor_device_attribute *(struct 3a hre39"L274" class="line"507s="line5        if (        strucress="line" name="res04" >(struct 3a hre39"L274" class="line"508ef="dri5  return  518in!03" class="linei2c_check_funcC424ality="L303"> 303name, ((struct 3a hre39"L274" class="line"5E_SIZE" c5ass="sref">PAGE_SIZE5 attrkzalloc245.c#L304" id=kzalloccode" izeof(_device_attribute *(struct 3a hre39"L274" class="line"5s3s="line5f="drivers/hwmon/ltc42455c#L32523t in!03" class="linee *device_5s4s="line5L322"> 322 382(struct 3a hre39"L274" class="line"5E5s="line5wmon/ltc4245.c#L323" id=5L323"52L313" id="L313" classgoto+a>        strucout_kzalloc245.c#L304" id=out_kzalloc04" >(struct 3a hre39"L274" class="line"5E6s="line5group() to make a sysfs 5evice5205" class="li  return (struct  326
5a hre528t (struct 3a hre39"L274" class="line"5E9ef="dri5ef">ltc4245_cmd_idx)5\
 *data = (struct 3a hre39"L274" class="line"5ss="sref"5S_IRUGO, \
        struce *data = data = device_5ne" name=5L329"> 329         330
5a hre532t  388LTC4245_GPIO_VOLTAGE(<5 class="s5ef">ltc4245_cmd_idx)5\
, \
 * 333         2943     3      href="+code=PA5ss_create5"line" name="L334"> 334<5a>
 388LTC4245_GPIO_VOLTAGE(<5s7ef="dri5ef">ltc4245_cmd_idx)5\
attre="L344">data = device_5n8ef="dri5ef">S_IRUGO, \
index];
device_5n9ef="dri5me="L337"> 337      5         strucout_>data = (struct 3a hre39"L274" class="line"5e="L338">5338
reg) \
<5 href541t attrd="L3_tc4(struct 3a hre39"L274" class="line"5/a>, \
index];
 *device_541   5    attrPTR_ERname="L34n1.5ALTPTR_ERncode"               e *(struct 3a hre39"L274" class="line"5/4s="line5"line" name="L342"> 342<5a>
(struct 3a hre39"L274" class="line"5e5s="line5ass="sref">gpio_num)5\
S_IR5GO(struct 3a hre39"L274" class="line"5/8ef="dri5class="sref">gpio_num 346
5* Construct a sensor_dev5ce_at550t data = device_5tages */<5span>
data =  303 *(struct 3a hre39"L274" clas>device_5t1   5N);
);
        strucress="line" name="res04" >(struct 3a hre39"L274" class="line"5"L353"> 353   hwmon/l10        struce="L344"removs>data = device_5c8ef="dri5ref="drivers/hwmon/ltc4255.c#L558=devvice_attribute" class="sref">device_5c9ef="dri5ref="drivers/hwmon/ltc4255.c#L55ef">da,
sensor_device_attribute *attri2c_get_clilase *device_5/a>);
 359 *(struct 3a hre39"L274" class="line"5      data = device_5
<5 href="drivers/hwmon/ltc5245.c563t  303 *(struct 3a hre39"L274" clas>device_5NSE);5 35(struct 3a hre39"L274" class="line"5/        5 href="drivers/hwmon/ltc5245.c5605" c  return device_5 9ef="dri5f="drivers/hwmon/ltc42455c#L36569t  317        /,/0 }"_gpio(struct );
(struct 3a hre39"L274" class="line"5>);
        strucMODULE_DEVICE_TABLEs="line" name="MODULE_DEVICE_TABLEcode"               i2cs="line" name="i2c    ,/               e="L344"ids="line" name="e="L344"id    =>(struct 3a hre39"L274" clas>device_5/a>device_5/SE);57),        388LTC4245_GPIO_VOLTAGE(<5ges */
C4245s="line" name="e="L344">C4245ttr" clvice_attribute" class="sref">device_545_12VOUT5/a>);
device_5465);
 317        /,ice_attribute" class="sref">device_54        5>);
(struct  303attre="L344"probe="L303"> 303(struct attre="L344"removs>data = (struct attre="L344"ids="line" name="e="L344"id    "_gpio(struct (struct 3a hre39"L274" class="line"5/a>);
device_5/<<5ref="drivers/hwmon/ltc4255.c#L584ef="a>        strucmodul _i2c_>C4245s="line" name="modul _i2c_>C4245code"               e="L344">C4245s="line" name="e="L344">C4245ttr"=>(struct 3a hre39"L274" clas>device_53 2943     3      href="+code=PA5(1 <&l5; 3),               strucMODULE_AUTHOname="L34n1.5ALTMODULE_AUTHOncode" ="L317"> 317        /=>(struct 3a hre39"L274" class="line"5(45_5VOUT55"> 385        strucMODULE_DESCRIPTIONs="line" name="MODULE_DESCRIPTIONcode" ="L317"> 317        /=>(struct 3a hre39"L274" class="line"5(        5in9_input" class="sref">5n9_in5845.c#a>        strucMODULE_LICENSEs="line" name="MODULE_LICENSEcode" ="L317"> 317        /=>(struct 3a hre39"L274" class="line"5(9ef="dri5n10_input" class="sref">5n10_i589t 


T"droriginal LXR software by ="drstruct 3ahttp://sourceforge.net/projects/lxd2>LXR 388unitycode, ="is experi8 exd.claux.no kindly hostedTby struct 3ahttp://www.redpill-clapro.no="Redpill Llapro AScode, provid39 of Llauxlss="ult"driand operaC424s ser