mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
usb: typec: maxim_contaminant: re-enable cc toggle if cc is open and port is clean
Presently in `max_contaminant_is_contaminant()` if there's no
contaminant detected previously, CC is open & stopped toggling and no
contaminant is currently present, TCPC.RC would be programmed to do DRP
toggling. However, it didn't actively look for a connection. This would
lead to Type-C not detect *any* new connections. Hence, in the above
situation, re-enable toggling & program TCPC to look for a new
connection.
Also, return early if TCPC was looking for connection as this indicates
TCPC has neither detected a potential connection nor a change in
contaminant state.
In addition, once dry detection is complete (port is dry), restart
toggling.
Fixes: 02b332a063
("usb: typec: maxim_contaminant: Implement check_contaminant callback")
Cc: stable <stable@kernel.org>
Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
Reviewed-by: Badhri Jagan Sridharan <badhri@google.com>
Link: https://lore.kernel.org/r/20250815-fix-upstream-contaminant-v2-2-6c8d6c3adafb@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
cabb6c5f4d
commit
a381c6d6f6
@ -329,6 +329,39 @@ static int max_contaminant_enable_dry_detection(struct max_tcpci_chip *chip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max_contaminant_enable_toggling(struct max_tcpci_chip *chip)
|
||||
{
|
||||
struct regmap *regmap = chip->data.regmap;
|
||||
int ret;
|
||||
|
||||
/* Disable dry detection if enabled. */
|
||||
ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCLPMODESEL,
|
||||
FIELD_PREP(CCLPMODESEL,
|
||||
LOW_POWER_MODE_DISABLE));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL1, CCCONNDRY, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = max_tcpci_write8(chip, TCPC_ROLE_CTRL, TCPC_ROLE_CTRL_DRP |
|
||||
FIELD_PREP(TCPC_ROLE_CTRL_CC1,
|
||||
TCPC_ROLE_CTRL_CC_RD) |
|
||||
FIELD_PREP(TCPC_ROLE_CTRL_CC2,
|
||||
TCPC_ROLE_CTRL_CC_RD));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(regmap, TCPC_TCPC_CTRL,
|
||||
TCPC_TCPC_CTRL_EN_LK4CONN_ALRT,
|
||||
TCPC_TCPC_CTRL_EN_LK4CONN_ALRT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return max_tcpci_write8(chip, TCPC_COMMAND, TCPC_CMD_LOOK4CONNECTION);
|
||||
}
|
||||
|
||||
bool max_contaminant_is_contaminant(struct max_tcpci_chip *chip, bool disconnect_while_debounce,
|
||||
bool *cc_handled)
|
||||
{
|
||||
@ -345,6 +378,12 @@ bool max_contaminant_is_contaminant(struct max_tcpci_chip *chip, bool disconnect
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
if (cc_status & TCPC_CC_STATUS_TOGGLING) {
|
||||
if (chip->contaminant_state == DETECTED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chip->contaminant_state == NOT_DETECTED || chip->contaminant_state == SINK) {
|
||||
if (!disconnect_while_debounce)
|
||||
msleep(100);
|
||||
@ -377,6 +416,12 @@ bool max_contaminant_is_contaminant(struct max_tcpci_chip *chip, bool disconnect
|
||||
max_contaminant_enable_dry_detection(chip);
|
||||
return true;
|
||||
}
|
||||
|
||||
ret = max_contaminant_enable_toggling(chip);
|
||||
if (ret)
|
||||
dev_err(chip->dev,
|
||||
"Failed to enable toggling, ret=%d",
|
||||
ret);
|
||||
}
|
||||
} else if (chip->contaminant_state == DETECTED) {
|
||||
if (!(cc_status & TCPC_CC_STATUS_TOGGLING)) {
|
||||
@ -384,6 +429,14 @@ bool max_contaminant_is_contaminant(struct max_tcpci_chip *chip, bool disconnect
|
||||
if (chip->contaminant_state == DETECTED) {
|
||||
max_contaminant_enable_dry_detection(chip);
|
||||
return true;
|
||||
} else {
|
||||
ret = max_contaminant_enable_toggling(chip);
|
||||
if (ret) {
|
||||
dev_err(chip->dev,
|
||||
"Failed to enable toggling, ret=%d",
|
||||
ret);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user