diff --git a/Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml b/Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml index d5cfa32ea52d..77115b361452 100644 --- a/Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml +++ b/Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml @@ -37,6 +37,12 @@ properties: GPIO pin (output) used to control VBUS. If skipped, no such control takes place. + vbus-supply: + maxItems: 1 + description: + VBUS regulator used to control VBUS. If skipped, no such control + takes place. + required: - compatible - interrupts diff --git a/drivers/extcon/extcon-ptn5150.c b/drivers/extcon/extcon-ptn5150.c index 4616da7e5430..02a5ef35d5f0 100644 --- a/drivers/extcon/extcon-ptn5150.c +++ b/drivers/extcon/extcon-ptn5150.c @@ -18,6 +18,7 @@ #include #include #include +#include /* PTN5150 registers */ #define PTN5150_REG_DEVICE_ID 0x01 @@ -54,6 +55,7 @@ struct ptn5150_info { struct work_struct irq_work; struct mutex mutex; struct usb_role_switch *role_sw; + struct regulator *vbus_reg; }; /* List of detectable cables */ @@ -69,10 +71,43 @@ static const struct regmap_config ptn5150_regmap_config = { .max_register = PTN5150_REG_END, }; +static void ptn5150_vbus_off(struct ptn5150_info *info) +{ + int ret = 0; + + gpiod_set_value_cansleep(info->vbus_gpiod, 0); + if (info->vbus_reg) { + dev_info(info->dev, "Disable VBUS regulator\n"); + + if (regulator_is_enabled(info->vbus_reg)) + ret = regulator_disable(info->vbus_reg); + + if (ret) + dev_err(info->dev, "VBUS regulator disable failed\n"); + } +} + +static void ptn5150_vbus_on(struct ptn5150_info *info) +{ + int ret = 0; + + gpiod_set_value_cansleep(info->vbus_gpiod, 1); + if (info->vbus_reg) { + dev_info(info->dev, "Enable VBUS regulator\n"); + + if (!regulator_is_enabled(info->vbus_reg)) + ret = regulator_enable(info->vbus_reg); + + if (ret) + dev_err(info->dev, "VBUS regulator enable failed\n"); + } +} + static void ptn5150_check_state(struct ptn5150_info *info) { unsigned int port_status, reg_data, vbus; enum usb_role usb_role = USB_ROLE_NONE; + bool vbus_reg_enable = false; int ret; ret = regmap_read(info->regmap, PTN5150_REG_CC_STATUS, ®_data); @@ -86,17 +121,14 @@ static void ptn5150_check_state(struct ptn5150_info *info) switch (port_status) { case PTN5150_DFP_ATTACHED: extcon_set_state_sync(info->edev, EXTCON_USB_HOST, false); - gpiod_set_value_cansleep(info->vbus_gpiod, 0); extcon_set_state_sync(info->edev, EXTCON_USB, true); usb_role = USB_ROLE_DEVICE; break; case PTN5150_UFP_ATTACHED: extcon_set_state_sync(info->edev, EXTCON_USB, false); vbus = FIELD_GET(PTN5150_REG_CC_VBUS_DETECTION, reg_data); - if (vbus) - gpiod_set_value_cansleep(info->vbus_gpiod, 0); - else - gpiod_set_value_cansleep(info->vbus_gpiod, 1); + if (!vbus) + vbus_reg_enable = true; extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true); usb_role = USB_ROLE_HOST; @@ -105,6 +137,11 @@ static void ptn5150_check_state(struct ptn5150_info *info) break; } + if (vbus_reg_enable) + ptn5150_vbus_on(info); + else + ptn5150_vbus_off(info); + if (usb_role) { ret = usb_role_switch_set_role(info->role_sw, usb_role); if (ret) @@ -144,7 +181,7 @@ static void ptn5150_irq_work(struct work_struct *work) EXTCON_USB_HOST, false); extcon_set_state_sync(info->edev, EXTCON_USB, false); - gpiod_set_value_cansleep(info->vbus_gpiod, 0); + ptn5150_vbus_off(info); ret = usb_role_switch_set_role(info->role_sw, USB_ROLE_NONE); @@ -249,6 +286,19 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c) } } + info->vbus_reg = NULL; + if (of_find_property(np, "vbus-supply", NULL)) { + struct regulator *vbus_reg; + + vbus_reg = devm_regulator_get_exclusive(dev, "vbus"); + if (IS_ERR_OR_NULL(vbus_reg)) { + return dev_err_probe(dev, PTR_ERR(vbus_reg), + "Couldn't get the VBUS power regulator.\n"); + } + + info->vbus_reg = vbus_reg; + } + mutex_init(&info->mutex); INIT_WORK(&info->irq_work, ptn5150_irq_work); diff --git a/labgrid.basesoftware b/labgrid.basesoftware index 612ac8d4a9ce..017c12dae556 160000 --- a/labgrid.basesoftware +++ b/labgrid.basesoftware @@ -1 +1 @@ -Subproject commit 612ac8d4a9ce7b359342c6e89f5d08a1b02a1b87 +Subproject commit 017c12dae556738cc3124ae65b64a80bbf70af6d