18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * BQ27xxx battery driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it> 68c2ecf20Sopenharmony_ci * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it> 78c2ecf20Sopenharmony_ci * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de> 88c2ecf20Sopenharmony_ci * Copyright (C) 2011 Pali Rohár <pali@kernel.org> 98c2ecf20Sopenharmony_ci * Copyright (C) 2017 Liam Breck <kernel@networkimprov.net> 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Datasheets: 148c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27000 158c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27200 168c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27010 178c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27210 188c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27500 198c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27510-g1 208c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27510-g2 218c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27510-g3 228c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27520-g1 238c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27520-g2 248c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27520-g3 258c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27520-g4 268c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27530-g1 278c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27531-g1 288c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27541-g1 298c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27542-g1 308c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27546-g1 318c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27742-g1 328c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27545-g1 338c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27421-g1 348c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27425-g1 358c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27426 368c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27411-g1 378c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27441-g1 388c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27621-g1 398c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq27z561 408c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq28z610 418c2ecf20Sopenharmony_ci * https://www.ti.com/product/bq34z100-g1 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#include <linux/device.h> 458c2ecf20Sopenharmony_ci#include <linux/module.h> 468c2ecf20Sopenharmony_ci#include <linux/mutex.h> 478c2ecf20Sopenharmony_ci#include <linux/param.h> 488c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 498c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 508c2ecf20Sopenharmony_ci#include <linux/delay.h> 518c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 528c2ecf20Sopenharmony_ci#include <linux/power_supply.h> 538c2ecf20Sopenharmony_ci#include <linux/slab.h> 548c2ecf20Sopenharmony_ci#include <linux/of.h> 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#include <linux/power/bq27xxx_battery.h> 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#define BQ27XXX_MANUFACTURER "Texas Instruments" 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/* BQ27XXX Flags */ 618c2ecf20Sopenharmony_ci#define BQ27XXX_FLAG_DSC BIT(0) 628c2ecf20Sopenharmony_ci#define BQ27XXX_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */ 638c2ecf20Sopenharmony_ci#define BQ27XXX_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */ 648c2ecf20Sopenharmony_ci#define BQ27XXX_FLAG_CFGUP BIT(4) 658c2ecf20Sopenharmony_ci#define BQ27XXX_FLAG_FC BIT(9) 668c2ecf20Sopenharmony_ci#define BQ27XXX_FLAG_OTD BIT(14) 678c2ecf20Sopenharmony_ci#define BQ27XXX_FLAG_OTC BIT(15) 688c2ecf20Sopenharmony_ci#define BQ27XXX_FLAG_UT BIT(14) 698c2ecf20Sopenharmony_ci#define BQ27XXX_FLAG_OT BIT(15) 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/* BQ27000 has different layout for Flags register */ 728c2ecf20Sopenharmony_ci#define BQ27000_FLAG_EDVF BIT(0) /* Final End-of-Discharge-Voltage flag */ 738c2ecf20Sopenharmony_ci#define BQ27000_FLAG_EDV1 BIT(1) /* First End-of-Discharge-Voltage flag */ 748c2ecf20Sopenharmony_ci#define BQ27000_FLAG_CI BIT(4) /* Capacity Inaccurate flag */ 758c2ecf20Sopenharmony_ci#define BQ27000_FLAG_FC BIT(5) 768c2ecf20Sopenharmony_ci#define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */ 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci/* BQ27Z561 has different layout for Flags register */ 798c2ecf20Sopenharmony_ci#define BQ27Z561_FLAG_FDC BIT(4) /* Battery fully discharged */ 808c2ecf20Sopenharmony_ci#define BQ27Z561_FLAG_FC BIT(5) /* Battery fully charged */ 818c2ecf20Sopenharmony_ci#define BQ27Z561_FLAG_DIS_CH BIT(6) /* Battery is discharging */ 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* control register params */ 848c2ecf20Sopenharmony_ci#define BQ27XXX_SEALED 0x20 858c2ecf20Sopenharmony_ci#define BQ27XXX_SET_CFGUPDATE 0x13 868c2ecf20Sopenharmony_ci#define BQ27XXX_SOFT_RESET 0x42 878c2ecf20Sopenharmony_ci#define BQ27XXX_RESET 0x41 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci#define BQ27XXX_RS (20) /* Resistor sense mOhm */ 908c2ecf20Sopenharmony_ci#define BQ27XXX_POWER_CONSTANT (29200) /* 29.2 µV^2 * 1000 */ 918c2ecf20Sopenharmony_ci#define BQ27XXX_CURRENT_CONSTANT (3570) /* 3.57 µV * 1000 */ 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci#define INVALID_REG_ADDR 0xff 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* 968c2ecf20Sopenharmony_ci * bq27xxx_reg_index - Register names 978c2ecf20Sopenharmony_ci * 988c2ecf20Sopenharmony_ci * These are indexes into a device's register mapping array. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cienum bq27xxx_reg_index { 1028c2ecf20Sopenharmony_ci BQ27XXX_REG_CTRL = 0, /* Control */ 1038c2ecf20Sopenharmony_ci BQ27XXX_REG_TEMP, /* Temperature */ 1048c2ecf20Sopenharmony_ci BQ27XXX_REG_INT_TEMP, /* Internal Temperature */ 1058c2ecf20Sopenharmony_ci BQ27XXX_REG_VOLT, /* Voltage */ 1068c2ecf20Sopenharmony_ci BQ27XXX_REG_AI, /* Average Current */ 1078c2ecf20Sopenharmony_ci BQ27XXX_REG_FLAGS, /* Flags */ 1088c2ecf20Sopenharmony_ci BQ27XXX_REG_TTE, /* Time-to-Empty */ 1098c2ecf20Sopenharmony_ci BQ27XXX_REG_TTF, /* Time-to-Full */ 1108c2ecf20Sopenharmony_ci BQ27XXX_REG_TTES, /* Time-to-Empty Standby */ 1118c2ecf20Sopenharmony_ci BQ27XXX_REG_TTECP, /* Time-to-Empty at Constant Power */ 1128c2ecf20Sopenharmony_ci BQ27XXX_REG_NAC, /* Nominal Available Capacity */ 1138c2ecf20Sopenharmony_ci BQ27XXX_REG_FCC, /* Full Charge Capacity */ 1148c2ecf20Sopenharmony_ci BQ27XXX_REG_CYCT, /* Cycle Count */ 1158c2ecf20Sopenharmony_ci BQ27XXX_REG_AE, /* Available Energy */ 1168c2ecf20Sopenharmony_ci BQ27XXX_REG_SOC, /* State-of-Charge */ 1178c2ecf20Sopenharmony_ci BQ27XXX_REG_DCAP, /* Design Capacity */ 1188c2ecf20Sopenharmony_ci BQ27XXX_REG_AP, /* Average Power */ 1198c2ecf20Sopenharmony_ci BQ27XXX_DM_CTRL, /* Block Data Control */ 1208c2ecf20Sopenharmony_ci BQ27XXX_DM_CLASS, /* Data Class */ 1218c2ecf20Sopenharmony_ci BQ27XXX_DM_BLOCK, /* Data Block */ 1228c2ecf20Sopenharmony_ci BQ27XXX_DM_DATA, /* Block Data */ 1238c2ecf20Sopenharmony_ci BQ27XXX_DM_CKSUM, /* Block Data Checksum */ 1248c2ecf20Sopenharmony_ci BQ27XXX_REG_MAX, /* sentinel */ 1258c2ecf20Sopenharmony_ci}; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci#define BQ27XXX_DM_REG_ROWS \ 1288c2ecf20Sopenharmony_ci [BQ27XXX_DM_CTRL] = 0x61, \ 1298c2ecf20Sopenharmony_ci [BQ27XXX_DM_CLASS] = 0x3e, \ 1308c2ecf20Sopenharmony_ci [BQ27XXX_DM_BLOCK] = 0x3f, \ 1318c2ecf20Sopenharmony_ci [BQ27XXX_DM_DATA] = 0x40, \ 1328c2ecf20Sopenharmony_ci [BQ27XXX_DM_CKSUM] = 0x60 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci/* Register mappings */ 1358c2ecf20Sopenharmony_cistatic u8 1368c2ecf20Sopenharmony_ci bq27000_regs[BQ27XXX_REG_MAX] = { 1378c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 1388c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 1398c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 1408c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 1418c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 1428c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 1438c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 1448c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 1458c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 1468c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = 0x26, 1478c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 1488c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 1498c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 1508c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 1518c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x0b, 1528c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x76, 1538c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 1548c2ecf20Sopenharmony_ci [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR, 1558c2ecf20Sopenharmony_ci [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR, 1568c2ecf20Sopenharmony_ci [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR, 1578c2ecf20Sopenharmony_ci [BQ27XXX_DM_DATA] = INVALID_REG_ADDR, 1588c2ecf20Sopenharmony_ci [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR, 1598c2ecf20Sopenharmony_ci }, 1608c2ecf20Sopenharmony_ci bq27010_regs[BQ27XXX_REG_MAX] = { 1618c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 1628c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 1638c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 1648c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 1658c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 1668c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 1678c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 1688c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 1698c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 1708c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = 0x26, 1718c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 1728c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 1738c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 1748c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 1758c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x0b, 1768c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x76, 1778c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = INVALID_REG_ADDR, 1788c2ecf20Sopenharmony_ci [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR, 1798c2ecf20Sopenharmony_ci [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR, 1808c2ecf20Sopenharmony_ci [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR, 1818c2ecf20Sopenharmony_ci [BQ27XXX_DM_DATA] = INVALID_REG_ADDR, 1828c2ecf20Sopenharmony_ci [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR, 1838c2ecf20Sopenharmony_ci }, 1848c2ecf20Sopenharmony_ci bq2750x_regs[BQ27XXX_REG_MAX] = { 1858c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 1868c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 1878c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x28, 1888c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 1898c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 1908c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 1918c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 1928c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 1938c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1a, 1948c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 1958c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 1968c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 1978c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 1988c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 1998c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 2008c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 2018c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = INVALID_REG_ADDR, 2028c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 2038c2ecf20Sopenharmony_ci }, 2048c2ecf20Sopenharmony_ci#define bq2751x_regs bq27510g3_regs 2058c2ecf20Sopenharmony_ci#define bq2752x_regs bq27510g3_regs 2068c2ecf20Sopenharmony_ci bq27500_regs[BQ27XXX_REG_MAX] = { 2078c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 2088c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 2098c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 2108c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 2118c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 2128c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 2138c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 2148c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 2158c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 2168c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = 0x26, 2178c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 2188c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 2198c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 2208c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 2218c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 2228c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 2238c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 2248c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 2258c2ecf20Sopenharmony_ci }, 2268c2ecf20Sopenharmony_ci#define bq27510g1_regs bq27500_regs 2278c2ecf20Sopenharmony_ci#define bq27510g2_regs bq27500_regs 2288c2ecf20Sopenharmony_ci bq27510g3_regs[BQ27XXX_REG_MAX] = { 2298c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 2308c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 2318c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x28, 2328c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 2338c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 2348c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 2358c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 2368c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 2378c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1a, 2388c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 2398c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 2408c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 2418c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x1e, 2428c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 2438c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x20, 2448c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x2e, 2458c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = INVALID_REG_ADDR, 2468c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 2478c2ecf20Sopenharmony_ci }, 2488c2ecf20Sopenharmony_ci bq27520g1_regs[BQ27XXX_REG_MAX] = { 2498c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 2508c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 2518c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 2528c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 2538c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 2548c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 2558c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 2568c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 2578c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 2588c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = 0x26, 2598c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 2608c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 2618c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = INVALID_REG_ADDR, 2628c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 2638c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 2648c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 2658c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 2668c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 2678c2ecf20Sopenharmony_ci }, 2688c2ecf20Sopenharmony_ci bq27520g2_regs[BQ27XXX_REG_MAX] = { 2698c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 2708c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 2718c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x36, 2728c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 2738c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 2748c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 2758c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 2768c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 2778c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 2788c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = 0x26, 2798c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 2808c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 2818c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 2828c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 2838c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 2848c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 2858c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 2868c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 2878c2ecf20Sopenharmony_ci }, 2888c2ecf20Sopenharmony_ci bq27520g3_regs[BQ27XXX_REG_MAX] = { 2898c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 2908c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 2918c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x36, 2928c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 2938c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 2948c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 2958c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 2968c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 2978c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 2988c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = 0x26, 2998c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 3008c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 3018c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 3028c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 3038c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 3048c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 3058c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 3068c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 3078c2ecf20Sopenharmony_ci }, 3088c2ecf20Sopenharmony_ci bq27520g4_regs[BQ27XXX_REG_MAX] = { 3098c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 3108c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 3118c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x28, 3128c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 3138c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 3148c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 3158c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 3168c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 3178c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 3188c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 3198c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 3208c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 3218c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x1e, 3228c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 3238c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x20, 3248c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, 3258c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = INVALID_REG_ADDR, 3268c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 3278c2ecf20Sopenharmony_ci }, 3288c2ecf20Sopenharmony_ci bq27521_regs[BQ27XXX_REG_MAX] = { 3298c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x02, 3308c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x0a, 3318c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 3328c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x0c, 3338c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x0e, 3348c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x08, 3358c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = INVALID_REG_ADDR, 3368c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 3378c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 3388c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 3398c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = INVALID_REG_ADDR, 3408c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = INVALID_REG_ADDR, 3418c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = INVALID_REG_ADDR, 3428c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 3438c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = INVALID_REG_ADDR, 3448c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, 3458c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = INVALID_REG_ADDR, 3468c2ecf20Sopenharmony_ci [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR, 3478c2ecf20Sopenharmony_ci [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR, 3488c2ecf20Sopenharmony_ci [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR, 3498c2ecf20Sopenharmony_ci [BQ27XXX_DM_DATA] = INVALID_REG_ADDR, 3508c2ecf20Sopenharmony_ci [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR, 3518c2ecf20Sopenharmony_ci }, 3528c2ecf20Sopenharmony_ci bq27530_regs[BQ27XXX_REG_MAX] = { 3538c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 3548c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 3558c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x32, 3568c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 3578c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 3588c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 3598c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 3608c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 3618c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 3628c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 3638c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 3648c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 3658c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 3668c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 3678c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 3688c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, 3698c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 3708c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 3718c2ecf20Sopenharmony_ci }, 3728c2ecf20Sopenharmony_ci#define bq27531_regs bq27530_regs 3738c2ecf20Sopenharmony_ci bq27541_regs[BQ27XXX_REG_MAX] = { 3748c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 3758c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 3768c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x28, 3778c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 3788c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 3798c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 3808c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 3818c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 3828c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 3838c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 3848c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 3858c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 3868c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 3878c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 3888c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 3898c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 3908c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 3918c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 3928c2ecf20Sopenharmony_ci }, 3938c2ecf20Sopenharmony_ci#define bq27542_regs bq27541_regs 3948c2ecf20Sopenharmony_ci#define bq27546_regs bq27541_regs 3958c2ecf20Sopenharmony_ci#define bq27742_regs bq27541_regs 3968c2ecf20Sopenharmony_ci bq27545_regs[BQ27XXX_REG_MAX] = { 3978c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 3988c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 3998c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x28, 4008c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 4018c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 4028c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 4038c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 4048c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 4058c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 4068c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 4078c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 4088c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 4098c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 4108c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 4118c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 4128c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, 4138c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 4148c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 4158c2ecf20Sopenharmony_ci }, 4168c2ecf20Sopenharmony_ci bq27421_regs[BQ27XXX_REG_MAX] = { 4178c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 4188c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x02, 4198c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x1e, 4208c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x04, 4218c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x10, 4228c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x06, 4238c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = INVALID_REG_ADDR, 4248c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 4258c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 4268c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 4278c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x08, 4288c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x0e, 4298c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = INVALID_REG_ADDR, 4308c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 4318c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x1c, 4328c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 4338c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = 0x18, 4348c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 4358c2ecf20Sopenharmony_ci }, 4368c2ecf20Sopenharmony_ci#define bq27411_regs bq27421_regs 4378c2ecf20Sopenharmony_ci#define bq27425_regs bq27421_regs 4388c2ecf20Sopenharmony_ci#define bq27426_regs bq27421_regs 4398c2ecf20Sopenharmony_ci#define bq27441_regs bq27421_regs 4408c2ecf20Sopenharmony_ci#define bq27621_regs bq27421_regs 4418c2ecf20Sopenharmony_ci bq27z561_regs[BQ27XXX_REG_MAX] = { 4428c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 4438c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 4448c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 4458c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 4468c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 4478c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 4488c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 4498c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 4508c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 4518c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 4528c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = INVALID_REG_ADDR, 4538c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 4548c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 4558c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 4568c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 4578c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 4588c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = 0x22, 4598c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 4608c2ecf20Sopenharmony_ci }, 4618c2ecf20Sopenharmony_ci bq28z610_regs[BQ27XXX_REG_MAX] = { 4628c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 4638c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 4648c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 4658c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 4668c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 4678c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 4688c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 4698c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 4708c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 4718c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 4728c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = INVALID_REG_ADDR, 4738c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 4748c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 4758c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 4768c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 4778c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 4788c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = 0x22, 4798c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 4808c2ecf20Sopenharmony_ci }, 4818c2ecf20Sopenharmony_ci bq34z100_regs[BQ27XXX_REG_MAX] = { 4828c2ecf20Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 4838c2ecf20Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x0c, 4848c2ecf20Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x2a, 4858c2ecf20Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 4868c2ecf20Sopenharmony_ci [BQ27XXX_REG_AI] = 0x0a, 4878c2ecf20Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0e, 4888c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x18, 4898c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x1a, 4908c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1e, 4918c2ecf20Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 4928c2ecf20Sopenharmony_ci [BQ27XXX_REG_NAC] = INVALID_REG_ADDR, 4938c2ecf20Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x06, 4948c2ecf20Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2c, 4958c2ecf20Sopenharmony_ci [BQ27XXX_REG_AE] = 0x24, 4968c2ecf20Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x02, 4978c2ecf20Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 4988c2ecf20Sopenharmony_ci [BQ27XXX_REG_AP] = 0x22, 4998c2ecf20Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 5008c2ecf20Sopenharmony_ci }; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_cistatic enum power_supply_property bq27000_props[] = { 5038c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 5048c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 5058c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 5068c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 5078c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 5088c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 5098c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 5108c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 5118c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 5128c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 5138c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 5148c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 5158c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 5168c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 5178c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 5188c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_ENERGY_NOW, 5198c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 5208c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 5218c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 5228c2ecf20Sopenharmony_ci}; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_cistatic enum power_supply_property bq27010_props[] = { 5258c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 5268c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 5278c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 5288c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 5298c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 5308c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 5318c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 5328c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 5338c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 5348c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 5358c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 5368c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 5378c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 5388c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 5398c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 5408c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 5418c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 5428c2ecf20Sopenharmony_ci}; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci#define bq2750x_props bq27510g3_props 5458c2ecf20Sopenharmony_ci#define bq2751x_props bq27510g3_props 5468c2ecf20Sopenharmony_ci#define bq2752x_props bq27510g3_props 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_cistatic enum power_supply_property bq27500_props[] = { 5498c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 5508c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 5518c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 5528c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 5538c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 5548c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 5558c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 5568c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 5578c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 5588c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 5598c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 5608c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 5618c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 5628c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 5638c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_ENERGY_NOW, 5648c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 5658c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 5668c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 5678c2ecf20Sopenharmony_ci}; 5688c2ecf20Sopenharmony_ci#define bq27510g1_props bq27500_props 5698c2ecf20Sopenharmony_ci#define bq27510g2_props bq27500_props 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_cistatic enum power_supply_property bq27510g3_props[] = { 5728c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 5738c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 5748c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 5758c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 5768c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 5778c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 5788c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 5798c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 5808c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 5818c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 5828c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 5838c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 5848c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 5858c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 5868c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 5878c2ecf20Sopenharmony_ci}; 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_cistatic enum power_supply_property bq27520g1_props[] = { 5908c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 5918c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 5928c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 5938c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 5948c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 5958c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 5968c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 5978c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 5988c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 5998c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 6008c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 6018c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 6028c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 6038c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_ENERGY_NOW, 6048c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 6058c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 6068c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 6078c2ecf20Sopenharmony_ci}; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci#define bq27520g2_props bq27500_props 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_cistatic enum power_supply_property bq27520g3_props[] = { 6128c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 6138c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 6148c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 6158c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 6168c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 6178c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 6188c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 6198c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 6208c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 6218c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 6228c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 6238c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 6248c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 6258c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_ENERGY_NOW, 6268c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 6278c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 6288c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 6298c2ecf20Sopenharmony_ci}; 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic enum power_supply_property bq27520g4_props[] = { 6328c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 6338c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 6348c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 6358c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 6368c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 6378c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 6388c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 6398c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 6408c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 6418c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 6428c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 6438c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 6448c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 6458c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 6468c2ecf20Sopenharmony_ci}; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_cistatic enum power_supply_property bq27521_props[] = { 6498c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 6508c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 6518c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 6528c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 6538c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 6548c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 6558c2ecf20Sopenharmony_ci}; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_cistatic enum power_supply_property bq27530_props[] = { 6588c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 6598c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 6608c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 6618c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 6628c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 6638c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 6648c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 6658c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 6668c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 6678c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 6688c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 6698c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 6708c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 6718c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 6728c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 6738c2ecf20Sopenharmony_ci}; 6748c2ecf20Sopenharmony_ci#define bq27531_props bq27530_props 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_cistatic enum power_supply_property bq27541_props[] = { 6778c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 6788c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 6798c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 6808c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 6818c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 6828c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 6838c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 6848c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 6858c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 6868c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 6878c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 6888c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 6898c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 6908c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 6918c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 6928c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 6938c2ecf20Sopenharmony_ci}; 6948c2ecf20Sopenharmony_ci#define bq27542_props bq27541_props 6958c2ecf20Sopenharmony_ci#define bq27546_props bq27541_props 6968c2ecf20Sopenharmony_ci#define bq27742_props bq27541_props 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_cistatic enum power_supply_property bq27545_props[] = { 6998c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 7008c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 7018c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 7028c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 7038c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 7048c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 7058c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 7068c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 7078c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 7088c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 7098c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 7108c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 7118c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 7128c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 7138c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 7148c2ecf20Sopenharmony_ci}; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_cistatic enum power_supply_property bq27421_props[] = { 7178c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 7188c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 7198c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 7208c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 7218c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 7228c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 7238c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 7248c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 7258c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 7268c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 7278c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 7288c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 7298c2ecf20Sopenharmony_ci}; 7308c2ecf20Sopenharmony_ci#define bq27411_props bq27421_props 7318c2ecf20Sopenharmony_ci#define bq27425_props bq27421_props 7328c2ecf20Sopenharmony_ci#define bq27426_props bq27421_props 7338c2ecf20Sopenharmony_ci#define bq27441_props bq27421_props 7348c2ecf20Sopenharmony_ci#define bq27621_props bq27421_props 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_cistatic enum power_supply_property bq27z561_props[] = { 7378c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 7388c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 7398c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 7408c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 7418c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 7428c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 7438c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 7448c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 7458c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 7468c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 7478c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 7488c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 7498c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 7508c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 7518c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 7528c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 7538c2ecf20Sopenharmony_ci}; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_cistatic enum power_supply_property bq28z610_props[] = { 7568c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 7578c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 7588c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 7598c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 7608c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 7618c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 7628c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 7638c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 7648c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 7658c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 7668c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 7678c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 7688c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 7698c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 7708c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 7718c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 7728c2ecf20Sopenharmony_ci}; 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_cistatic enum power_supply_property bq34z100_props[] = { 7758c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 7768c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 7778c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 7788c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 7798c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 7808c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 7818c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 7828c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 7838c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 7848c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 7858c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 7868c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 7878c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 7888c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 7898c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_ENERGY_NOW, 7908c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 7918c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 7928c2ecf20Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 7938c2ecf20Sopenharmony_ci}; 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_cistruct bq27xxx_dm_reg { 7968c2ecf20Sopenharmony_ci u8 subclass_id; 7978c2ecf20Sopenharmony_ci u8 offset; 7988c2ecf20Sopenharmony_ci u8 bytes; 7998c2ecf20Sopenharmony_ci u16 min, max; 8008c2ecf20Sopenharmony_ci}; 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_cienum bq27xxx_dm_reg_id { 8038c2ecf20Sopenharmony_ci BQ27XXX_DM_DESIGN_CAPACITY = 0, 8048c2ecf20Sopenharmony_ci BQ27XXX_DM_DESIGN_ENERGY, 8058c2ecf20Sopenharmony_ci BQ27XXX_DM_TERMINATE_VOLTAGE, 8068c2ecf20Sopenharmony_ci}; 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci#define bq27000_dm_regs 0 8098c2ecf20Sopenharmony_ci#define bq27010_dm_regs 0 8108c2ecf20Sopenharmony_ci#define bq2750x_dm_regs 0 8118c2ecf20Sopenharmony_ci#define bq2751x_dm_regs 0 8128c2ecf20Sopenharmony_ci#define bq2752x_dm_regs 0 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci#if 0 /* not yet tested */ 8158c2ecf20Sopenharmony_cistatic struct bq27xxx_dm_reg bq27500_dm_regs[] = { 8168c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 10, 2, 0, 65535 }, 8178c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { }, /* missing on chip */ 8188c2ecf20Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 48, 2, 1000, 32767 }, 8198c2ecf20Sopenharmony_ci}; 8208c2ecf20Sopenharmony_ci#else 8218c2ecf20Sopenharmony_ci#define bq27500_dm_regs 0 8228c2ecf20Sopenharmony_ci#endif 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci/* todo create data memory definitions from datasheets and test on chips */ 8258c2ecf20Sopenharmony_ci#define bq27510g1_dm_regs 0 8268c2ecf20Sopenharmony_ci#define bq27510g2_dm_regs 0 8278c2ecf20Sopenharmony_ci#define bq27510g3_dm_regs 0 8288c2ecf20Sopenharmony_ci#define bq27520g1_dm_regs 0 8298c2ecf20Sopenharmony_ci#define bq27520g2_dm_regs 0 8308c2ecf20Sopenharmony_ci#define bq27520g3_dm_regs 0 8318c2ecf20Sopenharmony_ci#define bq27520g4_dm_regs 0 8328c2ecf20Sopenharmony_ci#define bq27521_dm_regs 0 8338c2ecf20Sopenharmony_ci#define bq27530_dm_regs 0 8348c2ecf20Sopenharmony_ci#define bq27531_dm_regs 0 8358c2ecf20Sopenharmony_ci#define bq27541_dm_regs 0 8368c2ecf20Sopenharmony_ci#define bq27542_dm_regs 0 8378c2ecf20Sopenharmony_ci#define bq27546_dm_regs 0 8388c2ecf20Sopenharmony_ci#define bq27742_dm_regs 0 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci#if 0 /* not yet tested */ 8418c2ecf20Sopenharmony_cistatic struct bq27xxx_dm_reg bq27545_dm_regs[] = { 8428c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 23, 2, 0, 32767 }, 8438c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { 48, 25, 2, 0, 32767 }, 8448c2ecf20Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 67, 2, 2800, 3700 }, 8458c2ecf20Sopenharmony_ci}; 8468c2ecf20Sopenharmony_ci#else 8478c2ecf20Sopenharmony_ci#define bq27545_dm_regs 0 8488c2ecf20Sopenharmony_ci#endif 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_cistatic struct bq27xxx_dm_reg bq27411_dm_regs[] = { 8518c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 10, 2, 0, 32767 }, 8528c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 12, 2, 0, 32767 }, 8538c2ecf20Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 16, 2, 2800, 3700 }, 8548c2ecf20Sopenharmony_ci}; 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_cistatic struct bq27xxx_dm_reg bq27421_dm_regs[] = { 8578c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 10, 2, 0, 8000 }, 8588c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 12, 2, 0, 32767 }, 8598c2ecf20Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 16, 2, 2500, 3700 }, 8608c2ecf20Sopenharmony_ci}; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_cistatic struct bq27xxx_dm_reg bq27425_dm_regs[] = { 8638c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 12, 2, 0, 32767 }, 8648c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 14, 2, 0, 32767 }, 8658c2ecf20Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 18, 2, 2800, 3700 }, 8668c2ecf20Sopenharmony_ci}; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_cistatic struct bq27xxx_dm_reg bq27426_dm_regs[] = { 8698c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 6, 2, 0, 8000 }, 8708c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 8, 2, 0, 32767 }, 8718c2ecf20Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 10, 2, 2500, 3700 }, 8728c2ecf20Sopenharmony_ci}; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci#if 0 /* not yet tested */ 8758c2ecf20Sopenharmony_ci#define bq27441_dm_regs bq27421_dm_regs 8768c2ecf20Sopenharmony_ci#else 8778c2ecf20Sopenharmony_ci#define bq27441_dm_regs 0 8788c2ecf20Sopenharmony_ci#endif 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci#if 0 /* not yet tested */ 8818c2ecf20Sopenharmony_cistatic struct bq27xxx_dm_reg bq27621_dm_regs[] = { 8828c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 3, 2, 0, 8000 }, 8838c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 5, 2, 0, 32767 }, 8848c2ecf20Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 9, 2, 2500, 3700 }, 8858c2ecf20Sopenharmony_ci}; 8868c2ecf20Sopenharmony_ci#else 8878c2ecf20Sopenharmony_ci#define bq27621_dm_regs 0 8888c2ecf20Sopenharmony_ci#endif 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci#define bq27z561_dm_regs 0 8918c2ecf20Sopenharmony_ci#define bq28z610_dm_regs 0 8928c2ecf20Sopenharmony_ci#define bq34z100_dm_regs 0 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci#define BQ27XXX_O_ZERO BIT(0) 8958c2ecf20Sopenharmony_ci#define BQ27XXX_O_OTDC BIT(1) /* has OTC/OTD overtemperature flags */ 8968c2ecf20Sopenharmony_ci#define BQ27XXX_O_UTOT BIT(2) /* has OT overtemperature flag */ 8978c2ecf20Sopenharmony_ci#define BQ27XXX_O_CFGUP BIT(3) 8988c2ecf20Sopenharmony_ci#define BQ27XXX_O_RAM BIT(4) 8998c2ecf20Sopenharmony_ci#define BQ27Z561_O_BITS BIT(5) 9008c2ecf20Sopenharmony_ci#define BQ27XXX_O_SOC_SI BIT(6) /* SoC is single register */ 9018c2ecf20Sopenharmony_ci#define BQ27XXX_O_HAS_CI BIT(7) /* has Capacity Inaccurate flag */ 9028c2ecf20Sopenharmony_ci#define BQ27XXX_O_MUL_CHEM BIT(8) /* multiple chemistries supported */ 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci#define BQ27XXX_DATA(ref, key, opt) { \ 9058c2ecf20Sopenharmony_ci .opts = (opt), \ 9068c2ecf20Sopenharmony_ci .unseal_key = key, \ 9078c2ecf20Sopenharmony_ci .regs = ref##_regs, \ 9088c2ecf20Sopenharmony_ci .dm_regs = ref##_dm_regs, \ 9098c2ecf20Sopenharmony_ci .props = ref##_props, \ 9108c2ecf20Sopenharmony_ci .props_size = ARRAY_SIZE(ref##_props) } 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_cistatic struct { 9138c2ecf20Sopenharmony_ci u32 opts; 9148c2ecf20Sopenharmony_ci u32 unseal_key; 9158c2ecf20Sopenharmony_ci u8 *regs; 9168c2ecf20Sopenharmony_ci struct bq27xxx_dm_reg *dm_regs; 9178c2ecf20Sopenharmony_ci enum power_supply_property *props; 9188c2ecf20Sopenharmony_ci size_t props_size; 9198c2ecf20Sopenharmony_ci} bq27xxx_chip_data[] = { 9208c2ecf20Sopenharmony_ci [BQ27000] = BQ27XXX_DATA(bq27000, 0 , BQ27XXX_O_ZERO | BQ27XXX_O_SOC_SI | BQ27XXX_O_HAS_CI), 9218c2ecf20Sopenharmony_ci [BQ27010] = BQ27XXX_DATA(bq27010, 0 , BQ27XXX_O_ZERO | BQ27XXX_O_SOC_SI | BQ27XXX_O_HAS_CI), 9228c2ecf20Sopenharmony_ci [BQ2750X] = BQ27XXX_DATA(bq2750x, 0 , BQ27XXX_O_OTDC), 9238c2ecf20Sopenharmony_ci [BQ2751X] = BQ27XXX_DATA(bq2751x, 0 , BQ27XXX_O_OTDC), 9248c2ecf20Sopenharmony_ci [BQ2752X] = BQ27XXX_DATA(bq2752x, 0 , BQ27XXX_O_OTDC), 9258c2ecf20Sopenharmony_ci [BQ27500] = BQ27XXX_DATA(bq27500, 0x04143672, BQ27XXX_O_OTDC), 9268c2ecf20Sopenharmony_ci [BQ27510G1] = BQ27XXX_DATA(bq27510g1, 0 , BQ27XXX_O_OTDC), 9278c2ecf20Sopenharmony_ci [BQ27510G2] = BQ27XXX_DATA(bq27510g2, 0 , BQ27XXX_O_OTDC), 9288c2ecf20Sopenharmony_ci [BQ27510G3] = BQ27XXX_DATA(bq27510g3, 0 , BQ27XXX_O_OTDC), 9298c2ecf20Sopenharmony_ci [BQ27520G1] = BQ27XXX_DATA(bq27520g1, 0 , BQ27XXX_O_OTDC), 9308c2ecf20Sopenharmony_ci [BQ27520G2] = BQ27XXX_DATA(bq27520g2, 0 , BQ27XXX_O_OTDC), 9318c2ecf20Sopenharmony_ci [BQ27520G3] = BQ27XXX_DATA(bq27520g3, 0 , BQ27XXX_O_OTDC), 9328c2ecf20Sopenharmony_ci [BQ27520G4] = BQ27XXX_DATA(bq27520g4, 0 , BQ27XXX_O_OTDC), 9338c2ecf20Sopenharmony_ci [BQ27521] = BQ27XXX_DATA(bq27521, 0 , 0), 9348c2ecf20Sopenharmony_ci [BQ27530] = BQ27XXX_DATA(bq27530, 0 , BQ27XXX_O_UTOT), 9358c2ecf20Sopenharmony_ci [BQ27531] = BQ27XXX_DATA(bq27531, 0 , BQ27XXX_O_UTOT), 9368c2ecf20Sopenharmony_ci [BQ27541] = BQ27XXX_DATA(bq27541, 0 , BQ27XXX_O_OTDC), 9378c2ecf20Sopenharmony_ci [BQ27542] = BQ27XXX_DATA(bq27542, 0 , BQ27XXX_O_OTDC), 9388c2ecf20Sopenharmony_ci [BQ27546] = BQ27XXX_DATA(bq27546, 0 , BQ27XXX_O_OTDC), 9398c2ecf20Sopenharmony_ci [BQ27742] = BQ27XXX_DATA(bq27742, 0 , BQ27XXX_O_OTDC), 9408c2ecf20Sopenharmony_ci [BQ27545] = BQ27XXX_DATA(bq27545, 0x04143672, BQ27XXX_O_OTDC), 9418c2ecf20Sopenharmony_ci [BQ27411] = BQ27XXX_DATA(bq27411, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), 9428c2ecf20Sopenharmony_ci [BQ27421] = BQ27XXX_DATA(bq27421, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), 9438c2ecf20Sopenharmony_ci [BQ27425] = BQ27XXX_DATA(bq27425, 0x04143672, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP), 9448c2ecf20Sopenharmony_ci [BQ27426] = BQ27XXX_DATA(bq27426, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), 9458c2ecf20Sopenharmony_ci [BQ27441] = BQ27XXX_DATA(bq27441, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), 9468c2ecf20Sopenharmony_ci [BQ27621] = BQ27XXX_DATA(bq27621, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), 9478c2ecf20Sopenharmony_ci [BQ27Z561] = BQ27XXX_DATA(bq27z561, 0 , BQ27Z561_O_BITS), 9488c2ecf20Sopenharmony_ci [BQ28Z610] = BQ27XXX_DATA(bq28z610, 0 , BQ27Z561_O_BITS), 9498c2ecf20Sopenharmony_ci [BQ34Z100] = BQ27XXX_DATA(bq34z100, 0 , BQ27XXX_O_OTDC | BQ27XXX_O_SOC_SI | \ 9508c2ecf20Sopenharmony_ci BQ27XXX_O_HAS_CI | BQ27XXX_O_MUL_CHEM), 9518c2ecf20Sopenharmony_ci}; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(bq27xxx_list_lock); 9548c2ecf20Sopenharmony_cistatic LIST_HEAD(bq27xxx_battery_devices); 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci#define BQ27XXX_MSLEEP(i) usleep_range((i)*1000, (i)*1000+500) 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci#define BQ27XXX_DM_SZ 32 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci/** 9618c2ecf20Sopenharmony_ci * struct bq27xxx_dm_buf - chip data memory buffer 9628c2ecf20Sopenharmony_ci * @class: data memory subclass_id 9638c2ecf20Sopenharmony_ci * @block: data memory block number 9648c2ecf20Sopenharmony_ci * @data: data from/for the block 9658c2ecf20Sopenharmony_ci * @has_data: true if data has been filled by read 9668c2ecf20Sopenharmony_ci * @dirty: true if data has changed since last read/write 9678c2ecf20Sopenharmony_ci * 9688c2ecf20Sopenharmony_ci * Encapsulates info required to manage chip data memory blocks. 9698c2ecf20Sopenharmony_ci */ 9708c2ecf20Sopenharmony_cistruct bq27xxx_dm_buf { 9718c2ecf20Sopenharmony_ci u8 class; 9728c2ecf20Sopenharmony_ci u8 block; 9738c2ecf20Sopenharmony_ci u8 data[BQ27XXX_DM_SZ]; 9748c2ecf20Sopenharmony_ci bool has_data, dirty; 9758c2ecf20Sopenharmony_ci}; 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci#define BQ27XXX_DM_BUF(di, i) { \ 9788c2ecf20Sopenharmony_ci .class = (di)->dm_regs[i].subclass_id, \ 9798c2ecf20Sopenharmony_ci .block = (di)->dm_regs[i].offset / BQ27XXX_DM_SZ, \ 9808c2ecf20Sopenharmony_ci} 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_cistatic inline u16 *bq27xxx_dm_reg_ptr(struct bq27xxx_dm_buf *buf, 9838c2ecf20Sopenharmony_ci struct bq27xxx_dm_reg *reg) 9848c2ecf20Sopenharmony_ci{ 9858c2ecf20Sopenharmony_ci if (buf->class == reg->subclass_id && 9868c2ecf20Sopenharmony_ci buf->block == reg->offset / BQ27XXX_DM_SZ) 9878c2ecf20Sopenharmony_ci return (u16 *) (buf->data + reg->offset % BQ27XXX_DM_SZ); 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci return NULL; 9908c2ecf20Sopenharmony_ci} 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_cistatic const char * const bq27xxx_dm_reg_name[] = { 9938c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = "design-capacity", 9948c2ecf20Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = "design-energy", 9958c2ecf20Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = "terminate-voltage", 9968c2ecf20Sopenharmony_ci}; 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_cistatic bool bq27xxx_dt_to_nvm = true; 10008c2ecf20Sopenharmony_cimodule_param_named(dt_monitored_battery_updates_nvm, bq27xxx_dt_to_nvm, bool, 0444); 10018c2ecf20Sopenharmony_ciMODULE_PARM_DESC(dt_monitored_battery_updates_nvm, 10028c2ecf20Sopenharmony_ci "Devicetree monitored-battery config updates data memory on NVM/flash chips.\n" 10038c2ecf20Sopenharmony_ci "Users must set this =0 when installing a different type of battery!\n" 10048c2ecf20Sopenharmony_ci "Default is =1." 10058c2ecf20Sopenharmony_ci#ifndef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM 10068c2ecf20Sopenharmony_ci "\nSetting this affects future kernel updates, not the current configuration." 10078c2ecf20Sopenharmony_ci#endif 10088c2ecf20Sopenharmony_ci); 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_cistatic int poll_interval_param_set(const char *val, const struct kernel_param *kp) 10118c2ecf20Sopenharmony_ci{ 10128c2ecf20Sopenharmony_ci struct bq27xxx_device_info *di; 10138c2ecf20Sopenharmony_ci unsigned int prev_val = *(unsigned int *) kp->arg; 10148c2ecf20Sopenharmony_ci int ret; 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci ret = param_set_uint(val, kp); 10178c2ecf20Sopenharmony_ci if (ret < 0 || prev_val == *(unsigned int *) kp->arg) 10188c2ecf20Sopenharmony_ci return ret; 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci mutex_lock(&bq27xxx_list_lock); 10218c2ecf20Sopenharmony_ci list_for_each_entry(di, &bq27xxx_battery_devices, list) 10228c2ecf20Sopenharmony_ci mod_delayed_work(system_wq, &di->work, 0); 10238c2ecf20Sopenharmony_ci mutex_unlock(&bq27xxx_list_lock); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci return ret; 10268c2ecf20Sopenharmony_ci} 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_cistatic const struct kernel_param_ops param_ops_poll_interval = { 10298c2ecf20Sopenharmony_ci .get = param_get_uint, 10308c2ecf20Sopenharmony_ci .set = poll_interval_param_set, 10318c2ecf20Sopenharmony_ci}; 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_cistatic unsigned int poll_interval = 360; 10348c2ecf20Sopenharmony_cimodule_param_cb(poll_interval, ¶m_ops_poll_interval, &poll_interval, 0644); 10358c2ecf20Sopenharmony_ciMODULE_PARM_DESC(poll_interval, 10368c2ecf20Sopenharmony_ci "battery poll interval in seconds - 0 disables polling"); 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci/* 10398c2ecf20Sopenharmony_ci * Common code for BQ27xxx devices 10408c2ecf20Sopenharmony_ci */ 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_cistatic inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, 10438c2ecf20Sopenharmony_ci bool single) 10448c2ecf20Sopenharmony_ci{ 10458c2ecf20Sopenharmony_ci int ret; 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci if (!di || di->regs[reg_index] == INVALID_REG_ADDR) 10488c2ecf20Sopenharmony_ci return -EINVAL; 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci ret = di->bus.read(di, di->regs[reg_index], single); 10518c2ecf20Sopenharmony_ci if (ret < 0) 10528c2ecf20Sopenharmony_ci dev_dbg(di->dev, "failed to read register 0x%02x (index %d)\n", 10538c2ecf20Sopenharmony_ci di->regs[reg_index], reg_index); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci return ret; 10568c2ecf20Sopenharmony_ci} 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_cistatic inline int bq27xxx_write(struct bq27xxx_device_info *di, int reg_index, 10598c2ecf20Sopenharmony_ci u16 value, bool single) 10608c2ecf20Sopenharmony_ci{ 10618c2ecf20Sopenharmony_ci int ret; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci if (!di || di->regs[reg_index] == INVALID_REG_ADDR) 10648c2ecf20Sopenharmony_ci return -EINVAL; 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci if (!di->bus.write) 10678c2ecf20Sopenharmony_ci return -EPERM; 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci ret = di->bus.write(di, di->regs[reg_index], value, single); 10708c2ecf20Sopenharmony_ci if (ret < 0) 10718c2ecf20Sopenharmony_ci dev_dbg(di->dev, "failed to write register 0x%02x (index %d)\n", 10728c2ecf20Sopenharmony_ci di->regs[reg_index], reg_index); 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci return ret; 10758c2ecf20Sopenharmony_ci} 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_cistatic inline int bq27xxx_read_block(struct bq27xxx_device_info *di, int reg_index, 10788c2ecf20Sopenharmony_ci u8 *data, int len) 10798c2ecf20Sopenharmony_ci{ 10808c2ecf20Sopenharmony_ci int ret; 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci if (!di || di->regs[reg_index] == INVALID_REG_ADDR) 10838c2ecf20Sopenharmony_ci return -EINVAL; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci if (!di->bus.read_bulk) 10868c2ecf20Sopenharmony_ci return -EPERM; 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci ret = di->bus.read_bulk(di, di->regs[reg_index], data, len); 10898c2ecf20Sopenharmony_ci if (ret < 0) 10908c2ecf20Sopenharmony_ci dev_dbg(di->dev, "failed to read_bulk register 0x%02x (index %d)\n", 10918c2ecf20Sopenharmony_ci di->regs[reg_index], reg_index); 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci return ret; 10948c2ecf20Sopenharmony_ci} 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_cistatic inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_index, 10978c2ecf20Sopenharmony_ci u8 *data, int len) 10988c2ecf20Sopenharmony_ci{ 10998c2ecf20Sopenharmony_ci int ret; 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci if (!di || di->regs[reg_index] == INVALID_REG_ADDR) 11028c2ecf20Sopenharmony_ci return -EINVAL; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci if (!di->bus.write_bulk) 11058c2ecf20Sopenharmony_ci return -EPERM; 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci ret = di->bus.write_bulk(di, di->regs[reg_index], data, len); 11088c2ecf20Sopenharmony_ci if (ret < 0) 11098c2ecf20Sopenharmony_ci dev_dbg(di->dev, "failed to write_bulk register 0x%02x (index %d)\n", 11108c2ecf20Sopenharmony_ci di->regs[reg_index], reg_index); 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci return ret; 11138c2ecf20Sopenharmony_ci} 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_cistatic int bq27xxx_battery_seal(struct bq27xxx_device_info *di) 11168c2ecf20Sopenharmony_ci{ 11178c2ecf20Sopenharmony_ci int ret; 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, BQ27XXX_SEALED, false); 11208c2ecf20Sopenharmony_ci if (ret < 0) { 11218c2ecf20Sopenharmony_ci dev_err(di->dev, "bus error on seal: %d\n", ret); 11228c2ecf20Sopenharmony_ci return ret; 11238c2ecf20Sopenharmony_ci } 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci return 0; 11268c2ecf20Sopenharmony_ci} 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_cistatic int bq27xxx_battery_unseal(struct bq27xxx_device_info *di) 11298c2ecf20Sopenharmony_ci{ 11308c2ecf20Sopenharmony_ci int ret; 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci if (di->unseal_key == 0) { 11338c2ecf20Sopenharmony_ci dev_err(di->dev, "unseal failed due to missing key\n"); 11348c2ecf20Sopenharmony_ci return -EINVAL; 11358c2ecf20Sopenharmony_ci } 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, (u16)(di->unseal_key >> 16), false); 11388c2ecf20Sopenharmony_ci if (ret < 0) 11398c2ecf20Sopenharmony_ci goto out; 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, (u16)di->unseal_key, false); 11428c2ecf20Sopenharmony_ci if (ret < 0) 11438c2ecf20Sopenharmony_ci goto out; 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci return 0; 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ciout: 11488c2ecf20Sopenharmony_ci dev_err(di->dev, "bus error on unseal: %d\n", ret); 11498c2ecf20Sopenharmony_ci return ret; 11508c2ecf20Sopenharmony_ci} 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_cistatic u8 bq27xxx_battery_checksum_dm_block(struct bq27xxx_dm_buf *buf) 11538c2ecf20Sopenharmony_ci{ 11548c2ecf20Sopenharmony_ci u16 sum = 0; 11558c2ecf20Sopenharmony_ci int i; 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci for (i = 0; i < BQ27XXX_DM_SZ; i++) 11588c2ecf20Sopenharmony_ci sum += buf->data[i]; 11598c2ecf20Sopenharmony_ci sum &= 0xff; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci return 0xff - sum; 11628c2ecf20Sopenharmony_ci} 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_cistatic int bq27xxx_battery_read_dm_block(struct bq27xxx_device_info *di, 11658c2ecf20Sopenharmony_ci struct bq27xxx_dm_buf *buf) 11668c2ecf20Sopenharmony_ci{ 11678c2ecf20Sopenharmony_ci int ret; 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci buf->has_data = false; 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_DM_CLASS, buf->class, true); 11728c2ecf20Sopenharmony_ci if (ret < 0) 11738c2ecf20Sopenharmony_ci goto out; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_DM_BLOCK, buf->block, true); 11768c2ecf20Sopenharmony_ci if (ret < 0) 11778c2ecf20Sopenharmony_ci goto out; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci BQ27XXX_MSLEEP(1); 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci ret = bq27xxx_read_block(di, BQ27XXX_DM_DATA, buf->data, BQ27XXX_DM_SZ); 11828c2ecf20Sopenharmony_ci if (ret < 0) 11838c2ecf20Sopenharmony_ci goto out; 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci ret = bq27xxx_read(di, BQ27XXX_DM_CKSUM, true); 11868c2ecf20Sopenharmony_ci if (ret < 0) 11878c2ecf20Sopenharmony_ci goto out; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci if ((u8)ret != bq27xxx_battery_checksum_dm_block(buf)) { 11908c2ecf20Sopenharmony_ci ret = -EINVAL; 11918c2ecf20Sopenharmony_ci goto out; 11928c2ecf20Sopenharmony_ci } 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci buf->has_data = true; 11958c2ecf20Sopenharmony_ci buf->dirty = false; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci return 0; 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ciout: 12008c2ecf20Sopenharmony_ci dev_err(di->dev, "bus error reading chip memory: %d\n", ret); 12018c2ecf20Sopenharmony_ci return ret; 12028c2ecf20Sopenharmony_ci} 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_cistatic void bq27xxx_battery_update_dm_block(struct bq27xxx_device_info *di, 12058c2ecf20Sopenharmony_ci struct bq27xxx_dm_buf *buf, 12068c2ecf20Sopenharmony_ci enum bq27xxx_dm_reg_id reg_id, 12078c2ecf20Sopenharmony_ci unsigned int val) 12088c2ecf20Sopenharmony_ci{ 12098c2ecf20Sopenharmony_ci struct bq27xxx_dm_reg *reg = &di->dm_regs[reg_id]; 12108c2ecf20Sopenharmony_ci const char *str = bq27xxx_dm_reg_name[reg_id]; 12118c2ecf20Sopenharmony_ci u16 *prev = bq27xxx_dm_reg_ptr(buf, reg); 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci if (prev == NULL) { 12148c2ecf20Sopenharmony_ci dev_warn(di->dev, "buffer does not match %s dm spec\n", str); 12158c2ecf20Sopenharmony_ci return; 12168c2ecf20Sopenharmony_ci } 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci if (reg->bytes != 2) { 12198c2ecf20Sopenharmony_ci dev_warn(di->dev, "%s dm spec has unsupported byte size\n", str); 12208c2ecf20Sopenharmony_ci return; 12218c2ecf20Sopenharmony_ci } 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci if (!buf->has_data) 12248c2ecf20Sopenharmony_ci return; 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci if (be16_to_cpup(prev) == val) { 12278c2ecf20Sopenharmony_ci dev_info(di->dev, "%s has %u\n", str, val); 12288c2ecf20Sopenharmony_ci return; 12298c2ecf20Sopenharmony_ci } 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM 12328c2ecf20Sopenharmony_ci if (!(di->opts & BQ27XXX_O_RAM) && !bq27xxx_dt_to_nvm) { 12338c2ecf20Sopenharmony_ci#else 12348c2ecf20Sopenharmony_ci if (!(di->opts & BQ27XXX_O_RAM)) { 12358c2ecf20Sopenharmony_ci#endif 12368c2ecf20Sopenharmony_ci /* devicetree and NVM differ; defer to NVM */ 12378c2ecf20Sopenharmony_ci dev_warn(di->dev, "%s has %u; update to %u disallowed " 12388c2ecf20Sopenharmony_ci#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM 12398c2ecf20Sopenharmony_ci "by dt_monitored_battery_updates_nvm=0" 12408c2ecf20Sopenharmony_ci#else 12418c2ecf20Sopenharmony_ci "for flash/NVM data memory" 12428c2ecf20Sopenharmony_ci#endif 12438c2ecf20Sopenharmony_ci "\n", str, be16_to_cpup(prev), val); 12448c2ecf20Sopenharmony_ci return; 12458c2ecf20Sopenharmony_ci } 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci dev_info(di->dev, "update %s to %u\n", str, val); 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci *prev = cpu_to_be16(val); 12508c2ecf20Sopenharmony_ci buf->dirty = true; 12518c2ecf20Sopenharmony_ci} 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_cistatic int bq27xxx_battery_cfgupdate_priv(struct bq27xxx_device_info *di, bool active) 12548c2ecf20Sopenharmony_ci{ 12558c2ecf20Sopenharmony_ci const int limit = 100; 12568c2ecf20Sopenharmony_ci u16 cmd = active ? BQ27XXX_SET_CFGUPDATE : BQ27XXX_SOFT_RESET; 12578c2ecf20Sopenharmony_ci int ret, try = limit; 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, cmd, false); 12608c2ecf20Sopenharmony_ci if (ret < 0) 12618c2ecf20Sopenharmony_ci return ret; 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci do { 12648c2ecf20Sopenharmony_ci BQ27XXX_MSLEEP(25); 12658c2ecf20Sopenharmony_ci ret = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false); 12668c2ecf20Sopenharmony_ci if (ret < 0) 12678c2ecf20Sopenharmony_ci return ret; 12688c2ecf20Sopenharmony_ci } while (!!(ret & BQ27XXX_FLAG_CFGUP) != active && --try); 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci if (!try && di->chip != BQ27425) { // 425 has a bug 12718c2ecf20Sopenharmony_ci dev_err(di->dev, "timed out waiting for cfgupdate flag %d\n", active); 12728c2ecf20Sopenharmony_ci return -EINVAL; 12738c2ecf20Sopenharmony_ci } 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci if (limit - try > 3) 12768c2ecf20Sopenharmony_ci dev_warn(di->dev, "cfgupdate %d, retries %d\n", active, limit - try); 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci return 0; 12798c2ecf20Sopenharmony_ci} 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_cistatic inline int bq27xxx_battery_set_cfgupdate(struct bq27xxx_device_info *di) 12828c2ecf20Sopenharmony_ci{ 12838c2ecf20Sopenharmony_ci int ret = bq27xxx_battery_cfgupdate_priv(di, true); 12848c2ecf20Sopenharmony_ci if (ret < 0 && ret != -EINVAL) 12858c2ecf20Sopenharmony_ci dev_err(di->dev, "bus error on set_cfgupdate: %d\n", ret); 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci return ret; 12888c2ecf20Sopenharmony_ci} 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_cistatic inline int bq27xxx_battery_soft_reset(struct bq27xxx_device_info *di) 12918c2ecf20Sopenharmony_ci{ 12928c2ecf20Sopenharmony_ci int ret = bq27xxx_battery_cfgupdate_priv(di, false); 12938c2ecf20Sopenharmony_ci if (ret < 0 && ret != -EINVAL) 12948c2ecf20Sopenharmony_ci dev_err(di->dev, "bus error on soft_reset: %d\n", ret); 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci return ret; 12978c2ecf20Sopenharmony_ci} 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_cistatic int bq27xxx_battery_write_dm_block(struct bq27xxx_device_info *di, 13008c2ecf20Sopenharmony_ci struct bq27xxx_dm_buf *buf) 13018c2ecf20Sopenharmony_ci{ 13028c2ecf20Sopenharmony_ci bool cfgup = di->opts & BQ27XXX_O_CFGUP; 13038c2ecf20Sopenharmony_ci int ret; 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci if (!buf->dirty) 13068c2ecf20Sopenharmony_ci return 0; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci if (cfgup) { 13098c2ecf20Sopenharmony_ci ret = bq27xxx_battery_set_cfgupdate(di); 13108c2ecf20Sopenharmony_ci if (ret < 0) 13118c2ecf20Sopenharmony_ci return ret; 13128c2ecf20Sopenharmony_ci } 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_DM_CTRL, 0, true); 13158c2ecf20Sopenharmony_ci if (ret < 0) 13168c2ecf20Sopenharmony_ci goto out; 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_DM_CLASS, buf->class, true); 13198c2ecf20Sopenharmony_ci if (ret < 0) 13208c2ecf20Sopenharmony_ci goto out; 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_DM_BLOCK, buf->block, true); 13238c2ecf20Sopenharmony_ci if (ret < 0) 13248c2ecf20Sopenharmony_ci goto out; 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci BQ27XXX_MSLEEP(1); 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci ret = bq27xxx_write_block(di, BQ27XXX_DM_DATA, buf->data, BQ27XXX_DM_SZ); 13298c2ecf20Sopenharmony_ci if (ret < 0) 13308c2ecf20Sopenharmony_ci goto out; 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_DM_CKSUM, 13338c2ecf20Sopenharmony_ci bq27xxx_battery_checksum_dm_block(buf), true); 13348c2ecf20Sopenharmony_ci if (ret < 0) 13358c2ecf20Sopenharmony_ci goto out; 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci /* DO NOT read BQ27XXX_DM_CKSUM here to verify it! That may cause NVM 13388c2ecf20Sopenharmony_ci * corruption on the '425 chip (and perhaps others), which can damage 13398c2ecf20Sopenharmony_ci * the chip. 13408c2ecf20Sopenharmony_ci */ 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci if (cfgup) { 13438c2ecf20Sopenharmony_ci BQ27XXX_MSLEEP(1); 13448c2ecf20Sopenharmony_ci ret = bq27xxx_battery_soft_reset(di); 13458c2ecf20Sopenharmony_ci if (ret < 0) 13468c2ecf20Sopenharmony_ci return ret; 13478c2ecf20Sopenharmony_ci } else { 13488c2ecf20Sopenharmony_ci BQ27XXX_MSLEEP(100); /* flash DM updates in <100ms */ 13498c2ecf20Sopenharmony_ci } 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci buf->dirty = false; 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci return 0; 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_ciout: 13568c2ecf20Sopenharmony_ci if (cfgup) 13578c2ecf20Sopenharmony_ci bq27xxx_battery_soft_reset(di); 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci dev_err(di->dev, "bus error writing chip memory: %d\n", ret); 13608c2ecf20Sopenharmony_ci return ret; 13618c2ecf20Sopenharmony_ci} 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_cistatic void bq27xxx_battery_set_config(struct bq27xxx_device_info *di, 13648c2ecf20Sopenharmony_ci struct power_supply_battery_info *info) 13658c2ecf20Sopenharmony_ci{ 13668c2ecf20Sopenharmony_ci struct bq27xxx_dm_buf bd = BQ27XXX_DM_BUF(di, BQ27XXX_DM_DESIGN_CAPACITY); 13678c2ecf20Sopenharmony_ci struct bq27xxx_dm_buf bt = BQ27XXX_DM_BUF(di, BQ27XXX_DM_TERMINATE_VOLTAGE); 13688c2ecf20Sopenharmony_ci bool updated; 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci if (bq27xxx_battery_unseal(di) < 0) 13718c2ecf20Sopenharmony_ci return; 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci if (info->charge_full_design_uah != -EINVAL && 13748c2ecf20Sopenharmony_ci info->energy_full_design_uwh != -EINVAL) { 13758c2ecf20Sopenharmony_ci bq27xxx_battery_read_dm_block(di, &bd); 13768c2ecf20Sopenharmony_ci /* assume design energy & capacity are in same block */ 13778c2ecf20Sopenharmony_ci bq27xxx_battery_update_dm_block(di, &bd, 13788c2ecf20Sopenharmony_ci BQ27XXX_DM_DESIGN_CAPACITY, 13798c2ecf20Sopenharmony_ci info->charge_full_design_uah / 1000); 13808c2ecf20Sopenharmony_ci bq27xxx_battery_update_dm_block(di, &bd, 13818c2ecf20Sopenharmony_ci BQ27XXX_DM_DESIGN_ENERGY, 13828c2ecf20Sopenharmony_ci info->energy_full_design_uwh / 1000); 13838c2ecf20Sopenharmony_ci } 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci if (info->voltage_min_design_uv != -EINVAL) { 13868c2ecf20Sopenharmony_ci bool same = bd.class == bt.class && bd.block == bt.block; 13878c2ecf20Sopenharmony_ci if (!same) 13888c2ecf20Sopenharmony_ci bq27xxx_battery_read_dm_block(di, &bt); 13898c2ecf20Sopenharmony_ci bq27xxx_battery_update_dm_block(di, same ? &bd : &bt, 13908c2ecf20Sopenharmony_ci BQ27XXX_DM_TERMINATE_VOLTAGE, 13918c2ecf20Sopenharmony_ci info->voltage_min_design_uv / 1000); 13928c2ecf20Sopenharmony_ci } 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci updated = bd.dirty || bt.dirty; 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci bq27xxx_battery_write_dm_block(di, &bd); 13978c2ecf20Sopenharmony_ci bq27xxx_battery_write_dm_block(di, &bt); 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci bq27xxx_battery_seal(di); 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci if (updated && !(di->opts & BQ27XXX_O_CFGUP)) { 14028c2ecf20Sopenharmony_ci bq27xxx_write(di, BQ27XXX_REG_CTRL, BQ27XXX_RESET, false); 14038c2ecf20Sopenharmony_ci BQ27XXX_MSLEEP(300); /* reset time is not documented */ 14048c2ecf20Sopenharmony_ci } 14058c2ecf20Sopenharmony_ci /* assume bq27xxx_battery_update() is called hereafter */ 14068c2ecf20Sopenharmony_ci} 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_cistatic void bq27xxx_battery_settings(struct bq27xxx_device_info *di) 14098c2ecf20Sopenharmony_ci{ 14108c2ecf20Sopenharmony_ci struct power_supply_battery_info info = {}; 14118c2ecf20Sopenharmony_ci unsigned int min, max; 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci if (power_supply_get_battery_info(di->bat, &info) < 0) 14148c2ecf20Sopenharmony_ci return; 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci if (!di->dm_regs) { 14178c2ecf20Sopenharmony_ci dev_warn(di->dev, "data memory update not supported for chip\n"); 14188c2ecf20Sopenharmony_ci return; 14198c2ecf20Sopenharmony_ci } 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci if (info.energy_full_design_uwh != info.charge_full_design_uah) { 14228c2ecf20Sopenharmony_ci if (info.energy_full_design_uwh == -EINVAL) 14238c2ecf20Sopenharmony_ci dev_warn(di->dev, "missing battery:energy-full-design-microwatt-hours\n"); 14248c2ecf20Sopenharmony_ci else if (info.charge_full_design_uah == -EINVAL) 14258c2ecf20Sopenharmony_ci dev_warn(di->dev, "missing battery:charge-full-design-microamp-hours\n"); 14268c2ecf20Sopenharmony_ci } 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci /* assume min == 0 */ 14298c2ecf20Sopenharmony_ci max = di->dm_regs[BQ27XXX_DM_DESIGN_ENERGY].max; 14308c2ecf20Sopenharmony_ci if (info.energy_full_design_uwh > max * 1000) { 14318c2ecf20Sopenharmony_ci dev_err(di->dev, "invalid battery:energy-full-design-microwatt-hours %d\n", 14328c2ecf20Sopenharmony_ci info.energy_full_design_uwh); 14338c2ecf20Sopenharmony_ci info.energy_full_design_uwh = -EINVAL; 14348c2ecf20Sopenharmony_ci } 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci /* assume min == 0 */ 14378c2ecf20Sopenharmony_ci max = di->dm_regs[BQ27XXX_DM_DESIGN_CAPACITY].max; 14388c2ecf20Sopenharmony_ci if (info.charge_full_design_uah > max * 1000) { 14398c2ecf20Sopenharmony_ci dev_err(di->dev, "invalid battery:charge-full-design-microamp-hours %d\n", 14408c2ecf20Sopenharmony_ci info.charge_full_design_uah); 14418c2ecf20Sopenharmony_ci info.charge_full_design_uah = -EINVAL; 14428c2ecf20Sopenharmony_ci } 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci min = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].min; 14458c2ecf20Sopenharmony_ci max = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].max; 14468c2ecf20Sopenharmony_ci if ((info.voltage_min_design_uv < min * 1000 || 14478c2ecf20Sopenharmony_ci info.voltage_min_design_uv > max * 1000) && 14488c2ecf20Sopenharmony_ci info.voltage_min_design_uv != -EINVAL) { 14498c2ecf20Sopenharmony_ci dev_err(di->dev, "invalid battery:voltage-min-design-microvolt %d\n", 14508c2ecf20Sopenharmony_ci info.voltage_min_design_uv); 14518c2ecf20Sopenharmony_ci info.voltage_min_design_uv = -EINVAL; 14528c2ecf20Sopenharmony_ci } 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci if ((info.energy_full_design_uwh != -EINVAL && 14558c2ecf20Sopenharmony_ci info.charge_full_design_uah != -EINVAL) || 14568c2ecf20Sopenharmony_ci info.voltage_min_design_uv != -EINVAL) 14578c2ecf20Sopenharmony_ci bq27xxx_battery_set_config(di, &info); 14588c2ecf20Sopenharmony_ci} 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci/* 14618c2ecf20Sopenharmony_ci * Return the battery State-of-Charge 14628c2ecf20Sopenharmony_ci * Or < 0 if something fails. 14638c2ecf20Sopenharmony_ci */ 14648c2ecf20Sopenharmony_cistatic int bq27xxx_battery_read_soc(struct bq27xxx_device_info *di) 14658c2ecf20Sopenharmony_ci{ 14668c2ecf20Sopenharmony_ci int soc; 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_SOC_SI) 14698c2ecf20Sopenharmony_ci soc = bq27xxx_read(di, BQ27XXX_REG_SOC, true); 14708c2ecf20Sopenharmony_ci else 14718c2ecf20Sopenharmony_ci soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false); 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci if (soc < 0) 14748c2ecf20Sopenharmony_ci dev_dbg(di->dev, "error reading State-of-Charge\n"); 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci return soc; 14778c2ecf20Sopenharmony_ci} 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci/* 14808c2ecf20Sopenharmony_ci * Return a battery charge value in µAh 14818c2ecf20Sopenharmony_ci * Or < 0 if something fails. 14828c2ecf20Sopenharmony_ci */ 14838c2ecf20Sopenharmony_cistatic int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg) 14848c2ecf20Sopenharmony_ci{ 14858c2ecf20Sopenharmony_ci int charge; 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_ci charge = bq27xxx_read(di, reg, false); 14888c2ecf20Sopenharmony_ci if (charge < 0) { 14898c2ecf20Sopenharmony_ci dev_dbg(di->dev, "error reading charge register %02x: %d\n", 14908c2ecf20Sopenharmony_ci reg, charge); 14918c2ecf20Sopenharmony_ci return charge; 14928c2ecf20Sopenharmony_ci } 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 14958c2ecf20Sopenharmony_ci charge *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; 14968c2ecf20Sopenharmony_ci else 14978c2ecf20Sopenharmony_ci charge *= 1000; 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_ci return charge; 15008c2ecf20Sopenharmony_ci} 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci/* 15038c2ecf20Sopenharmony_ci * Return the battery Nominal available capacity in µAh 15048c2ecf20Sopenharmony_ci * Or < 0 if something fails. 15058c2ecf20Sopenharmony_ci */ 15068c2ecf20Sopenharmony_cistatic inline int bq27xxx_battery_read_nac(struct bq27xxx_device_info *di) 15078c2ecf20Sopenharmony_ci{ 15088c2ecf20Sopenharmony_ci return bq27xxx_battery_read_charge(di, BQ27XXX_REG_NAC); 15098c2ecf20Sopenharmony_ci} 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci/* 15128c2ecf20Sopenharmony_ci * Return the battery Full Charge Capacity in µAh 15138c2ecf20Sopenharmony_ci * Or < 0 if something fails. 15148c2ecf20Sopenharmony_ci */ 15158c2ecf20Sopenharmony_cistatic inline int bq27xxx_battery_read_fcc(struct bq27xxx_device_info *di) 15168c2ecf20Sopenharmony_ci{ 15178c2ecf20Sopenharmony_ci return bq27xxx_battery_read_charge(di, BQ27XXX_REG_FCC); 15188c2ecf20Sopenharmony_ci} 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci/* 15218c2ecf20Sopenharmony_ci * Return the Design Capacity in µAh 15228c2ecf20Sopenharmony_ci * Or < 0 if something fails. 15238c2ecf20Sopenharmony_ci */ 15248c2ecf20Sopenharmony_cistatic int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di) 15258c2ecf20Sopenharmony_ci{ 15268c2ecf20Sopenharmony_ci int dcap; 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 15298c2ecf20Sopenharmony_ci dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, true); 15308c2ecf20Sopenharmony_ci else 15318c2ecf20Sopenharmony_ci dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false); 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci if (dcap < 0) { 15348c2ecf20Sopenharmony_ci dev_dbg(di->dev, "error reading initial last measured discharge\n"); 15358c2ecf20Sopenharmony_ci return dcap; 15368c2ecf20Sopenharmony_ci } 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 15398c2ecf20Sopenharmony_ci dcap = (dcap << 8) * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; 15408c2ecf20Sopenharmony_ci else 15418c2ecf20Sopenharmony_ci dcap *= 1000; 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci return dcap; 15448c2ecf20Sopenharmony_ci} 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci/* 15478c2ecf20Sopenharmony_ci * Return the battery Available energy in µWh 15488c2ecf20Sopenharmony_ci * Or < 0 if something fails. 15498c2ecf20Sopenharmony_ci */ 15508c2ecf20Sopenharmony_cistatic int bq27xxx_battery_read_energy(struct bq27xxx_device_info *di) 15518c2ecf20Sopenharmony_ci{ 15528c2ecf20Sopenharmony_ci int ae; 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci ae = bq27xxx_read(di, BQ27XXX_REG_AE, false); 15558c2ecf20Sopenharmony_ci if (ae < 0) { 15568c2ecf20Sopenharmony_ci dev_dbg(di->dev, "error reading available energy\n"); 15578c2ecf20Sopenharmony_ci return ae; 15588c2ecf20Sopenharmony_ci } 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 15618c2ecf20Sopenharmony_ci ae *= BQ27XXX_POWER_CONSTANT / BQ27XXX_RS; 15628c2ecf20Sopenharmony_ci else 15638c2ecf20Sopenharmony_ci ae *= 1000; 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci return ae; 15668c2ecf20Sopenharmony_ci} 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci/* 15698c2ecf20Sopenharmony_ci * Return the battery temperature in tenths of degree Kelvin 15708c2ecf20Sopenharmony_ci * Or < 0 if something fails. 15718c2ecf20Sopenharmony_ci */ 15728c2ecf20Sopenharmony_cistatic int bq27xxx_battery_read_temperature(struct bq27xxx_device_info *di) 15738c2ecf20Sopenharmony_ci{ 15748c2ecf20Sopenharmony_ci int temp; 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci temp = bq27xxx_read(di, BQ27XXX_REG_TEMP, false); 15778c2ecf20Sopenharmony_ci if (temp < 0) { 15788c2ecf20Sopenharmony_ci dev_err(di->dev, "error reading temperature\n"); 15798c2ecf20Sopenharmony_ci return temp; 15808c2ecf20Sopenharmony_ci } 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 15838c2ecf20Sopenharmony_ci temp = 5 * temp / 2; 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci return temp; 15868c2ecf20Sopenharmony_ci} 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci/* 15898c2ecf20Sopenharmony_ci * Return the battery Cycle count total 15908c2ecf20Sopenharmony_ci * Or < 0 if something fails. 15918c2ecf20Sopenharmony_ci */ 15928c2ecf20Sopenharmony_cistatic int bq27xxx_battery_read_cyct(struct bq27xxx_device_info *di) 15938c2ecf20Sopenharmony_ci{ 15948c2ecf20Sopenharmony_ci int cyct; 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci cyct = bq27xxx_read(di, BQ27XXX_REG_CYCT, false); 15978c2ecf20Sopenharmony_ci if (cyct < 0) 15988c2ecf20Sopenharmony_ci dev_err(di->dev, "error reading cycle count total\n"); 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci return cyct; 16018c2ecf20Sopenharmony_ci} 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci/* 16048c2ecf20Sopenharmony_ci * Read a time register. 16058c2ecf20Sopenharmony_ci * Return < 0 if something fails. 16068c2ecf20Sopenharmony_ci */ 16078c2ecf20Sopenharmony_cistatic int bq27xxx_battery_read_time(struct bq27xxx_device_info *di, u8 reg) 16088c2ecf20Sopenharmony_ci{ 16098c2ecf20Sopenharmony_ci int tval; 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci tval = bq27xxx_read(di, reg, false); 16128c2ecf20Sopenharmony_ci if (tval < 0) { 16138c2ecf20Sopenharmony_ci dev_dbg(di->dev, "error reading time register %02x: %d\n", 16148c2ecf20Sopenharmony_ci reg, tval); 16158c2ecf20Sopenharmony_ci return tval; 16168c2ecf20Sopenharmony_ci } 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci if (tval == 65535) 16198c2ecf20Sopenharmony_ci return -ENODATA; 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci return tval * 60; 16228c2ecf20Sopenharmony_ci} 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci/* 16258c2ecf20Sopenharmony_ci * Returns true if a battery over temperature condition is detected 16268c2ecf20Sopenharmony_ci */ 16278c2ecf20Sopenharmony_cistatic bool bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags) 16288c2ecf20Sopenharmony_ci{ 16298c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_OTDC) 16308c2ecf20Sopenharmony_ci return flags & (BQ27XXX_FLAG_OTC | BQ27XXX_FLAG_OTD); 16318c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_UTOT) 16328c2ecf20Sopenharmony_ci return flags & BQ27XXX_FLAG_OT; 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci return false; 16358c2ecf20Sopenharmony_ci} 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci/* 16388c2ecf20Sopenharmony_ci * Returns true if a battery under temperature condition is detected 16398c2ecf20Sopenharmony_ci */ 16408c2ecf20Sopenharmony_cistatic bool bq27xxx_battery_undertemp(struct bq27xxx_device_info *di, u16 flags) 16418c2ecf20Sopenharmony_ci{ 16428c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_UTOT) 16438c2ecf20Sopenharmony_ci return flags & BQ27XXX_FLAG_UT; 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci return false; 16468c2ecf20Sopenharmony_ci} 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci/* 16498c2ecf20Sopenharmony_ci * Returns true if a low state of charge condition is detected 16508c2ecf20Sopenharmony_ci */ 16518c2ecf20Sopenharmony_cistatic bool bq27xxx_battery_dead(struct bq27xxx_device_info *di, u16 flags) 16528c2ecf20Sopenharmony_ci{ 16538c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 16548c2ecf20Sopenharmony_ci return flags & (BQ27000_FLAG_EDV1 | BQ27000_FLAG_EDVF); 16558c2ecf20Sopenharmony_ci else if (di->opts & BQ27Z561_O_BITS) 16568c2ecf20Sopenharmony_ci return flags & BQ27Z561_FLAG_FDC; 16578c2ecf20Sopenharmony_ci else 16588c2ecf20Sopenharmony_ci return flags & (BQ27XXX_FLAG_SOC1 | BQ27XXX_FLAG_SOCF); 16598c2ecf20Sopenharmony_ci} 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci/* 16628c2ecf20Sopenharmony_ci * Returns true if reported battery capacity is inaccurate 16638c2ecf20Sopenharmony_ci */ 16648c2ecf20Sopenharmony_cistatic bool bq27xxx_battery_capacity_inaccurate(struct bq27xxx_device_info *di, 16658c2ecf20Sopenharmony_ci u16 flags) 16668c2ecf20Sopenharmony_ci{ 16678c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_HAS_CI) 16688c2ecf20Sopenharmony_ci return (flags & BQ27000_FLAG_CI); 16698c2ecf20Sopenharmony_ci else 16708c2ecf20Sopenharmony_ci return false; 16718c2ecf20Sopenharmony_ci} 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_cistatic int bq27xxx_battery_read_health(struct bq27xxx_device_info *di) 16748c2ecf20Sopenharmony_ci{ 16758c2ecf20Sopenharmony_ci /* Unlikely but important to return first */ 16768c2ecf20Sopenharmony_ci if (unlikely(bq27xxx_battery_overtemp(di, di->cache.flags))) 16778c2ecf20Sopenharmony_ci return POWER_SUPPLY_HEALTH_OVERHEAT; 16788c2ecf20Sopenharmony_ci if (unlikely(bq27xxx_battery_undertemp(di, di->cache.flags))) 16798c2ecf20Sopenharmony_ci return POWER_SUPPLY_HEALTH_COLD; 16808c2ecf20Sopenharmony_ci if (unlikely(bq27xxx_battery_dead(di, di->cache.flags))) 16818c2ecf20Sopenharmony_ci return POWER_SUPPLY_HEALTH_DEAD; 16828c2ecf20Sopenharmony_ci if (unlikely(bq27xxx_battery_capacity_inaccurate(di, di->cache.flags))) 16838c2ecf20Sopenharmony_ci return POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED; 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci return POWER_SUPPLY_HEALTH_GOOD; 16868c2ecf20Sopenharmony_ci} 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_cistatic bool bq27xxx_battery_is_full(struct bq27xxx_device_info *di, int flags) 16898c2ecf20Sopenharmony_ci{ 16908c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 16918c2ecf20Sopenharmony_ci return (flags & BQ27000_FLAG_FC); 16928c2ecf20Sopenharmony_ci else if (di->opts & BQ27Z561_O_BITS) 16938c2ecf20Sopenharmony_ci return (flags & BQ27Z561_FLAG_FC); 16948c2ecf20Sopenharmony_ci else 16958c2ecf20Sopenharmony_ci return (flags & BQ27XXX_FLAG_FC); 16968c2ecf20Sopenharmony_ci} 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci/* 16998c2ecf20Sopenharmony_ci * Return the battery average current in µA and the status 17008c2ecf20Sopenharmony_ci * Note that current can be negative signed as well 17018c2ecf20Sopenharmony_ci * Or 0 if something fails. 17028c2ecf20Sopenharmony_ci */ 17038c2ecf20Sopenharmony_cistatic int bq27xxx_battery_current_and_status( 17048c2ecf20Sopenharmony_ci struct bq27xxx_device_info *di, 17058c2ecf20Sopenharmony_ci union power_supply_propval *val_curr, 17068c2ecf20Sopenharmony_ci union power_supply_propval *val_status, 17078c2ecf20Sopenharmony_ci struct bq27xxx_reg_cache *cache) 17088c2ecf20Sopenharmony_ci{ 17098c2ecf20Sopenharmony_ci bool single_flags = (di->opts & BQ27XXX_O_ZERO); 17108c2ecf20Sopenharmony_ci int curr; 17118c2ecf20Sopenharmony_ci int flags; 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_ci curr = bq27xxx_read(di, BQ27XXX_REG_AI, false); 17148c2ecf20Sopenharmony_ci if (curr < 0) { 17158c2ecf20Sopenharmony_ci dev_err(di->dev, "error reading current\n"); 17168c2ecf20Sopenharmony_ci return curr; 17178c2ecf20Sopenharmony_ci } 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci if (cache) { 17208c2ecf20Sopenharmony_ci flags = cache->flags; 17218c2ecf20Sopenharmony_ci } else { 17228c2ecf20Sopenharmony_ci flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, single_flags); 17238c2ecf20Sopenharmony_ci if (flags < 0) { 17248c2ecf20Sopenharmony_ci dev_err(di->dev, "error reading flags\n"); 17258c2ecf20Sopenharmony_ci return flags; 17268c2ecf20Sopenharmony_ci } 17278c2ecf20Sopenharmony_ci } 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) { 17308c2ecf20Sopenharmony_ci if (!(flags & BQ27000_FLAG_CHGS)) { 17318c2ecf20Sopenharmony_ci dev_dbg(di->dev, "negative current!\n"); 17328c2ecf20Sopenharmony_ci curr = -curr; 17338c2ecf20Sopenharmony_ci } 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci curr = curr * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; 17368c2ecf20Sopenharmony_ci } else { 17378c2ecf20Sopenharmony_ci /* Other gauges return signed value */ 17388c2ecf20Sopenharmony_ci curr = (int)((s16)curr) * 1000; 17398c2ecf20Sopenharmony_ci } 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci if (val_curr) 17428c2ecf20Sopenharmony_ci val_curr->intval = curr; 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci if (val_status) { 17458c2ecf20Sopenharmony_ci if (curr > 0) { 17468c2ecf20Sopenharmony_ci val_status->intval = POWER_SUPPLY_STATUS_CHARGING; 17478c2ecf20Sopenharmony_ci } else if (curr < 0) { 17488c2ecf20Sopenharmony_ci val_status->intval = POWER_SUPPLY_STATUS_DISCHARGING; 17498c2ecf20Sopenharmony_ci } else { 17508c2ecf20Sopenharmony_ci if (bq27xxx_battery_is_full(di, flags)) 17518c2ecf20Sopenharmony_ci val_status->intval = POWER_SUPPLY_STATUS_FULL; 17528c2ecf20Sopenharmony_ci else 17538c2ecf20Sopenharmony_ci val_status->intval = 17548c2ecf20Sopenharmony_ci POWER_SUPPLY_STATUS_NOT_CHARGING; 17558c2ecf20Sopenharmony_ci } 17568c2ecf20Sopenharmony_ci } 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_ci return 0; 17598c2ecf20Sopenharmony_ci} 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_cistatic void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di) 17628c2ecf20Sopenharmony_ci{ 17638c2ecf20Sopenharmony_ci union power_supply_propval status = di->last_status; 17648c2ecf20Sopenharmony_ci struct bq27xxx_reg_cache cache = {0, }; 17658c2ecf20Sopenharmony_ci bool has_singe_flag = di->opts & BQ27XXX_O_ZERO; 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag); 17688c2ecf20Sopenharmony_ci if ((cache.flags & 0xff) == 0xff) 17698c2ecf20Sopenharmony_ci cache.flags = -1; /* read error */ 17708c2ecf20Sopenharmony_ci if (cache.flags >= 0) { 17718c2ecf20Sopenharmony_ci cache.temperature = bq27xxx_battery_read_temperature(di); 17728c2ecf20Sopenharmony_ci if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR) 17738c2ecf20Sopenharmony_ci cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE); 17748c2ecf20Sopenharmony_ci if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR) 17758c2ecf20Sopenharmony_ci cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP); 17768c2ecf20Sopenharmony_ci if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR) 17778c2ecf20Sopenharmony_ci cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF); 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ci cache.charge_full = bq27xxx_battery_read_fcc(di); 17808c2ecf20Sopenharmony_ci cache.capacity = bq27xxx_battery_read_soc(di); 17818c2ecf20Sopenharmony_ci if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR) 17828c2ecf20Sopenharmony_ci cache.energy = bq27xxx_battery_read_energy(di); 17838c2ecf20Sopenharmony_ci di->cache.flags = cache.flags; 17848c2ecf20Sopenharmony_ci cache.health = bq27xxx_battery_read_health(di); 17858c2ecf20Sopenharmony_ci if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR) 17868c2ecf20Sopenharmony_ci cache.cycle_count = bq27xxx_battery_read_cyct(di); 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci /* 17898c2ecf20Sopenharmony_ci * On gauges with signed current reporting the current must be 17908c2ecf20Sopenharmony_ci * checked to detect charging <-> discharging status changes. 17918c2ecf20Sopenharmony_ci */ 17928c2ecf20Sopenharmony_ci if (!(di->opts & BQ27XXX_O_ZERO)) 17938c2ecf20Sopenharmony_ci bq27xxx_battery_current_and_status(di, NULL, &status, &cache); 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci /* We only have to read charge design full once */ 17968c2ecf20Sopenharmony_ci if (di->charge_design_full <= 0) 17978c2ecf20Sopenharmony_ci di->charge_design_full = bq27xxx_battery_read_dcap(di); 17988c2ecf20Sopenharmony_ci } 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci if ((di->cache.capacity != cache.capacity) || 18018c2ecf20Sopenharmony_ci (di->cache.flags != cache.flags) || 18028c2ecf20Sopenharmony_ci (di->last_status.intval != status.intval)) { 18038c2ecf20Sopenharmony_ci di->last_status.intval = status.intval; 18048c2ecf20Sopenharmony_ci power_supply_changed(di->bat); 18058c2ecf20Sopenharmony_ci } 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) 18088c2ecf20Sopenharmony_ci di->cache = cache; 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_ci di->last_update = jiffies; 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci if (!di->removed && poll_interval > 0) 18138c2ecf20Sopenharmony_ci mod_delayed_work(system_wq, &di->work, poll_interval * HZ); 18148c2ecf20Sopenharmony_ci} 18158c2ecf20Sopenharmony_ci 18168c2ecf20Sopenharmony_civoid bq27xxx_battery_update(struct bq27xxx_device_info *di) 18178c2ecf20Sopenharmony_ci{ 18188c2ecf20Sopenharmony_ci mutex_lock(&di->lock); 18198c2ecf20Sopenharmony_ci bq27xxx_battery_update_unlocked(di); 18208c2ecf20Sopenharmony_ci mutex_unlock(&di->lock); 18218c2ecf20Sopenharmony_ci} 18228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(bq27xxx_battery_update); 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_cistatic void bq27xxx_battery_poll(struct work_struct *work) 18258c2ecf20Sopenharmony_ci{ 18268c2ecf20Sopenharmony_ci struct bq27xxx_device_info *di = 18278c2ecf20Sopenharmony_ci container_of(work, struct bq27xxx_device_info, 18288c2ecf20Sopenharmony_ci work.work); 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci bq27xxx_battery_update(di); 18318c2ecf20Sopenharmony_ci} 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_ci/* 18348c2ecf20Sopenharmony_ci * Get the average power in µW 18358c2ecf20Sopenharmony_ci * Return < 0 if something fails. 18368c2ecf20Sopenharmony_ci */ 18378c2ecf20Sopenharmony_cistatic int bq27xxx_battery_pwr_avg(struct bq27xxx_device_info *di, 18388c2ecf20Sopenharmony_ci union power_supply_propval *val) 18398c2ecf20Sopenharmony_ci{ 18408c2ecf20Sopenharmony_ci int power; 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ci power = bq27xxx_read(di, BQ27XXX_REG_AP, false); 18438c2ecf20Sopenharmony_ci if (power < 0) { 18448c2ecf20Sopenharmony_ci dev_err(di->dev, 18458c2ecf20Sopenharmony_ci "error reading average power register %02x: %d\n", 18468c2ecf20Sopenharmony_ci BQ27XXX_REG_AP, power); 18478c2ecf20Sopenharmony_ci return power; 18488c2ecf20Sopenharmony_ci } 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 18518c2ecf20Sopenharmony_ci val->intval = (power * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS; 18528c2ecf20Sopenharmony_ci else 18538c2ecf20Sopenharmony_ci /* Other gauges return a signed value in units of 10mW */ 18548c2ecf20Sopenharmony_ci val->intval = (int)((s16)power) * 10000; 18558c2ecf20Sopenharmony_ci 18568c2ecf20Sopenharmony_ci return 0; 18578c2ecf20Sopenharmony_ci} 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_cistatic int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di, 18608c2ecf20Sopenharmony_ci union power_supply_propval *val) 18618c2ecf20Sopenharmony_ci{ 18628c2ecf20Sopenharmony_ci int level; 18638c2ecf20Sopenharmony_ci 18648c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) { 18658c2ecf20Sopenharmony_ci if (di->cache.flags & BQ27000_FLAG_FC) 18668c2ecf20Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; 18678c2ecf20Sopenharmony_ci else if (di->cache.flags & BQ27000_FLAG_EDV1) 18688c2ecf20Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_LOW; 18698c2ecf20Sopenharmony_ci else if (di->cache.flags & BQ27000_FLAG_EDVF) 18708c2ecf20Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; 18718c2ecf20Sopenharmony_ci else 18728c2ecf20Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 18738c2ecf20Sopenharmony_ci } else if (di->opts & BQ27Z561_O_BITS) { 18748c2ecf20Sopenharmony_ci if (di->cache.flags & BQ27Z561_FLAG_FC) 18758c2ecf20Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; 18768c2ecf20Sopenharmony_ci else if (di->cache.flags & BQ27Z561_FLAG_FDC) 18778c2ecf20Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; 18788c2ecf20Sopenharmony_ci else 18798c2ecf20Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 18808c2ecf20Sopenharmony_ci } else { 18818c2ecf20Sopenharmony_ci if (di->cache.flags & BQ27XXX_FLAG_FC) 18828c2ecf20Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; 18838c2ecf20Sopenharmony_ci else if (di->cache.flags & BQ27XXX_FLAG_SOC1) 18848c2ecf20Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_LOW; 18858c2ecf20Sopenharmony_ci else if (di->cache.flags & BQ27XXX_FLAG_SOCF) 18868c2ecf20Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; 18878c2ecf20Sopenharmony_ci else 18888c2ecf20Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 18898c2ecf20Sopenharmony_ci } 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci val->intval = level; 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_ci return 0; 18948c2ecf20Sopenharmony_ci} 18958c2ecf20Sopenharmony_ci 18968c2ecf20Sopenharmony_ci/* 18978c2ecf20Sopenharmony_ci * Return the battery Voltage in millivolts 18988c2ecf20Sopenharmony_ci * Or < 0 if something fails. 18998c2ecf20Sopenharmony_ci */ 19008c2ecf20Sopenharmony_cistatic int bq27xxx_battery_voltage(struct bq27xxx_device_info *di, 19018c2ecf20Sopenharmony_ci union power_supply_propval *val) 19028c2ecf20Sopenharmony_ci{ 19038c2ecf20Sopenharmony_ci int volt; 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_ci volt = bq27xxx_read(di, BQ27XXX_REG_VOLT, false); 19068c2ecf20Sopenharmony_ci if (volt < 0) { 19078c2ecf20Sopenharmony_ci dev_err(di->dev, "error reading voltage\n"); 19088c2ecf20Sopenharmony_ci return volt; 19098c2ecf20Sopenharmony_ci } 19108c2ecf20Sopenharmony_ci 19118c2ecf20Sopenharmony_ci val->intval = volt * 1000; 19128c2ecf20Sopenharmony_ci 19138c2ecf20Sopenharmony_ci return 0; 19148c2ecf20Sopenharmony_ci} 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_cistatic int bq27xxx_simple_value(int value, 19178c2ecf20Sopenharmony_ci union power_supply_propval *val) 19188c2ecf20Sopenharmony_ci{ 19198c2ecf20Sopenharmony_ci if (value < 0) 19208c2ecf20Sopenharmony_ci return value; 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci val->intval = value; 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci return 0; 19258c2ecf20Sopenharmony_ci} 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_cistatic int bq27xxx_battery_get_property(struct power_supply *psy, 19288c2ecf20Sopenharmony_ci enum power_supply_property psp, 19298c2ecf20Sopenharmony_ci union power_supply_propval *val) 19308c2ecf20Sopenharmony_ci{ 19318c2ecf20Sopenharmony_ci int ret = 0; 19328c2ecf20Sopenharmony_ci struct bq27xxx_device_info *di = power_supply_get_drvdata(psy); 19338c2ecf20Sopenharmony_ci 19348c2ecf20Sopenharmony_ci mutex_lock(&di->lock); 19358c2ecf20Sopenharmony_ci if (time_is_before_jiffies(di->last_update + 5 * HZ)) 19368c2ecf20Sopenharmony_ci bq27xxx_battery_update_unlocked(di); 19378c2ecf20Sopenharmony_ci mutex_unlock(&di->lock); 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0) 19408c2ecf20Sopenharmony_ci return -ENODEV; 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_ci switch (psp) { 19438c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_STATUS: 19448c2ecf20Sopenharmony_ci ret = bq27xxx_battery_current_and_status(di, NULL, val, NULL); 19458c2ecf20Sopenharmony_ci break; 19468c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_VOLTAGE_NOW: 19478c2ecf20Sopenharmony_ci ret = bq27xxx_battery_voltage(di, val); 19488c2ecf20Sopenharmony_ci break; 19498c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_PRESENT: 19508c2ecf20Sopenharmony_ci val->intval = di->cache.flags < 0 ? 0 : 1; 19518c2ecf20Sopenharmony_ci break; 19528c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CURRENT_NOW: 19538c2ecf20Sopenharmony_ci ret = bq27xxx_battery_current_and_status(di, val, NULL, NULL); 19548c2ecf20Sopenharmony_ci break; 19558c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CAPACITY: 19568c2ecf20Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.capacity, val); 19578c2ecf20Sopenharmony_ci break; 19588c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CAPACITY_LEVEL: 19598c2ecf20Sopenharmony_ci ret = bq27xxx_battery_capacity_level(di, val); 19608c2ecf20Sopenharmony_ci break; 19618c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_TEMP: 19628c2ecf20Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.temperature, val); 19638c2ecf20Sopenharmony_ci if (ret == 0) 19648c2ecf20Sopenharmony_ci val->intval -= 2731; /* convert decidegree k to c */ 19658c2ecf20Sopenharmony_ci break; 19668c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: 19678c2ecf20Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.time_to_empty, val); 19688c2ecf20Sopenharmony_ci break; 19698c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: 19708c2ecf20Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.time_to_empty_avg, val); 19718c2ecf20Sopenharmony_ci break; 19728c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: 19738c2ecf20Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.time_to_full, val); 19748c2ecf20Sopenharmony_ci break; 19758c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_TECHNOLOGY: 19768c2ecf20Sopenharmony_ci if (di->opts & BQ27XXX_O_MUL_CHEM) 19778c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; 19788c2ecf20Sopenharmony_ci else 19798c2ecf20Sopenharmony_ci val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 19808c2ecf20Sopenharmony_ci break; 19818c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CHARGE_NOW: 19828c2ecf20Sopenharmony_ci ret = bq27xxx_simple_value(bq27xxx_battery_read_nac(di), val); 19838c2ecf20Sopenharmony_ci break; 19848c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CHARGE_FULL: 19858c2ecf20Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.charge_full, val); 19868c2ecf20Sopenharmony_ci break; 19878c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 19888c2ecf20Sopenharmony_ci ret = bq27xxx_simple_value(di->charge_design_full, val); 19898c2ecf20Sopenharmony_ci break; 19908c2ecf20Sopenharmony_ci /* 19918c2ecf20Sopenharmony_ci * TODO: Implement these to make registers set from 19928c2ecf20Sopenharmony_ci * power_supply_battery_info visible in sysfs. 19938c2ecf20Sopenharmony_ci */ 19948c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: 19958c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 19968c2ecf20Sopenharmony_ci return -EINVAL; 19978c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_CYCLE_COUNT: 19988c2ecf20Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.cycle_count, val); 19998c2ecf20Sopenharmony_ci break; 20008c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_ENERGY_NOW: 20018c2ecf20Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.energy, val); 20028c2ecf20Sopenharmony_ci break; 20038c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_POWER_AVG: 20048c2ecf20Sopenharmony_ci ret = bq27xxx_battery_pwr_avg(di, val); 20058c2ecf20Sopenharmony_ci break; 20068c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_HEALTH: 20078c2ecf20Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.health, val); 20088c2ecf20Sopenharmony_ci break; 20098c2ecf20Sopenharmony_ci case POWER_SUPPLY_PROP_MANUFACTURER: 20108c2ecf20Sopenharmony_ci val->strval = BQ27XXX_MANUFACTURER; 20118c2ecf20Sopenharmony_ci break; 20128c2ecf20Sopenharmony_ci default: 20138c2ecf20Sopenharmony_ci return -EINVAL; 20148c2ecf20Sopenharmony_ci } 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci return ret; 20178c2ecf20Sopenharmony_ci} 20188c2ecf20Sopenharmony_ci 20198c2ecf20Sopenharmony_cistatic void bq27xxx_external_power_changed(struct power_supply *psy) 20208c2ecf20Sopenharmony_ci{ 20218c2ecf20Sopenharmony_ci struct bq27xxx_device_info *di = power_supply_get_drvdata(psy); 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci /* After charger plug in/out wait 0.5s for things to stabilize */ 20248c2ecf20Sopenharmony_ci mod_delayed_work(system_wq, &di->work, HZ / 2); 20258c2ecf20Sopenharmony_ci} 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_ciint bq27xxx_battery_setup(struct bq27xxx_device_info *di) 20288c2ecf20Sopenharmony_ci{ 20298c2ecf20Sopenharmony_ci struct power_supply_desc *psy_desc; 20308c2ecf20Sopenharmony_ci struct power_supply_config psy_cfg = { 20318c2ecf20Sopenharmony_ci .of_node = di->dev->of_node, 20328c2ecf20Sopenharmony_ci .drv_data = di, 20338c2ecf20Sopenharmony_ci }; 20348c2ecf20Sopenharmony_ci 20358c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll); 20368c2ecf20Sopenharmony_ci mutex_init(&di->lock); 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_ci di->regs = bq27xxx_chip_data[di->chip].regs; 20398c2ecf20Sopenharmony_ci di->unseal_key = bq27xxx_chip_data[di->chip].unseal_key; 20408c2ecf20Sopenharmony_ci di->dm_regs = bq27xxx_chip_data[di->chip].dm_regs; 20418c2ecf20Sopenharmony_ci di->opts = bq27xxx_chip_data[di->chip].opts; 20428c2ecf20Sopenharmony_ci 20438c2ecf20Sopenharmony_ci psy_desc = devm_kzalloc(di->dev, sizeof(*psy_desc), GFP_KERNEL); 20448c2ecf20Sopenharmony_ci if (!psy_desc) 20458c2ecf20Sopenharmony_ci return -ENOMEM; 20468c2ecf20Sopenharmony_ci 20478c2ecf20Sopenharmony_ci psy_desc->name = di->name; 20488c2ecf20Sopenharmony_ci psy_desc->type = POWER_SUPPLY_TYPE_BATTERY; 20498c2ecf20Sopenharmony_ci psy_desc->properties = bq27xxx_chip_data[di->chip].props; 20508c2ecf20Sopenharmony_ci psy_desc->num_properties = bq27xxx_chip_data[di->chip].props_size; 20518c2ecf20Sopenharmony_ci psy_desc->get_property = bq27xxx_battery_get_property; 20528c2ecf20Sopenharmony_ci psy_desc->external_power_changed = bq27xxx_external_power_changed; 20538c2ecf20Sopenharmony_ci 20548c2ecf20Sopenharmony_ci di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg); 20558c2ecf20Sopenharmony_ci if (IS_ERR(di->bat)) 20568c2ecf20Sopenharmony_ci return dev_err_probe(di->dev, PTR_ERR(di->bat), 20578c2ecf20Sopenharmony_ci "failed to register battery\n"); 20588c2ecf20Sopenharmony_ci 20598c2ecf20Sopenharmony_ci bq27xxx_battery_settings(di); 20608c2ecf20Sopenharmony_ci bq27xxx_battery_update(di); 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_ci mutex_lock(&bq27xxx_list_lock); 20638c2ecf20Sopenharmony_ci list_add(&di->list, &bq27xxx_battery_devices); 20648c2ecf20Sopenharmony_ci mutex_unlock(&bq27xxx_list_lock); 20658c2ecf20Sopenharmony_ci 20668c2ecf20Sopenharmony_ci return 0; 20678c2ecf20Sopenharmony_ci} 20688c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(bq27xxx_battery_setup); 20698c2ecf20Sopenharmony_ci 20708c2ecf20Sopenharmony_civoid bq27xxx_battery_teardown(struct bq27xxx_device_info *di) 20718c2ecf20Sopenharmony_ci{ 20728c2ecf20Sopenharmony_ci mutex_lock(&bq27xxx_list_lock); 20738c2ecf20Sopenharmony_ci list_del(&di->list); 20748c2ecf20Sopenharmony_ci mutex_unlock(&bq27xxx_list_lock); 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_ci /* Set removed to avoid bq27xxx_battery_update() re-queuing the work */ 20778c2ecf20Sopenharmony_ci mutex_lock(&di->lock); 20788c2ecf20Sopenharmony_ci di->removed = true; 20798c2ecf20Sopenharmony_ci mutex_unlock(&di->lock); 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&di->work); 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci power_supply_unregister(di->bat); 20848c2ecf20Sopenharmony_ci mutex_destroy(&di->lock); 20858c2ecf20Sopenharmony_ci} 20868c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(bq27xxx_battery_teardown); 20878c2ecf20Sopenharmony_ci 20888c2ecf20Sopenharmony_ciMODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); 20898c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("BQ27xxx battery monitor driver"); 20908c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 2091