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