xref: /linux/drivers/hwmon/max31827.c (revision f6154d8babbb8a98f0d3ea325aafae2e33bfd8be)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * max31827.c - Support for Maxim Low-Power Switch
4  *
5  * Copyright (c) 2023 Daniel Matyas <daniel.matyas@analog.com>
6  */
7 
8 #include <linux/bitfield.h>
9 #include <linux/bitops.h>
10 #include <linux/delay.h>
11 #include <linux/hwmon.h>
12 #include <linux/i2c.h>
13 #include <linux/mutex.h>
14 #include <linux/regmap.h>
15 #include <linux/regulator/consumer.h>
16 
17 #define MAX31827_T_REG			0x0
18 #define MAX31827_CONFIGURATION_REG	0x2
19 #define MAX31827_TH_REG			0x4
20 #define MAX31827_TL_REG			0x6
21 #define MAX31827_TH_HYST_REG		0x8
22 #define MAX31827_TL_HYST_REG		0xA
23 
24 #define MAX31827_CONFIGURATION_1SHOT_MASK	BIT(0)
25 #define MAX31827_CONFIGURATION_CNV_RATE_MASK	GENMASK(3, 1)
26 #define MAX31827_CONFIGURATION_U_TEMP_STAT_MASK	BIT(14)
27 #define MAX31827_CONFIGURATION_O_TEMP_STAT_MASK	BIT(15)
28 
29 #define MAX31827_12_BIT_CNV_TIME	140
30 
31 #define MAX31827_16_BIT_TO_M_DGR(x)	(sign_extend32(x, 15) * 1000 / 16)
32 #define MAX31827_M_DGR_TO_16_BIT(x)	(((x) << 4) / 1000)
33 #define MAX31827_DEVICE_ENABLE(x)	((x) ? 0xA : 0x0)
34 
35 enum max31827_cnv {
36 	MAX31827_CNV_1_DIV_64_HZ = 1,
37 	MAX31827_CNV_1_DIV_32_HZ,
38 	MAX31827_CNV_1_DIV_16_HZ,
39 	MAX31827_CNV_1_DIV_4_HZ,
40 	MAX31827_CNV_1_HZ,
41 	MAX31827_CNV_4_HZ,
42 	MAX31827_CNV_8_HZ,
43 };
44 
45 static const u16 max31827_conversions[] = {
46 	[MAX31827_CNV_1_DIV_64_HZ] = 64000,
47 	[MAX31827_CNV_1_DIV_32_HZ] = 32000,
48 	[MAX31827_CNV_1_DIV_16_HZ] = 16000,
49 	[MAX31827_CNV_1_DIV_4_HZ] = 4000,
50 	[MAX31827_CNV_1_HZ] = 1000,
51 	[MAX31827_CNV_4_HZ] = 250,
52 	[MAX31827_CNV_8_HZ] = 125,
53 };
54 
55 struct max31827_state {
56 	/*
57 	 * Prevent simultaneous access to the i2c client.
58 	 */
59 	struct mutex lock;
60 	struct regmap *regmap;
61 	bool enable;
62 };
63 
64 static const struct regmap_config max31827_regmap = {
65 	.reg_bits = 8,
66 	.val_bits = 16,
67 	.max_register = 0xA,
68 };
69 
70 static int shutdown_write(struct max31827_state *st, unsigned int reg,
71 			  unsigned int val)
72 {
73 	unsigned int cfg;
74 	unsigned int cnv_rate;
75 	int ret;
76 
77 	/*
78 	 * Before the Temperature Threshold Alarm and Alarm Hysteresis Threshold
79 	 * register values are changed over I2C, the part must be in shutdown
80 	 * mode.
81 	 *
82 	 * Mutex is used to ensure, that some other process doesn't change the
83 	 * configuration register.
84 	 */
85 	mutex_lock(&st->lock);
86 
87 	if (!st->enable) {
88 		ret = regmap_write(st->regmap, reg, val);
89 		goto unlock;
90 	}
91 
92 	ret = regmap_read(st->regmap, MAX31827_CONFIGURATION_REG, &cfg);
93 	if (ret)
94 		goto unlock;
95 
96 	cnv_rate = MAX31827_CONFIGURATION_CNV_RATE_MASK & cfg;
97 	cfg = cfg & ~(MAX31827_CONFIGURATION_1SHOT_MASK |
98 		      MAX31827_CONFIGURATION_CNV_RATE_MASK);
99 	ret = regmap_write(st->regmap, MAX31827_CONFIGURATION_REG, cfg);
100 	if (ret)
101 		goto unlock;
102 
103 	ret = regmap_write(st->regmap, reg, val);
104 	if (ret)
105 		goto unlock;
106 
107 	ret = regmap_update_bits(st->regmap, MAX31827_CONFIGURATION_REG,
108 				 MAX31827_CONFIGURATION_CNV_RATE_MASK,
109 				 cnv_rate);
110 
111 unlock:
112 	mutex_unlock(&st->lock);
113 	return ret;
114 }
115 
116 static int write_alarm_val(struct max31827_state *st, unsigned int reg,
117 			   long val)
118 {
119 	val = MAX31827_M_DGR_TO_16_BIT(val);
120 
121 	return shutdown_write(st, reg, val);
122 }
123 
124 static umode_t max31827_is_visible(const void *state,
125 				   enum hwmon_sensor_types type, u32 attr,
126 				   int channel)
127 {
128 	if (type == hwmon_temp) {
129 		switch (attr) {
130 		case hwmon_temp_enable:
131 		case hwmon_temp_max:
132 		case hwmon_temp_min:
133 		case hwmon_temp_max_hyst:
134 		case hwmon_temp_min_hyst:
135 			return 0644;
136 		case hwmon_temp_input:
137 		case hwmon_temp_min_alarm:
138 		case hwmon_temp_max_alarm:
139 			return 0444;
140 		default:
141 			return 0;
142 		}
143 	} else if (type == hwmon_chip) {
144 		if (attr == hwmon_chip_update_interval)
145 			return 0644;
146 	}
147 
148 	return 0;
149 }
150 
151 static int max31827_read(struct device *dev, enum hwmon_sensor_types type,
152 			 u32 attr, int channel, long *val)
153 {
154 	struct max31827_state *st = dev_get_drvdata(dev);
155 	unsigned int uval;
156 	int ret = 0;
157 
158 	switch (type) {
159 	case hwmon_temp:
160 		switch (attr) {
161 		case hwmon_temp_enable:
162 			ret = regmap_read(st->regmap,
163 					  MAX31827_CONFIGURATION_REG, &uval);
164 			if (ret)
165 				break;
166 
167 			uval = FIELD_GET(MAX31827_CONFIGURATION_1SHOT_MASK |
168 					 MAX31827_CONFIGURATION_CNV_RATE_MASK,
169 					 uval);
170 			*val = !!uval;
171 
172 			break;
173 		case hwmon_temp_input:
174 			mutex_lock(&st->lock);
175 
176 			if (!st->enable) {
177 				/*
178 				 * This operation requires mutex protection,
179 				 * because the chip configuration should not
180 				 * be changed during the conversion process.
181 				 */
182 
183 				ret = regmap_update_bits(st->regmap,
184 							 MAX31827_CONFIGURATION_REG,
185 							 MAX31827_CONFIGURATION_1SHOT_MASK,
186 							 1);
187 				if (ret) {
188 					mutex_unlock(&st->lock);
189 					return ret;
190 				}
191 
192 				msleep(MAX31827_12_BIT_CNV_TIME);
193 			}
194 			ret = regmap_read(st->regmap, MAX31827_T_REG, &uval);
195 
196 			mutex_unlock(&st->lock);
197 
198 			if (ret)
199 				break;
200 
201 			*val = MAX31827_16_BIT_TO_M_DGR(uval);
202 
203 			break;
204 		case hwmon_temp_max:
205 			ret = regmap_read(st->regmap, MAX31827_TH_REG, &uval);
206 			if (ret)
207 				break;
208 
209 			*val = MAX31827_16_BIT_TO_M_DGR(uval);
210 			break;
211 		case hwmon_temp_max_hyst:
212 			ret = regmap_read(st->regmap, MAX31827_TH_HYST_REG,
213 					  &uval);
214 			if (ret)
215 				break;
216 
217 			*val = MAX31827_16_BIT_TO_M_DGR(uval);
218 			break;
219 		case hwmon_temp_max_alarm:
220 			ret = regmap_read(st->regmap,
221 					  MAX31827_CONFIGURATION_REG, &uval);
222 			if (ret)
223 				break;
224 
225 			*val = FIELD_GET(MAX31827_CONFIGURATION_O_TEMP_STAT_MASK,
226 					 uval);
227 			break;
228 		case hwmon_temp_min:
229 			ret = regmap_read(st->regmap, MAX31827_TL_REG, &uval);
230 			if (ret)
231 				break;
232 
233 			*val = MAX31827_16_BIT_TO_M_DGR(uval);
234 			break;
235 		case hwmon_temp_min_hyst:
236 			ret = regmap_read(st->regmap, MAX31827_TL_HYST_REG,
237 					  &uval);
238 			if (ret)
239 				break;
240 
241 			*val = MAX31827_16_BIT_TO_M_DGR(uval);
242 			break;
243 		case hwmon_temp_min_alarm:
244 			ret = regmap_read(st->regmap,
245 					  MAX31827_CONFIGURATION_REG, &uval);
246 			if (ret)
247 				break;
248 
249 			*val = FIELD_GET(MAX31827_CONFIGURATION_U_TEMP_STAT_MASK,
250 					 uval);
251 			break;
252 		default:
253 			ret = -EOPNOTSUPP;
254 			break;
255 		}
256 
257 		break;
258 
259 	case hwmon_chip:
260 		if (attr == hwmon_chip_update_interval) {
261 			ret = regmap_read(st->regmap,
262 					  MAX31827_CONFIGURATION_REG, &uval);
263 			if (ret)
264 				break;
265 
266 			uval = FIELD_GET(MAX31827_CONFIGURATION_CNV_RATE_MASK,
267 					 uval);
268 			*val = max31827_conversions[uval];
269 		}
270 		break;
271 
272 	default:
273 		ret = -EOPNOTSUPP;
274 		break;
275 	}
276 
277 	return ret;
278 }
279 
280 static int max31827_write(struct device *dev, enum hwmon_sensor_types type,
281 			  u32 attr, int channel, long val)
282 {
283 	struct max31827_state *st = dev_get_drvdata(dev);
284 	int res = 1;
285 	int ret;
286 
287 	switch (type) {
288 	case hwmon_temp:
289 		switch (attr) {
290 		case hwmon_temp_enable:
291 			if (val >> 1)
292 				return -EINVAL;
293 
294 			mutex_lock(&st->lock);
295 			/**
296 			 * The chip should not be enabled while a conversion is
297 			 * performed. Neither should the chip be enabled when
298 			 * the alarm values are changed.
299 			 */
300 
301 			st->enable = val;
302 
303 			ret = regmap_update_bits(st->regmap,
304 						 MAX31827_CONFIGURATION_REG,
305 						 MAX31827_CONFIGURATION_1SHOT_MASK |
306 						 MAX31827_CONFIGURATION_CNV_RATE_MASK,
307 						 MAX31827_DEVICE_ENABLE(val));
308 
309 			mutex_unlock(&st->lock);
310 
311 			return ret;
312 
313 		case hwmon_temp_max:
314 			return write_alarm_val(st, MAX31827_TH_REG, val);
315 
316 		case hwmon_temp_max_hyst:
317 			return write_alarm_val(st, MAX31827_TH_HYST_REG, val);
318 
319 		case hwmon_temp_min:
320 			return write_alarm_val(st, MAX31827_TL_REG, val);
321 
322 		case hwmon_temp_min_hyst:
323 			return write_alarm_val(st, MAX31827_TL_HYST_REG, val);
324 
325 		default:
326 			return -EOPNOTSUPP;
327 		}
328 
329 	case hwmon_chip:
330 		if (attr == hwmon_chip_update_interval) {
331 			if (!st->enable)
332 				return -EINVAL;
333 
334 			/*
335 			 * Convert the desired conversion rate into register
336 			 * bits. res is already initialized with 1.
337 			 *
338 			 * This was inspired by lm73 driver.
339 			 */
340 			while (res < ARRAY_SIZE(max31827_conversions) &&
341 			       val < max31827_conversions[res])
342 				res++;
343 
344 			if (res == ARRAY_SIZE(max31827_conversions) ||
345 			    val != max31827_conversions[res])
346 				return -EINVAL;
347 
348 			res = FIELD_PREP(MAX31827_CONFIGURATION_CNV_RATE_MASK,
349 					 res);
350 
351 			return regmap_update_bits(st->regmap,
352 						  MAX31827_CONFIGURATION_REG,
353 						  MAX31827_CONFIGURATION_CNV_RATE_MASK,
354 						  res);
355 		}
356 		break;
357 
358 	default:
359 		return -EOPNOTSUPP;
360 	}
361 
362 	return -EOPNOTSUPP;
363 }
364 
365 static int max31827_init_client(struct max31827_state *st)
366 {
367 	st->enable = true;
368 
369 	return regmap_update_bits(st->regmap, MAX31827_CONFIGURATION_REG,
370 				  MAX31827_CONFIGURATION_1SHOT_MASK |
371 					  MAX31827_CONFIGURATION_CNV_RATE_MASK,
372 				  MAX31827_DEVICE_ENABLE(1));
373 }
374 
375 static const struct hwmon_channel_info *max31827_info[] = {
376 	HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT | HWMON_T_MIN |
377 					 HWMON_T_MIN_HYST | HWMON_T_MIN_ALARM |
378 					 HWMON_T_MAX | HWMON_T_MAX_HYST |
379 					 HWMON_T_MAX_ALARM),
380 	HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL),
381 	NULL,
382 };
383 
384 static const struct hwmon_ops max31827_hwmon_ops = {
385 	.is_visible = max31827_is_visible,
386 	.read = max31827_read,
387 	.write = max31827_write,
388 };
389 
390 static const struct hwmon_chip_info max31827_chip_info = {
391 	.ops = &max31827_hwmon_ops,
392 	.info = max31827_info,
393 };
394 
395 static int max31827_probe(struct i2c_client *client)
396 {
397 	struct device *dev = &client->dev;
398 	struct device *hwmon_dev;
399 	struct max31827_state *st;
400 	int err;
401 
402 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
403 		return -EOPNOTSUPP;
404 
405 	st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
406 	if (!st)
407 		return -ENOMEM;
408 
409 	mutex_init(&st->lock);
410 
411 	st->regmap = devm_regmap_init_i2c(client, &max31827_regmap);
412 	if (IS_ERR(st->regmap))
413 		return dev_err_probe(dev, PTR_ERR(st->regmap),
414 				     "Failed to allocate regmap.\n");
415 
416 	err = devm_regulator_get_enable(dev, "vref");
417 	if (err)
418 		return dev_err_probe(dev, err, "failed to enable regulator\n");
419 
420 	err = max31827_init_client(st);
421 	if (err)
422 		return err;
423 
424 	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, st,
425 							 &max31827_chip_info,
426 							 NULL);
427 
428 	return PTR_ERR_OR_ZERO(hwmon_dev);
429 }
430 
431 static const struct i2c_device_id max31827_i2c_ids[] = {
432 	{ "max31827", 0 },
433 	{ }
434 };
435 MODULE_DEVICE_TABLE(i2c, max31827_i2c_ids);
436 
437 static const struct of_device_id max31827_of_match[] = {
438 	{ .compatible = "adi,max31827" },
439 	{ }
440 };
441 MODULE_DEVICE_TABLE(of, max31827_of_match);
442 
443 static struct i2c_driver max31827_driver = {
444 	.class = I2C_CLASS_HWMON,
445 	.driver = {
446 		.name = "max31827",
447 		.of_match_table = max31827_of_match,
448 	},
449 	.probe = max31827_probe,
450 	.id_table = max31827_i2c_ids,
451 };
452 module_i2c_driver(max31827_driver);
453 
454 MODULE_AUTHOR("Daniel Matyas <daniel.matyas@analog.com>");
455 MODULE_DESCRIPTION("Maxim MAX31827 low-power temperature switch driver");
456 MODULE_LICENSE("GPL");
457