1 /* 2 * adt7410.c - Part of lm_sensors, Linux kernel modules for hardware 3 * monitoring 4 * This driver handles the ADT7410 and compatible digital temperature sensors. 5 * Hartmut Knaack <knaack.h@gmx.de> 2012-07-22 6 * based on lm75.c by Frodo Looijaard <frodol@dds.nl> 7 * and adt7410.c from iio-staging by Sonic Zhang <sonic.zhang@analog.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 */ 23 24 #include <linux/module.h> 25 #include <linux/init.h> 26 #include <linux/slab.h> 27 #include <linux/jiffies.h> 28 #include <linux/i2c.h> 29 #include <linux/hwmon.h> 30 #include <linux/hwmon-sysfs.h> 31 #include <linux/err.h> 32 #include <linux/mutex.h> 33 #include <linux/delay.h> 34 35 /* 36 * ADT7410 registers definition 37 */ 38 39 #define ADT7410_TEMPERATURE 0 40 #define ADT7410_STATUS 2 41 #define ADT7410_CONFIG 3 42 #define ADT7410_T_ALARM_HIGH 4 43 #define ADT7410_T_ALARM_LOW 6 44 #define ADT7410_T_CRIT 8 45 #define ADT7410_T_HYST 0xA 46 47 /* 48 * ADT7410 status 49 */ 50 #define ADT7410_STAT_T_LOW (1 << 4) 51 #define ADT7410_STAT_T_HIGH (1 << 5) 52 #define ADT7410_STAT_T_CRIT (1 << 6) 53 #define ADT7410_STAT_NOT_RDY (1 << 7) 54 55 /* 56 * ADT7410 config 57 */ 58 #define ADT7410_FAULT_QUEUE_MASK (1 << 0 | 1 << 1) 59 #define ADT7410_CT_POLARITY (1 << 2) 60 #define ADT7410_INT_POLARITY (1 << 3) 61 #define ADT7410_EVENT_MODE (1 << 4) 62 #define ADT7410_MODE_MASK (1 << 5 | 1 << 6) 63 #define ADT7410_FULL (0 << 5 | 0 << 6) 64 #define ADT7410_PD (1 << 5 | 1 << 6) 65 #define ADT7410_RESOLUTION (1 << 7) 66 67 /* 68 * ADT7410 masks 69 */ 70 #define ADT7410_T13_VALUE_MASK 0xFFF8 71 #define ADT7410_T_HYST_MASK 0xF 72 73 /* straight from the datasheet */ 74 #define ADT7410_TEMP_MIN (-55000) 75 #define ADT7410_TEMP_MAX 150000 76 77 enum adt7410_type { /* keep sorted in alphabetical order */ 78 adt7410, 79 }; 80 81 static const u8 ADT7410_REG_TEMP[4] = { 82 ADT7410_TEMPERATURE, /* input */ 83 ADT7410_T_ALARM_HIGH, /* high */ 84 ADT7410_T_ALARM_LOW, /* low */ 85 ADT7410_T_CRIT, /* critical */ 86 }; 87 88 /* Each client has this additional data */ 89 struct adt7410_data { 90 struct device *hwmon_dev; 91 struct mutex update_lock; 92 u8 config; 93 u8 oldconfig; 94 bool valid; /* true if registers valid */ 95 unsigned long last_updated; /* In jiffies */ 96 s16 temp[4]; /* Register values, 97 0 = input 98 1 = high 99 2 = low 100 3 = critical */ 101 u8 hyst; /* hysteresis offset */ 102 }; 103 104 /* 105 * adt7410 register access by I2C 106 */ 107 static int adt7410_temp_ready(struct i2c_client *client) 108 { 109 int i, status; 110 111 for (i = 0; i < 6; i++) { 112 status = i2c_smbus_read_byte_data(client, ADT7410_STATUS); 113 if (status < 0) 114 return status; 115 if (!(status & ADT7410_STAT_NOT_RDY)) 116 return 0; 117 msleep(60); 118 } 119 return -ETIMEDOUT; 120 } 121 122 static struct adt7410_data *adt7410_update_device(struct device *dev) 123 { 124 struct i2c_client *client = to_i2c_client(dev); 125 struct adt7410_data *data = i2c_get_clientdata(client); 126 struct adt7410_data *ret = data; 127 mutex_lock(&data->update_lock); 128 129 if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 130 || !data->valid) { 131 int i, status; 132 133 dev_dbg(&client->dev, "Starting update\n"); 134 135 status = adt7410_temp_ready(client); /* check for new value */ 136 if (unlikely(status)) { 137 ret = ERR_PTR(status); 138 goto abort; 139 } 140 for (i = 0; i < ARRAY_SIZE(data->temp); i++) { 141 status = i2c_smbus_read_word_swapped(client, 142 ADT7410_REG_TEMP[i]); 143 if (unlikely(status < 0)) { 144 dev_dbg(dev, 145 "Failed to read value: reg %d, error %d\n", 146 ADT7410_REG_TEMP[i], status); 147 ret = ERR_PTR(status); 148 goto abort; 149 } 150 data->temp[i] = status; 151 } 152 status = i2c_smbus_read_byte_data(client, ADT7410_T_HYST); 153 if (unlikely(status < 0)) { 154 dev_dbg(dev, 155 "Failed to read value: reg %d, error %d\n", 156 ADT7410_T_HYST, status); 157 ret = ERR_PTR(status); 158 goto abort; 159 } 160 data->hyst = status; 161 data->last_updated = jiffies; 162 data->valid = true; 163 } 164 165 abort: 166 mutex_unlock(&data->update_lock); 167 return ret; 168 } 169 170 static s16 ADT7410_TEMP_TO_REG(long temp) 171 { 172 return DIV_ROUND_CLOSEST(clamp_val(temp, ADT7410_TEMP_MIN, 173 ADT7410_TEMP_MAX) * 128, 1000); 174 } 175 176 static int ADT7410_REG_TO_TEMP(struct adt7410_data *data, s16 reg) 177 { 178 /* in 13 bit mode, bits 0-2 are status flags - mask them out */ 179 if (!(data->config & ADT7410_RESOLUTION)) 180 reg &= ADT7410_T13_VALUE_MASK; 181 /* 182 * temperature is stored in twos complement format, in steps of 183 * 1/128°C 184 */ 185 return DIV_ROUND_CLOSEST(reg * 1000, 128); 186 } 187 188 /*-----------------------------------------------------------------------*/ 189 190 /* sysfs attributes for hwmon */ 191 192 static ssize_t adt7410_show_temp(struct device *dev, 193 struct device_attribute *da, char *buf) 194 { 195 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 196 struct adt7410_data *data = adt7410_update_device(dev); 197 198 if (IS_ERR(data)) 199 return PTR_ERR(data); 200 201 return sprintf(buf, "%d\n", ADT7410_REG_TO_TEMP(data, 202 data->temp[attr->index])); 203 } 204 205 static ssize_t adt7410_set_temp(struct device *dev, 206 struct device_attribute *da, 207 const char *buf, size_t count) 208 { 209 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 210 struct i2c_client *client = to_i2c_client(dev); 211 struct adt7410_data *data = i2c_get_clientdata(client); 212 int nr = attr->index; 213 long temp; 214 int ret; 215 216 ret = kstrtol(buf, 10, &temp); 217 if (ret) 218 return ret; 219 220 mutex_lock(&data->update_lock); 221 data->temp[nr] = ADT7410_TEMP_TO_REG(temp); 222 ret = i2c_smbus_write_word_swapped(client, ADT7410_REG_TEMP[nr], 223 data->temp[nr]); 224 if (ret) 225 count = ret; 226 mutex_unlock(&data->update_lock); 227 return count; 228 } 229 230 static ssize_t adt7410_show_t_hyst(struct device *dev, 231 struct device_attribute *da, 232 char *buf) 233 { 234 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 235 struct adt7410_data *data; 236 int nr = attr->index; 237 int hyst; 238 239 data = adt7410_update_device(dev); 240 if (IS_ERR(data)) 241 return PTR_ERR(data); 242 hyst = (data->hyst & ADT7410_T_HYST_MASK) * 1000; 243 244 /* 245 * hysteresis is stored as a 4 bit offset in the device, convert it 246 * to an absolute value 247 */ 248 if (nr == 2) /* min has positive offset, others have negative */ 249 hyst = -hyst; 250 return sprintf(buf, "%d\n", 251 ADT7410_REG_TO_TEMP(data, data->temp[nr]) - hyst); 252 } 253 254 static ssize_t adt7410_set_t_hyst(struct device *dev, 255 struct device_attribute *da, 256 const char *buf, size_t count) 257 { 258 struct i2c_client *client = to_i2c_client(dev); 259 struct adt7410_data *data = i2c_get_clientdata(client); 260 int limit, ret; 261 long hyst; 262 263 ret = kstrtol(buf, 10, &hyst); 264 if (ret) 265 return ret; 266 /* convert absolute hysteresis value to a 4 bit delta value */ 267 limit = ADT7410_REG_TO_TEMP(data, data->temp[1]); 268 hyst = clamp_val(hyst, ADT7410_TEMP_MIN, ADT7410_TEMP_MAX); 269 data->hyst = clamp_val(DIV_ROUND_CLOSEST(limit - hyst, 1000), 0, 270 ADT7410_T_HYST_MASK); 271 ret = i2c_smbus_write_byte_data(client, ADT7410_T_HYST, data->hyst); 272 if (ret) 273 return ret; 274 275 return count; 276 } 277 278 static ssize_t adt7410_show_alarm(struct device *dev, 279 struct device_attribute *da, 280 char *buf) 281 { 282 struct i2c_client *client = to_i2c_client(dev); 283 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 284 int ret; 285 286 ret = i2c_smbus_read_byte_data(client, ADT7410_STATUS); 287 if (ret < 0) 288 return ret; 289 290 return sprintf(buf, "%d\n", !!(ret & attr->index)); 291 } 292 293 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7410_show_temp, NULL, 0); 294 static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, 295 adt7410_show_temp, adt7410_set_temp, 1); 296 static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, 297 adt7410_show_temp, adt7410_set_temp, 2); 298 static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, 299 adt7410_show_temp, adt7410_set_temp, 3); 300 static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, 301 adt7410_show_t_hyst, adt7410_set_t_hyst, 1); 302 static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO, 303 adt7410_show_t_hyst, NULL, 2); 304 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, 305 adt7410_show_t_hyst, NULL, 3); 306 static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7410_show_alarm, 307 NULL, ADT7410_STAT_T_LOW); 308 static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7410_show_alarm, 309 NULL, ADT7410_STAT_T_HIGH); 310 static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7410_show_alarm, 311 NULL, ADT7410_STAT_T_CRIT); 312 313 static struct attribute *adt7410_attributes[] = { 314 &sensor_dev_attr_temp1_input.dev_attr.attr, 315 &sensor_dev_attr_temp1_max.dev_attr.attr, 316 &sensor_dev_attr_temp1_min.dev_attr.attr, 317 &sensor_dev_attr_temp1_crit.dev_attr.attr, 318 &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, 319 &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, 320 &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, 321 &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, 322 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 323 &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, 324 NULL 325 }; 326 327 static const struct attribute_group adt7410_group = { 328 .attrs = adt7410_attributes, 329 }; 330 331 /*-----------------------------------------------------------------------*/ 332 333 /* device probe and removal */ 334 335 static int adt7410_probe(struct i2c_client *client, 336 const struct i2c_device_id *id) 337 { 338 struct adt7410_data *data; 339 int ret; 340 341 if (!i2c_check_functionality(client->adapter, 342 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) 343 return -ENODEV; 344 345 data = devm_kzalloc(&client->dev, sizeof(struct adt7410_data), 346 GFP_KERNEL); 347 if (!data) 348 return -ENOMEM; 349 350 i2c_set_clientdata(client, data); 351 mutex_init(&data->update_lock); 352 353 /* configure as specified */ 354 ret = i2c_smbus_read_byte_data(client, ADT7410_CONFIG); 355 if (ret < 0) { 356 dev_dbg(&client->dev, "Can't read config? %d\n", ret); 357 return ret; 358 } 359 data->oldconfig = ret; 360 /* 361 * Set to 16 bit resolution, continous conversion and comparator mode. 362 */ 363 ret &= ~ADT7410_MODE_MASK; 364 data->config = ret | ADT7410_FULL | ADT7410_RESOLUTION | 365 ADT7410_EVENT_MODE; 366 if (data->config != data->oldconfig) { 367 ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, 368 data->config); 369 if (ret) 370 return ret; 371 } 372 dev_dbg(&client->dev, "Config %02x\n", data->config); 373 374 /* Register sysfs hooks */ 375 ret = sysfs_create_group(&client->dev.kobj, &adt7410_group); 376 if (ret) 377 goto exit_restore; 378 379 data->hwmon_dev = hwmon_device_register(&client->dev); 380 if (IS_ERR(data->hwmon_dev)) { 381 ret = PTR_ERR(data->hwmon_dev); 382 goto exit_remove; 383 } 384 385 dev_info(&client->dev, "sensor '%s'\n", client->name); 386 387 return 0; 388 389 exit_remove: 390 sysfs_remove_group(&client->dev.kobj, &adt7410_group); 391 exit_restore: 392 i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->oldconfig); 393 return ret; 394 } 395 396 static int adt7410_remove(struct i2c_client *client) 397 { 398 struct adt7410_data *data = i2c_get_clientdata(client); 399 400 hwmon_device_unregister(data->hwmon_dev); 401 sysfs_remove_group(&client->dev.kobj, &adt7410_group); 402 if (data->oldconfig != data->config) 403 i2c_smbus_write_byte_data(client, ADT7410_CONFIG, 404 data->oldconfig); 405 return 0; 406 } 407 408 static const struct i2c_device_id adt7410_ids[] = { 409 { "adt7410", adt7410, }, 410 { "adt7420", adt7410, }, 411 { /* LIST END */ } 412 }; 413 MODULE_DEVICE_TABLE(i2c, adt7410_ids); 414 415 #ifdef CONFIG_PM_SLEEP 416 static int adt7410_suspend(struct device *dev) 417 { 418 int ret; 419 struct i2c_client *client = to_i2c_client(dev); 420 struct adt7410_data *data = i2c_get_clientdata(client); 421 422 ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, 423 data->config | ADT7410_PD); 424 return ret; 425 } 426 427 static int adt7410_resume(struct device *dev) 428 { 429 int ret; 430 struct i2c_client *client = to_i2c_client(dev); 431 struct adt7410_data *data = i2c_get_clientdata(client); 432 433 ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->config); 434 return ret; 435 } 436 437 static SIMPLE_DEV_PM_OPS(adt7410_dev_pm_ops, adt7410_suspend, adt7410_resume); 438 439 #define ADT7410_DEV_PM_OPS (&adt7410_dev_pm_ops) 440 #else 441 #define ADT7410_DEV_PM_OPS NULL 442 #endif /* CONFIG_PM */ 443 444 static struct i2c_driver adt7410_driver = { 445 .class = I2C_CLASS_HWMON, 446 .driver = { 447 .name = "adt7410", 448 .pm = ADT7410_DEV_PM_OPS, 449 }, 450 .probe = adt7410_probe, 451 .remove = adt7410_remove, 452 .id_table = adt7410_ids, 453 .address_list = I2C_ADDRS(0x48, 0x49, 0x4a, 0x4b), 454 }; 455 456 module_i2c_driver(adt7410_driver); 457 458 MODULE_AUTHOR("Hartmut Knaack"); 459 MODULE_DESCRIPTION("ADT7410/ADT7420 driver"); 460 MODULE_LICENSE("GPL"); 461