brintos

brintos / linux-shallow public Read only

0
0
Text · 30.8 KiB · 30ec76c Raw
1179 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Battery driver for CPCAP PMIC4 *5 * Copyright (C) 2017 Tony Lindgren <tony@atomide.com>6 *7 * Some parts of the code based on earlier Motorola mapphone Linux kernel8 * drivers:9 *10 * Copyright (C) 2009-2010 Motorola, Inc.11 */12 13#include <linux/delay.h>14#include <linux/err.h>15#include <linux/interrupt.h>16#include <linux/kernel.h>17#include <linux/module.h>18#include <linux/of.h>19#include <linux/platform_device.h>20#include <linux/power_supply.h>21#include <linux/reboot.h>22#include <linux/regmap.h>23#include <linux/nvmem-consumer.h>24#include <linux/moduleparam.h>25 26#include <linux/iio/consumer.h>27#include <linux/iio/types.h>28#include <linux/mfd/motorola-cpcap.h>29 30/*31 * Register bit defines for CPCAP_REG_BPEOL. Some of these seem to32 * map to MC13783UG.pdf "Table 5-19. Register 13, Power Control 0"33 * to enable BATTDETEN, LOBAT and EOL features. We currently use34 * LOBAT interrupts instead of EOL.35 */36#define CPCAP_REG_BPEOL_BIT_EOL9	BIT(9)	/* Set for EOL irq */37#define CPCAP_REG_BPEOL_BIT_EOL8	BIT(8)	/* Set for EOL irq */38#define CPCAP_REG_BPEOL_BIT_UNKNOWN7	BIT(7)39#define CPCAP_REG_BPEOL_BIT_UNKNOWN6	BIT(6)40#define CPCAP_REG_BPEOL_BIT_UNKNOWN5	BIT(5)41#define CPCAP_REG_BPEOL_BIT_EOL_MULTI	BIT(4)	/* Set for multiple EOL irqs */42#define CPCAP_REG_BPEOL_BIT_UNKNOWN3	BIT(3)43#define CPCAP_REG_BPEOL_BIT_UNKNOWN2	BIT(2)44#define CPCAP_REG_BPEOL_BIT_BATTDETEN	BIT(1)	/* Enable battery detect */45#define CPCAP_REG_BPEOL_BIT_EOLSEL	BIT(0)	/* BPDET = 0, EOL = 1 */46 47/*48 * Register bit defines for CPCAP_REG_CCC1. These seem similar to the twl603049 * coulomb counter registers rather than the mc13892 registers. Both twl603050 * and mc13892 set bits 2 and 1 to reset and clear registers. But mc1389251 * sets bit 0 to start the coulomb counter while twl6030 sets bit 0 to stop52 * the coulomb counter like cpcap does. So for now, we use the twl6030 style53 * naming for the registers.54 */55#define CPCAP_REG_CCC1_ACTIVE_MODE1	BIT(4)	/* Update rate */56#define CPCAP_REG_CCC1_ACTIVE_MODE0	BIT(3)	/* Update rate */57#define CPCAP_REG_CCC1_AUTOCLEAR	BIT(2)	/* Resets sample registers */58#define CPCAP_REG_CCC1_CAL_EN		BIT(1)	/* Clears after write in 1s */59#define CPCAP_REG_CCC1_PAUSE		BIT(0)	/* Stop counters, allow write */60#define CPCAP_REG_CCC1_RESET_MASK	(CPCAP_REG_CCC1_AUTOCLEAR | \61					 CPCAP_REG_CCC1_CAL_EN)62 63#define CPCAP_REG_CCCC2_RATE1		BIT(5)64#define CPCAP_REG_CCCC2_RATE0		BIT(4)65#define CPCAP_REG_CCCC2_ENABLE		BIT(3)66 67#define CPCAP_BATTERY_CC_SAMPLE_PERIOD_MS	25068 69#define CPCAP_BATTERY_EB41_HW4X_ID 0x9E70#define CPCAP_BATTERY_BW8X_ID 0x9871 72enum {73	CPCAP_BATTERY_IIO_BATTDET,74	CPCAP_BATTERY_IIO_VOLTAGE,75	CPCAP_BATTERY_IIO_CHRG_CURRENT,76	CPCAP_BATTERY_IIO_BATT_CURRENT,77	CPCAP_BATTERY_IIO_NR,78};79 80enum cpcap_battery_irq_action {81	CPCAP_BATTERY_IRQ_ACTION_NONE,82	CPCAP_BATTERY_IRQ_ACTION_CC_CAL_DONE,83	CPCAP_BATTERY_IRQ_ACTION_BATTERY_LOW,84	CPCAP_BATTERY_IRQ_ACTION_POWEROFF,85};86 87struct cpcap_interrupt_desc {88	const char *name;89	struct list_head node;90	int irq;91	enum cpcap_battery_irq_action action;92};93 94struct cpcap_battery_config {95	int cd_factor;96	struct power_supply_info info;97	struct power_supply_battery_info bat;98};99 100struct cpcap_coulomb_counter_data {101	s32 sample;		/* 24 or 32 bits */102	s32 accumulator;103	s16 offset;		/* 9 bits */104	s16 integrator;		/* 13 or 16 bits */105};106 107enum cpcap_battery_state {108	CPCAP_BATTERY_STATE_PREVIOUS,109	CPCAP_BATTERY_STATE_LATEST,110	CPCAP_BATTERY_STATE_EMPTY,111	CPCAP_BATTERY_STATE_FULL,112	CPCAP_BATTERY_STATE_NR,113};114 115struct cpcap_battery_state_data {116	int voltage;117	int current_ua;118	int counter_uah;119	int temperature;120	ktime_t time;121	struct cpcap_coulomb_counter_data cc;122};123 124struct cpcap_battery_ddata {125	struct device *dev;126	struct regmap *reg;127	struct list_head irq_list;128	struct iio_channel *channels[CPCAP_BATTERY_IIO_NR];129	struct power_supply *psy;130	struct cpcap_battery_config config;131	struct cpcap_battery_state_data state[CPCAP_BATTERY_STATE_NR];132	u32 cc_lsb;		/* μAms per LSB */133	atomic_t active;134	int charge_full;135	int status;136	u16 vendor;137	bool check_nvmem;138	unsigned int is_full:1;139};140 141#define CPCAP_NO_BATTERY	-400142 143static bool ignore_temperature_probe;144module_param(ignore_temperature_probe, bool, 0660);145 146static struct cpcap_battery_state_data *147cpcap_battery_get_state(struct cpcap_battery_ddata *ddata,148			enum cpcap_battery_state state)149{150	if (state >= CPCAP_BATTERY_STATE_NR)151		return NULL;152 153	return &ddata->state[state];154}155 156static struct cpcap_battery_state_data *157cpcap_battery_latest(struct cpcap_battery_ddata *ddata)158{159	return cpcap_battery_get_state(ddata, CPCAP_BATTERY_STATE_LATEST);160}161 162static struct cpcap_battery_state_data *163cpcap_battery_previous(struct cpcap_battery_ddata *ddata)164{165	return cpcap_battery_get_state(ddata, CPCAP_BATTERY_STATE_PREVIOUS);166}167 168static struct cpcap_battery_state_data *169cpcap_battery_get_empty(struct cpcap_battery_ddata *ddata)170{171	return cpcap_battery_get_state(ddata, CPCAP_BATTERY_STATE_EMPTY);172}173 174static struct cpcap_battery_state_data *175cpcap_battery_get_full(struct cpcap_battery_ddata *ddata)176{177	return cpcap_battery_get_state(ddata, CPCAP_BATTERY_STATE_FULL);178}179 180static int cpcap_charger_battery_temperature(struct cpcap_battery_ddata *ddata,181					     int *value)182{183	struct iio_channel *channel;184	int error;185 186	channel = ddata->channels[CPCAP_BATTERY_IIO_BATTDET];187	error = iio_read_channel_processed(channel, value);188	if (error < 0) {189		if (!ignore_temperature_probe)190			dev_warn(ddata->dev, "%s failed: %i\n", __func__, error);191		*value = CPCAP_NO_BATTERY;192 193		return error;194	}195 196	*value /= 100;197 198	return 0;199}200 201static int cpcap_battery_get_voltage(struct cpcap_battery_ddata *ddata)202{203	struct iio_channel *channel;204	int error, value = 0;205 206	channel = ddata->channels[CPCAP_BATTERY_IIO_VOLTAGE];207	error = iio_read_channel_processed(channel, &value);208	if (error < 0) {209		dev_warn(ddata->dev, "%s failed: %i\n", __func__, error);210 211		return 0;212	}213 214	return value * 1000;215}216 217static int cpcap_battery_get_current(struct cpcap_battery_ddata *ddata)218{219	struct iio_channel *channel;220	int error, value = 0;221 222	channel = ddata->channels[CPCAP_BATTERY_IIO_BATT_CURRENT];223	error = iio_read_channel_processed(channel, &value);224	if (error < 0) {225		dev_warn(ddata->dev, "%s failed: %i\n", __func__, error);226 227		return 0;228	}229 230	return value * 1000;231}232 233/**234 * cpcap_battery_cc_raw_div - calculate and divide coulomb counter μAms values235 * @ddata: device driver data236 * @sample: coulomb counter sample value237 * @accumulator: coulomb counter integrator value238 * @offset: coulomb counter offset value239 * @divider: conversion divider240 *241 * Note that cc_lsb and cc_dur values are from Motorola Linux kernel242 * function data_get_avg_curr_ua() and seem to be based on measured test243 * results. It also has the following comment:244 *245 * Adjustment factors are applied here as a temp solution per the test246 * results. Need to work out a formal solution for this adjustment.247 *248 * A coulomb counter for similar hardware seems to be documented in249 * "TWL6030 Gas Gauging Basics (Rev. A)" swca095a.pdf in chapter250 * "10 Calculating Accumulated Current". We however follow what the251 * Motorola mapphone Linux kernel is doing as there may be either a252 * TI or ST coulomb counter in the PMIC.253 */254static int cpcap_battery_cc_raw_div(struct cpcap_battery_ddata *ddata,255				    s32 sample, s32 accumulator,256				    s16 offset, u32 divider)257{258	s64 acc;259 260	if (!divider)261		return 0;262 263	acc = accumulator;264	acc -= (s64)sample * offset;265	acc *= ddata->cc_lsb;266	acc *= -1;267	acc = div_s64(acc, divider);268 269	return acc;270}271 272/* 3600000μAms = 1μAh */273static int cpcap_battery_cc_to_uah(struct cpcap_battery_ddata *ddata,274				   s32 sample, s32 accumulator,275				   s16 offset)276{277	return cpcap_battery_cc_raw_div(ddata, sample,278					accumulator, offset,279					3600000);280}281 282static int cpcap_battery_cc_to_ua(struct cpcap_battery_ddata *ddata,283				  s32 sample, s32 accumulator,284				  s16 offset)285{286	return cpcap_battery_cc_raw_div(ddata, sample,287					accumulator, offset,288					sample *289					CPCAP_BATTERY_CC_SAMPLE_PERIOD_MS);290}291 292/**293 * cpcap_battery_read_accumulated - reads cpcap coulomb counter294 * @ddata: device driver data295 * @ccd: coulomb counter values296 *297 * Based on Motorola mapphone kernel function data_read_regs().298 * Looking at the registers, the coulomb counter seems similar to299 * the coulomb counter in TWL6030. See "TWL6030 Gas Gauging Basics300 * (Rev. A) swca095a.pdf for "10 Calculating Accumulated Current".301 *302 * Note that swca095a.pdf instructs to stop the coulomb counter303 * before reading to avoid values changing. Motorola mapphone304 * Linux kernel does not do it, so let's assume they've verified305 * the data produced is correct.306 */307static int308cpcap_battery_read_accumulated(struct cpcap_battery_ddata *ddata,309			       struct cpcap_coulomb_counter_data *ccd)310{311	u16 buf[7];	/* CPCAP_REG_CCS1 to CCI */312	int error;313 314	ccd->sample = 0;315	ccd->accumulator = 0;316	ccd->offset = 0;317	ccd->integrator = 0;318 319	/* Read coulomb counter register range */320	error = regmap_bulk_read(ddata->reg, CPCAP_REG_CCS1,321				 buf, ARRAY_SIZE(buf));322	if (error)323		return 0;324 325	/* Sample value CPCAP_REG_CCS1 & 2 */326	ccd->sample = (buf[1] & 0x0fff) << 16;327	ccd->sample |= buf[0];328	if (ddata->vendor == CPCAP_VENDOR_TI)329		ccd->sample = sign_extend32(24, ccd->sample);330 331	/* Accumulator value CPCAP_REG_CCA1 & 2 */332	ccd->accumulator = ((s16)buf[3]) << 16;333	ccd->accumulator |= buf[2];334 335	/*336	 * Coulomb counter calibration offset is CPCAP_REG_CCM,337	 * REG_CCO seems unused338	 */339	ccd->offset = buf[4];340	ccd->offset = sign_extend32(ccd->offset, 9);341 342	/* Integrator register CPCAP_REG_CCI */343	if (ddata->vendor == CPCAP_VENDOR_TI)344		ccd->integrator = sign_extend32(buf[6], 13);345	else346		ccd->integrator = (s16)buf[6];347 348	return cpcap_battery_cc_to_uah(ddata,349				       ccd->sample,350				       ccd->accumulator,351				       ccd->offset);352}353 354 355/*356 * Based on the values from Motorola mapphone Linux kernel for the357 * stock Droid 4 battery eb41. In the Motorola mapphone Linux358 * kernel tree the value for pm_cd_factor is passed to the kernel359 * via device tree. If it turns out to be something device specific360 * we can consider that too later. These values are also fine for361 * Bionic's hw4x.362 *363 * And looking at the battery full and shutdown values for the stock364 * kernel on droid 4, full is 4351000 and software initiates shutdown365 * at 3078000. The device will die around 2743000.366 */367static const struct cpcap_battery_config cpcap_battery_eb41_data = {368	.cd_factor = 0x3cc,369	.info.technology = POWER_SUPPLY_TECHNOLOGY_LION,370	.info.voltage_max_design = 4351000,371	.info.voltage_min_design = 3100000,372	.info.charge_full_design = 1740000,373	.bat.constant_charge_voltage_max_uv = 4200000,374};375 376/* Values for the extended Droid Bionic battery bw8x. */377static const struct cpcap_battery_config cpcap_battery_bw8x_data = {378	.cd_factor = 0x3cc,379	.info.technology = POWER_SUPPLY_TECHNOLOGY_LION,380	.info.voltage_max_design = 4200000,381	.info.voltage_min_design = 3200000,382	.info.charge_full_design = 2760000,383	.bat.constant_charge_voltage_max_uv = 4200000,384};385 386/*387 * Safe values for any lipo battery likely to fit into a mapphone388 * battery bay.389 */390static const struct cpcap_battery_config cpcap_battery_unkown_data = {391	.cd_factor = 0x3cc,392	.info.technology = POWER_SUPPLY_TECHNOLOGY_LION,393	.info.voltage_max_design = 4200000,394	.info.voltage_min_design = 3200000,395	.info.charge_full_design = 3000000,396	.bat.constant_charge_voltage_max_uv = 4200000,397};398 399static int cpcap_battery_match_nvmem(struct device *dev, const void *data)400{401	if (strcmp(dev_name(dev), "89-500029ba0f73") == 0)402		return 1;403	else404		return 0;405}406 407static void cpcap_battery_detect_battery_type(struct cpcap_battery_ddata *ddata)408{409	struct nvmem_device *nvmem;410	u8 battery_id = 0;411 412	ddata->check_nvmem = false;413 414	nvmem = nvmem_device_find(NULL, &cpcap_battery_match_nvmem);415	if (IS_ERR_OR_NULL(nvmem)) {416		ddata->check_nvmem = true;417		dev_info_once(ddata->dev, "Can not find battery nvmem device. Assuming generic lipo battery\n");418	} else if (nvmem_device_read(nvmem, 2, 1, &battery_id) < 0) {419		battery_id = 0;420		ddata->check_nvmem = true;421		dev_warn(ddata->dev, "Can not read battery nvmem device. Assuming generic lipo battery\n");422	}423 424	switch (battery_id) {425	case CPCAP_BATTERY_EB41_HW4X_ID:426		ddata->config = cpcap_battery_eb41_data;427		break;428	case CPCAP_BATTERY_BW8X_ID:429		ddata->config = cpcap_battery_bw8x_data;430		break;431	default:432		ddata->config = cpcap_battery_unkown_data;433	}434}435 436/**437 * cpcap_battery_cc_get_avg_current - read cpcap coulumb counter438 * @ddata: cpcap battery driver device data439 */440static int cpcap_battery_cc_get_avg_current(struct cpcap_battery_ddata *ddata)441{442	int value, acc, error;443	s32 sample;444	s16 offset;445 446	/* Coulomb counter integrator */447	error = regmap_read(ddata->reg, CPCAP_REG_CCI, &value);448	if (error)449		return error;450 451	if (ddata->vendor == CPCAP_VENDOR_TI) {452		acc = sign_extend32(value, 13);453		sample = 1;454	} else {455		acc = (s16)value;456		sample = 4;457	}458 459	/* Coulomb counter calibration offset  */460	error = regmap_read(ddata->reg, CPCAP_REG_CCM, &value);461	if (error)462		return error;463 464	offset = sign_extend32(value, 9);465 466	return cpcap_battery_cc_to_ua(ddata, sample, acc, offset);467}468 469static int cpcap_battery_get_charger_status(struct cpcap_battery_ddata *ddata,470					    int *val)471{472	union power_supply_propval prop;473	struct power_supply *charger;474	int error;475 476	charger = power_supply_get_by_name("usb");477	if (!charger)478		return -ENODEV;479 480	error = power_supply_get_property(charger, POWER_SUPPLY_PROP_STATUS,481					  &prop);482	if (error)483		*val = POWER_SUPPLY_STATUS_UNKNOWN;484	else485		*val = prop.intval;486 487	power_supply_put(charger);488 489	return error;490}491 492static bool cpcap_battery_full(struct cpcap_battery_ddata *ddata)493{494	struct cpcap_battery_state_data *state = cpcap_battery_latest(ddata);495	unsigned int vfull;496	int error, val;497 498	error = cpcap_battery_get_charger_status(ddata, &val);499	if (!error) {500		switch (val) {501		case POWER_SUPPLY_STATUS_DISCHARGING:502			dev_dbg(ddata->dev, "charger disconnected\n");503			ddata->is_full = 0;504			break;505		case POWER_SUPPLY_STATUS_FULL:506			dev_dbg(ddata->dev, "charger full status\n");507			ddata->is_full = 1;508			break;509		default:510			break;511		}512	}513 514	/*515	 * The full battery voltage here can be inaccurate, it's used just to516	 * filter out any trickle charging events. We clear the is_full status517	 * on charger disconnect above anyways.518	 */519	vfull = ddata->config.bat.constant_charge_voltage_max_uv - 120000;520 521	if (ddata->is_full && state->voltage < vfull)522		ddata->is_full = 0;523 524	return ddata->is_full;525}526 527static bool cpcap_battery_low(struct cpcap_battery_ddata *ddata)528{529	struct cpcap_battery_state_data *state = cpcap_battery_latest(ddata);530	static bool is_low;531 532	if (state->current_ua > 0 && (state->voltage <= 3350000 || is_low))533		is_low = true;534	else535		is_low = false;536 537	return is_low;538}539 540static int cpcap_battery_update_status(struct cpcap_battery_ddata *ddata)541{542	struct cpcap_battery_state_data state, *latest, *previous,543					*empty, *full;544	ktime_t now;545	int error;546 547	memset(&state, 0, sizeof(state));548	now = ktime_get();549 550	latest = cpcap_battery_latest(ddata);551	if (latest) {552		s64 delta_ms = ktime_to_ms(ktime_sub(now, latest->time));553 554		if (delta_ms < CPCAP_BATTERY_CC_SAMPLE_PERIOD_MS)555			return delta_ms;556	}557 558	state.time = now;559	state.voltage = cpcap_battery_get_voltage(ddata);560	state.current_ua = cpcap_battery_get_current(ddata);561	state.counter_uah = cpcap_battery_read_accumulated(ddata, &state.cc);562 563	error = cpcap_charger_battery_temperature(ddata,564						  &state.temperature);565	if (error)566		return error;567 568	previous = cpcap_battery_previous(ddata);569	memcpy(previous, latest, sizeof(*previous));570	memcpy(latest, &state, sizeof(*latest));571 572	if (cpcap_battery_full(ddata)) {573		full = cpcap_battery_get_full(ddata);574		memcpy(full, latest, sizeof(*full));575 576		empty = cpcap_battery_get_empty(ddata);577		if (empty->voltage && empty->voltage != -1) {578			empty->voltage = -1;579			ddata->charge_full =580				empty->counter_uah - full->counter_uah;581		} else if (ddata->charge_full) {582			empty->voltage = -1;583			empty->counter_uah =584				full->counter_uah + ddata->charge_full;585		}586	} else if (cpcap_battery_low(ddata)) {587		empty = cpcap_battery_get_empty(ddata);588		memcpy(empty, latest, sizeof(*empty));589 590		full = cpcap_battery_get_full(ddata);591		if (full->voltage) {592			full->voltage = 0;593			ddata->charge_full =594				empty->counter_uah - full->counter_uah;595		}596	}597 598	return 0;599}600 601/*602 * Update battery status when cpcap-charger calls power_supply_changed().603 * This allows us to detect battery full condition before the charger604 * disconnects.605 */606static void cpcap_battery_external_power_changed(struct power_supply *psy)607{608	union power_supply_propval prop;609 610	power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &prop);611}612 613static enum power_supply_property cpcap_battery_props[] = {614	POWER_SUPPLY_PROP_STATUS,615	POWER_SUPPLY_PROP_PRESENT,616	POWER_SUPPLY_PROP_TECHNOLOGY,617	POWER_SUPPLY_PROP_VOLTAGE_NOW,618	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,619	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,620	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,621	POWER_SUPPLY_PROP_CURRENT_AVG,622	POWER_SUPPLY_PROP_CURRENT_NOW,623	POWER_SUPPLY_PROP_CHARGE_FULL,624	POWER_SUPPLY_PROP_CHARGE_NOW,625	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,626	POWER_SUPPLY_PROP_CHARGE_COUNTER,627	POWER_SUPPLY_PROP_POWER_NOW,628	POWER_SUPPLY_PROP_POWER_AVG,629	POWER_SUPPLY_PROP_CAPACITY,630	POWER_SUPPLY_PROP_CAPACITY_LEVEL,631	POWER_SUPPLY_PROP_SCOPE,632	POWER_SUPPLY_PROP_TEMP,633};634 635static int cpcap_battery_get_property(struct power_supply *psy,636				      enum power_supply_property psp,637				      union power_supply_propval *val)638{639	struct cpcap_battery_ddata *ddata = power_supply_get_drvdata(psy);640	struct cpcap_battery_state_data *latest, *previous, *empty;641	u32 sample;642	s32 accumulator;643	int cached;644	s64 tmp;645 646	cached = cpcap_battery_update_status(ddata);647	if (cached < 0)648		return cached;649 650	latest = cpcap_battery_latest(ddata);651	previous = cpcap_battery_previous(ddata);652 653	if (ddata->check_nvmem)654		cpcap_battery_detect_battery_type(ddata);655 656	switch (psp) {657	case POWER_SUPPLY_PROP_PRESENT:658		if (latest->temperature > CPCAP_NO_BATTERY || ignore_temperature_probe)659			val->intval = 1;660		else661			val->intval = 0;662		break;663	case POWER_SUPPLY_PROP_STATUS:664		if (cpcap_battery_full(ddata)) {665			val->intval = POWER_SUPPLY_STATUS_FULL;666			break;667		}668		if (cpcap_battery_cc_get_avg_current(ddata) < 0)669			val->intval = POWER_SUPPLY_STATUS_CHARGING;670		else671			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;672		break;673	case POWER_SUPPLY_PROP_TECHNOLOGY:674		val->intval = ddata->config.info.technology;675		break;676	case POWER_SUPPLY_PROP_VOLTAGE_NOW:677		val->intval = cpcap_battery_get_voltage(ddata);678		break;679	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:680		val->intval = ddata->config.info.voltage_max_design;681		break;682	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:683		val->intval = ddata->config.info.voltage_min_design;684		break;685	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:686		val->intval = ddata->config.bat.constant_charge_voltage_max_uv;687		break;688	case POWER_SUPPLY_PROP_CURRENT_AVG:689		sample = latest->cc.sample - previous->cc.sample;690		if (!sample) {691			val->intval = cpcap_battery_cc_get_avg_current(ddata);692			break;693		}694		accumulator = latest->cc.accumulator - previous->cc.accumulator;695		val->intval = cpcap_battery_cc_to_ua(ddata, sample,696						     accumulator,697						     latest->cc.offset);698		break;699	case POWER_SUPPLY_PROP_CURRENT_NOW:700		val->intval = latest->current_ua;701		break;702	case POWER_SUPPLY_PROP_CHARGE_COUNTER:703		val->intval = latest->counter_uah;704		break;705	case POWER_SUPPLY_PROP_POWER_NOW:706		tmp = (latest->voltage / 10000) * latest->current_ua;707		val->intval = div64_s64(tmp, 100);708		break;709	case POWER_SUPPLY_PROP_POWER_AVG:710		sample = latest->cc.sample - previous->cc.sample;711		if (!sample) {712			tmp = cpcap_battery_cc_get_avg_current(ddata);713			tmp *= (latest->voltage / 10000);714			val->intval = div64_s64(tmp, 100);715			break;716		}717		accumulator = latest->cc.accumulator - previous->cc.accumulator;718		tmp = cpcap_battery_cc_to_ua(ddata, sample, accumulator,719					     latest->cc.offset);720		tmp *= ((latest->voltage + previous->voltage) / 20000);721		val->intval = div64_s64(tmp, 100);722		break;723	case POWER_SUPPLY_PROP_CAPACITY:724		empty = cpcap_battery_get_empty(ddata);725		if (!empty->voltage || !ddata->charge_full)726			return -ENODATA;727		/* (ddata->charge_full / 200) is needed for rounding */728		val->intval = empty->counter_uah - latest->counter_uah +729			ddata->charge_full / 200;730		val->intval = clamp(val->intval, 0, ddata->charge_full);731		val->intval = val->intval * 100 / ddata->charge_full;732		break;733	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:734		if (cpcap_battery_full(ddata))735			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;736		else if (latest->voltage >= 3750000)737			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;738		else if (latest->voltage >= 3300000)739			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;740		else if (latest->voltage > 3100000)741			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;742		else if (latest->voltage <= 3100000)743			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;744		else745			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;746		break;747	case POWER_SUPPLY_PROP_CHARGE_NOW:748		empty = cpcap_battery_get_empty(ddata);749		if (!empty->voltage)750			return -ENODATA;751		val->intval = empty->counter_uah - latest->counter_uah;752		if (val->intval < 0) {753			/* Assume invalid config if CHARGE_NOW is -20% */754			if (ddata->charge_full && abs(val->intval) > ddata->charge_full/5) {755				empty->voltage = 0;756				ddata->charge_full = 0;757				return -ENODATA;758			}759			val->intval = 0;760		} else if (ddata->charge_full && ddata->charge_full < val->intval) {761			/* Assume invalid config if CHARGE_NOW exceeds CHARGE_FULL by 20% */762			if (val->intval > (6*ddata->charge_full)/5) {763				empty->voltage = 0;764				ddata->charge_full = 0;765				return -ENODATA;766			}767			val->intval = ddata->charge_full;768		}769		break;770	case POWER_SUPPLY_PROP_CHARGE_FULL:771		if (!ddata->charge_full)772			return -ENODATA;773		val->intval = ddata->charge_full;774		break;775	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:776		val->intval = ddata->config.info.charge_full_design;777		break;778	case POWER_SUPPLY_PROP_SCOPE:779		val->intval = POWER_SUPPLY_SCOPE_SYSTEM;780		break;781	case POWER_SUPPLY_PROP_TEMP:782		if (ignore_temperature_probe)783			return -ENODATA;784		val->intval = latest->temperature;785		break;786	default:787		return -EINVAL;788	}789 790	return 0;791}792 793static int cpcap_battery_update_charger(struct cpcap_battery_ddata *ddata,794					int const_charge_voltage)795{796	union power_supply_propval prop;797	union power_supply_propval val;798	struct power_supply *charger;799	int error;800 801	charger = power_supply_get_by_name("usb");802	if (!charger)803		return -ENODEV;804 805	error = power_supply_get_property(charger,806				POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,807				&prop);808	if (error)809		goto out_put;810 811	/* Allow charger const voltage lower than battery const voltage */812	if (const_charge_voltage > prop.intval)813		goto out_put;814 815	val.intval = const_charge_voltage;816 817	error = power_supply_set_property(charger,818			POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,819			&val);820out_put:821	power_supply_put(charger);822 823	return error;824}825 826static int cpcap_battery_set_property(struct power_supply *psy,827				      enum power_supply_property psp,828				      const union power_supply_propval *val)829{830	struct cpcap_battery_ddata *ddata = power_supply_get_drvdata(psy);831 832	switch (psp) {833	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:834		if (val->intval < ddata->config.info.voltage_min_design)835			return -EINVAL;836		if (val->intval > ddata->config.info.voltage_max_design)837			return -EINVAL;838 839		ddata->config.bat.constant_charge_voltage_max_uv = val->intval;840 841		return cpcap_battery_update_charger(ddata, val->intval);842	case POWER_SUPPLY_PROP_CHARGE_FULL:843		if (val->intval < 0)844			return -EINVAL;845		if (val->intval > (6*ddata->config.info.charge_full_design)/5)846			return -EINVAL;847 848		ddata->charge_full = val->intval;849 850		return 0;851	default:852		return -EINVAL;853	}854 855	return 0;856}857 858static int cpcap_battery_property_is_writeable(struct power_supply *psy,859					       enum power_supply_property psp)860{861	switch (psp) {862	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:863	case POWER_SUPPLY_PROP_CHARGE_FULL:864		return 1;865	default:866		return 0;867	}868}869 870static irqreturn_t cpcap_battery_irq_thread(int irq, void *data)871{872	struct cpcap_battery_ddata *ddata = data;873	struct cpcap_battery_state_data *latest;874	struct cpcap_interrupt_desc *d;875 876	if (!atomic_read(&ddata->active))877		return IRQ_NONE;878 879	list_for_each_entry(d, &ddata->irq_list, node) {880		if (irq == d->irq)881			break;882	}883 884	if (list_entry_is_head(d, &ddata->irq_list, node))885		return IRQ_NONE;886 887	latest = cpcap_battery_latest(ddata);888 889	switch (d->action) {890	case CPCAP_BATTERY_IRQ_ACTION_CC_CAL_DONE:891		dev_info(ddata->dev, "Coulomb counter calibration done\n");892		break;893	case CPCAP_BATTERY_IRQ_ACTION_BATTERY_LOW:894		if (latest->current_ua >= 0)895			dev_warn(ddata->dev, "Battery low at %imV!\n",896				latest->voltage / 1000);897		break;898	case CPCAP_BATTERY_IRQ_ACTION_POWEROFF:899		if (latest->current_ua >= 0 && latest->voltage <= 3200000) {900			dev_emerg(ddata->dev,901				  "Battery empty at %imV, powering off\n",902				  latest->voltage / 1000);903			orderly_poweroff(true);904		}905		break;906	default:907		break;908	}909 910	power_supply_changed(ddata->psy);911 912	return IRQ_HANDLED;913}914 915static int cpcap_battery_init_irq(struct platform_device *pdev,916				  struct cpcap_battery_ddata *ddata,917				  const char *name)918{919	struct cpcap_interrupt_desc *d;920	int irq, error;921 922	irq = platform_get_irq_byname(pdev, name);923	if (irq < 0)924		return irq;925 926	error = devm_request_threaded_irq(ddata->dev, irq, NULL,927					  cpcap_battery_irq_thread,928					  IRQF_SHARED | IRQF_ONESHOT,929					  name, ddata);930	if (error) {931		dev_err(ddata->dev, "could not get irq %s: %i\n",932			name, error);933 934		return error;935	}936 937	d = devm_kzalloc(ddata->dev, sizeof(*d), GFP_KERNEL);938	if (!d)939		return -ENOMEM;940 941	d->name = name;942	d->irq = irq;943 944	if (!strncmp(name, "cccal", 5))945		d->action = CPCAP_BATTERY_IRQ_ACTION_CC_CAL_DONE;946	else if (!strncmp(name, "lowbph", 6))947		d->action = CPCAP_BATTERY_IRQ_ACTION_BATTERY_LOW;948	else if (!strncmp(name, "lowbpl", 6))949		d->action = CPCAP_BATTERY_IRQ_ACTION_POWEROFF;950 951	list_add(&d->node, &ddata->irq_list);952 953	return 0;954}955 956static int cpcap_battery_init_interrupts(struct platform_device *pdev,957					 struct cpcap_battery_ddata *ddata)958{959	static const char * const cpcap_battery_irqs[] = {960		"eol", "lowbph", "lowbpl",961		"chrgcurr1", "battdetb"962	};963	int i, error;964 965	for (i = 0; i < ARRAY_SIZE(cpcap_battery_irqs); i++) {966		error = cpcap_battery_init_irq(pdev, ddata,967					       cpcap_battery_irqs[i]);968		if (error)969			return error;970	}971 972	/* Enable calibration interrupt if already available in dts */973	cpcap_battery_init_irq(pdev, ddata, "cccal");974 975	/* Enable low battery interrupts for 3.3V high and 3.1V low */976	error = regmap_update_bits(ddata->reg, CPCAP_REG_BPEOL,977				   0xffff,978				   CPCAP_REG_BPEOL_BIT_BATTDETEN);979	if (error)980		return error;981 982	return 0;983}984 985static int cpcap_battery_init_iio(struct cpcap_battery_ddata *ddata)986{987	const char * const names[CPCAP_BATTERY_IIO_NR] = {988		"battdetb", "battp", "chg_isense", "batti",989	};990	int error, i;991 992	for (i = 0; i < CPCAP_BATTERY_IIO_NR; i++) {993		ddata->channels[i] = devm_iio_channel_get(ddata->dev,994							  names[i]);995		if (IS_ERR(ddata->channels[i])) {996			error = PTR_ERR(ddata->channels[i]);997			goto out_err;998		}999 1000		if (!ddata->channels[i]->indio_dev) {1001			error = -ENXIO;1002			goto out_err;1003		}1004	}1005 1006	return 0;1007 1008out_err:1009	return dev_err_probe(ddata->dev, error,1010			     "could not initialize VBUS or ID IIO\n");1011}1012 1013/* Calibrate coulomb counter */1014static int cpcap_battery_calibrate(struct cpcap_battery_ddata *ddata)1015{1016	int error, ccc1, value;1017	unsigned long timeout;1018 1019	error = regmap_read(ddata->reg, CPCAP_REG_CCC1, &ccc1);1020	if (error)1021		return error;1022 1023	timeout = jiffies + msecs_to_jiffies(6000);1024 1025	/* Start calibration */1026	error = regmap_update_bits(ddata->reg, CPCAP_REG_CCC1,1027				   0xffff,1028				   CPCAP_REG_CCC1_CAL_EN);1029	if (error)1030		goto restore;1031 1032	while (time_before(jiffies, timeout)) {1033		error = regmap_read(ddata->reg, CPCAP_REG_CCC1, &value);1034		if (error)1035			goto restore;1036 1037		if (!(value & CPCAP_REG_CCC1_CAL_EN))1038			break;1039 1040		error = regmap_read(ddata->reg, CPCAP_REG_CCM, &value);1041		if (error)1042			goto restore;1043 1044		msleep(300);1045	}1046 1047	/* Read calibration offset from CCM */1048	error = regmap_read(ddata->reg, CPCAP_REG_CCM, &value);1049	if (error)1050		goto restore;1051 1052	dev_info(ddata->dev, "calibration done: 0x%04x\n", value);1053 1054restore:1055	if (error)1056		dev_err(ddata->dev, "%s: error %i\n", __func__, error);1057 1058	error = regmap_update_bits(ddata->reg, CPCAP_REG_CCC1,1059				   0xffff, ccc1);1060	if (error)1061		dev_err(ddata->dev, "%s: restore error %i\n",1062			__func__, error);1063 1064	return error;1065}1066 1067#ifdef CONFIG_OF1068static const struct of_device_id cpcap_battery_id_table[] = {1069	{1070		.compatible = "motorola,cpcap-battery",1071	},1072	{},1073};1074MODULE_DEVICE_TABLE(of, cpcap_battery_id_table);1075#endif1076 1077static const struct power_supply_desc cpcap_charger_battery_desc = {1078	.name		= "battery",1079	.type		= POWER_SUPPLY_TYPE_BATTERY,1080	.properties	= cpcap_battery_props,1081	.num_properties	= ARRAY_SIZE(cpcap_battery_props),1082	.get_property	= cpcap_battery_get_property,1083	.set_property	= cpcap_battery_set_property,1084	.property_is_writeable = cpcap_battery_property_is_writeable,1085	.external_power_changed = cpcap_battery_external_power_changed,1086};1087 1088static int cpcap_battery_probe(struct platform_device *pdev)1089{1090	struct cpcap_battery_ddata *ddata;1091	struct power_supply_config psy_cfg = {};1092	int error;1093 1094	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);1095	if (!ddata)1096		return -ENOMEM;1097 1098	cpcap_battery_detect_battery_type(ddata);1099 1100	INIT_LIST_HEAD(&ddata->irq_list);1101	ddata->dev = &pdev->dev;1102 1103	ddata->reg = dev_get_regmap(ddata->dev->parent, NULL);1104	if (!ddata->reg)1105		return -ENODEV;1106 1107	error = cpcap_get_vendor(ddata->dev, ddata->reg, &ddata->vendor);1108	if (error)1109		return error;1110 1111	switch (ddata->vendor) {1112	case CPCAP_VENDOR_ST:1113		ddata->cc_lsb = 95374;	/* μAms per LSB */1114		break;1115	case CPCAP_VENDOR_TI:1116		ddata->cc_lsb = 91501;	/* μAms per LSB */1117		break;1118	default:1119		return -EINVAL;1120	}1121	ddata->cc_lsb = (ddata->cc_lsb * ddata->config.cd_factor) / 1000;1122 1123	platform_set_drvdata(pdev, ddata);1124 1125	error = cpcap_battery_init_interrupts(pdev, ddata);1126	if (error)1127		return error;1128 1129	error = cpcap_battery_init_iio(ddata);1130	if (error)1131		return error;1132 1133	psy_cfg.of_node = pdev->dev.of_node;1134	psy_cfg.drv_data = ddata;1135 1136	ddata->psy = devm_power_supply_register(ddata->dev,1137						&cpcap_charger_battery_desc,1138						&psy_cfg);1139	error = PTR_ERR_OR_ZERO(ddata->psy);1140	if (error) {1141		dev_err(ddata->dev, "failed to register power supply\n");1142		return error;1143	}1144 1145	atomic_set(&ddata->active, 1);1146 1147	error = cpcap_battery_calibrate(ddata);1148	if (error)1149		return error;1150 1151	return 0;1152}1153 1154static void cpcap_battery_remove(struct platform_device *pdev)1155{1156	struct cpcap_battery_ddata *ddata = platform_get_drvdata(pdev);1157	int error;1158 1159	atomic_set(&ddata->active, 0);1160	error = regmap_update_bits(ddata->reg, CPCAP_REG_BPEOL,1161				   0xffff, 0);1162	if (error)1163		dev_err(&pdev->dev, "could not disable: %i\n", error);1164}1165 1166static struct platform_driver cpcap_battery_driver = {1167	.driver	= {1168		.name		= "cpcap_battery",1169		.of_match_table = of_match_ptr(cpcap_battery_id_table),1170	},1171	.probe	= cpcap_battery_probe,1172	.remove_new = cpcap_battery_remove,1173};1174module_platform_driver(cpcap_battery_driver);1175 1176MODULE_LICENSE("GPL v2");1177MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");1178MODULE_DESCRIPTION("CPCAP PMIC Battery Driver");1179