From 8ba04d595b8945ad73bd1a8d5a2bdffc406e26ea Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Tue, 2 May 2017 15:21:36 +0200 Subject: [PATCH] sensors: add lps22hb sensor driver Support for LPS22HB Pressure and temperature sensor provided with bare minimum features. For more info on this sensor: http://www.st.com/en/mems-and-sensors/lps22hb.html Change-Id: I14992b954053094beb054d0dba7581f6e29a3e68 Signed-off-by: Erwan Gouriou --- drivers/sensor/Kconfig | 2 + drivers/sensor/Makefile | 1 + drivers/sensor/lps22hb/Kconfig | 56 ++++++++++ drivers/sensor/lps22hb/Makefile | 1 + drivers/sensor/lps22hb/lps22hb.c | 158 ++++++++++++++++++++++++++++ drivers/sensor/lps22hb/lps22hb.h | 170 +++++++++++++++++++++++++++++++ 6 files changed, 388 insertions(+) create mode 100644 drivers/sensor/lps22hb/Kconfig create mode 100644 drivers/sensor/lps22hb/Makefile create mode 100644 drivers/sensor/lps22hb/lps22hb.c create mode 100644 drivers/sensor/lps22hb/lps22hb.h diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 4eabb4e3a83..27725ac9f83 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -76,6 +76,8 @@ source "drivers/sensor/lis3dh/Kconfig" source "drivers/sensor/lis3mdl/Kconfig" +source "drivers/sensor/lps22hb/Kconfig" + source "drivers/sensor/lps25hb/Kconfig" source "drivers/sensor/lsm6ds0/Kconfig" diff --git a/drivers/sensor/Makefile b/drivers/sensor/Makefile index 5f828cd15e3..60b4b0b2c7a 100644 --- a/drivers/sensor/Makefile +++ b/drivers/sensor/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_ISL29035) += isl29035/ obj-$(CONFIG_LIS2DH) += lis2dh/ obj-$(CONFIG_LIS3DH) += lis3dh/ obj-$(CONFIG_LIS3MDL) += lis3mdl/ +obj-$(CONFIG_LPS22HB) += lps22hb/ obj-$(CONFIG_LPS25HB) += lps25hb/ obj-$(CONFIG_LSM6DS0) += lsm6ds0/ obj-$(CONFIG_LSM9DS0_GYRO) += lsm9ds0_gyro/ diff --git a/drivers/sensor/lps22hb/Kconfig b/drivers/sensor/lps22hb/Kconfig new file mode 100644 index 00000000000..661b6156fa4 --- /dev/null +++ b/drivers/sensor/lps22hb/Kconfig @@ -0,0 +1,56 @@ +# +# Copyright (c) 2017 Linaro Limited +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig LPS22HB + bool + prompt "LPS22HB pressure and temperature" + depends on SENSOR && I2C + default n + help + Enable driver for LPS22HB I2C-based pressure and temperature + sensor. + +config LPS22HB_DEV_NAME + string + prompt "Device name" + default "LPS22HB" + depends on LPS22HB + help + Device name used for LPS22HB sensor identification. + +config LPS22HB_I2C_ADDR + hex + prompt "I2C address" + depends on LPS22HB + default 0x5D + range 0x5C 0x5D + help + I2C address of the LPS22HB sensor. + Use 0x5C if the SA0 pin is pulled to GND or 0x5D if the SA0 + pin is pulled to VDD. + +config LPS22HB_I2C_MASTER_DEV_NAME + string + prompt "I2C master where LPS22HB is connected" + depends on LPS22HB + default I2C_0_NAME + help + Specify the device name of the I2C master device to which + LPS22HB is connected. + +menu "Attributes" + depends on LPS22HB + +config LPS22HB_SAMPLING_RATE + int + prompt "Output data rate" + depends on LPS22HB + default 25 + help + Sensor output data rate expressed in samples per second. + Data rates supported by the chip are 1, 10, 25, 50, 75. + +endmenu diff --git a/drivers/sensor/lps22hb/Makefile b/drivers/sensor/lps22hb/Makefile new file mode 100644 index 00000000000..f03fc09f87c --- /dev/null +++ b/drivers/sensor/lps22hb/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_LPS22HB) += lps22hb.o diff --git a/drivers/sensor/lps22hb/lps22hb.c b/drivers/sensor/lps22hb/lps22hb.c new file mode 100644 index 00000000000..d942eaaa7a5 --- /dev/null +++ b/drivers/sensor/lps22hb/lps22hb.c @@ -0,0 +1,158 @@ +/* lps22hb.c - Driver for LPS22HB pressure and temperature sensor */ + +/* + * Copyright (c) 2017 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include "lps22hb.h" + +static inline int lps22hb_set_odr_raw(struct device *dev, u8_t odr) +{ + struct lps22hb_data *data = dev->driver_data; + const struct lps22hb_config *config = dev->config->config_info; + + return i2c_reg_update_byte(data->i2c_master, config->i2c_slave_addr, + LPS22HB_REG_CTRL_REG1, + LPS22HB_MASK_CTRL_REG1_ODR, + odr << LPS22HB_SHIFT_CTRL_REG1_ODR); +} + +static int lps22hb_sample_fetch(struct device *dev, + enum sensor_channel chan) +{ + struct lps22hb_data *data = dev->driver_data; + const struct lps22hb_config *config = dev->config->config_info; + u8_t out[5]; + + __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); + + if (i2c_burst_read(data->i2c_master, config->i2c_slave_addr, + LPS22HB_REG_PRESS_OUT_XL, out, 5) < 0) { + SYS_LOG_DBG("Failed to read sample"); + return -EIO; + } + + data->sample_press = (s32_t)((u32_t)(out[0]) | + ((u32_t)(out[1]) << 8) | + ((u32_t)(out[2]) << 16)); + data->sample_temp = (s16_t)((u16_t)(out[3]) | + ((u16_t)(out[4]) << 8)); + + return 0; +} + +static inline void lps22hb_press_convert(struct sensor_value *val, + s32_t raw_val) +{ + /* Pressure sensitivity is 4096 LSB/hPa */ + /* Convert raw_val to val in kPa */ + val->val1 = (raw_val >> 12) / 10; + val->val2 = ((s32_t)((raw_val) & 0x0FFF) * 1000L) >> 12; +} + +static inline void lps22hb_temp_convert(struct sensor_value *val, + s16_t raw_val) +{ + /* Temperature sensitivity is 100 LSB/deg C */ + val->val1 = raw_val / 100; + val->val2 = (s32_t)raw_val % 100; +} + +static int lps22hb_channel_get(struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct lps22hb_data *data = dev->driver_data; + + if (chan == SENSOR_CHAN_PRESS) { + lps22hb_press_convert(val, data->sample_press); + } else if (chan == SENSOR_CHAN_TEMP) { + lps22hb_temp_convert(val, data->sample_temp); + } else { + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api lps22hb_api_funcs = { + .sample_fetch = lps22hb_sample_fetch, + .channel_get = lps22hb_channel_get, +}; + +static int lps22hb_init_chip(struct device *dev) +{ + struct lps22hb_data *data = dev->driver_data; + const struct lps22hb_config *config = dev->config->config_info; + u8_t chip_id; + + if (i2c_reg_read_byte(data->i2c_master, config->i2c_slave_addr, + LPS22HB_REG_WHO_AM_I, &chip_id) < 0) { + SYS_LOG_DBG("Failed reading chip id"); + goto err_poweroff; + } + + if (chip_id != LPS22HB_VAL_WHO_AM_I) { + SYS_LOG_DBG("Invalid chip id 0x%x", chip_id); + goto err_poweroff; + } + + if (lps22hb_set_odr_raw(dev, LPS22HB_DEFAULT_SAMPLING_RATE) < 0) { + SYS_LOG_DBG("Failed to set sampling rate"); + goto err_poweroff; + } + + if (i2c_reg_update_byte(data->i2c_master, config->i2c_slave_addr, + LPS22HB_REG_CTRL_REG1, + LPS22HB_MASK_CTRL_REG1_BDU, + (1 << LPS22HB_SHIFT_CTRL_REG1_BDU)) < 0) { + SYS_LOG_DBG("Failed to set BDU"); + goto err_poweroff; + } + + return 0; + +err_poweroff: + return -EIO; +} + +static int lps22hb_init(struct device *dev) +{ + const struct lps22hb_config * const config = dev->config->config_info; + struct lps22hb_data *data = dev->driver_data; + + data->i2c_master = device_get_binding(config->i2c_master_dev_name); + + if (!data->i2c_master) { + SYS_LOG_DBG("I2c master not found: %s", + config->i2c_master_dev_name); + return -EINVAL; + } + + if (lps22hb_init_chip(dev) < 0) { + SYS_LOG_DBG("Failed to initialize chip"); + return -EIO; + } + + return 0; +} + +static const struct lps22hb_config lps22hb_config = { + .i2c_master_dev_name = CONFIG_LPS22HB_I2C_MASTER_DEV_NAME, + .i2c_slave_addr = CONFIG_LPS22HB_I2C_ADDR, +}; + +static struct lps22hb_data lps22hb_data; + +DEVICE_AND_API_INIT(lps22hb, CONFIG_LPS22HB_DEV_NAME, lps22hb_init, + &lps22hb_data, &lps22hb_config, POST_KERNEL, + CONFIG_SENSOR_INIT_PRIORITY, &lps22hb_api_funcs); diff --git a/drivers/sensor/lps22hb/lps22hb.h b/drivers/sensor/lps22hb/lps22hb.h new file mode 100644 index 00000000000..6ad987231c4 --- /dev/null +++ b/drivers/sensor/lps22hb/lps22hb.h @@ -0,0 +1,170 @@ +/* sensor_lps25hb.h - header file for LPS22HB pressure and temperature + * sensor driver + */ + +/* + * Copyright (c) 2017 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __SENSOR_LPS22HB_H__ +#define __SENSOR_LPS22HB_H__ + +#include +#include +#include + +#define LPS22HB_REG_WHO_AM_I 0x0F +#define LPS22HB_VAL_WHO_AM_I 0xB1 + +#define LPS22HB_REG_INTERRUPT_CFG 0x0B +#define LPS22HB_MASK_INTERRUPT_CFG_AUTORIFP BIT(7) +#define LPS22HB_SHIFT_INTERRUPT_CFG_AUTORIFP 7 +#define LPS22HB_MASK_INTERRUPT_CFG_RESET_ARP BIT(6) +#define LPS22HB_SHIFT_INTERRUPT_CFG_RESET_ARP 6 +#define LPS22HB_MASK_INTERRUPT_CFG_AUTOZERO BIT(5) +#define LPS22HB_SHIFT_INTERRUPT_CFG_AUTOZERO 5 +#define LPS22HB_MASK_INTERRUPT_CFG_RESET_AZ BIT(4) +#define LPS22HB_SHIFT_INTERRUPT_CFG_RESET_AZ 4 +#define LPS22HB_MASK_INTERRUPT_CFG_DIFF_EN BIT(3) +#define LPS22HB_SHIFT_INTERRUPT_CFG_DIFF_EN 3 +#define LPS22HB_MASK_INTERRUPT_CFG_LIR BIT(2) +#define LPS22HB_SHIFT_INTERRUPT_CFG_LIR 2 +#define LPS22HB_MASK_INTERRUPT_CFG_PL_E BIT(1) +#define LPS22HB_SHIFT_INTERRUPT_CFG_PL_E 1 +#define LPS22HB_MASK_INTERRUPT_CFG_PH_E BIT(0) +#define LPS22HB_SHIFT_INTERRUPT_CFG_PH_E 0 + +#define LPS22HB_REG_THS_P_L 0x0C +#define LPS22HB_REG_THS_P_H 0x0D + +#define LPS22HB_REG_CTRL_REG1 0x10 +#define LPS22HB_MASK_CTRL_REG1_ODR (BIT(6) | BIT(5) | BIT(4)) +#define LPS22HB_SHIFT_CTRL_REG1_ODR 4 +#define LPS22HB_MASK_CTRL_REG1_EN_LPFP BIT(3) +#define LPS22HB_SHIFT_CTRL_REG1_EN_LPFP 3 +#define LPS22HB_MASK_CTRL_REG1_LPFP_CFG BIT(2) +#define LPS22HB_SHIFT_CTRL_REG1_LPFP_CFG 2 +#define LPS22HB_MASK_CTRL_REG1_BDU BIT(1) +#define LPS22HB_SHIFT_CTRL_REG1_BDU 1 +#define LPS22HB_MASK_CTRL_REG1_SIM BIT(0) +#define LPS22HB_SHIFT_CTRL_REG1_SIM 0 + +#define LPS22HB_REG_CTRL_REG2 0x11 +#define LPS22HB_MASK_CTRL_REG2_BOOT BIT(7) +#define LPS22HB_SHIFT_CTRL_REG2_BOOT 7 +#define LPS22HB_MASK_CTRL_REG2_FIFO_EN BIT(6) +#define LPS22HB_SHIFT_CTRL_REG2_FIFO_EN 6 +#define LPS22HB_MASK_CTRL_REG2_STOP_ON_FTH BIT(5) +#define LPS22HB_SHIFT_CTRL_REG2_STOP_ON_FTH 5 +#define LPS22HB_MASK_CTRL_REG2_IF_ADD_INC BIT(4) +#define LPS22HB_SHIFT_CTRL_REG2_IF_ADD_INC 4 +#define LPS22HB_MASK_CTRL_REG2_I2C_DIS BIT(3) +#define LPS22HB_SHIFT_CTRL_REG2_I2C_DIS 3 +#define LPS22HB_MASK_CTRL_REG2_SWRESET BIT(2) +#define LPS22HB_SHIFT_CTRL_REG2_SWRESET 2 +#define LPS22HB_MASK_CTRL_REG2_ONE_SHOT BIT(0) +#define LPS22HB_SHIFT_CTRL_REG2_ONE_SHOT 0 + +#define LPS22HB_REG_CTRL_REG3 0x12 +#define LPS22HB_MASK_CTRL_REG3_INT_H_L BIT(7) +#define LPS22HB_SHIFT_CTRL_REG3_INT_H_L 7 +#define LPS22HB_MASK_CTRL_REG3_PP_OD BIT(6) +#define LPS22HB_SHIFT_CTRL_REG3_PP_OD 6 +#define LPS22HB_MASK_CTRL_REG3_F_FSS5 BIT(5) +#define LPS22HB_SHIFT_CTRL_REG3_F_FFS5 5 +#define LPS22HB_MASK_CTRL_REG3_F_FTH BIT(4) +#define LPS22HB_SHIFT_CTRL_REG3_F_FTH 4 +#define LPS22HB_MASK_CTRL_REG3_F_OVR BIT(3) +#define LPS22HB_SHIFT_CTRL_REG3_F_OVR 3 +#define LPS22HB_MASK_CTRL_REG3_DRDY BIT(2) +#define LPS22HB_SHIFT_CTRL_REG3_DRDY 2 +#define LPS22HB_MASK_CTRL_REG3_INT_S (BIT(1) | BIT(0)) +#define LPS22HB_SHIFT_CTRL_REG_INT_S 0 + +#define LPS22HB_REG_FIFO_CTRL 0x14 +#define LPS22HB_MASK_FIFO_CTRL_F_MODE (BIT(7) | BIT(6) | BIT(5)) +#define LPS22HB_SHIFT_FIFO_CTRL_F_MODE 5 +#define LPS22HB_MASK_FIFO_CTRL_WTM (BIT(4) | BIT(3) | BIT(2) | \ + BIT(2) | BIT(1) | BIT(0)) +#define LPS22HB_SHIFT_FIFO_CTRL_WTM 0 + +#define LPS22HB_REG_REF_P_XL 0x15 +#define LPS22HB_REG_REF_P_L 0x16 +#define LPS22HB_REG_REF_P_H 0x17 + +#define LPS22HB_REG_RPDS_L 0x18 +#define LPS22HB_REG_RPDS_H 0x19 + +#define LPS22HB_REG_RES_CONF 0x1A +#define LPS22HB_MASK_RES_CONF_LC_EN BIT(0) +#define LPS22HB_SHIFT_RES_CONF_LC_EN 0 + +#define LPS22HB_REG_INT_SOURCE 0x25 +#define LPS22HB_MASK_INT_SOURCE_IA BIT(2) +#define LPS22HB_SHIFT_INT_SOURCE_IA 2 +#define LPS22HB_MASK_INT_SOURCE_PL BIT(1) +#define LPS22HB_SHIFT_INT_SOURCE_PL 1 +#define LPS22HB_MASK_INT_SOURCE_PH BIT(0) +#define LPS22HB_SHIFT_INT_SOURCE_PH 0 + +#define LPS22HB_REG_FIFO_STATUS 0x26 +#define LPS22HB_MASK_FIFO_STATUS_FTH_FIFO BIT(7) +#define LPS22HB_SHIFT_FIFO_STATUS_FTH_FIFO 7 +#define LPS22HB_MASK_FIFO_STATUS_OVR BIT(6) +#define LPS22HB_SHIFT_FIFO_STATUS_OVR 6 +#define LPS22HB_MASK_FIFO_STATUS_EMPTY_FIFO BIT(5) +#define LPS22HB_SHIFT_FIFO_STATUS_EMPTY_FIFO 5 +#define LPS22HB_MASK_FIFO_STATUS_FSS (BIT(4) | BIT(3) | BIT(2) | \ + BIT(1) | BIT(0)) +#define LPS22HB_SHIFT_FIFO_STATUS_FSS 0 + +#define LPS22HB_REG_STATUS 0x27 +#define LPS22HB_MASK_STATUS_P_OR BIT(5) +#define LPS22HB_SHIFT_STATUS_P_OR 5 +#define LPS22HB_MASK_STATUS_T_OR BIT(4) +#define LPS22HB_SHIFT_STATUS_T_OR 4 +#define LPS22HB_MASK_STATUS_P_DA BIT(1) +#define LPS22HB_SHIFT_STATUS_P_DA 1 +#define LPS22HB_MASK_STATUS_T_DA BIT(0) +#define LPS22HB_SHIFT_STATUS_T_DA 0 + +#define LPS22HB_REG_PRESS_OUT_XL 0x28 +#define LPS22HB_REG_PRESS_OUT_L 0x29 +#define LPS22HB_REG_PRESS_OUT_H 0x2A + +#define LPS22HB_REG_TEMP_OUT_L 0x2B +#define LPS22HB_REG_TEMP_OUT_H 0x2C + +#define LPS22HB_REG_LPFP_RES 0x33 + + +#if CONFIG_LPS22HB_SAMPLING_RATE == 1 + #define LPS22HB_DEFAULT_SAMPLING_RATE 1 +#elif CONFIG_LPS22HB_SAMPLING_RATE == 10 + #define LPS22HB_DEFAULT_SAMPLING_RATE 2 +#elif CONFIG_LPS22HB_SAMPLING_RATE == 25 + #define LPS22HB_DEFAULT_SAMPLING_RATE 3 +#elif CONFIG_LPS22HB_SAMPLING_RATE == 50 + #define LPS22HB_DEFAULT_SAMPLING_RATE 4 +#elif CONFIG_LPS22HB_SAMPLING_RATE == 75 + #define LPS22HB_DEFAULT_SAMPLING_RATE 5 +#endif + + +struct lps22hb_config { + char *i2c_master_dev_name; + u16_t i2c_slave_addr; +}; + +struct lps22hb_data { + struct device *i2c_master; + s32_t sample_press; + s16_t sample_temp; +}; + +#define SYS_LOG_DOMAIN "LPS22HB" +#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SENSOR_LEVEL +#include +#endif /* __SENSOR_LPS22HB_H__ */