summaryrefslogtreecommitdiff
path: root/drivers/hwmon
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/Kconfig24
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/ad7418.c4
-rw-r--r--drivers/hwmon/ads7828.c5
-rw-r--r--drivers/hwmon/adt7475.c3
-rw-r--r--drivers/hwmon/aquacomputer_d5next.c39
-rw-r--r--drivers/hwmon/as370-hwmon.c3
-rw-r--r--drivers/hwmon/aspeed-pwm-tacho.c3
-rw-r--r--drivers/hwmon/asus-ec-sensors.c2
-rw-r--r--drivers/hwmon/bt1-pvt.c9
-rw-r--r--drivers/hwmon/g762.c1
-rw-r--r--drivers/hwmon/gxp-fan-ctrl.c2
-rw-r--r--drivers/hwmon/hp-wmi-sensors.c22
-rw-r--r--drivers/hwmon/hs3001.c242
-rw-r--r--drivers/hwmon/ina2xx.c3
-rw-r--r--drivers/hwmon/it87.c74
-rw-r--r--drivers/hwmon/k10temp.c25
-rw-r--r--drivers/hwmon/lan966x-hwmon.c24
-rw-r--r--drivers/hwmon/lm63.c4
-rw-r--r--drivers/hwmon/lm75.c3
-rw-r--r--drivers/hwmon/lm85.c4
-rw-r--r--drivers/hwmon/lm90.c4
-rw-r--r--drivers/hwmon/lochnagar-hwmon.c1
-rw-r--r--drivers/hwmon/ltq-cputemp.c3
-rw-r--r--drivers/hwmon/max31730.c1
-rw-r--r--drivers/hwmon/max6621.c2
-rw-r--r--drivers/hwmon/max6639.c6
-rw-r--r--drivers/hwmon/max6697.c3
-rw-r--r--drivers/hwmon/mcp3021.c1
-rw-r--r--drivers/hwmon/mlxreg-fan.c12
-rw-r--r--drivers/hwmon/nct6775-core.c375
-rw-r--r--drivers/hwmon/nct6775-platform.c4
-rw-r--r--drivers/hwmon/nct6775.h31
-rw-r--r--drivers/hwmon/nct7802.c2
-rw-r--r--drivers/hwmon/nsa320-hwmon.c4
-rw-r--r--drivers/hwmon/oxp-sensors.c67
-rw-r--r--drivers/hwmon/peci/dimmtemp.c26
-rw-r--r--drivers/hwmon/pmbus/Kconfig7
-rw-r--r--drivers/hwmon/pmbus/acbel-fsg032.c38
-rw-r--r--drivers/hwmon/pmbus/bel-pfe.c16
-rw-r--r--drivers/hwmon/pmbus/dps920ab.c2
-rw-r--r--drivers/hwmon/pmbus/ibm-cffps.c4
-rw-r--r--drivers/hwmon/pmbus/ir38064.c4
-rw-r--r--drivers/hwmon/pmbus/max20730.c68
-rw-r--r--drivers/hwmon/pmbus/mp2975.c429
-rw-r--r--drivers/hwmon/pmbus/mp5023.c2
-rw-r--r--drivers/hwmon/pmbus/mpq7932.c2
-rw-r--r--drivers/hwmon/pmbus/pli1209bc.c26
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c24
-rw-r--r--drivers/hwmon/pmbus/q54sj108a2.c2
-rw-r--r--drivers/hwmon/pmbus/tps53679.c4
-rw-r--r--drivers/hwmon/pmbus/ucd9000.c4
-rw-r--r--drivers/hwmon/pmbus/ucd9200.c4
-rw-r--r--drivers/hwmon/sbtsi_temp.c1
-rw-r--r--drivers/hwmon/scpi-hwmon.c2
-rw-r--r--drivers/hwmon/sht3x.c387
-rw-r--r--drivers/hwmon/sis5595.c35
-rw-r--r--drivers/hwmon/smm665.c706
-rw-r--r--drivers/hwmon/tmp421.c2
-rw-r--r--drivers/hwmon/tmp464.c2
-rw-r--r--drivers/hwmon/tmp513.c7
-rw-r--r--drivers/hwmon/tps23861.c2
-rw-r--r--drivers/hwmon/ultra45_env.c3
-rw-r--r--drivers/hwmon/vexpress-hwmon.c1
-rw-r--r--drivers/hwmon/via686a.c18
-rw-r--r--drivers/hwmon/vt8231.c11
-rw-r--r--drivers/hwmon/w83773g.c2
67 files changed, 1514 insertions, 1341 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 307477b8a371..ec38c8892158 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -734,6 +734,16 @@ config SENSORS_HIH6130
This driver can also be built as a module. If so, the module
will be called hih6130.
+config SENSORS_HS3001
+ tristate "Renesas HS3001 humidity and temperature sensors"
+ depends on I2C
+ help
+ If you say yes here you get support for the Renesas HS3001,
+ to HS3004 humidity and temperature sensors.
+
+ This driver can also be built as a module. If so, the module
+ will be called hs3001.
+
config SENSORS_IBMAEM
tristate "IBM Active Energy Manager temperature/power sensors and control"
select IPMI_SI
@@ -1951,20 +1961,6 @@ config SENSORS_SFCTEMP
This driver can also be built as a module. If so, the module
will be called sfctemp.
-config SENSORS_SMM665
- tristate "Summit Microelectronics SMM665"
- depends on I2C
- help
- If you say yes here you get support for the hardware monitoring
- features of the Summit Microelectronics SMM665/SMM665B Six-Channel
- Active DC Output Controller / Monitor.
-
- Other supported chips are SMM465, SMM665C, SMM764, and SMM766.
- Support for those chips is untested.
-
- This driver can also be built as a module. If so, the module will
- be called smm665.
-
config SENSORS_ADC128D818
tristate "Texas Instruments ADC128D818"
depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 3f4b0fda0998..4ac9452b5430 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -86,6 +86,7 @@ obj-$(CONFIG_SENSORS_GSC) += gsc-hwmon.o
obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o
obj-$(CONFIG_SENSORS_GXP_FAN_CTRL) += gxp-fan-ctrl.o
obj-$(CONFIG_SENSORS_HIH6130) += hih6130.o
+obj-$(CONFIG_SENSORS_HS3001) += hs3001.o
obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
obj-$(CONFIG_SENSORS_I5500) += i5500_temp.o
obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
@@ -191,7 +192,6 @@ obj-$(CONFIG_SENSORS_SHT3x) += sht3x.o
obj-$(CONFIG_SENSORS_SHT4x) += sht4x.o
obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o
obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
-obj-$(CONFIG_SENSORS_SMM665) += smm665.o
obj-$(CONFIG_SENSORS_SMPRO) += smpro-hwmon.o
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c
index ffe81e445010..4829f83ff52e 100644
--- a/drivers/hwmon/ad7418.c
+++ b/drivers/hwmon/ad7418.c
@@ -16,7 +16,7 @@
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/delay.h>
#include <linux/slab.h>
@@ -253,7 +253,7 @@ static int ad7418_probe(struct i2c_client *client)
mutex_init(&data->lock);
data->client = client;
if (dev->of_node)
- data->type = (enum chips)of_device_get_match_data(dev);
+ data->type = (uintptr_t)of_device_get_match_data(dev);
else
data->type = i2c_match_id(ad7418_id, client)->driver_data;
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
index 1932613ec095..809e830f52a6 100644
--- a/drivers/hwmon/ads7828.c
+++ b/drivers/hwmon/ads7828.c
@@ -18,7 +18,7 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/platform_data/ads7828.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@@ -139,8 +139,7 @@ static int ads7828_probe(struct i2c_client *client)
}
if (client->dev.of_node)
- chip = (enum ads7828_chips)
- of_device_get_match_data(&client->dev);
+ chip = (uintptr_t)of_device_get_match_data(&client->dev);
else
chip = i2c_match_id(ads7828_device_ids, client)->driver_data;
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index c0ce88324ea6..03acadc3a6cb 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -10,7 +10,6 @@
*/
#include <linux/module.h>
-#include <linux/of_device.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
@@ -1653,7 +1652,7 @@ static int adt7475_probe(struct i2c_client *client)
i2c_set_clientdata(client, data);
if (client->dev.of_node)
- chip = (enum chips)of_device_get_match_data(&client->dev);
+ chip = (uintptr_t)of_device_get_match_data(&client->dev);
else
chip = id->driver_data;
diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
index a981f7086114..023807859be7 100644
--- a/drivers/hwmon/aquacomputer_d5next.c
+++ b/drivers/hwmon/aquacomputer_d5next.c
@@ -13,9 +13,11 @@
#include <linux/crc16.h>
#include <linux/debugfs.h>
+#include <linux/delay.h>
#include <linux/hid.h>
#include <linux/hwmon.h>
#include <linux/jiffies.h>
+#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/seq_file.h>
@@ -63,6 +65,8 @@ static const char *const aqc_device_names[] = {
#define CTRL_REPORT_ID 0x03
#define AQUAERO_CTRL_REPORT_ID 0x0b
+#define CTRL_REPORT_DELAY 200 /* ms */
+
/* The HID report that the official software always sends
* after writing values, currently same for all devices
*/
@@ -527,6 +531,9 @@ struct aqc_data {
int secondary_ctrl_report_size;
u8 *secondary_ctrl_report;
+ ktime_t last_ctrl_report_op;
+ int ctrl_report_delay; /* Delay between two ctrl report operations, in ms */
+
int buffer_size;
u8 *buffer;
int checksum_start;
@@ -611,17 +618,35 @@ static int aqc_aquastreamxt_convert_fan_rpm(u16 val)
return 0;
}
+static void aqc_delay_ctrl_report(struct aqc_data *priv)
+{
+ /*
+ * If previous read or write is too close to this one, delay the current operation
+ * to give the device enough time to process the previous one.
+ */
+ if (priv->ctrl_report_delay) {
+ s64 delta = ktime_ms_delta(ktime_get(), priv->last_ctrl_report_op);
+
+ if (delta < priv->ctrl_report_delay)
+ msleep(priv->ctrl_report_delay - delta);
+ }
+}
+
/* Expects the mutex to be locked */
static int aqc_get_ctrl_data(struct aqc_data *priv)
{
int ret;
+ aqc_delay_ctrl_report(priv);
+
memset(priv->buffer, 0x00, priv->buffer_size);
ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
if (ret < 0)
ret = -ENODATA;
+ priv->last_ctrl_report_op = ktime_get();
+
return ret;
}
@@ -631,6 +656,8 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
int ret;
u16 checksum;
+ aqc_delay_ctrl_report(priv);
+
/* Checksum is not needed for Aquaero */
if (priv->kind != aquaero) {
/* Init and xorout value for CRC-16/USB is 0xffff */
@@ -646,12 +673,16 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
if (ret < 0)
- return ret;
+ goto record_access_and_ret;
/* The official software sends this report after every change, so do it here as well */
ret = hid_hw_raw_request(priv->hdev, priv->secondary_ctrl_report_id,
priv->secondary_ctrl_report, priv->secondary_ctrl_report_size,
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+
+record_access_and_ret:
+ priv->last_ctrl_report_op = ktime_get();
+
return ret;
}
@@ -1027,7 +1058,7 @@ static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
if (ret < 0)
return ret;
- *val = aqc_percent_to_pwm(ret);
+ *val = aqc_percent_to_pwm(*val);
break;
}
break;
@@ -1524,6 +1555,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->buffer_size = AQUAERO_CTRL_REPORT_SIZE;
priv->temp_ctrl_offset = AQUAERO_TEMP_CTRL_OFFSET;
+ priv->ctrl_report_delay = CTRL_REPORT_DELAY;
priv->temp_label = label_temp_sensors;
priv->virtual_temp_label = label_virtual_temp_sensors;
@@ -1547,6 +1579,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET;
priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE;
+ priv->ctrl_report_delay = CTRL_REPORT_DELAY;
priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
@@ -1597,6 +1630,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET;
priv->buffer_size = OCTO_CTRL_REPORT_SIZE;
+ priv->ctrl_report_delay = CTRL_REPORT_DELAY;
priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
@@ -1624,6 +1658,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET;
priv->buffer_size = QUADRO_CTRL_REPORT_SIZE;
+ priv->ctrl_report_delay = CTRL_REPORT_DELAY;
priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET;
priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
diff --git a/drivers/hwmon/as370-hwmon.c b/drivers/hwmon/as370-hwmon.c
index fffbf385a57f..316454bd983d 100644
--- a/drivers/hwmon/as370-hwmon.c
+++ b/drivers/hwmon/as370-hwmon.c
@@ -11,7 +11,8 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
#define CTRL 0x0
#define PD BIT(0)
diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c
index d11f674e3dc3..997df4b40509 100644
--- a/drivers/hwmon/aspeed-pwm-tacho.c
+++ b/drivers/hwmon/aspeed-pwm-tacho.c
@@ -12,8 +12,7 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c
index f52a539eb33e..51f9c2db403e 100644
--- a/drivers/hwmon/asus-ec-sensors.c
+++ b/drivers/hwmon/asus-ec-sensors.c
@@ -340,7 +340,7 @@ static const struct ec_board_info board_info_crosshair_x670e_hero = {
.sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE |
SENSOR_TEMP_MB | SENSOR_TEMP_VRM |
SENSOR_SET_TEMP_WATER,
- .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX,
+ .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH,
.family = family_amd_600_series,
};
diff --git a/drivers/hwmon/bt1-pvt.c b/drivers/hwmon/bt1-pvt.c
index 8d402a627306..b77ebac2e0ce 100644
--- a/drivers/hwmon/bt1-pvt.c
+++ b/drivers/hwmon/bt1-pvt.c
@@ -891,15 +891,8 @@ static struct pvt_hwmon *pvt_create_data(struct platform_device *pdev)
static int pvt_request_regs(struct pvt_hwmon *pvt)
{
struct platform_device *pdev = to_platform_device(pvt->dev);
- struct resource *res;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(pvt->dev, "Couldn't find PVT memresource\n");
- return -EINVAL;
- }
-
- pvt->regs = devm_ioremap_resource(pvt->dev, res);
+ pvt->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pvt->regs))
return PTR_ERR(pvt->regs);
diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
index 1b6ff4712138..fad69ef56c75 100644
--- a/drivers/hwmon/g762.c
+++ b/drivers/hwmon/g762.c
@@ -39,7 +39,6 @@
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/platform_data/g762.h>
#define DRVNAME "g762"
diff --git a/drivers/hwmon/gxp-fan-ctrl.c b/drivers/hwmon/gxp-fan-ctrl.c
index 2e05bc2f627a..00e057050437 100644
--- a/drivers/hwmon/gxp-fan-ctrl.c
+++ b/drivers/hwmon/gxp-fan-ctrl.c
@@ -6,7 +6,7 @@
#include <linux/hwmon.h>
#include <linux/io.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#define OFS_FAN_INST 0 /* Is 0 because plreg base will be set at INST */
diff --git a/drivers/hwmon/hp-wmi-sensors.c b/drivers/hwmon/hp-wmi-sensors.c
index ebe2fb513480..17ae62f88bbf 100644
--- a/drivers/hwmon/hp-wmi-sensors.c
+++ b/drivers/hwmon/hp-wmi-sensors.c
@@ -435,25 +435,11 @@ static union acpi_object *hp_wmi_get_wobj(const char *guid, u8 instance)
/* hp_wmi_wobj_instance_count - find count of WMI object instances */
static u8 hp_wmi_wobj_instance_count(const char *guid)
{
- u8 hi = HP_WMI_MAX_INSTANCES;
- union acpi_object *wobj;
- u8 lo = 0;
- u8 mid;
-
- while (lo < hi) {
- mid = (lo + hi) / 2;
+ int count;
- wobj = hp_wmi_get_wobj(guid, mid);
- if (!wobj) {
- hi = mid;
- continue;
- }
+ count = wmi_instance_count(guid);
- lo = mid + 1;
- kfree(wobj);
- }
-
- return lo;
+ return clamp(count, 0, (int)HP_WMI_MAX_INSTANCES);
}
static int check_wobj(const union acpi_object *wobj,
@@ -1927,7 +1913,7 @@ static bool add_event_handler(struct hp_wmi_sensors *state)
static int hp_wmi_sensors_init(struct hp_wmi_sensors *state)
{
struct hp_wmi_info *connected[HP_WMI_MAX_INSTANCES];
- struct hp_wmi_platform_events *pevents;
+ struct hp_wmi_platform_events *pevents = NULL;
struct device *dev = &state->wdev->dev;
struct hp_wmi_info *info;
struct device *hwdev;
diff --git a/drivers/hwmon/hs3001.c b/drivers/hwmon/hs3001.c
new file mode 100644
index 000000000000..ac574e46d069
--- /dev/null
+++ b/drivers/hwmon/hs3001.c
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * This is a non-complete driver implementation for the
+ * HS3001 humidity and temperature sensor and compatibles. It does not include
+ * the configuration possibilities, where it needs to be set to 'programming mode'
+ * during power-up.
+ *
+ *
+ * Copyright (C) 2023 SYS TEC electronic AG
+ * Author: Andre Werner <andre.werner@systec-electronic.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/* Measurement times */
+#define HS3001_WAKEUP_TIME 100 /* us */
+#define HS3001_8BIT_RESOLUTION 550 /* us */
+#define HS3001_10BIT_RESOLUTION 1310 /* us */
+#define HS3001_12BIT_RESOLUTION 4500 /* us */
+#define HS3001_14BIT_RESOLUTION 16900 /* us */
+
+#define HS3001_RESPONSE_LENGTH 4
+
+#define HS3001_FIXPOINT_ARITH 1000U
+
+#define HS3001_MASK_HUMIDITY_0X3FFF GENMASK(13, 0)
+#define HS3001_MASK_STATUS_0XC0 GENMASK(7, 6)
+
+/* Definitions for Status Bits of A/D Data */
+#define HS3001_DATA_VALID 0x00 /* Valid Data */
+#define HS3001_DATA_STALE 0x01 /* Stale Data */
+
+struct hs3001_data {
+ struct i2c_client *client;
+ struct mutex i2c_lock; /* lock for sending i2c commands */
+ u32 wait_time; /* in us */
+ int temperature; /* in milli degree */
+ u32 humidity; /* in milli % */
+};
+
+static int hs3001_extract_temperature(u16 raw)
+{
+ /* fixpoint arithmetic 1 digit */
+ u32 temp = (raw >> 2) * HS3001_FIXPOINT_ARITH * 165;
+
+ temp /= (1 << 14) - 1;
+
+ return (int)temp - 40 * HS3001_FIXPOINT_ARITH;
+}
+
+static u32 hs3001_extract_humidity(u16 raw)
+{
+ u32 hum = (raw & HS3001_MASK_HUMIDITY_0X3FFF) * HS3001_FIXPOINT_ARITH * 100;
+
+ return hum /= (1 << 14) - 1;
+}
+
+static int hs3001_data_fetch_command(struct i2c_client *client,
+ struct hs3001_data *data)
+{
+ int ret;
+ u8 buf[HS3001_RESPONSE_LENGTH];
+ u8 hs3001_status;
+
+ ret = i2c_master_recv(client, buf, HS3001_RESPONSE_LENGTH);
+ if (ret != HS3001_RESPONSE_LENGTH) {
+ ret = ret < 0 ? ret : -EIO;
+ dev_dbg(&client->dev,
+ "Error in i2c communication. Error code: %d.\n", ret);
+ return ret;
+ }
+
+ hs3001_status = FIELD_GET(HS3001_MASK_STATUS_0XC0, buf[0]);
+ if (hs3001_status == HS3001_DATA_STALE) {
+ dev_dbg(&client->dev, "Sensor busy.\n");
+ return -EBUSY;
+ }
+ if (hs3001_status != HS3001_DATA_VALID) {
+ dev_dbg(&client->dev, "Data invalid.\n");
+ return -EIO;
+ }
+
+ data->humidity =
+ hs3001_extract_humidity(be16_to_cpup((__be16 *)&buf[0]));
+ data->temperature =
+ hs3001_extract_temperature(be16_to_cpup((__be16 *)&buf[2]));
+
+ return 0;
+}
+
+static umode_t hs3001_is_visible(const void *data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ /* Both, humidity and temperature can only be read. */
+ return 0444;
+}
+
+static int hs3001_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct hs3001_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int ret;
+
+ mutex_lock(&data->i2c_lock);
+ ret = i2c_master_send(client, NULL, 0);
+ if (ret < 0) {
+ mutex_unlock(&data->i2c_lock);
+ return ret;
+ }
+
+ /*
+ * Sensor needs some time to process measurement depending on
+ * resolution (ref. datasheet)
+ */
+ fsleep(data->wait_time);
+
+ ret = hs3001_data_fetch_command(client, data);
+ mutex_unlock(&data->i2c_lock);
+
+ if (ret < 0)
+ return ret;
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ *val = data->temperature;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ case hwmon_humidity:
+ switch (attr) {
+ case hwmon_humidity_input:
+ *val = data->humidity;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct hwmon_channel_info *hs3001_info[] = {
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
+ HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT),
+ NULL
+};
+
+static const struct hwmon_ops hs3001_hwmon_ops = {
+ .is_visible = hs3001_is_visible,
+ .read = hs3001_read,
+};
+
+static const struct hwmon_chip_info hs3001_chip_info = {
+ .ops = &hs3001_hwmon_ops,
+ .info = hs3001_info,
+};
+
+/* device ID table */
+static const struct i2c_device_id hs3001_ids[] = {
+ { "hs3001", 0 },
+ { },
+};
+
+MODULE_DEVICE_TABLE(i2c, hs3001_ids);
+
+static const struct of_device_id hs3001_of_match[] = {
+ {.compatible = "renesas,hs3001"},
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, hs3001_of_match);
+
+static int hs3001_probe(struct i2c_client *client)
+{
+ struct hs3001_data *data;
+ struct device *hwmon_dev;
+ struct device *dev = &client->dev;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -EOPNOTSUPP;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->client = client;
+
+ /*
+ * Measurement time = wake-up time + measurement time temperature
+ * + measurement time humidity. This is currently static, because
+ * enabling programming mode is not supported, yet.
+ */
+ data->wait_time = (HS3001_WAKEUP_TIME + HS3001_14BIT_RESOLUTION +
+ HS3001_14BIT_RESOLUTION);
+
+ mutex_init(&data->i2c_lock);
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev,
+ client->name,
+ data,
+ &hs3001_chip_info,
+ NULL);
+
+ if (IS_ERR(hwmon_dev))
+ return dev_err_probe(dev, PTR_ERR(hwmon_dev),
+ "Unable to register hwmon device.\n");
+
+ return 0;
+}
+
+static struct i2c_driver hs3001_i2c_driver = {
+ .driver = {
+ .name = "hs3001",
+ .of_match_table = hs3001_of_match,
+ },
+ .probe = hs3001_probe,
+ .id_table = hs3001_ids,
+};
+
+module_i2c_driver(hs3001_i2c_driver);
+
+MODULE_AUTHOR("Andre Werner <andre.werner@systec-electronic.com>");
+MODULE_DESCRIPTION("HS3001 humidity and temperature sensor base driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index cfd7efef5cdf..d8415d1f21fc 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -31,7 +31,6 @@
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/jiffies.h>
-#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/delay.h>
#include <linux/util_macros.h>
@@ -625,7 +624,7 @@ static int ina2xx_probe(struct i2c_client *client)
enum ina2xx_ids chip;
if (client->dev.of_node)
- chip = (enum ina2xx_ids)of_device_get_match_data(&client->dev);
+ chip = (uintptr_t)of_device_get_match_data(&client->dev);
else
chip = i2c_match_id(ina2xx_id, client)->driver_data;
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 5deff5e5f693..fbe86cec6055 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -221,6 +221,10 @@ static bool fix_pwm_polarity;
* Super-I/O configuration space.
*/
#define IT87_REG_VID 0x0a
+
+/* Interface Selection register on other chips */
+#define IT87_REG_IFSEL 0x0a
+
/*
* The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b
* for fan divisors. Later IT8712F revisions must use 16-bit tachometer
@@ -1159,28 +1163,66 @@ static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0);
static SENSOR_DEVICE_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0);
static SENSOR_DEVICE_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0);
+static int get_temp_type(struct it87_data *data, int index)
+{
+ /*
+ * 2 is deprecated;
+ * 3 = thermal diode;
+ * 4 = thermistor;
+ * 5 = AMDTSI;
+ * 6 = Intel PECI;
+ * 0 = disabled
+ */
+ u8 reg, extra;
+ int ttype, type = 0;
+
+ /* Detect PECI vs. AMDTSI */
+ ttype = 6;
+ if ((has_temp_peci(data, index)) || data->type == it8721 ||
+ data->type == it8720) {
+ extra = it87_read_value(data, IT87_REG_IFSEL);
+ if ((extra & 0x70) == 0x40)
+ ttype = 5;
+ }
+
+ reg = it87_read_value(data, IT87_REG_TEMP_ENABLE);
+
+ /* Per chip special detection */
+ switch (data->type) {
+ case it8622:
+ if (!(reg & 0xc0) && index == 3)
+ type = ttype;
+ break;
+ default:
+ break;
+ }
+
+ if (type || index >= 3)
+ return type;
+
+ extra = it87_read_value(data, IT87_REG_TEMP_EXTRA);
+
+ if ((has_temp_peci(data, index) && (reg >> 6 == index + 1)) ||
+ (has_temp_old_peci(data, index) && (extra & 0x80)))
+ type = ttype; /* Intel PECI or AMDTSI */
+ else if (reg & BIT(index))
+ type = 3; /* thermal diode */
+ else if (reg & BIT(index + 3))
+ type = 4; /* thermistor */
+
+ return type;
+}
+
static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
- int nr = sensor_attr->index;
struct it87_data *data = it87_update_device(dev);
- u8 reg, extra;
if (IS_ERR(data))
return PTR_ERR(data);
- reg = data->sensor; /* In case value is updated while used */
- extra = data->extra;
-
- if ((has_temp_peci(data, nr) && (reg >> 6 == nr + 1)) ||
- (has_temp_old_peci(data, nr) && (extra & 0x80)))
- return sprintf(buf, "6\n"); /* Intel PECI */
- if (reg & (1 << nr))
- return sprintf(buf, "3\n"); /* thermal diode */
- if (reg & (8 << nr))
- return sprintf(buf, "4\n"); /* thermistor */
- return sprintf(buf, "0\n"); /* disabled */
+ return sprintf(buf, "%d\n", get_temp_type(data, sensor_attr->index));
}
static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr,
@@ -2313,6 +2355,12 @@ static umode_t it87_temp_is_visible(struct kobject *kobj,
if (!(data->has_temp & BIT(i)))
return 0;
+ if (a == 3) {
+ if (get_temp_type(data, i) == 0)
+ return 0;
+ return attr->mode;
+ }
+
if (a == 5 && !has_temp_offset(data))
return 0;
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index 7b177b9fbb09..bae0becfa24b 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -65,7 +65,7 @@ static DEFINE_MUTEX(nb_smu_ind_mutex);
#define F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET 0xd8200c64
#define F15H_M60H_REPORTED_TEMP_CTRL_OFFSET 0xd8200ca4
-/* Common for Zen CPU families (Family 17h and 18h and 19h) */
+/* Common for Zen CPU families (Family 17h and 18h and 19h and 1Ah) */
#define ZEN_REPORTED_TEMP_CTRL_BASE 0x00059800
#define ZEN_CCD_TEMP(offset, x) (ZEN_REPORTED_TEMP_CTRL_BASE + \
@@ -77,6 +77,13 @@ static DEFINE_MUTEX(nb_smu_ind_mutex);
#define ZEN_CUR_TEMP_RANGE_SEL_MASK BIT(19)
#define ZEN_CUR_TEMP_TJ_SEL_MASK GENMASK(17, 16)
+/*
+ * AMD's Industrial processor 3255 supports temperature from -40 deg to 105 deg Celsius.
+ * Use the model name to identify 3255 CPUs and set a flag to display negative temperature.
+ * Do not round off to zero for negative Tctl or Tdie values if the flag is set
+ */
+#define AMD_I3255_STR "3255"
+
struct k10temp_data {
struct pci_dev *pdev;
void (*read_htcreg)(struct pci_dev *pdev, u32 *regval);
@@ -86,6 +93,7 @@ struct k10temp_data {
u32 show_temp;
bool is_zen;
u32 ccd_offset;
+ bool disp_negative;
};
#define TCTL_BIT 0
@@ -204,12 +212,12 @@ static int k10temp_read_temp(struct device *dev, u32 attr, int channel,
switch (channel) {
case 0: /* Tctl */
*val = get_raw_temp(data);
- if (*val < 0)
+ if (*val < 0 && !data->disp_negative)
*val = 0;
break;
case 1: /* Tdie */
*val = get_raw_temp(data) - data->temp_offset;
- if (*val < 0)
+ if (*val < 0 && !data->disp_negative)
*val = 0;
break;
case 2 ... 13: /* Tccd{1-12} */
@@ -405,6 +413,11 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
data->pdev = pdev;
data->show_temp |= BIT(TCTL_BIT); /* Always show Tctl */
+ if (boot_cpu_data.x86 == 0x17 &&
+ strstr(boot_cpu_data.x86_model_id, AMD_I3255_STR)) {
+ data->disp_negative = true;
+ }
+
if (boot_cpu_data.x86 == 0x15 &&
((boot_cpu_data.x86_model & 0xf0) == 0x60 ||
(boot_cpu_data.x86_model & 0xf0) == 0x70)) {
@@ -462,6 +475,10 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
k10temp_get_ccd_support(pdev, data, 12);
break;
}
+ } else if (boot_cpu_data.x86 == 0x1a) {
+ data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK;
+ data->read_tempreg = read_tempreg_nb_zen;
+ data->is_zen = true;
} else {
data->read_htcreg = read_htcreg_pci;
data->read_tempreg = read_tempreg_pci;
@@ -508,6 +525,8 @@ static const struct pci_device_id k10temp_id_table[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M60H_DF_F3) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M70H_DF_F3) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M78H_DF_F3) },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_1AH_M00H_DF_F3) },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_1AH_M20H_DF_F3) },
{ PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
{}
};
diff --git a/drivers/hwmon/lan966x-hwmon.c b/drivers/hwmon/lan966x-hwmon.c
index f8658359a098..7247c03e4f44 100644
--- a/drivers/hwmon/lan966x-hwmon.c
+++ b/drivers/hwmon/lan966x-hwmon.c
@@ -334,24 +334,6 @@ static struct regmap *lan966x_init_regmap(struct platform_device *pdev,
return devm_regmap_init_mmio(&pdev->dev, base, &regmap_config);
}
-static void lan966x_clk_disable(void *data)
-{
- struct lan966x_hwmon *hwmon = data;
-
- clk_disable_unprepare(hwmon->clk);
-}
-
-static int lan966x_clk_enable(struct device *dev, struct lan966x_hwmon *hwmon)
-{
- int ret;
-
- ret = clk_prepare_enable(hwmon->clk);
- if (ret)
- return ret;
-
- return devm_add_action_or_reset(dev, lan966x_clk_disable, hwmon);
-}
-
static int lan966x_hwmon_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -363,15 +345,11 @@ static int lan966x_hwmon_probe(struct platform_device *pdev)
if (!hwmon)
return -ENOMEM;
- hwmon->clk = devm_clk_get(dev, NULL);
+ hwmon->clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(hwmon->clk))
return dev_err_probe(dev, PTR_ERR(hwmon->clk),
"failed to get clock\n");
- ret = lan966x_clk_enable(dev, hwmon);
- if (ret)
- return dev_err_probe(dev, ret, "failed to enable clock\n");
-
hwmon->clk_rate = clk_get_rate(hwmon->clk);
hwmon->regmap_pvt = lan966x_init_regmap(pdev, "pvt");
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 6972454eb4e0..0878a044dd8e 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -33,7 +33,7 @@
#include <linux/hwmon.h>
#include <linux/err.h>
#include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/sysfs.h>
#include <linux/types.h>
@@ -1105,7 +1105,7 @@ static int lm63_probe(struct i2c_client *client)
/* Set the device type */
if (client->dev.of_node)
- data->kind = (enum chips)of_device_get_match_data(&client->dev);
+ data->kind = (uintptr_t)of_device_get_match_data(&client->dev);
else
data->kind = i2c_match_id(lm63_id, client)->driver_data;
if (data->kind == lm64)
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 72e634d1b857..5b2ea05c951e 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -13,7 +13,6 @@
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
-#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/util_macros.h>
@@ -579,7 +578,7 @@ static int lm75_probe(struct i2c_client *client)
enum lm75_type kind;
if (client->dev.of_node)
- kind = (enum lm75_type)of_device_get_match_data(&client->dev);
+ kind = (uintptr_t)of_device_get_match_data(&client->dev);
else
kind = i2c_match_id(lm75_ids, client)->driver_data;
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index 8540178f5b74..68c210002357 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -12,7 +12,7 @@
*/
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
@@ -1559,7 +1559,7 @@ static int lm85_probe(struct i2c_client *client)
data->client = client;
if (client->dev.of_node)
- data->type = (enum chips)of_device_get_match_data(&client->dev);
+ data->type = (uintptr_t)of_device_get_match_data(&client->dev);
else
data->type = i2c_match_id(lm85_id, client)->driver_data;
mutex_init(&data->update_lock);
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 90101c236f35..e0d7454a301c 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -106,7 +106,7 @@
#include <linux/kstrtox.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
@@ -2765,7 +2765,7 @@ static int lm90_probe(struct i2c_client *client)
/* Set the device type */
if (client->dev.of_node)
- data->kind = (enum chips)of_device_get_match_data(&client->dev);
+ data->kind = (uintptr_t)of_device_get_match_data(&client->dev);
else
data->kind = i2c_match_id(lm90_id, client)->driver_data;
diff --git a/drivers/hwmon/lochnagar-hwmon.c b/drivers/hwmon/lochnagar-hwmon.c
index 6350904a8a8b..5202dddfd61e 100644
--- a/drivers/hwmon/lochnagar-hwmon.c
+++ b/drivers/hwmon/lochnagar-hwmon.c
@@ -16,7 +16,6 @@
#include <linux/mfd/lochnagar2_regs.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
diff --git a/drivers/hwmon/ltq-cputemp.c b/drivers/hwmon/ltq-cputemp.c
index 08e09a82acab..f7e4a4ca5239 100644
--- a/drivers/hwmon/ltq-cputemp.c
+++ b/drivers/hwmon/ltq-cputemp.c
@@ -9,8 +9,9 @@
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/init.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/platform_device.h>
#include <lantiq_soc.h>
diff --git a/drivers/hwmon/max31730.c b/drivers/hwmon/max31730.c
index b1300ca9db1f..7d237db6e57c 100644
--- a/drivers/hwmon/max31730.c
+++ b/drivers/hwmon/max31730.c
@@ -11,7 +11,6 @@
#include <linux/init.h>
#include <linux/hwmon.h>
#include <linux/module.h>
-#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/slab.h>
diff --git a/drivers/hwmon/max6621.c b/drivers/hwmon/max6621.c
index 7f709fd1af89..af7e62685898 100644
--- a/drivers/hwmon/max6621.c
+++ b/drivers/hwmon/max6621.c
@@ -12,7 +12,7 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/regmap.h>
#define MAX6621_DRV_NAME "max6621"
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
index caf527154fca..aa7f21ab2395 100644
--- a/drivers/hwmon/max6639.c
+++ b/drivers/hwmon/max6639.c
@@ -618,11 +618,17 @@ MODULE_DEVICE_TABLE(i2c, max6639_id);
static DEFINE_SIMPLE_DEV_PM_OPS(max6639_pm_ops, max6639_suspend, max6639_resume);
+static const struct of_device_id max6639_of_match[] = {
+ { .compatible = "maxim,max6639", },
+ { },
+};
+
static struct i2c_driver max6639_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "max6639",
.pm = pm_sleep_ptr(&max6639_pm_ops),
+ .of_match_table = max6639_of_match,
},
.probe = max6639_probe,
.id_table = max6639_id,
diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c
index 3a67778f111c..7d10dd434f2e 100644
--- a/drivers/hwmon/max6697.c
+++ b/drivers/hwmon/max6697.c
@@ -15,7 +15,6 @@
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
-#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_data/max6697.h>
@@ -703,7 +702,7 @@ static int max6697_probe(struct i2c_client *client)
return -ENOMEM;
if (client->dev.of_node)
- data->type = (enum chips)of_device_get_match_data(&client->dev);
+ data->type = (uintptr_t)of_device_get_match_data(&client->dev);
else
data->type = i2c_match_id(max6697_id, client)->driver_data;
data->chip = &max6697_chip_data[data->type];
diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c
index 127e15ff3e76..9814eaf24564 100644
--- a/drivers/hwmon/mcp3021.c
+++ b/drivers/hwmon/mcp3021.c
@@ -20,7 +20,6 @@
#include <linux/err.h>
#include <linux/device.h>
#include <linux/of.h>
-#include <linux/of_device.h>
/* Vdd / reference voltage in millivolt */
#define MCP3021_VDD_REF_MAX 5500
diff --git a/drivers/hwmon/mlxreg-fan.c b/drivers/hwmon/mlxreg-fan.c
index c2a96468c9b4..a5f89aab3fb4 100644
--- a/drivers/hwmon/mlxreg-fan.c
+++ b/drivers/hwmon/mlxreg-fan.c
@@ -12,7 +12,7 @@
#include <linux/regmap.h>
#include <linux/thermal.h>
-#define MLXREG_FAN_MAX_TACHO 14
+#define MLXREG_FAN_MAX_TACHO 24
#define MLXREG_FAN_MAX_PWM 4
#define MLXREG_FAN_PWM_NOT_CONNECTED 0xff
#define MLXREG_FAN_MAX_STATE 10
@@ -300,6 +300,16 @@ static const struct hwmon_channel_info * const mlxreg_fan_hwmon_info[] = {
HWMON_F_INPUT | HWMON_F_FAULT,
HWMON_F_INPUT | HWMON_F_FAULT,
HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT,
+ HWMON_F_INPUT | HWMON_F_FAULT,
HWMON_F_INPUT | HWMON_F_FAULT),
HWMON_CHANNEL_INFO(pwm,
HWMON_PWM_INPUT,
diff --git a/drivers/hwmon/nct6775-core.c b/drivers/hwmon/nct6775-core.c
index 236dc97f4d22..02a71244fc3b 100644
--- a/drivers/hwmon/nct6775-core.c
+++ b/drivers/hwmon/nct6775-core.c
@@ -33,7 +33,8 @@
* (0xd451)
* nct6798d 14 7 7 2+6 0xd428 0xc1 0x5ca3
* (0xd429)
- * nct6799d 14 7 7 2+6 0xd802 0xc1 0x5ca3
+ * nct6796d-s 18 7 7 6+2 0xd801 0xc1 0x5ca3
+ * nct6799d-r 18 7 7 6+2 0xd802 0xc1 0x5ca3
*
* #temp lists the number of monitored temperature sources (first value) plus
* the number of directly connectable temperature sensors (second value).
@@ -79,14 +80,17 @@ static const char * const nct6775_device_names[] = {
/* Common and NCT6775 specific data */
-/* Voltage min/max registers for nr=7..14 are in bank 5 */
+/*
+ * Voltage min/max registers for nr=7..14 are in bank 5
+ * min/max: 15-17 for NCT6799 only
+ */
static const u16 NCT6775_REG_IN_MAX[] = {
0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
- 0x55c, 0x55e, 0x560, 0x562 };
+ 0x55c, 0x55e, 0x560, 0x562, 0x564, 0x570, 0x572 };
static const u16 NCT6775_REG_IN_MIN[] = {
0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
- 0x55d, 0x55f, 0x561, 0x563 };
+ 0x55d, 0x55f, 0x561, 0x563, 0x565, 0x571, 0x573 };
static const u16 NCT6775_REG_IN[] = {
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
};
@@ -97,31 +101,23 @@ static const u16 NCT6775_REG_IN[] = {
static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
-/* 0..15 voltages, 16..23 fans, 24..29 temperatures, 30..31 intrusion */
-
-static const s8 NCT6775_ALARM_BITS[] = {
- 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
- 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
- -1, /* unused */
- 6, 7, 11, -1, -1, /* fan1..fan5 */
- -1, -1, -1, /* unused */
- 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
- 12, -1 }; /* intrusion0, intrusion1 */
+static const s8 NCT6775_ALARM_BITS[NUM_ALARM_BITS] = {
+ 0, 1, 2, 3, 8, 21, 20, 16, 17, -1, -1, -1, /* in0-in11 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 6, 7, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
+ 12, -1, /* intr0-intr1 */
+};
static const u16 NCT6775_REG_BEEP[NUM_REG_BEEP] = { 0x56, 0x57, 0x453, 0x4e };
-/*
- * 0..14 voltages, 15 global beep enable, 16..23 fans, 24..29 temperatures,
- * 30..31 intrusion
- */
-static const s8 NCT6775_BEEP_BITS[] = {
- 0, 1, 2, 3, 8, 9, 10, 16, /* in0.. in7 */
- 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
- 21, /* global beep enable */
- 6, 7, 11, 28, -1, /* fan1..fan5 */
- -1, -1, -1, /* unused */
- 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
- 12, -1 }; /* intrusion0, intrusion1 */
+static const s8 NCT6775_BEEP_BITS[NUM_BEEP_BITS] = {
+ 0, 1, 2, 3, 8, 9, 10, 16, 17, -1, -1, -1, /* in0-in11 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 6, 7, 11, 28, -1, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
+ 12, -1, 21 /* intr0-intr1, beep_en */
+};
/* DC or PWM output fan configuration */
static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
@@ -255,25 +251,24 @@ static const u16 NCT6775_REG_TSI_TEMP[] = { 0x669 };
#define NCT6776_REG_FAN_STEP_UP_TIME NCT6775_REG_FAN_STEP_DOWN_TIME
#define NCT6776_REG_FAN_STEP_DOWN_TIME NCT6775_REG_FAN_STEP_UP_TIME
-static const s8 NCT6776_ALARM_BITS[] = {
- 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
- 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
- -1, /* unused */
- 6, 7, 11, 10, 23, /* fan1..fan5 */
- -1, -1, -1, /* unused */
- 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
- 12, 9 }; /* intrusion0, intrusion1 */
-
-static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 };
-
-static const s8 NCT6776_BEEP_BITS[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
- 8, -1, -1, -1, -1, -1, -1, /* in8..in14 */
- 24, /* global beep enable */
- 25, 26, 27, 28, 29, /* fan1..fan5 */
- -1, -1, -1, /* unused */
- 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
- 30, 31 }; /* intrusion0, intrusion1 */
+static const s8 NCT6776_ALARM_BITS[NUM_ALARM_BITS] = {
+ 0, 1, 2, 3, 8, 21, 20, 16, 17, -1, -1, -1, /* in0-in11 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 6, 7, 11, 10, 23, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
+ 12, 9, /* intr0-intr1 */
+};
+
+/* 0xbf: nct6799 only */
+static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5, 0xbf };
+
+static const s8 NCT6776_BEEP_BITS[NUM_BEEP_BITS] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, /* in0-in11 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
+ 30, 31, 24 /* intr0-intr1, beep_en */
+};
static const u16 NCT6776_REG_TOLERANCE_H[] = {
0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c, 0xb0c };
@@ -337,30 +332,35 @@ static const u16 NCT6776_REG_TSI_TEMP[] = {
/* NCT6779 specific data */
+/*
+ * 15-17 for NCT6799 only, register labels are:
+ * CPUVC, VIN1, AVSB, 3VCC, VIN0, VIN8, VIN4, 3VSB
+ * VBAT, VTT, VIN5, VIN6, VIN2, VIN3, VIN7, VIN9
+ * VHIF, VIN10
+ */
static const u16 NCT6779_REG_IN[] = {
0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
- 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
+ 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e, 0x48f,
+ 0x470, 0x471};
static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
0x459, 0x45A, 0x45B, 0x568 };
-static const s8 NCT6779_ALARM_BITS[] = {
- 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
- 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
- -1, /* unused */
- 6, 7, 11, 10, 23, /* fan1..fan5 */
- -1, -1, -1, /* unused */
- 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
- 12, 9 }; /* intrusion0, intrusion1 */
-
-static const s8 NCT6779_BEEP_BITS[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */
- 8, 9, 10, 11, 12, 13, 14, /* in8..in14 */
- 24, /* global beep enable */
- 25, 26, 27, 28, 29, /* fan1..fan5 */
- -1, -1, -1, /* unused */
- 16, 17, -1, -1, -1, -1, /* temp1..temp6 */
- 30, 31 }; /* intrusion0, intrusion1 */
+static const s8 NCT6779_ALARM_BITS[NUM_ALARM_BITS] = {
+ 0, 1, 2, 3, 8, 21, 20, 16, 17, 24, 25, 26, /* in0-in11 */
+ 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 6, 7, 11, 10, 23, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
+ 12, 9, /* intr0-intr1 */
+};
+
+static const s8 NCT6779_BEEP_BITS[NUM_BEEP_BITS] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, /* in0-in11 */
+ 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
+ 30, 31, 24 /* intr0-intr1, beep_en */
+};
static const u16 NCT6779_REG_FAN[] = {
0x4c0, 0x4c2, 0x4c4, 0x4c6, 0x4c8, 0x4ca, 0x4ce };
@@ -448,14 +448,13 @@ static const u16 NCT6791_REG_WEIGHT_DUTY_BASE[NUM_FAN] = { 0, 0x23e };
static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
0x459, 0x45A, 0x45B, 0x568, 0x45D };
-static const s8 NCT6791_ALARM_BITS[] = {
- 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
- 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
- -1, /* unused */
- 6, 7, 11, 10, 23, 33, /* fan1..fan6 */
- -1, -1, /* unused */
- 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
- 12, 9 }; /* intrusion0, intrusion1 */
+static const s8 NCT6791_ALARM_BITS[NUM_ALARM_BITS] = {
+ 0, 1, 2, 3, 8, 21, 20, 16, 17, 24, 25, 26, /* in0-in11 */
+ 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 6, 7, 11, 10, 23, 33, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
+ 12, 9, /* intr0-intr1 */
+};
/* NCT6792/NCT6793 specific data */
@@ -618,6 +617,28 @@ static const char *const nct6796_temp_label[] = {
static const u16 NCT6796_REG_TSI_TEMP[] = { 0x409, 0x40b };
+static const u16 NCT6798_REG_TEMP[] = {
+ 0x27, 0x150, 0x670, 0x672, 0x674, 0x676, 0x678, 0x67a};
+
+static const u16 NCT6798_REG_TEMP_SOURCE[] = {
+ 0x621, 0x622, 0xc26, 0xc27, 0xc28, 0xc29, 0xc2a, 0xc2b };
+
+static const u16 NCT6798_REG_TEMP_MON[] = {
+ 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d, 0x4a0 };
+static const u16 NCT6798_REG_TEMP_OVER[] = {
+ 0x39, 0x155, 0xc1a, 0xc1b, 0xc1c, 0xc1d, 0xc1e, 0xc1f };
+static const u16 NCT6798_REG_TEMP_HYST[] = {
+ 0x3a, 0x153, 0xc20, 0xc21, 0xc22, 0xc23, 0xc24, 0xc25 };
+
+static const u16 NCT6798_REG_TEMP_CRIT[32] = {
+ 0x135, 0x235, 0x335, 0x835, 0x935, 0xa35, 0xb35, 0 };
+
+static const u16 NCT6798_REG_TEMP_ALTERNATE[32] = {
+ 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0x496, 0,
+ 0, 0, 0, 0, 0x4a2, 0, 0, 0,
+ 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
+ 0x408, 0x419, 0x41a, 0x4f4, 0x4f5 };
+
static const char *const nct6798_temp_label[] = {
"",
"SYSTIN",
@@ -656,6 +677,26 @@ static const char *const nct6798_temp_label[] = {
#define NCT6798_TEMP_MASK 0xbfff0ffe
#define NCT6798_VIRT_TEMP_MASK 0x80000c00
+static const u16 NCT6799_REG_ALARM[NUM_REG_ALARM] = {
+ 0x459, 0x45A, 0x45B, 0x568, 0x45D, 0xc01 };
+
+static const s8 NCT6799_ALARM_BITS[NUM_ALARM_BITS] = {
+ 0, 1, 2, 3, 8, -1, 20, 16, 17, 24, 25, 26, /* in0-in11 */
+ 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 6, 7, 11, 10, 23, 33, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 4, 5, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, /* temp1-temp12 */
+ 12, 9, /* intr0-intr1 */
+};
+
+static const s8 NCT6799_BEEP_BITS[NUM_BEEP_BITS] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, /* in0-in11 */
+ 12, 13, 14, 15, 34, 35, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 16, 17, 18, 19, 20, 21, 22, 23, -1, -1, -1, -1, /* temp1-temp12 */
+ 30, 31, 24 /* intr0-intr1, beep_en */
+};
+
+/* PECI Calibration only for NCT6799D, not NCT6796D-S */
static const char *const nct6799_temp_label[] = {
"",
"SYSTIN",
@@ -685,8 +726,8 @@ static const char *const nct6799_temp_label[] = {
"Agent1 Dimm1",
"BYTE_TEMP0",
"BYTE_TEMP1",
- "PECI Agent 0 Calibration", /* undocumented */
- "PECI Agent 1 Calibration", /* undocumented */
+ "PECI/TSI Agent 0 Calibration",
+ "PECI/TSI Agent 1 Calibration",
"",
"Virtual_TEMP"
};
@@ -763,27 +804,23 @@ static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
-static const s8 NCT6106_ALARM_BITS[] = {
- 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
- 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */
- -1, /* unused */
- 32, 33, 34, -1, -1, /* fan1..fan5 */
- -1, -1, -1, /* unused */
- 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
- 48, -1 /* intrusion0, intrusion1 */
+static const s8 NCT6106_ALARM_BITS[NUM_ALARM_BITS] = {
+ 0, 1, 2, 3, 4, 5, 7, 8, 9, -1, -1, -1, /* in0-in11 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 32, 33, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
+ 48, -1, /* intr0-intr1 */
};
static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
-static const s8 NCT6106_BEEP_BITS[] = {
- 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
- 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
- 32, /* global beep enable */
- 24, 25, 26, 27, 28, /* fan1..fan5 */
- -1, -1, -1, /* unused */
- 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
- 34, -1 /* intrusion0, intrusion1 */
+static const s8 NCT6106_BEEP_BITS[NUM_BEEP_BITS] = {
+ 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, /* in0-in11 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 24, 25, 26, 27, 28, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
+ 34, -1, 32 /* intr0-intr1, beep_en */
};
static const u16 NCT6106_REG_TEMP_ALTERNATE[32] = {
@@ -843,24 +880,20 @@ static const u16 NCT6116_REG_AUTO_TEMP[] = {
static const u16 NCT6116_REG_AUTO_PWM[] = {
0x164, 0x174, 0x184, 0x1d4, 0x1e4 };
-static const s8 NCT6116_ALARM_BITS[] = {
- 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
- 9, -1, -1, -1, -1, -1, -1, /* in8..in9 */
- -1, /* unused */
- 32, 33, 34, 35, 36, /* fan1..fan5 */
- -1, -1, -1, /* unused */
- 16, 17, 18, -1, -1, -1, /* temp1..temp6 */
- 48, -1 /* intrusion0, intrusion1 */
+static const s8 NCT6116_ALARM_BITS[NUM_ALARM_BITS] = {
+ 0, 1, 2, 3, 4, 5, 7, 8, 9, -1, -1, -1, /* in0-in11 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 32, 33, 34, 35, 36, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 16, 17, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
+ 48, -1, /* intr0-intr1 */
};
-static const s8 NCT6116_BEEP_BITS[] = {
- 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
- 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */
- 32, /* global beep enable */
- 24, 25, 26, 27, 28, /* fan1..fan5 */
- -1, -1, -1, /* unused */
- 16, 17, 18, -1, -1, -1, /* temp1..temp6 */
- 34, -1 /* intrusion0, intrusion1 */
+static const s8 NCT6116_BEEP_BITS[NUM_BEEP_BITS] = {
+ 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, /* in0-in11 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */
+ 24, 25, 26, 27, 28, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */
+ 16, 17, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */
+ 34, -1, 32 /* intr0-intr1, beep_en */
};
static const u16 NCT6116_REG_TSI_TEMP[] = { 0x59, 0x5b };
@@ -955,14 +988,25 @@ static const u16 scale_in[15] = {
800, 800
};
-static inline long in_from_reg(u8 reg, u8 nr)
+/*
+ * NCT6798 scaling:
+ * CPUVC, IN1, AVSB, 3VCC, IN0, IN8, IN4, 3VSB, VBAT, VTT, IN5, IN6, IN2,
+ * IN3, IN7, IN9, VHIF, IN10
+ * 15-17 for NCT6799 only
+ */
+static const u16 scale_in_6798[NUM_IN] = {
+ 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 1600, 1600, 1600, 800,
+ 800, 800, 800, 1600, 800
+};
+
+static inline long in_from_reg(u8 reg, u8 nr, const u16 *scales)
{
- return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
+ return DIV_ROUND_CLOSEST(reg * scales[nr], 100);
}
-static inline u8 in_to_reg(u32 val, u8 nr)
+static inline u8 in_to_reg(u32 val, u8 nr, const u16 *scales)
{
- return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
+ return clamp_val(DIV_ROUND_CLOSEST(val * 100, scales[nr]), 0, 255);
}
/* TSI temperatures are in 8.3 format */
@@ -1673,7 +1717,8 @@ show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
if (IS_ERR(data))
return PTR_ERR(data);
- return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
+ return sprintf(buf, "%ld\n",
+ in_from_reg(data->in[nr][index], nr, data->scale_in));
}
static ssize_t
@@ -1691,7 +1736,7 @@ store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
if (err < 0)
return err;
mutex_lock(&data->update_lock);
- data->in[nr][index] = in_to_reg(val, nr);
+ data->in[nr][index] = in_to_reg(val, nr, data->scale_in);
err = nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr], data->in[nr][index]);
mutex_unlock(&data->update_lock);
return err ? : count;
@@ -3462,6 +3507,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
mutex_init(&data->update_lock);
data->name = nct6775_device_names[data->kind];
data->bank = 0xff; /* Force initial bank selection */
+ data->scale_in = scale_in;
switch (data->kind) {
case nct6106:
@@ -3849,13 +3895,9 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
case nct6795:
case nct6796:
case nct6797:
- case nct6798:
- case nct6799:
data->in_num = 15;
data->pwm_num = (data->kind == nct6796 ||
- data->kind == nct6797 ||
- data->kind == nct6798 ||
- data->kind == nct6799) ? 7 : 6;
+ data->kind == nct6797) ? 7 : 6;
data->auto_pwm_num = 4;
data->has_fan_div = false;
data->temp_fixed_num = 6;
@@ -3899,16 +3941,6 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
data->temp_mask = NCT6796_TEMP_MASK;
data->virt_temp_mask = NCT6796_VIRT_TEMP_MASK;
break;
- case nct6798:
- data->temp_label = nct6798_temp_label;
- data->temp_mask = NCT6798_TEMP_MASK;
- data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK;
- break;
- case nct6799:
- data->temp_label = nct6799_temp_label;
- data->temp_mask = NCT6799_TEMP_MASK;
- data->virt_temp_mask = NCT6799_VIRT_TEMP_MASK;
- break;
}
data->REG_CONFIG = NCT6775_REG_CONFIG;
@@ -3967,8 +3999,6 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
case nct6795:
case nct6796:
case nct6797:
- case nct6798:
- case nct6799:
data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP;
num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP);
break;
@@ -3993,6 +4023,95 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
reg_temp_crit = NCT6779_REG_TEMP_CRIT;
break;
+ case nct6798:
+ case nct6799:
+ data->in_num = data->kind == nct6799 ? 18 : 15;
+ data->scale_in = scale_in_6798;
+ data->pwm_num = 7;
+ data->auto_pwm_num = 4;
+ data->has_fan_div = false;
+ data->temp_fixed_num = 6;
+ data->num_temp_alarms = 7;
+ data->num_temp_beeps = 8;
+
+ data->ALARM_BITS = NCT6799_ALARM_BITS;
+ data->BEEP_BITS = NCT6799_BEEP_BITS;
+
+ data->fan_from_reg = fan_from_reg_rpm;
+ data->fan_from_reg_min = fan_from_reg13;
+ data->target_temp_mask = 0xff;
+ data->tolerance_mask = 0x07;
+ data->speed_tolerance_limit = 63;
+
+ switch (data->kind) {
+ default:
+ case nct6798:
+ data->temp_label = nct6798_temp_label;
+ data->temp_mask = NCT6798_TEMP_MASK;
+ data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK;
+ break;
+ case nct6799:
+ data->temp_label = nct6799_temp_label;
+ data->temp_mask = NCT6799_TEMP_MASK;
+ data->virt_temp_mask = NCT6799_VIRT_TEMP_MASK;
+ break;
+ }
+
+ data->REG_CONFIG = NCT6775_REG_CONFIG;
+ data->REG_VBAT = NCT6775_REG_VBAT;
+ data->REG_DIODE = NCT6775_REG_DIODE;
+ data->DIODE_MASK = NCT6775_DIODE_MASK;
+ data->REG_VIN = NCT6779_REG_IN;
+ data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
+ data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
+ data->REG_TARGET = NCT6775_REG_TARGET;
+ data->REG_FAN = NCT6779_REG_FAN;
+ data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
+ data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
+ data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
+ data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
+ data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
+ data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME;
+ data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME;
+ data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
+ data->REG_PWM[0] = NCT6775_REG_PWM;
+ data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
+ data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
+ data->REG_PWM[5] = NCT6791_REG_WEIGHT_DUTY_STEP;
+ data->REG_PWM[6] = NCT6791_REG_WEIGHT_DUTY_BASE;
+ data->REG_PWM_READ = NCT6775_REG_PWM_READ;
+ data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
+ data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
+ data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
+ data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
+ data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
+ data->REG_CRITICAL_TEMP_TOLERANCE = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
+ data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
+ data->CRITICAL_PWM_ENABLE_MASK = NCT6779_CRITICAL_PWM_ENABLE_MASK;
+ data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
+ data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
+ data->REG_TEMP_SOURCE = NCT6798_REG_TEMP_SOURCE;
+ data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
+ data->REG_WEIGHT_TEMP_SEL = NCT6791_REG_WEIGHT_TEMP_SEL;
+ data->REG_WEIGHT_TEMP[0] = NCT6791_REG_WEIGHT_TEMP_STEP;
+ data->REG_WEIGHT_TEMP[1] = NCT6791_REG_WEIGHT_TEMP_STEP_TOL;
+ data->REG_WEIGHT_TEMP[2] = NCT6791_REG_WEIGHT_TEMP_BASE;
+ data->REG_ALARM = NCT6799_REG_ALARM;
+ data->REG_BEEP = NCT6792_REG_BEEP;
+ data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP;
+ num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP);
+
+ reg_temp = NCT6798_REG_TEMP;
+ num_reg_temp = ARRAY_SIZE(NCT6798_REG_TEMP);
+ reg_temp_mon = NCT6798_REG_TEMP_MON;
+ num_reg_temp_mon = ARRAY_SIZE(NCT6798_REG_TEMP_MON);
+ reg_temp_over = NCT6798_REG_TEMP_OVER;
+ reg_temp_hyst = NCT6798_REG_TEMP_HYST;
+ reg_temp_config = NCT6779_REG_TEMP_CONFIG;
+ reg_temp_alternate = NCT6798_REG_TEMP_ALTERNATE;
+ reg_temp_crit = NCT6798_REG_TEMP_CRIT;
+
+ break;
default:
return -ENODEV;
}
diff --git a/drivers/hwmon/nct6775-platform.c b/drivers/hwmon/nct6775-platform.c
index ada867d6b98a..81bf03dad6bb 100644
--- a/drivers/hwmon/nct6775-platform.c
+++ b/drivers/hwmon/nct6775-platform.c
@@ -35,7 +35,7 @@ static const char * const nct6775_sio_names[] __initconst = {
"NCT6796D",
"NCT6797D",
"NCT6798D",
- "NCT6799D",
+ "NCT6796D-S/NCT6799D-R",
};
static unsigned short force_id;
@@ -586,7 +586,7 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio
int creb;
int cred;
- cre6 = sio_data->sio_inb(sio_data, 0xe0);
+ cre6 = sio_data->sio_inb(sio_data, 0xe6);
sio_data->sio_select(sio_data, NCT6775_LD_12);
cre0 = sio_data->sio_inb(sio_data, 0xe0);
diff --git a/drivers/hwmon/nct6775.h b/drivers/hwmon/nct6775.h
index 44f79c5726a9..296eff99d003 100644
--- a/drivers/hwmon/nct6775.h
+++ b/drivers/hwmon/nct6775.h
@@ -8,7 +8,7 @@ enum kinds { nct6106, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792,
nct6793, nct6795, nct6796, nct6797, nct6798, nct6799 };
enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
-#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/
+#define NUM_TEMP 12 /* Max number of temp attribute sets w/ limits*/
#define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */
#define NUM_TSI_TEMP 8 /* Max number of TSI temp register pairs */
@@ -16,6 +16,7 @@ enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
#define NUM_REG_BEEP 5 /* Max number of beep registers */
#define NUM_FAN 7
+#define NUM_IN 18
struct nct6775_data {
int addr; /* IO base of hw monitor block */
@@ -97,7 +98,8 @@ struct nct6775_data {
/* Register values */
u8 bank; /* current register bank */
u8 in_num; /* number of in inputs we have */
- u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
+ u8 in[NUM_IN][3]; /* [0]=in, [1]=in_max, [2]=in_min */
+ const u16 *scale_in; /* internal scaling factors */
unsigned int rpm[NUM_FAN];
u16 fan_min[NUM_FAN];
u8 fan_pulses[NUM_FAN];
@@ -165,7 +167,7 @@ struct nct6775_data {
u16 have_temp;
u16 have_temp_fixed;
u16 have_tsi_temp;
- u16 have_in;
+ u32 have_in;
/* Remember extra register values over suspend/resume */
u8 vbat;
@@ -238,10 +240,25 @@ nct6775_add_attr_group(struct nct6775_data *data, const struct attribute_group *
#define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE 0x28
-#define FAN_ALARM_BASE 16
-#define TEMP_ALARM_BASE 24
-#define INTRUSION_ALARM_BASE 30
-#define BEEP_ENABLE_BASE 15
+/*
+ * ALARM_BITS and BEEP_BITS store bit-index for the mask of the registers
+ * loaded into data->alarm and data->beep.
+ *
+ * Every input register (IN/TEMP/FAN) must have a corresponding
+ * ALARM/BEEP bit at the same index BITS[BASE + index]
+ * Set value to -1 to disable the visibility of that '*_alarm' attribute and
+ * to pad the bits until the next BASE
+ *
+ * Beep has an additional GLOBAL_BEEP_ENABLE bit
+ */
+#define VIN_ALARM_BASE 0
+#define FAN_ALARM_BASE 24
+#define TEMP_ALARM_BASE 36
+#define INTRUSION_ALARM_BASE 48
+#define BEEP_ENABLE_BASE 50
+
+#define NUM_ALARM_BITS (INTRUSION_ALARM_BASE + 4)
+#define NUM_BEEP_BITS (BEEP_ENABLE_BASE + 1)
/*
* Not currently used:
diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c
index 9339bfc02a3e..024cff151c36 100644
--- a/drivers/hwmon/nct7802.c
+++ b/drivers/hwmon/nct7802.c
@@ -725,7 +725,7 @@ static umode_t nct7802_temp_is_visible(struct kobject *kobj,
if (index >= 38 && index < 46 && !(reg & 0x01)) /* PECI 0 */
return 0;
- if (index >= 0x46 && (!(reg & 0x02))) /* PECI 1 */
+ if (index >= 46 && !(reg & 0x02)) /* PECI 1 */
return 0;
return attr->mode;
diff --git a/drivers/hwmon/nsa320-hwmon.c b/drivers/hwmon/nsa320-hwmon.c
index ebe6b031e56f..18076ba7fc14 100644
--- a/drivers/hwmon/nsa320-hwmon.c
+++ b/drivers/hwmon/nsa320-hwmon.c
@@ -20,8 +20,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
#include <linux/platform_device.h>
/* Tests for error return values rely upon this value being < 0x80 */
@@ -193,7 +191,7 @@ static struct platform_driver nsa320_hwmon_driver = {
.probe = nsa320_hwmon_probe,
.driver = {
.name = "nsa320-hwmon",
- .of_match_table = of_match_ptr(of_nsa320_hwmon_match),
+ .of_match_table = of_nsa320_hwmon_match,
},
};
diff --git a/drivers/hwmon/oxp-sensors.c b/drivers/hwmon/oxp-sensors.c
index e1a907cae820..ea9602063eab 100644
--- a/drivers/hwmon/oxp-sensors.c
+++ b/drivers/hwmon/oxp-sensors.c
@@ -220,6 +220,20 @@ static int tt_toggle_disable(void)
}
/* Callbacks for turbo toggle attribute */
+static umode_t tt_toggle_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
+{
+ switch (board) {
+ case aok_zoe_a1:
+ case oxp_mini_amd_a07:
+ case oxp_mini_amd_pro:
+ return attr->mode;
+ default:
+ break;
+ }
+ return 0;
+}
+
static ssize_t tt_toggle_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
@@ -396,7 +410,15 @@ static struct attribute *oxp_ec_attrs[] = {
NULL
};
-ATTRIBUTE_GROUPS(oxp_ec);
+static struct attribute_group oxp_ec_attribute_group = {
+ .is_visible = tt_toggle_is_visible,
+ .attrs = oxp_ec_attrs,
+};
+
+static const struct attribute_group *oxp_ec_groups[] = {
+ &oxp_ec_attribute_group,
+ NULL
+};
static const struct hwmon_ops oxp_ec_hwmon_ops = {
.is_visible = oxp_ec_hwmon_is_visible,
@@ -412,35 +434,8 @@ static const struct hwmon_chip_info oxp_ec_chip_info = {
/* Initialization logic */
static int oxp_platform_probe(struct platform_device *pdev)
{
- const struct dmi_system_id *dmi_entry;
struct device *dev = &pdev->dev;
struct device *hwdev;
- int ret;
-
- /*
- * Have to check for AMD processor here because DMI strings are the
- * same between Intel and AMD boards, the only way to tell them apart
- * is the CPU.
- * Intel boards seem to have different EC registers and values to
- * read/write.
- */
- dmi_entry = dmi_first_match(dmi_table);
- if (!dmi_entry || boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
- return -ENODEV;
-
- board = (enum oxp_board)(unsigned long)dmi_entry->driver_data;
-
- switch (board) {
- case aok_zoe_a1:
- case oxp_mini_amd_a07:
- case oxp_mini_amd_pro:
- ret = devm_device_add_groups(dev, oxp_ec_groups);
- if (ret)
- return ret;
- break;
- default:
- break;
- }
hwdev = devm_hwmon_device_register_with_info(dev, "oxpec", NULL,
&oxp_ec_chip_info, NULL);
@@ -451,6 +446,7 @@ static int oxp_platform_probe(struct platform_device *pdev)
static struct platform_driver oxp_platform_driver = {
.driver = {
.name = "oxp-platform",
+ .dev_groups = oxp_ec_groups,
},
.probe = oxp_platform_probe,
};
@@ -459,6 +455,21 @@ static struct platform_device *oxp_platform_device;
static int __init oxp_platform_init(void)
{
+ const struct dmi_system_id *dmi_entry;
+
+ /*
+ * Have to check for AMD processor here because DMI strings are the
+ * same between Intel and AMD boards, the only way to tell them apart
+ * is the CPU.
+ * Intel boards seem to have different EC registers and values to
+ * read/write.
+ */
+ dmi_entry = dmi_first_match(dmi_table);
+ if (!dmi_entry || boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+ return -ENODEV;
+
+ board = (enum oxp_board)(unsigned long)dmi_entry->driver_data;
+
oxp_platform_device =
platform_create_bundle(&oxp_platform_driver,
oxp_platform_probe, NULL, 0, NULL, 0);
diff --git a/drivers/hwmon/peci/dimmtemp.c b/drivers/hwmon/peci/dimmtemp.c
index ed968401f93c..ce89da3937a0 100644
--- a/drivers/hwmon/peci/dimmtemp.c
+++ b/drivers/hwmon/peci/dimmtemp.c
@@ -219,19 +219,21 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
{
int chan_rank_max = priv->gen_info->chan_rank_max;
int dimm_idx_max = priv->gen_info->dimm_idx_max;
- u32 chan_rank_empty = 0;
- u32 dimm_mask = 0;
- int chan_rank, dimm_idx, ret;
+ DECLARE_BITMAP(dimm_mask, DIMM_NUMS_MAX);
+ DECLARE_BITMAP(chan_rank_empty, CHAN_RANK_MAX);
+
+ int chan_rank, dimm_idx, ret, i;
u32 pcs;
- BUILD_BUG_ON(BITS_PER_TYPE(chan_rank_empty) < CHAN_RANK_MAX);
- BUILD_BUG_ON(BITS_PER_TYPE(dimm_mask) < DIMM_NUMS_MAX);
if (chan_rank_max * dimm_idx_max > DIMM_NUMS_MAX) {
WARN_ONCE(1, "Unsupported number of DIMMs - chan_rank_max: %d, dimm_idx_max: %d",
chan_rank_max, dimm_idx_max);
return -EINVAL;
}
+ bitmap_zero(dimm_mask, DIMM_NUMS_MAX);
+ bitmap_zero(chan_rank_empty, CHAN_RANK_MAX);
+
for (chan_rank = 0; chan_rank < chan_rank_max; chan_rank++) {
ret = peci_pcs_read(priv->peci_dev, PECI_PCS_DDR_DIMM_TEMP, chan_rank, &pcs);
if (ret) {
@@ -242,7 +244,7 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
* detection to be performed at a later point in time.
*/
if (ret == -EINVAL) {
- chan_rank_empty |= BIT(chan_rank);
+ bitmap_set(chan_rank_empty, chan_rank, 1);
continue;
}
@@ -251,7 +253,7 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
for (dimm_idx = 0; dimm_idx < dimm_idx_max; dimm_idx++)
if (__dimm_temp(pcs, dimm_idx))
- dimm_mask |= BIT(chan_rank * dimm_idx_max + dimm_idx);
+ bitmap_set(dimm_mask, chan_rank * dimm_idx_max + dimm_idx, 1);
}
/*
@@ -260,7 +262,7 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
* host platform boot. Retrying a couple of times lets us make sure
* that the state is persistent.
*/
- if (chan_rank_empty == GENMASK(chan_rank_max - 1, 0)) {
+ if (bitmap_full(chan_rank_empty, chan_rank_max)) {
if (priv->no_dimm_retry_count < NO_DIMM_RETRY_COUNT_MAX) {
priv->no_dimm_retry_count++;
@@ -274,14 +276,16 @@ static int check_populated_dimms(struct peci_dimmtemp *priv)
* It's possible that memory training is not done yet. In this case we
* defer the detection to be performed at a later point in time.
*/
- if (!dimm_mask) {
+ if (bitmap_empty(dimm_mask, DIMM_NUMS_MAX)) {
priv->no_dimm_retry_count = 0;
return -EAGAIN;
}
- dev_dbg(priv->dev, "Scanned populated DIMMs: %#x\n", dimm_mask);
+ for_each_set_bit(i, dimm_mask, DIMM_NUMS_MAX) {
+ dev_dbg(priv->dev, "Found DIMM%#x\n", i);
+ }
- bitmap_from_arr32(priv->dimm_mask, &dimm_mask, DIMM_NUMS_MAX);
+ bitmap_copy(priv->dimm_mask, dimm_mask, DIMM_NUMS_MAX);
return 0;
}
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 270b6336b76d..b4e93bd5835e 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -317,6 +317,13 @@ config SENSORS_MP2975
This driver can also be built as a module. If so, the module will
be called mp2975.
+config SENSORS_MP2975_REGULATOR
+ depends on SENSORS_MP2975 && REGULATOR
+ bool "Regulator support for MPS MP2975"
+ help
+ If you say yes here you get regulator support for MPS MP2975
+ Dual Loop Digital Multi-Phase Controller.
+
config SENSORS_MP5023
tristate "MPS MP5023"
help
diff --git a/drivers/hwmon/pmbus/acbel-fsg032.c b/drivers/hwmon/pmbus/acbel-fsg032.c
index 0a0ef4ce3493..e0c55fd8f3a6 100644
--- a/drivers/hwmon/pmbus/acbel-fsg032.c
+++ b/drivers/hwmon/pmbus/acbel-fsg032.c
@@ -3,14 +3,51 @@
* Copyright 2023 IBM Corp.
*/
+#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/i2c.h>
+#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/pmbus.h>
#include <linux/hwmon-sysfs.h>
#include "pmbus.h"
+#define ACBEL_MFR_FW_REVISION 0xd9
+
+static ssize_t acbel_fsg032_debugfs_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct i2c_client *client = file->private_data;
+ u8 data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
+ char out[8];
+ int rc;
+
+ rc = i2c_smbus_read_block_data(client, ACBEL_MFR_FW_REVISION, data);
+ if (rc < 0)
+ return rc;
+
+ rc = snprintf(out, sizeof(out), "%*phN\n", min(rc, 3), data);
+ return simple_read_from_buffer(buf, count, ppos, out, rc);
+}
+
+static const struct file_operations acbel_debugfs_ops = {
+ .llseek = noop_llseek,
+ .read = acbel_fsg032_debugfs_read,
+ .write = NULL,
+ .open = simple_open,
+};
+
+static void acbel_fsg032_init_debugfs(struct i2c_client *client)
+{
+ struct dentry *debugfs = pmbus_get_debugfs_dir(client);
+
+ if (!debugfs)
+ return;
+
+ debugfs_create_file("fw_version", 0444, debugfs, client, &acbel_debugfs_ops);
+}
+
static const struct i2c_device_id acbel_fsg032_id[] = {
{ "acbel_fsg032" },
{}
@@ -59,6 +96,7 @@ static int acbel_fsg032_probe(struct i2c_client *client)
if (rc)
return rc;
+ acbel_fsg032_init_debugfs(client);
return 0;
}
diff --git a/drivers/hwmon/pmbus/bel-pfe.c b/drivers/hwmon/pmbus/bel-pfe.c
index fa5070ae26bc..7c5f4b10a7c1 100644
--- a/drivers/hwmon/pmbus/bel-pfe.c
+++ b/drivers/hwmon/pmbus/bel-pfe.c
@@ -17,12 +17,13 @@
enum chips {pfe1100, pfe3000};
/*
- * Disable status check for pfe3000 devices, because some devices report
- * communication error (invalid command) for VOUT_MODE command (0x20)
- * although correct VOUT_MODE (0x16) is returned: it leads to incorrect
- * exponent in linear mode.
+ * Disable status check because some devices report communication error
+ * (invalid command) for VOUT_MODE command (0x20) although the correct
+ * VOUT_MODE (0x16) is returned: it leads to incorrect exponent in linear
+ * mode.
+ * This affects both pfe3000 and pfe1100.
*/
-static struct pmbus_platform_data pfe3000_plat_data = {
+static struct pmbus_platform_data pfe_plat_data = {
.flags = PMBUS_SKIP_STATUS_CHECK,
};
@@ -94,16 +95,15 @@ static int pfe_pmbus_probe(struct i2c_client *client)
int model;
model = (int)i2c_match_id(pfe_device_id, client)->driver_data;
+ client->dev.platform_data = &pfe_plat_data;
/*
* PFE3000-12-069RA devices may not stay in page 0 during device
* probe which leads to probe failure (read status word failed).
* So let's set the device to page 0 at the beginning.
*/
- if (model == pfe3000) {
- client->dev.platform_data = &pfe3000_plat_data;
+ if (model == pfe3000)
i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
- }
return pmbus_do_probe(client, &pfe_driver_info[model]);
}
diff --git a/drivers/hwmon/pmbus/dps920ab.c b/drivers/hwmon/pmbus/dps920ab.c
index f7ff3e4650b7..04e0d598a6e5 100644
--- a/drivers/hwmon/pmbus/dps920ab.c
+++ b/drivers/hwmon/pmbus/dps920ab.c
@@ -9,7 +9,7 @@
#include <linux/debugfs.h>
#include <linux/i2c.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include "pmbus.h"
struct dps920ab_data {
diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c
index c791925b8907..1ba4c5e95820 100644
--- a/drivers/hwmon/pmbus/ibm-cffps.c
+++ b/drivers/hwmon/pmbus/ibm-cffps.c
@@ -13,7 +13,7 @@
#include <linux/leds.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/pmbus.h>
#include "pmbus.h"
@@ -489,7 +489,7 @@ static int ibm_cffps_probe(struct i2c_client *client)
const struct i2c_device_id *id;
if (md) {
- vs = (enum versions)md;
+ vs = (uintptr_t)md;
} else {
id = i2c_match_id(ibm_cffps_id, client);
if (id)
diff --git a/drivers/hwmon/pmbus/ir38064.c b/drivers/hwmon/pmbus/ir38064.c
index 871c322d3d51..04185be3fdb6 100644
--- a/drivers/hwmon/pmbus/ir38064.c
+++ b/drivers/hwmon/pmbus/ir38064.c
@@ -6,7 +6,7 @@
*
* 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.
*/
@@ -16,7 +16,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/regulator/driver.h>
#include "pmbus.h"
diff --git a/drivers/hwmon/pmbus/max20730.c b/drivers/hwmon/pmbus/max20730.c
index 7bcf27995033..d56ec24764fd 100644
--- a/drivers/hwmon/pmbus/max20730.c
+++ b/drivers/hwmon/pmbus/max20730.c
@@ -15,7 +15,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/pmbus.h>
#include <linux/util_macros.h>
#include "pmbus.h"
@@ -114,6 +114,7 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
const struct pmbus_driver_info *info;
const struct max20730_data *data;
char tbuf[DEBUG_FS_DATA_MAX] = { 0 };
+ char *result = tbuf;
u16 val;
info = pmbus_get_driver_info(psu->client);
@@ -148,13 +149,13 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
>> MAX20730_MFR_DEVSET1_TSTAT_BIT_POS;
if (val == 0)
- len = strlcpy(tbuf, "2000\n", DEBUG_FS_DATA_MAX);
+ result = "2000\n";
else if (val == 1)
- len = strlcpy(tbuf, "125\n", DEBUG_FS_DATA_MAX);
+ result = "125\n";
else if (val == 2)
- len = strlcpy(tbuf, "62.5\n", DEBUG_FS_DATA_MAX);
+ result = "62.5\n";
else
- len = strlcpy(tbuf, "32\n", DEBUG_FS_DATA_MAX);
+ result = "32\n";
break;
case MAX20730_DEBUGFS_INTERNAL_GAIN:
val = (data->mfr_devset1 & MAX20730_MFR_DEVSET1_RGAIN_MASK)
@@ -163,35 +164,35 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
if (data->id == max20734) {
/* AN6209 */
if (val == 0)
- len = strlcpy(tbuf, "0.8\n", DEBUG_FS_DATA_MAX);
+ result = "0.8\n";
else if (val == 1)
- len = strlcpy(tbuf, "3.2\n", DEBUG_FS_DATA_MAX);
+ result = "3.2\n";
else if (val == 2)
- len = strlcpy(tbuf, "1.6\n", DEBUG_FS_DATA_MAX);
+ result = "1.6\n";
else
- len = strlcpy(tbuf, "6.4\n", DEBUG_FS_DATA_MAX);
+ result = "6.4\n";
} else if (data->id == max20730 || data->id == max20710) {
/* AN6042 or AN6140 */
if (val == 0)
- len = strlcpy(tbuf, "0.9\n", DEBUG_FS_DATA_MAX);
+ result = "0.9\n";
else if (val == 1)
- len = strlcpy(tbuf, "3.6\n", DEBUG_FS_DATA_MAX);
+ result = "3.6\n";
else if (val == 2)
- len = strlcpy(tbuf, "1.8\n", DEBUG_FS_DATA_MAX);
+ result = "1.8\n";
else
- len = strlcpy(tbuf, "7.2\n", DEBUG_FS_DATA_MAX);
+ result = "7.2\n";
} else if (data->id == max20743) {
/* AN6042 */
if (val == 0)
- len = strlcpy(tbuf, "0.45\n", DEBUG_FS_DATA_MAX);
+ result = "0.45\n";
else if (val == 1)
- len = strlcpy(tbuf, "1.8\n", DEBUG_FS_DATA_MAX);
+ result = "1.8\n";
else if (val == 2)
- len = strlcpy(tbuf, "0.9\n", DEBUG_FS_DATA_MAX);
+ result = "0.9\n";
else
- len = strlcpy(tbuf, "3.6\n", DEBUG_FS_DATA_MAX);
+ result = "3.6\n";
} else {
- len = strlcpy(tbuf, "Not supported\n", DEBUG_FS_DATA_MAX);
+ result = "Not supported\n";
}
break;
case MAX20730_DEBUGFS_BOOT_VOLTAGE:
@@ -199,26 +200,26 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
>> MAX20730_MFR_DEVSET1_VBOOT_BIT_POS;
if (val == 0)
- len = strlcpy(tbuf, "0.6484\n", DEBUG_FS_DATA_MAX);
+ result = "0.6484\n";
else if (val == 1)
- len = strlcpy(tbuf, "0.8984\n", DEBUG_FS_DATA_MAX);
+ result = "0.8984\n";
else if (val == 2)
- len = strlcpy(tbuf, "1.0\n", DEBUG_FS_DATA_MAX);
+ result = "1.0\n";
else
- len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
+ result = "Invalid\n";
break;
case MAX20730_DEBUGFS_OUT_V_RAMP_RATE:
val = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_VRATE)
>> MAX20730_MFR_DEVSET2_VRATE_BIT_POS;
if (val == 0)
- len = strlcpy(tbuf, "4\n", DEBUG_FS_DATA_MAX);
+ result = "4\n";
else if (val == 1)
- len = strlcpy(tbuf, "2\n", DEBUG_FS_DATA_MAX);
+ result = "2\n";
else if (val == 2)
- len = strlcpy(tbuf, "1\n", DEBUG_FS_DATA_MAX);
+ result = "1\n";
else
- len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
+ result = "Invalid\n";
break;
case MAX20730_DEBUGFS_OC_PROTECT_MODE:
ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_OCPM_MASK)
@@ -230,13 +231,13 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
>> MAX20730_MFR_DEVSET2_SS_BIT_POS;
if (val == 0)
- len = strlcpy(tbuf, "0.75\n", DEBUG_FS_DATA_MAX);
+ result = "0.75\n";
else if (val == 1)
- len = strlcpy(tbuf, "1.5\n", DEBUG_FS_DATA_MAX);
+ result = "1.5\n";
else if (val == 2)
- len = strlcpy(tbuf, "3\n", DEBUG_FS_DATA_MAX);
+ result = "3\n";
else
- len = strlcpy(tbuf, "6\n", DEBUG_FS_DATA_MAX);
+ result = "6\n";
break;
case MAX20730_DEBUGFS_IMAX:
ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_IMAX_MASK)
@@ -287,10 +288,11 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf,
"%d.%d\n", ret / 10000, ret % 10000);
break;
default:
- len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX);
+ result = "Invalid\n";
}
- return simple_read_from_buffer(buf, count, ppos, tbuf, len);
+ len = strlen(result);
+ return simple_read_from_buffer(buf, count, ppos, result, len);
}
static const struct file_operations max20730_fops = {
@@ -714,7 +716,7 @@ static int max20730_probe(struct i2c_client *client)
}
if (client->dev.of_node)
- chip_id = (enum chips)of_device_get_match_data(dev);
+ chip_id = (uintptr_t)of_device_get_match_data(dev);
else
chip_id = i2c_match_id(max20730_id, client)->driver_data;
diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c
index 2109b0458a8b..26ba50633100 100644
--- a/drivers/hwmon/pmbus/mp2975.c
+++ b/drivers/hwmon/pmbus/mp2975.c
@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include "pmbus.h"
/* Vendor specific registers. */
@@ -34,6 +35,8 @@
#define MP2975_MFR_OVP_TH_SET 0xe5
#define MP2975_MFR_UVP_SET 0xe6
+#define MP2973_MFR_RESO_SET 0xc7
+
#define MP2975_VOUT_FORMAT BIT(15)
#define MP2975_VID_STEP_SEL_R1 BIT(4)
#define MP2975_IMVP9_EN_R1 BIT(13)
@@ -48,43 +51,80 @@
#define MP2975_SENSE_AMPL_HALF 2
#define MP2975_VIN_UV_LIMIT_UNIT 8
+#define MP2973_VOUT_FORMAT_R1 GENMASK(7, 6)
+#define MP2973_VOUT_FORMAT_R2 GENMASK(4, 3)
+#define MP2973_VOUT_FORMAT_DIRECT_R1 BIT(7)
+#define MP2973_VOUT_FORMAT_LINEAR_R1 BIT(6)
+#define MP2973_VOUT_FORMAT_DIRECT_R2 BIT(4)
+#define MP2973_VOUT_FORMAT_LINEAR_R2 BIT(3)
+
+#define MP2973_MFR_VR_MULTI_CONFIG_R1 0x0d
+#define MP2973_MFR_VR_MULTI_CONFIG_R2 0x1d
+#define MP2973_VID_STEP_SEL_R1 BIT(4)
+#define MP2973_IMVP9_EN_R1 BIT(14)
+#define MP2973_VID_STEP_SEL_R2 BIT(3)
+#define MP2973_IMVP9_EN_R2 BIT(13)
+
+#define MP2973_MFR_OCP_TOTAL_SET 0x5f
+#define MP2973_OCP_TOTAL_CUR_MASK GENMASK(6, 0)
+#define MP2973_MFR_OCP_LEVEL_RES BIT(15)
+
+#define MP2973_MFR_READ_IOUT_PK 0x90
+#define MP2973_MFR_READ_POUT_PK 0x91
+
#define MP2975_MAX_PHASE_RAIL1 8
#define MP2975_MAX_PHASE_RAIL2 4
+
+#define MP2973_MAX_PHASE_RAIL1 14
+#define MP2973_MAX_PHASE_RAIL2 6
+
+#define MP2971_MAX_PHASE_RAIL1 8
+#define MP2971_MAX_PHASE_RAIL2 3
+
#define MP2975_PAGE_NUM 2
#define MP2975_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \
PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | \
PMBUS_HAVE_POUT | PMBUS_PHASE_VIRTUAL)
+enum chips {
+ mp2971, mp2973, mp2975
+};
+
+static const int mp2975_max_phases[][MP2975_PAGE_NUM] = {
+ [mp2975] = { MP2975_MAX_PHASE_RAIL1, MP2975_MAX_PHASE_RAIL2 },
+ [mp2973] = { MP2973_MAX_PHASE_RAIL1, MP2973_MAX_PHASE_RAIL2 },
+ [mp2971] = { MP2971_MAX_PHASE_RAIL1, MP2971_MAX_PHASE_RAIL2 },
+};
+
struct mp2975_data {
struct pmbus_driver_info info;
+ enum chips chip_id;
int vout_scale;
+ int max_phases[MP2975_PAGE_NUM];
int vid_step[MP2975_PAGE_NUM];
int vref[MP2975_PAGE_NUM];
int vref_off[MP2975_PAGE_NUM];
int vout_max[MP2975_PAGE_NUM];
int vout_ov_fixed[MP2975_PAGE_NUM];
- int vout_format[MP2975_PAGE_NUM];
int curr_sense_gain[MP2975_PAGE_NUM];
};
-#define to_mp2975_data(x) container_of(x, struct mp2975_data, info)
+static const struct i2c_device_id mp2975_id[] = {
+ {"mp2971", mp2971},
+ {"mp2973", mp2973},
+ {"mp2975", mp2975},
+ {}
+};
-static int mp2975_read_byte_data(struct i2c_client *client, int page, int reg)
-{
- switch (reg) {
- case PMBUS_VOUT_MODE:
- /*
- * Enforce VOUT direct format, since device allows to set the
- * different formats for the different rails. Conversion from
- * VID to direct provided by driver internally, in case it is
- * necessary.
- */
- return PB_VOUT_MODE_DIRECT;
- default:
- return -ENODATA;
- }
-}
+MODULE_DEVICE_TABLE(i2c, mp2975_id);
+
+static const struct regulator_desc __maybe_unused mp2975_reg_desc[] = {
+ PMBUS_REGULATOR("vout", 0),
+ PMBUS_REGULATOR("vout", 1),
+};
+
+#define to_mp2975_data(x) container_of(x, struct mp2975_data, info)
static int
mp2975_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg,
@@ -117,6 +157,41 @@ mp2975_vid2direct(int vrf, int val)
return 0;
}
+#define MAX_LIN_MANTISSA (1023 * 1000)
+#define MIN_LIN_MANTISSA (511 * 1000)
+
+/* Converts a milli-unit DIRECT value to LINEAR11 format */
+static u16 mp2975_data2reg_linear11(s64 val)
+{
+ s16 exponent = 0, mantissa;
+ bool negative = false;
+
+ /* simple case */
+ if (val == 0)
+ return 0;
+
+ /* Reduce large mantissa until it fits into 10 bit */
+ while (val >= MAX_LIN_MANTISSA && exponent < 15) {
+ exponent++;
+ val >>= 1;
+ }
+ /* Increase small mantissa to improve precision */
+ while (val < MIN_LIN_MANTISSA && exponent > -15) {
+ exponent--;
+ val <<= 1;
+ }
+
+ /* Convert mantissa from milli-units to units */
+ mantissa = clamp_val(DIV_ROUND_CLOSEST_ULL(val, 1000), 0, 0x3ff);
+
+ /* restore sign */
+ if (negative)
+ mantissa = -mantissa;
+
+ /* Convert to 5 bit exponent, 11 bit mantissa */
+ return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
+}
+
static int
mp2975_read_phase(struct i2c_client *client, struct mp2975_data *data,
int page, int phase, u8 reg)
@@ -214,6 +289,89 @@ mp2975_read_phases(struct i2c_client *client, struct mp2975_data *data,
return ret;
}
+static int mp2973_read_word_data(struct i2c_client *client, int page,
+ int phase, int reg)
+{
+ const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+ struct mp2975_data *data = to_mp2975_data(info);
+ int ret;
+
+ switch (reg) {
+ case PMBUS_OT_FAULT_LIMIT:
+ ret = mp2975_read_word_helper(client, page, phase, reg,
+ GENMASK(7, 0));
+ break;
+ case PMBUS_VIN_OV_FAULT_LIMIT:
+ ret = mp2975_read_word_helper(client, page, phase, reg,
+ GENMASK(7, 0));
+ if (ret < 0)
+ return ret;
+
+ ret = DIV_ROUND_CLOSEST(ret, MP2975_VIN_UV_LIMIT_UNIT);
+ break;
+ case PMBUS_VOUT_OV_FAULT_LIMIT:
+ /*
+ * MP2971 and mp2973 only supports tracking (ovp1) mode.
+ */
+ ret = mp2975_read_word_helper(client, page, phase,
+ MP2975_MFR_OVP_TH_SET,
+ GENMASK(2, 0));
+ if (ret < 0)
+ return ret;
+
+ ret = data->vout_max[page] + 50 * (ret + 1);
+ break;
+ case PMBUS_VOUT_UV_FAULT_LIMIT:
+ ret = mp2975_read_word_helper(client, page, phase, reg,
+ GENMASK(8, 0));
+ if (ret < 0)
+ return ret;
+ ret = mp2975_vid2direct(info->vrm_version[page], ret);
+ break;
+ case PMBUS_VIRT_READ_POUT_MAX:
+ ret = pmbus_read_word_data(client, page, phase,
+ MP2973_MFR_READ_POUT_PK);
+ break;
+ case PMBUS_VIRT_READ_IOUT_MAX:
+ ret = pmbus_read_word_data(client, page, phase,
+ MP2973_MFR_READ_IOUT_PK);
+ break;
+ case PMBUS_IOUT_OC_FAULT_LIMIT:
+ ret = mp2975_read_word_helper(client, page, phase,
+ MP2973_MFR_OCP_TOTAL_SET,
+ GENMASK(15, 0));
+ if (ret < 0)
+ return ret;
+
+ if (ret & MP2973_MFR_OCP_LEVEL_RES)
+ ret = 2 * (ret & MP2973_OCP_TOTAL_CUR_MASK);
+ else
+ ret = ret & MP2973_OCP_TOTAL_CUR_MASK;
+
+ ret = mp2975_data2reg_linear11(ret * info->phases[page] * 1000);
+ break;
+ case PMBUS_UT_WARN_LIMIT:
+ case PMBUS_UT_FAULT_LIMIT:
+ case PMBUS_VIN_UV_WARN_LIMIT:
+ case PMBUS_VIN_UV_FAULT_LIMIT:
+ case PMBUS_VOUT_UV_WARN_LIMIT:
+ case PMBUS_VOUT_OV_WARN_LIMIT:
+ case PMBUS_VIN_OV_WARN_LIMIT:
+ case PMBUS_IIN_OC_FAULT_LIMIT:
+ case PMBUS_IOUT_OC_LV_FAULT_LIMIT:
+ case PMBUS_IOUT_OC_WARN_LIMIT:
+ case PMBUS_IOUT_UC_FAULT_LIMIT:
+ case PMBUS_POUT_OP_FAULT_LIMIT:
+ case PMBUS_POUT_OP_WARN_LIMIT:
+ case PMBUS_PIN_OP_WARN_LIMIT:
+ return -ENXIO;
+ default:
+ return -ENODATA;
+ }
+
+ return ret;
+}
+
static int mp2975_read_word_data(struct i2c_client *client, int page,
int phase, int reg)
{
@@ -222,6 +380,11 @@ static int mp2975_read_word_data(struct i2c_client *client, int page,
int ret;
switch (reg) {
+ case PMBUS_STATUS_WORD:
+ /* MP2973 & MP2971 return PGOOD instead of PB_STATUS_POWER_GOOD_N. */
+ ret = pmbus_read_word_data(client, page, phase, reg);
+ ret ^= PB_STATUS_POWER_GOOD_N;
+ break;
case PMBUS_OT_FAULT_LIMIT:
ret = mp2975_read_word_helper(client, page, phase, reg,
GENMASK(7, 0));
@@ -260,24 +423,6 @@ static int mp2975_read_word_data(struct i2c_client *client, int page,
ret = DIV_ROUND_CLOSEST(data->vref[page] * 10 - 50 *
(ret + 1) * data->vout_scale, 10);
break;
- case PMBUS_READ_VOUT:
- ret = mp2975_read_word_helper(client, page, phase, reg,
- GENMASK(11, 0));
- if (ret < 0)
- return ret;
-
- /*
- * READ_VOUT can be provided in VID or direct format. The
- * format type is specified by bit 15 of the register
- * MP2975_MFR_DC_LOOP_CTRL. The driver enforces VOUT direct
- * format, since device allows to set the different formats for
- * the different rails and also all VOUT limits registers are
- * provided in a direct format. In case format is VID - convert
- * to direct.
- */
- if (data->vout_format[page] == vid)
- ret = mp2975_vid2direct(info->vrm_version[page], ret);
- break;
case PMBUS_VIRT_READ_POUT_MAX:
ret = mp2975_read_word_helper(client, page, phase,
MP2975_MFR_READ_POUT_PK,
@@ -326,25 +471,25 @@ static int mp2975_read_word_data(struct i2c_client *client, int page,
return ret;
}
-static int mp2975_identify_multiphase_rail2(struct i2c_client *client)
+static int mp2975_identify_multiphase_rail2(struct i2c_client *client,
+ struct mp2975_data *data)
{
int ret;
/*
- * Identify multiphase for rail 2 - could be from 0 to 4.
+ * Identify multiphase for rail 2 - could be from 0 to data->max_phases[1].
* In case phase number is zero – only page zero is supported
*/
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2);
if (ret < 0)
return ret;
- /* Identify multiphase for rail 2 - could be from 0 to 4. */
ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R2);
if (ret < 0)
return ret;
ret &= GENMASK(2, 0);
- return (ret >= 4) ? 4 : ret;
+ return (ret >= data->max_phases[1]) ? data->max_phases[1] : ret;
}
static void mp2975_set_phase_rail1(struct pmbus_driver_info *info)
@@ -375,7 +520,7 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data,
if (ret < 0)
return ret;
- /* Identify multiphase for rail 1 - could be from 1 to 8. */
+ /* Identify multiphase for rail 1 - could be from 1 to data->max_phases[0]. */
ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R1);
if (ret <= 0)
return ret;
@@ -383,21 +528,23 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data,
info->phases[0] = ret & GENMASK(3, 0);
/*
- * The device provides a total of 8 PWM pins, and can be configured
+ * The device provides a total of $n PWM pins, and can be configured
* to different phase count applications for rail 1 and rail 2.
- * Rail 1 can be set to 8 phases, while rail 2 can only be set to 4
- * phases at most. When rail 1’s phase count is configured as 0, rail
+ * Rail 1 can be set to $n phases, while rail 2 can be set to less than
+ * that. When rail 1’s phase count is configured as 0, rail
* 1 operates with 1-phase DCM. When rail 2 phase count is configured
* as 0, rail 2 is disabled.
*/
- if (info->phases[0] > MP2975_MAX_PHASE_RAIL1)
+ if (info->phases[0] > data->max_phases[0])
return -EINVAL;
- mp2975_set_phase_rail1(info);
- num_phases2 = min(MP2975_MAX_PHASE_RAIL1 - info->phases[0],
- MP2975_MAX_PHASE_RAIL2);
- if (info->phases[1] && info->phases[1] <= num_phases2)
- mp2975_set_phase_rail2(info, num_phases2);
+ if (data->chip_id == mp2975) {
+ mp2975_set_phase_rail1(info);
+ num_phases2 = min(data->max_phases[0] - info->phases[0],
+ data->max_phases[1]);
+ if (info->phases[1] && info->phases[1] <= num_phases2)
+ mp2975_set_phase_rail2(info, num_phases2);
+ }
return 0;
}
@@ -451,6 +598,35 @@ mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data,
MP2975_MFR_VR_MULTI_CONFIG_R2, 1,
MP2975_IMVP9_EN_R2,
MP2975_VID_STEP_SEL_R2);
+
+ return ret;
+}
+
+static int
+mp2973_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data,
+ struct pmbus_driver_info *info)
+{
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2);
+ if (ret < 0)
+ return ret;
+
+ /* Identify VID mode for rail 1. */
+ ret = mp2975_identify_vid(client, data, info,
+ MP2973_MFR_VR_MULTI_CONFIG_R1, 0,
+ MP2973_IMVP9_EN_R1, MP2973_VID_STEP_SEL_R1);
+
+ if (ret < 0)
+ return ret;
+
+ /* Identify VID mode for rail 2, if connected. */
+ if (info->phases[1])
+ ret = mp2975_identify_vid(client, data, info,
+ MP2973_MFR_VR_MULTI_CONFIG_R2, 1,
+ MP2973_IMVP9_EN_R2,
+ MP2973_VID_STEP_SEL_R2);
+
return ret;
}
@@ -565,20 +741,37 @@ mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data,
}
static int
-mp2975_identify_vout_format(struct i2c_client *client,
- struct mp2975_data *data, int page)
+mp2975_set_vout_format(struct i2c_client *client,
+ struct mp2975_data *data, int page)
{
- int ret;
+ int ret, i;
- ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL);
- if (ret < 0)
- return ret;
-
- if (ret & MP2975_VOUT_FORMAT)
- data->vout_format[page] = vid;
- else
- data->vout_format[page] = direct;
- return 0;
+ /* Enable DIRECT VOUT format 1mV/LSB */
+ if (data->chip_id == mp2975) {
+ ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL);
+ if (ret < 0)
+ return ret;
+ if (ret & MP2975_VOUT_FORMAT) {
+ ret &= ~MP2975_VOUT_FORMAT;
+ ret = i2c_smbus_write_word_data(client, MP2975_MFR_DC_LOOP_CTRL, ret);
+ }
+ } else {
+ ret = i2c_smbus_read_word_data(client, MP2973_MFR_RESO_SET);
+ if (ret < 0)
+ return ret;
+ i = ret;
+
+ if (page == 0) {
+ i &= ~MP2973_VOUT_FORMAT_R1;
+ i |= MP2973_VOUT_FORMAT_DIRECT_R1;
+ } else {
+ i &= ~MP2973_VOUT_FORMAT_R2;
+ i |= MP2973_VOUT_FORMAT_DIRECT_R2;
+ }
+ if (i != ret)
+ ret = i2c_smbus_write_word_data(client, MP2973_MFR_RESO_SET, i);
+ }
+ return ret;
}
static int
@@ -600,7 +793,7 @@ mp2975_vout_ov_scale_get(struct i2c_client *client, struct mp2975_data *data,
if (ret < 0)
return ret;
thres_dev = ret & MP2975_PRT_THRES_DIV_OV_EN ? MP2975_PROT_DEV_OV_ON :
- MP2975_PROT_DEV_OV_OFF;
+ MP2975_PROT_DEV_OV_OFF;
/* Select the gain of remote sense amplifier. */
ret = i2c_smbus_read_word_data(client, PMBUS_VOUT_SCALE_LOOP);
@@ -624,10 +817,10 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client,
for (i = 0; i < data->info.pages; i++) {
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i);
if (ret < 0)
- return ret;
+ continue;
- /* Obtain voltage reference offsets. */
- ret = mp2975_vref_offset_get(client, data, i);
+ /* Set VOUT format for READ_VOUT command : direct. */
+ ret = mp2975_set_vout_format(client, data, i);
if (ret < 0)
return ret;
@@ -636,12 +829,12 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client,
if (ret < 0)
return ret;
- /*
- * Get VOUT format for READ_VOUT command : VID or direct.
- * Pages on same device can be configured with different
- * formats.
- */
- ret = mp2975_identify_vout_format(client, data, i);
+ /* Skip if reading Vref is unsupported */
+ if (data->chip_id != mp2975)
+ continue;
+
+ /* Obtain voltage reference offsets. */
+ ret = mp2975_vref_offset_get(client, data, i);
if (ret < 0)
return ret;
@@ -676,8 +869,32 @@ static struct pmbus_driver_info mp2975_info = {
PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT |
PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | PMBUS_PHASE_VIRTUAL,
- .read_byte_data = mp2975_read_byte_data,
.read_word_data = mp2975_read_word_data,
+#if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR)
+ .num_regulators = 1,
+ .reg_desc = mp2975_reg_desc,
+#endif
+};
+
+static struct pmbus_driver_info mp2973_info = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = linear,
+ .format[PSC_VOLTAGE_OUT] = direct,
+ .format[PSC_TEMPERATURE] = linear,
+ .format[PSC_CURRENT_IN] = linear,
+ .format[PSC_CURRENT_OUT] = linear,
+ .format[PSC_POWER] = linear,
+ .m[PSC_VOLTAGE_OUT] = 1,
+ .R[PSC_VOLTAGE_OUT] = 3,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
+ PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT |
+ PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
+ .read_word_data = mp2973_read_word_data,
+#if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR)
+ .num_regulators = 1,
+ .reg_desc = mp2975_reg_desc,
+#endif
};
static int mp2975_probe(struct i2c_client *client)
@@ -691,11 +908,23 @@ static int mp2975_probe(struct i2c_client *client)
if (!data)
return -ENOMEM;
- memcpy(&data->info, &mp2975_info, sizeof(*info));
+ if (client->dev.of_node)
+ data->chip_id = (enum chips)(unsigned long)of_device_get_match_data(&client->dev);
+ else
+ data->chip_id = i2c_match_id(mp2975_id, client)->driver_data;
+
+ memcpy(data->max_phases, mp2975_max_phases[data->chip_id],
+ sizeof(data->max_phases));
+
+ if (data->chip_id == mp2975)
+ memcpy(&data->info, &mp2975_info, sizeof(*info));
+ else
+ memcpy(&data->info, &mp2973_info, sizeof(*info));
+
info = &data->info;
/* Identify multiphase configuration for rail 2. */
- ret = mp2975_identify_multiphase_rail2(client);
+ ret = mp2975_identify_multiphase_rail2(client, data);
if (ret < 0)
return ret;
@@ -704,6 +933,8 @@ static int mp2975_probe(struct i2c_client *client)
data->info.pages = MP2975_PAGE_NUM;
data->info.phases[1] = ret;
data->info.func[1] = MP2975_RAIL2_FUNC;
+ if (IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR))
+ data->info.num_regulators = MP2975_PAGE_NUM;
}
/* Identify multiphase configuration. */
@@ -711,25 +942,32 @@ static int mp2975_probe(struct i2c_client *client)
if (ret)
return ret;
- /* Identify VID setting per rail. */
- ret = mp2975_identify_rails_vid(client, data, info);
- if (ret < 0)
- return ret;
+ if (data->chip_id == mp2975) {
+ /* Identify VID setting per rail. */
+ ret = mp2975_identify_rails_vid(client, data, info);
+ if (ret < 0)
+ return ret;
- /* Obtain current sense gain of power stage. */
- ret = mp2975_current_sense_gain_get(client, data);
- if (ret)
- return ret;
+ /* Obtain current sense gain of power stage. */
+ ret = mp2975_current_sense_gain_get(client, data);
+ if (ret)
+ return ret;
- /* Obtain voltage reference values. */
- ret = mp2975_vref_get(client, data, info);
- if (ret)
- return ret;
+ /* Obtain voltage reference values. */
+ ret = mp2975_vref_get(client, data, info);
+ if (ret)
+ return ret;
- /* Obtain vout over-voltage scales. */
- ret = mp2975_vout_ov_scale_get(client, data, info);
- if (ret < 0)
- return ret;
+ /* Obtain vout over-voltage scales. */
+ ret = mp2975_vout_ov_scale_get(client, data, info);
+ if (ret < 0)
+ return ret;
+ } else {
+ /* Identify VID setting per rail. */
+ ret = mp2973_identify_rails_vid(client, data, info);
+ if (ret < 0)
+ return ret;
+ }
/* Obtain offsets, maximum and format for vout. */
ret = mp2975_vout_per_rail_config_get(client, data, info);
@@ -739,15 +977,10 @@ static int mp2975_probe(struct i2c_client *client)
return pmbus_do_probe(client, info);
}
-static const struct i2c_device_id mp2975_id[] = {
- {"mp2975", 0},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, mp2975_id);
-
static const struct of_device_id __maybe_unused mp2975_of_match[] = {
- {.compatible = "mps,mp2975"},
+ {.compatible = "mps,mp2971", .data = (void *)mp2971},
+ {.compatible = "mps,mp2973", .data = (void *)mp2973},
+ {.compatible = "mps,mp2975", .data = (void *)mp2975},
{}
};
MODULE_DEVICE_TABLE(of, mp2975_of_match);
diff --git a/drivers/hwmon/pmbus/mp5023.c b/drivers/hwmon/pmbus/mp5023.c
index c4c4324d2b74..21acb7fd9a1a 100644
--- a/drivers/hwmon/pmbus/mp5023.c
+++ b/drivers/hwmon/pmbus/mp5023.c
@@ -5,7 +5,7 @@
#include <linux/i2c.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include "pmbus.h"
static struct pmbus_driver_info mp5023_info = {
diff --git a/drivers/hwmon/pmbus/mpq7932.c b/drivers/hwmon/pmbus/mpq7932.c
index 865d42edda1a..6c62f01da7c6 100644
--- a/drivers/hwmon/pmbus/mpq7932.c
+++ b/drivers/hwmon/pmbus/mpq7932.c
@@ -12,7 +12,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/pmbus.h>
#include "pmbus.h"
diff --git a/drivers/hwmon/pmbus/pli1209bc.c b/drivers/hwmon/pmbus/pli1209bc.c
index 7d8bd3167b21..c95433790b11 100644
--- a/drivers/hwmon/pmbus/pli1209bc.c
+++ b/drivers/hwmon/pmbus/pli1209bc.c
@@ -5,6 +5,7 @@
* Copyright (c) 2022 9elements GmbH
*/
+#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pmbus.h>
@@ -53,6 +54,30 @@ static int pli1209bc_read_word_data(struct i2c_client *client, int page,
}
}
+static int pli1209bc_write_byte(struct i2c_client *client, int page, u8 reg)
+{
+ int ret;
+
+ switch (reg) {
+ case PMBUS_CLEAR_FAULTS:
+ ret = pmbus_write_byte(client, page, reg);
+ /*
+ * PLI1209 takes 230 usec to execute the CLEAR_FAULTS command.
+ * During that time it's busy and NACKs all requests on the
+ * SMBUS interface. It also NACKs reads on PMBUS_STATUS_BYTE
+ * making it impossible to poll the BUSY flag.
+ *
+ * Just wait for not BUSY unconditionally.
+ */
+ usleep_range(250, 300);
+ break;
+ default:
+ ret = -ENODATA;
+ break;
+ }
+ return ret;
+}
+
#if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR)
static const struct regulator_desc pli1209bc_reg_desc = {
.name = "vout2",
@@ -102,6 +127,7 @@ static struct pmbus_driver_info pli1209bc_info = {
| PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
| PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT,
.read_word_data = pli1209bc_read_word_data,
+ .write_byte = pli1209bc_write_byte,
#if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR)
.num_regulators = 1,
.reg_desc = &pli1209bc_reg_desc,
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index fa06325f5a7c..1363d9f89181 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -561,7 +561,8 @@ static bool pmbus_check_register(struct i2c_client *client,
rv = pmbus_check_status_cml(client);
if (rv < 0 && (data->flags & PMBUS_READ_STATUS_AFTER_FAILED_CHECK))
data->read_status(client, -1);
- pmbus_clear_fault_page(client, -1);
+ if (reg < PMBUS_VIRT_BASE)
+ pmbus_clear_fault_page(client, -1);
return rv >= 0;
}
@@ -2540,7 +2541,6 @@ static int pmbus_identify_common(struct i2c_client *client,
}
}
- pmbus_clear_fault_page(client, page);
return 0;
}
@@ -2745,9 +2745,8 @@ static const struct pmbus_status_category __maybe_unused pmbus_status_flag_map[]
},
};
-static int _pmbus_is_enabled(struct device *dev, u8 page)
+static int _pmbus_is_enabled(struct i2c_client *client, u8 page)
{
- struct i2c_client *client = to_i2c_client(dev->parent);
int ret;
ret = _pmbus_read_byte_data(client, page, PMBUS_OPERATION);
@@ -2758,17 +2757,16 @@ static int _pmbus_is_enabled(struct device *dev, u8 page)
return !!(ret & PB_OPERATION_CONTROL_ON);
}
-static int __maybe_unused pmbus_is_enabled(struct device *dev, u8 page)
+static int __maybe_unused pmbus_is_enabled(struct i2c_client *client, u8 page)
{
- struct i2c_client *client = to_i2c_client(dev->parent);
struct pmbus_data *data = i2c_get_clientdata(client);
int ret;
mutex_lock(&data->update_lock);
- ret = _pmbus_is_enabled(dev, page);
+ ret = _pmbus_is_enabled(client, page);
mutex_unlock(&data->update_lock);
- return !!(ret & PB_OPERATION_CONTROL_ON);
+ return ret;
}
#define to_dev_attr(_dev_attr) \
@@ -2844,7 +2842,7 @@ static int _pmbus_get_flags(struct pmbus_data *data, u8 page, unsigned int *flag
if (status < 0)
return status;
- if (_pmbus_is_enabled(dev, page)) {
+ if (_pmbus_is_enabled(client, page)) {
if (status & PB_STATUS_OFF) {
*flags |= REGULATOR_ERROR_FAIL;
*event |= REGULATOR_EVENT_FAIL;
@@ -2898,7 +2896,10 @@ static int __maybe_unused pmbus_get_flags(struct pmbus_data *data, u8 page, unsi
#if IS_ENABLED(CONFIG_REGULATOR)
static int pmbus_regulator_is_enabled(struct regulator_dev *rdev)
{
- return pmbus_is_enabled(rdev_get_dev(rdev), rdev_get_id(rdev));
+ struct device *dev = rdev_get_dev(rdev);
+ struct i2c_client *client = to_i2c_client(dev->parent);
+
+ return pmbus_is_enabled(client, rdev_get_id(rdev));
}
static int _pmbus_regulator_on_off(struct regulator_dev *rdev, bool enable)
@@ -2945,6 +2946,7 @@ static int pmbus_regulator_get_status(struct regulator_dev *rdev)
struct pmbus_data *data = i2c_get_clientdata(client);
u8 page = rdev_get_id(rdev);
int status, ret;
+ int event;
mutex_lock(&data->update_lock);
status = pmbus_get_status(client, page, PMBUS_STATUS_WORD);
@@ -2964,7 +2966,7 @@ static int pmbus_regulator_get_status(struct regulator_dev *rdev)
goto unlock;
}
- ret = pmbus_regulator_get_error_flags(rdev, &status);
+ ret = _pmbus_get_flags(data, rdev_get_id(rdev), &status, &event, false);
if (ret)
goto unlock;
diff --git a/drivers/hwmon/pmbus/q54sj108a2.c b/drivers/hwmon/pmbus/q54sj108a2.c
index b830f3b02bcc..a235c1cdf4fe 100644
--- a/drivers/hwmon/pmbus/q54sj108a2.c
+++ b/drivers/hwmon/pmbus/q54sj108a2.c
@@ -10,7 +10,7 @@
#include <linux/i2c.h>
#include <linux/kstrtox.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include "pmbus.h"
#define STORE_DEFAULT_ALL 0x11
diff --git a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c
index ef99005a3af5..5c9466244d70 100644
--- a/drivers/hwmon/pmbus/tps53679.c
+++ b/drivers/hwmon/pmbus/tps53679.c
@@ -12,7 +12,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include "pmbus.h"
enum chips {
@@ -235,7 +235,7 @@ static int tps53679_probe(struct i2c_client *client)
enum chips chip_id;
if (dev->of_node)
- chip_id = (enum chips)of_device_get_match_data(dev);
+ chip_id = (uintptr_t)of_device_get_match_data(dev);
else
chip_id = i2c_match_id(tps53679_id, client)->driver_data;
diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c
index c404d306e8f7..8d9d422450e5 100644
--- a/drivers/hwmon/pmbus/ucd9000.c
+++ b/drivers/hwmon/pmbus/ucd9000.c
@@ -10,7 +10,7 @@
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/slab.h>
@@ -588,7 +588,7 @@ static int ucd9000_probe(struct i2c_client *client)
}
if (client->dev.of_node)
- chip = (enum chips)of_device_get_match_data(&client->dev);
+ chip = (uintptr_t)of_device_get_match_data(&client->dev);
else
chip = mid->driver_data;
diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c
index a82847945508..7920d1c06df0 100644
--- a/drivers/hwmon/pmbus/ucd9200.c
+++ b/drivers/hwmon/pmbus/ucd9200.c
@@ -7,7 +7,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/slab.h>
@@ -103,7 +103,7 @@ static int ucd9200_probe(struct i2c_client *client)
}
if (client->dev.of_node)
- chip = (enum chips)of_device_get_match_data(&client->dev);
+ chip = (uintptr_t)of_device_get_match_data(&client->dev);
else
chip = mid->driver_data;
diff --git a/drivers/hwmon/sbtsi_temp.c b/drivers/hwmon/sbtsi_temp.c
index b79cece4ac9a..dd85cf89f008 100644
--- a/drivers/hwmon/sbtsi_temp.c
+++ b/drivers/hwmon/sbtsi_temp.c
@@ -13,7 +13,6 @@
#include <linux/hwmon.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/of_device.h>
#include <linux/of.h>
/*
diff --git a/drivers/hwmon/scpi-hwmon.c b/drivers/hwmon/scpi-hwmon.c
index 121e5e9f487f..a0d220609565 100644
--- a/drivers/hwmon/scpi-hwmon.c
+++ b/drivers/hwmon/scpi-hwmon.c
@@ -8,7 +8,7 @@
#include <linux/hwmon.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/scpi_protocol.h>
#include <linux/slab.h>
diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c
index bf18630619e0..79657910b79e 100644
--- a/drivers/hwmon/sht3x.c
+++ b/drivers/hwmon/sht3x.c
@@ -147,8 +147,20 @@ static const u16 mode_to_update_interval[] = {
100,
};
+static const struct hwmon_channel_info * const sht3x_channel_info[] = {
+ HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL),
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MIN |
+ HWMON_T_MIN_HYST | HWMON_T_MAX |
+ HWMON_T_MAX_HYST | HWMON_T_ALARM),
+ HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT | HWMON_H_MIN |
+ HWMON_H_MIN_HYST | HWMON_H_MAX |
+ HWMON_H_MAX_HYST | HWMON_H_ALARM),
+ NULL,
+};
+
struct sht3x_data {
struct i2c_client *client;
+ enum sht3x_chips chip_id;
struct mutex i2c_lock; /* lock for sending i2c commands */
struct mutex data_lock; /* lock for updating driver data */
@@ -276,27 +288,24 @@ out:
return data;
}
-/* sysfs attributes */
-static ssize_t temp1_input_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static int temp1_input_read(struct device *dev)
{
struct sht3x_data *data = sht3x_update_client(dev);
if (IS_ERR(data))
return PTR_ERR(data);
- return sprintf(buf, "%d\n", data->temperature);
+ return data->temperature;
}
-static ssize_t humidity1_input_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static int humidity1_input_read(struct device *dev)
{
struct sht3x_data *data = sht3x_update_client(dev);
if (IS_ERR(data))
return PTR_ERR(data);
- return sprintf(buf, "%u\n", data->humidity);
+ return data->humidity;
}
/*
@@ -332,33 +341,24 @@ static int limits_update(struct sht3x_data *data)
return ret;
}
-static ssize_t temp1_limit_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int temp1_limit_read(struct device *dev, int index)
{
struct sht3x_data *data = dev_get_drvdata(dev);
- u8 index = to_sensor_dev_attr(attr)->index;
- int temperature_limit = data->temperature_limits[index];
- return sysfs_emit(buf, "%d\n", temperature_limit);
+ return data->temperature_limits[index];
}
-static ssize_t humidity1_limit_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int humidity1_limit_read(struct device *dev, int index)
{
struct sht3x_data *data = dev_get_drvdata(dev);
- u8 index = to_sensor_dev_attr(attr)->index;
- u32 humidity_limit = data->humidity_limits[index];
- return sysfs_emit(buf, "%u\n", humidity_limit);
+ return data->humidity_limits[index];
}
/*
- * limit_store must only be called with data_lock held
+ * limit_write must only be called with data_lock held
*/
-static size_t limit_store(struct device *dev,
- size_t count,
+static size_t limit_write(struct device *dev,
u8 index,
int temperature,
u32 humidity)
@@ -379,7 +379,7 @@ static size_t limit_store(struct device *dev,
* ST = (T + 45) / 175 * 2^16
* SRH = RH / 100 * 2^16
* adapted for fixed point arithmetic and packed the same as
- * in limit_show()
+ * in limit_read()
*/
raw = ((u32)(temperature + 45000) * 24543) >> (16 + 7);
raw |= ((humidity * 42950) >> 16) & 0xfe00;
@@ -400,50 +400,35 @@ static size_t limit_store(struct device *dev,
data->temperature_limits[index] = temperature;
data->humidity_limits[index] = humidity;
- return count;
+
+ return 0;
}
-static ssize_t temp1_limit_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
+static int temp1_limit_write(struct device *dev, int index, int val)
{
int temperature;
int ret;
struct sht3x_data *data = dev_get_drvdata(dev);
- u8 index = to_sensor_dev_attr(attr)->index;
- ret = kstrtoint(buf, 0, &temperature);
- if (ret)
- return ret;
-
- temperature = clamp_val(temperature, SHT3X_MIN_TEMPERATURE,
+ temperature = clamp_val(val, SHT3X_MIN_TEMPERATURE,
SHT3X_MAX_TEMPERATURE);
mutex_lock(&data->data_lock);
- ret = limit_store(dev, count, index, temperature,
+ ret = limit_write(dev, index, temperature,
data->humidity_limits[index]);
mutex_unlock(&data->data_lock);
return ret;
}
-static ssize_t humidity1_limit_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
+static int humidity1_limit_write(struct device *dev, int index, int val)
{
u32 humidity;
int ret;
struct sht3x_data *data = dev_get_drvdata(dev);
- u8 index = to_sensor_dev_attr(attr)->index;
-
- ret = kstrtou32(buf, 0, &humidity);
- if (ret)
- return ret;
- humidity = clamp_val(humidity, SHT3X_MIN_HUMIDITY, SHT3X_MAX_HUMIDITY);
+ humidity = clamp_val(val, SHT3X_MIN_HUMIDITY, SHT3X_MAX_HUMIDITY);
mutex_lock(&data->data_lock);
- ret = limit_store(dev, count, index, data->temperature_limits[index],
+ ret = limit_write(dev, index, data->temperature_limits[index],
humidity);
mutex_unlock(&data->data_lock);
@@ -474,7 +459,6 @@ static void sht3x_select_command(struct sht3x_data *data)
}
static int status_register_read(struct device *dev,
- struct device_attribute *attr,
char *buffer, int length)
{
int ret;
@@ -487,34 +471,30 @@ static int status_register_read(struct device *dev,
return ret;
}
-static ssize_t temp1_alarm_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int temp1_alarm_read(struct device *dev)
{
char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN];
int ret;
- ret = status_register_read(dev, attr, buffer,
+ ret = status_register_read(dev, buffer,
SHT3X_WORD_LEN + SHT3X_CRC8_LEN);
if (ret)
return ret;
- return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x04));
+ return !!(buffer[0] & 0x04);
}
-static ssize_t humidity1_alarm_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int humidity1_alarm_read(struct device *dev)
{
char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN];
int ret;
- ret = status_register_read(dev, attr, buffer,
+ ret = status_register_read(dev, buffer,
SHT3X_WORD_LEN + SHT3X_CRC8_LEN);
if (ret)
return ret;
- return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x08));
+ return !!(buffer[0] & 0x08);
}
static ssize_t heater_enable_show(struct device *dev,
@@ -524,7 +504,7 @@ static ssize_t heater_enable_show(struct device *dev,
char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN];
int ret;
- ret = status_register_read(dev, attr, buffer,
+ ret = status_register_read(dev, buffer,
SHT3X_WORD_LEN + SHT3X_CRC8_LEN);
if (ret)
return ret;
@@ -560,39 +540,28 @@ static ssize_t heater_enable_store(struct device *dev,
return ret;
}
-static ssize_t update_interval_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static int update_interval_read(struct device *dev)
{
struct sht3x_data *data = dev_get_drvdata(dev);
- return sysfs_emit(buf, "%u\n",
- mode_to_update_interval[data->mode]);
+ return mode_to_update_interval[data->mode];
}
-static ssize_t update_interval_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t count)
+static int update_interval_write(struct device *dev, int val)
{
- u16 update_interval;
u8 mode;
int ret;
const char *command;
struct sht3x_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
- ret = kstrtou16(buf, 0, &update_interval);
- if (ret)
- return ret;
-
- mode = get_mode_from_update_interval(update_interval);
+ mode = get_mode_from_update_interval(val);
mutex_lock(&data->data_lock);
/* mode did not change */
if (mode == data->mode) {
mutex_unlock(&data->data_lock);
- return count;
+ return 0;
}
mutex_lock(&data->i2c_lock);
@@ -634,7 +603,7 @@ out:
if (ret != SHT3X_CMD_LENGTH)
return ret < 0 ? ret : -EIO;
- return count;
+ return 0;
}
static ssize_t repeatability_show(struct device *dev,
@@ -668,60 +637,219 @@ static ssize_t repeatability_store(struct device *dev,
return count;
}
-static SENSOR_DEVICE_ATTR_RO(temp1_input, temp1_input, 0);
-static SENSOR_DEVICE_ATTR_RO(humidity1_input, humidity1_input, 0);
-static SENSOR_DEVICE_ATTR_RW(temp1_max, temp1_limit, limit_max);
-static SENSOR_DEVICE_ATTR_RW(humidity1_max, humidity1_limit, limit_max);
-static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp1_limit, limit_max_hyst);
-static SENSOR_DEVICE_ATTR_RW(humidity1_max_hyst, humidity1_limit,
- limit_max_hyst);
-static SENSOR_DEVICE_ATTR_RW(temp1_min, temp1_limit, limit_min);
-static SENSOR_DEVICE_ATTR_RW(humidity1_min, humidity1_limit, limit_min);
-static SENSOR_DEVICE_ATTR_RW(temp1_min_hyst, temp1_limit, limit_min_hyst);
-static SENSOR_DEVICE_ATTR_RW(humidity1_min_hyst, humidity1_limit,
- limit_min_hyst);
-static SENSOR_DEVICE_ATTR_RO(temp1_alarm, temp1_alarm, 0);
-static SENSOR_DEVICE_ATTR_RO(humidity1_alarm, humidity1_alarm, 0);
static SENSOR_DEVICE_ATTR_RW(heater_enable, heater_enable, 0);
-static SENSOR_DEVICE_ATTR_RW(update_interval, update_interval, 0);
static SENSOR_DEVICE_ATTR_RW(repeatability, repeatability, 0);
static struct attribute *sht3x_attrs[] = {
- &sensor_dev_attr_temp1_input.dev_attr.attr,
- &sensor_dev_attr_humidity1_input.dev_attr.attr,
- &sensor_dev_attr_temp1_max.dev_attr.attr,
- &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
- &sensor_dev_attr_humidity1_max.dev_attr.attr,
- &sensor_dev_attr_humidity1_max_hyst.dev_attr.attr,
- &sensor_dev_attr_temp1_min.dev_attr.attr,
- &sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
- &sensor_dev_attr_humidity1_min.dev_attr.attr,
- &sensor_dev_attr_humidity1_min_hyst.dev_attr.attr,
- &sensor_dev_attr_temp1_alarm.dev_attr.attr,
- &sensor_dev_attr_humidity1_alarm.dev_attr.attr,
&sensor_dev_attr_heater_enable.dev_attr.attr,
- &sensor_dev_attr_update_interval.dev_attr.attr,
&sensor_dev_attr_repeatability.dev_attr.attr,
NULL
};
-static struct attribute *sts3x_attrs[] = {
- &sensor_dev_attr_temp1_input.dev_attr.attr,
- &sensor_dev_attr_temp1_max.dev_attr.attr,
- &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
- &sensor_dev_attr_temp1_min.dev_attr.attr,
- &sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
- &sensor_dev_attr_temp1_alarm.dev_attr.attr,
- &sensor_dev_attr_heater_enable.dev_attr.attr,
- &sensor_dev_attr_update_interval.dev_attr.attr,
- &sensor_dev_attr_repeatability.dev_attr.attr,
- NULL
+ATTRIBUTE_GROUPS(sht3x);
+
+static umode_t sht3x_is_visible(const void *data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ const struct sht3x_data *chip_data = data;
+
+ switch (type) {
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_update_interval:
+ return 0644;
+ default:
+ break;
+ }
+ break;
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_alarm:
+ return 0444;
+ case hwmon_temp_max:
+ case hwmon_temp_max_hyst:
+ case hwmon_temp_min:
+ case hwmon_temp_min_hyst:
+ return 0644;
+ default:
+ break;
+ }
+ break;
+ case hwmon_humidity:
+ if (chip_data->chip_id == sts3x)
+ break;
+ switch (attr) {
+ case hwmon_humidity_input:
+ case hwmon_humidity_alarm:
+ return 0444;
+ case hwmon_humidity_max:
+ case hwmon_humidity_max_hyst:
+ case hwmon_humidity_min:
+ case hwmon_humidity_min_hyst:
+ return 0644;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int sht3x_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ enum sht3x_limits index;
+
+ switch (type) {
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_update_interval:
+ *val = update_interval_read(dev);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ break;
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ *val = temp1_input_read(dev);
+ break;
+ case hwmon_temp_alarm:
+ *val = temp1_alarm_read(dev);
+ break;
+ case hwmon_temp_max:
+ index = limit_max;
+ *val = temp1_limit_read(dev, index);
+ break;
+ case hwmon_temp_max_hyst:
+ index = limit_max_hyst;
+ *val = temp1_limit_read(dev, index);
+ break;
+ case hwmon_temp_min:
+ index = limit_min;
+ *val = temp1_limit_read(dev, index);
+ break;
+ case hwmon_temp_min_hyst:
+ index = limit_min_hyst;
+ *val = temp1_limit_read(dev, index);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ break;
+ case hwmon_humidity:
+ switch (attr) {
+ case hwmon_humidity_input:
+ *val = humidity1_input_read(dev);
+ break;
+ case hwmon_humidity_alarm:
+ *val = humidity1_alarm_read(dev);
+ break;
+ case hwmon_humidity_max:
+ index = limit_max;
+ *val = humidity1_limit_read(dev, index);
+ break;
+ case hwmon_humidity_max_hyst:
+ index = limit_max_hyst;
+ *val = humidity1_limit_read(dev, index);
+ break;
+ case hwmon_humidity_min:
+ index = limit_min;
+ *val = humidity1_limit_read(dev, index);
+ break;
+ case hwmon_humidity_min_hyst:
+ index = limit_min_hyst;
+ *val = humidity1_limit_read(dev, index);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int sht3x_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ enum sht3x_limits index;
+
+ switch (type) {
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_update_interval:
+ return update_interval_write(dev, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_max:
+ index = limit_max;
+ break;
+ case hwmon_temp_max_hyst:
+ index = limit_max_hyst;
+ break;
+ case hwmon_temp_min:
+ index = limit_min;
+ break;
+ case hwmon_temp_min_hyst:
+ index = limit_min_hyst;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return temp1_limit_write(dev, index, val);
+ case hwmon_humidity:
+ switch (attr) {
+ case hwmon_humidity_max:
+ index = limit_max;
+ break;
+ case hwmon_humidity_max_hyst:
+ index = limit_max_hyst;
+ break;
+ case hwmon_humidity_min:
+ index = limit_min;
+ break;
+ case hwmon_humidity_min_hyst:
+ index = limit_min_hyst;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return humidity1_limit_write(dev, index, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static const struct hwmon_ops sht3x_ops = {
+ .is_visible = sht3x_is_visible,
+ .read = sht3x_read,
+ .write = sht3x_write,
};
-ATTRIBUTE_GROUPS(sht3x);
-ATTRIBUTE_GROUPS(sts3x);
+static const struct hwmon_chip_info sht3x_chip_info = {
+ .ops = &sht3x_ops,
+ .info = sht3x_channel_info,
+};
+
+/* device ID table */
+static const struct i2c_device_id sht3x_ids[] = {
+ {"sht3x", sht3x},
+ {"sts3x", sts3x},
+ {}
+};
-static const struct i2c_device_id sht3x_ids[];
+MODULE_DEVICE_TABLE(i2c, sht3x_ids);
static int sht3x_probe(struct i2c_client *client)
{
@@ -730,7 +858,6 @@ static int sht3x_probe(struct i2c_client *client)
struct device *hwmon_dev;
struct i2c_adapter *adap = client->adapter;
struct device *dev = &client->dev;
- const struct attribute_group **attribute_groups;
/*
* we require full i2c support since the sht3x uses multi-byte read and
@@ -753,6 +880,7 @@ static int sht3x_probe(struct i2c_client *client)
data->mode = 0;
data->last_update = jiffies - msecs_to_jiffies(3000);
data->client = client;
+ data->chip_id = i2c_match_id(sht3x_ids, client)->driver_data;
crc8_populate_msb(sht3x_crc8_table, SHT3X_CRC8_POLYNOMIAL);
sht3x_select_command(data);
@@ -771,15 +899,11 @@ static int sht3x_probe(struct i2c_client *client)
if (ret)
return ret;
- if (i2c_match_id(sht3x_ids, client)->driver_data == sts3x)
- attribute_groups = sts3x_groups;
- else
- attribute_groups = sht3x_groups;
-
- hwmon_dev = devm_hwmon_device_register_with_groups(dev,
- client->name,
- data,
- attribute_groups);
+ hwmon_dev = devm_hwmon_device_register_with_info(dev,
+ client->name,
+ data,
+ &sht3x_chip_info,
+ sht3x_groups);
if (IS_ERR(hwmon_dev))
dev_dbg(dev, "unable to register hwmon device\n");
@@ -787,15 +911,6 @@ static int sht3x_probe(struct i2c_client *client)
return PTR_ERR_OR_ZERO(hwmon_dev);
}
-/* device ID table */
-static const struct i2c_device_id sht3x_ids[] = {
- {"sht3x", sht3x},
- {"sts3x", sts3x},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, sht3x_ids);
-
static struct i2c_driver sht3x_i2c_driver = {
.driver.name = "sht3x",
.probe = sht3x_probe,
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index b0b05fd12221..0a0479501e11 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -798,7 +798,7 @@ static int sis5595_pci_probe(struct pci_dev *dev,
{
u16 address;
u8 enable;
- int *i;
+ int *i, err;
for (i = blacklist; *i != 0; i++) {
struct pci_dev *d;
@@ -818,8 +818,8 @@ static int sis5595_pci_probe(struct pci_dev *dev,
pci_write_config_word(dev, SIS5595_BASE_REG, force_addr);
}
- if (PCIBIOS_SUCCESSFUL !=
- pci_read_config_word(dev, SIS5595_BASE_REG, &address)) {
+ err = pci_read_config_word(dev, SIS5595_BASE_REG, &address);
+ if (err != PCIBIOS_SUCCESSFUL) {
dev_err(&dev->dev, "Failed to read ISA address\n");
return -ENODEV;
}
@@ -836,22 +836,23 @@ static int sis5595_pci_probe(struct pci_dev *dev,
return -ENODEV;
}
- if (PCIBIOS_SUCCESSFUL !=
- pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable)) {
+ err = pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable);
+ if (err != PCIBIOS_SUCCESSFUL) {
dev_err(&dev->dev, "Failed to read enable register\n");
return -ENODEV;
}
if (!(enable & 0x80)) {
- if ((PCIBIOS_SUCCESSFUL !=
- pci_write_config_byte(dev, SIS5595_ENABLE_REG,
- enable | 0x80))
- || (PCIBIOS_SUCCESSFUL !=
- pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable))
- || (!(enable & 0x80))) {
- /* doesn't work for some chips! */
- dev_err(&dev->dev, "Failed to enable HWM device\n");
- return -ENODEV;
- }
+ err = pci_write_config_byte(dev, SIS5595_ENABLE_REG, enable | 0x80);
+ if (err != PCIBIOS_SUCCESSFUL)
+ goto enable_fail;
+
+ err = pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable);
+ if (err != PCIBIOS_SUCCESSFUL)
+ goto enable_fail;
+
+ /* doesn't work for some chips! */
+ if (!(enable & 0x80))
+ goto enable_fail;
}
if (platform_driver_register(&sis5595_driver)) {
@@ -871,6 +872,10 @@ static int sis5595_pci_probe(struct pci_dev *dev,
*/
return -ENODEV;
+enable_fail:
+ dev_err(&dev->dev, "Failed to enable HWM device\n");
+ goto exit;
+
exit_unregister:
pci_dev_put(dev);
platform_driver_unregister(&sis5595_driver);
diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c
deleted file mode 100644
index 026c76f8c22e..000000000000
--- a/drivers/hwmon/smm665.c
+++ /dev/null
@@ -1,706 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Driver for SMM665 Power Controller / Monitor
- *
- * Copyright (C) 2010 Ericsson AB.
- *
- * This driver should also work for SMM465, SMM764, and SMM766, but is untested
- * for those chips. Only monitoring functionality is implemented.
- *
- * Datasheets:
- * http://www.summitmicro.com/prod_select/summary/SMM665/SMM665B_2089_20.pdf
- * http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/delay.h>
-#include <linux/jiffies.h>
-
-/* Internal reference voltage (VREF, x 1000 */
-#define SMM665_VREF_ADC_X1000 1250
-
-/* module parameters */
-static int vref = SMM665_VREF_ADC_X1000;
-module_param(vref, int, 0);
-MODULE_PARM_DESC(vref, "Reference voltage in mV");
-
-enum chips { smm465, smm665, smm665c, smm764, smm766 };
-
-/*
- * ADC channel addresses
- */
-#define SMM665_MISC16_ADC_DATA_A 0x00
-#define SMM665_MISC16_ADC_DATA_B 0x01
-#define SMM665_MISC16_ADC_DATA_C 0x02
-#define SMM665_MISC16_ADC_DATA_D 0x03
-#define SMM665_MISC16_ADC_DATA_E 0x04
-#define SMM665_MISC16_ADC_DATA_F 0x05
-#define SMM665_MISC16_ADC_DATA_VDD 0x06
-#define SMM665_MISC16_ADC_DATA_12V 0x07
-#define SMM665_MISC16_ADC_DATA_INT_TEMP 0x08
-#define SMM665_MISC16_ADC_DATA_AIN1 0x09
-#define SMM665_MISC16_ADC_DATA_AIN2 0x0a
-
-/*
- * Command registers
- */
-#define SMM665_MISC8_CMD_STS 0x80
-#define SMM665_MISC8_STATUS1 0x81
-#define SMM665_MISC8_STATUSS2 0x82
-#define SMM665_MISC8_IO_POLARITY 0x83
-#define SMM665_MISC8_PUP_POLARITY 0x84
-#define SMM665_MISC8_ADOC_STATUS1 0x85
-#define SMM665_MISC8_ADOC_STATUS2 0x86
-#define SMM665_MISC8_WRITE_PROT 0x87
-#define SMM665_MISC8_STS_TRACK 0x88
-
-/*
- * Configuration registers and register groups
- */
-#define SMM665_ADOC_ENABLE 0x0d
-#define SMM665_LIMIT_BASE 0x80 /* First limit register */
-
-/*
- * Limit register bit masks
- */
-#define SMM665_TRIGGER_RST 0x8000
-#define SMM665_TRIGGER_HEALTHY 0x4000
-#define SMM665_TRIGGER_POWEROFF 0x2000
-#define SMM665_TRIGGER_SHUTDOWN 0x1000
-#define SMM665_ADC_MASK 0x03ff
-
-#define smm665_is_critical(lim) ((lim) & (SMM665_TRIGGER_RST \
- | SMM665_TRIGGER_POWEROFF \
- | SMM665_TRIGGER_SHUTDOWN))
-/*
- * Fault register bit definitions
- * Values are merged from status registers 1/2,
- * with status register 1 providing the upper 8 bits.
- */
-#define SMM665_FAULT_A 0x0001
-#define SMM665_FAULT_B 0x0002
-#define SMM665_FAULT_C 0x0004
-#define SMM665_FAULT_D 0x0008
-#define SMM665_FAULT_E 0x0010
-#define SMM665_FAULT_F 0x0020
-#define SMM665_FAULT_VDD 0x0040
-#define SMM665_FAULT_12V 0x0080
-#define SMM665_FAULT_TEMP 0x0100
-#define SMM665_FAULT_AIN1 0x0200
-#define SMM665_FAULT_AIN2 0x0400
-
-/*
- * I2C Register addresses
- *
- * The configuration register needs to be the configured base register.
- * The command/status register address is derived from it.
- */
-#define SMM665_REGMASK 0x78
-#define SMM665_CMDREG_BASE 0x48
-#define SMM665_CONFREG_BASE 0x50
-
-/*
- * Equations given by chip manufacturer to calculate voltage/temperature values
- * vref = Reference voltage on VREF_ADC pin (module parameter)
- * adc = 10bit ADC value read back from registers
- */
-
-/* Voltage A-F and VDD */
-#define SMM665_VMON_ADC_TO_VOLTS(adc) ((adc) * vref / 256)
-
-/* Voltage 12VIN */
-#define SMM665_12VIN_ADC_TO_VOLTS(adc) ((adc) * vref * 3 / 256)
-
-/* Voltage AIN1, AIN2 */
-#define SMM665_AIN_ADC_TO_VOLTS(adc) ((adc) * vref / 512)
-
-/* Temp Sensor */
-#define SMM665_TEMP_ADC_TO_CELSIUS(adc) (((adc) <= 511) ? \
- ((int)(adc) * 1000 / 4) : \
- (((int)(adc) - 0x400) * 1000 / 4))
-
-#define SMM665_NUM_ADC 11
-
-/*
- * Chip dependent ADC conversion time, in uS
- */
-#define SMM665_ADC_WAIT_SMM665 70
-#define SMM665_ADC_WAIT_SMM766 185
-
-struct smm665_data {
- enum chips type;
- int conversion_time; /* ADC conversion time */
- struct i2c_client *client;
- struct mutex update_lock;
- bool valid;
- unsigned long last_updated; /* in jiffies */
- u16 adc[SMM665_NUM_ADC]; /* adc values (raw) */
- u16 faults; /* fault status */
- /* The following values are in mV */
- int critical_min_limit[SMM665_NUM_ADC];
- int alarm_min_limit[SMM665_NUM_ADC];
- int critical_max_limit[SMM665_NUM_ADC];
- int alarm_max_limit[SMM665_NUM_ADC];
- struct i2c_client *cmdreg;
-};
-
-/*
- * smm665_read16()
- *
- * Read 16 bit value from <reg>, <reg+1>. Upper 8 bits are in <reg>.
- */
-static int smm665_read16(struct i2c_client *client, int reg)
-{
- int rv, val;
-
- rv = i2c_smbus_read_byte_data(client, reg);
- if (rv < 0)
- return rv;
- val = rv << 8;
- rv = i2c_smbus_read_byte_data(client, reg + 1);
- if (rv < 0)
- return rv;
- val |= rv;
- return val;
-}
-
-/*
- * Read adc value.
- */
-static int smm665_read_adc(struct smm665_data *data, int adc)
-{
- struct i2c_client *client = data->cmdreg;
- int rv;
- int radc;
-
- /*
- * Algorithm for reading ADC, per SMM665 datasheet
- *
- * {[S][addr][W][Ack]} {[offset][Ack]} {[S][addr][R][Nack]}
- * [wait conversion time]
- * {[S][addr][R][Ack]} {[datahi][Ack]} {[datalo][Ack][P]}
- *
- * To implement the first part of this exchange,
- * do a full read transaction and expect a failure/Nack.
- * This sets up the address pointer on the SMM665
- * and starts the ADC conversion.
- * Then do a two-byte read transaction.
- */
- rv = i2c_smbus_read_byte_data(client, adc << 3);
- if (rv != -ENXIO) {
- /*
- * We expect ENXIO to reflect NACK
- * (per Documentation/i2c/fault-codes.rst).
- * Everything else is an error.
- */
- dev_dbg(&client->dev,
- "Unexpected return code %d when setting ADC index", rv);
- return (rv < 0) ? rv : -EIO;
- }
-
- udelay(data->conversion_time);
-
- /*
- * Now read two bytes.
- *
- * Neither i2c_smbus_read_byte() nor
- * i2c_smbus_read_block_data() worked here,
- * so use i2c_smbus_read_word_swapped() instead.
- * We could also try to use i2c_master_recv(),
- * but that is not always supported.
- */
- rv = i2c_smbus_read_word_swapped(client, 0);
- if (rv < 0) {
- dev_dbg(&client->dev, "Failed to read ADC value: error %d", rv);
- return rv;
- }
- /*
- * Validate/verify readback adc channel (in bit 11..14).
- */
- radc = (rv >> 11) & 0x0f;
- if (radc != adc) {
- dev_dbg(&client->dev, "Unexpected RADC: Expected %d got %d",
- adc, radc);
- return -EIO;
- }
-
- return rv & SMM665_ADC_MASK;
-}
-
-static struct smm665_data *smm665_update_device(struct device *dev)
-{
- struct smm665_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- struct smm665_data *ret = data;
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
- int i, val;
-
- /*
- * read status registers
- */
- val = smm665_read16(client, SMM665_MISC8_STATUS1);
- if (unlikely(val < 0)) {
- ret = ERR_PTR(val);
- goto abort;
- }
- data->faults = val;
-
- /* Read adc registers */
- for (i = 0; i < SMM665_NUM_ADC; i++) {
- val = smm665_read_adc(data, i);
- if (unlikely(val < 0)) {
- ret = ERR_PTR(val);
- goto abort;
- }
- data->adc[i] = val;
- }
- data->last_updated = jiffies;
- data->valid = true;
- }
-abort:
- mutex_unlock(&data->update_lock);
- return ret;
-}
-
-/* Return converted value from given adc */
-static int smm665_convert(u16 adcval, int index)
-{
- int val = 0;
-
- switch (index) {
- case SMM665_MISC16_ADC_DATA_12V:
- val = SMM665_12VIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK);
- break;
-
- case SMM665_MISC16_ADC_DATA_VDD:
- case SMM665_MISC16_ADC_DATA_A:
- case SMM665_MISC16_ADC_DATA_B:
- case SMM665_MISC16_ADC_DATA_C:
- case SMM665_MISC16_ADC_DATA_D:
- case SMM665_MISC16_ADC_DATA_E:
- case SMM665_MISC16_ADC_DATA_F:
- val = SMM665_VMON_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK);
- break;
-
- case SMM665_MISC16_ADC_DATA_AIN1:
- case SMM665_MISC16_ADC_DATA_AIN2:
- val = SMM665_AIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK);
- break;
-
- case SMM665_MISC16_ADC_DATA_INT_TEMP:
- val = SMM665_TEMP_ADC_TO_CELSIUS(adcval & SMM665_ADC_MASK);
- break;
-
- default:
- /* If we get here, the developer messed up */
- WARN_ON_ONCE(1);
- break;
- }
-
- return val;
-}
-
-static int smm665_get_min(struct device *dev, int index)
-{
- struct smm665_data *data = dev_get_drvdata(dev);
-
- return data->alarm_min_limit[index];
-}
-
-static int smm665_get_max(struct device *dev, int index)
-{
- struct smm665_data *data = dev_get_drvdata(dev);
-
- return data->alarm_max_limit[index];
-}
-
-static int smm665_get_lcrit(struct device *dev, int index)
-{
- struct smm665_data *data = dev_get_drvdata(dev);
-
- return data->critical_min_limit[index];
-}
-
-static int smm665_get_crit(struct device *dev, int index)
-{
- struct smm665_data *data = dev_get_drvdata(dev);
-
- return data->critical_max_limit[index];
-}
-
-static ssize_t smm665_show_crit_alarm(struct device *dev,
- struct device_attribute *da, char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct smm665_data *data = smm665_update_device(dev);
- int val = 0;
-
- if (IS_ERR(data))
- return PTR_ERR(data);
-
- if (data->faults & (1 << attr->index))
- val = 1;
-
- return sysfs_emit(buf, "%d\n", val);
-}
-
-static ssize_t smm665_show_input(struct device *dev,
- struct device_attribute *da, char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct smm665_data *data = smm665_update_device(dev);
- int adc = attr->index;
- int val;
-
- if (IS_ERR(data))
- return PTR_ERR(data);
-
- val = smm665_convert(data->adc[adc], adc);
- return sysfs_emit(buf, "%d\n", val);
-}
-
-#define SMM665_SHOW(what) \
-static ssize_t smm665_show_##what(struct device *dev, \
- struct device_attribute *da, char *buf) \
-{ \
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
- const int val = smm665_get_##what(dev, attr->index); \
- return snprintf(buf, PAGE_SIZE, "%d\n", val); \
-}
-
-SMM665_SHOW(min);
-SMM665_SHOW(max);
-SMM665_SHOW(lcrit);
-SMM665_SHOW(crit);
-
-/*
- * These macros are used below in constructing device attribute objects
- * for use with sysfs_create_group() to make a sysfs device file
- * for each register.
- */
-
-#define SMM665_ATTR(name, type, cmd_idx) \
- static SENSOR_DEVICE_ATTR(name##_##type, S_IRUGO, \
- smm665_show_##type, NULL, cmd_idx)
-
-/* Construct a sensor_device_attribute structure for each register */
-
-/* Input voltages */
-SMM665_ATTR(in1, input, SMM665_MISC16_ADC_DATA_12V);
-SMM665_ATTR(in2, input, SMM665_MISC16_ADC_DATA_VDD);
-SMM665_ATTR(in3, input, SMM665_MISC16_ADC_DATA_A);
-SMM665_ATTR(in4, input, SMM665_MISC16_ADC_DATA_B);
-SMM665_ATTR(in5, input, SMM665_MISC16_ADC_DATA_C);
-SMM665_ATTR(in6, input, SMM665_MISC16_ADC_DATA_D);
-SMM665_ATTR(in7, input, SMM665_MISC16_ADC_DATA_E);
-SMM665_ATTR(in8, input, SMM665_MISC16_ADC_DATA_F);
-SMM665_ATTR(in9, input, SMM665_MISC16_ADC_DATA_AIN1);
-SMM665_ATTR(in10, input, SMM665_MISC16_ADC_DATA_AIN2);
-
-/* Input voltages min */
-SMM665_ATTR(in1, min, SMM665_MISC16_ADC_DATA_12V);
-SMM665_ATTR(in2, min, SMM665_MISC16_ADC_DATA_VDD);
-SMM665_ATTR(in3, min, SMM665_MISC16_ADC_DATA_A);
-SMM665_ATTR(in4, min, SMM665_MISC16_ADC_DATA_B);
-SMM665_ATTR(in5, min, SMM665_MISC16_ADC_DATA_C);
-SMM665_ATTR(in6, min, SMM665_MISC16_ADC_DATA_D);
-SMM665_ATTR(in7, min, SMM665_MISC16_ADC_DATA_E);
-SMM665_ATTR(in8, min, SMM665_MISC16_ADC_DATA_F);
-SMM665_ATTR(in9, min, SMM665_MISC16_ADC_DATA_AIN1);
-SMM665_ATTR(in10, min, SMM665_MISC16_ADC_DATA_AIN2);
-
-/* Input voltages max */
-SMM665_ATTR(in1, max, SMM665_MISC16_ADC_DATA_12V);
-SMM665_ATTR(in2, max, SMM665_MISC16_ADC_DATA_VDD);
-SMM665_ATTR(in3, max, SMM665_MISC16_ADC_DATA_A);
-SMM665_ATTR(in4, max, SMM665_MISC16_ADC_DATA_B);
-SMM665_ATTR(in5, max, SMM665_MISC16_ADC_DATA_C);
-SMM665_ATTR(in6, max, SMM665_MISC16_ADC_DATA_D);
-SMM665_ATTR(in7, max, SMM665_MISC16_ADC_DATA_E);
-SMM665_ATTR(in8, max, SMM665_MISC16_ADC_DATA_F);
-SMM665_ATTR(in9, max, SMM665_MISC16_ADC_DATA_AIN1);
-SMM665_ATTR(in10, max, SMM665_MISC16_ADC_DATA_AIN2);
-
-/* Input voltages lcrit */
-SMM665_ATTR(in1, lcrit, SMM665_MISC16_ADC_DATA_12V);
-SMM665_ATTR(in2, lcrit, SMM665_MISC16_ADC_DATA_VDD);
-SMM665_ATTR(in3, lcrit, SMM665_MISC16_ADC_DATA_A);
-SMM665_ATTR(in4, lcrit, SMM665_MISC16_ADC_DATA_B);
-SMM665_ATTR(in5, lcrit, SMM665_MISC16_ADC_DATA_C);
-SMM665_ATTR(in6, lcrit, SMM665_MISC16_ADC_DATA_D);
-SMM665_ATTR(in7, lcrit, SMM665_MISC16_ADC_DATA_E);
-SMM665_ATTR(in8, lcrit, SMM665_MISC16_ADC_DATA_F);
-SMM665_ATTR(in9, lcrit, SMM665_MISC16_ADC_DATA_AIN1);
-SMM665_ATTR(in10, lcrit, SMM665_MISC16_ADC_DATA_AIN2);
-
-/* Input voltages crit */
-SMM665_ATTR(in1, crit, SMM665_MISC16_ADC_DATA_12V);
-SMM665_ATTR(in2, crit, SMM665_MISC16_ADC_DATA_VDD);
-SMM665_ATTR(in3, crit, SMM665_MISC16_ADC_DATA_A);
-SMM665_ATTR(in4, crit, SMM665_MISC16_ADC_DATA_B);
-SMM665_ATTR(in5, crit, SMM665_MISC16_ADC_DATA_C);
-SMM665_ATTR(in6, crit, SMM665_MISC16_ADC_DATA_D);
-SMM665_ATTR(in7, crit, SMM665_MISC16_ADC_DATA_E);
-SMM665_ATTR(in8, crit, SMM665_MISC16_ADC_DATA_F);
-SMM665_ATTR(in9, crit, SMM665_MISC16_ADC_DATA_AIN1);
-SMM665_ATTR(in10, crit, SMM665_MISC16_ADC_DATA_AIN2);
-
-/* critical alarms */
-SMM665_ATTR(in1, crit_alarm, SMM665_FAULT_12V);
-SMM665_ATTR(in2, crit_alarm, SMM665_FAULT_VDD);
-SMM665_ATTR(in3, crit_alarm, SMM665_FAULT_A);
-SMM665_ATTR(in4, crit_alarm, SMM665_FAULT_B);
-SMM665_ATTR(in5, crit_alarm, SMM665_FAULT_C);
-SMM665_ATTR(in6, crit_alarm, SMM665_FAULT_D);
-SMM665_ATTR(in7, crit_alarm, SMM665_FAULT_E);
-SMM665_ATTR(in8, crit_alarm, SMM665_FAULT_F);
-SMM665_ATTR(in9, crit_alarm, SMM665_FAULT_AIN1);
-SMM665_ATTR(in10, crit_alarm, SMM665_FAULT_AIN2);
-
-/* Temperature */
-SMM665_ATTR(temp1, input, SMM665_MISC16_ADC_DATA_INT_TEMP);
-SMM665_ATTR(temp1, min, SMM665_MISC16_ADC_DATA_INT_TEMP);
-SMM665_ATTR(temp1, max, SMM665_MISC16_ADC_DATA_INT_TEMP);
-SMM665_ATTR(temp1, lcrit, SMM665_MISC16_ADC_DATA_INT_TEMP);
-SMM665_ATTR(temp1, crit, SMM665_MISC16_ADC_DATA_INT_TEMP);
-SMM665_ATTR(temp1, crit_alarm, SMM665_FAULT_TEMP);
-
-/*
- * Finally, construct an array of pointers to members of the above objects,
- * as required for sysfs_create_group()
- */
-static struct attribute *smm665_attrs[] = {
- &sensor_dev_attr_in1_input.dev_attr.attr,
- &sensor_dev_attr_in1_min.dev_attr.attr,
- &sensor_dev_attr_in1_max.dev_attr.attr,
- &sensor_dev_attr_in1_lcrit.dev_attr.attr,
- &sensor_dev_attr_in1_crit.dev_attr.attr,
- &sensor_dev_attr_in1_crit_alarm.dev_attr.attr,
-
- &sensor_dev_attr_in2_input.dev_attr.attr,
- &sensor_dev_attr_in2_min.dev_attr.attr,
- &sensor_dev_attr_in2_max.dev_attr.attr,
- &sensor_dev_attr_in2_lcrit.dev_attr.attr,
- &sensor_dev_attr_in2_crit.dev_attr.attr,
- &sensor_dev_attr_in2_crit_alarm.dev_attr.attr,
-
- &sensor_dev_attr_in3_input.dev_attr.attr,
- &sensor_dev_attr_in3_min.dev_attr.attr,
- &sensor_dev_attr_in3_max.dev_attr.attr,
- &sensor_dev_attr_in3_lcrit.dev_attr.attr,
- &sensor_dev_attr_in3_crit.dev_attr.attr,
- &sensor_dev_attr_in3_crit_alarm.dev_attr.attr,
-
- &sensor_dev_attr_in4_input.dev_attr.attr,
- &sensor_dev_attr_in4_min.dev_attr.attr,
- &sensor_dev_attr_in4_max.dev_attr.attr,
- &sensor_dev_attr_in4_lcrit.dev_attr.attr,
- &sensor_dev_attr_in4_crit.dev_attr.attr,
- &sensor_dev_attr_in4_crit_alarm.dev_attr.attr,
-
- &sensor_dev_attr_in5_input.dev_attr.attr,
- &sensor_dev_attr_in5_min.dev_attr.attr,
- &sensor_dev_attr_in5_max.dev_attr.attr,
- &sensor_dev_attr_in5_lcrit.dev_attr.attr,
- &sensor_dev_attr_in5_crit.dev_attr.attr,
- &sensor_dev_attr_in5_crit_alarm.dev_attr.attr,
-
- &sensor_dev_attr_in6_input.dev_attr.attr,
- &sensor_dev_attr_in6_min.dev_attr.attr,
- &sensor_dev_attr_in6_max.dev_attr.attr,
- &sensor_dev_attr_in6_lcrit.dev_attr.attr,
- &sensor_dev_attr_in6_crit.dev_attr.attr,
- &sensor_dev_attr_in6_crit_alarm.dev_attr.attr,
-
- &sensor_dev_attr_in7_input.dev_attr.attr,
- &sensor_dev_attr_in7_min.dev_attr.attr,
- &sensor_dev_attr_in7_max.dev_attr.attr,
- &sensor_dev_attr_in7_lcrit.dev_attr.attr,
- &sensor_dev_attr_in7_crit.dev_attr.attr,
- &sensor_dev_attr_in7_crit_alarm.dev_attr.attr,
-
- &sensor_dev_attr_in8_input.dev_attr.attr,
- &sensor_dev_attr_in8_min.dev_attr.attr,
- &sensor_dev_attr_in8_max.dev_attr.attr,
- &sensor_dev_attr_in8_lcrit.dev_attr.attr,
- &sensor_dev_attr_in8_crit.dev_attr.attr,
- &sensor_dev_attr_in8_crit_alarm.dev_attr.attr,
-
- &sensor_dev_attr_in9_input.dev_attr.attr,
- &sensor_dev_attr_in9_min.dev_attr.attr,
- &sensor_dev_attr_in9_max.dev_attr.attr,
- &sensor_dev_attr_in9_lcrit.dev_attr.attr,
- &sensor_dev_attr_in9_crit.dev_attr.attr,
- &sensor_dev_attr_in9_crit_alarm.dev_attr.attr,
-
- &sensor_dev_attr_in10_input.dev_attr.attr,
- &sensor_dev_attr_in10_min.dev_attr.attr,
- &sensor_dev_attr_in10_max.dev_attr.attr,
- &sensor_dev_attr_in10_lcrit.dev_attr.attr,
- &sensor_dev_attr_in10_crit.dev_attr.attr,
- &sensor_dev_attr_in10_crit_alarm.dev_attr.attr,
-
- &sensor_dev_attr_temp1_input.dev_attr.attr,
- &sensor_dev_attr_temp1_min.dev_attr.attr,
- &sensor_dev_attr_temp1_max.dev_attr.attr,
- &sensor_dev_attr_temp1_lcrit.dev_attr.attr,
- &sensor_dev_attr_temp1_crit.dev_attr.attr,
- &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
-
- NULL,
-};
-
-ATTRIBUTE_GROUPS(smm665);
-
-static const struct i2c_device_id smm665_id[];
-
-static int smm665_probe(struct i2c_client *client)
-{
- struct i2c_adapter *adapter = client->adapter;
- struct smm665_data *data;
- struct device *hwmon_dev;
- int i, ret;
-
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
- | I2C_FUNC_SMBUS_WORD_DATA))
- return -ENODEV;
-
- if (i2c_smbus_read_byte_data(client, SMM665_ADOC_ENABLE) < 0)
- return -ENODEV;
-
- data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- i2c_set_clientdata(client, data);
- mutex_init(&data->update_lock);
-
- data->client = client;
- data->type = i2c_match_id(smm665_id, client)->driver_data;
- data->cmdreg = i2c_new_dummy_device(adapter, (client->addr & ~SMM665_REGMASK)
- | SMM665_CMDREG_BASE);
- if (IS_ERR(data->cmdreg))
- return PTR_ERR(data->cmdreg);
-
- switch (data->type) {
- case smm465:
- case smm665:
- data->conversion_time = SMM665_ADC_WAIT_SMM665;
- break;
- case smm665c:
- case smm764:
- case smm766:
- data->conversion_time = SMM665_ADC_WAIT_SMM766;
- break;
- }
-
- ret = -ENODEV;
- if (i2c_smbus_read_byte_data(data->cmdreg, SMM665_MISC8_CMD_STS) < 0)
- goto out_unregister;
-
- /*
- * Read limits.
- *
- * Limit registers start with register SMM665_LIMIT_BASE.
- * Each channel uses 8 registers, providing four limit values
- * per channel. Each limit value requires two registers, with the
- * high byte in the first register and the low byte in the second
- * register. The first two limits are under limit values, followed
- * by two over limit values.
- *
- * Limit register order matches the ADC register order, so we use
- * ADC register defines throughout the code to index limit registers.
- *
- * We save the first retrieved value both as "critical" and "alarm"
- * value. The second value overwrites either the critical or the
- * alarm value, depending on its configuration. This ensures that both
- * critical and alarm values are initialized, even if both registers are
- * configured as critical or non-critical.
- */
- for (i = 0; i < SMM665_NUM_ADC; i++) {
- int val;
-
- val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8);
- if (unlikely(val < 0))
- goto out_unregister;
- data->critical_min_limit[i] = data->alarm_min_limit[i]
- = smm665_convert(val, i);
- val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 2);
- if (unlikely(val < 0))
- goto out_unregister;
- if (smm665_is_critical(val))
- data->critical_min_limit[i] = smm665_convert(val, i);
- else
- data->alarm_min_limit[i] = smm665_convert(val, i);
- val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 4);
- if (unlikely(val < 0))
- goto out_unregister;
- data->critical_max_limit[i] = data->alarm_max_limit[i]
- = smm665_convert(val, i);
- val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 6);
- if (unlikely(val < 0))
- goto out_unregister;
- if (smm665_is_critical(val))
- data->critical_max_limit[i] = smm665_convert(val, i);
- else
- data->alarm_max_limit[i] = smm665_convert(val, i);
- }
-
- hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
- client->name, data,
- smm665_groups);
- if (IS_ERR(hwmon_dev)) {
- ret = PTR_ERR(hwmon_dev);
- goto out_unregister;
- }
-
- return 0;
-
-out_unregister:
- i2c_unregister_device(data->cmdreg);
- return ret;
-}
-
-static void smm665_remove(struct i2c_client *client)
-{
- struct smm665_data *data = i2c_get_clientdata(client);
-
- i2c_unregister_device(data->cmdreg);
-}
-
-static const struct i2c_device_id smm665_id[] = {
- {"smm465", smm465},
- {"smm665", smm665},
- {"smm665c", smm665c},
- {"smm764", smm764},
- {"smm766", smm766},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, smm665_id);
-
-/* This is the driver that will be inserted */
-static struct i2c_driver smm665_driver = {
- .driver = {
- .name = "smm665",
- },
- .probe = smm665_probe,
- .remove = smm665_remove,
- .id_table = smm665_id,
-};
-
-module_i2c_driver(smm665_driver);
-
-MODULE_AUTHOR("Guenter Roeck");
-MODULE_DESCRIPTION("SMM665 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index 3cde3916ab6d..10b66c9ce045 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -20,7 +20,7 @@
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/sysfs.h>
/* Addresses to scan */
diff --git a/drivers/hwmon/tmp464.c b/drivers/hwmon/tmp464.c
index 4b79c3f4d9fe..f58ca4c6acb6 100644
--- a/drivers/hwmon/tmp464.c
+++ b/drivers/hwmon/tmp464.c
@@ -14,7 +14,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/slab.h>
diff --git a/drivers/hwmon/tmp513.c b/drivers/hwmon/tmp513.c
index bff10f4b56e1..9a180b1030c9 100644
--- a/drivers/hwmon/tmp513.c
+++ b/drivers/hwmon/tmp513.c
@@ -434,7 +434,7 @@ static umode_t tmp51x_is_visible(const void *_data,
switch (type) {
case hwmon_temp:
- if (data->id == tmp512 && channel == 4)
+ if (data->id == tmp512 && channel == 3)
return 0;
switch (attr) {
case hwmon_temp_input:
@@ -720,10 +720,7 @@ static int tmp51x_probe(struct i2c_client *client)
if (!data)
return -ENOMEM;
- if (client->dev.of_node)
- data->id = (enum tmp51x_ids)device_get_match_data(&client->dev);
- else
- data->id = i2c_match_id(tmp51x_id, client)->driver_data;
+ data->id = (uintptr_t)i2c_get_match_data(client);
ret = tmp51x_configure(dev, data);
if (ret < 0) {
diff --git a/drivers/hwmon/tps23861.c b/drivers/hwmon/tps23861.c
index 8fbbb29ae11d..d33ecbac00d6 100644
--- a/drivers/hwmon/tps23861.c
+++ b/drivers/hwmon/tps23861.c
@@ -14,7 +14,7 @@
#include <linux/hwmon.h>
#include <linux/i2c.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/regmap.h>
#define TEMPERATURE 0x2c
diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c
index b23cff2e3d5d..3b580f229887 100644
--- a/drivers/hwmon/ultra45_env.c
+++ b/drivers/hwmon/ultra45_env.c
@@ -9,7 +9,8 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
diff --git a/drivers/hwmon/vexpress-hwmon.c b/drivers/hwmon/vexpress-hwmon.c
index 2ac5fb96bba4..d82a3b454d0e 100644
--- a/drivers/hwmon/vexpress-hwmon.c
+++ b/drivers/hwmon/vexpress-hwmon.c
@@ -13,7 +13,6 @@
#include <linux/hwmon-sysfs.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/vexpress.h>
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 37d7374896f6..407933d6e425 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -855,16 +855,17 @@ static int via686a_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
u16 address, val;
+ int ret;
if (force_addr) {
address = force_addr & ~(VIA686A_EXTENT - 1);
dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", address);
- if (PCIBIOS_SUCCESSFUL !=
- pci_write_config_word(dev, VIA686A_BASE_REG, address | 1))
+ ret = pci_write_config_word(dev, VIA686A_BASE_REG, address | 1);
+ if (ret != PCIBIOS_SUCCESSFUL)
return -ENODEV;
}
- if (PCIBIOS_SUCCESSFUL !=
- pci_read_config_word(dev, VIA686A_BASE_REG, &val))
+ ret = pci_read_config_word(dev, VIA686A_BASE_REG, &val);
+ if (ret != PCIBIOS_SUCCESSFUL)
return -ENODEV;
address = val & ~(VIA686A_EXTENT - 1);
@@ -874,8 +875,8 @@ static int via686a_pci_probe(struct pci_dev *dev,
return -ENODEV;
}
- if (PCIBIOS_SUCCESSFUL !=
- pci_read_config_word(dev, VIA686A_ENABLE_REG, &val))
+ ret = pci_read_config_word(dev, VIA686A_ENABLE_REG, &val);
+ if (ret != PCIBIOS_SUCCESSFUL)
return -ENODEV;
if (!(val & 0x0001)) {
if (!force_addr) {
@@ -886,9 +887,8 @@ static int via686a_pci_probe(struct pci_dev *dev,
}
dev_warn(&dev->dev, "Enabling sensors\n");
- if (PCIBIOS_SUCCESSFUL !=
- pci_write_config_word(dev, VIA686A_ENABLE_REG,
- val | 0x0001))
+ ret = pci_write_config_word(dev, VIA686A_ENABLE_REG, val | 0x1);
+ if (ret != PCIBIOS_SUCCESSFUL)
return -ENODEV;
}
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index b7c6392ba673..16bc16d33cd1 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -971,13 +971,15 @@ static int vt8231_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
u16 address, val;
+ int ret;
+
if (force_addr) {
address = force_addr & 0xff00;
dev_warn(&dev->dev, "Forcing ISA address 0x%x\n",
address);
- if (PCIBIOS_SUCCESSFUL !=
- pci_write_config_word(dev, VT8231_BASE_REG, address | 1))
+ ret = pci_write_config_word(dev, VT8231_BASE_REG, address | 1);
+ if (ret != PCIBIOS_SUCCESSFUL)
return -ENODEV;
}
@@ -997,9 +999,8 @@ static int vt8231_pci_probe(struct pci_dev *dev,
if (!(val & 0x0001)) {
dev_warn(&dev->dev, "enabling sensors\n");
- if (PCIBIOS_SUCCESSFUL !=
- pci_write_config_word(dev, VT8231_ENABLE_REG,
- val | 0x0001))
+ ret = pci_write_config_word(dev, VT8231_ENABLE_REG, val | 0x1);
+ if (ret != PCIBIOS_SUCCESSFUL)
return -ENODEV;
}
diff --git a/drivers/hwmon/w83773g.c b/drivers/hwmon/w83773g.c
index 7f3615f5587c..045eea8378c2 100644
--- a/drivers/hwmon/w83773g.c
+++ b/drivers/hwmon/w83773g.c
@@ -12,7 +12,7 @@
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/regmap.h>
/* W83773 has 3 channels */