drivers: sensor: ti: tmp435: added driver for TMP435
The TMP435 is a remote temperature sensor monitor with a built-in local temperature sensor. Signed-off-by: Jaakko Rautiainen <jaakko.rautiainen@bittium.com>
This commit is contained in:
parent
1d441c239e
commit
516e5d61c6
8 changed files with 322 additions and 1 deletions
|
|
@ -20,4 +20,5 @@ add_subdirectory_ifdef(CONFIG_TMP108 tmp108)
|
|||
add_subdirectory_ifdef(CONFIG_TMP112 tmp112)
|
||||
add_subdirectory_ifdef(CONFIG_TMP114 tmp114)
|
||||
add_subdirectory_ifdef(CONFIG_TMP116 tmp116)
|
||||
add_subdirectory_ifdef(CONFIG_TMP435 tmp435)
|
||||
# zephyr-keep-sorted-stop
|
||||
|
|
|
|||
|
|
@ -20,4 +20,5 @@ source "drivers/sensor/ti/tmp108/Kconfig"
|
|||
source "drivers/sensor/ti/tmp112/Kconfig"
|
||||
source "drivers/sensor/ti/tmp114/Kconfig"
|
||||
source "drivers/sensor/ti/tmp116/Kconfig"
|
||||
source "drivers/sensor/ti/tmp435/Kconfig"
|
||||
# zephyr-keep-sorted-stop
|
||||
|
|
|
|||
7
drivers/sensor/ti/tmp435/CMakeLists.txt
Normal file
7
drivers/sensor/ti/tmp435/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Copyright (c) 2024 Bittium Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(tmp435.c)
|
||||
11
drivers/sensor/ti/tmp435/Kconfig
Normal file
11
drivers/sensor/ti/tmp435/Kconfig
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Copyright (c) 2024 Bittium Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config TMP435
|
||||
bool "TMP435 temperature sensor"
|
||||
default y
|
||||
depends on DT_HAS_TI_TMP435_ENABLED
|
||||
select I2C
|
||||
help
|
||||
Enable the driver for the TMP435 temperature sensor
|
||||
214
drivers/sensor/ti/tmp435/tmp435.c
Normal file
214
drivers/sensor/ti/tmp435/tmp435.c
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Bittium Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT ti_tmp435
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include "tmp435.h"
|
||||
|
||||
LOG_MODULE_REGISTER(TMP435, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static inline int tmp435_reg_read(const struct tmp435_config *cfg, uint8_t reg, uint8_t *buf,
|
||||
uint32_t size)
|
||||
{
|
||||
return i2c_burst_read_dt(&cfg->i2c, reg, buf, size);
|
||||
}
|
||||
|
||||
static inline int tmp435_reg_write(const struct tmp435_config *cfg, uint8_t reg, uint8_t *buf,
|
||||
uint32_t size)
|
||||
{
|
||||
return i2c_burst_write_dt(&cfg->i2c, reg, buf, size);
|
||||
}
|
||||
|
||||
static inline int tmp435_get_status(const struct tmp435_config *cfg, uint8_t *status)
|
||||
{
|
||||
return tmp435_reg_read(cfg, TMP435_STATUS_REG, status, 1);
|
||||
}
|
||||
|
||||
static int tmp435_one_shot(const struct device *dev)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
uint8_t status = 0;
|
||||
int ret = 0;
|
||||
const struct tmp435_config *cfg = dev->config;
|
||||
|
||||
data = 1; /* write anything to start */
|
||||
ret = tmp435_reg_write(cfg, TMP435_ONE_SHOT_START_REG, &data, 1);
|
||||
for (uint16_t i = 0; i < TMP435_CONV_LOOP_LIMIT; i++) {
|
||||
ret = tmp435_get_status(cfg, &status);
|
||||
if (ret < 0) {
|
||||
LOG_DBG("Failed to read TMP435_STATUS_REG, ret:%d", ret);
|
||||
} else {
|
||||
if (status & TMP435_STATUS_REG_BUSY) {
|
||||
/* conversion not ready */
|
||||
k_msleep(10);
|
||||
} else {
|
||||
LOG_DBG("conv over, loops:%d status:%x", i, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tmp435_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t value = 0;
|
||||
int32_t temp = 0;
|
||||
const struct tmp435_config *cfg = dev->config;
|
||||
struct tmp435_data *data = dev->data;
|
||||
|
||||
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP &&
|
||||
chan != SENSOR_CHAN_AMBIENT_TEMP) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
tmp435_one_shot(dev); /* start conversion */
|
||||
if ((chan == SENSOR_CHAN_ALL) || (chan == SENSOR_CHAN_DIE_TEMP)) {
|
||||
ret = tmp435_reg_read(cfg, TMP435_LOCAL_TEMP_H_REG, &value, sizeof(value));
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to read TMP435_LOCAL_TEMP_H_REG, ret:%d", ret);
|
||||
return ret;
|
||||
}
|
||||
temp = value;
|
||||
ret = tmp435_reg_read(cfg, TMP435_LOCAL_TEMP_L_REG, &value, sizeof(value));
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to read TMP435_LOCAL_TEMP_L_REG, ret:%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (value > TMP435_FRACTION_INC) {
|
||||
temp++;
|
||||
}
|
||||
data->temp_die = temp + tmp435_temp_offset;
|
||||
}
|
||||
|
||||
if ((chan == SENSOR_CHAN_ALL) || (chan == SENSOR_CHAN_AMBIENT_TEMP)) {
|
||||
if (!(cfg->external_channel)) {
|
||||
return 0; /* not enabled, just return */
|
||||
}
|
||||
ret = tmp435_reg_read(cfg, TMP435_REMOTE_TEMP_H_REG, &value, sizeof(value));
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to read TMP435_REMOTE_TEMP_H_REG ret:%d", ret);
|
||||
return ret;
|
||||
}
|
||||
temp = value;
|
||||
ret = tmp435_reg_read(cfg, TMP435_REMOTE_TEMP_L_REG, &value, sizeof(value));
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to read TMP435_REMOTE_TEMP_L_REG, ret:%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if (value > TMP435_FRACTION_INC) {
|
||||
temp++;
|
||||
}
|
||||
data->temp_ambient = temp + tmp435_temp_offset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tmp435_channel_get(const struct device *dev, enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
int ret = 0;
|
||||
struct tmp435_data *data = dev->data;
|
||||
const struct tmp435_config *cfg = dev->config;
|
||||
|
||||
switch (chan) {
|
||||
|
||||
case SENSOR_CHAN_DIE_TEMP:
|
||||
val->val1 = data->temp_die;
|
||||
val->val2 = 0;
|
||||
break;
|
||||
case SENSOR_CHAN_AMBIENT_TEMP:
|
||||
if (cfg->external_channel) {
|
||||
val->val1 = data->temp_ambient;
|
||||
val->val2 = 0;
|
||||
} else {
|
||||
ret = -ENOTSUP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUP;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api tmp435_driver_api = {
|
||||
.sample_fetch = tmp435_sample_fetch,
|
||||
.channel_get = tmp435_channel_get,
|
||||
};
|
||||
|
||||
static int tmp435_init(const struct device *dev)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
int ret = 0;
|
||||
const struct tmp435_config *cfg = dev->config;
|
||||
|
||||
if (!(i2c_is_ready_dt(&cfg->i2c))) {
|
||||
LOG_ERR("I2C dev not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data = 1; /* write anything to reset */
|
||||
ret = tmp435_reg_write(cfg, TMP435_SOFTWARE_RESET_REG, &data, 1);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to write TMP435_SOFTWARE_RESET_REG ret:%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data = TMP435_CONF_REG_1_DATA;
|
||||
ret = tmp435_reg_write(cfg, TMP435_CONF_REG_1, &data, 1);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to write TMP435_CONF_REG_1 ret:%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data = TMP435_CONF_REG_2_DATA;
|
||||
if (cfg->external_channel) {
|
||||
data = data + TMP435_CONF_REG_2_REN;
|
||||
}
|
||||
if (cfg->resistance_correction) {
|
||||
data = data + TMP435_CONF_REG_2_RC;
|
||||
}
|
||||
ret = tmp435_reg_write(cfg, TMP435_CONF_REG_2, &data, 1);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to write TMP435_CONF_REG_2 ret:%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data = cfg->beta_compensation;
|
||||
ret = tmp435_reg_write(cfg, TMP435_BETA_RANGE_REG, &data, 1);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to write TMP435_BETA_RANGE_REG ret:%d", ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Device creation macros
|
||||
*/
|
||||
|
||||
#define TMP435_INST(inst) \
|
||||
static struct tmp435_data tmp435_data_##inst; \
|
||||
static const struct tmp435_config tmp435_config_##inst = { \
|
||||
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
||||
.external_channel = DT_INST_PROP(inst, external_channel), \
|
||||
.resistance_correction = DT_INST_PROP(inst, resistance_correction), \
|
||||
.beta_compensation = DT_INST_PROP(inst, beta_compensation), \
|
||||
}; \
|
||||
SENSOR_DEVICE_DT_INST_DEFINE(inst, tmp435_init, NULL, &tmp435_data_##inst, \
|
||||
&tmp435_config_##inst, POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &tmp435_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(TMP435_INST)
|
||||
44
drivers/sensor/ti/tmp435/tmp435.h
Normal file
44
drivers/sensor/ti/tmp435/tmp435.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Bittium Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_SENSOR_TMP435_H_
|
||||
#define ZEPHYR_DRIVERS_SENSOR_TMP435_H_
|
||||
|
||||
#define TMP435_CONF_REG_1 0x03
|
||||
#define TMP435_CONF_REG_1_DATA 0xc4
|
||||
/* [7]=1 ALERT Masked, [6]=1 Shut Down (one shot mode), [2]=1 −55 C to +150 C */
|
||||
#define TMP435_CONF_REG_2 0x1a
|
||||
#define TMP435_CONF_REG_2_REN 0x10 /* [4]=1 External channel 1 enabled */
|
||||
#define TMP435_CONF_REG_2_RC 0x04 /* [2]=1 Resistance correction enabled */
|
||||
#define TMP435_CONF_REG_2_DATA 0x08 /* [3]=1 Local channel enabled */
|
||||
#define TMP435_BETA_RANGE_REG 0x25
|
||||
#define TMP435_STATUS_REG 0x02
|
||||
#define TMP435_STATUS_REG_BUSY 0x80 /* conv not ready */
|
||||
#define TMP435_SOFTWARE_RESET_REG 0xfc
|
||||
#define TMP435_ONE_SHOT_START_REG 0x0f
|
||||
#define TMP435_LOCAL_TEMP_H_REG 0x00
|
||||
#define TMP435_LOCAL_TEMP_L_REG 0x15
|
||||
#define TMP435_REMOTE_TEMP_H_REG 0x01
|
||||
#define TMP435_REMOTE_TEMP_L_REG 0x10
|
||||
|
||||
#define TMP435_CONV_LOOP_LIMIT 50 /* max 50*10 ms */
|
||||
#define TMP435_FRACTION_INC 0x80 /* 0.5000 */
|
||||
|
||||
static const int32_t tmp435_temp_offset = -64;
|
||||
|
||||
struct tmp435_data {
|
||||
int32_t temp_die; /* Celsius degrees */
|
||||
int32_t temp_ambient; /* Celsius degrees */
|
||||
};
|
||||
|
||||
struct tmp435_config {
|
||||
struct i2c_dt_spec i2c;
|
||||
bool external_channel;
|
||||
bool resistance_correction;
|
||||
uint8_t beta_compensation;
|
||||
};
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_TMP435_H_ */
|
||||
36
dts/bindings/sensor/ti,tmp435.yaml
Normal file
36
dts/bindings/sensor/ti,tmp435.yaml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#
|
||||
# Copyright (c) 2024 Bittium Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
description: Texas Instruments TMP435 temperature sensor
|
||||
|
||||
compatible: "ti,tmp435"
|
||||
|
||||
bus: tmp435
|
||||
|
||||
include: [sensor-device.yaml, i2c-device.yaml]
|
||||
|
||||
properties:
|
||||
external-channel:
|
||||
description: External temperature measurement is enabled
|
||||
type: boolean
|
||||
resistance-correction:
|
||||
description: |
|
||||
Resistance correction feature for the external
|
||||
temperature channel. If not enabled then conversion
|
||||
is faster but with lower accuracy.
|
||||
type: boolean
|
||||
beta-compensation:
|
||||
description: |
|
||||
Beta Compensation Configuration, see Table 8
|
||||
from TMP435 data sheet, some common values.
|
||||
0x0f, Automatically selected range 7 (beta > 27.0) or
|
||||
Automatically detected diode connected sensor
|
||||
0x07, Manually disabled beta correction
|
||||
Default is common value for general purpose transistors.
|
||||
type: int
|
||||
default: 0x0f
|
||||
enum: [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]
|
||||
|
|
@ -1219,7 +1219,14 @@ test_i2c_tmag3001: tmag3001@a8 {
|
|||
status = "okay";
|
||||
reg = <0xa8>;
|
||||
int-gpios = <&test_gpio 15 1>;
|
||||
|
||||
operation-mode = <TMAG5273_DT_OPER_MODE_CONTINUOUS>;
|
||||
angle-magnitude-axis = <TMAG5273_DT_ANGLE_MAG_XY>;
|
||||
};
|
||||
|
||||
test_i2c_tmp435: tmp435@a9 {
|
||||
compatible = "ti,tmp435";
|
||||
reg = <0xa9>;
|
||||
external-channel;
|
||||
resistance-correction;
|
||||
beta-compensation = <0x0f>;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue