Blame view

drivers/hwmon/max31722.c 3.9 KB
36edc9395   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
04e1e70af   Tiberiu Breana   hwmon: (max31722)...
2
3
4
5
6
  /*
   * max31722 - hwmon driver for Maxim Integrated MAX31722/MAX31723 SPI
   * digital thermometer and thermostats.
   *
   * Copyright (c) 2016, Intel Corporation.
04e1e70af   Tiberiu Breana   hwmon: (max31722)...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
   */
  
  #include <linux/acpi.h>
  #include <linux/hwmon.h>
  #include <linux/hwmon-sysfs.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/spi/spi.h>
  
  #define MAX31722_REG_CFG				0x00
  #define MAX31722_REG_TEMP_LSB				0x01
  
  #define MAX31722_MODE_CONTINUOUS			0x00
  #define MAX31722_MODE_STANDBY				0x01
  #define MAX31722_MODE_MASK				0xFE
  #define MAX31722_RESOLUTION_12BIT			0x06
  #define MAX31722_WRITE_MASK				0x80
  
  struct max31722_data {
  	struct device *hwmon_dev;
  	struct spi_device *spi_device;
  	u8 mode;
  };
  
  static int max31722_set_mode(struct max31722_data *data, u8 mode)
  {
  	int ret;
  	struct spi_device *spi = data->spi_device;
  	u8 buf[2] = {
  		MAX31722_REG_CFG | MAX31722_WRITE_MASK,
  		(data->mode & MAX31722_MODE_MASK) | mode
  	};
  
  	ret = spi_write(spi, &buf, sizeof(buf));
  	if (ret < 0) {
  		dev_err(&spi->dev, "failed to set sensor mode.
  ");
  		return ret;
  	}
  	data->mode = (data->mode & MAX31722_MODE_MASK) | mode;
  
  	return 0;
  }
845ee7092   Guenter Roeck   hwmon: (max31722)...
50
51
  static ssize_t max31722_temp_show(struct device *dev,
  				  struct device_attribute *attr, char *buf)
04e1e70af   Tiberiu Breana   hwmon: (max31722)...
52
53
54
55
56
57
58
59
60
61
62
  {
  	ssize_t ret;
  	struct max31722_data *data = dev_get_drvdata(dev);
  
  	ret = spi_w8r16(data->spi_device, MAX31722_REG_TEMP_LSB);
  	if (ret < 0)
  		return ret;
  	/* Keep 12 bits and multiply by the scale of 62.5 millidegrees/bit. */
  	return sprintf(buf, "%d
  ", (s16)le16_to_cpu(ret) * 125 / 32);
  }
845ee7092   Guenter Roeck   hwmon: (max31722)...
63
  static SENSOR_DEVICE_ATTR_RO(temp1_input, max31722_temp, 0);
04e1e70af   Tiberiu Breana   hwmon: (max31722)...
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  
  static struct attribute *max31722_attrs[] = {
  	&sensor_dev_attr_temp1_input.dev_attr.attr,
  	NULL,
  };
  
  ATTRIBUTE_GROUPS(max31722);
  
  static int max31722_probe(struct spi_device *spi)
  {
  	int ret;
  	struct max31722_data *data;
  
  	data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL);
  	if (!data)
  		return -ENOMEM;
  
  	spi_set_drvdata(spi, data);
  	data->spi_device = spi;
  	/*
  	 * Set SD bit to 0 so we can have continuous measurements.
  	 * Set resolution to 12 bits for maximum precision.
  	 */
  	data->mode = MAX31722_MODE_CONTINUOUS | MAX31722_RESOLUTION_12BIT;
  	ret = max31722_set_mode(data, MAX31722_MODE_CONTINUOUS);
  	if (ret < 0)
  		return ret;
  
  	data->hwmon_dev = hwmon_device_register_with_groups(&spi->dev,
  							    spi->modalias,
  							    data,
  							    max31722_groups);
  	if (IS_ERR(data->hwmon_dev)) {
  		max31722_set_mode(data, MAX31722_MODE_STANDBY);
  		return PTR_ERR(data->hwmon_dev);
  	}
  
  	return 0;
  }
  
  static int max31722_remove(struct spi_device *spi)
  {
  	struct max31722_data *data = spi_get_drvdata(spi);
  
  	hwmon_device_unregister(data->hwmon_dev);
  
  	return max31722_set_mode(data, MAX31722_MODE_STANDBY);
  }
  
  static int __maybe_unused max31722_suspend(struct device *dev)
  {
  	struct spi_device *spi_device = to_spi_device(dev);
  	struct max31722_data *data = spi_get_drvdata(spi_device);
  
  	return max31722_set_mode(data, MAX31722_MODE_STANDBY);
  }
  
  static int __maybe_unused max31722_resume(struct device *dev)
  {
  	struct spi_device *spi_device = to_spi_device(dev);
  	struct max31722_data *data = spi_get_drvdata(spi_device);
  
  	return max31722_set_mode(data, MAX31722_MODE_CONTINUOUS);
  }
  
  static SIMPLE_DEV_PM_OPS(max31722_pm_ops, max31722_suspend, max31722_resume);
  
  static const struct spi_device_id max31722_spi_id[] = {
  	{"max31722", 0},
  	{"max31723", 0},
  	{}
  };
  
  static const struct acpi_device_id __maybe_unused max31722_acpi_id[] = {
  	{"MAX31722", 0},
  	{"MAX31723", 0},
  	{}
  };
  
  MODULE_DEVICE_TABLE(spi, max31722_spi_id);
  
  static struct spi_driver max31722_driver = {
  	.driver = {
  		.name = "max31722",
  		.pm = &max31722_pm_ops,
  		.acpi_match_table = ACPI_PTR(max31722_acpi_id),
  	},
  	.probe =            max31722_probe,
  	.remove =           max31722_remove,
  	.id_table =         max31722_spi_id,
  };
  
  module_spi_driver(max31722_driver);
  
  MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>");
  MODULE_DESCRIPTION("max31722 sensor driver");
  MODULE_LICENSE("GPL v2");