* [PATCH v5 0/5] hwmon: (pmbus/pim4328) Add pim4328 PMBus driver
@ 2021-06-09 9:32 Erik Rosen
2021-06-09 9:32 ` [PATCH v5 1/5] hwmon: (pmbus/pim4328) Add new pmbus flag NO_WRITE_PROTECT Erik Rosen
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Erik Rosen @ 2021-06-09 9:32 UTC (permalink / raw)
To: Jean Delvare, Guenter Roeck, Jonathan Corbet, linux-hwmon,
linux-doc, linux-kernel
Cc: Erik Rosen
Add hardware monitoring support for the Flex power interface modules
PIM4006, PIM4328 and PIM4820.
The modules are equipped with dual feed input and has support for
hotswap, holdup and various circuit protection functionality.
[PATCH 1/5]
The modules have no CAPABILITY or WRITE_PROTECT commands. If these
commands are read, the modules return invalid data (0xFF),
so in addition to the NO_CAPABILITY flag we need a NO_WRITE_PROTECT
flag to tell the pmbus_core driver to not access this register.
[PATCH 2/5]
PIM4328 and PIM4820 use the direct mode data format so new functionality
is added to the pmbus_core driver to be able to read and decode
the COEFFICIENTS command.
This is an implementation of core driver support for reading
and decoding direct format coefficients. If the new flag
PMBUS_USE_COEFFICIENTS_CMD is set, the driver will use the
attribute information in the pmbus_sensor_attr structs together
with the COEFFICIENTS command to read and set the relevant
direct mode coefficients.
[PATCH 3/5]
The two inputs are modelled using virtual phases but there
is a limitation in the pmbus_core that disallows monitoring
of phase functions if there is no corresponding function on
the page level.
In this specific case the PIM4006 module allows
monitoring of current on each input separately,
but there is no corresponding command on the page level.
Is there a specific reason for this limitation?
Otherwise we suggest relaxing this criteria.
[PATCH 4/5]
All modules use manufacturer specific registers (mfr) for
status data and only supports the CML bit in the PMBus
STATUS register. The driver overrides reading the STATUS
register and maps the bits in the mfr registers to the STATUS
register alarm bits.
PATCH 5/5]
Add driver documentation
This patch has been tested with PIM4406, PIM4280 and PIM4328
modules.
v2
-Remove the for_reading parameter from the pmbus_read_coefficients
function.
-Use the correct namespace macro for the pmbus_read_coefficients
function.
-Fix alphabetic ordering of includes
-Remove override of STATUS_WORD since it will never get called by
the core driver.
-Add new patch with tentative implementation of core driver support
for reading direct mode coefficients using the COEFFICIENTS command.
v3
-Rework and simplify the code for initialization of direct mode
coefficients according to comments by Guenter.
-Updated commit message for patch 2/6
v4
-Use tabs for aligning #define.
-Move phase check before switch.
-Return immediately on error.
-Use existing PB_STATUS_ bit masks.
-Add missing error checks.
-Remove unnecessary !=0 check.
-Move pdata allocation ahead of the switch statement.
-Do not export the pmbus_read_coefficients function
-Change nattr type in struct pmbus_class_attr_map to int.
-Remove unnecessary initialization in pmbus_init_coefficients.
-Moved function pmbus_read_coefficients to keep related code together.
-Rewrite init and read coefficients functions to get rid of ugly cast.
-Squashed [PATCH 2/6] & [PATCH 3/6].
-Added Acked-By maintainer.
v5
-Drop MAINTAINERS update.
-Remove unnecessary line split.
-Substitute it's -> its.
-Fixed too many 'not' in commit message.
Erik Rosen (5):
Add new pmbus flag NO_WRITE_PROTECT
Add support for reading direct mode coefficients
Allow phase function even if it does not exist not on the associated
page
Add PMBus driver for PIM4006, PIM4328 and PIM4820
Add documentation for the pim4328 PMBus driver
Documentation/hwmon/index.rst | 1 +
Documentation/hwmon/pim4328.rst | 105 ++++++++++++++
drivers/hwmon/pmbus/Kconfig | 9 ++
drivers/hwmon/pmbus/Makefile | 1 +
drivers/hwmon/pmbus/pim4328.c | 233 +++++++++++++++++++++++++++++++
drivers/hwmon/pmbus/pmbus_core.c | 140 +++++++++++++++++--
include/linux/pmbus.h | 17 +++
7 files changed, 495 insertions(+), 11 deletions(-)
create mode 100644 Documentation/hwmon/pim4328.rst
create mode 100644 drivers/hwmon/pmbus/pim4328.c
base-commit: 6efb943b8616ec53a5e444193dccf1af9ad627b5
--
2.20.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v5 1/5] hwmon: (pmbus/pim4328) Add new pmbus flag NO_WRITE_PROTECT
2021-06-09 9:32 [PATCH v5 0/5] hwmon: (pmbus/pim4328) Add pim4328 PMBus driver Erik Rosen
@ 2021-06-09 9:32 ` Erik Rosen
2021-06-09 9:32 ` [PATCH v5 2/5] hwmon: (pmbus/pim4328) Add support for reading direct mode coefficients Erik Rosen
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Erik Rosen @ 2021-06-09 9:32 UTC (permalink / raw)
To: Jean Delvare, Guenter Roeck, Jonathan Corbet, linux-hwmon,
linux-doc, linux-kernel
Cc: Erik Rosen
Some PMBus chips respond with invalid data when reading the WRITE_PROTECT
register. For such chips, this flag should be set so that the PMBus core
driver doesn't use the WRITE_PROTECT command to determine its behavior.
Signed-off-by: Erik Rosen <erik.rosen@metormote.com>
---
drivers/hwmon/pmbus/pmbus_core.c | 8 +++++---
include/linux/pmbus.h | 9 +++++++++
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index bbd745178147..0579521b6c0a 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2226,9 +2226,11 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
* faults, and we should not try it. Also, in that case, writes into
* limit registers need to be disabled.
*/
- ret = i2c_smbus_read_byte_data(client, PMBUS_WRITE_PROTECT);
- if (ret > 0 && (ret & PB_WP_ANY))
- data->flags |= PMBUS_WRITE_PROTECTED | PMBUS_SKIP_STATUS_CHECK;
+ if (!(data->flags & PMBUS_NO_WRITE_PROTECT)) {
+ ret = i2c_smbus_read_byte_data(client, PMBUS_WRITE_PROTECT);
+ if (ret > 0 && (ret & PB_WP_ANY))
+ data->flags |= PMBUS_WRITE_PROTECTED | PMBUS_SKIP_STATUS_CHECK;
+ }
if (data->info->pages)
pmbus_clear_faults(client);
diff --git a/include/linux/pmbus.h b/include/linux/pmbus.h
index 12cbbf305969..86bacf57f8e9 100644
--- a/include/linux/pmbus.h
+++ b/include/linux/pmbus.h
@@ -43,6 +43,15 @@
*/
#define PMBUS_NO_CAPABILITY BIT(2)
+/*
+ * PMBUS_NO_WRITE_PROTECT
+ *
+ * Some PMBus chips respond with invalid data when reading the WRITE_PROTECT
+ * register. For such chips, this flag should be set so that the PMBus core
+ * driver doesn't use the WRITE_PROTECT command to determine its behavior.
+ */
+#define PMBUS_NO_WRITE_PROTECT BIT(4)
+
struct pmbus_platform_data {
u32 flags; /* Device specific flags */
--
2.20.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v5 2/5] hwmon: (pmbus/pim4328) Add support for reading direct mode coefficients
2021-06-09 9:32 [PATCH v5 0/5] hwmon: (pmbus/pim4328) Add pim4328 PMBus driver Erik Rosen
2021-06-09 9:32 ` [PATCH v5 1/5] hwmon: (pmbus/pim4328) Add new pmbus flag NO_WRITE_PROTECT Erik Rosen
@ 2021-06-09 9:32 ` Erik Rosen
2021-06-09 9:32 ` [PATCH v5 3/5] hwmon: (pmbus/pim4328) Allow phase function even if it's not on page Erik Rosen
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Erik Rosen @ 2021-06-09 9:32 UTC (permalink / raw)
To: Jean Delvare, Guenter Roeck, Jonathan Corbet, linux-hwmon,
linux-doc, linux-kernel
Cc: Erik Rosen
Add support for reading and decoding direct format coefficients to
the PMBus core driver. If the new flag PMBUS_USE_COEFFICIENTS_CMD
is set, the driver will use the COEFFICIENTS register together with
the information in the pmbus_sensor_attr structs to initialize
relevant coefficients for the direct mode format.
Signed-off-by: Erik Rosen <erik.rosen@metormote.com>
---
drivers/hwmon/pmbus/pmbus_core.c | 116 +++++++++++++++++++++++++++++++
include/linux/pmbus.h | 8 +++
2 files changed, 124 insertions(+)
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 0579521b6c0a..d022d3196ae9 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2139,6 +2139,111 @@ static int pmbus_find_attributes(struct i2c_client *client,
return ret;
}
+/*
+ * The pmbus_class_attr_map structure maps one sensor class to
+ * it's corresponding sensor attributes array.
+ */
+struct pmbus_class_attr_map {
+ enum pmbus_sensor_classes class;
+ int nattr;
+ const struct pmbus_sensor_attr *attr;
+};
+
+static const struct pmbus_class_attr_map class_attr_map[] = {
+ {
+ .class = PSC_VOLTAGE_IN,
+ .attr = voltage_attributes,
+ .nattr = ARRAY_SIZE(voltage_attributes),
+ }, {
+ .class = PSC_VOLTAGE_OUT,
+ .attr = voltage_attributes,
+ .nattr = ARRAY_SIZE(voltage_attributes),
+ }, {
+ .class = PSC_CURRENT_IN,
+ .attr = current_attributes,
+ .nattr = ARRAY_SIZE(current_attributes),
+ }, {
+ .class = PSC_CURRENT_OUT,
+ .attr = current_attributes,
+ .nattr = ARRAY_SIZE(current_attributes),
+ }, {
+ .class = PSC_POWER,
+ .attr = power_attributes,
+ .nattr = ARRAY_SIZE(power_attributes),
+ }, {
+ .class = PSC_TEMPERATURE,
+ .attr = temp_attributes,
+ .nattr = ARRAY_SIZE(temp_attributes),
+ }
+};
+
+/*
+ * Read the coefficients for direct mode.
+ */
+static int pmbus_read_coefficients(struct i2c_client *client,
+ struct pmbus_driver_info *info,
+ const struct pmbus_sensor_attr *attr)
+{
+ int rv;
+ union i2c_smbus_data data;
+ enum pmbus_sensor_classes class = attr->class;
+ s8 R;
+ s16 m, b;
+
+ data.block[0] = 2;
+ data.block[1] = attr->reg;
+ data.block[2] = 0x01;
+
+ rv = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+ I2C_SMBUS_WRITE, PMBUS_COEFFICIENTS,
+ I2C_SMBUS_BLOCK_PROC_CALL, &data);
+
+ if (rv < 0)
+ return rv;
+
+ if (data.block[0] != 5)
+ return -EIO;
+
+ m = data.block[1] | (data.block[2] << 8);
+ b = data.block[3] | (data.block[4] << 8);
+ R = data.block[5];
+ info->m[class] = m;
+ info->b[class] = b;
+ info->R[class] = R;
+
+ return rv;
+}
+
+static int pmbus_init_coefficients(struct i2c_client *client,
+ struct pmbus_driver_info *info)
+{
+ int i, n, ret;
+ const struct pmbus_class_attr_map *map;
+ const struct pmbus_sensor_attr *attr;
+
+ for (i = 0; i < ARRAY_SIZE(class_attr_map); i++) {
+ map = &class_attr_map[i];
+ if (info->format[map->class] != direct)
+ continue;
+ for (n = 0; n < map->nattr; n++) {
+ attr = &map->attr[n];
+ if (map->class != attr->class)
+ continue;
+ ret = pmbus_read_coefficients(client, info, attr);
+ if (ret >= 0)
+ break;
+ }
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "No coefficients found for sensor class %d\n",
+ map->class);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
/*
* Identify chip parameters.
* This function is called for all chips.
@@ -2257,6 +2362,17 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
return ret;
}
}
+
+ if (data->flags & PMBUS_USE_COEFFICIENTS_CMD) {
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL))
+ return -ENODEV;
+
+ ret = pmbus_init_coefficients(client, info);
+ if (ret < 0)
+ return ret;
+ }
+
return 0;
}
diff --git a/include/linux/pmbus.h b/include/linux/pmbus.h
index 86bacf57f8e9..f8ba23d911c8 100644
--- a/include/linux/pmbus.h
+++ b/include/linux/pmbus.h
@@ -52,6 +52,14 @@
*/
#define PMBUS_NO_WRITE_PROTECT BIT(4)
+/*
+ * PMBUS_USE_COEFFICIENTS_CMD
+ *
+ * When this flag is set the PMBus core driver will use the COEFFICIENTS
+ * register to initialize the coefficients for the direct mode format.
+ */
+#define PMBUS_USE_COEFFICIENTS_CMD BIT(5)
+
struct pmbus_platform_data {
u32 flags; /* Device specific flags */
--
2.20.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v5 3/5] hwmon: (pmbus/pim4328) Allow phase function even if it's not on page
2021-06-09 9:32 [PATCH v5 0/5] hwmon: (pmbus/pim4328) Add pim4328 PMBus driver Erik Rosen
2021-06-09 9:32 ` [PATCH v5 1/5] hwmon: (pmbus/pim4328) Add new pmbus flag NO_WRITE_PROTECT Erik Rosen
2021-06-09 9:32 ` [PATCH v5 2/5] hwmon: (pmbus/pim4328) Add support for reading direct mode coefficients Erik Rosen
@ 2021-06-09 9:32 ` Erik Rosen
2021-06-09 9:32 ` [PATCH v5 4/5] hwmon: (pmbus/pim4328) Add PMBus driver for PIM4006, PIM4328 and PIM4820 Erik Rosen
2021-06-09 9:32 ` [PATCH v5 5/5] hwmon: (pmbus/pim4328) Add documentation for the pim4328 PMBus driver Erik Rosen
4 siblings, 0 replies; 7+ messages in thread
From: Erik Rosen @ 2021-06-09 9:32 UTC (permalink / raw)
To: Jean Delvare, Guenter Roeck, Jonathan Corbet, linux-hwmon,
linux-doc, linux-kernel
Cc: Erik Rosen
Allow the use of a phase function even if it does not exist on
the associated page.
Signed-off-by: Erik Rosen <erik.rosen@metormote.com>
---
drivers/hwmon/pmbus/pmbus_core.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index d022d3196ae9..80a018cd2a8f 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -1327,14 +1327,14 @@ static int pmbus_add_sensor_attrs(struct i2c_client *client,
pages = paged ? info->pages : 1;
for (page = 0; page < pages; page++) {
- if (!(info->func[page] & attrs->func))
- continue;
- ret = pmbus_add_sensor_attrs_one(client, data, info,
- name, index, page,
- 0xff, attrs, paged);
- if (ret)
- return ret;
- index++;
+ if (info->func[page] & attrs->func) {
+ ret = pmbus_add_sensor_attrs_one(client, data, info,
+ name, index, page,
+ 0xff, attrs, paged);
+ if (ret)
+ return ret;
+ index++;
+ }
if (info->phases[page]) {
int phase;
--
2.20.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v5 4/5] hwmon: (pmbus/pim4328) Add PMBus driver for PIM4006, PIM4328 and PIM4820
2021-06-09 9:32 [PATCH v5 0/5] hwmon: (pmbus/pim4328) Add pim4328 PMBus driver Erik Rosen
` (2 preceding siblings ...)
2021-06-09 9:32 ` [PATCH v5 3/5] hwmon: (pmbus/pim4328) Allow phase function even if it's not on page Erik Rosen
@ 2021-06-09 9:32 ` Erik Rosen
2021-06-09 9:32 ` [PATCH v5 5/5] hwmon: (pmbus/pim4328) Add documentation for the pim4328 PMBus driver Erik Rosen
4 siblings, 0 replies; 7+ messages in thread
From: Erik Rosen @ 2021-06-09 9:32 UTC (permalink / raw)
To: Jean Delvare, Guenter Roeck, Jonathan Corbet, linux-hwmon,
linux-doc, linux-kernel
Cc: Erik Rosen
Add hardware monitoring support for Flex power interface modules PIM4006,
PIM4328 and PIM4820.
Signed-off-by: Erik Rosen <erik.rosen@metormote.com>
---
drivers/hwmon/pmbus/Kconfig | 9 ++
drivers/hwmon/pmbus/Makefile | 1 +
drivers/hwmon/pmbus/pim4328.c | 233 ++++++++++++++++++++++++++++++++++
3 files changed, 243 insertions(+)
create mode 100644 drivers/hwmon/pmbus/pim4328.c
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 37a5c39784fa..001527c71269 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -257,6 +257,15 @@ config SENSORS_MP2975
This driver can also be built as a module. If so, the module will
be called mp2975.
+config SENSORS_PIM4328
+ tristate "Flex PIM4328 and compatibles"
+ help
+ If you say yes here you get hardware monitoring support for Flex
+ PIM4328, PIM4820 and PIM4006 Power Interface Modules.
+
+ This driver can also be built as a module. If so, the module will
+ be called pim4328.
+
config SENSORS_PM6764TR
tristate "ST PM6764TR"
help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index f8dcc27cd56a..2a12397535ba 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -39,3 +39,4 @@ obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o
obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o
obj-$(CONFIG_SENSORS_XDPE122) += xdpe12284.o
obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o
+obj-$(CONFIG_SENSORS_PIM4328) += pim4328.o
diff --git a/drivers/hwmon/pmbus/pim4328.c b/drivers/hwmon/pmbus/pim4328.c
new file mode 100644
index 000000000000..273ff6e57654
--- /dev/null
+++ b/drivers/hwmon/pmbus/pim4328.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hardware monitoring driver for PIM4006, PIM4328 and PIM4820
+ *
+ * Copyright (c) 2021 Flextronics International Sweden AB
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pmbus.h>
+#include <linux/slab.h>
+#include "pmbus.h"
+
+enum chips { pim4006, pim4328, pim4820 };
+
+struct pim4328_data {
+ enum chips id;
+ struct pmbus_driver_info info;
+};
+
+#define to_pim4328_data(x) container_of(x, struct pim4328_data, info)
+
+/* PIM4006 and PIM4328 */
+#define PIM4328_MFR_READ_VINA 0xd3
+#define PIM4328_MFR_READ_VINB 0xd4
+
+/* PIM4006 */
+#define PIM4328_MFR_READ_IINA 0xd6
+#define PIM4328_MFR_READ_IINB 0xd7
+#define PIM4328_MFR_FET_CHECKSTATUS 0xd9
+
+/* PIM4328 */
+#define PIM4328_MFR_STATUS_BITS 0xd5
+
+/* PIM4820 */
+#define PIM4328_MFR_READ_STATUS 0xd0
+
+static const struct i2c_device_id pim4328_id[] = {
+ {"bmr455", pim4328},
+ {"pim4006", pim4006},
+ {"pim4106", pim4006},
+ {"pim4206", pim4006},
+ {"pim4306", pim4006},
+ {"pim4328", pim4328},
+ {"pim4406", pim4006},
+ {"pim4820", pim4820},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, pim4328_id);
+
+static int pim4328_read_word_data(struct i2c_client *client, int page,
+ int phase, int reg)
+{
+ int ret;
+
+ if (page > 0)
+ return -ENXIO;
+
+ if (phase == 0xff)
+ return -ENODATA;
+
+ switch (reg) {
+ case PMBUS_READ_VIN:
+ ret = pmbus_read_word_data(client, page, phase,
+ phase == 0 ? PIM4328_MFR_READ_VINA
+ : PIM4328_MFR_READ_VINB);
+ break;
+ case PMBUS_READ_IIN:
+ ret = pmbus_read_word_data(client, page, phase,
+ phase == 0 ? PIM4328_MFR_READ_IINA
+ : PIM4328_MFR_READ_IINB);
+ break;
+ default:
+ ret = -ENODATA;
+ }
+
+ return ret;
+}
+
+static int pim4328_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct pim4328_data *data = to_pim4328_data(info);
+ int ret, status;
+
+ if (page > 0)
+ return -ENXIO;
+
+ switch (reg) {
+ case PMBUS_STATUS_BYTE:
+ ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_BYTE);
+ if (ret < 0)
+ return ret;
+ if (data->id == pim4006) {
+ status = pmbus_read_word_data(client, page, 0xff,
+ PIM4328_MFR_FET_CHECKSTATUS);
+ if (status < 0)
+ return status;
+ if (status & 0x0630) /* Input UV */
+ ret |= PB_STATUS_VIN_UV;
+ } else if (data->id == pim4328) {
+ status = pmbus_read_byte_data(client, page,
+ PIM4328_MFR_STATUS_BITS);
+ if (status < 0)
+ return status;
+ if (status & 0x04) /* Input UV */
+ ret |= PB_STATUS_VIN_UV;
+ if (status & 0x40) /* Output UV */
+ ret |= PB_STATUS_NONE_ABOVE;
+ } else if (data->id == pim4820) {
+ status = pmbus_read_byte_data(client, page,
+ PIM4328_MFR_READ_STATUS);
+ if (status < 0)
+ return status;
+ if (status & 0x05) /* Input OV or OC */
+ ret |= PB_STATUS_NONE_ABOVE;
+ if (status & 0x1a) /* Input UV */
+ ret |= PB_STATUS_VIN_UV;
+ if (status & 0x40) /* OT */
+ ret |= PB_STATUS_TEMPERATURE;
+ }
+ break;
+ default:
+ ret = -ENODATA;
+ }
+
+ return ret;
+}
+
+static int pim4328_probe(struct i2c_client *client)
+{
+ int status;
+ u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
+ const struct i2c_device_id *mid;
+ struct pim4328_data *data;
+ struct pmbus_driver_info *info;
+ struct pmbus_platform_data *pdata;
+ struct device *dev = &client->dev;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_BYTE_DATA
+ | I2C_FUNC_SMBUS_BLOCK_DATA))
+ return -ENODEV;
+
+ data = devm_kzalloc(&client->dev, sizeof(struct pim4328_data),
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ status = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, device_id);
+ if (status < 0) {
+ dev_err(&client->dev, "Failed to read Manufacturer Model\n");
+ return status;
+ }
+ for (mid = pim4328_id; mid->name[0]; mid++) {
+ if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
+ break;
+ }
+ if (!mid->name[0]) {
+ dev_err(&client->dev, "Unsupported device\n");
+ return -ENODEV;
+ }
+
+ if (strcmp(client->name, mid->name))
+ dev_notice(&client->dev,
+ "Device mismatch: Configured %s, detected %s\n",
+ client->name, mid->name);
+
+ data->id = mid->driver_data;
+ info = &data->info;
+ info->pages = 1;
+ info->read_byte_data = pim4328_read_byte_data;
+ info->read_word_data = pim4328_read_word_data;
+
+ pdata = devm_kzalloc(dev, sizeof(struct pmbus_platform_data),
+ GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+ dev->platform_data = pdata;
+ pdata->flags = PMBUS_NO_CAPABILITY | PMBUS_NO_WRITE_PROTECT;
+
+ switch (data->id) {
+ case pim4006:
+ info->phases[0] = 2;
+ info->func[0] = PMBUS_PHASE_VIRTUAL | PMBUS_HAVE_VIN
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_IOUT;
+ info->pfunc[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN;
+ info->pfunc[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN;
+ break;
+ case pim4328:
+ info->phases[0] = 2;
+ info->func[0] = PMBUS_PHASE_VIRTUAL
+ | PMBUS_HAVE_VCAP | PMBUS_HAVE_VIN
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_IOUT;
+ info->pfunc[0] = PMBUS_HAVE_VIN;
+ info->pfunc[1] = PMBUS_HAVE_VIN;
+ info->format[PSC_VOLTAGE_IN] = direct;
+ info->format[PSC_TEMPERATURE] = direct;
+ info->format[PSC_CURRENT_OUT] = direct;
+ pdata->flags |= PMBUS_USE_COEFFICIENTS_CMD;
+ break;
+ case pim4820:
+ info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_TEMP
+ | PMBUS_HAVE_IIN;
+ info->format[PSC_VOLTAGE_IN] = direct;
+ info->format[PSC_TEMPERATURE] = direct;
+ info->format[PSC_CURRENT_IN] = direct;
+ pdata->flags |= PMBUS_USE_COEFFICIENTS_CMD;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ return pmbus_do_probe(client, info);
+}
+
+static struct i2c_driver pim4328_driver = {
+ .driver = {
+ .name = "pim4328",
+ },
+ .probe_new = pim4328_probe,
+ .id_table = pim4328_id,
+};
+
+module_i2c_driver(pim4328_driver);
+
+MODULE_AUTHOR("Erik Rosen <erik.rosen@metormote.com>");
+MODULE_DESCRIPTION("PMBus driver for PIM4006, PIM4328, PIM4820 power interface modules");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(PMBUS);
--
2.20.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v5 5/5] hwmon: (pmbus/pim4328) Add documentation for the pim4328 PMBus driver
2021-06-09 9:32 [PATCH v5 0/5] hwmon: (pmbus/pim4328) Add pim4328 PMBus driver Erik Rosen
` (3 preceding siblings ...)
2021-06-09 9:32 ` [PATCH v5 4/5] hwmon: (pmbus/pim4328) Add PMBus driver for PIM4006, PIM4328 and PIM4820 Erik Rosen
@ 2021-06-09 9:32 ` Erik Rosen
4 siblings, 0 replies; 7+ messages in thread
From: Erik Rosen @ 2021-06-09 9:32 UTC (permalink / raw)
To: Jean Delvare, Guenter Roeck, Jonathan Corbet, linux-hwmon,
linux-doc, linux-kernel
Cc: Erik Rosen
Add documentation and index link for pim4328 PMBus driver.
Signed-off-by: Erik Rosen <erik.rosen@metormote.com>
---
Documentation/hwmon/index.rst | 1 +
Documentation/hwmon/pim4328.rst | 105 ++++++++++++++++++++++++++++++++
2 files changed, 106 insertions(+)
create mode 100644 Documentation/hwmon/pim4328.rst
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 9ed60fa84cbe..719625f8f755 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -150,6 +150,7 @@ Hardware Monitoring Kernel Drivers
pc87360
pc87427
pcf8591
+ pim4328
pm6764tr
pmbus
powr1220
diff --git a/Documentation/hwmon/pim4328.rst b/Documentation/hwmon/pim4328.rst
new file mode 100644
index 000000000000..70c9e7a6882c
--- /dev/null
+++ b/Documentation/hwmon/pim4328.rst
@@ -0,0 +1,105 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver pim4328
+=====================
+
+Supported chips:
+
+ * Flex PIM4328
+
+ Prefix: 'pim4328', 'bmr455'
+
+ Addresses scanned: -
+
+ Datasheet:
+
+https://flexpowermodules.com/resources/fpm-techspec-pim4328
+
+ * Flex PIM4820
+
+ Prefixes: 'pim4820'
+
+ Addresses scanned: -
+
+ Datasheet: https://flexpowermodules.com/resources/fpm-techspec-pim4820
+
+ * Flex PIM4006, PIM4106, PIM4206, PIM4306, PIM4406
+
+ Prefixes: 'pim4006', 'pim4106', 'pim4206', 'pim4306', 'pim4406'
+
+ Addresses scanned: -
+
+ Datasheet: https://flexpowermodules.com/resources/fpm-techspec-pim4006
+
+Author: Erik Rosen <erik.rosen@metormote.com>
+
+
+Description
+-----------
+
+This driver supports hardware monitoring for Flex PIM4328 and
+compatible digital power interface modules.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus.rst and Documentation.hwmon/pmbus-core for details
+on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices.rst for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. All attributes are read-only.
+
+======================= ========================================================
+in1_label "vin"
+in1_input Measured input voltage.
+in1_alarm Input voltage alarm.
+
+in2_label "vin.0"
+in2_input Measured input voltage on input A.
+
+ PIM4328 and PIM4X06
+
+in3_label "vin.1"
+in3_input Measured input voltage on input B.
+
+ PIM4328 and PIM4X06
+
+in4_label "vcap"
+in4_input Measured voltage on holdup capacitor.
+
+ PIM4328
+
+curr1_label "iin.0"
+curr1_input Measured input current on input A.
+
+ PIM4X06
+
+curr2_label "iin.1"
+curr2_input Measured input current on input B.
+
+ PIM4X06
+
+currX_label "iout1"
+currX_input Measured output current.
+currX_alarm Output current alarm.
+
+ X is 1 for PIM4820, 3 otherwise.
+
+temp1_input Measured temperature.
+temp1_alarm High temperature alarm.
+======================= ========================================================
--
2.20.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v5 1/5] hwmon: (pmbus/pim4328) Add new pmbus flag NO_WRITE_PROTECT
@ 2021-06-09 18:45 Guenter Roeck
0 siblings, 0 replies; 7+ messages in thread
From: Guenter Roeck @ 2021-06-09 18:45 UTC (permalink / raw)
To: Erik Rosen
Cc: Jean Delvare, Jonathan Corbet, linux-hwmon, linux-doc, linux-kernel
On Wed, Jun 09, 2021 at 11:32:05AM +0200, Erik Rosen wrote:
> Some PMBus chips respond with invalid data when reading the WRITE_PROTECT
> register. For such chips, this flag should be set so that the PMBus core
> driver doesn't use the WRITE_PROTECT command to determine its behavior.
>
> Signed-off-by: Erik Rosen <erik.rosen@metormote.com>
Series applied.
Thanks,
Guenter
> ---
> drivers/hwmon/pmbus/pmbus_core.c | 8 +++++---
> include/linux/pmbus.h | 9 +++++++++
> 2 files changed, 14 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
> index bbd745178147..0579521b6c0a 100644
> --- a/drivers/hwmon/pmbus/pmbus_core.c
> +++ b/drivers/hwmon/pmbus/pmbus_core.c
> @@ -2226,9 +2226,11 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
> * faults, and we should not try it. Also, in that case, writes into
> * limit registers need to be disabled.
> */
> - ret = i2c_smbus_read_byte_data(client, PMBUS_WRITE_PROTECT);
> - if (ret > 0 && (ret & PB_WP_ANY))
> - data->flags |= PMBUS_WRITE_PROTECTED | PMBUS_SKIP_STATUS_CHECK;
> + if (!(data->flags & PMBUS_NO_WRITE_PROTECT)) {
> + ret = i2c_smbus_read_byte_data(client, PMBUS_WRITE_PROTECT);
> + if (ret > 0 && (ret & PB_WP_ANY))
> + data->flags |= PMBUS_WRITE_PROTECTED | PMBUS_SKIP_STATUS_CHECK;
> + }
>
> if (data->info->pages)
> pmbus_clear_faults(client);
> diff --git a/include/linux/pmbus.h b/include/linux/pmbus.h
> index 12cbbf305969..86bacf57f8e9 100644
> --- a/include/linux/pmbus.h
> +++ b/include/linux/pmbus.h
> @@ -43,6 +43,15 @@
> */
> #define PMBUS_NO_CAPABILITY BIT(2)
>
> +/*
> + * PMBUS_NO_WRITE_PROTECT
> + *
> + * Some PMBus chips respond with invalid data when reading the WRITE_PROTECT
> + * register. For such chips, this flag should be set so that the PMBus core
> + * driver doesn't use the WRITE_PROTECT command to determine its behavior.
> + */
> +#define PMBUS_NO_WRITE_PROTECT BIT(4)
> +
> struct pmbus_platform_data {
> u32 flags; /* Device specific flags */
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2021-06-09 18:46 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-09 9:32 [PATCH v5 0/5] hwmon: (pmbus/pim4328) Add pim4328 PMBus driver Erik Rosen
2021-06-09 9:32 ` [PATCH v5 1/5] hwmon: (pmbus/pim4328) Add new pmbus flag NO_WRITE_PROTECT Erik Rosen
2021-06-09 9:32 ` [PATCH v5 2/5] hwmon: (pmbus/pim4328) Add support for reading direct mode coefficients Erik Rosen
2021-06-09 9:32 ` [PATCH v5 3/5] hwmon: (pmbus/pim4328) Allow phase function even if it's not on page Erik Rosen
2021-06-09 9:32 ` [PATCH v5 4/5] hwmon: (pmbus/pim4328) Add PMBus driver for PIM4006, PIM4328 and PIM4820 Erik Rosen
2021-06-09 9:32 ` [PATCH v5 5/5] hwmon: (pmbus/pim4328) Add documentation for the pim4328 PMBus driver Erik Rosen
2021-06-09 18:45 [PATCH v5 1/5] hwmon: (pmbus/pim4328) Add new pmbus flag NO_WRITE_PROTECT Guenter Roeck
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).