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/bitops.h> |
9 | #include <linux/err.h> |
10 | #include <linux/i2c.h> |
11 | #include <linux/init.h> |
12 | #include <linux/kernel.h> |
13 | #include <linux/mod_devicetable.h> |
14 | #include <linux/module.h> |
15 | |
16 | #include "pmbus.h" |
17 | |
18 | /* Vendor specific registers. */ |
19 | #define MP2975_MFR_APS_HYS_R2 0x0d |
20 | #define MP2975_MFR_SLOPE_TRIM3 0x1d |
21 | #define MP2975_MFR_VR_MULTI_CONFIG_R1 0x0d |
22 | #define MP2975_MFR_VR_MULTI_CONFIG_R2 0x1d |
23 | #define MP2975_MFR_APS_DECAY_ADV 0x56 |
24 | #define MP2975_MFR_DC_LOOP_CTRL 0x59 |
25 | #define MP2975_MFR_OCP_UCP_PHASE_SET 0x65 |
26 | #define MP2975_MFR_VR_CONFIG1 0x68 |
27 | #define MP2975_MFR_READ_CS1_2 0x82 |
28 | #define MP2975_MFR_READ_CS3_4 0x83 |
29 | #define MP2975_MFR_READ_CS5_6 0x84 |
30 | #define MP2975_MFR_READ_CS7_8 0x85 |
31 | #define MP2975_MFR_READ_CS9_10 0x86 |
32 | #define MP2975_MFR_READ_CS11_12 0x87 |
33 | #define MP2975_MFR_READ_IOUT_PK 0x90 |
34 | #define MP2975_MFR_READ_POUT_PK 0x91 |
35 | #define MP2975_MFR_READ_VREF_R1 0xa1 |
36 | #define MP2975_MFR_READ_VREF_R2 0xa3 |
37 | #define MP2975_MFR_OVP_TH_SET 0xe5 |
38 | #define MP2975_MFR_UVP_SET 0xe6 |
39 | |
40 | #define MP2973_MFR_RESO_SET 0xc7 |
41 | |
42 | #define MP2975_VOUT_FORMAT BIT(15) |
43 | #define MP2975_VID_STEP_SEL_R1 BIT(4) |
44 | #define MP2975_IMVP9_EN_R1 BIT(13) |
45 | #define MP2975_VID_STEP_SEL_R2 BIT(3) |
46 | #define MP2975_IMVP9_EN_R2 BIT(12) |
47 | #define MP2975_PRT_THRES_DIV_OV_EN BIT(14) |
48 | #define MP2975_DRMOS_KCS GENMASK(13, 12) |
49 | #define MP2975_PROT_DEV_OV_OFF 10 |
50 | #define MP2975_PROT_DEV_OV_ON 5 |
51 | #define MP2975_SENSE_AMPL BIT(11) |
52 | #define MP2975_SENSE_AMPL_UNIT 1 |
53 | #define MP2975_SENSE_AMPL_HALF 2 |
54 | #define MP2975_VIN_UV_LIMIT_UNIT 8 |
55 | |
56 | #define MP2973_VOUT_FORMAT_R1 GENMASK(7, 6) |
57 | #define MP2973_VOUT_FORMAT_R2 GENMASK(4, 3) |
58 | #define MP2973_VOUT_FORMAT_DIRECT_R1 BIT(7) |
59 | #define MP2973_VOUT_FORMAT_LINEAR_R1 BIT(6) |
60 | #define MP2973_VOUT_FORMAT_DIRECT_R2 BIT(4) |
61 | #define MP2973_VOUT_FORMAT_LINEAR_R2 BIT(3) |
62 | |
63 | #define MP2973_MFR_VR_MULTI_CONFIG_R1 0x0d |
64 | #define MP2973_MFR_VR_MULTI_CONFIG_R2 0x1d |
65 | #define MP2973_VID_STEP_SEL_R1 BIT(4) |
66 | #define MP2973_IMVP9_EN_R1 BIT(14) |
67 | #define MP2973_VID_STEP_SEL_R2 BIT(3) |
68 | #define MP2973_IMVP9_EN_R2 BIT(13) |
69 | |
70 | #define MP2973_MFR_OCP_TOTAL_SET 0x5f |
71 | #define MP2973_OCP_TOTAL_CUR_MASK GENMASK(6, 0) |
72 | #define MP2973_MFR_OCP_LEVEL_RES BIT(15) |
73 | |
74 | #define MP2973_MFR_READ_IOUT_PK 0x90 |
75 | #define MP2973_MFR_READ_POUT_PK 0x91 |
76 | |
77 | #define MP2975_MAX_PHASE_RAIL1 8 |
78 | #define MP2975_MAX_PHASE_RAIL2 4 |
79 | |
80 | #define MP2973_MAX_PHASE_RAIL1 14 |
81 | #define MP2973_MAX_PHASE_RAIL2 6 |
82 | |
83 | #define MP2971_MAX_PHASE_RAIL1 8 |
84 | #define MP2971_MAX_PHASE_RAIL2 3 |
85 | |
86 | #define MP2975_PAGE_NUM 2 |
87 | |
88 | #define MP2975_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \ |
89 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | \ |
90 | PMBUS_HAVE_POUT | PMBUS_PHASE_VIRTUAL) |
91 | |
92 | enum chips { |
93 | mp2971, mp2973, mp2975 |
94 | }; |
95 | |
96 | static const int mp2975_max_phases[][MP2975_PAGE_NUM] = { |
97 | [mp2975] = { MP2975_MAX_PHASE_RAIL1, MP2975_MAX_PHASE_RAIL2 }, |
98 | [mp2973] = { MP2973_MAX_PHASE_RAIL1, MP2973_MAX_PHASE_RAIL2 }, |
99 | [mp2971] = { MP2971_MAX_PHASE_RAIL1, MP2971_MAX_PHASE_RAIL2 }, |
100 | }; |
101 | |
102 | struct mp2975_driver_info { |
103 | const struct pmbus_driver_info *info; |
104 | enum chips chip_id; |
105 | }; |
106 | |
107 | struct mp2975_data { |
108 | struct pmbus_driver_info info; |
109 | enum chips chip_id; |
110 | int vout_scale; |
111 | int max_phases[MP2975_PAGE_NUM]; |
112 | int vid_step[MP2975_PAGE_NUM]; |
113 | int vref[MP2975_PAGE_NUM]; |
114 | int vref_off[MP2975_PAGE_NUM]; |
115 | int vout_max[MP2975_PAGE_NUM]; |
116 | int vout_ov_fixed[MP2975_PAGE_NUM]; |
117 | int curr_sense_gain[MP2975_PAGE_NUM]; |
118 | }; |
119 | |
120 | static const struct regulator_desc __maybe_unused mp2975_reg_desc[] = { |
121 | PMBUS_REGULATOR("vout", 0), |
122 | PMBUS_REGULATOR("vout", 1), |
123 | }; |
124 | |
125 | #define to_mp2975_data(x) container_of(x, struct mp2975_data, info) |
126 | |
127 | static int mp2975_read_byte_data(struct i2c_client *client, int page, int reg) |
128 | { |
129 | switch (reg) { |
130 | case PMBUS_VOUT_MODE: |
131 | /* |
132 | * Report direct format as configured by MFR_DC_LOOP_CTRL. |
133 | * Unlike on MP2971/MP2973 the reported VOUT_MODE isn't automatically |
134 | * internally updated, but always reads as PB_VOUT_MODE_VID. |
135 | */ |
136 | return PB_VOUT_MODE_DIRECT; |
137 | default: |
138 | return -ENODATA; |
139 | } |
140 | } |
141 | |
142 | static int |
143 | mp2975_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg, |
144 | u16 mask) |
145 | { |
146 | int ret = pmbus_read_word_data(client, page, phase, reg); |
147 | |
148 | return (ret > 0) ? ret & mask : ret; |
149 | } |
150 | |
151 | static int |
152 | mp2975_vid2direct(int vrf, int val) |
153 | { |
154 | switch (vrf) { |
155 | case vr12: |
156 | if (val >= 0x01) |
157 | return 250 + (val - 1) * 5; |
158 | break; |
159 | case vr13: |
160 | if (val >= 0x01) |
161 | return 500 + (val - 1) * 10; |
162 | break; |
163 | case imvp9: |
164 | if (val >= 0x01) |
165 | return 200 + (val - 1) * 10; |
166 | break; |
167 | default: |
168 | return -EINVAL; |
169 | } |
170 | return 0; |
171 | } |
172 | |
173 | #define MAX_LIN_MANTISSA (1023 * 1000) |
174 | #define MIN_LIN_MANTISSA (511 * 1000) |
175 | |
176 | /* Converts a milli-unit DIRECT value to LINEAR11 format */ |
177 | static u16 mp2975_data2reg_linear11(s64 val) |
178 | { |
179 | s16 exponent = 0, mantissa; |
180 | bool negative = false; |
181 | |
182 | /* simple case */ |
183 | if (val == 0) |
184 | return 0; |
185 | |
186 | /* Reduce large mantissa until it fits into 10 bit */ |
187 | while (val >= MAX_LIN_MANTISSA && exponent < 15) { |
188 | exponent++; |
189 | val >>= 1; |
190 | } |
191 | /* Increase small mantissa to improve precision */ |
192 | while (val < MIN_LIN_MANTISSA && exponent > -15) { |
193 | exponent--; |
194 | val <<= 1; |
195 | } |
196 | |
197 | /* Convert mantissa from milli-units to units */ |
198 | mantissa = clamp_val(DIV_ROUND_CLOSEST_ULL(val, 1000), 0, 0x3ff); |
199 | |
200 | /* restore sign */ |
201 | if (negative) |
202 | mantissa = -mantissa; |
203 | |
204 | /* Convert to 5 bit exponent, 11 bit mantissa */ |
205 | return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800); |
206 | } |
207 | |
208 | static int |
209 | mp2975_read_phase(struct i2c_client *client, struct mp2975_data *data, |
210 | int page, int phase, u8 reg) |
211 | { |
212 | int ph_curr, ret; |
213 | |
214 | ret = pmbus_read_word_data(client, page, phase, reg); |
215 | if (ret < 0) |
216 | return ret; |
217 | |
218 | if (!((phase + 1) % MP2975_PAGE_NUM)) |
219 | ret >>= 8; |
220 | ret &= 0xff; |
221 | |
222 | /* |
223 | * Output value is calculated as: (READ_CSx / 80 – 1.23) / (Kcs * Rcs) |
224 | * where: |
225 | * - Kcs is the DrMOS current sense gain of power stage, which is |
226 | * obtained from the register MP2975_MFR_VR_CONFIG1, bits 13-12 with |
227 | * the following selection of DrMOS (data->curr_sense_gain[page]): |
228 | * 00b - 5µA/A, 01b - 8.5µA/A, 10b - 9.7µA/A, 11b - 10µA/A. |
229 | * - Rcs is the internal phase current sense resistor which is constant |
230 | * value 1kΩ. |
231 | */ |
232 | ph_curr = ret * 100 - 9800; |
233 | |
234 | /* |
235 | * Current phase sensing, providing by the device is not accurate |
236 | * for the light load. This because sampling of current occurrence of |
237 | * bit weight has a big deviation for light load. For handling such |
238 | * case phase current is represented as the maximum between the value |
239 | * calculated above and total rail current divided by number phases. |
240 | */ |
241 | ret = pmbus_read_word_data(client, page, phase, reg: PMBUS_READ_IOUT); |
242 | if (ret < 0) |
243 | return ret; |
244 | |
245 | return max_t(int, DIV_ROUND_CLOSEST(ret, data->info.phases[page]), |
246 | DIV_ROUND_CLOSEST(ph_curr, data->curr_sense_gain[page])); |
247 | } |
248 | |
249 | static int |
250 | mp2975_read_phases(struct i2c_client *client, struct mp2975_data *data, |
251 | int page, int phase) |
252 | { |
253 | int ret; |
254 | |
255 | if (page) { |
256 | switch (phase) { |
257 | case 0 ... 1: |
258 | ret = mp2975_read_phase(client, data, page, phase, |
259 | MP2975_MFR_READ_CS7_8); |
260 | break; |
261 | case 2 ... 3: |
262 | ret = mp2975_read_phase(client, data, page, phase, |
263 | MP2975_MFR_READ_CS9_10); |
264 | break; |
265 | case 4 ... 5: |
266 | ret = mp2975_read_phase(client, data, page, phase, |
267 | MP2975_MFR_READ_CS11_12); |
268 | break; |
269 | default: |
270 | return -ENODATA; |
271 | } |
272 | } else { |
273 | switch (phase) { |
274 | case 0 ... 1: |
275 | ret = mp2975_read_phase(client, data, page, phase, |
276 | MP2975_MFR_READ_CS1_2); |
277 | break; |
278 | case 2 ... 3: |
279 | ret = mp2975_read_phase(client, data, page, phase, |
280 | MP2975_MFR_READ_CS3_4); |
281 | break; |
282 | case 4 ... 5: |
283 | ret = mp2975_read_phase(client, data, page, phase, |
284 | MP2975_MFR_READ_CS5_6); |
285 | break; |
286 | case 6 ... 7: |
287 | ret = mp2975_read_phase(client, data, page, phase, |
288 | MP2975_MFR_READ_CS7_8); |
289 | break; |
290 | case 8 ... 9: |
291 | ret = mp2975_read_phase(client, data, page, phase, |
292 | MP2975_MFR_READ_CS9_10); |
293 | break; |
294 | case 10 ... 11: |
295 | ret = mp2975_read_phase(client, data, page, phase, |
296 | MP2975_MFR_READ_CS11_12); |
297 | break; |
298 | default: |
299 | return -ENODATA; |
300 | } |
301 | } |
302 | return ret; |
303 | } |
304 | |
305 | static int mp2973_read_word_data(struct i2c_client *client, int page, |
306 | int phase, int reg) |
307 | { |
308 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); |
309 | struct mp2975_data *data = to_mp2975_data(info); |
310 | int ret; |
311 | |
312 | switch (reg) { |
313 | case PMBUS_STATUS_WORD: |
314 | /* MP2973 & MP2971 return PGOOD instead of PB_STATUS_POWER_GOOD_N. */ |
315 | ret = pmbus_read_word_data(client, page, phase, reg); |
316 | ret ^= PB_STATUS_POWER_GOOD_N; |
317 | break; |
318 | case PMBUS_OT_FAULT_LIMIT: |
319 | ret = mp2975_read_word_helper(client, page, phase, reg, |
320 | GENMASK(7, 0)); |
321 | break; |
322 | case PMBUS_VIN_OV_FAULT_LIMIT: |
323 | ret = mp2975_read_word_helper(client, page, phase, reg, |
324 | GENMASK(7, 0)); |
325 | if (ret < 0) |
326 | return ret; |
327 | |
328 | ret = DIV_ROUND_CLOSEST(ret, MP2975_VIN_UV_LIMIT_UNIT); |
329 | break; |
330 | case PMBUS_VOUT_OV_FAULT_LIMIT: |
331 | /* |
332 | * MP2971 and mp2973 only supports tracking (ovp1) mode. |
333 | */ |
334 | ret = mp2975_read_word_helper(client, page, phase, |
335 | MP2975_MFR_OVP_TH_SET, |
336 | GENMASK(2, 0)); |
337 | if (ret < 0) |
338 | return ret; |
339 | |
340 | ret = data->vout_max[page] + 50 * (ret + 1); |
341 | break; |
342 | case PMBUS_VOUT_UV_FAULT_LIMIT: |
343 | ret = mp2975_read_word_helper(client, page, phase, reg, |
344 | GENMASK(8, 0)); |
345 | if (ret < 0) |
346 | return ret; |
347 | ret = mp2975_vid2direct(vrf: info->vrm_version[page], val: ret); |
348 | break; |
349 | case PMBUS_VIRT_READ_POUT_MAX: |
350 | ret = pmbus_read_word_data(client, page, phase, |
351 | MP2973_MFR_READ_POUT_PK); |
352 | break; |
353 | case PMBUS_VIRT_READ_IOUT_MAX: |
354 | ret = pmbus_read_word_data(client, page, phase, |
355 | MP2973_MFR_READ_IOUT_PK); |
356 | break; |
357 | case PMBUS_IOUT_OC_FAULT_LIMIT: |
358 | ret = mp2975_read_word_helper(client, page, phase, |
359 | MP2973_MFR_OCP_TOTAL_SET, |
360 | GENMASK(15, 0)); |
361 | if (ret < 0) |
362 | return ret; |
363 | |
364 | if (ret & MP2973_MFR_OCP_LEVEL_RES) |
365 | ret = 2 * (ret & MP2973_OCP_TOTAL_CUR_MASK); |
366 | else |
367 | ret = ret & MP2973_OCP_TOTAL_CUR_MASK; |
368 | |
369 | ret = mp2975_data2reg_linear11(val: ret * info->phases[page] * 1000); |
370 | break; |
371 | case PMBUS_UT_WARN_LIMIT: |
372 | case PMBUS_UT_FAULT_LIMIT: |
373 | case PMBUS_VIN_UV_WARN_LIMIT: |
374 | case PMBUS_VIN_UV_FAULT_LIMIT: |
375 | case PMBUS_VOUT_UV_WARN_LIMIT: |
376 | case PMBUS_VOUT_OV_WARN_LIMIT: |
377 | case PMBUS_VIN_OV_WARN_LIMIT: |
378 | case PMBUS_IIN_OC_FAULT_LIMIT: |
379 | case PMBUS_IOUT_OC_LV_FAULT_LIMIT: |
380 | case PMBUS_IOUT_OC_WARN_LIMIT: |
381 | case PMBUS_IOUT_UC_FAULT_LIMIT: |
382 | case PMBUS_POUT_OP_FAULT_LIMIT: |
383 | case PMBUS_POUT_OP_WARN_LIMIT: |
384 | case PMBUS_PIN_OP_WARN_LIMIT: |
385 | return -ENXIO; |
386 | default: |
387 | return -ENODATA; |
388 | } |
389 | |
390 | return ret; |
391 | } |
392 | |
393 | static int mp2973_write_word_data(struct i2c_client *client, int page, |
394 | int reg, u16 word) |
395 | { |
396 | u8 target, mask; |
397 | long ret; |
398 | |
399 | if (reg != PMBUS_SMBALERT_MASK) |
400 | return -ENODATA; |
401 | |
402 | /* |
403 | * Vendor-specific SMBALERT_MASK register with 16 maskable bits. |
404 | */ |
405 | ret = pmbus_read_word_data(client, page: 0, phase: 0, reg: PMBUS_SMBALERT_MASK); |
406 | if (ret < 0) |
407 | return ret; |
408 | |
409 | target = word & 0xff; |
410 | mask = word >> 8; |
411 | |
412 | /* |
413 | * Set/Clear 'bit' in 'ret' based on condition followed by define for each bit in SMBALERT_MASK. |
414 | * Also bit 2 & 15 are reserved. |
415 | */ |
416 | |
417 | #define MP2973_TEMP_OT 0 |
418 | #define MP2973_VIN_UVLO 1 |
419 | #define MP2973_VIN_OVP 3 |
420 | #define MP2973_MTP_FAULT 4 |
421 | #define MP2973_OTHER_COMM 5 |
422 | #define MP2973_MTP_BLK_TRIG 6 |
423 | #define MP2973_PACKET_ERROR 7 |
424 | #define MP2973_INVALID_DATA 8 |
425 | #define MP2973_INVALID_COMMAND 9 |
426 | #define MP2973_IOUT_OC_LV 10 |
427 | #define MP2973_IOUT_OC 11 |
428 | #define MP2973_VOUT_MAX_MIN_WARNING 12 |
429 | #define MP2973_VOLTAGE_UV 13 |
430 | #define MP2973_VOLTAGE_OV 14 |
431 | |
432 | switch (target) { |
433 | case PMBUS_STATUS_CML: |
434 | __assign_bit(MP2973_INVALID_DATA, &ret, !(mask & PB_CML_FAULT_INVALID_DATA)); |
435 | __assign_bit(MP2973_INVALID_COMMAND, &ret, !(mask & PB_CML_FAULT_INVALID_COMMAND)); |
436 | __assign_bit(MP2973_OTHER_COMM, &ret, !(mask & PB_CML_FAULT_OTHER_COMM)); |
437 | __assign_bit(MP2973_PACKET_ERROR, &ret, !(mask & PB_CML_FAULT_PACKET_ERROR)); |
438 | break; |
439 | case PMBUS_STATUS_VOUT: |
440 | __assign_bit(MP2973_VOLTAGE_UV, &ret, !(mask & PB_VOLTAGE_UV_FAULT)); |
441 | __assign_bit(MP2973_VOLTAGE_OV, &ret, !(mask & PB_VOLTAGE_OV_FAULT)); |
442 | break; |
443 | case PMBUS_STATUS_IOUT: |
444 | __assign_bit(MP2973_IOUT_OC, &ret, !(mask & PB_IOUT_OC_FAULT)); |
445 | __assign_bit(MP2973_IOUT_OC_LV, &ret, !(mask & PB_IOUT_OC_LV_FAULT)); |
446 | break; |
447 | case PMBUS_STATUS_TEMPERATURE: |
448 | __assign_bit(MP2973_TEMP_OT, &ret, !(mask & PB_TEMP_OT_FAULT)); |
449 | break; |
450 | /* |
451 | * Map remaining bits to MFR specific to let the PMBUS core mask |
452 | * those bits by default. |
453 | */ |
454 | case PMBUS_STATUS_MFR_SPECIFIC: |
455 | __assign_bit(MP2973_VIN_UVLO, &ret, !(mask & BIT(1))); |
456 | __assign_bit(MP2973_VIN_OVP, &ret, !(mask & BIT(3))); |
457 | __assign_bit(MP2973_MTP_FAULT, &ret, !(mask & BIT(4))); |
458 | __assign_bit(MP2973_MTP_BLK_TRIG, &ret, !(mask & BIT(6))); |
459 | break; |
460 | default: |
461 | return 0; |
462 | } |
463 | |
464 | return pmbus_write_word_data(client, page: 0, reg: PMBUS_SMBALERT_MASK, word: ret); |
465 | } |
466 | |
467 | static int mp2975_read_word_data(struct i2c_client *client, int page, |
468 | int phase, int reg) |
469 | { |
470 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); |
471 | struct mp2975_data *data = to_mp2975_data(info); |
472 | int ret; |
473 | |
474 | switch (reg) { |
475 | case PMBUS_OT_FAULT_LIMIT: |
476 | ret = mp2975_read_word_helper(client, page, phase, reg, |
477 | GENMASK(7, 0)); |
478 | break; |
479 | case PMBUS_VIN_OV_FAULT_LIMIT: |
480 | ret = mp2975_read_word_helper(client, page, phase, reg, |
481 | GENMASK(7, 0)); |
482 | if (ret < 0) |
483 | return ret; |
484 | |
485 | ret = DIV_ROUND_CLOSEST(ret, MP2975_VIN_UV_LIMIT_UNIT); |
486 | break; |
487 | case PMBUS_VOUT_OV_FAULT_LIMIT: |
488 | /* |
489 | * Register provides two values for over-voltage protection |
490 | * threshold for fixed (ovp2) and tracking (ovp1) modes. The |
491 | * minimum of these two values is provided as over-voltage |
492 | * fault alarm. |
493 | */ |
494 | ret = mp2975_read_word_helper(client, page, phase, |
495 | MP2975_MFR_OVP_TH_SET, |
496 | GENMASK(2, 0)); |
497 | if (ret < 0) |
498 | return ret; |
499 | |
500 | ret = min_t(int, data->vout_max[page] + 50 * (ret + 1), |
501 | data->vout_ov_fixed[page]); |
502 | break; |
503 | case PMBUS_VOUT_UV_FAULT_LIMIT: |
504 | ret = mp2975_read_word_helper(client, page, phase, |
505 | MP2975_MFR_UVP_SET, |
506 | GENMASK(2, 0)); |
507 | if (ret < 0) |
508 | return ret; |
509 | |
510 | ret = DIV_ROUND_CLOSEST(data->vref[page] * 10 - 50 * |
511 | (ret + 1) * data->vout_scale, 10); |
512 | break; |
513 | case PMBUS_VIRT_READ_POUT_MAX: |
514 | ret = mp2975_read_word_helper(client, page, phase, |
515 | MP2975_MFR_READ_POUT_PK, |
516 | GENMASK(12, 0)); |
517 | if (ret < 0) |
518 | return ret; |
519 | |
520 | ret = DIV_ROUND_CLOSEST(ret, 4); |
521 | break; |
522 | case PMBUS_VIRT_READ_IOUT_MAX: |
523 | ret = mp2975_read_word_helper(client, page, phase, |
524 | MP2975_MFR_READ_IOUT_PK, |
525 | GENMASK(12, 0)); |
526 | if (ret < 0) |
527 | return ret; |
528 | |
529 | ret = DIV_ROUND_CLOSEST(ret, 4); |
530 | break; |
531 | case PMBUS_READ_IOUT: |
532 | ret = mp2975_read_phases(client, data, page, phase); |
533 | if (ret < 0) |
534 | return ret; |
535 | |
536 | break; |
537 | case PMBUS_UT_WARN_LIMIT: |
538 | case PMBUS_UT_FAULT_LIMIT: |
539 | case PMBUS_VIN_UV_WARN_LIMIT: |
540 | case PMBUS_VIN_UV_FAULT_LIMIT: |
541 | case PMBUS_VOUT_UV_WARN_LIMIT: |
542 | case PMBUS_VOUT_OV_WARN_LIMIT: |
543 | case PMBUS_VIN_OV_WARN_LIMIT: |
544 | case PMBUS_IIN_OC_FAULT_LIMIT: |
545 | case PMBUS_IOUT_OC_LV_FAULT_LIMIT: |
546 | case PMBUS_IIN_OC_WARN_LIMIT: |
547 | case PMBUS_IOUT_OC_WARN_LIMIT: |
548 | case PMBUS_IOUT_OC_FAULT_LIMIT: |
549 | case PMBUS_IOUT_UC_FAULT_LIMIT: |
550 | case PMBUS_POUT_OP_FAULT_LIMIT: |
551 | case PMBUS_POUT_OP_WARN_LIMIT: |
552 | case PMBUS_PIN_OP_WARN_LIMIT: |
553 | return -ENXIO; |
554 | default: |
555 | return -ENODATA; |
556 | } |
557 | |
558 | return ret; |
559 | } |
560 | |
561 | static int mp2975_identify_multiphase_rail2(struct i2c_client *client, |
562 | struct mp2975_data *data) |
563 | { |
564 | int ret; |
565 | |
566 | /* |
567 | * Identify multiphase for rail 2 - could be from 0 to data->max_phases[1]. |
568 | * In case phase number is zero – only page zero is supported |
569 | */ |
570 | ret = i2c_smbus_write_byte_data(client, command: PMBUS_PAGE, value: 2); |
571 | if (ret < 0) |
572 | return ret; |
573 | |
574 | ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R2); |
575 | if (ret < 0) |
576 | return ret; |
577 | |
578 | ret &= GENMASK(2, 0); |
579 | return (ret >= data->max_phases[1]) ? data->max_phases[1] : ret; |
580 | } |
581 | |
582 | static void mp2975_set_phase_rail1(struct pmbus_driver_info *info) |
583 | { |
584 | int i; |
585 | |
586 | for (i = 0 ; i < info->phases[0]; i++) |
587 | info->pfunc[i] = PMBUS_HAVE_IOUT; |
588 | } |
589 | |
590 | static void |
591 | mp2975_set_phase_rail2(struct pmbus_driver_info *info, int num_phases) |
592 | { |
593 | int i; |
594 | |
595 | /* Set phases for rail 2 from upper to lower. */ |
596 | for (i = 1; i <= num_phases; i++) |
597 | info->pfunc[MP2975_MAX_PHASE_RAIL1 - i] = PMBUS_HAVE_IOUT; |
598 | } |
599 | |
600 | static int |
601 | mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data, |
602 | struct pmbus_driver_info *info) |
603 | { |
604 | int num_phases2, ret; |
605 | |
606 | ret = i2c_smbus_write_byte_data(client, command: PMBUS_PAGE, value: 2); |
607 | if (ret < 0) |
608 | return ret; |
609 | |
610 | /* Identify multiphase for rail 1 - could be from 1 to data->max_phases[0]. */ |
611 | ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R1); |
612 | if (ret <= 0) |
613 | return ret; |
614 | |
615 | info->phases[0] = ret & GENMASK(3, 0); |
616 | |
617 | /* |
618 | * The device provides a total of $n PWM pins, and can be configured |
619 | * to different phase count applications for rail 1 and rail 2. |
620 | * Rail 1 can be set to $n phases, while rail 2 can be set to less than |
621 | * that. When rail 1’s phase count is configured as 0, rail |
622 | * 1 operates with 1-phase DCM. When rail 2 phase count is configured |
623 | * as 0, rail 2 is disabled. |
624 | */ |
625 | if (info->phases[0] > data->max_phases[0]) |
626 | return -EINVAL; |
627 | |
628 | if (data->chip_id == mp2975) { |
629 | mp2975_set_phase_rail1(info); |
630 | num_phases2 = min(data->max_phases[0] - info->phases[0], |
631 | data->max_phases[1]); |
632 | if (info->phases[1] && info->phases[1] <= num_phases2) |
633 | mp2975_set_phase_rail2(info, num_phases: num_phases2); |
634 | } |
635 | |
636 | return 0; |
637 | } |
638 | |
639 | static int |
640 | mp2975_identify_vid(struct i2c_client *client, struct mp2975_data *data, |
641 | struct pmbus_driver_info *info, u32 reg, int page, |
642 | u32 imvp_bit, u32 vr_bit) |
643 | { |
644 | int ret; |
645 | |
646 | /* Identify VID mode and step selection. */ |
647 | ret = i2c_smbus_read_word_data(client, command: reg); |
648 | if (ret < 0) |
649 | return ret; |
650 | |
651 | if (ret & imvp_bit) { |
652 | info->vrm_version[page] = imvp9; |
653 | data->vid_step[page] = MP2975_PROT_DEV_OV_OFF; |
654 | } else if (ret & vr_bit) { |
655 | info->vrm_version[page] = vr12; |
656 | data->vid_step[page] = MP2975_PROT_DEV_OV_ON; |
657 | } else { |
658 | info->vrm_version[page] = vr13; |
659 | data->vid_step[page] = MP2975_PROT_DEV_OV_OFF; |
660 | } |
661 | |
662 | return 0; |
663 | } |
664 | |
665 | static int |
666 | mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data, |
667 | struct pmbus_driver_info *info) |
668 | { |
669 | int ret; |
670 | |
671 | ret = i2c_smbus_write_byte_data(client, command: PMBUS_PAGE, value: 2); |
672 | if (ret < 0) |
673 | return ret; |
674 | |
675 | /* Identify VID mode for rail 1. */ |
676 | ret = mp2975_identify_vid(client, data, info, |
677 | MP2975_MFR_VR_MULTI_CONFIG_R1, page: 0, |
678 | MP2975_IMVP9_EN_R1, MP2975_VID_STEP_SEL_R1); |
679 | if (ret < 0) |
680 | return ret; |
681 | |
682 | /* Identify VID mode for rail 2, if connected. */ |
683 | if (info->phases[1]) |
684 | ret = mp2975_identify_vid(client, data, info, |
685 | MP2975_MFR_VR_MULTI_CONFIG_R2, page: 1, |
686 | MP2975_IMVP9_EN_R2, |
687 | MP2975_VID_STEP_SEL_R2); |
688 | |
689 | return ret; |
690 | } |
691 | |
692 | static int |
693 | mp2973_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data, |
694 | struct pmbus_driver_info *info) |
695 | { |
696 | int ret; |
697 | |
698 | ret = i2c_smbus_write_byte_data(client, command: PMBUS_PAGE, value: 2); |
699 | if (ret < 0) |
700 | return ret; |
701 | |
702 | /* Identify VID mode for rail 1. */ |
703 | ret = mp2975_identify_vid(client, data, info, |
704 | MP2973_MFR_VR_MULTI_CONFIG_R1, page: 0, |
705 | MP2973_IMVP9_EN_R1, MP2973_VID_STEP_SEL_R1); |
706 | |
707 | if (ret < 0) |
708 | return ret; |
709 | |
710 | /* Identify VID mode for rail 2, if connected. */ |
711 | if (info->phases[1]) |
712 | ret = mp2975_identify_vid(client, data, info, |
713 | MP2973_MFR_VR_MULTI_CONFIG_R2, page: 1, |
714 | MP2973_IMVP9_EN_R2, |
715 | MP2973_VID_STEP_SEL_R2); |
716 | |
717 | return ret; |
718 | } |
719 | |
720 | static int |
721 | mp2975_current_sense_gain_get(struct i2c_client *client, |
722 | struct mp2975_data *data) |
723 | { |
724 | int i, ret; |
725 | |
726 | /* |
727 | * Obtain DrMOS current sense gain of power stage from the register |
728 | * MP2975_MFR_VR_CONFIG1, bits 13-12. The value is selected as below: |
729 | * 00b - 5µA/A, 01b - 8.5µA/A, 10b - 9.7µA/A, 11b - 10µA/A. Other |
730 | * values are invalid. |
731 | */ |
732 | for (i = 0 ; i < data->info.pages; i++) { |
733 | ret = i2c_smbus_write_byte_data(client, command: PMBUS_PAGE, value: i); |
734 | if (ret < 0) |
735 | return ret; |
736 | ret = i2c_smbus_read_word_data(client, |
737 | MP2975_MFR_VR_CONFIG1); |
738 | if (ret < 0) |
739 | return ret; |
740 | |
741 | switch ((ret & MP2975_DRMOS_KCS) >> 12) { |
742 | case 0: |
743 | data->curr_sense_gain[i] = 50; |
744 | break; |
745 | case 1: |
746 | data->curr_sense_gain[i] = 85; |
747 | break; |
748 | case 2: |
749 | data->curr_sense_gain[i] = 97; |
750 | break; |
751 | default: |
752 | data->curr_sense_gain[i] = 100; |
753 | break; |
754 | } |
755 | } |
756 | |
757 | return 0; |
758 | } |
759 | |
760 | static int |
761 | mp2975_vref_get(struct i2c_client *client, struct mp2975_data *data, |
762 | struct pmbus_driver_info *info) |
763 | { |
764 | int ret; |
765 | |
766 | ret = i2c_smbus_write_byte_data(client, command: PMBUS_PAGE, value: 3); |
767 | if (ret < 0) |
768 | return ret; |
769 | |
770 | /* Get voltage reference value for rail 1. */ |
771 | ret = i2c_smbus_read_word_data(client, MP2975_MFR_READ_VREF_R1); |
772 | if (ret < 0) |
773 | return ret; |
774 | |
775 | data->vref[0] = ret * data->vid_step[0]; |
776 | |
777 | /* Get voltage reference value for rail 2, if connected. */ |
778 | if (data->info.pages == MP2975_PAGE_NUM) { |
779 | ret = i2c_smbus_read_word_data(client, MP2975_MFR_READ_VREF_R2); |
780 | if (ret < 0) |
781 | return ret; |
782 | |
783 | data->vref[1] = ret * data->vid_step[1]; |
784 | } |
785 | return 0; |
786 | } |
787 | |
788 | static int |
789 | mp2975_vref_offset_get(struct i2c_client *client, struct mp2975_data *data, |
790 | int page) |
791 | { |
792 | int ret; |
793 | |
794 | ret = i2c_smbus_read_word_data(client, MP2975_MFR_OVP_TH_SET); |
795 | if (ret < 0) |
796 | return ret; |
797 | |
798 | switch ((ret & GENMASK(5, 3)) >> 3) { |
799 | case 1: |
800 | data->vref_off[page] = 140; |
801 | break; |
802 | case 2: |
803 | data->vref_off[page] = 220; |
804 | break; |
805 | case 4: |
806 | data->vref_off[page] = 400; |
807 | break; |
808 | default: |
809 | return -EINVAL; |
810 | } |
811 | return 0; |
812 | } |
813 | |
814 | static int |
815 | mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, |
816 | struct pmbus_driver_info *info, int page) |
817 | { |
818 | int ret; |
819 | |
820 | /* Get maximum reference voltage of VID-DAC in VID format. */ |
821 | ret = i2c_smbus_read_word_data(client, command: PMBUS_VOUT_MAX); |
822 | if (ret < 0) |
823 | return ret; |
824 | |
825 | data->vout_max[page] = mp2975_vid2direct(vrf: info->vrm_version[page], val: ret & |
826 | GENMASK(8, 0)); |
827 | return 0; |
828 | } |
829 | |
830 | static int |
831 | mp2975_set_vout_format(struct i2c_client *client, |
832 | struct mp2975_data *data, int page) |
833 | { |
834 | int ret, i; |
835 | |
836 | /* Enable DIRECT VOUT format 1mV/LSB */ |
837 | if (data->chip_id == mp2975) { |
838 | ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL); |
839 | if (ret < 0) |
840 | return ret; |
841 | if (ret & MP2975_VOUT_FORMAT) { |
842 | ret &= ~MP2975_VOUT_FORMAT; |
843 | ret = i2c_smbus_write_word_data(client, MP2975_MFR_DC_LOOP_CTRL, value: ret); |
844 | } |
845 | } else { |
846 | ret = i2c_smbus_read_word_data(client, MP2973_MFR_RESO_SET); |
847 | if (ret < 0) |
848 | return ret; |
849 | i = ret; |
850 | |
851 | if (page == 0) { |
852 | i &= ~MP2973_VOUT_FORMAT_R1; |
853 | i |= MP2973_VOUT_FORMAT_DIRECT_R1; |
854 | } else { |
855 | i &= ~MP2973_VOUT_FORMAT_R2; |
856 | i |= MP2973_VOUT_FORMAT_DIRECT_R2; |
857 | } |
858 | if (i != ret) |
859 | ret = i2c_smbus_write_word_data(client, MP2973_MFR_RESO_SET, value: i); |
860 | } |
861 | return ret; |
862 | } |
863 | |
864 | static int |
865 | mp2975_vout_ov_scale_get(struct i2c_client *client, struct mp2975_data *data, |
866 | struct pmbus_driver_info *info) |
867 | { |
868 | int thres_dev, sense_ampl, ret; |
869 | |
870 | ret = i2c_smbus_write_byte_data(client, command: PMBUS_PAGE, value: 0); |
871 | if (ret < 0) |
872 | return ret; |
873 | |
874 | /* |
875 | * Get divider for over- and under-voltage protection thresholds |
876 | * configuration from the Advanced Options of Auto Phase Shedding and |
877 | * decay register. |
878 | */ |
879 | ret = i2c_smbus_read_word_data(client, MP2975_MFR_APS_DECAY_ADV); |
880 | if (ret < 0) |
881 | return ret; |
882 | thres_dev = ret & MP2975_PRT_THRES_DIV_OV_EN ? MP2975_PROT_DEV_OV_ON : |
883 | MP2975_PROT_DEV_OV_OFF; |
884 | |
885 | /* Select the gain of remote sense amplifier. */ |
886 | ret = i2c_smbus_read_word_data(client, command: PMBUS_VOUT_SCALE_LOOP); |
887 | if (ret < 0) |
888 | return ret; |
889 | sense_ampl = ret & MP2975_SENSE_AMPL ? MP2975_SENSE_AMPL_HALF : |
890 | MP2975_SENSE_AMPL_UNIT; |
891 | |
892 | data->vout_scale = sense_ampl * thres_dev; |
893 | |
894 | return 0; |
895 | } |
896 | |
897 | static int |
898 | mp2975_vout_per_rail_config_get(struct i2c_client *client, |
899 | struct mp2975_data *data, |
900 | struct pmbus_driver_info *info) |
901 | { |
902 | int i, ret; |
903 | |
904 | for (i = 0; i < data->info.pages; i++) { |
905 | ret = i2c_smbus_write_byte_data(client, command: PMBUS_PAGE, value: i); |
906 | if (ret < 0) |
907 | continue; |
908 | |
909 | /* Set VOUT format for READ_VOUT command : direct. */ |
910 | ret = mp2975_set_vout_format(client, data, page: i); |
911 | if (ret < 0) |
912 | return ret; |
913 | |
914 | /* Obtain maximum voltage values. */ |
915 | ret = mp2975_vout_max_get(client, data, info, page: i); |
916 | if (ret < 0) |
917 | return ret; |
918 | |
919 | /* Skip if reading Vref is unsupported */ |
920 | if (data->chip_id != mp2975) |
921 | continue; |
922 | |
923 | /* Obtain voltage reference offsets. */ |
924 | ret = mp2975_vref_offset_get(client, data, page: i); |
925 | if (ret < 0) |
926 | return ret; |
927 | |
928 | /* |
929 | * Set over-voltage fixed value. Thresholds are provided as |
930 | * fixed value, and tracking value. The minimum of them are |
931 | * exposed as over-voltage critical threshold. |
932 | */ |
933 | data->vout_ov_fixed[i] = data->vref[i] + |
934 | DIV_ROUND_CLOSEST(data->vref_off[i] * |
935 | data->vout_scale, |
936 | 10); |
937 | } |
938 | |
939 | return 0; |
940 | } |
941 | |
942 | static const struct pmbus_driver_info mp2975_info = { |
943 | .pages = 1, |
944 | .format[PSC_VOLTAGE_IN] = linear, |
945 | .format[PSC_VOLTAGE_OUT] = direct, |
946 | .format[PSC_TEMPERATURE] = direct, |
947 | .format[PSC_CURRENT_IN] = linear, |
948 | .format[PSC_CURRENT_OUT] = direct, |
949 | .format[PSC_POWER] = direct, |
950 | .m[PSC_TEMPERATURE] = 1, |
951 | .m[PSC_VOLTAGE_OUT] = 1, |
952 | .R[PSC_VOLTAGE_OUT] = 3, |
953 | .m[PSC_CURRENT_OUT] = 1, |
954 | .m[PSC_POWER] = 1, |
955 | .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | |
956 | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | |
957 | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT | |
958 | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | PMBUS_PHASE_VIRTUAL, |
959 | .read_byte_data = mp2975_read_byte_data, |
960 | .read_word_data = mp2975_read_word_data, |
961 | #if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR) |
962 | .num_regulators = 1, |
963 | .reg_desc = mp2975_reg_desc, |
964 | #endif |
965 | }; |
966 | |
967 | static const struct pmbus_driver_info mp2973_info = { |
968 | .pages = 1, |
969 | .format[PSC_VOLTAGE_IN] = linear, |
970 | .format[PSC_VOLTAGE_OUT] = direct, |
971 | .format[PSC_TEMPERATURE] = linear, |
972 | .format[PSC_CURRENT_IN] = linear, |
973 | .format[PSC_CURRENT_OUT] = linear, |
974 | .format[PSC_POWER] = linear, |
975 | .m[PSC_VOLTAGE_OUT] = 1, |
976 | .R[PSC_VOLTAGE_OUT] = 3, |
977 | .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | |
978 | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | |
979 | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT | |
980 | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT, |
981 | .read_word_data = mp2973_read_word_data, |
982 | .write_word_data = mp2973_write_word_data, |
983 | #if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR) |
984 | .num_regulators = 1, |
985 | .reg_desc = mp2975_reg_desc, |
986 | #endif |
987 | }; |
988 | |
989 | static const struct mp2975_driver_info mp2975_ddinfo[] = { |
990 | [mp2975] = { .info = &mp2975_info, .chip_id = mp2975 }, |
991 | [mp2973] = { .info = &mp2973_info, .chip_id = mp2973 }, |
992 | [mp2971] = { .info = &mp2973_info, .chip_id = mp2971 }, |
993 | }; |
994 | |
995 | static int mp2975_probe(struct i2c_client *client) |
996 | { |
997 | const struct mp2975_driver_info *ddinfo; |
998 | struct pmbus_driver_info *info; |
999 | struct mp2975_data *data; |
1000 | int ret; |
1001 | |
1002 | ddinfo = i2c_get_match_data(client); |
1003 | if (!ddinfo) |
1004 | return -ENODEV; |
1005 | |
1006 | data = devm_kzalloc(dev: &client->dev, size: sizeof(struct mp2975_data), |
1007 | GFP_KERNEL); |
1008 | if (!data) |
1009 | return -ENOMEM; |
1010 | |
1011 | data->chip_id = ddinfo->chip_id; |
1012 | |
1013 | memcpy(data->max_phases, mp2975_max_phases[data->chip_id], |
1014 | sizeof(data->max_phases)); |
1015 | |
1016 | memcpy(&data->info, ddinfo->info, sizeof(data->info)); |
1017 | |
1018 | info = &data->info; |
1019 | |
1020 | /* Identify multiphase configuration for rail 2. */ |
1021 | ret = mp2975_identify_multiphase_rail2(client, data); |
1022 | if (ret < 0) |
1023 | return ret; |
1024 | |
1025 | if (ret) { |
1026 | /* Two rails are connected. */ |
1027 | data->info.pages = MP2975_PAGE_NUM; |
1028 | data->info.phases[1] = ret; |
1029 | data->info.func[1] = MP2975_RAIL2_FUNC; |
1030 | if (IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR)) |
1031 | data->info.num_regulators = MP2975_PAGE_NUM; |
1032 | } |
1033 | |
1034 | /* Identify multiphase configuration. */ |
1035 | ret = mp2975_identify_multiphase(client, data, info); |
1036 | if (ret) |
1037 | return ret; |
1038 | |
1039 | if (data->chip_id == mp2975) { |
1040 | /* Identify VID setting per rail. */ |
1041 | ret = mp2975_identify_rails_vid(client, data, info); |
1042 | if (ret < 0) |
1043 | return ret; |
1044 | |
1045 | /* Obtain current sense gain of power stage. */ |
1046 | ret = mp2975_current_sense_gain_get(client, data); |
1047 | if (ret) |
1048 | return ret; |
1049 | |
1050 | /* Obtain voltage reference values. */ |
1051 | ret = mp2975_vref_get(client, data, info); |
1052 | if (ret) |
1053 | return ret; |
1054 | |
1055 | /* Obtain vout over-voltage scales. */ |
1056 | ret = mp2975_vout_ov_scale_get(client, data, info); |
1057 | if (ret < 0) |
1058 | return ret; |
1059 | } else { |
1060 | /* Identify VID setting per rail. */ |
1061 | ret = mp2973_identify_rails_vid(client, data, info); |
1062 | if (ret < 0) |
1063 | return ret; |
1064 | } |
1065 | |
1066 | /* Obtain offsets, maximum and format for vout. */ |
1067 | ret = mp2975_vout_per_rail_config_get(client, data, info); |
1068 | if (ret) |
1069 | return ret; |
1070 | |
1071 | return pmbus_do_probe(client, info); |
1072 | } |
1073 | |
1074 | static const struct of_device_id mp2975_of_match[] = { |
1075 | {.compatible = "mps,mp2971", .data = &mp2975_ddinfo[mp2971]}, |
1076 | {.compatible = "mps,mp2973", .data = &mp2975_ddinfo[mp2973]}, |
1077 | {.compatible = "mps,mp2975", .data = &mp2975_ddinfo[mp2975]}, |
1078 | {} |
1079 | }; |
1080 | MODULE_DEVICE_TABLE(of, mp2975_of_match); |
1081 | |
1082 | static const struct i2c_device_id mp2975_id[] = { |
1083 | {"mp2971", (kernel_ulong_t)&mp2975_ddinfo[mp2971]}, |
1084 | {"mp2973", (kernel_ulong_t)&mp2975_ddinfo[mp2973]}, |
1085 | {"mp2975", (kernel_ulong_t)&mp2975_ddinfo[mp2975]}, |
1086 | {} |
1087 | }; |
1088 | MODULE_DEVICE_TABLE(i2c, mp2975_id); |
1089 | |
1090 | static struct i2c_driver mp2975_driver = { |
1091 | .driver = { |
1092 | .name = "mp2975", |
1093 | .of_match_table = mp2975_of_match, |
1094 | }, |
1095 | .probe = mp2975_probe, |
1096 | .id_table = mp2975_id, |
1097 | }; |
1098 | |
1099 | module_i2c_driver(mp2975_driver); |
1100 | |
1101 | MODULE_AUTHOR("Vadim Pasternak <vadimp@nvidia.com>"); |
1102 | MODULE_DESCRIPTION("PMBus driver for MPS MP2975 device"); |
1103 | MODULE_LICENSE("GPL"); |
1104 | MODULE_IMPORT_NS("PMBUS"); |
1105 |
Definitions
- chips
- mp2975_max_phases
- mp2975_driver_info
- mp2975_data
- mp2975_reg_desc
- mp2975_read_byte_data
- mp2975_read_word_helper
- mp2975_vid2direct
- mp2975_data2reg_linear11
- mp2975_read_phase
- mp2975_read_phases
- mp2973_read_word_data
- mp2973_write_word_data
- mp2975_read_word_data
- mp2975_identify_multiphase_rail2
- mp2975_set_phase_rail1
- mp2975_set_phase_rail2
- mp2975_identify_multiphase
- mp2975_identify_vid
- mp2975_identify_rails_vid
- mp2973_identify_rails_vid
- mp2975_current_sense_gain_get
- mp2975_vref_get
- mp2975_vref_offset_get
- mp2975_vout_max_get
- mp2975_set_vout_format
- mp2975_vout_ov_scale_get
- mp2975_vout_per_rail_config_get
- mp2975_info
- mp2973_info
- mp2975_ddinfo
- mp2975_probe
- mp2975_of_match
- mp2975_id
Improve your Profiling and Debugging skills
Find out more