1 // SPDX-License-Identifier: GPL-2.0+
3 * Hardware monitoring driver for BEL PFE family power supplies.
5 * Copyright (c) 2019 Facebook Inc.
10 #include <linux/init.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/pmbus.h>
17 enum chips
{pfe1100
, pfe3000
};
20 * Disable status check for pfe3000 devices, because some devices report
21 * communication error (invalid command) for VOUT_MODE command (0x20)
22 * although correct VOUT_MODE (0x16) is returned: it leads to incorrect
23 * exponent in linear mode.
25 static struct pmbus_platform_data pfe3000_plat_data
= {
26 .flags
= PMBUS_SKIP_STATUS_CHECK
,
29 static struct pmbus_driver_info pfe_driver_info
[] = {
32 .format
[PSC_VOLTAGE_IN
] = linear
,
33 .format
[PSC_VOLTAGE_OUT
] = linear
,
34 .format
[PSC_CURRENT_IN
] = linear
,
35 .format
[PSC_CURRENT_OUT
] = linear
,
36 .format
[PSC_POWER
] = linear
,
37 .format
[PSC_TEMPERATURE
] = linear
,
38 .format
[PSC_FAN
] = linear
,
40 .func
[0] = PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT
|
41 PMBUS_HAVE_IOUT
| PMBUS_HAVE_STATUS_IOUT
|
43 PMBUS_HAVE_VIN
| PMBUS_HAVE_IIN
|
44 PMBUS_HAVE_PIN
| PMBUS_HAVE_STATUS_INPUT
|
45 PMBUS_HAVE_TEMP
| PMBUS_HAVE_TEMP2
|
46 PMBUS_HAVE_STATUS_TEMP
|
52 .format
[PSC_VOLTAGE_IN
] = linear
,
53 .format
[PSC_VOLTAGE_OUT
] = linear
,
54 .format
[PSC_CURRENT_IN
] = linear
,
55 .format
[PSC_CURRENT_OUT
] = linear
,
56 .format
[PSC_POWER
] = linear
,
57 .format
[PSC_TEMPERATURE
] = linear
,
58 .format
[PSC_FAN
] = linear
,
61 .func
[0] = PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT
|
62 PMBUS_HAVE_IOUT
| PMBUS_HAVE_STATUS_IOUT
|
63 PMBUS_HAVE_POUT
| PMBUS_HAVE_FAN12
|
64 PMBUS_HAVE_VIN
| PMBUS_HAVE_IIN
|
65 PMBUS_HAVE_PIN
| PMBUS_HAVE_STATUS_INPUT
|
66 PMBUS_HAVE_TEMP
| PMBUS_HAVE_TEMP2
|
67 PMBUS_HAVE_TEMP3
| PMBUS_HAVE_STATUS_TEMP
|
71 .func
[1] = PMBUS_HAVE_VOUT
| PMBUS_HAVE_STATUS_VOUT
|
72 PMBUS_HAVE_IOUT
| PMBUS_HAVE_STATUS_IOUT
|
73 PMBUS_HAVE_PIN
| PMBUS_HAVE_STATUS_INPUT
|
80 * Page 5: Vsb Cathode.
83 .func
[2] = PMBUS_HAVE_VOUT
,
84 .func
[4] = PMBUS_HAVE_VOUT
,
85 .func
[5] = PMBUS_HAVE_VOUT
,
86 .func
[6] = PMBUS_HAVE_VOUT
,
90 static int pfe_pmbus_probe(struct i2c_client
*client
,
91 const struct i2c_device_id
*id
)
95 model
= (int)id
->driver_data
;
98 * PFE3000-12-069RA devices may not stay in page 0 during device
99 * probe which leads to probe failure (read status word failed).
100 * So let's set the device to page 0 at the beginning.
102 if (model
== pfe3000
) {
103 client
->dev
.platform_data
= &pfe3000_plat_data
;
104 i2c_smbus_write_byte_data(client
, PMBUS_PAGE
, 0);
107 return pmbus_do_probe(client
, id
, &pfe_driver_info
[model
]);
110 static const struct i2c_device_id pfe_device_id
[] = {
111 {"pfe1100", pfe1100
},
112 {"pfe3000", pfe3000
},
116 MODULE_DEVICE_TABLE(i2c
, pfe_device_id
);
118 static struct i2c_driver pfe_pmbus_driver
= {
122 .probe
= pfe_pmbus_probe
,
123 .remove
= pmbus_do_remove
,
124 .id_table
= pfe_device_id
,
127 module_i2c_driver(pfe_pmbus_driver
);
129 MODULE_AUTHOR("Tao Ren <rentao.bupt@gmail.com>");
130 MODULE_DESCRIPTION("PMBus driver for BEL PFE Family Power Supplies");
131 MODULE_LICENSE("GPL");