| .. | .. |
|---|
| 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); |
|---|