cachepc-linux

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

ltc4162-l-charger.c (23555B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Driver for Analog Devices (Linear Technology) LTC4162-L charger IC.
      4 *  Copyright (C) 2020, Topic Embedded Products
      5 */
      6
      7#include <linux/module.h>
      8#include <linux/delay.h>
      9#include <linux/of_device.h>
     10#include <linux/pm_runtime.h>
     11#include <linux/power_supply.h>
     12#include <linux/i2c.h>
     13#include <linux/regmap.h>
     14
     15/* Registers (names based on what datasheet uses) */
     16#define LTC4162L_EN_LIMIT_ALERTS_REG		0x0D
     17#define LTC4162L_EN_CHARGER_STATE_ALERTS_REG	0x0E
     18#define LTC4162L_EN_CHARGE_STATUS_ALERTS_REG	0x0F
     19#define LTC4162L_CONFIG_BITS_REG		0x14
     20#define LTC4162L_IIN_LIMIT_TARGET		0x15
     21#define LTC4162L_ARM_SHIP_MODE			0x19
     22#define LTC4162L_CHARGE_CURRENT_SETTING		0X1A
     23#define LTC4162L_VCHARGE_SETTING		0X1B
     24#define LTC4162L_C_OVER_X_THRESHOLD		0x1C
     25#define LTC4162L_MAX_CV_TIME			0X1D
     26#define LTC4162L_MAX_CHARGE_TIME		0X1E
     27#define LTC4162L_CHARGER_CONFIG_BITS		0x29
     28#define LTC4162L_CHARGER_STATE			0x34
     29#define LTC4162L_CHARGE_STATUS			0x35
     30#define LTC4162L_LIMIT_ALERTS_REG		0x36
     31#define LTC4162L_CHARGER_STATE_ALERTS_REG	0x37
     32#define LTC4162L_CHARGE_STATUS_ALERTS_REG	0x38
     33#define LTC4162L_SYSTEM_STATUS_REG		0x39
     34#define LTC4162L_VBAT				0x3A
     35#define LTC4162L_VIN				0x3B
     36#define LTC4162L_VOUT				0x3C
     37#define LTC4162L_IBAT				0x3D
     38#define LTC4162L_IIN				0x3E
     39#define LTC4162L_DIE_TEMPERATURE		0x3F
     40#define LTC4162L_THERMISTOR_VOLTAGE		0x40
     41#define LTC4162L_BSR				0x41
     42#define LTC4162L_JEITA_REGION			0x42
     43#define LTC4162L_CHEM_CELLS_REG			0x43
     44#define LTC4162L_ICHARGE_DAC			0x44
     45#define LTC4162L_VCHARGE_DAC			0x45
     46#define LTC4162L_IIN_LIMIT_DAC			0x46
     47#define LTC4162L_VBAT_FILT			0x47
     48#define LTC4162L_INPUT_UNDERVOLTAGE_DAC		0x4B
     49
     50/* Enumeration as in datasheet. Individual bits are mutually exclusive. */
     51enum ltc4162l_state {
     52	battery_detection = 2048,
     53	charger_suspended = 256,
     54	precharge = 128,   /* trickle on low bat voltage */
     55	cc_cv_charge = 64, /* normal charge */
     56	ntc_pause = 32,
     57	timer_term = 16,
     58	c_over_x_term = 8, /* battery is full */
     59	max_charge_time_fault = 4,
     60	bat_missing_fault = 2,
     61	bat_short_fault = 1
     62};
     63
     64/* Individual bits are mutually exclusive. Only active in charging states.*/
     65enum ltc4162l_charge_status {
     66	ilim_reg_active = 32,
     67	thermal_reg_active = 16,
     68	vin_uvcl_active = 8,
     69	iin_limit_active = 4,
     70	constant_current = 2,
     71	constant_voltage = 1,
     72	charger_off = 0
     73};
     74
     75/* Magic number to write to ARM_SHIP_MODE register */
     76#define LTC4162L_ARM_SHIP_MODE_MAGIC 21325
     77
     78struct ltc4162l_info {
     79	struct i2c_client	*client;
     80	struct regmap		*regmap;
     81	struct power_supply	*charger;
     82	u32 rsnsb;	/* Series resistor that sets charge current, microOhm */
     83	u32 rsnsi;	/* Series resistor to measure input current, microOhm */
     84	u8 cell_count;	/* Number of connected cells, 0 while unknown */
     85};
     86
     87static u8 ltc4162l_get_cell_count(struct ltc4162l_info *info)
     88{
     89	int ret;
     90	unsigned int val;
     91
     92	/* Once read successfully */
     93	if (info->cell_count)
     94		return info->cell_count;
     95
     96	ret = regmap_read(info->regmap, LTC4162L_CHEM_CELLS_REG, &val);
     97	if (ret)
     98		return 0;
     99
    100	/* Lower 4 bits is the cell count, or 0 if the chip doesn't know yet */
    101	val &= 0x0f;
    102	if (!val)
    103		return 0;
    104
    105	/* Once determined, keep the value */
    106	info->cell_count = val;
    107
    108	return val;
    109};
    110
    111/* Convert enum value to POWER_SUPPLY_STATUS value */
    112static int ltc4162l_state_decode(enum ltc4162l_state value)
    113{
    114	switch (value) {
    115	case precharge:
    116	case cc_cv_charge:
    117		return POWER_SUPPLY_STATUS_CHARGING;
    118	case c_over_x_term:
    119		return POWER_SUPPLY_STATUS_FULL;
    120	case bat_missing_fault:
    121	case bat_short_fault:
    122		return POWER_SUPPLY_STATUS_UNKNOWN;
    123	default:
    124		return POWER_SUPPLY_STATUS_NOT_CHARGING;
    125	}
    126};
    127
    128static int ltc4162l_get_status(struct ltc4162l_info *info,
    129			       union power_supply_propval *val)
    130{
    131	unsigned int regval;
    132	int ret;
    133
    134	ret = regmap_read(info->regmap, LTC4162L_CHARGER_STATE, &regval);
    135	if (ret) {
    136		dev_err(&info->client->dev, "Failed to read CHARGER_STATE\n");
    137		return ret;
    138	}
    139
    140	val->intval = ltc4162l_state_decode(regval);
    141
    142	return 0;
    143}
    144
    145static int ltc4162l_charge_status_decode(enum ltc4162l_charge_status value)
    146{
    147	if (!value)
    148		return POWER_SUPPLY_CHARGE_TYPE_NONE;
    149
    150	/* constant voltage/current and input_current limit are "fast" modes */
    151	if (value <= iin_limit_active)
    152		return POWER_SUPPLY_CHARGE_TYPE_FAST;
    153
    154	/* Anything that's not fast we'll return as trickle */
    155	return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
    156}
    157
    158static int ltc4162l_get_charge_type(struct ltc4162l_info *info,
    159				    union power_supply_propval *val)
    160{
    161	unsigned int regval;
    162	int ret;
    163
    164	ret = regmap_read(info->regmap, LTC4162L_CHARGE_STATUS, &regval);
    165	if (ret)
    166		return ret;
    167
    168	val->intval = ltc4162l_charge_status_decode(regval);
    169
    170	return 0;
    171}
    172
    173static int ltc4162l_state_to_health(enum ltc4162l_state value)
    174{
    175	switch (value) {
    176	case ntc_pause:
    177		return POWER_SUPPLY_HEALTH_OVERHEAT;
    178	case timer_term:
    179		return POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
    180	case max_charge_time_fault:
    181		return POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE;
    182	case bat_missing_fault:
    183		return POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
    184	case bat_short_fault:
    185		return POWER_SUPPLY_HEALTH_DEAD;
    186	default:
    187		return POWER_SUPPLY_HEALTH_GOOD;
    188	}
    189}
    190
    191static int ltc4162l_get_health(struct ltc4162l_info *info,
    192			       union power_supply_propval *val)
    193{
    194	unsigned int regval;
    195	int ret;
    196
    197	ret = regmap_read(info->regmap, LTC4162L_CHARGER_STATE, &regval);
    198	if (ret)
    199		return ret;
    200
    201	val->intval = ltc4162l_state_to_health(regval);
    202
    203	return 0;
    204}
    205
    206static int ltc4162l_get_online(struct ltc4162l_info *info,
    207			       union power_supply_propval *val)
    208{
    209	unsigned int regval;
    210	int ret;
    211
    212	ret = regmap_read(info->regmap, LTC4162L_SYSTEM_STATUS_REG, &regval);
    213	if (ret)
    214		return ret;
    215
    216	/* BIT(2) indicates if input voltage is sufficient to charge */
    217	val->intval = !!(regval & BIT(2));
    218
    219	return 0;
    220}
    221
    222static int ltc4162l_get_vbat(struct ltc4162l_info *info,
    223				  unsigned int reg,
    224				  union power_supply_propval *val)
    225{
    226	unsigned int regval;
    227	int ret;
    228
    229	ret = regmap_read(info->regmap, reg, &regval);
    230	if (ret)
    231		return ret;
    232
    233	/* cell_count × 192.4μV/LSB */
    234	regval *= 1924;
    235	regval *= ltc4162l_get_cell_count(info);
    236	regval /= 10;
    237	val->intval = regval;
    238
    239	return 0;
    240}
    241
    242static int ltc4162l_get_ibat(struct ltc4162l_info *info,
    243			     union power_supply_propval *val)
    244{
    245	unsigned int regval;
    246	int ret;
    247
    248	ret = regmap_read(info->regmap, LTC4162L_IBAT, &regval);
    249	if (ret)
    250		return ret;
    251
    252	/* Signed 16-bit number, 1.466μV / RSNSB amperes/LSB. */
    253	ret = (s16)(regval & 0xFFFF);
    254	val->intval = 100 * mult_frac(ret, 14660, (int)info->rsnsb);
    255
    256	return 0;
    257}
    258
    259
    260static int ltc4162l_get_input_voltage(struct ltc4162l_info *info,
    261				      union power_supply_propval *val)
    262{
    263	unsigned int regval;
    264	int ret;
    265
    266	ret = regmap_read(info->regmap, LTC4162L_VIN, &regval);
    267	if (ret)
    268		return ret;
    269
    270	/* 1.649mV/LSB */
    271	val->intval =  regval * 1694;
    272
    273	return 0;
    274}
    275
    276static int ltc4162l_get_input_current(struct ltc4162l_info *info,
    277				      union power_supply_propval *val)
    278{
    279	unsigned int regval;
    280	int ret;
    281
    282	ret = regmap_read(info->regmap, LTC4162L_IIN, &regval);
    283	if (ret)
    284		return ret;
    285
    286	/* Signed 16-bit number, 1.466μV / RSNSI amperes/LSB. */
    287	ret = (s16)(regval & 0xFFFF);
    288	ret *= 14660;
    289	ret /= info->rsnsi;
    290	ret *= 100;
    291
    292	val->intval = ret;
    293
    294	return 0;
    295}
    296
    297static int ltc4162l_get_icharge(struct ltc4162l_info *info,
    298				unsigned int reg,
    299				union power_supply_propval *val)
    300{
    301	unsigned int regval;
    302	int ret;
    303
    304	ret = regmap_read(info->regmap, reg, &regval);
    305	if (ret)
    306		return ret;
    307
    308	regval &= BIT(6) - 1; /* Only the lower 5 bits */
    309
    310	/* The charge current servo level: (icharge_dac + 1) × 1mV/RSNSB */
    311	++regval;
    312	val->intval = 10000u * mult_frac(regval, 100000u, info->rsnsb);
    313
    314	return 0;
    315}
    316
    317static int ltc4162l_set_icharge(struct ltc4162l_info *info,
    318				unsigned int reg,
    319				unsigned int value)
    320{
    321	value = mult_frac(value, info->rsnsb, 100000u);
    322	value /= 10000u;
    323
    324	/* Round to lowest possible */
    325	if (value)
    326		--value;
    327
    328	if (value > 31)
    329		return -EINVAL;
    330
    331	return regmap_write(info->regmap, reg, value);
    332}
    333
    334
    335static int ltc4162l_get_vcharge(struct ltc4162l_info *info,
    336				unsigned int reg,
    337				union power_supply_propval *val)
    338{
    339	unsigned int regval;
    340	int ret;
    341	u32 voltage;
    342
    343	ret = regmap_read(info->regmap, reg, &regval);
    344	if (ret)
    345		return ret;
    346
    347	regval &= BIT(6) - 1; /* Only the lower 5 bits */
    348
    349	/*
    350	 * charge voltage setting can be computed from
    351	 * cell_count × (vcharge_setting × 12.5mV + 3.8125V)
    352	 * where vcharge_setting ranges from 0 to 31 (4.2V max).
    353	 */
    354	voltage = 3812500 + (regval * 12500);
    355	voltage *= ltc4162l_get_cell_count(info);
    356	val->intval = voltage;
    357
    358	return 0;
    359}
    360
    361static int ltc4162l_set_vcharge(struct ltc4162l_info *info,
    362				unsigned int reg,
    363				unsigned int value)
    364{
    365	u8 cell_count = ltc4162l_get_cell_count(info);
    366
    367	if (!cell_count)
    368		return -EBUSY; /* Not available yet, try again later */
    369
    370	value /= cell_count;
    371
    372	if (value < 3812500)
    373		return -EINVAL;
    374
    375	value -= 3812500;
    376	value /= 12500;
    377
    378	if (value > 31)
    379		return -EINVAL;
    380
    381	return regmap_write(info->regmap, reg, value);
    382}
    383
    384static int ltc4162l_get_iin_limit_dac(struct ltc4162l_info *info,
    385				     union power_supply_propval *val)
    386{
    387	unsigned int regval;
    388	int ret;
    389
    390	ret = regmap_read(info->regmap, LTC4162L_IIN_LIMIT_DAC, &regval);
    391	if (ret)
    392		return ret;
    393
    394	regval &= BIT(6) - 1; /* Only 6 bits */
    395
    396	/* (iin_limit_dac + 1) × 500μV / RSNSI */
    397	++regval;
    398	regval *= 5000000u;
    399	regval /= info->rsnsi;
    400	val->intval = 100u * regval;
    401
    402	return 0;
    403}
    404
    405static int ltc4162l_set_iin_limit(struct ltc4162l_info *info,
    406				  unsigned int value)
    407{
    408	unsigned int regval;
    409
    410	regval = mult_frac(value, info->rsnsi, 50000u);
    411	regval /= 10000u;
    412	if (regval)
    413		--regval;
    414	if (regval > 63)
    415		regval = 63;
    416
    417	return regmap_write(info->regmap, LTC4162L_IIN_LIMIT_TARGET, regval);
    418}
    419
    420static int ltc4162l_get_die_temp(struct ltc4162l_info *info,
    421				 union power_supply_propval *val)
    422{
    423	unsigned int regval;
    424	int ret;
    425
    426	ret = regmap_read(info->regmap, LTC4162L_DIE_TEMPERATURE, &regval);
    427	if (ret)
    428		return ret;
    429
    430	/* die_temp × 0.0215°C/LSB - 264.4°C */
    431	ret = (s16)(regval & 0xFFFF);
    432	ret *= 215;
    433	ret /= 100; /* Centidegrees scale */
    434	ret -= 26440;
    435	val->intval = ret;
    436
    437	return 0;
    438}
    439
    440static int ltc4162l_get_term_current(struct ltc4162l_info *info,
    441				     union power_supply_propval *val)
    442{
    443	unsigned int regval;
    444	int ret;
    445
    446	ret = regmap_read(info->regmap, LTC4162L_CHARGER_CONFIG_BITS, &regval);
    447	if (ret)
    448		return ret;
    449
    450	/* Check if C_OVER_X_THRESHOLD is enabled */
    451	if (!(regval & BIT(2))) {
    452		val->intval = 0;
    453		return 0;
    454	}
    455
    456	ret = regmap_read(info->regmap, LTC4162L_C_OVER_X_THRESHOLD, &regval);
    457	if (ret)
    458		return ret;
    459
    460	/* 1.466μV / RSNSB amperes/LSB */
    461	regval *= 14660u;
    462	regval /= info->rsnsb;
    463	val->intval = 100 * regval;
    464
    465	return 0;
    466}
    467
    468static int ltc4162l_set_term_current(struct ltc4162l_info *info,
    469				     unsigned int value)
    470{
    471	int ret;
    472	unsigned int regval;
    473
    474	if (!value) {
    475		/* Disable en_c_over_x_term when set to zero */
    476		return regmap_update_bits(info->regmap,
    477					  LTC4162L_CHARGER_CONFIG_BITS,
    478					  BIT(2), 0);
    479	}
    480
    481	regval = mult_frac(value, info->rsnsb, 14660u);
    482	regval /= 100u;
    483
    484	ret =  regmap_write(info->regmap, LTC4162L_C_OVER_X_THRESHOLD, regval);
    485	if (ret)
    486		return ret;
    487
    488	/* Set en_c_over_x_term after changing the threshold value */
    489	return regmap_update_bits(info->regmap, LTC4162L_CHARGER_CONFIG_BITS,
    490				  BIT(2), BIT(2));
    491}
    492
    493/* Custom properties */
    494static const char * const ltc4162l_charge_status_name[] = {
    495	"ilim_reg_active", /* 32 */
    496	"thermal_reg_active",
    497	"vin_uvcl_active",
    498	"iin_limit_active",
    499	"constant_current",
    500	"constant_voltage",
    501	"charger_off" /* 0 */
    502};
    503
    504static ssize_t charge_status_show(struct device *dev,
    505				  struct device_attribute *attr, char *buf)
    506{
    507	struct power_supply *psy = to_power_supply(dev);
    508	struct ltc4162l_info *info = power_supply_get_drvdata(psy);
    509	const char *result = ltc4162l_charge_status_name[
    510				ARRAY_SIZE(ltc4162l_charge_status_name) - 1];
    511	unsigned int regval;
    512	unsigned int mask;
    513	unsigned int index;
    514	int ret;
    515
    516	ret = regmap_read(info->regmap, LTC4162L_CHARGE_STATUS, &regval);
    517	if (ret)
    518		return ret;
    519
    520	/* Only one bit is set according to datasheet, let's be safe here */
    521	for (mask = 32, index = 0; mask != 0; mask >>= 1, ++index) {
    522		if (regval & mask) {
    523			result = ltc4162l_charge_status_name[index];
    524			break;
    525		}
    526	}
    527
    528	return sprintf(buf, "%s\n", result);
    529}
    530static DEVICE_ATTR_RO(charge_status);
    531
    532static ssize_t vbat_show(struct device *dev,
    533				  struct device_attribute *attr, char *buf)
    534{
    535	struct power_supply *psy = to_power_supply(dev);
    536	struct ltc4162l_info *info = power_supply_get_drvdata(psy);
    537	union power_supply_propval val;
    538	int ret;
    539
    540	ret = ltc4162l_get_vbat(info, LTC4162L_VBAT, &val);
    541	if (ret)
    542		return ret;
    543
    544	return sprintf(buf, "%d\n", val.intval);
    545}
    546static DEVICE_ATTR_RO(vbat);
    547
    548static ssize_t vbat_avg_show(struct device *dev,
    549				  struct device_attribute *attr, char *buf)
    550{
    551	struct power_supply *psy = to_power_supply(dev);
    552	struct ltc4162l_info *info = power_supply_get_drvdata(psy);
    553	union power_supply_propval val;
    554	int ret;
    555
    556	ret = ltc4162l_get_vbat(info, LTC4162L_VBAT_FILT, &val);
    557	if (ret)
    558		return ret;
    559
    560	return sprintf(buf, "%d\n", val.intval);
    561}
    562static DEVICE_ATTR_RO(vbat_avg);
    563
    564static ssize_t ibat_show(struct device *dev,
    565				  struct device_attribute *attr, char *buf)
    566{
    567	struct power_supply *psy = to_power_supply(dev);
    568	struct ltc4162l_info *info = power_supply_get_drvdata(psy);
    569	union power_supply_propval val;
    570	int ret;
    571
    572	ret = ltc4162l_get_ibat(info, &val);
    573	if (ret)
    574		return ret;
    575
    576	return sprintf(buf, "%d\n", val.intval);
    577}
    578static DEVICE_ATTR_RO(ibat);
    579
    580static ssize_t force_telemetry_show(struct device *dev,
    581				    struct device_attribute *attr, char *buf)
    582{
    583	struct power_supply *psy = to_power_supply(dev);
    584	struct ltc4162l_info *info = power_supply_get_drvdata(psy);
    585	unsigned int regval;
    586	int ret;
    587
    588	ret = regmap_read(info->regmap, LTC4162L_CONFIG_BITS_REG, &regval);
    589	if (ret)
    590		return ret;
    591
    592	return sprintf(buf, "%u\n", regval & BIT(2) ? 1 : 0);
    593}
    594
    595static ssize_t force_telemetry_store(struct device *dev,
    596	struct device_attribute *attr,
    597	const char *buf,
    598	size_t count)
    599{
    600	struct power_supply *psy = to_power_supply(dev);
    601	struct ltc4162l_info *info = power_supply_get_drvdata(psy);
    602	int ret;
    603	unsigned int value;
    604
    605	ret = kstrtouint(buf, 0, &value);
    606	if (ret < 0)
    607		return ret;
    608
    609	ret = regmap_update_bits(info->regmap, LTC4162L_CONFIG_BITS_REG,
    610				 BIT(2), value ? BIT(2) : 0);
    611	if (ret < 0)
    612		return ret;
    613
    614	return count;
    615}
    616
    617static DEVICE_ATTR_RW(force_telemetry);
    618
    619static ssize_t arm_ship_mode_show(struct device *dev,
    620				    struct device_attribute *attr, char *buf)
    621{
    622	struct power_supply *psy = to_power_supply(dev);
    623	struct ltc4162l_info *info = power_supply_get_drvdata(psy);
    624	unsigned int regval;
    625	int ret;
    626
    627	ret = regmap_read(info->regmap, LTC4162L_ARM_SHIP_MODE, &regval);
    628	if (ret)
    629		return ret;
    630
    631	return sprintf(buf, "%u\n",
    632		regval == LTC4162L_ARM_SHIP_MODE_MAGIC ? 1 : 0);
    633}
    634
    635static ssize_t arm_ship_mode_store(struct device *dev,
    636	struct device_attribute *attr,
    637	const char *buf,
    638	size_t count)
    639{
    640	struct power_supply *psy = to_power_supply(dev);
    641	struct ltc4162l_info *info = power_supply_get_drvdata(psy);
    642	int ret;
    643	unsigned int value;
    644
    645	ret = kstrtouint(buf, 0, &value);
    646	if (ret < 0)
    647		return ret;
    648
    649	ret = regmap_write(info->regmap, LTC4162L_ARM_SHIP_MODE,
    650				value ? LTC4162L_ARM_SHIP_MODE_MAGIC : 0);
    651	if (ret < 0)
    652		return ret;
    653
    654	return count;
    655}
    656
    657static DEVICE_ATTR_RW(arm_ship_mode);
    658
    659static struct attribute *ltc4162l_sysfs_entries[] = {
    660	&dev_attr_charge_status.attr,
    661	&dev_attr_ibat.attr,
    662	&dev_attr_vbat.attr,
    663	&dev_attr_vbat_avg.attr,
    664	&dev_attr_force_telemetry.attr,
    665	&dev_attr_arm_ship_mode.attr,
    666	NULL,
    667};
    668
    669static const struct attribute_group ltc4162l_attr_group = {
    670	.name	= NULL,	/* put in device directory */
    671	.attrs	= ltc4162l_sysfs_entries,
    672};
    673
    674static const struct attribute_group *ltc4162l_attr_groups[] = {
    675	&ltc4162l_attr_group,
    676	NULL,
    677};
    678
    679static int ltc4162l_get_property(struct power_supply *psy,
    680				 enum power_supply_property psp,
    681				 union power_supply_propval *val)
    682{
    683	struct ltc4162l_info *info = power_supply_get_drvdata(psy);
    684
    685	switch (psp) {
    686	case POWER_SUPPLY_PROP_STATUS:
    687		return ltc4162l_get_status(info, val);
    688	case POWER_SUPPLY_PROP_CHARGE_TYPE:
    689		return ltc4162l_get_charge_type(info, val);
    690	case POWER_SUPPLY_PROP_HEALTH:
    691		return ltc4162l_get_health(info, val);
    692	case POWER_SUPPLY_PROP_ONLINE:
    693		return ltc4162l_get_online(info, val);
    694	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
    695		return ltc4162l_get_input_voltage(info, val);
    696	case POWER_SUPPLY_PROP_CURRENT_NOW:
    697		return ltc4162l_get_input_current(info, val);
    698	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
    699		return ltc4162l_get_icharge(info,
    700				LTC4162L_ICHARGE_DAC, val);
    701	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
    702		return ltc4162l_get_icharge(info,
    703				LTC4162L_CHARGE_CURRENT_SETTING, val);
    704	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
    705		return ltc4162l_get_vcharge(info,
    706				LTC4162L_VCHARGE_DAC, val);
    707	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
    708		return ltc4162l_get_vcharge(info,
    709				LTC4162L_VCHARGE_SETTING, val);
    710	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
    711		return ltc4162l_get_iin_limit_dac(info, val);
    712	case POWER_SUPPLY_PROP_TEMP:
    713		return ltc4162l_get_die_temp(info, val);
    714	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
    715		return ltc4162l_get_term_current(info, val);
    716	default:
    717		return -EINVAL;
    718	}
    719}
    720
    721static int ltc4162l_set_property(struct power_supply *psy,
    722					 enum power_supply_property psp,
    723					 const union power_supply_propval *val)
    724{
    725	struct ltc4162l_info *info = power_supply_get_drvdata(psy);
    726
    727	switch (psp) {
    728	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
    729		return ltc4162l_set_icharge(info,
    730				LTC4162L_CHARGE_CURRENT_SETTING, val->intval);
    731	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
    732		return ltc4162l_set_vcharge(info,
    733				LTC4162L_VCHARGE_SETTING, val->intval);
    734	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
    735		return ltc4162l_set_iin_limit(info, val->intval);
    736	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
    737		return ltc4162l_set_term_current(info, val->intval);
    738	default:
    739		return -EINVAL;
    740	}
    741}
    742
    743static int ltc4162l_property_is_writeable(struct power_supply *psy,
    744						enum power_supply_property psp)
    745{
    746	switch (psp) {
    747	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
    748	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
    749	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
    750	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
    751		return 1;
    752	default:
    753		return 0;
    754	}
    755}
    756
    757/* Charger power supply property routines */
    758static enum power_supply_property ltc4162l_properties[] = {
    759	POWER_SUPPLY_PROP_STATUS,
    760	POWER_SUPPLY_PROP_CHARGE_TYPE,
    761	POWER_SUPPLY_PROP_HEALTH,
    762	POWER_SUPPLY_PROP_ONLINE,
    763	POWER_SUPPLY_PROP_VOLTAGE_NOW,
    764	POWER_SUPPLY_PROP_CURRENT_NOW,
    765	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
    766	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
    767	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
    768	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
    769	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
    770	POWER_SUPPLY_PROP_TEMP,
    771	POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
    772};
    773
    774static const struct power_supply_desc ltc4162l_desc = {
    775	.name		= "ltc4162-l",
    776	.type		= POWER_SUPPLY_TYPE_MAINS,
    777	.properties	= ltc4162l_properties,
    778	.num_properties	= ARRAY_SIZE(ltc4162l_properties),
    779	.get_property	= ltc4162l_get_property,
    780	.set_property	= ltc4162l_set_property,
    781	.property_is_writeable = ltc4162l_property_is_writeable,
    782};
    783
    784static bool ltc4162l_is_writeable_reg(struct device *dev, unsigned int reg)
    785{
    786	/* all registers up to this one are writeable */
    787	if (reg <= LTC4162L_CHARGER_CONFIG_BITS)
    788		return true;
    789
    790	/* The ALERTS registers can be written to clear alerts */
    791	if (reg >= LTC4162L_LIMIT_ALERTS_REG &&
    792	    reg <= LTC4162L_CHARGE_STATUS_ALERTS_REG)
    793		return true;
    794
    795	return false;
    796}
    797
    798static bool ltc4162l_is_volatile_reg(struct device *dev, unsigned int reg)
    799{
    800	/* all registers after this one are read-only status registers */
    801	return reg > LTC4162L_CHARGER_CONFIG_BITS;
    802}
    803
    804static const struct regmap_config ltc4162l_regmap_config = {
    805	.reg_bits	= 8,
    806	.val_bits	= 16,
    807	.val_format_endian = REGMAP_ENDIAN_LITTLE,
    808	.writeable_reg	= ltc4162l_is_writeable_reg,
    809	.volatile_reg	= ltc4162l_is_volatile_reg,
    810	.max_register	= LTC4162L_INPUT_UNDERVOLTAGE_DAC,
    811	.cache_type	= REGCACHE_RBTREE,
    812};
    813
    814static void ltc4162l_clear_interrupts(struct ltc4162l_info *info)
    815{
    816	/* Acknowledge interrupt to chip by clearing all events */
    817	regmap_write(info->regmap, LTC4162L_LIMIT_ALERTS_REG, 0);
    818	regmap_write(info->regmap, LTC4162L_CHARGER_STATE_ALERTS_REG, 0);
    819	regmap_write(info->regmap, LTC4162L_CHARGE_STATUS_ALERTS_REG, 0);
    820}
    821
    822static int ltc4162l_probe(struct i2c_client *client,
    823			const struct i2c_device_id *id)
    824{
    825	struct i2c_adapter *adapter = client->adapter;
    826	struct device *dev = &client->dev;
    827	struct ltc4162l_info *info;
    828	struct power_supply_config ltc4162l_config = {};
    829	u32 value;
    830	int ret;
    831
    832	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
    833		dev_err(dev, "No support for SMBUS_WORD_DATA\n");
    834		return -ENODEV;
    835	}
    836	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
    837	if (!info)
    838		return -ENOMEM;
    839
    840	info->client = client;
    841	i2c_set_clientdata(client, info);
    842
    843	info->regmap = devm_regmap_init_i2c(client, &ltc4162l_regmap_config);
    844	if (IS_ERR(info->regmap)) {
    845		dev_err(dev, "Failed to initialize register map\n");
    846		return PTR_ERR(info->regmap);
    847	}
    848
    849	ret = device_property_read_u32(dev, "lltc,rsnsb-micro-ohms",
    850				       &info->rsnsb);
    851	if (ret) {
    852		dev_err(dev, "Missing lltc,rsnsb-micro-ohms property\n");
    853		return ret;
    854	}
    855	if (!info->rsnsb)
    856		return -EINVAL;
    857
    858	ret = device_property_read_u32(dev, "lltc,rsnsi-micro-ohms",
    859				       &info->rsnsi);
    860	if (ret) {
    861		dev_err(dev, "Missing lltc,rsnsi-micro-ohms property\n");
    862		return ret;
    863	}
    864	if (!info->rsnsi)
    865		return -EINVAL;
    866
    867	if (!device_property_read_u32(dev, "lltc,cell-count", &value))
    868		info->cell_count = value;
    869
    870	ltc4162l_config.of_node = dev->of_node;
    871	ltc4162l_config.drv_data = info;
    872	ltc4162l_config.attr_grp = ltc4162l_attr_groups;
    873
    874	info->charger = devm_power_supply_register(dev, &ltc4162l_desc,
    875						   &ltc4162l_config);
    876	if (IS_ERR(info->charger)) {
    877		dev_err(dev, "Failed to register charger\n");
    878		return PTR_ERR(info->charger);
    879	}
    880
    881	/* Disable the threshold alerts, we're not using them */
    882	regmap_write(info->regmap, LTC4162L_EN_LIMIT_ALERTS_REG, 0);
    883
    884	/* Enable interrupts on all status changes */
    885	regmap_write(info->regmap, LTC4162L_EN_CHARGER_STATE_ALERTS_REG,
    886		     0x1fff);
    887	regmap_write(info->regmap, LTC4162L_EN_CHARGE_STATUS_ALERTS_REG, 0x1f);
    888
    889	ltc4162l_clear_interrupts(info);
    890
    891	return 0;
    892}
    893
    894static void ltc4162l_alert(struct i2c_client *client,
    895			   enum i2c_alert_protocol type, unsigned int flag)
    896{
    897	struct ltc4162l_info *info = i2c_get_clientdata(client);
    898
    899	if (type != I2C_PROTOCOL_SMBUS_ALERT)
    900		return;
    901
    902	ltc4162l_clear_interrupts(info);
    903	power_supply_changed(info->charger);
    904}
    905
    906static const struct i2c_device_id ltc4162l_i2c_id_table[] = {
    907	{ "ltc4162-l", 0 },
    908	{ },
    909};
    910MODULE_DEVICE_TABLE(i2c, ltc4162l_i2c_id_table);
    911
    912static const struct of_device_id ltc4162l_of_match[] = {
    913	{ .compatible = "lltc,ltc4162-l", },
    914	{ },
    915};
    916MODULE_DEVICE_TABLE(of, ltc4162l_of_match);
    917
    918static struct i2c_driver ltc4162l_driver = {
    919	.probe		= ltc4162l_probe,
    920	.alert		= ltc4162l_alert,
    921	.id_table	= ltc4162l_i2c_id_table,
    922	.driver = {
    923		.name		= "ltc4162-l-charger",
    924		.of_match_table	= of_match_ptr(ltc4162l_of_match),
    925	},
    926};
    927module_i2c_driver(ltc4162l_driver);
    928
    929MODULE_LICENSE("GPL");
    930MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
    931MODULE_DESCRIPTION("LTC4162-L charger driver");