ibm-cffps.c 15.4 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
3
4
5
/*
 * Copyright 2017 IBM Corp.
 */

6
#include <linux/bitfield.h>
7
#include <linux/bitops.h>
8
#include <linux/debugfs.h>
9
#include <linux/device.h>
10
#include <linux/fs.h>
11
#include <linux/i2c.h>
12
#include <linux/jiffies.h>
13
#include <linux/leds.h>
14
#include <linux/module.h>
15
#include <linux/mutex.h>
16
#include <linux/of_device.h>
17
#include <linux/pmbus.h>
18
19
20

#include "pmbus.h"

21
22
#define CFFPS_FRU_CMD				0x9A
#define CFFPS_PN_CMD				0x9B
23
#define CFFPS_HEADER_CMD			0x9C
24
#define CFFPS_SN_CMD				0x9E
25
#define CFFPS_MAX_POWER_OUT_CMD			0xA7
26
#define CFFPS_CCIN_CMD				0xBD
27
28
29
#define CFFPS_FW_CMD				0xFA
#define CFFPS1_FW_NUM_BYTES			4
#define CFFPS2_FW_NUM_WORDS			3
30
#define CFFPS_SYS_CONFIG_CMD			0xDA
31
#define CFFPS_12VCS_VOUT_CMD			0xDE
32
33
34
35

#define CFFPS_INPUT_HISTORY_CMD			0xD6
#define CFFPS_INPUT_HISTORY_SIZE		100

36
37
#define CFFPS_CCIN_REVISION			GENMASK(7, 0)
#define  CFFPS_CCIN_REVISION_LEGACY		 0xde
38
39
40
#define CFFPS_CCIN_VERSION			GENMASK(15, 8)
#define CFFPS_CCIN_VERSION_1			 0x2b
#define CFFPS_CCIN_VERSION_2			 0x2e
41
#define CFFPS_CCIN_VERSION_3			 0x51
42

43
44
45
46
47
48
49
50
51
52
/* STATUS_MFR_SPECIFIC bits */
#define CFFPS_MFR_FAN_FAULT			BIT(0)
#define CFFPS_MFR_THERMAL_FAULT			BIT(1)
#define CFFPS_MFR_OV_FAULT			BIT(2)
#define CFFPS_MFR_UV_FAULT			BIT(3)
#define CFFPS_MFR_PS_KILL			BIT(4)
#define CFFPS_MFR_OC_FAULT			BIT(5)
#define CFFPS_MFR_VAUX_FAULT			BIT(6)
#define CFFPS_MFR_CURRENT_SHARE_WARNING		BIT(7)

53
54
55
#define CFFPS_LED_BLINK				(BIT(0) | BIT(6))
#define CFFPS_LED_ON				(BIT(1) | BIT(6))
#define CFFPS_LED_OFF				(BIT(2) | BIT(6))
56
57
#define CFFPS_BLINK_RATE_MS			250

58
59
60
61
enum {
	CFFPS_DEBUGFS_INPUT_HISTORY = 0,
	CFFPS_DEBUGFS_FRU,
	CFFPS_DEBUGFS_PN,
62
	CFFPS_DEBUGFS_HEADER,
63
	CFFPS_DEBUGFS_SN,
64
	CFFPS_DEBUGFS_MAX_POWER_OUT,
65
66
	CFFPS_DEBUGFS_CCIN,
	CFFPS_DEBUGFS_FW,
67
	CFFPS_DEBUGFS_ON_OFF_CONFIG,
68
69
70
	CFFPS_DEBUGFS_NUM_ENTRIES
};

71
enum versions { cffps1, cffps2, cffps_unknown };
72

73
74
75
76
77
78
79
80
81
struct ibm_cffps_input_history {
	struct mutex update_lock;
	unsigned long last_update;

	u8 byte_count;
	u8 data[CFFPS_INPUT_HISTORY_SIZE];
};

struct ibm_cffps {
82
	enum versions version;
83
84
85
86
87
	struct i2c_client *client;

	struct ibm_cffps_input_history input_history;

	int debugfs_entries[CFFPS_DEBUGFS_NUM_ENTRIES];
88
89
90
91

	char led_name[32];
	u8 led_state;
	struct led_classdev led;
92
93
};

94
95
static const struct i2c_device_id ibm_cffps_id[];

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#define to_psu(x, y) container_of((x), struct ibm_cffps, debugfs_entries[(y)])

static ssize_t ibm_cffps_read_input_history(struct ibm_cffps *psu,
					    char __user *buf, size_t count,
					    loff_t *ppos)
{
	int rc;
	u8 msgbuf0[1] = { CFFPS_INPUT_HISTORY_CMD };
	u8 msgbuf1[CFFPS_INPUT_HISTORY_SIZE + 1] = { 0 };
	struct i2c_msg msg[2] = {
		{
			.addr = psu->client->addr,
			.flags = psu->client->flags,
			.len = 1,
			.buf = msgbuf0,
		}, {
			.addr = psu->client->addr,
			.flags = psu->client->flags | I2C_M_RD,
			.len = CFFPS_INPUT_HISTORY_SIZE + 1,
			.buf = msgbuf1,
		},
	};

	if (!*ppos) {
		mutex_lock(&psu->input_history.update_lock);
		if (time_after(jiffies, psu->input_history.last_update + HZ)) {
			/*
			 * Use a raw i2c transfer, since we need more bytes
			 * than Linux I2C supports through smbus xfr (only 32).
			 */
			rc = i2c_transfer(psu->client->adapter, msg, 2);
			if (rc < 0) {
				mutex_unlock(&psu->input_history.update_lock);
				return rc;
			}

			psu->input_history.byte_count = msgbuf1[0];
			memcpy(psu->input_history.data, &msgbuf1[1],
			       CFFPS_INPUT_HISTORY_SIZE);
			psu->input_history.last_update = jiffies;
		}

		mutex_unlock(&psu->input_history.update_lock);
	}

	return simple_read_from_buffer(buf, count, ppos,
				       psu->input_history.data,
				       psu->input_history.byte_count);
}

146
147
static ssize_t ibm_cffps_debugfs_read(struct file *file, char __user *buf,
				      size_t count, loff_t *ppos)
148
149
150
151
152
153
{
	u8 cmd;
	int i, rc;
	int *idxp = file->private_data;
	int idx = *idxp;
	struct ibm_cffps *psu = to_psu(idxp, idx);
154
	char data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
155

156
	pmbus_set_page(psu->client, 0, 0xff);
157

158
159
160
161
162
163
164
165
166
	switch (idx) {
	case CFFPS_DEBUGFS_INPUT_HISTORY:
		return ibm_cffps_read_input_history(psu, buf, count, ppos);
	case CFFPS_DEBUGFS_FRU:
		cmd = CFFPS_FRU_CMD;
		break;
	case CFFPS_DEBUGFS_PN:
		cmd = CFFPS_PN_CMD;
		break;
167
168
169
	case CFFPS_DEBUGFS_HEADER:
		cmd = CFFPS_HEADER_CMD;
		break;
170
171
172
	case CFFPS_DEBUGFS_SN:
		cmd = CFFPS_SN_CMD;
		break;
173
	case CFFPS_DEBUGFS_MAX_POWER_OUT:
174
175
176
177
178
179
180
181
		if (psu->version == cffps1) {
			rc = i2c_smbus_read_word_swapped(psu->client,
					CFFPS_MAX_POWER_OUT_CMD);
		} else {
			rc = i2c_smbus_read_word_data(psu->client,
					CFFPS_MAX_POWER_OUT_CMD);
		}

182
183
184
185
186
		if (rc < 0)
			return rc;

		rc = snprintf(data, I2C_SMBUS_BLOCK_MAX, "%d", rc);
		goto done;
187
188
189
190
191
192
193
194
	case CFFPS_DEBUGFS_CCIN:
		rc = i2c_smbus_read_word_swapped(psu->client, CFFPS_CCIN_CMD);
		if (rc < 0)
			return rc;

		rc = snprintf(data, 5, "%04X", rc);
		goto done;
	case CFFPS_DEBUGFS_FW:
195
196
197
198
199
200
201
202
203
204
205
		switch (psu->version) {
		case cffps1:
			for (i = 0; i < CFFPS1_FW_NUM_BYTES; ++i) {
				rc = i2c_smbus_read_byte_data(psu->client,
							      CFFPS_FW_CMD +
								i);
				if (rc < 0)
					return rc;

				snprintf(&data[i * 2], 3, "%02X", rc);
			}
206

207
208
209
210
211
212
213
214
215
216
217
218
			rc = i * 2;
			break;
		case cffps2:
			for (i = 0; i < CFFPS2_FW_NUM_WORDS; ++i) {
				rc = i2c_smbus_read_word_data(psu->client,
							      CFFPS_FW_CMD +
								i);
				if (rc < 0)
					return rc;

				snprintf(&data[i * 4], 5, "%04X", rc);
			}
219

220
221
222
223
224
			rc = i * 4;
			break;
		default:
			return -EOPNOTSUPP;
		}
225
		goto done;
226
227
228
229
230
231
232
233
	case CFFPS_DEBUGFS_ON_OFF_CONFIG:
		rc = i2c_smbus_read_byte_data(psu->client,
					      PMBUS_ON_OFF_CONFIG);
		if (rc < 0)
			return rc;

		rc = snprintf(data, 3, "%02x", rc);
		goto done;
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
	default:
		return -EINVAL;
	}

	rc = i2c_smbus_read_block_data(psu->client, cmd, data);
	if (rc < 0)
		return rc;

done:
	data[rc] = '\n';
	rc += 2;

	return simple_read_from_buffer(buf, count, ppos, data, rc);
}

249
250
251
252
253
254
255
256
257
258
259
260
static ssize_t ibm_cffps_debugfs_write(struct file *file,
				       const char __user *buf, size_t count,
				       loff_t *ppos)
{
	u8 data;
	ssize_t rc;
	int *idxp = file->private_data;
	int idx = *idxp;
	struct ibm_cffps *psu = to_psu(idxp, idx);

	switch (idx) {
	case CFFPS_DEBUGFS_ON_OFF_CONFIG:
261
		pmbus_set_page(psu->client, 0, 0xff);
262
263

		rc = simple_write_to_buffer(&data, 1, ppos, buf, count);
264
		if (rc <= 0)
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
			return rc;

		rc = i2c_smbus_write_byte_data(psu->client,
					       PMBUS_ON_OFF_CONFIG, data);
		if (rc)
			return rc;

		rc = 1;
		break;
	default:
		return -EINVAL;
	}

	return rc;
}

281
282
static const struct file_operations ibm_cffps_fops = {
	.llseek = noop_llseek,
283
284
	.read = ibm_cffps_debugfs_read,
	.write = ibm_cffps_debugfs_write,
285
286
287
	.open = simple_open,
};

288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
static int ibm_cffps_read_byte_data(struct i2c_client *client, int page,
				    int reg)
{
	int rc, mfr;

	switch (reg) {
	case PMBUS_STATUS_VOUT:
	case PMBUS_STATUS_IOUT:
	case PMBUS_STATUS_TEMPERATURE:
	case PMBUS_STATUS_FAN_12:
		rc = pmbus_read_byte_data(client, page, reg);
		if (rc < 0)
			return rc;

		mfr = pmbus_read_byte_data(client, page,
					   PMBUS_STATUS_MFR_SPECIFIC);
		if (mfr < 0)
			/*
			 * Return the status register instead of an error,
			 * since we successfully read status.
			 */
			return rc;

		/* Add MFR_SPECIFIC bits to the standard pmbus status regs. */
		if (reg == PMBUS_STATUS_FAN_12) {
			if (mfr & CFFPS_MFR_FAN_FAULT)
				rc |= PB_FAN_FAN1_FAULT;
		} else if (reg == PMBUS_STATUS_TEMPERATURE) {
			if (mfr & CFFPS_MFR_THERMAL_FAULT)
				rc |= PB_TEMP_OT_FAULT;
		} else if (reg == PMBUS_STATUS_VOUT) {
			if (mfr & (CFFPS_MFR_OV_FAULT | CFFPS_MFR_VAUX_FAULT))
				rc |= PB_VOLTAGE_OV_FAULT;
			if (mfr & CFFPS_MFR_UV_FAULT)
				rc |= PB_VOLTAGE_UV_FAULT;
		} else if (reg == PMBUS_STATUS_IOUT) {
			if (mfr & CFFPS_MFR_OC_FAULT)
				rc |= PB_IOUT_OC_FAULT;
			if (mfr & CFFPS_MFR_CURRENT_SHARE_WARNING)
				rc |= PB_CURRENT_SHARE_FAULT;
		}
		break;
	default:
		rc = -ENODATA;
		break;
	}

	return rc;
}

static int ibm_cffps_read_word_data(struct i2c_client *client, int page,
339
				    int phase, int reg)
340
341
342
343
344
{
	int rc, mfr;

	switch (reg) {
	case PMBUS_STATUS_WORD:
345
		rc = pmbus_read_word_data(client, page, phase, reg);
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
		if (rc < 0)
			return rc;

		mfr = pmbus_read_byte_data(client, page,
					   PMBUS_STATUS_MFR_SPECIFIC);
		if (mfr < 0)
			/*
			 * Return the status register instead of an error,
			 * since we successfully read status.
			 */
			return rc;

		if (mfr & CFFPS_MFR_PS_KILL)
			rc |= PB_STATUS_OFF;
		break;
361
	case PMBUS_VIRT_READ_VMON:
362
363
		rc = pmbus_read_word_data(client, page, phase,
					  CFFPS_12VCS_VOUT_CMD);
364
		break;
365
366
367
368
369
370
371
372
	default:
		rc = -ENODATA;
		break;
	}

	return rc;
}

373
374
static int ibm_cffps_led_brightness_set(struct led_classdev *led_cdev,
					enum led_brightness brightness)
375
376
{
	int rc;
377
	u8 next_led_state;
378
379
380
	struct ibm_cffps *psu = container_of(led_cdev, struct ibm_cffps, led);

	if (brightness == LED_OFF) {
381
		next_led_state = CFFPS_LED_OFF;
382
383
	} else {
		brightness = LED_FULL;
384

385
		if (psu->led_state != CFFPS_LED_BLINK)
386
387
388
			next_led_state = CFFPS_LED_ON;
		else
			next_led_state = CFFPS_LED_BLINK;
389
390
	}

391
392
393
	dev_dbg(&psu->client->dev, "LED brightness set: %d. Command: %d.\n",
		brightness, next_led_state);

394
	pmbus_set_page(psu->client, 0, 0xff);
395

396
	rc = i2c_smbus_write_byte_data(psu->client, CFFPS_SYS_CONFIG_CMD,
397
				       next_led_state);
398
	if (rc < 0)
399
		return rc;
400

401
	psu->led_state = next_led_state;
402
	led_cdev->brightness = brightness;
403
404

	return 0;
405
406
407
408
409
410
411
412
413
}

static int ibm_cffps_led_blink_set(struct led_classdev *led_cdev,
				   unsigned long *delay_on,
				   unsigned long *delay_off)
{
	int rc;
	struct ibm_cffps *psu = container_of(led_cdev, struct ibm_cffps, led);

414
	dev_dbg(&psu->client->dev, "LED blink set.\n");
415

416
	pmbus_set_page(psu->client, 0, 0xff);
417

418
419
420
421
422
	rc = i2c_smbus_write_byte_data(psu->client, CFFPS_SYS_CONFIG_CMD,
				       CFFPS_LED_BLINK);
	if (rc < 0)
		return rc;

423
424
	psu->led_state = CFFPS_LED_BLINK;
	led_cdev->brightness = LED_FULL;
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
	*delay_on = CFFPS_BLINK_RATE_MS;
	*delay_off = CFFPS_BLINK_RATE_MS;

	return 0;
}

static void ibm_cffps_create_led_class(struct ibm_cffps *psu)
{
	int rc;
	struct i2c_client *client = psu->client;
	struct device *dev = &client->dev;

	snprintf(psu->led_name, sizeof(psu->led_name), "%s-%02x", client->name,
		 client->addr);
	psu->led.name = psu->led_name;
	psu->led.max_brightness = LED_FULL;
441
	psu->led.brightness_set_blocking = ibm_cffps_led_brightness_set;
442
443
444
445
446
	psu->led.blink_set = ibm_cffps_led_blink_set;

	rc = devm_led_classdev_register(dev, &psu->led);
	if (rc)
		dev_warn(dev, "failed to register led class: %d\n", rc);
447
448
449
	else
		i2c_smbus_write_byte_data(client, CFFPS_SYS_CONFIG_CMD,
					  CFFPS_LED_OFF);
450
451
}

452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
static struct pmbus_driver_info ibm_cffps_info[] = {
	[cffps1] = {
		.pages = 1,
		.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
			PMBUS_HAVE_PIN | PMBUS_HAVE_FAN12 | PMBUS_HAVE_TEMP |
			PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
			PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
			PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP |
			PMBUS_HAVE_STATUS_FAN12,
		.read_byte_data = ibm_cffps_read_byte_data,
		.read_word_data = ibm_cffps_read_word_data,
	},
	[cffps2] = {
		.pages = 2,
		.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
			PMBUS_HAVE_PIN | PMBUS_HAVE_FAN12 | PMBUS_HAVE_TEMP |
			PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
			PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
			PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP |
471
			PMBUS_HAVE_STATUS_FAN12 | PMBUS_HAVE_VMON,
472
473
474
475
476
477
		.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
			PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
			PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT,
		.read_byte_data = ibm_cffps_read_byte_data,
		.read_word_data = ibm_cffps_read_word_data,
	},
478
479
};

480
static struct pmbus_platform_data ibm_cffps_pdata = {
481
	.flags = PMBUS_SKIP_STATUS_CHECK | PMBUS_NO_CAPABILITY,
482
483
};

484
static int ibm_cffps_probe(struct i2c_client *client)
485
{
486
	int i, rc;
487
	enum versions vs = cffps_unknown;
488
489
490
	struct dentry *debugfs;
	struct dentry *ibm_cffps_dir;
	struct ibm_cffps *psu;
491
	const void *md = of_device_get_match_data(&client->dev);
492
	const struct i2c_device_id *id;
493

494
	if (md) {
495
		vs = (enum versions)md;
496
497
498
499
500
	} else {
		id = i2c_match_id(ibm_cffps_id, client);
		if (id)
			vs = (enum versions)id->driver_data;
	}
501
502

	if (vs == cffps_unknown) {
503
		u16 ccin_revision = 0;
504
505
506
		u16 ccin_version = CFFPS_CCIN_VERSION_1;
		int ccin = i2c_smbus_read_word_swapped(client, CFFPS_CCIN_CMD);

507
508
		if (ccin > 0) {
			ccin_revision = FIELD_GET(CFFPS_CCIN_REVISION, ccin);
509
			ccin_version = FIELD_GET(CFFPS_CCIN_VERSION, ccin);
510
		}
511
512
513
514
515
516
517
518
519

		switch (ccin_version) {
		default:
		case CFFPS_CCIN_VERSION_1:
			vs = cffps1;
			break;
		case CFFPS_CCIN_VERSION_2:
			vs = cffps2;
			break;
520
521
522
523
524
525
		case CFFPS_CCIN_VERSION_3:
			if (ccin_revision == CFFPS_CCIN_REVISION_LEGACY)
				vs = cffps1;
			else
				vs = cffps2;
			break;
526
527
528
529
530
		}

		/* Set the client name to include the version number. */
		snprintf(client->name, I2C_NAME_SIZE, "cffps%d", vs + 1);
	}
531

532
	client->dev.platform_data = &ibm_cffps_pdata;
533
	rc = pmbus_do_probe(client, &ibm_cffps_info[vs]);
534
535
536
	if (rc)
		return rc;

537
538
539
540
541
542
543
544
	/*
	 * Don't fail the probe if there isn't enough memory for leds and
	 * debugfs.
	 */
	psu = devm_kzalloc(&client->dev, sizeof(*psu), GFP_KERNEL);
	if (!psu)
		return 0;

545
	psu->version = vs;
546
547
548
549
550
551
	psu->client = client;
	mutex_init(&psu->input_history.update_lock);
	psu->input_history.last_update = jiffies - HZ;

	ibm_cffps_create_led_class(psu);

552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
	/* Don't fail the probe if we can't create debugfs */
	debugfs = pmbus_get_debugfs_dir(client);
	if (!debugfs)
		return 0;

	ibm_cffps_dir = debugfs_create_dir(client->name, debugfs);
	if (!ibm_cffps_dir)
		return 0;

	for (i = 0; i < CFFPS_DEBUGFS_NUM_ENTRIES; ++i)
		psu->debugfs_entries[i] = i;

	debugfs_create_file("input_history", 0444, ibm_cffps_dir,
			    &psu->debugfs_entries[CFFPS_DEBUGFS_INPUT_HISTORY],
			    &ibm_cffps_fops);
	debugfs_create_file("fru", 0444, ibm_cffps_dir,
			    &psu->debugfs_entries[CFFPS_DEBUGFS_FRU],
			    &ibm_cffps_fops);
	debugfs_create_file("part_number", 0444, ibm_cffps_dir,
			    &psu->debugfs_entries[CFFPS_DEBUGFS_PN],
			    &ibm_cffps_fops);
573
574
575
	debugfs_create_file("header", 0444, ibm_cffps_dir,
			    &psu->debugfs_entries[CFFPS_DEBUGFS_HEADER],
			    &ibm_cffps_fops);
576
577
578
	debugfs_create_file("serial_number", 0444, ibm_cffps_dir,
			    &psu->debugfs_entries[CFFPS_DEBUGFS_SN],
			    &ibm_cffps_fops);
579
580
581
	debugfs_create_file("max_power_out", 0444, ibm_cffps_dir,
			    &psu->debugfs_entries[CFFPS_DEBUGFS_MAX_POWER_OUT],
			    &ibm_cffps_fops);
582
583
584
585
586
587
	debugfs_create_file("ccin", 0444, ibm_cffps_dir,
			    &psu->debugfs_entries[CFFPS_DEBUGFS_CCIN],
			    &ibm_cffps_fops);
	debugfs_create_file("fw_version", 0444, ibm_cffps_dir,
			    &psu->debugfs_entries[CFFPS_DEBUGFS_FW],
			    &ibm_cffps_fops);
588
589
590
	debugfs_create_file("on_off_config", 0644, ibm_cffps_dir,
			    &psu->debugfs_entries[CFFPS_DEBUGFS_ON_OFF_CONFIG],
			    &ibm_cffps_fops);
591
592

	return 0;
593
594
595
}

static const struct i2c_device_id ibm_cffps_id[] = {
596
597
	{ "ibm_cffps1", cffps1 },
	{ "ibm_cffps2", cffps2 },
598
	{ "ibm_cffps", cffps_unknown },
599
600
601
602
603
	{}
};
MODULE_DEVICE_TABLE(i2c, ibm_cffps_id);

static const struct of_device_id ibm_cffps_of_match[] = {
604
605
606
607
608
609
610
611
	{
		.compatible = "ibm,cffps1",
		.data = (void *)cffps1
	},
	{
		.compatible = "ibm,cffps2",
		.data = (void *)cffps2
	},
612
613
614
615
	{
		.compatible = "ibm,cffps",
		.data = (void *)cffps_unknown
	},
616
617
618
619
620
621
622
623
624
	{}
};
MODULE_DEVICE_TABLE(of, ibm_cffps_of_match);

static struct i2c_driver ibm_cffps_driver = {
	.driver = {
		.name = "ibm-cffps",
		.of_match_table = ibm_cffps_of_match,
	},
625
	.probe_new = ibm_cffps_probe,
626
627
628
629
630
631
632
633
	.id_table = ibm_cffps_id,
};

module_i2c_driver(ibm_cffps_driver);

MODULE_AUTHOR("Eddie James");
MODULE_DESCRIPTION("PMBus driver for IBM Common Form Factor power supplies");
MODULE_LICENSE("GPL");
634
MODULE_IMPORT_NS(PMBUS);