hwmon: (pmbus) Add support for Infineon XDP710

Add support for Infineon XDP710.This is a Hot-Swap Controller.

Signed-off-by: Peter Yin <peteryin.openbmc@gmail.com>
Link: https://lore.kernel.org/r/20240425153608.4003782-2-peteryin.openbmc@gmail.com
[groeck: s/microOhmRsense/micro_ohm_osense/g; declared array static]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Peter Yin 2024-04-25 23:36:01 +08:00 committed by Guenter Roeck
parent cffa8fb56a
commit 35fe06d94e
5 changed files with 225 additions and 0 deletions

View File

@ -251,6 +251,7 @@ Hardware Monitoring Kernel Drivers
wm831x
wm8350
xgene-hwmon
xdp710
xdpe12284
xdpe152c4
zl6100

View File

@ -0,0 +1,83 @@
.. SPDX-License-Identifier: GPL-2.0
Kernel driver xdp710
====================
Supported chips:
* Infineon XDP710
Prefix: 'xdp710'
* Datasheet
Publicly available at the Infineon website : https://www.infineon.com/dgdl/Infineon-XDP710-001-DataSheet-v01_00-EN.pdf?fileId=8ac78c8c8412f8d301848a5316290b97
Author:
Peter Yin <peteryin.openbmc@gmail.com>
Description
-----------
This driver implements support for Infineon XDP710 Hot-Swap Controller.
Device compliant with:
- PMBus rev 1.3 interface.
Device supports direct and linear format for reading input voltage,
output voltage, output current, input power and temperature.
The driver exports the following attributes via the 'sysfs' files
for input voltage:
**in1_input**
**in1_label**
**in1_max**
**in1_max_alarm**
**in1_min**
**in1_min_alarm**
The driver provides the following attributes for output voltage:
**in2_input**
**in2_label**
**in2_alarm**
The driver provides the following attributes for output current:
**curr1_input**
**curr1_label**
**curr1_alarm**
**curr1_max**
The driver provides the following attributes for input power:
**power1_input**
**power1_label**
**power1_alarm**
The driver provides the following attributes for temperature:
**temp1_input**
**temp1_max**
**temp1_max_alarm**
**temp1_crit**
**temp1_crit_alarm**

View File

@ -521,6 +521,15 @@ config SENSORS_UCD9200
This driver can also be built as a module. If so, the module will
be called ucd9200.
config SENSORS_XDP710
tristate "Infineon XDP710 family"
help
If you say yes here you get hardware monitoring support for Infineon
XDP710.
This driver can also be built as a module. If so, the module will
be called xdp710.
config SENSORS_XDPE152
tristate "Infineon XDPE152 family"
help

View File

@ -52,6 +52,7 @@ obj-$(CONFIG_SENSORS_TPS53679) += tps53679.o
obj-$(CONFIG_SENSORS_TPS546D24) += tps546d24.o
obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o
obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o
obj-$(CONFIG_SENSORS_XDP710) += xdp710.o
obj-$(CONFIG_SENSORS_XDPE122) += xdpe12284.o
obj-$(CONFIG_SENSORS_XDPE152) += xdpe152c4.o
obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o

View File

@ -0,0 +1,131 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Driver for Infineon XDP710 Hot-Swap Controller
*/
#include <linux/bitops.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include "pmbus.h"
#define XDP710_REG_CFG 0xD3
#define XDP710_V_SNS_CFG 0xD4
#define XDP710_CS_RNG 0xD5
/*
* The table to map configuration register values
* to sense resistor values
*/
static const int micro_ohm_rsense[] = {
200, 250, 300, 330, 400, 470, 500, 600,
670, 700, 750, 800, 900, 1000, 1100, 1200,
1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900,
2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700,
2800, 3000, 3100, 3200, 3300, 3400, 3500, 3600,
3700, 3800, 3900, 4000, 4100, 4200, 4300, 4400,
4500, 4600, 4700, 4800, 4900, 5000, 5500, 6000,
6500, 7000, 7500, 8000, 8500, 9000, 9500, 10000
};
static struct pmbus_driver_info xdp710_info = {
.pages = 1,
.format[PSC_VOLTAGE_IN] = direct,
.format[PSC_VOLTAGE_OUT] = direct,
.format[PSC_CURRENT_OUT] = direct,
.format[PSC_POWER] = direct,
.format[PSC_TEMPERATURE] = direct,
.m[PSC_VOLTAGE_IN] = 4653,
.b[PSC_VOLTAGE_IN] = 0,
.R[PSC_VOLTAGE_IN] = -2,
.m[PSC_VOLTAGE_OUT] = 4653,
.b[PSC_VOLTAGE_OUT] = 0,
.R[PSC_VOLTAGE_OUT] = -2,
.m[PSC_CURRENT_OUT] = 23165,
.b[PSC_CURRENT_OUT] = 0,
.R[PSC_CURRENT_OUT] = -2,
.m[PSC_POWER] = 4211,
.b[PSC_POWER] = 0,
.R[PSC_POWER] = -2,
.m[PSC_TEMPERATURE] = 52,
.b[PSC_TEMPERATURE] = 14321,
.R[PSC_TEMPERATURE] = -1,
.func[0] =
PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_PIN |
PMBUS_HAVE_TEMP | PMBUS_HAVE_IOUT |
PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
};
static int xdp710_probe(struct i2c_client *client)
{
struct pmbus_driver_info *info;
u8 cs_rng;
u8 vtlm_rng;
int rsense;
int ret;
int m = 0;
info = devm_kmemdup(&client->dev, &xdp710_info, sizeof(*info),
GFP_KERNEL);
if (!info)
return -ENOMEM;
ret = i2c_smbus_read_word_data(client, XDP710_CS_RNG);
if (ret < 0) {
dev_err(&client->dev, "Can't get CS_RNG");
return ret;
}
cs_rng = (ret >> 6) & GENMASK(1, 0);
ret = i2c_smbus_read_word_data(client, XDP710_V_SNS_CFG);
if (ret < 0) {
dev_err(&client->dev, "Can't get V_SNS_CFG");
return ret;
}
vtlm_rng = ret & GENMASK(1, 0);
ret = i2c_smbus_read_word_data(client, XDP710_REG_CFG);
if (ret < 0) {
dev_err(&client->dev, "Can't get REG_CFG");
return ret;
}
ret &= GENMASK(5, 0);
rsense = micro_ohm_rsense[ret];
info->m[PSC_VOLTAGE_IN] <<= vtlm_rng;
info->m[PSC_VOLTAGE_OUT] <<= vtlm_rng;
m = info->m[PSC_CURRENT_OUT];
info->m[PSC_CURRENT_OUT] = DIV_ROUND_CLOSEST(m * rsense >> cs_rng, 1000);
m = info->m[PSC_POWER];
info->m[PSC_POWER] = DIV_ROUND_CLOSEST(m * rsense >> cs_rng, 1000);
return pmbus_do_probe(client, info);
}
static const struct of_device_id xdp710_of_match[] = {
{ .compatible = "infineon,xdp710" },
{}
};
static const struct i2c_device_id xdp710_id[] = {
{"xdp710", 0},
{ }
};
MODULE_DEVICE_TABLE(i2c, xdp710_id);
static struct i2c_driver xdp710_driver = {
.driver = {
.name = "xdp710",
.of_match_table = xdp710_of_match,
},
.probe = xdp710_probe,
.id_table = xdp710_id,
};
module_i2c_driver(xdp710_driver);
MODULE_AUTHOR("Peter Yin <peter.yin@quantatw.com>");
MODULE_DESCRIPTION("PMBus driver for XDP710 HSC");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(PMBUS);