mp2975.c (1f6f34d08a95b953c58e1c7388a787e78d819c83) mp2975.c (1feb31e810b0634d962920b7c2ccb54d2817ba56)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Hardware monitoring driver for MPS Multi-phase Digital VR Controllers
4 *
5 * Copyright (C) 2020 Nvidia Technologies Ltd.
6 */
7
8#include <linux/err.h>

--- 56 unchanged lines hidden (view full) ---

65 struct pmbus_driver_info info;
66 enum chips chip_id;
67 int vout_scale;
68 int vid_step[MP2975_PAGE_NUM];
69 int vref[MP2975_PAGE_NUM];
70 int vref_off[MP2975_PAGE_NUM];
71 int vout_max[MP2975_PAGE_NUM];
72 int vout_ov_fixed[MP2975_PAGE_NUM];
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Hardware monitoring driver for MPS Multi-phase Digital VR Controllers
4 *
5 * Copyright (C) 2020 Nvidia Technologies Ltd.
6 */
7
8#include <linux/err.h>

--- 56 unchanged lines hidden (view full) ---

65 struct pmbus_driver_info info;
66 enum chips chip_id;
67 int vout_scale;
68 int vid_step[MP2975_PAGE_NUM];
69 int vref[MP2975_PAGE_NUM];
70 int vref_off[MP2975_PAGE_NUM];
71 int vout_max[MP2975_PAGE_NUM];
72 int vout_ov_fixed[MP2975_PAGE_NUM];
73 int vout_format[MP2975_PAGE_NUM];
74 int curr_sense_gain[MP2975_PAGE_NUM];
75};
76
77static const struct i2c_device_id mp2975_id[] = {
78 {"mp2975", mp2975},
79 {}
80};
81
82MODULE_DEVICE_TABLE(i2c, mp2975_id);
83
84#define to_mp2975_data(x) container_of(x, struct mp2975_data, info)
85
73 int curr_sense_gain[MP2975_PAGE_NUM];
74};
75
76static const struct i2c_device_id mp2975_id[] = {
77 {"mp2975", mp2975},
78 {}
79};
80
81MODULE_DEVICE_TABLE(i2c, mp2975_id);
82
83#define to_mp2975_data(x) container_of(x, struct mp2975_data, info)
84
86static int mp2975_read_byte_data(struct i2c_client *client, int page, int reg)
87{
88 switch (reg) {
89 case PMBUS_VOUT_MODE:
90 /*
91 * Enforce VOUT direct format, since device allows to set the
92 * different formats for the different rails. Conversion from
93 * VID to direct provided by driver internally, in case it is
94 * necessary.
95 */
96 return PB_VOUT_MODE_DIRECT;
97 default:
98 return -ENODATA;
99 }
100}
101
102static int
103mp2975_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg,
104 u16 mask)
105{
106 int ret = pmbus_read_word_data(client, page, phase, reg);
107
108 return (ret > 0) ? ret & mask : ret;
109}

--- 158 unchanged lines hidden (view full) ---

268 MP2975_MFR_UVP_SET,
269 GENMASK(2, 0));
270 if (ret < 0)
271 return ret;
272
273 ret = DIV_ROUND_CLOSEST(data->vref[page] * 10 - 50 *
274 (ret + 1) * data->vout_scale, 10);
275 break;
85static int
86mp2975_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg,
87 u16 mask)
88{
89 int ret = pmbus_read_word_data(client, page, phase, reg);
90
91 return (ret > 0) ? ret & mask : ret;
92}

--- 158 unchanged lines hidden (view full) ---

251 MP2975_MFR_UVP_SET,
252 GENMASK(2, 0));
253 if (ret < 0)
254 return ret;
255
256 ret = DIV_ROUND_CLOSEST(data->vref[page] * 10 - 50 *
257 (ret + 1) * data->vout_scale, 10);
258 break;
276 case PMBUS_READ_VOUT:
277 ret = mp2975_read_word_helper(client, page, phase, reg,
278 GENMASK(11, 0));
279 if (ret < 0)
280 return ret;
281
282 /*
283 * READ_VOUT can be provided in VID or direct format. The
284 * format type is specified by bit 15 of the register
285 * MP2975_MFR_DC_LOOP_CTRL. The driver enforces VOUT direct
286 * format, since device allows to set the different formats for
287 * the different rails and also all VOUT limits registers are
288 * provided in a direct format. In case format is VID - convert
289 * to direct.
290 */
291 if (data->vout_format[page] == vid)
292 ret = mp2975_vid2direct(info->vrm_version[page], ret);
293 break;
294 case PMBUS_VIRT_READ_POUT_MAX:
295 ret = mp2975_read_word_helper(client, page, phase,
296 MP2975_MFR_READ_POUT_PK,
297 GENMASK(12, 0));
298 if (ret < 0)
299 return ret;
300
301 ret = DIV_ROUND_CLOSEST(ret, 4);

--- 271 unchanged lines hidden (view full) ---

573 return ret;
574
575 data->vout_max[page] = mp2975_vid2direct(info->vrm_version[page], ret &
576 GENMASK(8, 0));
577 return 0;
578}
579
580static int
259 case PMBUS_VIRT_READ_POUT_MAX:
260 ret = mp2975_read_word_helper(client, page, phase,
261 MP2975_MFR_READ_POUT_PK,
262 GENMASK(12, 0));
263 if (ret < 0)
264 return ret;
265
266 ret = DIV_ROUND_CLOSEST(ret, 4);

--- 271 unchanged lines hidden (view full) ---

538 return ret;
539
540 data->vout_max[page] = mp2975_vid2direct(info->vrm_version[page], ret &
541 GENMASK(8, 0));
542 return 0;
543}
544
545static int
581mp2975_identify_vout_format(struct i2c_client *client,
582 struct mp2975_data *data, int page)
546mp2975_set_vout_format(struct i2c_client *client,
547 struct mp2975_data *data, int page)
583{
584 int ret;
585
586 ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL);
587 if (ret < 0)
588 return ret;
548{
549 int ret;
550
551 ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL);
552 if (ret < 0)
553 return ret;
589
590 if (ret & MP2975_VOUT_FORMAT)
591 data->vout_format[page] = vid;
592 else
593 data->vout_format[page] = direct;
594 return 0;
554 /* Enable DIRECT VOUT format 1mV/LSB */
555 if (ret & MP2975_VOUT_FORMAT) {
556 ret &= ~MP2975_VOUT_FORMAT;
557 ret = i2c_smbus_write_word_data(client, MP2975_MFR_DC_LOOP_CTRL, ret);
558 }
559 return ret;
595}
596
597static int
598mp2975_vout_ov_scale_get(struct i2c_client *client, struct mp2975_data *data,
599 struct pmbus_driver_info *info)
600{
601 int thres_dev, sense_ampl, ret;
602

--- 41 unchanged lines hidden (view full) ---

644 if (ret < 0)
645 return ret;
646
647 /* Obtain maximum voltage values. */
648 ret = mp2975_vout_max_get(client, data, info, i);
649 if (ret < 0)
650 return ret;
651
560}
561
562static int
563mp2975_vout_ov_scale_get(struct i2c_client *client, struct mp2975_data *data,
564 struct pmbus_driver_info *info)
565{
566 int thres_dev, sense_ampl, ret;
567

--- 41 unchanged lines hidden (view full) ---

609 if (ret < 0)
610 return ret;
611
612 /* Obtain maximum voltage values. */
613 ret = mp2975_vout_max_get(client, data, info, i);
614 if (ret < 0)
615 return ret;
616
652 /*
653 * Get VOUT format for READ_VOUT command : VID or direct.
654 * Pages on same device can be configured with different
655 * formats.
656 */
657 ret = mp2975_identify_vout_format(client, data, i);
617 /* Set VOUT format for READ_VOUT command : direct. */
618 ret = mp2975_set_vout_format(client, data, i);
658 if (ret < 0)
659 return ret;
660
661 /*
662 * Set over-voltage fixed value. Thresholds are provided as
663 * fixed value, and tracking value. The minimum of them are
664 * exposed as over-voltage critical threshold.
665 */

--- 18 unchanged lines hidden (view full) ---

684 .m[PSC_VOLTAGE_OUT] = 1,
685 .R[PSC_VOLTAGE_OUT] = 3,
686 .m[PSC_CURRENT_OUT] = 1,
687 .m[PSC_POWER] = 1,
688 .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
689 PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
690 PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT |
691 PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | PMBUS_PHASE_VIRTUAL,
619 if (ret < 0)
620 return ret;
621
622 /*
623 * Set over-voltage fixed value. Thresholds are provided as
624 * fixed value, and tracking value. The minimum of them are
625 * exposed as over-voltage critical threshold.
626 */

--- 18 unchanged lines hidden (view full) ---

645 .m[PSC_VOLTAGE_OUT] = 1,
646 .R[PSC_VOLTAGE_OUT] = 3,
647 .m[PSC_CURRENT_OUT] = 1,
648 .m[PSC_POWER] = 1,
649 .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
650 PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
651 PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT |
652 PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | PMBUS_PHASE_VIRTUAL,
692 .read_byte_data = mp2975_read_byte_data,
693 .read_word_data = mp2975_read_word_data,
694};
695
696static int mp2975_probe(struct i2c_client *client)
697{
698 struct pmbus_driver_info *info;
699 struct mp2975_data *data;
700 int ret;

--- 80 unchanged lines hidden ---
653 .read_word_data = mp2975_read_word_data,
654};
655
656static int mp2975_probe(struct i2c_client *client)
657{
658 struct pmbus_driver_info *info;
659 struct mp2975_data *data;
660 int ret;

--- 80 unchanged lines hidden ---