Merge branch 'master' into topic/rg/cc100_dali

This commit is contained in:
Oleg KARFICH 2025-10-20 16:51:28 +02:00 committed by GitHub Enterprise
commit 6f507e81b6
3 changed files with 63 additions and 7 deletions

@ -37,6 +37,12 @@ properties:
GPIO pin (output) used to control VBUS. If skipped, no such control GPIO pin (output) used to control VBUS. If skipped, no such control
takes place. takes place.
vbus-supply:
maxItems: 1
description:
VBUS regulator used to control VBUS. If skipped, no such control
takes place.
required: required:
- compatible - compatible
- interrupts - interrupts

@ -18,6 +18,7 @@
#include <linux/extcon-provider.h> #include <linux/extcon-provider.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/usb/role.h> #include <linux/usb/role.h>
#include <linux/regulator/consumer.h>
/* PTN5150 registers */ /* PTN5150 registers */
#define PTN5150_REG_DEVICE_ID 0x01 #define PTN5150_REG_DEVICE_ID 0x01
@ -54,6 +55,7 @@ struct ptn5150_info {
struct work_struct irq_work; struct work_struct irq_work;
struct mutex mutex; struct mutex mutex;
struct usb_role_switch *role_sw; struct usb_role_switch *role_sw;
struct regulator *vbus_reg;
}; };
/* List of detectable cables */ /* List of detectable cables */
@ -69,10 +71,43 @@ static const struct regmap_config ptn5150_regmap_config = {
.max_register = PTN5150_REG_END, .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) static void ptn5150_check_state(struct ptn5150_info *info)
{ {
unsigned int port_status, reg_data, vbus; unsigned int port_status, reg_data, vbus;
enum usb_role usb_role = USB_ROLE_NONE; enum usb_role usb_role = USB_ROLE_NONE;
bool vbus_reg_enable = false;
int ret; int ret;
ret = regmap_read(info->regmap, PTN5150_REG_CC_STATUS, &reg_data); ret = regmap_read(info->regmap, PTN5150_REG_CC_STATUS, &reg_data);
@ -86,17 +121,14 @@ static void ptn5150_check_state(struct ptn5150_info *info)
switch (port_status) { switch (port_status) {
case PTN5150_DFP_ATTACHED: case PTN5150_DFP_ATTACHED:
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, false); 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); extcon_set_state_sync(info->edev, EXTCON_USB, true);
usb_role = USB_ROLE_DEVICE; usb_role = USB_ROLE_DEVICE;
break; break;
case PTN5150_UFP_ATTACHED: case PTN5150_UFP_ATTACHED:
extcon_set_state_sync(info->edev, EXTCON_USB, false); extcon_set_state_sync(info->edev, EXTCON_USB, false);
vbus = FIELD_GET(PTN5150_REG_CC_VBUS_DETECTION, reg_data); vbus = FIELD_GET(PTN5150_REG_CC_VBUS_DETECTION, reg_data);
if (vbus) if (!vbus)
gpiod_set_value_cansleep(info->vbus_gpiod, 0); vbus_reg_enable = true;
else
gpiod_set_value_cansleep(info->vbus_gpiod, 1);
extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true); extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true);
usb_role = USB_ROLE_HOST; usb_role = USB_ROLE_HOST;
@ -105,6 +137,11 @@ static void ptn5150_check_state(struct ptn5150_info *info)
break; break;
} }
if (vbus_reg_enable)
ptn5150_vbus_on(info);
else
ptn5150_vbus_off(info);
if (usb_role) { if (usb_role) {
ret = usb_role_switch_set_role(info->role_sw, usb_role); ret = usb_role_switch_set_role(info->role_sw, usb_role);
if (ret) if (ret)
@ -144,7 +181,7 @@ static void ptn5150_irq_work(struct work_struct *work)
EXTCON_USB_HOST, false); EXTCON_USB_HOST, false);
extcon_set_state_sync(info->edev, extcon_set_state_sync(info->edev,
EXTCON_USB, false); EXTCON_USB, false);
gpiod_set_value_cansleep(info->vbus_gpiod, 0); ptn5150_vbus_off(info);
ret = usb_role_switch_set_role(info->role_sw, ret = usb_role_switch_set_role(info->role_sw,
USB_ROLE_NONE); 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); mutex_init(&info->mutex);
INIT_WORK(&info->irq_work, ptn5150_irq_work); INIT_WORK(&info->irq_work, ptn5150_irq_work);

@ -1 +1 @@
Subproject commit 612ac8d4a9ce7b359342c6e89f5d08a1b02a1b87 Subproject commit 017c12dae556738cc3124ae65b64a80bbf70af6d