Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: common: usb-conn-gpio: Make VBUS supply optional

If the connector is the child of a USB port and that USB port already
has a VBUS supply attached to it, it would be redundant to require the
connector to have a VBUS supply. In this case, allow the VBUS supply to
be optional.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Link: https://lore.kernel.org/r/20200806160248.3936771-1-thierry.reding@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Thierry Reding and committed by
Greg Kroah-Hartman
4ddf1ac7 4d671957

+24 -6
+24 -6
drivers/usb/common/usb-conn-gpio.c
··· 91 91 return; 92 92 } 93 93 94 - if (info->last_role == USB_ROLE_HOST) 94 + if (info->last_role == USB_ROLE_HOST && info->vbus) 95 95 regulator_disable(info->vbus); 96 96 97 97 ret = usb_role_switch_set_role(info->role_sw, role); 98 98 if (ret) 99 99 dev_err(info->dev, "failed to set role: %d\n", ret); 100 100 101 - if (role == USB_ROLE_HOST) { 101 + if (role == USB_ROLE_HOST && info->vbus) { 102 102 ret = regulator_enable(info->vbus); 103 103 if (ret) 104 104 dev_err(info->dev, "enable vbus regulator failed\n"); ··· 106 106 107 107 info->last_role = role; 108 108 109 - dev_dbg(info->dev, "vbus regulator is %s\n", 110 - regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); 109 + if (info->vbus) 110 + dev_dbg(info->dev, "vbus regulator is %s\n", 111 + regulator_is_enabled(info->vbus) ? "enabled" : "disabled"); 111 112 112 113 power_supply_changed(info->charger); 113 114 } ··· 157 156 struct power_supply_config cfg = { 158 157 .of_node = dev->of_node, 159 158 }; 159 + bool need_vbus = true; 160 160 int ret = 0; 161 161 162 162 info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); ··· 187 185 188 186 INIT_DELAYED_WORK(&info->dw_det, usb_conn_detect_cable); 189 187 190 - info->vbus = devm_regulator_get(dev, "vbus"); 188 + /* 189 + * If the USB connector is a child of a USB port and that port already provides the VBUS 190 + * supply, there's no need for the USB connector to provide it again. 191 + */ 192 + if (dev->parent && dev->parent->of_node) { 193 + if (of_find_property(dev->parent->of_node, "vbus-supply", NULL)) 194 + need_vbus = false; 195 + } 196 + 197 + if (!need_vbus) { 198 + info->vbus = devm_regulator_get_optional(dev, "vbus"); 199 + if (PTR_ERR(info->vbus) == -ENODEV) 200 + info->vbus = NULL; 201 + } else { 202 + info->vbus = devm_regulator_get(dev, "vbus"); 203 + } 204 + 191 205 if (IS_ERR(info->vbus)) { 192 206 if (PTR_ERR(info->vbus) != -EPROBE_DEFER) 193 207 dev_err(dev, "failed to get vbus\n"); ··· 284 266 285 267 cancel_delayed_work_sync(&info->dw_det); 286 268 287 - if (info->last_role == USB_ROLE_HOST) 269 + if (info->last_role == USB_ROLE_HOST && info->vbus) 288 270 regulator_disable(info->vbus); 289 271 290 272 usb_role_switch_put(info->role_sw);