Skip to content

Commit

Permalink
extcon: usbc-tusb320: Update state on probe even if no IRQ pending
Browse files Browse the repository at this point in the history
[ Upstream commit 581c848 ]

Currently this driver triggers extcon and typec state update in its
probe function, to read out current state reported by the chip and
report the correct state to upper layers. This synchronization is
performed correctly, but only in case the chip indicates a pending
interrupt in reg09 register.

This fails to cover the situation where all interrupts reported by
the chip were already handled by Linux before reboot, then the system
rebooted, and then Linux starts again. In this case, the TUSB320 no
longer reports any interrupts in reg09, and the state update does not
perform any update as it depends on that interrupt indication.

Fix this by turning tusb320_irq_handler() into a thin wrapper around
tusb320_state_update_handler(), where the later now contains the bulk
of the code of tusb320_irq_handler(), but adds new function parameter
"force_update". The "force_update" parameter can be used by the probe
function to assure that the state synchronization is always performed,
independent of the interrupt indicated in reg09. The interrupt handler
tusb320_irq_handler() callback uses force_update=false to avoid state
updates on potential spurious interrupts and retain current behavior.

Fixes: 06bc4ca ("extcon: Add driver for TI TUSB320")
Signed-off-by: Marek Vasut <marex@denx.de>
Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>
Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20221120141509.81012-1-marex@denx.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Marek Vasut authored and gregkh committed Dec 31, 2022
1 parent ac067e7 commit f46f9d2
Showing 1 changed file with 12 additions and 5 deletions.
17 changes: 12 additions & 5 deletions drivers/extcon/extcon-usbc-tusb320.c
Expand Up @@ -313,17 +313,17 @@ static void tusb320_typec_irq_handler(struct tusb320_priv *priv, u8 reg9)
typec_set_pwr_opmode(port, TYPEC_PWR_MODE_USB);
}

static irqreturn_t tusb320_irq_handler(int irq, void *dev_id)
static irqreturn_t tusb320_state_update_handler(struct tusb320_priv *priv,
bool force_update)
{
struct tusb320_priv *priv = dev_id;
unsigned int reg;

if (regmap_read(priv->regmap, TUSB320_REG9, &reg)) {
dev_err(priv->dev, "error during i2c read!\n");
return IRQ_NONE;
}

if (!(reg & TUSB320_REG9_INTERRUPT_STATUS))
if (!force_update && !(reg & TUSB320_REG9_INTERRUPT_STATUS))
return IRQ_NONE;

tusb320_extcon_irq_handler(priv, reg);
Expand All @@ -334,6 +334,13 @@ static irqreturn_t tusb320_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}

static irqreturn_t tusb320_irq_handler(int irq, void *dev_id)
{
struct tusb320_priv *priv = dev_id;

return tusb320_state_update_handler(priv, false);
}

static const struct regmap_config tusb320_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
Expand Down Expand Up @@ -460,7 +467,7 @@ static int tusb320_probe(struct i2c_client *client,
return ret;

/* update initial state */
tusb320_irq_handler(client->irq, priv);
tusb320_state_update_handler(priv, true);

/* Reset chip to its default state */
ret = tusb320_reset(priv);
Expand All @@ -471,7 +478,7 @@ static int tusb320_probe(struct i2c_client *client,
* State and polarity might change after a reset, so update
* them again and make sure the interrupt status bit is cleared.
*/
tusb320_irq_handler(client->irq, priv);
tusb320_state_update_handler(priv, true);

ret = devm_request_threaded_irq(priv->dev, client->irq, NULL,
tusb320_irq_handler,
Expand Down

0 comments on commit f46f9d2

Please sign in to comment.