cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cw2015_battery.c (19641B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Fuel gauge driver for CellWise 2013 / 2015
      4 *
      5 * Copyright (C) 2012, RockChip
      6 * Copyright (C) 2020, Tobias Schramm
      7 *
      8 * Authors: xuhuicong <xhc@rock-chips.com>
      9 * Authors: Tobias Schramm <t.schramm@manjaro.org>
     10 */
     11
     12#include <linux/bits.h>
     13#include <linux/delay.h>
     14#include <linux/i2c.h>
     15#include <linux/gfp.h>
     16#include <linux/gpio/consumer.h>
     17#include <linux/kernel.h>
     18#include <linux/module.h>
     19#include <linux/power_supply.h>
     20#include <linux/property.h>
     21#include <linux/regmap.h>
     22#include <linux/time.h>
     23#include <linux/workqueue.h>
     24
     25#define CW2015_SIZE_BATINFO		64
     26
     27#define CW2015_RESET_TRIES		5
     28
     29#define CW2015_REG_VERSION		0x00
     30#define CW2015_REG_VCELL		0x02
     31#define CW2015_REG_SOC			0x04
     32#define CW2015_REG_RRT_ALERT		0x06
     33#define CW2015_REG_CONFIG		0x08
     34#define CW2015_REG_MODE			0x0A
     35#define CW2015_REG_BATINFO		0x10
     36
     37#define CW2015_MODE_SLEEP_MASK		GENMASK(7, 6)
     38#define CW2015_MODE_SLEEP		(0x03 << 6)
     39#define CW2015_MODE_NORMAL		(0x00 << 6)
     40#define CW2015_MODE_QUICK_START		(0x03 << 4)
     41#define CW2015_MODE_RESTART		(0x0f << 0)
     42
     43#define CW2015_CONFIG_UPDATE_FLG	(0x01 << 1)
     44#define CW2015_ATHD(x)			((x) << 3)
     45#define CW2015_MASK_ATHD		GENMASK(7, 3)
     46#define CW2015_MASK_SOC			GENMASK(12, 0)
     47
     48/* reset gauge of no valid state of charge could be polled for 40s */
     49#define CW2015_BAT_SOC_ERROR_MS		(40 * MSEC_PER_SEC)
     50/* reset gauge if state of charge stuck for half an hour during charging */
     51#define CW2015_BAT_CHARGING_STUCK_MS	(1800 * MSEC_PER_SEC)
     52
     53/* poll interval from CellWise GPL Android driver example */
     54#define CW2015_DEFAULT_POLL_INTERVAL_MS		8000
     55
     56#define CW2015_AVERAGING_SAMPLES		3
     57
     58struct cw_battery {
     59	struct device *dev;
     60	struct workqueue_struct *battery_workqueue;
     61	struct delayed_work battery_delay_work;
     62	struct regmap *regmap;
     63	struct power_supply *rk_bat;
     64	struct power_supply_battery_info *battery;
     65	u8 *bat_profile;
     66
     67	bool charger_attached;
     68	bool battery_changed;
     69
     70	int soc;
     71	int voltage_mv;
     72	int status;
     73	int time_to_empty;
     74	int charge_count;
     75
     76	u32 poll_interval_ms;
     77	u8 alert_level;
     78
     79	unsigned int read_errors;
     80	unsigned int charge_stuck_cnt;
     81};
     82
     83static int cw_read_word(struct cw_battery *cw_bat, u8 reg, u16 *val)
     84{
     85	__be16 value;
     86	int ret;
     87
     88	ret = regmap_bulk_read(cw_bat->regmap, reg, &value, sizeof(value));
     89	if (ret)
     90		return ret;
     91
     92	*val = be16_to_cpu(value);
     93	return 0;
     94}
     95
     96static int cw_update_profile(struct cw_battery *cw_bat)
     97{
     98	int ret;
     99	unsigned int reg_val;
    100	u8 reset_val;
    101
    102	/* make sure gauge is not in sleep mode */
    103	ret = regmap_read(cw_bat->regmap, CW2015_REG_MODE, &reg_val);
    104	if (ret)
    105		return ret;
    106
    107	reset_val = reg_val;
    108	if ((reg_val & CW2015_MODE_SLEEP_MASK) == CW2015_MODE_SLEEP) {
    109		dev_err(cw_bat->dev,
    110			"Gauge is in sleep mode, can't update battery info\n");
    111		return -EINVAL;
    112	}
    113
    114	/* write new battery info */
    115	ret = regmap_raw_write(cw_bat->regmap, CW2015_REG_BATINFO,
    116			       cw_bat->bat_profile,
    117			       CW2015_SIZE_BATINFO);
    118	if (ret)
    119		return ret;
    120
    121	/* set config update flag  */
    122	reg_val |= CW2015_CONFIG_UPDATE_FLG;
    123	reg_val &= ~CW2015_MASK_ATHD;
    124	reg_val |= CW2015_ATHD(cw_bat->alert_level);
    125	ret = regmap_write(cw_bat->regmap, CW2015_REG_CONFIG, reg_val);
    126	if (ret)
    127		return ret;
    128
    129	/* reset gauge to apply new battery profile */
    130	reset_val &= ~CW2015_MODE_RESTART;
    131	reg_val = reset_val | CW2015_MODE_RESTART;
    132	ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reg_val);
    133	if (ret)
    134		return ret;
    135
    136	/* wait for gauge to reset */
    137	msleep(20);
    138
    139	/* clear reset flag */
    140	ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reset_val);
    141	if (ret)
    142		return ret;
    143
    144	/* wait for gauge to become ready */
    145	ret = regmap_read_poll_timeout(cw_bat->regmap, CW2015_REG_SOC,
    146				       reg_val, reg_val <= 100,
    147				       10 * USEC_PER_MSEC, 10 * USEC_PER_SEC);
    148	if (ret)
    149		dev_err(cw_bat->dev,
    150			"Gauge did not become ready after profile upload\n");
    151	else
    152		dev_dbg(cw_bat->dev, "Battery profile updated\n");
    153
    154	return ret;
    155}
    156
    157static int cw_init(struct cw_battery *cw_bat)
    158{
    159	int ret;
    160	unsigned int reg_val = CW2015_MODE_SLEEP;
    161
    162	if ((reg_val & CW2015_MODE_SLEEP_MASK) == CW2015_MODE_SLEEP) {
    163		reg_val = CW2015_MODE_NORMAL;
    164		ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reg_val);
    165		if (ret)
    166			return ret;
    167	}
    168
    169	ret = regmap_read(cw_bat->regmap, CW2015_REG_CONFIG, &reg_val);
    170	if (ret)
    171		return ret;
    172
    173	if ((reg_val & CW2015_MASK_ATHD) != CW2015_ATHD(cw_bat->alert_level)) {
    174		dev_dbg(cw_bat->dev, "Setting new alert level\n");
    175		reg_val &= ~CW2015_MASK_ATHD;
    176		reg_val |= ~CW2015_ATHD(cw_bat->alert_level);
    177		ret = regmap_write(cw_bat->regmap, CW2015_REG_CONFIG, reg_val);
    178		if (ret)
    179			return ret;
    180	}
    181
    182	ret = regmap_read(cw_bat->regmap, CW2015_REG_CONFIG, &reg_val);
    183	if (ret)
    184		return ret;
    185
    186	if (!(reg_val & CW2015_CONFIG_UPDATE_FLG)) {
    187		dev_dbg(cw_bat->dev,
    188			"Battery profile not present, uploading battery profile\n");
    189		if (cw_bat->bat_profile) {
    190			ret = cw_update_profile(cw_bat);
    191			if (ret) {
    192				dev_err(cw_bat->dev,
    193					"Failed to upload battery profile\n");
    194				return ret;
    195			}
    196		} else {
    197			dev_warn(cw_bat->dev,
    198				 "No profile specified, continuing without profile\n");
    199		}
    200	} else if (cw_bat->bat_profile) {
    201		u8 bat_info[CW2015_SIZE_BATINFO];
    202
    203		ret = regmap_raw_read(cw_bat->regmap, CW2015_REG_BATINFO,
    204				      bat_info, CW2015_SIZE_BATINFO);
    205		if (ret) {
    206			dev_err(cw_bat->dev,
    207				"Failed to read stored battery profile\n");
    208			return ret;
    209		}
    210
    211		if (memcmp(bat_info, cw_bat->bat_profile, CW2015_SIZE_BATINFO)) {
    212			dev_warn(cw_bat->dev, "Replacing stored battery profile\n");
    213			ret = cw_update_profile(cw_bat);
    214			if (ret)
    215				return ret;
    216		}
    217	} else {
    218		dev_warn(cw_bat->dev,
    219			 "Can't check current battery profile, no profile provided\n");
    220	}
    221
    222	dev_dbg(cw_bat->dev, "Battery profile configured\n");
    223	return 0;
    224}
    225
    226static int cw_power_on_reset(struct cw_battery *cw_bat)
    227{
    228	int ret;
    229	unsigned char reset_val;
    230
    231	reset_val = CW2015_MODE_SLEEP;
    232	ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reset_val);
    233	if (ret)
    234		return ret;
    235
    236	/* wait for gauge to enter sleep */
    237	msleep(20);
    238
    239	reset_val = CW2015_MODE_NORMAL;
    240	ret = regmap_write(cw_bat->regmap, CW2015_REG_MODE, reset_val);
    241	if (ret)
    242		return ret;
    243
    244	ret = cw_init(cw_bat);
    245	if (ret)
    246		return ret;
    247	return 0;
    248}
    249
    250#define HYSTERESIS(current, previous, up, down) \
    251	(((current) < (previous) + (up)) && ((current) > (previous) - (down)))
    252
    253static int cw_get_soc(struct cw_battery *cw_bat)
    254{
    255	unsigned int soc;
    256	int ret;
    257
    258	ret = regmap_read(cw_bat->regmap, CW2015_REG_SOC, &soc);
    259	if (ret)
    260		return ret;
    261
    262	if (soc > 100) {
    263		int max_error_cycles =
    264			CW2015_BAT_SOC_ERROR_MS / cw_bat->poll_interval_ms;
    265
    266		dev_err(cw_bat->dev, "Invalid SoC %d%%\n", soc);
    267		cw_bat->read_errors++;
    268		if (cw_bat->read_errors > max_error_cycles) {
    269			dev_warn(cw_bat->dev,
    270				 "Too many invalid SoC reports, resetting gauge\n");
    271			cw_power_on_reset(cw_bat);
    272			cw_bat->read_errors = 0;
    273		}
    274		return cw_bat->soc;
    275	}
    276	cw_bat->read_errors = 0;
    277
    278	/* Reset gauge if stuck while charging */
    279	if (cw_bat->status == POWER_SUPPLY_STATUS_CHARGING && soc == cw_bat->soc) {
    280		int max_stuck_cycles =
    281			CW2015_BAT_CHARGING_STUCK_MS / cw_bat->poll_interval_ms;
    282
    283		cw_bat->charge_stuck_cnt++;
    284		if (cw_bat->charge_stuck_cnt > max_stuck_cycles) {
    285			dev_warn(cw_bat->dev,
    286				 "SoC stuck @%u%%, resetting gauge\n", soc);
    287			cw_power_on_reset(cw_bat);
    288			cw_bat->charge_stuck_cnt = 0;
    289		}
    290	} else {
    291		cw_bat->charge_stuck_cnt = 0;
    292	}
    293
    294	/* Ignore voltage dips during charge */
    295	if (cw_bat->charger_attached && HYSTERESIS(soc, cw_bat->soc, 0, 3))
    296		soc = cw_bat->soc;
    297
    298	/* Ignore voltage spikes during discharge */
    299	if (!cw_bat->charger_attached && HYSTERESIS(soc, cw_bat->soc, 3, 0))
    300		soc = cw_bat->soc;
    301
    302	return soc;
    303}
    304
    305static int cw_get_voltage(struct cw_battery *cw_bat)
    306{
    307	int ret, i, voltage_mv;
    308	u16 reg_val;
    309	u32 avg = 0;
    310
    311	for (i = 0; i < CW2015_AVERAGING_SAMPLES; i++) {
    312		ret = cw_read_word(cw_bat, CW2015_REG_VCELL, &reg_val);
    313		if (ret)
    314			return ret;
    315
    316		avg += reg_val;
    317	}
    318	avg /= CW2015_AVERAGING_SAMPLES;
    319
    320	/*
    321	 * 305 uV per ADC step
    322	 * Use 312 / 1024  as efficient approximation of 305 / 1000
    323	 * Negligible error of 0.1%
    324	 */
    325	voltage_mv = avg * 312 / 1024;
    326
    327	dev_dbg(cw_bat->dev, "Read voltage: %d mV, raw=0x%04x\n",
    328		voltage_mv, reg_val);
    329	return voltage_mv;
    330}
    331
    332static int cw_get_time_to_empty(struct cw_battery *cw_bat)
    333{
    334	int ret;
    335	u16 value16;
    336
    337	ret = cw_read_word(cw_bat, CW2015_REG_RRT_ALERT, &value16);
    338	if (ret)
    339		return ret;
    340
    341	return value16 & CW2015_MASK_SOC;
    342}
    343
    344static void cw_update_charge_status(struct cw_battery *cw_bat)
    345{
    346	int ret;
    347
    348	ret = power_supply_am_i_supplied(cw_bat->rk_bat);
    349	if (ret < 0) {
    350		dev_warn(cw_bat->dev, "Failed to get supply state: %d\n", ret);
    351	} else {
    352		bool charger_attached;
    353
    354		charger_attached = !!ret;
    355		if (cw_bat->charger_attached != charger_attached) {
    356			cw_bat->battery_changed = true;
    357			if (charger_attached)
    358				cw_bat->charge_count++;
    359		}
    360		cw_bat->charger_attached = charger_attached;
    361	}
    362}
    363
    364static void cw_update_soc(struct cw_battery *cw_bat)
    365{
    366	int soc;
    367
    368	soc = cw_get_soc(cw_bat);
    369	if (soc < 0)
    370		dev_err(cw_bat->dev, "Failed to get SoC from gauge: %d\n", soc);
    371	else if (cw_bat->soc != soc) {
    372		cw_bat->soc = soc;
    373		cw_bat->battery_changed = true;
    374	}
    375}
    376
    377static void cw_update_voltage(struct cw_battery *cw_bat)
    378{
    379	int voltage_mv;
    380
    381	voltage_mv = cw_get_voltage(cw_bat);
    382	if (voltage_mv < 0)
    383		dev_err(cw_bat->dev, "Failed to get voltage from gauge: %d\n",
    384			voltage_mv);
    385	else
    386		cw_bat->voltage_mv = voltage_mv;
    387}
    388
    389static void cw_update_status(struct cw_battery *cw_bat)
    390{
    391	int status = POWER_SUPPLY_STATUS_DISCHARGING;
    392
    393	if (cw_bat->charger_attached) {
    394		if (cw_bat->soc >= 100)
    395			status = POWER_SUPPLY_STATUS_FULL;
    396		else
    397			status = POWER_SUPPLY_STATUS_CHARGING;
    398	}
    399
    400	if (cw_bat->status != status)
    401		cw_bat->battery_changed = true;
    402	cw_bat->status = status;
    403}
    404
    405static void cw_update_time_to_empty(struct cw_battery *cw_bat)
    406{
    407	int time_to_empty;
    408
    409	time_to_empty = cw_get_time_to_empty(cw_bat);
    410	if (time_to_empty < 0)
    411		dev_err(cw_bat->dev, "Failed to get time to empty from gauge: %d\n",
    412			time_to_empty);
    413	else if (cw_bat->time_to_empty != time_to_empty) {
    414		cw_bat->time_to_empty = time_to_empty;
    415		cw_bat->battery_changed = true;
    416	}
    417}
    418
    419static void cw_bat_work(struct work_struct *work)
    420{
    421	struct delayed_work *delay_work;
    422	struct cw_battery *cw_bat;
    423	int ret;
    424	unsigned int reg_val;
    425
    426	delay_work = to_delayed_work(work);
    427	cw_bat = container_of(delay_work, struct cw_battery, battery_delay_work);
    428	ret = regmap_read(cw_bat->regmap, CW2015_REG_MODE, &reg_val);
    429	if (ret) {
    430		dev_err(cw_bat->dev, "Failed to read mode from gauge: %d\n", ret);
    431	} else {
    432		if ((reg_val & CW2015_MODE_SLEEP_MASK) == CW2015_MODE_SLEEP) {
    433			int i;
    434
    435			for (i = 0; i < CW2015_RESET_TRIES; i++) {
    436				if (!cw_power_on_reset(cw_bat))
    437					break;
    438			}
    439		}
    440		cw_update_soc(cw_bat);
    441		cw_update_voltage(cw_bat);
    442		cw_update_charge_status(cw_bat);
    443		cw_update_status(cw_bat);
    444		cw_update_time_to_empty(cw_bat);
    445	}
    446	dev_dbg(cw_bat->dev, "charger_attached = %d\n", cw_bat->charger_attached);
    447	dev_dbg(cw_bat->dev, "status = %d\n", cw_bat->status);
    448	dev_dbg(cw_bat->dev, "soc = %d%%\n", cw_bat->soc);
    449	dev_dbg(cw_bat->dev, "voltage = %dmV\n", cw_bat->voltage_mv);
    450
    451	if (cw_bat->battery_changed)
    452		power_supply_changed(cw_bat->rk_bat);
    453	cw_bat->battery_changed = false;
    454
    455	queue_delayed_work(cw_bat->battery_workqueue,
    456			   &cw_bat->battery_delay_work,
    457			   msecs_to_jiffies(cw_bat->poll_interval_ms));
    458}
    459
    460static bool cw_battery_valid_time_to_empty(struct cw_battery *cw_bat)
    461{
    462	return	cw_bat->time_to_empty > 0 &&
    463		cw_bat->time_to_empty < CW2015_MASK_SOC &&
    464		cw_bat->status == POWER_SUPPLY_STATUS_DISCHARGING;
    465}
    466
    467static int cw_battery_get_property(struct power_supply *psy,
    468				   enum power_supply_property psp,
    469				   union power_supply_propval *val)
    470{
    471	struct cw_battery *cw_bat;
    472
    473	cw_bat = power_supply_get_drvdata(psy);
    474	switch (psp) {
    475	case POWER_SUPPLY_PROP_CAPACITY:
    476		val->intval = cw_bat->soc;
    477		break;
    478
    479	case POWER_SUPPLY_PROP_STATUS:
    480		val->intval = cw_bat->status;
    481		break;
    482
    483	case POWER_SUPPLY_PROP_PRESENT:
    484		val->intval = !!cw_bat->voltage_mv;
    485		break;
    486
    487	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
    488		val->intval = cw_bat->voltage_mv * 1000;
    489		break;
    490
    491	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
    492		if (cw_battery_valid_time_to_empty(cw_bat))
    493			val->intval = cw_bat->time_to_empty;
    494		else
    495			val->intval = 0;
    496		break;
    497
    498	case POWER_SUPPLY_PROP_TECHNOLOGY:
    499		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
    500		break;
    501
    502	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
    503		val->intval = cw_bat->charge_count;
    504		break;
    505
    506	case POWER_SUPPLY_PROP_CHARGE_FULL:
    507	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
    508		if (cw_bat->battery->charge_full_design_uah > 0)
    509			val->intval = cw_bat->battery->charge_full_design_uah;
    510		else
    511			val->intval = 0;
    512		break;
    513
    514	case POWER_SUPPLY_PROP_CHARGE_NOW:
    515		val->intval = cw_bat->battery->charge_full_design_uah;
    516		val->intval = val->intval * cw_bat->soc / 100;
    517		break;
    518
    519	case POWER_SUPPLY_PROP_CURRENT_NOW:
    520		if (cw_battery_valid_time_to_empty(cw_bat) &&
    521		    cw_bat->battery->charge_full_design_uah > 0) {
    522			/* calculate remaining capacity */
    523			val->intval = cw_bat->battery->charge_full_design_uah;
    524			val->intval = val->intval * cw_bat->soc / 100;
    525
    526			/* estimate current based on time to empty */
    527			val->intval = 60 * val->intval / cw_bat->time_to_empty;
    528		} else {
    529			val->intval = 0;
    530		}
    531
    532		break;
    533
    534	default:
    535		break;
    536	}
    537	return 0;
    538}
    539
    540static enum power_supply_property cw_battery_properties[] = {
    541	POWER_SUPPLY_PROP_CAPACITY,
    542	POWER_SUPPLY_PROP_STATUS,
    543	POWER_SUPPLY_PROP_PRESENT,
    544	POWER_SUPPLY_PROP_VOLTAGE_NOW,
    545	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
    546	POWER_SUPPLY_PROP_TECHNOLOGY,
    547	POWER_SUPPLY_PROP_CHARGE_COUNTER,
    548	POWER_SUPPLY_PROP_CHARGE_FULL,
    549	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
    550	POWER_SUPPLY_PROP_CHARGE_NOW,
    551	POWER_SUPPLY_PROP_CURRENT_NOW,
    552};
    553
    554static const struct power_supply_desc cw2015_bat_desc = {
    555	.name		= "cw2015-battery",
    556	.type		= POWER_SUPPLY_TYPE_BATTERY,
    557	.properties	= cw_battery_properties,
    558	.num_properties	= ARRAY_SIZE(cw_battery_properties),
    559	.get_property	= cw_battery_get_property,
    560};
    561
    562static int cw2015_parse_properties(struct cw_battery *cw_bat)
    563{
    564	struct device *dev = cw_bat->dev;
    565	int length;
    566	int ret;
    567
    568	length = device_property_count_u8(dev, "cellwise,battery-profile");
    569	if (length < 0) {
    570		dev_warn(cw_bat->dev,
    571			 "No battery-profile found, using current flash contents\n");
    572	} else if (length != CW2015_SIZE_BATINFO) {
    573		dev_err(cw_bat->dev, "battery-profile must be %d bytes\n",
    574			CW2015_SIZE_BATINFO);
    575		return -EINVAL;
    576	} else {
    577		cw_bat->bat_profile = devm_kzalloc(dev, length, GFP_KERNEL);
    578		if (!cw_bat->bat_profile)
    579			return -ENOMEM;
    580
    581		ret = device_property_read_u8_array(dev,
    582						"cellwise,battery-profile",
    583						cw_bat->bat_profile,
    584						length);
    585		if (ret)
    586			return ret;
    587	}
    588
    589	ret = device_property_read_u32(dev, "cellwise,monitor-interval-ms",
    590				       &cw_bat->poll_interval_ms);
    591	if (ret) {
    592		dev_dbg(cw_bat->dev, "Using default poll interval\n");
    593		cw_bat->poll_interval_ms = CW2015_DEFAULT_POLL_INTERVAL_MS;
    594	}
    595
    596	return 0;
    597}
    598
    599static const struct regmap_range regmap_ranges_rd_yes[] = {
    600	regmap_reg_range(CW2015_REG_VERSION, CW2015_REG_VERSION),
    601	regmap_reg_range(CW2015_REG_VCELL, CW2015_REG_CONFIG),
    602	regmap_reg_range(CW2015_REG_MODE, CW2015_REG_MODE),
    603	regmap_reg_range(CW2015_REG_BATINFO,
    604			CW2015_REG_BATINFO + CW2015_SIZE_BATINFO - 1),
    605};
    606
    607static const struct regmap_access_table regmap_rd_table = {
    608	.yes_ranges = regmap_ranges_rd_yes,
    609	.n_yes_ranges = 4,
    610};
    611
    612static const struct regmap_range regmap_ranges_wr_yes[] = {
    613	regmap_reg_range(CW2015_REG_RRT_ALERT, CW2015_REG_CONFIG),
    614	regmap_reg_range(CW2015_REG_MODE, CW2015_REG_MODE),
    615	regmap_reg_range(CW2015_REG_BATINFO,
    616			CW2015_REG_BATINFO + CW2015_SIZE_BATINFO - 1),
    617};
    618
    619static const struct regmap_access_table regmap_wr_table = {
    620	.yes_ranges = regmap_ranges_wr_yes,
    621	.n_yes_ranges = 3,
    622};
    623
    624static const struct regmap_range regmap_ranges_vol_yes[] = {
    625	regmap_reg_range(CW2015_REG_VCELL, CW2015_REG_SOC + 1),
    626};
    627
    628static const struct regmap_access_table regmap_vol_table = {
    629	.yes_ranges = regmap_ranges_vol_yes,
    630	.n_yes_ranges = 1,
    631};
    632
    633static const struct regmap_config cw2015_regmap_config = {
    634	.reg_bits = 8,
    635	.val_bits = 8,
    636	.rd_table = &regmap_rd_table,
    637	.wr_table = &regmap_wr_table,
    638	.volatile_table = &regmap_vol_table,
    639	.max_register = CW2015_REG_BATINFO + CW2015_SIZE_BATINFO - 1,
    640};
    641
    642static int cw_bat_probe(struct i2c_client *client)
    643{
    644	int ret;
    645	struct cw_battery *cw_bat;
    646	struct power_supply_config psy_cfg = { 0 };
    647
    648	cw_bat = devm_kzalloc(&client->dev, sizeof(*cw_bat), GFP_KERNEL);
    649	if (!cw_bat)
    650		return -ENOMEM;
    651
    652	i2c_set_clientdata(client, cw_bat);
    653	cw_bat->dev = &client->dev;
    654	cw_bat->soc = 1;
    655
    656	ret = cw2015_parse_properties(cw_bat);
    657	if (ret) {
    658		dev_err(cw_bat->dev, "Failed to parse cw2015 properties\n");
    659		return ret;
    660	}
    661
    662	cw_bat->regmap = devm_regmap_init_i2c(client, &cw2015_regmap_config);
    663	if (IS_ERR(cw_bat->regmap)) {
    664		dev_err(cw_bat->dev, "Failed to allocate regmap: %ld\n",
    665			PTR_ERR(cw_bat->regmap));
    666		return PTR_ERR(cw_bat->regmap);
    667	}
    668
    669	ret = cw_init(cw_bat);
    670	if (ret) {
    671		dev_err(cw_bat->dev, "Init failed: %d\n", ret);
    672		return ret;
    673	}
    674
    675	psy_cfg.drv_data = cw_bat;
    676	psy_cfg.fwnode = dev_fwnode(cw_bat->dev);
    677
    678	cw_bat->rk_bat = devm_power_supply_register(&client->dev,
    679						    &cw2015_bat_desc,
    680						    &psy_cfg);
    681	if (IS_ERR(cw_bat->rk_bat)) {
    682		/* try again if this happens */
    683		dev_err_probe(&client->dev, PTR_ERR(cw_bat->rk_bat),
    684			"Failed to register power supply\n");
    685		return PTR_ERR(cw_bat->rk_bat);
    686	}
    687
    688	ret = power_supply_get_battery_info(cw_bat->rk_bat, &cw_bat->battery);
    689	if (ret) {
    690		/* Allocate an empty battery */
    691		cw_bat->battery = devm_kzalloc(&client->dev,
    692					       sizeof(*cw_bat->battery),
    693					       GFP_KERNEL);
    694		if (!cw_bat->battery)
    695			return -ENOMEM;
    696		dev_warn(cw_bat->dev,
    697			 "No monitored battery, some properties will be missing\n");
    698	}
    699
    700	cw_bat->battery_workqueue = create_singlethread_workqueue("rk_battery");
    701	INIT_DELAYED_WORK(&cw_bat->battery_delay_work, cw_bat_work);
    702	queue_delayed_work(cw_bat->battery_workqueue,
    703			   &cw_bat->battery_delay_work, msecs_to_jiffies(10));
    704	return 0;
    705}
    706
    707static int __maybe_unused cw_bat_suspend(struct device *dev)
    708{
    709	struct i2c_client *client = to_i2c_client(dev);
    710	struct cw_battery *cw_bat = i2c_get_clientdata(client);
    711
    712	cancel_delayed_work_sync(&cw_bat->battery_delay_work);
    713	return 0;
    714}
    715
    716static int __maybe_unused cw_bat_resume(struct device *dev)
    717{
    718	struct i2c_client *client = to_i2c_client(dev);
    719	struct cw_battery *cw_bat = i2c_get_clientdata(client);
    720
    721	queue_delayed_work(cw_bat->battery_workqueue,
    722			   &cw_bat->battery_delay_work, 0);
    723	return 0;
    724}
    725
    726static SIMPLE_DEV_PM_OPS(cw_bat_pm_ops, cw_bat_suspend, cw_bat_resume);
    727
    728static int cw_bat_remove(struct i2c_client *client)
    729{
    730	struct cw_battery *cw_bat = i2c_get_clientdata(client);
    731
    732	cancel_delayed_work_sync(&cw_bat->battery_delay_work);
    733	power_supply_put_battery_info(cw_bat->rk_bat, cw_bat->battery);
    734	return 0;
    735}
    736
    737static const struct i2c_device_id cw_bat_id_table[] = {
    738	{ "cw2015", 0 },
    739	{ }
    740};
    741
    742static const struct of_device_id cw2015_of_match[] = {
    743	{ .compatible = "cellwise,cw2015" },
    744	{ }
    745};
    746MODULE_DEVICE_TABLE(of, cw2015_of_match);
    747
    748static struct i2c_driver cw_bat_driver = {
    749	.driver = {
    750		.name = "cw2015",
    751		.of_match_table = cw2015_of_match,
    752		.pm = &cw_bat_pm_ops,
    753	},
    754	.probe_new = cw_bat_probe,
    755	.remove = cw_bat_remove,
    756	.id_table = cw_bat_id_table,
    757};
    758
    759module_i2c_driver(cw_bat_driver);
    760
    761MODULE_AUTHOR("xhc<xhc@rock-chips.com>");
    762MODULE_AUTHOR("Tobias Schramm <t.schramm@manjaro.org>");
    763MODULE_DESCRIPTION("cw2015/cw2013 battery driver");
    764MODULE_LICENSE("GPL");