aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/pmbus
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/pmbus')
-rw-r--r--drivers/hwmon/pmbus/Kconfig37
-rw-r--r--drivers/hwmon/pmbus/Makefile4
-rw-r--r--drivers/hwmon/pmbus/adm1275.c116
-rw-r--r--drivers/hwmon/pmbus/ibm-cffps.c6
-rw-r--r--drivers/hwmon/pmbus/ir35221.c6
-rw-r--r--drivers/hwmon/pmbus/ir38064.c65
-rw-r--r--drivers/hwmon/pmbus/irps5401.c67
-rw-r--r--drivers/hwmon/pmbus/isl68137.c169
-rw-r--r--drivers/hwmon/pmbus/lm25066.c32
-rw-r--r--drivers/hwmon/pmbus/ltc2978.c11
-rw-r--r--drivers/hwmon/pmbus/ltc3815.c11
-rw-r--r--drivers/hwmon/pmbus/max16064.c15
-rw-r--r--drivers/hwmon/pmbus/max20751.c11
-rw-r--r--drivers/hwmon/pmbus/max31785.c6
-rw-r--r--drivers/hwmon/pmbus/max34440.c15
-rw-r--r--drivers/hwmon/pmbus/max8688.c15
-rw-r--r--drivers/hwmon/pmbus/pmbus.c15
-rw-r--r--drivers/hwmon/pmbus/pmbus.h33
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c181
-rw-r--r--drivers/hwmon/pmbus/pxe1610.c139
-rw-r--r--drivers/hwmon/pmbus/tps40422.c11
-rw-r--r--drivers/hwmon/pmbus/tps53679.c13
-rw-r--r--drivers/hwmon/pmbus/ucd9000.c17
-rw-r--r--drivers/hwmon/pmbus/ucd9200.c17
-rw-r--r--drivers/hwmon/pmbus/zl6100.c15
25 files changed, 799 insertions, 228 deletions
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 629cb45f8557..b6588483fae1 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
#
# PMBus chip drivers configuration
#
@@ -54,6 +55,33 @@ config SENSORS_IR35221
This driver can also be built as a module. If so, the module will
be called ir35521.
+config SENSORS_IR38064
+ tristate "Infineon IR38064"
+ help
+ If you say yes here you get hardware monitoring support for Infineon
+ IR38064.
+
+ This driver can also be built as a module. If so, the module will
+ be called ir38064.
+
+config SENSORS_IRPS5401
+ tristate "Infineon IRPS5401"
+ help
+ If you say yes here you get hardware monitoring support for the
+ Infineon IRPS5401 controller.
+
+ This driver can also be built as a module. If so, the module will
+ be called irps5401.
+
+config SENSORS_ISL68137
+ tristate "Intersil ISL68137"
+ help
+ If you say yes here you get hardware monitoring support for Intersil
+ ISL68137.
+
+ This driver can also be built as a module. If so, the module will
+ be called isl68137.
+
config SENSORS_LM25066
tristate "National Semiconductor LM25066 and compatibles"
help
@@ -135,6 +163,15 @@ config SENSORS_MAX8688
This driver can also be built as a module. If so, the module will
be called max8688.
+config SENSORS_PXE1610
+ tristate "Infineon PXE1610"
+ help
+ If you say yes here you get hardware monitoring support for Infineon
+ PXE1610.
+
+ This driver can also be built as a module. If so, the module will
+ be called pxe1610.
+
config SENSORS_TPS40422
tristate "TI TPS40422"
help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index ea0e39518c21..c950ea9a5d00 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -8,6 +8,9 @@ obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o
obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o
obj-$(CONFIG_SENSORS_IBM_CFFPS) += ibm-cffps.o
obj-$(CONFIG_SENSORS_IR35221) += ir35221.o
+obj-$(CONFIG_SENSORS_IR38064) += ir38064.o
+obj-$(CONFIG_SENSORS_IRPS5401) += irps5401.o
+obj-$(CONFIG_SENSORS_ISL68137) += isl68137.o
obj-$(CONFIG_SENSORS_LM25066) += lm25066.o
obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o
obj-$(CONFIG_SENSORS_LTC3815) += ltc3815.o
@@ -16,6 +19,7 @@ obj-$(CONFIG_SENSORS_MAX20751) += max20751.o
obj-$(CONFIG_SENSORS_MAX31785) += max31785.o
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
+obj-$(CONFIG_SENSORS_PXE1610) += pxe1610.o
obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o
obj-$(CONFIG_SENSORS_TPS53679) += tps53679.o
obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o
diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c
index f569372c9204..5caa37fbfc18 100644
--- a/drivers/hwmon/pmbus/adm1275.c
+++ b/drivers/hwmon/pmbus/adm1275.c
@@ -1,19 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for Analog Devices ADM1275 Hot-Swap Controller
* and Digital Power Monitor
*
* Copyright (c) 2011 Ericsson AB.
* Copyright (c) 2018 Guenter Roeck
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/kernel.h>
@@ -23,6 +14,8 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/bitops.h>
+#include <linux/bitfield.h>
+#include <linux/log2.h>
#include "pmbus.h"
enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 };
@@ -78,6 +71,18 @@ enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 };
#define ADM1075_VAUX_OV_WARN BIT(7)
#define ADM1075_VAUX_UV_WARN BIT(6)
+#define ADM1275_VI_AVG_SHIFT 0
+#define ADM1275_VI_AVG_MASK GENMASK(ADM1275_VI_AVG_SHIFT + 2, \
+ ADM1275_VI_AVG_SHIFT)
+#define ADM1275_SAMPLES_AVG_MAX 128
+
+#define ADM1278_PWR_AVG_SHIFT 11
+#define ADM1278_PWR_AVG_MASK GENMASK(ADM1278_PWR_AVG_SHIFT + 2, \
+ ADM1278_PWR_AVG_SHIFT)
+#define ADM1278_VI_AVG_SHIFT 8
+#define ADM1278_VI_AVG_MASK GENMASK(ADM1278_VI_AVG_SHIFT + 2, \
+ ADM1278_VI_AVG_SHIFT)
+
struct adm1275_data {
int id;
bool have_oc_fault;
@@ -89,6 +94,7 @@ struct adm1275_data {
bool have_pin_min;
bool have_pin_max;
bool have_temp_max;
+ bool have_power_sampling;
struct pmbus_driver_info info;
};
@@ -164,6 +170,62 @@ static const struct coefficients adm1293_coefficients[] = {
[18] = { 7658, 0, -3 }, /* power, 21V, irange200 */
};
+static int adm1275_read_pmon_config(const struct adm1275_data *data,
+ struct i2c_client *client, bool is_power)
+{
+ int shift, ret;
+ u16 mask;
+
+ /*
+ * The PMON configuration register is a 16-bit register only on chips
+ * supporting power average sampling. On other chips it is an 8-bit
+ * register.
+ */
+ if (data->have_power_sampling) {
+ ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
+ mask = is_power ? ADM1278_PWR_AVG_MASK : ADM1278_VI_AVG_MASK;
+ shift = is_power ? ADM1278_PWR_AVG_SHIFT : ADM1278_VI_AVG_SHIFT;
+ } else {
+ ret = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
+ mask = ADM1275_VI_AVG_MASK;
+ shift = ADM1275_VI_AVG_SHIFT;
+ }
+ if (ret < 0)
+ return ret;
+
+ return (ret & mask) >> shift;
+}
+
+static int adm1275_write_pmon_config(const struct adm1275_data *data,
+ struct i2c_client *client,
+ bool is_power, u16 word)
+{
+ int shift, ret;
+ u16 mask;
+
+ if (data->have_power_sampling) {
+ ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG);
+ mask = is_power ? ADM1278_PWR_AVG_MASK : ADM1278_VI_AVG_MASK;
+ shift = is_power ? ADM1278_PWR_AVG_SHIFT : ADM1278_VI_AVG_SHIFT;
+ } else {
+ ret = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
+ mask = ADM1275_VI_AVG_MASK;
+ shift = ADM1275_VI_AVG_SHIFT;
+ }
+ if (ret < 0)
+ return ret;
+
+ word = (ret & ~mask) | ((word << shift) & mask);
+ if (data->have_power_sampling)
+ ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG,
+ word);
+ else
+ ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG,
+ word);
+
+ return ret;
+}
+
static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
@@ -242,6 +304,21 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
if (!data->have_temp_max)
return -ENXIO;
break;
+ case PMBUS_VIRT_POWER_SAMPLES:
+ if (!data->have_power_sampling)
+ return -ENXIO;
+ ret = adm1275_read_pmon_config(data, client, true);
+ if (ret < 0)
+ break;
+ ret = BIT(ret);
+ break;
+ case PMBUS_VIRT_IN_SAMPLES:
+ case PMBUS_VIRT_CURR_SAMPLES:
+ ret = adm1275_read_pmon_config(data, client, false);
+ if (ret < 0)
+ break;
+ ret = BIT(ret);
+ break;
default:
ret = -ENODATA;
break;
@@ -286,6 +363,19 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
case PMBUS_VIRT_RESET_TEMP_HISTORY:
ret = pmbus_write_word_data(client, 0, ADM1278_PEAK_TEMP, 0);
break;
+ case PMBUS_VIRT_POWER_SAMPLES:
+ if (!data->have_power_sampling)
+ return -ENXIO;
+ word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX);
+ ret = adm1275_write_pmon_config(data, client, true,
+ ilog2(word));
+ break;
+ case PMBUS_VIRT_IN_SAMPLES:
+ case PMBUS_VIRT_CURR_SAMPLES:
+ word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX);
+ ret = adm1275_write_pmon_config(data, client, false,
+ ilog2(word));
+ break;
default:
ret = -ENODATA;
break;
@@ -439,7 +529,8 @@ static int adm1275_probe(struct i2c_client *client,
info->format[PSC_CURRENT_OUT] = direct;
info->format[PSC_POWER] = direct;
info->format[PSC_TEMPERATURE] = direct;
- info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
+ info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_SAMPLES;
info->read_word_data = adm1275_read_word_data;
info->read_byte_data = adm1275_read_byte_data;
@@ -480,6 +571,7 @@ static int adm1275_probe(struct i2c_client *client,
data->have_vout = true;
data->have_pin_max = true;
data->have_temp_max = true;
+ data->have_power_sampling = true;
coefficients = adm1272_coefficients;
vindex = (config & ADM1275_VRANGE) ? 1 : 0;
@@ -565,6 +657,7 @@ static int adm1275_probe(struct i2c_client *client,
data->have_vout = true;
data->have_pin_max = true;
data->have_temp_max = true;
+ data->have_power_sampling = true;
coefficients = adm1278_coefficients;
vindex = 0;
@@ -600,6 +693,7 @@ static int adm1275_probe(struct i2c_client *client,
data->have_pin_min = true;
data->have_pin_max = true;
data->have_mfr_vaux_status = true;
+ data->have_power_sampling = true;
coefficients = adm1293_coefficients;
diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c
index 93d9a9ea112b..ee2ee9e3ffd7 100644
--- a/drivers/hwmon/pmbus/ibm-cffps.c
+++ b/drivers/hwmon/pmbus/ibm-cffps.c
@@ -1,10 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2017 IBM Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
*/
#include <linux/bitops.h>
diff --git a/drivers/hwmon/pmbus/ir35221.c b/drivers/hwmon/pmbus/ir35221.c
index 977315b0fd90..0d878bcd6d26 100644
--- a/drivers/hwmon/pmbus/ir35221.c
+++ b/drivers/hwmon/pmbus/ir35221.c
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for IR35221
*
* Copyright (C) IBM Corporation 2017.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
*/
#include <linux/err.h>
diff --git a/drivers/hwmon/pmbus/ir38064.c b/drivers/hwmon/pmbus/ir38064.c
new file mode 100644
index 000000000000..1820f5077f66
--- /dev/null
+++ b/drivers/hwmon/pmbus/ir38064.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Hardware monitoring driver for Infineon IR38064
+ *
+ * Copyright (c) 2017 Google Inc
+ *
+ * VOUT_MODE is not supported by the device. The driver fakes VOUT linear16
+ * mode with exponent value -8 as direct mode with m=256/b=0/R=0.
+ *
+ * The device supports VOUT_PEAK, IOUT_PEAK, and TEMPERATURE_PEAK, however
+ * this driver does not currently support them.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include "pmbus.h"
+
+static struct pmbus_driver_info ir38064_info = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = direct,
+ .format[PSC_CURRENT_OUT] = linear,
+ .format[PSC_POWER] = linear,
+ .format[PSC_TEMPERATURE] = linear,
+ .m[PSC_VOLTAGE_OUT] = 256,
+ .b[PSC_VOLTAGE_OUT] = 0,
+ .R[PSC_VOLTAGE_OUT] = 0,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_POUT,
+};
+
+static int ir38064_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return pmbus_do_probe(client, id, &ir38064_info);
+}
+
+static const struct i2c_device_id ir38064_id[] = {
+ {"ir38064", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ir38064_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ir38064_driver = {
+ .driver = {
+ .name = "ir38064",
+ },
+ .probe = ir38064_probe,
+ .remove = pmbus_do_remove,
+ .id_table = ir38064_id,
+};
+
+module_i2c_driver(ir38064_driver);
+
+MODULE_AUTHOR("Maxim Sloyko <maxims@google.com>");
+MODULE_DESCRIPTION("PMBus driver for Infineon IR38064");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pmbus/irps5401.c b/drivers/hwmon/pmbus/irps5401.c
new file mode 100644
index 000000000000..d37daa001fb3
--- /dev/null
+++ b/drivers/hwmon/pmbus/irps5401.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Hardware monitoring driver for the Infineon IRPS5401M PMIC.
+ *
+ * Copyright (c) 2019 SED Systems, a division of Calian Ltd.
+ *
+ * The device supports VOUT_PEAK, IOUT_PEAK, and TEMPERATURE_PEAK, however
+ * this driver does not currently support them.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include "pmbus.h"
+
+#define IRPS5401_SW_FUNC (PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | \
+ PMBUS_HAVE_STATUS_INPUT | \
+ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | \
+ PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | \
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP)
+
+#define IRPS5401_LDO_FUNC (PMBUS_HAVE_VIN | \
+ PMBUS_HAVE_STATUS_INPUT | \
+ PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | \
+ PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | \
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP)
+
+static struct pmbus_driver_info irps5401_info = {
+ .pages = 5,
+ .func[0] = IRPS5401_SW_FUNC,
+ .func[1] = IRPS5401_SW_FUNC,
+ .func[2] = IRPS5401_SW_FUNC,
+ .func[3] = IRPS5401_SW_FUNC,
+ .func[4] = IRPS5401_LDO_FUNC,
+};
+
+static int irps5401_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return pmbus_do_probe(client, id, &irps5401_info);
+}
+
+static const struct i2c_device_id irps5401_id[] = {
+ {"irps5401", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, irps5401_id);
+
+static struct i2c_driver irps5401_driver = {
+ .driver = {
+ .name = "irps5401",
+ },
+ .probe = irps5401_probe,
+ .remove = pmbus_do_remove,
+ .id_table = irps5401_id,
+};
+
+module_i2c_driver(irps5401_driver);
+
+MODULE_AUTHOR("Robert Hancock");
+MODULE_DESCRIPTION("PMBus driver for Infineon IRPS5401");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pmbus/isl68137.c b/drivers/hwmon/pmbus/isl68137.c
new file mode 100644
index 000000000000..515596c92fe1
--- /dev/null
+++ b/drivers/hwmon/pmbus/isl68137.c
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Hardware monitoring driver for Intersil ISL68137
+ *
+ * Copyright (c) 2017 Google Inc
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include "pmbus.h"
+
+#define ISL68137_VOUT_AVS 0x30
+
+static ssize_t isl68137_avs_enable_show_page(struct i2c_client *client,
+ int page,
+ char *buf)
+{
+ int val = pmbus_read_byte_data(client, page, PMBUS_OPERATION);
+
+ return sprintf(buf, "%d\n",
+ (val & ISL68137_VOUT_AVS) == ISL68137_VOUT_AVS ? 1 : 0);
+}
+
+static ssize_t isl68137_avs_enable_store_page(struct i2c_client *client,
+ int page,
+ const char *buf, size_t count)
+{
+ int rc, op_val;
+ bool result;
+
+ rc = kstrtobool(buf, &result);
+ if (rc)
+ return rc;
+
+ op_val = result ? ISL68137_VOUT_AVS : 0;
+
+ /*
+ * Writes to VOUT setpoint over AVSBus will persist after the VRM is
+ * switched to PMBus control. Switching back to AVSBus control
+ * restores this persisted setpoint rather than re-initializing to
+ * PMBus VOUT_COMMAND. Writing VOUT_COMMAND first over PMBus before
+ * enabling AVS control is the workaround.
+ */
+ if (op_val == ISL68137_VOUT_AVS) {
+ rc = pmbus_read_word_data(client, page, PMBUS_VOUT_COMMAND);
+ if (rc < 0)
+ return rc;
+
+ rc = pmbus_write_word_data(client, page, PMBUS_VOUT_COMMAND,
+ rc);
+ if (rc < 0)
+ return rc;
+ }
+
+ rc = pmbus_update_byte_data(client, page, PMBUS_OPERATION,
+ ISL68137_VOUT_AVS, op_val);
+
+ return (rc < 0) ? rc : count;
+}
+
+static ssize_t isl68137_avs_enable_show(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+ return isl68137_avs_enable_show_page(client, attr->index, buf);
+}
+
+static ssize_t isl68137_avs_enable_store(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+ return isl68137_avs_enable_store_page(client, attr->index, buf, count);
+}
+
+static SENSOR_DEVICE_ATTR_RW(avs0_enable, isl68137_avs_enable, 0);
+static SENSOR_DEVICE_ATTR_RW(avs1_enable, isl68137_avs_enable, 1);
+
+static struct attribute *enable_attrs[] = {
+ &sensor_dev_attr_avs0_enable.dev_attr.attr,
+ &sensor_dev_attr_avs1_enable.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group enable_group = {
+ .attrs = enable_attrs,
+};
+
+static const struct attribute_group *attribute_groups[] = {
+ &enable_group,
+ NULL,
+};
+
+static struct pmbus_driver_info isl68137_info = {
+ .pages = 2,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .format[PSC_VOLTAGE_OUT] = direct,
+ .format[PSC_CURRENT_IN] = direct,
+ .format[PSC_CURRENT_OUT] = direct,
+ .format[PSC_POWER] = direct,
+ .format[PSC_TEMPERATURE] = direct,
+ .m[PSC_VOLTAGE_IN] = 1,
+ .b[PSC_VOLTAGE_IN] = 0,
+ .R[PSC_VOLTAGE_IN] = 3,
+ .m[PSC_VOLTAGE_OUT] = 1,
+ .b[PSC_VOLTAGE_OUT] = 0,
+ .R[PSC_VOLTAGE_OUT] = 3,
+ .m[PSC_CURRENT_IN] = 1,
+ .b[PSC_CURRENT_IN] = 0,
+ .R[PSC_CURRENT_IN] = 2,
+ .m[PSC_CURRENT_OUT] = 1,
+ .b[PSC_CURRENT_OUT] = 0,
+ .R[PSC_CURRENT_OUT] = 1,
+ .m[PSC_POWER] = 1,
+ .b[PSC_POWER] = 0,
+ .R[PSC_POWER] = 0,
+ .m[PSC_TEMPERATURE] = 1,
+ .b[PSC_TEMPERATURE] = 0,
+ .R[PSC_TEMPERATURE] = 0,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_PIN
+ | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2
+ | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
+ .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
+ .groups = attribute_groups,
+};
+
+static int isl68137_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return pmbus_do_probe(client, id, &isl68137_info);
+}
+
+static const struct i2c_device_id isl68137_id[] = {
+ {"isl68137", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, isl68137_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver isl68137_driver = {
+ .driver = {
+ .name = "isl68137",
+ },
+ .probe = isl68137_probe,
+ .remove = pmbus_do_remove,
+ .id_table = isl68137_id,
+};
+
+module_i2c_driver(isl68137_driver);
+
+MODULE_AUTHOR("Maxim Sloyko <maxims@google.com>");
+MODULE_DESCRIPTION("PMBus driver for Intersil ISL68137");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
index 53db78753a0d..05fce86f1f81 100644
--- a/drivers/hwmon/pmbus/lm25066.c
+++ b/drivers/hwmon/pmbus/lm25066.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM5066
*
* Copyright (c) 2011 Ericsson AB.
* Copyright (c) 2013 Guenter Roeck
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/bitops.h>
@@ -26,6 +13,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/log2.h>
#include "pmbus.h"
enum chips { lm25056, lm25066, lm5064, lm5066, lm5066i };
@@ -39,12 +27,15 @@ enum chips { lm25056, lm25066, lm5064, lm5066, lm5066i };
#define LM25066_CLEAR_PIN_PEAK 0xd6
#define LM25066_DEVICE_SETUP 0xd9
#define LM25066_READ_AVG_VIN 0xdc
+#define LM25066_SAMPLES_FOR_AVG 0xdb
#define LM25066_READ_AVG_VOUT 0xdd
#define LM25066_READ_AVG_IIN 0xde
#define LM25066_READ_AVG_PIN 0xdf
#define LM25066_DEV_SETUP_CL BIT(4) /* Current limit */
+#define LM25066_SAMPLES_FOR_AVG_MAX 4096
+
/* LM25056 only */
#define LM25056_VAUX_OV_WARN_LIMIT 0xe3
@@ -284,6 +275,12 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
case PMBUS_VIRT_RESET_PIN_HISTORY:
ret = 0;
break;
+ case PMBUS_VIRT_SAMPLES:
+ ret = pmbus_read_byte_data(client, 0, LM25066_SAMPLES_FOR_AVG);
+ if (ret < 0)
+ break;
+ ret = 1 << ret;
+ break;
default:
ret = -ENODATA;
break;
@@ -398,6 +395,11 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
case PMBUS_VIRT_RESET_PIN_HISTORY:
ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK);
break;
+ case PMBUS_VIRT_SAMPLES:
+ word = clamp_val(word, 1, LM25066_SAMPLES_FOR_AVG_MAX);
+ ret = pmbus_write_byte_data(client, 0, LM25066_SAMPLES_FOR_AVG,
+ ilog2(word));
+ break;
default:
ret = -ENODATA;
break;
@@ -438,7 +440,7 @@ static int lm25066_probe(struct i2c_client *client,
info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON
| PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT
- | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+ | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_SAMPLES;
if (data->id == lm25056) {
info->func[0] |= PMBUS_HAVE_STATUS_VMON;
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
index 29c0b7219aaa..f01f4887fb2e 100644
--- a/drivers/hwmon/pmbus/ltc2978.c
+++ b/drivers/hwmon/pmbus/ltc2978.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for LTC2978 and compatible chips.
*
@@ -5,16 +6,6 @@
* Copyright (c) 2013, 2014, 2015 Guenter Roeck
* Copyright (c) 2015 Linear Technology
* Copyright (c) 2018 Analog Devices Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/delay.h>
diff --git a/drivers/hwmon/pmbus/ltc3815.c b/drivers/hwmon/pmbus/ltc3815.c
index bb32e6276622..b83a18a58364 100644
--- a/drivers/hwmon/pmbus/ltc3815.c
+++ b/drivers/hwmon/pmbus/ltc3815.c
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for LTC3815
*
* Copyright (c) 2015 Linear Technology
* Copyright (c) 2015 Guenter Roeck
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/err.h>
diff --git a/drivers/hwmon/pmbus/max16064.c b/drivers/hwmon/pmbus/max16064.c
index fa237a3c3291..b3e7b8d2e69d 100644
--- a/drivers/hwmon/pmbus/max16064.c
+++ b/drivers/hwmon/pmbus/max16064.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for Maxim MAX16064
*
* Copyright (c) 2011 Ericsson AB.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/hwmon/pmbus/max20751.c b/drivers/hwmon/pmbus/max20751.c
index ab74aeae8cf2..ee5f0cdbde06 100644
--- a/drivers/hwmon/pmbus/max20751.c
+++ b/drivers/hwmon/pmbus/max20751.c
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for Maxim MAX20751
*
* Copyright (c) 2015 Guenter Roeck
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/kernel.h>
diff --git a/drivers/hwmon/pmbus/max31785.c b/drivers/hwmon/pmbus/max31785.c
index c9dc8799b5e1..69d9029ea410 100644
--- a/drivers/hwmon/pmbus/max31785.c
+++ b/drivers/hwmon/pmbus/max31785.c
@@ -1,10 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2017 IBM Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
*/
#include <linux/kernel.h>
diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c
index 47576c460010..5c63a6600729 100644
--- a/drivers/hwmon/pmbus/max34440.c
+++ b/drivers/hwmon/pmbus/max34440.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for Maxim MAX34440/MAX34441
*
* Copyright (c) 2011 Ericsson AB.
* Copyright (c) 2012 Guenter Roeck
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/bitops.h>
diff --git a/drivers/hwmon/pmbus/max8688.c b/drivers/hwmon/pmbus/max8688.c
index e951f9b87abb..bc5f4cb6450e 100644
--- a/drivers/hwmon/pmbus/max8688.c
+++ b/drivers/hwmon/pmbus/max8688.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for Maxim MAX8688
*
* Copyright (c) 2011 Ericsson AB.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/bitops.h>
diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c
index f05eaa50535e..c0bc43d01018 100644
--- a/drivers/hwmon/pmbus/pmbus.c
+++ b/drivers/hwmon/pmbus/pmbus.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for PMBus devices
*
* Copyright (c) 2010, 2011 Ericsson AB.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
index 1d24397d36ec..d198af3a92b6 100644
--- a/drivers/hwmon/pmbus/pmbus.h
+++ b/drivers/hwmon/pmbus/pmbus.h
@@ -1,22 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* pmbus.h - Common defines and structures for PMBus devices
*
* Copyright (c) 2010, 2011 Ericsson AB.
* Copyright (c) 2012 Guenter Roeck
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef PMBUS_H
@@ -217,6 +204,20 @@ enum pmbus_regs {
PMBUS_VIRT_PWM_ENABLE_2,
PMBUS_VIRT_PWM_ENABLE_3,
PMBUS_VIRT_PWM_ENABLE_4,
+
+ /* Samples for average
+ *
+ * Drivers wanting to expose functionality for changing the number of
+ * samples used for average values should implement support in
+ * {read,write}_word_data callback for either PMBUS_VIRT_SAMPLES if it
+ * applies to all types of measurements, or any number of specific
+ * PMBUS_VIRT_*_SAMPLES registers to allow for individual control.
+ */
+ PMBUS_VIRT_SAMPLES,
+ PMBUS_VIRT_IN_SAMPLES,
+ PMBUS_VIRT_CURR_SAMPLES,
+ PMBUS_VIRT_POWER_SAMPLES,
+ PMBUS_VIRT_TEMP_SAMPLES,
};
/*
@@ -371,6 +372,7 @@ enum pmbus_sensor_classes {
#define PMBUS_HAVE_STATUS_VMON BIT(19)
#define PMBUS_HAVE_PWM12 BIT(20)
#define PMBUS_HAVE_PWM34 BIT(21)
+#define PMBUS_HAVE_SAMPLES BIT(22)
#define PMBUS_PAGE_VIRTUAL BIT(31)
@@ -417,6 +419,9 @@ struct pmbus_driver_info {
/* Regulator functionality, if supported by this chip driver. */
int num_regulators;
const struct regulator_desc *reg_desc;
+
+ /* custom attributes */
+ const struct attribute_group **groups;
};
/* Regulator ops */
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 2e2b5851139c..8470097907bc 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for PMBus devices
*
* Copyright (c) 2010, 2011 Ericsson AB.
* Copyright (c) 2012 Guenter Roeck
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/debugfs.h>
@@ -103,7 +90,7 @@ struct pmbus_data {
int max_attributes;
int num_attributes;
struct attribute_group group;
- const struct attribute_group *groups[2];
+ const struct attribute_group **groups;
struct dentry *debugfs; /* debugfs device directory */
struct pmbus_sensor *sensors;
@@ -1073,7 +1060,7 @@ static int pmbus_add_boolean(struct pmbus_data *data,
name, seq, type);
boolean->s1 = s1;
boolean->s2 = s2;
- pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL,
+ pmbus_attr_init(a, boolean->name, 0444, pmbus_show_boolean, NULL,
(reg << 16) | mask);
return pmbus_add_attribute(data, &a->dev_attr.attr);
@@ -1107,7 +1094,7 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
sensor->update = update;
sensor->convert = convert;
pmbus_dev_attr_init(a, sensor->name,
- readonly ? S_IRUGO : S_IRUGO | S_IWUSR,
+ readonly ? 0444 : 0644,
pmbus_show_sensor, pmbus_set_sensor);
if (pmbus_add_attribute(data, &a->attr))
@@ -1139,7 +1126,7 @@ static int pmbus_add_label(struct pmbus_data *data,
snprintf(label->label, sizeof(label->label), "%s%d", lstring,
index);
- pmbus_dev_attr_init(a, label->name, S_IRUGO, pmbus_show_label, NULL);
+ pmbus_dev_attr_init(a, label->name, 0444, pmbus_show_label, NULL);
return pmbus_add_attribute(data, &a->attr);
}
@@ -1230,7 +1217,8 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
const struct pmbus_driver_info *info,
const char *name,
int index, int page,
- const struct pmbus_sensor_attr *attr)
+ const struct pmbus_sensor_attr *attr,
+ bool paged)
{
struct pmbus_sensor *base;
bool upper = !!(attr->gbit & 0xff00); /* need to check STATUS_WORD */
@@ -1238,7 +1226,7 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
if (attr->label) {
ret = pmbus_add_label(data, name, index, attr->label,
- attr->paged ? page + 1 : 0);
+ paged ? page + 1 : 0);
if (ret)
return ret;
}
@@ -1271,6 +1259,30 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
return 0;
}
+static bool pmbus_sensor_is_paged(const struct pmbus_driver_info *info,
+ const struct pmbus_sensor_attr *attr)
+{
+ int p;
+
+ if (attr->paged)
+ return true;
+
+ /*
+ * Some attributes may be present on more than one page despite
+ * not being marked with the paged attribute. If that is the case,
+ * then treat the sensor as being paged and add the page suffix to the
+ * attribute name.
+ * We don't just add the paged attribute to all such attributes, in
+ * order to maintain the un-suffixed labels in the case where the
+ * attribute is only on page 0.
+ */
+ for (p = 1; p < info->pages; p++) {
+ if (info->func[p] & attr->func)
+ return true;
+ }
+ return false;
+}
+
static int pmbus_add_sensor_attrs(struct i2c_client *client,
struct pmbus_data *data,
const char *name,
@@ -1284,14 +1296,15 @@ static int pmbus_add_sensor_attrs(struct i2c_client *client,
index = 1;
for (i = 0; i < nattrs; i++) {
int page, pages;
+ bool paged = pmbus_sensor_is_paged(info, attrs);
- pages = attrs->paged ? info->pages : 1;
+ 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,
- attrs);
+ attrs, paged);
if (ret)
return ret;
index++;
@@ -1901,6 +1914,115 @@ static int pmbus_add_fan_attributes(struct i2c_client *client,
return 0;
}
+struct pmbus_samples_attr {
+ int reg;
+ char *name;
+};
+
+struct pmbus_samples_reg {
+ int page;
+ struct pmbus_samples_attr *attr;
+ struct device_attribute dev_attr;
+};
+
+static struct pmbus_samples_attr pmbus_samples_registers[] = {
+ {
+ .reg = PMBUS_VIRT_SAMPLES,
+ .name = "samples",
+ }, {
+ .reg = PMBUS_VIRT_IN_SAMPLES,
+ .name = "in_samples",
+ }, {
+ .reg = PMBUS_VIRT_CURR_SAMPLES,
+ .name = "curr_samples",
+ }, {
+ .reg = PMBUS_VIRT_POWER_SAMPLES,
+ .name = "power_samples",
+ }, {
+ .reg = PMBUS_VIRT_TEMP_SAMPLES,
+ .name = "temp_samples",
+ }
+};
+
+#define to_samples_reg(x) container_of(x, struct pmbus_samples_reg, dev_attr)
+
+static ssize_t pmbus_show_samples(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ int val;
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct pmbus_samples_reg *reg = to_samples_reg(devattr);
+
+ val = _pmbus_read_word_data(client, reg->page, reg->attr->reg);
+ if (val < 0)
+ return val;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t pmbus_set_samples(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ int ret;
+ long val;
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct pmbus_samples_reg *reg = to_samples_reg(devattr);
+ struct pmbus_data *data = i2c_get_clientdata(client);
+
+ if (kstrtol(buf, 0, &val) < 0)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ ret = _pmbus_write_word_data(client, reg->page, reg->attr->reg, val);
+ mutex_unlock(&data->update_lock);
+
+ return ret ? : count;
+}
+
+static int pmbus_add_samples_attr(struct pmbus_data *data, int page,
+ struct pmbus_samples_attr *attr)
+{
+ struct pmbus_samples_reg *reg;
+
+ reg = devm_kzalloc(data->dev, sizeof(*reg), GFP_KERNEL);
+ if (!reg)
+ return -ENOMEM;
+
+ reg->attr = attr;
+ reg->page = page;
+
+ pmbus_dev_attr_init(&reg->dev_attr, attr->name, 0644,
+ pmbus_show_samples, pmbus_set_samples);
+
+ return pmbus_add_attribute(data, &reg->dev_attr.attr);
+}
+
+static int pmbus_add_samples_attributes(struct i2c_client *client,
+ struct pmbus_data *data)
+{
+ const struct pmbus_driver_info *info = data->info;
+ int s;
+
+ if (!(info->func[0] & PMBUS_HAVE_SAMPLES))
+ return 0;
+
+ for (s = 0; s < ARRAY_SIZE(pmbus_samples_registers); s++) {
+ struct pmbus_samples_attr *attr;
+ int ret;
+
+ attr = &pmbus_samples_registers[s];
+ if (!pmbus_check_word_register(client, 0, attr->reg))
+ continue;
+
+ ret = pmbus_add_samples_attr(data, 0, attr);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static int pmbus_find_attributes(struct i2c_client *client,
struct pmbus_data *data)
{
@@ -1932,6 +2054,10 @@ static int pmbus_find_attributes(struct i2c_client *client,
/* Fans */
ret = pmbus_add_fan_attributes(client, data);
+ if (ret)
+ return ret;
+
+ ret = pmbus_add_samples_attributes(client, data);
return ret;
}
@@ -2305,6 +2431,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
struct device *dev = &client->dev;
const struct pmbus_platform_data *pdata = dev_get_platdata(dev);
struct pmbus_data *data;
+ size_t groups_num = 0;
int ret;
if (!info)
@@ -2319,6 +2446,15 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
if (!data)
return -ENOMEM;
+ if (info->groups)
+ while (info->groups[groups_num])
+ groups_num++;
+
+ data->groups = devm_kcalloc(dev, groups_num + 2, sizeof(void *),
+ GFP_KERNEL);
+ if (!data->groups)
+ return -ENOMEM;
+
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
data->dev = dev;
@@ -2346,6 +2482,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
}
data->groups[0] = &data->group;
+ memcpy(data->groups + 1, info->groups, sizeof(void *) * groups_num);
data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
data, data->groups);
if (IS_ERR(data->hwmon_dev)) {
diff --git a/drivers/hwmon/pmbus/pxe1610.c b/drivers/hwmon/pmbus/pxe1610.c
new file mode 100644
index 000000000000..ebe3f023f840
--- /dev/null
+++ b/drivers/hwmon/pmbus/pxe1610.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Hardware monitoring driver for Infineon PXE1610
+ *
+ * Copyright (c) 2019 Facebook Inc
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include "pmbus.h"
+
+#define PXE1610_NUM_PAGES 3
+
+/* Identify chip parameters. */
+static int pxe1610_identify(struct i2c_client *client,
+ struct pmbus_driver_info *info)
+{
+ if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) {
+ u8 vout_mode;
+ int ret;
+
+ /* Read the register with VOUT scaling value.*/
+ ret = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
+ if (ret < 0)
+ return ret;
+
+ vout_mode = ret & GENMASK(4, 0);
+
+ switch (vout_mode) {
+ case 1:
+ info->vrm_version = vr12;
+ break;
+ case 2:
+ info->vrm_version = vr13;
+ break;
+ default:
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static struct pmbus_driver_info pxe1610_info = {
+ .pages = PXE1610_NUM_PAGES,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = vid,
+ .format[PSC_CURRENT_IN] = linear,
+ .format[PSC_CURRENT_OUT] = linear,
+ .format[PSC_TEMPERATURE] = linear,
+ .format[PSC_POWER] = linear,
+ .func[0] = PMBUS_HAVE_VIN
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN
+ | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
+ | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
+ .func[1] = PMBUS_HAVE_VIN
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN
+ | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
+ | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
+ .func[2] = PMBUS_HAVE_VIN
+ | PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN
+ | PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN
+ | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
+ | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
+ | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
+ .identify = pxe1610_identify,
+};
+
+static int pxe1610_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pmbus_driver_info *info;
+ u8 buf[I2C_SMBUS_BLOCK_MAX];
+ int ret;
+
+ if (!i2c_check_functionality(
+ client->adapter,
+ I2C_FUNC_SMBUS_READ_BYTE_DATA
+ | I2C_FUNC_SMBUS_READ_WORD_DATA
+ | I2C_FUNC_SMBUS_READ_BLOCK_DATA))
+ return -ENODEV;
+
+ /*
+ * By default this device doesn't boot to page 0, so set page 0
+ * to access all pmbus registers.
+ */
+ i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
+
+ /* Read Manufacturer id */
+ ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to read PMBUS_MFR_ID\n");
+ return ret;
+ }
+ if (ret != 2 || strncmp(buf, "XP", 2)) {
+ dev_err(&client->dev, "MFR_ID unrecognized\n");
+ return -ENODEV;
+ }
+
+ info = devm_kmemdup(&client->dev, &pxe1610_info,
+ sizeof(struct pmbus_driver_info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ return pmbus_do_probe(client, id, info);
+}
+
+static const struct i2c_device_id pxe1610_id[] = {
+ {"pxe1610", 0},
+ {"pxe1110", 0},
+ {"pxm1310", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, pxe1610_id);
+
+static struct i2c_driver pxe1610_driver = {
+ .driver = {
+ .name = "pxe1610",
+ },
+ .probe = pxe1610_probe,
+ .remove = pmbus_do_remove,
+ .id_table = pxe1610_id,
+};
+
+module_i2c_driver(pxe1610_driver);
+
+MODULE_AUTHOR("Vijay Khemka <vijaykhemka@fb.com>");
+MODULE_DESCRIPTION("PMBus driver for Infineon PXE1610, PXE1110 and PXM1310");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pmbus/tps40422.c b/drivers/hwmon/pmbus/tps40422.c
index 32803825d47e..2b83dcda964a 100644
--- a/drivers/hwmon/pmbus/tps40422.c
+++ b/drivers/hwmon/pmbus/tps40422.c
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for TI TPS40422
*
* Copyright (c) 2014 Nokia Solutions and Networks.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/kernel.h>
diff --git a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c
index 2bc352c5357f..86bb3aca09ed 100644
--- a/drivers/hwmon/pmbus/tps53679.c
+++ b/drivers/hwmon/pmbus/tps53679.c
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for Texas Instruments TPS53679
*
* Copyright (c) 2017 Mellanox Technologies. All rights reserved.
* Copyright (c) 2017 Vadim Pasternak <vadimp@mellanox.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/err.h>
@@ -97,7 +88,7 @@ static const struct i2c_device_id tps53679_id[] = {
MODULE_DEVICE_TABLE(i2c, tps53679_id);
-static const struct of_device_id tps53679_of_match[] = {
+static const struct of_device_id __maybe_unused tps53679_of_match[] = {
{.compatible = "ti,tps53679"},
{}
};
diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c
index ae93885fccd8..c846759bc1c0 100644
--- a/drivers/hwmon/pmbus/ucd9000.c
+++ b/drivers/hwmon/pmbus/ucd9000.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for UCD90xxx Sequencer and System Health
* Controller series
*
* Copyright (C) 2011 Ericsson AB.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/debugfs.h>
@@ -151,7 +138,7 @@ static const struct i2c_device_id ucd9000_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ucd9000_id);
-static const struct of_device_id ucd9000_of_match[] = {
+static const struct of_device_id __maybe_unused ucd9000_of_match[] = {
{
.compatible = "ti,ucd9000",
.data = (void *)ucd9000
diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c
index 3ed94585837a..7c04745a9709 100644
--- a/drivers/hwmon/pmbus/ucd9200.c
+++ b/drivers/hwmon/pmbus/ucd9200.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for ucd9200 series Digital PWM System Controllers
*
* Copyright (C) 2011 Ericsson AB.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
@@ -47,7 +34,7 @@ static const struct i2c_device_id ucd9200_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ucd9200_id);
-static const struct of_device_id ucd9200_of_match[] = {
+static const struct of_device_id __maybe_unused ucd9200_of_match[] = {
{
.compatible = "ti,cd9200",
.data = (void *)ucd9200
diff --git a/drivers/hwmon/pmbus/zl6100.c b/drivers/hwmon/pmbus/zl6100.c
index 771802d7e20d..190b898e404a 100644
--- a/drivers/hwmon/pmbus/zl6100.c
+++ b/drivers/hwmon/pmbus/zl6100.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Hardware monitoring driver for ZL6100 and compatibles
*
* Copyright (c) 2011 Ericsson AB.
* Copyright (c) 2012 Guenter Roeck
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/bitops.h>