From 6494e9ee09caf8402f38aa94d95c0bba0882846a Mon Sep 17 00:00:00 2001 From: Vijayavardhan Vennapusa Date: Tue, 28 Aug 2018 11:06:16 +0530 Subject: [PATCH] USB: pd: Notify selfpowered state based on type C current It is required to notify device as selfpowered and bmaxpower as zero even for non PD capable devices based on Type C current. Hence notify as selfpowerer in bMattributes of configuation descriptor in case of medium or high Type C current. Change-Id: Ie552560d93a8195f4c69fdaf6086ef3a52b31d39 Signed-off-by: Vijayavardhan Vennapusa --- drivers/usb/dwc3/dwc3-msm.c | 8 ++++++++ drivers/usb/gadget/composite.c | 4 ++++ drivers/usb/pd/policy_engine.c | 3 +++ include/linux/extcon.h | 3 +++ 4 files changed, 18 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 623f3ce211aa..2b4a6de99876 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -2629,6 +2629,7 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb, struct extcon_dev *edev = ptr; int cc_state; int speed; + int self_powered; if (!edev) { dev_err(mdwc->dev, "%s: edev null\n", __func__); @@ -2654,6 +2655,13 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb, if (dwc->maximum_speed > dwc->max_hw_supp_speed) dwc->maximum_speed = dwc->max_hw_supp_speed; + self_powered = extcon_get_cable_state_(edev, + EXTCON_USB_TYPEC_MED_HIGH_CURRENT); + if (self_powered < 0) + dwc->gadget.is_selfpowered = 0; + else + dwc->gadget.is_selfpowered = self_powered; + mdwc->vbus_active = event; if (dwc->is_drd && !mdwc->in_restart) { dbg_event(0xFF, "Q RW (vbus)", mdwc->vbus_active); diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 9d795489c285..2db7474a1730 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -509,6 +509,10 @@ static int config_buf(struct usb_configuration *config, c->iConfiguration = config->iConfiguration; c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes; c->bMaxPower = encode_bMaxPower(speed, config); + if (config->cdev->gadget->is_selfpowered) { + c->bmAttributes |= USB_CONFIG_ATT_SELFPOWER; + c->bMaxPower = 0; + } /* There may be e.g. OTG descriptors */ if (config->descriptors) { diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 935bd0778bfb..f35360b9523c 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -375,6 +375,7 @@ static const unsigned int usbpd_extcon_cable[] = { EXTCON_USB_HOST, EXTCON_USB_CC, EXTCON_USB_SPEED, + EXTCON_USB_TYPEC_MED_HIGH_CURRENT, EXTCON_NONE, }; @@ -422,6 +423,8 @@ static inline void start_usb_peripheral(struct usbpd *pd) extcon_set_cable_state_(pd->extcon, EXTCON_USB_CC, cc == ORIENTATION_CC2); extcon_set_cable_state_(pd->extcon, EXTCON_USB_SPEED, 1); + extcon_set_cable_state_(pd->extcon, EXTCON_USB_TYPEC_MED_HIGH_CURRENT, + pd->typec_mode > POWER_SUPPLY_TYPEC_SOURCE_DEFAULT ? 1 : 0); extcon_set_cable_state_(pd->extcon, EXTCON_USB, 1); } diff --git a/include/linux/extcon.h b/include/linux/extcon.h index e1360198955a..081afbe982c0 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -61,6 +61,9 @@ /* connector speed 0 - High Speed, 1 - super speed */ #define EXTCON_USB_SPEED 29 +/* connector type C current 0 - default current, 1 - medium or high current */ +#define EXTCON_USB_TYPEC_MED_HIGH_CURRENT 30 + /* Display external connector */ #define EXTCON_DISP_HDMI 40 /* High-Definition Multimedia Interface */ #define EXTCON_DISP_MHL 41 /* Mobile High-Definition Link */