sensor: eeprom: Add TMP116 EEPROM access

eeprom access is supported by using
either custom or eeprom API

Signed-off-by: Guillaume Lager <g.lager@innoseis.com>
This commit is contained in:
Guillaume Lager 2021-08-09 11:24:18 +02:00 committed by Maureen Helm
commit 972e5d0274
9 changed files with 209 additions and 1 deletions

View file

@ -10,3 +10,4 @@ zephyr_library_sources_ifdef(CONFIG_EEPROM_LPC11U6X eeprom_lpc11u6x.c)
zephyr_library_sources_ifdef(CONFIG_EEPROM_STM32 eeprom_stm32.c)
zephyr_library_sources_ifdef(CONFIG_EEPROM_SIMULATOR eeprom_simulator.c)
zephyr_library_sources_ifdef(CONFIG_EEPROM_EMULATOR eeprom_emulator.c)
zephyr_library_sources_ifdef(CONFIG_EEPROM_TMP116 eeprom_tmp116.c)

View file

@ -58,6 +58,7 @@ config EEPROM_AT25
source "drivers/eeprom/Kconfig.lpc11u6x"
source "drivers/eeprom/Kconfig.stm32"
source "drivers/eeprom/Kconfig.eeprom_emu"
source "drivers/eeprom/Kconfig.tmp116"
config EEPROM_SIMULATOR
bool "Simulated EEPROM driver"

View file

@ -0,0 +1,10 @@
# Copyright (c) 2021 Innoseis B.V.
# SPDX-License-Identifier: Apache-2.0
config EEPROM_TMP116
bool "TMP116 EEPROM driver"
depends on TMP116
default y
help
Enable support for the on-chip EEPROM found on
Texas instrument TMP116 temperature sensor

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2020 Innoseis B.V
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <devicetree.h>
#include <drivers/eeprom.h>
#include <drivers/sensor/tmp116.h>
#define DT_DRV_COMPAT ti_tmp116_eeprom
struct eeprom_tmp116_config {
const struct device *parent;
};
BUILD_ASSERT(CONFIG_EEPROM_INIT_PRIORITY >
CONFIG_SENSOR_INIT_PRIORITY,
"TMP116 eeprom driver must be initialized after TMP116 sensor "
"driver");
static size_t eeprom_tmp116_size(const struct device *dev)
{
return EEPROM_TMP116_SIZE;
}
static int eeprom_tmp116_write(const struct device *dev, off_t offset,
const void *data, size_t len)
{
const struct eeprom_tmp116_config *config = dev->config;
return tmp116_eeprom_write(config->parent, offset, data, len);
}
static int eeprom_tmp116_read(const struct device *dev, off_t offset, void *data,
size_t len)
{
const struct eeprom_tmp116_config *config = dev->config;
return tmp116_eeprom_read(config->parent, offset, data, len);
}
static int eeprom_tmp116_init(const struct device *dev)
{
const struct eeprom_tmp116_config *config = dev->config;
if (!device_is_ready(config->parent)) {
return -ENODEV;
}
return 0;
}
static const struct eeprom_driver_api eeprom_tmp116_api = {
.read = eeprom_tmp116_read,
.write = eeprom_tmp116_write,
.size = eeprom_tmp116_size,
};
#define DEFINE_TMP116(_num) \
static const struct eeprom_tmp116_config eeprom_tmp116_config##_num = { \
.parent = DEVICE_DT_GET(DT_INST_BUS(_num)) \
}; \
DEVICE_DT_INST_DEFINE(_num, eeprom_tmp116_init, NULL, \
NULL, &eeprom_tmp116_config##_num, POST_KERNEL, \
CONFIG_EEPROM_INIT_PRIORITY, &eeprom_tmp116_api);
DT_INST_FOREACH_STATUS_OKAY(DEFINE_TMP116);

View file

@ -9,6 +9,7 @@
#include <device.h>
#include <drivers/i2c.h>
#include <drivers/sensor.h>
#include <drivers/sensor/tmp116.h>
#include <sys/util.h>
#include <sys/byteorder.h>
#include <sys/__assert.h>
@ -17,6 +18,10 @@
#include "tmp116.h"
#define EEPROM_SIZE_REG sizeof(uint16_t)
#define EEPROM_TMP117_RESERVED (2 * sizeof(uint16_t))
#define EEPROM_MIN_BUSY_MS 7
LOG_MODULE_REGISTER(TMP116, CONFIG_SENSOR_LOG_LEVEL);
static int tmp116_reg_read(const struct device *dev, uint8_t reg,
@ -43,6 +48,94 @@ static int tmp116_reg_write(const struct device *dev, uint8_t reg,
return i2c_write_dt(&cfg->bus, tx_buf, sizeof(tx_buf));
}
static bool check_eeprom_bounds(const struct device *dev, off_t offset,
size_t len)
{
struct tmp116_data *drv_data = dev->data;
if ((offset + len) > EEPROM_TMP116_SIZE ||
offset % EEPROM_SIZE_REG != 0 ||
len % EEPROM_SIZE_REG != 0) {
return false;
}
/* TMP117 uses EEPROM[2] as temperature offset register */
if (drv_data->id == TMP117_DEVICE_ID &&
offset <= EEPROM_TMP117_RESERVED &&
(offset + len) > EEPROM_TMP117_RESERVED) {
return false;
}
return true;
}
int tmp116_eeprom_write(const struct device *dev, off_t offset,
const void *data, size_t len)
{
uint8_t reg;
const uint16_t *src = data;
int res;
if (!check_eeprom_bounds(dev, offset, len)) {
return -EINVAL;
}
res = tmp116_reg_write(dev, TMP116_REG_EEPROM_UL, TMP116_EEPROM_UL_UNLOCK);
if (res) {
return res;
}
for (reg = (offset / 2); reg < offset / 2 + len / 2; reg++) {
uint16_t val = *src;
res = tmp116_reg_write(dev, reg + TMP116_REG_EEPROM1, val);
if (res != 0) {
break;
}
k_sleep(K_MSEC(EEPROM_MIN_BUSY_MS));
do {
res = tmp116_reg_read(dev, TMP116_REG_EEPROM_UL, &val);
if (res != 0) {
break;
}
} while (val & TMP116_EEPROM_UL_BUSY);
src++;
if (res != 0) {
break;
}
}
res = tmp116_reg_write(dev, TMP116_REG_EEPROM_UL, 0);
return res;
}
int tmp116_eeprom_read(const struct device *dev, off_t offset, void *data,
size_t len)
{
uint8_t reg;
uint16_t *dst = data;
int res = 0;
if (!check_eeprom_bounds(dev, offset, len)) {
return -EINVAL;
}
for (reg = (offset / 2); reg < offset / 2 + len / 2; reg++) {
res = tmp116_reg_read(dev, reg + TMP116_REG_EEPROM1, dst);
if (res != 0) {
break;
}
dst++;
}
return res;
}
/**
* @brief Check the Device ID
*

View file

@ -25,7 +25,9 @@
#define TMP116_DEVICE_ID 0x1116
#define TMP117_DEVICE_ID 0x0117
#define TMP116_CFGR_DATA_READY BIT(13)
#define TMP116_CFGR_DATA_READY BIT(13)
#define TMP116_EEPROM_UL_UNLOCK BIT(15)
#define TMP116_EEPROM_UL_BUSY BIT(14)
struct tmp116_data {
uint16_t sample;

View file

@ -0,0 +1,10 @@
# Copyright (c) 2020 Innoseis B.V
# SPDX-License-Identifier: Apache-2.0
description: TI TMP116 EEPROM controller binding
compatible: "ti,tmp116-eeprom"
include: eeprom-base.yaml
on-bus: tmp116

View file

@ -5,4 +5,6 @@ description: Texas Instruments TMP116 temperature sensor
compatible: "ti,tmp116"
bus: tmp116
include: i2c-device.yaml

View file

@ -0,0 +1,21 @@
/*
* Copyright (c) 2021 Innoseis B.V
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_TMP116_H_
#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_TMP116_H_
#include <device.h>
#include <sys/types.h>
#define EEPROM_TMP116_SIZE (4 * sizeof(uint16_t))
int tmp116_eeprom_read(const struct device *dev, off_t offset, void *data,
size_t len);
int tmp116_eeprom_write(const struct device *dev, off_t offset,
const void *data, size_t len);
#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_TMP116_H_ */