drivers: sensor: tmp112: Add default device initialization

This allow to have a smaller driver footprint when a single
configuration is required.

Signed-off-by: Guillaume Lager <g.lager@innoseis.com>
This commit is contained in:
Guillaume Lager 2021-06-11 15:41:54 +02:00 committed by Carles Cufí
commit 4c986a266f
4 changed files with 134 additions and 57 deletions

View file

@ -12,3 +12,17 @@ config TMP112
The TMP102 is compatible with the TMP112 but is less accurate and has The TMP102 is compatible with the TMP112 but is less accurate and has
been successfully tested with this driver. been successfully tested with this driver.
config TMP112_FULL_SCALE_RUNTIME
bool "Allow to set extended mode at runtime"
default y
help
When set extended mode can be selected using tmp112_attr_set
with SENSOR_ATTR_FULL_SCALE and value to set either 128 or 150
config TMP112_SAMPLING_FREQUENCY_RUNTIME
bool "Allow to set conversion rate at runtime"
default y
help
When set conversion rate can be set at runtime using sensor_attr_set
with SENSOR_ATTR_SAMPLING_FREQUENCY

View file

@ -14,29 +14,10 @@
#include <drivers/sensor.h> #include <drivers/sensor.h>
#include <sys/__assert.h> #include <sys/__assert.h>
#include <logging/log.h> #include <logging/log.h>
#include "tmp112.h"
LOG_MODULE_REGISTER(TMP112, CONFIG_SENSOR_LOG_LEVEL); LOG_MODULE_REGISTER(TMP112, CONFIG_SENSOR_LOG_LEVEL);
#define TMP112_REG_TEMPERATURE 0x00
#define TMP112_D0_BIT BIT(0)
#define TMP112_REG_CONFIG 0x01
#define TMP112_EM_BIT BIT(4)
#define TMP112_CR0_BIT BIT(6)
#define TMP112_CR1_BIT BIT(7)
/* scale in micro degrees Celsius */
#define TMP112_TEMP_SCALE 62500
struct tmp112_data {
int16_t sample;
};
struct tmp112_config {
struct i2c_dt_spec bus;
};
static int tmp112_reg_read(const struct tmp112_config *cfg, static int tmp112_reg_read(const struct tmp112_config *cfg,
uint8_t reg, uint16_t *val) uint8_t reg, uint16_t *val)
{ {
@ -59,20 +40,25 @@ static int tmp112_reg_write(const struct tmp112_config *cfg,
return i2c_burst_write_dt(&cfg->bus, reg, (uint8_t *)&val_be, 2); return i2c_burst_write_dt(&cfg->bus, reg, (uint8_t *)&val_be, 2);
} }
static int tmp112_reg_update(const struct tmp112_config *cfg, uint8_t reg, static uint16_t set_config_flags(struct tmp112_data *data, uint16_t mask,
uint16_t mask, uint16_t val) uint16_t value)
{ {
uint16_t old_val = 0U; return (data->config_reg & ~mask) | (value & mask);
uint16_t new_val;
if (tmp112_reg_read(cfg, reg, &old_val) < 0) {
return -EIO;
} }
new_val = old_val & ~mask; static int tmp112_update_config(const struct device *dev, uint16_t mask,
new_val |= val & mask; uint16_t val)
{
int rc;
struct tmp112_data *data = dev->data;
const uint16_t new_val = set_config_flags(data, mask, val);
return tmp112_reg_write(cfg, reg, new_val); rc = tmp112_reg_write(dev->config, TMP112_REG_CONFIG, new_val);
if (rc == 0) {
data->config_reg = val;
}
return rc;
} }
static int tmp112_attr_set(const struct device *dev, static int tmp112_attr_set(const struct device *dev,
@ -80,7 +66,6 @@ static int tmp112_attr_set(const struct device *dev,
enum sensor_attribute attr, enum sensor_attribute attr,
const struct sensor_value *val) const struct sensor_value *val)
{ {
const struct tmp112_config *cfg = dev->config;
uint16_t value; uint16_t value;
uint16_t cr; uint16_t cr;
@ -89,26 +74,26 @@ static int tmp112_attr_set(const struct device *dev,
} }
switch (attr) { switch (attr) {
#if CONFIG_TMP112_FULL_SCALE_RUNTIME
case SENSOR_ATTR_FULL_SCALE: case SENSOR_ATTR_FULL_SCALE:
/* the sensor supports two ranges -55 to 128 and -55 to 150 */ /* the sensor supports two ranges -55 to 128 and -55 to 150 */
/* the value contains the upper limit */ /* the value contains the upper limit */
if (val->val1 == 128) { if (val->val1 == 128) {
value = 0x0000; value = 0x0000;
} else if (val->val1 == 150) { } else if (val->val1 == 150) {
value = TMP112_EM_BIT; value = TMP112_CONFIG_EM;
} else { } else {
return -ENOTSUP; return -ENOTSUP;
} }
if (tmp112_reg_update(cfg, TMP112_REG_CONFIG, if (tmp112_update_config(dev, TMP112_CONFIG_EM, value) < 0) {
TMP112_EM_BIT, value) < 0) {
LOG_DBG("Failed to set attribute!"); LOG_DBG("Failed to set attribute!");
return -EIO; return -EIO;
} }
break;
return 0; #endif
case SENSOR_ATTR_SAMPLING_FREQUENCY: case SENSOR_ATTR_SAMPLING_FREQUENCY:
#if CONFIG_TMP112_SAMPLING_FREQUENCY_RUNTIME
/* conversion rate in mHz */ /* conversion rate in mHz */
cr = val->val1 * 1000 + val->val2 / 1000; cr = val->val1 * 1000 + val->val2 / 1000;
@ -116,33 +101,32 @@ static int tmp112_attr_set(const struct device *dev,
/* conversion rate */ /* conversion rate */
switch (cr) { switch (cr) {
case 250: case 250:
value = 0x0000; value = TMP112_CONV_RATE(TMP112_CONV_RATE_025);
break; break;
case 1000: case 1000:
value = TMP112_CR0_BIT; value = TMP112_CONV_RATE(TMP112_CONV_RATE_1000);
break; break;
case 4000: case 4000:
value = TMP112_CR1_BIT; value = TMP112_CONV_RATE(TMP112_CONV_RATE_4);
break; break;
case 8000: case 8000:
value = TMP112_CR0_BIT | TMP112_CR1_BIT; value = TMP112_CONV_RATE(TMP112_CONV_RATE_8);
break; break;
default: default:
return -ENOTSUP; return -ENOTSUP;
} }
if (tmp112_reg_update(cfg, TMP112_REG_CONFIG, if (tmp112_update_config(dev, TMP112_CONV_RATE_MASK, value) < 0) {
TMP112_CR0_BIT | TMP112_CR1_BIT,
value) < 0) {
LOG_DBG("Failed to set attribute!"); LOG_DBG("Failed to set attribute!");
return -EIO; return -EIO;
} }
return 0; break;
#endif
default: default:
return -ENOTSUP; return -ENOTSUP;
@ -164,10 +148,12 @@ static int tmp112_sample_fetch(const struct device *dev,
return -EIO; return -EIO;
} }
if (val & TMP112_D0_BIT) { if (val & TMP112_DATA_EXTENDED) {
drv_data->sample = arithmetic_shift_right((int16_t)val, 3); drv_data->sample = arithmetic_shift_right((int16_t)val,
TMP112_DATA_EXTENDED_SHIFT);
} else { } else {
drv_data->sample = arithmetic_shift_right((int16_t)val, 4); drv_data->sample = arithmetic_shift_right((int16_t)val,
TMP112_DATA_NORMAL_SHIFT);
} }
return 0; return 0;
@ -200,20 +186,28 @@ static const struct sensor_driver_api tmp112_driver_api = {
int tmp112_init(const struct device *dev) int tmp112_init(const struct device *dev)
{ {
const struct tmp112_config *cfg = dev->config; const struct tmp112_config *cfg = dev->config;
struct tmp112_data *data = dev->data;
if (!device_is_ready(cfg->bus.bus)) { if (!device_is_ready(cfg->bus.bus)) {
LOG_ERR("I2C dev %s not ready", cfg->bus.bus->name); LOG_ERR("I2C dev %s not ready", cfg->bus.bus->name);
return -EINVAL; return -EINVAL;
} }
return 0; data->config_reg = TMP112_CONV_RATE(cfg->cr) | TMP112_CONV_RES_MASK
| (cfg->extended_mode ? TMP112_CONFIG_EM : 0);
return tmp112_update_config(dev, 0, 0);
} }
#define TMP112_INST(inst) \ #define TMP112_INST(inst) \
static struct tmp112_data tmp112_data_##inst; \ static struct tmp112_data tmp112_data_##inst; \
static const struct tmp112_config tmp112_config_##inst = { \ static const struct tmp112_config tmp112_config_##inst = { \
.bus = I2C_DT_SPEC_INST_GET(inst) \ .bus = I2C_DT_SPEC_INST_GET(inst), \
.cr = DT_ENUM_IDX(DT_DRV_INST(inst), conversion_rate), \
.extended_mode = DT_INST_PROP(inst, extended_mode), \
}; \ }; \
\
DEVICE_DT_INST_DEFINE(inst, tmp112_init, NULL, &tmp112_data_##inst, \ DEVICE_DT_INST_DEFINE(inst, tmp112_init, NULL, &tmp112_data_##inst, \
&tmp112_config_##inst, POST_KERNEL, \ &tmp112_config_##inst, POST_KERNEL, \
CONFIG_SENSOR_INIT_PRIORITY, &tmp112_driver_api); CONFIG_SENSOR_INIT_PRIORITY, &tmp112_driver_api);

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2020 Innoseis BV
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_DRIVERS_SENSOR_TMP112_TMP112_H_
#define ZEPHYR_DRIVERS_SENSOR_TMP112_TMP112_H_
#include <device.h>
#include <sys/util.h>
#define TMP112_REG_TEMPERATURE 0x00
#define TMP112_DATA_INVALID_BIT (BIT(1) | BIT(2))
#define TMP112_DATA_EXTENDED (BIT(0))
#define TMP112_DATA_EXTENDED_SHIFT 3
#define TMP112_DATA_NORMAL_SHIFT 4
#define TMP112_REG_CONFIG 0x01
#define TMP112_CONFIG_EM BIT(4)
#define TMP112_ALERT_EN_BIT BIT(5)
#define TMP112_CONV_RATE_SHIFT 6
#define TMP112_CONV_RATE_MASK (BIT_MASK(2) << TMP112_CONV_RATE_SHIFT)
#define TMP112_CONV_RATE_025 0
#define TMP112_CONV_RATE_1000 1
#define TMP112_CONV_RATE_4 2
#define TMP112_CONV_RATE_8 3
#define TMP112_CONV_RATE(cr) ((cr) << TMP112_CONV_RATE_SHIFT)
#define TMP112_CONV_RES_SHIFT 13
#define TMP112_CONV_RES_MASK (BIT_MASK(2) << TMP112_CONV_RES_SHIFT)
#define TMP112_ONE_SHOT BIT(15)
#define TMP112_REG_TLOW 0x02
#define TMP112_REG_THIGH 0x03
/* scale in micro degrees Celsius */
#define TMP112_TEMP_SCALE 62500
struct tmp112_data {
int16_t sample;
uint16_t config_reg;
};
struct tmp112_config {
const struct i2c_dt_spec bus;
uint8_t cr;
bool extended_mode : 1;
};
#endif

View file

@ -8,3 +8,17 @@ description: |
compatible: "ti,tmp112" compatible: "ti,tmp112"
include: i2c-device.yaml include: i2c-device.yaml
properties:
conversion-rate:
description: Conversion rate in mHz (milli-Hertz)
type: int
default: 4000
enum:
- 250
- 1000
- 4000
- 8000
extended-mode:
description: When true use 13-bit data format allowing measuring temperature up to 128°C
type: boolean