hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/power/supply/bq24190_charger.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Driver for the TI bq24190 battery charger.
34 *
45 * Author: Mark A. Greer <mgreer@animalcreek.com>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
96 */
107
118 #include <linux/module.h>
....@@ -21,6 +18,7 @@
2118 #include <linux/workqueue.h>
2219 #include <linux/gpio.h>
2320 #include <linux/i2c.h>
21
+#include <linux/extcon-provider.h>
2422
2523 #define BQ24190_MANUFACTURER "Texas Instruments"
2624
....@@ -43,6 +41,7 @@
4341 #define BQ24190_REG_POC_CHG_CONFIG_DISABLE 0x0
4442 #define BQ24190_REG_POC_CHG_CONFIG_CHARGE 0x1
4543 #define BQ24190_REG_POC_CHG_CONFIG_OTG 0x2
44
+#define BQ24190_REG_POC_CHG_CONFIG_OTG_ALT 0x3
4645 #define BQ24190_REG_POC_SYS_MIN_MASK (BIT(3) | BIT(2) | BIT(1))
4746 #define BQ24190_REG_POC_SYS_MIN_SHIFT 1
4847 #define BQ24190_REG_POC_SYS_MIN_MIN 3000
....@@ -142,7 +141,7 @@
142141 #define BQ24190_REG_VPRS_PN_MASK (BIT(5) | BIT(4) | BIT(3))
143142 #define BQ24190_REG_VPRS_PN_SHIFT 3
144143 #define BQ24190_REG_VPRS_PN_24190 0x4
145
-#define BQ24190_REG_VPRS_PN_24192 0x5 /* Also 24193 */
144
+#define BQ24190_REG_VPRS_PN_24192 0x5 /* Also 24193, 24196 */
146145 #define BQ24190_REG_VPRS_PN_24192I 0x3
147146 #define BQ24190_REG_VPRS_TS_PROFILE_MASK BIT(2)
148147 #define BQ24190_REG_VPRS_TS_PROFILE_SHIFT 2
....@@ -159,6 +158,7 @@
159158 struct bq24190_dev_info {
160159 struct i2c_client *client;
161160 struct device *dev;
161
+ struct extcon_dev *edev;
162162 struct power_supply *charger;
163163 struct power_supply *battery;
164164 struct delayed_work input_current_limit_work;
....@@ -172,6 +172,11 @@
172172 u8 f_reg;
173173 u8 ss_reg;
174174 u8 watchdog;
175
+};
176
+
177
+static const unsigned int bq24190_usb_extcon_cable[] = {
178
+ EXTCON_USB,
179
+ EXTCON_NONE,
175180 };
176181
177182 /*
....@@ -402,9 +407,7 @@
402407 static struct attribute *
403408 bq24190_sysfs_attrs[ARRAY_SIZE(bq24190_sysfs_field_tbl) + 1];
404409
405
-static const struct attribute_group bq24190_sysfs_attr_group = {
406
- .attrs = bq24190_sysfs_attrs,
407
-};
410
+ATTRIBUTE_GROUPS(bq24190_sysfs);
408411
409412 static void bq24190_sysfs_init_attrs(void)
410413 {
....@@ -481,8 +484,10 @@
481484 return ret;
482485
483486 ret = pm_runtime_get_sync(bdi->dev);
484
- if (ret < 0)
487
+ if (ret < 0) {
488
+ pm_runtime_put_noidle(bdi->dev);
485489 return ret;
490
+ }
486491
487492 ret = bq24190_write_mask(bdi, info->reg, info->mask, info->shift, v);
488493 if (ret)
....@@ -493,26 +498,6 @@
493498
494499 return count;
495500 }
496
-
497
-static int bq24190_sysfs_create_group(struct bq24190_dev_info *bdi)
498
-{
499
- bq24190_sysfs_init_attrs();
500
-
501
- return sysfs_create_group(&bdi->charger->dev.kobj,
502
- &bq24190_sysfs_attr_group);
503
-}
504
-
505
-static void bq24190_sysfs_remove_group(struct bq24190_dev_info *bdi)
506
-{
507
- sysfs_remove_group(&bdi->charger->dev.kobj, &bq24190_sysfs_attr_group);
508
-}
509
-#else
510
-static int bq24190_sysfs_create_group(struct bq24190_dev_info *bdi)
511
-{
512
- return 0;
513
-}
514
-
515
-static inline void bq24190_sysfs_remove_group(struct bq24190_dev_info *bdi) {}
516501 #endif
517502
518503 #ifdef CONFIG_REGULATOR
....@@ -568,7 +553,11 @@
568553 pm_runtime_mark_last_busy(bdi->dev);
569554 pm_runtime_put_autosuspend(bdi->dev);
570555
571
- return ret ? ret : val == BQ24190_REG_POC_CHG_CONFIG_OTG;
556
+ if (ret)
557
+ return ret;
558
+
559
+ return (val == BQ24190_REG_POC_CHG_CONFIG_OTG ||
560
+ val == BQ24190_REG_POC_CHG_CONFIG_OTG_ALT);
572561 }
573562
574563 static const struct regulator_ops bq24190_vbus_ops = {
....@@ -579,6 +568,7 @@
579568
580569 static const struct regulator_desc bq24190_vbus_desc = {
581570 .name = "usb_otg_vbus",
571
+ .of_match = "usb-otg-vbus",
582572 .type = REGULATOR_VOLTAGE,
583573 .owner = THIS_MODULE,
584574 .ops = &bq24190_vbus_ops,
....@@ -692,7 +682,7 @@
692682 * { .type = "bq24190", .addr = 0x6b, .properties = pe, .irq = irq };
693683 * struct i2c_adapter ad = { ... };
694684 * i2c_add_adapter(&ad);
695
- * i2c_new_device(&ad, &bi);
685
+ * i2c_new_client_device(&ad, &bi);
696686 */
697687 if (device_property_read_bool(bdi->dev, "disable-reset"))
698688 return 0;
....@@ -1537,6 +1527,20 @@
15371527 .property_is_writeable = bq24190_battery_property_is_writeable,
15381528 };
15391529
1530
+static int bq24190_configure_usb_otg(struct bq24190_dev_info *bdi, u8 ss_reg)
1531
+{
1532
+ bool otg_enabled;
1533
+ int ret;
1534
+
1535
+ otg_enabled = !!(ss_reg & BQ24190_REG_SS_VBUS_STAT_MASK);
1536
+ ret = extcon_set_state_sync(bdi->edev, EXTCON_USB, otg_enabled);
1537
+ if (ret < 0)
1538
+ dev_err(bdi->dev, "Can't set extcon state to %d: %d\n",
1539
+ otg_enabled, ret);
1540
+
1541
+ return ret;
1542
+}
1543
+
15401544 static void bq24190_check_status(struct bq24190_dev_info *bdi)
15411545 {
15421546 const u8 battery_mask_ss = BQ24190_REG_SS_CHRG_STAT_MASK;
....@@ -1606,8 +1610,10 @@
16061610 bdi->ss_reg = ss_reg;
16071611 }
16081612
1609
- if (alert_charger || alert_battery)
1613
+ if (alert_charger || alert_battery) {
16101614 power_supply_changed(bdi->charger);
1615
+ bq24190_configure_usb_otg(bdi, ss_reg);
1616
+ }
16111617 if (alert_battery && bdi->battery)
16121618 power_supply_changed(bdi->battery);
16131619
....@@ -1647,8 +1653,12 @@
16471653 if (ret < 0)
16481654 return ret;
16491655
1650
- if (v != BQ24190_REG_VPRS_PN_24190 &&
1651
- v != BQ24190_REG_VPRS_PN_24192I) {
1656
+ switch (v) {
1657
+ case BQ24190_REG_VPRS_PN_24190:
1658
+ case BQ24190_REG_VPRS_PN_24192:
1659
+ case BQ24190_REG_VPRS_PN_24192I:
1660
+ break;
1661
+ default:
16521662 dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v);
16531663 return -ENODEV;
16541664 }
....@@ -1704,7 +1714,7 @@
17041714 static int bq24190_probe(struct i2c_client *client,
17051715 const struct i2c_device_id *id)
17061716 {
1707
- struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
1717
+ struct i2c_adapter *adapter = client->adapter;
17081718 struct device *dev = &client->dev;
17091719 struct power_supply_config charger_cfg = {}, battery_cfg = {};
17101720 struct bq24190_dev_info *bdi;
....@@ -1737,6 +1747,14 @@
17371747 return -EINVAL;
17381748 }
17391749
1750
+ bdi->edev = devm_extcon_dev_allocate(dev, bq24190_usb_extcon_cable);
1751
+ if (IS_ERR(bdi->edev))
1752
+ return PTR_ERR(bdi->edev);
1753
+
1754
+ ret = devm_extcon_dev_register(dev, bdi->edev);
1755
+ if (ret < 0)
1756
+ return ret;
1757
+
17401758 pm_runtime_enable(dev);
17411759 pm_runtime_use_autosuspend(dev);
17421760 pm_runtime_set_autosuspend_delay(dev, 600);
....@@ -1745,6 +1763,11 @@
17451763 dev_err(dev, "pm_runtime_get failed: %i\n", ret);
17461764 goto out_pmrt;
17471765 }
1766
+
1767
+#ifdef CONFIG_SYSFS
1768
+ bq24190_sysfs_init_attrs();
1769
+ charger_cfg.attr_grp = bq24190_sysfs_groups;
1770
+#endif
17481771
17491772 charger_cfg.drv_data = bdi;
17501773 charger_cfg.of_node = dev->of_node;
....@@ -1783,11 +1806,9 @@
17831806 goto out_charger;
17841807 }
17851808
1786
- ret = bq24190_sysfs_create_group(bdi);
1787
- if (ret < 0) {
1788
- dev_err(dev, "Can't create sysfs entries\n");
1809
+ ret = bq24190_configure_usb_otg(bdi, bdi->ss_reg);
1810
+ if (ret < 0)
17891811 goto out_charger;
1790
- }
17911812
17921813 bdi->initialized = true;
17931814
....@@ -1797,12 +1818,12 @@
17971818 "bq24190-charger", bdi);
17981819 if (ret < 0) {
17991820 dev_err(dev, "Can't set up irq handler\n");
1800
- goto out_sysfs;
1821
+ goto out_charger;
18011822 }
18021823
18031824 ret = bq24190_register_vbus_regulator(bdi);
18041825 if (ret < 0)
1805
- goto out_sysfs;
1826
+ goto out_charger;
18061827
18071828 enable_irq_wake(client->irq);
18081829
....@@ -1810,9 +1831,6 @@
18101831 pm_runtime_put_autosuspend(dev);
18111832
18121833 return 0;
1813
-
1814
-out_sysfs:
1815
- bq24190_sysfs_remove_group(bdi);
18161834
18171835 out_charger:
18181836 if (!IS_ERR_OR_NULL(bdi->battery))
....@@ -1838,7 +1856,6 @@
18381856 }
18391857
18401858 bq24190_register_reset(bdi);
1841
- bq24190_sysfs_remove_group(bdi);
18421859 if (bdi->battery)
18431860 power_supply_unregister(bdi->battery);
18441861 power_supply_unregister(bdi->charger);
....@@ -1941,7 +1958,9 @@
19411958
19421959 static const struct i2c_device_id bq24190_i2c_ids[] = {
19431960 { "bq24190" },
1961
+ { "bq24192" },
19441962 { "bq24192i" },
1963
+ { "bq24196" },
19451964 { },
19461965 };
19471966 MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids);
....@@ -1949,7 +1968,9 @@
19491968 #ifdef CONFIG_OF
19501969 static const struct of_device_id bq24190_of_match[] = {
19511970 { .compatible = "ti,bq24190", },
1971
+ { .compatible = "ti,bq24192", },
19521972 { .compatible = "ti,bq24192i", },
1973
+ { .compatible = "ti,bq24196", },
19531974 { },
19541975 };
19551976 MODULE_DEVICE_TABLE(of, bq24190_of_match);