drivers: sensors: lis2dh: Allow any movement on interrupt 1

Allow movement detection to be used on hardware
that only has one interrupt line connected.
Change hardware configuration to a bitmask.

Signed-off-by: Andrew Hedin <andrew.hedin@lairdconnect.com>
This commit is contained in:
Andrew Hedin 2021-09-27 16:37:20 -05:00 committed by Carles Cufí
commit c64783f29d
4 changed files with 120 additions and 56 deletions

View file

@ -352,14 +352,14 @@ int lis2dh_init(const struct device *dev)
}
/* Fix LSM303AGR_ACCEL device scale values */
if (cfg->is_lsm303agr_dev) {
if (cfg->hw.is_lsm303agr_dev) {
lis2dh_reg_val_to_scale[0] = ACCEL_SCALE(1563);
lis2dh_reg_val_to_scale[1] = ACCEL_SCALE(3126);
lis2dh_reg_val_to_scale[2] = ACCEL_SCALE(6252);
lis2dh_reg_val_to_scale[3] = ACCEL_SCALE(18758);
}
if (cfg->disc_pull_up) {
if (cfg->hw.disc_pull_up) {
status = lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL0,
LIS2DH_SDO_PU_DISC_MASK,
LIS2DH_SDO_PU_DISC_MASK);
@ -455,17 +455,24 @@ int lis2dh_init(const struct device *dev)
#define DISC_PULL_UP(inst) \
DT_INST_PROP(inst, disconnect_sdo_sa0_pull_up)
#define ANYM_ON_INT1(inst) \
DT_INST_PROP(inst, anym_on_int1)
#ifdef CONFIG_LIS2DH_TRIGGER
#define GPIO_DT_SPEC_INST_GET_BY_IDX_COND(id, prop, idx) \
COND_CODE_1(DT_INST_PROP_HAS_IDX(id, prop, idx), \
(GPIO_DT_SPEC_INST_GET_BY_IDX(id, prop, idx)), \
({.port = NULL, .pin = 0, .dt_flags = 0}))
#define LIS2DH_CFG_INT(inst) \
#define LIS2DH_CFG_INT(inst) \
.gpio_drdy = \
GPIO_DT_SPEC_INST_GET_BY_IDX_COND(inst, irq_gpios, 0), \
.gpio_int = \
GPIO_DT_SPEC_INST_GET_BY_IDX_COND(inst, irq_gpios, 1),
COND_CODE_1(ANYM_ON_INT1(inst), \
({.port = NULL, .pin = 0, .dt_flags = 0}), \
(GPIO_DT_SPEC_INST_GET_BY_IDX_COND(inst, irq_gpios, 0))), \
.gpio_int = \
COND_CODE_1(ANYM_ON_INT1(inst), \
(GPIO_DT_SPEC_INST_GET_BY_IDX_COND(inst, irq_gpios, 0)), \
(GPIO_DT_SPEC_INST_GET_BY_IDX_COND(inst, irq_gpios, 1))),
#else
#define LIS2DH_CFG_INT(inst)
#endif /* CONFIG_LIS2DH_TRIGGER */
@ -504,8 +511,9 @@ int lis2dh_init(const struct device *dev)
SPI_MODE_CPOL | \
SPI_MODE_CPHA, \
0) }, \
.is_lsm303agr_dev = IS_LSM303AGR_DEV(inst), \
.disc_pull_up = DISC_PULL_UP(inst), \
.hw = { .is_lsm303agr_dev = IS_LSM303AGR_DEV(inst), \
.disc_pull_up = DISC_PULL_UP(inst), \
.anym_on_int1 = ANYM_ON_INT1(inst), }, \
LIS2DH_CFG_TEMPERATURE(inst) \
LIS2DH_CFG_INT(inst) \
}
@ -525,8 +533,9 @@ int lis2dh_init(const struct device *dev)
.bus_name = DT_INST_BUS_LABEL(inst), \
.bus_init = lis2dh_i2c_init, \
.bus_cfg = { .i2c_slv_addr = DT_INST_REG_ADDR(inst), }, \
.is_lsm303agr_dev = IS_LSM303AGR_DEV(inst), \
.disc_pull_up = DISC_PULL_UP(inst), \
.hw = { .is_lsm303agr_dev = IS_LSM303AGR_DEV(inst), \
.disc_pull_up = DISC_PULL_UP(inst), \
.anym_on_int1 = ANYM_ON_INT1(inst), }, \
LIS2DH_CFG_TEMPERATURE(inst) \
LIS2DH_CFG_INT(inst) \
}

View file

@ -117,11 +117,15 @@
#define LIS2DH_REG_CTRL5 0x24
#define LIS2DH_LIR_INT2_SHIFT 1
#define LIS2DH_LIR_INT1_SHIFT 3
#define LIS2DH_EN_LIR_INT2 BIT(LIS2DH_LIR_INT2_SHIFT)
#define LIS2DH_EN_LIR_INT1 BIT(LIS2DH_LIR_INT1_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_EN_INT1_INT1_SHIFT 6
#define LIS2DH_EN_INT1_INT1 BIT(LIS2DH_EN_INT1_INT1_SHIFT)
#define LIS2DH_REG_REFERENCE 0x26
@ -145,7 +149,14 @@
#define LIS2DH_REG_ACCEL_Z_MSB 0x2D
#define LIS2DH_REG_INT1_CFG 0x30
#define LIS2DH_REG_INT1_SRC 0x31
#define LIS2DH_REG_INT1_THS 0x32
#define LIS2DH_REG_INT1_DUR 0x33
#define LIS2DH_REG_INT2_CFG 0x34
#define LIS2DH_REG_INT2_SRC 0x35
#define LIS2DH_REG_INT2_THS 0x36
#define LIS2DH_REG_INT2_DUR 0x37
#define LIS2DH_AOI_CFG BIT(7)
#define LIS2DH_INT_CFG_ZHIE_ZUPE BIT(5)
#define LIS2DH_INT_CFG_ZLIE_ZDOWNE BIT(4)
@ -154,12 +165,6 @@
#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 */
#define LIS2DH_BUF_SZ 7
@ -198,8 +203,11 @@ struct lis2dh_config {
const struct gpio_dt_spec gpio_drdy;
const struct gpio_dt_spec gpio_int;
#endif /* CONFIG_LIS2DH_TRIGGER */
bool is_lsm303agr_dev;
bool disc_pull_up;
struct {
bool is_lsm303agr_dev : 1;
bool disc_pull_up : 1;
bool anym_on_int1 : 1;
} hw;
#ifdef CONFIG_LIS2DH_MEASURE_TEMPERATURE
const struct temperature temperature;
#endif

View file

@ -143,11 +143,22 @@ static int lis2dh_trigger_anym_set(const struct device *dev,
/* cancel potentially pending trigger */
atomic_clear_bit(&lis2dh->trig_flags, TRIGGED_INT2);
/* disable all interrupt 2 events */
status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_INT2_CFG, 0);
if (cfg->hw.anym_on_int1) {
status = lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL3,
LIS2DH_EN_DRDY1_INT1, 0);
}
/* disable any movement interrupt events */
status = lis2dh->hw_tf->write_reg(
dev,
cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_CFG : LIS2DH_REG_INT2_CFG,
0);
/* make sure any pending interrupt is cleared */
status = lis2dh->hw_tf->read_reg(dev, LIS2DH_REG_INT2_SRC, &reg_val);
status = lis2dh->hw_tf->read_reg(
dev,
cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_SRC : LIS2DH_REG_INT2_SRC,
&reg_val);
lis2dh->handler_anymotion = handler;
if ((handler == NULL) || (status < 0)) {
@ -169,11 +180,14 @@ static int lis2dh_trigger_anym_set(const struct device *dev,
static int lis2dh_start_trigger_int2(const struct device *dev)
{
struct lis2dh_data *lis2dh = dev->data;
const struct lis2dh_config *cfg = dev->config;
setup_int2(dev, true);
return lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_INT2_CFG,
LIS2DH_ANYM_CFG);
return lis2dh->hw_tf->write_reg(
dev,
cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_CFG : LIS2DH_REG_INT2_CFG,
LIS2DH_ANYM_CFG);
}
int lis2dh_trigger_set(const struct device *dev,
@ -195,6 +209,7 @@ int lis2dh_acc_slope_config(const struct device *dev,
const struct sensor_value *val)
{
struct lis2dh_data *lis2dh = dev->data;
const struct lis2dh_config *cfg = dev->config;
int status;
if (attr == SENSOR_ATTR_SLOPE_TH) {
@ -224,7 +239,10 @@ int lis2dh_acc_slope_config(const struct device *dev,
LOG_INF("int2_ths=0x%x range_g=%d ums2=%u", reg_val,
range_g, slope_th_ums2 - 1);
status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_INT2_THS,
status = lis2dh->hw_tf->write_reg(dev,
cfg->hw.anym_on_int1 ?
LIS2DH_REG_INT1_THS :
LIS2DH_REG_INT2_THS,
reg_val);
} else { /* SENSOR_ATTR_SLOPE_DUR */
/*
@ -237,7 +255,10 @@ int lis2dh_acc_slope_config(const struct device *dev,
LOG_INF("int2_dur=0x%x", val->val1);
status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_INT2_DUR,
status = lis2dh->hw_tf->write_reg(dev,
cfg->hw.anym_on_int1 ?
LIS2DH_REG_INT1_DUR :
LIS2DH_REG_INT2_DUR,
val->val1);
}
@ -344,8 +365,11 @@ static void lis2dh_thread_cb(const struct device *dev)
};
uint8_t reg_val;
/* clear interrupt 2 to de-assert int2 line */
status = lis2dh->hw_tf->read_reg(dev, LIS2DH_REG_INT2_SRC,
/* clear interrupt to de-assert int line */
status = lis2dh->hw_tf->read_reg(dev,
cfg->hw.anym_on_int1 ?
LIS2DH_REG_INT1_SRC :
LIS2DH_REG_INT2_SRC,
&reg_val);
if (status < 0) {
LOG_ERR("clearing interrupt 2 failed: %d", status);
@ -397,6 +421,18 @@ int lis2dh_init_interrupt(const struct device *dev)
int status;
uint8_t raw[2];
lis2dh->dev = dev;
#if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
k_sem_init(&lis2dh->gpio_sem, 0, K_SEM_MAX_LIMIT);
k_thread_create(&lis2dh->thread, lis2dh->thread_stack, CONFIG_LIS2DH_THREAD_STACK_SIZE,
(k_thread_entry_t)lis2dh_thread, lis2dh, NULL, NULL,
K_PRIO_COOP(CONFIG_LIS2DH_THREAD_PRIORITY), 0, K_NO_WAIT);
#elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
lis2dh->work.handler = lis2dh_work_cb;
#endif
/*
* Setup INT1 (for DRDY) if defined in DT
*/
@ -414,20 +450,6 @@ int lis2dh_init_interrupt(const struct device *dev)
goto check_gpio_int;
}
lis2dh->dev = dev;
#if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
k_sem_init(&lis2dh->gpio_sem, 0, K_SEM_MAX_LIMIT);
k_thread_create(&lis2dh->thread, lis2dh->thread_stack,
CONFIG_LIS2DH_THREAD_STACK_SIZE,
(k_thread_entry_t)lis2dh_thread, lis2dh, NULL, NULL,
K_PRIO_COOP(CONFIG_LIS2DH_THREAD_PRIORITY), 0,
K_NO_WAIT);
#elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
lis2dh->work.handler = lis2dh_work_cb;
#endif
/* data ready int1 gpio configuration */
status = gpio_pin_configure_dt(&cfg->gpio_drdy, GPIO_INPUT);
if (status < 0) {
@ -452,7 +474,7 @@ int lis2dh_init_interrupt(const struct device *dev)
check_gpio_int:
/*
* Setup INT2 (for Any Motion) if defined in DT
* Setup Interrupt (for Any Motion) if defined in DT
*/
/* setup any motion gpio interrupt */
@ -491,31 +513,48 @@ check_gpio_int:
cfg->gpio_int.port->name,
cfg->gpio_int.pin);
/* disable interrupt 2 in case of warm (re)boot */
status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_INT2_CFG, 0);
/* disable interrupt in case of warm (re)boot */
status = lis2dh->hw_tf->write_reg(
dev,
cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_CFG : LIS2DH_REG_INT2_CFG,
0);
if (status < 0) {
LOG_ERR("Interrupt 2 disable reg write failed (%d)", status);
LOG_ERR("Interrupt disable reg write failed (%d)", status);
return status;
}
(void)memset(raw, 0, sizeof(raw));
status = lis2dh->hw_tf->write_data(dev, LIS2DH_REG_INT2_THS,
raw, sizeof(raw));
status = lis2dh->hw_tf->write_data(
dev,
cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_THS : LIS2DH_REG_INT2_THS,
raw, sizeof(raw));
if (status < 0) {
LOG_ERR("Burst write to INT2 THS failed (%d)", status);
LOG_ERR("Burst write to THS failed (%d)", status);
return status;
}
/* enable interrupt 2 on int2 line */
status = lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL6,
LIS2DH_EN_INT2_INT2,
LIS2DH_EN_INT2_INT2);
if (cfg->hw.anym_on_int1) {
/* enable interrupt 1 on int1 line */
status = lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL3,
LIS2DH_EN_INT1_INT1,
LIS2DH_EN_INT1_INT1);
/* latch int1 line interrupt */
status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_CTRL5,
LIS2DH_EN_LIR_INT1);
} else {
/* enable interrupt 2 on int2 line */
status = lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL6,
LIS2DH_EN_INT2_INT2,
LIS2DH_EN_INT2_INT2);
/* latch int2 line interrupt */
status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_CTRL5,
LIS2DH_EN_LIR_INT2);
}
/* latch int2 line interrupt */
status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_CTRL5,
LIS2DH_EN_LIR_INT2);
if (status < 0) {
LOG_ERR("INT2 latch enable reg write failed (%d)", status);
LOG_ERR("latch enable reg write failed (%d)", status);
return status;
}

View file

@ -17,3 +17,11 @@ properties:
during device initialization (e.g. to save current
leakage). Note that only subset of devices supported by this
binding have SDO/SA0 pull-up (e.g. LIS2DH12, LIS3DH).
anym-on-int1:
type: boolean
required: false
description: |
Indicates that the device driver should use interrupt 1
for any movement. This is for boards that only have one
interrupt line connected from the sensor to the processor.