hwmon: (sht3x) read out sensor serial number

The temperature/humidity sensors of the STS3x/SHT3x family are
calibrated and factory-programmed with a unique serial number.
For some sensors, this serial number can be used to obtain a calibration
certificate via an API provided by the manufacturer (Sensirion).
Expose the serial number via debugfs.

Tested with: 2x STS31, 1x STS32, 1x SHT31

Signed-off-by: Stefan Gloor <code@stefan-gloor.ch>
Link: https://lore.kernel.org/r/20240131111512.25321-2-code@stefan-gloor.ch
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Stefan Gloor 2024-01-31 12:15:12 +01:00 committed by Guenter Roeck
parent f20b4a9311
commit 9d613d9b8a
2 changed files with 76 additions and 1 deletions

View File

@ -65,6 +65,10 @@ When the temperature and humidity readings move back between the hysteresis
values, the alert bit is set to 0 and the alert pin on the sensor is set to
low.
The serial number exposed to debugfs allows for unique identification of the
sensors. For sts32, sts33 and sht33, the manufacturer provides calibration
certificates through an API.
sysfs-Interface
---------------
@ -99,3 +103,10 @@ repeatability: write or read repeatability, higher repeatability means
- 1: medium repeatability
- 2: high repeatability
=================== ============================================================
debugfs-Interface
-----------------
=================== ============================================================
serial_number: unique serial number of the sensor in decimal
=================== ============================================================

View File

@ -10,6 +10,7 @@
#include <asm/page.h>
#include <linux/crc8.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/hwmon.h>
@ -41,6 +42,9 @@ 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 };
static struct dentry *debugfs;
/* delays for single-shot mode i2c commands, both in us */
#define SHT3X_SINGLE_WAIT_TIME_HPM 15000
@ -163,12 +167,14 @@ struct sht3x_data {
enum sht3x_chips chip_id;
struct mutex i2c_lock; /* lock for sending i2c commands */
struct mutex data_lock; /* lock for updating driver data */
struct dentry *sensor_dir;
u8 mode;
const unsigned char *command;
u32 wait_time; /* in us*/
unsigned long last_update; /* last update in periodic mode*/
enum sht3x_repeatability repeatability;
u32 serial_number;
/*
* cached values for temperature and humidity and limits
@ -831,6 +837,40 @@ static int sht3x_write(struct device *dev, enum hwmon_sensor_types type,
}
}
static void sht3x_debugfs_init(struct sht3x_data *data)
{
char name[32];
snprintf(name, sizeof(name), "i2c%u-%02x",
data->client->adapter->nr, data->client->addr);
data->sensor_dir = debugfs_create_dir(name, debugfs);
debugfs_create_u32("serial_number", 0444,
data->sensor_dir, &data->serial_number);
}
static void sht3x_debugfs_remove(void *sensor_dir)
{
debugfs_remove_recursive(sensor_dir);
}
static int 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 ret;
data->serial_number = (buffer[0] << 24) | (buffer[1] << 16) |
(buffer[3] << 8) | buffer[4];
return ret;
}
static const struct hwmon_ops sht3x_ops = {
.is_visible = sht3x_is_visible,
.read = sht3x_read,
@ -899,6 +939,18 @@ static int sht3x_probe(struct i2c_client *client)
if (ret)
return ret;
ret = sht3x_serial_number_read(data);
if (ret) {
dev_dbg(dev, "unable to read serial number\n");
} else {
sht3x_debugfs_init(data);
ret = devm_add_action_or_reset(dev,
sht3x_debugfs_remove,
data->sensor_dir);
if (ret)
return ret;
}
hwmon_dev = devm_hwmon_device_register_with_info(dev,
client->name,
data,
@ -917,7 +969,19 @@ static struct i2c_driver sht3x_i2c_driver = {
.id_table = sht3x_ids,
};
module_i2c_driver(sht3x_i2c_driver);
static int __init sht3x_init(void)
{
debugfs = debugfs_create_dir("sht3x", NULL);
return i2c_add_driver(&sht3x_i2c_driver);
}
module_init(sht3x_init);
static void __exit sht3x_cleanup(void)
{
debugfs_remove_recursive(debugfs);
i2c_del_driver(&sht3x_i2c_driver);
}
module_exit(sht3x_cleanup);
MODULE_AUTHOR("David Frey <david.frey@sensirion.com>");
MODULE_AUTHOR("Pascal Sachs <pascal.sachs@sensirion.com>");