drivers: sensors: Add driver for LM95234 temperature sensor
Add a driver for the National/TI LM95234 Quad Remote Diode and Local Temperature Sensor with SMBus Interface and TruTherm Technology. Signed-off-by: Robert Hancock <robert.hancock@calian.com>
This commit is contained in:
parent
2c7cd3dc1e
commit
2d171efcec
8 changed files with 376 additions and 0 deletions
|
@ -8,6 +8,7 @@ add_subdirectory_ifdef(CONFIG_INA219 ina219)
|
|||
add_subdirectory_ifdef(CONFIG_INA226 ina226)
|
||||
add_subdirectory_ifdef(CONFIG_INA23X ina23x)
|
||||
add_subdirectory_ifdef(CONFIG_INA3221 ina3221)
|
||||
add_subdirectory_ifdef(CONFIG_LM95234 lm95234)
|
||||
add_subdirectory_ifdef(CONFIG_OPT3001 opt3001)
|
||||
add_subdirectory_ifdef(CONFIG_TI_HDC ti_hdc)
|
||||
add_subdirectory_ifdef(CONFIG_TI_HDC20XX ti_hdc20xx)
|
||||
|
|
|
@ -8,6 +8,7 @@ source "drivers/sensor/ti/ina219/Kconfig"
|
|||
source "drivers/sensor/ti/ina226/Kconfig"
|
||||
source "drivers/sensor/ti/ina23x/Kconfig"
|
||||
source "drivers/sensor/ti/ina3221/Kconfig"
|
||||
source "drivers/sensor/ti/lm95234/Kconfig"
|
||||
source "drivers/sensor/ti/opt3001/Kconfig"
|
||||
source "drivers/sensor/ti/ti_hdc/Kconfig"
|
||||
source "drivers/sensor/ti/ti_hdc20xx/Kconfig"
|
||||
|
|
5
drivers/sensor/ti/lm95234/CMakeLists.txt
Normal file
5
drivers/sensor/ti/lm95234/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(lm95234.c)
|
13
drivers/sensor/ti/lm95234/Kconfig
Normal file
13
drivers/sensor/ti/lm95234/Kconfig
Normal file
|
@ -0,0 +1,13 @@
|
|||
# LM95234 temperature sensor config
|
||||
|
||||
# Copyright (c) 2024 Calian Advanced Technologies
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config LM95234
|
||||
bool "LM95234 Temperature Sensor"
|
||||
default y
|
||||
depends on DT_HAS_NATIONAL_LM95234_ENABLED
|
||||
select I2C
|
||||
help
|
||||
Enable the driver for the LM95234 Quad Remote Diode and Local
|
||||
Temperature Sensor with SMBus Interface.
|
322
drivers/sensor/ti/lm95234/lm95234.c
Normal file
322
drivers/sensor/ti/lm95234/lm95234.c
Normal file
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Calian Advanced Technologies
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT national_lm95234
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/drivers/sensor/lm95234.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
#include <zephyr/pm/device_runtime.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(LM95234, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
#define LM95234_REG_LOCAL_TEMP_SIGNED_MSB 0x10
|
||||
#define LM95234_REG_LOCAL_TEMP_SIGNED_LSB 0x20
|
||||
#define LM95234_REG_REMOTE_TEMP_1_SIGNED_MSB 0x11
|
||||
#define LM95234_REG_REMOTE_TEMP_1_SIGNED_LSB 0x21
|
||||
#define LM95234_REG_REMOTE_TEMP_2_SIGNED_MSB 0x12
|
||||
#define LM95234_REG_REMOTE_TEMP_2_SIGNED_LSB 0x22
|
||||
#define LM95234_REG_REMOTE_TEMP_3_SIGNED_MSB 0x13
|
||||
#define LM95234_REG_REMOTE_TEMP_3_SIGNED_LSB 0x23
|
||||
#define LM95234_REG_REMOTE_TEMP_4_SIGNED_MSB 0x14
|
||||
#define LM95234_REG_REMOTE_TEMP_4_SIGNED_LSB 0x24
|
||||
#define LM95234_REG_REMOTE_TEMP_1_UNSIGNED_MSB 0x19
|
||||
#define LM95234_REG_REMOTE_TEMP_1_UNSIGNED_LSB 0x29
|
||||
#define LM95234_REG_REMOTE_TEMP_2_UNSIGNED_MSB 0x1a
|
||||
#define LM95234_REG_REMOTE_TEMP_2_UNSIGNED_LSB 0x2a
|
||||
#define LM95234_REG_REMOTE_TEMP_3_UNSIGNED_MSB 0x1b
|
||||
#define LM95234_REG_REMOTE_TEMP_3_UNSIGNED_LSB 0x2b
|
||||
#define LM95234_REG_REMOTE_TEMP_4_UNSIGNED_MSB 0x1c
|
||||
#define LM95234_REG_REMOTE_TEMP_4_UNSIGNED_LSB 0x2c
|
||||
#define LM95234_REG_DIODE_MODEL_SELECT 0x30
|
||||
#define LM95234_REG_REMOTE_1_OFFSET 0x31
|
||||
#define LM95234_REG_REMOTE_2_OFFSET 0x32
|
||||
#define LM95234_REG_REMOTE_3_OFFSET 0x33
|
||||
#define LM95234_REG_REMOTE_4_OFFSET 0x34
|
||||
#define LM95234_REG_CONFIG 0x03
|
||||
#define LM95234_REG_CONV_RATE 0x04
|
||||
#define LM95234_REG_CHANNEL_CONV_ENABLE 0x05
|
||||
#define LM95234_REG_FILTER_SETTING 0x06
|
||||
#define LM95234_REG_ONESHOT 0x0f
|
||||
#define LM95234_REG_COMMON_STATUS 0x02
|
||||
#define LM95234_REG_STATUS_1 0x07
|
||||
#define LM95234_REG_STATUS_2 0x08
|
||||
#define LM95234_REG_STATUS_3 0x09
|
||||
#define LM95234_REG_STATUS_4 0x0a
|
||||
#define LM95234_REG_DIODE_MODEL_STATUS 0x38
|
||||
#define LM95234_REG_TCRIT1_MASK 0x0c
|
||||
#define LM95234_REG_TCRIT2_MASK 0x0d
|
||||
#define LM95234_REG_TCRIT3_MASK 0x0e
|
||||
#define LM95234_REG_LOCAL_TCRIT_LIMIT 0x40
|
||||
#define LM95234_REG_REMOTE1_TCRIT1_LIMIT 0x41
|
||||
#define LM95234_REG_REMOTE2_TCRIT1_LIMIT 0x42
|
||||
#define LM95234_REG_REMOTE3_TCRIT_LIMIT 0x43
|
||||
#define LM95234_REG_REMOTE4_TCRIT_LIMIT 0x44
|
||||
#define LM95234_REG_REMOTE1_TCRIT23_LIMIT 0x49
|
||||
#define LM95234_REG_REMOTE2_TCRIT23_LIMIT 0x4a
|
||||
#define LM95234_REG_COMMON_TCRIT_HYSTERESIS 0x5a
|
||||
#define LM95234_REG_MANUF_ID 0xfe
|
||||
#define LM95234_REG_REV_ID 0xff
|
||||
|
||||
#define LM95234_MAN_ID 0x01
|
||||
#define LM95234_CHIP_ID 0x79
|
||||
|
||||
#define LM95234_CONFIG_STANDBY BIT(6)
|
||||
|
||||
struct lm95234_data {
|
||||
/** Temperatures in raw format read from sensor */
|
||||
int32_t local;
|
||||
int32_t remote[4];
|
||||
};
|
||||
|
||||
struct lm95234_config {
|
||||
struct i2c_dt_spec i2c;
|
||||
};
|
||||
|
||||
static inline int lm95234_fetch_temp(const struct lm95234_config *cfg, struct lm95234_data *data,
|
||||
enum sensor_channel chan, int32_t *output)
|
||||
{
|
||||
int ret;
|
||||
uint8_t val;
|
||||
int32_t result = 0;
|
||||
|
||||
if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
|
||||
uint16_t temp;
|
||||
int offset = (chan - SENSOR_CHAN_LM95234_REMOTE_TEMP_1);
|
||||
|
||||
ret = i2c_reg_read_byte_dt(&cfg->i2c,
|
||||
LM95234_REG_REMOTE_TEMP_1_UNSIGNED_MSB + offset, &val);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
temp = val << 8;
|
||||
ret = i2c_reg_read_byte_dt(&cfg->i2c,
|
||||
LM95234_REG_REMOTE_TEMP_1_UNSIGNED_LSB + offset, &val);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
temp |= val;
|
||||
result = temp;
|
||||
}
|
||||
|
||||
/* Read signed temperature if unsigned temperature is 0, or for local sensor */
|
||||
if (chan == SENSOR_CHAN_AMBIENT_TEMP || result == 0) {
|
||||
int offset = chan == SENSOR_CHAN_AMBIENT_TEMP ? 0 :
|
||||
(chan - SENSOR_CHAN_LM95234_REMOTE_TEMP_1 + 1);
|
||||
int16_t temp;
|
||||
|
||||
ret = i2c_reg_read_byte_dt(&cfg->i2c,
|
||||
LM95234_REG_LOCAL_TEMP_SIGNED_MSB + offset, &val);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
temp = val << 8;
|
||||
ret = i2c_reg_read_byte_dt(&cfg->i2c,
|
||||
LM95234_REG_LOCAL_TEMP_SIGNED_LSB + offset, &val);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
temp |= val;
|
||||
result = temp;
|
||||
}
|
||||
*output = result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lm95234_sample_fetch(const struct device *dev,
|
||||
enum sensor_channel chan)
|
||||
{
|
||||
struct lm95234_data *data = dev->data;
|
||||
const struct lm95234_config *cfg = dev->config;
|
||||
enum pm_device_state pm_state;
|
||||
int ret;
|
||||
|
||||
(void)pm_device_state_get(dev, &pm_state);
|
||||
if (pm_state != PM_DEVICE_STATE_ACTIVE) {
|
||||
ret = -EIO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch ((uint32_t)chan) {
|
||||
case SENSOR_CHAN_ALL:
|
||||
ret = lm95234_fetch_temp(cfg, data, SENSOR_CHAN_AMBIENT_TEMP, &data->local);
|
||||
if (ret)
|
||||
return ret;
|
||||
for (int i = 0; i < ARRAY_SIZE(data->remote); i++) {
|
||||
ret = lm95234_fetch_temp(cfg, data,
|
||||
SENSOR_CHAN_LM95234_REMOTE_TEMP_1 + i,
|
||||
&data->remote[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case SENSOR_CHAN_AMBIENT_TEMP:
|
||||
ret = lm95234_fetch_temp(cfg, data, chan, &data->local);
|
||||
break;
|
||||
case SENSOR_CHAN_LM95234_REMOTE_TEMP_1:
|
||||
case SENSOR_CHAN_LM95234_REMOTE_TEMP_2:
|
||||
case SENSOR_CHAN_LM95234_REMOTE_TEMP_3:
|
||||
case SENSOR_CHAN_LM95234_REMOTE_TEMP_4:
|
||||
ret = lm95234_fetch_temp(cfg, data, chan,
|
||||
&data->remote[chan - SENSOR_CHAN_LM95234_REMOTE_TEMP_1]);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUP;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lm95234_channel_get(const struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
struct lm95234_data *data = dev->data;
|
||||
int32_t raw_temp;
|
||||
|
||||
switch ((uint32_t)chan) {
|
||||
case SENSOR_CHAN_AMBIENT_TEMP:
|
||||
raw_temp = data->local;
|
||||
break;
|
||||
case SENSOR_CHAN_LM95234_REMOTE_TEMP_1:
|
||||
case SENSOR_CHAN_LM95234_REMOTE_TEMP_2:
|
||||
case SENSOR_CHAN_LM95234_REMOTE_TEMP_3:
|
||||
case SENSOR_CHAN_LM95234_REMOTE_TEMP_4:
|
||||
raw_temp = data->remote[chan - SENSOR_CHAN_LM95234_REMOTE_TEMP_1];
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Raw data format is 8 bits integer, 5 bits fractional, 3 bits zero */
|
||||
val->val1 = raw_temp / 256;
|
||||
val->val2 = (raw_temp % 256) * 1000000 / 256;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api lm95234_driver_api = {
|
||||
.sample_fetch = lm95234_sample_fetch,
|
||||
.channel_get = lm95234_channel_get,
|
||||
};
|
||||
|
||||
static int lm95234_init(const struct device *dev)
|
||||
{
|
||||
const struct lm95234_config *cfg = dev->config;
|
||||
int ret = 0;
|
||||
uint8_t value, model_select, model_status;
|
||||
|
||||
if (!i2c_is_ready_dt(&cfg->i2c)) {
|
||||
LOG_ERR("I2C dev not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_MANUF_ID, &value);
|
||||
if (ret) {
|
||||
LOG_ERR("Could not read manufacturer ID: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (value != LM95234_MAN_ID) {
|
||||
LOG_ERR("Invalid manufacturer ID: %02x", value);
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_REV_ID, &value);
|
||||
if (ret) {
|
||||
LOG_ERR("Could not read revision ID: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (value != LM95234_CHIP_ID) {
|
||||
LOG_ERR("Invalid chip ID: %02x", value);
|
||||
return -ENODEV;
|
||||
}
|
||||
ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_CONFIG, &value);
|
||||
if (ret) {
|
||||
LOG_ERR("Could not read config: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (value & LM95234_CONFIG_STANDBY) {
|
||||
value &= ~LM95234_CONFIG_STANDBY;
|
||||
ret = i2c_reg_write_byte_dt(&cfg->i2c, LM95234_REG_CONFIG, value);
|
||||
if (ret) {
|
||||
LOG_ERR("Could not write config: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_DIODE_MODEL_SELECT, &model_select);
|
||||
if (ret) {
|
||||
LOG_ERR("Could not read diode model select: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_DIODE_MODEL_STATUS, &model_status);
|
||||
if (ret) {
|
||||
LOG_ERR("Could not read diode model status: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* Check if any remote inputs have a 3904 transistor detected but are not configured
|
||||
* as such. If so, configure them as 3904 transistors.
|
||||
*/
|
||||
if (model_select & model_status) {
|
||||
model_select &= ~model_status;
|
||||
ret = i2c_reg_write_byte_dt(&cfg->i2c, LM95234_REG_DIODE_MODEL_SELECT,
|
||||
model_select);
|
||||
if (ret) {
|
||||
LOG_ERR("Could not write diode model select: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_DEVICE_RUNTIME
|
||||
pm_device_init_suspended(dev);
|
||||
|
||||
ret = pm_device_runtime_enable(dev);
|
||||
if (ret < 0 && ret != -ENOTSUP) {
|
||||
LOG_ERR("Failed to enable runtime power management");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_DEVICE
|
||||
|
||||
static int lm95234_pm_action(const struct device *dev, enum pm_device_action action)
|
||||
{
|
||||
switch (action) {
|
||||
case PM_DEVICE_ACTION_TURN_ON:
|
||||
case PM_DEVICE_ACTION_RESUME:
|
||||
case PM_DEVICE_ACTION_TURN_OFF:
|
||||
case PM_DEVICE_ACTION_SUSPEND:
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define LM95234_INST(inst) \
|
||||
static struct lm95234_data lm95234_data_##inst; \
|
||||
static const struct lm95234_config lm95234_config_##inst = { \
|
||||
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
||||
}; \
|
||||
PM_DEVICE_DT_INST_DEFINE(inst, lm95234_pm_action); \
|
||||
SENSOR_DEVICE_DT_INST_DEFINE(inst, lm95234_init, \
|
||||
PM_DEVICE_DT_INST_GET(inst), \
|
||||
&lm95234_data_##inst, \
|
||||
&lm95234_config_##inst, \
|
||||
POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, \
|
||||
&lm95234_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(LM95234_INST)
|
8
dts/bindings/sensor/national,lm95234.yaml
Normal file
8
dts/bindings/sensor/national,lm95234.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2024 Calian Advanced Technologies
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: LM95234 Quad Remote Diode and Local Temperature Sensor with SMBus Interface
|
||||
|
||||
compatible: "national,lm95234"
|
||||
|
||||
include: [sensor-device.yaml, i2c-device.yaml]
|
20
include/zephyr/drivers/sensor/lm95234.h
Normal file
20
include/zephyr/drivers/sensor/lm95234.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Calian Advanced Technologies
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_LM95234_H_
|
||||
#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_LM95234_H_
|
||||
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
|
||||
enum sensor_channel_lm95234 {
|
||||
/* External temperature inputs */
|
||||
SENSOR_CHAN_LM95234_REMOTE_TEMP_1 = SENSOR_CHAN_PRIV_START,
|
||||
SENSOR_CHAN_LM95234_REMOTE_TEMP_2,
|
||||
SENSOR_CHAN_LM95234_REMOTE_TEMP_3,
|
||||
SENSOR_CHAN_LM95234_REMOTE_TEMP_4
|
||||
};
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_LM95234_H_ */
|
|
@ -1055,3 +1055,9 @@ test_i2c_shtc1: shtc1@8e {
|
|||
measure-mode = "low-power";
|
||||
clock-stretching;
|
||||
};
|
||||
|
||||
test_i2c_lm95234: lm95234@8f {
|
||||
compatible = "national,lm95234";
|
||||
reg = <0x8f>;
|
||||
status = "okay";
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue