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