From fd63157b5e6433e545876010a35d84667e14f86f Mon Sep 17 00:00:00 2001 From: Krishna Kurapati Date: Thu, 27 Oct 2022 18:49:34 +0530 Subject: [PATCH] usb: pd: Send extcon notification as soon as APSD detection is done In some targets, it is observed that the time difference between vbus being provided by exerciser and the terminations being applied is more than 1 second causing failures of Type-C compliance testcases 4.10.2 and 4.10.3 When policy engine's psy changed work gets kicked in first time from vbus present interrupt callback of charger driver, we kick in usb pd sm work and it keeps running. Since apsd is not yet done, we don't queue peripheral work. When apsd is done and charger driver invokes power supply changed work, policy engine bails out as sm work is already running although the charger type is detected as SDP/CDP and were supposed to send an extcon notification. As a result the extcon is sent when the sm work hits enter snk startup call and it recognises that apsd is done and charger type is SDP or CDP and sends extcon. This is results in a delay of roughly 1.3 seconds from the moment vbus got detected to the moment we provide extcon notification to dwc3-msm. To avoid this, check for charger type and provide extcon if haven't done already in the psy_changed_notifier_work. This reduces the time delay to around 0.5 seconds helping resolve compliance issue. Change-Id: I02c9a4a6b21ca75d43fd68f2447a7388210a4856 Signed-off-by: Krishna Kurapati --- drivers/usb/pd/policy_engine.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 99f271551ecc..2839abb1d86c 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -3724,6 +3725,7 @@ static void psy_changed_notifier_work(struct work_struct *w) union power_supply_propval val; enum power_supply_typec_mode typec_mode; int ret; + int usb_extcon_state; ret = usbpd_get_psy_iio_property(pd, POWER_SUPPLY_PROP_TYPEC_MODE, &val); @@ -3794,8 +3796,28 @@ static void psy_changed_notifier_work(struct work_struct *w) return; } - if (pd->typec_mode == typec_mode) + if (pd->typec_mode == typec_mode) { + if (!((pd->current_dr == DR_NONE) || (pd->current_dr == DR_UFP))) + return; + + usb_extcon_state = extcon_get_state(pd->extcon, EXTCON_USB); + + if (usb_extcon_state == 0) { + ret = usbpd_get_psy_iio_property(pd, POWER_SUPPLY_PROP_REAL_TYPE, + &val); + if (ret) { + usbpd_err(&pd->dev, "Unable to read USB PROP_REAL_TYPE: %d\n", + ret); + return; + } + + if (val.intval == POWER_SUPPLY_TYPE_USB || + val.intval == POWER_SUPPLY_TYPE_USB_CDP || + val.intval == QTI_POWER_SUPPLY_TYPE_USB_FLOAT) + queue_work(pd->wq, &pd->start_periph_work); + } return; + } pd->typec_mode = typec_mode;