summaryrefslogtreecommitdiff
path: root/drivers/hwmon/sht3x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/sht3x.c')
-rw-r--r--drivers/hwmon/sht3x.c545
1 files changed, 357 insertions, 188 deletions
diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c
index 370b57dafab7..f36c0229328f 100644
--- a/drivers/hwmon/sht3x.c
+++ b/drivers/hwmon/sht3x.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/* Sensirion SHT3x-DIS humidity and temperature sensor driver.
* The SHT3x comes in many different versions, this driver is for the
* I2C version only.
@@ -5,21 +6,11 @@
* Copyright (C) 2016 Sensirion AG, Switzerland
* Author: David Frey <david.frey@sensirion.com>
* Author: Pascal Sachs <pascal.sachs@sensirion.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
*/
#include <asm/page.h>
#include <linux/crc8.h>
+#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/hwmon.h>
@@ -30,15 +21,15 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
-#include <linux/platform_data/sht3x.h>
-/* commands (high precision mode) */
-static const unsigned char sht3x_cmd_measure_blocking_hpm[] = { 0x2c, 0x06 };
-static const unsigned char sht3x_cmd_measure_nonblocking_hpm[] = { 0x24, 0x00 };
+/* commands (high repeatability mode) */
+static const unsigned char sht3x_cmd_measure_single_hpm[] = { 0x24, 0x00 };
+
+/* commands (medium repeatability mode) */
+static const unsigned char sht3x_cmd_measure_single_mpm[] = { 0x24, 0x0b };
-/* commands (low power mode) */
-static const unsigned char sht3x_cmd_measure_blocking_lpm[] = { 0x2c, 0x10 };
-static const unsigned char sht3x_cmd_measure_nonblocking_lpm[] = { 0x24, 0x16 };
+/* commands (low repeatability mode) */
+static const unsigned char sht3x_cmd_measure_single_lpm[] = { 0x24, 0x16 };
/* commands for periodic mode */
static const unsigned char sht3x_cmd_measure_periodic_mode[] = { 0xe0, 0x00 };
@@ -51,10 +42,12 @@ static const unsigned char sht3x_cmd_heater_off[] = { 0x30, 0x66 };
/* other commands */
static const unsigned char sht3x_cmd_read_status_reg[] = { 0xf3, 0x2d };
static const unsigned char sht3x_cmd_clear_status_reg[] = { 0x30, 0x41 };
+static const unsigned char sht3x_cmd_read_serial_number[] = { 0x37, 0x80 };
-/* delays for non-blocking i2c commands, both in us */
-#define SHT3X_NONBLOCKING_WAIT_TIME_HPM 15000
-#define SHT3X_NONBLOCKING_WAIT_TIME_LPM 4000
+/* delays for single-shot mode i2c commands, both in us */
+#define SHT3X_SINGLE_WAIT_TIME_HPM 15000
+#define SHT3X_SINGLE_WAIT_TIME_MPM 6000
+#define SHT3X_SINGLE_WAIT_TIME_LPM 4000
#define SHT3X_WORD_LEN 2
#define SHT3X_CMD_LENGTH 2
@@ -79,9 +72,15 @@ enum sht3x_limits {
limit_min_hyst,
};
+enum sht3x_repeatability {
+ low_repeatability,
+ medium_repeatability,
+ high_repeatability,
+};
+
DECLARE_CRC8_TABLE(sht3x_crc8_table);
-/* periodic measure commands (high precision mode) */
+/* periodic measure commands (high repeatability mode) */
static const char periodic_measure_commands_hpm[][SHT3X_CMD_LENGTH] = {
/* 0.5 measurements per second */
{0x20, 0x32},
@@ -95,7 +94,21 @@ static const char periodic_measure_commands_hpm[][SHT3X_CMD_LENGTH] = {
{0x27, 0x37},
};
-/* periodic measure commands (low power mode) */
+/* periodic measure commands (medium repeatability) */
+static const char periodic_measure_commands_mpm[][SHT3X_CMD_LENGTH] = {
+ /* 0.5 measurements per second */
+ {0x20, 0x24},
+ /* 1 measurements per second */
+ {0x21, 0x26},
+ /* 2 measurements per second */
+ {0x22, 0x20},
+ /* 4 measurements per second */
+ {0x23, 0x22},
+ /* 10 measurements per second */
+ {0x27, 0x21},
+};
+
+/* periodic measure commands (low repeatability mode) */
static const char periodic_measure_commands_lpm[][SHT3X_CMD_LENGTH] = {
/* 0.5 measurements per second */
{0x20, 0x2f},
@@ -136,8 +149,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 */
@@ -145,8 +170,8 @@ struct sht3x_data {
const unsigned char *command;
u32 wait_time; /* in us*/
unsigned long last_update; /* last update in periodic mode*/
-
- struct sht3x_platform_data setup;
+ enum sht3x_repeatability repeatability;
+ u32 serial_number;
/*
* cached values for temperature and humidity and limits
@@ -266,27 +291,26 @@ 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, long *temp)
{
struct sht3x_data *data = sht3x_update_client(dev);
if (IS_ERR(data))
return PTR_ERR(data);
- return sprintf(buf, "%d\n", data->temperature);
+ *temp = data->temperature;
+ return 0;
}
-static ssize_t humidity1_input_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static int humidity1_input_read(struct device *dev, long *humidity)
{
struct sht3x_data *data = sht3x_update_client(dev);
if (IS_ERR(data))
return PTR_ERR(data);
- return sprintf(buf, "%u\n", data->humidity);
+ *humidity = data->humidity;
+ return 0;
}
/*
@@ -322,33 +346,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 scnprintf(buf, PAGE_SIZE, "%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 scnprintf(buf, PAGE_SIZE, "%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)
@@ -369,7 +384,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;
@@ -390,50 +405,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);
@@ -443,32 +443,27 @@ static ssize_t humidity1_limit_store(struct device *dev,
static void sht3x_select_command(struct sht3x_data *data)
{
/*
- * In blocking mode (clock stretching mode) the I2C bus
- * is blocked for other traffic, thus the call to i2c_master_recv()
- * will wait until the data is ready. For non blocking mode, we
- * have to wait ourselves.
+ * For single-shot mode, only non blocking mode is support,
+ * we have to wait ourselves for result.
*/
if (data->mode > 0) {
data->command = sht3x_cmd_measure_periodic_mode;
data->wait_time = 0;
- } else if (data->setup.blocking_io) {
- data->command = data->setup.high_precision ?
- sht3x_cmd_measure_blocking_hpm :
- sht3x_cmd_measure_blocking_lpm;
- data->wait_time = 0;
} else {
- if (data->setup.high_precision) {
- data->command = sht3x_cmd_measure_nonblocking_hpm;
- data->wait_time = SHT3X_NONBLOCKING_WAIT_TIME_HPM;
+ if (data->repeatability == high_repeatability) {
+ data->command = sht3x_cmd_measure_single_hpm;
+ data->wait_time = SHT3X_SINGLE_WAIT_TIME_HPM;
+ } else if (data->repeatability == medium_repeatability) {
+ data->command = sht3x_cmd_measure_single_mpm;
+ data->wait_time = SHT3X_SINGLE_WAIT_TIME_MPM;
} else {
- data->command = sht3x_cmd_measure_nonblocking_lpm;
- data->wait_time = SHT3X_NONBLOCKING_WAIT_TIME_LPM;
+ data->command = sht3x_cmd_measure_single_lpm;
+ data->wait_time = SHT3X_SINGLE_WAIT_TIME_LPM;
}
}
}
static int status_register_read(struct device *dev,
- struct device_attribute *attr,
char *buffer, int length)
{
int ret;
@@ -481,34 +476,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 scnprintf(buf, PAGE_SIZE, "%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 scnprintf(buf, PAGE_SIZE, "%d\n", !!(buffer[0] & 0x08));
+ return !!(buffer[0] & 0x08);
}
static ssize_t heater_enable_show(struct device *dev,
@@ -518,12 +509,12 @@ 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;
- return scnprintf(buf, PAGE_SIZE, "%d\n", !!(buffer[0] & 0x20));
+ return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x20));
}
static ssize_t heater_enable_store(struct device *dev,
@@ -554,39 +545,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 scnprintf(buf, PAGE_SIZE, "%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);
@@ -605,8 +585,10 @@ static ssize_t update_interval_store(struct device *dev,
}
if (mode > 0) {
- if (data->setup.high_precision)
+ if (data->repeatability == high_repeatability)
command = periodic_measure_commands_hpm[mode - 1];
+ else if (data->repeatability == medium_repeatability)
+ command = periodic_measure_commands_mpm[mode - 1];
else
command = periodic_measure_commands_lpm[mode - 1];
@@ -626,79 +608,276 @@ out:
if (ret != SHT3X_CMD_LENGTH)
return ret < 0 ? ret : -EIO;
+ return 0;
+}
+
+static ssize_t repeatability_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sht3x_data *data = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%d\n", data->repeatability);
+}
+
+static ssize_t repeatability_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int ret;
+ u8 val;
+
+ struct sht3x_data *data = dev_get_drvdata(dev);
+
+ ret = kstrtou8(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ if (val > 2)
+ return -EINVAL;
+
+ data->repeatability = val;
+
return count;
}
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, temp1_input_show, NULL, 0);
-static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, humidity1_input_show,
- NULL, 0);
-static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
- temp1_limit_show, temp1_limit_store,
- limit_max);
-static SENSOR_DEVICE_ATTR(humidity1_max, S_IRUGO | S_IWUSR,
- humidity1_limit_show, humidity1_limit_store,
- limit_max);
-static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
- temp1_limit_show, temp1_limit_store,
- limit_max_hyst);
-static SENSOR_DEVICE_ATTR(humidity1_max_hyst, S_IRUGO | S_IWUSR,
- humidity1_limit_show, humidity1_limit_store,
- limit_max_hyst);
-static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR,
- temp1_limit_show, temp1_limit_store,
- limit_min);
-static SENSOR_DEVICE_ATTR(humidity1_min, S_IRUGO | S_IWUSR,
- humidity1_limit_show, humidity1_limit_store,
- limit_min);
-static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO | S_IWUSR,
- temp1_limit_show, temp1_limit_store,
- limit_min_hyst);
-static SENSOR_DEVICE_ATTR(humidity1_min_hyst, S_IRUGO | S_IWUSR,
- humidity1_limit_show, humidity1_limit_store,
- limit_min_hyst);
-static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, temp1_alarm_show, NULL, 0);
-static SENSOR_DEVICE_ATTR(humidity1_alarm, S_IRUGO, humidity1_alarm_show,
- NULL, 0);
-static SENSOR_DEVICE_ATTR(heater_enable, S_IRUGO | S_IWUSR,
- heater_enable_show, heater_enable_store, 0);
-static SENSOR_DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR,
- update_interval_show, update_interval_store, 0);
+static SENSOR_DEVICE_ATTR_RW(heater_enable, heater_enable, 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,
- 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;
+ int ret;
+
+ 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:
+ return temp1_input_read(dev, val);
+ case hwmon_temp_alarm:
+ ret = temp1_alarm_read(dev);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ 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:
+ return humidity1_input_read(dev, val);
+ case hwmon_humidity_alarm:
+ ret = humidity1_alarm_read(dev);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ 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 void sht3x_serial_number_read(struct sht3x_data *data)
+{
+ int ret;
+ char buffer[SHT3X_RESPONSE_LENGTH];
+ struct i2c_client *client = data->client;
+
+ ret = sht3x_read_from_command(client, data,
+ sht3x_cmd_read_serial_number,
+ buffer,
+ SHT3X_RESPONSE_LENGTH, 0);
+ if (ret)
+ return;
+
+ data->serial_number = (buffer[0] << 24) | (buffer[1] << 16) |
+ (buffer[3] << 8) | buffer[4];
+
+ debugfs_create_u32("serial_number", 0444, client->debugfs, &data->serial_number);
+}
+
+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,
+};
-static int sht3x_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int sht3x_probe(struct i2c_client *client)
{
int ret;
struct sht3x_data *data;
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
@@ -717,16 +896,13 @@ static int sht3x_probe(struct i2c_client *client,
if (!data)
return -ENOMEM;
- data->setup.blocking_io = false;
- data->setup.high_precision = true;
+ data->repeatability = high_repeatability;
data->mode = 0;
data->last_update = jiffies - msecs_to_jiffies(3000);
data->client = client;
+ data->chip_id = (uintptr_t)i2c_get_match_data(client);
crc8_populate_msb(sht3x_crc8_table, SHT3X_CRC8_POLYNOMIAL);
- if (client->dev.platform_data)
- data->setup = *(struct sht3x_platform_data *)dev->platform_data;
-
sht3x_select_command(data);
mutex_init(&data->i2c_lock);
@@ -743,20 +919,14 @@ static int sht3x_probe(struct i2c_client *client,
if (ret)
return ret;
- if (id->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");
+ return PTR_ERR(hwmon_dev);
+
+ sht3x_serial_number_read(data);
- return PTR_ERR_OR_ZERO(hwmon_dev);
+ return 0;
}
/* device ID table */
@@ -773,7 +943,6 @@ static struct i2c_driver sht3x_i2c_driver = {
.probe = sht3x_probe,
.id_table = sht3x_ids,
};
-
module_i2c_driver(sht3x_i2c_driver);
MODULE_AUTHOR("David Frey <david.frey@sensirion.com>");