From 4cfce5cb6457514947f2ffeba9e3168945cd370d Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 28 Sep 2017 08:13:01 +0200 Subject: i2c: Add temperature sensor LM75A driver Close #3163. --- cpukit/dev/Makefile.am | 2 + cpukit/dev/i2c/sensor-lm75a.c | 198 ++++++++++++++++++++++++++++++ cpukit/dev/include/dev/i2c/sensor-lm75a.h | 125 +++++++++++++++++++ cpukit/dev/preinstall.am | 4 + 4 files changed, 329 insertions(+) create mode 100644 cpukit/dev/i2c/sensor-lm75a.c create mode 100644 cpukit/dev/include/dev/i2c/sensor-lm75a.h (limited to 'cpukit') diff --git a/cpukit/dev/Makefile.am b/cpukit/dev/Makefile.am index debb084990..b60e035fdb 100644 --- a/cpukit/dev/Makefile.am +++ b/cpukit/dev/Makefile.am @@ -10,6 +10,7 @@ include_dev_i2c_HEADERS += include/dev/i2c/eeprom.h include_dev_i2c_HEADERS += include/dev/i2c/fpga-i2c-slave.h include_dev_i2c_HEADERS += include/dev/i2c/gpio-nxp-pca9535.h include_dev_i2c_HEADERS += include/dev/i2c/i2c.h +include_dev_i2c_HEADERS += include/dev/i2c/sensor-lm75a.h include_dev_i2c_HEADERS += include/dev/i2c/switch-nxp-pca9548a.h include_dev_i2c_HEADERS += include/dev/i2c/xilinx-axi-i2c.h include_dev_i2c_HEADERS += include/dev/i2c/ti-ads-16bit-adc.h @@ -41,6 +42,7 @@ libdev_a_SOURCES += i2c/fpga-i2c-slave.c libdev_a_SOURCES += i2c/gpio-nxp-pca9535.c libdev_a_SOURCES += i2c/i2c-bus.c libdev_a_SOURCES += i2c/i2c-dev.c +libdev_a_SOURCES += i2c/sensor-lm75a.c libdev_a_SOURCES += i2c/switch-nxp-pca9548a.c libdev_a_SOURCES += i2c/xilinx-axi-i2c.c libdev_a_SOURCES += i2c/ti-ads-16bit-adc.c diff --git a/cpukit/dev/i2c/sensor-lm75a.c b/cpukit/dev/i2c/sensor-lm75a.c new file mode 100644 index 0000000000..4cc1ae681e --- /dev/null +++ b/cpukit/dev/i2c/sensor-lm75a.c @@ -0,0 +1,198 @@ +/** + * @file + * + * @brief Temperature Sensor LM75A Driver Implementation + * + * @ingroup I2CSensorLM75A + */ + +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +typedef enum { + SENSOR_LM75A_PTR_TEMP, + SENSOR_LM75A_PTR_CONF, + SENSOR_LM75A_PTR_THYST, + SENSOR_LM75A_PTR_TOS +} sensor_lm75a_ptr; + +static int sensor_lm75a_get_reg_8( + i2c_dev *dev, + sensor_lm75a_ptr ptr, + uint8_t *val +) +{ + uint8_t out[1] = { ptr }; + uint8_t in[sizeof(*val)]; + i2c_msg msgs[2] = { + { + .addr = dev->address, + .flags = 0, + .len = (uint16_t) sizeof(out), + .buf = &out[0] + }, { + .addr = dev->address, + .flags = I2C_M_RD, + .len = (uint16_t) sizeof(in), + .buf = &in[0] + } + }; + int err; + + err = i2c_bus_transfer(dev->bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs)); + *val = in[0]; + + return err; +} + +static int sensor_lm75a_set_reg_8( + i2c_dev *dev, + sensor_lm75a_ptr ptr, + uint8_t val +) +{ + uint8_t out[2] = { ptr, val }; + i2c_msg msgs[1] = { + { + .addr = dev->address, + .flags = 0, + .len = (uint16_t) sizeof(out), + .buf = &out[0] + } + }; + + return i2c_bus_transfer(dev->bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs)); +} + +static int sensor_lm75a_get_reg_16( + i2c_dev *dev, + sensor_lm75a_ptr ptr, + uint16_t *val +) +{ + uint8_t out[1] = { ptr }; + uint8_t in[sizeof(*val)]; + i2c_msg msgs[2] = { + { + .addr = dev->address, + .flags = 0, + .len = (uint16_t) sizeof(out), + .buf = &out[0] + }, { + .addr = dev->address, + .flags = I2C_M_RD, + .len = (uint16_t) sizeof(in), + .buf = &in[0] + } + }; + int err; + + err = i2c_bus_transfer(dev->bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs)); + *val = (in[0] << 8) | in[1]; + + return err; +} + +static int sensor_lm75a_set_reg_16( + i2c_dev *dev, + sensor_lm75a_ptr ptr, + uint16_t val +) +{ + uint8_t out[3] = { ptr, (uint8_t) (val >> 8), (uint8_t) val }; + i2c_msg msgs[1] = { + { + .addr = dev->address, + .flags = 0, + .len = (uint16_t) sizeof(out), + .buf = &out[0] + } + }; + + return i2c_bus_transfer(dev->bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs)); +} + +static int sensor_lm75a_ioctl( + i2c_dev *dev, + ioctl_command_t command, + void *arg +) +{ + uint8_t v8 = (uint8_t) (uintptr_t) arg; + uint16_t v16 = (uint16_t) (uintptr_t) arg; + int err; + + switch (command) { + case SENSOR_LM75A_GET_CONF: + err = sensor_lm75a_get_reg_8(dev, SENSOR_LM75A_PTR_CONF, arg); + break; + case SENSOR_LM75A_SET_CONF: + err = sensor_lm75a_set_reg_8(dev, SENSOR_LM75A_PTR_CONF, v8); + break; + case SENSOR_LM75A_CLEAR_AND_SET_CONF: + i2c_bus_obtain(dev->bus); + err = sensor_lm75a_get_reg_8(dev, SENSOR_LM75A_PTR_CONF, &v8); + if (err == 0) { + v8 &= ~((uint8_t) v16); + v8 |= (uint8_t) (v16 >> 8); + err = sensor_lm75a_set_reg_8(dev, SENSOR_LM75A_PTR_CONF, v8); + } + i2c_bus_release(dev->bus); + break; + case SENSOR_LM75A_GET_TEMP: + err = sensor_lm75a_get_reg_16(dev, SENSOR_LM75A_PTR_TEMP, arg); + break; + case SENSOR_LM75A_GET_TOS: + err = sensor_lm75a_get_reg_16(dev, SENSOR_LM75A_PTR_TOS, arg); + break; + case SENSOR_LM75A_SET_TOS: + err = sensor_lm75a_set_reg_16(dev, SENSOR_LM75A_PTR_TOS, v16); + break; + case SENSOR_LM75A_GET_THYST: + err = sensor_lm75a_get_reg_16(dev, SENSOR_LM75A_PTR_THYST, arg); + break; + case SENSOR_LM75A_SET_THYST: + err = sensor_lm75a_set_reg_16(dev, SENSOR_LM75A_PTR_THYST, v16); + break; + default: + err = -ENOTTY; + break; + } + + return err; +} + +int i2c_dev_register_sensor_lm75a( + const char *bus_path, + const char *dev_path, + uint16_t address +) +{ + i2c_dev *dev; + + dev = i2c_dev_alloc_and_init(sizeof(*dev), bus_path, address); + if (dev == NULL) { + return -1; + } + + dev->ioctl = sensor_lm75a_ioctl; + + return i2c_dev_register(dev, dev_path); +} diff --git a/cpukit/dev/include/dev/i2c/sensor-lm75a.h b/cpukit/dev/include/dev/i2c/sensor-lm75a.h new file mode 100644 index 0000000000..e1957dad19 --- /dev/null +++ b/cpukit/dev/include/dev/i2c/sensor-lm75a.h @@ -0,0 +1,125 @@ +/** + * @file + * + * @brief Temperature Sensor LM75A Driver API + * + * @ingroup I2CSensorLM75A + */ + +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef _DEV_I2C_SENSOR_LM75A_H +#define _DEV_I2C_SENSOR_LM75A_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup I2CSensorLM75A Temperature Sensor LM75A Driver + * + * @ingroup I2CDevice + * + * @brief Driver for NXP or Texas Instruments LM75A temperature sensor. + * + * @{ + */ + +int i2c_dev_register_sensor_lm75a( + const char *bus_path, + const char *dev_path, + uint16_t address +); + +typedef enum { + SENSOR_LM75A_GET_CONF = I2C_DEV_IO_CONTROL, + SENSOR_LM75A_SET_CONF, + SENSOR_LM75A_CLEAR_AND_SET_CONF, + SENSOR_LM75A_GET_TEMP, + SENSOR_LM75A_GET_TOS, + SENSOR_LM75A_SET_TOS, + SENSOR_LM75A_GET_THYST, + SENSOR_LM75A_SET_THYST +} sensor_lm75a_command; + +static inline int sensor_lm75a_get_conf(int fd, uint8_t *val) +{ + return ioctl(fd, SENSOR_LM75A_GET_CONF, val); +} + +static inline int sensor_lm75a_set_conf(int fd, uint8_t val) +{ + return ioctl(fd, SENSOR_LM75A_SET_CONF, (void *)(uintptr_t) val); +} + +static inline int sensor_lm75a_clear_and_set_conf( + int fd, + uint8_t clear, + uint8_t set +) +{ + uint16_t clear_and_set = (uint16_t) (((uint16_t) set << 8) | clear); + + return ioctl( + fd, + SENSOR_LM75A_CLEAR_AND_SET_CONF, + (void *)(uintptr_t) clear_and_set + ); +} + +static inline int sensor_lm75a_get_temp(int fd, int16_t *val) +{ + return ioctl(fd, SENSOR_LM75A_GET_TEMP, val); +} + +static inline int sensor_lm75a_get_temp_celsius(int fd, double *celsius) +{ + int rv; + int16_t val; + + rv = ioctl(fd, SENSOR_LM75A_GET_TEMP, &val); + *celsius = (((int) val) >> 5) * 0.125; + return rv; +} + +static inline int sensor_lm75a_get_tos(int fd, uint16_t *val) +{ + return ioctl(fd, SENSOR_LM75A_GET_TOS, val); +} + +static inline int sensor_lm75a_set_tos(int fd, uint16_t val) +{ + return ioctl(fd, SENSOR_LM75A_SET_TOS, (void *)(uintptr_t) val); +} + +static inline int sensor_lm75a_get_thyst(int fd, uint16_t *val) +{ + return ioctl(fd, SENSOR_LM75A_GET_THYST, val); +} + +static inline int sensor_lm75a_set_thyst(int fd, uint16_t val) +{ + return ioctl(fd, SENSOR_LM75A_SET_THYST, (void *)(uintptr_t) val); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _DEV_I2C_SENSOR_LM75A_H */ diff --git a/cpukit/dev/preinstall.am b/cpukit/dev/preinstall.am index fd35488fd0..4cb1dce127 100644 --- a/cpukit/dev/preinstall.am +++ b/cpukit/dev/preinstall.am @@ -39,6 +39,10 @@ $(PROJECT_INCLUDE)/dev/i2c/i2c.h: include/dev/i2c/i2c.h $(PROJECT_INCLUDE)/dev/i $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dev/i2c/i2c.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/dev/i2c/i2c.h +$(PROJECT_INCLUDE)/dev/i2c/sensor-lm75a.h: include/dev/i2c/sensor-lm75a.h $(PROJECT_INCLUDE)/dev/i2c/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dev/i2c/sensor-lm75a.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/dev/i2c/sensor-lm75a.h + $(PROJECT_INCLUDE)/dev/i2c/switch-nxp-pca9548a.h: include/dev/i2c/switch-nxp-pca9548a.h $(PROJECT_INCLUDE)/dev/i2c/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dev/i2c/switch-nxp-pca9548a.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/dev/i2c/switch-nxp-pca9548a.h -- cgit v1.2.3