lm92.c (9630B)
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 */ 44static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 45 I2C_CLIENT_END }; 46enum 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 */ 64static inline int TEMP_FROM_REG(s16 reg) 65{ 66 return reg / 8 * 625 / 10; 67} 68 69static 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 */ 76static inline u8 ALARMS_FROM_REG(s16 reg) 77{ 78 return reg & 0x0007; 79} 80 81enum temp_index { 82 t_input, 83 t_crit, 84 t_min, 85 t_max, 86 t_hyst, 87 t_num_regs 88}; 89 90static 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) */ 99struct lm92_data { 100 struct i2c_client *client; 101 struct mutex update_lock; 102 bool valid; /* false 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 113static 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 = true; 130 } 131 132 mutex_unlock(&data->update_lock); 133 134 return data; 135} 136 137static 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 146static 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 168static 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 178static 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 187static 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 211static 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 219static 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 227static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, t_input); 228static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp, t_crit); 229static SENSOR_DEVICE_ATTR_RW(temp1_crit_hyst, temp_hyst, t_crit); 230static SENSOR_DEVICE_ATTR_RW(temp1_min, temp, t_min); 231static DEVICE_ATTR_RO(temp1_min_hyst); 232static SENSOR_DEVICE_ATTR_RW(temp1_max, temp, t_max); 233static SENSOR_DEVICE_ATTR_RO(temp1_max_hyst, temp_hyst, t_max); 234static DEVICE_ATTR_RO(alarms); 235static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 2); 236static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 0); 237static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 1); 238 239/* 240 * Detection and registration 241 */ 242 243static 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 254static 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}; 268ATTRIBUTE_GROUPS(lm92); 269 270/* Return 0 if detection is successful, -ENODEV otherwise */ 271static 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 295static int lm92_probe(struct i2c_client *new_client) 296{ 297 struct device *hwmon_dev; 298 struct lm92_data *data; 299 300 data = devm_kzalloc(&new_client->dev, sizeof(struct lm92_data), 301 GFP_KERNEL); 302 if (!data) 303 return -ENOMEM; 304 305 data->client = new_client; 306 mutex_init(&data->update_lock); 307 308 /* Initialize the chipset */ 309 lm92_init_client(new_client); 310 311 hwmon_dev = devm_hwmon_device_register_with_groups(&new_client->dev, 312 new_client->name, 313 data, lm92_groups); 314 return PTR_ERR_OR_ZERO(hwmon_dev); 315} 316 317/* 318 * Module and driver stuff 319 */ 320 321static const struct i2c_device_id lm92_id[] = { 322 { "lm92", lm92 }, 323 { "max6635", max6635 }, 324 { } 325}; 326MODULE_DEVICE_TABLE(i2c, lm92_id); 327 328static struct i2c_driver lm92_driver = { 329 .class = I2C_CLASS_HWMON, 330 .driver = { 331 .name = "lm92", 332 }, 333 .probe_new = lm92_probe, 334 .id_table = lm92_id, 335 .detect = lm92_detect, 336 .address_list = normal_i2c, 337}; 338 339module_i2c_driver(lm92_driver); 340 341MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); 342MODULE_DESCRIPTION("LM92/MAX6635 driver"); 343MODULE_LICENSE("GPL");