2 * Copyright 2017 IBM Corp.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
10 #include <linux/bitops.h>
11 #include <linux/device.h>
12 #include <linux/i2c.h>
13 #include <linux/module.h>
17 /* STATUS_MFR_SPECIFIC bits */
18 #define CFFPS_MFR_FAN_FAULT BIT(0)
19 #define CFFPS_MFR_THERMAL_FAULT BIT(1)
20 #define CFFPS_MFR_OV_FAULT BIT(2)
21 #define CFFPS_MFR_UV_FAULT BIT(3)
22 #define CFFPS_MFR_PS_KILL BIT(4)
23 #define CFFPS_MFR_OC_FAULT BIT(5)
24 #define CFFPS_MFR_VAUX_FAULT BIT(6)
25 #define CFFPS_MFR_CURRENT_SHARE_WARNING BIT(7)
27 static int ibm_cffps_read_byte_data(struct i2c_client
*client
, int page
,
33 case PMBUS_STATUS_VOUT
:
34 case PMBUS_STATUS_IOUT
:
35 case PMBUS_STATUS_TEMPERATURE
:
36 case PMBUS_STATUS_FAN_12
:
37 rc
= pmbus_read_byte_data(client
, page
, reg
);
41 mfr
= pmbus_read_byte_data(client
, page
,
42 PMBUS_STATUS_MFR_SPECIFIC
);
45 * Return the status register instead of an error,
46 * since we successfully read status.
50 /* Add MFR_SPECIFIC bits to the standard pmbus status regs. */
51 if (reg
== PMBUS_STATUS_FAN_12
) {
52 if (mfr
& CFFPS_MFR_FAN_FAULT
)
53 rc
|= PB_FAN_FAN1_FAULT
;
54 } else if (reg
== PMBUS_STATUS_TEMPERATURE
) {
55 if (mfr
& CFFPS_MFR_THERMAL_FAULT
)
56 rc
|= PB_TEMP_OT_FAULT
;
57 } else if (reg
== PMBUS_STATUS_VOUT
) {
58 if (mfr
& (CFFPS_MFR_OV_FAULT
| CFFPS_MFR_VAUX_FAULT
))
59 rc
|= PB_VOLTAGE_OV_FAULT
;
60 if (mfr
& CFFPS_MFR_UV_FAULT
)
61 rc
|= PB_VOLTAGE_UV_FAULT
;
62 } else if (reg
== PMBUS_STATUS_IOUT
) {
63 if (mfr
& CFFPS_MFR_OC_FAULT
)
64 rc
|= PB_IOUT_OC_FAULT
;
65 if (mfr
& CFFPS_MFR_CURRENT_SHARE_WARNING
)
66 rc
|= PB_CURRENT_SHARE_FAULT
;
77 static int ibm_cffps_read_word_data(struct i2c_client
*client
, int page
,
83 case PMBUS_STATUS_WORD
:
84 rc
= pmbus_read_word_data(client
, page
, reg
);
88 mfr
= pmbus_read_byte_data(client
, page
,
89 PMBUS_STATUS_MFR_SPECIFIC
);
92 * Return the status register instead of an error,
93 * since we successfully read status.
97 if (mfr
& CFFPS_MFR_PS_KILL
)
108 static struct pmbus_driver_info ibm_cffps_info
= {
110 .func
[0] = PMBUS_HAVE_VIN
| PMBUS_HAVE_VOUT
| PMBUS_HAVE_IOUT
|
111 PMBUS_HAVE_PIN
| PMBUS_HAVE_FAN12
| PMBUS_HAVE_TEMP
|
112 PMBUS_HAVE_TEMP2
| PMBUS_HAVE_TEMP3
| PMBUS_HAVE_STATUS_VOUT
|
113 PMBUS_HAVE_STATUS_IOUT
| PMBUS_HAVE_STATUS_INPUT
|
114 PMBUS_HAVE_STATUS_TEMP
| PMBUS_HAVE_STATUS_FAN12
,
115 .read_byte_data
= ibm_cffps_read_byte_data
,
116 .read_word_data
= ibm_cffps_read_word_data
,
119 static int ibm_cffps_probe(struct i2c_client
*client
,
120 const struct i2c_device_id
*id
)
122 return pmbus_do_probe(client
, id
, &ibm_cffps_info
);
125 static const struct i2c_device_id ibm_cffps_id
[] = {
129 MODULE_DEVICE_TABLE(i2c
, ibm_cffps_id
);
131 static const struct of_device_id ibm_cffps_of_match
[] = {
132 { .compatible
= "ibm,cffps1" },
135 MODULE_DEVICE_TABLE(of
, ibm_cffps_of_match
);
137 static struct i2c_driver ibm_cffps_driver
= {
140 .of_match_table
= ibm_cffps_of_match
,
142 .probe
= ibm_cffps_probe
,
143 .remove
= pmbus_do_remove
,
144 .id_table
= ibm_cffps_id
,
147 module_i2c_driver(ibm_cffps_driver
);
149 MODULE_AUTHOR("Eddie James");
150 MODULE_DESCRIPTION("PMBus driver for IBM Common Form Factor power supplies");
151 MODULE_LICENSE("GPL");