linux/drivers/hwmon/emc6w201.c
<<
>>
Prefs
   1/*
   2 * emc6w201.c - Hardware monitoring driver for the SMSC EMC6W201
   3 * Copyright (C) 2011  Jean Delvare <khali@linux-fr.org>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18 */
  19
  20#include <linux/module.h>
  21#include <linux/init.h>
  22#include <linux/slab.h>
  23#include <linux/jiffies.h>
  24#include <linux/i2c.h>
  25#include <linux/hwmon.h>
  26#include <linux/hwmon-sysfs.h>
  27#include <linux/err.h>
  28#include <linux/mutex.h>
  29
  30/*
  31 * Addresses to scan
  32 */
  33
  34static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
  35
  36/*
  37 * The EMC6W201 registers
  38 */
  39
  40#define EMC6W201_REG_IN(nr)             (0x20 + (nr))
  41#define EMC6W201_REG_TEMP(nr)           (0x26 + (nr))
  42#define EMC6W201_REG_FAN(nr)            (0x2C + (nr) * 2)
  43#define EMC6W201_REG_COMPANY            0x3E
  44#define EMC6W201_REG_VERSTEP            0x3F
  45#define EMC6W201_REG_CONFIG             0x40
  46#define EMC6W201_REG_IN_LOW(nr)         (0x4A + (nr) * 2)
  47#define EMC6W201_REG_IN_HIGH(nr)        (0x4B + (nr) * 2)
  48#define EMC6W201_REG_TEMP_LOW(nr)       (0x56 + (nr) * 2)
  49#define EMC6W201_REG_TEMP_HIGH(nr)      (0x57 + (nr) * 2)
  50#define EMC6W201_REG_FAN_MIN(nr)        (0x62 + (nr) * 2)
  51
  52enum { input, min, max } subfeature;
  53
  54/*
  55 * Per-device data
  56 */
  57
  58struct emc6w201_data {
  59        struct device *hwmon_dev;
  60        struct mutex update_lock;
  61        char valid; /* zero until following fields are valid */
  62        unsigned long last_updated; /* in jiffies */
  63
  64        /* registers values */
  65        u8 in[3][6];
  66        s8 temp[3][6];
  67        u16 fan[2][5];
  68};
  69
  70/*
  71 * Combine LSB and MSB registers in a single value
  72 * Locking: must be called with data->update_lock held
  73 */
  74static u16 emc6w201_read16(struct i2c_client *client, u8 reg)
  75{
  76        int lsb, msb;
  77
  78        lsb = i2c_smbus_read_byte_data(client, reg);
  79        msb = i2c_smbus_read_byte_data(client, reg + 1);
  80        if (unlikely(lsb < 0 || msb < 0)) {
  81                dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
  82                        16, "read", reg);
  83                return 0xFFFF;  /* Arbitrary value */
  84        }
  85
  86        return (msb << 8) | lsb;
  87}
  88
  89/*
  90 * Write 16-bit value to LSB and MSB registers
  91 * Locking: must be called with data->update_lock held
  92 */
  93static int emc6w201_write16(struct i2c_client *client, u8 reg, u16 val)
  94{
  95        int err;
  96
  97        err = i2c_smbus_write_byte_data(client, reg, val & 0xff);
  98        if (likely(!err))
  99                err = i2c_smbus_write_byte_data(client, reg + 1, val >> 8);
 100        if (unlikely(err < 0))
 101                dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
 102                        16, "write", reg);
 103
 104        return err;
 105}
 106
 107/* Read 8-bit value from register */
 108static u8 emc6w201_read8(struct i2c_client *client, u8 reg)
 109{
 110        int val;
 111
 112        val = i2c_smbus_read_byte_data(client, reg);
 113        if (unlikely(val < 0)) {
 114                dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
 115                        8, "read", reg);
 116                return 0x00;    /* Arbitrary value */
 117        }
 118
 119        return val;
 120}
 121
 122/* Write 8-bit value to register */
 123static int emc6w201_write8(struct i2c_client *client, u8 reg, u8 val)
 124{
 125        int err;
 126
 127        err = i2c_smbus_write_byte_data(client, reg, val);
 128        if (unlikely(err < 0))
 129                dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
 130                        8, "write", reg);
 131
 132        return err;
 133}
 134
 135static struct emc6w201_data *emc6w201_update_device(struct device *dev)
 136{
 137        struct i2c_client *client = to_i2c_client(dev);
 138        struct emc6w201_data *data = i2c_get_clientdata(client);
 139        int nr;
 140
 141        mutex_lock(&data->update_lock);
 142
 143        if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
 144                for (nr = 0; nr < 6; nr++) {
 145                        data->in[input][nr] =
 146                                emc6w201_read8(client,
 147                                                EMC6W201_REG_IN(nr));
 148                        data->in[min][nr] =
 149                                emc6w201_read8(client,
 150                                                EMC6W201_REG_IN_LOW(nr));
 151                        data->in[max][nr] =
 152                                emc6w201_read8(client,
 153                                                EMC6W201_REG_IN_HIGH(nr));
 154                }
 155
 156                for (nr = 0; nr < 6; nr++) {
 157                        data->temp[input][nr] =
 158                                emc6w201_read8(client,
 159                                                EMC6W201_REG_TEMP(nr));
 160                        data->temp[min][nr] =
 161                                emc6w201_read8(client,
 162                                                EMC6W201_REG_TEMP_LOW(nr));
 163                        data->temp[max][nr] =
 164                                emc6w201_read8(client,
 165                                                EMC6W201_REG_TEMP_HIGH(nr));
 166                }
 167
 168                for (nr = 0; nr < 5; nr++) {
 169                        data->fan[input][nr] =
 170                                emc6w201_read16(client,
 171                                                EMC6W201_REG_FAN(nr));
 172                        data->fan[min][nr] =
 173                                emc6w201_read16(client,
 174                                                EMC6W201_REG_FAN_MIN(nr));
 175                }
 176
 177                data->last_updated = jiffies;
 178                data->valid = 1;
 179        }
 180
 181        mutex_unlock(&data->update_lock);
 182
 183        return data;
 184}
 185
 186/*
 187 * Sysfs callback functions
 188 */
 189
 190static const s16 nominal_mv[6] = { 2500, 1500, 3300, 5000, 1500, 1500 };
 191
 192static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
 193        char *buf)
 194{
 195        struct emc6w201_data *data = emc6w201_update_device(dev);
 196        int sf = to_sensor_dev_attr_2(devattr)->index;
 197        int nr = to_sensor_dev_attr_2(devattr)->nr;
 198
 199        return sprintf(buf, "%u\n",
 200                       (unsigned)data->in[sf][nr] * nominal_mv[nr] / 0xC0);
 201}
 202
 203static ssize_t set_in(struct device *dev, struct device_attribute *devattr,
 204                      const char *buf, size_t count)
 205{
 206        struct i2c_client *client = to_i2c_client(dev);
 207        struct emc6w201_data *data = i2c_get_clientdata(client);
 208        int sf = to_sensor_dev_attr_2(devattr)->index;
 209        int nr = to_sensor_dev_attr_2(devattr)->nr;
 210        int err;
 211        long val;
 212        u8 reg;
 213
 214        err = kstrtol(buf, 10, &val);
 215        if (err < 0)
 216                return err;
 217
 218        val = DIV_ROUND_CLOSEST(val * 0xC0, nominal_mv[nr]);
 219        reg = (sf == min) ? EMC6W201_REG_IN_LOW(nr)
 220                          : EMC6W201_REG_IN_HIGH(nr);
 221
 222        mutex_lock(&data->update_lock);
 223        data->in[sf][nr] = SENSORS_LIMIT(val, 0, 255);
 224        err = emc6w201_write8(client, reg, data->in[sf][nr]);
 225        mutex_unlock(&data->update_lock);
 226
 227        return err < 0 ? err : count;
 228}
 229
 230static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
 231        char *buf)
 232{
 233        struct emc6w201_data *data = emc6w201_update_device(dev);
 234        int sf = to_sensor_dev_attr_2(devattr)->index;
 235        int nr = to_sensor_dev_attr_2(devattr)->nr;
 236
 237        return sprintf(buf, "%d\n", (int)data->temp[sf][nr] * 1000);
 238}
 239
 240static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
 241                        const char *buf, size_t count)
 242{
 243        struct i2c_client *client = to_i2c_client(dev);
 244        struct emc6w201_data *data = i2c_get_clientdata(client);
 245        int sf = to_sensor_dev_attr_2(devattr)->index;
 246        int nr = to_sensor_dev_attr_2(devattr)->nr;
 247        int err;
 248        long val;
 249        u8 reg;
 250
 251        err = kstrtol(buf, 10, &val);
 252        if (err < 0)
 253                return err;
 254
 255        val /= 1000;
 256        reg = (sf == min) ? EMC6W201_REG_TEMP_LOW(nr)
 257                          : EMC6W201_REG_TEMP_HIGH(nr);
 258
 259        mutex_lock(&data->update_lock);
 260        data->temp[sf][nr] = SENSORS_LIMIT(val, -127, 128);
 261        err = emc6w201_write8(client, reg, data->temp[sf][nr]);
 262        mutex_unlock(&data->update_lock);
 263
 264        return err < 0 ? err : count;
 265}
 266
 267static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
 268        char *buf)
 269{
 270        struct emc6w201_data *data = emc6w201_update_device(dev);
 271        int sf = to_sensor_dev_attr_2(devattr)->index;
 272        int nr = to_sensor_dev_attr_2(devattr)->nr;
 273        unsigned rpm;
 274
 275        if (data->fan[sf][nr] == 0 || data->fan[sf][nr] == 0xFFFF)
 276                rpm = 0;
 277        else
 278                rpm = 5400000U / data->fan[sf][nr];
 279
 280        return sprintf(buf, "%u\n", rpm);
 281}
 282
 283static ssize_t set_fan(struct device *dev, struct device_attribute *devattr,
 284                       const char *buf, size_t count)
 285{
 286        struct i2c_client *client = to_i2c_client(dev);
 287        struct emc6w201_data *data = i2c_get_clientdata(client);
 288        int sf = to_sensor_dev_attr_2(devattr)->index;
 289        int nr = to_sensor_dev_attr_2(devattr)->nr;
 290        int err;
 291        unsigned long val;
 292
 293        err = kstrtoul(buf, 10, &val);
 294        if (err < 0)
 295                return err;
 296
 297        if (val == 0) {
 298                val = 0xFFFF;
 299        } else {
 300                val = DIV_ROUND_CLOSEST(5400000U, val);
 301                val = SENSORS_LIMIT(val, 0, 0xFFFE);
 302        }
 303
 304        mutex_lock(&data->update_lock);
 305        data->fan[sf][nr] = val;
 306        err = emc6w201_write16(client, EMC6W201_REG_FAN_MIN(nr),
 307                               data->fan[sf][nr]);
 308        mutex_unlock(&data->update_lock);
 309
 310        return err < 0 ? err : count;
 311}
 312
 313static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, input);
 314static SENSOR_DEVICE_ATTR_2(in0_min, S_IRUGO | S_IWUSR, show_in, set_in,
 315                            0, min);
 316static SENSOR_DEVICE_ATTR_2(in0_max, S_IRUGO | S_IWUSR, show_in, set_in,
 317                            0, max);
 318static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 1, input);
 319static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_in, set_in,
 320                            1, min);
 321static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_in, set_in,
 322                            1, max);
 323static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 2, input);
 324static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_in, set_in,
 325                            2, min);
 326static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_in, set_in,
 327                            2, max);
 328static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 3, input);
 329static SENSOR_DEVICE_ATTR_2(in3_min, S_IRUGO | S_IWUSR, show_in, set_in,
 330                            3, min);
 331static SENSOR_DEVICE_ATTR_2(in3_max, S_IRUGO | S_IWUSR, show_in, set_in,
 332                            3, max);
 333static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 4, input);
 334static SENSOR_DEVICE_ATTR_2(in4_min, S_IRUGO | S_IWUSR, show_in, set_in,
 335                            4, min);
 336static SENSOR_DEVICE_ATTR_2(in4_max, S_IRUGO | S_IWUSR, show_in, set_in,
 337                            4, max);
 338static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 5, input);
 339static SENSOR_DEVICE_ATTR_2(in5_min, S_IRUGO | S_IWUSR, show_in, set_in,
 340                            5, min);
 341static SENSOR_DEVICE_ATTR_2(in5_max, S_IRUGO | S_IWUSR, show_in, set_in,
 342                            5, max);
 343
 344static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, input);
 345static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
 346                            0, min);
 347static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
 348                            0, max);
 349static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, input);
 350static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
 351                            1, min);
 352static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
 353                            1, max);
 354static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, input);
 355static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
 356                            2, min);
 357static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
 358                            2, max);
 359static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, input);
 360static SENSOR_DEVICE_ATTR_2(temp4_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
 361                            3, min);
 362static SENSOR_DEVICE_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
 363                            3, max);
 364static SENSOR_DEVICE_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, input);
 365static SENSOR_DEVICE_ATTR_2(temp5_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
 366                            4, min);
 367static SENSOR_DEVICE_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
 368                            4, max);
 369static SENSOR_DEVICE_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, input);
 370static SENSOR_DEVICE_ATTR_2(temp6_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
 371                            5, min);
 372static SENSOR_DEVICE_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
 373                            5, max);
 374
 375static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, input);
 376static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
 377                            0, min);
 378static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 1, input);
 379static SENSOR_DEVICE_ATTR_2(fan2_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
 380                            1, min);
 381static SENSOR_DEVICE_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 2, input);
 382static SENSOR_DEVICE_ATTR_2(fan3_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
 383                            2, min);
 384static SENSOR_DEVICE_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 3, input);
 385static SENSOR_DEVICE_ATTR_2(fan4_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
 386                            3, min);
 387static SENSOR_DEVICE_ATTR_2(fan5_input, S_IRUGO, show_fan, NULL, 4, input);
 388static SENSOR_DEVICE_ATTR_2(fan5_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
 389                            4, min);
 390
 391static struct attribute *emc6w201_attributes[] = {
 392        &sensor_dev_attr_in0_input.dev_attr.attr,
 393        &sensor_dev_attr_in0_min.dev_attr.attr,
 394        &sensor_dev_attr_in0_max.dev_attr.attr,
 395        &sensor_dev_attr_in1_input.dev_attr.attr,
 396        &sensor_dev_attr_in1_min.dev_attr.attr,
 397        &sensor_dev_attr_in1_max.dev_attr.attr,
 398        &sensor_dev_attr_in2_input.dev_attr.attr,
 399        &sensor_dev_attr_in2_min.dev_attr.attr,
 400        &sensor_dev_attr_in2_max.dev_attr.attr,
 401        &sensor_dev_attr_in3_input.dev_attr.attr,
 402        &sensor_dev_attr_in3_min.dev_attr.attr,
 403        &sensor_dev_attr_in3_max.dev_attr.attr,
 404        &sensor_dev_attr_in4_input.dev_attr.attr,
 405        &sensor_dev_attr_in4_min.dev_attr.attr,
 406        &sensor_dev_attr_in4_max.dev_attr.attr,
 407        &sensor_dev_attr_in5_input.dev_attr.attr,
 408        &sensor_dev_attr_in5_min.dev_attr.attr,
 409        &sensor_dev_attr_in5_max.dev_attr.attr,
 410
 411        &sensor_dev_attr_temp1_input.dev_attr.attr,
 412        &sensor_dev_attr_temp1_min.dev_attr.attr,
 413        &sensor_dev_attr_temp1_max.dev_attr.attr,
 414        &sensor_dev_attr_temp2_input.dev_attr.attr,
 415        &sensor_dev_attr_temp2_min.dev_attr.attr,
 416        &sensor_dev_attr_temp2_max.dev_attr.attr,
 417        &sensor_dev_attr_temp3_input.dev_attr.attr,
 418        &sensor_dev_attr_temp3_min.dev_attr.attr,
 419        &sensor_dev_attr_temp3_max.dev_attr.attr,
 420        &sensor_dev_attr_temp4_input.dev_attr.attr,
 421        &sensor_dev_attr_temp4_min.dev_attr.attr,
 422        &sensor_dev_attr_temp4_max.dev_attr.attr,
 423        &sensor_dev_attr_temp5_input.dev_attr.attr,
 424        &sensor_dev_attr_temp5_min.dev_attr.attr,
 425        &sensor_dev_attr_temp5_max.dev_attr.attr,
 426        &sensor_dev_attr_temp6_input.dev_attr.attr,
 427        &sensor_dev_attr_temp6_min.dev_attr.attr,
 428        &sensor_dev_attr_temp6_max.dev_attr.attr,
 429
 430        &sensor_dev_attr_fan1_input.dev_attr.attr,
 431        &sensor_dev_attr_fan1_min.dev_attr.attr,
 432        &sensor_dev_attr_fan2_input.dev_attr.attr,
 433        &sensor_dev_attr_fan2_min.dev_attr.attr,
 434        &sensor_dev_attr_fan3_input.dev_attr.attr,
 435        &sensor_dev_attr_fan3_min.dev_attr.attr,
 436        &sensor_dev_attr_fan4_input.dev_attr.attr,
 437        &sensor_dev_attr_fan4_min.dev_attr.attr,
 438        &sensor_dev_attr_fan5_input.dev_attr.attr,
 439        &sensor_dev_attr_fan5_min.dev_attr.attr,
 440        NULL
 441};
 442
 443static const struct attribute_group emc6w201_group = {
 444        .attrs = emc6w201_attributes,
 445};
 446
 447/*
 448 * Driver interface
 449 */
 450
 451/* Return 0 if detection is successful, -ENODEV otherwise */
 452static int emc6w201_detect(struct i2c_client *client,
 453                           struct i2c_board_info *info)
 454{
 455        struct i2c_adapter *adapter = client->adapter;
 456        int company, verstep, config;
 457
 458        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 459                return -ENODEV;
 460
 461        /* Identification */
 462        company = i2c_smbus_read_byte_data(client, EMC6W201_REG_COMPANY);
 463        if (company != 0x5C)
 464                return -ENODEV;
 465        verstep = i2c_smbus_read_byte_data(client, EMC6W201_REG_VERSTEP);
 466        if (verstep < 0 || (verstep & 0xF0) != 0xB0)
 467                return -ENODEV;
 468        if ((verstep & 0x0F) > 2) {
 469                dev_dbg(&client->dev, "Unknwown EMC6W201 stepping %d\n",
 470                        verstep & 0x0F);
 471                return -ENODEV;
 472        }
 473
 474        /* Check configuration */
 475        config = i2c_smbus_read_byte_data(client, EMC6W201_REG_CONFIG);
 476        if (config < 0 || (config & 0xF4) != 0x04)
 477                return -ENODEV;
 478        if (!(config & 0x01)) {
 479                dev_err(&client->dev, "Monitoring not enabled\n");
 480                return -ENODEV;
 481        }
 482
 483        strlcpy(info->type, "emc6w201", I2C_NAME_SIZE);
 484
 485        return 0;
 486}
 487
 488static int emc6w201_probe(struct i2c_client *client,
 489                          const struct i2c_device_id *id)
 490{
 491        struct emc6w201_data *data;
 492        int err;
 493
 494        data = devm_kzalloc(&client->dev, sizeof(struct emc6w201_data),
 495                            GFP_KERNEL);
 496        if (!data)
 497                return -ENOMEM;
 498
 499        i2c_set_clientdata(client, data);
 500        mutex_init(&data->update_lock);
 501
 502        /* Create sysfs attribute */
 503        err = sysfs_create_group(&client->dev.kobj, &emc6w201_group);
 504        if (err)
 505                return err;
 506
 507        /* Expose as a hwmon device */
 508        data->hwmon_dev = hwmon_device_register(&client->dev);
 509        if (IS_ERR(data->hwmon_dev)) {
 510                err = PTR_ERR(data->hwmon_dev);
 511                goto exit_remove;
 512        }
 513
 514        return 0;
 515
 516 exit_remove:
 517        sysfs_remove_group(&client->dev.kobj, &emc6w201_group);
 518        return err;
 519}
 520
 521static int emc6w201_remove(struct i2c_client *client)
 522{
 523        struct emc6w201_data *data = i2c_get_clientdata(client);
 524
 525        hwmon_device_unregister(data->hwmon_dev);
 526        sysfs_remove_group(&client->dev.kobj, &emc6w201_group);
 527
 528        return 0;
 529}
 530
 531static const struct i2c_device_id emc6w201_id[] = {
 532        { "emc6w201", 0 },
 533        { }
 534};
 535MODULE_DEVICE_TABLE(i2c, emc6w201_id);
 536
 537static struct i2c_driver emc6w201_driver = {
 538        .class          = I2C_CLASS_HWMON,
 539        .driver = {
 540                .name   = "emc6w201",
 541        },
 542        .probe          = emc6w201_probe,
 543        .remove         = emc6w201_remove,
 544        .id_table       = emc6w201_id,
 545        .detect         = emc6w201_detect,
 546        .address_list   = normal_i2c,
 547};
 548
 549module_i2c_driver(emc6w201_driver);
 550
 551MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
 552MODULE_DESCRIPTION("SMSC EMC6W201 hardware monitoring driver");
 553MODULE_LICENSE("GPL");
 554
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.