1 /* 2 * tmp007.c - Support for TI TMP007 IR thermopile sensor with integrated math engine 3 * 4 * Copyright (c) 2017 Manivannan Sadhasivam <manivannanece23@gmail.com> 5 * 6 * This file is subject to the terms and conditions of version 2 of 7 * the GNU General Public License. See the file COPYING in the main 8 * directory of this archive for more details. 9 * 10 * Driver for the Texas Instruments I2C 16-bit IR thermopile sensor 11 * 12 * (7-bit I2C slave address (0x40 - 0x47), changeable via ADR pins) 13 * 14 * Note: 15 * 1. This driver assumes that the sensor has been calibrated beforehand 16 * 2. Limit threshold events are enabled at the start 17 * 3. Operating mode: INT 18 * 19 */ 20 21 #include <linux/err.h> 22 #include <linux/i2c.h> 23 #include <linux/delay.h> 24 #include <linux/module.h> 25 #include <linux/pm.h> 26 #include <linux/bitops.h> 27 #include <linux/of.h> 28 #include <linux/irq.h> 29 #include <linux/interrupt.h> 30 31 #include <linux/iio/iio.h> 32 #include <linux/iio/sysfs.h> 33 #include <linux/iio/events.h> 34 35 #define TMP007_TDIE 0x01 36 #define TMP007_CONFIG 0x02 37 #define TMP007_TOBJECT 0x03 38 #define TMP007_STATUS 0x04 39 #define TMP007_STATUS_MASK 0x05 40 #define TMP007_TOBJ_HIGH_LIMIT 0x06 41 #define TMP007_TOBJ_LOW_LIMIT 0x07 42 #define TMP007_TDIE_HIGH_LIMIT 0x08 43 #define TMP007_TDIE_LOW_LIMIT 0x09 44 #define TMP007_MANUFACTURER_ID 0x1e 45 #define TMP007_DEVICE_ID 0x1f 46 47 #define TMP007_CONFIG_CONV_EN BIT(12) 48 #define TMP007_CONFIG_TC_EN BIT(6) 49 #define TMP007_CONFIG_CR_MASK GENMASK(11, 9) 50 #define TMP007_CONFIG_ALERT_EN BIT(8) 51 #define TMP007_CONFIG_CR_SHIFT 9 52 53 /* Status register flags */ 54 #define TMP007_STATUS_ALERT BIT(15) 55 #define TMP007_STATUS_CONV_READY BIT(14) 56 #define TMP007_STATUS_OHF BIT(13) 57 #define TMP007_STATUS_OLF BIT(12) 58 #define TMP007_STATUS_LHF BIT(11) 59 #define TMP007_STATUS_LLF BIT(10) 60 #define TMP007_STATUS_DATA_VALID BIT(9) 61 62 #define TMP007_MANUFACTURER_MAGIC 0x5449 63 #define TMP007_DEVICE_MAGIC 0x0078 64 65 #define TMP007_TEMP_SHIFT 2 66 67 struct tmp007_data { 68 struct i2c_client *client; 69 struct mutex lock; 70 u16 config; 71 u16 status_mask; 72 }; 73 74 static const int tmp007_avgs[5][2] = { {4, 0}, {2, 0}, {1, 0}, 75 {0, 500000}, {0, 250000} }; 76 77 static int tmp007_read_temperature(struct tmp007_data *data, u8 reg) 78 { 79 s32 ret; 80 int tries = 50; 81 82 while (tries-- > 0) { 83 ret = i2c_smbus_read_word_swapped(data->client, 84 TMP007_STATUS); 85 if (ret < 0) 86 return ret; 87 if ((ret & TMP007_STATUS_CONV_READY) && 88 !(ret & TMP007_STATUS_DATA_VALID)) 89 break; 90 msleep(100); 91 } 92 93 if (tries < 0) 94 return -EIO; 95 96 return i2c_smbus_read_word_swapped(data->client, reg); 97 } 98 99 static int tmp007_powerdown(struct tmp007_data *data) 100 { 101 return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG, 102 data->config & ~TMP007_CONFIG_CONV_EN); 103 } 104 105 static int tmp007_read_raw(struct iio_dev *indio_dev, 106 struct iio_chan_spec const *channel, int *val, 107 int *val2, long mask) 108 { 109 struct tmp007_data *data = iio_priv(indio_dev); 110 s32 ret; 111 int conv_rate; 112 113 switch (mask) { 114 case IIO_CHAN_INFO_RAW: 115 switch (channel->channel2) { 116 case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.03125 degree Celsius */ 117 ret = i2c_smbus_read_word_swapped(data->client, TMP007_TDIE); 118 if (ret < 0) 119 return ret; 120 break; 121 case IIO_MOD_TEMP_OBJECT: 122 ret = tmp007_read_temperature(data, TMP007_TOBJECT); 123 if (ret < 0) 124 return ret; 125 break; 126 default: 127 return -EINVAL; 128 } 129 130 *val = sign_extend32(ret, 15) >> TMP007_TEMP_SHIFT; 131 132 return IIO_VAL_INT; 133 case IIO_CHAN_INFO_SCALE: 134 *val = 31; 135 *val2 = 250000; 136 137 return IIO_VAL_INT_PLUS_MICRO; 138 case IIO_CHAN_INFO_SAMP_FREQ: 139 conv_rate = (data->config & TMP007_CONFIG_CR_MASK) 140 >> TMP007_CONFIG_CR_SHIFT; 141 *val = tmp007_avgs[conv_rate][0]; 142 *val2 = tmp007_avgs[conv_rate][1]; 143 144 return IIO_VAL_INT_PLUS_MICRO; 145 default: 146 return -EINVAL; 147 } 148 } 149 150 static int tmp007_write_raw(struct iio_dev *indio_dev, 151 struct iio_chan_spec const *channel, int val, 152 int val2, long mask) 153 { 154 struct tmp007_data *data = iio_priv(indio_dev); 155 int i; 156 u16 tmp; 157 158 if (mask == IIO_CHAN_INFO_SAMP_FREQ) { 159 for (i = 0; i < ARRAY_SIZE(tmp007_avgs); i++) { 160 if ((val == tmp007_avgs[i][0]) && 161 (val2 == tmp007_avgs[i][1])) { 162 tmp = data->config & ~TMP007_CONFIG_CR_MASK; 163 tmp |= (i << TMP007_CONFIG_CR_SHIFT); 164 165 return i2c_smbus_write_word_swapped(data->client, 166 TMP007_CONFIG, 167 data->config = tmp); 168 } 169 } 170 } 171 172 return -EINVAL; 173 } 174 175 static irqreturn_t tmp007_interrupt_handler(int irq, void *private) 176 { 177 struct iio_dev *indio_dev = private; 178 struct tmp007_data *data = iio_priv(indio_dev); 179 int ret; 180 181 ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS); 182 if ((ret < 0) || !(ret & (TMP007_STATUS_OHF | TMP007_STATUS_OLF | 183 TMP007_STATUS_LHF | TMP007_STATUS_LLF))) 184 return IRQ_NONE; 185 186 if (ret & TMP007_STATUS_OHF) 187 iio_push_event(indio_dev, 188 IIO_MOD_EVENT_CODE(IIO_TEMP, 0, 189 IIO_MOD_TEMP_OBJECT, 190 IIO_EV_TYPE_THRESH, 191 IIO_EV_DIR_RISING), 192 iio_get_time_ns(indio_dev)); 193 194 if (ret & TMP007_STATUS_OLF) 195 iio_push_event(indio_dev, 196 IIO_MOD_EVENT_CODE(IIO_TEMP, 0, 197 IIO_MOD_TEMP_OBJECT, 198 IIO_EV_TYPE_THRESH, 199 IIO_EV_DIR_FALLING), 200 iio_get_time_ns(indio_dev)); 201 202 if (ret & TMP007_STATUS_LHF) 203 iio_push_event(indio_dev, 204 IIO_MOD_EVENT_CODE(IIO_TEMP, 0, 205 IIO_MOD_TEMP_AMBIENT, 206 IIO_EV_TYPE_THRESH, 207 IIO_EV_DIR_RISING), 208 iio_get_time_ns(indio_dev)); 209 210 if (ret & TMP007_STATUS_LLF) 211 iio_push_event(indio_dev, 212 IIO_MOD_EVENT_CODE(IIO_TEMP, 0, 213 IIO_MOD_TEMP_AMBIENT, 214 IIO_EV_TYPE_THRESH, 215 IIO_EV_DIR_FALLING), 216 iio_get_time_ns(indio_dev)); 217 218 return IRQ_HANDLED; 219 } 220 221 static int tmp007_write_event_config(struct iio_dev *indio_dev, 222 const struct iio_chan_spec *chan, enum iio_event_type type, 223 enum iio_event_direction dir, int state) 224 { 225 struct tmp007_data *data = iio_priv(indio_dev); 226 unsigned int status_mask; 227 int ret; 228 229 switch (chan->channel2) { 230 case IIO_MOD_TEMP_AMBIENT: 231 if (dir == IIO_EV_DIR_RISING) 232 status_mask = TMP007_STATUS_LHF; 233 else 234 status_mask = TMP007_STATUS_LLF; 235 break; 236 case IIO_MOD_TEMP_OBJECT: 237 if (dir == IIO_EV_DIR_RISING) 238 status_mask = TMP007_STATUS_OHF; 239 else 240 status_mask = TMP007_STATUS_OLF; 241 break; 242 default: 243 return -EINVAL; 244 } 245 246 mutex_lock(&data->lock); 247 ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK); 248 mutex_unlock(&data->lock); 249 if (ret < 0) 250 return ret; 251 252 if (state) 253 ret |= status_mask; 254 else 255 ret &= ~status_mask; 256 257 return i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK, 258 data->status_mask = ret); 259 } 260 261 static int tmp007_read_event_config(struct iio_dev *indio_dev, 262 const struct iio_chan_spec *chan, enum iio_event_type type, 263 enum iio_event_direction dir) 264 { 265 struct tmp007_data *data = iio_priv(indio_dev); 266 unsigned int mask; 267 268 switch (chan->channel2) { 269 case IIO_MOD_TEMP_AMBIENT: 270 if (dir == IIO_EV_DIR_RISING) 271 mask = TMP007_STATUS_LHF; 272 else 273 mask = TMP007_STATUS_LLF; 274 break; 275 case IIO_MOD_TEMP_OBJECT: 276 if (dir == IIO_EV_DIR_RISING) 277 mask = TMP007_STATUS_OHF; 278 else 279 mask = TMP007_STATUS_OLF; 280 break; 281 default: 282 return -EINVAL; 283 } 284 285 return !!(data->status_mask & mask); 286 } 287 288 static int tmp007_read_thresh(struct iio_dev *indio_dev, 289 const struct iio_chan_spec *chan, enum iio_event_type type, 290 enum iio_event_direction dir, enum iio_event_info info, 291 int *val, int *val2) 292 { 293 struct tmp007_data *data = iio_priv(indio_dev); 294 int ret; 295 u8 reg; 296 297 switch (chan->channel2) { 298 case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.5 degree Celsius */ 299 if (dir == IIO_EV_DIR_RISING) 300 reg = TMP007_TDIE_HIGH_LIMIT; 301 else 302 reg = TMP007_TDIE_LOW_LIMIT; 303 break; 304 case IIO_MOD_TEMP_OBJECT: 305 if (dir == IIO_EV_DIR_RISING) 306 reg = TMP007_TOBJ_HIGH_LIMIT; 307 else 308 reg = TMP007_TOBJ_LOW_LIMIT; 309 break; 310 default: 311 return -EINVAL; 312 } 313 314 ret = i2c_smbus_read_word_swapped(data->client, reg); 315 if (ret < 0) 316 return ret; 317 318 /* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */ 319 *val = sign_extend32(ret, 15) >> 7; 320 321 return IIO_VAL_INT; 322 } 323 324 static int tmp007_write_thresh(struct iio_dev *indio_dev, 325 const struct iio_chan_spec *chan, enum iio_event_type type, 326 enum iio_event_direction dir, enum iio_event_info info, 327 int val, int val2) 328 { 329 struct tmp007_data *data = iio_priv(indio_dev); 330 u8 reg; 331 332 switch (chan->channel2) { 333 case IIO_MOD_TEMP_AMBIENT: 334 if (dir == IIO_EV_DIR_RISING) 335 reg = TMP007_TDIE_HIGH_LIMIT; 336 else 337 reg = TMP007_TDIE_LOW_LIMIT; 338 break; 339 case IIO_MOD_TEMP_OBJECT: 340 if (dir == IIO_EV_DIR_RISING) 341 reg = TMP007_TOBJ_HIGH_LIMIT; 342 else 343 reg = TMP007_TOBJ_LOW_LIMIT; 344 break; 345 default: 346 return -EINVAL; 347 } 348 349 /* Full scale threshold value is +/- 256 degree Celsius */ 350 if (val < -256 || val > 255) 351 return -EINVAL; 352 353 /* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */ 354 return i2c_smbus_write_word_swapped(data->client, reg, (val << 7)); 355 } 356 357 static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25"); 358 359 static struct attribute *tmp007_attributes[] = { 360 &iio_const_attr_sampling_frequency_available.dev_attr.attr, 361 NULL 362 }; 363 364 static const struct attribute_group tmp007_attribute_group = { 365 .attrs = tmp007_attributes, 366 }; 367 368 static const struct iio_event_spec tmp007_obj_event[] = { 369 { 370 .type = IIO_EV_TYPE_THRESH, 371 .dir = IIO_EV_DIR_RISING, 372 .mask_separate = BIT(IIO_EV_INFO_VALUE) | 373 BIT(IIO_EV_INFO_ENABLE), 374 }, 375 { 376 .type = IIO_EV_TYPE_THRESH, 377 .dir = IIO_EV_DIR_FALLING, 378 .mask_separate = BIT(IIO_EV_INFO_VALUE) | 379 BIT(IIO_EV_INFO_ENABLE), 380 }, 381 }; 382 383 static const struct iio_event_spec tmp007_die_event[] = { 384 { 385 .type = IIO_EV_TYPE_THRESH, 386 .dir = IIO_EV_DIR_RISING, 387 .mask_separate = BIT(IIO_EV_INFO_VALUE) | 388 BIT(IIO_EV_INFO_ENABLE), 389 }, 390 { 391 .type = IIO_EV_TYPE_THRESH, 392 .dir = IIO_EV_DIR_FALLING, 393 .mask_separate = BIT(IIO_EV_INFO_VALUE) | 394 BIT(IIO_EV_INFO_ENABLE), 395 }, 396 }; 397 398 static const struct iio_chan_spec tmp007_channels[] = { 399 { 400 .type = IIO_TEMP, 401 .modified = 1, 402 .channel2 = IIO_MOD_TEMP_AMBIENT, 403 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 404 BIT(IIO_CHAN_INFO_SCALE), 405 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), 406 .event_spec = tmp007_die_event, 407 .num_event_specs = ARRAY_SIZE(tmp007_die_event), 408 }, 409 { 410 .type = IIO_TEMP, 411 .modified = 1, 412 .channel2 = IIO_MOD_TEMP_OBJECT, 413 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 414 BIT(IIO_CHAN_INFO_SCALE), 415 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), 416 .event_spec = tmp007_obj_event, 417 .num_event_specs = ARRAY_SIZE(tmp007_obj_event), 418 } 419 }; 420 421 static const struct iio_info tmp007_info = { 422 .read_raw = tmp007_read_raw, 423 .write_raw = tmp007_write_raw, 424 .read_event_config = tmp007_read_event_config, 425 .write_event_config = tmp007_write_event_config, 426 .read_event_value = tmp007_read_thresh, 427 .write_event_value = tmp007_write_thresh, 428 .attrs = &tmp007_attribute_group, 429 .driver_module = THIS_MODULE, 430 }; 431 432 static bool tmp007_identify(struct i2c_client *client) 433 { 434 int manf_id, dev_id; 435 436 manf_id = i2c_smbus_read_word_swapped(client, TMP007_MANUFACTURER_ID); 437 if (manf_id < 0) 438 return false; 439 440 dev_id = i2c_smbus_read_word_swapped(client, TMP007_DEVICE_ID); 441 if (dev_id < 0) 442 return false; 443 444 return (manf_id == TMP007_MANUFACTURER_MAGIC && dev_id == TMP007_DEVICE_MAGIC); 445 } 446 447 static int tmp007_probe(struct i2c_client *client, 448 const struct i2c_device_id *tmp007_id) 449 { 450 struct tmp007_data *data; 451 struct iio_dev *indio_dev; 452 int ret; 453 454 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) 455 return -EOPNOTSUPP; 456 457 if (!tmp007_identify(client)) { 458 dev_err(&client->dev, "TMP007 not found\n"); 459 return -ENODEV; 460 } 461 462 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 463 if (!indio_dev) 464 return -ENOMEM; 465 466 data = iio_priv(indio_dev); 467 i2c_set_clientdata(client, indio_dev); 468 data->client = client; 469 mutex_init(&data->lock); 470 471 indio_dev->dev.parent = &client->dev; 472 indio_dev->name = "tmp007"; 473 indio_dev->modes = INDIO_DIRECT_MODE; 474 indio_dev->info = &tmp007_info; 475 476 indio_dev->channels = tmp007_channels; 477 indio_dev->num_channels = ARRAY_SIZE(tmp007_channels); 478 479 /* 480 * Set Configuration register: 481 * 1. Conversion ON 482 * 2. ALERT enable 483 * 3. Transient correction enable 484 */ 485 486 ret = i2c_smbus_read_word_swapped(data->client, TMP007_CONFIG); 487 if (ret < 0) 488 return ret; 489 490 data->config = ret; 491 data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_ALERT_EN | TMP007_CONFIG_TC_EN); 492 493 ret = i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG, 494 data->config); 495 if (ret < 0) 496 return ret; 497 498 /* 499 * Only the following flags can activate ALERT pin. Data conversion/validity flags 500 * flags can still be polled for getting temperature data 501 * 502 * Set Status Mask register: 503 * 1. Object temperature high limit enable 504 * 2. Object temperature low limit enable 505 * 3. TDIE temperature high limit enable 506 * 4. TDIE temperature low limit enable 507 */ 508 509 ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK); 510 if (ret < 0) 511 goto error_powerdown; 512 513 data->status_mask = ret; 514 data->status_mask |= (TMP007_STATUS_OHF | TMP007_STATUS_OLF 515 | TMP007_STATUS_LHF | TMP007_STATUS_LLF); 516 517 ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK, data->status_mask); 518 if (ret < 0) 519 goto error_powerdown; 520 521 if (client->irq) { 522 ret = devm_request_threaded_irq(&client->dev, client->irq, 523 NULL, tmp007_interrupt_handler, 524 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 525 tmp007_id->name, indio_dev); 526 if (ret) { 527 dev_err(&client->dev, "irq request error %d\n", -ret); 528 goto error_powerdown; 529 } 530 } 531 532 return iio_device_register(indio_dev); 533 534 error_powerdown: 535 tmp007_powerdown(data); 536 537 return ret; 538 } 539 540 static int tmp007_remove(struct i2c_client *client) 541 { 542 struct iio_dev *indio_dev = i2c_get_clientdata(client); 543 struct tmp007_data *data = iio_priv(indio_dev); 544 545 iio_device_unregister(indio_dev); 546 tmp007_powerdown(data); 547 548 return 0; 549 } 550 551 #ifdef CONFIG_PM_SLEEP 552 static int tmp007_suspend(struct device *dev) 553 { 554 struct tmp007_data *data = iio_priv(i2c_get_clientdata( 555 to_i2c_client(dev))); 556 557 return tmp007_powerdown(data); 558 } 559 560 static int tmp007_resume(struct device *dev) 561 { 562 struct tmp007_data *data = iio_priv(i2c_get_clientdata( 563 to_i2c_client(dev))); 564 565 return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG, 566 data->config | TMP007_CONFIG_CONV_EN); 567 } 568 #endif 569 570 static SIMPLE_DEV_PM_OPS(tmp007_pm_ops, tmp007_suspend, tmp007_resume); 571 572 static const struct of_device_id tmp007_of_match[] = { 573 { .compatible = "ti,tmp007", }, 574 { }, 575 }; 576 MODULE_DEVICE_TABLE(of, tmp007_of_match); 577 578 static const struct i2c_device_id tmp007_id[] = { 579 { "tmp007", 0 }, 580 { } 581 }; 582 MODULE_DEVICE_TABLE(i2c, tmp007_id); 583 584 static struct i2c_driver tmp007_driver = { 585 .driver = { 586 .name = "tmp007", 587 .of_match_table = of_match_ptr(tmp007_of_match), 588 .pm = &tmp007_pm_ops, 589 }, 590 .probe = tmp007_probe, 591 .remove = tmp007_remove, 592 .id_table = tmp007_id, 593 }; 594 module_i2c_driver(tmp007_driver); 595 596 MODULE_AUTHOR("Manivannan Sadhasivam <manivannanece23@gmail.com>"); 597 MODULE_DESCRIPTION("TI TMP007 IR thermopile sensor driver"); 598 MODULE_LICENSE("GPL"); 599