power: supply: bq24190_charger: Support usb role switching

Change-Id: Ia1e650f15ae55bb0972612b378d093a20d8a8a98
This commit is contained in:
Aaron Kling committed 2026-08-22 16:55:13 -05:00
1 parent 87a623ba79
commit 249af64b93
1 file changed
+25
+25
View File
@@ -18,6 +18,7 @@
#include <linux/workqueue.h>
#include <linux/i2c.h>
#include <linux/extcon-provider.h>
#include <linux/usb/role.h>
#define BQ24190_MANUFACTURER "Texas Instruments"
@@ -245,6 +246,7 @@ struct bq24190_dev_info {
u8 ss_reg;
u8 watchdog;
const struct bq24190_chip_info *info;
struct usb_role_switch *role_sw;
};
struct bq24190_chip_info {
@@ -1829,6 +1831,7 @@ static const struct power_supply_desc bq24190_battery_desc = {
static int bq24190_configure_usb_otg(struct bq24190_dev_info *bdi, u8 ss_reg)
{
bool otg_enabled;
enum usb_role usb_role;
int ret;
otg_enabled = !!(ss_reg & BQ24190_REG_SS_VBUS_STAT_MASK);
@@ -1837,6 +1840,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",
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;
}
@@ -2147,6 +2155,7 @@ static int bq24190_probe(struct i2c_client *client)
struct device *dev = &client->dev;
struct power_supply_config charger_cfg = {}, battery_cfg = {};
struct bq24190_dev_info *bdi;
struct fwnode_handle *ep, *remote;
int ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -2189,6 +2198,19 @@ static int bq24190_probe(struct i2c_client *client)
if (ret < 0)
return ret;
/* Role switch is optional */
ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0);
if (ep) {
remote = fwnode_graph_get_remote_endpoint(ep);
if (remote) {
bdi->role_sw = fwnode_usb_role_switch_get(remote);
if (IS_ERR(bdi->role_sw)) {
ret = PTR_ERR(bdi->role_sw);
return dev_err_probe(dev, ret, "USB role switch handle not found\n");
}
}
}
pm_runtime_enable(dev);
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, 600);
@@ -2286,6 +2308,9 @@ static void bq24190_remove(struct i2c_client *client)
struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
int error;
if (bdi->role_sw)
usb_role_switch_put(bdi->role_sw);
error = pm_runtime_resume_and_get(bdi->dev);
if (error < 0)
dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);