drivers/ioexpander/icjx.c: reconfigure icjx after undervoltage

According to a reference manual, VCC and VDD undervoltage
and VDD burst leads to the reset of all registers.
Therefore we have to reconfigure the expander to make
it functional again.

Signed-off-by: Michal Lenc <michallenc@seznam.cz>
This commit is contained in:
Michal Lenc
2025-07-18 14:19:00 +02:00
committed by Alan C. Assis
parent cbdc1a4108
commit e96ef8abe3
+80
View File
@@ -932,6 +932,74 @@ static int icjx_detach(FAR struct ioexpander_dev_s *dev, FAR void *handle)
return OK; return OK;
} }
/****************************************************************************
* Name: icjx_reconfigure
*
* Description:
* Reconfigure icjx chip. This might be required if VCC or VDD drops
* below a limit or if VDD burst occurs as registers are reset to a
* default state.
*
* Input Parameters:
* priv - Private icjx data structure.
*
* Returned Value:
* 0 on success, else a negative error code
*
****************************************************************************/
static int icjx_reconfigure(FAR struct icjx_dev_s *priv)
{
FAR struct icjx_config_s *config = priv->config;
uint8_t regval;
uint16_t direction;
int ret;
ret = nxmutex_lock(&priv->lock);
if (ret < 0)
{
return ret;
}
/* Re-enable pull ups */
regval = (config->current_src << 4) | config->current_src;
icjx_write(priv, ICJX_CTRL_WORD_2_A, regval, ICJX_NOB1);
icjx_write(priv, ICJX_CTRL_WORD_2_B, regval, ICJX_NOB1);
/* Re-enable filters */
if (config->filters != ICJX_CTRL_WORD_FILTER_DISABLED)
{
regval = ICJX_CTRL_WORD_3_ICLK;
}
else
{
regval = ICJX_CTRL_WORD_3_DIS;
}
icjx_write(priv, ICJX_CTRL_WORD_3_B, regval, ICJX_NOB1);
regval = (config->filters << 4) | config->filters;
icjx_write(priv, ICJX_CTRL_WORD_1_A, regval, ICJX_NOB1);
icjx_write(priv, ICJX_CTRL_WORD_1_B, regval, ICJX_NOB1);
/* Re-enable outputs */
icjx_read(priv, ICJX_CTRL_WORD_2_A, &direction, ICJX_NOB2);
direction |= priv->outpins & 0xf ? ICJX_CTRL_WORD_2_NIOL : 0;
direction |= priv->outpins & 0xf0 ? ICJX_CTRL_WORD_2_NIOH : 0;
direction |= priv->outpins & 0xf00 ? ICJX_CTRL_WORD_2_NIOL << 8 : 0;
direction |= priv->outpins & 0xf000 ? ICJX_CTRL_WORD_2_NIOH << 8 : 0;
icjx_write(priv, ICJX_CTRL_WORD_2_A, direction, ICJX_NOB2);
/* Re-enable interrupts */
icjx_write(priv, ICJX_CHNG_INT_EN_A, priv->irqpins, ICJX_NOB2);
nxmutex_unlock(&priv->lock);
return 0;
}
/**************************************************************************** /****************************************************************************
* Name: icjx_interrupt_worker * Name: icjx_interrupt_worker
* *
@@ -978,6 +1046,18 @@ static void icjx_interrupt_worker(void *arg)
} }
} }
if (((isr >> 8) & (ICJX_ISR_B_IUSA | ICJX_ISR_B_IUSD |
ICJX_ISR_B_ISD)) != 0)
{
/* According to a reference manual, VCC and VDD undervoltage
* and VDD burst leads to the reset of all registers.
* Therefore we have to reconfigure the expander to make
* it functional again.
*/
icjx_reconfigure(priv);
}
/* Clear interrupt and check ISR again */ /* Clear interrupt and check ISR again */
icjx_write(priv, ICJX_CTRL_WORD_4, ICJX_CTRL_WORD_4_EOI, ICJX_NOB1); icjx_write(priv, ICJX_CTRL_WORD_4, ICJX_CTRL_WORD_4_EOI, ICJX_NOB1);