diff options
Diffstat (limited to 'drivers/power/supply/bq24190_charger.c')
-rw-r--r-- | drivers/power/supply/bq24190_charger.c | 91 |
1 files changed, 54 insertions, 37 deletions
diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index b58df04d03b3..cc0dfdc9e85a 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -21,6 +21,7 @@ #include <linux/workqueue.h> #include <linux/gpio.h> #include <linux/i2c.h> +#include <linux/extcon-provider.h> #define BQ24190_MANUFACTURER "Texas Instruments" @@ -142,7 +143,7 @@ #define BQ24190_REG_VPRS_PN_MASK (BIT(5) | BIT(4) | BIT(3)) #define BQ24190_REG_VPRS_PN_SHIFT 3 #define BQ24190_REG_VPRS_PN_24190 0x4 -#define BQ24190_REG_VPRS_PN_24192 0x5 /* Also 24193 */ +#define BQ24190_REG_VPRS_PN_24192 0x5 /* Also 24193, 24196 */ #define BQ24190_REG_VPRS_PN_24192I 0x3 #define BQ24190_REG_VPRS_TS_PROFILE_MASK BIT(2) #define BQ24190_REG_VPRS_TS_PROFILE_SHIFT 2 @@ -159,6 +160,7 @@ struct bq24190_dev_info { struct i2c_client *client; struct device *dev; + struct extcon_dev *edev; struct power_supply *charger; struct power_supply *battery; struct delayed_work input_current_limit_work; @@ -174,6 +176,11 @@ struct bq24190_dev_info { u8 watchdog; }; +static const unsigned int bq24190_usb_extcon_cable[] = { + EXTCON_USB, + EXTCON_NONE, +}; + /* * The tables below provide a 2-way mapping for the value that goes in * the register field and the real-world value that it represents. @@ -402,9 +409,7 @@ static struct bq24190_sysfs_field_info bq24190_sysfs_field_tbl[] = { static struct attribute * bq24190_sysfs_attrs[ARRAY_SIZE(bq24190_sysfs_field_tbl) + 1]; -static const struct attribute_group bq24190_sysfs_attr_group = { - .attrs = bq24190_sysfs_attrs, -}; +ATTRIBUTE_GROUPS(bq24190_sysfs); static void bq24190_sysfs_init_attrs(void) { @@ -491,26 +496,6 @@ static ssize_t bq24190_sysfs_store(struct device *dev, return count; } - -static int bq24190_sysfs_create_group(struct bq24190_dev_info *bdi) -{ - bq24190_sysfs_init_attrs(); - - return sysfs_create_group(&bdi->charger->dev.kobj, - &bq24190_sysfs_attr_group); -} - -static void bq24190_sysfs_remove_group(struct bq24190_dev_info *bdi) -{ - sysfs_remove_group(&bdi->charger->dev.kobj, &bq24190_sysfs_attr_group); -} -#else -static int bq24190_sysfs_create_group(struct bq24190_dev_info *bdi) -{ - return 0; -} - -static inline void bq24190_sysfs_remove_group(struct bq24190_dev_info *bdi) {} #endif #ifdef CONFIG_REGULATOR @@ -577,6 +562,7 @@ static const struct regulator_ops bq24190_vbus_ops = { static const struct regulator_desc bq24190_vbus_desc = { .name = "usb_otg_vbus", + .of_match = "usb-otg-vbus", .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, .ops = &bq24190_vbus_ops, @@ -1527,6 +1513,20 @@ static const struct power_supply_desc bq24190_battery_desc = { .property_is_writeable = bq24190_battery_property_is_writeable, }; +static int bq24190_configure_usb_otg(struct bq24190_dev_info *bdi, u8 ss_reg) +{ + bool otg_enabled; + int ret; + + otg_enabled = !!(ss_reg & BQ24190_REG_SS_VBUS_STAT_MASK); + ret = extcon_set_state_sync(bdi->edev, EXTCON_USB, otg_enabled); + if (ret < 0) + dev_err(bdi->dev, "Can't set extcon state to %d: %d\n", + otg_enabled, ret); + + return ret; +} + static void bq24190_check_status(struct bq24190_dev_info *bdi) { const u8 battery_mask_ss = BQ24190_REG_SS_CHRG_STAT_MASK; @@ -1596,8 +1596,10 @@ static void bq24190_check_status(struct bq24190_dev_info *bdi) bdi->ss_reg = ss_reg; } - if (alert_charger || alert_battery) + if (alert_charger || alert_battery) { power_supply_changed(bdi->charger); + bq24190_configure_usb_otg(bdi, ss_reg); + } if (alert_battery && bdi->battery) power_supply_changed(bdi->battery); @@ -1637,8 +1639,12 @@ static int bq24190_hw_init(struct bq24190_dev_info *bdi) if (ret < 0) return ret; - if (v != BQ24190_REG_VPRS_PN_24190 && - v != BQ24190_REG_VPRS_PN_24192I) { + switch (v) { + case BQ24190_REG_VPRS_PN_24190: + case BQ24190_REG_VPRS_PN_24192: + case BQ24190_REG_VPRS_PN_24192I: + break; + default: dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v); return -ENODEV; } @@ -1727,6 +1733,14 @@ static int bq24190_probe(struct i2c_client *client, return -EINVAL; } + bdi->edev = devm_extcon_dev_allocate(dev, bq24190_usb_extcon_cable); + if (IS_ERR(bdi->edev)) + return PTR_ERR(bdi->edev); + + ret = devm_extcon_dev_register(dev, bdi->edev); + if (ret < 0) + return ret; + pm_runtime_enable(dev); pm_runtime_use_autosuspend(dev); pm_runtime_set_autosuspend_delay(dev, 600); @@ -1736,6 +1750,11 @@ static int bq24190_probe(struct i2c_client *client, goto out_pmrt; } +#ifdef CONFIG_SYSFS + bq24190_sysfs_init_attrs(); + charger_cfg.attr_grp = bq24190_sysfs_groups; +#endif + charger_cfg.drv_data = bdi; charger_cfg.of_node = dev->of_node; charger_cfg.supplied_to = bq24190_charger_supplied_to; @@ -1773,11 +1792,9 @@ static int bq24190_probe(struct i2c_client *client, goto out_charger; } - ret = bq24190_sysfs_create_group(bdi); - if (ret < 0) { - dev_err(dev, "Can't create sysfs entries\n"); + ret = bq24190_configure_usb_otg(bdi, bdi->ss_reg); + if (ret < 0) goto out_charger; - } bdi->initialized = true; @@ -1787,12 +1804,12 @@ static int bq24190_probe(struct i2c_client *client, "bq24190-charger", bdi); if (ret < 0) { dev_err(dev, "Can't set up irq handler\n"); - goto out_sysfs; + goto out_charger; } ret = bq24190_register_vbus_regulator(bdi); if (ret < 0) - goto out_sysfs; + goto out_charger; enable_irq_wake(client->irq); @@ -1801,9 +1818,6 @@ static int bq24190_probe(struct i2c_client *client, return 0; -out_sysfs: - bq24190_sysfs_remove_group(bdi); - out_charger: if (!IS_ERR_OR_NULL(bdi->battery)) power_supply_unregister(bdi->battery); @@ -1828,7 +1842,6 @@ static int bq24190_remove(struct i2c_client *client) } bq24190_register_reset(bdi); - bq24190_sysfs_remove_group(bdi); if (bdi->battery) power_supply_unregister(bdi->battery); power_supply_unregister(bdi->charger); @@ -1931,7 +1944,9 @@ static const struct dev_pm_ops bq24190_pm_ops = { static const struct i2c_device_id bq24190_i2c_ids[] = { { "bq24190" }, + { "bq24192" }, { "bq24192i" }, + { "bq24196" }, { }, }; MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids); @@ -1939,7 +1954,9 @@ MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids); #ifdef CONFIG_OF static const struct of_device_id bq24190_of_match[] = { { .compatible = "ti,bq24190", }, + { .compatible = "ti,bq24192", }, { .compatible = "ti,bq24192i", }, + { .compatible = "ti,bq24196", }, { }, }; MODULE_DEVICE_TABLE(of, bq24190_of_match); |