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