blob: e01cc78fe7c4f1816caae3ccb924976fbb9f7d97 [file] [log] [blame]
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/sensor.h>
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
#include <zephyr/drivers/spi.h>
#endif
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
#include <zephyr/drivers/i2c.h>
#endif
#include <zephyr/drivers/gpio.h>
#include <zephyr/kernel.h>
#define FXLS8974_BUS_I2C (1<<0)
#define FXLS8974_BUS_SPI (1<<1)
#define FXLS8974_REG_OUTXLSB 0x04
#define FXLS8974_REG_OUTTEMP 0x01
#define FXLS8974_REG_WHOAMI 0x13
#define FXLS8974_REG_CTRLREG1 0x15
#define FXLS8974_REG_CTRLREG2 0x16
#define FXLS8974_REG_CTRLREG3 0x17
#define FXLS8974_REG_CTRLREG4 0x18
#define FXLS8974_REG_CTRLREG5 0x19
#define WHOAMI_ID_FXLS8974 0x86
#define FXLS8974_CTRLREG1_ACTIVE_MASK 0x01
#define FXLS8974_CTRLREG1_RST_MASK 0x80
#define FXLS8974_CTRLREG1_FSR_MASK 0x06
#define FXLS8974_CTRLREG1_FSR_2G 0x00
#define FXLS8974_CTRLREG1_FSR_4G 0x02
#define FXLS8974_CTRLREG1_FSR_8G 0x04
#define FXLS8974_CTRLREG1_FSR_16G 0x06
#define FXLS8974_CTRLREG2_WAKE_PM_MASK 0xC0
#define FXLS8974_CTRLREG2_SLEEP_PM_MASK 0x30
#define FXLS8974_CTRLREG3_WAKE_ODR_MASK 0xF0
#define FXLS8974_CTRLREG3_SLEEP_ODR_MASK 0x0F
#define FXLS8974_CTRLREG3_ODR_RATE_3200 0x00
#define FXLS8974_CTRLREG3_ODR_RATE_1600 0x01
#define FXLS8974_CTRLREG3_ODR_RATE_800 0x02
#define FXLS8974_CTRLREG3_ODR_RATE_400 0x03
#define FXLS8974_CTRLREG3_ODR_RATE_200 0x04
#define FXLS8974_CTRLREG3_ODR_RATE_100 0x05
#define FXLS8974_CTRLREG3_ODR_RATE_50 0x06
#define FXLS8974_CTRLREG3_ODR_RATE_25 0x07
#define FXLS8974_CTRLREG3_ODR_RATE_12_5 0x08
#define FXLS8974_CTRLREG3_ODR_RATE_6_25 0x09
#define FXLS8974_CTRLREG3_ODR_RATE_3_125 0x0A
#define FXLS8974_CTRLREG3_ODR_RATE_1_563 0x0B
#define FXLS8974_CTRLREG3_ODR_RATE_0_781 0x0C
#define FXLS8974_CTRLREG4_INT_POL_HIGH 0x01
#define FXLS8974_INTREG_EN 0x20
#define FXLS8974_INT_PIN_SEL_REG 0x21
#define FXLS8974_DATA_ACCEL_X_OFFSET 0
#define FXLS8974_DATA_ACCEL_Y_OFFSET FXLS8974_BYTES_PER_CHANNEL_NORMAL
#define FXLS8974_DATA_ACCEL_Z_OFFSET 2*FXLS8974_BYTES_PER_CHANNEL_NORMAL
#define FXLS8974_DATA_TEMP_OFFSET 3*FXLS8974_BYTES_PER_CHANNEL_NORMAL
#define FXLS8974_ZERO_TEMP 25
#define FXLS8974_MAX_NUM_CHANNELS 4
#define FXLS8974_MAX_ACCEL_CHANNELS 3
#define FXLS8974_MAX_TEMP_CHANNELS 1
#define FXLS8974_BYTES_PER_CHANNEL_NORMAL 2
#define FXLS8974_BYTES_PER_CHANNEL_FAST 1
#define FXLS8974_MAX_ACCEL_BYTES (FXLS8974_MAX_ACCEL_CHANNELS*2)
#define FXLS8974_MAX_NUM_BYTES (FXLS8974_MAX_ACCEL_BYTES + FXLS8974_MAX_TEMP_CHANNELS)
#define FXLS8974_DRDY_MASK 0x80
enum fxls8974_active {
FXLS8974_ACTIVE_OFF = 0,
FXLS8974_ACTIVE_ON,
};
enum fxls8974_wake {
FXLS8974_WAKE = 0,
FXLS8974_SLEEP,
};
enum fxls8974_channel {
FXLS8974_CHANNEL_ACCEL_X = 0,
FXLS8974_CHANNEL_ACCEL_Y,
FXLS8974_CHANNEL_ACCEL_Z,
FXLS8974_CHANNEL_TEMP,
};
struct fxls8974_io_ops {
int (*read)(const struct device *dev,
uint8_t reg,
void *data,
size_t length);
int (*byte_read)(const struct device *dev,
uint8_t reg,
uint8_t *byte);
int (*byte_write)(const struct device *dev,
uint8_t reg,
uint8_t byte);
int (*reg_field_update)(const struct device *dev,
uint8_t reg,
uint8_t mask,
uint8_t val);
};
union fxls8974_bus_cfg {
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
struct spi_dt_spec spi;
#endif
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
struct i2c_dt_spec i2c;
#endif
};
struct fxls8974_config {
const union fxls8974_bus_cfg bus_cfg;
const struct fxls8974_io_ops *ops;
struct gpio_dt_spec reset_gpio;
uint8_t range;
uint8_t inst_on_bus;
#ifdef CONFIG_FXLS8974_TRIGGER
struct gpio_dt_spec int_gpio;
#endif
};
struct fxls8974_data {
struct k_sem sem;
int16_t raw[FXLS8974_MAX_NUM_CHANNELS];
uint8_t whoami;
#ifdef CONFIG_FXLS8974_TRIGGER
const struct device *dev;
struct gpio_callback gpio_cb;
sensor_trigger_handler_t drdy_handler;
const struct sensor_trigger *drdy_trig;
#endif
#ifdef CONFIG_FXLS8974_TRIGGER_OWN_THREAD
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_FXLS8974_THREAD_STACK_SIZE);
struct k_thread thread;
struct k_sem trig_sem;
#endif
#ifdef CONFIG_FXLS8974_TRIGGER_GLOBAL_THREAD
struct k_work work;
#endif
};
int fxls8974_get_active(const struct device *dev, enum fxls8974_active *active);
int fxls8974_set_active(const struct device *dev, enum fxls8974_active active);
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
int fxls8974_byte_write_spi(const struct device *dev,
uint8_t reg,
uint8_t byte);
int fxls8974_byte_read_spi(const struct device *dev,
uint8_t reg,
uint8_t *byte);
int fxls8974_reg_field_update_spi(const struct device *dev,
uint8_t reg,
uint8_t mask,
uint8_t val);
int fxls8974_read_spi(const struct device *dev,
uint8_t reg,
void *data,
size_t length);
#endif
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
int fxls8974_byte_write_i2c(const struct device *dev,
uint8_t reg,
uint8_t byte);
int fxls8974_byte_read_i2c(const struct device *dev,
uint8_t reg,
uint8_t *byte);
int fxls8974_reg_field_update_i2c(const struct device *dev,
uint8_t reg,
uint8_t mask,
uint8_t val);
int fxls8974_read_i2c(const struct device *dev,
uint8_t reg,
void *data,
size_t length);
#endif
#if CONFIG_FXLS8974_TRIGGER
int fxls8974_trigger_init(const struct device *dev);
int fxls8974_trigger_set(const struct device *dev,
const struct sensor_trigger *trig,
sensor_trigger_handler_t handler);
#endif