hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
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 {
....@@ -445,11 +448,9 @@
445448 if (!info)
446449 return -EINVAL;
447450
448
- ret = pm_runtime_get_sync(bdi->dev);
449
- if (ret < 0) {
450
- pm_runtime_put_noidle(bdi->dev);
451
+ ret = pm_runtime_resume_and_get(bdi->dev);
452
+ if (ret < 0)
451453 return ret;
452
- }
453454
454455 ret = bq24190_read_mask(bdi, info->reg, info->mask, info->shift, &v);
455456 if (ret)
....@@ -480,7 +481,7 @@
480481 if (ret < 0)
481482 return ret;
482483
483
- ret = pm_runtime_get_sync(bdi->dev);
484
+ ret = pm_runtime_resume_and_get(bdi->dev);
484485 if (ret < 0)
485486 return ret;
486487
....@@ -493,26 +494,6 @@
493494
494495 return count;
495496 }
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) {}
516497 #endif
517498
518499 #ifdef CONFIG_REGULATOR
....@@ -521,10 +502,9 @@
521502 struct bq24190_dev_info *bdi = rdev_get_drvdata(dev);
522503 int ret;
523504
524
- ret = pm_runtime_get_sync(bdi->dev);
505
+ ret = pm_runtime_resume_and_get(bdi->dev);
525506 if (ret < 0) {
526507 dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret);
527
- pm_runtime_put_noidle(bdi->dev);
528508 return ret;
529509 }
530510
....@@ -554,10 +534,9 @@
554534 int ret;
555535 u8 val;
556536
557
- ret = pm_runtime_get_sync(bdi->dev);
537
+ ret = pm_runtime_resume_and_get(bdi->dev);
558538 if (ret < 0) {
559539 dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret);
560
- pm_runtime_put_noidle(bdi->dev);
561540 return ret;
562541 }
563542
....@@ -568,7 +547,11 @@
568547 pm_runtime_mark_last_busy(bdi->dev);
569548 pm_runtime_put_autosuspend(bdi->dev);
570549
571
- return ret ? ret : val == BQ24190_REG_POC_CHG_CONFIG_OTG;
550
+ if (ret)
551
+ return ret;
552
+
553
+ return (val == BQ24190_REG_POC_CHG_CONFIG_OTG ||
554
+ val == BQ24190_REG_POC_CHG_CONFIG_OTG_ALT);
572555 }
573556
574557 static const struct regulator_ops bq24190_vbus_ops = {
....@@ -579,6 +562,7 @@
579562
580563 static const struct regulator_desc bq24190_vbus_desc = {
581564 .name = "usb_otg_vbus",
565
+ .of_match = "usb-otg-vbus",
582566 .type = REGULATOR_VOLTAGE,
583567 .owner = THIS_MODULE,
584568 .ops = &bq24190_vbus_ops,
....@@ -692,7 +676,7 @@
692676 * { .type = "bq24190", .addr = 0x6b, .properties = pe, .irq = irq };
693677 * struct i2c_adapter ad = { ... };
694678 * i2c_add_adapter(&ad);
695
- * i2c_new_device(&ad, &bi);
679
+ * i2c_new_client_device(&ad, &bi);
696680 */
697681 if (device_property_read_bool(bdi->dev, "disable-reset"))
698682 return 0;
....@@ -1093,11 +1077,9 @@
10931077
10941078 dev_dbg(bdi->dev, "prop: %d\n", psp);
10951079
1096
- ret = pm_runtime_get_sync(bdi->dev);
1097
- if (ret < 0) {
1098
- pm_runtime_put_noidle(bdi->dev);
1080
+ ret = pm_runtime_resume_and_get(bdi->dev);
1081
+ if (ret < 0)
10991082 return ret;
1100
- }
11011083
11021084 switch (psp) {
11031085 case POWER_SUPPLY_PROP_CHARGE_TYPE:
....@@ -1167,11 +1149,9 @@
11671149
11681150 dev_dbg(bdi->dev, "prop: %d\n", psp);
11691151
1170
- ret = pm_runtime_get_sync(bdi->dev);
1171
- if (ret < 0) {
1172
- pm_runtime_put_noidle(bdi->dev);
1152
+ ret = pm_runtime_resume_and_get(bdi->dev);
1153
+ if (ret < 0)
11731154 return ret;
1174
- }
11751155
11761156 switch (psp) {
11771157 case POWER_SUPPLY_PROP_ONLINE:
....@@ -1223,8 +1203,19 @@
12231203 struct bq24190_dev_info *bdi =
12241204 container_of(work, struct bq24190_dev_info,
12251205 input_current_limit_work.work);
1206
+ union power_supply_propval val;
1207
+ int ret;
12261208
1227
- power_supply_set_input_current_limit_from_supplier(bdi->charger);
1209
+ ret = power_supply_get_property_from_supplier(bdi->charger,
1210
+ POWER_SUPPLY_PROP_CURRENT_MAX,
1211
+ &val);
1212
+ if (ret)
1213
+ return;
1214
+
1215
+ bq24190_charger_set_property(bdi->charger,
1216
+ POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
1217
+ &val);
1218
+ power_supply_changed(bdi->charger);
12281219 }
12291220
12301221 /* Sync the input-current-limit with our parent supply (if we have one) */
....@@ -1430,11 +1421,9 @@
14301421 dev_warn(bdi->dev, "warning: /sys/class/power_supply/bq24190-battery is deprecated\n");
14311422 dev_dbg(bdi->dev, "prop: %d\n", psp);
14321423
1433
- ret = pm_runtime_get_sync(bdi->dev);
1434
- if (ret < 0) {
1435
- pm_runtime_put_noidle(bdi->dev);
1424
+ ret = pm_runtime_resume_and_get(bdi->dev);
1425
+ if (ret < 0)
14361426 return ret;
1437
- }
14381427
14391428 switch (psp) {
14401429 case POWER_SUPPLY_PROP_STATUS:
....@@ -1478,11 +1467,9 @@
14781467 dev_warn(bdi->dev, "warning: /sys/class/power_supply/bq24190-battery is deprecated\n");
14791468 dev_dbg(bdi->dev, "prop: %d\n", psp);
14801469
1481
- ret = pm_runtime_get_sync(bdi->dev);
1482
- if (ret < 0) {
1483
- pm_runtime_put_noidle(bdi->dev);
1470
+ ret = pm_runtime_resume_and_get(bdi->dev);
1471
+ if (ret < 0)
14841472 return ret;
1485
- }
14861473
14871474 switch (psp) {
14881475 case POWER_SUPPLY_PROP_ONLINE:
....@@ -1536,6 +1523,20 @@
15361523 .set_property = bq24190_battery_set_property,
15371524 .property_is_writeable = bq24190_battery_property_is_writeable,
15381525 };
1526
+
1527
+static int bq24190_configure_usb_otg(struct bq24190_dev_info *bdi, u8 ss_reg)
1528
+{
1529
+ bool otg_enabled;
1530
+ int ret;
1531
+
1532
+ otg_enabled = !!(ss_reg & BQ24190_REG_SS_VBUS_STAT_MASK);
1533
+ ret = extcon_set_state_sync(bdi->edev, EXTCON_USB, otg_enabled);
1534
+ if (ret < 0)
1535
+ dev_err(bdi->dev, "Can't set extcon state to %d: %d\n",
1536
+ otg_enabled, ret);
1537
+
1538
+ return ret;
1539
+}
15391540
15401541 static void bq24190_check_status(struct bq24190_dev_info *bdi)
15411542 {
....@@ -1606,8 +1607,10 @@
16061607 bdi->ss_reg = ss_reg;
16071608 }
16081609
1609
- if (alert_charger || alert_battery)
1610
+ if (alert_charger || alert_battery) {
16101611 power_supply_changed(bdi->charger);
1612
+ bq24190_configure_usb_otg(bdi, ss_reg);
1613
+ }
16111614 if (alert_battery && bdi->battery)
16121615 power_supply_changed(bdi->battery);
16131616
....@@ -1620,10 +1623,9 @@
16201623 int error;
16211624
16221625 bdi->irq_event = true;
1623
- error = pm_runtime_get_sync(bdi->dev);
1626
+ error = pm_runtime_resume_and_get(bdi->dev);
16241627 if (error < 0) {
16251628 dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);
1626
- pm_runtime_put_noidle(bdi->dev);
16271629 return IRQ_NONE;
16281630 }
16291631 bq24190_check_status(bdi);
....@@ -1647,8 +1649,12 @@
16471649 if (ret < 0)
16481650 return ret;
16491651
1650
- if (v != BQ24190_REG_VPRS_PN_24190 &&
1651
- v != BQ24190_REG_VPRS_PN_24192I) {
1652
+ switch (v) {
1653
+ case BQ24190_REG_VPRS_PN_24190:
1654
+ case BQ24190_REG_VPRS_PN_24192:
1655
+ case BQ24190_REG_VPRS_PN_24192I:
1656
+ break;
1657
+ default:
16521658 dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v);
16531659 return -ENODEV;
16541660 }
....@@ -1704,7 +1710,7 @@
17041710 static int bq24190_probe(struct i2c_client *client,
17051711 const struct i2c_device_id *id)
17061712 {
1707
- struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
1713
+ struct i2c_adapter *adapter = client->adapter;
17081714 struct device *dev = &client->dev;
17091715 struct power_supply_config charger_cfg = {}, battery_cfg = {};
17101716 struct bq24190_dev_info *bdi;
....@@ -1737,6 +1743,14 @@
17371743 return -EINVAL;
17381744 }
17391745
1746
+ bdi->edev = devm_extcon_dev_allocate(dev, bq24190_usb_extcon_cable);
1747
+ if (IS_ERR(bdi->edev))
1748
+ return PTR_ERR(bdi->edev);
1749
+
1750
+ ret = devm_extcon_dev_register(dev, bdi->edev);
1751
+ if (ret < 0)
1752
+ return ret;
1753
+
17401754 pm_runtime_enable(dev);
17411755 pm_runtime_use_autosuspend(dev);
17421756 pm_runtime_set_autosuspend_delay(dev, 600);
....@@ -1745,6 +1759,11 @@
17451759 dev_err(dev, "pm_runtime_get failed: %i\n", ret);
17461760 goto out_pmrt;
17471761 }
1762
+
1763
+#ifdef CONFIG_SYSFS
1764
+ bq24190_sysfs_init_attrs();
1765
+ charger_cfg.attr_grp = bq24190_sysfs_groups;
1766
+#endif
17481767
17491768 charger_cfg.drv_data = bdi;
17501769 charger_cfg.of_node = dev->of_node;
....@@ -1783,11 +1802,9 @@
17831802 goto out_charger;
17841803 }
17851804
1786
- ret = bq24190_sysfs_create_group(bdi);
1787
- if (ret < 0) {
1788
- dev_err(dev, "Can't create sysfs entries\n");
1805
+ ret = bq24190_configure_usb_otg(bdi, bdi->ss_reg);
1806
+ if (ret < 0)
17891807 goto out_charger;
1790
- }
17911808
17921809 bdi->initialized = true;
17931810
....@@ -1797,12 +1814,12 @@
17971814 "bq24190-charger", bdi);
17981815 if (ret < 0) {
17991816 dev_err(dev, "Can't set up irq handler\n");
1800
- goto out_sysfs;
1817
+ goto out_charger;
18011818 }
18021819
18031820 ret = bq24190_register_vbus_regulator(bdi);
18041821 if (ret < 0)
1805
- goto out_sysfs;
1822
+ goto out_charger;
18061823
18071824 enable_irq_wake(client->irq);
18081825
....@@ -1810,9 +1827,6 @@
18101827 pm_runtime_put_autosuspend(dev);
18111828
18121829 return 0;
1813
-
1814
-out_sysfs:
1815
- bq24190_sysfs_remove_group(bdi);
18161830
18171831 out_charger:
18181832 if (!IS_ERR_OR_NULL(bdi->battery))
....@@ -1831,14 +1845,12 @@
18311845 struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
18321846 int error;
18331847
1834
- error = pm_runtime_get_sync(bdi->dev);
1835
- if (error < 0) {
1848
+ cancel_delayed_work_sync(&bdi->input_current_limit_work);
1849
+ error = pm_runtime_resume_and_get(bdi->dev);
1850
+ if (error < 0)
18361851 dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);
1837
- pm_runtime_put_noidle(bdi->dev);
1838
- }
18391852
18401853 bq24190_register_reset(bdi);
1841
- bq24190_sysfs_remove_group(bdi);
18421854 if (bdi->battery)
18431855 power_supply_unregister(bdi->battery);
18441856 power_supply_unregister(bdi->charger);
....@@ -1885,11 +1897,9 @@
18851897 struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
18861898 int error;
18871899
1888
- error = pm_runtime_get_sync(bdi->dev);
1889
- if (error < 0) {
1900
+ error = pm_runtime_resume_and_get(bdi->dev);
1901
+ if (error < 0)
18901902 dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);
1891
- pm_runtime_put_noidle(bdi->dev);
1892
- }
18931903
18941904 bq24190_register_reset(bdi);
18951905
....@@ -1910,11 +1920,9 @@
19101920 bdi->f_reg = 0;
19111921 bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */
19121922
1913
- error = pm_runtime_get_sync(bdi->dev);
1914
- if (error < 0) {
1923
+ error = pm_runtime_resume_and_get(bdi->dev);
1924
+ if (error < 0)
19151925 dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);
1916
- pm_runtime_put_noidle(bdi->dev);
1917
- }
19181926
19191927 bq24190_register_reset(bdi);
19201928 bq24190_set_config(bdi);
....@@ -1941,7 +1949,9 @@
19411949
19421950 static const struct i2c_device_id bq24190_i2c_ids[] = {
19431951 { "bq24190" },
1952
+ { "bq24192" },
19441953 { "bq24192i" },
1954
+ { "bq24196" },
19451955 { },
19461956 };
19471957 MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids);
....@@ -1949,7 +1959,9 @@
19491959 #ifdef CONFIG_OF
19501960 static const struct of_device_id bq24190_of_match[] = {
19511961 { .compatible = "ti,bq24190", },
1962
+ { .compatible = "ti,bq24192", },
19521963 { .compatible = "ti,bq24192i", },
1964
+ { .compatible = "ti,bq24196", },
19531965 { },
19541966 };
19551967 MODULE_DEVICE_TABLE(of, bq24190_of_match);