xref: /openbmc/linux/drivers/hwmon/lm95245.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2fffd80ccSAlexander Stein /*
3fffd80ccSAlexander Stein  * Copyright (C) 2011 Alexander Stein <alexander.stein@systec-electronic.com>
4fffd80ccSAlexander Stein  *
5162a8dfeSGuenter Roeck  * The LM95245 is a sensor chip made by TI / National Semiconductor.
6fffd80ccSAlexander Stein  * It reports up to two temperatures (its own plus an external one).
7fffd80ccSAlexander Stein  *
8fffd80ccSAlexander Stein  * This driver is based on lm95241.c
9fffd80ccSAlexander Stein  */
10fffd80ccSAlexander Stein 
11fffd80ccSAlexander Stein #include <linux/err.h>
12c0a4b9ecSGuenter Roeck #include <linux/init.h>
13c0a4b9ecSGuenter Roeck #include <linux/hwmon.h>
14c0a4b9ecSGuenter Roeck #include <linux/i2c.h>
15c0a4b9ecSGuenter Roeck #include <linux/module.h>
16fffd80ccSAlexander Stein #include <linux/mutex.h>
17c0a4b9ecSGuenter Roeck #include <linux/regmap.h>
18c0a4b9ecSGuenter Roeck #include <linux/slab.h>
19fffd80ccSAlexander Stein 
20fffd80ccSAlexander Stein static const unsigned short normal_i2c[] = {
21fffd80ccSAlexander Stein 	0x18, 0x19, 0x29, 0x4c, 0x4d, I2C_CLIENT_END };
22fffd80ccSAlexander Stein 
23fffd80ccSAlexander Stein /* LM95245 registers */
24fffd80ccSAlexander Stein /* general registers */
25fffd80ccSAlexander Stein #define LM95245_REG_RW_CONFIG1		0x03
26fffd80ccSAlexander Stein #define LM95245_REG_RW_CONVERS_RATE	0x04
27fffd80ccSAlexander Stein #define LM95245_REG_W_ONE_SHOT		0x0F
28fffd80ccSAlexander Stein 
29fffd80ccSAlexander Stein /* diode configuration */
30fffd80ccSAlexander Stein #define LM95245_REG_RW_CONFIG2		0xBF
31fffd80ccSAlexander Stein #define LM95245_REG_RW_REMOTE_OFFH	0x11
32fffd80ccSAlexander Stein #define LM95245_REG_RW_REMOTE_OFFL	0x12
33fffd80ccSAlexander Stein 
34fffd80ccSAlexander Stein /* status registers */
35fffd80ccSAlexander Stein #define LM95245_REG_R_STATUS1		0x02
36fffd80ccSAlexander Stein #define LM95245_REG_R_STATUS2		0x33
37fffd80ccSAlexander Stein 
38fffd80ccSAlexander Stein /* limit registers */
39fffd80ccSAlexander Stein #define LM95245_REG_RW_REMOTE_OS_LIMIT		0x07
40fffd80ccSAlexander Stein #define LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT	0x20
41fffd80ccSAlexander Stein #define LM95245_REG_RW_REMOTE_TCRIT_LIMIT	0x19
42fffd80ccSAlexander Stein #define LM95245_REG_RW_COMMON_HYSTERESIS	0x21
43fffd80ccSAlexander Stein 
44fffd80ccSAlexander Stein /* temperature signed */
45fffd80ccSAlexander Stein #define LM95245_REG_R_LOCAL_TEMPH_S	0x00
46fffd80ccSAlexander Stein #define LM95245_REG_R_LOCAL_TEMPL_S	0x30
47fffd80ccSAlexander Stein #define LM95245_REG_R_REMOTE_TEMPH_S	0x01
48fffd80ccSAlexander Stein #define LM95245_REG_R_REMOTE_TEMPL_S	0x10
49fffd80ccSAlexander Stein /* temperature unsigned */
50fffd80ccSAlexander Stein #define LM95245_REG_R_REMOTE_TEMPH_U	0x31
51fffd80ccSAlexander Stein #define LM95245_REG_R_REMOTE_TEMPL_U	0x32
52fffd80ccSAlexander Stein 
53fffd80ccSAlexander Stein /* id registers */
54fffd80ccSAlexander Stein #define LM95245_REG_R_MAN_ID		0xFE
55fffd80ccSAlexander Stein #define LM95245_REG_R_CHIP_ID		0xFF
56fffd80ccSAlexander Stein 
57fffd80ccSAlexander Stein /* LM95245 specific bitfields */
58fffd80ccSAlexander Stein #define CFG_STOP		0x40
59fffd80ccSAlexander Stein #define CFG_REMOTE_TCRIT_MASK	0x10
60fffd80ccSAlexander Stein #define CFG_REMOTE_OS_MASK	0x08
61fffd80ccSAlexander Stein #define CFG_LOCAL_TCRIT_MASK	0x04
62fffd80ccSAlexander Stein #define CFG_LOCAL_OS_MASK	0x02
63fffd80ccSAlexander Stein 
64fffd80ccSAlexander Stein #define CFG2_OS_A0		0x40
65fffd80ccSAlexander Stein #define CFG2_DIODE_FAULT_OS	0x20
66fffd80ccSAlexander Stein #define CFG2_DIODE_FAULT_TCRIT	0x10
67fffd80ccSAlexander Stein #define CFG2_REMOTE_TT		0x08
68fffd80ccSAlexander Stein #define CFG2_REMOTE_FILTER_DIS	0x00
69fffd80ccSAlexander Stein #define CFG2_REMOTE_FILTER_EN	0x06
70fffd80ccSAlexander Stein 
71fffd80ccSAlexander Stein /* conversation rate in ms */
72fffd80ccSAlexander Stein #define RATE_CR0063	0x00
73fffd80ccSAlexander Stein #define RATE_CR0364	0x01
74fffd80ccSAlexander Stein #define RATE_CR1000	0x02
75fffd80ccSAlexander Stein #define RATE_CR2500	0x03
76fffd80ccSAlexander Stein 
77c0a4b9ecSGuenter Roeck #define STATUS1_ROS		0x10
78fffd80ccSAlexander Stein #define STATUS1_DIODE_FAULT	0x04
79fffd80ccSAlexander Stein #define STATUS1_RTCRIT		0x02
80fffd80ccSAlexander Stein #define STATUS1_LOC		0x01
81fffd80ccSAlexander Stein 
82fffd80ccSAlexander Stein #define MANUFACTURER_ID		0x01
83162a8dfeSGuenter Roeck #define LM95235_REVISION	0xB1
84162a8dfeSGuenter Roeck #define LM95245_REVISION	0xB3
85fffd80ccSAlexander Stein 
86fffd80ccSAlexander Stein /* Client data (each client gets its own) */
87fffd80ccSAlexander Stein struct lm95245_data {
88c0a4b9ecSGuenter Roeck 	struct regmap *regmap;
89fffd80ccSAlexander Stein 	struct mutex update_lock;
90c0a4b9ecSGuenter Roeck 	int interval;	/* in msecs */
91fffd80ccSAlexander Stein };
92fffd80ccSAlexander Stein 
93fffd80ccSAlexander Stein /* Conversions */
temp_from_reg_unsigned(u8 val_h,u8 val_l)94fffd80ccSAlexander Stein static int temp_from_reg_unsigned(u8 val_h, u8 val_l)
95fffd80ccSAlexander Stein {
96fffd80ccSAlexander Stein 	return val_h * 1000 + val_l * 1000 / 256;
97fffd80ccSAlexander Stein }
98fffd80ccSAlexander Stein 
temp_from_reg_signed(u8 val_h,u8 val_l)99fffd80ccSAlexander Stein static int temp_from_reg_signed(u8 val_h, u8 val_l)
100fffd80ccSAlexander Stein {
101fffd80ccSAlexander Stein 	if (val_h & 0x80)
102fffd80ccSAlexander Stein 		return (val_h - 0x100) * 1000;
103fffd80ccSAlexander Stein 	return temp_from_reg_unsigned(val_h, val_l);
104fffd80ccSAlexander Stein }
105fffd80ccSAlexander Stein 
lm95245_read_conversion_rate(struct lm95245_data * data)106c0a4b9ecSGuenter Roeck static int lm95245_read_conversion_rate(struct lm95245_data *data)
107fffd80ccSAlexander Stein {
108c0a4b9ecSGuenter Roeck 	unsigned int rate;
109c0a4b9ecSGuenter Roeck 	int ret;
110fffd80ccSAlexander Stein 
111c0a4b9ecSGuenter Roeck 	ret = regmap_read(data->regmap, LM95245_REG_RW_CONVERS_RATE, &rate);
112c0a4b9ecSGuenter Roeck 	if (ret < 0)
113c0a4b9ecSGuenter Roeck 		return ret;
114fffd80ccSAlexander Stein 
115fffd80ccSAlexander Stein 	switch (rate) {
116fffd80ccSAlexander Stein 	case RATE_CR0063:
117c0a4b9ecSGuenter Roeck 		data->interval = 63;
118fffd80ccSAlexander Stein 		break;
119fffd80ccSAlexander Stein 	case RATE_CR0364:
120c0a4b9ecSGuenter Roeck 		data->interval = 364;
121fffd80ccSAlexander Stein 		break;
122fffd80ccSAlexander Stein 	case RATE_CR1000:
123c0a4b9ecSGuenter Roeck 		data->interval = 1000;
124fffd80ccSAlexander Stein 		break;
125fffd80ccSAlexander Stein 	case RATE_CR2500:
126fffd80ccSAlexander Stein 	default:
127c0a4b9ecSGuenter Roeck 		data->interval = 2500;
128fffd80ccSAlexander Stein 		break;
129fffd80ccSAlexander Stein 	}
130c0a4b9ecSGuenter Roeck 	return 0;
131fffd80ccSAlexander Stein }
132fffd80ccSAlexander Stein 
lm95245_set_conversion_rate(struct lm95245_data * data,long interval)133c0a4b9ecSGuenter Roeck static int lm95245_set_conversion_rate(struct lm95245_data *data, long interval)
134fffd80ccSAlexander Stein {
135c0a4b9ecSGuenter Roeck 	int ret, rate;
136fffd80ccSAlexander Stein 
137fffd80ccSAlexander Stein 	if (interval <= 63) {
138fffd80ccSAlexander Stein 		interval = 63;
139fffd80ccSAlexander Stein 		rate = RATE_CR0063;
140fffd80ccSAlexander Stein 	} else if (interval <= 364) {
141fffd80ccSAlexander Stein 		interval = 364;
142fffd80ccSAlexander Stein 		rate = RATE_CR0364;
143fffd80ccSAlexander Stein 	} else if (interval <= 1000) {
144fffd80ccSAlexander Stein 		interval = 1000;
145fffd80ccSAlexander Stein 		rate = RATE_CR1000;
146fffd80ccSAlexander Stein 	} else {
147fffd80ccSAlexander Stein 		interval = 2500;
148fffd80ccSAlexander Stein 		rate = RATE_CR2500;
149fffd80ccSAlexander Stein 	}
150fffd80ccSAlexander Stein 
151c0a4b9ecSGuenter Roeck 	ret = regmap_write(data->regmap, LM95245_REG_RW_CONVERS_RATE, rate);
152c0a4b9ecSGuenter Roeck 	if (ret < 0)
153c0a4b9ecSGuenter Roeck 		return ret;
154fffd80ccSAlexander Stein 
155c0a4b9ecSGuenter Roeck 	data->interval = interval;
156c0a4b9ecSGuenter Roeck 	return 0;
157fffd80ccSAlexander Stein }
158fffd80ccSAlexander Stein 
lm95245_read_temp(struct device * dev,u32 attr,int channel,long * val)159c0a4b9ecSGuenter Roeck static int lm95245_read_temp(struct device *dev, u32 attr, int channel,
160c0a4b9ecSGuenter Roeck 			     long *val)
161fffd80ccSAlexander Stein {
162c0a4b9ecSGuenter Roeck 	struct lm95245_data *data = dev_get_drvdata(dev);
163c0a4b9ecSGuenter Roeck 	struct regmap *regmap = data->regmap;
164c0a4b9ecSGuenter Roeck 	int ret, regl, regh, regvall, regvalh;
165fffd80ccSAlexander Stein 
166c0a4b9ecSGuenter Roeck 	switch (attr) {
167c0a4b9ecSGuenter Roeck 	case hwmon_temp_input:
168c0a4b9ecSGuenter Roeck 		regl = channel ? LM95245_REG_R_REMOTE_TEMPL_S :
169c0a4b9ecSGuenter Roeck 				 LM95245_REG_R_LOCAL_TEMPL_S;
170c0a4b9ecSGuenter Roeck 		regh = channel ? LM95245_REG_R_REMOTE_TEMPH_S :
171c0a4b9ecSGuenter Roeck 				 LM95245_REG_R_LOCAL_TEMPH_S;
172c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, regl, &regvall);
173c0a4b9ecSGuenter Roeck 		if (ret < 0)
174c0a4b9ecSGuenter Roeck 			return ret;
175c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, regh, &regvalh);
176c0a4b9ecSGuenter Roeck 		if (ret < 0)
177c0a4b9ecSGuenter Roeck 			return ret;
178fffd80ccSAlexander Stein 		/*
179c0a4b9ecSGuenter Roeck 		 * Local temp is always signed.
180c0a4b9ecSGuenter Roeck 		 * Remote temp has both signed and unsigned data.
181c0a4b9ecSGuenter Roeck 		 * Use signed calculation for remote if signed bit is set
182c0a4b9ecSGuenter Roeck 		 * or if reported temperature is below signed limit.
183fffd80ccSAlexander Stein 		 */
184c0a4b9ecSGuenter Roeck 		if (!channel || (regvalh & 0x80) || regvalh < 0x7f) {
185c0a4b9ecSGuenter Roeck 			*val = temp_from_reg_signed(regvalh, regvall);
186c0a4b9ecSGuenter Roeck 			return 0;
187c0a4b9ecSGuenter Roeck 		}
188c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_R_REMOTE_TEMPL_U,
189c0a4b9ecSGuenter Roeck 				  &regvall);
190c0a4b9ecSGuenter Roeck 		if (ret < 0)
191c0a4b9ecSGuenter Roeck 			return ret;
192c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_R_REMOTE_TEMPH_U,
193c0a4b9ecSGuenter Roeck 				  &regvalh);
194c0a4b9ecSGuenter Roeck 		if (ret < 0)
195c0a4b9ecSGuenter Roeck 			return ret;
196c0a4b9ecSGuenter Roeck 		*val = temp_from_reg_unsigned(regvalh, regvall);
197c0a4b9ecSGuenter Roeck 		return 0;
198c0a4b9ecSGuenter Roeck 	case hwmon_temp_max:
199c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OS_LIMIT,
200c0a4b9ecSGuenter Roeck 				  &regvalh);
201c0a4b9ecSGuenter Roeck 		if (ret < 0)
202c0a4b9ecSGuenter Roeck 			return ret;
203c0a4b9ecSGuenter Roeck 		*val = regvalh * 1000;
204c0a4b9ecSGuenter Roeck 		return 0;
205c0a4b9ecSGuenter Roeck 	case hwmon_temp_crit:
206c0a4b9ecSGuenter Roeck 		regh = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
207c0a4b9ecSGuenter Roeck 				 LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT;
208c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, regh, &regvalh);
209c0a4b9ecSGuenter Roeck 		if (ret < 0)
210c0a4b9ecSGuenter Roeck 			return ret;
211c0a4b9ecSGuenter Roeck 		*val = regvalh * 1000;
212c0a4b9ecSGuenter Roeck 		return 0;
213c0a4b9ecSGuenter Roeck 	case hwmon_temp_max_hyst:
214c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OS_LIMIT,
215c0a4b9ecSGuenter Roeck 				  &regvalh);
216c0a4b9ecSGuenter Roeck 		if (ret < 0)
217c0a4b9ecSGuenter Roeck 			return ret;
218c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_RW_COMMON_HYSTERESIS,
219c0a4b9ecSGuenter Roeck 				  &regvall);
220c0a4b9ecSGuenter Roeck 		if (ret < 0)
221c0a4b9ecSGuenter Roeck 			return ret;
222c0a4b9ecSGuenter Roeck 		*val = (regvalh - regvall) * 1000;
223c0a4b9ecSGuenter Roeck 		return 0;
224c0a4b9ecSGuenter Roeck 	case hwmon_temp_crit_hyst:
225c0a4b9ecSGuenter Roeck 		regh = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
226c0a4b9ecSGuenter Roeck 				 LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT;
227c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, regh, &regvalh);
228c0a4b9ecSGuenter Roeck 		if (ret < 0)
229c0a4b9ecSGuenter Roeck 			return ret;
230c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_RW_COMMON_HYSTERESIS,
231c0a4b9ecSGuenter Roeck 				  &regvall);
232c0a4b9ecSGuenter Roeck 		if (ret < 0)
233c0a4b9ecSGuenter Roeck 			return ret;
234c0a4b9ecSGuenter Roeck 		*val = (regvalh - regvall) * 1000;
235c0a4b9ecSGuenter Roeck 		return 0;
236c0a4b9ecSGuenter Roeck 	case hwmon_temp_type:
237c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_RW_CONFIG2, &regvalh);
238c0a4b9ecSGuenter Roeck 		if (ret < 0)
239c0a4b9ecSGuenter Roeck 			return ret;
240c0a4b9ecSGuenter Roeck 		*val = (regvalh & CFG2_REMOTE_TT) ? 1 : 2;
241c0a4b9ecSGuenter Roeck 		return 0;
242c0a4b9ecSGuenter Roeck 	case hwmon_temp_offset:
243c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OFFL,
244c0a4b9ecSGuenter Roeck 				  &regvall);
245c0a4b9ecSGuenter Roeck 		if (ret < 0)
246c0a4b9ecSGuenter Roeck 			return ret;
247c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OFFH,
248c0a4b9ecSGuenter Roeck 				  &regvalh);
249c0a4b9ecSGuenter Roeck 		if (ret < 0)
250c0a4b9ecSGuenter Roeck 			return ret;
251c0a4b9ecSGuenter Roeck 		*val = temp_from_reg_signed(regvalh, regvall);
252c0a4b9ecSGuenter Roeck 		return 0;
253c0a4b9ecSGuenter Roeck 	case hwmon_temp_max_alarm:
254c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_R_STATUS1, &regvalh);
255c0a4b9ecSGuenter Roeck 		if (ret < 0)
256c0a4b9ecSGuenter Roeck 			return ret;
257c0a4b9ecSGuenter Roeck 		*val = !!(regvalh & STATUS1_ROS);
258c0a4b9ecSGuenter Roeck 		return 0;
259c0a4b9ecSGuenter Roeck 	case hwmon_temp_crit_alarm:
260c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_R_STATUS1, &regvalh);
261c0a4b9ecSGuenter Roeck 		if (ret < 0)
262c0a4b9ecSGuenter Roeck 			return ret;
263c0a4b9ecSGuenter Roeck 		*val = !!(regvalh & (channel ? STATUS1_RTCRIT : STATUS1_LOC));
264c0a4b9ecSGuenter Roeck 		return 0;
265c0a4b9ecSGuenter Roeck 	case hwmon_temp_fault:
266c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_R_STATUS1, &regvalh);
267c0a4b9ecSGuenter Roeck 		if (ret < 0)
268c0a4b9ecSGuenter Roeck 			return ret;
269c0a4b9ecSGuenter Roeck 		*val = !!(regvalh & STATUS1_DIODE_FAULT);
270c0a4b9ecSGuenter Roeck 		return 0;
271c0a4b9ecSGuenter Roeck 	default:
272c0a4b9ecSGuenter Roeck 		return -EOPNOTSUPP;
273c0a4b9ecSGuenter Roeck 	}
274fffd80ccSAlexander Stein }
275fffd80ccSAlexander Stein 
lm95245_write_temp(struct device * dev,u32 attr,int channel,long val)276c0a4b9ecSGuenter Roeck static int lm95245_write_temp(struct device *dev, u32 attr, int channel,
277c0a4b9ecSGuenter Roeck 			      long val)
278fffd80ccSAlexander Stein {
2797276d55eSGuenter Roeck 	struct lm95245_data *data = dev_get_drvdata(dev);
280c0a4b9ecSGuenter Roeck 	struct regmap *regmap = data->regmap;
281c0a4b9ecSGuenter Roeck 	unsigned int regval;
282c0a4b9ecSGuenter Roeck 	int ret, reg;
283fffd80ccSAlexander Stein 
284c0a4b9ecSGuenter Roeck 	switch (attr) {
285c0a4b9ecSGuenter Roeck 	case hwmon_temp_max:
286c0a4b9ecSGuenter Roeck 		val = clamp_val(val / 1000, 0, 255);
287c0a4b9ecSGuenter Roeck 		ret = regmap_write(regmap, LM95245_REG_RW_REMOTE_OS_LIMIT, val);
288c0a4b9ecSGuenter Roeck 		return ret;
289c0a4b9ecSGuenter Roeck 	case hwmon_temp_crit:
290c0a4b9ecSGuenter Roeck 		reg = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT :
291c0a4b9ecSGuenter Roeck 				LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT;
292c0a4b9ecSGuenter Roeck 		val = clamp_val(val / 1000, 0, channel ? 255 : 127);
293c0a4b9ecSGuenter Roeck 		ret = regmap_write(regmap, reg, val);
294c0a4b9ecSGuenter Roeck 		return ret;
295c0a4b9ecSGuenter Roeck 	case hwmon_temp_crit_hyst:
296fffd80ccSAlexander Stein 		mutex_lock(&data->update_lock);
297c0a4b9ecSGuenter Roeck 		ret = regmap_read(regmap, LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT,
298c0a4b9ecSGuenter Roeck 				  &regval);
299c0a4b9ecSGuenter Roeck 		if (ret < 0) {
300fffd80ccSAlexander Stein 			mutex_unlock(&data->update_lock);
301c0a4b9ecSGuenter Roeck 			return ret;
302fffd80ccSAlexander Stein 		}
303c0a4b9ecSGuenter Roeck 		/* Clamp to reasonable range to prevent overflow */
304c0a4b9ecSGuenter Roeck 		val = clamp_val(val, -1000000, 1000000);
305c0a4b9ecSGuenter Roeck 		val = regval - val / 1000;
306c0a4b9ecSGuenter Roeck 		val = clamp_val(val, 0, 31);
307c0a4b9ecSGuenter Roeck 		ret = regmap_write(regmap, LM95245_REG_RW_COMMON_HYSTERESIS,
308c0a4b9ecSGuenter Roeck 				   val);
309c0a4b9ecSGuenter Roeck 		mutex_unlock(&data->update_lock);
310c0a4b9ecSGuenter Roeck 		return ret;
311c0a4b9ecSGuenter Roeck 	case hwmon_temp_offset:
312c0a4b9ecSGuenter Roeck 		val = clamp_val(val, -128000, 127875);
313c0a4b9ecSGuenter Roeck 		val = val * 256 / 1000;
314fffd80ccSAlexander Stein 		mutex_lock(&data->update_lock);
315c0a4b9ecSGuenter Roeck 		ret = regmap_write(regmap, LM95245_REG_RW_REMOTE_OFFL,
316c0a4b9ecSGuenter Roeck 				   val & 0xe0);
317c0a4b9ecSGuenter Roeck 		if (ret < 0) {
318fffd80ccSAlexander Stein 			mutex_unlock(&data->update_lock);
319c0a4b9ecSGuenter Roeck 			return ret;
320fffd80ccSAlexander Stein 		}
321c0a4b9ecSGuenter Roeck 		ret = regmap_write(regmap, LM95245_REG_RW_REMOTE_OFFH,
322c0a4b9ecSGuenter Roeck 				   (val >> 8) & 0xff);
323c0a4b9ecSGuenter Roeck 		mutex_unlock(&data->update_lock);
324c0a4b9ecSGuenter Roeck 		return ret;
325c0a4b9ecSGuenter Roeck 	case hwmon_temp_type:
326fffd80ccSAlexander Stein 		if (val != 1 && val != 2)
327fffd80ccSAlexander Stein 			return -EINVAL;
328c0a4b9ecSGuenter Roeck 		ret = regmap_update_bits(regmap, LM95245_REG_RW_CONFIG2,
329c0a4b9ecSGuenter Roeck 					 CFG2_REMOTE_TT,
330c0a4b9ecSGuenter Roeck 					 val == 1 ? CFG2_REMOTE_TT : 0);
331c0a4b9ecSGuenter Roeck 		return ret;
332c0a4b9ecSGuenter Roeck 	default:
333c0a4b9ecSGuenter Roeck 		return -EOPNOTSUPP;
334c0a4b9ecSGuenter Roeck 	}
335fffd80ccSAlexander Stein }
336fffd80ccSAlexander Stein 
lm95245_read_chip(struct device * dev,u32 attr,int channel,long * val)337c0a4b9ecSGuenter Roeck static int lm95245_read_chip(struct device *dev, u32 attr, int channel,
338c0a4b9ecSGuenter Roeck 			     long *val)
339fffd80ccSAlexander Stein {
3407276d55eSGuenter Roeck 	struct lm95245_data *data = dev_get_drvdata(dev);
341fffd80ccSAlexander Stein 
342c0a4b9ecSGuenter Roeck 	switch (attr) {
343c0a4b9ecSGuenter Roeck 	case hwmon_chip_update_interval:
344c0a4b9ecSGuenter Roeck 		*val = data->interval;
345c0a4b9ecSGuenter Roeck 		return 0;
346c0a4b9ecSGuenter Roeck 	default:
347c0a4b9ecSGuenter Roeck 		return -EOPNOTSUPP;
348c0a4b9ecSGuenter Roeck 	}
349fffd80ccSAlexander Stein }
350fffd80ccSAlexander Stein 
lm95245_write_chip(struct device * dev,u32 attr,int channel,long val)351c0a4b9ecSGuenter Roeck static int lm95245_write_chip(struct device *dev, u32 attr, int channel,
352c0a4b9ecSGuenter Roeck 			      long val)
353c0a4b9ecSGuenter Roeck {
354c0a4b9ecSGuenter Roeck 	struct lm95245_data *data = dev_get_drvdata(dev);
355c0a4b9ecSGuenter Roeck 	int ret;
356fffd80ccSAlexander Stein 
357c0a4b9ecSGuenter Roeck 	switch (attr) {
358c0a4b9ecSGuenter Roeck 	case hwmon_chip_update_interval:
359c0a4b9ecSGuenter Roeck 		mutex_lock(&data->update_lock);
360c0a4b9ecSGuenter Roeck 		ret = lm95245_set_conversion_rate(data, val);
361c0a4b9ecSGuenter Roeck 		mutex_unlock(&data->update_lock);
362c0a4b9ecSGuenter Roeck 		return ret;
363c0a4b9ecSGuenter Roeck 	default:
364c0a4b9ecSGuenter Roeck 		return -EOPNOTSUPP;
365c0a4b9ecSGuenter Roeck 	}
366c0a4b9ecSGuenter Roeck }
367fffd80ccSAlexander Stein 
lm95245_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)368c0a4b9ecSGuenter Roeck static int lm95245_read(struct device *dev, enum hwmon_sensor_types type,
369c0a4b9ecSGuenter Roeck 			u32 attr, int channel, long *val)
370c0a4b9ecSGuenter Roeck {
371c0a4b9ecSGuenter Roeck 	switch (type) {
372c0a4b9ecSGuenter Roeck 	case hwmon_chip:
373c0a4b9ecSGuenter Roeck 		return lm95245_read_chip(dev, attr, channel, val);
374c0a4b9ecSGuenter Roeck 	case hwmon_temp:
375c0a4b9ecSGuenter Roeck 		return lm95245_read_temp(dev, attr, channel, val);
376c0a4b9ecSGuenter Roeck 	default:
377c0a4b9ecSGuenter Roeck 		return -EOPNOTSUPP;
378c0a4b9ecSGuenter Roeck 	}
379c0a4b9ecSGuenter Roeck }
380fffd80ccSAlexander Stein 
lm95245_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)381c0a4b9ecSGuenter Roeck static int lm95245_write(struct device *dev, enum hwmon_sensor_types type,
382c0a4b9ecSGuenter Roeck 			 u32 attr, int channel, long val)
383c0a4b9ecSGuenter Roeck {
384c0a4b9ecSGuenter Roeck 	switch (type) {
385c0a4b9ecSGuenter Roeck 	case hwmon_chip:
386c0a4b9ecSGuenter Roeck 		return lm95245_write_chip(dev, attr, channel, val);
387c0a4b9ecSGuenter Roeck 	case hwmon_temp:
388c0a4b9ecSGuenter Roeck 		return lm95245_write_temp(dev, attr, channel, val);
389c0a4b9ecSGuenter Roeck 	default:
390c0a4b9ecSGuenter Roeck 		return -EOPNOTSUPP;
391c0a4b9ecSGuenter Roeck 	}
392c0a4b9ecSGuenter Roeck }
393c0a4b9ecSGuenter Roeck 
lm95245_temp_is_visible(const void * data,u32 attr,int channel)394c0a4b9ecSGuenter Roeck static umode_t lm95245_temp_is_visible(const void *data, u32 attr, int channel)
395c0a4b9ecSGuenter Roeck {
396c0a4b9ecSGuenter Roeck 	switch (attr) {
397c0a4b9ecSGuenter Roeck 	case hwmon_temp_input:
398c0a4b9ecSGuenter Roeck 	case hwmon_temp_max_alarm:
399c0a4b9ecSGuenter Roeck 	case hwmon_temp_max_hyst:
400c0a4b9ecSGuenter Roeck 	case hwmon_temp_crit_alarm:
401c0a4b9ecSGuenter Roeck 	case hwmon_temp_fault:
4025a2d18cbSGuenter Roeck 		return 0444;
403c0a4b9ecSGuenter Roeck 	case hwmon_temp_type:
404c0a4b9ecSGuenter Roeck 	case hwmon_temp_max:
405c0a4b9ecSGuenter Roeck 	case hwmon_temp_crit:
406c0a4b9ecSGuenter Roeck 	case hwmon_temp_offset:
4075a2d18cbSGuenter Roeck 		return 0644;
408c0a4b9ecSGuenter Roeck 	case hwmon_temp_crit_hyst:
4095a2d18cbSGuenter Roeck 		return (channel == 0) ? 0644 : 0444;
410c0a4b9ecSGuenter Roeck 	default:
411c0a4b9ecSGuenter Roeck 		return 0;
412c0a4b9ecSGuenter Roeck 	}
413c0a4b9ecSGuenter Roeck }
414c0a4b9ecSGuenter Roeck 
lm95245_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)415c0a4b9ecSGuenter Roeck static umode_t lm95245_is_visible(const void *data,
416c0a4b9ecSGuenter Roeck 				  enum hwmon_sensor_types type,
417c0a4b9ecSGuenter Roeck 				  u32 attr, int channel)
418c0a4b9ecSGuenter Roeck {
419c0a4b9ecSGuenter Roeck 	switch (type) {
420c0a4b9ecSGuenter Roeck 	case hwmon_chip:
421c0a4b9ecSGuenter Roeck 		switch (attr) {
422c0a4b9ecSGuenter Roeck 		case hwmon_chip_update_interval:
4235a2d18cbSGuenter Roeck 			return 0644;
424c0a4b9ecSGuenter Roeck 		default:
425c0a4b9ecSGuenter Roeck 			return 0;
426c0a4b9ecSGuenter Roeck 		}
427c0a4b9ecSGuenter Roeck 	case hwmon_temp:
428c0a4b9ecSGuenter Roeck 		return lm95245_temp_is_visible(data, attr, channel);
429c0a4b9ecSGuenter Roeck 	default:
430c0a4b9ecSGuenter Roeck 		return 0;
431c0a4b9ecSGuenter Roeck 	}
432c0a4b9ecSGuenter Roeck }
433fffd80ccSAlexander Stein 
434fffd80ccSAlexander Stein /* Return 0 if detection is successful, -ENODEV otherwise */
lm95245_detect(struct i2c_client * new_client,struct i2c_board_info * info)435fffd80ccSAlexander Stein static int lm95245_detect(struct i2c_client *new_client,
436fffd80ccSAlexander Stein 			  struct i2c_board_info *info)
437fffd80ccSAlexander Stein {
438fffd80ccSAlexander Stein 	struct i2c_adapter *adapter = new_client->adapter;
439162a8dfeSGuenter Roeck 	int address = new_client->addr;
440162a8dfeSGuenter Roeck 	const char *name;
441162a8dfeSGuenter Roeck 	int rev, id;
442fffd80ccSAlexander Stein 
443fffd80ccSAlexander Stein 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
444fffd80ccSAlexander Stein 		return -ENODEV;
445fffd80ccSAlexander Stein 
446162a8dfeSGuenter Roeck 	id = i2c_smbus_read_byte_data(new_client, LM95245_REG_R_MAN_ID);
447162a8dfeSGuenter Roeck 	if (id != MANUFACTURER_ID)
448fffd80ccSAlexander Stein 		return -ENODEV;
449fffd80ccSAlexander Stein 
450162a8dfeSGuenter Roeck 	rev = i2c_smbus_read_byte_data(new_client, LM95245_REG_R_CHIP_ID);
451162a8dfeSGuenter Roeck 	switch (rev) {
452162a8dfeSGuenter Roeck 	case LM95235_REVISION:
453162a8dfeSGuenter Roeck 		if (address != 0x18 && address != 0x29 && address != 0x4c)
454162a8dfeSGuenter Roeck 			return -ENODEV;
455162a8dfeSGuenter Roeck 		name = "lm95235";
456162a8dfeSGuenter Roeck 		break;
457162a8dfeSGuenter Roeck 	case LM95245_REVISION:
458162a8dfeSGuenter Roeck 		name = "lm95245";
459162a8dfeSGuenter Roeck 		break;
460162a8dfeSGuenter Roeck 	default:
461162a8dfeSGuenter Roeck 		return -ENODEV;
462162a8dfeSGuenter Roeck 	}
463162a8dfeSGuenter Roeck 
464f2f394dbSWolfram Sang 	strscpy(info->type, name, I2C_NAME_SIZE);
465fffd80ccSAlexander Stein 	return 0;
466fffd80ccSAlexander Stein }
467fffd80ccSAlexander Stein 
lm95245_init_client(struct lm95245_data * data)468c0a4b9ecSGuenter Roeck static int lm95245_init_client(struct lm95245_data *data)
469fffd80ccSAlexander Stein {
470c0a4b9ecSGuenter Roeck 	int ret;
471fffd80ccSAlexander Stein 
472c0a4b9ecSGuenter Roeck 	ret = lm95245_read_conversion_rate(data);
473c0a4b9ecSGuenter Roeck 	if (ret < 0)
474c0a4b9ecSGuenter Roeck 		return ret;
475fffd80ccSAlexander Stein 
476c0a4b9ecSGuenter Roeck 	return regmap_update_bits(data->regmap, LM95245_REG_RW_CONFIG1,
477c0a4b9ecSGuenter Roeck 				  CFG_STOP, 0);
478c0a4b9ecSGuenter Roeck }
479c0a4b9ecSGuenter Roeck 
lm95245_is_writeable_reg(struct device * dev,unsigned int reg)480c0a4b9ecSGuenter Roeck static bool lm95245_is_writeable_reg(struct device *dev, unsigned int reg)
481c0a4b9ecSGuenter Roeck {
482c0a4b9ecSGuenter Roeck 	switch (reg) {
483c0a4b9ecSGuenter Roeck 	case LM95245_REG_RW_CONFIG1:
484c0a4b9ecSGuenter Roeck 	case LM95245_REG_RW_CONVERS_RATE:
485c0a4b9ecSGuenter Roeck 	case LM95245_REG_W_ONE_SHOT:
486c0a4b9ecSGuenter Roeck 	case LM95245_REG_RW_CONFIG2:
487c0a4b9ecSGuenter Roeck 	case LM95245_REG_RW_REMOTE_OFFH:
488c0a4b9ecSGuenter Roeck 	case LM95245_REG_RW_REMOTE_OFFL:
489c0a4b9ecSGuenter Roeck 	case LM95245_REG_RW_REMOTE_OS_LIMIT:
490c0a4b9ecSGuenter Roeck 	case LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT:
491c0a4b9ecSGuenter Roeck 	case LM95245_REG_RW_REMOTE_TCRIT_LIMIT:
492c0a4b9ecSGuenter Roeck 	case LM95245_REG_RW_COMMON_HYSTERESIS:
493c0a4b9ecSGuenter Roeck 		return true;
494c0a4b9ecSGuenter Roeck 	default:
495c0a4b9ecSGuenter Roeck 		return false;
496fffd80ccSAlexander Stein 	}
497fffd80ccSAlexander Stein }
498fffd80ccSAlexander Stein 
lm95245_is_volatile_reg(struct device * dev,unsigned int reg)499c0a4b9ecSGuenter Roeck static bool lm95245_is_volatile_reg(struct device *dev, unsigned int reg)
500c0a4b9ecSGuenter Roeck {
501c0a4b9ecSGuenter Roeck 	switch (reg) {
502c0a4b9ecSGuenter Roeck 	case LM95245_REG_R_STATUS1:
503c0a4b9ecSGuenter Roeck 	case LM95245_REG_R_STATUS2:
504c0a4b9ecSGuenter Roeck 	case LM95245_REG_R_LOCAL_TEMPH_S:
505c0a4b9ecSGuenter Roeck 	case LM95245_REG_R_LOCAL_TEMPL_S:
506c0a4b9ecSGuenter Roeck 	case LM95245_REG_R_REMOTE_TEMPH_S:
507c0a4b9ecSGuenter Roeck 	case LM95245_REG_R_REMOTE_TEMPL_S:
508c0a4b9ecSGuenter Roeck 	case LM95245_REG_R_REMOTE_TEMPH_U:
509c0a4b9ecSGuenter Roeck 	case LM95245_REG_R_REMOTE_TEMPL_U:
510c0a4b9ecSGuenter Roeck 		return true;
511c0a4b9ecSGuenter Roeck 	default:
512c0a4b9ecSGuenter Roeck 		return false;
513c0a4b9ecSGuenter Roeck 	}
514c0a4b9ecSGuenter Roeck }
515c0a4b9ecSGuenter Roeck 
516c0a4b9ecSGuenter Roeck static const struct regmap_config lm95245_regmap_config = {
517c0a4b9ecSGuenter Roeck 	.reg_bits = 8,
518c0a4b9ecSGuenter Roeck 	.val_bits = 8,
519c0a4b9ecSGuenter Roeck 	.writeable_reg = lm95245_is_writeable_reg,
520c0a4b9ecSGuenter Roeck 	.volatile_reg = lm95245_is_volatile_reg,
521c0a4b9ecSGuenter Roeck 	.cache_type = REGCACHE_MAPLE,
5221c96a2f6SDavid Frey 	.use_single_read = true,
5231c96a2f6SDavid Frey 	.use_single_write = true,
524c0a4b9ecSGuenter Roeck };
525c0a4b9ecSGuenter Roeck 
526*043f90c8SKrzysztof Kozlowski static const struct hwmon_channel_info * const lm95245_info[] = {
5277aea0064SGuenter Roeck 	HWMON_CHANNEL_INFO(chip,
5287aea0064SGuenter Roeck 			   HWMON_C_UPDATE_INTERVAL),
5297aea0064SGuenter Roeck 	HWMON_CHANNEL_INFO(temp,
5307aea0064SGuenter Roeck 			   HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_HYST |
5317aea0064SGuenter Roeck 			   HWMON_T_CRIT_ALARM,
5327aea0064SGuenter Roeck 			   HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST |
5337aea0064SGuenter Roeck 			   HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_FAULT |
5347aea0064SGuenter Roeck 			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM |
5357aea0064SGuenter Roeck 			   HWMON_T_TYPE | HWMON_T_OFFSET),
536c0a4b9ecSGuenter Roeck 	NULL
537c0a4b9ecSGuenter Roeck };
538c0a4b9ecSGuenter Roeck 
539c0a4b9ecSGuenter Roeck static const struct hwmon_ops lm95245_hwmon_ops = {
540c0a4b9ecSGuenter Roeck 	.is_visible = lm95245_is_visible,
541c0a4b9ecSGuenter Roeck 	.read = lm95245_read,
542c0a4b9ecSGuenter Roeck 	.write = lm95245_write,
543c0a4b9ecSGuenter Roeck };
544c0a4b9ecSGuenter Roeck 
545c0a4b9ecSGuenter Roeck static const struct hwmon_chip_info lm95245_chip_info = {
546c0a4b9ecSGuenter Roeck 	.ops = &lm95245_hwmon_ops,
547c0a4b9ecSGuenter Roeck 	.info = lm95245_info,
548c0a4b9ecSGuenter Roeck };
549c0a4b9ecSGuenter Roeck 
lm95245_probe(struct i2c_client * client)55067487038SStephen Kitt static int lm95245_probe(struct i2c_client *client)
551fffd80ccSAlexander Stein {
5527276d55eSGuenter Roeck 	struct device *dev = &client->dev;
553fffd80ccSAlexander Stein 	struct lm95245_data *data;
5547276d55eSGuenter Roeck 	struct device *hwmon_dev;
555c0a4b9ecSGuenter Roeck 	int ret;
556fffd80ccSAlexander Stein 
5577276d55eSGuenter Roeck 	data = devm_kzalloc(dev, sizeof(struct lm95245_data), GFP_KERNEL);
558a8dd946cSGuenter Roeck 	if (!data)
559a8dd946cSGuenter Roeck 		return -ENOMEM;
560fffd80ccSAlexander Stein 
561c0a4b9ecSGuenter Roeck 	data->regmap = devm_regmap_init_i2c(client, &lm95245_regmap_config);
562c0a4b9ecSGuenter Roeck 	if (IS_ERR(data->regmap))
563c0a4b9ecSGuenter Roeck 		return PTR_ERR(data->regmap);
564c0a4b9ecSGuenter Roeck 
565fffd80ccSAlexander Stein 	mutex_init(&data->update_lock);
566fffd80ccSAlexander Stein 
567fffd80ccSAlexander Stein 	/* Initialize the LM95245 chip */
568c0a4b9ecSGuenter Roeck 	ret = lm95245_init_client(data);
569c0a4b9ecSGuenter Roeck 	if (ret < 0)
570c0a4b9ecSGuenter Roeck 		return ret;
571fffd80ccSAlexander Stein 
572c0a4b9ecSGuenter Roeck 	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
5737276d55eSGuenter Roeck 							 data,
574c0a4b9ecSGuenter Roeck 							 &lm95245_chip_info,
575c0a4b9ecSGuenter Roeck 							 NULL);
5767276d55eSGuenter Roeck 	return PTR_ERR_OR_ZERO(hwmon_dev);
577fffd80ccSAlexander Stein }
578fffd80ccSAlexander Stein 
579fffd80ccSAlexander Stein /* Driver data (common to all clients) */
580fffd80ccSAlexander Stein static const struct i2c_device_id lm95245_id[] = {
581162a8dfeSGuenter Roeck 	{ "lm95235", 0 },
582162a8dfeSGuenter Roeck 	{ "lm95245", 0 },
583fffd80ccSAlexander Stein 	{ }
584fffd80ccSAlexander Stein };
585fffd80ccSAlexander Stein MODULE_DEVICE_TABLE(i2c, lm95245_id);
586fffd80ccSAlexander Stein 
5870e09e9f9SGuenter Roeck static const struct of_device_id __maybe_unused lm95245_of_match[] = {
5885ada7055SJavier Martinez Canillas 	{ .compatible = "national,lm95235" },
5895ada7055SJavier Martinez Canillas 	{ .compatible = "national,lm95245" },
5905ada7055SJavier Martinez Canillas 	{ },
5915ada7055SJavier Martinez Canillas };
5925ada7055SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, lm95245_of_match);
5935ada7055SJavier Martinez Canillas 
594fffd80ccSAlexander Stein static struct i2c_driver lm95245_driver = {
595fffd80ccSAlexander Stein 	.class		= I2C_CLASS_HWMON,
596fffd80ccSAlexander Stein 	.driver = {
597162a8dfeSGuenter Roeck 		.name	= "lm95245",
5985ada7055SJavier Martinez Canillas 		.of_match_table = of_match_ptr(lm95245_of_match),
599fffd80ccSAlexander Stein 	},
60067487038SStephen Kitt 	.probe		= lm95245_probe,
601fffd80ccSAlexander Stein 	.id_table	= lm95245_id,
602fffd80ccSAlexander Stein 	.detect		= lm95245_detect,
603fffd80ccSAlexander Stein 	.address_list	= normal_i2c,
604fffd80ccSAlexander Stein };
605fffd80ccSAlexander Stein 
606f0967eeaSAxel Lin module_i2c_driver(lm95245_driver);
607fffd80ccSAlexander Stein 
608fffd80ccSAlexander Stein MODULE_AUTHOR("Alexander Stein <alexander.stein@systec-electronic.com>");
609162a8dfeSGuenter Roeck MODULE_DESCRIPTION("LM95235/LM95245 sensor driver");
610fffd80ccSAlexander Stein MODULE_LICENSE("GPL");
611