drivers: mfd: npm1300: Fixed race condition in event callback

If an event occurs between the status registers being read and
the event being cleared, the interrupt line will remain active.

As the interrupt is edge triggered,  all future interrupts
will being ignored.  This problem will also occur if an I2C
transation fails in the callback.

The state of the interrupt pin is now checked at the end of the
callback, and a retry is attempted if the interrupt has not
been cleared.

Signed-off-by: Andy Sinclair <andy.sinclair@nordicsemi.no>
This commit is contained in:
Andy Sinclair 2023-10-11 13:42:30 +01:00 committed by Carles Cufí
parent 733834851d
commit 7cf4eff731

View file

@ -79,12 +79,14 @@ static void gpio_callback(const struct device *dev, struct gpio_callback *cb, ui
static void work_callback(struct k_work *work)
{
struct mfd_npm1300_data *data = CONTAINER_OF(work, struct mfd_npm1300_data, work);
const struct mfd_npm1300_config *config = data->dev->config;
uint8_t buf[MAIN_SIZE];
int ret;
/* Read all MAIN registers into temporary buffer */
ret = mfd_npm1300_reg_read_burst(data->dev, MAIN_BASE, 0U, buf, sizeof(buf));
if (ret < 0) {
k_work_submit(&data->work);
return;
}
@ -97,10 +99,16 @@ static void work_callback(struct k_work *work)
ret = mfd_npm1300_reg_write(data->dev, MAIN_BASE, offset,
event_reg[i].mask);
if (ret < 0) {
k_work_submit(&data->work);
return;
}
}
}
/* Resubmit handler to queue if interrupt is still active */
if (gpio_pin_get_dt(&config->host_int_gpios) != 0) {
k_work_submit(&data->work);
}
}
static int mfd_npm1300_init(const struct device *dev)