diff options
author | Hans de Goede <hdegoede@redhat.com> | 2021-12-28 20:01:41 +0300 |
---|---|---|
committer | Chanwoo Choi <cw00.choi@samsung.com> | 2022-05-13 11:03:40 +0300 |
commit | 4c018cc87e5592f5bb8160e6fd42059778e1b0dc (patch) | |
tree | fad46a0eb0992ff997294509c6b5a1ba8af9b325 /drivers/extcon | |
parent | c26aef6d396b015d89a10a3b433dc9d7f759bb9f (diff) | |
download | linux-4c018cc87e5592f5bb8160e6fd42059778e1b0dc.tar.xz |
extcon: int3496: Add support for controlling Vbus through a regulator
On some boards the 5V vboost-regulator for powering devices connected to
the micro USB connector is not controlled through a GPIO. This happens
for example when the 5V vboost-regulator is integrated into the charger IC
and controlled over I2C.
Add support for controlling the 5V vboost-regulator through the regulator
framework for such boards.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Diffstat (limited to 'drivers/extcon')
-rw-r--r-- | drivers/extcon/extcon-intel-int3496.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/extcon/extcon-intel-int3496.c b/drivers/extcon/extcon-intel-int3496.c index 0830076d8c05..ded1a85a5549 100644 --- a/drivers/extcon/extcon-intel-int3496.c +++ b/drivers/extcon/extcon-intel-int3496.c @@ -17,6 +17,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/regulator/consumer.h> #define INT3496_GPIO_USB_ID 0 #define INT3496_GPIO_VBUS_EN 1 @@ -30,7 +31,9 @@ struct int3496_data { struct gpio_desc *gpio_usb_id; struct gpio_desc *gpio_vbus_en; struct gpio_desc *gpio_usb_mux; + struct regulator *vbus_boost; int usb_id_irq; + bool vbus_boost_enabled; }; static const unsigned int int3496_cable[] = { @@ -53,6 +56,27 @@ static const struct acpi_gpio_mapping acpi_int3496_default_gpios[] = { { }, }; +static void int3496_set_vbus_boost(struct int3496_data *data, bool enable) +{ + int ret; + + if (IS_ERR_OR_NULL(data->vbus_boost)) + return; + + if (data->vbus_boost_enabled == enable) + return; + + if (enable) + ret = regulator_enable(data->vbus_boost); + else + ret = regulator_disable(data->vbus_boost); + + if (ret == 0) + data->vbus_boost_enabled = enable; + else + dev_err(data->dev, "Error updating Vbus boost regulator: %d\n", ret); +} + static void int3496_do_usb_id(struct work_struct *work) { struct int3496_data *data = @@ -71,6 +95,8 @@ static void int3496_do_usb_id(struct work_struct *work) if (!IS_ERR(data->gpio_vbus_en)) gpiod_direction_output(data->gpio_vbus_en, !id); + else + int3496_set_vbus_boost(data, !id); extcon_set_state_sync(data->edev, EXTCON_USB_HOST, !id); } @@ -123,8 +149,10 @@ static int int3496_probe(struct platform_device *pdev) } data->gpio_vbus_en = devm_gpiod_get(dev, "vbus", GPIOD_ASIS); - if (IS_ERR(data->gpio_vbus_en)) + if (IS_ERR(data->gpio_vbus_en)) { dev_dbg(dev, "can't request VBUS EN GPIO\n"); + data->vbus_boost = devm_regulator_get_optional(dev, "vbus"); + } data->gpio_usb_mux = devm_gpiod_get(dev, "mux", GPIOD_ASIS); if (IS_ERR(data->gpio_usb_mux)) |