power: supply: bq24190_charger: Support usb role switching

Change-Id: Ia1e650f15ae55bb0972612b378d093a20d8a8a98
This commit is contained in:
Aaron Kling
2025-06-10 02:45:03 -05:00
committed by Thomas Makin
parent e24dd8dceb
commit 412e4e172e

View File

@@ -17,6 +17,7 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/extcon-provider.h> #include <linux/extcon-provider.h>
#include <linux/usb/role.h>
#define BQ24190_MANUFACTURER "Texas Instruments" #define BQ24190_MANUFACTURER "Texas Instruments"
@@ -242,6 +243,7 @@ struct bq24190_dev_info {
u8 ss_reg; u8 ss_reg;
u8 watchdog; u8 watchdog;
const struct bq24190_chip_info *info; const struct bq24190_chip_info *info;
struct usb_role_switch *role_sw;
}; };
struct bq24190_chip_info { struct bq24190_chip_info {
@@ -1823,6 +1825,7 @@ static const struct power_supply_desc bq24190_battery_desc = {
static int bq24190_configure_usb_otg(struct bq24190_dev_info *bdi, u8 ss_reg) static int bq24190_configure_usb_otg(struct bq24190_dev_info *bdi, u8 ss_reg)
{ {
bool otg_enabled; bool otg_enabled;
enum usb_role usb_role;
int ret; int ret;
otg_enabled = !!(ss_reg & BQ24190_REG_SS_VBUS_STAT_MASK); otg_enabled = !!(ss_reg & BQ24190_REG_SS_VBUS_STAT_MASK);
@@ -1831,6 +1834,11 @@ static int bq24190_configure_usb_otg(struct bq24190_dev_info *bdi, u8 ss_reg)
dev_err(bdi->dev, "Can't set extcon state to %d: %d\n", dev_err(bdi->dev, "Can't set extcon state to %d: %d\n",
otg_enabled, ret); otg_enabled, ret);
if (bdi->role_sw) {
usb_role = otg_enabled ? USB_ROLE_DEVICE : USB_ROLE_NONE;
usb_role_switch_set_role(bdi->role_sw, usb_role);
}
return ret; return ret;
} }
@@ -2128,6 +2136,7 @@ static int bq24190_probe(struct i2c_client *client)
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct power_supply_config charger_cfg = {}, battery_cfg = {}; struct power_supply_config charger_cfg = {}, battery_cfg = {};
struct bq24190_dev_info *bdi; struct bq24190_dev_info *bdi;
struct fwnode_handle *connector;
int ret; int ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -2167,6 +2176,16 @@ static int bq24190_probe(struct i2c_client *client)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* The usb connector is optional */
connector = device_get_named_child_node(dev, "connector");
if (connector) {
bdi->role_sw = fwnode_usb_role_switch_get(connector);
if (IS_ERR(bdi->role_sw)) {
ret = PTR_ERR(bdi->role_sw);
goto out_put;
}
}
pm_runtime_enable(dev); pm_runtime_enable(dev);
pm_runtime_use_autosuspend(dev); pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 600); pm_runtime_set_autosuspend_delay(dev, 600);
@@ -2257,6 +2276,10 @@ out_pmrt:
pm_runtime_put_sync(dev); pm_runtime_put_sync(dev);
pm_runtime_dont_use_autosuspend(dev); pm_runtime_dont_use_autosuspend(dev);
pm_runtime_disable(dev); pm_runtime_disable(dev);
out_put:
if (connector)
fwnode_handle_put(connector);
return ret; return ret;
} }
@@ -2265,6 +2288,9 @@ static void bq24190_remove(struct i2c_client *client)
struct bq24190_dev_info *bdi = i2c_get_clientdata(client); struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
int error; int error;
if (bdi->role_sw)
usb_role_switch_put(bdi->role_sw);
cancel_delayed_work_sync(&bdi->input_current_limit_work); cancel_delayed_work_sync(&bdi->input_current_limit_work);
error = pm_runtime_resume_and_get(bdi->dev); error = pm_runtime_resume_and_get(bdi->dev);
if (error < 0) if (error < 0)