linux/drivers/hwmon/thmc50.c
<<
>>
Prefs
   1/*
   2 * thmc50.c - Part of lm_sensors, Linux kernel modules for hardware
   3 *            monitoring
   4 * Copyright (C) 2007 Krzysztof Helt <krzysztof.h1@wp.pl>
   5 * Based on 2.4 driver by Frodo Looijaard <frodol@dds.nl> and
   6 * Philip Edelbrock <phil@netroedge.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21 */
  22
  23#include <linux/module.h>
  24#include <linux/init.h>
  25#include <linux/slab.h>
  26#include <linux/i2c.h>
  27#include <linux/hwmon.h>
  28#include <linux/hwmon-sysfs.h>
  29#include <linux/err.h>
  30#include <linux/mutex.h>
  31#include <linux/jiffies.h>
  32
  33MODULE_LICENSE("GPL");
  34
  35/* Addresses to scan */
  36static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
  37
  38/* Insmod parameters */
  39enum chips { thmc50, adm1022 };
  40
  41static unsigned short adm1022_temp3[16];
  42static unsigned int adm1022_temp3_num;
  43module_param_array(adm1022_temp3, ushort, &adm1022_temp3_num, 0);
  44MODULE_PARM_DESC(adm1022_temp3,
  45                 "List of adapter,address pairs to enable 3rd temperature (ADM1022 only)");
  46
  47/* Many THMC50 constants specified below */
  48
  49/* The THMC50 registers */
  50#define THMC50_REG_CONF                         0x40
  51#define THMC50_REG_COMPANY_ID                   0x3E
  52#define THMC50_REG_DIE_CODE                     0x3F
  53#define THMC50_REG_ANALOG_OUT                   0x19
  54/*
  55 * The mirror status register cannot be used as
  56 * reading it does not clear alarms.
  57 */
  58#define THMC50_REG_INTR                         0x41
  59
  60static const u8 THMC50_REG_TEMP[] = { 0x27, 0x26, 0x20 };
  61static const u8 THMC50_REG_TEMP_MIN[] = { 0x3A, 0x38, 0x2C };
  62static const u8 THMC50_REG_TEMP_MAX[] = { 0x39, 0x37, 0x2B };
  63static const u8 THMC50_REG_TEMP_CRITICAL[] = { 0x13, 0x14, 0x14 };
  64static const u8 THMC50_REG_TEMP_DEFAULT[] = { 0x17, 0x18, 0x18 };
  65
  66#define THMC50_REG_CONF_nFANOFF                 0x20
  67#define THMC50_REG_CONF_PROGRAMMED              0x08
  68
  69/* Each client has this additional data */
  70struct thmc50_data {
  71        struct i2c_client *client;
  72        const struct attribute_group *groups[3];
  73
  74        struct mutex update_lock;
  75        enum chips type;
  76        unsigned long last_updated;     /* In jiffies */
  77        char has_temp3;         /* !=0 if it is ADM1022 in temp3 mode */
  78        char valid;             /* !=0 if following fields are valid */
  79
  80        /* Register values */
  81        s8 temp_input[3];
  82        s8 temp_max[3];
  83        s8 temp_min[3];
  84        s8 temp_critical[3];
  85        u8 analog_out;
  86        u8 alarms;
  87};
  88
  89static struct thmc50_data *thmc50_update_device(struct device *dev)
  90{
  91        struct thmc50_data *data = dev_get_drvdata(dev);
  92        struct i2c_client *client = data->client;
  93        int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0);
  94
  95        mutex_lock(&data->update_lock);
  96
  97        if (time_after(jiffies, data->last_updated + timeout)
  98            || !data->valid) {
  99
 100                int temps = data->has_temp3 ? 3 : 2;
 101                int i;
 102                int prog = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
 103
 104                prog &= THMC50_REG_CONF_PROGRAMMED;
 105
 106                for (i = 0; i < temps; i++) {
 107                        data->temp_input[i] = i2c_smbus_read_byte_data(client,
 108                                                THMC50_REG_TEMP[i]);
 109                        data->temp_max[i] = i2c_smbus_read_byte_data(client,
 110                                                THMC50_REG_TEMP_MAX[i]);
 111                        data->temp_min[i] = i2c_smbus_read_byte_data(client,
 112                                                THMC50_REG_TEMP_MIN[i]);
 113                        data->temp_critical[i] =
 114                                i2c_smbus_read_byte_data(client,
 115                                        prog ? THMC50_REG_TEMP_CRITICAL[i]
 116                                             : THMC50_REG_TEMP_DEFAULT[i]);
 117                }
 118                data->analog_out =
 119                    i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT);
 120                data->alarms =
 121                    i2c_smbus_read_byte_data(client, THMC50_REG_INTR);
 122                data->last_updated = jiffies;
 123                data->valid = 1;
 124        }
 125
 126        mutex_unlock(&data->update_lock);
 127
 128        return data;
 129}
 130
 131static ssize_t show_analog_out(struct device *dev,
 132                               struct device_attribute *attr, char *buf)
 133{
 134        struct thmc50_data *data = thmc50_update_device(dev);
 135        return sprintf(buf, "%d\n", data->analog_out);
 136}
 137
 138static ssize_t set_analog_out(struct device *dev,
 139                              struct device_attribute *attr,
 140                              const char *buf, size_t count)
 141{
 142        struct thmc50_data *data = dev_get_drvdata(dev);
 143        struct i2c_client *client = data->client;
 144        int config;
 145        unsigned long tmp;
 146        int err;
 147
 148        err = kstrtoul(buf, 10, &tmp);
 149        if (err)
 150                return err;
 151
 152        mutex_lock(&data->update_lock);
 153        data->analog_out = clamp_val(tmp, 0, 255);
 154        i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT,
 155                                  data->analog_out);
 156
 157        config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
 158        if (data->analog_out == 0)
 159                config &= ~THMC50_REG_CONF_nFANOFF;
 160        else
 161                config |= THMC50_REG_CONF_nFANOFF;
 162        i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config);
 163
 164        mutex_unlock(&data->update_lock);
 165        return count;
 166}
 167
 168/* There is only one PWM mode = DC */
 169static ssize_t show_pwm_mode(struct device *dev, struct device_attribute *attr,
 170                             char *buf)
 171{
 172        return sprintf(buf, "0\n");
 173}
 174
 175/* Temperatures */
 176static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
 177                         char *buf)
 178{
 179        int nr = to_sensor_dev_attr(attr)->index;
 180        struct thmc50_data *data = thmc50_update_device(dev);
 181        return sprintf(buf, "%d\n", data->temp_input[nr] * 1000);
 182}
 183
 184static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
 185                             char *buf)
 186{
 187        int nr = to_sensor_dev_attr(attr)->index;
 188        struct thmc50_data *data = thmc50_update_device(dev);
 189        return sprintf(buf, "%d\n", data->temp_min[nr] * 1000);
 190}
 191
 192static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 193                            const char *buf, size_t count)
 194{
 195        int nr = to_sensor_dev_attr(attr)->index;
 196        struct thmc50_data *data = dev_get_drvdata(dev);
 197        struct i2c_client *client = data->client;
 198        long val;
 199        int err;
 200
 201        err = kstrtol(buf, 10, &val);
 202        if (err)
 203                return err;
 204
 205        mutex_lock(&data->update_lock);
 206        data->temp_min[nr] = clamp_val(val / 1000, -128, 127);
 207        i2c_smbus_write_byte_data(client, THMC50_REG_TEMP_MIN[nr],
 208                                  data->temp_min[nr]);
 209        mutex_unlock(&data->update_lock);
 210        return count;
 211}
 212
 213static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
 214                             char *buf)
 215{
 216        int nr = to_sensor_dev_attr(attr)->index;
 217        struct thmc50_data *data = thmc50_update_device(dev);
 218        return sprintf(buf, "%d\n", data->temp_max[nr] * 1000);
 219}
 220
 221static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 222                            const char *buf, size_t count)
 223{
 224        int nr = to_sensor_dev_attr(attr)->index;
 225        struct thmc50_data *data = dev_get_drvdata(dev);
 226        struct i2c_client *client = data->client;
 227        long val;
 228        int err;
 229
 230        err = kstrtol(buf, 10, &val);
 231        if (err)
 232                return err;
 233
 234        mutex_lock(&data->update_lock);
 235        data->temp_max[nr] = clamp_val(val / 1000, -128, 127);
 236        i2c_smbus_write_byte_data(client, THMC50_REG_TEMP_MAX[nr],
 237                                  data->temp_max[nr]);
 238        mutex_unlock(&data->update_lock);
 239        return count;
 240}
 241
 242static ssize_t show_temp_critical(struct device *dev,
 243                                  struct device_attribute *attr,
 244                                  char *buf)
 245{
 246        int nr = to_sensor_dev_attr(attr)->index;
 247        struct thmc50_data *data = thmc50_update_device(dev);
 248        return sprintf(buf, "%d\n", data->temp_critical[nr] * 1000);
 249}
 250
 251static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
 252                          char *buf)
 253{
 254        int index = to_sensor_dev_attr(attr)->index;
 255        struct thmc50_data *data = thmc50_update_device(dev);
 256
 257        return sprintf(buf, "%u\n", (data->alarms >> index) & 1);
 258}
 259
 260#define temp_reg(offset)                                                \
 261static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp,     \
 262                        NULL, offset - 1);                              \
 263static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,        \
 264                        show_temp_min, set_temp_min, offset - 1);       \
 265static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,        \
 266                        show_temp_max, set_temp_max, offset - 1);       \
 267static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO,                 \
 268                        show_temp_critical, NULL, offset - 1);
 269
 270temp_reg(1);
 271temp_reg(2);
 272temp_reg(3);
 273
 274static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0);
 275static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
 276static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 1);
 277static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 7);
 278static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2);
 279
 280static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_analog_out,
 281                          set_analog_out, 0);
 282static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0);
 283
 284static struct attribute *thmc50_attributes[] = {
 285        &sensor_dev_attr_temp1_max.dev_attr.attr,
 286        &sensor_dev_attr_temp1_min.dev_attr.attr,
 287        &sensor_dev_attr_temp1_input.dev_attr.attr,
 288        &sensor_dev_attr_temp1_crit.dev_attr.attr,
 289        &sensor_dev_attr_temp1_alarm.dev_attr.attr,
 290        &sensor_dev_attr_temp2_max.dev_attr.attr,
 291        &sensor_dev_attr_temp2_min.dev_attr.attr,
 292        &sensor_dev_attr_temp2_input.dev_attr.attr,
 293        &sensor_dev_attr_temp2_crit.dev_attr.attr,
 294        &sensor_dev_attr_temp2_alarm.dev_attr.attr,
 295        &sensor_dev_attr_temp2_fault.dev_attr.attr,
 296        &sensor_dev_attr_pwm1.dev_attr.attr,
 297        &sensor_dev_attr_pwm1_mode.dev_attr.attr,
 298        NULL
 299};
 300
 301static const struct attribute_group thmc50_group = {
 302        .attrs = thmc50_attributes,
 303};
 304
 305/* for ADM1022 3rd temperature mode */
 306static struct attribute *temp3_attributes[] = {
 307        &sensor_dev_attr_temp3_max.dev_attr.attr,
 308        &sensor_dev_attr_temp3_min.dev_attr.attr,
 309        &sensor_dev_attr_temp3_input.dev_attr.attr,
 310        &sensor_dev_attr_temp3_crit.dev_attr.attr,
 311        &sensor_dev_attr_temp3_alarm.dev_attr.attr,
 312        &sensor_dev_attr_temp3_fault.dev_attr.attr,
 313        NULL
 314};
 315
 316static const struct attribute_group temp3_group = {
 317        .attrs = temp3_attributes,
 318};
 319
 320/* Return 0 if detection is successful, -ENODEV otherwise */
 321static int thmc50_detect(struct i2c_client *client,
 322                         struct i2c_board_info *info)
 323{
 324        unsigned company;
 325        unsigned revision;
 326        unsigned config;
 327        struct i2c_adapter *adapter = client->adapter;
 328        const char *type_name;
 329
 330        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 331                pr_debug("thmc50: detect failed, smbus byte data not supported!\n");
 332                return -ENODEV;
 333        }
 334
 335        pr_debug("thmc50: Probing for THMC50 at 0x%2X on bus %d\n",
 336                 client->addr, i2c_adapter_id(client->adapter));
 337
 338        company = i2c_smbus_read_byte_data(client, THMC50_REG_COMPANY_ID);
 339        revision = i2c_smbus_read_byte_data(client, THMC50_REG_DIE_CODE);
 340        config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
 341        if (revision < 0xc0 || (config & 0x10))
 342                return -ENODEV;
 343
 344        if (company == 0x41) {
 345                int id = i2c_adapter_id(client->adapter);
 346                int i;
 347
 348                type_name = "adm1022";
 349                for (i = 0; i + 1 < adm1022_temp3_num; i += 2)
 350                        if (adm1022_temp3[i] == id &&
 351                            adm1022_temp3[i + 1] == client->addr) {
 352                                /* enable 2nd remote temp */
 353                                config |= (1 << 7);
 354                                i2c_smbus_write_byte_data(client,
 355                                                          THMC50_REG_CONF,
 356                                                          config);
 357                                break;
 358                        }
 359        } else if (company == 0x49) {
 360                type_name = "thmc50";
 361        } else {
 362                pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n");
 363                return -ENODEV;
 364        }
 365
 366        pr_debug("thmc50: Detected %s (version %x, revision %x)\n",
 367                 type_name, (revision >> 4) - 0xc, revision & 0xf);
 368
 369        strlcpy(info->type, type_name, I2C_NAME_SIZE);
 370
 371        return 0;
 372}
 373
 374static void thmc50_init_client(struct thmc50_data *data)
 375{
 376        struct i2c_client *client = data->client;
 377        int config;
 378
 379        data->analog_out = i2c_smbus_read_byte_data(client,
 380                                                    THMC50_REG_ANALOG_OUT);
 381        /* set up to at least 1 */
 382        if (data->analog_out == 0) {
 383                data->analog_out = 1;
 384                i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT,
 385                                          data->analog_out);
 386        }
 387        config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
 388        config |= 0x1;  /* start the chip if it is in standby mode */
 389        if (data->type == adm1022 && (config & (1 << 7)))
 390                data->has_temp3 = 1;
 391        i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config);
 392}
 393
 394static int thmc50_probe(struct i2c_client *client,
 395                        const struct i2c_device_id *id)
 396{
 397        struct device *dev = &client->dev;
 398        struct thmc50_data *data;
 399        struct device *hwmon_dev;
 400        int idx = 0;
 401
 402        data = devm_kzalloc(dev, sizeof(struct thmc50_data), GFP_KERNEL);
 403        if (!data)
 404                return -ENOMEM;
 405
 406        data->client = client;
 407        data->type = id->driver_data;
 408        mutex_init(&data->update_lock);
 409
 410        thmc50_init_client(data);
 411
 412        /* sysfs hooks */
 413        data->groups[idx++] = &thmc50_group;
 414
 415        /* Register additional ADM1022 sysfs hooks */
 416        if (data->has_temp3)
 417                data->groups[idx++] = &temp3_group;
 418
 419        hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
 420                                                           data, data->groups);
 421        return PTR_ERR_OR_ZERO(hwmon_dev);
 422}
 423
 424static const struct i2c_device_id thmc50_id[] = {
 425        { "adm1022", adm1022 },
 426        { "thmc50", thmc50 },
 427        { }
 428};
 429MODULE_DEVICE_TABLE(i2c, thmc50_id);
 430
 431static struct i2c_driver thmc50_driver = {
 432        .class = I2C_CLASS_HWMON,
 433        .driver = {
 434                .name = "thmc50",
 435        },
 436        .probe = thmc50_probe,
 437        .id_table = thmc50_id,
 438        .detect = thmc50_detect,
 439        .address_list = normal_i2c,
 440};
 441
 442module_i2c_driver(thmc50_driver);
 443
 444MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>");
 445MODULE_DESCRIPTION("THMC50 driver");
 446