]> Git Repo - linux.git/blob - drivers/hwmon/pmbus/mp2856.c
Linux 6.14-rc3
[linux.git] / drivers / hwmon / pmbus / mp2856.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Hardware monitoring driver for MPS2856/2857
4  * Monolithic Power Systems VR Controllers
5  *
6  * Copyright (C) 2023 Quanta Computer lnc.
7  */
8
9 #include <linux/err.h>
10 #include <linux/i2c.h>
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/pmbus.h>
15 #include "pmbus.h"
16
17 /* Vendor specific registers. */
18 #define MP2856_MFR_VR_MULTI_CONFIG_R1   0x0d
19 #define MP2856_MFR_VR_MULTI_CONFIG_R2   0x1d
20
21 #define MP2856_MUL1_BOOT_SR_R2          0x10
22 #define MP2856_VR_ACTIVE                BIT(15)
23
24 #define MP2856_MFR_VR_CONFIG2           0x5e
25 #define MP2856_VOUT_MODE                BIT(11)
26
27 #define MP2856_MFR_VR_CONFIG1           0x68
28 #define MP2856_DRMOS_KCS                GENMASK(13, 12)
29
30 #define MP2856_MFR_READ_CS1_2_R1        0x82
31 #define MP2856_MFR_READ_CS3_4_R1        0x83
32 #define MP2856_MFR_READ_CS5_6_R1        0x84
33 #define MP2856_MFR_READ_CS7_8_R1        0x85
34 #define MP2856_MFR_READ_CS9_10_R1       0x86
35 #define MP2856_MFR_READ_CS11_12_R1      0x87
36
37 #define MP2856_MFR_READ_CS1_2_R2        0x85
38 #define MP2856_MFR_READ_CS3_4_R2        0x86
39 #define MP2856_MFR_READ_CS5_6_R2        0x87
40
41 #define MP2856_MAX_PHASE_RAIL1          8
42 #define MP2856_MAX_PHASE_RAIL2          4
43
44 #define MP2857_MAX_PHASE_RAIL1          12
45 #define MP2857_MAX_PHASE_RAIL2          4
46
47 #define MP2856_PAGE_NUM                 2
48
49 enum chips { mp2856, mp2857 };
50
51 static const int mp2856_max_phases[][MP2856_PAGE_NUM] = {
52         [mp2856] = { MP2856_MAX_PHASE_RAIL1, MP2856_MAX_PHASE_RAIL2 },
53         [mp2857] = { MP2857_MAX_PHASE_RAIL1, MP2857_MAX_PHASE_RAIL2 },
54 };
55
56 static const struct i2c_device_id mp2856_id[] = {
57         {"mp2856", mp2856},
58         {"mp2857", mp2857},
59         {}
60 };
61
62 MODULE_DEVICE_TABLE(i2c, mp2856_id);
63
64 struct mp2856_data {
65         struct pmbus_driver_info info;
66         int vout_format[MP2856_PAGE_NUM];
67         int curr_sense_gain[MP2856_PAGE_NUM];
68         int max_phases[MP2856_PAGE_NUM];
69 };
70
71 #define to_mp2856_data(x)       container_of(x, struct mp2856_data, info)
72
73 #define MAX_LIN_MANTISSA        (1023 * 1000)
74 #define MIN_LIN_MANTISSA        (511 * 1000)
75
76 static u16 val2linear11(s64 val)
77 {
78         s16 exponent = 0, mantissa;
79         bool negative = false;
80
81         if (val == 0)
82                 return 0;
83
84         if (val < 0) {
85                 negative = true;
86                 val = -val;
87         }
88
89         /* Reduce large mantissa until it fits into 10 bit */
90         while (val >= MAX_LIN_MANTISSA && exponent < 15) {
91                 exponent++;
92                 val >>= 1;
93         }
94         /* Increase small mantissa to improve precision */
95         while (val < MIN_LIN_MANTISSA && exponent > -15) {
96                 exponent--;
97                 val <<= 1;
98         }
99
100         /* Convert mantissa from milli-units to units */
101         mantissa = clamp_val(DIV_ROUND_CLOSEST_ULL(val, 1000), 0, 0x3ff);
102
103         /* restore sign */
104         if (negative)
105                 mantissa = -mantissa;
106
107         /* Convert to 5 bit exponent, 11 bit mantissa */
108         return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
109 }
110
111 static int
112 mp2856_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg,
113                         u16 mask)
114 {
115         int ret = pmbus_read_word_data(client, page, phase, reg);
116
117         return (ret > 0) ? ret & mask : ret;
118 }
119
120 static int
121 mp2856_read_vout(struct i2c_client *client, struct mp2856_data *data, int page,
122                  int phase, u8 reg)
123 {
124         int ret;
125
126         ret = mp2856_read_word_helper(client, page, phase, reg,
127                                       GENMASK(9, 0));
128         if (ret < 0)
129                 return ret;
130
131         /* convert vout result to direct format */
132         ret = (data->vout_format[page] == vid) ?
133                 ((ret + 49) * 5) : ((ret * 1000) >> 8);
134
135         return ret;
136 }
137
138 static int
139 mp2856_read_phase(struct i2c_client *client, struct mp2856_data *data,
140                   int page, int phase, u8 reg)
141 {
142         int ret;
143         int val;
144
145         ret = pmbus_read_word_data(client, page, phase, reg);
146         if (ret < 0)
147                 return ret;
148
149         if (!((phase + 1) % MP2856_PAGE_NUM))
150                 ret >>= 8;
151         ret &= 0xff;
152
153         /*
154          * Output value is calculated as: (READ_CSx * 12.5mV - 1.23V) / (Kcs * Rcs)
155          */
156         val = (ret * 125) - 12300;
157
158         return val2linear11(val);
159 }
160
161 static int
162 mp2856_read_phases(struct i2c_client *client, struct mp2856_data *data,
163                    int page, int phase)
164 {
165         int ret;
166
167         if (page == 0) {
168                 switch (phase) {
169                 case 0 ... 1:
170                         ret = mp2856_read_phase(client, data, page, phase,
171                                                 MP2856_MFR_READ_CS1_2_R1);
172                         break;
173                 case 2 ... 3:
174                         ret = mp2856_read_phase(client, data, page, phase,
175                                                 MP2856_MFR_READ_CS3_4_R1);
176                         break;
177                 case 4 ... 5:
178                         ret = mp2856_read_phase(client, data, page, phase,
179                                                 MP2856_MFR_READ_CS5_6_R1);
180                         break;
181                 case 6 ... 7:
182                         ret = mp2856_read_phase(client, data, page, phase,
183                                                 MP2856_MFR_READ_CS7_8_R1);
184                         break;
185                 default:
186                         return -ENODATA;
187                 }
188         } else {
189                 switch (phase) {
190                 case 0 ... 1:
191                         ret = mp2856_read_phase(client, data, page, phase,
192                                                 MP2856_MFR_READ_CS1_2_R2);
193                         break;
194                 case 2 ... 3:
195                         ret = mp2856_read_phase(client, data, page, phase,
196                                                 MP2856_MFR_READ_CS1_2_R2);
197                         break;
198                 default:
199                         return -ENODATA;
200                 }
201         }
202         return ret;
203 }
204
205 static int
206 mp2856_read_word_data(struct i2c_client *client, int page,
207                       int phase, int reg)
208 {
209         const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
210         struct mp2856_data *data = to_mp2856_data(info);
211         int ret;
212
213         switch (reg) {
214         case PMBUS_READ_VOUT:
215                 ret = mp2856_read_vout(client, data, page, phase, reg);
216                 break;
217         case PMBUS_READ_IOUT:
218                 if (phase != 0xff)
219                         ret = mp2856_read_phases(client, data, page, phase);
220                 else
221                         ret = pmbus_read_word_data(client, page, phase, reg);
222                 break;
223         default:
224                 return -ENODATA;
225         }
226
227         return ret;
228 }
229
230 static int
231 mp2856_read_byte_data(struct i2c_client *client, int page, int reg)
232 {
233         switch (reg) {
234         case PMBUS_VOUT_MODE:
235                 /* Enforce VOUT direct format. */
236                 return PB_VOUT_MODE_DIRECT;
237         default:
238                 return -ENODATA;
239         }
240 }
241
242 static int
243 mp2856_identify_multiphase(struct i2c_client *client, u8 reg, u8 max_phase,
244                            u16 mask)
245 {
246         int ret;
247
248         ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2);
249         if (ret < 0)
250                 return ret;
251
252         ret = i2c_smbus_read_word_data(client, reg);
253         if (ret < 0)
254                 return ret;
255
256         ret &= mask;
257         return (ret >= max_phase) ? max_phase : ret;
258 }
259
260 static int
261 mp2856_identify_multiphase_rail1(struct i2c_client *client,
262                                  struct mp2856_data *data)
263 {
264         int ret, i;
265
266         ret = mp2856_identify_multiphase(client, MP2856_MFR_VR_MULTI_CONFIG_R1,
267                                          MP2856_MAX_PHASE_RAIL1, GENMASK(3, 0));
268         if (ret < 0)
269                 return ret;
270
271         data->info.phases[0] = (ret > data->max_phases[0]) ?
272                                 data->max_phases[0] : ret;
273
274         for (i = 0 ; i < data->info.phases[0]; i++)
275                 data->info.pfunc[i] |= PMBUS_HAVE_IOUT;
276
277         return 0;
278 }
279
280 static int
281 mp2856_identify_multiphase_rail2(struct i2c_client *client,
282                                  struct mp2856_data *data)
283 {
284         int ret, i;
285
286         ret = mp2856_identify_multiphase(client, MP2856_MFR_VR_MULTI_CONFIG_R2,
287                                          MP2856_MAX_PHASE_RAIL2, GENMASK(2, 0));
288         if (ret < 0)
289                 return ret;
290
291         data->info.phases[1] = (ret > data->max_phases[1]) ?
292                                 data->max_phases[1] : ret;
293
294         for (i = 0 ; i < data->info.phases[0]; i++)
295                 data->info.pfunc[i] |= PMBUS_HAVE_IOUT;
296
297         return 0;
298 }
299
300 static int
301 mp2856_current_sense_gain_get(struct i2c_client *client,
302                               struct mp2856_data *data)
303 {
304         int i, ret;
305
306         /*
307          * Obtain DrMOS current sense gain of power stage from the register
308          * MP2856_MFR_VR_CONFIG1, bits 13-12. The value is selected as below:
309          * 00b - 5µA/A, 01b - 8.5µA/A, 10b - 9.7µA/A, 11b - 10µA/A. Other
310          * values are invalid.
311          */
312         for (i = 0 ; i < data->info.pages; i++) {
313                 ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i);
314                 if (ret < 0)
315                         return ret;
316                 ret = i2c_smbus_read_word_data(client,
317                                                MP2856_MFR_VR_CONFIG1);
318                 if (ret < 0)
319                         return ret;
320
321                 switch ((ret & MP2856_DRMOS_KCS) >> 12) {
322                 case 0:
323                         data->curr_sense_gain[i] = 50;
324                         break;
325                 case 1:
326                         data->curr_sense_gain[i] = 85;
327                         break;
328                 case 2:
329                         data->curr_sense_gain[i] = 97;
330                         break;
331                 default:
332                         data->curr_sense_gain[i] = 100;
333                         break;
334                 }
335         }
336         return 0;
337 }
338
339 static int
340 mp2856_identify_vout_format(struct i2c_client *client,
341                             struct mp2856_data *data)
342 {
343         int i, ret;
344
345         for (i = 0; i < data->info.pages; i++) {
346                 ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i);
347                 if (ret < 0)
348                         return ret;
349
350                 ret = i2c_smbus_read_word_data(client, MP2856_MFR_VR_CONFIG2);
351                 if (ret < 0)
352                         return ret;
353
354                 data->vout_format[i] = (ret & MP2856_VOUT_MODE) ? linear : vid;
355         }
356         return 0;
357 }
358
359 static bool
360 mp2856_is_rail2_active(struct i2c_client *client)
361 {
362         int ret;
363
364         ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2);
365         if (ret < 0)
366                 return true;
367
368         ret = i2c_smbus_read_word_data(client, MP2856_MUL1_BOOT_SR_R2);
369         if (ret < 0)
370                 return true;
371
372         return (ret & MP2856_VR_ACTIVE) ? true : false;
373 }
374
375 static struct pmbus_driver_info mp2856_info = {
376         .pages = MP2856_PAGE_NUM,
377         .format[PSC_VOLTAGE_IN] = linear,
378         .format[PSC_VOLTAGE_OUT] = direct,
379         .format[PSC_TEMPERATURE] = linear,
380         .format[PSC_CURRENT_IN] = linear,
381         .format[PSC_CURRENT_OUT] = linear,
382         .format[PSC_POWER] = linear,
383         .m[PSC_VOLTAGE_OUT] = 1,
384         .R[PSC_VOLTAGE_OUT] = 3,
385         .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
386                 PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
387                 PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT |
388                 PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
389         .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_IOUT |
390                 PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP,
391         .read_byte_data = mp2856_read_byte_data,
392         .read_word_data = mp2856_read_word_data,
393 };
394
395 static int mp2856_probe(struct i2c_client *client)
396 {
397         struct pmbus_driver_info *info;
398         struct mp2856_data *data;
399         enum chips chip_id;
400         int ret;
401
402         data = devm_kzalloc(&client->dev, sizeof(struct mp2856_data),
403                             GFP_KERNEL);
404         if (!data)
405                 return -ENOMEM;
406
407         chip_id = (kernel_ulong_t)i2c_get_match_data(client);
408
409         memcpy(data->max_phases, mp2856_max_phases[chip_id],
410                sizeof(data->max_phases));
411
412         memcpy(&data->info, &mp2856_info, sizeof(*info));
413         info = &data->info;
414
415         /* Identify multiphase configuration. */
416         ret = mp2856_identify_multiphase_rail1(client, data);
417         if (ret < 0)
418                 return ret;
419
420         if (mp2856_is_rail2_active(client)) {
421                 ret = mp2856_identify_multiphase_rail2(client, data);
422                 if (ret < 0)
423                         return ret;
424         } else {
425                 /* rail2 is not active */
426                 info->pages = 1;
427         }
428
429         /* Obtain current sense gain of power stage. */
430         ret = mp2856_current_sense_gain_get(client, data);
431         if (ret)
432                 return ret;
433
434         /* Identify vout format. */
435         ret = mp2856_identify_vout_format(client, data);
436         if (ret)
437                 return ret;
438
439         /* set the device to page 0 */
440         i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
441
442         return pmbus_do_probe(client, info);
443 }
444
445 static const struct of_device_id __maybe_unused mp2856_of_match[] = {
446         {.compatible = "mps,mp2856", .data = (void *)mp2856},
447         {.compatible = "mps,mp2857", .data = (void *)mp2857},
448         {}
449 };
450 MODULE_DEVICE_TABLE(of, mp2856_of_match);
451
452 static struct i2c_driver mp2856_driver = {
453         .driver = {
454                 .name = "mp2856",
455                 .of_match_table = mp2856_of_match,
456         },
457         .probe = mp2856_probe,
458         .id_table = mp2856_id,
459 };
460
461 module_i2c_driver(mp2856_driver);
462
463 MODULE_AUTHOR("Peter Yin <[email protected]>");
464 MODULE_DESCRIPTION("PMBus driver for MPS MP2856/MP2857 device");
465 MODULE_LICENSE("GPL");
466 MODULE_IMPORT_NS("PMBUS");
This page took 0.056162 seconds and 4 git commands to generate.