diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c index 98b5afa5b615..8045d994c8a6 100644 --- a/drivers/extcon/extcon-usb-gpio.c +++ b/drivers/extcon/extcon-usb-gpio.c @@ -28,6 +28,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; @@ -72,12 +73,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) @@ -113,6 +119,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"); @@ -125,6 +133,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");