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