Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: mcp9600: Recognize chip id for mcp9601

The current driver works with mcp9601, but emits a warning because it
does not recognize the chip id.

MCP9601 is a superset of MCP9600. The drivers works without changes
on this chipset.

However, the 9601 chip supports open/closed-circuit detection if wired
properly, so we'll need to be able to differentiate between them.

Moved "struct mcp9600_data" up in the file since a later patch will
need it and chip_info before the declarations.

Signed-off-by: Ben Collins <bcollins@watter.com>
Reviewed-by: David Lechner <dlechner@baylibre.com>
Link: https://patch.msgid.link/20250822-upstream-changes-v8-4-40bb1739e3e2@watter.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Ben Collins and committed by
Jonathan Cameron
5efd60c9 74cae3eb

+57 -19
+5 -3
drivers/iio/temperature/Kconfig
··· 173 173 will be called max31865. 174 174 175 175 config MCP9600 176 - tristate "MCP9600 thermocouple EMF converter" 176 + tristate "MCP9600 and similar thermocouple EMF converters" 177 177 depends on I2C 178 178 help 179 - If you say yes here you get support for MCP9600 180 - thermocouple EMF converter connected via I2C. 179 + If you say yes here you get support for... 180 + - MCP9600 181 + - MCP9601 182 + ...thermocouple EMF converters connected via I2C. 181 183 182 184 This driver can also be built as a module. If so, the module 183 185 will be called mcp9600.
+52 -16
drivers/iio/temperature/mcp9600.c
··· 42 42 43 43 /* MCP9600 device id value */ 44 44 #define MCP9600_DEVICE_ID_MCP9600 0x40 45 + #define MCP9600_DEVICE_ID_MCP9601 0x41 45 46 46 47 #define MCP9600_ALERT_COUNT 4 47 48 ··· 81 80 BIT(IIO_EV_INFO_VALUE) | 82 81 BIT(IIO_EV_INFO_HYSTERESIS), 83 82 }, 83 + }; 84 + 85 + struct mcp_chip_info { 86 + u8 chip_id; 87 + const char *chip_name; 88 + }; 89 + 90 + struct mcp9600_data { 91 + struct i2c_client *client; 84 92 }; 85 93 86 94 #define MCP9600_CHANNELS(hj_num_ev, hj_ev_spec_off, cj_num_ev, cj_ev_spec_off) \ ··· 131 121 MCP9600_CHANNELS(1, 0, 2, 0), /* Alerts: 1 - 3 4 */ 132 122 MCP9600_CHANNELS(1, 1, 2, 0), /* Alerts: - 2 3 4 */ 133 123 MCP9600_CHANNELS(2, 0, 2, 0), /* Alerts: 1 2 3 4 */ 134 - }; 135 - 136 - struct mcp9600_data { 137 - struct i2c_client *client; 138 124 }; 139 125 140 126 static int mcp9600_read(struct mcp9600_data *data, ··· 422 416 423 417 static int mcp9600_probe(struct i2c_client *client) 424 418 { 419 + struct device *dev = &client->dev; 420 + const struct mcp_chip_info *chip_info; 425 421 struct iio_dev *indio_dev; 426 422 struct mcp9600_data *data; 427 - int ret, ch_sel; 423 + int ch_sel, dev_id; 428 424 429 - ret = i2c_smbus_read_byte_data(client, MCP9600_DEVICE_ID); 430 - if (ret < 0) 431 - return dev_err_probe(&client->dev, ret, "Failed to read device ID\n"); 432 - if (ret != MCP9600_DEVICE_ID_MCP9600) 433 - dev_warn(&client->dev, "Expected ID %x, got %x\n", 434 - MCP9600_DEVICE_ID_MCP9600, ret); 425 + chip_info = i2c_get_match_data(client); 426 + if (!chip_info) 427 + return dev_err_probe(dev, -ENODEV, 428 + "No chip-info found for device\n"); 435 429 436 - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 430 + dev_id = i2c_smbus_read_byte_data(client, MCP9600_DEVICE_ID); 431 + if (dev_id < 0) 432 + return dev_err_probe(dev, dev_id, "Failed to read device ID\n"); 433 + 434 + switch (dev_id) { 435 + case MCP9600_DEVICE_ID_MCP9600: 436 + case MCP9600_DEVICE_ID_MCP9601: 437 + if (dev_id != chip_info->chip_id) 438 + dev_warn(dev, 439 + "Expected id %02x, but device responded with %02x\n", 440 + chip_info->chip_id, dev_id); 441 + break; 442 + 443 + default: 444 + dev_warn(dev, "Unknown id %x, using %x\n", dev_id, 445 + chip_info->chip_id); 446 + } 447 + 448 + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 437 449 if (!indio_dev) 438 450 return -ENOMEM; 439 451 ··· 463 439 return ch_sel; 464 440 465 441 indio_dev->info = &mcp9600_info; 466 - indio_dev->name = "mcp9600"; 442 + indio_dev->name = chip_info->chip_name; 467 443 indio_dev->modes = INDIO_DIRECT_MODE; 468 444 indio_dev->channels = mcp9600_channels[ch_sel]; 469 445 indio_dev->num_channels = ARRAY_SIZE(mcp9600_channels[ch_sel]); 470 446 471 - return devm_iio_device_register(&client->dev, indio_dev); 447 + return devm_iio_device_register(dev, indio_dev); 472 448 } 473 449 450 + static const struct mcp_chip_info mcp9600_chip_info = { 451 + .chip_id = MCP9600_DEVICE_ID_MCP9600, 452 + .chip_name = "mcp9600", 453 + }; 454 + 455 + static const struct mcp_chip_info mcp9601_chip_info = { 456 + .chip_id = MCP9600_DEVICE_ID_MCP9601, 457 + .chip_name = "mcp9601", 458 + }; 459 + 474 460 static const struct i2c_device_id mcp9600_id[] = { 475 - { "mcp9600" }, 461 + { "mcp9600", .driver_data = (kernel_ulong_t)&mcp9600_chip_info }, 462 + { "mcp9601", .driver_data = (kernel_ulong_t)&mcp9601_chip_info }, 476 463 { } 477 464 }; 478 465 MODULE_DEVICE_TABLE(i2c, mcp9600_id); 479 466 480 467 static const struct of_device_id mcp9600_of_match[] = { 481 - { .compatible = "microchip,mcp9600" }, 468 + { .compatible = "microchip,mcp9600", .data = &mcp9600_chip_info }, 469 + { .compatible = "microchip,mcp9601", .data = &mcp9601_chip_info }, 482 470 { } 483 471 }; 484 472 MODULE_DEVICE_TABLE(of, mcp9600_of_match);