From c64783f29d97f10f5bb90a29183909648be979c3 Mon Sep 17 00:00:00 2001 From: Andrew Hedin Date: Mon, 27 Sep 2021 16:37:20 -0500 Subject: [PATCH] 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 --- drivers/sensor/lis2dh/lis2dh.c | 29 ++++-- drivers/sensor/lis2dh/lis2dh.h | 24 +++-- drivers/sensor/lis2dh/lis2dh_trigger.c | 115 +++++++++++++++------- dts/bindings/sensor/st,lis2dh-common.yaml | 8 ++ 4 files changed, 120 insertions(+), 56 deletions(-) diff --git a/drivers/sensor/lis2dh/lis2dh.c b/drivers/sensor/lis2dh/lis2dh.c index e8a9e2c6bb9..7cdd8b51809 100644 --- a/drivers/sensor/lis2dh/lis2dh.c +++ b/drivers/sensor/lis2dh/lis2dh.c @@ -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) \ } diff --git a/drivers/sensor/lis2dh/lis2dh.h b/drivers/sensor/lis2dh/lis2dh.h index 2a4f6be695b..4f586108d7b 100644 --- a/drivers/sensor/lis2dh/lis2dh.h +++ b/drivers/sensor/lis2dh/lis2dh.h @@ -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 diff --git a/drivers/sensor/lis2dh/lis2dh_trigger.c b/drivers/sensor/lis2dh/lis2dh_trigger.c index d2b84dd2042..63a7523d9d1 100644 --- a/drivers/sensor/lis2dh/lis2dh_trigger.c +++ b/drivers/sensor/lis2dh/lis2dh_trigger.c @@ -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, ®_val); + status = lis2dh->hw_tf->read_reg( + dev, + cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_SRC : LIS2DH_REG_INT2_SRC, + ®_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, ®_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; } diff --git a/dts/bindings/sensor/st,lis2dh-common.yaml b/dts/bindings/sensor/st,lis2dh-common.yaml index aac6962eef1..23c970ca5aa 100644 --- a/dts/bindings/sensor/st,lis2dh-common.yaml +++ b/dts/bindings/sensor/st,lis2dh-common.yaml @@ -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.