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 }; 430 431 static bool tmp007_identify(struct i2c_client *client) 432 { 433 int manf_id, dev_id; 434 435 manf_id = i2c_smbus_read_word_swapped(client, TMP007_MANUFACTURER_ID); 436 if (manf_id < 0) 437 return false; 438 439 dev_id = i2c_smbus_read_word_swapped(client, TMP007_DEVICE_ID); 440 if (dev_id < 0) 441 return false; 442 443 return (manf_id == TMP007_MANUFACTURER_MAGIC && dev_id == TMP007_DEVICE_MAGIC); 444 } 445 446 static int tmp007_probe(struct i2c_client *client, 447 const struct i2c_device_id *tmp007_id) 448 { 449 struct tmp007_data *data; 450 struct iio_dev *indio_dev; 451 int ret; 452 453 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) 454 return -EOPNOTSUPP; 455 456 if (!tmp007_identify(client)) { 457 dev_err(&client->dev, "TMP007 not found\n"); 458 return -ENODEV; 459 } 460 461 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 462 if (!indio_dev) 463 return -ENOMEM; 464 465 data = iio_priv(indio_dev); 466 i2c_set_clientdata(client, indio_dev); 467 data->client = client; 468 mutex_init(&data->lock); 469 470 indio_dev->dev.parent = &client->dev; 471 indio_dev->name = "tmp007"; 472 indio_dev->modes = INDIO_DIRECT_MODE; 473 indio_dev->info = &tmp007_info; 474 475 indio_dev->channels = tmp007_channels; 476 indio_dev->num_channels = ARRAY_SIZE(tmp007_channels); 477 478 /* 479 * Set Configuration register: 480 * 1. Conversion ON 481 * 2. ALERT enable 482 * 3. Transient correction enable 483 */ 484 485 ret = i2c_smbus_read_word_swapped(data->client, TMP007_CONFIG); 486 if (ret < 0) 487 return ret; 488 489 data->config = ret; 490 data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_ALERT_EN | TMP007_CONFIG_TC_EN); 491 492 ret = i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG, 493 data->config); 494 if (ret < 0) 495 return ret; 496 497 /* 498 * Only the following flags can activate ALERT pin. Data conversion/validity flags 499 * flags can still be polled for getting temperature data 500 * 501 * Set Status Mask register: 502 * 1. Object temperature high limit enable 503 * 2. Object temperature low limit enable 504 * 3. TDIE temperature high limit enable 505 * 4. TDIE temperature low limit enable 506 */ 507 508 ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK); 509 if (ret < 0) 510 goto error_powerdown; 511 512 data->status_mask = ret; 513 data->status_mask |= (TMP007_STATUS_OHF | TMP007_STATUS_OLF 514 | TMP007_STATUS_LHF | TMP007_STATUS_LLF); 515 516 ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK, data->status_mask); 517 if (ret < 0) 518 goto error_powerdown; 519 520 if (client->irq) { 521 ret = devm_request_threaded_irq(&client->dev, client->irq, 522 NULL, tmp007_interrupt_handler, 523 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 524 tmp007_id->name, indio_dev); 525 if (ret) { 526 dev_err(&client->dev, "irq request error %d\n", -ret); 527 goto error_powerdown; 528 } 529 } 530 531 return iio_device_register(indio_dev); 532 533 error_powerdown: 534 tmp007_powerdown(data); 535 536 return ret; 537 } 538 539 static int tmp007_remove(struct i2c_client *client) 540 { 541 struct iio_dev *indio_dev = i2c_get_clientdata(client); 542 struct tmp007_data *data = iio_priv(indio_dev); 543 544 iio_device_unregister(indio_dev); 545 tmp007_powerdown(data); 546 547 return 0; 548 } 549 550 #ifdef CONFIG_PM_SLEEP 551 static int tmp007_suspend(struct device *dev) 552 { 553 struct tmp007_data *data = iio_priv(i2c_get_clientdata( 554 to_i2c_client(dev))); 555 556 return tmp007_powerdown(data); 557 } 558 559 static int tmp007_resume(struct device *dev) 560 { 561 struct tmp007_data *data = iio_priv(i2c_get_clientdata( 562 to_i2c_client(dev))); 563 564 return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG, 565 data->config | TMP007_CONFIG_CONV_EN); 566 } 567 #endif 568 569 static SIMPLE_DEV_PM_OPS(tmp007_pm_ops, tmp007_suspend, tmp007_resume); 570 571 static const struct of_device_id tmp007_of_match[] = { 572 { .compatible = "ti,tmp007", }, 573 { }, 574 }; 575 MODULE_DEVICE_TABLE(of, tmp007_of_match); 576 577 static const struct i2c_device_id tmp007_id[] = { 578 { "tmp007", 0 }, 579 { } 580 }; 581 MODULE_DEVICE_TABLE(i2c, tmp007_id); 582 583 static struct i2c_driver tmp007_driver = { 584 .driver = { 585 .name = "tmp007", 586 .of_match_table = of_match_ptr(tmp007_of_match), 587 .pm = &tmp007_pm_ops, 588 }, 589 .probe = tmp007_probe, 590 .remove = tmp007_remove, 591 .id_table = tmp007_id, 592 }; 593 module_i2c_driver(tmp007_driver); 594 595 MODULE_AUTHOR("Manivannan Sadhasivam <manivannanece23@gmail.com>"); 596 MODULE_DESCRIPTION("TI TMP007 IR thermopile sensor driver"); 597 MODULE_LICENSE("GPL"); 598