On Mon, Nov 15, 2021 at 09:11:42AM +0200, Heikki Krogerus wrote: > On Mon, Nov 08, 2021 at 11:28:32AM +0100, Ondrej Jirman wrote: > > The code that enables either BC_LVL or COMP_CHNG interrupt in tcpm_set_cc > > wrongly assumes that the interrupt is unmasked by writing 1 to the apropriate > > bit in the mask register. In fact, interrupts are enabled when the mask > > is 0, so the tcpm_set_cc enables interrupt for COMP_CHNG when it expects > > BC_LVL interrupt to be enabled. > > > > This causes inability of the driver to recognize cable unplug events > > in host mode (unplug is recognized only via a COMP_CHNG interrupt). > > > > In device mode this bug was masked by simultaneous triggering of the VBUS > > change interrupt, because of loss of VBUS when the port peer is providing > > power. > > > > Fixes: 48242e30532b ("usb: typec: fusb302: Revert "Resolve fixed power role contract setup"") > > Signed-off-by: Ondrej Jirman <megous@xxxxxxxxxx> > > Cc: Hans de Goede <hdegoede@xxxxxxxxxx> > > Should this go to stable? Without this patch, VBUS is not turned off when I disconnect a hub from the Type-C port (because fusb302 will not notice the disconnect), and it stays on until next plugin of some device, say a normal non PD charger. So I guess for a brief period you can have both sides provide VBUS (until fusb302/tcpm processes the next plugin). It may be a problem if VBUS was more than 5V (not very likely for devices running this driver, I guess). regards, o. > Acked-by: Heikki Krogerus@xxxxxxxxxxxxxxx > > > --- > > drivers/usb/typec/tcpm/fusb302.c | 6 ++++-- > > 1 file changed, 4 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c > > index 7a2a17866a823..72f9001b07921 100644 > > --- a/drivers/usb/typec/tcpm/fusb302.c > > +++ b/drivers/usb/typec/tcpm/fusb302.c > > @@ -669,25 +669,27 @@ static int tcpm_set_cc(struct tcpc_dev *dev, enum typec_cc_status cc) > > ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK, > > FUSB_REG_MASK_BC_LVL | > > FUSB_REG_MASK_COMP_CHNG, > > - FUSB_REG_MASK_COMP_CHNG); > > + FUSB_REG_MASK_BC_LVL); > > if (ret < 0) { > > fusb302_log(chip, "cannot set SRC interrupt, ret=%d", > > ret); > > goto done; > > } > > chip->intr_comp_chng = true; > > + chip->intr_bc_lvl = false; > > break; > > case TYPEC_CC_RD: > > ret = fusb302_i2c_mask_write(chip, FUSB_REG_MASK, > > FUSB_REG_MASK_BC_LVL | > > FUSB_REG_MASK_COMP_CHNG, > > - FUSB_REG_MASK_BC_LVL); > > + FUSB_REG_MASK_COMP_CHNG); > > if (ret < 0) { > > fusb302_log(chip, "cannot set SRC interrupt, ret=%d", > > ret); > > goto done; > > } > > chip->intr_bc_lvl = true; > > + chip->intr_comp_chng = false; > > break; > > default: > > break; > > thanks, > > -- > heikki