136edc939SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
204e1e70aSTiberiu Breana /*
304e1e70aSTiberiu Breana * max31722 - hwmon driver for Maxim Integrated MAX31722/MAX31723 SPI
404e1e70aSTiberiu Breana * digital thermometer and thermostats.
504e1e70aSTiberiu Breana *
604e1e70aSTiberiu Breana * Copyright (c) 2016, Intel Corporation.
704e1e70aSTiberiu Breana */
804e1e70aSTiberiu Breana
904e1e70aSTiberiu Breana #include <linux/hwmon.h>
1004e1e70aSTiberiu Breana #include <linux/hwmon-sysfs.h>
1104e1e70aSTiberiu Breana #include <linux/kernel.h>
1204e1e70aSTiberiu Breana #include <linux/module.h>
1304e1e70aSTiberiu Breana #include <linux/spi/spi.h>
1404e1e70aSTiberiu Breana
1504e1e70aSTiberiu Breana #define MAX31722_REG_CFG 0x00
1604e1e70aSTiberiu Breana #define MAX31722_REG_TEMP_LSB 0x01
1704e1e70aSTiberiu Breana
1804e1e70aSTiberiu Breana #define MAX31722_MODE_CONTINUOUS 0x00
1904e1e70aSTiberiu Breana #define MAX31722_MODE_STANDBY 0x01
2004e1e70aSTiberiu Breana #define MAX31722_MODE_MASK 0xFE
2104e1e70aSTiberiu Breana #define MAX31722_RESOLUTION_12BIT 0x06
2204e1e70aSTiberiu Breana #define MAX31722_WRITE_MASK 0x80
2304e1e70aSTiberiu Breana
2404e1e70aSTiberiu Breana struct max31722_data {
2504e1e70aSTiberiu Breana struct device *hwmon_dev;
2604e1e70aSTiberiu Breana struct spi_device *spi_device;
2704e1e70aSTiberiu Breana u8 mode;
2804e1e70aSTiberiu Breana };
2904e1e70aSTiberiu Breana
max31722_set_mode(struct max31722_data * data,u8 mode)3004e1e70aSTiberiu Breana static int max31722_set_mode(struct max31722_data *data, u8 mode)
3104e1e70aSTiberiu Breana {
3204e1e70aSTiberiu Breana int ret;
3304e1e70aSTiberiu Breana struct spi_device *spi = data->spi_device;
3404e1e70aSTiberiu Breana u8 buf[2] = {
3504e1e70aSTiberiu Breana MAX31722_REG_CFG | MAX31722_WRITE_MASK,
3604e1e70aSTiberiu Breana (data->mode & MAX31722_MODE_MASK) | mode
3704e1e70aSTiberiu Breana };
3804e1e70aSTiberiu Breana
3904e1e70aSTiberiu Breana ret = spi_write(spi, &buf, sizeof(buf));
4004e1e70aSTiberiu Breana if (ret < 0) {
4104e1e70aSTiberiu Breana dev_err(&spi->dev, "failed to set sensor mode.\n");
4204e1e70aSTiberiu Breana return ret;
4304e1e70aSTiberiu Breana }
4404e1e70aSTiberiu Breana data->mode = (data->mode & MAX31722_MODE_MASK) | mode;
4504e1e70aSTiberiu Breana
4604e1e70aSTiberiu Breana return 0;
4704e1e70aSTiberiu Breana }
4804e1e70aSTiberiu Breana
max31722_temp_show(struct device * dev,struct device_attribute * attr,char * buf)49845ee709SGuenter Roeck static ssize_t max31722_temp_show(struct device *dev,
50845ee709SGuenter Roeck struct device_attribute *attr, char *buf)
5104e1e70aSTiberiu Breana {
5204e1e70aSTiberiu Breana ssize_t ret;
5304e1e70aSTiberiu Breana struct max31722_data *data = dev_get_drvdata(dev);
5404e1e70aSTiberiu Breana
5504e1e70aSTiberiu Breana ret = spi_w8r16(data->spi_device, MAX31722_REG_TEMP_LSB);
5604e1e70aSTiberiu Breana if (ret < 0)
5704e1e70aSTiberiu Breana return ret;
5804e1e70aSTiberiu Breana /* Keep 12 bits and multiply by the scale of 62.5 millidegrees/bit. */
5904e1e70aSTiberiu Breana return sprintf(buf, "%d\n", (s16)le16_to_cpu(ret) * 125 / 32);
6004e1e70aSTiberiu Breana }
6104e1e70aSTiberiu Breana
62845ee709SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_input, max31722_temp, 0);
6304e1e70aSTiberiu Breana
6404e1e70aSTiberiu Breana static struct attribute *max31722_attrs[] = {
6504e1e70aSTiberiu Breana &sensor_dev_attr_temp1_input.dev_attr.attr,
6604e1e70aSTiberiu Breana NULL,
6704e1e70aSTiberiu Breana };
6804e1e70aSTiberiu Breana
6904e1e70aSTiberiu Breana ATTRIBUTE_GROUPS(max31722);
7004e1e70aSTiberiu Breana
max31722_probe(struct spi_device * spi)7104e1e70aSTiberiu Breana static int max31722_probe(struct spi_device *spi)
7204e1e70aSTiberiu Breana {
7304e1e70aSTiberiu Breana int ret;
7404e1e70aSTiberiu Breana struct max31722_data *data;
7504e1e70aSTiberiu Breana
7604e1e70aSTiberiu Breana data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL);
7704e1e70aSTiberiu Breana if (!data)
7804e1e70aSTiberiu Breana return -ENOMEM;
7904e1e70aSTiberiu Breana
8004e1e70aSTiberiu Breana spi_set_drvdata(spi, data);
8104e1e70aSTiberiu Breana data->spi_device = spi;
8204e1e70aSTiberiu Breana /*
8304e1e70aSTiberiu Breana * Set SD bit to 0 so we can have continuous measurements.
8404e1e70aSTiberiu Breana * Set resolution to 12 bits for maximum precision.
8504e1e70aSTiberiu Breana */
8604e1e70aSTiberiu Breana data->mode = MAX31722_MODE_CONTINUOUS | MAX31722_RESOLUTION_12BIT;
8704e1e70aSTiberiu Breana ret = max31722_set_mode(data, MAX31722_MODE_CONTINUOUS);
8804e1e70aSTiberiu Breana if (ret < 0)
8904e1e70aSTiberiu Breana return ret;
9004e1e70aSTiberiu Breana
9104e1e70aSTiberiu Breana data->hwmon_dev = hwmon_device_register_with_groups(&spi->dev,
9204e1e70aSTiberiu Breana spi->modalias,
9304e1e70aSTiberiu Breana data,
9404e1e70aSTiberiu Breana max31722_groups);
9504e1e70aSTiberiu Breana if (IS_ERR(data->hwmon_dev)) {
9604e1e70aSTiberiu Breana max31722_set_mode(data, MAX31722_MODE_STANDBY);
9704e1e70aSTiberiu Breana return PTR_ERR(data->hwmon_dev);
9804e1e70aSTiberiu Breana }
9904e1e70aSTiberiu Breana
10004e1e70aSTiberiu Breana return 0;
10104e1e70aSTiberiu Breana }
10204e1e70aSTiberiu Breana
max31722_remove(struct spi_device * spi)103a0386bbaSUwe Kleine-König static void max31722_remove(struct spi_device *spi)
10404e1e70aSTiberiu Breana {
10504e1e70aSTiberiu Breana struct max31722_data *data = spi_get_drvdata(spi);
106efb389b8SUwe Kleine-König int ret;
10704e1e70aSTiberiu Breana
10804e1e70aSTiberiu Breana hwmon_device_unregister(data->hwmon_dev);
10904e1e70aSTiberiu Breana
110efb389b8SUwe Kleine-König ret = max31722_set_mode(data, MAX31722_MODE_STANDBY);
111efb389b8SUwe Kleine-König if (ret)
112efb389b8SUwe Kleine-König /* There is nothing we can do about this ... */
113efb389b8SUwe Kleine-König dev_warn(&spi->dev, "Failed to put device in stand-by mode\n");
11404e1e70aSTiberiu Breana }
11504e1e70aSTiberiu Breana
max31722_suspend(struct device * dev)116*80294537SJonathan Cameron static int max31722_suspend(struct device *dev)
11704e1e70aSTiberiu Breana {
11804e1e70aSTiberiu Breana struct spi_device *spi_device = to_spi_device(dev);
11904e1e70aSTiberiu Breana struct max31722_data *data = spi_get_drvdata(spi_device);
12004e1e70aSTiberiu Breana
12104e1e70aSTiberiu Breana return max31722_set_mode(data, MAX31722_MODE_STANDBY);
12204e1e70aSTiberiu Breana }
12304e1e70aSTiberiu Breana
max31722_resume(struct device * dev)124*80294537SJonathan Cameron static int max31722_resume(struct device *dev)
12504e1e70aSTiberiu Breana {
12604e1e70aSTiberiu Breana struct spi_device *spi_device = to_spi_device(dev);
12704e1e70aSTiberiu Breana struct max31722_data *data = spi_get_drvdata(spi_device);
12804e1e70aSTiberiu Breana
12904e1e70aSTiberiu Breana return max31722_set_mode(data, MAX31722_MODE_CONTINUOUS);
13004e1e70aSTiberiu Breana }
13104e1e70aSTiberiu Breana
132*80294537SJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(max31722_pm_ops, max31722_suspend, max31722_resume);
13304e1e70aSTiberiu Breana
13404e1e70aSTiberiu Breana static const struct spi_device_id max31722_spi_id[] = {
13504e1e70aSTiberiu Breana {"max31722", 0},
13604e1e70aSTiberiu Breana {"max31723", 0},
13704e1e70aSTiberiu Breana {}
13804e1e70aSTiberiu Breana };
13904e1e70aSTiberiu Breana MODULE_DEVICE_TABLE(spi, max31722_spi_id);
14004e1e70aSTiberiu Breana
14104e1e70aSTiberiu Breana static struct spi_driver max31722_driver = {
14204e1e70aSTiberiu Breana .driver = {
14304e1e70aSTiberiu Breana .name = "max31722",
144*80294537SJonathan Cameron .pm = pm_sleep_ptr(&max31722_pm_ops),
14504e1e70aSTiberiu Breana },
14604e1e70aSTiberiu Breana .probe = max31722_probe,
14704e1e70aSTiberiu Breana .remove = max31722_remove,
14804e1e70aSTiberiu Breana .id_table = max31722_spi_id,
14904e1e70aSTiberiu Breana };
15004e1e70aSTiberiu Breana
15104e1e70aSTiberiu Breana module_spi_driver(max31722_driver);
15204e1e70aSTiberiu Breana
15304e1e70aSTiberiu Breana MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>");
15404e1e70aSTiberiu Breana MODULE_DESCRIPTION("max31722 sensor driver");
15504e1e70aSTiberiu Breana MODULE_LICENSE("GPL v2");
156