1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Hardware monitoring driver for MPS Multi-phase Digital VR Controllers(MP2993)
7 #include <linux/module.h>
8 #include <linux/of_device.h>
11 #define MP2993_VOUT_OVUV_UINT 125
12 #define MP2993_VOUT_OVUV_DIV 64
13 #define MP2993_VIN_LIMIT_UINT 1
14 #define MP2993_VIN_LIMIT_DIV 8
15 #define MP2993_READ_VIN_UINT 1
16 #define MP2993_READ_VIN_DIV 32
18 #define MP2993_PAGE_NUM 2
20 #define MP2993_RAIL1_FUNC (PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | \
21 PMBUS_HAVE_IOUT | PMBUS_HAVE_POUT | \
22 PMBUS_HAVE_TEMP | PMBUS_HAVE_PIN | \
24 PMBUS_HAVE_STATUS_VOUT | \
25 PMBUS_HAVE_STATUS_IOUT | \
26 PMBUS_HAVE_STATUS_TEMP | \
27 PMBUS_HAVE_STATUS_INPUT)
29 #define MP2993_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | \
30 PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP | \
31 PMBUS_HAVE_STATUS_VOUT | \
32 PMBUS_HAVE_STATUS_IOUT | \
33 PMBUS_HAVE_STATUS_TEMP | \
34 PMBUS_HAVE_STATUS_INPUT)
36 /* Converts a linear11 data exponent to a specified value */
37 static u16
mp2993_linear11_exponent_transfer(u16 word
, u16 expect_exponent
)
39 s16 exponent
, mantissa
, target_exponent
;
41 exponent
= ((s16
)word
) >> 11;
42 mantissa
= ((s16
)((word
& 0x7ff) << 5)) >> 5;
43 target_exponent
= (s16
)((expect_exponent
& 0x1f) << 11) >> 11;
45 if (exponent
> target_exponent
)
46 mantissa
= mantissa
<< (exponent
- target_exponent
);
48 mantissa
= mantissa
>> (target_exponent
- exponent
);
50 return (mantissa
& 0x7ff) | ((expect_exponent
<< 11) & 0xf800);
54 mp2993_set_vout_format(struct i2c_client
*client
, int page
, int format
)
58 ret
= i2c_smbus_write_byte_data(client
, PMBUS_PAGE
, page
);
62 return i2c_smbus_write_byte_data(client
, PMBUS_VOUT_MODE
, format
);
65 static int mp2993_identify(struct i2c_client
*client
, struct pmbus_driver_info
*info
)
69 /* Set vout to direct format for rail1. */
70 ret
= mp2993_set_vout_format(client
, 0, PB_VOUT_MODE_DIRECT
);
74 /* Set vout to direct format for rail2. */
75 return mp2993_set_vout_format(client
, 1, PB_VOUT_MODE_DIRECT
);
78 static int mp2993_read_word_data(struct i2c_client
*client
, int page
, int phase
,
84 case PMBUS_VOUT_OV_FAULT_LIMIT
:
85 case PMBUS_VOUT_UV_FAULT_LIMIT
:
86 ret
= pmbus_read_word_data(client
, page
, phase
, reg
);
90 ret
= DIV_ROUND_CLOSEST(ret
* MP2993_VOUT_OVUV_UINT
, MP2993_VOUT_OVUV_DIV
);
92 case PMBUS_OT_FAULT_LIMIT
:
93 case PMBUS_OT_WARN_LIMIT
:
95 * The MP2993 ot fault limit value and ot warn limit value
96 * per rail are always the same, so only PMBUS_OT_FAULT_LIMIT
97 * and PMBUS_OT_WARN_LIMIT register in page 0 are defined to
98 * indicates the limit value.
100 ret
= pmbus_read_word_data(client
, 0, phase
, reg
);
103 /* The MP2993 vin scale is (1/32V)/Lsb */
104 ret
= pmbus_read_word_data(client
, page
, phase
, reg
);
108 ret
= DIV_ROUND_CLOSEST((ret
& GENMASK(9, 0)) * MP2993_READ_VIN_UINT
,
109 MP2993_READ_VIN_DIV
);
111 case PMBUS_VIN_OV_FAULT_LIMIT
:
112 case PMBUS_VIN_OV_WARN_LIMIT
:
113 case PMBUS_VIN_UV_WARN_LIMIT
:
114 case PMBUS_VIN_UV_FAULT_LIMIT
:
115 /* The MP2993 vin limit scale is (1/8V)/Lsb */
116 ret
= pmbus_read_word_data(client
, page
, phase
, reg
);
120 ret
= DIV_ROUND_CLOSEST((ret
& GENMASK(7, 0)) * MP2993_VIN_LIMIT_UINT
,
121 MP2993_VIN_LIMIT_DIV
);
123 case PMBUS_READ_IOUT
:
125 case PMBUS_IIN_OC_WARN_LIMIT
:
126 case PMBUS_IOUT_OC_FAULT_LIMIT
:
127 case PMBUS_IOUT_OC_WARN_LIMIT
:
128 case PMBUS_READ_VOUT
:
130 case PMBUS_READ_POUT
:
131 case PMBUS_READ_TEMPERATURE_1
:
142 static int mp2993_write_word_data(struct i2c_client
*client
, int page
, int reg
,
148 case PMBUS_VOUT_OV_FAULT_LIMIT
:
149 case PMBUS_VOUT_UV_FAULT_LIMIT
:
150 ret
= DIV_ROUND_CLOSEST(word
* MP2993_VOUT_OVUV_DIV
, MP2993_VOUT_OVUV_UINT
);
151 ret
= pmbus_write_word_data(client
, 0, reg
, ret
);
153 case PMBUS_OT_FAULT_LIMIT
:
154 case PMBUS_OT_WARN_LIMIT
:
156 * The MP2993 ot fault limit value and ot warn limit value
157 * per rail are always the same, so only PMBUS_OT_FAULT_LIMIT
158 * and PMBUS_OT_WARN_LIMIT register in page 0 are defined to
159 * config the ot limit value.
161 ret
= pmbus_write_word_data(client
, 0, reg
, word
);
163 case PMBUS_VIN_OV_FAULT_LIMIT
:
164 case PMBUS_VIN_OV_WARN_LIMIT
:
165 case PMBUS_VIN_UV_WARN_LIMIT
:
166 case PMBUS_VIN_UV_FAULT_LIMIT
:
167 /* The MP2993 vin limit scale is (1/8V)/Lsb */
168 ret
= pmbus_write_word_data(client
, 0, reg
,
169 DIV_ROUND_CLOSEST(word
* MP2993_VIN_LIMIT_DIV
,
170 MP2993_VIN_LIMIT_UINT
));
172 case PMBUS_IIN_OC_WARN_LIMIT
:
174 * The PMBUS_IIN_OC_WARN_LIMIT of MP2993 is linear11 format,
175 * and the exponent is a constant value(5'b00000), so the
176 * exponent of word parameter should be converted to 5'b00000.
178 ret
= pmbus_write_word_data(client
, page
, reg
,
179 mp2993_linear11_exponent_transfer(word
, 0x00));
182 case PMBUS_IOUT_OC_FAULT_LIMIT
:
183 case PMBUS_IOUT_OC_WARN_LIMIT
:
185 * The PMBUS_IOUT_OC_FAULT_LIMIT and PMBUS_IOUT_OC_WARN_LIMIT
186 * of MP2993 can be regarded as linear11 format, and the
187 * exponent is a 5'b00001 or 5'b00000. To ensure a larger
188 * range of limit value, so the exponent of word parameter
189 * should be converted to 5'b00001.
191 ret
= pmbus_write_word_data(client
, page
, reg
,
192 mp2993_linear11_exponent_transfer(word
, 0x01));
202 static struct pmbus_driver_info mp2993_info
= {
203 .pages
= MP2993_PAGE_NUM
,
204 .format
[PSC_VOLTAGE_IN
] = direct
,
205 .format
[PSC_CURRENT_IN
] = linear
,
206 .format
[PSC_CURRENT_OUT
] = linear
,
207 .format
[PSC_TEMPERATURE
] = direct
,
208 .format
[PSC_POWER
] = linear
,
209 .format
[PSC_VOLTAGE_OUT
] = direct
,
211 .m
[PSC_VOLTAGE_OUT
] = 1,
212 .R
[PSC_VOLTAGE_OUT
] = 3,
213 .b
[PSC_VOLTAGE_OUT
] = 0,
215 .m
[PSC_VOLTAGE_IN
] = 1,
216 .R
[PSC_VOLTAGE_IN
] = 0,
217 .b
[PSC_VOLTAGE_IN
] = 0,
219 .m
[PSC_TEMPERATURE
] = 1,
220 .R
[PSC_TEMPERATURE
] = 0,
221 .b
[PSC_TEMPERATURE
] = 0,
223 .func
[0] = MP2993_RAIL1_FUNC
,
224 .func
[1] = MP2993_RAIL2_FUNC
,
225 .read_word_data
= mp2993_read_word_data
,
226 .write_word_data
= mp2993_write_word_data
,
227 .identify
= mp2993_identify
,
230 static int mp2993_probe(struct i2c_client
*client
)
232 return pmbus_do_probe(client
, &mp2993_info
);
235 static const struct i2c_device_id mp2993_id
[] = {
239 MODULE_DEVICE_TABLE(i2c
, mp2993_id
);
241 static const struct of_device_id __maybe_unused mp2993_of_match
[] = {
242 {.compatible
= "mps,mp2993"},
245 MODULE_DEVICE_TABLE(of
, mp2993_of_match
);
247 static struct i2c_driver mp2993_driver
= {
250 .of_match_table
= mp2993_of_match
,
252 .probe
= mp2993_probe
,
253 .id_table
= mp2993_id
,
256 module_i2c_driver(mp2993_driver
);
258 MODULE_AUTHOR("Noah Wang <noahwang.wang@outlook.com>");
259 MODULE_DESCRIPTION("PMBus driver for MPS MP2993");
260 MODULE_LICENSE("GPL");
261 MODULE_IMPORT_NS("PMBUS");