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:
parent
5c37441256
commit
c64783f29d
4 changed files with 120 additions and 56 deletions
|
@ -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) \
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue