mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-24 12:16:35 +00:00
move spi.h to drivers/spi.h and create a shim for backward-compatibility. No functional changes to the headers. A warning in the shim can be controlled with CONFIG_COMPAT_INCLUDES. Related to #16539 Signed-off-by: Anas Nashif <anas.nashif@intel.com>
352 lines
9.7 KiB
C
352 lines
9.7 KiB
C
/*
|
|
* Copyright (c) 2017 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#ifndef ZEPHYR_DRIVERS_SENSOR_LIS2DH_LIS2DH_H_
|
|
#define ZEPHYR_DRIVERS_SENSOR_LIS2DH_LIS2DH_H_
|
|
|
|
#include <kernel.h>
|
|
#include <device.h>
|
|
#include <misc/util.h>
|
|
#include <stdint.h>
|
|
#include <drivers/gpio.h>
|
|
#include <drivers/sensor.h>
|
|
#include <string.h>
|
|
|
|
#define LIS2DH_BUS_ADDRESS DT_INST_0_ST_LIS2DH_BASE_ADDRESS
|
|
#define LIS2DH_BUS_DEV_NAME DT_INST_0_ST_LIS2DH_BUS_NAME
|
|
|
|
#if defined(DT_ST_LIS2DH_BUS_SPI)
|
|
#include <drivers/spi.h>
|
|
|
|
#define LIS2DH_SPI_READ_BIT BIT(7)
|
|
#define LIS2DH_SPI_AUTOINC_ADDR BIT(6)
|
|
#define LIS2DH_SPI_ADDR_MASK BIT_MASK(6)
|
|
|
|
/* LIS2DH supports only SPI mode 0, word size 8 bits, MSB first */
|
|
#define LIS2DH_SPI_CFG SPI_WORD_SET(8)
|
|
|
|
#elif defined(DT_ST_LIS2DH_BUS_I2C)
|
|
#include <drivers/i2c.h>
|
|
#else
|
|
#error "define bus type (I2C/SPI)"
|
|
#endif
|
|
|
|
#define LIS2DH_AUTOINCREMENT_ADDR BIT(7)
|
|
|
|
#define LIS2DH_REG_CTRL1 0x20
|
|
#define LIS2DH_ACCEL_XYZ_SHIFT 0
|
|
#define LIS2DH_ACCEL_X_EN_BIT BIT(0)
|
|
#define LIS2DH_ACCEL_Y_EN_BIT BIT(1)
|
|
#define LIS2DH_ACCEL_Z_EN_BIT BIT(2)
|
|
#define LIS2DH_ACCEL_EN_BITS (LIS2DH_ACCEL_X_EN_BIT | \
|
|
LIS2DH_ACCEL_Y_EN_BIT | \
|
|
LIS2DH_ACCEL_Z_EN_BIT)
|
|
#define LIS2DH_ACCEL_XYZ_MASK BIT_MASK(3)
|
|
|
|
#define LIS2DH_LP_EN_BIT_MASK BIT(3)
|
|
#if defined(CONFIG_LIS2DH_POWER_MODE_LOW)
|
|
#define LIS2DH_LP_EN_BIT BIT(3)
|
|
#elif defined(CONFIG_LIS2DH_POWER_MODE_NORMAL)
|
|
#define LIS2DH_LP_EN_BIT 0
|
|
#endif
|
|
|
|
#define LIS2DH_ODR_1 1
|
|
#define LIS2DH_ODR_2 2
|
|
#define LIS2DH_ODR_3 3
|
|
#define LIS2DH_ODR_4 4
|
|
#define LIS2DH_ODR_5 5
|
|
#define LIS2DH_ODR_6 6
|
|
#define LIS2DH_ODR_7 7
|
|
#define LIS2DH_ODR_8 8
|
|
#define LIS2DH_ODR_9 9
|
|
|
|
#if defined(CONFIG_LIS2DH_ODR_1)
|
|
#define LIS2DH_ODR_IDX LIS2DH_ODR_1
|
|
#elif defined(CONFIG_LIS2DH_ODR_2)
|
|
#define LIS2DH_ODR_IDX LIS2DH_ODR_2
|
|
#elif defined(CONFIG_LIS2DH_ODR_3)
|
|
#define LIS2DH_ODR_IDX LIS2DH_ODR_3
|
|
#elif defined(CONFIG_LIS2DH_ODR_4) || defined(CONFIG_LIS2DH_ODR_RUNTIME)
|
|
#define LIS2DH_ODR_IDX LIS2DH_ODR_4
|
|
#elif defined(CONFIG_LIS2DH_ODR_5)
|
|
#define LIS2DH_ODR_IDX LIS2DH_ODR_5
|
|
#elif defined(CONFIG_LIS2DH_ODR_6)
|
|
#define LIS2DH_ODR_IDX LIS2DH_ODR_6
|
|
#elif defined(CONFIG_LIS2DH_ODR_7)
|
|
#define LIS2DH_ODR_IDX LIS2DH_ODR_7
|
|
#elif defined(CONFIG_LIS2DH_ODR_8)
|
|
#define LIS2DH_ODR_IDX LIS2DH_ODR_8
|
|
#elif defined(CONFIG_LIS2DH_ODR_9_NORMAL) || defined(CONFIG_LIS2DH_ODR_9_LOW)
|
|
#define LIS2DH_ODR_IDX LIS2DH_ODR_9
|
|
#endif
|
|
|
|
#define LIS2DH_ODR_SHIFT 4
|
|
#define LIS2DH_ODR_RATE(r) ((r) << LIS2DH_ODR_SHIFT)
|
|
#define LIS2DH_ODR_BITS (LIS2DH_ODR_RATE(LIS2DH_ODR_IDX))
|
|
#define LIS2DH_ODR_MASK (BIT_MASK(4) << LIS2DH_ODR_SHIFT)
|
|
|
|
#define LIS2DH_REG_CTRL2 0x21
|
|
#define LIS2DH_HPIS2_EN_BIT BIT(1)
|
|
#define LIS2DH_FDS_EN_BIT BIT(3)
|
|
|
|
#define LIS2DH_REG_CTRL3 0x22
|
|
#define LIS2DH_EN_DRDY1_INT1_SHIFT 4
|
|
#define LIS2DH_EN_DRDY1_INT1 BIT(LIS2DH_EN_DRDY1_INT1_SHIFT)
|
|
|
|
#define LIS2DH_REG_CTRL4 0x23
|
|
#define LIS2DH_FS_SHIFT 4
|
|
#define LIS2DH_FS_MASK (BIT_MASK(2) << LIS2DH_FS_SHIFT)
|
|
|
|
#if defined(CONFIG_LIS2DH_ACCEL_RANGE_2G) ||\
|
|
defined(CONFIG_LIS2DH_ACCEL_RANGE_RUNTIME)
|
|
#define LIS2DH_FS_IDX 0
|
|
#elif defined(CONFIG_LIS2DH_ACCEL_RANGE_4G)
|
|
#define LIS2DH_FS_IDX 1
|
|
#elif defined(CONFIG_LIS2DH_ACCEL_RANGE_8G)
|
|
#define LIS2DH_FS_IDX 2
|
|
#elif defined(CONFIG_LIS2DH_ACCEL_RANGE_16G)
|
|
#define LIS2DH_FS_IDX 3
|
|
#endif
|
|
|
|
#define LIS2DH_FS_SELECT(fs) ((fs) << LIS2DH_FS_SHIFT)
|
|
#define LIS2DH_FS_BITS (LIS2DH_FS_SELECT(LIS2DH_FS_IDX))
|
|
#define LIS2DH_ACCEL_SCALE(range_g) ((SENSOR_G * 2 * (range_g)) / 65636LL)
|
|
|
|
#define LIS2DH_REG_CTRL5 0x24
|
|
#define LIS2DH_LIR_INT2_SHIFT 1
|
|
#define LIS2DH_EN_LIR_INT2 BIT(LIS2DH_LIR_INT2_SHIFT)
|
|
|
|
#define LIS2DH_REG_CTRL6 0x25
|
|
#define LIS2DH_EN_INT2_INT2_SHIFT 5
|
|
#define LIS2DH_EN_INT2_INT2 BIT(LIS2DH_EN_INT2_INT2_SHIFT)
|
|
|
|
#define LIS2DH_REG_REFERENCE 0x26
|
|
|
|
#define LIS2DH_REG_STATUS 0x27
|
|
#define LIS2DH_STATUS_ZYZ_OVR BIT(7)
|
|
#define LIS2DH_STATUS_Z_OVR BIT(6)
|
|
#define LIS2DH_STATUS_Y_OVR BIT(5)
|
|
#define LIS2DH_STATUS_X_OVR BIT(4)
|
|
#define LIS2DH_STATUS_OVR_MASK (BIT_MASK(4) << 4)
|
|
#define LIS2DH_STATUS_ZYX_DRDY BIT(3)
|
|
#define LIS2DH_STATUS_Z_DRDY BIT(2)
|
|
#define LIS2DH_STATUS_Y_DRDY BIT(1)
|
|
#define LIS2DH_STATUS_X_DRDY BIT(0)
|
|
#define LIS2DH_STATUS_DRDY_MASK BIT_MASK(4)
|
|
|
|
#define LIS2DH_REG_ACCEL_X_LSB 0x28
|
|
#define LIS2DH_REG_ACCEL_Y_LSB 0x2A
|
|
#define LIS2DH_REG_ACCEL_Z_LSB 0x2C
|
|
#define LIS2DH_REG_ACCEL_X_MSB 0x29
|
|
#define LIS2DH_REG_ACCEL_Y_MSB 0x2B
|
|
#define LIS2DH_REG_ACCEL_Z_MSB 0x2D
|
|
|
|
#define LIS2DH_REG_INT1_CFG 0x30
|
|
#define LIS2DH_REG_INT2_CFG 0x34
|
|
#define LIS2DH_AOI_CFG BIT(7)
|
|
#define LIS2DH_INT_CFG_ZHIE_ZUPE BIT(5)
|
|
#define LIS2DH_INT_CFG_ZLIE_ZDOWNE BIT(4)
|
|
#define LIS2DH_INT_CFG_YHIE_YUPE BIT(3)
|
|
#define LIS2DH_INT_CFG_YLIE_YDOWNE BIT(2)
|
|
#define LIS2DH_INT_CFG_XHIE_XUPE BIT(1)
|
|
#define LIS2DH_INT_CFG_XLIE_XDOWNE BIT(0)
|
|
|
|
#define LIS2DH_REG_INT2_SRC 0x35
|
|
|
|
#define LIS2DH_REG_INT2_THS 0x36
|
|
|
|
#define LIS2DH_REG_INT2_DUR 0x37
|
|
|
|
/* sample buffer size includes status register */
|
|
#if defined(DT_ST_LIS2DH_BUS_SPI)
|
|
#define LIS2DH_BUF_SZ 8
|
|
#define LIS2DH_DATA_OFS 1
|
|
#else
|
|
#define LIS2DH_BUF_SZ 7
|
|
#define LIS2DH_DATA_OFS 0
|
|
#endif
|
|
|
|
#if defined(DT_INST_0_ST_LIS2DH_IRQ_GPIOS_CONTROLLER_1)
|
|
/* INT1 and INT2 are configured */
|
|
#define DT_LIS2DH_INT1_GPIOS_PIN DT_INST_0_ST_LIS2DH_IRQ_GPIOS_PIN_0
|
|
#define DT_LIS2DH_INT1_GPIO_DEV_NAME DT_INST_0_ST_LIS2DH_IRQ_GPIOS_CONTROLLER_0
|
|
#define DT_LIS2DH_INT2_GPIOS_PIN DT_INST_0_ST_LIS2DH_IRQ_GPIOS_PIN_1
|
|
#define DT_LIS2DH_INT2_GPIO_DEV_NAME DT_INST_0_ST_LIS2DH_IRQ_GPIOS_CONTROLLER_1
|
|
#else
|
|
/* INT1 only */
|
|
#define DT_LIS2DH_INT1_GPIOS_PIN DT_INST_0_ST_LIS2DH_IRQ_GPIOS_PIN
|
|
#define DT_LIS2DH_INT1_GPIO_DEV_NAME DT_INST_0_ST_LIS2DH_IRQ_GPIOS_CONTROLLER
|
|
#endif
|
|
|
|
union lis2dh_sample {
|
|
u8_t raw[LIS2DH_BUF_SZ];
|
|
struct {
|
|
#if defined(DT_ST_LIS2DH_BUS_SPI)
|
|
u8_t dummy;
|
|
#endif
|
|
u8_t status;
|
|
s16_t xyz[3];
|
|
} __packed;
|
|
};
|
|
|
|
struct lis2dh_data {
|
|
#if defined(DT_ST_LIS2DH_BUS_SPI)
|
|
struct device *spi;
|
|
struct spi_config spi_cfg;
|
|
#else
|
|
struct device *bus;
|
|
#endif
|
|
union lis2dh_sample sample;
|
|
/* current scaling factor, in micro m/s^2 / lsb */
|
|
u16_t scale;
|
|
|
|
#ifdef CONFIG_LIS2DH_TRIGGER
|
|
struct device *gpio_int1;
|
|
struct device *gpio_int2;
|
|
struct gpio_callback gpio_int1_cb;
|
|
struct gpio_callback gpio_int2_cb;
|
|
|
|
sensor_trigger_handler_t handler_drdy;
|
|
sensor_trigger_handler_t handler_anymotion;
|
|
atomic_t trig_flags;
|
|
enum sensor_channel chan_drdy;
|
|
|
|
#if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
|
|
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_LIS2DH_THREAD_STACK_SIZE);
|
|
struct k_thread thread;
|
|
struct k_sem gpio_sem;
|
|
#elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
|
|
struct k_work work;
|
|
struct device *dev;
|
|
#endif
|
|
|
|
#endif /* CONFIG_LIS2DH_TRIGGER */
|
|
};
|
|
|
|
#if defined(DT_ST_LIS2DH_BUS_SPI)
|
|
int lis2dh_spi_access(struct lis2dh_data *ctx, u8_t cmd,
|
|
void *data, size_t length);
|
|
#endif
|
|
|
|
static inline int lis2dh_bus_configure(struct device *dev)
|
|
{
|
|
struct lis2dh_data *lis2dh = dev->driver_data;
|
|
|
|
#if defined(DT_ST_LIS2DH_BUS_SPI)
|
|
lis2dh->spi = device_get_binding(LIS2DH_BUS_DEV_NAME);
|
|
if (lis2dh->spi == NULL) {
|
|
LOG_ERR("Could not get pointer to %s device",
|
|
LIS2DH_BUS_DEV_NAME);
|
|
return -EINVAL;
|
|
}
|
|
|
|
lis2dh->spi_cfg.operation = LIS2DH_SPI_CFG;
|
|
lis2dh->spi_cfg.frequency = DT_INST_0_ST_LIS2DH_SPI_MAX_FREQUENCY;
|
|
lis2dh->spi_cfg.slave = LIS2DH_BUS_ADDRESS;
|
|
|
|
return 0;
|
|
#elif defined(DT_ST_LIS2DH_BUS_I2C)
|
|
lis2dh->bus = device_get_binding(LIS2DH_BUS_DEV_NAME);
|
|
if (lis2dh->bus == NULL) {
|
|
LOG_ERR("Could not get pointer to %s device",
|
|
LIS2DH_BUS_DEV_NAME);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
#else
|
|
return -ENODEV;
|
|
#endif
|
|
}
|
|
|
|
static inline int lis2dh_burst_read(struct device *dev, u8_t start_addr,
|
|
u8_t *buf, u8_t num_bytes)
|
|
{
|
|
struct lis2dh_data *lis2dh = dev->driver_data;
|
|
|
|
#if defined(DT_ST_LIS2DH_BUS_SPI)
|
|
start_addr |= LIS2DH_SPI_READ_BIT | LIS2DH_SPI_AUTOINC_ADDR;
|
|
|
|
return lis2dh_spi_access(lis2dh, start_addr, buf, num_bytes);
|
|
#elif defined(DT_ST_LIS2DH_BUS_I2C)
|
|
return i2c_burst_read(lis2dh->bus, LIS2DH_BUS_ADDRESS,
|
|
start_addr | LIS2DH_AUTOINCREMENT_ADDR,
|
|
buf, num_bytes);
|
|
#else
|
|
return -ENODEV;
|
|
#endif
|
|
}
|
|
|
|
static inline int lis2dh_reg_read_byte(struct device *dev, u8_t reg_addr,
|
|
u8_t *value)
|
|
{
|
|
struct lis2dh_data *lis2dh = dev->driver_data;
|
|
|
|
#if defined(DT_ST_LIS2DH_BUS_SPI)
|
|
reg_addr |= LIS2DH_SPI_READ_BIT;
|
|
|
|
return lis2dh_spi_access(lis2dh, reg_addr, value, 1);
|
|
#elif defined(DT_ST_LIS2DH_BUS_I2C)
|
|
return i2c_reg_read_byte(lis2dh->bus, LIS2DH_BUS_ADDRESS,
|
|
reg_addr, value);
|
|
#else
|
|
return -ENODEV;
|
|
#endif
|
|
}
|
|
|
|
static inline int lis2dh_burst_write(struct device *dev, u8_t start_addr,
|
|
u8_t *buf, u8_t num_bytes)
|
|
{
|
|
struct lis2dh_data *lis2dh = dev->driver_data;
|
|
|
|
#if defined(DT_ST_LIS2DH_BUS_SPI)
|
|
start_addr |= LIS2DH_SPI_AUTOINC_ADDR;
|
|
|
|
return lis2dh_spi_access(lis2dh, start_addr, buf, num_bytes);
|
|
#elif defined(DT_ST_LIS2DH_BUS_I2C)
|
|
return i2c_burst_write(lis2dh->bus, LIS2DH_BUS_ADDRESS,
|
|
start_addr | LIS2DH_AUTOINCREMENT_ADDR,
|
|
buf, num_bytes);
|
|
#else
|
|
return -ENODEV;
|
|
#endif
|
|
}
|
|
|
|
static inline int lis2dh_reg_write_byte(struct device *dev, u8_t reg_addr,
|
|
u8_t value)
|
|
{
|
|
struct lis2dh_data *lis2dh = dev->driver_data;
|
|
|
|
#if defined(DT_ST_LIS2DH_BUS_SPI)
|
|
reg_addr &= LIS2DH_SPI_ADDR_MASK;
|
|
|
|
return lis2dh_spi_access(lis2dh, reg_addr, &value, 1);
|
|
#elif defined(DT_ST_LIS2DH_BUS_I2C)
|
|
u8_t tx_buf[2] = {reg_addr, value};
|
|
|
|
return i2c_write(lis2dh->bus, tx_buf, sizeof(tx_buf),
|
|
LIS2DH_BUS_ADDRESS);
|
|
#else
|
|
return -ENODEV;
|
|
#endif
|
|
}
|
|
|
|
#ifdef CONFIG_LIS2DH_TRIGGER
|
|
int lis2dh_trigger_set(struct device *dev,
|
|
const struct sensor_trigger *trig,
|
|
sensor_trigger_handler_t handler);
|
|
|
|
int lis2dh_init_interrupt(struct device *dev);
|
|
|
|
int lis2dh_reg_field_update(struct device *dev, u8_t reg_addr,
|
|
u8_t pos, u8_t mask, u8_t val);
|
|
|
|
int lis2dh_acc_slope_config(struct device *dev, enum sensor_attribute attr,
|
|
const struct sensor_value *val);
|
|
#endif
|
|
|
|
#endif /* __SENSOR_LIS2DH__ */
|