Merge tag 'trace-tools-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[linux-2.6-block.git] / drivers / hwmon / max31827.c
CommitLineData
16d60ba8
DM
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
42struct 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
51static const struct regmap_config max31827_regmap = {
52 .reg_bits = 8,
53 .val_bits = 16,
54 .max_register = 0xA,
55};
56
57static 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
97unlock:
98 mutex_unlock(&st->lock);
99 return ret;
100}
101
102static 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
129static 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
283static 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
379static 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
389static 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
398static const struct hwmon_ops max31827_hwmon_ops = {
399 .is_visible = max31827_is_visible,
400 .read = max31827_read,
401 .write = max31827_write,
402};
403
404static const struct hwmon_chip_info max31827_chip_info = {
405 .ops = &max31827_hwmon_ops,
406 .info = max31827_info,
407};
408
409static 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
441static const struct i2c_device_id max31827_i2c_ids[] = {
442 { "max31827", 0 },
443 { }
444};
445MODULE_DEVICE_TABLE(i2c, max31827_i2c_ids);
446
447static const struct of_device_id max31827_of_match[] = {
448 { .compatible = "adi,max31827" },
449 { }
450};
451MODULE_DEVICE_TABLE(of, max31827_of_match);
452
453static struct i2c_driver max31827_driver = {
454 .class = I2C_CLASS_HWMON,
455 .driver = {
456 .name = "max31827",
457 .of_match_table = max31827_of_match,
458 },
90fc660e 459 .probe = max31827_probe,
16d60ba8
DM
460 .id_table = max31827_i2c_ids,
461};
462module_i2c_driver(max31827_driver);
463
464MODULE_AUTHOR("Daniel Matyas <daniel.matyas@analog.com>");
465MODULE_DESCRIPTION("Maxim MAX31827 low-power temperature switch driver");
466MODULE_LICENSE("GPL");