162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * BQ27xxx battery driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it> 662306a36Sopenharmony_ci * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it> 762306a36Sopenharmony_ci * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de> 862306a36Sopenharmony_ci * Copyright (C) 2011 Pali Rohár <pali@kernel.org> 962306a36Sopenharmony_ci * Copyright (C) 2017 Liam Breck <kernel@networkimprov.net> 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Datasheets: 1462306a36Sopenharmony_ci * https://www.ti.com/product/bq27000 1562306a36Sopenharmony_ci * https://www.ti.com/product/bq27200 1662306a36Sopenharmony_ci * https://www.ti.com/product/bq27010 1762306a36Sopenharmony_ci * https://www.ti.com/product/bq27210 1862306a36Sopenharmony_ci * https://www.ti.com/product/bq27500 1962306a36Sopenharmony_ci * https://www.ti.com/product/bq27510-g1 2062306a36Sopenharmony_ci * https://www.ti.com/product/bq27510-g2 2162306a36Sopenharmony_ci * https://www.ti.com/product/bq27510-g3 2262306a36Sopenharmony_ci * https://www.ti.com/product/bq27520-g1 2362306a36Sopenharmony_ci * https://www.ti.com/product/bq27520-g2 2462306a36Sopenharmony_ci * https://www.ti.com/product/bq27520-g3 2562306a36Sopenharmony_ci * https://www.ti.com/product/bq27520-g4 2662306a36Sopenharmony_ci * https://www.ti.com/product/bq27530-g1 2762306a36Sopenharmony_ci * https://www.ti.com/product/bq27531-g1 2862306a36Sopenharmony_ci * https://www.ti.com/product/bq27541-g1 2962306a36Sopenharmony_ci * https://www.ti.com/product/bq27542-g1 3062306a36Sopenharmony_ci * https://www.ti.com/product/bq27546-g1 3162306a36Sopenharmony_ci * https://www.ti.com/product/bq27742-g1 3262306a36Sopenharmony_ci * https://www.ti.com/product/bq27545-g1 3362306a36Sopenharmony_ci * https://www.ti.com/product/bq27421-g1 3462306a36Sopenharmony_ci * https://www.ti.com/product/bq27425-g1 3562306a36Sopenharmony_ci * https://www.ti.com/product/bq27426 3662306a36Sopenharmony_ci * https://www.ti.com/product/bq27411-g1 3762306a36Sopenharmony_ci * https://www.ti.com/product/bq27441-g1 3862306a36Sopenharmony_ci * https://www.ti.com/product/bq27621-g1 3962306a36Sopenharmony_ci * https://www.ti.com/product/bq27z561 4062306a36Sopenharmony_ci * https://www.ti.com/product/bq28z610 4162306a36Sopenharmony_ci * https://www.ti.com/product/bq34z100-g1 4262306a36Sopenharmony_ci * https://www.ti.com/product/bq78z100 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#include <linux/device.h> 4662306a36Sopenharmony_ci#include <linux/module.h> 4762306a36Sopenharmony_ci#include <linux/mutex.h> 4862306a36Sopenharmony_ci#include <linux/param.h> 4962306a36Sopenharmony_ci#include <linux/jiffies.h> 5062306a36Sopenharmony_ci#include <linux/workqueue.h> 5162306a36Sopenharmony_ci#include <linux/delay.h> 5262306a36Sopenharmony_ci#include <linux/platform_device.h> 5362306a36Sopenharmony_ci#include <linux/power_supply.h> 5462306a36Sopenharmony_ci#include <linux/slab.h> 5562306a36Sopenharmony_ci#include <linux/of.h> 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#include <linux/power/bq27xxx_battery.h> 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define BQ27XXX_MANUFACTURER "Texas Instruments" 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* BQ27XXX Flags */ 6262306a36Sopenharmony_ci#define BQ27XXX_FLAG_DSC BIT(0) 6362306a36Sopenharmony_ci#define BQ27XXX_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */ 6462306a36Sopenharmony_ci#define BQ27XXX_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */ 6562306a36Sopenharmony_ci#define BQ27XXX_FLAG_CFGUP BIT(4) 6662306a36Sopenharmony_ci#define BQ27XXX_FLAG_FC BIT(9) 6762306a36Sopenharmony_ci#define BQ27XXX_FLAG_OTD BIT(14) 6862306a36Sopenharmony_ci#define BQ27XXX_FLAG_OTC BIT(15) 6962306a36Sopenharmony_ci#define BQ27XXX_FLAG_UT BIT(14) 7062306a36Sopenharmony_ci#define BQ27XXX_FLAG_OT BIT(15) 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* BQ27000 has different layout for Flags register */ 7362306a36Sopenharmony_ci#define BQ27000_FLAG_EDVF BIT(0) /* Final End-of-Discharge-Voltage flag */ 7462306a36Sopenharmony_ci#define BQ27000_FLAG_EDV1 BIT(1) /* First End-of-Discharge-Voltage flag */ 7562306a36Sopenharmony_ci#define BQ27000_FLAG_CI BIT(4) /* Capacity Inaccurate flag */ 7662306a36Sopenharmony_ci#define BQ27000_FLAG_FC BIT(5) 7762306a36Sopenharmony_ci#define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */ 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* BQ27Z561 has different layout for Flags register */ 8062306a36Sopenharmony_ci#define BQ27Z561_FLAG_FDC BIT(4) /* Battery fully discharged */ 8162306a36Sopenharmony_ci#define BQ27Z561_FLAG_FC BIT(5) /* Battery fully charged */ 8262306a36Sopenharmony_ci#define BQ27Z561_FLAG_DIS_CH BIT(6) /* Battery is discharging */ 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/* control register params */ 8562306a36Sopenharmony_ci#define BQ27XXX_SEALED 0x20 8662306a36Sopenharmony_ci#define BQ27XXX_SET_CFGUPDATE 0x13 8762306a36Sopenharmony_ci#define BQ27XXX_SOFT_RESET 0x42 8862306a36Sopenharmony_ci#define BQ27XXX_RESET 0x41 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci#define BQ27XXX_RS (20) /* Resistor sense mOhm */ 9162306a36Sopenharmony_ci#define BQ27XXX_POWER_CONSTANT (29200) /* 29.2 µV^2 * 1000 */ 9262306a36Sopenharmony_ci#define BQ27XXX_CURRENT_CONSTANT (3570) /* 3.57 µV * 1000 */ 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#define INVALID_REG_ADDR 0xff 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* 9762306a36Sopenharmony_ci * bq27xxx_reg_index - Register names 9862306a36Sopenharmony_ci * 9962306a36Sopenharmony_ci * These are indexes into a device's register mapping array. 10062306a36Sopenharmony_ci */ 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cienum bq27xxx_reg_index { 10362306a36Sopenharmony_ci BQ27XXX_REG_CTRL = 0, /* Control */ 10462306a36Sopenharmony_ci BQ27XXX_REG_TEMP, /* Temperature */ 10562306a36Sopenharmony_ci BQ27XXX_REG_INT_TEMP, /* Internal Temperature */ 10662306a36Sopenharmony_ci BQ27XXX_REG_VOLT, /* Voltage */ 10762306a36Sopenharmony_ci BQ27XXX_REG_AI, /* Average Current */ 10862306a36Sopenharmony_ci BQ27XXX_REG_FLAGS, /* Flags */ 10962306a36Sopenharmony_ci BQ27XXX_REG_TTE, /* Time-to-Empty */ 11062306a36Sopenharmony_ci BQ27XXX_REG_TTF, /* Time-to-Full */ 11162306a36Sopenharmony_ci BQ27XXX_REG_TTES, /* Time-to-Empty Standby */ 11262306a36Sopenharmony_ci BQ27XXX_REG_TTECP, /* Time-to-Empty at Constant Power */ 11362306a36Sopenharmony_ci BQ27XXX_REG_NAC, /* Nominal Available Capacity */ 11462306a36Sopenharmony_ci BQ27XXX_REG_RC, /* Remaining Capacity */ 11562306a36Sopenharmony_ci BQ27XXX_REG_FCC, /* Full Charge Capacity */ 11662306a36Sopenharmony_ci BQ27XXX_REG_CYCT, /* Cycle Count */ 11762306a36Sopenharmony_ci BQ27XXX_REG_AE, /* Available Energy */ 11862306a36Sopenharmony_ci BQ27XXX_REG_SOC, /* State-of-Charge */ 11962306a36Sopenharmony_ci BQ27XXX_REG_DCAP, /* Design Capacity */ 12062306a36Sopenharmony_ci BQ27XXX_REG_AP, /* Average Power */ 12162306a36Sopenharmony_ci BQ27XXX_DM_CTRL, /* Block Data Control */ 12262306a36Sopenharmony_ci BQ27XXX_DM_CLASS, /* Data Class */ 12362306a36Sopenharmony_ci BQ27XXX_DM_BLOCK, /* Data Block */ 12462306a36Sopenharmony_ci BQ27XXX_DM_DATA, /* Block Data */ 12562306a36Sopenharmony_ci BQ27XXX_DM_CKSUM, /* Block Data Checksum */ 12662306a36Sopenharmony_ci BQ27XXX_REG_MAX, /* sentinel */ 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci#define BQ27XXX_DM_REG_ROWS \ 13062306a36Sopenharmony_ci [BQ27XXX_DM_CTRL] = 0x61, \ 13162306a36Sopenharmony_ci [BQ27XXX_DM_CLASS] = 0x3e, \ 13262306a36Sopenharmony_ci [BQ27XXX_DM_BLOCK] = 0x3f, \ 13362306a36Sopenharmony_ci [BQ27XXX_DM_DATA] = 0x40, \ 13462306a36Sopenharmony_ci [BQ27XXX_DM_CKSUM] = 0x60 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci/* Register mappings */ 13762306a36Sopenharmony_cistatic u8 13862306a36Sopenharmony_ci bq27000_regs[BQ27XXX_REG_MAX] = { 13962306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 14062306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 14162306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 14262306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 14362306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 14462306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 14562306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 14662306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 14762306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 14862306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = 0x26, 14962306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 15062306a36Sopenharmony_ci [BQ27XXX_REG_RC] = INVALID_REG_ADDR, 15162306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 15262306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 15362306a36Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 15462306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x0b, 15562306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x76, 15662306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 15762306a36Sopenharmony_ci [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR, 15862306a36Sopenharmony_ci [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR, 15962306a36Sopenharmony_ci [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR, 16062306a36Sopenharmony_ci [BQ27XXX_DM_DATA] = INVALID_REG_ADDR, 16162306a36Sopenharmony_ci [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR, 16262306a36Sopenharmony_ci }, 16362306a36Sopenharmony_ci bq27010_regs[BQ27XXX_REG_MAX] = { 16462306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 16562306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 16662306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 16762306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 16862306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 16962306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 17062306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 17162306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 17262306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 17362306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = 0x26, 17462306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 17562306a36Sopenharmony_ci [BQ27XXX_REG_RC] = INVALID_REG_ADDR, 17662306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 17762306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 17862306a36Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 17962306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x0b, 18062306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x76, 18162306a36Sopenharmony_ci [BQ27XXX_REG_AP] = INVALID_REG_ADDR, 18262306a36Sopenharmony_ci [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR, 18362306a36Sopenharmony_ci [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR, 18462306a36Sopenharmony_ci [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR, 18562306a36Sopenharmony_ci [BQ27XXX_DM_DATA] = INVALID_REG_ADDR, 18662306a36Sopenharmony_ci [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR, 18762306a36Sopenharmony_ci }, 18862306a36Sopenharmony_ci bq2750x_regs[BQ27XXX_REG_MAX] = { 18962306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 19062306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 19162306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x28, 19262306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 19362306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 19462306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 19562306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 19662306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 19762306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1a, 19862306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 19962306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 20062306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 20162306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 20262306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 20362306a36Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 20462306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 20562306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 20662306a36Sopenharmony_ci [BQ27XXX_REG_AP] = INVALID_REG_ADDR, 20762306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 20862306a36Sopenharmony_ci }, 20962306a36Sopenharmony_ci#define bq2751x_regs bq27510g3_regs 21062306a36Sopenharmony_ci#define bq2752x_regs bq27510g3_regs 21162306a36Sopenharmony_ci bq27500_regs[BQ27XXX_REG_MAX] = { 21262306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 21362306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 21462306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 21562306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 21662306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 21762306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 21862306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 21962306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 22062306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 22162306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = 0x26, 22262306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 22362306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 22462306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 22562306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 22662306a36Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 22762306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 22862306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 22962306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 23062306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 23162306a36Sopenharmony_ci }, 23262306a36Sopenharmony_ci#define bq27510g1_regs bq27500_regs 23362306a36Sopenharmony_ci#define bq27510g2_regs bq27500_regs 23462306a36Sopenharmony_ci bq27510g3_regs[BQ27XXX_REG_MAX] = { 23562306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 23662306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 23762306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x28, 23862306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 23962306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 24062306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 24162306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 24262306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 24362306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1a, 24462306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 24562306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 24662306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 24762306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 24862306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x1e, 24962306a36Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 25062306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x20, 25162306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x2e, 25262306a36Sopenharmony_ci [BQ27XXX_REG_AP] = INVALID_REG_ADDR, 25362306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 25462306a36Sopenharmony_ci }, 25562306a36Sopenharmony_ci bq27520g1_regs[BQ27XXX_REG_MAX] = { 25662306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 25762306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 25862306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 25962306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 26062306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 26162306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 26262306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 26362306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 26462306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 26562306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = 0x26, 26662306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 26762306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 26862306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 26962306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = INVALID_REG_ADDR, 27062306a36Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 27162306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 27262306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 27362306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 27462306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 27562306a36Sopenharmony_ci }, 27662306a36Sopenharmony_ci bq27520g2_regs[BQ27XXX_REG_MAX] = { 27762306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 27862306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 27962306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x36, 28062306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 28162306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 28262306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 28362306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 28462306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 28562306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 28662306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = 0x26, 28762306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 28862306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 28962306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 29062306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 29162306a36Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 29262306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 29362306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 29462306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 29562306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 29662306a36Sopenharmony_ci }, 29762306a36Sopenharmony_ci bq27520g3_regs[BQ27XXX_REG_MAX] = { 29862306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 29962306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 30062306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x36, 30162306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 30262306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 30362306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 30462306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 30562306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 30662306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 30762306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = 0x26, 30862306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 30962306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 31062306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 31162306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 31262306a36Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 31362306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 31462306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 31562306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 31662306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 31762306a36Sopenharmony_ci }, 31862306a36Sopenharmony_ci bq27520g4_regs[BQ27XXX_REG_MAX] = { 31962306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 32062306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 32162306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x28, 32262306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 32362306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 32462306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 32562306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 32662306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 32762306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 32862306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 32962306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 33062306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 33162306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 33262306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x1e, 33362306a36Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 33462306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x20, 33562306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, 33662306a36Sopenharmony_ci [BQ27XXX_REG_AP] = INVALID_REG_ADDR, 33762306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 33862306a36Sopenharmony_ci }, 33962306a36Sopenharmony_ci bq27521_regs[BQ27XXX_REG_MAX] = { 34062306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x02, 34162306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x0a, 34262306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 34362306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x0c, 34462306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x0e, 34562306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x08, 34662306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = INVALID_REG_ADDR, 34762306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 34862306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 34962306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 35062306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = INVALID_REG_ADDR, 35162306a36Sopenharmony_ci [BQ27XXX_REG_RC] = INVALID_REG_ADDR, 35262306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = INVALID_REG_ADDR, 35362306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = INVALID_REG_ADDR, 35462306a36Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 35562306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = INVALID_REG_ADDR, 35662306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, 35762306a36Sopenharmony_ci [BQ27XXX_REG_AP] = INVALID_REG_ADDR, 35862306a36Sopenharmony_ci [BQ27XXX_DM_CTRL] = INVALID_REG_ADDR, 35962306a36Sopenharmony_ci [BQ27XXX_DM_CLASS] = INVALID_REG_ADDR, 36062306a36Sopenharmony_ci [BQ27XXX_DM_BLOCK] = INVALID_REG_ADDR, 36162306a36Sopenharmony_ci [BQ27XXX_DM_DATA] = INVALID_REG_ADDR, 36262306a36Sopenharmony_ci [BQ27XXX_DM_CKSUM] = INVALID_REG_ADDR, 36362306a36Sopenharmony_ci }, 36462306a36Sopenharmony_ci bq27530_regs[BQ27XXX_REG_MAX] = { 36562306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 36662306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 36762306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x32, 36862306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 36962306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 37062306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 37162306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 37262306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 37362306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 37462306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 37562306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 37662306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 37762306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 37862306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 37962306a36Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 38062306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 38162306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, 38262306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 38362306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 38462306a36Sopenharmony_ci }, 38562306a36Sopenharmony_ci#define bq27531_regs bq27530_regs 38662306a36Sopenharmony_ci bq27541_regs[BQ27XXX_REG_MAX] = { 38762306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 38862306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 38962306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x28, 39062306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 39162306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 39262306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 39362306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 39462306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 39562306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 39662306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 39762306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 39862306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 39962306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 40062306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 40162306a36Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 40262306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 40362306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 40462306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 40562306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 40662306a36Sopenharmony_ci }, 40762306a36Sopenharmony_ci#define bq27542_regs bq27541_regs 40862306a36Sopenharmony_ci#define bq27546_regs bq27541_regs 40962306a36Sopenharmony_ci#define bq27742_regs bq27541_regs 41062306a36Sopenharmony_ci bq27545_regs[BQ27XXX_REG_MAX] = { 41162306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 41262306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 41362306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x28, 41462306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 41562306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 41662306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 41762306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 41862306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 41962306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 42062306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 42162306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x0c, 42262306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 42362306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 42462306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 42562306a36Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 42662306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 42762306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = INVALID_REG_ADDR, 42862306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x24, 42962306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 43062306a36Sopenharmony_ci }, 43162306a36Sopenharmony_ci bq27421_regs[BQ27XXX_REG_MAX] = { 43262306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 43362306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x02, 43462306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x1e, 43562306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x04, 43662306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x10, 43762306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x06, 43862306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = INVALID_REG_ADDR, 43962306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, 44062306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 44162306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 44262306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = 0x08, 44362306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x0c, 44462306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x0e, 44562306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = INVALID_REG_ADDR, 44662306a36Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 44762306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x1c, 44862306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 44962306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x18, 45062306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 45162306a36Sopenharmony_ci }, 45262306a36Sopenharmony_ci#define bq27411_regs bq27421_regs 45362306a36Sopenharmony_ci#define bq27425_regs bq27421_regs 45462306a36Sopenharmony_ci#define bq27426_regs bq27421_regs 45562306a36Sopenharmony_ci#define bq27441_regs bq27421_regs 45662306a36Sopenharmony_ci#define bq27621_regs bq27421_regs 45762306a36Sopenharmony_ci bq27z561_regs[BQ27XXX_REG_MAX] = { 45862306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 45962306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 46062306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 46162306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 46262306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 46362306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 46462306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 46562306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 46662306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 46762306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 46862306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = INVALID_REG_ADDR, 46962306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 47062306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 47162306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 47262306a36Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 47362306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 47462306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 47562306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x22, 47662306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 47762306a36Sopenharmony_ci }, 47862306a36Sopenharmony_ci bq28z610_regs[BQ27XXX_REG_MAX] = { 47962306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 48062306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 48162306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR, 48262306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 48362306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 48462306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 48562306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 48662306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 48762306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = INVALID_REG_ADDR, 48862306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 48962306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = INVALID_REG_ADDR, 49062306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 49162306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 49262306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 49362306a36Sopenharmony_ci [BQ27XXX_REG_AE] = 0x22, 49462306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 49562306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 49662306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x22, 49762306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 49862306a36Sopenharmony_ci }, 49962306a36Sopenharmony_ci bq34z100_regs[BQ27XXX_REG_MAX] = { 50062306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 50162306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x0c, 50262306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x2a, 50362306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 50462306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x0a, 50562306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0e, 50662306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x18, 50762306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x1a, 50862306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1e, 50962306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 51062306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = INVALID_REG_ADDR, 51162306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x04, 51262306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x06, 51362306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2c, 51462306a36Sopenharmony_ci [BQ27XXX_REG_AE] = 0x24, 51562306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x02, 51662306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 51762306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x22, 51862306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 51962306a36Sopenharmony_ci }, 52062306a36Sopenharmony_ci bq78z100_regs[BQ27XXX_REG_MAX] = { 52162306a36Sopenharmony_ci [BQ27XXX_REG_CTRL] = 0x00, 52262306a36Sopenharmony_ci [BQ27XXX_REG_TEMP] = 0x06, 52362306a36Sopenharmony_ci [BQ27XXX_REG_INT_TEMP] = 0x28, 52462306a36Sopenharmony_ci [BQ27XXX_REG_VOLT] = 0x08, 52562306a36Sopenharmony_ci [BQ27XXX_REG_AI] = 0x14, 52662306a36Sopenharmony_ci [BQ27XXX_REG_FLAGS] = 0x0a, 52762306a36Sopenharmony_ci [BQ27XXX_REG_TTE] = 0x16, 52862306a36Sopenharmony_ci [BQ27XXX_REG_TTF] = 0x18, 52962306a36Sopenharmony_ci [BQ27XXX_REG_TTES] = 0x1c, 53062306a36Sopenharmony_ci [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, 53162306a36Sopenharmony_ci [BQ27XXX_REG_NAC] = INVALID_REG_ADDR, 53262306a36Sopenharmony_ci [BQ27XXX_REG_RC] = 0x10, 53362306a36Sopenharmony_ci [BQ27XXX_REG_FCC] = 0x12, 53462306a36Sopenharmony_ci [BQ27XXX_REG_CYCT] = 0x2a, 53562306a36Sopenharmony_ci [BQ27XXX_REG_AE] = INVALID_REG_ADDR, 53662306a36Sopenharmony_ci [BQ27XXX_REG_SOC] = 0x2c, 53762306a36Sopenharmony_ci [BQ27XXX_REG_DCAP] = 0x3c, 53862306a36Sopenharmony_ci [BQ27XXX_REG_AP] = 0x22, 53962306a36Sopenharmony_ci BQ27XXX_DM_REG_ROWS, 54062306a36Sopenharmony_ci }; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic enum power_supply_property bq27000_props[] = { 54362306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 54462306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 54562306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 54662306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 54762306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 54862306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 54962306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 55062306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 55162306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 55262306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 55362306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 55462306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 55562306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 55662306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 55762306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 55862306a36Sopenharmony_ci POWER_SUPPLY_PROP_ENERGY_NOW, 55962306a36Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 56062306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 56162306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 56262306a36Sopenharmony_ci}; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_cistatic enum power_supply_property bq27010_props[] = { 56562306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 56662306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 56762306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 56862306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 56962306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 57062306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 57162306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 57262306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 57362306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 57462306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 57562306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 57662306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 57762306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 57862306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 57962306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 58062306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 58162306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 58262306a36Sopenharmony_ci}; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci#define bq2750x_props bq27510g3_props 58562306a36Sopenharmony_ci#define bq2751x_props bq27510g3_props 58662306a36Sopenharmony_ci#define bq2752x_props bq27510g3_props 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_cistatic enum power_supply_property bq27500_props[] = { 58962306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 59062306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 59162306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 59262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 59362306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 59462306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 59562306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 59662306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 59762306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 59862306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 59962306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 60062306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 60162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 60262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 60362306a36Sopenharmony_ci POWER_SUPPLY_PROP_ENERGY_NOW, 60462306a36Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 60562306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 60662306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 60762306a36Sopenharmony_ci}; 60862306a36Sopenharmony_ci#define bq27510g1_props bq27500_props 60962306a36Sopenharmony_ci#define bq27510g2_props bq27500_props 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_cistatic enum power_supply_property bq27510g3_props[] = { 61262306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 61362306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 61462306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 61562306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 61662306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 61762306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 61862306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 61962306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 62062306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 62162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 62262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 62362306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 62462306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 62562306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 62662306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 62762306a36Sopenharmony_ci}; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_cistatic enum power_supply_property bq27520g1_props[] = { 63062306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 63162306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 63262306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 63362306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 63462306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 63562306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 63662306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 63762306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 63862306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 63962306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 64062306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 64162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 64262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 64362306a36Sopenharmony_ci POWER_SUPPLY_PROP_ENERGY_NOW, 64462306a36Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 64562306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 64662306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 64762306a36Sopenharmony_ci}; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci#define bq27520g2_props bq27500_props 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cistatic enum power_supply_property bq27520g3_props[] = { 65262306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 65362306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 65462306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 65562306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 65662306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 65762306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 65862306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 65962306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 66062306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 66162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 66262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 66362306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 66462306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 66562306a36Sopenharmony_ci POWER_SUPPLY_PROP_ENERGY_NOW, 66662306a36Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 66762306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 66862306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 66962306a36Sopenharmony_ci}; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_cistatic enum power_supply_property bq27520g4_props[] = { 67262306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 67362306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 67462306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 67562306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 67662306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 67762306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 67862306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 67962306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 68062306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 68162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 68262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 68362306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 68462306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 68562306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 68662306a36Sopenharmony_ci}; 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_cistatic enum power_supply_property bq27521_props[] = { 68962306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 69062306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 69162306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 69262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 69362306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 69462306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 69562306a36Sopenharmony_ci}; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_cistatic enum power_supply_property bq27530_props[] = { 69862306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 69962306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 70062306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 70162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 70262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 70362306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 70462306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 70562306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 70662306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 70762306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 70862306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 70962306a36Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 71062306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 71162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 71262306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 71362306a36Sopenharmony_ci}; 71462306a36Sopenharmony_ci#define bq27531_props bq27530_props 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_cistatic enum power_supply_property bq27541_props[] = { 71762306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 71862306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 71962306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 72062306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 72162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 72262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 72362306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 72462306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 72562306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 72662306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 72762306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 72862306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 72962306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 73062306a36Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 73162306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 73262306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 73362306a36Sopenharmony_ci}; 73462306a36Sopenharmony_ci#define bq27542_props bq27541_props 73562306a36Sopenharmony_ci#define bq27546_props bq27541_props 73662306a36Sopenharmony_ci#define bq27742_props bq27541_props 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_cistatic enum power_supply_property bq27545_props[] = { 73962306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 74062306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 74162306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 74262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 74362306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 74462306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 74562306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 74662306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 74762306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 74862306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 74962306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 75062306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 75162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 75262306a36Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 75362306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 75462306a36Sopenharmony_ci}; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_cistatic enum power_supply_property bq27421_props[] = { 75762306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 75862306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 75962306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 76062306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 76162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 76262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 76362306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 76462306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 76562306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 76662306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 76762306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 76862306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 76962306a36Sopenharmony_ci}; 77062306a36Sopenharmony_ci#define bq27411_props bq27421_props 77162306a36Sopenharmony_ci#define bq27425_props bq27421_props 77262306a36Sopenharmony_ci#define bq27426_props bq27421_props 77362306a36Sopenharmony_ci#define bq27441_props bq27421_props 77462306a36Sopenharmony_ci#define bq27621_props bq27421_props 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_cistatic enum power_supply_property bq27z561_props[] = { 77762306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 77862306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 77962306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 78062306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 78162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 78262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 78362306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 78462306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 78562306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 78662306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 78762306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 78862306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 78962306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 79062306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 79162306a36Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 79262306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 79362306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 79462306a36Sopenharmony_ci}; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_cistatic enum power_supply_property bq28z610_props[] = { 79762306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 79862306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 79962306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 80062306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 80162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 80262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 80362306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 80462306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 80562306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 80662306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 80762306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 80862306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 80962306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 81062306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 81162306a36Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 81262306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 81362306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 81462306a36Sopenharmony_ci}; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_cistatic enum power_supply_property bq34z100_props[] = { 81762306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 81862306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 81962306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 82062306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 82162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 82262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 82362306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 82462306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 82562306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 82662306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 82762306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 82862306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 82962306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 83062306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 83162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 83262306a36Sopenharmony_ci POWER_SUPPLY_PROP_ENERGY_NOW, 83362306a36Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 83462306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 83562306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 83662306a36Sopenharmony_ci}; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_cistatic enum power_supply_property bq78z100_props[] = { 83962306a36Sopenharmony_ci POWER_SUPPLY_PROP_STATUS, 84062306a36Sopenharmony_ci POWER_SUPPLY_PROP_PRESENT, 84162306a36Sopenharmony_ci POWER_SUPPLY_PROP_VOLTAGE_NOW, 84262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CURRENT_NOW, 84362306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY, 84462306a36Sopenharmony_ci POWER_SUPPLY_PROP_CAPACITY_LEVEL, 84562306a36Sopenharmony_ci POWER_SUPPLY_PROP_TEMP, 84662306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 84762306a36Sopenharmony_ci POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 84862306a36Sopenharmony_ci POWER_SUPPLY_PROP_TECHNOLOGY, 84962306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL, 85062306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_NOW, 85162306a36Sopenharmony_ci POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 85262306a36Sopenharmony_ci POWER_SUPPLY_PROP_CYCLE_COUNT, 85362306a36Sopenharmony_ci POWER_SUPPLY_PROP_POWER_AVG, 85462306a36Sopenharmony_ci POWER_SUPPLY_PROP_HEALTH, 85562306a36Sopenharmony_ci POWER_SUPPLY_PROP_MANUFACTURER, 85662306a36Sopenharmony_ci}; 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_cistruct bq27xxx_dm_reg { 85962306a36Sopenharmony_ci u8 subclass_id; 86062306a36Sopenharmony_ci u8 offset; 86162306a36Sopenharmony_ci u8 bytes; 86262306a36Sopenharmony_ci u16 min, max; 86362306a36Sopenharmony_ci}; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_cienum bq27xxx_dm_reg_id { 86662306a36Sopenharmony_ci BQ27XXX_DM_DESIGN_CAPACITY = 0, 86762306a36Sopenharmony_ci BQ27XXX_DM_DESIGN_ENERGY, 86862306a36Sopenharmony_ci BQ27XXX_DM_TERMINATE_VOLTAGE, 86962306a36Sopenharmony_ci}; 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci#define bq27000_dm_regs NULL 87262306a36Sopenharmony_ci#define bq27010_dm_regs NULL 87362306a36Sopenharmony_ci#define bq2750x_dm_regs NULL 87462306a36Sopenharmony_ci#define bq2751x_dm_regs NULL 87562306a36Sopenharmony_ci#define bq2752x_dm_regs NULL 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci#if 0 /* not yet tested */ 87862306a36Sopenharmony_cistatic struct bq27xxx_dm_reg bq27500_dm_regs[] = { 87962306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 10, 2, 0, 65535 }, 88062306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { }, /* missing on chip */ 88162306a36Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 48, 2, 1000, 32767 }, 88262306a36Sopenharmony_ci}; 88362306a36Sopenharmony_ci#else 88462306a36Sopenharmony_ci#define bq27500_dm_regs NULL 88562306a36Sopenharmony_ci#endif 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci/* todo create data memory definitions from datasheets and test on chips */ 88862306a36Sopenharmony_ci#define bq27510g1_dm_regs NULL 88962306a36Sopenharmony_ci#define bq27510g2_dm_regs NULL 89062306a36Sopenharmony_ci#define bq27510g3_dm_regs NULL 89162306a36Sopenharmony_ci#define bq27520g1_dm_regs NULL 89262306a36Sopenharmony_ci#define bq27520g2_dm_regs NULL 89362306a36Sopenharmony_ci#define bq27520g3_dm_regs NULL 89462306a36Sopenharmony_ci#define bq27520g4_dm_regs NULL 89562306a36Sopenharmony_ci#define bq27521_dm_regs NULL 89662306a36Sopenharmony_ci#define bq27530_dm_regs NULL 89762306a36Sopenharmony_ci#define bq27531_dm_regs NULL 89862306a36Sopenharmony_ci#define bq27541_dm_regs NULL 89962306a36Sopenharmony_ci#define bq27542_dm_regs NULL 90062306a36Sopenharmony_ci#define bq27546_dm_regs NULL 90162306a36Sopenharmony_ci#define bq27742_dm_regs NULL 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci#if 0 /* not yet tested */ 90462306a36Sopenharmony_cistatic struct bq27xxx_dm_reg bq27545_dm_regs[] = { 90562306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 48, 23, 2, 0, 32767 }, 90662306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { 48, 25, 2, 0, 32767 }, 90762306a36Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 80, 67, 2, 2800, 3700 }, 90862306a36Sopenharmony_ci}; 90962306a36Sopenharmony_ci#else 91062306a36Sopenharmony_ci#define bq27545_dm_regs NULL 91162306a36Sopenharmony_ci#endif 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_cistatic struct bq27xxx_dm_reg bq27411_dm_regs[] = { 91462306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 10, 2, 0, 32767 }, 91562306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 12, 2, 0, 32767 }, 91662306a36Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 16, 2, 2800, 3700 }, 91762306a36Sopenharmony_ci}; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_cistatic struct bq27xxx_dm_reg bq27421_dm_regs[] = { 92062306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 10, 2, 0, 8000 }, 92162306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 12, 2, 0, 32767 }, 92262306a36Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 16, 2, 2500, 3700 }, 92362306a36Sopenharmony_ci}; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_cistatic struct bq27xxx_dm_reg bq27425_dm_regs[] = { 92662306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 12, 2, 0, 32767 }, 92762306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 14, 2, 0, 32767 }, 92862306a36Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 18, 2, 2800, 3700 }, 92962306a36Sopenharmony_ci}; 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_cistatic struct bq27xxx_dm_reg bq27426_dm_regs[] = { 93262306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 6, 2, 0, 8000 }, 93362306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 8, 2, 0, 32767 }, 93462306a36Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 10, 2, 2500, 3700 }, 93562306a36Sopenharmony_ci}; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci#if 0 /* not yet tested */ 93862306a36Sopenharmony_ci#define bq27441_dm_regs bq27421_dm_regs 93962306a36Sopenharmony_ci#else 94062306a36Sopenharmony_ci#define bq27441_dm_regs NULL 94162306a36Sopenharmony_ci#endif 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci#if 0 /* not yet tested */ 94462306a36Sopenharmony_cistatic struct bq27xxx_dm_reg bq27621_dm_regs[] = { 94562306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = { 82, 3, 2, 0, 8000 }, 94662306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = { 82, 5, 2, 0, 32767 }, 94762306a36Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = { 82, 9, 2, 2500, 3700 }, 94862306a36Sopenharmony_ci}; 94962306a36Sopenharmony_ci#else 95062306a36Sopenharmony_ci#define bq27621_dm_regs NULL 95162306a36Sopenharmony_ci#endif 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci#define bq27z561_dm_regs NULL 95462306a36Sopenharmony_ci#define bq28z610_dm_regs NULL 95562306a36Sopenharmony_ci#define bq34z100_dm_regs NULL 95662306a36Sopenharmony_ci#define bq78z100_dm_regs NULL 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci#define BQ27XXX_O_ZERO BIT(0) 95962306a36Sopenharmony_ci#define BQ27XXX_O_OTDC BIT(1) /* has OTC/OTD overtemperature flags */ 96062306a36Sopenharmony_ci#define BQ27XXX_O_UTOT BIT(2) /* has OT overtemperature flag */ 96162306a36Sopenharmony_ci#define BQ27XXX_O_CFGUP BIT(3) 96262306a36Sopenharmony_ci#define BQ27XXX_O_RAM BIT(4) 96362306a36Sopenharmony_ci#define BQ27Z561_O_BITS BIT(5) 96462306a36Sopenharmony_ci#define BQ27XXX_O_SOC_SI BIT(6) /* SoC is single register */ 96562306a36Sopenharmony_ci#define BQ27XXX_O_HAS_CI BIT(7) /* has Capacity Inaccurate flag */ 96662306a36Sopenharmony_ci#define BQ27XXX_O_MUL_CHEM BIT(8) /* multiple chemistries supported */ 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci#define BQ27XXX_DATA(ref, key, opt) { \ 96962306a36Sopenharmony_ci .opts = (opt), \ 97062306a36Sopenharmony_ci .unseal_key = key, \ 97162306a36Sopenharmony_ci .regs = ref##_regs, \ 97262306a36Sopenharmony_ci .dm_regs = ref##_dm_regs, \ 97362306a36Sopenharmony_ci .props = ref##_props, \ 97462306a36Sopenharmony_ci .props_size = ARRAY_SIZE(ref##_props) } 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_cistatic struct { 97762306a36Sopenharmony_ci u32 opts; 97862306a36Sopenharmony_ci u32 unseal_key; 97962306a36Sopenharmony_ci u8 *regs; 98062306a36Sopenharmony_ci struct bq27xxx_dm_reg *dm_regs; 98162306a36Sopenharmony_ci enum power_supply_property *props; 98262306a36Sopenharmony_ci size_t props_size; 98362306a36Sopenharmony_ci} bq27xxx_chip_data[] = { 98462306a36Sopenharmony_ci [BQ27000] = BQ27XXX_DATA(bq27000, 0 , BQ27XXX_O_ZERO | BQ27XXX_O_SOC_SI | BQ27XXX_O_HAS_CI), 98562306a36Sopenharmony_ci [BQ27010] = BQ27XXX_DATA(bq27010, 0 , BQ27XXX_O_ZERO | BQ27XXX_O_SOC_SI | BQ27XXX_O_HAS_CI), 98662306a36Sopenharmony_ci [BQ2750X] = BQ27XXX_DATA(bq2750x, 0 , BQ27XXX_O_OTDC), 98762306a36Sopenharmony_ci [BQ2751X] = BQ27XXX_DATA(bq2751x, 0 , BQ27XXX_O_OTDC), 98862306a36Sopenharmony_ci [BQ2752X] = BQ27XXX_DATA(bq2752x, 0 , BQ27XXX_O_OTDC), 98962306a36Sopenharmony_ci [BQ27500] = BQ27XXX_DATA(bq27500, 0x04143672, BQ27XXX_O_OTDC), 99062306a36Sopenharmony_ci [BQ27510G1] = BQ27XXX_DATA(bq27510g1, 0 , BQ27XXX_O_OTDC), 99162306a36Sopenharmony_ci [BQ27510G2] = BQ27XXX_DATA(bq27510g2, 0 , BQ27XXX_O_OTDC), 99262306a36Sopenharmony_ci [BQ27510G3] = BQ27XXX_DATA(bq27510g3, 0 , BQ27XXX_O_OTDC), 99362306a36Sopenharmony_ci [BQ27520G1] = BQ27XXX_DATA(bq27520g1, 0 , BQ27XXX_O_OTDC), 99462306a36Sopenharmony_ci [BQ27520G2] = BQ27XXX_DATA(bq27520g2, 0 , BQ27XXX_O_OTDC), 99562306a36Sopenharmony_ci [BQ27520G3] = BQ27XXX_DATA(bq27520g3, 0 , BQ27XXX_O_OTDC), 99662306a36Sopenharmony_ci [BQ27520G4] = BQ27XXX_DATA(bq27520g4, 0 , BQ27XXX_O_OTDC), 99762306a36Sopenharmony_ci [BQ27521] = BQ27XXX_DATA(bq27521, 0 , 0), 99862306a36Sopenharmony_ci [BQ27530] = BQ27XXX_DATA(bq27530, 0 , BQ27XXX_O_UTOT), 99962306a36Sopenharmony_ci [BQ27531] = BQ27XXX_DATA(bq27531, 0 , BQ27XXX_O_UTOT), 100062306a36Sopenharmony_ci [BQ27541] = BQ27XXX_DATA(bq27541, 0 , BQ27XXX_O_OTDC), 100162306a36Sopenharmony_ci [BQ27542] = BQ27XXX_DATA(bq27542, 0 , BQ27XXX_O_OTDC), 100262306a36Sopenharmony_ci [BQ27546] = BQ27XXX_DATA(bq27546, 0 , BQ27XXX_O_OTDC), 100362306a36Sopenharmony_ci [BQ27742] = BQ27XXX_DATA(bq27742, 0 , BQ27XXX_O_OTDC), 100462306a36Sopenharmony_ci [BQ27545] = BQ27XXX_DATA(bq27545, 0x04143672, BQ27XXX_O_OTDC), 100562306a36Sopenharmony_ci [BQ27411] = BQ27XXX_DATA(bq27411, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), 100662306a36Sopenharmony_ci [BQ27421] = BQ27XXX_DATA(bq27421, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), 100762306a36Sopenharmony_ci [BQ27425] = BQ27XXX_DATA(bq27425, 0x04143672, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP), 100862306a36Sopenharmony_ci [BQ27426] = BQ27XXX_DATA(bq27426, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), 100962306a36Sopenharmony_ci [BQ27441] = BQ27XXX_DATA(bq27441, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), 101062306a36Sopenharmony_ci [BQ27621] = BQ27XXX_DATA(bq27621, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM), 101162306a36Sopenharmony_ci [BQ27Z561] = BQ27XXX_DATA(bq27z561, 0 , BQ27Z561_O_BITS), 101262306a36Sopenharmony_ci [BQ28Z610] = BQ27XXX_DATA(bq28z610, 0 , BQ27Z561_O_BITS), 101362306a36Sopenharmony_ci [BQ34Z100] = BQ27XXX_DATA(bq34z100, 0 , BQ27XXX_O_OTDC | BQ27XXX_O_SOC_SI | \ 101462306a36Sopenharmony_ci BQ27XXX_O_HAS_CI | BQ27XXX_O_MUL_CHEM), 101562306a36Sopenharmony_ci [BQ78Z100] = BQ27XXX_DATA(bq78z100, 0 , BQ27Z561_O_BITS), 101662306a36Sopenharmony_ci}; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_cistatic DEFINE_MUTEX(bq27xxx_list_lock); 101962306a36Sopenharmony_cistatic LIST_HEAD(bq27xxx_battery_devices); 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci#define BQ27XXX_MSLEEP(i) usleep_range((i)*1000, (i)*1000+500) 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci#define BQ27XXX_DM_SZ 32 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci/** 102662306a36Sopenharmony_ci * struct bq27xxx_dm_buf - chip data memory buffer 102762306a36Sopenharmony_ci * @class: data memory subclass_id 102862306a36Sopenharmony_ci * @block: data memory block number 102962306a36Sopenharmony_ci * @data: data from/for the block 103062306a36Sopenharmony_ci * @has_data: true if data has been filled by read 103162306a36Sopenharmony_ci * @dirty: true if data has changed since last read/write 103262306a36Sopenharmony_ci * 103362306a36Sopenharmony_ci * Encapsulates info required to manage chip data memory blocks. 103462306a36Sopenharmony_ci */ 103562306a36Sopenharmony_cistruct bq27xxx_dm_buf { 103662306a36Sopenharmony_ci u8 class; 103762306a36Sopenharmony_ci u8 block; 103862306a36Sopenharmony_ci u8 data[BQ27XXX_DM_SZ]; 103962306a36Sopenharmony_ci bool has_data, dirty; 104062306a36Sopenharmony_ci}; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci#define BQ27XXX_DM_BUF(di, i) { \ 104362306a36Sopenharmony_ci .class = (di)->dm_regs[i].subclass_id, \ 104462306a36Sopenharmony_ci .block = (di)->dm_regs[i].offset / BQ27XXX_DM_SZ, \ 104562306a36Sopenharmony_ci} 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_cistatic inline __be16 *bq27xxx_dm_reg_ptr(struct bq27xxx_dm_buf *buf, 104862306a36Sopenharmony_ci struct bq27xxx_dm_reg *reg) 104962306a36Sopenharmony_ci{ 105062306a36Sopenharmony_ci if (buf->class == reg->subclass_id && 105162306a36Sopenharmony_ci buf->block == reg->offset / BQ27XXX_DM_SZ) 105262306a36Sopenharmony_ci return (__be16 *) (buf->data + reg->offset % BQ27XXX_DM_SZ); 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci return NULL; 105562306a36Sopenharmony_ci} 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_cistatic const char * const bq27xxx_dm_reg_name[] = { 105862306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_CAPACITY] = "design-capacity", 105962306a36Sopenharmony_ci [BQ27XXX_DM_DESIGN_ENERGY] = "design-energy", 106062306a36Sopenharmony_ci [BQ27XXX_DM_TERMINATE_VOLTAGE] = "terminate-voltage", 106162306a36Sopenharmony_ci}; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_cistatic bool bq27xxx_dt_to_nvm = true; 106562306a36Sopenharmony_cimodule_param_named(dt_monitored_battery_updates_nvm, bq27xxx_dt_to_nvm, bool, 0444); 106662306a36Sopenharmony_ciMODULE_PARM_DESC(dt_monitored_battery_updates_nvm, 106762306a36Sopenharmony_ci "Devicetree monitored-battery config updates data memory on NVM/flash chips.\n" 106862306a36Sopenharmony_ci "Users must set this =0 when installing a different type of battery!\n" 106962306a36Sopenharmony_ci "Default is =1." 107062306a36Sopenharmony_ci#ifndef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM 107162306a36Sopenharmony_ci "\nSetting this affects future kernel updates, not the current configuration." 107262306a36Sopenharmony_ci#endif 107362306a36Sopenharmony_ci); 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_cistatic int poll_interval_param_set(const char *val, const struct kernel_param *kp) 107662306a36Sopenharmony_ci{ 107762306a36Sopenharmony_ci struct bq27xxx_device_info *di; 107862306a36Sopenharmony_ci unsigned int prev_val = *(unsigned int *) kp->arg; 107962306a36Sopenharmony_ci int ret; 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci ret = param_set_uint(val, kp); 108262306a36Sopenharmony_ci if (ret < 0 || prev_val == *(unsigned int *) kp->arg) 108362306a36Sopenharmony_ci return ret; 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci mutex_lock(&bq27xxx_list_lock); 108662306a36Sopenharmony_ci list_for_each_entry(di, &bq27xxx_battery_devices, list) 108762306a36Sopenharmony_ci mod_delayed_work(system_wq, &di->work, 0); 108862306a36Sopenharmony_ci mutex_unlock(&bq27xxx_list_lock); 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci return ret; 109162306a36Sopenharmony_ci} 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_cistatic const struct kernel_param_ops param_ops_poll_interval = { 109462306a36Sopenharmony_ci .get = param_get_uint, 109562306a36Sopenharmony_ci .set = poll_interval_param_set, 109662306a36Sopenharmony_ci}; 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_cistatic unsigned int poll_interval = 360; 109962306a36Sopenharmony_cimodule_param_cb(poll_interval, ¶m_ops_poll_interval, &poll_interval, 0644); 110062306a36Sopenharmony_ciMODULE_PARM_DESC(poll_interval, 110162306a36Sopenharmony_ci "battery poll interval in seconds - 0 disables polling"); 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci/* 110462306a36Sopenharmony_ci * Common code for BQ27xxx devices 110562306a36Sopenharmony_ci */ 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_cistatic inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, 110862306a36Sopenharmony_ci bool single) 110962306a36Sopenharmony_ci{ 111062306a36Sopenharmony_ci int ret; 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci if (!di || di->regs[reg_index] == INVALID_REG_ADDR) 111362306a36Sopenharmony_ci return -EINVAL; 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci ret = di->bus.read(di, di->regs[reg_index], single); 111662306a36Sopenharmony_ci if (ret < 0) 111762306a36Sopenharmony_ci dev_dbg(di->dev, "failed to read register 0x%02x (index %d)\n", 111862306a36Sopenharmony_ci di->regs[reg_index], reg_index); 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci return ret; 112162306a36Sopenharmony_ci} 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_cistatic inline int bq27xxx_write(struct bq27xxx_device_info *di, int reg_index, 112462306a36Sopenharmony_ci u16 value, bool single) 112562306a36Sopenharmony_ci{ 112662306a36Sopenharmony_ci int ret; 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci if (!di || di->regs[reg_index] == INVALID_REG_ADDR) 112962306a36Sopenharmony_ci return -EINVAL; 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci if (!di->bus.write) 113262306a36Sopenharmony_ci return -EPERM; 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci ret = di->bus.write(di, di->regs[reg_index], value, single); 113562306a36Sopenharmony_ci if (ret < 0) 113662306a36Sopenharmony_ci dev_dbg(di->dev, "failed to write register 0x%02x (index %d)\n", 113762306a36Sopenharmony_ci di->regs[reg_index], reg_index); 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci return ret; 114062306a36Sopenharmony_ci} 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_cistatic inline int bq27xxx_read_block(struct bq27xxx_device_info *di, int reg_index, 114362306a36Sopenharmony_ci u8 *data, int len) 114462306a36Sopenharmony_ci{ 114562306a36Sopenharmony_ci int ret; 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci if (!di || di->regs[reg_index] == INVALID_REG_ADDR) 114862306a36Sopenharmony_ci return -EINVAL; 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci if (!di->bus.read_bulk) 115162306a36Sopenharmony_ci return -EPERM; 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci ret = di->bus.read_bulk(di, di->regs[reg_index], data, len); 115462306a36Sopenharmony_ci if (ret < 0) 115562306a36Sopenharmony_ci dev_dbg(di->dev, "failed to read_bulk register 0x%02x (index %d)\n", 115662306a36Sopenharmony_ci di->regs[reg_index], reg_index); 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci return ret; 115962306a36Sopenharmony_ci} 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_cistatic inline int bq27xxx_write_block(struct bq27xxx_device_info *di, int reg_index, 116262306a36Sopenharmony_ci u8 *data, int len) 116362306a36Sopenharmony_ci{ 116462306a36Sopenharmony_ci int ret; 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci if (!di || di->regs[reg_index] == INVALID_REG_ADDR) 116762306a36Sopenharmony_ci return -EINVAL; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci if (!di->bus.write_bulk) 117062306a36Sopenharmony_ci return -EPERM; 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci ret = di->bus.write_bulk(di, di->regs[reg_index], data, len); 117362306a36Sopenharmony_ci if (ret < 0) 117462306a36Sopenharmony_ci dev_dbg(di->dev, "failed to write_bulk register 0x%02x (index %d)\n", 117562306a36Sopenharmony_ci di->regs[reg_index], reg_index); 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci return ret; 117862306a36Sopenharmony_ci} 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_cistatic int bq27xxx_battery_seal(struct bq27xxx_device_info *di) 118162306a36Sopenharmony_ci{ 118262306a36Sopenharmony_ci int ret; 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, BQ27XXX_SEALED, false); 118562306a36Sopenharmony_ci if (ret < 0) { 118662306a36Sopenharmony_ci dev_err(di->dev, "bus error on seal: %d\n", ret); 118762306a36Sopenharmony_ci return ret; 118862306a36Sopenharmony_ci } 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci return 0; 119162306a36Sopenharmony_ci} 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_cistatic int bq27xxx_battery_unseal(struct bq27xxx_device_info *di) 119462306a36Sopenharmony_ci{ 119562306a36Sopenharmony_ci int ret; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci if (di->unseal_key == 0) { 119862306a36Sopenharmony_ci dev_err(di->dev, "unseal failed due to missing key\n"); 119962306a36Sopenharmony_ci return -EINVAL; 120062306a36Sopenharmony_ci } 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, (u16)(di->unseal_key >> 16), false); 120362306a36Sopenharmony_ci if (ret < 0) 120462306a36Sopenharmony_ci goto out; 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, (u16)di->unseal_key, false); 120762306a36Sopenharmony_ci if (ret < 0) 120862306a36Sopenharmony_ci goto out; 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci return 0; 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ciout: 121362306a36Sopenharmony_ci dev_err(di->dev, "bus error on unseal: %d\n", ret); 121462306a36Sopenharmony_ci return ret; 121562306a36Sopenharmony_ci} 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_cistatic u8 bq27xxx_battery_checksum_dm_block(struct bq27xxx_dm_buf *buf) 121862306a36Sopenharmony_ci{ 121962306a36Sopenharmony_ci u16 sum = 0; 122062306a36Sopenharmony_ci int i; 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci for (i = 0; i < BQ27XXX_DM_SZ; i++) 122362306a36Sopenharmony_ci sum += buf->data[i]; 122462306a36Sopenharmony_ci sum &= 0xff; 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci return 0xff - sum; 122762306a36Sopenharmony_ci} 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_cistatic int bq27xxx_battery_read_dm_block(struct bq27xxx_device_info *di, 123062306a36Sopenharmony_ci struct bq27xxx_dm_buf *buf) 123162306a36Sopenharmony_ci{ 123262306a36Sopenharmony_ci int ret; 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci buf->has_data = false; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_DM_CLASS, buf->class, true); 123762306a36Sopenharmony_ci if (ret < 0) 123862306a36Sopenharmony_ci goto out; 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_DM_BLOCK, buf->block, true); 124162306a36Sopenharmony_ci if (ret < 0) 124262306a36Sopenharmony_ci goto out; 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci BQ27XXX_MSLEEP(1); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci ret = bq27xxx_read_block(di, BQ27XXX_DM_DATA, buf->data, BQ27XXX_DM_SZ); 124762306a36Sopenharmony_ci if (ret < 0) 124862306a36Sopenharmony_ci goto out; 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci ret = bq27xxx_read(di, BQ27XXX_DM_CKSUM, true); 125162306a36Sopenharmony_ci if (ret < 0) 125262306a36Sopenharmony_ci goto out; 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci if ((u8)ret != bq27xxx_battery_checksum_dm_block(buf)) { 125562306a36Sopenharmony_ci ret = -EINVAL; 125662306a36Sopenharmony_ci goto out; 125762306a36Sopenharmony_ci } 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci buf->has_data = true; 126062306a36Sopenharmony_ci buf->dirty = false; 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci return 0; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ciout: 126562306a36Sopenharmony_ci dev_err(di->dev, "bus error reading chip memory: %d\n", ret); 126662306a36Sopenharmony_ci return ret; 126762306a36Sopenharmony_ci} 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_cistatic void bq27xxx_battery_update_dm_block(struct bq27xxx_device_info *di, 127062306a36Sopenharmony_ci struct bq27xxx_dm_buf *buf, 127162306a36Sopenharmony_ci enum bq27xxx_dm_reg_id reg_id, 127262306a36Sopenharmony_ci unsigned int val) 127362306a36Sopenharmony_ci{ 127462306a36Sopenharmony_ci struct bq27xxx_dm_reg *reg = &di->dm_regs[reg_id]; 127562306a36Sopenharmony_ci const char *str = bq27xxx_dm_reg_name[reg_id]; 127662306a36Sopenharmony_ci __be16 *prev = bq27xxx_dm_reg_ptr(buf, reg); 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci if (prev == NULL) { 127962306a36Sopenharmony_ci dev_warn(di->dev, "buffer does not match %s dm spec\n", str); 128062306a36Sopenharmony_ci return; 128162306a36Sopenharmony_ci } 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci if (reg->bytes != 2) { 128462306a36Sopenharmony_ci dev_warn(di->dev, "%s dm spec has unsupported byte size\n", str); 128562306a36Sopenharmony_ci return; 128662306a36Sopenharmony_ci } 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci if (!buf->has_data) 128962306a36Sopenharmony_ci return; 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci if (be16_to_cpup(prev) == val) { 129262306a36Sopenharmony_ci dev_info(di->dev, "%s has %u\n", str, val); 129362306a36Sopenharmony_ci return; 129462306a36Sopenharmony_ci } 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM 129762306a36Sopenharmony_ci if (!(di->opts & BQ27XXX_O_RAM) && !bq27xxx_dt_to_nvm) { 129862306a36Sopenharmony_ci#else 129962306a36Sopenharmony_ci if (!(di->opts & BQ27XXX_O_RAM)) { 130062306a36Sopenharmony_ci#endif 130162306a36Sopenharmony_ci /* devicetree and NVM differ; defer to NVM */ 130262306a36Sopenharmony_ci dev_warn(di->dev, "%s has %u; update to %u disallowed " 130362306a36Sopenharmony_ci#ifdef CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM 130462306a36Sopenharmony_ci "by dt_monitored_battery_updates_nvm=0" 130562306a36Sopenharmony_ci#else 130662306a36Sopenharmony_ci "for flash/NVM data memory" 130762306a36Sopenharmony_ci#endif 130862306a36Sopenharmony_ci "\n", str, be16_to_cpup(prev), val); 130962306a36Sopenharmony_ci return; 131062306a36Sopenharmony_ci } 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci dev_info(di->dev, "update %s to %u\n", str, val); 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci *prev = cpu_to_be16(val); 131562306a36Sopenharmony_ci buf->dirty = true; 131662306a36Sopenharmony_ci} 131762306a36Sopenharmony_ci 131862306a36Sopenharmony_cistatic int bq27xxx_battery_cfgupdate_priv(struct bq27xxx_device_info *di, bool active) 131962306a36Sopenharmony_ci{ 132062306a36Sopenharmony_ci const int limit = 100; 132162306a36Sopenharmony_ci u16 cmd = active ? BQ27XXX_SET_CFGUPDATE : BQ27XXX_SOFT_RESET; 132262306a36Sopenharmony_ci int ret, try = limit; 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_REG_CTRL, cmd, false); 132562306a36Sopenharmony_ci if (ret < 0) 132662306a36Sopenharmony_ci return ret; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci do { 132962306a36Sopenharmony_ci BQ27XXX_MSLEEP(25); 133062306a36Sopenharmony_ci ret = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false); 133162306a36Sopenharmony_ci if (ret < 0) 133262306a36Sopenharmony_ci return ret; 133362306a36Sopenharmony_ci } while (!!(ret & BQ27XXX_FLAG_CFGUP) != active && --try); 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci if (!try && di->chip != BQ27425) { // 425 has a bug 133662306a36Sopenharmony_ci dev_err(di->dev, "timed out waiting for cfgupdate flag %d\n", active); 133762306a36Sopenharmony_ci return -EINVAL; 133862306a36Sopenharmony_ci } 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci if (limit - try > 3) 134162306a36Sopenharmony_ci dev_warn(di->dev, "cfgupdate %d, retries %d\n", active, limit - try); 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci return 0; 134462306a36Sopenharmony_ci} 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_cistatic inline int bq27xxx_battery_set_cfgupdate(struct bq27xxx_device_info *di) 134762306a36Sopenharmony_ci{ 134862306a36Sopenharmony_ci int ret = bq27xxx_battery_cfgupdate_priv(di, true); 134962306a36Sopenharmony_ci if (ret < 0 && ret != -EINVAL) 135062306a36Sopenharmony_ci dev_err(di->dev, "bus error on set_cfgupdate: %d\n", ret); 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci return ret; 135362306a36Sopenharmony_ci} 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_cistatic inline int bq27xxx_battery_soft_reset(struct bq27xxx_device_info *di) 135662306a36Sopenharmony_ci{ 135762306a36Sopenharmony_ci int ret = bq27xxx_battery_cfgupdate_priv(di, false); 135862306a36Sopenharmony_ci if (ret < 0 && ret != -EINVAL) 135962306a36Sopenharmony_ci dev_err(di->dev, "bus error on soft_reset: %d\n", ret); 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci return ret; 136262306a36Sopenharmony_ci} 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_cistatic int bq27xxx_battery_write_dm_block(struct bq27xxx_device_info *di, 136562306a36Sopenharmony_ci struct bq27xxx_dm_buf *buf) 136662306a36Sopenharmony_ci{ 136762306a36Sopenharmony_ci bool cfgup = di->opts & BQ27XXX_O_CFGUP; 136862306a36Sopenharmony_ci int ret; 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci if (!buf->dirty) 137162306a36Sopenharmony_ci return 0; 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci if (cfgup) { 137462306a36Sopenharmony_ci ret = bq27xxx_battery_set_cfgupdate(di); 137562306a36Sopenharmony_ci if (ret < 0) 137662306a36Sopenharmony_ci return ret; 137762306a36Sopenharmony_ci } 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_DM_CTRL, 0, true); 138062306a36Sopenharmony_ci if (ret < 0) 138162306a36Sopenharmony_ci goto out; 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_DM_CLASS, buf->class, true); 138462306a36Sopenharmony_ci if (ret < 0) 138562306a36Sopenharmony_ci goto out; 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_DM_BLOCK, buf->block, true); 138862306a36Sopenharmony_ci if (ret < 0) 138962306a36Sopenharmony_ci goto out; 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci BQ27XXX_MSLEEP(1); 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci ret = bq27xxx_write_block(di, BQ27XXX_DM_DATA, buf->data, BQ27XXX_DM_SZ); 139462306a36Sopenharmony_ci if (ret < 0) 139562306a36Sopenharmony_ci goto out; 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci ret = bq27xxx_write(di, BQ27XXX_DM_CKSUM, 139862306a36Sopenharmony_ci bq27xxx_battery_checksum_dm_block(buf), true); 139962306a36Sopenharmony_ci if (ret < 0) 140062306a36Sopenharmony_ci goto out; 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci /* DO NOT read BQ27XXX_DM_CKSUM here to verify it! That may cause NVM 140362306a36Sopenharmony_ci * corruption on the '425 chip (and perhaps others), which can damage 140462306a36Sopenharmony_ci * the chip. 140562306a36Sopenharmony_ci */ 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci if (cfgup) { 140862306a36Sopenharmony_ci BQ27XXX_MSLEEP(1); 140962306a36Sopenharmony_ci ret = bq27xxx_battery_soft_reset(di); 141062306a36Sopenharmony_ci if (ret < 0) 141162306a36Sopenharmony_ci return ret; 141262306a36Sopenharmony_ci } else { 141362306a36Sopenharmony_ci BQ27XXX_MSLEEP(100); /* flash DM updates in <100ms */ 141462306a36Sopenharmony_ci } 141562306a36Sopenharmony_ci 141662306a36Sopenharmony_ci buf->dirty = false; 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci return 0; 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ciout: 142162306a36Sopenharmony_ci if (cfgup) 142262306a36Sopenharmony_ci bq27xxx_battery_soft_reset(di); 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_ci dev_err(di->dev, "bus error writing chip memory: %d\n", ret); 142562306a36Sopenharmony_ci return ret; 142662306a36Sopenharmony_ci} 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_cistatic void bq27xxx_battery_set_config(struct bq27xxx_device_info *di, 142962306a36Sopenharmony_ci struct power_supply_battery_info *info) 143062306a36Sopenharmony_ci{ 143162306a36Sopenharmony_ci struct bq27xxx_dm_buf bd = BQ27XXX_DM_BUF(di, BQ27XXX_DM_DESIGN_CAPACITY); 143262306a36Sopenharmony_ci struct bq27xxx_dm_buf bt = BQ27XXX_DM_BUF(di, BQ27XXX_DM_TERMINATE_VOLTAGE); 143362306a36Sopenharmony_ci bool updated; 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci if (bq27xxx_battery_unseal(di) < 0) 143662306a36Sopenharmony_ci return; 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci if (info->charge_full_design_uah != -EINVAL && 143962306a36Sopenharmony_ci info->energy_full_design_uwh != -EINVAL) { 144062306a36Sopenharmony_ci bq27xxx_battery_read_dm_block(di, &bd); 144162306a36Sopenharmony_ci /* assume design energy & capacity are in same block */ 144262306a36Sopenharmony_ci bq27xxx_battery_update_dm_block(di, &bd, 144362306a36Sopenharmony_ci BQ27XXX_DM_DESIGN_CAPACITY, 144462306a36Sopenharmony_ci info->charge_full_design_uah / 1000); 144562306a36Sopenharmony_ci bq27xxx_battery_update_dm_block(di, &bd, 144662306a36Sopenharmony_ci BQ27XXX_DM_DESIGN_ENERGY, 144762306a36Sopenharmony_ci info->energy_full_design_uwh / 1000); 144862306a36Sopenharmony_ci } 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci if (info->voltage_min_design_uv != -EINVAL) { 145162306a36Sopenharmony_ci bool same = bd.class == bt.class && bd.block == bt.block; 145262306a36Sopenharmony_ci if (!same) 145362306a36Sopenharmony_ci bq27xxx_battery_read_dm_block(di, &bt); 145462306a36Sopenharmony_ci bq27xxx_battery_update_dm_block(di, same ? &bd : &bt, 145562306a36Sopenharmony_ci BQ27XXX_DM_TERMINATE_VOLTAGE, 145662306a36Sopenharmony_ci info->voltage_min_design_uv / 1000); 145762306a36Sopenharmony_ci } 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci updated = bd.dirty || bt.dirty; 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci bq27xxx_battery_write_dm_block(di, &bd); 146262306a36Sopenharmony_ci bq27xxx_battery_write_dm_block(di, &bt); 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci bq27xxx_battery_seal(di); 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci if (updated && !(di->opts & BQ27XXX_O_CFGUP)) { 146762306a36Sopenharmony_ci bq27xxx_write(di, BQ27XXX_REG_CTRL, BQ27XXX_RESET, false); 146862306a36Sopenharmony_ci BQ27XXX_MSLEEP(300); /* reset time is not documented */ 146962306a36Sopenharmony_ci } 147062306a36Sopenharmony_ci /* assume bq27xxx_battery_update() is called hereafter */ 147162306a36Sopenharmony_ci} 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_cistatic void bq27xxx_battery_settings(struct bq27xxx_device_info *di) 147462306a36Sopenharmony_ci{ 147562306a36Sopenharmony_ci struct power_supply_battery_info *info; 147662306a36Sopenharmony_ci unsigned int min, max; 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ci if (power_supply_get_battery_info(di->bat, &info) < 0) 147962306a36Sopenharmony_ci return; 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci if (!di->dm_regs) { 148262306a36Sopenharmony_ci dev_warn(di->dev, "data memory update not supported for chip\n"); 148362306a36Sopenharmony_ci return; 148462306a36Sopenharmony_ci } 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci if (info->energy_full_design_uwh != info->charge_full_design_uah) { 148762306a36Sopenharmony_ci if (info->energy_full_design_uwh == -EINVAL) 148862306a36Sopenharmony_ci dev_warn(di->dev, "missing battery:energy-full-design-microwatt-hours\n"); 148962306a36Sopenharmony_ci else if (info->charge_full_design_uah == -EINVAL) 149062306a36Sopenharmony_ci dev_warn(di->dev, "missing battery:charge-full-design-microamp-hours\n"); 149162306a36Sopenharmony_ci } 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci /* assume min == 0 */ 149462306a36Sopenharmony_ci max = di->dm_regs[BQ27XXX_DM_DESIGN_ENERGY].max; 149562306a36Sopenharmony_ci if (info->energy_full_design_uwh > max * 1000) { 149662306a36Sopenharmony_ci dev_err(di->dev, "invalid battery:energy-full-design-microwatt-hours %d\n", 149762306a36Sopenharmony_ci info->energy_full_design_uwh); 149862306a36Sopenharmony_ci info->energy_full_design_uwh = -EINVAL; 149962306a36Sopenharmony_ci } 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci /* assume min == 0 */ 150262306a36Sopenharmony_ci max = di->dm_regs[BQ27XXX_DM_DESIGN_CAPACITY].max; 150362306a36Sopenharmony_ci if (info->charge_full_design_uah > max * 1000) { 150462306a36Sopenharmony_ci dev_err(di->dev, "invalid battery:charge-full-design-microamp-hours %d\n", 150562306a36Sopenharmony_ci info->charge_full_design_uah); 150662306a36Sopenharmony_ci info->charge_full_design_uah = -EINVAL; 150762306a36Sopenharmony_ci } 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci min = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].min; 151062306a36Sopenharmony_ci max = di->dm_regs[BQ27XXX_DM_TERMINATE_VOLTAGE].max; 151162306a36Sopenharmony_ci if ((info->voltage_min_design_uv < min * 1000 || 151262306a36Sopenharmony_ci info->voltage_min_design_uv > max * 1000) && 151362306a36Sopenharmony_ci info->voltage_min_design_uv != -EINVAL) { 151462306a36Sopenharmony_ci dev_err(di->dev, "invalid battery:voltage-min-design-microvolt %d\n", 151562306a36Sopenharmony_ci info->voltage_min_design_uv); 151662306a36Sopenharmony_ci info->voltage_min_design_uv = -EINVAL; 151762306a36Sopenharmony_ci } 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci if ((info->energy_full_design_uwh != -EINVAL && 152062306a36Sopenharmony_ci info->charge_full_design_uah != -EINVAL) || 152162306a36Sopenharmony_ci info->voltage_min_design_uv != -EINVAL) 152262306a36Sopenharmony_ci bq27xxx_battery_set_config(di, info); 152362306a36Sopenharmony_ci} 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci/* 152662306a36Sopenharmony_ci * Return the battery State-of-Charge 152762306a36Sopenharmony_ci * Or < 0 if something fails. 152862306a36Sopenharmony_ci */ 152962306a36Sopenharmony_cistatic int bq27xxx_battery_read_soc(struct bq27xxx_device_info *di) 153062306a36Sopenharmony_ci{ 153162306a36Sopenharmony_ci int soc; 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_SOC_SI) 153462306a36Sopenharmony_ci soc = bq27xxx_read(di, BQ27XXX_REG_SOC, true); 153562306a36Sopenharmony_ci else 153662306a36Sopenharmony_ci soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false); 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_ci if (soc < 0) 153962306a36Sopenharmony_ci dev_dbg(di->dev, "error reading State-of-Charge\n"); 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_ci return soc; 154262306a36Sopenharmony_ci} 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_ci/* 154562306a36Sopenharmony_ci * Return a battery charge value in µAh 154662306a36Sopenharmony_ci * Or < 0 if something fails. 154762306a36Sopenharmony_ci */ 154862306a36Sopenharmony_cistatic int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg) 154962306a36Sopenharmony_ci{ 155062306a36Sopenharmony_ci int charge; 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci charge = bq27xxx_read(di, reg, false); 155362306a36Sopenharmony_ci if (charge < 0) { 155462306a36Sopenharmony_ci dev_dbg(di->dev, "error reading charge register %02x: %d\n", 155562306a36Sopenharmony_ci reg, charge); 155662306a36Sopenharmony_ci return charge; 155762306a36Sopenharmony_ci } 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 156062306a36Sopenharmony_ci charge *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; 156162306a36Sopenharmony_ci else 156262306a36Sopenharmony_ci charge *= 1000; 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci return charge; 156562306a36Sopenharmony_ci} 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_ci/* 156862306a36Sopenharmony_ci * Return the battery Nominal available capacity in µAh 156962306a36Sopenharmony_ci * Or < 0 if something fails. 157062306a36Sopenharmony_ci */ 157162306a36Sopenharmony_cistatic inline int bq27xxx_battery_read_nac(struct bq27xxx_device_info *di) 157262306a36Sopenharmony_ci{ 157362306a36Sopenharmony_ci return bq27xxx_battery_read_charge(di, BQ27XXX_REG_NAC); 157462306a36Sopenharmony_ci} 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci/* 157762306a36Sopenharmony_ci * Return the battery Remaining Capacity in µAh 157862306a36Sopenharmony_ci * Or < 0 if something fails. 157962306a36Sopenharmony_ci */ 158062306a36Sopenharmony_cistatic inline int bq27xxx_battery_read_rc(struct bq27xxx_device_info *di) 158162306a36Sopenharmony_ci{ 158262306a36Sopenharmony_ci return bq27xxx_battery_read_charge(di, BQ27XXX_REG_RC); 158362306a36Sopenharmony_ci} 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci/* 158662306a36Sopenharmony_ci * Return the battery Full Charge Capacity in µAh 158762306a36Sopenharmony_ci * Or < 0 if something fails. 158862306a36Sopenharmony_ci */ 158962306a36Sopenharmony_cistatic inline int bq27xxx_battery_read_fcc(struct bq27xxx_device_info *di) 159062306a36Sopenharmony_ci{ 159162306a36Sopenharmony_ci return bq27xxx_battery_read_charge(di, BQ27XXX_REG_FCC); 159262306a36Sopenharmony_ci} 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci/* 159562306a36Sopenharmony_ci * Return the Design Capacity in µAh 159662306a36Sopenharmony_ci * Or < 0 if something fails. 159762306a36Sopenharmony_ci */ 159862306a36Sopenharmony_cistatic int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di) 159962306a36Sopenharmony_ci{ 160062306a36Sopenharmony_ci int dcap; 160162306a36Sopenharmony_ci 160262306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 160362306a36Sopenharmony_ci dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, true); 160462306a36Sopenharmony_ci else 160562306a36Sopenharmony_ci dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false); 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci if (dcap < 0) { 160862306a36Sopenharmony_ci dev_dbg(di->dev, "error reading initial last measured discharge\n"); 160962306a36Sopenharmony_ci return dcap; 161062306a36Sopenharmony_ci } 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 161362306a36Sopenharmony_ci dcap = (dcap << 8) * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; 161462306a36Sopenharmony_ci else 161562306a36Sopenharmony_ci dcap *= 1000; 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_ci return dcap; 161862306a36Sopenharmony_ci} 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci/* 162162306a36Sopenharmony_ci * Return the battery Available energy in µWh 162262306a36Sopenharmony_ci * Or < 0 if something fails. 162362306a36Sopenharmony_ci */ 162462306a36Sopenharmony_cistatic int bq27xxx_battery_read_energy(struct bq27xxx_device_info *di) 162562306a36Sopenharmony_ci{ 162662306a36Sopenharmony_ci int ae; 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci ae = bq27xxx_read(di, BQ27XXX_REG_AE, false); 162962306a36Sopenharmony_ci if (ae < 0) { 163062306a36Sopenharmony_ci dev_dbg(di->dev, "error reading available energy\n"); 163162306a36Sopenharmony_ci return ae; 163262306a36Sopenharmony_ci } 163362306a36Sopenharmony_ci 163462306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 163562306a36Sopenharmony_ci ae *= BQ27XXX_POWER_CONSTANT / BQ27XXX_RS; 163662306a36Sopenharmony_ci else 163762306a36Sopenharmony_ci ae *= 1000; 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_ci return ae; 164062306a36Sopenharmony_ci} 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci/* 164362306a36Sopenharmony_ci * Return the battery temperature in tenths of degree Kelvin 164462306a36Sopenharmony_ci * Or < 0 if something fails. 164562306a36Sopenharmony_ci */ 164662306a36Sopenharmony_cistatic int bq27xxx_battery_read_temperature(struct bq27xxx_device_info *di) 164762306a36Sopenharmony_ci{ 164862306a36Sopenharmony_ci int temp; 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci temp = bq27xxx_read(di, BQ27XXX_REG_TEMP, false); 165162306a36Sopenharmony_ci if (temp < 0) { 165262306a36Sopenharmony_ci dev_err(di->dev, "error reading temperature\n"); 165362306a36Sopenharmony_ci return temp; 165462306a36Sopenharmony_ci } 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 165762306a36Sopenharmony_ci temp = 5 * temp / 2; 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci return temp; 166062306a36Sopenharmony_ci} 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci/* 166362306a36Sopenharmony_ci * Return the battery Cycle count total 166462306a36Sopenharmony_ci * Or < 0 if something fails. 166562306a36Sopenharmony_ci */ 166662306a36Sopenharmony_cistatic int bq27xxx_battery_read_cyct(struct bq27xxx_device_info *di) 166762306a36Sopenharmony_ci{ 166862306a36Sopenharmony_ci int cyct; 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci cyct = bq27xxx_read(di, BQ27XXX_REG_CYCT, false); 167162306a36Sopenharmony_ci if (cyct < 0) 167262306a36Sopenharmony_ci dev_err(di->dev, "error reading cycle count total\n"); 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci return cyct; 167562306a36Sopenharmony_ci} 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci/* 167862306a36Sopenharmony_ci * Read a time register. 167962306a36Sopenharmony_ci * Return < 0 if something fails. 168062306a36Sopenharmony_ci */ 168162306a36Sopenharmony_cistatic int bq27xxx_battery_read_time(struct bq27xxx_device_info *di, u8 reg) 168262306a36Sopenharmony_ci{ 168362306a36Sopenharmony_ci int tval; 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci tval = bq27xxx_read(di, reg, false); 168662306a36Sopenharmony_ci if (tval < 0) { 168762306a36Sopenharmony_ci dev_dbg(di->dev, "error reading time register %02x: %d\n", 168862306a36Sopenharmony_ci reg, tval); 168962306a36Sopenharmony_ci return tval; 169062306a36Sopenharmony_ci } 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci if (tval == 65535) 169362306a36Sopenharmony_ci return -ENODATA; 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_ci return tval * 60; 169662306a36Sopenharmony_ci} 169762306a36Sopenharmony_ci 169862306a36Sopenharmony_ci/* 169962306a36Sopenharmony_ci * Returns true if a battery over temperature condition is detected 170062306a36Sopenharmony_ci */ 170162306a36Sopenharmony_cistatic bool bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags) 170262306a36Sopenharmony_ci{ 170362306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_OTDC) 170462306a36Sopenharmony_ci return flags & (BQ27XXX_FLAG_OTC | BQ27XXX_FLAG_OTD); 170562306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_UTOT) 170662306a36Sopenharmony_ci return flags & BQ27XXX_FLAG_OT; 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ci return false; 170962306a36Sopenharmony_ci} 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci/* 171262306a36Sopenharmony_ci * Returns true if a battery under temperature condition is detected 171362306a36Sopenharmony_ci */ 171462306a36Sopenharmony_cistatic bool bq27xxx_battery_undertemp(struct bq27xxx_device_info *di, u16 flags) 171562306a36Sopenharmony_ci{ 171662306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_UTOT) 171762306a36Sopenharmony_ci return flags & BQ27XXX_FLAG_UT; 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci return false; 172062306a36Sopenharmony_ci} 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci/* 172362306a36Sopenharmony_ci * Returns true if a low state of charge condition is detected 172462306a36Sopenharmony_ci */ 172562306a36Sopenharmony_cistatic bool bq27xxx_battery_dead(struct bq27xxx_device_info *di, u16 flags) 172662306a36Sopenharmony_ci{ 172762306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 172862306a36Sopenharmony_ci return flags & (BQ27000_FLAG_EDV1 | BQ27000_FLAG_EDVF); 172962306a36Sopenharmony_ci else if (di->opts & BQ27Z561_O_BITS) 173062306a36Sopenharmony_ci return flags & BQ27Z561_FLAG_FDC; 173162306a36Sopenharmony_ci else 173262306a36Sopenharmony_ci return flags & (BQ27XXX_FLAG_SOC1 | BQ27XXX_FLAG_SOCF); 173362306a36Sopenharmony_ci} 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_ci/* 173662306a36Sopenharmony_ci * Returns true if reported battery capacity is inaccurate 173762306a36Sopenharmony_ci */ 173862306a36Sopenharmony_cistatic bool bq27xxx_battery_capacity_inaccurate(struct bq27xxx_device_info *di, 173962306a36Sopenharmony_ci u16 flags) 174062306a36Sopenharmony_ci{ 174162306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_HAS_CI) 174262306a36Sopenharmony_ci return (flags & BQ27000_FLAG_CI); 174362306a36Sopenharmony_ci else 174462306a36Sopenharmony_ci return false; 174562306a36Sopenharmony_ci} 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_cistatic int bq27xxx_battery_read_health(struct bq27xxx_device_info *di) 174862306a36Sopenharmony_ci{ 174962306a36Sopenharmony_ci /* Unlikely but important to return first */ 175062306a36Sopenharmony_ci if (unlikely(bq27xxx_battery_overtemp(di, di->cache.flags))) 175162306a36Sopenharmony_ci return POWER_SUPPLY_HEALTH_OVERHEAT; 175262306a36Sopenharmony_ci if (unlikely(bq27xxx_battery_undertemp(di, di->cache.flags))) 175362306a36Sopenharmony_ci return POWER_SUPPLY_HEALTH_COLD; 175462306a36Sopenharmony_ci if (unlikely(bq27xxx_battery_dead(di, di->cache.flags))) 175562306a36Sopenharmony_ci return POWER_SUPPLY_HEALTH_DEAD; 175662306a36Sopenharmony_ci if (unlikely(bq27xxx_battery_capacity_inaccurate(di, di->cache.flags))) 175762306a36Sopenharmony_ci return POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED; 175862306a36Sopenharmony_ci 175962306a36Sopenharmony_ci return POWER_SUPPLY_HEALTH_GOOD; 176062306a36Sopenharmony_ci} 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_cistatic bool bq27xxx_battery_is_full(struct bq27xxx_device_info *di, int flags) 176362306a36Sopenharmony_ci{ 176462306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 176562306a36Sopenharmony_ci return (flags & BQ27000_FLAG_FC); 176662306a36Sopenharmony_ci else if (di->opts & BQ27Z561_O_BITS) 176762306a36Sopenharmony_ci return (flags & BQ27Z561_FLAG_FC); 176862306a36Sopenharmony_ci else 176962306a36Sopenharmony_ci return (flags & BQ27XXX_FLAG_FC); 177062306a36Sopenharmony_ci} 177162306a36Sopenharmony_ci 177262306a36Sopenharmony_ci/* 177362306a36Sopenharmony_ci * Return the battery average current in µA and the status 177462306a36Sopenharmony_ci * Note that current can be negative signed as well 177562306a36Sopenharmony_ci * Or 0 if something fails. 177662306a36Sopenharmony_ci */ 177762306a36Sopenharmony_cistatic int bq27xxx_battery_current_and_status( 177862306a36Sopenharmony_ci struct bq27xxx_device_info *di, 177962306a36Sopenharmony_ci union power_supply_propval *val_curr, 178062306a36Sopenharmony_ci union power_supply_propval *val_status, 178162306a36Sopenharmony_ci struct bq27xxx_reg_cache *cache) 178262306a36Sopenharmony_ci{ 178362306a36Sopenharmony_ci bool single_flags = (di->opts & BQ27XXX_O_ZERO); 178462306a36Sopenharmony_ci int curr; 178562306a36Sopenharmony_ci int flags; 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci curr = bq27xxx_read(di, BQ27XXX_REG_AI, false); 178862306a36Sopenharmony_ci if (curr < 0) { 178962306a36Sopenharmony_ci dev_err(di->dev, "error reading current\n"); 179062306a36Sopenharmony_ci return curr; 179162306a36Sopenharmony_ci } 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ci if (cache) { 179462306a36Sopenharmony_ci flags = cache->flags; 179562306a36Sopenharmony_ci } else { 179662306a36Sopenharmony_ci flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, single_flags); 179762306a36Sopenharmony_ci if (flags < 0) { 179862306a36Sopenharmony_ci dev_err(di->dev, "error reading flags\n"); 179962306a36Sopenharmony_ci return flags; 180062306a36Sopenharmony_ci } 180162306a36Sopenharmony_ci } 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) { 180462306a36Sopenharmony_ci if (!(flags & BQ27000_FLAG_CHGS)) { 180562306a36Sopenharmony_ci dev_dbg(di->dev, "negative current!\n"); 180662306a36Sopenharmony_ci curr = -curr; 180762306a36Sopenharmony_ci } 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci curr = curr * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; 181062306a36Sopenharmony_ci } else { 181162306a36Sopenharmony_ci /* Other gauges return signed value */ 181262306a36Sopenharmony_ci curr = (int)((s16)curr) * 1000; 181362306a36Sopenharmony_ci } 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_ci if (val_curr) 181662306a36Sopenharmony_ci val_curr->intval = curr; 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci if (val_status) { 181962306a36Sopenharmony_ci if (curr > 0) { 182062306a36Sopenharmony_ci val_status->intval = POWER_SUPPLY_STATUS_CHARGING; 182162306a36Sopenharmony_ci } else if (curr < 0) { 182262306a36Sopenharmony_ci val_status->intval = POWER_SUPPLY_STATUS_DISCHARGING; 182362306a36Sopenharmony_ci } else { 182462306a36Sopenharmony_ci if (bq27xxx_battery_is_full(di, flags)) 182562306a36Sopenharmony_ci val_status->intval = POWER_SUPPLY_STATUS_FULL; 182662306a36Sopenharmony_ci else 182762306a36Sopenharmony_ci val_status->intval = 182862306a36Sopenharmony_ci POWER_SUPPLY_STATUS_NOT_CHARGING; 182962306a36Sopenharmony_ci } 183062306a36Sopenharmony_ci } 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ci return 0; 183362306a36Sopenharmony_ci} 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_cistatic void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di) 183662306a36Sopenharmony_ci{ 183762306a36Sopenharmony_ci union power_supply_propval status = di->last_status; 183862306a36Sopenharmony_ci struct bq27xxx_reg_cache cache = {0, }; 183962306a36Sopenharmony_ci bool has_singe_flag = di->opts & BQ27XXX_O_ZERO; 184062306a36Sopenharmony_ci 184162306a36Sopenharmony_ci cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag); 184262306a36Sopenharmony_ci if ((cache.flags & 0xff) == 0xff) 184362306a36Sopenharmony_ci cache.flags = -1; /* read error */ 184462306a36Sopenharmony_ci if (cache.flags >= 0) { 184562306a36Sopenharmony_ci cache.temperature = bq27xxx_battery_read_temperature(di); 184662306a36Sopenharmony_ci if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR) 184762306a36Sopenharmony_ci cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE); 184862306a36Sopenharmony_ci if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR) 184962306a36Sopenharmony_ci cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP); 185062306a36Sopenharmony_ci if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR) 185162306a36Sopenharmony_ci cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF); 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_ci cache.charge_full = bq27xxx_battery_read_fcc(di); 185462306a36Sopenharmony_ci cache.capacity = bq27xxx_battery_read_soc(di); 185562306a36Sopenharmony_ci if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR) 185662306a36Sopenharmony_ci cache.energy = bq27xxx_battery_read_energy(di); 185762306a36Sopenharmony_ci di->cache.flags = cache.flags; 185862306a36Sopenharmony_ci cache.health = bq27xxx_battery_read_health(di); 185962306a36Sopenharmony_ci if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR) 186062306a36Sopenharmony_ci cache.cycle_count = bq27xxx_battery_read_cyct(di); 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci /* 186362306a36Sopenharmony_ci * On gauges with signed current reporting the current must be 186462306a36Sopenharmony_ci * checked to detect charging <-> discharging status changes. 186562306a36Sopenharmony_ci */ 186662306a36Sopenharmony_ci if (!(di->opts & BQ27XXX_O_ZERO)) 186762306a36Sopenharmony_ci bq27xxx_battery_current_and_status(di, NULL, &status, &cache); 186862306a36Sopenharmony_ci 186962306a36Sopenharmony_ci /* We only have to read charge design full once */ 187062306a36Sopenharmony_ci if (di->charge_design_full <= 0) 187162306a36Sopenharmony_ci di->charge_design_full = bq27xxx_battery_read_dcap(di); 187262306a36Sopenharmony_ci } 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci if ((di->cache.capacity != cache.capacity) || 187562306a36Sopenharmony_ci (di->cache.flags != cache.flags) || 187662306a36Sopenharmony_ci (di->last_status.intval != status.intval)) { 187762306a36Sopenharmony_ci di->last_status.intval = status.intval; 187862306a36Sopenharmony_ci power_supply_changed(di->bat); 187962306a36Sopenharmony_ci } 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ci if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) 188262306a36Sopenharmony_ci di->cache = cache; 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_ci di->last_update = jiffies; 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci if (!di->removed && poll_interval > 0) 188762306a36Sopenharmony_ci mod_delayed_work(system_wq, &di->work, poll_interval * HZ); 188862306a36Sopenharmony_ci} 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_civoid bq27xxx_battery_update(struct bq27xxx_device_info *di) 189162306a36Sopenharmony_ci{ 189262306a36Sopenharmony_ci mutex_lock(&di->lock); 189362306a36Sopenharmony_ci bq27xxx_battery_update_unlocked(di); 189462306a36Sopenharmony_ci mutex_unlock(&di->lock); 189562306a36Sopenharmony_ci} 189662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bq27xxx_battery_update); 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_cistatic void bq27xxx_battery_poll(struct work_struct *work) 189962306a36Sopenharmony_ci{ 190062306a36Sopenharmony_ci struct bq27xxx_device_info *di = 190162306a36Sopenharmony_ci container_of(work, struct bq27xxx_device_info, 190262306a36Sopenharmony_ci work.work); 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_ci bq27xxx_battery_update(di); 190562306a36Sopenharmony_ci} 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci/* 190862306a36Sopenharmony_ci * Get the average power in µW 190962306a36Sopenharmony_ci * Return < 0 if something fails. 191062306a36Sopenharmony_ci */ 191162306a36Sopenharmony_cistatic int bq27xxx_battery_pwr_avg(struct bq27xxx_device_info *di, 191262306a36Sopenharmony_ci union power_supply_propval *val) 191362306a36Sopenharmony_ci{ 191462306a36Sopenharmony_ci int power; 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ci power = bq27xxx_read(di, BQ27XXX_REG_AP, false); 191762306a36Sopenharmony_ci if (power < 0) { 191862306a36Sopenharmony_ci dev_err(di->dev, 191962306a36Sopenharmony_ci "error reading average power register %02x: %d\n", 192062306a36Sopenharmony_ci BQ27XXX_REG_AP, power); 192162306a36Sopenharmony_ci return power; 192262306a36Sopenharmony_ci } 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) 192562306a36Sopenharmony_ci val->intval = (power * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS; 192662306a36Sopenharmony_ci else 192762306a36Sopenharmony_ci /* Other gauges return a signed value in units of 10mW */ 192862306a36Sopenharmony_ci val->intval = (int)((s16)power) * 10000; 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci return 0; 193162306a36Sopenharmony_ci} 193262306a36Sopenharmony_ci 193362306a36Sopenharmony_cistatic int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di, 193462306a36Sopenharmony_ci union power_supply_propval *val) 193562306a36Sopenharmony_ci{ 193662306a36Sopenharmony_ci int level; 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_ZERO) { 193962306a36Sopenharmony_ci if (di->cache.flags & BQ27000_FLAG_FC) 194062306a36Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; 194162306a36Sopenharmony_ci else if (di->cache.flags & BQ27000_FLAG_EDVF) 194262306a36Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; 194362306a36Sopenharmony_ci else if (di->cache.flags & BQ27000_FLAG_EDV1) 194462306a36Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_LOW; 194562306a36Sopenharmony_ci else 194662306a36Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 194762306a36Sopenharmony_ci } else if (di->opts & BQ27Z561_O_BITS) { 194862306a36Sopenharmony_ci if (di->cache.flags & BQ27Z561_FLAG_FC) 194962306a36Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; 195062306a36Sopenharmony_ci else if (di->cache.flags & BQ27Z561_FLAG_FDC) 195162306a36Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; 195262306a36Sopenharmony_ci else 195362306a36Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 195462306a36Sopenharmony_ci } else { 195562306a36Sopenharmony_ci if (di->cache.flags & BQ27XXX_FLAG_FC) 195662306a36Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; 195762306a36Sopenharmony_ci else if (di->cache.flags & BQ27XXX_FLAG_SOCF) 195862306a36Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; 195962306a36Sopenharmony_ci else if (di->cache.flags & BQ27XXX_FLAG_SOC1) 196062306a36Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_LOW; 196162306a36Sopenharmony_ci else 196262306a36Sopenharmony_ci level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; 196362306a36Sopenharmony_ci } 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ci val->intval = level; 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci return 0; 196862306a36Sopenharmony_ci} 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci/* 197162306a36Sopenharmony_ci * Return the battery Voltage in millivolts 197262306a36Sopenharmony_ci * Or < 0 if something fails. 197362306a36Sopenharmony_ci */ 197462306a36Sopenharmony_cistatic int bq27xxx_battery_voltage(struct bq27xxx_device_info *di, 197562306a36Sopenharmony_ci union power_supply_propval *val) 197662306a36Sopenharmony_ci{ 197762306a36Sopenharmony_ci int volt; 197862306a36Sopenharmony_ci 197962306a36Sopenharmony_ci volt = bq27xxx_read(di, BQ27XXX_REG_VOLT, false); 198062306a36Sopenharmony_ci if (volt < 0) { 198162306a36Sopenharmony_ci dev_err(di->dev, "error reading voltage\n"); 198262306a36Sopenharmony_ci return volt; 198362306a36Sopenharmony_ci } 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ci val->intval = volt * 1000; 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci return 0; 198862306a36Sopenharmony_ci} 198962306a36Sopenharmony_ci 199062306a36Sopenharmony_cistatic int bq27xxx_simple_value(int value, 199162306a36Sopenharmony_ci union power_supply_propval *val) 199262306a36Sopenharmony_ci{ 199362306a36Sopenharmony_ci if (value < 0) 199462306a36Sopenharmony_ci return value; 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci val->intval = value; 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci return 0; 199962306a36Sopenharmony_ci} 200062306a36Sopenharmony_ci 200162306a36Sopenharmony_cistatic int bq27xxx_battery_get_property(struct power_supply *psy, 200262306a36Sopenharmony_ci enum power_supply_property psp, 200362306a36Sopenharmony_ci union power_supply_propval *val) 200462306a36Sopenharmony_ci{ 200562306a36Sopenharmony_ci int ret = 0; 200662306a36Sopenharmony_ci struct bq27xxx_device_info *di = power_supply_get_drvdata(psy); 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_ci mutex_lock(&di->lock); 200962306a36Sopenharmony_ci if (time_is_before_jiffies(di->last_update + 5 * HZ)) 201062306a36Sopenharmony_ci bq27xxx_battery_update_unlocked(di); 201162306a36Sopenharmony_ci mutex_unlock(&di->lock); 201262306a36Sopenharmony_ci 201362306a36Sopenharmony_ci if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0) 201462306a36Sopenharmony_ci return -ENODEV; 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci switch (psp) { 201762306a36Sopenharmony_ci case POWER_SUPPLY_PROP_STATUS: 201862306a36Sopenharmony_ci ret = bq27xxx_battery_current_and_status(di, NULL, val, NULL); 201962306a36Sopenharmony_ci break; 202062306a36Sopenharmony_ci case POWER_SUPPLY_PROP_VOLTAGE_NOW: 202162306a36Sopenharmony_ci ret = bq27xxx_battery_voltage(di, val); 202262306a36Sopenharmony_ci break; 202362306a36Sopenharmony_ci case POWER_SUPPLY_PROP_PRESENT: 202462306a36Sopenharmony_ci val->intval = di->cache.flags < 0 ? 0 : 1; 202562306a36Sopenharmony_ci break; 202662306a36Sopenharmony_ci case POWER_SUPPLY_PROP_CURRENT_NOW: 202762306a36Sopenharmony_ci ret = bq27xxx_battery_current_and_status(di, val, NULL, NULL); 202862306a36Sopenharmony_ci break; 202962306a36Sopenharmony_ci case POWER_SUPPLY_PROP_CAPACITY: 203062306a36Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.capacity, val); 203162306a36Sopenharmony_ci break; 203262306a36Sopenharmony_ci case POWER_SUPPLY_PROP_CAPACITY_LEVEL: 203362306a36Sopenharmony_ci ret = bq27xxx_battery_capacity_level(di, val); 203462306a36Sopenharmony_ci break; 203562306a36Sopenharmony_ci case POWER_SUPPLY_PROP_TEMP: 203662306a36Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.temperature, val); 203762306a36Sopenharmony_ci if (ret == 0) 203862306a36Sopenharmony_ci val->intval -= 2731; /* convert decidegree k to c */ 203962306a36Sopenharmony_ci break; 204062306a36Sopenharmony_ci case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: 204162306a36Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.time_to_empty, val); 204262306a36Sopenharmony_ci break; 204362306a36Sopenharmony_ci case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: 204462306a36Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.time_to_empty_avg, val); 204562306a36Sopenharmony_ci break; 204662306a36Sopenharmony_ci case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: 204762306a36Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.time_to_full, val); 204862306a36Sopenharmony_ci break; 204962306a36Sopenharmony_ci case POWER_SUPPLY_PROP_TECHNOLOGY: 205062306a36Sopenharmony_ci if (di->opts & BQ27XXX_O_MUL_CHEM) 205162306a36Sopenharmony_ci val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; 205262306a36Sopenharmony_ci else 205362306a36Sopenharmony_ci val->intval = POWER_SUPPLY_TECHNOLOGY_LION; 205462306a36Sopenharmony_ci break; 205562306a36Sopenharmony_ci case POWER_SUPPLY_PROP_CHARGE_NOW: 205662306a36Sopenharmony_ci if (di->regs[BQ27XXX_REG_NAC] != INVALID_REG_ADDR) 205762306a36Sopenharmony_ci ret = bq27xxx_simple_value(bq27xxx_battery_read_nac(di), val); 205862306a36Sopenharmony_ci else 205962306a36Sopenharmony_ci ret = bq27xxx_simple_value(bq27xxx_battery_read_rc(di), val); 206062306a36Sopenharmony_ci break; 206162306a36Sopenharmony_ci case POWER_SUPPLY_PROP_CHARGE_FULL: 206262306a36Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.charge_full, val); 206362306a36Sopenharmony_ci break; 206462306a36Sopenharmony_ci case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 206562306a36Sopenharmony_ci ret = bq27xxx_simple_value(di->charge_design_full, val); 206662306a36Sopenharmony_ci break; 206762306a36Sopenharmony_ci /* 206862306a36Sopenharmony_ci * TODO: Implement these to make registers set from 206962306a36Sopenharmony_ci * power_supply_battery_info visible in sysfs. 207062306a36Sopenharmony_ci */ 207162306a36Sopenharmony_ci case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: 207262306a36Sopenharmony_ci case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 207362306a36Sopenharmony_ci return -EINVAL; 207462306a36Sopenharmony_ci case POWER_SUPPLY_PROP_CYCLE_COUNT: 207562306a36Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.cycle_count, val); 207662306a36Sopenharmony_ci break; 207762306a36Sopenharmony_ci case POWER_SUPPLY_PROP_ENERGY_NOW: 207862306a36Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.energy, val); 207962306a36Sopenharmony_ci break; 208062306a36Sopenharmony_ci case POWER_SUPPLY_PROP_POWER_AVG: 208162306a36Sopenharmony_ci ret = bq27xxx_battery_pwr_avg(di, val); 208262306a36Sopenharmony_ci break; 208362306a36Sopenharmony_ci case POWER_SUPPLY_PROP_HEALTH: 208462306a36Sopenharmony_ci ret = bq27xxx_simple_value(di->cache.health, val); 208562306a36Sopenharmony_ci break; 208662306a36Sopenharmony_ci case POWER_SUPPLY_PROP_MANUFACTURER: 208762306a36Sopenharmony_ci val->strval = BQ27XXX_MANUFACTURER; 208862306a36Sopenharmony_ci break; 208962306a36Sopenharmony_ci default: 209062306a36Sopenharmony_ci return -EINVAL; 209162306a36Sopenharmony_ci } 209262306a36Sopenharmony_ci 209362306a36Sopenharmony_ci return ret; 209462306a36Sopenharmony_ci} 209562306a36Sopenharmony_ci 209662306a36Sopenharmony_cistatic void bq27xxx_external_power_changed(struct power_supply *psy) 209762306a36Sopenharmony_ci{ 209862306a36Sopenharmony_ci struct bq27xxx_device_info *di = power_supply_get_drvdata(psy); 209962306a36Sopenharmony_ci 210062306a36Sopenharmony_ci /* After charger plug in/out wait 0.5s for things to stabilize */ 210162306a36Sopenharmony_ci mod_delayed_work(system_wq, &di->work, HZ / 2); 210262306a36Sopenharmony_ci} 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ciint bq27xxx_battery_setup(struct bq27xxx_device_info *di) 210562306a36Sopenharmony_ci{ 210662306a36Sopenharmony_ci struct power_supply_desc *psy_desc; 210762306a36Sopenharmony_ci struct power_supply_config psy_cfg = { 210862306a36Sopenharmony_ci .of_node = di->dev->of_node, 210962306a36Sopenharmony_ci .drv_data = di, 211062306a36Sopenharmony_ci }; 211162306a36Sopenharmony_ci 211262306a36Sopenharmony_ci INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll); 211362306a36Sopenharmony_ci mutex_init(&di->lock); 211462306a36Sopenharmony_ci 211562306a36Sopenharmony_ci di->regs = bq27xxx_chip_data[di->chip].regs; 211662306a36Sopenharmony_ci di->unseal_key = bq27xxx_chip_data[di->chip].unseal_key; 211762306a36Sopenharmony_ci di->dm_regs = bq27xxx_chip_data[di->chip].dm_regs; 211862306a36Sopenharmony_ci di->opts = bq27xxx_chip_data[di->chip].opts; 211962306a36Sopenharmony_ci 212062306a36Sopenharmony_ci psy_desc = devm_kzalloc(di->dev, sizeof(*psy_desc), GFP_KERNEL); 212162306a36Sopenharmony_ci if (!psy_desc) 212262306a36Sopenharmony_ci return -ENOMEM; 212362306a36Sopenharmony_ci 212462306a36Sopenharmony_ci psy_desc->name = di->name; 212562306a36Sopenharmony_ci psy_desc->type = POWER_SUPPLY_TYPE_BATTERY; 212662306a36Sopenharmony_ci psy_desc->properties = bq27xxx_chip_data[di->chip].props; 212762306a36Sopenharmony_ci psy_desc->num_properties = bq27xxx_chip_data[di->chip].props_size; 212862306a36Sopenharmony_ci psy_desc->get_property = bq27xxx_battery_get_property; 212962306a36Sopenharmony_ci psy_desc->external_power_changed = bq27xxx_external_power_changed; 213062306a36Sopenharmony_ci 213162306a36Sopenharmony_ci di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg); 213262306a36Sopenharmony_ci if (IS_ERR(di->bat)) 213362306a36Sopenharmony_ci return dev_err_probe(di->dev, PTR_ERR(di->bat), 213462306a36Sopenharmony_ci "failed to register battery\n"); 213562306a36Sopenharmony_ci 213662306a36Sopenharmony_ci bq27xxx_battery_settings(di); 213762306a36Sopenharmony_ci bq27xxx_battery_update(di); 213862306a36Sopenharmony_ci 213962306a36Sopenharmony_ci mutex_lock(&bq27xxx_list_lock); 214062306a36Sopenharmony_ci list_add(&di->list, &bq27xxx_battery_devices); 214162306a36Sopenharmony_ci mutex_unlock(&bq27xxx_list_lock); 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci return 0; 214462306a36Sopenharmony_ci} 214562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bq27xxx_battery_setup); 214662306a36Sopenharmony_ci 214762306a36Sopenharmony_civoid bq27xxx_battery_teardown(struct bq27xxx_device_info *di) 214862306a36Sopenharmony_ci{ 214962306a36Sopenharmony_ci mutex_lock(&bq27xxx_list_lock); 215062306a36Sopenharmony_ci list_del(&di->list); 215162306a36Sopenharmony_ci mutex_unlock(&bq27xxx_list_lock); 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci /* Set removed to avoid bq27xxx_battery_update() re-queuing the work */ 215462306a36Sopenharmony_ci mutex_lock(&di->lock); 215562306a36Sopenharmony_ci di->removed = true; 215662306a36Sopenharmony_ci mutex_unlock(&di->lock); 215762306a36Sopenharmony_ci 215862306a36Sopenharmony_ci cancel_delayed_work_sync(&di->work); 215962306a36Sopenharmony_ci 216062306a36Sopenharmony_ci power_supply_unregister(di->bat); 216162306a36Sopenharmony_ci mutex_destroy(&di->lock); 216262306a36Sopenharmony_ci} 216362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(bq27xxx_battery_teardown); 216462306a36Sopenharmony_ci 216562306a36Sopenharmony_ciMODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); 216662306a36Sopenharmony_ciMODULE_DESCRIPTION("BQ27xxx battery monitor driver"); 216762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 2168