linux/drivers/hwmon/smsc47m192.c
<<
>>
Prefs
   1/*
   2 * smsc47m192.c - Support for hardware monitoring block of
   3 *                SMSC LPC47M192 and compatible Super I/O chips
   4 *
   5 * Copyright (C) 2006  Hartmut Rick <linux@rick.claranet.de>
   6 *
   7 * Derived from lm78.c and other chip drivers.
   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
  24#include <linux/module.h>
  25#include <linux/init.h>
  26#include <linux/slab.h>
  27#include <linux/jiffies.h>
  28#include <linux/i2c.h>
  29#include <linux/hwmon.h>
  30#include <linux/hwmon-sysfs.h>
  31#include <linux/hwmon-vid.h>
  32#include <linux/err.h>
  33#include <linux/sysfs.h>
  34#include <linux/mutex.h>
  35
  36/* Addresses to scan */
  37static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
  38
  39/* SMSC47M192 registers */
  40#define SMSC47M192_REG_IN(nr)           ((nr) < 6 ? (0x20 + (nr)) : \
  41                                        (0x50 + (nr) - 6))
  42#define SMSC47M192_REG_IN_MAX(nr)       ((nr) < 6 ? (0x2b + (nr) * 2) : \
  43                                        (0x54 + (((nr) - 6) * 2)))
  44#define SMSC47M192_REG_IN_MIN(nr)       ((nr) < 6 ? (0x2c + (nr) * 2) : \
  45                                        (0x55 + (((nr) - 6) * 2)))
  46static u8 SMSC47M192_REG_TEMP[3] =      { 0x27, 0x26, 0x52 };
  47static u8 SMSC47M192_REG_TEMP_MAX[3] =  { 0x39, 0x37, 0x58 };
  48static u8 SMSC47M192_REG_TEMP_MIN[3] =  { 0x3A, 0x38, 0x59 };
  49#define SMSC47M192_REG_TEMP_OFFSET(nr)  ((nr) == 2 ? 0x1e : 0x1f)
  50#define SMSC47M192_REG_ALARM1           0x41
  51#define SMSC47M192_REG_ALARM2           0x42
  52#define SMSC47M192_REG_VID              0x47
  53#define SMSC47M192_REG_VID4             0x49
  54#define SMSC47M192_REG_CONFIG           0x40
  55#define SMSC47M192_REG_SFR              0x4f
  56#define SMSC47M192_REG_COMPANY_ID       0x3e
  57#define SMSC47M192_REG_VERSION          0x3f
  58
  59/* generalised scaling with integer rounding */
  60static inline int SCALE(long val, int mul, int div)
  61{
  62        if (val < 0)
  63                return (val * mul - div / 2) / div;
  64        else
  65                return (val * mul + div / 2) / div;
  66}
  67
  68/* Conversions */
  69
  70/* smsc47m192 internally scales voltage measurements */
  71static const u16 nom_mv[] = { 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 };
  72
  73static inline unsigned int IN_FROM_REG(u8 reg, int n)
  74{
  75        return SCALE(reg, nom_mv[n], 192);
  76}
  77
  78static inline u8 IN_TO_REG(unsigned long val, int n)
  79{
  80        return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255);
  81}
  82
  83/*
  84 * TEMP: 0.001 degC units (-128C to +127C)
  85 * REG: 1C/bit, two's complement
  86 */
  87static inline s8 TEMP_TO_REG(int val)
  88{
  89        return SENSORS_LIMIT(SCALE(val, 1, 1000), -128000, 127000);
  90}
  91
  92static inline int TEMP_FROM_REG(s8 val)
  93{
  94        return val * 1000;
  95}
  96
  97struct smsc47m192_data {
  98        struct device *hwmon_dev;
  99        struct mutex update_lock;
 100        char valid;             /* !=0 if following fields are valid */
 101        unsigned long last_updated;     /* In jiffies */
 102
 103        u8 in[8];               /* Register value */
 104        u8 in_max[8];           /* Register value */
 105        u8 in_min[8];           /* Register value */
 106        s8 temp[3];             /* Register value */
 107        s8 temp_max[3];         /* Register value */
 108        s8 temp_min[3];         /* Register value */
 109        s8 temp_offset[3];      /* Register value */
 110        u16 alarms;             /* Register encoding, combined */
 111        u8 vid;                 /* Register encoding, combined */
 112        u8 vrm;
 113};
 114
 115static int smsc47m192_probe(struct i2c_client *client,
 116                            const struct i2c_device_id *id);
 117static int smsc47m192_detect(struct i2c_client *client,
 118                             struct i2c_board_info *info);
 119static int smsc47m192_remove(struct i2c_client *client);
 120static struct smsc47m192_data *smsc47m192_update_device(struct device *dev);
 121
 122static const struct i2c_device_id smsc47m192_id[] = {
 123        { "smsc47m192", 0 },
 124        { }
 125};
 126MODULE_DEVICE_TABLE(i2c, smsc47m192_id);
 127
 128static struct i2c_driver smsc47m192_driver = {
 129        .class          = I2C_CLASS_HWMON,
 130        .driver = {
 131                .name   = "smsc47m192",
 132        },
 133        .probe          = smsc47m192_probe,
 134        .remove         = smsc47m192_remove,
 135        .id_table       = smsc47m192_id,
 136        .detect         = smsc47m192_detect,
 137        .address_list   = normal_i2c,
 138};
 139
 140/* Voltages */
 141static ssize_t show_in(struct device *dev, struct device_attribute *attr,
 142                char *buf)
 143{
 144        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 145        int nr = sensor_attr->index;
 146        struct smsc47m192_data *data = smsc47m192_update_device(dev);
 147        return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr));
 148}
 149
 150static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
 151                char *buf)
 152{
 153        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 154        int nr = sensor_attr->index;
 155        struct smsc47m192_data *data = smsc47m192_update_device(dev);
 156        return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr));
 157}
 158
 159static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
 160                char *buf)
 161{
 162        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 163        int nr = sensor_attr->index;
 164        struct smsc47m192_data *data = smsc47m192_update_device(dev);
 165        return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr));
 166}
 167
 168static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
 169                const char *buf, size_t count)
 170{
 171        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 172        int nr = sensor_attr->index;
 173        struct i2c_client *client = to_i2c_client(dev);
 174        struct smsc47m192_data *data = i2c_get_clientdata(client);
 175        unsigned long val;
 176        int err;
 177
 178        err = kstrtoul(buf, 10, &val);
 179        if (err)
 180                return err;
 181
 182        mutex_lock(&data->update_lock);
 183        data->in_min[nr] = IN_TO_REG(val, nr);
 184        i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr),
 185                                                        data->in_min[nr]);
 186        mutex_unlock(&data->update_lock);
 187        return count;
 188}
 189
 190static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
 191                const char *buf, size_t count)
 192{
 193        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 194        int nr = sensor_attr->index;
 195        struct i2c_client *client = to_i2c_client(dev);
 196        struct smsc47m192_data *data = i2c_get_clientdata(client);
 197        unsigned long val;
 198        int err;
 199
 200        err = kstrtoul(buf, 10, &val);
 201        if (err)
 202                return err;
 203
 204        mutex_lock(&data->update_lock);
 205        data->in_max[nr] = IN_TO_REG(val, nr);
 206        i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr),
 207                                                        data->in_max[nr]);
 208        mutex_unlock(&data->update_lock);
 209        return count;
 210}
 211
 212#define show_in_offset(offset)                                  \
 213static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,          \
 214                show_in, NULL, offset);                         \
 215static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,  \
 216                show_in_min, set_in_min, offset);               \
 217static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,  \
 218                show_in_max, set_in_max, offset);
 219
 220show_in_offset(0)
 221show_in_offset(1)
 222show_in_offset(2)
 223show_in_offset(3)
 224show_in_offset(4)
 225show_in_offset(5)
 226show_in_offset(6)
 227show_in_offset(7)
 228
 229/* Temperatures */
 230static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
 231                char *buf)
 232{
 233        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 234        int nr = sensor_attr->index;
 235        struct smsc47m192_data *data = smsc47m192_update_device(dev);
 236        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
 237}
 238
 239static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
 240                char *buf)
 241{
 242        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 243        int nr = sensor_attr->index;
 244        struct smsc47m192_data *data = smsc47m192_update_device(dev);
 245        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
 246}
 247
 248static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
 249                char *buf)
 250{
 251        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 252        int nr = sensor_attr->index;
 253        struct smsc47m192_data *data = smsc47m192_update_device(dev);
 254        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
 255}
 256
 257static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 258                const char *buf, size_t count)
 259{
 260        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 261        int nr = sensor_attr->index;
 262        struct i2c_client *client = to_i2c_client(dev);
 263        struct smsc47m192_data *data = i2c_get_clientdata(client);
 264        long val;
 265        int err;
 266
 267        err = kstrtol(buf, 10, &val);
 268        if (err)
 269                return err;
 270
 271        mutex_lock(&data->update_lock);
 272        data->temp_min[nr] = TEMP_TO_REG(val);
 273        i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr],
 274                                                data->temp_min[nr]);
 275        mutex_unlock(&data->update_lock);
 276        return count;
 277}
 278
 279static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 280                const char *buf, size_t count)
 281{
 282        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 283        int nr = sensor_attr->index;
 284        struct i2c_client *client = to_i2c_client(dev);
 285        struct smsc47m192_data *data = i2c_get_clientdata(client);
 286        long val;
 287        int err;
 288
 289        err = kstrtol(buf, 10, &val);
 290        if (err)
 291                return err;
 292
 293        mutex_lock(&data->update_lock);
 294        data->temp_max[nr] = TEMP_TO_REG(val);
 295        i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr],
 296                                                data->temp_max[nr]);
 297        mutex_unlock(&data->update_lock);
 298        return count;
 299}
 300
 301static ssize_t show_temp_offset(struct device *dev, struct device_attribute
 302                *attr, char *buf)
 303{
 304        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 305        int nr = sensor_attr->index;
 306        struct smsc47m192_data *data = smsc47m192_update_device(dev);
 307        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
 308}
 309
 310static ssize_t set_temp_offset(struct device *dev, struct device_attribute
 311                *attr, const char *buf, size_t count)
 312{
 313        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 314        int nr = sensor_attr->index;
 315        struct i2c_client *client = to_i2c_client(dev);
 316        struct smsc47m192_data *data = i2c_get_clientdata(client);
 317        u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
 318        long val;
 319        int err;
 320
 321        err = kstrtol(buf, 10, &val);
 322        if (err)
 323                return err;
 324
 325        mutex_lock(&data->update_lock);
 326        data->temp_offset[nr] = TEMP_TO_REG(val);
 327        if (nr > 1)
 328                i2c_smbus_write_byte_data(client,
 329                        SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]);
 330        else if (data->temp_offset[nr] != 0) {
 331                /*
 332                 * offset[0] and offset[1] share the same register,
 333                 * SFR bit 4 activates offset[0]
 334                 */
 335                i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR,
 336                                        (sfr & 0xef) | (nr == 0 ? 0x10 : 0));
 337                data->temp_offset[1-nr] = 0;
 338                i2c_smbus_write_byte_data(client,
 339                        SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]);
 340        } else if ((sfr & 0x10) == (nr == 0 ? 0x10 : 0))
 341                i2c_smbus_write_byte_data(client,
 342                                        SMSC47M192_REG_TEMP_OFFSET(nr), 0);
 343        mutex_unlock(&data->update_lock);
 344        return count;
 345}
 346
 347#define show_temp_index(index)                                          \
 348static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO,                 \
 349                show_temp, NULL, index-1);                              \
 350static SENSOR_DEVICE_ATTR(temp##index##_min, S_IRUGO | S_IWUSR,         \
 351                show_temp_min, set_temp_min, index-1);                  \
 352static SENSOR_DEVICE_ATTR(temp##index##_max, S_IRUGO | S_IWUSR,         \
 353                show_temp_max, set_temp_max, index-1);                  \
 354static SENSOR_DEVICE_ATTR(temp##index##_offset, S_IRUGO | S_IWUSR,      \
 355                show_temp_offset, set_temp_offset, index-1);
 356
 357show_temp_index(1)
 358show_temp_index(2)
 359show_temp_index(3)
 360
 361/* VID */
 362static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
 363                char *buf)
 364{
 365        struct smsc47m192_data *data = smsc47m192_update_device(dev);
 366        return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
 367}
 368static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 369
 370static ssize_t show_vrm(struct device *dev, struct device_attribute *attr,
 371                char *buf)
 372{
 373        struct smsc47m192_data *data = dev_get_drvdata(dev);
 374        return sprintf(buf, "%d\n", data->vrm);
 375}
 376
 377static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
 378                const char *buf, size_t count)
 379{
 380        struct smsc47m192_data *data = dev_get_drvdata(dev);
 381        unsigned long val;
 382        int err;
 383
 384        err = kstrtoul(buf, 10, &val);
 385        if (err)
 386                return err;
 387
 388        data->vrm = val;
 389        return count;
 390}
 391static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
 392
 393/* Alarms */
 394static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
 395                char *buf)
 396{
 397        struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 398        int nr = sensor_attr->index;
 399        struct smsc47m192_data *data = smsc47m192_update_device(dev);
 400        return sprintf(buf, "%u\n", (data->alarms & nr) ? 1 : 0);
 401}
 402
 403static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010);
 404static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020);
 405static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040);
 406static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 0x4000);
 407static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 0x8000);
 408static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001);
 409static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002);
 410static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004);
 411static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 0x0008);
 412static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 0x0100);
 413static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200);
 414static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400);
 415static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800);
 416
 417static struct attribute *smsc47m192_attributes[] = {
 418        &sensor_dev_attr_in0_input.dev_attr.attr,
 419        &sensor_dev_attr_in0_min.dev_attr.attr,
 420        &sensor_dev_attr_in0_max.dev_attr.attr,
 421        &sensor_dev_attr_in0_alarm.dev_attr.attr,
 422        &sensor_dev_attr_in1_input.dev_attr.attr,
 423        &sensor_dev_attr_in1_min.dev_attr.attr,
 424        &sensor_dev_attr_in1_max.dev_attr.attr,
 425        &sensor_dev_attr_in1_alarm.dev_attr.attr,
 426        &sensor_dev_attr_in2_input.dev_attr.attr,
 427        &sensor_dev_attr_in2_min.dev_attr.attr,
 428        &sensor_dev_attr_in2_max.dev_attr.attr,
 429        &sensor_dev_attr_in2_alarm.dev_attr.attr,
 430        &sensor_dev_attr_in3_input.dev_attr.attr,
 431        &sensor_dev_attr_in3_min.dev_attr.attr,
 432        &sensor_dev_attr_in3_max.dev_attr.attr,
 433        &sensor_dev_attr_in3_alarm.dev_attr.attr,
 434        &sensor_dev_attr_in5_input.dev_attr.attr,
 435        &sensor_dev_attr_in5_min.dev_attr.attr,
 436        &sensor_dev_attr_in5_max.dev_attr.attr,
 437        &sensor_dev_attr_in5_alarm.dev_attr.attr,
 438        &sensor_dev_attr_in6_input.dev_attr.attr,
 439        &sensor_dev_attr_in6_min.dev_attr.attr,
 440        &sensor_dev_attr_in6_max.dev_attr.attr,
 441        &sensor_dev_attr_in6_alarm.dev_attr.attr,
 442        &sensor_dev_attr_in7_input.dev_attr.attr,
 443        &sensor_dev_attr_in7_min.dev_attr.attr,
 444        &sensor_dev_attr_in7_max.dev_attr.attr,
 445        &sensor_dev_attr_in7_alarm.dev_attr.attr,
 446
 447        &sensor_dev_attr_temp1_input.dev_attr.attr,
 448        &sensor_dev_attr_temp1_max.dev_attr.attr,
 449        &sensor_dev_attr_temp1_min.dev_attr.attr,
 450        &sensor_dev_attr_temp1_offset.dev_attr.attr,
 451        &sensor_dev_attr_temp1_alarm.dev_attr.attr,
 452        &sensor_dev_attr_temp2_input.dev_attr.attr,
 453        &sensor_dev_attr_temp2_max.dev_attr.attr,
 454        &sensor_dev_attr_temp2_min.dev_attr.attr,
 455        &sensor_dev_attr_temp2_offset.dev_attr.attr,
 456        &sensor_dev_attr_temp2_alarm.dev_attr.attr,
 457        &sensor_dev_attr_temp2_fault.dev_attr.attr,
 458        &sensor_dev_attr_temp3_input.dev_attr.attr,
 459        &sensor_dev_attr_temp3_max.dev_attr.attr,
 460        &sensor_dev_attr_temp3_min.dev_attr.attr,
 461        &sensor_dev_attr_temp3_offset.dev_attr.attr,
 462        &sensor_dev_attr_temp3_alarm.dev_attr.attr,
 463        &sensor_dev_attr_temp3_fault.dev_attr.attr,
 464
 465        &dev_attr_cpu0_vid.attr,
 466        &dev_attr_vrm.attr,
 467        NULL
 468};
 469
 470static const struct attribute_group smsc47m192_group = {
 471        .attrs = smsc47m192_attributes,
 472};
 473
 474static struct attribute *smsc47m192_attributes_in4[] = {
 475        &sensor_dev_attr_in4_input.dev_attr.attr,
 476        &sensor_dev_attr_in4_min.dev_attr.attr,
 477        &sensor_dev_attr_in4_max.dev_attr.attr,
 478        &sensor_dev_attr_in4_alarm.dev_attr.attr,
 479        NULL
 480};
 481
 482static const struct attribute_group smsc47m192_group_in4 = {
 483        .attrs = smsc47m192_attributes_in4,
 484};
 485
 486static void smsc47m192_init_client(struct i2c_client *client)
 487{
 488        int i;
 489        u8 config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
 490        u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
 491
 492        /* select cycle mode (pause 1 sec between updates) */
 493        i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR,
 494                                                (sfr & 0xfd) | 0x02);
 495        if (!(config & 0x01)) {
 496                /* initialize alarm limits */
 497                for (i = 0; i < 8; i++) {
 498                        i2c_smbus_write_byte_data(client,
 499                                SMSC47M192_REG_IN_MIN(i), 0);
 500                        i2c_smbus_write_byte_data(client,
 501                                SMSC47M192_REG_IN_MAX(i), 0xff);
 502                }
 503                for (i = 0; i < 3; i++) {
 504                        i2c_smbus_write_byte_data(client,
 505                                SMSC47M192_REG_TEMP_MIN[i], 0x80);
 506                        i2c_smbus_write_byte_data(client,
 507                                SMSC47M192_REG_TEMP_MAX[i], 0x7f);
 508                }
 509
 510                /* start monitoring */
 511                i2c_smbus_write_byte_data(client, SMSC47M192_REG_CONFIG,
 512                                                (config & 0xf7) | 0x01);
 513        }
 514}
 515
 516/* Return 0 if detection is successful, -ENODEV otherwise */
 517static int smsc47m192_detect(struct i2c_client *client,
 518                             struct i2c_board_info *info)
 519{
 520        struct i2c_adapter *adapter = client->adapter;
 521        int version;
 522
 523        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 524                return -ENODEV;
 525
 526        /* Detection criteria from sensors_detect script */
 527        version = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VERSION);
 528        if (i2c_smbus_read_byte_data(client,
 529                                SMSC47M192_REG_COMPANY_ID) == 0x55
 530         && (version & 0xf0) == 0x20
 531         && (i2c_smbus_read_byte_data(client,
 532                                SMSC47M192_REG_VID) & 0x70) == 0x00
 533         && (i2c_smbus_read_byte_data(client,
 534                                SMSC47M192_REG_VID4) & 0xfe) == 0x80) {
 535                dev_info(&adapter->dev,
 536                         "found SMSC47M192 or compatible, "
 537                         "version 2, stepping A%d\n", version & 0x0f);
 538        } else {
 539                dev_dbg(&adapter->dev,
 540                        "SMSC47M192 detection failed at 0x%02x\n",
 541                        client->addr);
 542                return -ENODEV;
 543        }
 544
 545        strlcpy(info->type, "smsc47m192", I2C_NAME_SIZE);
 546
 547        return 0;
 548}
 549
 550static int smsc47m192_probe(struct i2c_client *client,
 551                            const struct i2c_device_id *id)
 552{
 553        struct smsc47m192_data *data;
 554        int config;
 555        int err;
 556
 557        data = devm_kzalloc(&client->dev, sizeof(struct smsc47m192_data),
 558                            GFP_KERNEL);
 559        if (!data)
 560                return -ENOMEM;
 561
 562        i2c_set_clientdata(client, data);
 563        data->vrm = vid_which_vrm();
 564        mutex_init(&data->update_lock);
 565
 566        /* Initialize the SMSC47M192 chip */
 567        smsc47m192_init_client(client);
 568
 569        /* Register sysfs hooks */
 570        err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group);
 571        if (err)
 572                return err;
 573
 574        /* Pin 110 is either in4 (+12V) or VID4 */
 575        config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
 576        if (!(config & 0x20)) {
 577                err = sysfs_create_group(&client->dev.kobj,
 578                                         &smsc47m192_group_in4);
 579                if (err)
 580                        goto exit_remove_files;
 581        }
 582
 583        data->hwmon_dev = hwmon_device_register(&client->dev);
 584        if (IS_ERR(data->hwmon_dev)) {
 585                err = PTR_ERR(data->hwmon_dev);
 586                goto exit_remove_files;
 587        }
 588
 589        return 0;
 590
 591exit_remove_files:
 592        sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
 593        sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
 594        return err;
 595}
 596
 597static int smsc47m192_remove(struct i2c_client *client)
 598{
 599        struct smsc47m192_data *data = i2c_get_clientdata(client);
 600
 601        hwmon_device_unregister(data->hwmon_dev);
 602        sysfs_remove_group(&client->dev.kobj, &smsc47m192_group);
 603        sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4);
 604
 605        return 0;
 606}
 607
 608static struct smsc47m192_data *smsc47m192_update_device(struct device *dev)
 609{
 610        struct i2c_client *client = to_i2c_client(dev);
 611        struct smsc47m192_data *data = i2c_get_clientdata(client);
 612        int i, config;
 613
 614        mutex_lock(&data->update_lock);
 615
 616        if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
 617         || !data->valid) {
 618                u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
 619
 620                dev_dbg(&client->dev, "Starting smsc47m192 update\n");
 621
 622                for (i = 0; i <= 7; i++) {
 623                        data->in[i] = i2c_smbus_read_byte_data(client,
 624                                                SMSC47M192_REG_IN(i));
 625                        data->in_min[i] = i2c_smbus_read_byte_data(client,
 626                                                SMSC47M192_REG_IN_MIN(i));
 627                        data->in_max[i] = i2c_smbus_read_byte_data(client,
 628                                                SMSC47M192_REG_IN_MAX(i));
 629                }
 630                for (i = 0; i < 3; i++) {
 631                        data->temp[i] = i2c_smbus_read_byte_data(client,
 632                                                SMSC47M192_REG_TEMP[i]);
 633                        data->temp_max[i] = i2c_smbus_read_byte_data(client,
 634                                                SMSC47M192_REG_TEMP_MAX[i]);
 635                        data->temp_min[i] = i2c_smbus_read_byte_data(client,
 636                                                SMSC47M192_REG_TEMP_MIN[i]);
 637                }
 638                for (i = 1; i < 3; i++)
 639                        data->temp_offset[i] = i2c_smbus_read_byte_data(client,
 640                                                SMSC47M192_REG_TEMP_OFFSET(i));
 641                /*
 642                 * first offset is temp_offset[0] if SFR bit 4 is set,
 643                 * temp_offset[1] otherwise
 644                 */
 645                if (sfr & 0x10) {
 646                        data->temp_offset[0] = data->temp_offset[1];
 647                        data->temp_offset[1] = 0;
 648                } else
 649                        data->temp_offset[0] = 0;
 650
 651                data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID)
 652                            & 0x0f;
 653                config = i2c_smbus_read_byte_data(client,
 654                                                  SMSC47M192_REG_CONFIG);
 655                if (config & 0x20)
 656                        data->vid |= (i2c_smbus_read_byte_data(client,
 657                                        SMSC47M192_REG_VID4) & 0x01) << 4;
 658                data->alarms = i2c_smbus_read_byte_data(client,
 659                                                SMSC47M192_REG_ALARM1) |
 660                               (i2c_smbus_read_byte_data(client,
 661                                                SMSC47M192_REG_ALARM2) << 8);
 662
 663                data->last_updated = jiffies;
 664                data->valid = 1;
 665        }
 666
 667        mutex_unlock(&data->update_lock);
 668
 669        return data;
 670}
 671
 672module_i2c_driver(smsc47m192_driver);
 673
 674MODULE_AUTHOR("Hartmut Rick <linux@rick.claranet.de>");
 675MODULE_DESCRIPTION("SMSC47M192 driver");
 676MODULE_LICENSE("GPL");
 677
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.