Re: [PATCH v2 08/12] iio: imu: inv_icm42600: add device interrupt
On Wed, 27 May 2020 20:57:07 +0200 Jean-Baptiste Maneyrol wrote: > Add INT1 interrupt support. Support interrupt edge and level, > active high or low. Push-pull or open-drain configurations. > > Interrupt will be used to read data from the FIFO. > > Signed-off-by: Jean-Baptiste Maneyrol Some nitpicks inline - all cases where a blank line would slightly help readability. J > --- > drivers/iio/imu/inv_icm42600/inv_icm42600.h | 2 +- > .../iio/imu/inv_icm42600/inv_icm42600_core.c | 96 ++- > .../iio/imu/inv_icm42600/inv_icm42600_i2c.c | 3 +- > .../iio/imu/inv_icm42600/inv_icm42600_spi.c | 3 +- > 4 files changed, 100 insertions(+), 4 deletions(-) > > diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h > b/drivers/iio/imu/inv_icm42600/inv_icm42600.h > index c534acae0308..43749f56426c 100644 > --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h > +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h > @@ -372,7 +372,7 @@ int inv_icm42600_set_temp_conf(struct inv_icm42600_state > *st, bool enable, > int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, >unsigned int writeval, unsigned int *readval); > > -int inv_icm42600_core_probe(struct regmap *regmap, int chip, > +int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, > inv_icm42600_bus_setup bus_setup); > > int inv_icm42600_gyro_init(struct inv_icm42600_state *st); > diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c > b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c > index e7f7835aca9b..246c1eb52231 100644 > --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c > +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c > @@ -9,8 +9,11 @@ > #include > #include > #include > +#include > +#include > #include > #include > +#include > #include > #include > > @@ -409,6 +412,79 @@ static int inv_icm42600_setup(struct inv_icm42600_state > *st, > return inv_icm42600_set_conf(st, hw->conf); > } > > +static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data) > +{ > + struct inv_icm42600_state *st = _data; > + struct device *dev = regmap_get_device(st->map); > + unsigned int status; > + int ret; > + > + mutex_lock(>lock); > + > + ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, ); > + if (ret) > + goto out_unlock; > + > + /* FIFO full */ > + if (status & INV_ICM42600_INT_STATUS_FIFO_FULL) > + dev_warn(dev, "FIFO full data lost!\n"); > + > +out_unlock: > + mutex_unlock(>lock); > + return IRQ_HANDLED; > +} > + > +/** > + * inv_icm42600_irq_init() - initialize int pin and interrupt handler > + * @st: driver internal state > + * @irq: irq number > + * @irq_type:irq trigger type > + * @open_drain: true if irq is open drain, false for push-pull > + * > + * Returns 0 on success, a negative error code otherwise. > + */ > +static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq, > + int irq_type, bool open_drain) > +{ > + struct device *dev = regmap_get_device(st->map); > + unsigned int val; > + int ret; > + > + /* configure INT1 interrupt: default is active low on edge */ > + switch (irq_type) { > + case IRQF_TRIGGER_RISING: > + case IRQF_TRIGGER_HIGH: > + val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH; > + break; > + default: > + val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW; > + break; > + } blank line here > + switch (irq_type) { > + case IRQF_TRIGGER_LOW: > + case IRQF_TRIGGER_HIGH: > + val |= INV_ICM42600_INT_CONFIG_INT1_LATCHED; > + break; > + default: > + break; > + } blank line here. > + if (!open_drain) > + val |= INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL; blank line here > + ret = regmap_write(st->map, INV_ICM42600_REG_INT_CONFIG, val); > + if (ret) > + return ret; > + > + /* Deassert async reset for proper INT pin operation (cf datasheet) */ > + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_CONFIG1, > + INV_ICM42600_INT_CONFIG1_ASYNC_RESET, 0); > + if (ret) > + return ret; > + > + return devm_request_threaded_irq(dev, irq, NULL, > + inv_icm42600_irq_handler, irq_type, > + "inv_icm42600", st); > +} > + > static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st) > { > int ret; > @@ -453,11 +529,14 @@ static void inv_icm42600_disable_pm(void *_data) > pm_runtime_disable(dev); > } > > -int inv_icm42600_core_probe(struct regmap *regmap, int chip, > +int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, > inv_icm42600_bus_setup bus_setup) > { >
[PATCH v2 08/12] iio: imu: inv_icm42600: add device interrupt
Add INT1 interrupt support. Support interrupt edge and level, active high or low. Push-pull or open-drain configurations. Interrupt will be used to read data from the FIFO. Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/imu/inv_icm42600/inv_icm42600.h | 2 +- .../iio/imu/inv_icm42600/inv_icm42600_core.c | 96 ++- .../iio/imu/inv_icm42600/inv_icm42600_i2c.c | 3 +- .../iio/imu/inv_icm42600/inv_icm42600_spi.c | 3 +- 4 files changed, 100 insertions(+), 4 deletions(-) diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h index c534acae0308..43749f56426c 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -372,7 +372,7 @@ int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable, int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, unsigned int writeval, unsigned int *readval); -int inv_icm42600_core_probe(struct regmap *regmap, int chip, +int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, inv_icm42600_bus_setup bus_setup); int inv_icm42600_gyro_init(struct inv_icm42600_state *st); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c index e7f7835aca9b..246c1eb52231 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -9,8 +9,11 @@ #include #include #include +#include +#include #include #include +#include #include #include @@ -409,6 +412,79 @@ static int inv_icm42600_setup(struct inv_icm42600_state *st, return inv_icm42600_set_conf(st, hw->conf); } +static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data) +{ + struct inv_icm42600_state *st = _data; + struct device *dev = regmap_get_device(st->map); + unsigned int status; + int ret; + + mutex_lock(>lock); + + ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, ); + if (ret) + goto out_unlock; + + /* FIFO full */ + if (status & INV_ICM42600_INT_STATUS_FIFO_FULL) + dev_warn(dev, "FIFO full data lost!\n"); + +out_unlock: + mutex_unlock(>lock); + return IRQ_HANDLED; +} + +/** + * inv_icm42600_irq_init() - initialize int pin and interrupt handler + * @st:driver internal state + * @irq: irq number + * @irq_type: irq trigger type + * @open_drain:true if irq is open drain, false for push-pull + * + * Returns 0 on success, a negative error code otherwise. + */ +static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq, +int irq_type, bool open_drain) +{ + struct device *dev = regmap_get_device(st->map); + unsigned int val; + int ret; + + /* configure INT1 interrupt: default is active low on edge */ + switch (irq_type) { + case IRQF_TRIGGER_RISING: + case IRQF_TRIGGER_HIGH: + val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH; + break; + default: + val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW; + break; + } + switch (irq_type) { + case IRQF_TRIGGER_LOW: + case IRQF_TRIGGER_HIGH: + val |= INV_ICM42600_INT_CONFIG_INT1_LATCHED; + break; + default: + break; + } + if (!open_drain) + val |= INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL; + ret = regmap_write(st->map, INV_ICM42600_REG_INT_CONFIG, val); + if (ret) + return ret; + + /* Deassert async reset for proper INT pin operation (cf datasheet) */ + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_CONFIG1, +INV_ICM42600_INT_CONFIG1_ASYNC_RESET, 0); + if (ret) + return ret; + + return devm_request_threaded_irq(dev, irq, NULL, +inv_icm42600_irq_handler, irq_type, +"inv_icm42600", st); +} + static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st) { int ret; @@ -453,11 +529,14 @@ static void inv_icm42600_disable_pm(void *_data) pm_runtime_disable(dev); } -int inv_icm42600_core_probe(struct regmap *regmap, int chip, +int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, inv_icm42600_bus_setup bus_setup) { struct device *dev = regmap_get_device(regmap); struct inv_icm42600_state *st; + struct irq_data *irq_desc; + int irq_type; + bool open_drain; int ret; if (chip < 0 || chip >= INV_CHIP_NB) { @@ -465,6 +544,17 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, return -ENODEV; } + /*