Merge tag 'for-5.13-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[linux-2.6-microblaze.git] / drivers / hwmon / max6621.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Hardware monitoring driver for Maxim MAX6621
4  *
5  * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
6  * Copyright (c) 2017 Vadim Pasternak <vadimp@mellanox.com>
7  */
8
9 #include <linux/bitops.h>
10 #include <linux/hwmon.h>
11 #include <linux/hwmon-sysfs.h>
12 #include <linux/i2c.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/of_device.h>
16 #include <linux/regmap.h>
17
18 #define MAX6621_DRV_NAME                "max6621"
19 #define MAX6621_TEMP_INPUT_REG_NUM      9
20 #define MAX6621_TEMP_INPUT_MIN          -127000
21 #define MAX6621_TEMP_INPUT_MAX          128000
22 #define MAX6621_TEMP_ALERT_CHAN_SHIFT   1
23
24 #define MAX6621_TEMP_S0D0_REG           0x00
25 #define MAX6621_TEMP_S0D1_REG           0x01
26 #define MAX6621_TEMP_S1D0_REG           0x02
27 #define MAX6621_TEMP_S1D1_REG           0x03
28 #define MAX6621_TEMP_S2D0_REG           0x04
29 #define MAX6621_TEMP_S2D1_REG           0x05
30 #define MAX6621_TEMP_S3D0_REG           0x06
31 #define MAX6621_TEMP_S3D1_REG           0x07
32 #define MAX6621_TEMP_MAX_REG            0x08
33 #define MAX6621_TEMP_MAX_ADDR_REG       0x0a
34 #define MAX6621_TEMP_ALERT_CAUSE_REG    0x0b
35 #define MAX6621_CONFIG0_REG             0x0c
36 #define MAX6621_CONFIG1_REG             0x0d
37 #define MAX6621_CONFIG2_REG             0x0e
38 #define MAX6621_CONFIG3_REG             0x0f
39 #define MAX6621_TEMP_S0_ALERT_REG       0x10
40 #define MAX6621_TEMP_S1_ALERT_REG       0x11
41 #define MAX6621_TEMP_S2_ALERT_REG       0x12
42 #define MAX6621_TEMP_S3_ALERT_REG       0x13
43 #define MAX6621_CLEAR_ALERT_REG         0x15
44 #define MAX6621_REG_MAX                 (MAX6621_CLEAR_ALERT_REG + 1)
45 #define MAX6621_REG_TEMP_SHIFT          0x06
46
47 #define MAX6621_ENABLE_TEMP_ALERTS_BIT  4
48 #define MAX6621_ENABLE_I2C_CRC_BIT      5
49 #define MAX6621_ENABLE_ALTERNATE_DATA   6
50 #define MAX6621_ENABLE_LOCKUP_TO        7
51 #define MAX6621_ENABLE_S0D0_BIT         8
52 #define MAX6621_ENABLE_S3D1_BIT         15
53 #define MAX6621_ENABLE_TEMP_ALL         GENMASK(MAX6621_ENABLE_S3D1_BIT, \
54                                                 MAX6621_ENABLE_S0D0_BIT)
55 #define MAX6621_POLL_DELAY_MASK         0x5
56 #define MAX6621_CONFIG0_INIT            (MAX6621_ENABLE_TEMP_ALL | \
57                                          BIT(MAX6621_ENABLE_LOCKUP_TO) | \
58                                          BIT(MAX6621_ENABLE_I2C_CRC_BIT) | \
59                                          MAX6621_POLL_DELAY_MASK)
60 #define MAX6621_PECI_BIT_TIME           0x2
61 #define MAX6621_PECI_RETRY_NUM          0x3
62 #define MAX6621_CONFIG1_INIT            ((MAX6621_PECI_BIT_TIME << 8) | \
63                                          MAX6621_PECI_RETRY_NUM)
64
65 /* Error codes */
66 #define MAX6621_TRAN_FAILED     0x8100  /*
67                                          * PECI transaction failed for more
68                                          * than the configured number of
69                                          * consecutive retries.
70                                          */
71 #define MAX6621_POOL_DIS        0x8101  /*
72                                          * Polling disabled for requested
73                                          * socket/domain.
74                                          */
75 #define MAX6621_POOL_UNCOMPLETE 0x8102  /*
76                                          * First poll not yet completed for
77                                          * requested socket/domain (on
78                                          * startup).
79                                          */
80 #define MAX6621_SD_DIS          0x8103  /*
81                                          * Read maximum temperature requested,
82                                          * but no sockets/domains enabled or
83                                          * all enabled sockets/domains have
84                                          * errors; or read maximum temperature
85                                          * address requested, but read maximum
86                                          * temperature was not called.
87                                          */
88 #define MAX6621_ALERT_DIS       0x8104  /*
89                                          * Get alert socket/domain requested,
90                                          * but no alert active.
91                                          */
92 #define MAX6621_PECI_ERR_MIN    0x8000  /* Intel spec PECI error min value. */
93 #define MAX6621_PECI_ERR_MAX    0x80ff  /* Intel spec PECI error max value. */
94
95 static const u32 max6621_temp_regs[] = {
96         MAX6621_TEMP_MAX_REG, MAX6621_TEMP_S0D0_REG, MAX6621_TEMP_S1D0_REG,
97         MAX6621_TEMP_S2D0_REG, MAX6621_TEMP_S3D0_REG, MAX6621_TEMP_S0D1_REG,
98         MAX6621_TEMP_S1D1_REG, MAX6621_TEMP_S2D1_REG, MAX6621_TEMP_S3D1_REG,
99 };
100
101 static const char *const max6621_temp_labels[] = {
102         "maximum",
103         "socket0_0",
104         "socket1_0",
105         "socket2_0",
106         "socket3_0",
107         "socket0_1",
108         "socket1_1",
109         "socket2_1",
110         "socket3_1",
111 };
112
113 static const int max6621_temp_alert_chan2reg[] = {
114         MAX6621_TEMP_S0_ALERT_REG,
115         MAX6621_TEMP_S1_ALERT_REG,
116         MAX6621_TEMP_S2_ALERT_REG,
117         MAX6621_TEMP_S3_ALERT_REG,
118 };
119
120 /**
121  * struct max6621_data - private data:
122  *
123  * @client: I2C client;
124  * @regmap: register map handle;
125  * @input_chan2reg: mapping from channel to register;
126  */
127 struct max6621_data {
128         struct i2c_client       *client;
129         struct regmap           *regmap;
130         int                     input_chan2reg[MAX6621_TEMP_INPUT_REG_NUM + 1];
131 };
132
133 static long max6621_temp_mc2reg(long val)
134 {
135         return (val / 1000L) << MAX6621_REG_TEMP_SHIFT;
136 }
137
138 static umode_t
139 max6621_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,
140                    int channel)
141 {
142         /* Skip channels which are not physically conncted. */
143         if (((struct max6621_data *)data)->input_chan2reg[channel] < 0)
144                 return 0;
145
146         switch (type) {
147         case hwmon_temp:
148                 switch (attr) {
149                 case hwmon_temp_input:
150                 case hwmon_temp_label:
151                 case hwmon_temp_crit_alarm:
152                         return 0444;
153                 case hwmon_temp_offset:
154                 case hwmon_temp_crit:
155                         return 0644;
156                 default:
157                         break;
158                 }
159
160         default:
161                 break;
162         }
163
164         return 0;
165 }
166
167 static int max6621_verify_reg_data(struct device *dev, int regval)
168 {
169         if (regval >= MAX6621_PECI_ERR_MIN &&
170             regval <= MAX6621_PECI_ERR_MAX) {
171                 dev_dbg(dev, "PECI error code - err 0x%04x.\n",
172                         regval);
173
174                 return -EIO;
175         }
176
177         switch (regval) {
178         case MAX6621_TRAN_FAILED:
179                 dev_dbg(dev, "PECI transaction failed - err 0x%04x.\n",
180                         regval);
181                 return -EIO;
182         case MAX6621_POOL_DIS:
183                 dev_dbg(dev, "Polling disabled - err 0x%04x.\n", regval);
184                 return -EOPNOTSUPP;
185         case MAX6621_POOL_UNCOMPLETE:
186                 dev_dbg(dev, "First poll not completed on startup - err 0x%04x.\n",
187                         regval);
188                 return -EIO;
189         case MAX6621_SD_DIS:
190                 dev_dbg(dev, "Resource is disabled - err 0x%04x.\n", regval);
191                 return -EOPNOTSUPP;
192         case MAX6621_ALERT_DIS:
193                 dev_dbg(dev, "No alert active - err 0x%04x.\n", regval);
194                 return -EOPNOTSUPP;
195         default:
196                 return 0;
197         }
198 }
199
200 static int
201 max6621_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
202              int channel, long *val)
203 {
204         struct max6621_data *data = dev_get_drvdata(dev);
205         u32 regval;
206         int reg;
207         s8 temp;
208         int ret;
209
210         switch (type) {
211         case hwmon_temp:
212                 switch (attr) {
213                 case hwmon_temp_input:
214                         reg = data->input_chan2reg[channel];
215                         ret = regmap_read(data->regmap, reg, &regval);
216                         if (ret)
217                                 return ret;
218
219                         ret = max6621_verify_reg_data(dev, regval);
220                         if (ret)
221                                 return ret;
222
223                         /*
224                          * Bit MAX6621_REG_TEMP_SHIFT represents 1 degree step.
225                          * The temperature is given in two's complement and 8
226                          * bits is used for the register conversion.
227                          */
228                         temp = (regval >> MAX6621_REG_TEMP_SHIFT);
229                         *val = temp * 1000L;
230
231                         break;
232                 case hwmon_temp_offset:
233                         ret = regmap_read(data->regmap, MAX6621_CONFIG2_REG,
234                                           &regval);
235                         if (ret)
236                                 return ret;
237
238                         ret = max6621_verify_reg_data(dev, regval);
239                         if (ret)
240                                 return ret;
241
242                         *val = (regval >> MAX6621_REG_TEMP_SHIFT) *
243                                1000L;
244
245                         break;
246                 case hwmon_temp_crit:
247                         channel -= MAX6621_TEMP_ALERT_CHAN_SHIFT;
248                         reg = max6621_temp_alert_chan2reg[channel];
249                         ret = regmap_read(data->regmap, reg, &regval);
250                         if (ret)
251                                 return ret;
252
253                         ret = max6621_verify_reg_data(dev, regval);
254                         if (ret)
255                                 return ret;
256
257                         *val = regval * 1000L;
258
259                         break;
260                 case hwmon_temp_crit_alarm:
261                         /*
262                          * Set val to zero to recover the case, when reading
263                          * MAX6621_TEMP_ALERT_CAUSE_REG results in for example
264                          * MAX6621_ALERT_DIS. Reading will return with error,
265                          * but in such case alarm should be returned as 0.
266                          */
267                         *val = 0;
268                         ret = regmap_read(data->regmap,
269                                           MAX6621_TEMP_ALERT_CAUSE_REG,
270                                           &regval);
271                         if (ret)
272                                 return ret;
273
274                         ret = max6621_verify_reg_data(dev, regval);
275                         if (ret) {
276                                 /* Do not report error if alert is disabled. */
277                                 if (regval == MAX6621_ALERT_DIS)
278                                         return 0;
279                                 else
280                                         return ret;
281                         }
282
283                         /*
284                          * Clear the alert automatically, using send-byte
285                          * smbus protocol for clearing alert.
286                          */
287                         if (regval) {
288                                 ret = i2c_smbus_write_byte(data->client,
289                                                 MAX6621_CLEAR_ALERT_REG);
290                                 if (ret)
291                                         return ret;
292                         }
293
294                         *val = !!regval;
295
296                         break;
297                 default:
298                         return -EOPNOTSUPP;
299                 }
300                 break;
301
302         default:
303                 return -EOPNOTSUPP;
304         }
305
306         return 0;
307 }
308
309 static int
310 max6621_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
311               int channel, long val)
312 {
313         struct max6621_data *data = dev_get_drvdata(dev);
314         u32 reg;
315
316         switch (type) {
317         case hwmon_temp:
318                 switch (attr) {
319                 case hwmon_temp_offset:
320                         /* Clamp to allowed range to prevent overflow. */
321                         val = clamp_val(val, MAX6621_TEMP_INPUT_MIN,
322                                         MAX6621_TEMP_INPUT_MAX);
323                         val = max6621_temp_mc2reg(val);
324
325                         return regmap_write(data->regmap,
326                                             MAX6621_CONFIG2_REG, val);
327                 case hwmon_temp_crit:
328                         channel -= MAX6621_TEMP_ALERT_CHAN_SHIFT;
329                         reg = max6621_temp_alert_chan2reg[channel];
330                         /* Clamp to allowed range to prevent overflow. */
331                         val = clamp_val(val, MAX6621_TEMP_INPUT_MIN,
332                                         MAX6621_TEMP_INPUT_MAX);
333                         val = val / 1000L;
334
335                         return regmap_write(data->regmap, reg, val);
336                 default:
337                         return -EOPNOTSUPP;
338                 }
339                 break;
340
341         default:
342                 return -EOPNOTSUPP;
343         }
344
345         return -EOPNOTSUPP;
346 }
347
348 static int
349 max6621_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,
350                     int channel, const char **str)
351 {
352         switch (type) {
353         case hwmon_temp:
354                 switch (attr) {
355                 case hwmon_temp_label:
356                         *str = max6621_temp_labels[channel];
357                         return 0;
358                 default:
359                         return -EOPNOTSUPP;
360                 }
361                 break;
362         default:
363                 return -EOPNOTSUPP;
364         }
365
366         return -EOPNOTSUPP;
367 }
368
369 static bool max6621_writeable_reg(struct device *dev, unsigned int reg)
370 {
371         switch (reg) {
372         case MAX6621_CONFIG0_REG:
373         case MAX6621_CONFIG1_REG:
374         case MAX6621_CONFIG2_REG:
375         case MAX6621_CONFIG3_REG:
376         case MAX6621_TEMP_S0_ALERT_REG:
377         case MAX6621_TEMP_S1_ALERT_REG:
378         case MAX6621_TEMP_S2_ALERT_REG:
379         case MAX6621_TEMP_S3_ALERT_REG:
380         case MAX6621_TEMP_ALERT_CAUSE_REG:
381                 return true;
382         }
383         return false;
384 }
385
386 static bool max6621_readable_reg(struct device *dev, unsigned int reg)
387 {
388         switch (reg) {
389         case MAX6621_TEMP_S0D0_REG:
390         case MAX6621_TEMP_S0D1_REG:
391         case MAX6621_TEMP_S1D0_REG:
392         case MAX6621_TEMP_S1D1_REG:
393         case MAX6621_TEMP_S2D0_REG:
394         case MAX6621_TEMP_S2D1_REG:
395         case MAX6621_TEMP_S3D0_REG:
396         case MAX6621_TEMP_S3D1_REG:
397         case MAX6621_TEMP_MAX_REG:
398         case MAX6621_TEMP_MAX_ADDR_REG:
399         case MAX6621_CONFIG0_REG:
400         case MAX6621_CONFIG1_REG:
401         case MAX6621_CONFIG2_REG:
402         case MAX6621_CONFIG3_REG:
403         case MAX6621_TEMP_S0_ALERT_REG:
404         case MAX6621_TEMP_S1_ALERT_REG:
405         case MAX6621_TEMP_S2_ALERT_REG:
406         case MAX6621_TEMP_S3_ALERT_REG:
407                 return true;
408         }
409         return false;
410 }
411
412 static bool max6621_volatile_reg(struct device *dev, unsigned int reg)
413 {
414         switch (reg) {
415         case MAX6621_TEMP_S0D0_REG:
416         case MAX6621_TEMP_S0D1_REG:
417         case MAX6621_TEMP_S1D0_REG:
418         case MAX6621_TEMP_S1D1_REG:
419         case MAX6621_TEMP_S2D0_REG:
420         case MAX6621_TEMP_S2D1_REG:
421         case MAX6621_TEMP_S3D0_REG:
422         case MAX6621_TEMP_S3D1_REG:
423         case MAX6621_TEMP_MAX_REG:
424         case MAX6621_TEMP_S0_ALERT_REG:
425         case MAX6621_TEMP_S1_ALERT_REG:
426         case MAX6621_TEMP_S2_ALERT_REG:
427         case MAX6621_TEMP_S3_ALERT_REG:
428         case MAX6621_TEMP_ALERT_CAUSE_REG:
429                 return true;
430         }
431         return false;
432 }
433
434 static const struct reg_default max6621_regmap_default[] = {
435         { MAX6621_CONFIG0_REG, MAX6621_CONFIG0_INIT },
436         { MAX6621_CONFIG1_REG, MAX6621_CONFIG1_INIT },
437 };
438
439 static const struct regmap_config max6621_regmap_config = {
440         .reg_bits = 8,
441         .val_bits = 16,
442         .max_register = MAX6621_REG_MAX,
443         .val_format_endian = REGMAP_ENDIAN_LITTLE,
444         .cache_type = REGCACHE_FLAT,
445         .writeable_reg = max6621_writeable_reg,
446         .readable_reg = max6621_readable_reg,
447         .volatile_reg = max6621_volatile_reg,
448         .reg_defaults = max6621_regmap_default,
449         .num_reg_defaults = ARRAY_SIZE(max6621_regmap_default),
450 };
451
452 static const struct hwmon_channel_info *max6621_info[] = {
453         HWMON_CHANNEL_INFO(chip,
454                            HWMON_C_REGISTER_TZ),
455         HWMON_CHANNEL_INFO(temp,
456                            HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
457                            HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_LABEL,
458                            HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_LABEL,
459                            HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_LABEL,
460                            HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_LABEL,
461                            HWMON_T_INPUT | HWMON_T_LABEL,
462                            HWMON_T_INPUT | HWMON_T_LABEL,
463                            HWMON_T_INPUT | HWMON_T_LABEL,
464                            HWMON_T_INPUT | HWMON_T_LABEL),
465         NULL
466 };
467
468 static const struct hwmon_ops max6621_hwmon_ops = {
469         .read = max6621_read,
470         .write = max6621_write,
471         .read_string = max6621_read_string,
472         .is_visible = max6621_is_visible,
473 };
474
475 static const struct hwmon_chip_info max6621_chip_info = {
476         .ops = &max6621_hwmon_ops,
477         .info = max6621_info,
478 };
479
480 static int max6621_probe(struct i2c_client *client)
481 {
482         struct device *dev = &client->dev;
483         struct max6621_data *data;
484         struct device *hwmon_dev;
485         int i;
486         int ret;
487
488         data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
489         if (!data)
490                 return -ENOMEM;
491
492         data->regmap = devm_regmap_init_i2c(client, &max6621_regmap_config);
493         if (IS_ERR(data->regmap))
494                 return PTR_ERR(data->regmap);
495
496         i2c_set_clientdata(client, data);
497         data->client = client;
498
499         /* Set CONFIG0 register masking temperature alerts and PEC. */
500         ret = regmap_write(data->regmap, MAX6621_CONFIG0_REG,
501                            MAX6621_CONFIG0_INIT);
502         if (ret)
503                 return ret;
504
505         /* Set CONFIG1 register for PEC access retry number. */
506         ret = regmap_write(data->regmap, MAX6621_CONFIG1_REG,
507                            MAX6621_CONFIG1_INIT);
508         if (ret)
509                 return ret;
510
511         /* Sync registers with hardware. */
512         regcache_mark_dirty(data->regmap);
513         ret = regcache_sync(data->regmap);
514         if (ret)
515                 return ret;
516
517         /* Verify which temperature input registers are enabled. */
518         for (i = 0; i < MAX6621_TEMP_INPUT_REG_NUM; i++) {
519                 ret = i2c_smbus_read_word_data(client, max6621_temp_regs[i]);
520                 if (ret < 0)
521                         return ret;
522                 ret = max6621_verify_reg_data(dev, ret);
523                 if (ret) {
524                         data->input_chan2reg[i] = -1;
525                         continue;
526                 }
527
528                 data->input_chan2reg[i] = max6621_temp_regs[i];
529         }
530
531         hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
532                                                          data,
533                                                          &max6621_chip_info,
534                                                          NULL);
535
536         return PTR_ERR_OR_ZERO(hwmon_dev);
537 }
538
539 static const struct i2c_device_id max6621_id[] = {
540         { MAX6621_DRV_NAME, 0 },
541         { }
542 };
543 MODULE_DEVICE_TABLE(i2c, max6621_id);
544
545 static const struct of_device_id __maybe_unused max6621_of_match[] = {
546         { .compatible = "maxim,max6621" },
547         { }
548 };
549 MODULE_DEVICE_TABLE(of, max6621_of_match);
550
551 static struct i2c_driver max6621_driver = {
552         .class          = I2C_CLASS_HWMON,
553         .driver = {
554                 .name = MAX6621_DRV_NAME,
555                 .of_match_table = of_match_ptr(max6621_of_match),
556         },
557         .probe_new      = max6621_probe,
558         .id_table       = max6621_id,
559 };
560
561 module_i2c_driver(max6621_driver);
562
563 MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
564 MODULE_DESCRIPTION("Driver for Maxim MAX6621");
565 MODULE_LICENSE("GPL");