root/drivers/hwmon/lm92.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. TEMP_FROM_REG
  2. TEMP_TO_REG
  3. ALARMS_FROM_REG
  4. lm92_update_device
  5. temp_show
  6. temp_store
  7. temp_hyst_show
  8. temp1_min_hyst_show
  9. temp_hyst_store
  10. alarms_show
  11. alarm_show
  12. lm92_init_client
  13. lm92_detect
  14. lm92_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * lm92 - Hardware monitoring driver
   4  * Copyright (C) 2005-2008  Jean Delvare <jdelvare@suse.de>
   5  *
   6  * Based on the lm90 driver, with some ideas taken from the lm_sensors
   7  * lm92 driver as well.
   8  *
   9  * The LM92 is a sensor chip made by National Semiconductor. It reports
  10  * its own temperature with a 0.0625 deg resolution and a 0.33 deg
  11  * accuracy. Complete datasheet can be obtained from National's website
  12  * at:
  13  *   http://www.national.com/pf/LM/LM92.html
  14  *
  15  * This driver also supports the MAX6635 sensor chip made by Maxim.
  16  * This chip is compatible with the LM92, but has a lesser accuracy
  17  * (1.0 deg). Complete datasheet can be obtained from Maxim's website
  18  * at:
  19  *   http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074
  20  *
  21  * Since the LM92 was the first chipset supported by this driver, most
  22  * comments will refer to this chipset, but are actually general and
  23  * concern all supported chipsets, unless mentioned otherwise.
  24  *
  25  * Support could easily be added for the National Semiconductor LM76
  26  * and Maxim MAX6633 and MAX6634 chips, which are mostly compatible
  27  * with the LM92.
  28  */
  29 
  30 #include <linux/module.h>
  31 #include <linux/init.h>
  32 #include <linux/slab.h>
  33 #include <linux/i2c.h>
  34 #include <linux/hwmon.h>
  35 #include <linux/hwmon-sysfs.h>
  36 #include <linux/err.h>
  37 #include <linux/mutex.h>
  38 #include <linux/jiffies.h>
  39 
  40 /*
  41  * The LM92 and MAX6635 have 2 two-state pins for address selection,
  42  * resulting in 4 possible addresses.
  43  */
  44 static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
  45                                                 I2C_CLIENT_END };
  46 enum chips { lm92, max6635 };
  47 
  48 /* The LM92 registers */
  49 #define LM92_REG_CONFIG                 0x01 /* 8-bit, RW */
  50 #define LM92_REG_TEMP                   0x00 /* 16-bit, RO */
  51 #define LM92_REG_TEMP_HYST              0x02 /* 16-bit, RW */
  52 #define LM92_REG_TEMP_CRIT              0x03 /* 16-bit, RW */
  53 #define LM92_REG_TEMP_LOW               0x04 /* 16-bit, RW */
  54 #define LM92_REG_TEMP_HIGH              0x05 /* 16-bit, RW */
  55 #define LM92_REG_MAN_ID                 0x07 /* 16-bit, RO, LM92 only */
  56 
  57 /*
  58  * The LM92 uses signed 13-bit values with LSB = 0.0625 degree Celsius,
  59  * left-justified in 16-bit registers. No rounding is done, with such
  60  * a resolution it's just not worth it. Note that the MAX6635 doesn't
  61  * make use of the 4 lower bits for limits (i.e. effective resolution
  62  * for limits is 1 degree Celsius).
  63  */
  64 static inline int TEMP_FROM_REG(s16 reg)
  65 {
  66         return reg / 8 * 625 / 10;
  67 }
  68 
  69 static inline s16 TEMP_TO_REG(long val)
  70 {
  71         val = clamp_val(val, -60000, 160000);
  72         return val * 10 / 625 * 8;
  73 }
  74 
  75 /* Alarm flags are stored in the 3 LSB of the temperature register */
  76 static inline u8 ALARMS_FROM_REG(s16 reg)
  77 {
  78         return reg & 0x0007;
  79 }
  80 
  81 enum temp_index {
  82         t_input,
  83         t_crit,
  84         t_min,
  85         t_max,
  86         t_hyst,
  87         t_num_regs
  88 };
  89 
  90 static const u8 regs[t_num_regs] = {
  91         [t_input] = LM92_REG_TEMP,
  92         [t_crit] = LM92_REG_TEMP_CRIT,
  93         [t_min] = LM92_REG_TEMP_LOW,
  94         [t_max] = LM92_REG_TEMP_HIGH,
  95         [t_hyst] = LM92_REG_TEMP_HYST,
  96 };
  97 
  98 /* Client data (each client gets its own) */
  99 struct lm92_data {
 100         struct i2c_client *client;
 101         struct mutex update_lock;
 102         char valid; /* zero until following fields are valid */
 103         unsigned long last_updated; /* in jiffies */
 104 
 105         /* registers values */
 106         s16 temp[t_num_regs];   /* index with enum temp_index */
 107 };
 108 
 109 /*
 110  * Sysfs attributes and callback functions
 111  */
 112 
 113 static struct lm92_data *lm92_update_device(struct device *dev)
 114 {
 115         struct lm92_data *data = dev_get_drvdata(dev);
 116         struct i2c_client *client = data->client;
 117         int i;
 118 
 119         mutex_lock(&data->update_lock);
 120 
 121         if (time_after(jiffies, data->last_updated + HZ) ||
 122             !data->valid) {
 123                 dev_dbg(&client->dev, "Updating lm92 data\n");
 124                 for (i = 0; i < t_num_regs; i++) {
 125                         data->temp[i] =
 126                                 i2c_smbus_read_word_swapped(client, regs[i]);
 127                 }
 128                 data->last_updated = jiffies;
 129                 data->valid = 1;
 130         }
 131 
 132         mutex_unlock(&data->update_lock);
 133 
 134         return data;
 135 }
 136 
 137 static ssize_t temp_show(struct device *dev, struct device_attribute *devattr,
 138                          char *buf)
 139 {
 140         struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 141         struct lm92_data *data = lm92_update_device(dev);
 142 
 143         return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
 144 }
 145 
 146 static ssize_t temp_store(struct device *dev,
 147                           struct device_attribute *devattr, const char *buf,
 148                           size_t count)
 149 {
 150         struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 151         struct lm92_data *data = dev_get_drvdata(dev);
 152         struct i2c_client *client = data->client;
 153         int nr = attr->index;
 154         long val;
 155         int err;
 156 
 157         err = kstrtol(buf, 10, &val);
 158         if (err)
 159                 return err;
 160 
 161         mutex_lock(&data->update_lock);
 162         data->temp[nr] = TEMP_TO_REG(val);
 163         i2c_smbus_write_word_swapped(client, regs[nr], data->temp[nr]);
 164         mutex_unlock(&data->update_lock);
 165         return count;
 166 }
 167 
 168 static ssize_t temp_hyst_show(struct device *dev,
 169                               struct device_attribute *devattr, char *buf)
 170 {
 171         struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 172         struct lm92_data *data = lm92_update_device(dev);
 173 
 174         return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])
 175                        - TEMP_FROM_REG(data->temp[t_hyst]));
 176 }
 177 
 178 static ssize_t temp1_min_hyst_show(struct device *dev,
 179                                    struct device_attribute *attr, char *buf)
 180 {
 181         struct lm92_data *data = lm92_update_device(dev);
 182 
 183         return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[t_min])
 184                        + TEMP_FROM_REG(data->temp[t_hyst]));
 185 }
 186 
 187 static ssize_t temp_hyst_store(struct device *dev,
 188                                struct device_attribute *devattr,
 189                                const char *buf, size_t count)
 190 {
 191         struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 192         struct lm92_data *data = dev_get_drvdata(dev);
 193         struct i2c_client *client = data->client;
 194         long val;
 195         int err;
 196 
 197         err = kstrtol(buf, 10, &val);
 198         if (err)
 199                 return err;
 200 
 201         val = clamp_val(val, -120000, 220000);
 202         mutex_lock(&data->update_lock);
 203         data->temp[t_hyst] =
 204                 TEMP_TO_REG(TEMP_FROM_REG(data->temp[attr->index]) - val);
 205         i2c_smbus_write_word_swapped(client, LM92_REG_TEMP_HYST,
 206                                      data->temp[t_hyst]);
 207         mutex_unlock(&data->update_lock);
 208         return count;
 209 }
 210 
 211 static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
 212                            char *buf)
 213 {
 214         struct lm92_data *data = lm92_update_device(dev);
 215 
 216         return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp[t_input]));
 217 }
 218 
 219 static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
 220                           char *buf)
 221 {
 222         int bitnr = to_sensor_dev_attr(attr)->index;
 223         struct lm92_data *data = lm92_update_device(dev);
 224         return sprintf(buf, "%d\n", (data->temp[t_input] >> bitnr) & 1);
 225 }
 226 
 227 static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, t_input);
 228 static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp, t_crit);
 229 static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, temp_hyst, t_crit);
 230 static SENSOR_DEVICE_ATTR_RW(temp1_min, temp, t_min);
 231 static DEVICE_ATTR_RO(temp1_min_hyst);
 232 static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, t_max);
 233 static SENSOR_DEVICE_ATTR_RO(temp1_max_hyst, temp_hyst, t_max);
 234 static DEVICE_ATTR_RO(alarms);
 235 static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 2);
 236 static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 0);
 237 static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 1);
 238 
 239 /*
 240  * Detection and registration
 241  */
 242 
 243 static void lm92_init_client(struct i2c_client *client)
 244 {
 245         u8 config;
 246 
 247         /* Start the conversions if needed */
 248         config = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG);
 249         if (config & 0x01)
 250                 i2c_smbus_write_byte_data(client, LM92_REG_CONFIG,
 251                                           config & 0xFE);
 252 }
 253 
 254 static struct attribute *lm92_attrs[] = {
 255         &sensor_dev_attr_temp1_input.dev_attr.attr,
 256         &sensor_dev_attr_temp1_crit.dev_attr.attr,
 257         &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
 258         &sensor_dev_attr_temp1_min.dev_attr.attr,
 259         &dev_attr_temp1_min_hyst.attr,
 260         &sensor_dev_attr_temp1_max.dev_attr.attr,
 261         &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
 262         &dev_attr_alarms.attr,
 263         &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
 264         &sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
 265         &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
 266         NULL
 267 };
 268 ATTRIBUTE_GROUPS(lm92);
 269 
 270 /* Return 0 if detection is successful, -ENODEV otherwise */
 271 static int lm92_detect(struct i2c_client *new_client,
 272                        struct i2c_board_info *info)
 273 {
 274         struct i2c_adapter *adapter = new_client->adapter;
 275         u8 config;
 276         u16 man_id;
 277 
 278         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
 279                                             | I2C_FUNC_SMBUS_WORD_DATA))
 280                 return -ENODEV;
 281 
 282         config = i2c_smbus_read_byte_data(new_client, LM92_REG_CONFIG);
 283         man_id = i2c_smbus_read_word_data(new_client, LM92_REG_MAN_ID);
 284 
 285         if ((config & 0xe0) == 0x00 && man_id == 0x0180)
 286                 pr_info("lm92: Found National Semiconductor LM92 chip\n");
 287         else
 288                 return -ENODEV;
 289 
 290         strlcpy(info->type, "lm92", I2C_NAME_SIZE);
 291 
 292         return 0;
 293 }
 294 
 295 static int lm92_probe(struct i2c_client *new_client,
 296                       const struct i2c_device_id *id)
 297 {
 298         struct device *hwmon_dev;
 299         struct lm92_data *data;
 300 
 301         data = devm_kzalloc(&new_client->dev, sizeof(struct lm92_data),
 302                             GFP_KERNEL);
 303         if (!data)
 304                 return -ENOMEM;
 305 
 306         data->client = new_client;
 307         mutex_init(&data->update_lock);
 308 
 309         /* Initialize the chipset */
 310         lm92_init_client(new_client);
 311 
 312         hwmon_dev = devm_hwmon_device_register_with_groups(&new_client->dev,
 313                                                            new_client->name,
 314                                                            data, lm92_groups);
 315         return PTR_ERR_OR_ZERO(hwmon_dev);
 316 }
 317 
 318 /*
 319  * Module and driver stuff
 320  */
 321 
 322 static const struct i2c_device_id lm92_id[] = {
 323         { "lm92", lm92 },
 324         { "max6635", max6635 },
 325         { }
 326 };
 327 MODULE_DEVICE_TABLE(i2c, lm92_id);
 328 
 329 static struct i2c_driver lm92_driver = {
 330         .class          = I2C_CLASS_HWMON,
 331         .driver = {
 332                 .name   = "lm92",
 333         },
 334         .probe          = lm92_probe,
 335         .id_table       = lm92_id,
 336         .detect         = lm92_detect,
 337         .address_list   = normal_i2c,
 338 };
 339 
 340 module_i2c_driver(lm92_driver);
 341 
 342 MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
 343 MODULE_DESCRIPTION("LM92/MAX6635 driver");
 344 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */