linux/drivers/hwmon/gl518sm.c
<<
>>
Prefs
   1/*
   2 * gl518sm.c - Part of lm_sensors, Linux kernel modules for hardware
   3 *             monitoring
   4 * Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
   5 * Kyosti Malkki <kmalkki@cc.hut.fi>
   6 * Copyright (C) 2004 Hong-Gunn Chew <hglinux@gunnet.org> and
   7 * Jean Delvare <khali@linux-fr.org>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2 of the License, or
  12 * (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22 *
  23 * Ported to Linux 2.6 by Hong-Gunn Chew with the help of Jean Delvare
  24 * and advice of Greg Kroah-Hartman.
  25 *
  26 * Notes about the port:
  27 * Release 0x00 of the GL518SM chipset doesn't support reading of in0,
  28 * in1 nor in2. The original driver had an ugly workaround to get them
  29 * anyway (changing limits and watching alarms trigger and wear off).
  30 * We did not keep that part of the original driver in the Linux 2.6
  31 * version, since it was making the driver significantly more complex
  32 * with no real benefit.
  33 */
  34
  35#include <linux/module.h>
  36#include <linux/init.h>
  37#include <linux/slab.h>
  38#include <linux/jiffies.h>
  39#include <linux/i2c.h>
  40#include <linux/hwmon.h>
  41#include <linux/hwmon-sysfs.h>
  42#include <linux/err.h>
  43#include <linux/mutex.h>
  44#include <linux/sysfs.h>
  45
  46/* Addresses to scan */
  47static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
  48
  49/* Insmod parameters */
  50I2C_CLIENT_INSMOD_2(gl518sm_r00, gl518sm_r80);
  51
  52/* Many GL518 constants specified below */
  53
  54/* The GL518 registers */
  55#define GL518_REG_CHIP_ID       0x00
  56#define GL518_REG_REVISION      0x01
  57#define GL518_REG_VENDOR_ID     0x02
  58#define GL518_REG_CONF          0x03
  59#define GL518_REG_TEMP_IN       0x04
  60#define GL518_REG_TEMP_MAX      0x05
  61#define GL518_REG_TEMP_HYST     0x06
  62#define GL518_REG_FAN_COUNT     0x07
  63#define GL518_REG_FAN_LIMIT     0x08
  64#define GL518_REG_VIN1_LIMIT    0x09
  65#define GL518_REG_VIN2_LIMIT    0x0a
  66#define GL518_REG_VIN3_LIMIT    0x0b
  67#define GL518_REG_VDD_LIMIT     0x0c
  68#define GL518_REG_VIN3          0x0d
  69#define GL518_REG_MISC          0x0f
  70#define GL518_REG_ALARM         0x10
  71#define GL518_REG_MASK          0x11
  72#define GL518_REG_INT           0x12
  73#define GL518_REG_VIN2          0x13
  74#define GL518_REG_VIN1          0x14
  75#define GL518_REG_VDD           0x15
  76
  77
  78/*
  79 * Conversions. Rounding and limit checking is only done on the TO_REG
  80 * variants. Note that you should be a bit careful with which arguments
  81 * these macros are called: arguments may be evaluated more than once.
  82 * Fixing this is just not worth it.
  83 */
  84
  85#define RAW_FROM_REG(val)       val
  86
  87#define BOOL_FROM_REG(val)      ((val)?0:1)
  88#define BOOL_TO_REG(val)        ((val)?0:1)
  89
  90#define TEMP_TO_REG(val)        (SENSORS_LIMIT(((((val)<0? \
  91                                (val)-500:(val)+500)/1000)+119),0,255))
  92#define TEMP_FROM_REG(val)      (((val) - 119) * 1000)
  93
  94static inline u8 FAN_TO_REG(long rpm, int div)
  95{
  96        long rpmdiv;
  97        if (rpm == 0)
  98                return 0;
  99        rpmdiv = SENSORS_LIMIT(rpm, 1, 960000) * div;
 100        return SENSORS_LIMIT((480000 + rpmdiv / 2) / rpmdiv, 1, 255);
 101}
 102#define FAN_FROM_REG(val,div)   ((val)==0 ? 0 : (480000/((val)*(div))))
 103
 104#define IN_TO_REG(val)          (SENSORS_LIMIT((((val)+9)/19),0,255))
 105#define IN_FROM_REG(val)        ((val)*19)
 106
 107#define VDD_TO_REG(val)         (SENSORS_LIMIT((((val)*4+47)/95),0,255))
 108#define VDD_FROM_REG(val)       (((val)*95+2)/4)
 109
 110#define DIV_FROM_REG(val)       (1 << (val))
 111
 112#define BEEP_MASK_TO_REG(val)   ((val) & 0x7f & data->alarm_mask)
 113#define BEEP_MASK_FROM_REG(val) ((val) & 0x7f)
 114
 115/* Each client has this additional data */
 116struct gl518_data {
 117        struct device *hwmon_dev;
 118        enum chips type;
 119
 120        struct mutex update_lock;
 121        char valid;             /* !=0 if following fields are valid */
 122        unsigned long last_updated;     /* In jiffies */
 123
 124        u8 voltage_in[4];       /* Register values; [0] = VDD */
 125        u8 voltage_min[4];      /* Register values; [0] = VDD */
 126        u8 voltage_max[4];      /* Register values; [0] = VDD */
 127        u8 fan_in[2];
 128        u8 fan_min[2];
 129        u8 fan_div[2];          /* Register encoding, shifted right */
 130        u8 fan_auto1;           /* Boolean */
 131        u8 temp_in;             /* Register values */
 132        u8 temp_max;            /* Register values */
 133        u8 temp_hyst;           /* Register values */
 134        u8 alarms;              /* Register value */
 135        u8 alarm_mask;
 136        u8 beep_mask;           /* Register value */
 137        u8 beep_enable;         /* Boolean */
 138};
 139
 140static int gl518_probe(struct i2c_client *client,
 141                       const struct i2c_device_id *id);
 142static int gl518_detect(struct i2c_client *client, int kind,
 143                        struct i2c_board_info *info);
 144static void gl518_init_client(struct i2c_client *client);
 145static int gl518_remove(struct i2c_client *client);
 146static int gl518_read_value(struct i2c_client *client, u8 reg);
 147static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value);
 148static struct gl518_data *gl518_update_device(struct device *dev);
 149
 150static const struct i2c_device_id gl518_id[] = {
 151        { "gl518sm", 0 },
 152        { }
 153};
 154MODULE_DEVICE_TABLE(i2c, gl518_id);
 155
 156/* This is the driver that will be inserted */
 157static struct i2c_driver gl518_driver = {
 158        .class          = I2C_CLASS_HWMON,
 159        .driver = {
 160                .name   = "gl518sm",
 161        },
 162        .probe          = gl518_probe,
 163        .remove         = gl518_remove,
 164        .id_table       = gl518_id,
 165        .detect         = gl518_detect,
 166        .address_data   = &addr_data,
 167};
 168
 169/*
 170 * Sysfs stuff
 171 */
 172
 173#define show(type, suffix, value)                                       \
 174static ssize_t show_##suffix(struct device *dev, struct device_attribute *attr, char *buf)              \
 175{                                                                       \
 176        struct gl518_data *data = gl518_update_device(dev);             \
 177        return sprintf(buf, "%d\n", type##_FROM_REG(data->value));      \
 178}
 179
 180show(TEMP, temp_input1, temp_in);
 181show(TEMP, temp_max1, temp_max);
 182show(TEMP, temp_hyst1, temp_hyst);
 183show(BOOL, fan_auto1, fan_auto1);
 184show(VDD, in_input0, voltage_in[0]);
 185show(IN, in_input1, voltage_in[1]);
 186show(IN, in_input2, voltage_in[2]);
 187show(IN, in_input3, voltage_in[3]);
 188show(VDD, in_min0, voltage_min[0]);
 189show(IN, in_min1, voltage_min[1]);
 190show(IN, in_min2, voltage_min[2]);
 191show(IN, in_min3, voltage_min[3]);
 192show(VDD, in_max0, voltage_max[0]);
 193show(IN, in_max1, voltage_max[1]);
 194show(IN, in_max2, voltage_max[2]);
 195show(IN, in_max3, voltage_max[3]);
 196show(RAW, alarms, alarms);
 197show(BOOL, beep_enable, beep_enable);
 198show(BEEP_MASK, beep_mask, beep_mask);
 199
 200static ssize_t show_fan_input(struct device *dev,
 201                              struct device_attribute *attr, char *buf)
 202{
 203        int nr = to_sensor_dev_attr(attr)->index;
 204        struct gl518_data *data = gl518_update_device(dev);
 205        return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_in[nr],
 206                                        DIV_FROM_REG(data->fan_div[nr])));
 207}
 208
 209static ssize_t show_fan_min(struct device *dev,
 210                            struct device_attribute *attr, char *buf)
 211{
 212        int nr = to_sensor_dev_attr(attr)->index;
 213        struct gl518_data *data = gl518_update_device(dev);
 214        return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
 215                                        DIV_FROM_REG(data->fan_div[nr])));
 216}
 217
 218static ssize_t show_fan_div(struct device *dev,
 219                            struct device_attribute *attr, char *buf)
 220{
 221        int nr = to_sensor_dev_attr(attr)->index;
 222        struct gl518_data *data = gl518_update_device(dev);
 223        return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
 224}
 225
 226#define set(type, suffix, value, reg)                                   \
 227static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
 228        size_t count)                                                   \
 229{                                                                       \
 230        struct i2c_client *client = to_i2c_client(dev);                 \
 231        struct gl518_data *data = i2c_get_clientdata(client);           \
 232        long val = simple_strtol(buf, NULL, 10);                        \
 233                                                                        \
 234        mutex_lock(&data->update_lock);                                 \
 235        data->value = type##_TO_REG(val);                               \
 236        gl518_write_value(client, reg, data->value);                    \
 237        mutex_unlock(&data->update_lock);                               \
 238        return count;                                                   \
 239}
 240
 241#define set_bits(type, suffix, value, reg, mask, shift)                 \
 242static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
 243        size_t count)                                                   \
 244{                                                                       \
 245        struct i2c_client *client = to_i2c_client(dev);                 \
 246        struct gl518_data *data = i2c_get_clientdata(client);           \
 247        int regvalue;                                                   \
 248        unsigned long val = simple_strtoul(buf, NULL, 10);              \
 249                                                                        \
 250        mutex_lock(&data->update_lock);                                 \
 251        regvalue = gl518_read_value(client, reg);                       \
 252        data->value = type##_TO_REG(val);                               \
 253        regvalue = (regvalue & ~mask) | (data->value << shift);         \
 254        gl518_write_value(client, reg, regvalue);                       \
 255        mutex_unlock(&data->update_lock);                               \
 256        return count;                                                   \
 257}
 258
 259#define set_low(type, suffix, value, reg)                               \
 260        set_bits(type, suffix, value, reg, 0x00ff, 0)
 261#define set_high(type, suffix, value, reg)                              \
 262        set_bits(type, suffix, value, reg, 0xff00, 8)
 263
 264set(TEMP, temp_max1, temp_max, GL518_REG_TEMP_MAX);
 265set(TEMP, temp_hyst1, temp_hyst, GL518_REG_TEMP_HYST);
 266set_bits(BOOL, fan_auto1, fan_auto1, GL518_REG_MISC, 0x08, 3);
 267set_low(VDD, in_min0, voltage_min[0], GL518_REG_VDD_LIMIT);
 268set_low(IN, in_min1, voltage_min[1], GL518_REG_VIN1_LIMIT);
 269set_low(IN, in_min2, voltage_min[2], GL518_REG_VIN2_LIMIT);
 270set_low(IN, in_min3, voltage_min[3], GL518_REG_VIN3_LIMIT);
 271set_high(VDD, in_max0, voltage_max[0], GL518_REG_VDD_LIMIT);
 272set_high(IN, in_max1, voltage_max[1], GL518_REG_VIN1_LIMIT);
 273set_high(IN, in_max2, voltage_max[2], GL518_REG_VIN2_LIMIT);
 274set_high(IN, in_max3, voltage_max[3], GL518_REG_VIN3_LIMIT);
 275set_bits(BOOL, beep_enable, beep_enable, GL518_REG_CONF, 0x04, 2);
 276set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM);
 277
 278static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 279                           const char *buf, size_t count)
 280{
 281        struct i2c_client *client = to_i2c_client(dev);
 282        struct gl518_data *data = i2c_get_clientdata(client);
 283        int nr = to_sensor_dev_attr(attr)->index;
 284        int regvalue;
 285        unsigned long val = simple_strtoul(buf, NULL, 10);
 286
 287        mutex_lock(&data->update_lock);
 288        regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT);
 289        data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
 290        regvalue = (regvalue & (0xff << (8 * nr)))
 291                 | (data->fan_min[nr] << (8 * (1 - nr)));
 292        gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue);
 293
 294        data->beep_mask = gl518_read_value(client, GL518_REG_ALARM);
 295        if (data->fan_min[nr] == 0)
 296                data->alarm_mask &= ~(0x20 << nr);
 297        else
 298                data->alarm_mask |= (0x20 << nr);
 299        data->beep_mask &= data->alarm_mask;
 300        gl518_write_value(client, GL518_REG_ALARM, data->beep_mask);
 301
 302        mutex_unlock(&data->update_lock);
 303        return count;
 304}
 305
 306static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 307                           const char *buf, size_t count)
 308{
 309        struct i2c_client *client = to_i2c_client(dev);
 310        struct gl518_data *data = i2c_get_clientdata(client);
 311        int nr = to_sensor_dev_attr(attr)->index;
 312        int regvalue;
 313        unsigned long val = simple_strtoul(buf, NULL, 10);
 314
 315        switch (val) {
 316        case 1: val = 0; break;
 317        case 2: val = 1; break;
 318        case 4: val = 2; break;
 319        case 8: val = 3; break;
 320        default:
 321                dev_err(dev, "Invalid fan clock divider %lu, choose one "
 322                        "of 1, 2, 4 or 8\n", val);
 323                return -EINVAL;
 324        }
 325
 326        mutex_lock(&data->update_lock);
 327        regvalue = gl518_read_value(client, GL518_REG_MISC);
 328        data->fan_div[nr] = val;
 329        regvalue = (regvalue & ~(0xc0 >> (2 * nr)))
 330                 | (data->fan_div[nr] << (6 - 2 * nr));
 331        gl518_write_value(client, GL518_REG_MISC, regvalue);
 332        mutex_unlock(&data->update_lock);
 333        return count;
 334}
 335
 336static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
 337static DEVICE_ATTR(temp1_max, S_IWUSR|S_IRUGO, show_temp_max1, set_temp_max1);
 338static DEVICE_ATTR(temp1_max_hyst, S_IWUSR|S_IRUGO,
 339        show_temp_hyst1, set_temp_hyst1);
 340static DEVICE_ATTR(fan1_auto, S_IWUSR|S_IRUGO, show_fan_auto1, set_fan_auto1);
 341static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
 342static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
 343static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR|S_IRUGO,
 344        show_fan_min, set_fan_min, 0);
 345static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR|S_IRUGO,
 346        show_fan_min, set_fan_min, 1);
 347static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR|S_IRUGO,
 348        show_fan_div, set_fan_div, 0);
 349static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR|S_IRUGO,
 350        show_fan_div, set_fan_div, 1);
 351static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL);
 352static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL);
 353static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL);
 354static DEVICE_ATTR(in3_input, S_IRUGO, show_in_input3, NULL);
 355static DEVICE_ATTR(in0_min, S_IWUSR|S_IRUGO, show_in_min0, set_in_min0);
 356static DEVICE_ATTR(in1_min, S_IWUSR|S_IRUGO, show_in_min1, set_in_min1);
 357static DEVICE_ATTR(in2_min, S_IWUSR|S_IRUGO, show_in_min2, set_in_min2);
 358static DEVICE_ATTR(in3_min, S_IWUSR|S_IRUGO, show_in_min3, set_in_min3);
 359static DEVICE_ATTR(in0_max, S_IWUSR|S_IRUGO, show_in_max0, set_in_max0);
 360static DEVICE_ATTR(in1_max, S_IWUSR|S_IRUGO, show_in_max1, set_in_max1);
 361static DEVICE_ATTR(in2_max, S_IWUSR|S_IRUGO, show_in_max2, set_in_max2);
 362static DEVICE_ATTR(in3_max, S_IWUSR|S_IRUGO, show_in_max3, set_in_max3);
 363static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 364static DEVICE_ATTR(beep_enable, S_IWUSR|S_IRUGO,
 365        show_beep_enable, set_beep_enable);
 366static DEVICE_ATTR(beep_mask, S_IWUSR|S_IRUGO,
 367        show_beep_mask, set_beep_mask);
 368
 369static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
 370                          char *buf)
 371{
 372        int bitnr = to_sensor_dev_attr(attr)->index;
 373        struct gl518_data *data = gl518_update_device(dev);
 374        return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
 375}
 376
 377static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
 378static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
 379static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
 380static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
 381static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
 382static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 5);
 383static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 6);
 384
 385static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
 386                          char *buf)
 387{
 388        int bitnr = to_sensor_dev_attr(attr)->index;
 389        struct gl518_data *data = gl518_update_device(dev);
 390        return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1);
 391}
 392
 393static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
 394                        const char *buf, size_t count)
 395{
 396        struct i2c_client *client = to_i2c_client(dev);
 397        struct gl518_data *data = i2c_get_clientdata(client);
 398        int bitnr = to_sensor_dev_attr(attr)->index;
 399        unsigned long bit;
 400
 401        bit = simple_strtoul(buf, NULL, 10);
 402        if (bit & ~1)
 403                return -EINVAL;
 404
 405        mutex_lock(&data->update_lock);
 406        data->beep_mask = gl518_read_value(client, GL518_REG_ALARM);
 407        if (bit)
 408                data->beep_mask |= (1 << bitnr);
 409        else
 410                data->beep_mask &= ~(1 << bitnr);
 411        gl518_write_value(client, GL518_REG_ALARM, data->beep_mask);
 412        mutex_unlock(&data->update_lock);
 413        return count;
 414}
 415
 416static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 0);
 417static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 1);
 418static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 2);
 419static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 3);
 420static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 4);
 421static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 5);
 422static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 6);
 423
 424static struct attribute *gl518_attributes[] = {
 425        &dev_attr_in3_input.attr,
 426        &dev_attr_in0_min.attr,
 427        &dev_attr_in1_min.attr,
 428        &dev_attr_in2_min.attr,
 429        &dev_attr_in3_min.attr,
 430        &dev_attr_in0_max.attr,
 431        &dev_attr_in1_max.attr,
 432        &dev_attr_in2_max.attr,
 433        &dev_attr_in3_max.attr,
 434        &sensor_dev_attr_in0_alarm.dev_attr.attr,
 435        &sensor_dev_attr_in1_alarm.dev_attr.attr,
 436        &sensor_dev_attr_in2_alarm.dev_attr.attr,
 437        &sensor_dev_attr_in3_alarm.dev_attr.attr,
 438        &sensor_dev_attr_in0_beep.dev_attr.attr,
 439        &sensor_dev_attr_in1_beep.dev_attr.attr,
 440        &sensor_dev_attr_in2_beep.dev_attr.attr,
 441        &sensor_dev_attr_in3_beep.dev_attr.attr,
 442
 443        &dev_attr_fan1_auto.attr,
 444        &sensor_dev_attr_fan1_input.dev_attr.attr,
 445        &sensor_dev_attr_fan2_input.dev_attr.attr,
 446        &sensor_dev_attr_fan1_min.dev_attr.attr,
 447        &sensor_dev_attr_fan2_min.dev_attr.attr,
 448        &sensor_dev_attr_fan1_div.dev_attr.attr,
 449        &sensor_dev_attr_fan2_div.dev_attr.attr,
 450        &sensor_dev_attr_fan1_alarm.dev_attr.attr,
 451        &sensor_dev_attr_fan2_alarm.dev_attr.attr,
 452        &sensor_dev_attr_fan1_beep.dev_attr.attr,
 453        &sensor_dev_attr_fan2_beep.dev_attr.attr,
 454
 455        &dev_attr_temp1_input.attr,
 456        &dev_attr_temp1_max.attr,
 457        &dev_attr_temp1_max_hyst.attr,
 458        &sensor_dev_attr_temp1_alarm.dev_attr.attr,
 459        &sensor_dev_attr_temp1_beep.dev_attr.attr,
 460
 461        &dev_attr_alarms.attr,
 462        &dev_attr_beep_enable.attr,
 463        &dev_attr_beep_mask.attr,
 464        NULL
 465};
 466
 467static const struct attribute_group gl518_group = {
 468        .attrs = gl518_attributes,
 469};
 470
 471static struct attribute *gl518_attributes_r80[] = {
 472        &dev_attr_in0_input.attr,
 473        &dev_attr_in1_input.attr,
 474        &dev_attr_in2_input.attr,
 475        NULL
 476};
 477
 478static const struct attribute_group gl518_group_r80 = {
 479        .attrs = gl518_attributes_r80,
 480};
 481
 482/*
 483 * Real code
 484 */
 485
 486/* Return 0 if detection is successful, -ENODEV otherwise */
 487static int gl518_detect(struct i2c_client *client, int kind,
 488                        struct i2c_board_info *info)
 489{
 490        struct i2c_adapter *adapter = client->adapter;
 491        int i;
 492
 493        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
 494                                     I2C_FUNC_SMBUS_WORD_DATA))
 495                return -ENODEV;
 496
 497        /* Now, we do the remaining detection. */
 498
 499        if (kind < 0) {
 500                if ((gl518_read_value(client, GL518_REG_CHIP_ID) != 0x80)
 501                 || (gl518_read_value(client, GL518_REG_CONF) & 0x80))
 502                        return -ENODEV;
 503        }
 504
 505        /* Determine the chip type. */
 506        if (kind <= 0) {
 507                i = gl518_read_value(client, GL518_REG_REVISION);
 508                if (i == 0x00) {
 509                        kind = gl518sm_r00;
 510                } else if (i == 0x80) {
 511                        kind = gl518sm_r80;
 512                } else {
 513                        if (kind <= 0)
 514                                dev_info(&adapter->dev,
 515                                    "Ignoring 'force' parameter for unknown "
 516                                    "chip at adapter %d, address 0x%02x\n",
 517                                    i2c_adapter_id(adapter), client->addr);
 518                        return -ENODEV;
 519                }
 520        }
 521
 522        strlcpy(info->type, "gl518sm", I2C_NAME_SIZE);
 523
 524        return 0;
 525}
 526
 527static int gl518_probe(struct i2c_client *client,
 528                       const struct i2c_device_id *id)
 529{
 530        struct gl518_data *data;
 531        int err, revision;
 532
 533        data = kzalloc(sizeof(struct gl518_data), GFP_KERNEL);
 534        if (!data) {
 535                err = -ENOMEM;
 536                goto exit;
 537        }
 538
 539        i2c_set_clientdata(client, data);
 540        revision = gl518_read_value(client, GL518_REG_REVISION);
 541        data->type = revision == 0x80 ? gl518sm_r80 : gl518sm_r00;
 542        mutex_init(&data->update_lock);
 543
 544        /* Initialize the GL518SM chip */
 545        data->alarm_mask = 0xff;
 546        gl518_init_client(client);
 547
 548        /* Register sysfs hooks */
 549        if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group)))
 550                goto exit_free;
 551        if (data->type == gl518sm_r80)
 552                if ((err = sysfs_create_group(&client->dev.kobj,
 553                                              &gl518_group_r80)))
 554                        goto exit_remove_files;
 555
 556        data->hwmon_dev = hwmon_device_register(&client->dev);
 557        if (IS_ERR(data->hwmon_dev)) {
 558                err = PTR_ERR(data->hwmon_dev);
 559                goto exit_remove_files;
 560        }
 561
 562        return 0;
 563
 564exit_remove_files:
 565        sysfs_remove_group(&client->dev.kobj, &gl518_group);
 566        if (data->type == gl518sm_r80)
 567                sysfs_remove_group(&client->dev.kobj, &gl518_group_r80);
 568exit_free:
 569        kfree(data);
 570exit:
 571        return err;
 572}
 573
 574
 575/* Called when we have found a new GL518SM.
 576   Note that we preserve D4:NoFan2 and D2:beep_enable. */
 577static void gl518_init_client(struct i2c_client *client)
 578{
 579        /* Make sure we leave D7:Reset untouched */
 580        u8 regvalue = gl518_read_value(client, GL518_REG_CONF) & 0x7f;
 581
 582        /* Comparator mode (D3=0), standby mode (D6=0) */
 583        gl518_write_value(client, GL518_REG_CONF, (regvalue &= 0x37));
 584
 585        /* Never interrupts */
 586        gl518_write_value(client, GL518_REG_MASK, 0x00);
 587
 588        /* Clear status register (D5=1), start (D6=1) */
 589        gl518_write_value(client, GL518_REG_CONF, 0x20 | regvalue);
 590        gl518_write_value(client, GL518_REG_CONF, 0x40 | regvalue);
 591}
 592
 593static int gl518_remove(struct i2c_client *client)
 594{
 595        struct gl518_data *data = i2c_get_clientdata(client);
 596
 597        hwmon_device_unregister(data->hwmon_dev);
 598        sysfs_remove_group(&client->dev.kobj, &gl518_group);
 599        if (data->type == gl518sm_r80)
 600                sysfs_remove_group(&client->dev.kobj, &gl518_group_r80);
 601
 602        kfree(data);
 603        return 0;
 604}
 605
 606/* Registers 0x07 to 0x0c are word-sized, others are byte-sized
 607   GL518 uses a high-byte first convention, which is exactly opposite to
 608   the SMBus standard. */
 609static int gl518_read_value(struct i2c_client *client, u8 reg)
 610{
 611        if ((reg >= 0x07) && (reg <= 0x0c))
 612                return swab16(i2c_smbus_read_word_data(client, reg));
 613        else
 614                return i2c_smbus_read_byte_data(client, reg);
 615}
 616
 617static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value)
 618{
 619        if ((reg >= 0x07) && (reg <= 0x0c))
 620                return i2c_smbus_write_word_data(client, reg, swab16(value));
 621        else
 622                return i2c_smbus_write_byte_data(client, reg, value);
 623}
 624
 625static struct gl518_data *gl518_update_device(struct device *dev)
 626{
 627        struct i2c_client *client = to_i2c_client(dev);
 628        struct gl518_data *data = i2c_get_clientdata(client);
 629        int val;
 630
 631        mutex_lock(&data->update_lock);
 632
 633        if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
 634            || !data->valid) {
 635                dev_dbg(&client->dev, "Starting gl518 update\n");
 636
 637                data->alarms = gl518_read_value(client, GL518_REG_INT);
 638                data->beep_mask = gl518_read_value(client, GL518_REG_ALARM);
 639
 640                val = gl518_read_value(client, GL518_REG_VDD_LIMIT);
 641                data->voltage_min[0] = val & 0xff;
 642                data->voltage_max[0] = (val >> 8) & 0xff;
 643                val = gl518_read_value(client, GL518_REG_VIN1_LIMIT);
 644                data->voltage_min[1] = val & 0xff;
 645                data->voltage_max[1] = (val >> 8) & 0xff;
 646                val = gl518_read_value(client, GL518_REG_VIN2_LIMIT);
 647                data->voltage_min[2] = val & 0xff;
 648                data->voltage_max[2] = (val >> 8) & 0xff;
 649                val = gl518_read_value(client, GL518_REG_VIN3_LIMIT);
 650                data->voltage_min[3] = val & 0xff;
 651                data->voltage_max[3] = (val >> 8) & 0xff;
 652
 653                val = gl518_read_value(client, GL518_REG_FAN_COUNT);
 654                data->fan_in[0] = (val >> 8) & 0xff;
 655                data->fan_in[1] = val & 0xff;
 656
 657                val = gl518_read_value(client, GL518_REG_FAN_LIMIT);
 658                data->fan_min[0] = (val >> 8) & 0xff;
 659                data->fan_min[1] = val & 0xff;
 660
 661                data->temp_in = gl518_read_value(client, GL518_REG_TEMP_IN);
 662                data->temp_max =
 663                    gl518_read_value(client, GL518_REG_TEMP_MAX);
 664                data->temp_hyst =
 665                    gl518_read_value(client, GL518_REG_TEMP_HYST);
 666
 667                val = gl518_read_value(client, GL518_REG_MISC);
 668                data->fan_div[0] = (val >> 6) & 0x03;
 669                data->fan_div[1] = (val >> 4) & 0x03;
 670                data->fan_auto1  = (val >> 3) & 0x01;
 671
 672                data->alarms &= data->alarm_mask;
 673
 674                val = gl518_read_value(client, GL518_REG_CONF);
 675                data->beep_enable = (val >> 2) & 1;
 676
 677                if (data->type != gl518sm_r00) {
 678                        data->voltage_in[0] =
 679                            gl518_read_value(client, GL518_REG_VDD);
 680                        data->voltage_in[1] =
 681                            gl518_read_value(client, GL518_REG_VIN1);
 682                        data->voltage_in[2] =
 683                            gl518_read_value(client, GL518_REG_VIN2);
 684                }
 685                data->voltage_in[3] =
 686                    gl518_read_value(client, GL518_REG_VIN3);
 687
 688                data->last_updated = jiffies;
 689                data->valid = 1;
 690        }
 691
 692        mutex_unlock(&data->update_lock);
 693
 694        return data;
 695}
 696
 697static int __init sensors_gl518sm_init(void)
 698{
 699        return i2c_add_driver(&gl518_driver);
 700}
 701
 702static void __exit sensors_gl518sm_exit(void)
 703{
 704        i2c_del_driver(&gl518_driver);
 705}
 706
 707MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
 708        "Kyosti Malkki <kmalkki@cc.hut.fi> and "
 709        "Hong-Gunn Chew <hglinux@gunnet.org>");
 710MODULE_DESCRIPTION("GL518SM driver");
 711MODULE_LICENSE("GPL");
 712
 713module_init(sensors_gl518sm_init);
 714module_exit(sensors_gl518sm_exit);
 715