Skip to content

Commit

Permalink
[dps200] Add dps200 PSU module driver (#207)
Browse files Browse the repository at this point in the history
Fix #6602

This change is add new dps200 PSU module driver for fix this issue #6602

I have try to use the generic pmbus driver, but it not support.

[ 5733.051510] pmbus 12-005a: Chip identification failed
[ 5733.112598] i2c i2c-12: new_device: Instantiated device pmbus at 0x5a
[ 5748.459851] pmbus 13-005b: Chip identification failed
[ 5748.520975] i2c i2c-13: new_device: Instantiated device pmbus at 0x5b
  • Loading branch information
schobtr authored May 6, 2021
1 parent 99ad210 commit 12d8a0a
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 0 deletions.
158 changes: 158 additions & 0 deletions patch/driver-hwmon-pmbus-dps200.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
From 966db1e756443757cf74b7d0ba56a3254e35fd79 Mon Sep 17 00:00:00 2001

From: Saranpong Chobtrong <schobtr@celestica.com>

Subject: [PATCH] hwmon: (pmbus/dps200): Support DPS200 PSU module

The generic PMBUS driver does not support the chip that uses direct mode yet.
This driver supports dps200 which uses coefficients defined in the datasheet.
Ref: datasheet is DPS200PB184E-ES002.pdf [not public access datasheet]

DP200 does not support pmbus coefficient commands.
Each field of direct mode has a conversion definition defined by the datasheet.

Add dps200 device to the dps1900 driver.

Signed-off-by: Saranpong Chobtrong <schobtr@celestica.com>
---
drivers/hwmon/pmbus/dps1900.c | 104 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 98 insertions(+), 6 deletions(-)

diff --git a/drivers/hwmon/pmbus/dps1900.c b/drivers/hwmon/pmbus/dps1900.c
index f737f6480..d60c48e2c 100644
--- a/drivers/hwmon/pmbus/dps1900.c
+++ b/drivers/hwmon/pmbus/dps1900.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -7,6 +9,8 @@
#include <linux/pmbus.h>
#include "pmbus.h"

+enum chips { dps1900, dps200 };
+
static int dps1900_read_word_data(struct i2c_client *client, int page, int reg)
{
if (reg >= PMBUS_VIRT_BASE ||
@@ -30,24 +34,112 @@ static int dps1900_read_word_data(struct i2c_client *client, int page, int reg)
return pmbus_read_word_data(client, page, reg);
}

+static int dps200_read_word_data(struct i2c_client *client, int page, int reg)
+{
+
+ if (reg >= PMBUS_VIRT_BASE ||
+ reg == PMBUS_VOUT_OV_FAULT_LIMIT ||
+ reg == PMBUS_VOUT_OV_WARN_LIMIT ||
+ reg == PMBUS_VOUT_UV_WARN_LIMIT ||
+ reg == PMBUS_VOUT_UV_FAULT_LIMIT ||
+ reg == PMBUS_IOUT_OC_LV_FAULT_LIMIT ||
+ reg == PMBUS_IOUT_UC_FAULT_LIMIT ||
+ reg == PMBUS_UT_WARN_LIMIT ||
+ reg == PMBUS_UT_FAULT_LIMIT ||
+ reg == PMBUS_VIN_OV_FAULT_LIMIT ||
+ reg == PMBUS_VIN_OV_WARN_LIMIT ||
+ reg == PMBUS_IIN_OC_FAULT_LIMIT ||
+ reg == PMBUS_POUT_MAX)
+ return -ENXIO;
+
+ /*
+ * NOTE: The following field have constant driver value.
+ * If the register are PMBUS_IOUT_OC_WARN_LIMIT or
+ * PMBUS_IOUT_OC_FAULT_LIMIT convert the constant value from linear
+ * to direct format.
+ */
+ if (reg == PMBUS_IOUT_OC_WARN_LIMIT)
+ return 0xb4;
+ else if (reg == PMBUS_IOUT_OC_FAULT_LIMIT)
+ return 0xc8;
+ else
+ return pmbus_read_word_data(client, page, reg);
+}
+
static struct pmbus_driver_info dps1900_info = {
.pages = 1,
.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
- | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
- | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12
- | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP
- | PMBUS_HAVE_STATUS_INPUT,
+ | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP
+ | PMBUS_HAVE_STATUS_INPUT,
.read_word_data = dps1900_read_word_data,
};

+/*
+ * From DPS-200 datasheet the supported sensors format defined as:
+ * VOUT: direct mode with one decimal place.
+ *
+ * Other sensors:
+ * IOUT: direct mode with one decimal place.
+ * IOUT Limits: linear mode, which difference from IOUT.
+ * VIN, IIN, POWER, TEMP, & FAN: linear mode.
+ */
+static struct pmbus_driver_info dps200_info = {
+ .pages = 1,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT
+ | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3
+ | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_STATUS_INPUT,
+ .format = {
+ [PSC_VOLTAGE_OUT] = direct,
+ [PSC_CURRENT_OUT] = direct,
+ },
+ .m = {
+ [PSC_VOLTAGE_OUT] = 10,
+ [PSC_CURRENT_OUT] = 10,
+ },
+ .b = {
+ [PSC_VOLTAGE_OUT] = 0,
+ [PSC_CURRENT_OUT] = 0,
+ },
+ .R = {
+ [PSC_VOLTAGE_OUT] = 0,
+ [PSC_CURRENT_OUT] = 0,
+ },
+ .read_word_data = dps200_read_word_data,
+};
+
static int dps1900_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- return pmbus_do_probe(client, id, &dps1900_info);
+ struct pmbus_driver_info *info;
+
+ info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ switch (id->driver_data) {
+ case dps1900:
+ info = &dps1900_info;
+ break;
+ case dps200:
+ info = &dps200_info;
+ break;
+ default:
+ dev_err(&client->dev, "Unsupported device\n");
+ return -ENODEV;
+ }
+
+ return pmbus_do_probe(client, id, info);
}

static const struct i2c_device_id dps1900_id[] = {
- {"dps1900", 0},
+ {"dps1900", dps1900},
+ {"dps200", dps200},
{}
};

1 change: 1 addition & 0 deletions patch/series
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ driver-hwmon-pmbus-dni_dps460.patch
driver-hwmon-pmbus-dni_dps460-update-pmbus-core.patch
driver-hwmon-pmbus-dni_dps460-add-status-attributes.patch
driver-hwmon-pmbus-dps1900.patch
driver-hwmon-pmbus-dps200.patch
driver-support-tun-config-carrier-enable.patch
driver-support-optoe.patch
driver-support-optoe-EOF_fix.patch
Expand Down

0 comments on commit 12d8a0a

Please sign in to comment.