1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Hardware monitoring driver for Infineon Multi-phase Digital VR Controllers
5 * Copyright (c) 2020 Mellanox Technologies. All rights reserved.
10 #include <linux/init.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/regulator/driver.h>
17 #define XDPE122_PROT_VR12_5MV 0x01 /* VR12.0 mode, 5-mV DAC */
18 #define XDPE122_PROT_VR12_5_10MV 0x02 /* VR12.5 mode, 10-mV DAC */
19 #define XDPE122_PROT_IMVP9_10MV 0x03 /* IMVP9 mode, 10-mV DAC */
20 #define XDPE122_AMD_625MV 0x10 /* AMD mode 6.25mV */
21 #define XDPE122_PAGE_NUM 2
23 static int xdpe122_read_word_data(struct i2c_client
*client
, int page
,
26 const struct pmbus_driver_info
*info
= pmbus_get_driver_info(client
);
33 case PMBUS_VOUT_OV_FAULT_LIMIT
:
34 case PMBUS_VOUT_UV_FAULT_LIMIT
:
35 ret
= pmbus_read_word_data(client
, page
, phase
, reg
);
39 /* Convert register value to LINEAR11 data. */
40 exponent
= ((s16
)ret
) >> 11;
41 mantissa
= ((s16
)((ret
& GENMASK(10, 0)) << 5)) >> 5;
42 val
= mantissa
* 1000L;
48 /* Convert data to VID register. */
49 switch (info
->vrm_version
[page
]) {
52 return 1 + DIV_ROUND_CLOSEST(val
- 500, 10);
56 return 1 + DIV_ROUND_CLOSEST(val
- 250, 5);
60 return 1 + DIV_ROUND_CLOSEST(val
- 200, 10);
63 if (val
>= 200 && val
<= 1550)
64 return DIV_ROUND_CLOSEST((1550 - val
) * 100,
77 static int xdpe122_identify(struct i2c_client
*client
,
78 struct pmbus_driver_info
*info
)
81 int i
, ret
, vout_mode
;
83 vout_mode
= pmbus_read_byte_data(client
, 0, PMBUS_VOUT_MODE
);
84 if (vout_mode
>= 0 && vout_mode
!= 0xff) {
85 switch (vout_mode
>> 5) {
87 info
->format
[PSC_VOLTAGE_OUT
] = linear
;
90 info
->format
[PSC_VOLTAGE_OUT
] = vid
;
91 info
->read_word_data
= xdpe122_read_word_data
;
98 for (i
= 0; i
< XDPE122_PAGE_NUM
; i
++) {
99 /* Read the register with VOUT scaling value.*/
100 ret
= pmbus_read_byte_data(client
, i
, PMBUS_VOUT_MODE
);
104 vout_params
= ret
& GENMASK(4, 0);
106 switch (vout_params
) {
107 case XDPE122_PROT_VR12_5_10MV
:
108 info
->vrm_version
[i
] = vr13
;
110 case XDPE122_PROT_VR12_5MV
:
111 info
->vrm_version
[i
] = vr12
;
113 case XDPE122_PROT_IMVP9_10MV
:
114 info
->vrm_version
[i
] = imvp9
;
116 case XDPE122_AMD_625MV
:
117 info
->vrm_version
[i
] = amd625mv
;
127 static const struct regulator_desc __maybe_unused xdpe122_reg_desc
[] = {
128 PMBUS_REGULATOR("vout", 0),
129 PMBUS_REGULATOR("vout", 1),
132 static struct pmbus_driver_info xdpe122_info
= {
133 .pages
= XDPE122_PAGE_NUM
,
134 .format
[PSC_VOLTAGE_IN
] = linear
,
135 .format
[PSC_TEMPERATURE
] = linear
,
136 .format
[PSC_CURRENT_IN
] = linear
,
137 .format
[PSC_CURRENT_OUT
] = linear
,
138 .format
[PSC_POWER
] = linear
,
139 .func
[0] = PMBUS_HAVE_VIN
| PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT
|
140 PMBUS_HAVE_IIN
| PMBUS_HAVE_IOUT
| PMBUS_HAVE_STATUS_IOUT
|
141 PMBUS_HAVE_TEMP
| PMBUS_HAVE_STATUS_TEMP
|
142 PMBUS_HAVE_POUT
| PMBUS_HAVE_PIN
| PMBUS_HAVE_STATUS_INPUT
,
143 .func
[1] = PMBUS_HAVE_VIN
| PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT
|
144 PMBUS_HAVE_IIN
| PMBUS_HAVE_IOUT
| PMBUS_HAVE_STATUS_IOUT
|
145 PMBUS_HAVE_TEMP
| PMBUS_HAVE_STATUS_TEMP
|
146 PMBUS_HAVE_POUT
| PMBUS_HAVE_PIN
| PMBUS_HAVE_STATUS_INPUT
,
147 .identify
= xdpe122_identify
,
148 #if IS_ENABLED(CONFIG_SENSORS_XDPE122_REGULATOR)
150 .reg_desc
= xdpe122_reg_desc
,
154 static int xdpe122_probe(struct i2c_client
*client
)
156 struct pmbus_driver_info
*info
;
158 info
= devm_kmemdup(&client
->dev
, &xdpe122_info
, sizeof(*info
),
163 return pmbus_do_probe(client
, info
);
166 static const struct i2c_device_id xdpe122_id
[] = {
173 MODULE_DEVICE_TABLE(i2c
, xdpe122_id
);
175 static const struct of_device_id __maybe_unused xdpe122_of_match
[] = {
176 {.compatible
= "infineon,xdpe11280"},
177 {.compatible
= "infineon,xdpe12254"},
178 {.compatible
= "infineon,xdpe12284"},
181 MODULE_DEVICE_TABLE(of
, xdpe122_of_match
);
183 static struct i2c_driver xdpe122_driver
= {
186 .of_match_table
= of_match_ptr(xdpe122_of_match
),
188 .probe
= xdpe122_probe
,
189 .id_table
= xdpe122_id
,
192 module_i2c_driver(xdpe122_driver
);
194 MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
195 MODULE_DESCRIPTION("PMBus driver for Infineon XDPE122 family");
196 MODULE_LICENSE("GPL");
197 MODULE_IMPORT_NS(PMBUS
);