aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPali Rohár <pali.rohar@gmail.com>2015-08-11 07:22:19 -0400
committerSebastian Reichel <sre@kernel.org>2015-08-21 10:46:38 -0400
commitb68c3161430a4c7c0a001e658188bfea6a2fe5bd (patch)
tree4b27f2cc3f0380211227c4a34b4889cfee384aea
parentb49d15d138aa4632f35a2db93dee775d920f3653 (diff)
bq2415x_charger: Allow to load and use driver even if notify device is not registered yet
Driver bq2415x_charger works also without notify power supply device for charger detection. But when charger detection is specified in DT, then bq2415x_charger refused to loaded with -EPROBE_DEFER. This patch rewrites code so that notify device for charger detection is checked when power supply event is received and not when registering power supply device. So this patch allows to use bq2415x_charger driver also when kernel is compiled without driver for notify power supply device. Now after this patch scheduled workqueue is called after INIT_DELAYED_WORK, so it also fix problem when scheduled workqueue was called before init. Signed-off-by: Pali Rohár <pali.rohar@gmail.com> Signed-off-by: Sebastian Reichel <sre@kernel.org>
-rw-r--r--drivers/power/bq2415x_charger.c143
1 files changed, 79 insertions, 64 deletions
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
index e98dcb661cc9..ec212b5be755 100644
--- a/drivers/power/bq2415x_charger.c
+++ b/drivers/power/bq2415x_charger.c
@@ -170,7 +170,7 @@ struct bq2415x_device {
170 struct power_supply *charger; 170 struct power_supply *charger;
171 struct power_supply_desc charger_desc; 171 struct power_supply_desc charger_desc;
172 struct delayed_work work; 172 struct delayed_work work;
173 struct power_supply *notify_psy; 173 struct device_node *notify_node;
174 struct notifier_block nb; 174 struct notifier_block nb;
175 enum bq2415x_mode reported_mode;/* mode reported by hook function */ 175 enum bq2415x_mode reported_mode;/* mode reported by hook function */
176 enum bq2415x_mode mode; /* currently configured mode */ 176 enum bq2415x_mode mode; /* currently configured mode */
@@ -792,22 +792,47 @@ static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode)
792 792
793} 793}
794 794
795static bool bq2415x_update_reported_mode(struct bq2415x_device *bq, int mA)
796{
797 enum bq2415x_mode mode;
798
799 if (mA == 0)
800 mode = BQ2415X_MODE_OFF;
801 else if (mA < 500)
802 mode = BQ2415X_MODE_NONE;
803 else if (mA < 1800)
804 mode = BQ2415X_MODE_HOST_CHARGER;
805 else
806 mode = BQ2415X_MODE_DEDICATED_CHARGER;
807
808 if (bq->reported_mode == mode)
809 return false;
810
811 bq->reported_mode = mode;
812 return true;
813}
814
795static int bq2415x_notifier_call(struct notifier_block *nb, 815static int bq2415x_notifier_call(struct notifier_block *nb,
796 unsigned long val, void *v) 816 unsigned long val, void *v)
797{ 817{
798 struct bq2415x_device *bq = 818 struct bq2415x_device *bq =
799 container_of(nb, struct bq2415x_device, nb); 819 container_of(nb, struct bq2415x_device, nb);
800 struct power_supply *psy = v; 820 struct power_supply *psy = v;
801 enum bq2415x_mode mode;
802 union power_supply_propval prop; 821 union power_supply_propval prop;
803 int ret; 822 int ret;
804 int mA;
805 823
806 if (val != PSY_EVENT_PROP_CHANGED) 824 if (val != PSY_EVENT_PROP_CHANGED)
807 return NOTIFY_OK; 825 return NOTIFY_OK;
808 826
809 if (psy != bq->notify_psy) 827 /* Ignore event if it was not send by notify_node/notify_device */
810 return NOTIFY_OK; 828 if (bq->notify_node) {
829 if (!psy->dev.parent ||
830 psy->dev.parent->of_node != bq->notify_node)
831 return NOTIFY_OK;
832 } else if (bq->init_data.notify_device) {
833 if (strcmp(psy->desc->name, bq->init_data.notify_device) != 0)
834 return NOTIFY_OK;
835 }
811 836
812 dev_dbg(bq->dev, "notifier call was called\n"); 837 dev_dbg(bq->dev, "notifier call was called\n");
813 838
@@ -816,22 +841,9 @@ static int bq2415x_notifier_call(struct notifier_block *nb,
816 if (ret != 0) 841 if (ret != 0)
817 return NOTIFY_OK; 842 return NOTIFY_OK;
818 843
819 mA = prop.intval; 844 if (!bq2415x_update_reported_mode(bq, prop.intval))
820
821 if (mA == 0)
822 mode = BQ2415X_MODE_OFF;
823 else if (mA < 500)
824 mode = BQ2415X_MODE_NONE;
825 else if (mA < 1800)
826 mode = BQ2415X_MODE_HOST_CHARGER;
827 else
828 mode = BQ2415X_MODE_DEDICATED_CHARGER;
829
830 if (bq->reported_mode == mode)
831 return NOTIFY_OK; 845 return NOTIFY_OK;
832 846
833 bq->reported_mode = mode;
834
835 /* if automode is not enabled do not tell about reported_mode */ 847 /* if automode is not enabled do not tell about reported_mode */
836 if (bq->automode < 1) 848 if (bq->automode < 1)
837 return NOTIFY_OK; 849 return NOTIFY_OK;
@@ -1536,6 +1548,8 @@ static int bq2415x_probe(struct i2c_client *client,
1536 struct device_node *np = client->dev.of_node; 1548 struct device_node *np = client->dev.of_node;
1537 struct bq2415x_platform_data *pdata = client->dev.platform_data; 1549 struct bq2415x_platform_data *pdata = client->dev.platform_data;
1538 const struct acpi_device_id *acpi_id = NULL; 1550 const struct acpi_device_id *acpi_id = NULL;
1551 struct power_supply *notify_psy = NULL;
1552 union power_supply_propval prop;
1539 1553
1540 if (!np && !pdata && !ACPI_HANDLE(&client->dev)) { 1554 if (!np && !pdata && !ACPI_HANDLE(&client->dev)) {
1541 dev_err(&client->dev, "Neither devicetree, nor platform data, nor ACPI support\n"); 1555 dev_err(&client->dev, "Neither devicetree, nor platform data, nor ACPI support\n");
@@ -1569,25 +1583,6 @@ static int bq2415x_probe(struct i2c_client *client,
1569 goto error_2; 1583 goto error_2;
1570 } 1584 }
1571 1585
1572 if (np) {
1573 bq->notify_psy = power_supply_get_by_phandle(np,
1574 "ti,usb-charger-detection");
1575
1576 if (IS_ERR(bq->notify_psy)) {
1577 dev_info(&client->dev,
1578 "no 'ti,usb-charger-detection' property (err=%ld)\n",
1579 PTR_ERR(bq->notify_psy));
1580 bq->notify_psy = NULL;
1581 } else if (!bq->notify_psy) {
1582 ret = -EPROBE_DEFER;
1583 goto error_2;
1584 }
1585 } else if (pdata && pdata->notify_device) {
1586 bq->notify_psy = power_supply_get_by_name(pdata->notify_device);
1587 } else {
1588 bq->notify_psy = NULL;
1589 }
1590
1591 i2c_set_clientdata(client, bq); 1586 i2c_set_clientdata(client, bq);
1592 1587
1593 bq->id = num; 1588 bq->id = num;
@@ -1607,32 +1602,35 @@ static int bq2415x_probe(struct i2c_client *client,
1607 "ti,current-limit", 1602 "ti,current-limit",
1608 &bq->init_data.current_limit); 1603 &bq->init_data.current_limit);
1609 if (ret) 1604 if (ret)
1610 goto error_3; 1605 goto error_2;
1611 ret = device_property_read_u32(bq->dev, 1606 ret = device_property_read_u32(bq->dev,
1612 "ti,weak-battery-voltage", 1607 "ti,weak-battery-voltage",
1613 &bq->init_data.weak_battery_voltage); 1608 &bq->init_data.weak_battery_voltage);
1614 if (ret) 1609 if (ret)
1615 goto error_3; 1610 goto error_2;
1616 ret = device_property_read_u32(bq->dev, 1611 ret = device_property_read_u32(bq->dev,
1617 "ti,battery-regulation-voltage", 1612 "ti,battery-regulation-voltage",
1618 &bq->init_data.battery_regulation_voltage); 1613 &bq->init_data.battery_regulation_voltage);
1619 if (ret) 1614 if (ret)
1620 goto error_3; 1615 goto error_2;
1621 ret = device_property_read_u32(bq->dev, 1616 ret = device_property_read_u32(bq->dev,
1622 "ti,charge-current", 1617 "ti,charge-current",
1623 &bq->init_data.charge_current); 1618 &bq->init_data.charge_current);
1624 if (ret) 1619 if (ret)
1625 goto error_3; 1620 goto error_2;
1626 ret = device_property_read_u32(bq->dev, 1621 ret = device_property_read_u32(bq->dev,
1627 "ti,termination-current", 1622 "ti,termination-current",
1628 &bq->init_data.termination_current); 1623 &bq->init_data.termination_current);
1629 if (ret) 1624 if (ret)
1630 goto error_3; 1625 goto error_2;
1631 ret = device_property_read_u32(bq->dev, 1626 ret = device_property_read_u32(bq->dev,
1632 "ti,resistor-sense", 1627 "ti,resistor-sense",
1633 &bq->init_data.resistor_sense); 1628 &bq->init_data.resistor_sense);
1634 if (ret) 1629 if (ret)
1635 goto error_3; 1630 goto error_2;
1631 if (np)
1632 bq->notify_node = of_parse_phandle(np,
1633 "ti,usb-charger-detection", 0);
1636 } else { 1634 } else {
1637 memcpy(&bq->init_data, pdata, sizeof(bq->init_data)); 1635 memcpy(&bq->init_data, pdata, sizeof(bq->init_data));
1638 } 1636 }
@@ -1642,56 +1640,72 @@ static int bq2415x_probe(struct i2c_client *client,
1642 ret = bq2415x_power_supply_init(bq); 1640 ret = bq2415x_power_supply_init(bq);
1643 if (ret) { 1641 if (ret) {
1644 dev_err(bq->dev, "failed to register power supply: %d\n", ret); 1642 dev_err(bq->dev, "failed to register power supply: %d\n", ret);
1645 goto error_3; 1643 goto error_2;
1646 } 1644 }
1647 1645
1648 ret = bq2415x_sysfs_init(bq); 1646 ret = bq2415x_sysfs_init(bq);
1649 if (ret) { 1647 if (ret) {
1650 dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret); 1648 dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret);
1651 goto error_4; 1649 goto error_3;
1652 } 1650 }
1653 1651
1654 ret = bq2415x_set_defaults(bq); 1652 ret = bq2415x_set_defaults(bq);
1655 if (ret) { 1653 if (ret) {
1656 dev_err(bq->dev, "failed to set default values: %d\n", ret); 1654 dev_err(bq->dev, "failed to set default values: %d\n", ret);
1657 goto error_5; 1655 goto error_4;
1658 } 1656 }
1659 1657
1660 if (bq->notify_psy) { 1658 if (bq->notify_node || bq->init_data.notify_device) {
1661 bq->nb.notifier_call = bq2415x_notifier_call; 1659 bq->nb.notifier_call = bq2415x_notifier_call;
1662 ret = power_supply_reg_notifier(&bq->nb); 1660 ret = power_supply_reg_notifier(&bq->nb);
1663 if (ret) { 1661 if (ret) {
1664 dev_err(bq->dev, "failed to reg notifier: %d\n", ret); 1662 dev_err(bq->dev, "failed to reg notifier: %d\n", ret);
1665 goto error_6; 1663 goto error_4;
1666 } 1664 }
1667 1665
1668 /* Query for initial reported_mode and set it */
1669 bq2415x_notifier_call(&bq->nb, PSY_EVENT_PROP_CHANGED,
1670 bq->notify_psy);
1671 bq2415x_set_mode(bq, bq->reported_mode);
1672
1673 bq->automode = 1; 1666 bq->automode = 1;
1674 dev_info(bq->dev, "automode enabled\n"); 1667 dev_info(bq->dev, "automode supported, waiting for events\n");
1675 } else { 1668 } else {
1676 bq->automode = -1; 1669 bq->automode = -1;
1677 dev_info(bq->dev, "automode not supported\n"); 1670 dev_info(bq->dev, "automode not supported\n");
1678 } 1671 }
1679 1672
1673 /* Query for initial reported_mode and set it */
1674 if (bq->nb.notifier_call) {
1675 if (np) {
1676 notify_psy = power_supply_get_by_phandle(np,
1677 "ti,usb-charger-detection");
1678 if (IS_ERR(notify_psy))
1679 notify_psy = NULL;
1680 } else if (bq->init_data.notify_device) {
1681 notify_psy = power_supply_get_by_name(
1682 bq->init_data.notify_device);
1683 }
1684 }
1685 if (notify_psy) {
1686 ret = power_supply_get_property(notify_psy,
1687 POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
1688 power_supply_put(notify_psy);
1689
1690 if (ret == 0) {
1691 bq2415x_update_reported_mode(bq, prop.intval);
1692 bq2415x_set_mode(bq, bq->reported_mode);
1693 }
1694 }
1695
1680 INIT_DELAYED_WORK(&bq->work, bq2415x_timer_work); 1696 INIT_DELAYED_WORK(&bq->work, bq2415x_timer_work);
1681 bq2415x_set_autotimer(bq, 1); 1697 bq2415x_set_autotimer(bq, 1);
1682 1698
1683 dev_info(bq->dev, "driver registered\n"); 1699 dev_info(bq->dev, "driver registered\n");
1684 return 0; 1700 return 0;
1685 1701
1686error_6:
1687error_5:
1688 bq2415x_sysfs_exit(bq);
1689error_4: 1702error_4:
1690 bq2415x_power_supply_exit(bq); 1703 bq2415x_sysfs_exit(bq);
1691error_3: 1704error_3:
1692 if (bq->notify_psy) 1705 bq2415x_power_supply_exit(bq);
1693 power_supply_put(bq->notify_psy);
1694error_2: 1706error_2:
1707 if (bq->notify_node)
1708 of_node_put(bq->notify_node);
1695 kfree(name); 1709 kfree(name);
1696error_1: 1710error_1:
1697 mutex_lock(&bq2415x_id_mutex); 1711 mutex_lock(&bq2415x_id_mutex);
@@ -1707,10 +1721,11 @@ static int bq2415x_remove(struct i2c_client *client)
1707{ 1721{
1708 struct bq2415x_device *bq = i2c_get_clientdata(client); 1722 struct bq2415x_device *bq = i2c_get_clientdata(client);
1709 1723
1710 if (bq->notify_psy) { 1724 if (bq->nb.notifier_call)
1711 power_supply_unreg_notifier(&bq->nb); 1725 power_supply_unreg_notifier(&bq->nb);
1712 power_supply_put(bq->notify_psy); 1726
1713 } 1727 if (bq->notify_node)
1728 of_node_put(bq->notify_node);
1714 1729
1715 bq2415x_sysfs_exit(bq); 1730 bq2415x_sysfs_exit(bq);
1716 bq2415x_power_supply_exit(bq); 1731 bq2415x_power_supply_exit(bq);