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 int adt7410_update_temp(struct device *dev) 123 { 124 struct i2c_client *client = to_i2c_client(dev); 125 struct adt7410_data *data = i2c_get_clientdata(client); 126 int ret = 0; 127 128 mutex_lock(&data->update_lock); 129 130 if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 131 || !data->valid) { 132 int temp; 133 134 dev_dbg(&client->dev, "Starting update\n"); 135 136 ret = adt7410_temp_ready(client); /* check for new value */ 137 if (ret) 138 goto abort; 139 140 temp = i2c_smbus_read_word_swapped(client, ADT7410_REG_TEMP[0]); 141 if (temp < 0) { 142 ret = temp; 143 dev_dbg(dev, "Failed to read value: reg %d, error %d\n", 144 ADT7410_REG_TEMP[0], ret); 145 goto abort; 146 } 147 data->temp[0] = temp; 148 149 data->last_updated = jiffies; 150 data->valid = true; 151 } 152 153 abort: 154 mutex_unlock(&data->update_lock); 155 return ret; 156 } 157 158 static int adt7410_fill_cache(struct i2c_client *client) 159 { 160 struct adt7410_data *data = i2c_get_clientdata(client); 161 int ret; 162 int i; 163 164 for (i = 1; i < ARRAY_SIZE(ADT7410_REG_TEMP); i++) { 165 ret = i2c_smbus_read_word_swapped(client, ADT7410_REG_TEMP[i]); 166 if (ret < 0) { 167 dev_dbg(&client->dev, 168 "Failed to read value: reg %d, error %d\n", 169 ADT7410_REG_TEMP[i], ret); 170 return ret; 171 } 172 data->temp[i] = ret; 173 } 174 175 ret = i2c_smbus_read_byte_data(client, ADT7410_T_HYST); 176 if (ret < 0) { 177 dev_dbg(&client->dev, 178 "Failed to read value: hyst reg, error %d\n", 179 ret); 180 return ret; 181 } 182 data->hyst = ret; 183 184 return 0; 185 } 186 187 static s16 ADT7410_TEMP_TO_REG(long temp) 188 { 189 return DIV_ROUND_CLOSEST(clamp_val(temp, ADT7410_TEMP_MIN, 190 ADT7410_TEMP_MAX) * 128, 1000); 191 } 192 193 static int ADT7410_REG_TO_TEMP(struct adt7410_data *data, s16 reg) 194 { 195 /* in 13 bit mode, bits 0-2 are status flags - mask them out */ 196 if (!(data->config & ADT7410_RESOLUTION)) 197 reg &= ADT7410_T13_VALUE_MASK; 198 /* 199 * temperature is stored in twos complement format, in steps of 200 * 1/128°C 201 */ 202 return DIV_ROUND_CLOSEST(reg * 1000, 128); 203 } 204 205 /*-----------------------------------------------------------------------*/ 206 207 /* sysfs attributes for hwmon */ 208 209 static ssize_t adt7410_show_temp(struct device *dev, 210 struct device_attribute *da, char *buf) 211 { 212 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 213 struct i2c_client *client = to_i2c_client(dev); 214 struct adt7410_data *data = i2c_get_clientdata(client); 215 216 if (attr->index == 0) { 217 int ret; 218 219 ret = adt7410_update_temp(dev); 220 if (ret) 221 return ret; 222 } 223 224 return sprintf(buf, "%d\n", ADT7410_REG_TO_TEMP(data, 225 data->temp[attr->index])); 226 } 227 228 static ssize_t adt7410_set_temp(struct device *dev, 229 struct device_attribute *da, 230 const char *buf, size_t count) 231 { 232 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 233 struct i2c_client *client = to_i2c_client(dev); 234 struct adt7410_data *data = i2c_get_clientdata(client); 235 int nr = attr->index; 236 long temp; 237 int ret; 238 239 ret = kstrtol(buf, 10, &temp); 240 if (ret) 241 return ret; 242 243 mutex_lock(&data->update_lock); 244 data->temp[nr] = ADT7410_TEMP_TO_REG(temp); 245 ret = i2c_smbus_write_word_swapped(client, ADT7410_REG_TEMP[nr], 246 data->temp[nr]); 247 if (ret) 248 count = ret; 249 mutex_unlock(&data->update_lock); 250 return count; 251 } 252 253 static ssize_t adt7410_show_t_hyst(struct device *dev, 254 struct device_attribute *da, 255 char *buf) 256 { 257 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 258 struct i2c_client *client = to_i2c_client(dev); 259 struct adt7410_data *data = i2c_get_clientdata(client); 260 int nr = attr->index; 261 int hyst; 262 263 hyst = (data->hyst & ADT7410_T_HYST_MASK) * 1000; 264 265 /* 266 * hysteresis is stored as a 4 bit offset in the device, convert it 267 * to an absolute value 268 */ 269 if (nr == 2) /* min has positive offset, others have negative */ 270 hyst = -hyst; 271 return sprintf(buf, "%d\n", 272 ADT7410_REG_TO_TEMP(data, data->temp[nr]) - hyst); 273 } 274 275 static ssize_t adt7410_set_t_hyst(struct device *dev, 276 struct device_attribute *da, 277 const char *buf, size_t count) 278 { 279 struct i2c_client *client = to_i2c_client(dev); 280 struct adt7410_data *data = i2c_get_clientdata(client); 281 int limit, ret; 282 long hyst; 283 284 ret = kstrtol(buf, 10, &hyst); 285 if (ret) 286 return ret; 287 /* convert absolute hysteresis value to a 4 bit delta value */ 288 limit = ADT7410_REG_TO_TEMP(data, data->temp[1]); 289 hyst = clamp_val(hyst, ADT7410_TEMP_MIN, ADT7410_TEMP_MAX); 290 data->hyst = clamp_val(DIV_ROUND_CLOSEST(limit - hyst, 1000), 0, 291 ADT7410_T_HYST_MASK); 292 ret = i2c_smbus_write_byte_data(client, ADT7410_T_HYST, data->hyst); 293 if (ret) 294 return ret; 295 296 return count; 297 } 298 299 static ssize_t adt7410_show_alarm(struct device *dev, 300 struct device_attribute *da, 301 char *buf) 302 { 303 struct i2c_client *client = to_i2c_client(dev); 304 struct sensor_device_attribute *attr = to_sensor_dev_attr(da); 305 int ret; 306 307 ret = i2c_smbus_read_byte_data(client, ADT7410_STATUS); 308 if (ret < 0) 309 return ret; 310 311 return sprintf(buf, "%d\n", !!(ret & attr->index)); 312 } 313 314 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7410_show_temp, NULL, 0); 315 static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, 316 adt7410_show_temp, adt7410_set_temp, 1); 317 static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, 318 adt7410_show_temp, adt7410_set_temp, 2); 319 static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, 320 adt7410_show_temp, adt7410_set_temp, 3); 321 static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, 322 adt7410_show_t_hyst, adt7410_set_t_hyst, 1); 323 static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO, 324 adt7410_show_t_hyst, NULL, 2); 325 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, 326 adt7410_show_t_hyst, NULL, 3); 327 static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7410_show_alarm, 328 NULL, ADT7410_STAT_T_LOW); 329 static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7410_show_alarm, 330 NULL, ADT7410_STAT_T_HIGH); 331 static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7410_show_alarm, 332 NULL, ADT7410_STAT_T_CRIT); 333 334 static struct attribute *adt7410_attributes[] = { 335 &sensor_dev_attr_temp1_input.dev_attr.attr, 336 &sensor_dev_attr_temp1_max.dev_attr.attr, 337 &sensor_dev_attr_temp1_min.dev_attr.attr, 338 &sensor_dev_attr_temp1_crit.dev_attr.attr, 339 &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, 340 &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, 341 &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, 342 &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, 343 &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, 344 &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, 345 NULL 346 }; 347 348 static const struct attribute_group adt7410_group = { 349 .attrs = adt7410_attributes, 350 }; 351 352 /*-----------------------------------------------------------------------*/ 353 354 /* device probe and removal */ 355 356 static int adt7410_probe(struct i2c_client *client, 357 const struct i2c_device_id *id) 358 { 359 struct adt7410_data *data; 360 int ret; 361 362 if (!i2c_check_functionality(client->adapter, 363 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) 364 return -ENODEV; 365 366 data = devm_kzalloc(&client->dev, sizeof(struct adt7410_data), 367 GFP_KERNEL); 368 if (!data) 369 return -ENOMEM; 370 371 i2c_set_clientdata(client, data); 372 mutex_init(&data->update_lock); 373 374 /* configure as specified */ 375 ret = i2c_smbus_read_byte_data(client, ADT7410_CONFIG); 376 if (ret < 0) { 377 dev_dbg(&client->dev, "Can't read config? %d\n", ret); 378 return ret; 379 } 380 data->oldconfig = ret; 381 /* 382 * Set to 16 bit resolution, continous conversion and comparator mode. 383 */ 384 ret &= ~ADT7410_MODE_MASK; 385 data->config = ret | ADT7410_FULL | ADT7410_RESOLUTION | 386 ADT7410_EVENT_MODE; 387 if (data->config != data->oldconfig) { 388 ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, 389 data->config); 390 if (ret) 391 return ret; 392 } 393 dev_dbg(&client->dev, "Config %02x\n", data->config); 394 395 ret = adt7410_fill_cache(client); 396 if (ret) 397 goto exit_restore; 398 399 /* Register sysfs hooks */ 400 ret = sysfs_create_group(&client->dev.kobj, &adt7410_group); 401 if (ret) 402 goto exit_restore; 403 404 data->hwmon_dev = hwmon_device_register(&client->dev); 405 if (IS_ERR(data->hwmon_dev)) { 406 ret = PTR_ERR(data->hwmon_dev); 407 goto exit_remove; 408 } 409 410 dev_info(&client->dev, "sensor '%s'\n", client->name); 411 412 return 0; 413 414 exit_remove: 415 sysfs_remove_group(&client->dev.kobj, &adt7410_group); 416 exit_restore: 417 i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->oldconfig); 418 return ret; 419 } 420 421 static int adt7410_remove(struct i2c_client *client) 422 { 423 struct adt7410_data *data = i2c_get_clientdata(client); 424 425 hwmon_device_unregister(data->hwmon_dev); 426 sysfs_remove_group(&client->dev.kobj, &adt7410_group); 427 if (data->oldconfig != data->config) 428 i2c_smbus_write_byte_data(client, ADT7410_CONFIG, 429 data->oldconfig); 430 return 0; 431 } 432 433 static const struct i2c_device_id adt7410_ids[] = { 434 { "adt7410", adt7410, }, 435 { "adt7420", adt7410, }, 436 { /* LIST END */ } 437 }; 438 MODULE_DEVICE_TABLE(i2c, adt7410_ids); 439 440 #ifdef CONFIG_PM_SLEEP 441 static int adt7410_suspend(struct device *dev) 442 { 443 int ret; 444 struct i2c_client *client = to_i2c_client(dev); 445 struct adt7410_data *data = i2c_get_clientdata(client); 446 447 ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, 448 data->config | ADT7410_PD); 449 return ret; 450 } 451 452 static int adt7410_resume(struct device *dev) 453 { 454 int ret; 455 struct i2c_client *client = to_i2c_client(dev); 456 struct adt7410_data *data = i2c_get_clientdata(client); 457 458 ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->config); 459 return ret; 460 } 461 462 static SIMPLE_DEV_PM_OPS(adt7410_dev_pm_ops, adt7410_suspend, adt7410_resume); 463 464 #define ADT7410_DEV_PM_OPS (&adt7410_dev_pm_ops) 465 #else 466 #define ADT7410_DEV_PM_OPS NULL 467 #endif /* CONFIG_PM */ 468 469 static struct i2c_driver adt7410_driver = { 470 .class = I2C_CLASS_HWMON, 471 .driver = { 472 .name = "adt7410", 473 .pm = ADT7410_DEV_PM_OPS, 474 }, 475 .probe = adt7410_probe, 476 .remove = adt7410_remove, 477 .id_table = adt7410_ids, 478 .address_list = I2C_ADDRS(0x48, 0x49, 0x4a, 0x4b), 479 }; 480 481 module_i2c_driver(adt7410_driver); 482 483 MODULE_AUTHOR("Hartmut Knaack"); 484 MODULE_DESCRIPTION("ADT7410/ADT7420 driver"); 485 MODULE_LICENSE("GPL"); 486