diff --git a/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt b/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt index dfc14f71e81f..1e904ca94538 100644 --- a/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt +++ b/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt @@ -10,6 +10,9 @@ Either one of id-gpio or vbus-gpio must be present. Both can be present as well. - id-gpio: gpio for USB ID pin. See gpio binding. - vbus-gpio: gpio for USB VBUS pin. +Optional properties: +- vbus-out-gpio: gpio for enabling VBUS output (e.g. when entering host mode) + Example: Examples of extcon-usb-gpio node in dra7-evm.dts as listed below: extcon_usb1 { compatible = "linux,extcon-usb-gpio"; diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c index 3f48e9398c3b..ee19c03401ae 100644 --- a/drivers/extcon/extcon-usb-gpio.c +++ b/drivers/extcon/extcon-usb-gpio.c @@ -36,6 +36,7 @@ struct usb_extcon_info { struct gpio_desc *id_gpiod; struct gpio_desc *vbus_gpiod; + struct gpio_desc *vbus_out_gpiod; int id_irq; int vbus_irq; @@ -80,12 +81,17 @@ static void usb_extcon_detect_cable(struct work_struct *work) gpiod_get_value_cansleep(info->vbus_gpiod) : id; /* at first we clean states which are no longer active */ - if (id) + if (id) { + if (info->vbus_out_gpiod) + gpiod_set_value_cansleep(info->vbus_out_gpiod, 0); extcon_set_state_sync(info->edev, EXTCON_USB_HOST, false); + } if (!vbus) extcon_set_state_sync(info->edev, EXTCON_USB, false); if (!id) { + if (info->vbus_out_gpiod) + gpiod_set_value_cansleep(info->vbus_out_gpiod, 1); extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true); } else { if (vbus) @@ -121,6 +127,8 @@ static int usb_extcon_probe(struct platform_device *pdev) info->id_gpiod = devm_gpiod_get_optional(&pdev->dev, "id", GPIOD_IN); info->vbus_gpiod = devm_gpiod_get_optional(&pdev->dev, "vbus", GPIOD_IN); + info->vbus_out_gpiod = devm_gpiod_get_optional(&pdev->dev, "vbus-out", + GPIOD_OUT_HIGH); if (!info->id_gpiod && !info->vbus_gpiod) { dev_err(dev, "failed to get gpios\n"); @@ -133,6 +141,9 @@ static int usb_extcon_probe(struct platform_device *pdev) if (IS_ERR(info->vbus_gpiod)) return PTR_ERR(info->vbus_gpiod); + if (IS_ERR(info->vbus_out_gpiod)) + return PTR_ERR(info->vbus_out_gpiod); + info->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable); if (IS_ERR(info->edev)) { dev_err(dev, "failed to allocate extcon device\n");