File Index
Files and directories
Sign in
FILE

mp2869.c

File preview with syntax highlighting.

linux-6.19.14/drivers/hwmon/pmbus/mp2869.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Hardware monitoring driver for MPS Multi-phase Digital VR Controllers(MP2869)
  4 */
  5
  6#include <linux/bitfield.h>
  7#include <linux/i2c.h>
  8#include <linux/module.h>
  9#include <linux/of_device.h>
 10#include "pmbus.h"
 11
 12/*
 13 * Vender specific registers, the register MFR_SVI3_IOUT_PRT(0x67),
 14 * READ_PIN_EST(0x94)and READ_IIN_EST(0x95) redefine the standard
 15 * PMBUS register. The MFR_VOUT_LOOP_CTRL(0x29) is used to identify
 16 * the vout scale and the MFR_SVI3_IOUT_PRT(0x67) is used to identify
 17 * the iout scale. The READ_PIN_EST(0x94) is used to read input power
 18 * per rail. The MP2891 does not have standard READ_IIN register(0x89),
 19 * the iin telemetry can be obtained through the vendor redefined
 20 * register READ_IIN_EST(0x95).
 21 */
 22#define MFR_SVI3_IOUT_PRT	0x67
 23#define MFR_READ_PIN_EST	0x94
 24#define MFR_READ_IIN_EST	0x95
 25#define MFR_TSNS_FLT_SET	0xBB
 26
 27#define MP2869_VIN_OV_FAULT_GAIN	4
 28#define MP2869_READ_VOUT_DIV	1024
 29#define MP2869_READ_IOUT_DIV	32
 30#define MP2869_OVUV_LIMIT_SCALE	10
 31#define MP2869_OVUV_DELTA_SCALE	50
 32#define MP2869_TEMP_LIMIT_OFFSET	40
 33#define MP2869_IOUT_LIMIT_UINT	8
 34#define MP2869_POUT_OP_GAIN	2
 35
 36#define MP2869_PAGE_NUM	2
 37
 38#define MP2869_RAIL1_FUNC	(PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | \
 39							PMBUS_HAVE_IOUT | PMBUS_HAVE_POUT | \
 40							PMBUS_HAVE_TEMP | PMBUS_HAVE_PIN | \
 41							PMBUS_HAVE_IIN | \
 42							PMBUS_HAVE_STATUS_VOUT | \
 43							PMBUS_HAVE_STATUS_IOUT | \
 44							PMBUS_HAVE_STATUS_TEMP | \
 45							PMBUS_HAVE_STATUS_INPUT)
 46
 47#define MP2869_RAIL2_FUNC	(PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | \
 48							 PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP | \
 49							 PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | \
 50							 PMBUS_HAVE_STATUS_VOUT | \
 51							 PMBUS_HAVE_STATUS_IOUT | \
 52							 PMBUS_HAVE_STATUS_TEMP | \
 53							 PMBUS_HAVE_STATUS_INPUT)
 54
 55struct mp2869_data {
 56	struct pmbus_driver_info info;
 57	bool mfr_thwn_flt_en;
 58	int vout_scale[MP2869_PAGE_NUM];
 59	int iout_scale[MP2869_PAGE_NUM];
 60};
 61
 62static const int mp2869_vout_sacle[8] = {6400, 5120, 2560, 2048, 1024,
 63										 4, 2, 1};
 64static const int mp2869_iout_sacle[8] = {32, 1, 2, 4, 8, 16, 32, 64};
 65
 66#define to_mp2869_data(x)	container_of(x, struct mp2869_data, info)
 67
 68static u16 mp2869_reg2data_linear11(u16 word)
 69{
 70	s16 exponent;
 71	s32 mantissa;
 72	s64 val;
 73
 74	exponent = ((s16)word) >> 11;
 75	mantissa = ((s16)((word & 0x7ff) << 5)) >> 5;
 76	val = mantissa;
 77
 78	if (exponent >= 0)
 79		val <<= exponent;
 80	else
 81		val >>= -exponent;
 82
 83	return val;
 84}
 85
 86static int
 87mp2869_identify_thwn_flt(struct i2c_client *client, struct pmbus_driver_info *info,
 88			 int page)
 89{
 90	struct mp2869_data *data = to_mp2869_data(info);
 91	int ret;
 92
 93	ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
 94	if (ret < 0)
 95		return ret;
 96
 97	ret = i2c_smbus_read_word_data(client, MFR_TSNS_FLT_SET);
 98	if (ret < 0)
 99		return ret;
100
101	data->mfr_thwn_flt_en = FIELD_GET(GENMASK(13, 13), ret);
102
103	return 0;
104}
105
106static int
107mp2869_identify_vout_scale(struct i2c_client *client, struct pmbus_driver_info *info,
108			   int page)
109{
110	struct mp2869_data *data = to_mp2869_data(info);
111	int ret;
112
113	ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
114	if (ret < 0)
115		return ret;
116
117	ret = i2c_smbus_read_word_data(client, PMBUS_VOUT_SCALE_LOOP);
118	if (ret < 0)
119		return ret;
120
121	/*
122	 * The output voltage is equal to the READ_VOUT(0x8B) register value multiply
123	 * by vout_scale.
124	 * Obtain vout scale from the register PMBUS_VOUT_SCALE_LOOP, bits 12-10
125	 * PMBUS_VOUT_SCALE_LOOP[12:10]:
126	 * 000b - 6.25mV/LSB, 001b - 5mV/LSB, 010b - 2.5mV/LSB, 011b - 2mV/LSB
127	 * 100b - 1mV/Lsb, 101b - (1/256)mV/LSB, 110b - (1/512)mV/LSB,
128	 * 111b - (1/1024)mV/LSB
129	 */
130	data->vout_scale[page] = mp2869_vout_sacle[FIELD_GET(GENMASK(12, 10), ret)];
131
132	return 0;
133}
134
135static int
136mp2869_identify_iout_scale(struct i2c_client *client, struct pmbus_driver_info *info,
137			   int page)
138{
139	struct mp2869_data *data = to_mp2869_data(info);
140	int ret;
141
142	ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
143	if (ret < 0)
144		return ret;
145
146	ret = i2c_smbus_read_word_data(client, MFR_SVI3_IOUT_PRT);
147	if (ret < 0)
148		return ret;
149
150	/*
151	 * The output current is equal to the READ_IOUT(0x8C) register value
152	 * multiply by iout_scale.
153	 * Obtain iout_scale from the register MFR_SVI3_IOUT_PRT[2:0].
154	 * The value is selected as below:
155	 * 000b - 1A/LSB, 001b - (1/32)A/LSB, 010b - (1/16)A/LSB,
156	 * 011b - (1/8)A/LSB, 100b - (1/4)A/LSB, 101b - (1/2)A/LSB
157	 * 110b - 1A/LSB, 111b - 2A/LSB
158	 */
159	data->iout_scale[page] = mp2869_iout_sacle[FIELD_GET(GENMASK(2, 0), ret)];
160
161	return 0;
162}
163
164static int mp2869_read_byte_data(struct i2c_client *client, int page, int reg)
165{
166	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
167	struct mp2869_data *data = to_mp2869_data(info);
168	int ret, mfr;
169
170	switch (reg) {
171	case PMBUS_VOUT_MODE:
172		/*
173		 * The calculation of vout in this driver is based on direct format.
174		 * As a result, the format of vout is enforced to direct.
175		 */
176		ret = PB_VOUT_MODE_DIRECT;
177		break;
178	case PMBUS_STATUS_BYTE:
179		/*
180		 * If the tsns digital fault is enabled, the TEMPERATURE flag
181		 * of PMBUS_STATUS_BYTE should come from STATUS_MFR_SPECIFIC
182		 * register bit1.
183		 */
184		if (!data->mfr_thwn_flt_en)
185			return -ENODATA;
186
187		ret = pmbus_read_byte_data(client, page, reg);
188		if (ret < 0)
189			return ret;
190
191		mfr = pmbus_read_byte_data(client, page,
192					   PMBUS_STATUS_MFR_SPECIFIC);
193		if (mfr < 0)
194			return mfr;
195
196		ret = (ret & ~GENMASK(2, 2)) |
197			FIELD_PREP(GENMASK(2, 2),
198				   FIELD_GET(GENMASK(1, 1), mfr));
199		break;
200	case PMBUS_STATUS_TEMPERATURE:
201		/*
202		 * If the tsns digital fault is enabled, the OT Fault and OT Warning
203		 * flag of PMBUS_STATUS_TEMPERATURE should come from STATUS_MFR_SPECIFIC
204		 * register bit1.
205		 */
206		if (!data->mfr_thwn_flt_en)
207			return -ENODATA;
208
209		ret = pmbus_read_byte_data(client, page, reg);
210		if (ret < 0)
211			return ret;
212
213		mfr = pmbus_read_byte_data(client, page,
214					   PMBUS_STATUS_MFR_SPECIFIC);
215		if (mfr < 0)
216			return mfr;
217
218		ret = (ret & ~GENMASK(7, 6)) |
219			FIELD_PREP(GENMASK(6, 6),
220				   FIELD_GET(GENMASK(1, 1), mfr)) |
221			 FIELD_PREP(GENMASK(7, 7),
222				    FIELD_GET(GENMASK(1, 1), mfr));
223		break;
224	default:
225		ret = -ENODATA;
226		break;
227	}
228
229	return ret;
230}
231
232static int mp2869_read_word_data(struct i2c_client *client, int page, int phase,
233				 int reg)
234{
235	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
236	struct mp2869_data *data = to_mp2869_data(info);
237	int ret, mfr;
238
239	switch (reg) {
240	case PMBUS_STATUS_WORD:
241		/*
242		 * If the tsns digital fault is enabled, the OT Fault flag
243		 * of PMBUS_STATUS_WORD should come from STATUS_MFR_SPECIFIC
244		 * register bit1.
245		 */
246		if (!data->mfr_thwn_flt_en)
247			return -ENODATA;
248
249		ret = pmbus_read_word_data(client, page, phase, reg);
250		if (ret < 0)
251			return ret;
252
253		mfr = pmbus_read_byte_data(client, page,
254					   PMBUS_STATUS_MFR_SPECIFIC);
255		if (mfr < 0)
256			return mfr;
257
258		ret = (ret & ~GENMASK(2, 2)) |
259			 FIELD_PREP(GENMASK(2, 2),
260				    FIELD_GET(GENMASK(1, 1), mfr));
261		break;
262	case PMBUS_READ_VIN:
263		/*
264		 * The MP2869 PMBUS_READ_VIN[10:0] is the vin value, the vin scale is
265		 * 31.25mV/LSB. And the vin scale is set to 31.25mV/Lsb(using r/m/b scale)
266		 * in MP2869 pmbus_driver_info struct, so the word data bit0-bit10 can be
267		 * returned to pmbus core directly.
268		 */
269		ret = pmbus_read_word_data(client, page, phase, reg);
270		if (ret < 0)
271			return ret;
272
273		ret = FIELD_GET(GENMASK(10, 0), ret);
274		break;
275	case PMBUS_READ_IIN:
276		/*
277		 * The MP2869 redefine the standard 0x95 register as iin telemetry
278		 * per rail.
279		 */
280		ret = pmbus_read_word_data(client, page, phase, MFR_READ_IIN_EST);
281		if (ret < 0)
282			return ret;
283
284		break;
285	case PMBUS_READ_PIN:
286		/*
287		 * The MP2869 redefine the standard 0x94 register as pin telemetry
288		 * per rail. The MP2869 MFR_READ_PIN_EST register is linear11 format,
289		 * but the pin scale is set to 1W/Lsb(using r/m/b scale). As a result,
290		 * the pin read from MP2869 should be converted to W, then return
291		 * the result to pmbus core.
292		 */
293		ret = pmbus_read_word_data(client, page, phase, MFR_READ_PIN_EST);
294		if (ret < 0)
295			return ret;
296
297		ret = mp2869_reg2data_linear11(ret);
298		break;
299	case PMBUS_READ_VOUT:
300		ret = pmbus_read_word_data(client, page, phase, reg);
301		if (ret < 0)
302			return ret;
303
304		ret = DIV_ROUND_CLOSEST((ret &  GENMASK(11, 0)) * data->vout_scale[page],
305					MP2869_READ_VOUT_DIV);
306		break;
307	case PMBUS_READ_IOUT:
308		ret = pmbus_read_word_data(client, page, phase, reg);
309		if (ret < 0)
310			return ret;
311
312		ret = DIV_ROUND_CLOSEST((ret & GENMASK(10, 0)) * data->iout_scale[page],
313					MP2869_READ_IOUT_DIV);
314		break;
315	case PMBUS_READ_POUT:
316		/*
317		 * The MP2869 PMBUS_READ_POUT register is linear11 format, but the pout
318		 * scale is set to 1W/Lsb(using r/m/b scale). As a result, the pout read
319		 * from MP2869 should be converted to W, then return the result to pmbus
320		 * core.
321		 */
322		ret = pmbus_read_word_data(client, page, phase, reg);
323		if (ret < 0)
324			return ret;
325
326		ret = mp2869_reg2data_linear11(ret);
327		break;
328	case PMBUS_READ_TEMPERATURE_1:
329		ret = pmbus_read_word_data(client, page, phase, reg);
330		if (ret < 0)
331			return ret;
332
333		ret = FIELD_GET(GENMASK(10, 0), ret);
334		break;
335	case PMBUS_VOUT_OV_FAULT_LIMIT:
336		ret = pmbus_read_word_data(client, page, phase, reg);
337		if (ret < 0)
338			return ret;
339
340		if (FIELD_GET(GENMASK(12, 9), ret))
341			ret = FIELD_GET(GENMASK(8, 0), ret) * MP2869_OVUV_LIMIT_SCALE +
342				(FIELD_GET(GENMASK(12, 9), ret) + 1) * MP2869_OVUV_DELTA_SCALE;
343		else
344			ret = FIELD_GET(GENMASK(8, 0), ret) * MP2869_OVUV_LIMIT_SCALE;
345		break;
346	case PMBUS_VOUT_UV_FAULT_LIMIT:
347		ret = pmbus_read_word_data(client, page, phase, reg);
348		if (ret < 0)
349			return ret;
350
351		if (FIELD_GET(GENMASK(12, 9), ret))
352			ret = FIELD_GET(GENMASK(8, 0), ret) * MP2869_OVUV_LIMIT_SCALE -
353				(FIELD_GET(GENMASK(12, 9), ret) + 1) * MP2869_OVUV_DELTA_SCALE;
354		else
355			ret = FIELD_GET(GENMASK(8, 0), ret) * MP2869_OVUV_LIMIT_SCALE;
356		break;
357	case PMBUS_OT_FAULT_LIMIT:
358	case PMBUS_OT_WARN_LIMIT:
359		/*
360		 * The scale of MP2869 PMBUS_OT_FAULT_LIMIT and PMBUS_OT_WARN_LIMIT
361		 * is 1°C/LSB and they have 40°C offset.
362		 */
363		ret = pmbus_read_word_data(client, page, phase, reg);
364		if (ret < 0)
365			return ret;
366
367		ret = (ret & GENMASK(7, 0)) - MP2869_TEMP_LIMIT_OFFSET;
368		break;
369	case PMBUS_VIN_OV_FAULT_LIMIT:
370		ret = pmbus_read_word_data(client, page, phase, reg);
371		if (ret < 0)
372			return ret;
373
374		ret = (ret & GENMASK(7, 0)) * MP2869_VIN_OV_FAULT_GAIN;
375		break;
376	case PMBUS_VIN_UV_WARN_LIMIT:
377	case PMBUS_VIN_UV_FAULT_LIMIT:
378		ret = pmbus_read_word_data(client, page, phase, reg);
379		if (ret < 0)
380			return ret;
381
382		ret = FIELD_GET(GENMASK(9, 0), ret);
383		break;
384	case PMBUS_IOUT_OC_FAULT_LIMIT:
385	case PMBUS_IOUT_OC_WARN_LIMIT:
386		ret = pmbus_read_word_data(client, page, phase, reg);
387		if (ret < 0)
388			return ret;
389
390		ret = DIV_ROUND_CLOSEST((ret & GENMASK(7, 0)) * data->iout_scale[page] *
391						MP2869_IOUT_LIMIT_UINT, MP2869_READ_IOUT_DIV);
392		break;
393	case PMBUS_POUT_OP_WARN_LIMIT:
394		ret = pmbus_read_word_data(client, page, phase, reg);
395		if (ret < 0)
396			return ret;
397
398		ret = (ret & GENMASK(7, 0)) * MP2869_POUT_OP_GAIN;
399		break;
400	default:
401		ret = -EINVAL;
402		break;
403	}
404
405	return ret;
406}
407
408static int mp2869_write_word_data(struct i2c_client *client, int page, int reg,
409				  u16 word)
410{
411	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
412	struct mp2869_data *data = to_mp2869_data(info);
413	int ret;
414
415	switch (reg) {
416	case PMBUS_VOUT_UV_FAULT_LIMIT:
417		/*
418		 * The MP2869 PMBUS_VOUT_UV_FAULT_LIMIT[8:0] is the limit value,
419		 * and bit9-bit15 should not be changed.
420		 */
421		ret = pmbus_read_word_data(client, page, 0xff, reg);
422		if (ret < 0)
423			return ret;
424
425		if (FIELD_GET(GENMASK(12, 9), ret))
426			ret = pmbus_write_word_data(client, page, reg,
427						    (ret & ~GENMASK(8, 0)) |
428				FIELD_PREP(GENMASK(8, 0),
429					   DIV_ROUND_CLOSEST(word +
430						(FIELD_GET(GENMASK(12, 9),
431						ret) + 1) *
432					MP2869_OVUV_DELTA_SCALE,
433					MP2869_OVUV_LIMIT_SCALE)));
434		else
435			ret = pmbus_write_word_data(client, page, reg,
436						    (ret & ~GENMASK(8, 0)) |
437					FIELD_PREP(GENMASK(8, 0),
438						   DIV_ROUND_CLOSEST(word,
439								     MP2869_OVUV_LIMIT_SCALE)));
440		break;
441	case PMBUS_VOUT_OV_FAULT_LIMIT:
442		/*
443		 * The MP2869 PMBUS_VOUT_OV_FAULT_LIMIT[8:0] is the limit value,
444		 * and bit9-bit15 should not be changed.
445		 */
446		ret = pmbus_read_word_data(client, page, 0xff, reg);
447		if (ret < 0)
448			return ret;
449
450		if (FIELD_GET(GENMASK(12, 9), ret))
451			ret = pmbus_write_word_data(client, page, reg,
452						    (ret & ~GENMASK(8, 0)) |
453				FIELD_PREP(GENMASK(8, 0),
454					   DIV_ROUND_CLOSEST(word -
455							(FIELD_GET(GENMASK(12, 9),
456							ret) + 1) *
457						MP2869_OVUV_DELTA_SCALE,
458						MP2869_OVUV_LIMIT_SCALE)));
459		else
460			ret = pmbus_write_word_data(client, page, reg,
461						    (ret & ~GENMASK(8, 0)) |
462				FIELD_PREP(GENMASK(8, 0),
463					   DIV_ROUND_CLOSEST(word,
464							     MP2869_OVUV_LIMIT_SCALE)));
465		break;
466	case PMBUS_OT_FAULT_LIMIT:
467	case PMBUS_OT_WARN_LIMIT:
468		/*
469		 * If the tsns digital fault is enabled, the PMBUS_OT_FAULT_LIMIT and
470		 * PMBUS_OT_WARN_LIMIT can not be written.
471		 */
472		if (data->mfr_thwn_flt_en)
473			return -EINVAL;
474
475		/*
476		 * The MP2869 scale of MP2869 PMBUS_OT_FAULT_LIMIT and PMBUS_OT_WARN_LIMIT
477		 * have 40°C offset. The bit0-bit7 is the limit value, and bit8-bit15
478		 * should not be changed.
479		 */
480		ret = pmbus_read_word_data(client, page, 0xff, reg);
481		if (ret < 0)
482			return ret;
483
484		ret = pmbus_write_word_data(client, page, reg,
485					    (ret & ~GENMASK(7, 0)) |
486					 FIELD_PREP(GENMASK(7, 0),
487						    word + MP2869_TEMP_LIMIT_OFFSET));
488		break;
489	case PMBUS_VIN_OV_FAULT_LIMIT:
490		/*
491		 * The MP2869 PMBUS_VIN_OV_FAULT_LIMIT[7:0] is the limit value, and bit8-bit15
492		 * should not be changed. The scale of PMBUS_VIN_OV_FAULT_LIMIT is 125mV/Lsb,
493		 * but the vin scale is set to 31.25mV/Lsb(using r/m/b scale), so the word data
494		 * should divide by MP2869_VIN_OV_FAULT_GAIN(4)
495		 */
496		ret = pmbus_read_word_data(client, page, 0xff, reg);
497		if (ret < 0)
498			return ret;
499
500		ret = pmbus_write_word_data(client, page, reg,
501					    (ret & ~GENMASK(7, 0)) |
502					FIELD_PREP(GENMASK(7, 0),
503						   DIV_ROUND_CLOSEST(word,
504								     MP2869_VIN_OV_FAULT_GAIN)));
505		break;
506	case PMBUS_VIN_UV_WARN_LIMIT:
507	case PMBUS_VIN_UV_FAULT_LIMIT:
508		/*
509		 * The PMBUS_VIN_UV_LIMIT[9:0] is the limit value, and bit10-bit15 should
510		 * not be changed. The scale of PMBUS_VIN_UV_LIMIT is 31.25mV/Lsb, and the
511		 * vin scale is set to 31.25mV/Lsb(using r/m/b scale), so the word data can
512		 * be written directly.
513		 */
514		ret = pmbus_read_word_data(client, page, 0xff, reg);
515		if (ret < 0)
516			return ret;
517
518		ret = pmbus_write_word_data(client, page, reg,
519					    (ret & ~GENMASK(9, 0)) |
520						FIELD_PREP(GENMASK(9, 0),
521							   word));
522		break;
523	case PMBUS_IOUT_OC_FAULT_LIMIT:
524	case PMBUS_IOUT_OC_WARN_LIMIT:
525		ret = pmbus_write_word_data(client, page, reg,
526					    DIV_ROUND_CLOSEST(word * MP2869_READ_IOUT_DIV,
527							      MP2869_IOUT_LIMIT_UINT *
528								  data->iout_scale[page]));
529		break;
530	case PMBUS_POUT_OP_WARN_LIMIT:
531		/*
532		 * The POUT_OP_WARN_LIMIT[11:0] is the limit value, and bit12-bit15 should
533		 * not be changed. The scale of POUT_OP_WARN_LIMIT is 2W/Lsb.
534		 */
535		ret = pmbus_read_word_data(client, page, 0xff, reg);
536		if (ret < 0)
537			return ret;
538
539		ret = pmbus_write_word_data(client, page, reg,
540					    (ret & ~GENMASK(11, 0)) |
541					FIELD_PREP(GENMASK(11, 0),
542						   DIV_ROUND_CLOSEST(word,
543								     MP2869_POUT_OP_GAIN)));
544		break;
545	default:
546		ret = -EINVAL;
547		break;
548	}
549
550	return ret;
551}
552
553static int mp2869_identify(struct i2c_client *client, struct pmbus_driver_info *info)
554{
555	int ret;
556
557	/* Identify whether tsns digital fault is enable */
558	ret = mp2869_identify_thwn_flt(client, info, 1);
559	if (ret < 0)
560		return 0;
561
562	/* Identify vout scale for rail1. */
563	ret = mp2869_identify_vout_scale(client, info, 0);
564	if (ret < 0)
565		return ret;
566
567	/* Identify vout scale for rail2. */
568	ret = mp2869_identify_vout_scale(client, info, 1);
569	if (ret < 0)
570		return ret;
571
572	/* Identify iout scale for rail 1. */
573	ret = mp2869_identify_iout_scale(client, info, 0);
574	if (ret < 0)
575		return ret;
576
577	/* Identify iout scale for rail 2. */
578	return mp2869_identify_iout_scale(client, info, 1);
579}
580
581static const struct pmbus_driver_info mp2869_info = {
582	.pages = MP2869_PAGE_NUM,
583	.format[PSC_VOLTAGE_IN] = direct,
584	.format[PSC_CURRENT_IN] = linear,
585	.format[PSC_CURRENT_OUT] = direct,
586	.format[PSC_TEMPERATURE] = direct,
587	.format[PSC_POWER] = direct,
588	.format[PSC_VOLTAGE_OUT] = direct,
589
590	.m[PSC_VOLTAGE_IN] = 32,
591	.R[PSC_VOLTAGE_IN] = 0,
592	.b[PSC_VOLTAGE_IN] = 0,
593
594	.m[PSC_VOLTAGE_OUT] = 1,
595	.R[PSC_VOLTAGE_OUT] = 3,
596	.b[PSC_VOLTAGE_OUT] = 0,
597
598	.m[PSC_CURRENT_OUT] = 1,
599	.R[PSC_CURRENT_OUT] = 0,
600	.b[PSC_CURRENT_OUT] = 0,
601
602	.m[PSC_TEMPERATURE] = 1,
603	.R[PSC_TEMPERATURE] = 0,
604	.b[PSC_TEMPERATURE] = 0,
605
606	.m[PSC_POWER] = 1,
607	.R[PSC_POWER] = 0,
608	.b[PSC_POWER] = 0,
609
610	.func[0] = MP2869_RAIL1_FUNC,
611	.func[1] = MP2869_RAIL2_FUNC,
612	.read_word_data = mp2869_read_word_data,
613	.write_word_data = mp2869_write_word_data,
614	.read_byte_data = mp2869_read_byte_data,
615	.identify = mp2869_identify,
616};
617
618static int mp2869_probe(struct i2c_client *client)
619{
620	struct pmbus_driver_info *info;
621	struct mp2869_data *data;
622
623	data = devm_kzalloc(&client->dev, sizeof(struct mp2869_data),
624			    GFP_KERNEL);
625	if (!data)
626		return -ENOMEM;
627
628	memcpy(&data->info, &mp2869_info, sizeof(*info));
629	info = &data->info;
630
631	return pmbus_do_probe(client, info);
632}
633
634static const struct i2c_device_id mp2869_id[] = {
635	{"mp2869", 0},
636	{"mp29608", 1},
637	{"mp29612", 2},
638	{"mp29816", 3},
639	{}
640};
641MODULE_DEVICE_TABLE(i2c, mp2869_id);
642
643static const struct of_device_id __maybe_unused mp2869_of_match[] = {
644	{.compatible = "mps,mp2869", .data = (void *)0},
645	{.compatible = "mps,mp29608", .data = (void *)1},
646	{.compatible = "mps,mp29612", .data = (void *)2},
647	{.compatible = "mps,mp29816", .data = (void *)3},
648	{}
649};
650MODULE_DEVICE_TABLE(of, mp2869_of_match);
651
652static struct i2c_driver mp2869_driver = {
653	.driver = {
654		.name = "mp2869",
655		.of_match_table = mp2869_of_match,
656	},
657	.probe = mp2869_probe,
658	.id_table = mp2869_id,
659};
660
661module_i2c_driver(mp2869_driver);
662
663MODULE_AUTHOR("Wensheng Wang <wenswang@yeah.net>");
664MODULE_DESCRIPTION("PMBus driver for MPS MP2869");
665MODULE_LICENSE("GPL");
666MODULE_IMPORT_NS("PMBUS");
~/ Read-only file preview.