linux/drivers/power/supply/ltc4162-l-charger.c
<<
>>
Prefs
   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");
 932