drivers/sensor: lis2dh: Fix interrupt handling for multi instance
Handle interrupts correctly for multi instance, checking per device DT bindings instead of global Kconfig definitions. The old interrupt behaviour has been maintained, fixing DRDY to be on INT1 and Any Motion event on INT2. Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
parent
df2ca14df3
commit
d962e3590f
3 changed files with 96 additions and 63 deletions
|
@ -409,11 +409,39 @@ int lis2dh_init(const struct device *dev)
|
|||
.cs_gpios_label = LIS2DH_SPI_CS_LABEL(inst), \
|
||||
})
|
||||
|
||||
#ifdef CONFIG_LIS2DH_TRIGGER
|
||||
#define LIS2DH_HAS_IRQ_IDX(inst, idx) \
|
||||
DT_INST_PROP_HAS_IDX(inst, irq_gpios, idx)
|
||||
|
||||
#define LIS2DH_CFG_INT(inst) \
|
||||
.irq1_dev_name = COND_CODE_1(LIS2DH_HAS_IRQ_IDX(inst, 0), \
|
||||
(DT_INST_GPIO_LABEL_BY_IDX(inst, irq_gpios, 0)), \
|
||||
(NULL)), \
|
||||
.irq1_pin = COND_CODE_1(LIS2DH_HAS_IRQ_IDX(inst, 0), \
|
||||
(DT_INST_GPIO_PIN_BY_IDX(inst, irq_gpios, 0)), \
|
||||
(0)), \
|
||||
.irq1_flags = COND_CODE_1(LIS2DH_HAS_IRQ_IDX(inst, 0), \
|
||||
(DT_INST_GPIO_FLAGS_BY_IDX(inst, irq_gpios, 0)), \
|
||||
(0)), \
|
||||
.irq2_dev_name = COND_CODE_1(LIS2DH_HAS_IRQ_IDX(inst, 1), \
|
||||
(DT_INST_GPIO_LABEL_BY_IDX(inst, irq_gpios, 1)), \
|
||||
(NULL)), \
|
||||
.irq2_pin = COND_CODE_1(LIS2DH_HAS_IRQ_IDX(inst, 1), \
|
||||
(DT_INST_GPIO_PIN_BY_IDX(inst, irq_gpios, 1)), \
|
||||
(0)), \
|
||||
.irq2_flags = COND_CODE_1(LIS2DH_HAS_IRQ_IDX(inst, 1), \
|
||||
(DT_INST_GPIO_FLAGS_BY_IDX(inst, irq_gpios, 1)), \
|
||||
(0)),
|
||||
#else
|
||||
#define LIS2DH_CFG_INT(inst)
|
||||
#endif /* CONFIG_LIS2DH_TRIGGER */
|
||||
|
||||
#define LIS2DH_CONFIG_SPI(inst) \
|
||||
{ \
|
||||
.bus_name = DT_INST_BUS_LABEL(inst), \
|
||||
.bus_init = lis2dh_spi_init, \
|
||||
.bus_cfg = { .spi_cfg = LIS2DH_SPI_CFG(inst) } \
|
||||
.bus_cfg = { .spi_cfg = LIS2DH_SPI_CFG(inst) }, \
|
||||
LIS2DH_CFG_INT(inst) \
|
||||
}
|
||||
|
||||
#define LIS2DH_DEFINE_SPI(inst) \
|
||||
|
@ -431,7 +459,8 @@ 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), } \
|
||||
.bus_cfg = { .i2c_slv_addr = DT_INST_REG_ADDR(inst), }, \
|
||||
LIS2DH_CFG_INT(inst) \
|
||||
}
|
||||
|
||||
#define LIS2DH_DEFINE_I2C(inst) \
|
||||
|
|
|
@ -163,21 +163,6 @@
|
|||
/* sample buffer size includes status register */
|
||||
#define LIS2DH_BUF_SZ 7
|
||||
|
||||
#if DT_INST_PROP_HAS_IDX(0, irq_gpios, 1)
|
||||
/* INT1 and INT2 are configured */
|
||||
#define LIS2DH_INT1_GPIOS_PIN DT_INST_GPIO_PIN_BY_IDX(0, irq_gpios, 0)
|
||||
#define LIS2DH_INT1_GPIOS_FLAGS DT_INST_GPIO_FLAGS_BY_IDX(0, irq_gpios, 0)
|
||||
#define LIS2DH_INT1_GPIO_DEV_NAME DT_INST_GPIO_LABEL_BY_IDX(0, irq_gpios, 0)
|
||||
#define LIS2DH_INT2_GPIOS_PIN DT_INST_GPIO_PIN_BY_IDX(0, irq_gpios, 1)
|
||||
#define LIS2DH_INT2_GPIOS_FLAGS DT_INST_GPIO_FLAGS_BY_IDX(0, irq_gpios, 1)
|
||||
#define LIS2DH_INT2_GPIO_DEV_NAME DT_INST_GPIO_LABEL_BY_IDX(0, irq_gpios, 1)
|
||||
#else
|
||||
/* INT1 only */
|
||||
#define LIS2DH_INT1_GPIOS_PIN DT_INST_GPIO_PIN(0, irq_gpios)
|
||||
#define LIS2DH_INT1_GPIOS_FLAGS DT_INST_GPIO_FLAGS(0, irq_gpios)
|
||||
#define LIS2DH_INT1_GPIO_DEV_NAME DT_INST_GPIO_LABEL(0, irq_gpios)
|
||||
#endif
|
||||
|
||||
union lis2dh_sample {
|
||||
uint8_t raw[LIS2DH_BUF_SZ];
|
||||
struct {
|
||||
|
@ -207,6 +192,14 @@ struct lis2dh_config {
|
|||
const char *bus_name;
|
||||
int (*bus_init)(const struct device *dev);
|
||||
const union lis2dh_bus_cfg bus_cfg;
|
||||
#ifdef CONFIG_LIS2DH_TRIGGER
|
||||
const char *irq1_dev_name;
|
||||
gpio_pin_t irq1_pin;
|
||||
gpio_dt_flags_t irq1_flags;
|
||||
const char *irq2_dev_name;
|
||||
gpio_pin_t irq2_pin;
|
||||
gpio_dt_flags_t irq2_flags;
|
||||
#endif /* CONFIG_LIS2DH_TRIGGER */
|
||||
};
|
||||
|
||||
struct lis2dh_transfer_function {
|
||||
|
|
|
@ -22,9 +22,10 @@ static inline void setup_int1(const struct device *dev,
|
|||
bool enable)
|
||||
{
|
||||
struct lis2dh_data *lis2dh = dev->data;
|
||||
const struct lis2dh_config *cfg = dev->config;
|
||||
|
||||
gpio_pin_interrupt_configure(lis2dh->gpio_int1,
|
||||
LIS2DH_INT1_GPIOS_PIN,
|
||||
cfg->irq1_pin,
|
||||
enable
|
||||
? GPIO_INT_EDGE_TO_ACTIVE
|
||||
: GPIO_INT_DISABLE);
|
||||
|
@ -106,7 +107,6 @@ static int lis2dh_start_trigger_int1(const struct device *dev)
|
|||
LIS2DH_EN_DRDY1_INT1);
|
||||
}
|
||||
|
||||
#if DT_INST_PROP_HAS_IDX(0, irq_gpios, 1)
|
||||
#define LIS2DH_ANYM_CFG (LIS2DH_INT_CFG_ZHIE_ZUPE | LIS2DH_INT_CFG_YHIE_YUPE |\
|
||||
LIS2DH_INT_CFG_XHIE_XUPE)
|
||||
|
||||
|
@ -114,9 +114,10 @@ static inline void setup_int2(const struct device *dev,
|
|||
bool enable)
|
||||
{
|
||||
struct lis2dh_data *lis2dh = dev->data;
|
||||
const struct lis2dh_config *cfg = dev->config;
|
||||
|
||||
gpio_pin_interrupt_configure(lis2dh->gpio_int2,
|
||||
LIS2DH_INT2_GPIOS_PIN,
|
||||
cfg->irq2_pin,
|
||||
enable
|
||||
? GPIO_INT_EDGE_TO_ACTIVE
|
||||
: GPIO_INT_DISABLE);
|
||||
|
@ -166,19 +167,29 @@ static int lis2dh_start_trigger_int2(const struct device *dev)
|
|||
return lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_INT2_CFG,
|
||||
LIS2DH_ANYM_CFG);
|
||||
}
|
||||
#endif /* DT_INST_PROP_HAS_IDX(0, irq_gpios, 1) */
|
||||
|
||||
int lis2dh_trigger_set(const struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler)
|
||||
{
|
||||
struct lis2dh_data *lis2dh = dev->data;
|
||||
|
||||
if (trig->type == SENSOR_TRIG_DATA_READY &&
|
||||
trig->chan == SENSOR_CHAN_ACCEL_XYZ) {
|
||||
/* If irq_gpio is not configured in DT just return error */
|
||||
if (!lis2dh->gpio_int1) {
|
||||
LOG_ERR("DRDY (INT1) trigger not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return lis2dh_trigger_drdy_set(dev, trig->chan, handler);
|
||||
#if DT_INST_PROP_HAS_IDX(0, irq_gpios, 1)
|
||||
} else if (trig->type == SENSOR_TRIG_DELTA) {
|
||||
/* If irq_gpio is not configured in DT just return error */
|
||||
if (!lis2dh->gpio_int2) {
|
||||
LOG_ERR("AnyMotion (INT2) trigger not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
return lis2dh_trigger_anym_set(dev, handler);
|
||||
#endif /* DT_INST_PROP_HAS_IDX(0, irq_gpios, 1) */
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
|
@ -255,7 +266,6 @@ static void lis2dh_gpio_int1_callback(const struct device *dev,
|
|||
#endif
|
||||
}
|
||||
|
||||
#if DT_INST_PROP_HAS_IDX(0, irq_gpios, 1)
|
||||
static void lis2dh_gpio_int2_callback(const struct device *dev,
|
||||
struct gpio_callback *cb, uint32_t pins)
|
||||
{
|
||||
|
@ -272,15 +282,15 @@ static void lis2dh_gpio_int2_callback(const struct device *dev,
|
|||
k_work_submit(&lis2dh->work);
|
||||
#endif
|
||||
}
|
||||
#endif /* DT_INST_PROP_HAS_IDX(0, irq_gpios, 1) */
|
||||
|
||||
static void lis2dh_thread_cb(const struct device *dev)
|
||||
{
|
||||
struct lis2dh_data *lis2dh = dev->data;
|
||||
int status;
|
||||
|
||||
if (unlikely(atomic_test_and_clear_bit(&lis2dh->trig_flags,
|
||||
START_TRIG_INT1))) {
|
||||
if (lis2dh->gpio_int1 &&
|
||||
unlikely(atomic_test_and_clear_bit(&lis2dh->trig_flags,
|
||||
START_TRIG_INT1))) {
|
||||
status = lis2dh_start_trigger_int1(dev);
|
||||
|
||||
if (unlikely(status < 0)) {
|
||||
|
@ -289,9 +299,9 @@ static void lis2dh_thread_cb(const struct device *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
#if DT_INST_PROP_HAS_IDX(0, irq_gpios, 1)
|
||||
if (unlikely(atomic_test_and_clear_bit(&lis2dh->trig_flags,
|
||||
START_TRIG_INT2))) {
|
||||
if (lis2dh->gpio_int2 &&
|
||||
unlikely(atomic_test_and_clear_bit(&lis2dh->trig_flags,
|
||||
START_TRIG_INT2))) {
|
||||
status = lis2dh_start_trigger_int2(dev);
|
||||
|
||||
if (unlikely(status < 0)) {
|
||||
|
@ -299,10 +309,10 @@ static void lis2dh_thread_cb(const struct device *dev)
|
|||
}
|
||||
return;
|
||||
}
|
||||
#endif /* DT_INST_PROP_HAS_IDX(0, irq_gpios, 1) */
|
||||
|
||||
if (atomic_test_and_clear_bit(&lis2dh->trig_flags,
|
||||
TRIGGED_INT1)) {
|
||||
if (lis2dh->gpio_int1 &&
|
||||
atomic_test_and_clear_bit(&lis2dh->trig_flags,
|
||||
TRIGGED_INT1)) {
|
||||
struct sensor_trigger drdy_trigger = {
|
||||
.type = SENSOR_TRIG_DATA_READY,
|
||||
.chan = lis2dh->chan_drdy,
|
||||
|
@ -315,9 +325,9 @@ static void lis2dh_thread_cb(const struct device *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
#if DT_INST_PROP_HAS_IDX(0, irq_gpios, 1)
|
||||
if (atomic_test_and_clear_bit(&lis2dh->trig_flags,
|
||||
TRIGGED_INT2)) {
|
||||
if (lis2dh->gpio_int2 &&
|
||||
atomic_test_and_clear_bit(&lis2dh->trig_flags,
|
||||
TRIGGED_INT2)) {
|
||||
struct sensor_trigger anym_trigger = {
|
||||
.type = SENSOR_TRIG_DELTA,
|
||||
.chan = lis2dh->chan_drdy,
|
||||
|
@ -341,7 +351,6 @@ static void lis2dh_thread_cb(const struct device *dev)
|
|||
|
||||
return;
|
||||
}
|
||||
#endif /* DT_INST_PROP_HAS_IDX(0, irq_gpios, 1) */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LIS2DH_TRIGGER_OWN_THREAD
|
||||
|
@ -367,17 +376,20 @@ static void lis2dh_work_cb(struct k_work *work)
|
|||
int lis2dh_init_interrupt(const struct device *dev)
|
||||
{
|
||||
struct lis2dh_data *lis2dh = dev->data;
|
||||
const struct lis2dh_config *cfg = dev->config;
|
||||
int status;
|
||||
#if DT_INST_PROP_HAS_IDX(0, irq_gpios, 1)
|
||||
uint8_t raw[2];
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Setup INT1 (for DRDY) if defined in DT
|
||||
*/
|
||||
|
||||
/* setup data ready gpio interrupt */
|
||||
lis2dh->gpio_int1 = device_get_binding(LIS2DH_INT1_GPIO_DEV_NAME);
|
||||
lis2dh->gpio_int1 = device_get_binding(cfg->irq1_dev_name);
|
||||
if (lis2dh->gpio_int1 == NULL) {
|
||||
LOG_ERR("Cannot get pointer to %s device",
|
||||
LIS2DH_INT1_GPIO_DEV_NAME);
|
||||
return -EINVAL;
|
||||
LOG_INF("Cannot get pointer to irq1_dev_name");
|
||||
status = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
lis2dh->dev = dev;
|
||||
|
@ -395,17 +407,16 @@ int lis2dh_init_interrupt(const struct device *dev)
|
|||
#endif
|
||||
|
||||
/* data ready int1 gpio configuration */
|
||||
status = gpio_pin_configure(lis2dh->gpio_int1, LIS2DH_INT1_GPIOS_PIN,
|
||||
GPIO_INPUT | LIS2DH_INT1_GPIOS_FLAGS);
|
||||
status = gpio_pin_configure(lis2dh->gpio_int1, cfg->irq1_pin,
|
||||
GPIO_INPUT | cfg->irq1_flags);
|
||||
if (status < 0) {
|
||||
LOG_ERR("Could not configure gpio %d",
|
||||
LIS2DH_INT1_GPIOS_PIN);
|
||||
LOG_ERR("Could not configure gpio %d", cfg->irq1_pin);
|
||||
return status;
|
||||
}
|
||||
|
||||
gpio_init_callback(&lis2dh->gpio_int1_cb,
|
||||
lis2dh_gpio_int1_callback,
|
||||
BIT(LIS2DH_INT1_GPIOS_PIN));
|
||||
BIT(cfg->irq1_pin));
|
||||
|
||||
status = gpio_add_callback(lis2dh->gpio_int1, &lis2dh->gpio_int1_cb);
|
||||
if (status < 0) {
|
||||
|
@ -413,29 +424,30 @@ int lis2dh_init_interrupt(const struct device *dev)
|
|||
return status;
|
||||
}
|
||||
|
||||
LOG_INF("int1 on pin=%d", LIS2DH_INT1_GPIOS_PIN);
|
||||
LOG_INF("int1 on %s.%02u", cfg->irq1_dev_name, cfg->irq1_pin);
|
||||
|
||||
#if DT_INST_PROP_HAS_IDX(0, irq_gpios, 1)
|
||||
/*
|
||||
* Setup INT2 (for Any Motion) if defined in DT
|
||||
*/
|
||||
/* setup any motion gpio interrupt */
|
||||
lis2dh->gpio_int2 = device_get_binding(LIS2DH_INT2_GPIO_DEV_NAME);
|
||||
lis2dh->gpio_int2 = device_get_binding(cfg->irq2_dev_name);
|
||||
if (lis2dh->gpio_int2 == NULL) {
|
||||
LOG_ERR("Cannot get pointer to %s device",
|
||||
LIS2DH_INT2_GPIO_DEV_NAME);
|
||||
return -EINVAL;
|
||||
LOG_INF("Cannot get pointer to irq2_dev_name");
|
||||
status = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* any motion int2 gpio configuration */
|
||||
status = gpio_pin_configure(lis2dh->gpio_int2, LIS2DH_INT2_GPIOS_PIN,
|
||||
GPIO_INPUT | LIS2DH_INT2_GPIOS_FLAGS);
|
||||
status = gpio_pin_configure(lis2dh->gpio_int2, cfg->irq2_pin,
|
||||
GPIO_INPUT | cfg->irq2_flags);
|
||||
if (status < 0) {
|
||||
LOG_ERR("Could not configure gpio %d",
|
||||
LIS2DH_INT2_GPIOS_PIN);
|
||||
LOG_ERR("Could not configure gpio %d", cfg->irq2_pin);
|
||||
return status;
|
||||
}
|
||||
|
||||
gpio_init_callback(&lis2dh->gpio_int2_cb,
|
||||
lis2dh_gpio_int2_callback,
|
||||
BIT(LIS2DH_INT2_GPIOS_PIN));
|
||||
BIT(cfg->irq2_pin));
|
||||
|
||||
/* callback is going to be enabled by trigger setting function */
|
||||
status = gpio_add_callback(lis2dh->gpio_int2, &lis2dh->gpio_int2_cb);
|
||||
|
@ -444,13 +456,12 @@ int lis2dh_init_interrupt(const struct device *dev)
|
|||
return status;
|
||||
}
|
||||
|
||||
LOG_INF("int2 on pin=%d", LIS2DH_INT2_GPIOS_PIN);
|
||||
LOG_INF("int2 on %s.%02u", cfg->irq2_dev_name, cfg->irq2_pin);
|
||||
|
||||
/* disable interrupt 2 in case of warm (re)boot */
|
||||
status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_INT2_CFG, 0);
|
||||
if (status < 0) {
|
||||
LOG_ERR("Interrupt 2 disable reg write failed (%d)",
|
||||
status);
|
||||
LOG_ERR("Interrupt 2 disable reg write failed (%d)", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -474,7 +485,7 @@ int lis2dh_init_interrupt(const struct device *dev)
|
|||
LOG_ERR("INT2 latch enable reg write failed (%d)", status);
|
||||
return status;
|
||||
}
|
||||
#endif /* DT_INST_PROP_HAS_IDX(0, irq_gpios, 1) */
|
||||
|
||||
end:
|
||||
return status;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue