linux/drivers/hwmon/max6642.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Driver for +/-1 degree C, SMBus-Compatible Remote/Local Temperature Sensor
   4 * with Overtemperature Alarm
   5 *
   6 * Copyright (C) 2011 AppearTV AS
   7 *
   8 * Derived from:
   9 *
  10 *  Based on the max1619 driver.
  11 *  Copyright (C) 2003-2004 Oleksij Rempel <bug-track@fisher-privat.net>
  12 *                          Jean Delvare <jdelvare@suse.de>
  13 *
  14 * The MAX6642 is a sensor chip made by Maxim.
  15 * It reports up to two temperatures (its own plus up to
  16 * one external one). Complete datasheet can be
  17 * obtained from Maxim's website at:
  18 *   http://datasheets.maxim-ic.com/en/ds/MAX6642.pdf
  19 */
  20
  21
  22#include <linux/module.h>
  23#include <linux/init.h>
  24#include <linux/slab.h>
  25#include <linux/jiffies.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/sysfs.h>
  32
  33static const unsigned short normal_i2c[] = {
  34        0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
  35
  36/*
  37 * The MAX6642 registers
  38 */
  39
  40#define MAX6642_REG_R_MAN_ID            0xFE
  41#define MAX6642_REG_R_CONFIG            0x03
  42#define MAX6642_REG_W_CONFIG            0x09
  43#define MAX6642_REG_R_STATUS            0x02
  44#define MAX6642_REG_R_LOCAL_TEMP        0x00
  45#define MAX6642_REG_R_LOCAL_TEMPL       0x11
  46#define MAX6642_REG_R_LOCAL_HIGH        0x05
  47#define MAX6642_REG_W_LOCAL_HIGH        0x0B
  48#define MAX6642_REG_R_REMOTE_TEMP       0x01
  49#define MAX6642_REG_R_REMOTE_TEMPL      0x10
  50#define MAX6642_REG_R_REMOTE_HIGH       0x07
  51#define MAX6642_REG_W_REMOTE_HIGH       0x0D
  52
  53/*
  54 * Conversions
  55 */
  56
  57static int temp_from_reg10(int val)
  58{
  59        return val * 250;
  60}
  61
  62static int temp_from_reg(int val)
  63{
  64        return val * 1000;
  65}
  66
  67static int temp_to_reg(int val)
  68{
  69        return val / 1000;
  70}
  71
  72/*
  73 * Client data (each client gets its own)
  74 */
  75
  76struct max6642_data {
  77        struct i2c_client *client;
  78        struct mutex update_lock;
  79        bool valid; /* zero until following fields are valid */
  80        unsigned long last_updated; /* in jiffies */
  81
  82        /* registers values */
  83        u16 temp_input[2]; /* local/remote */
  84        u16 temp_high[2]; /* local/remote */
  85        u8 alarms;
  86};
  87
  88/*
  89 * Real code
  90 */
  91
  92static void max6642_init_client(struct max6642_data *data,
  93                                struct i2c_client *client)
  94{
  95        u8 config;
  96
  97        /*
  98         * Start the conversions.
  99         */
 100        config = i2c_smbus_read_byte_data(client, MAX6642_REG_R_CONFIG);
 101        if (config & 0x40)
 102                i2c_smbus_write_byte_data(client, MAX6642_REG_W_CONFIG,
 103                                          config & 0xBF); /* run */
 104
 105        data->temp_high[0] = i2c_smbus_read_byte_data(client,
 106                                MAX6642_REG_R_LOCAL_HIGH);
 107        data->temp_high[1] = i2c_smbus_read_byte_data(client,
 108                                MAX6642_REG_R_REMOTE_HIGH);
 109}
 110
 111/* Return 0 if detection is successful, -ENODEV otherwise */
 112static int max6642_detect(struct i2c_client *client,
 113                          struct i2c_board_info *info)
 114{
 115        struct i2c_adapter *adapter = client->adapter;
 116        u8 reg_config, reg_status, man_id;
 117
 118        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 119                return -ENODEV;
 120
 121        /* identification */
 122        man_id = i2c_smbus_read_byte_data(client, MAX6642_REG_R_MAN_ID);
 123        if (man_id != 0x4D)
 124                return -ENODEV;
 125
 126        /* sanity check */
 127        if (i2c_smbus_read_byte_data(client, 0x04) != 0x4D
 128            || i2c_smbus_read_byte_data(client, 0x06) != 0x4D
 129            || i2c_smbus_read_byte_data(client, 0xff) != 0x4D)
 130                return -ENODEV;
 131
 132        /*
 133         * We read the config and status register, the 4 lower bits in the
 134         * config register should be zero and bit 5, 3, 1 and 0 should be
 135         * zero in the status register.
 136         */
 137        reg_config = i2c_smbus_read_byte_data(client, MAX6642_REG_R_CONFIG);
 138        if ((reg_config & 0x0f) != 0x00)
 139                return -ENODEV;
 140
 141        /* in between, another round of sanity checks */
 142        if (i2c_smbus_read_byte_data(client, 0x04) != reg_config
 143            || i2c_smbus_read_byte_data(client, 0x06) != reg_config
 144            || i2c_smbus_read_byte_data(client, 0xff) != reg_config)
 145                return -ENODEV;
 146
 147        reg_status = i2c_smbus_read_byte_data(client, MAX6642_REG_R_STATUS);
 148        if ((reg_status & 0x2b) != 0x00)
 149                return -ENODEV;
 150
 151        strlcpy(info->type, "max6642", I2C_NAME_SIZE);
 152
 153        return 0;
 154}
 155
 156static struct max6642_data *max6642_update_device(struct device *dev)
 157{
 158        struct max6642_data *data = dev_get_drvdata(dev);
 159        struct i2c_client *client = data->client;
 160        u16 val, tmp;
 161
 162        mutex_lock(&data->update_lock);
 163
 164        if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
 165                dev_dbg(dev, "Updating max6642 data.\n");
 166                val = i2c_smbus_read_byte_data(client,
 167                                        MAX6642_REG_R_LOCAL_TEMPL);
 168                tmp = (val >> 6) & 3;
 169                val = i2c_smbus_read_byte_data(client,
 170                                        MAX6642_REG_R_LOCAL_TEMP);
 171                val = (val << 2) | tmp;
 172                data->temp_input[0] = val;
 173                val = i2c_smbus_read_byte_data(client,
 174                                        MAX6642_REG_R_REMOTE_TEMPL);
 175                tmp = (val >> 6) & 3;
 176                val = i2c_smbus_read_byte_data(client,
 177                                        MAX6642_REG_R_REMOTE_TEMP);
 178                val = (val << 2) | tmp;
 179                data->temp_input[1] = val;
 180                data->alarms = i2c_smbus_read_byte_data(client,
 181                                        MAX6642_REG_R_STATUS);
 182
 183                data->last_updated = jiffies;
 184                data->valid = 1;
 185        }
 186
 187        mutex_unlock(&data->update_lock);
 188
 189        return data;
 190}
 191
 192/*
 193 * Sysfs stuff
 194 */
 195
 196static ssize_t temp_max10_show(struct device *dev,
 197                               struct device_attribute *dev_attr, char *buf)
 198{
 199        struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
 200        struct max6642_data *data = max6642_update_device(dev);
 201
 202        return sprintf(buf, "%d\n",
 203                       temp_from_reg10(data->temp_input[attr->index]));
 204}
 205
 206static ssize_t temp_max_show(struct device *dev,
 207                             struct device_attribute *attr, char *buf)
 208{
 209        struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
 210        struct max6642_data *data = max6642_update_device(dev);
 211
 212        return sprintf(buf, "%d\n", temp_from_reg(data->temp_high[attr2->nr]));
 213}
 214
 215static ssize_t temp_max_store(struct device *dev,
 216                              struct device_attribute *attr, const char *buf,
 217                              size_t count)
 218{
 219        struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
 220        struct max6642_data *data = dev_get_drvdata(dev);
 221        unsigned long val;
 222        int err;
 223
 224        err = kstrtoul(buf, 10, &val);
 225        if (err < 0)
 226                return err;
 227
 228        mutex_lock(&data->update_lock);
 229        data->temp_high[attr2->nr] = clamp_val(temp_to_reg(val), 0, 255);
 230        i2c_smbus_write_byte_data(data->client, attr2->index,
 231                                  data->temp_high[attr2->nr]);
 232        mutex_unlock(&data->update_lock);
 233        return count;
 234}
 235
 236static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
 237                          char *buf)
 238{
 239        int bitnr = to_sensor_dev_attr(attr)->index;
 240        struct max6642_data *data = max6642_update_device(dev);
 241        return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
 242}
 243
 244static SENSOR_DEVICE_ATTR_RO(temp1_input, temp_max10, 0);
 245static SENSOR_DEVICE_ATTR_RO(temp2_input, temp_max10, 1);
 246static SENSOR_DEVICE_ATTR_2_RW(temp1_max, temp_max, 0,
 247                               MAX6642_REG_W_LOCAL_HIGH);
 248static SENSOR_DEVICE_ATTR_2_RW(temp2_max, temp_max, 1,
 249                               MAX6642_REG_W_REMOTE_HIGH);
 250static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 2);
 251static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6);
 252static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 4);
 253
 254static struct attribute *max6642_attrs[] = {
 255        &sensor_dev_attr_temp1_input.dev_attr.attr,
 256        &sensor_dev_attr_temp2_input.dev_attr.attr,
 257        &sensor_dev_attr_temp1_max.dev_attr.attr,
 258        &sensor_dev_attr_temp2_max.dev_attr.attr,
 259
 260        &sensor_dev_attr_temp2_fault.dev_attr.attr,
 261        &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
 262        &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
 263        NULL
 264};
 265ATTRIBUTE_GROUPS(max6642);
 266
 267static int max6642_probe(struct i2c_client *client)
 268{
 269        struct device *dev = &client->dev;
 270        struct max6642_data *data;
 271        struct device *hwmon_dev;
 272
 273        data = devm_kzalloc(dev, sizeof(struct max6642_data), GFP_KERNEL);
 274        if (!data)
 275                return -ENOMEM;
 276
 277        data->client = client;
 278        mutex_init(&data->update_lock);
 279
 280        /* Initialize the MAX6642 chip */
 281        max6642_init_client(data, client);
 282
 283        hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
 284                                                           client->name, data,
 285                                                           max6642_groups);
 286        return PTR_ERR_OR_ZERO(hwmon_dev);
 287}
 288
 289/*
 290 * Driver data (common to all clients)
 291 */
 292
 293static const struct i2c_device_id max6642_id[] = {
 294        { "max6642", 0 },
 295        { }
 296};
 297MODULE_DEVICE_TABLE(i2c, max6642_id);
 298
 299static struct i2c_driver max6642_driver = {
 300        .class          = I2C_CLASS_HWMON,
 301        .driver = {
 302                .name   = "max6642",
 303        },
 304        .probe_new      = max6642_probe,
 305        .id_table       = max6642_id,
 306        .detect         = max6642_detect,
 307        .address_list   = normal_i2c,
 308};
 309
 310module_i2c_driver(max6642_driver);
 311
 312MODULE_AUTHOR("Per Dalen <per.dalen@appeartv.com>");
 313MODULE_DESCRIPTION("MAX6642 sensor driver");
 314MODULE_LICENSE("GPL");
 315