0001
0002
0003
0004
0005
0006
0007 #include <linux/module.h>
0008 #include <linux/delay.h>
0009 #include <linux/of_device.h>
0010 #include <linux/pm_runtime.h>
0011 #include <linux/power_supply.h>
0012 #include <linux/i2c.h>
0013 #include <linux/regmap.h>
0014
0015
0016 #define LTC4162L_EN_LIMIT_ALERTS_REG 0x0D
0017 #define LTC4162L_EN_CHARGER_STATE_ALERTS_REG 0x0E
0018 #define LTC4162L_EN_CHARGE_STATUS_ALERTS_REG 0x0F
0019 #define LTC4162L_CONFIG_BITS_REG 0x14
0020 #define LTC4162L_IIN_LIMIT_TARGET 0x15
0021 #define LTC4162L_ARM_SHIP_MODE 0x19
0022 #define LTC4162L_CHARGE_CURRENT_SETTING 0X1A
0023 #define LTC4162L_VCHARGE_SETTING 0X1B
0024 #define LTC4162L_C_OVER_X_THRESHOLD 0x1C
0025 #define LTC4162L_MAX_CV_TIME 0X1D
0026 #define LTC4162L_MAX_CHARGE_TIME 0X1E
0027 #define LTC4162L_CHARGER_CONFIG_BITS 0x29
0028 #define LTC4162L_CHARGER_STATE 0x34
0029 #define LTC4162L_CHARGE_STATUS 0x35
0030 #define LTC4162L_LIMIT_ALERTS_REG 0x36
0031 #define LTC4162L_CHARGER_STATE_ALERTS_REG 0x37
0032 #define LTC4162L_CHARGE_STATUS_ALERTS_REG 0x38
0033 #define LTC4162L_SYSTEM_STATUS_REG 0x39
0034 #define LTC4162L_VBAT 0x3A
0035 #define LTC4162L_VIN 0x3B
0036 #define LTC4162L_VOUT 0x3C
0037 #define LTC4162L_IBAT 0x3D
0038 #define LTC4162L_IIN 0x3E
0039 #define LTC4162L_DIE_TEMPERATURE 0x3F
0040 #define LTC4162L_THERMISTOR_VOLTAGE 0x40
0041 #define LTC4162L_BSR 0x41
0042 #define LTC4162L_JEITA_REGION 0x42
0043 #define LTC4162L_CHEM_CELLS_REG 0x43
0044 #define LTC4162L_ICHARGE_DAC 0x44
0045 #define LTC4162L_VCHARGE_DAC 0x45
0046 #define LTC4162L_IIN_LIMIT_DAC 0x46
0047 #define LTC4162L_VBAT_FILT 0x47
0048 #define LTC4162L_INPUT_UNDERVOLTAGE_DAC 0x4B
0049
0050
0051 enum ltc4162l_state {
0052 battery_detection = 2048,
0053 charger_suspended = 256,
0054 precharge = 128,
0055 cc_cv_charge = 64,
0056 ntc_pause = 32,
0057 timer_term = 16,
0058 c_over_x_term = 8,
0059 max_charge_time_fault = 4,
0060 bat_missing_fault = 2,
0061 bat_short_fault = 1
0062 };
0063
0064
0065 enum ltc4162l_charge_status {
0066 ilim_reg_active = 32,
0067 thermal_reg_active = 16,
0068 vin_uvcl_active = 8,
0069 iin_limit_active = 4,
0070 constant_current = 2,
0071 constant_voltage = 1,
0072 charger_off = 0
0073 };
0074
0075
0076 #define LTC4162L_ARM_SHIP_MODE_MAGIC 21325
0077
0078 struct ltc4162l_info {
0079 struct i2c_client *client;
0080 struct regmap *regmap;
0081 struct power_supply *charger;
0082 u32 rsnsb;
0083 u32 rsnsi;
0084 u8 cell_count;
0085 };
0086
0087 static u8 ltc4162l_get_cell_count(struct ltc4162l_info *info)
0088 {
0089 int ret;
0090 unsigned int val;
0091
0092
0093 if (info->cell_count)
0094 return info->cell_count;
0095
0096 ret = regmap_read(info->regmap, LTC4162L_CHEM_CELLS_REG, &val);
0097 if (ret)
0098 return 0;
0099
0100
0101 val &= 0x0f;
0102 if (!val)
0103 return 0;
0104
0105
0106 info->cell_count = val;
0107
0108 return val;
0109 };
0110
0111
0112 static int ltc4162l_state_decode(enum ltc4162l_state value)
0113 {
0114 switch (value) {
0115 case precharge:
0116 case cc_cv_charge:
0117 return POWER_SUPPLY_STATUS_CHARGING;
0118 case c_over_x_term:
0119 return POWER_SUPPLY_STATUS_FULL;
0120 case bat_missing_fault:
0121 case bat_short_fault:
0122 return POWER_SUPPLY_STATUS_UNKNOWN;
0123 default:
0124 return POWER_SUPPLY_STATUS_NOT_CHARGING;
0125 }
0126 };
0127
0128 static int ltc4162l_get_status(struct ltc4162l_info *info,
0129 union power_supply_propval *val)
0130 {
0131 unsigned int regval;
0132 int ret;
0133
0134 ret = regmap_read(info->regmap, LTC4162L_CHARGER_STATE, ®val);
0135 if (ret) {
0136 dev_err(&info->client->dev, "Failed to read CHARGER_STATE\n");
0137 return ret;
0138 }
0139
0140 val->intval = ltc4162l_state_decode(regval);
0141
0142 return 0;
0143 }
0144
0145 static int ltc4162l_charge_status_decode(enum ltc4162l_charge_status value)
0146 {
0147 if (!value)
0148 return POWER_SUPPLY_CHARGE_TYPE_NONE;
0149
0150
0151 if (value <= iin_limit_active)
0152 return POWER_SUPPLY_CHARGE_TYPE_FAST;
0153
0154
0155 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
0156 }
0157
0158 static int ltc4162l_get_charge_type(struct ltc4162l_info *info,
0159 union power_supply_propval *val)
0160 {
0161 unsigned int regval;
0162 int ret;
0163
0164 ret = regmap_read(info->regmap, LTC4162L_CHARGE_STATUS, ®val);
0165 if (ret)
0166 return ret;
0167
0168 val->intval = ltc4162l_charge_status_decode(regval);
0169
0170 return 0;
0171 }
0172
0173 static int ltc4162l_state_to_health(enum ltc4162l_state value)
0174 {
0175 switch (value) {
0176 case ntc_pause:
0177 return POWER_SUPPLY_HEALTH_OVERHEAT;
0178 case timer_term:
0179 return POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
0180 case max_charge_time_fault:
0181 return POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE;
0182 case bat_missing_fault:
0183 return POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
0184 case bat_short_fault:
0185 return POWER_SUPPLY_HEALTH_DEAD;
0186 default:
0187 return POWER_SUPPLY_HEALTH_GOOD;
0188 }
0189 }
0190
0191 static int ltc4162l_get_health(struct ltc4162l_info *info,
0192 union power_supply_propval *val)
0193 {
0194 unsigned int regval;
0195 int ret;
0196
0197 ret = regmap_read(info->regmap, LTC4162L_CHARGER_STATE, ®val);
0198 if (ret)
0199 return ret;
0200
0201 val->intval = ltc4162l_state_to_health(regval);
0202
0203 return 0;
0204 }
0205
0206 static int ltc4162l_get_online(struct ltc4162l_info *info,
0207 union power_supply_propval *val)
0208 {
0209 unsigned int regval;
0210 int ret;
0211
0212 ret = regmap_read(info->regmap, LTC4162L_SYSTEM_STATUS_REG, ®val);
0213 if (ret)
0214 return ret;
0215
0216
0217 val->intval = !!(regval & BIT(2));
0218
0219 return 0;
0220 }
0221
0222 static int ltc4162l_get_vbat(struct ltc4162l_info *info,
0223 unsigned int reg,
0224 union power_supply_propval *val)
0225 {
0226 unsigned int regval;
0227 int ret;
0228
0229 ret = regmap_read(info->regmap, reg, ®val);
0230 if (ret)
0231 return ret;
0232
0233
0234 regval *= 1924;
0235 regval *= ltc4162l_get_cell_count(info);
0236 regval /= 10;
0237 val->intval = regval;
0238
0239 return 0;
0240 }
0241
0242 static int ltc4162l_get_ibat(struct ltc4162l_info *info,
0243 union power_supply_propval *val)
0244 {
0245 unsigned int regval;
0246 int ret;
0247
0248 ret = regmap_read(info->regmap, LTC4162L_IBAT, ®val);
0249 if (ret)
0250 return ret;
0251
0252
0253 ret = (s16)(regval & 0xFFFF);
0254 val->intval = 100 * mult_frac(ret, 14660, (int)info->rsnsb);
0255
0256 return 0;
0257 }
0258
0259
0260 static int ltc4162l_get_input_voltage(struct ltc4162l_info *info,
0261 union power_supply_propval *val)
0262 {
0263 unsigned int regval;
0264 int ret;
0265
0266 ret = regmap_read(info->regmap, LTC4162L_VIN, ®val);
0267 if (ret)
0268 return ret;
0269
0270
0271 val->intval = regval * 1694;
0272
0273 return 0;
0274 }
0275
0276 static int ltc4162l_get_input_current(struct ltc4162l_info *info,
0277 union power_supply_propval *val)
0278 {
0279 unsigned int regval;
0280 int ret;
0281
0282 ret = regmap_read(info->regmap, LTC4162L_IIN, ®val);
0283 if (ret)
0284 return ret;
0285
0286
0287 ret = (s16)(regval & 0xFFFF);
0288 ret *= 14660;
0289 ret /= info->rsnsi;
0290 ret *= 100;
0291
0292 val->intval = ret;
0293
0294 return 0;
0295 }
0296
0297 static int ltc4162l_get_icharge(struct ltc4162l_info *info,
0298 unsigned int reg,
0299 union power_supply_propval *val)
0300 {
0301 unsigned int regval;
0302 int ret;
0303
0304 ret = regmap_read(info->regmap, reg, ®val);
0305 if (ret)
0306 return ret;
0307
0308 regval &= BIT(6) - 1;
0309
0310
0311 ++regval;
0312 val->intval = 10000u * mult_frac(regval, 100000u, info->rsnsb);
0313
0314 return 0;
0315 }
0316
0317 static int ltc4162l_set_icharge(struct ltc4162l_info *info,
0318 unsigned int reg,
0319 unsigned int value)
0320 {
0321 value = mult_frac(value, info->rsnsb, 100000u);
0322 value /= 10000u;
0323
0324
0325 if (value)
0326 --value;
0327
0328 if (value > 31)
0329 return -EINVAL;
0330
0331 return regmap_write(info->regmap, reg, value);
0332 }
0333
0334
0335 static int ltc4162l_get_vcharge(struct ltc4162l_info *info,
0336 unsigned int reg,
0337 union power_supply_propval *val)
0338 {
0339 unsigned int regval;
0340 int ret;
0341 u32 voltage;
0342
0343 ret = regmap_read(info->regmap, reg, ®val);
0344 if (ret)
0345 return ret;
0346
0347 regval &= BIT(6) - 1;
0348
0349
0350
0351
0352
0353
0354 voltage = 3812500 + (regval * 12500);
0355 voltage *= ltc4162l_get_cell_count(info);
0356 val->intval = voltage;
0357
0358 return 0;
0359 }
0360
0361 static int ltc4162l_set_vcharge(struct ltc4162l_info *info,
0362 unsigned int reg,
0363 unsigned int value)
0364 {
0365 u8 cell_count = ltc4162l_get_cell_count(info);
0366
0367 if (!cell_count)
0368 return -EBUSY;
0369
0370 value /= cell_count;
0371
0372 if (value < 3812500)
0373 return -EINVAL;
0374
0375 value -= 3812500;
0376 value /= 12500;
0377
0378 if (value > 31)
0379 return -EINVAL;
0380
0381 return regmap_write(info->regmap, reg, value);
0382 }
0383
0384 static int ltc4162l_get_iin_limit_dac(struct ltc4162l_info *info,
0385 union power_supply_propval *val)
0386 {
0387 unsigned int regval;
0388 int ret;
0389
0390 ret = regmap_read(info->regmap, LTC4162L_IIN_LIMIT_DAC, ®val);
0391 if (ret)
0392 return ret;
0393
0394 regval &= BIT(6) - 1;
0395
0396
0397 ++regval;
0398 regval *= 5000000u;
0399 regval /= info->rsnsi;
0400 val->intval = 100u * regval;
0401
0402 return 0;
0403 }
0404
0405 static int ltc4162l_set_iin_limit(struct ltc4162l_info *info,
0406 unsigned int value)
0407 {
0408 unsigned int regval;
0409
0410 regval = mult_frac(value, info->rsnsi, 50000u);
0411 regval /= 10000u;
0412 if (regval)
0413 --regval;
0414 if (regval > 63)
0415 regval = 63;
0416
0417 return regmap_write(info->regmap, LTC4162L_IIN_LIMIT_TARGET, regval);
0418 }
0419
0420 static int ltc4162l_get_die_temp(struct ltc4162l_info *info,
0421 union power_supply_propval *val)
0422 {
0423 unsigned int regval;
0424 int ret;
0425
0426 ret = regmap_read(info->regmap, LTC4162L_DIE_TEMPERATURE, ®val);
0427 if (ret)
0428 return ret;
0429
0430
0431 ret = (s16)(regval & 0xFFFF);
0432 ret *= 215;
0433 ret /= 100;
0434 ret -= 26440;
0435 val->intval = ret;
0436
0437 return 0;
0438 }
0439
0440 static int ltc4162l_get_term_current(struct ltc4162l_info *info,
0441 union power_supply_propval *val)
0442 {
0443 unsigned int regval;
0444 int ret;
0445
0446 ret = regmap_read(info->regmap, LTC4162L_CHARGER_CONFIG_BITS, ®val);
0447 if (ret)
0448 return ret;
0449
0450
0451 if (!(regval & BIT(2))) {
0452 val->intval = 0;
0453 return 0;
0454 }
0455
0456 ret = regmap_read(info->regmap, LTC4162L_C_OVER_X_THRESHOLD, ®val);
0457 if (ret)
0458 return ret;
0459
0460
0461 regval *= 14660u;
0462 regval /= info->rsnsb;
0463 val->intval = 100 * regval;
0464
0465 return 0;
0466 }
0467
0468 static int ltc4162l_set_term_current(struct ltc4162l_info *info,
0469 unsigned int value)
0470 {
0471 int ret;
0472 unsigned int regval;
0473
0474 if (!value) {
0475
0476 return regmap_update_bits(info->regmap,
0477 LTC4162L_CHARGER_CONFIG_BITS,
0478 BIT(2), 0);
0479 }
0480
0481 regval = mult_frac(value, info->rsnsb, 14660u);
0482 regval /= 100u;
0483
0484 ret = regmap_write(info->regmap, LTC4162L_C_OVER_X_THRESHOLD, regval);
0485 if (ret)
0486 return ret;
0487
0488
0489 return regmap_update_bits(info->regmap, LTC4162L_CHARGER_CONFIG_BITS,
0490 BIT(2), BIT(2));
0491 }
0492
0493
0494 static const char * const ltc4162l_charge_status_name[] = {
0495 "ilim_reg_active",
0496 "thermal_reg_active",
0497 "vin_uvcl_active",
0498 "iin_limit_active",
0499 "constant_current",
0500 "constant_voltage",
0501 "charger_off"
0502 };
0503
0504 static ssize_t charge_status_show(struct device *dev,
0505 struct device_attribute *attr, char *buf)
0506 {
0507 struct power_supply *psy = to_power_supply(dev);
0508 struct ltc4162l_info *info = power_supply_get_drvdata(psy);
0509 const char *result = ltc4162l_charge_status_name[
0510 ARRAY_SIZE(ltc4162l_charge_status_name) - 1];
0511 unsigned int regval;
0512 unsigned int mask;
0513 unsigned int index;
0514 int ret;
0515
0516 ret = regmap_read(info->regmap, LTC4162L_CHARGE_STATUS, ®val);
0517 if (ret)
0518 return ret;
0519
0520
0521 for (mask = 32, index = 0; mask != 0; mask >>= 1, ++index) {
0522 if (regval & mask) {
0523 result = ltc4162l_charge_status_name[index];
0524 break;
0525 }
0526 }
0527
0528 return sprintf(buf, "%s\n", result);
0529 }
0530 static DEVICE_ATTR_RO(charge_status);
0531
0532 static ssize_t vbat_show(struct device *dev,
0533 struct device_attribute *attr, char *buf)
0534 {
0535 struct power_supply *psy = to_power_supply(dev);
0536 struct ltc4162l_info *info = power_supply_get_drvdata(psy);
0537 union power_supply_propval val;
0538 int ret;
0539
0540 ret = ltc4162l_get_vbat(info, LTC4162L_VBAT, &val);
0541 if (ret)
0542 return ret;
0543
0544 return sprintf(buf, "%d\n", val.intval);
0545 }
0546 static DEVICE_ATTR_RO(vbat);
0547
0548 static ssize_t vbat_avg_show(struct device *dev,
0549 struct device_attribute *attr, char *buf)
0550 {
0551 struct power_supply *psy = to_power_supply(dev);
0552 struct ltc4162l_info *info = power_supply_get_drvdata(psy);
0553 union power_supply_propval val;
0554 int ret;
0555
0556 ret = ltc4162l_get_vbat(info, LTC4162L_VBAT_FILT, &val);
0557 if (ret)
0558 return ret;
0559
0560 return sprintf(buf, "%d\n", val.intval);
0561 }
0562 static DEVICE_ATTR_RO(vbat_avg);
0563
0564 static ssize_t ibat_show(struct device *dev,
0565 struct device_attribute *attr, char *buf)
0566 {
0567 struct power_supply *psy = to_power_supply(dev);
0568 struct ltc4162l_info *info = power_supply_get_drvdata(psy);
0569 union power_supply_propval val;
0570 int ret;
0571
0572 ret = ltc4162l_get_ibat(info, &val);
0573 if (ret)
0574 return ret;
0575
0576 return sprintf(buf, "%d\n", val.intval);
0577 }
0578 static DEVICE_ATTR_RO(ibat);
0579
0580 static ssize_t force_telemetry_show(struct device *dev,
0581 struct device_attribute *attr, char *buf)
0582 {
0583 struct power_supply *psy = to_power_supply(dev);
0584 struct ltc4162l_info *info = power_supply_get_drvdata(psy);
0585 unsigned int regval;
0586 int ret;
0587
0588 ret = regmap_read(info->regmap, LTC4162L_CONFIG_BITS_REG, ®val);
0589 if (ret)
0590 return ret;
0591
0592 return sprintf(buf, "%u\n", regval & BIT(2) ? 1 : 0);
0593 }
0594
0595 static ssize_t force_telemetry_store(struct device *dev,
0596 struct device_attribute *attr,
0597 const char *buf,
0598 size_t count)
0599 {
0600 struct power_supply *psy = to_power_supply(dev);
0601 struct ltc4162l_info *info = power_supply_get_drvdata(psy);
0602 int ret;
0603 unsigned int value;
0604
0605 ret = kstrtouint(buf, 0, &value);
0606 if (ret < 0)
0607 return ret;
0608
0609 ret = regmap_update_bits(info->regmap, LTC4162L_CONFIG_BITS_REG,
0610 BIT(2), value ? BIT(2) : 0);
0611 if (ret < 0)
0612 return ret;
0613
0614 return count;
0615 }
0616
0617 static DEVICE_ATTR_RW(force_telemetry);
0618
0619 static ssize_t arm_ship_mode_show(struct device *dev,
0620 struct device_attribute *attr, char *buf)
0621 {
0622 struct power_supply *psy = to_power_supply(dev);
0623 struct ltc4162l_info *info = power_supply_get_drvdata(psy);
0624 unsigned int regval;
0625 int ret;
0626
0627 ret = regmap_read(info->regmap, LTC4162L_ARM_SHIP_MODE, ®val);
0628 if (ret)
0629 return ret;
0630
0631 return sprintf(buf, "%u\n",
0632 regval == LTC4162L_ARM_SHIP_MODE_MAGIC ? 1 : 0);
0633 }
0634
0635 static ssize_t arm_ship_mode_store(struct device *dev,
0636 struct device_attribute *attr,
0637 const char *buf,
0638 size_t count)
0639 {
0640 struct power_supply *psy = to_power_supply(dev);
0641 struct ltc4162l_info *info = power_supply_get_drvdata(psy);
0642 int ret;
0643 unsigned int value;
0644
0645 ret = kstrtouint(buf, 0, &value);
0646 if (ret < 0)
0647 return ret;
0648
0649 ret = regmap_write(info->regmap, LTC4162L_ARM_SHIP_MODE,
0650 value ? LTC4162L_ARM_SHIP_MODE_MAGIC : 0);
0651 if (ret < 0)
0652 return ret;
0653
0654 return count;
0655 }
0656
0657 static DEVICE_ATTR_RW(arm_ship_mode);
0658
0659 static struct attribute *ltc4162l_sysfs_entries[] = {
0660 &dev_attr_charge_status.attr,
0661 &dev_attr_ibat.attr,
0662 &dev_attr_vbat.attr,
0663 &dev_attr_vbat_avg.attr,
0664 &dev_attr_force_telemetry.attr,
0665 &dev_attr_arm_ship_mode.attr,
0666 NULL,
0667 };
0668
0669 static const struct attribute_group ltc4162l_attr_group = {
0670 .name = NULL,
0671 .attrs = ltc4162l_sysfs_entries,
0672 };
0673
0674 static const struct attribute_group *ltc4162l_attr_groups[] = {
0675 <c4162l_attr_group,
0676 NULL,
0677 };
0678
0679 static int ltc4162l_get_property(struct power_supply *psy,
0680 enum power_supply_property psp,
0681 union power_supply_propval *val)
0682 {
0683 struct ltc4162l_info *info = power_supply_get_drvdata(psy);
0684
0685 switch (psp) {
0686 case POWER_SUPPLY_PROP_STATUS:
0687 return ltc4162l_get_status(info, val);
0688 case POWER_SUPPLY_PROP_CHARGE_TYPE:
0689 return ltc4162l_get_charge_type(info, val);
0690 case POWER_SUPPLY_PROP_HEALTH:
0691 return ltc4162l_get_health(info, val);
0692 case POWER_SUPPLY_PROP_ONLINE:
0693 return ltc4162l_get_online(info, val);
0694 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
0695 return ltc4162l_get_input_voltage(info, val);
0696 case POWER_SUPPLY_PROP_CURRENT_NOW:
0697 return ltc4162l_get_input_current(info, val);
0698 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
0699 return ltc4162l_get_icharge(info,
0700 LTC4162L_ICHARGE_DAC, val);
0701 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
0702 return ltc4162l_get_icharge(info,
0703 LTC4162L_CHARGE_CURRENT_SETTING, val);
0704 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
0705 return ltc4162l_get_vcharge(info,
0706 LTC4162L_VCHARGE_DAC, val);
0707 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
0708 return ltc4162l_get_vcharge(info,
0709 LTC4162L_VCHARGE_SETTING, val);
0710 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0711 return ltc4162l_get_iin_limit_dac(info, val);
0712 case POWER_SUPPLY_PROP_TEMP:
0713 return ltc4162l_get_die_temp(info, val);
0714 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
0715 return ltc4162l_get_term_current(info, val);
0716 default:
0717 return -EINVAL;
0718 }
0719 }
0720
0721 static int ltc4162l_set_property(struct power_supply *psy,
0722 enum power_supply_property psp,
0723 const union power_supply_propval *val)
0724 {
0725 struct ltc4162l_info *info = power_supply_get_drvdata(psy);
0726
0727 switch (psp) {
0728 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
0729 return ltc4162l_set_icharge(info,
0730 LTC4162L_CHARGE_CURRENT_SETTING, val->intval);
0731 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
0732 return ltc4162l_set_vcharge(info,
0733 LTC4162L_VCHARGE_SETTING, val->intval);
0734 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0735 return ltc4162l_set_iin_limit(info, val->intval);
0736 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
0737 return ltc4162l_set_term_current(info, val->intval);
0738 default:
0739 return -EINVAL;
0740 }
0741 }
0742
0743 static int ltc4162l_property_is_writeable(struct power_supply *psy,
0744 enum power_supply_property psp)
0745 {
0746 switch (psp) {
0747 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
0748 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
0749 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0750 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
0751 return 1;
0752 default:
0753 return 0;
0754 }
0755 }
0756
0757
0758 static enum power_supply_property ltc4162l_properties[] = {
0759 POWER_SUPPLY_PROP_STATUS,
0760 POWER_SUPPLY_PROP_CHARGE_TYPE,
0761 POWER_SUPPLY_PROP_HEALTH,
0762 POWER_SUPPLY_PROP_ONLINE,
0763 POWER_SUPPLY_PROP_VOLTAGE_NOW,
0764 POWER_SUPPLY_PROP_CURRENT_NOW,
0765 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
0766 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
0767 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
0768 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
0769 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
0770 POWER_SUPPLY_PROP_TEMP,
0771 POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
0772 };
0773
0774 static const struct power_supply_desc ltc4162l_desc = {
0775 .name = "ltc4162-l",
0776 .type = POWER_SUPPLY_TYPE_MAINS,
0777 .properties = ltc4162l_properties,
0778 .num_properties = ARRAY_SIZE(ltc4162l_properties),
0779 .get_property = ltc4162l_get_property,
0780 .set_property = ltc4162l_set_property,
0781 .property_is_writeable = ltc4162l_property_is_writeable,
0782 };
0783
0784 static bool ltc4162l_is_writeable_reg(struct device *dev, unsigned int reg)
0785 {
0786
0787 if (reg <= LTC4162L_CHARGER_CONFIG_BITS)
0788 return true;
0789
0790
0791 if (reg >= LTC4162L_LIMIT_ALERTS_REG &&
0792 reg <= LTC4162L_CHARGE_STATUS_ALERTS_REG)
0793 return true;
0794
0795 return false;
0796 }
0797
0798 static bool ltc4162l_is_volatile_reg(struct device *dev, unsigned int reg)
0799 {
0800
0801 return reg > LTC4162L_CHARGER_CONFIG_BITS;
0802 }
0803
0804 static const struct regmap_config ltc4162l_regmap_config = {
0805 .reg_bits = 8,
0806 .val_bits = 16,
0807 .val_format_endian = REGMAP_ENDIAN_LITTLE,
0808 .writeable_reg = ltc4162l_is_writeable_reg,
0809 .volatile_reg = ltc4162l_is_volatile_reg,
0810 .max_register = LTC4162L_INPUT_UNDERVOLTAGE_DAC,
0811 .cache_type = REGCACHE_RBTREE,
0812 };
0813
0814 static void ltc4162l_clear_interrupts(struct ltc4162l_info *info)
0815 {
0816
0817 regmap_write(info->regmap, LTC4162L_LIMIT_ALERTS_REG, 0);
0818 regmap_write(info->regmap, LTC4162L_CHARGER_STATE_ALERTS_REG, 0);
0819 regmap_write(info->regmap, LTC4162L_CHARGE_STATUS_ALERTS_REG, 0);
0820 }
0821
0822 static int ltc4162l_probe(struct i2c_client *client,
0823 const struct i2c_device_id *id)
0824 {
0825 struct i2c_adapter *adapter = client->adapter;
0826 struct device *dev = &client->dev;
0827 struct ltc4162l_info *info;
0828 struct power_supply_config ltc4162l_config = {};
0829 u32 value;
0830 int ret;
0831
0832 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
0833 dev_err(dev, "No support for SMBUS_WORD_DATA\n");
0834 return -ENODEV;
0835 }
0836 info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
0837 if (!info)
0838 return -ENOMEM;
0839
0840 info->client = client;
0841 i2c_set_clientdata(client, info);
0842
0843 info->regmap = devm_regmap_init_i2c(client, <c4162l_regmap_config);
0844 if (IS_ERR(info->regmap)) {
0845 dev_err(dev, "Failed to initialize register map\n");
0846 return PTR_ERR(info->regmap);
0847 }
0848
0849 ret = device_property_read_u32(dev, "lltc,rsnsb-micro-ohms",
0850 &info->rsnsb);
0851 if (ret) {
0852 dev_err(dev, "Missing lltc,rsnsb-micro-ohms property\n");
0853 return ret;
0854 }
0855 if (!info->rsnsb)
0856 return -EINVAL;
0857
0858 ret = device_property_read_u32(dev, "lltc,rsnsi-micro-ohms",
0859 &info->rsnsi);
0860 if (ret) {
0861 dev_err(dev, "Missing lltc,rsnsi-micro-ohms property\n");
0862 return ret;
0863 }
0864 if (!info->rsnsi)
0865 return -EINVAL;
0866
0867 if (!device_property_read_u32(dev, "lltc,cell-count", &value))
0868 info->cell_count = value;
0869
0870 ltc4162l_config.of_node = dev->of_node;
0871 ltc4162l_config.drv_data = info;
0872 ltc4162l_config.attr_grp = ltc4162l_attr_groups;
0873
0874 info->charger = devm_power_supply_register(dev, <c4162l_desc,
0875 <c4162l_config);
0876 if (IS_ERR(info->charger)) {
0877 dev_err(dev, "Failed to register charger\n");
0878 return PTR_ERR(info->charger);
0879 }
0880
0881
0882 regmap_write(info->regmap, LTC4162L_EN_LIMIT_ALERTS_REG, 0);
0883
0884
0885 regmap_write(info->regmap, LTC4162L_EN_CHARGER_STATE_ALERTS_REG,
0886 0x1fff);
0887 regmap_write(info->regmap, LTC4162L_EN_CHARGE_STATUS_ALERTS_REG, 0x1f);
0888
0889 ltc4162l_clear_interrupts(info);
0890
0891 return 0;
0892 }
0893
0894 static void ltc4162l_alert(struct i2c_client *client,
0895 enum i2c_alert_protocol type, unsigned int flag)
0896 {
0897 struct ltc4162l_info *info = i2c_get_clientdata(client);
0898
0899 if (type != I2C_PROTOCOL_SMBUS_ALERT)
0900 return;
0901
0902 ltc4162l_clear_interrupts(info);
0903 power_supply_changed(info->charger);
0904 }
0905
0906 static const struct i2c_device_id ltc4162l_i2c_id_table[] = {
0907 { "ltc4162-l", 0 },
0908 { },
0909 };
0910 MODULE_DEVICE_TABLE(i2c, ltc4162l_i2c_id_table);
0911
0912 static const struct of_device_id ltc4162l_of_match[] = {
0913 { .compatible = "lltc,ltc4162-l", },
0914 { },
0915 };
0916 MODULE_DEVICE_TABLE(of, ltc4162l_of_match);
0917
0918 static struct i2c_driver ltc4162l_driver = {
0919 .probe = ltc4162l_probe,
0920 .alert = ltc4162l_alert,
0921 .id_table = ltc4162l_i2c_id_table,
0922 .driver = {
0923 .name = "ltc4162-l-charger",
0924 .of_match_table = of_match_ptr(ltc4162l_of_match),
0925 },
0926 };
0927 module_i2c_driver(ltc4162l_driver);
0928
0929 MODULE_LICENSE("GPL");
0930 MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
0931 MODULE_DESCRIPTION("LTC4162-L charger driver");