1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * mcp9600.c - Support for Microchip MCP9600 thermocouple EMF converter 4 * 5 * Copyright (c) 2022 Andrew Hepp 6 * Author: <andrew.hepp@ahepp.dev> 7 */ 8 9 #include <linux/bitfield.h> 10 #include <linux/bitops.h> 11 #include <linux/bits.h> 12 #include <linux/err.h> 13 #include <linux/i2c.h> 14 #include <linux/init.h> 15 #include <linux/interrupt.h> 16 #include <linux/irq.h> 17 #include <linux/math.h> 18 #include <linux/minmax.h> 19 #include <linux/mod_devicetable.h> 20 #include <linux/module.h> 21 22 #include <linux/iio/events.h> 23 #include <linux/iio/iio.h> 24 25 #include <dt-bindings/iio/temperature/thermocouple.h> 26 27 /* MCP9600 registers */ 28 #define MCP9600_HOT_JUNCTION 0x00 29 #define MCP9600_COLD_JUNCTION 0x02 30 #define MCP9600_STATUS 0x04 31 #define MCP9600_STATUS_ALERT(x) BIT(x) 32 #define MCP9600_SENSOR_CFG 0x05 33 #define MCP9600_SENSOR_TYPE_MASK GENMASK(6, 4) 34 #define MCP9600_ALERT_CFG1 0x08 35 #define MCP9600_ALERT_CFG(x) (MCP9600_ALERT_CFG1 + (x - 1)) 36 #define MCP9600_ALERT_CFG_ENABLE BIT(0) 37 #define MCP9600_ALERT_CFG_ACTIVE_HIGH BIT(2) 38 #define MCP9600_ALERT_CFG_FALLING BIT(3) 39 #define MCP9600_ALERT_CFG_COLD_JUNCTION BIT(4) 40 #define MCP9600_ALERT_HYSTERESIS1 0x0c 41 #define MCP9600_ALERT_HYSTERESIS(x) (MCP9600_ALERT_HYSTERESIS1 + (x - 1)) 42 #define MCP9600_ALERT_LIMIT1 0x10 43 #define MCP9600_ALERT_LIMIT(x) (MCP9600_ALERT_LIMIT1 + (x - 1)) 44 #define MCP9600_ALERT_LIMIT_MASK GENMASK(15, 2) 45 #define MCP9600_DEVICE_ID 0x20 46 47 /* MCP9600 device id value */ 48 #define MCP9600_DEVICE_ID_MCP9600 0x40 49 #define MCP9600_DEVICE_ID_MCP9601 0x41 50 51 #define MCP9600_ALERT_COUNT 4 52 53 #define MCP9600_MIN_TEMP_HOT_JUNCTION_MICRO -200000000 54 #define MCP9600_MAX_TEMP_HOT_JUNCTION_MICRO 1800000000 55 56 #define MCP9600_MIN_TEMP_COLD_JUNCTION_MICRO -40000000 57 #define MCP9600_MAX_TEMP_COLD_JUNCTION_MICRO 125000000 58 59 enum mcp9600_alert { 60 MCP9600_ALERT1, 61 MCP9600_ALERT2, 62 MCP9600_ALERT3, 63 MCP9600_ALERT4 64 }; 65 66 static const char * const mcp9600_alert_name[MCP9600_ALERT_COUNT] = { 67 [MCP9600_ALERT1] = "alert1", 68 [MCP9600_ALERT2] = "alert2", 69 [MCP9600_ALERT3] = "alert3", 70 [MCP9600_ALERT4] = "alert4", 71 }; 72 73 /* Map between dt-bindings enum and the chip's type value */ 74 static const unsigned int mcp9600_type_map[] = { 75 [THERMOCOUPLE_TYPE_K] = 0, 76 [THERMOCOUPLE_TYPE_J] = 1, 77 [THERMOCOUPLE_TYPE_T] = 2, 78 [THERMOCOUPLE_TYPE_N] = 3, 79 [THERMOCOUPLE_TYPE_S] = 4, 80 [THERMOCOUPLE_TYPE_E] = 5, 81 [THERMOCOUPLE_TYPE_B] = 6, 82 [THERMOCOUPLE_TYPE_R] = 7, 83 }; 84 85 /* Map thermocouple type to a char for iio info in sysfs */ 86 static const int mcp9600_tc_types[] = { 87 [THERMOCOUPLE_TYPE_K] = 'K', 88 [THERMOCOUPLE_TYPE_J] = 'J', 89 [THERMOCOUPLE_TYPE_T] = 'T', 90 [THERMOCOUPLE_TYPE_N] = 'N', 91 [THERMOCOUPLE_TYPE_S] = 'S', 92 [THERMOCOUPLE_TYPE_E] = 'E', 93 [THERMOCOUPLE_TYPE_B] = 'B', 94 [THERMOCOUPLE_TYPE_R] = 'R', 95 }; 96 97 static const struct iio_event_spec mcp9600_events[] = { 98 { 99 .type = IIO_EV_TYPE_THRESH, 100 .dir = IIO_EV_DIR_RISING, 101 .mask_separate = BIT(IIO_EV_INFO_ENABLE) | 102 BIT(IIO_EV_INFO_VALUE) | 103 BIT(IIO_EV_INFO_HYSTERESIS), 104 }, 105 { 106 .type = IIO_EV_TYPE_THRESH, 107 .dir = IIO_EV_DIR_FALLING, 108 .mask_separate = BIT(IIO_EV_INFO_ENABLE) | 109 BIT(IIO_EV_INFO_VALUE) | 110 BIT(IIO_EV_INFO_HYSTERESIS), 111 }, 112 }; 113 114 struct mcp_chip_info { 115 u8 chip_id; 116 const char *chip_name; 117 }; 118 119 struct mcp9600_data { 120 struct i2c_client *client; 121 u32 thermocouple_type; 122 }; 123 124 static int mcp9600_config(struct mcp9600_data *data) 125 { 126 struct i2c_client *client = data->client; 127 int ret; 128 u8 cfg; 129 130 cfg = FIELD_PREP(MCP9600_SENSOR_TYPE_MASK, 131 mcp9600_type_map[data->thermocouple_type]); 132 133 ret = i2c_smbus_write_byte_data(client, MCP9600_SENSOR_CFG, cfg); 134 if (ret < 0) { 135 dev_err(&client->dev, "Failed to set sensor configuration\n"); 136 return ret; 137 } 138 139 return 0; 140 } 141 142 #define MCP9600_CHANNELS(hj_num_ev, hj_ev_spec_off, cj_num_ev, cj_ev_spec_off) \ 143 { \ 144 { \ 145 .type = IIO_TEMP, \ 146 .address = MCP9600_HOT_JUNCTION, \ 147 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 148 BIT(IIO_CHAN_INFO_THERMOCOUPLE_TYPE) | \ 149 BIT(IIO_CHAN_INFO_SCALE), \ 150 .event_spec = &mcp9600_events[hj_ev_spec_off], \ 151 .num_event_specs = hj_num_ev, \ 152 }, \ 153 { \ 154 .type = IIO_TEMP, \ 155 .address = MCP9600_COLD_JUNCTION, \ 156 .channel2 = IIO_MOD_TEMP_AMBIENT, \ 157 .modified = 1, \ 158 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 159 BIT(IIO_CHAN_INFO_SCALE), \ 160 .event_spec = &mcp9600_events[cj_ev_spec_off], \ 161 .num_event_specs = cj_num_ev, \ 162 }, \ 163 } 164 165 static const struct iio_chan_spec mcp9600_channels[][2] = { 166 MCP9600_CHANNELS(0, 0, 0, 0), /* Alerts: - - - - */ 167 MCP9600_CHANNELS(1, 0, 0, 0), /* Alerts: 1 - - - */ 168 MCP9600_CHANNELS(1, 1, 0, 0), /* Alerts: - 2 - - */ 169 MCP9600_CHANNELS(2, 0, 0, 0), /* Alerts: 1 2 - - */ 170 MCP9600_CHANNELS(0, 0, 1, 0), /* Alerts: - - 3 - */ 171 MCP9600_CHANNELS(1, 0, 1, 0), /* Alerts: 1 - 3 - */ 172 MCP9600_CHANNELS(1, 1, 1, 0), /* Alerts: - 2 3 - */ 173 MCP9600_CHANNELS(2, 0, 1, 0), /* Alerts: 1 2 3 - */ 174 MCP9600_CHANNELS(0, 0, 1, 1), /* Alerts: - - - 4 */ 175 MCP9600_CHANNELS(1, 0, 1, 1), /* Alerts: 1 - - 4 */ 176 MCP9600_CHANNELS(1, 1, 1, 1), /* Alerts: - 2 - 4 */ 177 MCP9600_CHANNELS(2, 0, 1, 1), /* Alerts: 1 2 - 4 */ 178 MCP9600_CHANNELS(0, 0, 2, 0), /* Alerts: - - 3 4 */ 179 MCP9600_CHANNELS(1, 0, 2, 0), /* Alerts: 1 - 3 4 */ 180 MCP9600_CHANNELS(1, 1, 2, 0), /* Alerts: - 2 3 4 */ 181 MCP9600_CHANNELS(2, 0, 2, 0), /* Alerts: 1 2 3 4 */ 182 }; 183 184 static int mcp9600_read(struct mcp9600_data *data, 185 struct iio_chan_spec const *chan, int *val) 186 { 187 int ret; 188 189 ret = i2c_smbus_read_word_swapped(data->client, chan->address); 190 191 if (ret < 0) 192 return ret; 193 194 *val = sign_extend32(ret, 15); 195 196 return 0; 197 } 198 199 static int mcp9600_read_raw(struct iio_dev *indio_dev, 200 struct iio_chan_spec const *chan, int *val, 201 int *val2, long mask) 202 { 203 struct mcp9600_data *data = iio_priv(indio_dev); 204 int ret; 205 206 switch (mask) { 207 case IIO_CHAN_INFO_RAW: 208 ret = mcp9600_read(data, chan, val); 209 if (ret) 210 return ret; 211 return IIO_VAL_INT; 212 case IIO_CHAN_INFO_SCALE: 213 *val = 62; 214 *val2 = 500000; 215 return IIO_VAL_INT_PLUS_MICRO; 216 case IIO_CHAN_INFO_THERMOCOUPLE_TYPE: 217 *val = mcp9600_tc_types[data->thermocouple_type]; 218 return IIO_VAL_CHAR; 219 default: 220 return -EINVAL; 221 } 222 } 223 224 static int mcp9600_get_alert_index(int channel2, enum iio_event_direction dir) 225 { 226 if (channel2 == IIO_MOD_TEMP_AMBIENT) { 227 if (dir == IIO_EV_DIR_RISING) 228 return MCP9600_ALERT3; 229 else 230 return MCP9600_ALERT4; 231 } else { 232 if (dir == IIO_EV_DIR_RISING) 233 return MCP9600_ALERT1; 234 else 235 return MCP9600_ALERT2; 236 } 237 } 238 239 static int mcp9600_read_event_config(struct iio_dev *indio_dev, 240 const struct iio_chan_spec *chan, 241 enum iio_event_type type, 242 enum iio_event_direction dir) 243 { 244 struct mcp9600_data *data = iio_priv(indio_dev); 245 struct i2c_client *client = data->client; 246 int i, ret; 247 248 i = mcp9600_get_alert_index(chan->channel2, dir); 249 ret = i2c_smbus_read_byte_data(client, MCP9600_ALERT_CFG(i + 1)); 250 if (ret < 0) 251 return ret; 252 253 return FIELD_GET(MCP9600_ALERT_CFG_ENABLE, ret); 254 } 255 256 static int mcp9600_write_event_config(struct iio_dev *indio_dev, 257 const struct iio_chan_spec *chan, 258 enum iio_event_type type, 259 enum iio_event_direction dir, 260 bool state) 261 { 262 struct mcp9600_data *data = iio_priv(indio_dev); 263 struct i2c_client *client = data->client; 264 int i, ret; 265 266 i = mcp9600_get_alert_index(chan->channel2, dir); 267 ret = i2c_smbus_read_byte_data(client, MCP9600_ALERT_CFG(i + 1)); 268 if (ret < 0) 269 return ret; 270 271 if (state) 272 ret |= MCP9600_ALERT_CFG_ENABLE; 273 else 274 ret &= ~MCP9600_ALERT_CFG_ENABLE; 275 276 return i2c_smbus_write_byte_data(client, MCP9600_ALERT_CFG(i + 1), ret); 277 } 278 279 static int mcp9600_read_thresh(struct iio_dev *indio_dev, 280 const struct iio_chan_spec *chan, 281 enum iio_event_type type, 282 enum iio_event_direction dir, 283 enum iio_event_info info, int *val, int *val2) 284 { 285 struct mcp9600_data *data = iio_priv(indio_dev); 286 struct i2c_client *client = data->client; 287 s32 ret; 288 int i; 289 290 i = mcp9600_get_alert_index(chan->channel2, dir); 291 switch (info) { 292 case IIO_EV_INFO_VALUE: 293 ret = i2c_smbus_read_word_swapped(client, MCP9600_ALERT_LIMIT(i + 1)); 294 if (ret < 0) 295 return ret; 296 /* 297 * Temperature is stored in two’s complement format in 298 * bits(15:2), LSB is 0.25 degree celsius. 299 */ 300 *val = sign_extend32(FIELD_GET(MCP9600_ALERT_LIMIT_MASK, ret), 13); 301 *val2 = 4; 302 return IIO_VAL_FRACTIONAL; 303 case IIO_EV_INFO_HYSTERESIS: 304 ret = i2c_smbus_read_byte_data(client, MCP9600_ALERT_HYSTERESIS(i + 1)); 305 if (ret < 0) 306 return ret; 307 308 *val = ret; 309 return IIO_VAL_INT; 310 default: 311 return -EINVAL; 312 } 313 } 314 315 static int mcp9600_write_thresh(struct iio_dev *indio_dev, 316 const struct iio_chan_spec *chan, 317 enum iio_event_type type, 318 enum iio_event_direction dir, 319 enum iio_event_info info, int val, int val2) 320 { 321 struct mcp9600_data *data = iio_priv(indio_dev); 322 struct i2c_client *client = data->client; 323 int s_val, i; 324 s16 thresh; 325 u8 hyst; 326 327 i = mcp9600_get_alert_index(chan->channel2, dir); 328 switch (info) { 329 case IIO_EV_INFO_VALUE: 330 /* Scale value to include decimal part into calculations */ 331 s_val = (val < 0) ? ((val * 1000000) - val2) : 332 ((val * 1000000) + val2); 333 if (chan->channel2 == IIO_MOD_TEMP_AMBIENT) { 334 s_val = max(s_val, MCP9600_MIN_TEMP_COLD_JUNCTION_MICRO); 335 s_val = min(s_val, MCP9600_MAX_TEMP_COLD_JUNCTION_MICRO); 336 } else { 337 s_val = max(s_val, MCP9600_MIN_TEMP_HOT_JUNCTION_MICRO); 338 s_val = min(s_val, MCP9600_MAX_TEMP_HOT_JUNCTION_MICRO); 339 } 340 341 /* 342 * Shift length 4 bits = 2(15:2) + 2(0.25 LSB), temperature is 343 * stored in two’s complement format. 344 */ 345 thresh = (s16)(s_val / (1000000 >> 4)); 346 return i2c_smbus_write_word_swapped(client, 347 MCP9600_ALERT_LIMIT(i + 1), 348 thresh); 349 case IIO_EV_INFO_HYSTERESIS: 350 hyst = min(abs(val), 255); 351 return i2c_smbus_write_byte_data(client, 352 MCP9600_ALERT_HYSTERESIS(i + 1), 353 hyst); 354 default: 355 return -EINVAL; 356 } 357 } 358 359 static const struct iio_info mcp9600_info = { 360 .read_raw = mcp9600_read_raw, 361 .read_event_config = mcp9600_read_event_config, 362 .write_event_config = mcp9600_write_event_config, 363 .read_event_value = mcp9600_read_thresh, 364 .write_event_value = mcp9600_write_thresh, 365 }; 366 367 static irqreturn_t mcp9600_alert_handler(void *private, 368 enum mcp9600_alert alert, 369 enum iio_modifier mod, 370 enum iio_event_direction dir) 371 { 372 struct iio_dev *indio_dev = private; 373 struct mcp9600_data *data = iio_priv(indio_dev); 374 int ret; 375 376 ret = i2c_smbus_read_byte_data(data->client, MCP9600_STATUS); 377 if (ret < 0) 378 return IRQ_HANDLED; 379 380 if (!(ret & MCP9600_STATUS_ALERT(alert))) 381 return IRQ_NONE; 382 383 iio_push_event(indio_dev, 384 IIO_MOD_EVENT_CODE(IIO_TEMP, 0, mod, IIO_EV_TYPE_THRESH, 385 dir), 386 iio_get_time_ns(indio_dev)); 387 388 return IRQ_HANDLED; 389 } 390 391 static irqreturn_t mcp9600_alert1_handler(int irq, void *private) 392 { 393 return mcp9600_alert_handler(private, MCP9600_ALERT1, IIO_NO_MOD, 394 IIO_EV_DIR_RISING); 395 } 396 397 static irqreturn_t mcp9600_alert2_handler(int irq, void *private) 398 { 399 return mcp9600_alert_handler(private, MCP9600_ALERT2, IIO_NO_MOD, 400 IIO_EV_DIR_FALLING); 401 } 402 403 static irqreturn_t mcp9600_alert3_handler(int irq, void *private) 404 { 405 return mcp9600_alert_handler(private, MCP9600_ALERT3, 406 IIO_MOD_TEMP_AMBIENT, IIO_EV_DIR_RISING); 407 } 408 409 static irqreturn_t mcp9600_alert4_handler(int irq, void *private) 410 { 411 return mcp9600_alert_handler(private, MCP9600_ALERT4, 412 IIO_MOD_TEMP_AMBIENT, IIO_EV_DIR_FALLING); 413 } 414 415 static irqreturn_t (*mcp9600_alert_handler_func[MCP9600_ALERT_COUNT]) (int, void *) = { 416 mcp9600_alert1_handler, 417 mcp9600_alert2_handler, 418 mcp9600_alert3_handler, 419 mcp9600_alert4_handler, 420 }; 421 422 static int mcp9600_probe_alerts(struct iio_dev *indio_dev) 423 { 424 struct mcp9600_data *data = iio_priv(indio_dev); 425 struct i2c_client *client = data->client; 426 struct device *dev = &client->dev; 427 struct fwnode_handle *fwnode = dev_fwnode(dev); 428 unsigned int irq_type; 429 int ret, irq, i; 430 u8 val, ch_sel; 431 432 /* 433 * alert1: hot junction, rising temperature 434 * alert2: hot junction, falling temperature 435 * alert3: cold junction, rising temperature 436 * alert4: cold junction, falling temperature 437 */ 438 ch_sel = 0; 439 for (i = 0; i < MCP9600_ALERT_COUNT; i++) { 440 irq = fwnode_irq_get_byname(fwnode, mcp9600_alert_name[i]); 441 if (irq <= 0) 442 continue; 443 444 val = 0; 445 irq_type = irq_get_trigger_type(irq); 446 if (irq_type == IRQ_TYPE_EDGE_RISING) 447 val |= MCP9600_ALERT_CFG_ACTIVE_HIGH; 448 449 if (i == MCP9600_ALERT2 || i == MCP9600_ALERT4) 450 val |= MCP9600_ALERT_CFG_FALLING; 451 452 if (i == MCP9600_ALERT3 || i == MCP9600_ALERT4) 453 val |= MCP9600_ALERT_CFG_COLD_JUNCTION; 454 455 ret = i2c_smbus_write_byte_data(client, 456 MCP9600_ALERT_CFG(i + 1), 457 val); 458 if (ret < 0) 459 return ret; 460 461 ret = devm_request_threaded_irq(dev, irq, NULL, 462 mcp9600_alert_handler_func[i], 463 IRQF_ONESHOT, "mcp9600", 464 indio_dev); 465 if (ret) 466 return ret; 467 468 ch_sel |= BIT(i); 469 } 470 471 return ch_sel; 472 } 473 474 static int mcp9600_probe(struct i2c_client *client) 475 { 476 struct device *dev = &client->dev; 477 const struct mcp_chip_info *chip_info; 478 struct iio_dev *indio_dev; 479 struct mcp9600_data *data; 480 int ch_sel, dev_id, ret; 481 482 chip_info = i2c_get_match_data(client); 483 if (!chip_info) 484 return dev_err_probe(dev, -ENODEV, 485 "No chip-info found for device\n"); 486 487 dev_id = i2c_smbus_read_byte_data(client, MCP9600_DEVICE_ID); 488 if (dev_id < 0) 489 return dev_err_probe(dev, dev_id, "Failed to read device ID\n"); 490 491 switch (dev_id) { 492 case MCP9600_DEVICE_ID_MCP9600: 493 case MCP9600_DEVICE_ID_MCP9601: 494 if (dev_id != chip_info->chip_id) 495 dev_warn(dev, 496 "Expected id %02x, but device responded with %02x\n", 497 chip_info->chip_id, dev_id); 498 break; 499 500 default: 501 dev_warn(dev, "Unknown id %x, using %x\n", dev_id, 502 chip_info->chip_id); 503 } 504 505 indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 506 if (!indio_dev) 507 return -ENOMEM; 508 509 data = iio_priv(indio_dev); 510 data->client = client; 511 512 /* Accept type from dt with default of Type-K. */ 513 data->thermocouple_type = THERMOCOUPLE_TYPE_K; 514 ret = device_property_read_u32(dev, "thermocouple-type", 515 &data->thermocouple_type); 516 if (ret && ret != -EINVAL) 517 return dev_err_probe(dev, ret, 518 "Error reading thermocouple-type property\n"); 519 520 if (data->thermocouple_type >= ARRAY_SIZE(mcp9600_type_map)) 521 return dev_err_probe(dev, -EINVAL, 522 "Invalid thermocouple-type property %u.\n", 523 data->thermocouple_type); 524 525 /* Set initial config. */ 526 ret = mcp9600_config(data); 527 if (ret) 528 return ret; 529 530 ch_sel = mcp9600_probe_alerts(indio_dev); 531 if (ch_sel < 0) 532 return ch_sel; 533 534 indio_dev->info = &mcp9600_info; 535 indio_dev->name = chip_info->chip_name; 536 indio_dev->modes = INDIO_DIRECT_MODE; 537 indio_dev->channels = mcp9600_channels[ch_sel]; 538 indio_dev->num_channels = ARRAY_SIZE(mcp9600_channels[ch_sel]); 539 540 return devm_iio_device_register(dev, indio_dev); 541 } 542 543 static const struct mcp_chip_info mcp9600_chip_info = { 544 .chip_id = MCP9600_DEVICE_ID_MCP9600, 545 .chip_name = "mcp9600", 546 }; 547 548 static const struct mcp_chip_info mcp9601_chip_info = { 549 .chip_id = MCP9600_DEVICE_ID_MCP9601, 550 .chip_name = "mcp9601", 551 }; 552 553 static const struct i2c_device_id mcp9600_id[] = { 554 { "mcp9600", .driver_data = (kernel_ulong_t)&mcp9600_chip_info }, 555 { "mcp9601", .driver_data = (kernel_ulong_t)&mcp9601_chip_info }, 556 { } 557 }; 558 MODULE_DEVICE_TABLE(i2c, mcp9600_id); 559 560 static const struct of_device_id mcp9600_of_match[] = { 561 { .compatible = "microchip,mcp9600", .data = &mcp9600_chip_info }, 562 { .compatible = "microchip,mcp9601", .data = &mcp9601_chip_info }, 563 { } 564 }; 565 MODULE_DEVICE_TABLE(of, mcp9600_of_match); 566 567 static struct i2c_driver mcp9600_driver = { 568 .driver = { 569 .name = "mcp9600", 570 .of_match_table = mcp9600_of_match, 571 }, 572 .probe = mcp9600_probe, 573 .id_table = mcp9600_id 574 }; 575 module_i2c_driver(mcp9600_driver); 576 577 MODULE_AUTHOR("Dimitri Fedrau <dima.fedrau@gmail.com>"); 578 MODULE_AUTHOR("Andrew Hepp <andrew.hepp@ahepp.dev>"); 579 MODULE_DESCRIPTION("Microchip MCP9600 thermocouple EMF converter driver"); 580 MODULE_LICENSE("GPL"); 581