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, &param_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