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, ®vall);
173c0a4b9ecSGuenter Roeck if (ret < 0)
174c0a4b9ecSGuenter Roeck return ret;
175c0a4b9ecSGuenter Roeck ret = regmap_read(regmap, regh, ®valh);
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 ®vall);
190c0a4b9ecSGuenter Roeck if (ret < 0)
191c0a4b9ecSGuenter Roeck return ret;
192c0a4b9ecSGuenter Roeck ret = regmap_read(regmap, LM95245_REG_R_REMOTE_TEMPH_U,
193c0a4b9ecSGuenter Roeck ®valh);
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 ®valh);
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, ®valh);
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 ®valh);
216c0a4b9ecSGuenter Roeck if (ret < 0)
217c0a4b9ecSGuenter Roeck return ret;
218c0a4b9ecSGuenter Roeck ret = regmap_read(regmap, LM95245_REG_RW_COMMON_HYSTERESIS,
219c0a4b9ecSGuenter Roeck ®vall);
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, ®valh);
228c0a4b9ecSGuenter Roeck if (ret < 0)
229c0a4b9ecSGuenter Roeck return ret;
230c0a4b9ecSGuenter Roeck ret = regmap_read(regmap, LM95245_REG_RW_COMMON_HYSTERESIS,
231c0a4b9ecSGuenter Roeck ®vall);
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, ®valh);
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 ®vall);
245c0a4b9ecSGuenter Roeck if (ret < 0)
246c0a4b9ecSGuenter Roeck return ret;
247c0a4b9ecSGuenter Roeck ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OFFH,
248c0a4b9ecSGuenter Roeck ®valh);
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, ®valh);
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, ®valh);
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, ®valh);
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 ®val);
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