]> Git Repo - linux.git/blob - drivers/hwmon/pmbus/max20730.c
Merge tag 'perf-tools-2020-08-14' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / drivers / hwmon / pmbus / max20730.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Driver for MAX20710, MAX20730, MAX20734, and MAX20743 Integrated,
4  * Step-Down Switching Regulators
5  *
6  * Copyright 2019 Google LLC.
7  * Copyright 2020 Maxim Integrated
8  */
9
10 #include <linux/bits.h>
11 #include <linux/err.h>
12 #include <linux/i2c.h>
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/mutex.h>
17 #include <linux/of_device.h>
18 #include <linux/pmbus.h>
19 #include <linux/util_macros.h>
20 #include "pmbus.h"
21
22 enum chips {
23         max20710,
24         max20730,
25         max20734,
26         max20743
27 };
28
29 struct max20730_data {
30         enum chips id;
31         struct pmbus_driver_info info;
32         struct mutex lock;      /* Used to protect against parallel writes */
33         u16 mfr_devset1;
34 };
35
36 #define to_max20730_data(x)  container_of(x, struct max20730_data, info)
37
38 #define MAX20730_MFR_DEVSET1    0xd2
39
40 /*
41  * Convert discreet value to direct data format. Strictly speaking, all passed
42  * values are constants, so we could do that calculation manually. On the
43  * downside, that would make the driver more difficult to maintain, so lets
44  * use this approach.
45  */
46 static u16 val_to_direct(int v, enum pmbus_sensor_classes class,
47                          const struct pmbus_driver_info *info)
48 {
49         int R = info->R[class] - 3;     /* take milli-units into account */
50         int b = info->b[class] * 1000;
51         long d;
52
53         d = v * info->m[class] + b;
54         /*
55          * R < 0 is true for all callers, so we don't need to bother
56          * about the R > 0 case.
57          */
58         while (R < 0) {
59                 d = DIV_ROUND_CLOSEST(d, 10);
60                 R++;
61         }
62         return (u16)d;
63 }
64
65 static long direct_to_val(u16 w, enum pmbus_sensor_classes class,
66                           const struct pmbus_driver_info *info)
67 {
68         int R = info->R[class] - 3;
69         int b = info->b[class] * 1000;
70         int m = info->m[class];
71         long d = (s16)w;
72
73         if (m == 0)
74                 return 0;
75
76         while (R < 0) {
77                 d *= 10;
78                 R++;
79         }
80         d = (d - b) / m;
81         return d;
82 }
83
84 static u32 max_current[][5] = {
85         [max20710] = { 6200, 8000, 9700, 11600 },
86         [max20730] = { 13000, 16600, 20100, 23600 },
87         [max20734] = { 21000, 27000, 32000, 38000 },
88         [max20743] = { 18900, 24100, 29200, 34100 },
89 };
90
91 static int max20730_read_word_data(struct i2c_client *client, int page,
92                                    int phase, int reg)
93 {
94         const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
95         const struct max20730_data *data = to_max20730_data(info);
96         int ret = 0;
97         u32 max_c;
98
99         switch (reg) {
100         case PMBUS_OT_FAULT_LIMIT:
101                 switch ((data->mfr_devset1 >> 11) & 0x3) {
102                 case 0x0:
103                         ret = val_to_direct(150000, PSC_TEMPERATURE, info);
104                         break;
105                 case 0x1:
106                         ret = val_to_direct(130000, PSC_TEMPERATURE, info);
107                         break;
108                 default:
109                         ret = -ENODATA;
110                         break;
111                 }
112                 break;
113         case PMBUS_IOUT_OC_FAULT_LIMIT:
114                 max_c = max_current[data->id][(data->mfr_devset1 >> 5) & 0x3];
115                 ret = val_to_direct(max_c, PSC_CURRENT_OUT, info);
116                 break;
117         default:
118                 ret = -ENODATA;
119                 break;
120         }
121         return ret;
122 }
123
124 static int max20730_write_word_data(struct i2c_client *client, int page,
125                                     int reg, u16 word)
126 {
127         struct pmbus_driver_info *info;
128         struct max20730_data *data;
129         u16 devset1;
130         int ret = 0;
131         int idx;
132
133         info = (struct pmbus_driver_info *)pmbus_get_driver_info(client);
134         data = to_max20730_data(info);
135
136         mutex_lock(&data->lock);
137         devset1 = data->mfr_devset1;
138
139         switch (reg) {
140         case PMBUS_OT_FAULT_LIMIT:
141                 devset1 &= ~(BIT(11) | BIT(12));
142                 if (direct_to_val(word, PSC_TEMPERATURE, info) < 140000)
143                         devset1 |= BIT(11);
144                 break;
145         case PMBUS_IOUT_OC_FAULT_LIMIT:
146                 devset1 &= ~(BIT(5) | BIT(6));
147
148                 idx = find_closest(direct_to_val(word, PSC_CURRENT_OUT, info),
149                                    max_current[data->id], 4);
150                 devset1 |= (idx << 5);
151                 break;
152         default:
153                 ret = -ENODATA;
154                 break;
155         }
156
157         if (!ret && devset1 != data->mfr_devset1) {
158                 ret = i2c_smbus_write_word_data(client, MAX20730_MFR_DEVSET1,
159                                                 devset1);
160                 if (!ret) {
161                         data->mfr_devset1 = devset1;
162                         pmbus_clear_cache(client);
163                 }
164         }
165         mutex_unlock(&data->lock);
166         return ret;
167 }
168
169 static const struct pmbus_driver_info max20730_info[] = {
170         [max20710] = {
171                 .pages = 1,
172                 .read_word_data = max20730_read_word_data,
173                 .write_word_data = max20730_write_word_data,
174
175                 /* Source : Maxim AN6140 and AN6042 */
176                 .format[PSC_TEMPERATURE] = direct,
177                 .m[PSC_TEMPERATURE] = 21,
178                 .b[PSC_TEMPERATURE] = 5887,
179                 .R[PSC_TEMPERATURE] = -1,
180
181                 .format[PSC_VOLTAGE_IN] = direct,
182                 .m[PSC_VOLTAGE_IN] = 3609,
183                 .b[PSC_VOLTAGE_IN] = 0,
184                 .R[PSC_VOLTAGE_IN] = -2,
185
186                 .format[PSC_CURRENT_OUT] = direct,
187                 .m[PSC_CURRENT_OUT] = 153,
188                 .b[PSC_CURRENT_OUT] = 4976,
189                 .R[PSC_CURRENT_OUT] = -1,
190
191                 .format[PSC_VOLTAGE_OUT] = linear,
192
193                 .func[0] = PMBUS_HAVE_VIN |
194                         PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
195                         PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
196                         PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
197                         PMBUS_HAVE_STATUS_INPUT,
198         },
199         [max20730] = {
200                 .pages = 1,
201                 .read_word_data = max20730_read_word_data,
202                 .write_word_data = max20730_write_word_data,
203
204                 /* Source : Maxim AN6042 */
205                 .format[PSC_TEMPERATURE] = direct,
206                 .m[PSC_TEMPERATURE] = 21,
207                 .b[PSC_TEMPERATURE] = 5887,
208                 .R[PSC_TEMPERATURE] = -1,
209
210                 .format[PSC_VOLTAGE_IN] = direct,
211                 .m[PSC_VOLTAGE_IN] = 3609,
212                 .b[PSC_VOLTAGE_IN] = 0,
213                 .R[PSC_VOLTAGE_IN] = -2,
214
215                 /*
216                  * Values in the datasheet are adjusted for temperature and
217                  * for the relationship between Vin and Vout.
218                  * Unfortunately, the data sheet suggests that Vout measurement
219                  * may be scaled with a resistor array. This is indeed the case
220                  * at least on the evaulation boards. As a result, any in-driver
221                  * adjustments would either be wrong or require elaborate means
222                  * to configure the scaling. Instead of doing that, just report
223                  * raw values and let userspace handle adjustments.
224                  */
225                 .format[PSC_CURRENT_OUT] = direct,
226                 .m[PSC_CURRENT_OUT] = 153,
227                 .b[PSC_CURRENT_OUT] = 4976,
228                 .R[PSC_CURRENT_OUT] = -1,
229
230                 .format[PSC_VOLTAGE_OUT] = linear,
231
232                 .func[0] = PMBUS_HAVE_VIN |
233                         PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
234                         PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
235                         PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
236                         PMBUS_HAVE_STATUS_INPUT,
237         },
238         [max20734] = {
239                 .pages = 1,
240                 .read_word_data = max20730_read_word_data,
241                 .write_word_data = max20730_write_word_data,
242
243                 /* Source : Maxim AN6209 */
244                 .format[PSC_TEMPERATURE] = direct,
245                 .m[PSC_TEMPERATURE] = 21,
246                 .b[PSC_TEMPERATURE] = 5887,
247                 .R[PSC_TEMPERATURE] = -1,
248
249                 .format[PSC_VOLTAGE_IN] = direct,
250                 .m[PSC_VOLTAGE_IN] = 3592,
251                 .b[PSC_VOLTAGE_IN] = 0,
252                 .R[PSC_VOLTAGE_IN] = -2,
253
254                 .format[PSC_CURRENT_OUT] = direct,
255                 .m[PSC_CURRENT_OUT] = 111,
256                 .b[PSC_CURRENT_OUT] = 3461,
257                 .R[PSC_CURRENT_OUT] = -1,
258
259                 .format[PSC_VOLTAGE_OUT] = linear,
260
261                 .func[0] = PMBUS_HAVE_VIN |
262                         PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
263                         PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
264                         PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
265                         PMBUS_HAVE_STATUS_INPUT,
266         },
267         [max20743] = {
268                 .pages = 1,
269                 .read_word_data = max20730_read_word_data,
270                 .write_word_data = max20730_write_word_data,
271
272                 /* Source : Maxim AN6042 */
273                 .format[PSC_TEMPERATURE] = direct,
274                 .m[PSC_TEMPERATURE] = 21,
275                 .b[PSC_TEMPERATURE] = 5887,
276                 .R[PSC_TEMPERATURE] = -1,
277
278                 .format[PSC_VOLTAGE_IN] = direct,
279                 .m[PSC_VOLTAGE_IN] = 3597,
280                 .b[PSC_VOLTAGE_IN] = 0,
281                 .R[PSC_VOLTAGE_IN] = -2,
282
283                 .format[PSC_CURRENT_OUT] = direct,
284                 .m[PSC_CURRENT_OUT] = 95,
285                 .b[PSC_CURRENT_OUT] = 5014,
286                 .R[PSC_CURRENT_OUT] = -1,
287
288                 .format[PSC_VOLTAGE_OUT] = linear,
289
290                 .func[0] = PMBUS_HAVE_VIN |
291                         PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
292                         PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
293                         PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP |
294                         PMBUS_HAVE_STATUS_INPUT,
295         },
296 };
297
298 static int max20730_probe(struct i2c_client *client,
299                           const struct i2c_device_id *id)
300 {
301         struct device *dev = &client->dev;
302         u8 buf[I2C_SMBUS_BLOCK_MAX + 1];
303         struct max20730_data *data;
304         enum chips chip_id;
305         int ret;
306
307         if (!i2c_check_functionality(client->adapter,
308                                      I2C_FUNC_SMBUS_READ_BYTE_DATA |
309                                      I2C_FUNC_SMBUS_READ_WORD_DATA |
310                                      I2C_FUNC_SMBUS_BLOCK_DATA))
311                 return -ENODEV;
312
313         ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
314         if (ret < 0) {
315                 dev_err(&client->dev, "Failed to read Manufacturer ID\n");
316                 return ret;
317         }
318         if (ret != 5 || strncmp(buf, "MAXIM", 5)) {
319                 buf[ret] = '\0';
320                 dev_err(dev, "Unsupported Manufacturer ID '%s'\n", buf);
321                 return -ENODEV;
322         }
323
324         /*
325          * The chips support reading PMBUS_MFR_MODEL. On both MAX20730
326          * and MAX20734, reading it returns M20743. Presumably that is
327          * the reason why the command is not documented. Unfortunately,
328          * that means that there is no reliable means to detect the chip.
329          * However, we can at least detect the chip series. Compare
330          * the returned value against 'M20743' and bail out if there is
331          * a mismatch. If that doesn't work for all chips, we may have
332          * to remove this check.
333          */
334         ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, buf);
335         if (ret < 0) {
336                 dev_err(dev, "Failed to read Manufacturer Model\n");
337                 return ret;
338         }
339         if (ret != 6 || strncmp(buf, "M20743", 6)) {
340                 buf[ret] = '\0';
341                 dev_err(dev, "Unsupported Manufacturer Model '%s'\n", buf);
342                 return -ENODEV;
343         }
344
345         ret = i2c_smbus_read_block_data(client, PMBUS_MFR_REVISION, buf);
346         if (ret < 0) {
347                 dev_err(dev, "Failed to read Manufacturer Revision\n");
348                 return ret;
349         }
350         if (ret != 1 || buf[0] != 'F') {
351                 buf[ret] = '\0';
352                 dev_err(dev, "Unsupported Manufacturer Revision '%s'\n", buf);
353                 return -ENODEV;
354         }
355
356         if (client->dev.of_node)
357                 chip_id = (enum chips)of_device_get_match_data(dev);
358         else
359                 chip_id = id->driver_data;
360
361         data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
362         if (!data)
363                 return -ENOMEM;
364         data->id = chip_id;
365         mutex_init(&data->lock);
366         memcpy(&data->info, &max20730_info[chip_id], sizeof(data->info));
367
368         ret = i2c_smbus_read_word_data(client, MAX20730_MFR_DEVSET1);
369         if (ret < 0)
370                 return ret;
371         data->mfr_devset1 = ret;
372
373         return pmbus_do_probe(client, id, &data->info);
374 }
375
376 static const struct i2c_device_id max20730_id[] = {
377         { "max20710", max20710 },
378         { "max20730", max20730 },
379         { "max20734", max20734 },
380         { "max20743", max20743 },
381         { },
382 };
383
384 MODULE_DEVICE_TABLE(i2c, max20730_id);
385
386 static const struct of_device_id max20730_of_match[] = {
387         { .compatible = "maxim,max20710", .data = (void *)max20710 },
388         { .compatible = "maxim,max20730", .data = (void *)max20730 },
389         { .compatible = "maxim,max20734", .data = (void *)max20734 },
390         { .compatible = "maxim,max20743", .data = (void *)max20743 },
391         { },
392 };
393
394 MODULE_DEVICE_TABLE(of, max20730_of_match);
395
396 static struct i2c_driver max20730_driver = {
397         .driver = {
398                 .name = "max20730",
399                 .of_match_table = max20730_of_match,
400         },
401         .probe = max20730_probe,
402         .remove = pmbus_do_remove,
403         .id_table = max20730_id,
404 };
405
406 module_i2c_driver(max20730_driver);
407
408 MODULE_AUTHOR("Guenter Roeck <[email protected]>");
409 MODULE_DESCRIPTION("PMBus driver for Maxim MAX20710 / MAX20730 / MAX20734 / MAX20743");
410 MODULE_LICENSE("GPL");
This page took 0.053934 seconds and 4 git commands to generate.