brintos

brintos / linux-shallow public Read only

0
0
Text · 61.8 KiB · 2b393eb Raw
2316 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Driver for the TI bq24190 battery charger.4 *5 * Author: Mark A. Greer <mgreer@animalcreek.com>6 */7 8#include <linux/mod_devicetable.h>9#include <linux/module.h>10#include <linux/interrupt.h>11#include <linux/delay.h>12#include <linux/pm_runtime.h>13#include <linux/power_supply.h>14#include <linux/power/bq24190_charger.h>15#include <linux/regulator/driver.h>16#include <linux/regulator/machine.h>17#include <linux/workqueue.h>18#include <linux/i2c.h>19#include <linux/extcon-provider.h>20 21#define	BQ24190_MANUFACTURER	"Texas Instruments"22 23#define BQ24190_REG_ISC		0x00 /* Input Source Control */24#define BQ24190_REG_ISC_EN_HIZ_MASK		BIT(7)25#define BQ24190_REG_ISC_EN_HIZ_SHIFT		726#define BQ24190_REG_ISC_VINDPM_MASK		(BIT(6) | BIT(5) | BIT(4) | \27						 BIT(3))28#define BQ24190_REG_ISC_VINDPM_SHIFT		329#define BQ24190_REG_ISC_IINLIM_MASK		(BIT(2) | BIT(1) | BIT(0))30#define BQ24190_REG_ISC_IINLIM_SHIFT		031 32#define BQ24190_REG_POC		0x01 /* Power-On Configuration */33#define BQ24190_REG_POC_RESET_MASK		BIT(7)34#define BQ24190_REG_POC_RESET_SHIFT		735#define BQ24190_REG_POC_WDT_RESET_MASK		BIT(6)36#define BQ24190_REG_POC_WDT_RESET_SHIFT		637#define BQ24190_REG_POC_CHG_CONFIG_MASK		(BIT(5) | BIT(4))38#define BQ24190_REG_POC_CHG_CONFIG_SHIFT	439#define BQ24190_REG_POC_CHG_CONFIG_DISABLE	0x040#define BQ24190_REG_POC_CHG_CONFIG_CHARGE	0x141#define BQ24190_REG_POC_CHG_CONFIG_OTG		0x242#define BQ24190_REG_POC_CHG_CONFIG_OTG_ALT	0x343#define BQ24296_REG_POC_OTG_CONFIG_MASK		BIT(5)44#define BQ24296_REG_POC_OTG_CONFIG_SHIFT	545#define BQ24296_REG_POC_CHG_CONFIG_MASK		BIT(4)46#define BQ24296_REG_POC_CHG_CONFIG_SHIFT	447#define BQ24296_REG_POC_OTG_CONFIG_DISABLE	0x048#define BQ24296_REG_POC_OTG_CONFIG_OTG		0x149#define BQ24190_REG_POC_SYS_MIN_MASK		(BIT(3) | BIT(2) | BIT(1))50#define BQ24190_REG_POC_SYS_MIN_SHIFT		151#define BQ24190_REG_POC_SYS_MIN_MIN			300052#define BQ24190_REG_POC_SYS_MIN_MAX			370053#define BQ24190_REG_POC_BOOST_LIM_MASK		BIT(0)54#define BQ24190_REG_POC_BOOST_LIM_SHIFT		055 56#define BQ24190_REG_CCC		0x02 /* Charge Current Control */57#define BQ24190_REG_CCC_ICHG_MASK		(BIT(7) | BIT(6) | BIT(5) | \58						 BIT(4) | BIT(3) | BIT(2))59#define BQ24190_REG_CCC_ICHG_SHIFT		260#define BQ24190_REG_CCC_FORCE_20PCT_MASK	BIT(0)61#define BQ24190_REG_CCC_FORCE_20PCT_SHIFT	062 63#define BQ24190_REG_PCTCC	0x03 /* Pre-charge/Termination Current Cntl */64#define BQ24190_REG_PCTCC_IPRECHG_MASK		(BIT(7) | BIT(6) | BIT(5) | \65						 BIT(4))66#define BQ24190_REG_PCTCC_IPRECHG_SHIFT		467#define BQ24190_REG_PCTCC_IPRECHG_MIN			12868#define BQ24190_REG_PCTCC_IPRECHG_MAX			204869#define BQ24190_REG_PCTCC_ITERM_MASK		(BIT(3) | BIT(2) | BIT(1) | \70						 BIT(0))71#define BQ24190_REG_PCTCC_ITERM_SHIFT		072#define BQ24190_REG_PCTCC_ITERM_MIN			12873#define BQ24190_REG_PCTCC_ITERM_MAX			204874 75#define BQ24190_REG_CVC		0x04 /* Charge Voltage Control */76#define BQ24190_REG_CVC_VREG_MASK		(BIT(7) | BIT(6) | BIT(5) | \77						 BIT(4) | BIT(3) | BIT(2))78#define BQ24190_REG_CVC_VREG_SHIFT		279#define BQ24190_REG_CVC_BATLOWV_MASK		BIT(1)80#define BQ24190_REG_CVC_BATLOWV_SHIFT		181#define BQ24190_REG_CVC_VRECHG_MASK		BIT(0)82#define BQ24190_REG_CVC_VRECHG_SHIFT		083 84#define BQ24190_REG_CTTC	0x05 /* Charge Term/Timer Control */85#define BQ24190_REG_CTTC_EN_TERM_MASK		BIT(7)86#define BQ24190_REG_CTTC_EN_TERM_SHIFT		787#define BQ24190_REG_CTTC_TERM_STAT_MASK		BIT(6)88#define BQ24190_REG_CTTC_TERM_STAT_SHIFT	689#define BQ24190_REG_CTTC_WATCHDOG_MASK		(BIT(5) | BIT(4))90#define BQ24190_REG_CTTC_WATCHDOG_SHIFT		491#define BQ24190_REG_CTTC_EN_TIMER_MASK		BIT(3)92#define BQ24190_REG_CTTC_EN_TIMER_SHIFT		393#define BQ24190_REG_CTTC_CHG_TIMER_MASK		(BIT(2) | BIT(1))94#define BQ24190_REG_CTTC_CHG_TIMER_SHIFT	195#define BQ24190_REG_CTTC_JEITA_ISET_MASK	BIT(0)96#define BQ24190_REG_CTTC_JEITA_ISET_SHIFT	097 98#define BQ24190_REG_ICTRC	0x06 /* IR Comp/Thermal Regulation Control */99#define BQ24190_REG_ICTRC_BAT_COMP_MASK		(BIT(7) | BIT(6) | BIT(5))100#define BQ24190_REG_ICTRC_BAT_COMP_SHIFT	5101#define BQ24190_REG_ICTRC_VCLAMP_MASK		(BIT(4) | BIT(3) | BIT(2))102#define BQ24190_REG_ICTRC_VCLAMP_SHIFT		2103#define BQ24190_REG_ICTRC_TREG_MASK		(BIT(1) | BIT(0))104#define BQ24190_REG_ICTRC_TREG_SHIFT		0105 106#define BQ24190_REG_MOC		0x07 /* Misc. Operation Control */107#define BQ24190_REG_MOC_DPDM_EN_MASK		BIT(7)108#define BQ24190_REG_MOC_DPDM_EN_SHIFT		7109#define BQ24190_REG_MOC_TMR2X_EN_MASK		BIT(6)110#define BQ24190_REG_MOC_TMR2X_EN_SHIFT		6111#define BQ24190_REG_MOC_BATFET_DISABLE_MASK	BIT(5)112#define BQ24190_REG_MOC_BATFET_DISABLE_SHIFT	5113#define BQ24190_REG_MOC_JEITA_VSET_MASK		BIT(4)114#define BQ24190_REG_MOC_JEITA_VSET_SHIFT	4115#define BQ24190_REG_MOC_INT_MASK_MASK		(BIT(1) | BIT(0))116#define BQ24190_REG_MOC_INT_MASK_SHIFT		0117 118#define BQ24190_REG_SS		0x08 /* System Status */119#define BQ24190_REG_SS_VBUS_STAT_MASK		(BIT(7) | BIT(6))120#define BQ24190_REG_SS_VBUS_STAT_SHIFT		6121#define BQ24190_REG_SS_CHRG_STAT_MASK		(BIT(5) | BIT(4))122#define BQ24190_REG_SS_CHRG_STAT_SHIFT		4123#define BQ24190_REG_SS_DPM_STAT_MASK		BIT(3)124#define BQ24190_REG_SS_DPM_STAT_SHIFT		3125#define BQ24190_REG_SS_PG_STAT_MASK		BIT(2)126#define BQ24190_REG_SS_PG_STAT_SHIFT		2127#define BQ24190_REG_SS_THERM_STAT_MASK		BIT(1)128#define BQ24190_REG_SS_THERM_STAT_SHIFT		1129#define BQ24190_REG_SS_VSYS_STAT_MASK		BIT(0)130#define BQ24190_REG_SS_VSYS_STAT_SHIFT		0131 132#define BQ24190_REG_F		0x09 /* Fault */133#define BQ24190_REG_F_WATCHDOG_FAULT_MASK	BIT(7)134#define BQ24190_REG_F_WATCHDOG_FAULT_SHIFT	7135#define BQ24190_REG_F_BOOST_FAULT_MASK		BIT(6)136#define BQ24190_REG_F_BOOST_FAULT_SHIFT		6137#define BQ24190_REG_F_CHRG_FAULT_MASK		(BIT(5) | BIT(4))138#define BQ24190_REG_F_CHRG_FAULT_SHIFT		4139#define BQ24190_REG_F_BAT_FAULT_MASK		BIT(3)140#define BQ24190_REG_F_BAT_FAULT_SHIFT		3141#define BQ24190_REG_F_NTC_FAULT_MASK		(BIT(2) | BIT(1) | BIT(0))142#define BQ24190_REG_F_NTC_FAULT_SHIFT		0143#define BQ24296_REG_F_NTC_FAULT_MASK		(BIT(1) | BIT(0))144#define BQ24296_REG_F_NTC_FAULT_SHIFT		0145 146#define BQ24190_REG_VPRS	0x0A /* Vendor/Part/Revision Status */147#define BQ24190_REG_VPRS_PN_MASK		(BIT(5) | BIT(4) | BIT(3))148#define BQ24190_REG_VPRS_PN_SHIFT		3149#define BQ24190_REG_VPRS_PN_24190		0x4150#define BQ24190_REG_VPRS_PN_24192		0x5 /* Also 24193, 24196 */151#define BQ24190_REG_VPRS_PN_24192I		0x3152#define BQ24296_REG_VPRS_PN_MASK		(BIT(7) | BIT(6) | BIT(5))153#define BQ24296_REG_VPRS_PN_SHIFT		5154#define BQ24296_REG_VPRS_PN_24296		0x1155#define BQ24190_REG_VPRS_TS_PROFILE_MASK	BIT(2)156#define BQ24190_REG_VPRS_TS_PROFILE_SHIFT	2157#define BQ24190_REG_VPRS_DEV_REG_MASK		(BIT(1) | BIT(0))158#define BQ24190_REG_VPRS_DEV_REG_SHIFT		0159 160/*161 * The tables below provide a 2-way mapping for the value that goes in162 * the register field and the real-world value that it represents.163 * The index of the array is the value that goes in the register; the164 * number at that index in the array is the real-world value that it165 * represents.166 */167 168/* REG00[2:0] (IINLIM) in uAh */169static const int bq24190_isc_iinlim_values[] = {170	 100000,  150000,  500000,  900000, 1200000, 1500000, 2000000, 3000000171};172 173/* REG02[7:2] (ICHG) in uAh */174static const int bq24190_ccc_ichg_values[] = {175	 512000,  576000,  640000,  704000,  768000,  832000,  896000,  960000,176	1024000, 1088000, 1152000, 1216000, 1280000, 1344000, 1408000, 1472000,177	1536000, 1600000, 1664000, 1728000, 1792000, 1856000, 1920000, 1984000,178	2048000, 2112000, 2176000, 2240000, 2304000, 2368000, 2432000, 2496000,179	2560000, 2624000, 2688000, 2752000, 2816000, 2880000, 2944000, 3008000,180	3072000, 3136000, 3200000, 3264000, 3328000, 3392000, 3456000, 3520000,181	3584000, 3648000, 3712000, 3776000, 3840000, 3904000, 3968000, 4032000,182	4096000, 4160000, 4224000, 4288000, 4352000, 4416000, 4480000, 4544000183};184 185/* ICHG higher than 3008mA is not supported in BQ24296 */186#define BQ24296_CCC_ICHG_VALUES_LEN	40187 188/* REG04[7:2] (VREG) in uV */189static const int bq24190_cvc_vreg_values[] = {190	3504000, 3520000, 3536000, 3552000, 3568000, 3584000, 3600000, 3616000,191	3632000, 3648000, 3664000, 3680000, 3696000, 3712000, 3728000, 3744000,192	3760000, 3776000, 3792000, 3808000, 3824000, 3840000, 3856000, 3872000,193	3888000, 3904000, 3920000, 3936000, 3952000, 3968000, 3984000, 4000000,194	4016000, 4032000, 4048000, 4064000, 4080000, 4096000, 4112000, 4128000,195	4144000, 4160000, 4176000, 4192000, 4208000, 4224000, 4240000, 4256000,196	4272000, 4288000, 4304000, 4320000, 4336000, 4352000, 4368000, 4384000,197	4400000198};199 200/* REG06[1:0] (TREG) in tenths of degrees Celsius */201static const int bq24190_ictrc_treg_values[] = {202	600, 800, 1000, 1200203};204 205enum bq24190_chip {206	BQ24190,207	BQ24192,208	BQ24192i,209	BQ24196,210	BQ24296,211};212 213/*214 * The FAULT register is latched by the bq24190 (except for NTC_FAULT)215 * so the first read after a fault returns the latched value and subsequent216 * reads return the current value.  In order to return the fault status217 * to the user, have the interrupt handler save the reg's value and retrieve218 * it in the appropriate health/status routine.219 */220struct bq24190_dev_info {221	struct i2c_client		*client;222	struct device			*dev;223	struct extcon_dev		*edev;224	struct power_supply		*charger;225	struct power_supply		*battery;226	struct delayed_work		input_current_limit_work;227	char				model_name[I2C_NAME_SIZE];228	bool				initialized;229	bool				irq_event;230	bool				otg_vbus_enabled;231	int				charge_type;232	u16				sys_min;233	u16				iprechg;234	u16				iterm;235	u32				ichg;236	u32				ichg_max;237	u32				vreg;238	u32				vreg_max;239	struct mutex			f_reg_lock;240	u8				f_reg;241	u8				ss_reg;242	u8				watchdog;243	const struct bq24190_chip_info	*info;244};245 246struct bq24190_chip_info {247	int ichg_array_size;248#ifdef CONFIG_REGULATOR249	const struct regulator_desc *vbus_desc;250#endif251	int (*check_chip)(struct bq24190_dev_info *bdi);252	int (*set_chg_config)(struct bq24190_dev_info *bdi, const u8 chg_config);253	int (*set_otg_vbus)(struct bq24190_dev_info *bdi, bool enable);254	u8 ntc_fault_mask;255	int (*get_ntc_status)(const u8 value);256};257 258static int bq24190_charger_set_charge_type(struct bq24190_dev_info *bdi,259					   const union power_supply_propval *val);260 261static const unsigned int bq24190_usb_extcon_cable[] = {262	EXTCON_USB,263	EXTCON_NONE,264};265 266 267/*268 * Return the index in 'tbl' of greatest value that is less than or equal to269 * 'val'.  The index range returned is 0 to 'tbl_size' - 1.  Assumes that270 * the values in 'tbl' are sorted from smallest to largest and 'tbl_size'271 * is less than 2^8.272 */273static u8 bq24190_find_idx(const int tbl[], int tbl_size, int v)274{275	int i;276 277	for (i = 1; i < tbl_size; i++)278		if (v < tbl[i])279			break;280 281	return i - 1;282}283 284/* Basic driver I/O routines */285 286static int bq24190_read(struct bq24190_dev_info *bdi, u8 reg, u8 *data)287{288	int ret;289 290	ret = i2c_smbus_read_byte_data(bdi->client, reg);291	if (ret < 0)292		return ret;293 294	*data = ret;295	return 0;296}297 298static int bq24190_write(struct bq24190_dev_info *bdi, u8 reg, u8 data)299{300	return i2c_smbus_write_byte_data(bdi->client, reg, data);301}302 303static int bq24190_read_mask(struct bq24190_dev_info *bdi, u8 reg,304		u8 mask, u8 shift, u8 *data)305{306	u8 v;307	int ret;308 309	ret = bq24190_read(bdi, reg, &v);310	if (ret < 0)311		return ret;312 313	v &= mask;314	v >>= shift;315	*data = v;316 317	return 0;318}319 320static int bq24190_write_mask(struct bq24190_dev_info *bdi, u8 reg,321		u8 mask, u8 shift, u8 data)322{323	u8 v;324	int ret;325 326	ret = bq24190_read(bdi, reg, &v);327	if (ret < 0)328		return ret;329 330	v &= ~mask;331	v |= ((data << shift) & mask);332 333	return bq24190_write(bdi, reg, v);334}335 336static int bq24190_get_field_val(struct bq24190_dev_info *bdi,337		u8 reg, u8 mask, u8 shift,338		const int tbl[], int tbl_size,339		int *val)340{341	u8 v;342	int ret;343 344	ret = bq24190_read_mask(bdi, reg, mask, shift, &v);345	if (ret < 0)346		return ret;347 348	v = (v >= tbl_size) ? (tbl_size - 1) : v;349	*val = tbl[v];350 351	return 0;352}353 354static int bq24190_set_field_val(struct bq24190_dev_info *bdi,355		u8 reg, u8 mask, u8 shift,356		const int tbl[], int tbl_size,357		int val)358{359	u8 idx;360 361	idx = bq24190_find_idx(tbl, tbl_size, val);362 363	return bq24190_write_mask(bdi, reg, mask, shift, idx);364}365 366#ifdef CONFIG_SYSFS367/*368 * There are a numerous options that are configurable on the bq24190369 * that go well beyond what the power_supply properties provide access to.370 * Provide sysfs access to them so they can be examined and possibly modified371 * on the fly.  They will be provided for the charger power_supply object only372 * and will be prefixed by 'f_' to make them easier to recognize.373 */374 375#define BQ24190_SYSFS_FIELD(_name, r, f, m, store)			\376{									\377	.attr	= __ATTR(f_##_name, m, bq24190_sysfs_show, store),	\378	.reg	= BQ24190_REG_##r,					\379	.mask	= BQ24190_REG_##r##_##f##_MASK,				\380	.shift	= BQ24190_REG_##r##_##f##_SHIFT,			\381}382 383#define BQ24190_SYSFS_FIELD_RW(_name, r, f)				\384		BQ24190_SYSFS_FIELD(_name, r, f, S_IWUSR | S_IRUGO,	\385				bq24190_sysfs_store)386 387#define BQ24190_SYSFS_FIELD_RO(_name, r, f)				\388		BQ24190_SYSFS_FIELD(_name, r, f, S_IRUGO, NULL)389 390static ssize_t bq24190_sysfs_show(struct device *dev,391		struct device_attribute *attr, char *buf);392static ssize_t bq24190_sysfs_store(struct device *dev,393		struct device_attribute *attr, const char *buf, size_t count);394 395struct bq24190_sysfs_field_info {396	struct device_attribute	attr;397	u8	reg;398	u8	mask;399	u8	shift;400};401 402/* On i386 ptrace-abi.h defines SS that breaks the macro calls below. */403#undef SS404 405static struct bq24190_sysfs_field_info bq24190_sysfs_field_tbl[] = {406			/*	sysfs name	reg	field in reg */407	BQ24190_SYSFS_FIELD_RW(en_hiz,		ISC,	EN_HIZ),408	BQ24190_SYSFS_FIELD_RW(vindpm,		ISC,	VINDPM),409	BQ24190_SYSFS_FIELD_RW(iinlim,		ISC,	IINLIM),410	BQ24190_SYSFS_FIELD_RW(chg_config,	POC,	CHG_CONFIG),411	BQ24190_SYSFS_FIELD_RW(sys_min,		POC,	SYS_MIN),412	BQ24190_SYSFS_FIELD_RW(boost_lim,	POC,	BOOST_LIM),413	BQ24190_SYSFS_FIELD_RW(ichg,		CCC,	ICHG),414	BQ24190_SYSFS_FIELD_RW(force_20_pct,	CCC,	FORCE_20PCT),415	BQ24190_SYSFS_FIELD_RW(iprechg,		PCTCC,	IPRECHG),416	BQ24190_SYSFS_FIELD_RW(iterm,		PCTCC,	ITERM),417	BQ24190_SYSFS_FIELD_RW(vreg,		CVC,	VREG),418	BQ24190_SYSFS_FIELD_RW(batlowv,		CVC,	BATLOWV),419	BQ24190_SYSFS_FIELD_RW(vrechg,		CVC,	VRECHG),420	BQ24190_SYSFS_FIELD_RW(en_term,		CTTC,	EN_TERM),421	BQ24190_SYSFS_FIELD_RW(term_stat,	CTTC,	TERM_STAT),422	BQ24190_SYSFS_FIELD_RO(watchdog,	CTTC,	WATCHDOG),423	BQ24190_SYSFS_FIELD_RW(en_timer,	CTTC,	EN_TIMER),424	BQ24190_SYSFS_FIELD_RW(chg_timer,	CTTC,	CHG_TIMER),425	BQ24190_SYSFS_FIELD_RW(jeta_iset,	CTTC,	JEITA_ISET),426	BQ24190_SYSFS_FIELD_RW(bat_comp,	ICTRC,	BAT_COMP),427	BQ24190_SYSFS_FIELD_RW(vclamp,		ICTRC,	VCLAMP),428	BQ24190_SYSFS_FIELD_RW(treg,		ICTRC,	TREG),429	BQ24190_SYSFS_FIELD_RW(dpdm_en,		MOC,	DPDM_EN),430	BQ24190_SYSFS_FIELD_RW(tmr2x_en,	MOC,	TMR2X_EN),431	BQ24190_SYSFS_FIELD_RW(batfet_disable,	MOC,	BATFET_DISABLE),432	BQ24190_SYSFS_FIELD_RW(jeita_vset,	MOC,	JEITA_VSET),433	BQ24190_SYSFS_FIELD_RO(int_mask,	MOC,	INT_MASK),434	BQ24190_SYSFS_FIELD_RO(vbus_stat,	SS,	VBUS_STAT),435	BQ24190_SYSFS_FIELD_RO(chrg_stat,	SS,	CHRG_STAT),436	BQ24190_SYSFS_FIELD_RO(dpm_stat,	SS,	DPM_STAT),437	BQ24190_SYSFS_FIELD_RO(pg_stat,		SS,	PG_STAT),438	BQ24190_SYSFS_FIELD_RO(therm_stat,	SS,	THERM_STAT),439	BQ24190_SYSFS_FIELD_RO(vsys_stat,	SS,	VSYS_STAT),440	BQ24190_SYSFS_FIELD_RO(watchdog_fault,	F,	WATCHDOG_FAULT),441	BQ24190_SYSFS_FIELD_RO(boost_fault,	F,	BOOST_FAULT),442	BQ24190_SYSFS_FIELD_RO(chrg_fault,	F,	CHRG_FAULT),443	BQ24190_SYSFS_FIELD_RO(bat_fault,	F,	BAT_FAULT),444	BQ24190_SYSFS_FIELD_RO(ntc_fault,	F,	NTC_FAULT),445	BQ24190_SYSFS_FIELD_RO(pn,		VPRS,	PN),446	BQ24190_SYSFS_FIELD_RO(ts_profile,	VPRS,	TS_PROFILE),447	BQ24190_SYSFS_FIELD_RO(dev_reg,		VPRS,	DEV_REG),448};449 450static struct attribute *451	bq24190_sysfs_attrs[ARRAY_SIZE(bq24190_sysfs_field_tbl) + 1];452 453ATTRIBUTE_GROUPS(bq24190_sysfs);454 455static void bq24190_sysfs_init_attrs(void)456{457	int i, limit = ARRAY_SIZE(bq24190_sysfs_field_tbl);458 459	for (i = 0; i < limit; i++)460		bq24190_sysfs_attrs[i] = &bq24190_sysfs_field_tbl[i].attr.attr;461 462	bq24190_sysfs_attrs[limit] = NULL; /* Has additional entry for this */463}464 465static struct bq24190_sysfs_field_info *bq24190_sysfs_field_lookup(466		const char *name)467{468	int i, limit = ARRAY_SIZE(bq24190_sysfs_field_tbl);469 470	for (i = 0; i < limit; i++)471		if (!strcmp(name, bq24190_sysfs_field_tbl[i].attr.attr.name))472			break;473 474	if (i >= limit)475		return NULL;476 477	return &bq24190_sysfs_field_tbl[i];478}479 480static ssize_t bq24190_sysfs_show(struct device *dev,481		struct device_attribute *attr, char *buf)482{483	struct power_supply *psy = dev_get_drvdata(dev);484	struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);485	struct bq24190_sysfs_field_info *info;486	ssize_t count;487	int ret;488	u8 v;489 490	info = bq24190_sysfs_field_lookup(attr->attr.name);491	if (!info)492		return -EINVAL;493 494	ret = pm_runtime_resume_and_get(bdi->dev);495	if (ret < 0)496		return ret;497 498	ret = bq24190_read_mask(bdi, info->reg, info->mask, info->shift, &v);499	if (ret)500		count = ret;501	else502		count = sysfs_emit(buf, "%hhx\n", v);503 504	pm_runtime_mark_last_busy(bdi->dev);505	pm_runtime_put_autosuspend(bdi->dev);506 507	return count;508}509 510static ssize_t bq24190_sysfs_store(struct device *dev,511		struct device_attribute *attr, const char *buf, size_t count)512{513	struct power_supply *psy = dev_get_drvdata(dev);514	struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);515	struct bq24190_sysfs_field_info *info;516	int ret;517	u8 v;518 519	info = bq24190_sysfs_field_lookup(attr->attr.name);520	if (!info)521		return -EINVAL;522 523	ret = kstrtou8(buf, 0, &v);524	if (ret < 0)525		return ret;526 527	ret = pm_runtime_resume_and_get(bdi->dev);528	if (ret < 0)529		return ret;530 531	ret = bq24190_write_mask(bdi, info->reg, info->mask, info->shift, v);532	if (ret)533		count = ret;534 535	pm_runtime_mark_last_busy(bdi->dev);536	pm_runtime_put_autosuspend(bdi->dev);537 538	return count;539}540#endif541 542static int bq24190_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)543{544	union power_supply_propval val = { .intval = bdi->charge_type };545	int ret;546 547	ret = pm_runtime_resume_and_get(bdi->dev);548	if (ret < 0) {549		dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret);550		return ret;551	}552 553	bdi->otg_vbus_enabled = enable;554	if (enable)555		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,556					 BQ24190_REG_POC_CHG_CONFIG_MASK,557					 BQ24190_REG_POC_CHG_CONFIG_SHIFT,558					 BQ24190_REG_POC_CHG_CONFIG_OTG);559	else560		ret = bq24190_charger_set_charge_type(bdi, &val);561 562	pm_runtime_mark_last_busy(bdi->dev);563	pm_runtime_put_autosuspend(bdi->dev);564 565	return ret;566}567 568static int bq24296_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)569{570	int ret;571 572	ret = pm_runtime_resume_and_get(bdi->dev);573	if (ret < 0) {574		dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret);575		return ret;576	}577 578	bdi->otg_vbus_enabled = enable;579	if (enable) {580		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,581					 BQ24296_REG_POC_CHG_CONFIG_MASK,582					 BQ24296_REG_POC_CHG_CONFIG_SHIFT,583					 BQ24190_REG_POC_CHG_CONFIG_DISABLE);584 585		if (ret < 0)586			goto out;587 588		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,589					 BQ24296_REG_POC_OTG_CONFIG_MASK,590					 BQ24296_REG_POC_CHG_CONFIG_SHIFT,591					 BQ24296_REG_POC_OTG_CONFIG_OTG);592	} else593		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,594					 BQ24296_REG_POC_OTG_CONFIG_MASK,595					 BQ24296_REG_POC_CHG_CONFIG_SHIFT,596					 BQ24296_REG_POC_OTG_CONFIG_DISABLE);597 598out:599	pm_runtime_mark_last_busy(bdi->dev);600	pm_runtime_put_autosuspend(bdi->dev);601 602	return ret;603}604 605#ifdef CONFIG_REGULATOR606static int bq24190_vbus_enable(struct regulator_dev *dev)607{608	return bq24190_set_otg_vbus(rdev_get_drvdata(dev), true);609}610 611static int bq24190_vbus_disable(struct regulator_dev *dev)612{613	return bq24190_set_otg_vbus(rdev_get_drvdata(dev), false);614}615 616static int bq24190_vbus_is_enabled(struct regulator_dev *dev)617{618	struct bq24190_dev_info *bdi = rdev_get_drvdata(dev);619	int ret;620	u8 val;621 622	ret = pm_runtime_resume_and_get(bdi->dev);623	if (ret < 0) {624		dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret);625		return ret;626	}627 628	ret = bq24190_read_mask(bdi, BQ24190_REG_POC,629				BQ24190_REG_POC_CHG_CONFIG_MASK,630				BQ24190_REG_POC_CHG_CONFIG_SHIFT, &val);631 632	pm_runtime_mark_last_busy(bdi->dev);633	pm_runtime_put_autosuspend(bdi->dev);634 635	if (ret)636		return ret;637 638	bdi->otg_vbus_enabled = (val == BQ24190_REG_POC_CHG_CONFIG_OTG ||639				 val == BQ24190_REG_POC_CHG_CONFIG_OTG_ALT);640	return bdi->otg_vbus_enabled;641}642 643static int bq24296_vbus_enable(struct regulator_dev *dev)644{645	return bq24296_set_otg_vbus(rdev_get_drvdata(dev), true);646}647 648static int bq24296_vbus_disable(struct regulator_dev *dev)649{650	return bq24296_set_otg_vbus(rdev_get_drvdata(dev), false);651}652 653static int bq24296_vbus_is_enabled(struct regulator_dev *dev)654{655	struct bq24190_dev_info *bdi = rdev_get_drvdata(dev);656	int ret;657	u8 val;658 659	ret = pm_runtime_resume_and_get(bdi->dev);660	if (ret < 0) {661		dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", ret);662		return ret;663	}664 665	ret = bq24190_read_mask(bdi, BQ24190_REG_POC,666				BQ24296_REG_POC_OTG_CONFIG_MASK,667				BQ24296_REG_POC_OTG_CONFIG_SHIFT, &val);668 669	pm_runtime_mark_last_busy(bdi->dev);670	pm_runtime_put_autosuspend(bdi->dev);671 672	if (ret)673		return ret;674 675	bdi->otg_vbus_enabled = (val == BQ24296_REG_POC_OTG_CONFIG_OTG);676 677	return bdi->otg_vbus_enabled;678}679 680static const struct regulator_ops bq24190_vbus_ops = {681	.enable = bq24190_vbus_enable,682	.disable = bq24190_vbus_disable,683	.is_enabled = bq24190_vbus_is_enabled,684};685 686static const struct regulator_desc bq24190_vbus_desc = {687	.name = "usb_otg_vbus",688	.of_match = "usb-otg-vbus",689	.type = REGULATOR_VOLTAGE,690	.owner = THIS_MODULE,691	.ops = &bq24190_vbus_ops,692	.fixed_uV = 5000000,693	.n_voltages = 1,694};695 696static const struct regulator_ops bq24296_vbus_ops = {697	.enable = bq24296_vbus_enable,698	.disable = bq24296_vbus_disable,699	.is_enabled = bq24296_vbus_is_enabled,700};701 702static const struct regulator_desc bq24296_vbus_desc = {703	.name = "usb_otg_vbus",704	.of_match = "usb-otg-vbus",705	.type = REGULATOR_VOLTAGE,706	.owner = THIS_MODULE,707	.ops = &bq24296_vbus_ops,708	.fixed_uV = 5000000,709	.n_voltages = 1,710};711 712static const struct regulator_init_data bq24190_vbus_init_data = {713	.constraints = {714		.valid_ops_mask = REGULATOR_CHANGE_STATUS,715	},716};717 718static int bq24190_register_vbus_regulator(struct bq24190_dev_info *bdi)719{720	struct bq24190_platform_data *pdata = bdi->dev->platform_data;721	struct regulator_config cfg = { };722	struct regulator_dev *reg;723	int ret = 0;724 725	cfg.dev = bdi->dev;726	if (pdata && pdata->regulator_init_data)727		cfg.init_data = pdata->regulator_init_data;728	else729		cfg.init_data = &bq24190_vbus_init_data;730	cfg.driver_data = bdi;731	reg = devm_regulator_register(bdi->dev, bdi->info->vbus_desc, &cfg);732	if (IS_ERR(reg)) {733		ret = PTR_ERR(reg);734		dev_err(bdi->dev, "Can't register regulator: %d\n", ret);735	}736 737	return ret;738}739#else740static int bq24190_register_vbus_regulator(struct bq24190_dev_info *bdi)741{742	return 0;743}744#endif745 746static int bq24190_set_config(struct bq24190_dev_info *bdi)747{748	int ret;749	u8 v;750 751	ret = bq24190_read(bdi, BQ24190_REG_CTTC, &v);752	if (ret < 0)753		return ret;754 755	bdi->watchdog = ((v & BQ24190_REG_CTTC_WATCHDOG_MASK) >>756					BQ24190_REG_CTTC_WATCHDOG_SHIFT);757 758	/*759	 * According to the "Host Mode and default Mode" section of the760	 * manual, a write to any register causes the bq24190 to switch761	 * from default mode to host mode.  It will switch back to default762	 * mode after a WDT timeout unless the WDT is turned off as well.763	 * So, by simply turning off the WDT, we accomplish both with the764	 * same write.765	 */766	v &= ~BQ24190_REG_CTTC_WATCHDOG_MASK;767 768	ret = bq24190_write(bdi, BQ24190_REG_CTTC, v);769	if (ret < 0)770		return ret;771 772	if (bdi->sys_min) {773		v = bdi->sys_min / 100 - 30; // manual section 9.5.1.2, table 9774		ret = bq24190_write_mask(bdi, BQ24190_REG_POC,775					 BQ24190_REG_POC_SYS_MIN_MASK,776					 BQ24190_REG_POC_SYS_MIN_SHIFT,777					 v);778		if (ret < 0)779			return ret;780	}781 782	if (bdi->iprechg) {783		v = bdi->iprechg / 128 - 1; // manual section 9.5.1.4, table 11784		ret = bq24190_write_mask(bdi, BQ24190_REG_PCTCC,785					 BQ24190_REG_PCTCC_IPRECHG_MASK,786					 BQ24190_REG_PCTCC_IPRECHG_SHIFT,787					 v);788		if (ret < 0)789			return ret;790	}791 792	if (bdi->iterm) {793		v = bdi->iterm / 128 - 1; // manual section 9.5.1.4, table 11794		ret = bq24190_write_mask(bdi, BQ24190_REG_PCTCC,795					 BQ24190_REG_PCTCC_ITERM_MASK,796					 BQ24190_REG_PCTCC_ITERM_SHIFT,797					 v);798		if (ret < 0)799			return ret;800	}801 802	if (bdi->ichg) {803		ret = bq24190_set_field_val(bdi, BQ24190_REG_CCC,804					    BQ24190_REG_CCC_ICHG_MASK,805					    BQ24190_REG_CCC_ICHG_SHIFT,806					    bq24190_ccc_ichg_values,807					    bdi->info->ichg_array_size,808					    bdi->ichg);809		if (ret < 0)810			return ret;811	}812 813	if (bdi->vreg) {814		ret = bq24190_set_field_val(bdi, BQ24190_REG_CVC,815					    BQ24190_REG_CVC_VREG_MASK,816					    BQ24190_REG_CVC_VREG_SHIFT,817					    bq24190_cvc_vreg_values,818					    ARRAY_SIZE(bq24190_cvc_vreg_values),819					    bdi->vreg);820		if (ret < 0)821			return ret;822	}823 824	return 0;825}826 827static int bq24190_register_reset(struct bq24190_dev_info *bdi)828{829	int ret, limit = 100;830	u8 v;831 832	/*833	 * This prop. can be passed on device instantiation from platform code:834	 * struct property_entry pe[] =835	 *   { PROPERTY_ENTRY_BOOL("disable-reset"), ... };836	 * struct i2c_board_info bi =837	 *   { .type = "bq24190", .addr = 0x6b, .properties = pe, .irq = irq };838	 * struct i2c_adapter ad = { ... };839	 * i2c_add_adapter(&ad);840	 * i2c_new_client_device(&ad, &bi);841	 */842	if (device_property_read_bool(bdi->dev, "disable-reset"))843		return 0;844 845	/* Reset the registers */846	ret = bq24190_write_mask(bdi, BQ24190_REG_POC,847			BQ24190_REG_POC_RESET_MASK,848			BQ24190_REG_POC_RESET_SHIFT,849			0x1);850	if (ret < 0)851		return ret;852 853	/* Reset bit will be cleared by hardware so poll until it is */854	do {855		ret = bq24190_read_mask(bdi, BQ24190_REG_POC,856				BQ24190_REG_POC_RESET_MASK,857				BQ24190_REG_POC_RESET_SHIFT,858				&v);859		if (ret < 0)860			return ret;861 862		if (v == 0)863			return 0;864 865		usleep_range(100, 200);866	} while (--limit);867 868	return -EIO;869}870 871/* Charger power supply property routines */872 873static int bq24190_charger_get_charge_type(struct bq24190_dev_info *bdi,874		union power_supply_propval *val)875{876	u8 v;877	int type, ret;878 879	ret = bq24190_read_mask(bdi, BQ24190_REG_POC,880			BQ24190_REG_POC_CHG_CONFIG_MASK,881			BQ24190_REG_POC_CHG_CONFIG_SHIFT,882			&v);883	if (ret < 0)884		return ret;885 886	/* If POC[CHG_CONFIG] (REG01[5:4]) == 0, charge is disabled */887	if (!v) {888		type = POWER_SUPPLY_CHARGE_TYPE_NONE;889	} else {890		ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,891				BQ24190_REG_CCC_FORCE_20PCT_MASK,892				BQ24190_REG_CCC_FORCE_20PCT_SHIFT,893				&v);894		if (ret < 0)895			return ret;896 897		type = (v) ? POWER_SUPPLY_CHARGE_TYPE_TRICKLE :898			     POWER_SUPPLY_CHARGE_TYPE_FAST;899	}900 901	val->intval = type;902 903	return 0;904}905 906static int bq24190_battery_set_chg_config(struct bq24190_dev_info *bdi,907		const u8 chg_config)908{909	return bq24190_write_mask(bdi, BQ24190_REG_POC,910			BQ24190_REG_POC_CHG_CONFIG_MASK,911			BQ24190_REG_POC_CHG_CONFIG_SHIFT,912			chg_config);913}914 915static int bq24296_battery_set_chg_config(struct bq24190_dev_info *bdi,916		const u8 chg_config)917{918	return bq24190_write_mask(bdi, BQ24190_REG_POC,919			BQ24296_REG_POC_CHG_CONFIG_MASK,920			BQ24296_REG_POC_CHG_CONFIG_SHIFT,921			chg_config);922}923 924static int bq24190_charger_set_charge_type(struct bq24190_dev_info *bdi,925		const union power_supply_propval *val)926{927	u8 chg_config, force_20pct, en_term;928	int ret;929 930	/*931	 * According to the "Termination when REG02[0] = 1" section of932	 * the bq24190 manual, the trickle charge could be less than the933	 * termination current so it recommends turning off the termination934	 * function.935	 *936	 * Note: AFAICT from the datasheet, the user will have to manually937	 * turn off the charging when in 20% mode.  If its not turned off,938	 * there could be battery damage.  So, use this mode at your own risk.939	 */940	switch (val->intval) {941	case POWER_SUPPLY_CHARGE_TYPE_NONE:942		chg_config = 0x0;943		break;944	case POWER_SUPPLY_CHARGE_TYPE_TRICKLE:945		chg_config = 0x1;946		force_20pct = 0x1;947		en_term = 0x0;948		break;949	case POWER_SUPPLY_CHARGE_TYPE_FAST:950		chg_config = 0x1;951		force_20pct = 0x0;952		en_term = 0x1;953		break;954	default:955		return -EINVAL;956	}957 958	bdi->charge_type = val->intval;959	/*960	 * If the 5V Vbus boost regulator is enabled delay setting961	 * the charge-type until its gets disabled.962	 */963	if (bdi->otg_vbus_enabled)964		return 0;965 966	if (chg_config) { /* Enabling the charger */967		ret = bq24190_write_mask(bdi, BQ24190_REG_CCC,968				BQ24190_REG_CCC_FORCE_20PCT_MASK,969				BQ24190_REG_CCC_FORCE_20PCT_SHIFT,970				force_20pct);971		if (ret < 0)972			return ret;973 974		ret = bq24190_write_mask(bdi, BQ24190_REG_CTTC,975				BQ24190_REG_CTTC_EN_TERM_MASK,976				BQ24190_REG_CTTC_EN_TERM_SHIFT,977				en_term);978		if (ret < 0)979			return ret;980	}981 982	return bdi->info->set_chg_config(bdi, chg_config);983}984 985static int bq24190_charger_get_ntc_status(u8 value)986{987	int health;988 989	switch (value >> BQ24190_REG_F_NTC_FAULT_SHIFT & 0x7) {990	case 0x1: /* TS1  Cold */991	case 0x3: /* TS2  Cold */992	case 0x5: /* Both Cold */993		health = POWER_SUPPLY_HEALTH_COLD;994		break;995	case 0x2: /* TS1  Hot */996	case 0x4: /* TS2  Hot */997	case 0x6: /* Both Hot */998		health = POWER_SUPPLY_HEALTH_OVERHEAT;999		break;1000	default:1001		health = POWER_SUPPLY_HEALTH_UNKNOWN;1002	}1003 1004	return health;1005}1006 1007static int bq24296_charger_get_ntc_status(u8 value)1008{1009	int health;1010 1011	switch (value >> BQ24296_REG_F_NTC_FAULT_SHIFT & 0x3) {1012	case 0x0: /* Normal */1013		health = POWER_SUPPLY_HEALTH_GOOD;1014		break;1015	case 0x1: /* Hot */1016		health = POWER_SUPPLY_HEALTH_OVERHEAT;1017		break;1018	case 0x2: /* Cold */1019		health = POWER_SUPPLY_HEALTH_COLD;1020		break;1021	default:1022		health = POWER_SUPPLY_HEALTH_UNKNOWN;1023	}1024 1025	return health;1026}1027 1028static int bq24190_charger_get_health(struct bq24190_dev_info *bdi,1029		union power_supply_propval *val)1030{1031	u8 v;1032	int health;1033 1034	mutex_lock(&bdi->f_reg_lock);1035	v = bdi->f_reg;1036	mutex_unlock(&bdi->f_reg_lock);1037 1038	if (v & bdi->info->ntc_fault_mask) {1039		health = bdi->info->get_ntc_status(v);1040	} else if (v & BQ24190_REG_F_BAT_FAULT_MASK) {1041		health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;1042	} else if (v & BQ24190_REG_F_CHRG_FAULT_MASK) {1043		switch (v >> BQ24190_REG_F_CHRG_FAULT_SHIFT & 0x3) {1044		case 0x1: /* Input Fault (VBUS OVP or VBAT<VBUS<3.8V) */1045			/*1046			 * This could be over-voltage or under-voltage1047			 * and there's no way to tell which.  Instead1048			 * of looking foolish and returning 'OVERVOLTAGE'1049			 * when its really under-voltage, just return1050			 * 'UNSPEC_FAILURE'.1051			 */1052			health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;1053			break;1054		case 0x2: /* Thermal Shutdown */1055			health = POWER_SUPPLY_HEALTH_OVERHEAT;1056			break;1057		case 0x3: /* Charge Safety Timer Expiration */1058			health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;1059			break;1060		default:  /* prevent compiler warning */1061			health = -1;1062		}1063	} else if (v & BQ24190_REG_F_BOOST_FAULT_MASK) {1064		/*1065		 * This could be over-current or over-voltage but there's1066		 * no way to tell which.  Return 'OVERVOLTAGE' since there1067		 * isn't an 'OVERCURRENT' value defined that we can return1068		 * even if it was over-current.1069		 */1070		health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;1071	} else {1072		health = POWER_SUPPLY_HEALTH_GOOD;1073	}1074 1075	val->intval = health;1076 1077	return 0;1078}1079 1080static int bq24190_charger_get_online(struct bq24190_dev_info *bdi,1081		union power_supply_propval *val)1082{1083	u8 pg_stat, batfet_disable;1084	int ret;1085 1086	ret = bq24190_read_mask(bdi, BQ24190_REG_SS,1087			BQ24190_REG_SS_PG_STAT_MASK,1088			BQ24190_REG_SS_PG_STAT_SHIFT, &pg_stat);1089	if (ret < 0)1090		return ret;1091 1092	ret = bq24190_read_mask(bdi, BQ24190_REG_MOC,1093			BQ24190_REG_MOC_BATFET_DISABLE_MASK,1094			BQ24190_REG_MOC_BATFET_DISABLE_SHIFT, &batfet_disable);1095	if (ret < 0)1096		return ret;1097 1098	val->intval = pg_stat && !batfet_disable;1099 1100	return 0;1101}1102 1103static int bq24190_battery_set_online(struct bq24190_dev_info *bdi,1104				      const union power_supply_propval *val);1105static int bq24190_battery_get_status(struct bq24190_dev_info *bdi,1106				      union power_supply_propval *val);1107static int bq24190_battery_get_temp_alert_max(struct bq24190_dev_info *bdi,1108					      union power_supply_propval *val);1109static int bq24190_battery_set_temp_alert_max(struct bq24190_dev_info *bdi,1110					      const union power_supply_propval *val);1111 1112static int bq24190_charger_set_online(struct bq24190_dev_info *bdi,1113				      const union power_supply_propval *val)1114{1115	return bq24190_battery_set_online(bdi, val);1116}1117 1118static int bq24190_charger_get_status(struct bq24190_dev_info *bdi,1119				      union power_supply_propval *val)1120{1121	return bq24190_battery_get_status(bdi, val);1122}1123 1124static int bq24190_charger_get_temp_alert_max(struct bq24190_dev_info *bdi,1125					      union power_supply_propval *val)1126{1127	return bq24190_battery_get_temp_alert_max(bdi, val);1128}1129 1130static int bq24190_charger_set_temp_alert_max(struct bq24190_dev_info *bdi,1131					      const union power_supply_propval *val)1132{1133	return bq24190_battery_set_temp_alert_max(bdi, val);1134}1135 1136static int bq24190_charger_get_precharge(struct bq24190_dev_info *bdi,1137		union power_supply_propval *val)1138{1139	u8 v;1140	int curr, ret;1141 1142	ret = bq24190_read_mask(bdi, BQ24190_REG_PCTCC,1143			BQ24190_REG_PCTCC_IPRECHG_MASK,1144			BQ24190_REG_PCTCC_IPRECHG_SHIFT, &v);1145	if (ret < 0)1146		return ret;1147 1148	curr = ++v * 128 * 1000;1149 1150	ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,1151			BQ24190_REG_CCC_FORCE_20PCT_MASK,1152			BQ24190_REG_CCC_FORCE_20PCT_SHIFT, &v);1153	if (ret < 0)1154		return ret;1155 1156	/* If FORCE_20PCT is enabled, then current is 50% of IPRECHG value */1157	if (v)1158		curr /= 2;1159 1160	val->intval = curr;1161 1162	return 0;1163}1164 1165static int bq24190_charger_get_charge_term(struct bq24190_dev_info *bdi,1166		union power_supply_propval *val)1167{1168	u8 v;1169	int ret;1170 1171	ret = bq24190_read_mask(bdi, BQ24190_REG_PCTCC,1172			BQ24190_REG_PCTCC_ITERM_MASK,1173			BQ24190_REG_PCTCC_ITERM_SHIFT, &v);1174	if (ret < 0)1175		return ret;1176 1177	val->intval = ++v * 128 * 1000;1178	return 0;1179}1180 1181static int bq24190_charger_get_current(struct bq24190_dev_info *bdi,1182		union power_supply_propval *val)1183{1184	u8 v;1185	int curr, ret;1186 1187	ret = bq24190_get_field_val(bdi, BQ24190_REG_CCC,1188			BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT,1189			bq24190_ccc_ichg_values,1190			bdi->info->ichg_array_size, &curr);1191	if (ret < 0)1192		return ret;1193 1194	ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,1195			BQ24190_REG_CCC_FORCE_20PCT_MASK,1196			BQ24190_REG_CCC_FORCE_20PCT_SHIFT, &v);1197	if (ret < 0)1198		return ret;1199 1200	/* If FORCE_20PCT is enabled, then current is 20% of ICHG value */1201	if (v)1202		curr /= 5;1203 1204	val->intval = curr;1205	return 0;1206}1207 1208static int bq24190_charger_set_current(struct bq24190_dev_info *bdi,1209		const union power_supply_propval *val)1210{1211	u8 v;1212	int ret, curr = val->intval;1213 1214	ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,1215			BQ24190_REG_CCC_FORCE_20PCT_MASK,1216			BQ24190_REG_CCC_FORCE_20PCT_SHIFT, &v);1217	if (ret < 0)1218		return ret;1219 1220	/* If FORCE_20PCT is enabled, have to multiply value passed in by 5 */1221	if (v)1222		curr *= 5;1223 1224	if (curr > bdi->ichg_max)1225		return -EINVAL;1226 1227	ret = bq24190_set_field_val(bdi, BQ24190_REG_CCC,1228			BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT,1229			bq24190_ccc_ichg_values,1230			bdi->info->ichg_array_size, curr);1231	if (ret < 0)1232		return ret;1233 1234	bdi->ichg = curr;1235 1236	return 0;1237}1238 1239static int bq24190_charger_get_voltage(struct bq24190_dev_info *bdi,1240		union power_supply_propval *val)1241{1242	int voltage, ret;1243 1244	ret = bq24190_get_field_val(bdi, BQ24190_REG_CVC,1245			BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,1246			bq24190_cvc_vreg_values,1247			ARRAY_SIZE(bq24190_cvc_vreg_values), &voltage);1248	if (ret < 0)1249		return ret;1250 1251	val->intval = voltage;1252	return 0;1253}1254 1255static int bq24190_charger_set_voltage(struct bq24190_dev_info *bdi,1256		const union power_supply_propval *val)1257{1258	int ret;1259 1260	if (val->intval > bdi->vreg_max)1261		return -EINVAL;1262 1263	ret = bq24190_set_field_val(bdi, BQ24190_REG_CVC,1264			BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,1265			bq24190_cvc_vreg_values,1266			ARRAY_SIZE(bq24190_cvc_vreg_values), val->intval);1267	if (ret < 0)1268		return ret;1269 1270	bdi->vreg = val->intval;1271 1272	return 0;1273}1274 1275static int bq24190_charger_get_iinlimit(struct bq24190_dev_info *bdi,1276		union power_supply_propval *val)1277{1278	int iinlimit, ret;1279 1280	ret = bq24190_get_field_val(bdi, BQ24190_REG_ISC,1281			BQ24190_REG_ISC_IINLIM_MASK,1282			BQ24190_REG_ISC_IINLIM_SHIFT,1283			bq24190_isc_iinlim_values,1284			ARRAY_SIZE(bq24190_isc_iinlim_values), &iinlimit);1285	if (ret < 0)1286		return ret;1287 1288	val->intval = iinlimit;1289	return 0;1290}1291 1292static int bq24190_charger_set_iinlimit(struct bq24190_dev_info *bdi,1293		const union power_supply_propval *val)1294{1295	return bq24190_set_field_val(bdi, BQ24190_REG_ISC,1296			BQ24190_REG_ISC_IINLIM_MASK,1297			BQ24190_REG_ISC_IINLIM_SHIFT,1298			bq24190_isc_iinlim_values,1299			ARRAY_SIZE(bq24190_isc_iinlim_values), val->intval);1300}1301 1302static int bq24190_charger_get_property(struct power_supply *psy,1303		enum power_supply_property psp, union power_supply_propval *val)1304{1305	struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);1306	int ret;1307 1308	dev_dbg(bdi->dev, "prop: %d\n", psp);1309 1310	ret = pm_runtime_resume_and_get(bdi->dev);1311	if (ret < 0)1312		return ret;1313 1314	switch (psp) {1315	case POWER_SUPPLY_PROP_CHARGE_TYPE:1316		ret = bq24190_charger_get_charge_type(bdi, val);1317		break;1318	case POWER_SUPPLY_PROP_HEALTH:1319		ret = bq24190_charger_get_health(bdi, val);1320		break;1321	case POWER_SUPPLY_PROP_ONLINE:1322		ret = bq24190_charger_get_online(bdi, val);1323		break;1324	case POWER_SUPPLY_PROP_STATUS:1325		ret = bq24190_charger_get_status(bdi, val);1326		break;1327	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:1328		ret =  bq24190_charger_get_temp_alert_max(bdi, val);1329		break;1330	case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:1331		ret = bq24190_charger_get_precharge(bdi, val);1332		break;1333	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:1334		ret = bq24190_charger_get_charge_term(bdi, val);1335		break;1336	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:1337		ret = bq24190_charger_get_current(bdi, val);1338		break;1339	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:1340		val->intval = bdi->ichg_max;1341		ret = 0;1342		break;1343	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:1344		ret = bq24190_charger_get_voltage(bdi, val);1345		break;1346	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:1347		val->intval = bdi->vreg_max;1348		ret = 0;1349		break;1350	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:1351		ret = bq24190_charger_get_iinlimit(bdi, val);1352		break;1353	case POWER_SUPPLY_PROP_SCOPE:1354		val->intval = POWER_SUPPLY_SCOPE_SYSTEM;1355		ret = 0;1356		break;1357	case POWER_SUPPLY_PROP_MODEL_NAME:1358		val->strval = bdi->model_name;1359		ret = 0;1360		break;1361	case POWER_SUPPLY_PROP_MANUFACTURER:1362		val->strval = BQ24190_MANUFACTURER;1363		ret = 0;1364		break;1365	default:1366		ret = -ENODATA;1367	}1368 1369	pm_runtime_mark_last_busy(bdi->dev);1370	pm_runtime_put_autosuspend(bdi->dev);1371 1372	return ret;1373}1374 1375static int bq24190_charger_set_property(struct power_supply *psy,1376		enum power_supply_property psp,1377		const union power_supply_propval *val)1378{1379	struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);1380	int ret;1381 1382	dev_dbg(bdi->dev, "prop: %d\n", psp);1383 1384	ret = pm_runtime_resume_and_get(bdi->dev);1385	if (ret < 0)1386		return ret;1387 1388	switch (psp) {1389	case POWER_SUPPLY_PROP_ONLINE:1390		ret = bq24190_charger_set_online(bdi, val);1391		break;1392	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:1393		ret = bq24190_charger_set_temp_alert_max(bdi, val);1394		break;1395	case POWER_SUPPLY_PROP_CHARGE_TYPE:1396		ret = bq24190_charger_set_charge_type(bdi, val);1397		break;1398	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:1399		ret = bq24190_charger_set_current(bdi, val);1400		break;1401	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:1402		ret = bq24190_charger_set_voltage(bdi, val);1403		break;1404	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:1405		ret = bq24190_charger_set_iinlimit(bdi, val);1406		break;1407	default:1408		ret = -EINVAL;1409	}1410 1411	pm_runtime_mark_last_busy(bdi->dev);1412	pm_runtime_put_autosuspend(bdi->dev);1413 1414	return ret;1415}1416 1417static int bq24190_charger_property_is_writeable(struct power_supply *psy,1418		enum power_supply_property psp)1419{1420	switch (psp) {1421	case POWER_SUPPLY_PROP_ONLINE:1422	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:1423	case POWER_SUPPLY_PROP_CHARGE_TYPE:1424	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:1425	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:1426	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:1427		return 1;1428	default:1429		return 0;1430	}1431}1432 1433static void bq24190_input_current_limit_work(struct work_struct *work)1434{1435	struct bq24190_dev_info *bdi =1436		container_of(work, struct bq24190_dev_info,1437			     input_current_limit_work.work);1438	union power_supply_propval val;1439	int ret;1440 1441	ret = power_supply_get_property_from_supplier(bdi->charger,1442						      POWER_SUPPLY_PROP_CURRENT_MAX,1443						      &val);1444	if (ret)1445		return;1446 1447	bq24190_charger_set_property(bdi->charger,1448				     POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,1449				     &val);1450	power_supply_changed(bdi->charger);1451}1452 1453/* Sync the input-current-limit with our parent supply (if we have one) */1454static void bq24190_charger_external_power_changed(struct power_supply *psy)1455{1456	struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);1457 1458	/*1459	 * The Power-Good detection may take up to 220ms, sometimes1460	 * the external charger detection is quicker, and the bq24190 will1461	 * reset to iinlim based on its own charger detection (which is not1462	 * hooked up when using external charger detection) resulting in a1463	 * too low default 500mA iinlim. Delay setting the input-current-limit1464	 * for 300ms to avoid this.1465	 */1466	queue_delayed_work(system_wq, &bdi->input_current_limit_work,1467			   msecs_to_jiffies(300));1468}1469 1470static enum power_supply_property bq24190_charger_properties[] = {1471	POWER_SUPPLY_PROP_CHARGE_TYPE,1472	POWER_SUPPLY_PROP_HEALTH,1473	POWER_SUPPLY_PROP_ONLINE,1474	POWER_SUPPLY_PROP_STATUS,1475	POWER_SUPPLY_PROP_TEMP_ALERT_MAX,1476	POWER_SUPPLY_PROP_PRECHARGE_CURRENT,1477	POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,1478	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,1479	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,1480	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,1481	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,1482	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,1483	POWER_SUPPLY_PROP_SCOPE,1484	POWER_SUPPLY_PROP_MODEL_NAME,1485	POWER_SUPPLY_PROP_MANUFACTURER,1486};1487 1488static char *bq24190_charger_supplied_to[] = {1489	"main-battery",1490};1491 1492static const struct power_supply_desc bq24190_charger_desc = {1493	.name			= "bq24190-charger",1494	.type			= POWER_SUPPLY_TYPE_USB,1495	.properties		= bq24190_charger_properties,1496	.num_properties		= ARRAY_SIZE(bq24190_charger_properties),1497	.get_property		= bq24190_charger_get_property,1498	.set_property		= bq24190_charger_set_property,1499	.property_is_writeable	= bq24190_charger_property_is_writeable,1500	.external_power_changed	= bq24190_charger_external_power_changed,1501};1502 1503/* Battery power supply property routines */1504 1505static int bq24190_battery_get_status(struct bq24190_dev_info *bdi,1506		union power_supply_propval *val)1507{1508	u8 ss_reg, chrg_fault;1509	int status, ret;1510 1511	mutex_lock(&bdi->f_reg_lock);1512	chrg_fault = bdi->f_reg;1513	mutex_unlock(&bdi->f_reg_lock);1514 1515	chrg_fault &= BQ24190_REG_F_CHRG_FAULT_MASK;1516	chrg_fault >>= BQ24190_REG_F_CHRG_FAULT_SHIFT;1517 1518	ret = bq24190_read(bdi, BQ24190_REG_SS, &ss_reg);1519	if (ret < 0)1520		return ret;1521 1522	/*1523	 * The battery must be discharging when any of these are true:1524	 * - there is no good power source;1525	 * - there is a charge fault.1526	 * Could also be discharging when in "supplement mode" but1527	 * there is no way to tell when its in that mode.1528	 */1529	if (!(ss_reg & BQ24190_REG_SS_PG_STAT_MASK) || chrg_fault) {1530		status = POWER_SUPPLY_STATUS_DISCHARGING;1531	} else {1532		ss_reg &= BQ24190_REG_SS_CHRG_STAT_MASK;1533		ss_reg >>= BQ24190_REG_SS_CHRG_STAT_SHIFT;1534 1535		switch (ss_reg) {1536		case 0x0: /* Not Charging */1537			status = POWER_SUPPLY_STATUS_NOT_CHARGING;1538			break;1539		case 0x1: /* Pre-charge */1540		case 0x2: /* Fast Charging */1541			status = POWER_SUPPLY_STATUS_CHARGING;1542			break;1543		case 0x3: /* Charge Termination Done */1544			status = POWER_SUPPLY_STATUS_FULL;1545			break;1546		default:1547			ret = -EIO;1548		}1549	}1550 1551	if (!ret)1552		val->intval = status;1553 1554	return ret;1555}1556 1557static int bq24190_battery_get_health(struct bq24190_dev_info *bdi,1558		union power_supply_propval *val)1559{1560	u8 v;1561	int health;1562 1563	mutex_lock(&bdi->f_reg_lock);1564	v = bdi->f_reg;1565	mutex_unlock(&bdi->f_reg_lock);1566 1567	if (v & BQ24190_REG_F_BAT_FAULT_MASK) {1568		health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;1569	} else {1570		v &= bdi->info->ntc_fault_mask;1571 1572		health = v ? bdi->info->get_ntc_status(v) : POWER_SUPPLY_HEALTH_GOOD;1573	}1574 1575	val->intval = health;1576	return 0;1577}1578 1579static int bq24190_battery_get_online(struct bq24190_dev_info *bdi,1580		union power_supply_propval *val)1581{1582	u8 batfet_disable;1583	int ret;1584 1585	ret = bq24190_read_mask(bdi, BQ24190_REG_MOC,1586			BQ24190_REG_MOC_BATFET_DISABLE_MASK,1587			BQ24190_REG_MOC_BATFET_DISABLE_SHIFT, &batfet_disable);1588	if (ret < 0)1589		return ret;1590 1591	val->intval = !batfet_disable;1592	return 0;1593}1594 1595static int bq24190_battery_set_online(struct bq24190_dev_info *bdi,1596		const union power_supply_propval *val)1597{1598	return bq24190_write_mask(bdi, BQ24190_REG_MOC,1599			BQ24190_REG_MOC_BATFET_DISABLE_MASK,1600			BQ24190_REG_MOC_BATFET_DISABLE_SHIFT, !val->intval);1601}1602 1603static int bq24190_battery_get_temp_alert_max(struct bq24190_dev_info *bdi,1604		union power_supply_propval *val)1605{1606	int temp, ret;1607 1608	ret = bq24190_get_field_val(bdi, BQ24190_REG_ICTRC,1609			BQ24190_REG_ICTRC_TREG_MASK,1610			BQ24190_REG_ICTRC_TREG_SHIFT,1611			bq24190_ictrc_treg_values,1612			ARRAY_SIZE(bq24190_ictrc_treg_values), &temp);1613	if (ret < 0)1614		return ret;1615 1616	val->intval = temp;1617	return 0;1618}1619 1620static int bq24190_battery_set_temp_alert_max(struct bq24190_dev_info *bdi,1621		const union power_supply_propval *val)1622{1623	return bq24190_set_field_val(bdi, BQ24190_REG_ICTRC,1624			BQ24190_REG_ICTRC_TREG_MASK,1625			BQ24190_REG_ICTRC_TREG_SHIFT,1626			bq24190_ictrc_treg_values,1627			ARRAY_SIZE(bq24190_ictrc_treg_values), val->intval);1628}1629 1630static int bq24190_battery_get_property(struct power_supply *psy,1631		enum power_supply_property psp, union power_supply_propval *val)1632{1633	struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);1634	int ret;1635 1636	dev_warn(bdi->dev, "warning: /sys/class/power_supply/bq24190-battery is deprecated\n");1637	dev_dbg(bdi->dev, "prop: %d\n", psp);1638 1639	ret = pm_runtime_resume_and_get(bdi->dev);1640	if (ret < 0)1641		return ret;1642 1643	switch (psp) {1644	case POWER_SUPPLY_PROP_STATUS:1645		ret = bq24190_battery_get_status(bdi, val);1646		break;1647	case POWER_SUPPLY_PROP_HEALTH:1648		ret = bq24190_battery_get_health(bdi, val);1649		break;1650	case POWER_SUPPLY_PROP_ONLINE:1651		ret = bq24190_battery_get_online(bdi, val);1652		break;1653	case POWER_SUPPLY_PROP_TECHNOLOGY:1654		/* Could be Li-on or Li-polymer but no way to tell which */1655		val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;1656		ret = 0;1657		break;1658	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:1659		ret = bq24190_battery_get_temp_alert_max(bdi, val);1660		break;1661	case POWER_SUPPLY_PROP_SCOPE:1662		val->intval = POWER_SUPPLY_SCOPE_SYSTEM;1663		ret = 0;1664		break;1665	default:1666		ret = -ENODATA;1667	}1668 1669	pm_runtime_mark_last_busy(bdi->dev);1670	pm_runtime_put_autosuspend(bdi->dev);1671 1672	return ret;1673}1674 1675static int bq24190_battery_set_property(struct power_supply *psy,1676		enum power_supply_property psp,1677		const union power_supply_propval *val)1678{1679	struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);1680	int ret;1681 1682	dev_warn(bdi->dev, "warning: /sys/class/power_supply/bq24190-battery is deprecated\n");1683	dev_dbg(bdi->dev, "prop: %d\n", psp);1684 1685	ret = pm_runtime_resume_and_get(bdi->dev);1686	if (ret < 0)1687		return ret;1688 1689	switch (psp) {1690	case POWER_SUPPLY_PROP_ONLINE:1691		ret = bq24190_battery_set_online(bdi, val);1692		break;1693	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:1694		ret = bq24190_battery_set_temp_alert_max(bdi, val);1695		break;1696	default:1697		ret = -EINVAL;1698	}1699 1700	pm_runtime_mark_last_busy(bdi->dev);1701	pm_runtime_put_autosuspend(bdi->dev);1702 1703	return ret;1704}1705 1706static int bq24190_battery_property_is_writeable(struct power_supply *psy,1707		enum power_supply_property psp)1708{1709	int ret;1710 1711	switch (psp) {1712	case POWER_SUPPLY_PROP_ONLINE:1713	case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:1714		ret = 1;1715		break;1716	default:1717		ret = 0;1718	}1719 1720	return ret;1721}1722 1723static enum power_supply_property bq24190_battery_properties[] = {1724	POWER_SUPPLY_PROP_STATUS,1725	POWER_SUPPLY_PROP_HEALTH,1726	POWER_SUPPLY_PROP_ONLINE,1727	POWER_SUPPLY_PROP_TECHNOLOGY,1728	POWER_SUPPLY_PROP_TEMP_ALERT_MAX,1729	POWER_SUPPLY_PROP_SCOPE,1730};1731 1732static const struct power_supply_desc bq24190_battery_desc = {1733	.name			= "bq24190-battery",1734	.type			= POWER_SUPPLY_TYPE_BATTERY,1735	.properties		= bq24190_battery_properties,1736	.num_properties		= ARRAY_SIZE(bq24190_battery_properties),1737	.get_property		= bq24190_battery_get_property,1738	.set_property		= bq24190_battery_set_property,1739	.property_is_writeable	= bq24190_battery_property_is_writeable,1740};1741 1742static int bq24190_configure_usb_otg(struct bq24190_dev_info *bdi, u8 ss_reg)1743{1744	bool otg_enabled;1745	int ret;1746 1747	otg_enabled = !!(ss_reg & BQ24190_REG_SS_VBUS_STAT_MASK);1748	ret = extcon_set_state_sync(bdi->edev, EXTCON_USB, otg_enabled);1749	if (ret < 0)1750		dev_err(bdi->dev, "Can't set extcon state to %d: %d\n",1751			otg_enabled, ret);1752 1753	return ret;1754}1755 1756static void bq24190_check_status(struct bq24190_dev_info *bdi)1757{1758	const u8 battery_mask_ss = BQ24190_REG_SS_CHRG_STAT_MASK;1759	u8 battery_mask_f = BQ24190_REG_F_BAT_FAULT_MASK;1760	bool alert_charger = false, alert_battery = false;1761	u8 ss_reg = 0, f_reg = 0;1762	int i, ret;1763 1764	battery_mask_f |= bdi->info->ntc_fault_mask;1765 1766	ret = bq24190_read(bdi, BQ24190_REG_SS, &ss_reg);1767	if (ret < 0) {1768		dev_err(bdi->dev, "Can't read SS reg: %d\n", ret);1769		return;1770	}1771 1772	i = 0;1773	do {1774		ret = bq24190_read(bdi, BQ24190_REG_F, &f_reg);1775		if (ret < 0) {1776			dev_err(bdi->dev, "Can't read F reg: %d\n", ret);1777			return;1778		}1779	} while (f_reg && ++i < 2);1780 1781	/* ignore over/under voltage fault after disconnect */1782	if (f_reg == (1 << BQ24190_REG_F_CHRG_FAULT_SHIFT) &&1783	    !(ss_reg & BQ24190_REG_SS_PG_STAT_MASK))1784		f_reg = 0;1785 1786	if (f_reg != bdi->f_reg) {1787		dev_warn(bdi->dev,1788			"Fault: boost %d, charge %d, battery %d, ntc %d\n",1789			!!(f_reg & BQ24190_REG_F_BOOST_FAULT_MASK),1790			!!(f_reg & BQ24190_REG_F_CHRG_FAULT_MASK),1791			!!(f_reg & BQ24190_REG_F_BAT_FAULT_MASK),1792			!!(f_reg & bdi->info->ntc_fault_mask));1793 1794		mutex_lock(&bdi->f_reg_lock);1795		if ((bdi->f_reg & battery_mask_f) != (f_reg & battery_mask_f))1796			alert_battery = true;1797		if ((bdi->f_reg & ~battery_mask_f) != (f_reg & ~battery_mask_f))1798			alert_charger = true;1799		bdi->f_reg = f_reg;1800		mutex_unlock(&bdi->f_reg_lock);1801	}1802 1803	if (ss_reg != bdi->ss_reg) {1804		/*1805		 * The device is in host mode so when PG_STAT goes from 1->01806		 * (i.e., power removed) HIZ needs to be disabled.1807		 */1808		if ((bdi->ss_reg & BQ24190_REG_SS_PG_STAT_MASK) &&1809				!(ss_reg & BQ24190_REG_SS_PG_STAT_MASK)) {1810			ret = bq24190_write_mask(bdi, BQ24190_REG_ISC,1811					BQ24190_REG_ISC_EN_HIZ_MASK,1812					BQ24190_REG_ISC_EN_HIZ_SHIFT,1813					0);1814			if (ret < 0)1815				dev_err(bdi->dev, "Can't access ISC reg: %d\n",1816					ret);1817		}1818 1819		if ((bdi->ss_reg & battery_mask_ss) != (ss_reg & battery_mask_ss))1820			alert_battery = true;1821		if ((bdi->ss_reg & ~battery_mask_ss) != (ss_reg & ~battery_mask_ss))1822			alert_charger = true;1823		bdi->ss_reg = ss_reg;1824	}1825 1826	if (alert_charger || alert_battery) {1827		power_supply_changed(bdi->charger);1828		bq24190_configure_usb_otg(bdi, ss_reg);1829	}1830	if (alert_battery && bdi->battery)1831		power_supply_changed(bdi->battery);1832 1833	dev_dbg(bdi->dev, "ss_reg: 0x%02x, f_reg: 0x%02x\n", ss_reg, f_reg);1834}1835 1836static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)1837{1838	struct bq24190_dev_info *bdi = data;1839	int error;1840 1841	bdi->irq_event = true;1842	error = pm_runtime_resume_and_get(bdi->dev);1843	if (error < 0) {1844		dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);1845		return IRQ_NONE;1846	}1847	bq24190_check_status(bdi);1848	pm_runtime_mark_last_busy(bdi->dev);1849	pm_runtime_put_autosuspend(bdi->dev);1850	bdi->irq_event = false;1851 1852	return IRQ_HANDLED;1853}1854 1855static int bq24190_check_chip(struct bq24190_dev_info *bdi)1856{1857	u8 v;1858	int ret;1859 1860	ret = bq24190_read_mask(bdi, BQ24190_REG_VPRS,1861			BQ24190_REG_VPRS_PN_MASK,1862			BQ24190_REG_VPRS_PN_SHIFT,1863			&v);1864	if (ret < 0)1865		return ret;1866 1867	switch (v) {1868	case BQ24190_REG_VPRS_PN_24190:1869	case BQ24190_REG_VPRS_PN_24192:1870	case BQ24190_REG_VPRS_PN_24192I:1871		break;1872	default:1873		dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v);1874		return -ENODEV;1875	}1876 1877	return 0;1878}1879 1880static int bq24296_check_chip(struct bq24190_dev_info *bdi)1881{1882	u8 v;1883	int ret;1884 1885	ret = bq24190_read_mask(bdi, BQ24190_REG_VPRS,1886			BQ24296_REG_VPRS_PN_MASK,1887			BQ24296_REG_VPRS_PN_SHIFT,1888			&v);1889	if (ret < 0)1890		return ret;1891 1892	switch (v) {1893	case BQ24296_REG_VPRS_PN_24296:1894		break;1895	default:1896		dev_err(bdi->dev, "Error unknown model: 0x%02x\n", v);1897		return -ENODEV;1898	}1899 1900	return 0;1901}1902 1903static int bq24190_hw_init(struct bq24190_dev_info *bdi)1904{1905	int ret;1906 1907	ret = bdi->info->check_chip(bdi);1908	if (ret < 0)1909		return ret;1910 1911	ret = bq24190_register_reset(bdi);1912	if (ret < 0)1913		return ret;1914 1915	ret = bq24190_set_config(bdi);1916	if (ret < 0)1917		return ret;1918 1919	return bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);1920}1921 1922static int bq24190_get_config(struct bq24190_dev_info *bdi)1923{1924	const char * const s = "ti,system-minimum-microvolt";1925	struct power_supply_battery_info *info;1926	int v, idx;1927 1928	idx = bdi->info->ichg_array_size - 1;1929 1930	bdi->ichg_max = bq24190_ccc_ichg_values[idx];1931 1932	idx = ARRAY_SIZE(bq24190_cvc_vreg_values) - 1;1933	bdi->vreg_max = bq24190_cvc_vreg_values[idx];1934 1935	if (device_property_read_u32(bdi->dev, s, &v) == 0) {1936		v /= 1000;1937		if (v >= BQ24190_REG_POC_SYS_MIN_MIN1938		 && v <= BQ24190_REG_POC_SYS_MIN_MAX)1939			bdi->sys_min = v;1940		else1941			dev_warn(bdi->dev, "invalid value for %s: %u\n", s, v);1942	}1943 1944	if (!power_supply_get_battery_info(bdi->charger, &info)) {1945		v = info->precharge_current_ua / 1000;1946		if (v >= BQ24190_REG_PCTCC_IPRECHG_MIN1947		 && v <= BQ24190_REG_PCTCC_IPRECHG_MAX)1948			bdi->iprechg = v;1949		else1950			dev_warn(bdi->dev, "invalid value for battery:precharge-current-microamp: %d\n",1951				 v);1952 1953		v = info->charge_term_current_ua / 1000;1954		if (v >= BQ24190_REG_PCTCC_ITERM_MIN1955		 && v <= BQ24190_REG_PCTCC_ITERM_MAX)1956			bdi->iterm = v;1957		else1958			dev_warn(bdi->dev, "invalid value for battery:charge-term-current-microamp: %d\n",1959				 v);1960 1961		/* These are optional, so no warning when not set */1962		v = info->constant_charge_current_max_ua;1963		if (v >= bq24190_ccc_ichg_values[0] && v <= bdi->ichg_max)1964			bdi->ichg = bdi->ichg_max = v;1965 1966		v = info->constant_charge_voltage_max_uv;1967		if (v >= bq24190_cvc_vreg_values[0] && v <= bdi->vreg_max)1968			bdi->vreg = bdi->vreg_max = v;1969	}1970 1971	return 0;1972}1973 1974static const struct bq24190_chip_info bq24190_chip_info_tbl[] = {1975	[BQ24190] = {1976		.ichg_array_size = ARRAY_SIZE(bq24190_ccc_ichg_values),1977#ifdef CONFIG_REGULATOR1978		.vbus_desc = &bq24190_vbus_desc,1979#endif1980		.check_chip = bq24190_check_chip,1981		.set_chg_config = bq24190_battery_set_chg_config,1982		.ntc_fault_mask = BQ24190_REG_F_NTC_FAULT_MASK,1983		.get_ntc_status = bq24190_charger_get_ntc_status,1984		.set_otg_vbus = bq24190_set_otg_vbus,1985	},1986	[BQ24192] = {1987		.ichg_array_size = ARRAY_SIZE(bq24190_ccc_ichg_values),1988#ifdef CONFIG_REGULATOR1989		.vbus_desc = &bq24190_vbus_desc,1990#endif1991		.check_chip = bq24190_check_chip,1992		.set_chg_config = bq24190_battery_set_chg_config,1993		.ntc_fault_mask = BQ24190_REG_F_NTC_FAULT_MASK,1994		.get_ntc_status = bq24190_charger_get_ntc_status,1995		.set_otg_vbus = bq24190_set_otg_vbus,1996	},1997	[BQ24192i] = {1998		.ichg_array_size = ARRAY_SIZE(bq24190_ccc_ichg_values),1999#ifdef CONFIG_REGULATOR2000		.vbus_desc = &bq24190_vbus_desc,2001#endif2002		.check_chip = bq24190_check_chip,2003		.set_chg_config = bq24190_battery_set_chg_config,2004		.ntc_fault_mask = BQ24190_REG_F_NTC_FAULT_MASK,2005		.get_ntc_status = bq24190_charger_get_ntc_status,2006		.set_otg_vbus = bq24190_set_otg_vbus,2007	},2008	[BQ24196] = {2009		.ichg_array_size = ARRAY_SIZE(bq24190_ccc_ichg_values),2010#ifdef CONFIG_REGULATOR2011		.vbus_desc = &bq24190_vbus_desc,2012#endif2013		.check_chip = bq24190_check_chip,2014		.set_chg_config = bq24190_battery_set_chg_config,2015		.ntc_fault_mask = BQ24190_REG_F_NTC_FAULT_MASK,2016		.get_ntc_status = bq24190_charger_get_ntc_status,2017		.set_otg_vbus = bq24190_set_otg_vbus,2018	},2019	[BQ24296] = {2020		.ichg_array_size = BQ24296_CCC_ICHG_VALUES_LEN,2021#ifdef CONFIG_REGULATOR2022		.vbus_desc = &bq24296_vbus_desc,2023#endif2024		.check_chip = bq24296_check_chip,2025		.set_chg_config = bq24296_battery_set_chg_config,2026		.ntc_fault_mask = BQ24296_REG_F_NTC_FAULT_MASK,2027		.get_ntc_status = bq24296_charger_get_ntc_status,2028		.set_otg_vbus = bq24296_set_otg_vbus,2029	},2030};2031 2032static int bq24190_probe(struct i2c_client *client)2033{2034	const struct i2c_device_id *id = i2c_client_get_device_id(client);2035	struct i2c_adapter *adapter = client->adapter;2036	struct device *dev = &client->dev;2037	struct power_supply_config charger_cfg = {}, battery_cfg = {};2038	struct bq24190_dev_info *bdi;2039	int ret;2040 2041	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {2042		dev_err(dev, "No support for SMBUS_BYTE_DATA\n");2043		return -ENODEV;2044	}2045 2046	bdi = devm_kzalloc(dev, sizeof(*bdi), GFP_KERNEL);2047	if (!bdi) {2048		dev_err(dev, "Can't alloc bdi struct\n");2049		return -ENOMEM;2050	}2051 2052	bdi->client = client;2053	bdi->dev = dev;2054	strscpy(bdi->model_name, id->name, sizeof(bdi->model_name));2055	bdi->info = i2c_get_match_data(client);2056	mutex_init(&bdi->f_reg_lock);2057	bdi->charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST;2058	bdi->f_reg = 0;2059	bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */2060	INIT_DELAYED_WORK(&bdi->input_current_limit_work,2061			  bq24190_input_current_limit_work);2062 2063	i2c_set_clientdata(client, bdi);2064 2065	if (client->irq <= 0) {2066		dev_err(dev, "Can't get irq info\n");2067		return -EINVAL;2068	}2069 2070	bdi->edev = devm_extcon_dev_allocate(dev, bq24190_usb_extcon_cable);2071	if (IS_ERR(bdi->edev))2072		return PTR_ERR(bdi->edev);2073 2074	ret = devm_extcon_dev_register(dev, bdi->edev);2075	if (ret < 0)2076		return ret;2077 2078	pm_runtime_enable(dev);2079	pm_runtime_use_autosuspend(dev);2080	pm_runtime_set_autosuspend_delay(dev, 600);2081	ret = pm_runtime_get_sync(dev);2082	if (ret < 0) {2083		dev_err(dev, "pm_runtime_get failed: %i\n", ret);2084		goto out_pmrt;2085	}2086 2087#ifdef CONFIG_SYSFS2088	bq24190_sysfs_init_attrs();2089	charger_cfg.attr_grp = bq24190_sysfs_groups;2090#endif2091 2092	charger_cfg.drv_data = bdi;2093	charger_cfg.of_node = dev->of_node;2094	charger_cfg.supplied_to = bq24190_charger_supplied_to;2095	charger_cfg.num_supplicants = ARRAY_SIZE(bq24190_charger_supplied_to);2096	bdi->charger = power_supply_register(dev, &bq24190_charger_desc,2097						&charger_cfg);2098	if (IS_ERR(bdi->charger)) {2099		dev_err(dev, "Can't register charger\n");2100		ret = PTR_ERR(bdi->charger);2101		goto out_pmrt;2102	}2103 2104	/* the battery class is deprecated and will be removed. */2105	/* in the interim, this property hides it.              */2106	if (!device_property_read_bool(dev, "omit-battery-class")) {2107		battery_cfg.drv_data = bdi;2108		bdi->battery = power_supply_register(dev, &bq24190_battery_desc,2109						     &battery_cfg);2110		if (IS_ERR(bdi->battery)) {2111			dev_err(dev, "Can't register battery\n");2112			ret = PTR_ERR(bdi->battery);2113			goto out_charger;2114		}2115	}2116 2117	ret = bq24190_get_config(bdi);2118	if (ret < 0) {2119		dev_err(dev, "Can't get devicetree config\n");2120		goto out_charger;2121	}2122 2123	ret = bq24190_hw_init(bdi);2124	if (ret < 0) {2125		dev_err(dev, "Hardware init failed\n");2126		goto out_charger;2127	}2128 2129	ret = bq24190_configure_usb_otg(bdi, bdi->ss_reg);2130	if (ret < 0)2131		goto out_charger;2132 2133	bdi->initialized = true;2134 2135	ret = devm_request_threaded_irq(dev, client->irq, NULL,2136			bq24190_irq_handler_thread,2137			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,2138			"bq24190-charger", bdi);2139	if (ret < 0) {2140		dev_err(dev, "Can't set up irq handler\n");2141		goto out_charger;2142	}2143 2144	ret = bq24190_register_vbus_regulator(bdi);2145	if (ret < 0)2146		goto out_charger;2147 2148	enable_irq_wake(client->irq);2149 2150	pm_runtime_mark_last_busy(dev);2151	pm_runtime_put_autosuspend(dev);2152 2153	return 0;2154 2155out_charger:2156	if (!IS_ERR_OR_NULL(bdi->battery))2157		power_supply_unregister(bdi->battery);2158	power_supply_unregister(bdi->charger);2159 2160out_pmrt:2161	pm_runtime_put_sync(dev);2162	pm_runtime_dont_use_autosuspend(dev);2163	pm_runtime_disable(dev);2164	return ret;2165}2166 2167static void bq24190_remove(struct i2c_client *client)2168{2169	struct bq24190_dev_info *bdi = i2c_get_clientdata(client);2170	int error;2171 2172	cancel_delayed_work_sync(&bdi->input_current_limit_work);2173	error = pm_runtime_resume_and_get(bdi->dev);2174	if (error < 0)2175		dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);2176 2177	bq24190_register_reset(bdi);2178	if (bdi->battery)2179		power_supply_unregister(bdi->battery);2180	power_supply_unregister(bdi->charger);2181	if (error >= 0)2182		pm_runtime_put_sync(bdi->dev);2183	pm_runtime_dont_use_autosuspend(bdi->dev);2184	pm_runtime_disable(bdi->dev);2185}2186 2187static void bq24190_shutdown(struct i2c_client *client)2188{2189	struct bq24190_dev_info *bdi = i2c_get_clientdata(client);2190 2191	/* Turn off 5V boost regulator on shutdown */2192	bdi->info->set_otg_vbus(bdi, false);2193}2194 2195static __maybe_unused int bq24190_runtime_suspend(struct device *dev)2196{2197	struct i2c_client *client = to_i2c_client(dev);2198	struct bq24190_dev_info *bdi = i2c_get_clientdata(client);2199 2200	if (!bdi->initialized)2201		return 0;2202 2203	dev_dbg(bdi->dev, "%s\n", __func__);2204 2205	return 0;2206}2207 2208static __maybe_unused int bq24190_runtime_resume(struct device *dev)2209{2210	struct i2c_client *client = to_i2c_client(dev);2211	struct bq24190_dev_info *bdi = i2c_get_clientdata(client);2212 2213	if (!bdi->initialized)2214		return 0;2215 2216	if (!bdi->irq_event) {2217		dev_dbg(bdi->dev, "checking events on possible wakeirq\n");2218		bq24190_check_status(bdi);2219	}2220 2221	return 0;2222}2223 2224static __maybe_unused int bq24190_pm_suspend(struct device *dev)2225{2226	struct i2c_client *client = to_i2c_client(dev);2227	struct bq24190_dev_info *bdi = i2c_get_clientdata(client);2228	int error;2229 2230	error = pm_runtime_resume_and_get(bdi->dev);2231	if (error < 0)2232		dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);2233 2234	bq24190_register_reset(bdi);2235 2236	if (error >= 0) {2237		pm_runtime_mark_last_busy(bdi->dev);2238		pm_runtime_put_autosuspend(bdi->dev);2239	}2240 2241	return 0;2242}2243 2244static __maybe_unused int bq24190_pm_resume(struct device *dev)2245{2246	struct i2c_client *client = to_i2c_client(dev);2247	struct bq24190_dev_info *bdi = i2c_get_clientdata(client);2248	int error;2249 2250	bdi->f_reg = 0;2251	bdi->ss_reg = BQ24190_REG_SS_VBUS_STAT_MASK; /* impossible state */2252 2253	error = pm_runtime_resume_and_get(bdi->dev);2254	if (error < 0)2255		dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);2256 2257	bq24190_register_reset(bdi);2258	bq24190_set_config(bdi);2259	bq24190_read(bdi, BQ24190_REG_SS, &bdi->ss_reg);2260 2261	if (error >= 0) {2262		pm_runtime_mark_last_busy(bdi->dev);2263		pm_runtime_put_autosuspend(bdi->dev);2264	}2265 2266	/* Things may have changed while suspended so alert upper layer */2267	power_supply_changed(bdi->charger);2268	if (bdi->battery)2269		power_supply_changed(bdi->battery);2270 2271	return 0;2272}2273 2274static const struct dev_pm_ops bq24190_pm_ops = {2275	SET_RUNTIME_PM_OPS(bq24190_runtime_suspend, bq24190_runtime_resume,2276			   NULL)2277	SET_SYSTEM_SLEEP_PM_OPS(bq24190_pm_suspend, bq24190_pm_resume)2278};2279 2280static const struct i2c_device_id bq24190_i2c_ids[] = {2281	{ "bq24190", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24190] },2282	{ "bq24192", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192] },2283	{ "bq24192i", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24192i] },2284	{ "bq24196", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24196] },2285	{ "bq24296", (kernel_ulong_t)&bq24190_chip_info_tbl[BQ24296] },2286	{ },2287};2288MODULE_DEVICE_TABLE(i2c, bq24190_i2c_ids);2289 2290static const struct of_device_id bq24190_of_match[] = {2291	{ .compatible = "ti,bq24190", .data = &bq24190_chip_info_tbl[BQ24190] },2292	{ .compatible = "ti,bq24192", .data = &bq24190_chip_info_tbl[BQ24192] },2293	{ .compatible = "ti,bq24192i", .data = &bq24190_chip_info_tbl[BQ24192i] },2294	{ .compatible = "ti,bq24196", .data = &bq24190_chip_info_tbl[BQ24196] },2295	{ .compatible = "ti,bq24296", .data = &bq24190_chip_info_tbl[BQ24296] },2296	{ },2297};2298MODULE_DEVICE_TABLE(of, bq24190_of_match);2299 2300static struct i2c_driver bq24190_driver = {2301	.probe		= bq24190_probe,2302	.remove		= bq24190_remove,2303	.shutdown	= bq24190_shutdown,2304	.id_table	= bq24190_i2c_ids,2305	.driver = {2306		.name		= "bq24190-charger",2307		.pm		= &bq24190_pm_ops,2308		.of_match_table	= bq24190_of_match,2309	},2310};2311module_i2c_driver(bq24190_driver);2312 2313MODULE_LICENSE("GPL");2314MODULE_AUTHOR("Mark A. Greer <mgreer@animalcreek.com>");2315MODULE_DESCRIPTION("TI BQ24190 Charger Driver");2316