From 38cc775a5c900899617b5ab0d70a1dde20525efd Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Fri, 16 Mar 2018 14:03:52 -0700 Subject: [PATCH] extcon: usb-gpio: Add support for optional VBUS output enable GPIO On many platforms 5V VBUS output can be provided by external circuitry and turned on via GPIO. For convenience, on micro-AB ports this can be done in conjunction when ID pin becomes low meaning USB_HOST mode is to be entered. Add support for an optional "vbus-out" GPIO to this driver. Change-Id: Id58e5dca5375b8140c75ce7cd6769dd8a31a2af7 Signed-off-by: Jack Pham --- drivers/extcon/extcon-usb-gpio.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) 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");