1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright 2017 IBM Corp.
6 #include <linux/bitfield.h>
7 #include <linux/bitops.h>
8 #include <linux/debugfs.h>
9 #include <linux/device.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>
21 #define CFFPS_FRU_CMD 0x9A
22 #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 #define CFFPS_FW_CMD 0xFA
28 #define CFFPS1_FW_NUM_BYTES 4
29 #define CFFPS2_FW_NUM_WORDS 3
30 #define CFFPS_SYS_CONFIG_CMD 0xDA
31 #define CFFPS_12VCS_VOUT_CMD 0xDE
33 #define CFFPS_INPUT_HISTORY_CMD 0xD6
34 #define CFFPS_INPUT_HISTORY_SIZE 100
36 #define CFFPS_CCIN_REVISION GENMASK(7, 0)
37 #define CFFPS_CCIN_REVISION_LEGACY 0xde
38 #define CFFPS_CCIN_VERSION GENMASK(15, 8)
39 #define CFFPS_CCIN_VERSION_1 0x2b
40 #define CFFPS_CCIN_VERSION_2 0x2e
41 #define CFFPS_CCIN_VERSION_3 0x51
43 /* STATUS_MFR_SPECIFIC bits */
44 #define CFFPS_MFR_FAN_FAULT BIT(0)
45 #define CFFPS_MFR_THERMAL_FAULT BIT(1)
46 #define CFFPS_MFR_OV_FAULT BIT(2)
47 #define CFFPS_MFR_UV_FAULT BIT(3)
48 #define CFFPS_MFR_PS_KILL BIT(4)
49 #define CFFPS_MFR_OC_FAULT BIT(5)
50 #define CFFPS_MFR_VAUX_FAULT BIT(6)
51 #define CFFPS_MFR_CURRENT_SHARE_WARNING BIT(7)
53 #define CFFPS_LED_BLINK BIT(0)
54 #define CFFPS_LED_ON BIT(1)
55 #define CFFPS_LED_OFF BIT(2)
56 #define CFFPS_BLINK_RATE_MS 250
59 CFFPS_DEBUGFS_INPUT_HISTORY
= 0,
64 CFFPS_DEBUGFS_MAX_POWER_OUT
,
67 CFFPS_DEBUGFS_ON_OFF_CONFIG
,
68 CFFPS_DEBUGFS_NUM_ENTRIES
71 enum versions
{ cffps1
, cffps2
, cffps_unknown
};
73 struct ibm_cffps_input_history
{
74 struct mutex update_lock
;
75 unsigned long last_update
;
78 u8 data
[CFFPS_INPUT_HISTORY_SIZE
];
82 enum versions version
;
83 struct i2c_client
*client
;
85 struct ibm_cffps_input_history input_history
;
87 int debugfs_entries
[CFFPS_DEBUGFS_NUM_ENTRIES
];
91 struct led_classdev led
;
94 static const struct i2c_device_id ibm_cffps_id
[];
96 #define to_psu(x, y) container_of((x), struct ibm_cffps, debugfs_entries[(y)])
98 static ssize_t
ibm_cffps_read_input_history(struct ibm_cffps
*psu
,
99 char __user
*buf
, size_t count
,
103 u8 msgbuf0
[1] = { CFFPS_INPUT_HISTORY_CMD
};
104 u8 msgbuf1
[CFFPS_INPUT_HISTORY_SIZE
+ 1] = { 0 };
105 struct i2c_msg msg
[2] = {
107 .addr
= psu
->client
->addr
,
108 .flags
= psu
->client
->flags
,
112 .addr
= psu
->client
->addr
,
113 .flags
= psu
->client
->flags
| I2C_M_RD
,
114 .len
= CFFPS_INPUT_HISTORY_SIZE
+ 1,
120 mutex_lock(&psu
->input_history
.update_lock
);
121 if (time_after(jiffies
, psu
->input_history
.last_update
+ HZ
)) {
123 * Use a raw i2c transfer, since we need more bytes
124 * than Linux I2C supports through smbus xfr (only 32).
126 rc
= i2c_transfer(psu
->client
->adapter
, msg
, 2);
128 mutex_unlock(&psu
->input_history
.update_lock
);
132 psu
->input_history
.byte_count
= msgbuf1
[0];
133 memcpy(psu
->input_history
.data
, &msgbuf1
[1],
134 CFFPS_INPUT_HISTORY_SIZE
);
135 psu
->input_history
.last_update
= jiffies
;
138 mutex_unlock(&psu
->input_history
.update_lock
);
141 return simple_read_from_buffer(buf
, count
, ppos
,
142 psu
->input_history
.data
,
143 psu
->input_history
.byte_count
);
146 static ssize_t
ibm_cffps_debugfs_read(struct file
*file
, char __user
*buf
,
147 size_t count
, loff_t
*ppos
)
151 int *idxp
= file
->private_data
;
153 struct ibm_cffps
*psu
= to_psu(idxp
, idx
);
154 char data
[I2C_SMBUS_BLOCK_MAX
+ 2] = { 0 };
156 pmbus_set_page(psu
->client
, 0, 0xff);
159 case CFFPS_DEBUGFS_INPUT_HISTORY
:
160 return ibm_cffps_read_input_history(psu
, buf
, count
, ppos
);
161 case CFFPS_DEBUGFS_FRU
:
164 case CFFPS_DEBUGFS_PN
:
167 case CFFPS_DEBUGFS_HEADER
:
168 cmd
= CFFPS_HEADER_CMD
;
170 case CFFPS_DEBUGFS_SN
:
173 case CFFPS_DEBUGFS_MAX_POWER_OUT
:
174 rc
= i2c_smbus_read_word_swapped(psu
->client
,
175 CFFPS_MAX_POWER_OUT_CMD
);
179 rc
= snprintf(data
, I2C_SMBUS_BLOCK_MAX
, "%d", rc
);
181 case CFFPS_DEBUGFS_CCIN
:
182 rc
= i2c_smbus_read_word_swapped(psu
->client
, CFFPS_CCIN_CMD
);
186 rc
= snprintf(data
, 5, "%04X", rc
);
188 case CFFPS_DEBUGFS_FW
:
189 switch (psu
->version
) {
191 for (i
= 0; i
< CFFPS1_FW_NUM_BYTES
; ++i
) {
192 rc
= i2c_smbus_read_byte_data(psu
->client
,
198 snprintf(&data
[i
* 2], 3, "%02X", rc
);
204 for (i
= 0; i
< CFFPS2_FW_NUM_WORDS
; ++i
) {
205 rc
= i2c_smbus_read_word_data(psu
->client
,
211 snprintf(&data
[i
* 4], 5, "%04X", rc
);
220 case CFFPS_DEBUGFS_ON_OFF_CONFIG
:
221 rc
= i2c_smbus_read_byte_data(psu
->client
,
222 PMBUS_ON_OFF_CONFIG
);
226 rc
= snprintf(data
, 3, "%02x", rc
);
232 rc
= i2c_smbus_read_block_data(psu
->client
, cmd
, data
);
240 return simple_read_from_buffer(buf
, count
, ppos
, data
, rc
);
243 static ssize_t
ibm_cffps_debugfs_write(struct file
*file
,
244 const char __user
*buf
, size_t count
,
249 int *idxp
= file
->private_data
;
251 struct ibm_cffps
*psu
= to_psu(idxp
, idx
);
254 case CFFPS_DEBUGFS_ON_OFF_CONFIG
:
255 pmbus_set_page(psu
->client
, 0, 0xff);
257 rc
= simple_write_to_buffer(&data
, 1, ppos
, buf
, count
);
261 rc
= i2c_smbus_write_byte_data(psu
->client
,
262 PMBUS_ON_OFF_CONFIG
, data
);
275 static const struct file_operations ibm_cffps_fops
= {
276 .llseek
= noop_llseek
,
277 .read
= ibm_cffps_debugfs_read
,
278 .write
= ibm_cffps_debugfs_write
,
282 static int ibm_cffps_read_byte_data(struct i2c_client
*client
, int page
,
288 case PMBUS_STATUS_VOUT
:
289 case PMBUS_STATUS_IOUT
:
290 case PMBUS_STATUS_TEMPERATURE
:
291 case PMBUS_STATUS_FAN_12
:
292 rc
= pmbus_read_byte_data(client
, page
, reg
);
296 mfr
= pmbus_read_byte_data(client
, page
,
297 PMBUS_STATUS_MFR_SPECIFIC
);
300 * Return the status register instead of an error,
301 * since we successfully read status.
305 /* Add MFR_SPECIFIC bits to the standard pmbus status regs. */
306 if (reg
== PMBUS_STATUS_FAN_12
) {
307 if (mfr
& CFFPS_MFR_FAN_FAULT
)
308 rc
|= PB_FAN_FAN1_FAULT
;
309 } else if (reg
== PMBUS_STATUS_TEMPERATURE
) {
310 if (mfr
& CFFPS_MFR_THERMAL_FAULT
)
311 rc
|= PB_TEMP_OT_FAULT
;
312 } else if (reg
== PMBUS_STATUS_VOUT
) {
313 if (mfr
& (CFFPS_MFR_OV_FAULT
| CFFPS_MFR_VAUX_FAULT
))
314 rc
|= PB_VOLTAGE_OV_FAULT
;
315 if (mfr
& CFFPS_MFR_UV_FAULT
)
316 rc
|= PB_VOLTAGE_UV_FAULT
;
317 } else if (reg
== PMBUS_STATUS_IOUT
) {
318 if (mfr
& CFFPS_MFR_OC_FAULT
)
319 rc
|= PB_IOUT_OC_FAULT
;
320 if (mfr
& CFFPS_MFR_CURRENT_SHARE_WARNING
)
321 rc
|= PB_CURRENT_SHARE_FAULT
;
332 static int ibm_cffps_read_word_data(struct i2c_client
*client
, int page
,
338 case PMBUS_STATUS_WORD
:
339 rc
= pmbus_read_word_data(client
, page
, phase
, reg
);
343 mfr
= pmbus_read_byte_data(client
, page
,
344 PMBUS_STATUS_MFR_SPECIFIC
);
347 * Return the status register instead of an error,
348 * since we successfully read status.
352 if (mfr
& CFFPS_MFR_PS_KILL
)
355 case PMBUS_VIRT_READ_VMON
:
356 rc
= pmbus_read_word_data(client
, page
, phase
,
357 CFFPS_12VCS_VOUT_CMD
);
367 static int ibm_cffps_led_brightness_set(struct led_classdev
*led_cdev
,
368 enum led_brightness brightness
)
372 struct ibm_cffps
*psu
= container_of(led_cdev
, struct ibm_cffps
, led
);
374 if (brightness
== LED_OFF
) {
375 next_led_state
= CFFPS_LED_OFF
;
377 brightness
= LED_FULL
;
379 if (psu
->led_state
!= CFFPS_LED_BLINK
)
380 next_led_state
= CFFPS_LED_ON
;
382 next_led_state
= CFFPS_LED_BLINK
;
385 dev_dbg(&psu
->client
->dev
, "LED brightness set: %d. Command: %d.\n",
386 brightness
, next_led_state
);
388 pmbus_set_page(psu
->client
, 0, 0xff);
390 rc
= i2c_smbus_write_byte_data(psu
->client
, CFFPS_SYS_CONFIG_CMD
,
395 psu
->led_state
= next_led_state
;
396 led_cdev
->brightness
= brightness
;
401 static int ibm_cffps_led_blink_set(struct led_classdev
*led_cdev
,
402 unsigned long *delay_on
,
403 unsigned long *delay_off
)
406 struct ibm_cffps
*psu
= container_of(led_cdev
, struct ibm_cffps
, led
);
408 dev_dbg(&psu
->client
->dev
, "LED blink set.\n");
410 pmbus_set_page(psu
->client
, 0, 0xff);
412 rc
= i2c_smbus_write_byte_data(psu
->client
, CFFPS_SYS_CONFIG_CMD
,
417 psu
->led_state
= CFFPS_LED_BLINK
;
418 led_cdev
->brightness
= LED_FULL
;
419 *delay_on
= CFFPS_BLINK_RATE_MS
;
420 *delay_off
= CFFPS_BLINK_RATE_MS
;
425 static void ibm_cffps_create_led_class(struct ibm_cffps
*psu
)
428 struct i2c_client
*client
= psu
->client
;
429 struct device
*dev
= &client
->dev
;
431 snprintf(psu
->led_name
, sizeof(psu
->led_name
), "%s-%02x", client
->name
,
433 psu
->led
.name
= psu
->led_name
;
434 psu
->led
.max_brightness
= LED_FULL
;
435 psu
->led
.brightness_set_blocking
= ibm_cffps_led_brightness_set
;
436 psu
->led
.blink_set
= ibm_cffps_led_blink_set
;
438 rc
= devm_led_classdev_register(dev
, &psu
->led
);
440 dev_warn(dev
, "failed to register led class: %d\n", rc
);
442 i2c_smbus_write_byte_data(client
, CFFPS_SYS_CONFIG_CMD
,
446 static struct pmbus_driver_info ibm_cffps_info
[] = {
449 .func
[0] = PMBUS_HAVE_VIN
| PMBUS_HAVE_VOUT
| PMBUS_HAVE_IOUT
|
450 PMBUS_HAVE_PIN
| PMBUS_HAVE_FAN12
| PMBUS_HAVE_TEMP
|
451 PMBUS_HAVE_TEMP2
| PMBUS_HAVE_TEMP3
|
452 PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_STATUS_IOUT
|
453 PMBUS_HAVE_STATUS_INPUT
| PMBUS_HAVE_STATUS_TEMP
|
454 PMBUS_HAVE_STATUS_FAN12
,
455 .read_byte_data
= ibm_cffps_read_byte_data
,
456 .read_word_data
= ibm_cffps_read_word_data
,
460 .func
[0] = PMBUS_HAVE_VIN
| PMBUS_HAVE_VOUT
| PMBUS_HAVE_IOUT
|
461 PMBUS_HAVE_PIN
| PMBUS_HAVE_FAN12
| PMBUS_HAVE_TEMP
|
462 PMBUS_HAVE_TEMP2
| PMBUS_HAVE_TEMP3
|
463 PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_STATUS_IOUT
|
464 PMBUS_HAVE_STATUS_INPUT
| PMBUS_HAVE_STATUS_TEMP
|
465 PMBUS_HAVE_STATUS_FAN12
| PMBUS_HAVE_VMON
,
466 .func
[1] = PMBUS_HAVE_VOUT
| PMBUS_HAVE_IOUT
|
467 PMBUS_HAVE_TEMP
| PMBUS_HAVE_TEMP2
| PMBUS_HAVE_TEMP3
|
468 PMBUS_HAVE_STATUS_VOUT
| PMBUS_HAVE_STATUS_IOUT
,
469 .read_byte_data
= ibm_cffps_read_byte_data
,
470 .read_word_data
= ibm_cffps_read_word_data
,
474 static struct pmbus_platform_data ibm_cffps_pdata
= {
475 .flags
= PMBUS_SKIP_STATUS_CHECK
,
478 static int ibm_cffps_probe(struct i2c_client
*client
)
481 enum versions vs
= cffps_unknown
;
482 struct dentry
*debugfs
;
483 struct dentry
*ibm_cffps_dir
;
484 struct ibm_cffps
*psu
;
485 const void *md
= of_device_get_match_data(&client
->dev
);
486 const struct i2c_device_id
*id
;
489 vs
= (enum versions
)md
;
491 id
= i2c_match_id(ibm_cffps_id
, client
);
493 vs
= (enum versions
)id
->driver_data
;
496 if (vs
== cffps_unknown
) {
497 u16 ccin_revision
= 0;
498 u16 ccin_version
= CFFPS_CCIN_VERSION_1
;
499 int ccin
= i2c_smbus_read_word_swapped(client
, CFFPS_CCIN_CMD
);
502 ccin_revision
= FIELD_GET(CFFPS_CCIN_REVISION
, ccin
);
503 ccin_version
= FIELD_GET(CFFPS_CCIN_VERSION
, ccin
);
506 switch (ccin_version
) {
508 case CFFPS_CCIN_VERSION_1
:
511 case CFFPS_CCIN_VERSION_2
:
514 case CFFPS_CCIN_VERSION_3
:
515 if (ccin_revision
== CFFPS_CCIN_REVISION_LEGACY
)
522 /* Set the client name to include the version number. */
523 snprintf(client
->name
, I2C_NAME_SIZE
, "cffps%d", vs
+ 1);
526 client
->dev
.platform_data
= &ibm_cffps_pdata
;
527 rc
= pmbus_do_probe(client
, &ibm_cffps_info
[vs
]);
532 * Don't fail the probe if there isn't enough memory for leds and
535 psu
= devm_kzalloc(&client
->dev
, sizeof(*psu
), GFP_KERNEL
);
540 psu
->client
= client
;
541 mutex_init(&psu
->input_history
.update_lock
);
542 psu
->input_history
.last_update
= jiffies
- HZ
;
544 ibm_cffps_create_led_class(psu
);
546 /* Don't fail the probe if we can't create debugfs */
547 debugfs
= pmbus_get_debugfs_dir(client
);
551 ibm_cffps_dir
= debugfs_create_dir(client
->name
, debugfs
);
555 for (i
= 0; i
< CFFPS_DEBUGFS_NUM_ENTRIES
; ++i
)
556 psu
->debugfs_entries
[i
] = i
;
558 debugfs_create_file("input_history", 0444, ibm_cffps_dir
,
559 &psu
->debugfs_entries
[CFFPS_DEBUGFS_INPUT_HISTORY
],
561 debugfs_create_file("fru", 0444, ibm_cffps_dir
,
562 &psu
->debugfs_entries
[CFFPS_DEBUGFS_FRU
],
564 debugfs_create_file("part_number", 0444, ibm_cffps_dir
,
565 &psu
->debugfs_entries
[CFFPS_DEBUGFS_PN
],
567 debugfs_create_file("header", 0444, ibm_cffps_dir
,
568 &psu
->debugfs_entries
[CFFPS_DEBUGFS_HEADER
],
570 debugfs_create_file("serial_number", 0444, ibm_cffps_dir
,
571 &psu
->debugfs_entries
[CFFPS_DEBUGFS_SN
],
573 debugfs_create_file("max_power_out", 0444, ibm_cffps_dir
,
574 &psu
->debugfs_entries
[CFFPS_DEBUGFS_MAX_POWER_OUT
],
576 debugfs_create_file("ccin", 0444, ibm_cffps_dir
,
577 &psu
->debugfs_entries
[CFFPS_DEBUGFS_CCIN
],
579 debugfs_create_file("fw_version", 0444, ibm_cffps_dir
,
580 &psu
->debugfs_entries
[CFFPS_DEBUGFS_FW
],
582 debugfs_create_file("on_off_config", 0644, ibm_cffps_dir
,
583 &psu
->debugfs_entries
[CFFPS_DEBUGFS_ON_OFF_CONFIG
],
589 static const struct i2c_device_id ibm_cffps_id
[] = {
590 { "ibm_cffps1", cffps1
},
591 { "ibm_cffps2", cffps2
},
592 { "ibm_cffps", cffps_unknown
},
595 MODULE_DEVICE_TABLE(i2c
, ibm_cffps_id
);
597 static const struct of_device_id ibm_cffps_of_match
[] = {
599 .compatible
= "ibm,cffps1",
600 .data
= (void *)cffps1
603 .compatible
= "ibm,cffps2",
604 .data
= (void *)cffps2
607 .compatible
= "ibm,cffps",
608 .data
= (void *)cffps_unknown
612 MODULE_DEVICE_TABLE(of
, ibm_cffps_of_match
);
614 static struct i2c_driver ibm_cffps_driver
= {
617 .of_match_table
= ibm_cffps_of_match
,
619 .probe_new
= ibm_cffps_probe
,
620 .id_table
= ibm_cffps_id
,
623 module_i2c_driver(ibm_cffps_driver
);
625 MODULE_AUTHOR("Eddie James");
626 MODULE_DESCRIPTION("PMBus driver for IBM Common Form Factor power supplies");
627 MODULE_LICENSE("GPL");