.. | .. |
---|
1018 | 1018 | return ret; |
---|
1019 | 1019 | |
---|
1020 | 1020 | mutex_lock(&bq27xxx_list_lock); |
---|
1021 | | - list_for_each_entry(di, &bq27xxx_battery_devices, list) { |
---|
1022 | | - cancel_delayed_work_sync(&di->work); |
---|
1023 | | - schedule_delayed_work(&di->work, 0); |
---|
1024 | | - } |
---|
| 1021 | + list_for_each_entry(di, &bq27xxx_battery_devices, list) |
---|
| 1022 | + mod_delayed_work(system_wq, &di->work, 0); |
---|
1025 | 1023 | mutex_unlock(&bq27xxx_list_lock); |
---|
1026 | 1024 | |
---|
1027 | 1025 | return ret; |
---|
.. | .. |
---|
1507 | 1505 | */ |
---|
1508 | 1506 | static inline int bq27xxx_battery_read_nac(struct bq27xxx_device_info *di) |
---|
1509 | 1507 | { |
---|
1510 | | - int flags; |
---|
1511 | | - |
---|
1512 | | - if (di->opts & BQ27XXX_O_ZERO) { |
---|
1513 | | - flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, true); |
---|
1514 | | - if (flags >= 0 && (flags & BQ27000_FLAG_CI)) |
---|
1515 | | - return -ENODATA; |
---|
1516 | | - } |
---|
1517 | | - |
---|
1518 | 1508 | return bq27xxx_battery_read_charge(di, BQ27XXX_REG_NAC); |
---|
1519 | 1509 | } |
---|
1520 | 1510 | |
---|
.. | .. |
---|
1668 | 1658 | return flags & (BQ27XXX_FLAG_SOC1 | BQ27XXX_FLAG_SOCF); |
---|
1669 | 1659 | } |
---|
1670 | 1660 | |
---|
| 1661 | +/* |
---|
| 1662 | + * Returns true if reported battery capacity is inaccurate |
---|
| 1663 | + */ |
---|
| 1664 | +static bool bq27xxx_battery_capacity_inaccurate(struct bq27xxx_device_info *di, |
---|
| 1665 | + u16 flags) |
---|
| 1666 | +{ |
---|
| 1667 | + if (di->opts & BQ27XXX_O_HAS_CI) |
---|
| 1668 | + return (flags & BQ27000_FLAG_CI); |
---|
| 1669 | + else |
---|
| 1670 | + return false; |
---|
| 1671 | +} |
---|
| 1672 | + |
---|
1671 | 1673 | static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di) |
---|
1672 | 1674 | { |
---|
1673 | 1675 | /* Unlikely but important to return first */ |
---|
.. | .. |
---|
1677 | 1679 | return POWER_SUPPLY_HEALTH_COLD; |
---|
1678 | 1680 | if (unlikely(bq27xxx_battery_dead(di, di->cache.flags))) |
---|
1679 | 1681 | return POWER_SUPPLY_HEALTH_DEAD; |
---|
| 1682 | + if (unlikely(bq27xxx_battery_capacity_inaccurate(di, di->cache.flags))) |
---|
| 1683 | + return POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED; |
---|
1680 | 1684 | |
---|
1681 | 1685 | return POWER_SUPPLY_HEALTH_GOOD; |
---|
1682 | 1686 | } |
---|
1683 | 1687 | |
---|
1684 | | -void bq27xxx_battery_update(struct bq27xxx_device_info *di) |
---|
| 1688 | +static bool bq27xxx_battery_is_full(struct bq27xxx_device_info *di, int flags) |
---|
1685 | 1689 | { |
---|
| 1690 | + if (di->opts & BQ27XXX_O_ZERO) |
---|
| 1691 | + return (flags & BQ27000_FLAG_FC); |
---|
| 1692 | + else if (di->opts & BQ27Z561_O_BITS) |
---|
| 1693 | + return (flags & BQ27Z561_FLAG_FC); |
---|
| 1694 | + else |
---|
| 1695 | + return (flags & BQ27XXX_FLAG_FC); |
---|
| 1696 | +} |
---|
| 1697 | + |
---|
| 1698 | +/* |
---|
| 1699 | + * Return the battery average current in µA and the status |
---|
| 1700 | + * Note that current can be negative signed as well |
---|
| 1701 | + * Or 0 if something fails. |
---|
| 1702 | + */ |
---|
| 1703 | +static int bq27xxx_battery_current_and_status( |
---|
| 1704 | + struct bq27xxx_device_info *di, |
---|
| 1705 | + union power_supply_propval *val_curr, |
---|
| 1706 | + union power_supply_propval *val_status, |
---|
| 1707 | + struct bq27xxx_reg_cache *cache) |
---|
| 1708 | +{ |
---|
| 1709 | + bool single_flags = (di->opts & BQ27XXX_O_ZERO); |
---|
| 1710 | + int curr; |
---|
| 1711 | + int flags; |
---|
| 1712 | + |
---|
| 1713 | + curr = bq27xxx_read(di, BQ27XXX_REG_AI, false); |
---|
| 1714 | + if (curr < 0) { |
---|
| 1715 | + dev_err(di->dev, "error reading current\n"); |
---|
| 1716 | + return curr; |
---|
| 1717 | + } |
---|
| 1718 | + |
---|
| 1719 | + if (cache) { |
---|
| 1720 | + flags = cache->flags; |
---|
| 1721 | + } else { |
---|
| 1722 | + flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, single_flags); |
---|
| 1723 | + if (flags < 0) { |
---|
| 1724 | + dev_err(di->dev, "error reading flags\n"); |
---|
| 1725 | + return flags; |
---|
| 1726 | + } |
---|
| 1727 | + } |
---|
| 1728 | + |
---|
| 1729 | + if (di->opts & BQ27XXX_O_ZERO) { |
---|
| 1730 | + if (!(flags & BQ27000_FLAG_CHGS)) { |
---|
| 1731 | + dev_dbg(di->dev, "negative current!\n"); |
---|
| 1732 | + curr = -curr; |
---|
| 1733 | + } |
---|
| 1734 | + |
---|
| 1735 | + curr = curr * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; |
---|
| 1736 | + } else { |
---|
| 1737 | + /* Other gauges return signed value */ |
---|
| 1738 | + curr = (int)((s16)curr) * 1000; |
---|
| 1739 | + } |
---|
| 1740 | + |
---|
| 1741 | + if (val_curr) |
---|
| 1742 | + val_curr->intval = curr; |
---|
| 1743 | + |
---|
| 1744 | + if (val_status) { |
---|
| 1745 | + if (curr > 0) { |
---|
| 1746 | + val_status->intval = POWER_SUPPLY_STATUS_CHARGING; |
---|
| 1747 | + } else if (curr < 0) { |
---|
| 1748 | + val_status->intval = POWER_SUPPLY_STATUS_DISCHARGING; |
---|
| 1749 | + } else { |
---|
| 1750 | + if (bq27xxx_battery_is_full(di, flags)) |
---|
| 1751 | + val_status->intval = POWER_SUPPLY_STATUS_FULL; |
---|
| 1752 | + else |
---|
| 1753 | + val_status->intval = |
---|
| 1754 | + POWER_SUPPLY_STATUS_NOT_CHARGING; |
---|
| 1755 | + } |
---|
| 1756 | + } |
---|
| 1757 | + |
---|
| 1758 | + return 0; |
---|
| 1759 | +} |
---|
| 1760 | + |
---|
| 1761 | +static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di) |
---|
| 1762 | +{ |
---|
| 1763 | + union power_supply_propval status = di->last_status; |
---|
1686 | 1764 | struct bq27xxx_reg_cache cache = {0, }; |
---|
1687 | | - bool has_ci_flag = di->opts & BQ27XXX_O_HAS_CI; |
---|
1688 | 1765 | bool has_singe_flag = di->opts & BQ27XXX_O_ZERO; |
---|
1689 | 1766 | |
---|
1690 | 1767 | cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag); |
---|
.. | .. |
---|
1692 | 1769 | cache.flags = -1; /* read error */ |
---|
1693 | 1770 | if (cache.flags >= 0) { |
---|
1694 | 1771 | cache.temperature = bq27xxx_battery_read_temperature(di); |
---|
1695 | | - if (has_ci_flag && (cache.flags & BQ27000_FLAG_CI)) { |
---|
1696 | | - dev_info_once(di->dev, "battery is not calibrated! ignoring capacity values\n"); |
---|
1697 | | - cache.capacity = -ENODATA; |
---|
1698 | | - cache.energy = -ENODATA; |
---|
1699 | | - cache.time_to_empty = -ENODATA; |
---|
1700 | | - cache.time_to_empty_avg = -ENODATA; |
---|
1701 | | - cache.time_to_full = -ENODATA; |
---|
1702 | | - cache.charge_full = -ENODATA; |
---|
1703 | | - cache.health = -ENODATA; |
---|
1704 | | - } else { |
---|
1705 | | - if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR) |
---|
1706 | | - cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE); |
---|
1707 | | - if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR) |
---|
1708 | | - cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP); |
---|
1709 | | - if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR) |
---|
1710 | | - cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF); |
---|
| 1772 | + if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR) |
---|
| 1773 | + cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE); |
---|
| 1774 | + if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR) |
---|
| 1775 | + cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP); |
---|
| 1776 | + if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR) |
---|
| 1777 | + cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF); |
---|
1711 | 1778 | |
---|
1712 | | - cache.charge_full = bq27xxx_battery_read_fcc(di); |
---|
1713 | | - cache.capacity = bq27xxx_battery_read_soc(di); |
---|
1714 | | - if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR) |
---|
1715 | | - cache.energy = bq27xxx_battery_read_energy(di); |
---|
1716 | | - di->cache.flags = cache.flags; |
---|
1717 | | - cache.health = bq27xxx_battery_read_health(di); |
---|
1718 | | - } |
---|
| 1779 | + cache.charge_full = bq27xxx_battery_read_fcc(di); |
---|
| 1780 | + cache.capacity = bq27xxx_battery_read_soc(di); |
---|
| 1781 | + if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR) |
---|
| 1782 | + cache.energy = bq27xxx_battery_read_energy(di); |
---|
| 1783 | + di->cache.flags = cache.flags; |
---|
| 1784 | + cache.health = bq27xxx_battery_read_health(di); |
---|
1719 | 1785 | if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR) |
---|
1720 | 1786 | cache.cycle_count = bq27xxx_battery_read_cyct(di); |
---|
| 1787 | + |
---|
| 1788 | + /* |
---|
| 1789 | + * On gauges with signed current reporting the current must be |
---|
| 1790 | + * checked to detect charging <-> discharging status changes. |
---|
| 1791 | + */ |
---|
| 1792 | + if (!(di->opts & BQ27XXX_O_ZERO)) |
---|
| 1793 | + bq27xxx_battery_current_and_status(di, NULL, &status, &cache); |
---|
1721 | 1794 | |
---|
1722 | 1795 | /* We only have to read charge design full once */ |
---|
1723 | 1796 | if (di->charge_design_full <= 0) |
---|
.. | .. |
---|
1725 | 1798 | } |
---|
1726 | 1799 | |
---|
1727 | 1800 | if ((di->cache.capacity != cache.capacity) || |
---|
1728 | | - (di->cache.flags != cache.flags)) |
---|
| 1801 | + (di->cache.flags != cache.flags) || |
---|
| 1802 | + (di->last_status.intval != status.intval)) { |
---|
| 1803 | + di->last_status.intval = status.intval; |
---|
1729 | 1804 | power_supply_changed(di->bat); |
---|
| 1805 | + } |
---|
1730 | 1806 | |
---|
1731 | 1807 | if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) |
---|
1732 | 1808 | di->cache = cache; |
---|
1733 | 1809 | |
---|
1734 | 1810 | di->last_update = jiffies; |
---|
| 1811 | + |
---|
| 1812 | + if (!di->removed && poll_interval > 0) |
---|
| 1813 | + mod_delayed_work(system_wq, &di->work, poll_interval * HZ); |
---|
| 1814 | +} |
---|
| 1815 | + |
---|
| 1816 | +void bq27xxx_battery_update(struct bq27xxx_device_info *di) |
---|
| 1817 | +{ |
---|
| 1818 | + mutex_lock(&di->lock); |
---|
| 1819 | + bq27xxx_battery_update_unlocked(di); |
---|
| 1820 | + mutex_unlock(&di->lock); |
---|
1735 | 1821 | } |
---|
1736 | 1822 | EXPORT_SYMBOL_GPL(bq27xxx_battery_update); |
---|
1737 | 1823 | |
---|
.. | .. |
---|
1742 | 1828 | work.work); |
---|
1743 | 1829 | |
---|
1744 | 1830 | bq27xxx_battery_update(di); |
---|
1745 | | - |
---|
1746 | | - if (poll_interval > 0) |
---|
1747 | | - schedule_delayed_work(&di->work, poll_interval * HZ); |
---|
1748 | | -} |
---|
1749 | | - |
---|
1750 | | -/* |
---|
1751 | | - * Return the battery average current in µA |
---|
1752 | | - * Note that current can be negative signed as well |
---|
1753 | | - * Or 0 if something fails. |
---|
1754 | | - */ |
---|
1755 | | -static int bq27xxx_battery_current(struct bq27xxx_device_info *di, |
---|
1756 | | - union power_supply_propval *val) |
---|
1757 | | -{ |
---|
1758 | | - int curr; |
---|
1759 | | - int flags; |
---|
1760 | | - |
---|
1761 | | - curr = bq27xxx_read(di, BQ27XXX_REG_AI, false); |
---|
1762 | | - if (curr < 0) { |
---|
1763 | | - dev_err(di->dev, "error reading current\n"); |
---|
1764 | | - return curr; |
---|
1765 | | - } |
---|
1766 | | - |
---|
1767 | | - if (di->opts & BQ27XXX_O_ZERO) { |
---|
1768 | | - flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, true); |
---|
1769 | | - if (flags & BQ27000_FLAG_CHGS) { |
---|
1770 | | - dev_dbg(di->dev, "negative current!\n"); |
---|
1771 | | - curr = -curr; |
---|
1772 | | - } |
---|
1773 | | - |
---|
1774 | | - val->intval = curr * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; |
---|
1775 | | - } else { |
---|
1776 | | - /* Other gauges return signed value */ |
---|
1777 | | - val->intval = (int)((s16)curr) * 1000; |
---|
1778 | | - } |
---|
1779 | | - |
---|
1780 | | - return 0; |
---|
1781 | 1831 | } |
---|
1782 | 1832 | |
---|
1783 | 1833 | /* |
---|
.. | .. |
---|
1802 | 1852 | else |
---|
1803 | 1853 | /* Other gauges return a signed value in units of 10mW */ |
---|
1804 | 1854 | val->intval = (int)((s16)power) * 10000; |
---|
1805 | | - |
---|
1806 | | - return 0; |
---|
1807 | | -} |
---|
1808 | | - |
---|
1809 | | -static int bq27xxx_battery_status(struct bq27xxx_device_info *di, |
---|
1810 | | - union power_supply_propval *val) |
---|
1811 | | -{ |
---|
1812 | | - int status; |
---|
1813 | | - |
---|
1814 | | - if (di->opts & BQ27XXX_O_ZERO) { |
---|
1815 | | - if (di->cache.flags & BQ27000_FLAG_FC) |
---|
1816 | | - status = POWER_SUPPLY_STATUS_FULL; |
---|
1817 | | - else if (di->cache.flags & BQ27000_FLAG_CHGS) |
---|
1818 | | - status = POWER_SUPPLY_STATUS_CHARGING; |
---|
1819 | | - else |
---|
1820 | | - status = POWER_SUPPLY_STATUS_DISCHARGING; |
---|
1821 | | - } else if (di->opts & BQ27Z561_O_BITS) { |
---|
1822 | | - if (di->cache.flags & BQ27Z561_FLAG_FC) |
---|
1823 | | - status = POWER_SUPPLY_STATUS_FULL; |
---|
1824 | | - else if (di->cache.flags & BQ27Z561_FLAG_DIS_CH) |
---|
1825 | | - status = POWER_SUPPLY_STATUS_DISCHARGING; |
---|
1826 | | - else |
---|
1827 | | - status = POWER_SUPPLY_STATUS_CHARGING; |
---|
1828 | | - } else { |
---|
1829 | | - if (di->cache.flags & BQ27XXX_FLAG_FC) |
---|
1830 | | - status = POWER_SUPPLY_STATUS_FULL; |
---|
1831 | | - else if (di->cache.flags & BQ27XXX_FLAG_DSC) |
---|
1832 | | - status = POWER_SUPPLY_STATUS_DISCHARGING; |
---|
1833 | | - else |
---|
1834 | | - status = POWER_SUPPLY_STATUS_CHARGING; |
---|
1835 | | - } |
---|
1836 | | - |
---|
1837 | | - if ((status == POWER_SUPPLY_STATUS_DISCHARGING) && |
---|
1838 | | - (power_supply_am_i_supplied(di->bat) > 0)) |
---|
1839 | | - status = POWER_SUPPLY_STATUS_NOT_CHARGING; |
---|
1840 | | - |
---|
1841 | | - val->intval = status; |
---|
1842 | 1855 | |
---|
1843 | 1856 | return 0; |
---|
1844 | 1857 | } |
---|
.. | .. |
---|
1919 | 1932 | struct bq27xxx_device_info *di = power_supply_get_drvdata(psy); |
---|
1920 | 1933 | |
---|
1921 | 1934 | mutex_lock(&di->lock); |
---|
1922 | | - if (time_is_before_jiffies(di->last_update + 5 * HZ)) { |
---|
1923 | | - cancel_delayed_work_sync(&di->work); |
---|
1924 | | - bq27xxx_battery_poll(&di->work.work); |
---|
1925 | | - } |
---|
| 1935 | + if (time_is_before_jiffies(di->last_update + 5 * HZ)) |
---|
| 1936 | + bq27xxx_battery_update_unlocked(di); |
---|
1926 | 1937 | mutex_unlock(&di->lock); |
---|
1927 | 1938 | |
---|
1928 | 1939 | if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0) |
---|
.. | .. |
---|
1930 | 1941 | |
---|
1931 | 1942 | switch (psp) { |
---|
1932 | 1943 | case POWER_SUPPLY_PROP_STATUS: |
---|
1933 | | - ret = bq27xxx_battery_status(di, val); |
---|
| 1944 | + ret = bq27xxx_battery_current_and_status(di, NULL, val, NULL); |
---|
1934 | 1945 | break; |
---|
1935 | 1946 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
---|
1936 | 1947 | ret = bq27xxx_battery_voltage(di, val); |
---|
.. | .. |
---|
1939 | 1950 | val->intval = di->cache.flags < 0 ? 0 : 1; |
---|
1940 | 1951 | break; |
---|
1941 | 1952 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
---|
1942 | | - ret = bq27xxx_battery_current(di, val); |
---|
| 1953 | + ret = bq27xxx_battery_current_and_status(di, val, NULL, NULL); |
---|
1943 | 1954 | break; |
---|
1944 | 1955 | case POWER_SUPPLY_PROP_CAPACITY: |
---|
1945 | 1956 | ret = bq27xxx_simple_value(di->cache.capacity, val); |
---|
.. | .. |
---|
2009 | 2020 | { |
---|
2010 | 2021 | struct bq27xxx_device_info *di = power_supply_get_drvdata(psy); |
---|
2011 | 2022 | |
---|
2012 | | - cancel_delayed_work_sync(&di->work); |
---|
2013 | | - schedule_delayed_work(&di->work, 0); |
---|
| 2023 | + /* After charger plug in/out wait 0.5s for things to stabilize */ |
---|
| 2024 | + mod_delayed_work(system_wq, &di->work, HZ / 2); |
---|
2014 | 2025 | } |
---|
2015 | 2026 | |
---|
2016 | 2027 | int bq27xxx_battery_setup(struct bq27xxx_device_info *di) |
---|
.. | .. |
---|
2058 | 2069 | |
---|
2059 | 2070 | void bq27xxx_battery_teardown(struct bq27xxx_device_info *di) |
---|
2060 | 2071 | { |
---|
2061 | | - /* |
---|
2062 | | - * power_supply_unregister call bq27xxx_battery_get_property which |
---|
2063 | | - * call bq27xxx_battery_poll. |
---|
2064 | | - * Make sure that bq27xxx_battery_poll will not call |
---|
2065 | | - * schedule_delayed_work again after unregister (which cause OOPS). |
---|
2066 | | - */ |
---|
2067 | | - poll_interval = 0; |
---|
2068 | | - |
---|
2069 | | - cancel_delayed_work_sync(&di->work); |
---|
2070 | | - |
---|
2071 | | - power_supply_unregister(di->bat); |
---|
2072 | | - |
---|
2073 | 2072 | mutex_lock(&bq27xxx_list_lock); |
---|
2074 | 2073 | list_del(&di->list); |
---|
2075 | 2074 | mutex_unlock(&bq27xxx_list_lock); |
---|
2076 | 2075 | |
---|
| 2076 | + /* Set removed to avoid bq27xxx_battery_update() re-queuing the work */ |
---|
| 2077 | + mutex_lock(&di->lock); |
---|
| 2078 | + di->removed = true; |
---|
| 2079 | + mutex_unlock(&di->lock); |
---|
| 2080 | + |
---|
| 2081 | + cancel_delayed_work_sync(&di->work); |
---|
| 2082 | + |
---|
| 2083 | + power_supply_unregister(di->bat); |
---|
2077 | 2084 | mutex_destroy(&di->lock); |
---|
2078 | 2085 | } |
---|
2079 | 2086 | EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown); |
---|