linux/drivers/power/axp288_charger.c
<<
>>
Prefs
   1/*
   2 * axp288_charger.c - X-power AXP288 PMIC Charger driver
   3 *
   4 * Copyright (C) 2014 Intel Corporation
   5 * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 */
  16
  17#include <linux/module.h>
  18#include <linux/device.h>
  19#include <linux/regmap.h>
  20#include <linux/workqueue.h>
  21#include <linux/delay.h>
  22#include <linux/platform_device.h>
  23#include <linux/usb/otg.h>
  24#include <linux/notifier.h>
  25#include <linux/power_supply.h>
  26#include <linux/notifier.h>
  27#include <linux/property.h>
  28#include <linux/mfd/axp20x.h>
  29#include <linux/extcon.h>
  30
  31#define PS_STAT_VBUS_TRIGGER            (1 << 0)
  32#define PS_STAT_BAT_CHRG_DIR            (1 << 2)
  33#define PS_STAT_VBAT_ABOVE_VHOLD        (1 << 3)
  34#define PS_STAT_VBUS_VALID              (1 << 4)
  35#define PS_STAT_VBUS_PRESENT            (1 << 5)
  36
  37#define CHRG_STAT_BAT_SAFE_MODE         (1 << 3)
  38#define CHRG_STAT_BAT_VALID             (1 << 4)
  39#define CHRG_STAT_BAT_PRESENT           (1 << 5)
  40#define CHRG_STAT_CHARGING              (1 << 6)
  41#define CHRG_STAT_PMIC_OTP              (1 << 7)
  42
  43#define VBUS_ISPOUT_CUR_LIM_MASK        0x03
  44#define VBUS_ISPOUT_CUR_LIM_BIT_POS     0
  45#define VBUS_ISPOUT_CUR_LIM_900MA       0x0     /* 900mA */
  46#define VBUS_ISPOUT_CUR_LIM_1500MA      0x1     /* 1500mA */
  47#define VBUS_ISPOUT_CUR_LIM_2000MA      0x2     /* 2000mA */
  48#define VBUS_ISPOUT_CUR_NO_LIM          0x3     /* 2500mA */
  49#define VBUS_ISPOUT_VHOLD_SET_MASK      0x31
  50#define VBUS_ISPOUT_VHOLD_SET_BIT_POS   0x3
  51#define VBUS_ISPOUT_VHOLD_SET_OFFSET    4000    /* 4000mV */
  52#define VBUS_ISPOUT_VHOLD_SET_LSB_RES   100     /* 100mV */
  53#define VBUS_ISPOUT_VHOLD_SET_4300MV    0x3     /* 4300mV */
  54#define VBUS_ISPOUT_VBUS_PATH_DIS       (1 << 7)
  55
  56#define CHRG_CCCV_CC_MASK               0xf             /* 4 bits */
  57#define CHRG_CCCV_CC_BIT_POS            0
  58#define CHRG_CCCV_CC_OFFSET             200             /* 200mA */
  59#define CHRG_CCCV_CC_LSB_RES            200             /* 200mA */
  60#define CHRG_CCCV_ITERM_20P             (1 << 4)        /* 20% of CC */
  61#define CHRG_CCCV_CV_MASK               0x60            /* 2 bits */
  62#define CHRG_CCCV_CV_BIT_POS            5
  63#define CHRG_CCCV_CV_4100MV             0x0             /* 4.10V */
  64#define CHRG_CCCV_CV_4150MV             0x1             /* 4.15V */
  65#define CHRG_CCCV_CV_4200MV             0x2             /* 4.20V */
  66#define CHRG_CCCV_CV_4350MV             0x3             /* 4.35V */
  67#define CHRG_CCCV_CHG_EN                (1 << 7)
  68
  69#define CNTL2_CC_TIMEOUT_MASK           0x3     /* 2 bits */
  70#define CNTL2_CC_TIMEOUT_OFFSET         6       /* 6 Hrs */
  71#define CNTL2_CC_TIMEOUT_LSB_RES        2       /* 2 Hrs */
  72#define CNTL2_CC_TIMEOUT_12HRS          0x3     /* 12 Hrs */
  73#define CNTL2_CHGLED_TYPEB              (1 << 4)
  74#define CNTL2_CHG_OUT_TURNON            (1 << 5)
  75#define CNTL2_PC_TIMEOUT_MASK           0xC0
  76#define CNTL2_PC_TIMEOUT_OFFSET         40      /* 40 mins */
  77#define CNTL2_PC_TIMEOUT_LSB_RES        10      /* 10 mins */
  78#define CNTL2_PC_TIMEOUT_70MINS         0x3
  79
  80#define CHRG_ILIM_TEMP_LOOP_EN          (1 << 3)
  81#define CHRG_VBUS_ILIM_MASK             0xf0
  82#define CHRG_VBUS_ILIM_BIT_POS          4
  83#define CHRG_VBUS_ILIM_100MA            0x0     /* 100mA */
  84#define CHRG_VBUS_ILIM_500MA            0x1     /* 500mA */
  85#define CHRG_VBUS_ILIM_900MA            0x2     /* 900mA */
  86#define CHRG_VBUS_ILIM_1500MA           0x3     /* 1500mA */
  87#define CHRG_VBUS_ILIM_2000MA           0x4     /* 2000mA */
  88#define CHRG_VBUS_ILIM_2500MA           0x5     /* 2500mA */
  89#define CHRG_VBUS_ILIM_3000MA           0x6     /* 3000mA */
  90
  91#define CHRG_VLTFC_0C                   0xA5    /* 0 DegC */
  92#define CHRG_VHTFC_45C                  0x1F    /* 45 DegC */
  93
  94#define BAT_IRQ_CFG_CHRG_DONE           (1 << 2)
  95#define BAT_IRQ_CFG_CHRG_START          (1 << 3)
  96#define BAT_IRQ_CFG_BAT_SAFE_EXIT       (1 << 4)
  97#define BAT_IRQ_CFG_BAT_SAFE_ENTER      (1 << 5)
  98#define BAT_IRQ_CFG_BAT_DISCON          (1 << 6)
  99#define BAT_IRQ_CFG_BAT_CONN            (1 << 7)
 100#define BAT_IRQ_CFG_BAT_MASK            0xFC
 101
 102#define TEMP_IRQ_CFG_QCBTU              (1 << 4)
 103#define TEMP_IRQ_CFG_CBTU               (1 << 5)
 104#define TEMP_IRQ_CFG_QCBTO              (1 << 6)
 105#define TEMP_IRQ_CFG_CBTO               (1 << 7)
 106#define TEMP_IRQ_CFG_MASK               0xF0
 107
 108#define FG_CNTL_OCV_ADJ_EN              (1 << 3)
 109
 110#define CV_4100MV                       4100    /* 4100mV */
 111#define CV_4150MV                       4150    /* 4150mV */
 112#define CV_4200MV                       4200    /* 4200mV */
 113#define CV_4350MV                       4350    /* 4350mV */
 114
 115#define CC_200MA                        200     /*  200mA */
 116#define CC_600MA                        600     /*  600mA */
 117#define CC_800MA                        800     /*  800mA */
 118#define CC_1000MA                       1000    /* 1000mA */
 119#define CC_1600MA                       1600    /* 1600mA */
 120#define CC_2000MA                       2000    /* 2000mA */
 121
 122#define ILIM_100MA                      100     /* 100mA */
 123#define ILIM_500MA                      500     /* 500mA */
 124#define ILIM_900MA                      900     /* 900mA */
 125#define ILIM_1500MA                     1500    /* 1500mA */
 126#define ILIM_2000MA                     2000    /* 2000mA */
 127#define ILIM_2500MA                     2500    /* 2500mA */
 128#define ILIM_3000MA                     3000    /* 3000mA */
 129
 130#define AXP288_EXTCON_DEV_NAME          "axp288_extcon"
 131
 132#define AXP288_EXTCON_SLOW_CHARGER              "SLOW-CHARGER"
 133#define AXP288_EXTCON_DOWNSTREAM_CHARGER        "CHARGE-DOWNSTREAM"
 134#define AXP288_EXTCON_FAST_CHARGER              "FAST-CHARGER"
 135
 136enum {
 137        VBUS_OV_IRQ = 0,
 138        CHARGE_DONE_IRQ,
 139        CHARGE_CHARGING_IRQ,
 140        BAT_SAFE_QUIT_IRQ,
 141        BAT_SAFE_ENTER_IRQ,
 142        QCBTU_IRQ,
 143        CBTU_IRQ,
 144        QCBTO_IRQ,
 145        CBTO_IRQ,
 146        CHRG_INTR_END,
 147};
 148
 149struct axp288_chrg_info {
 150        struct platform_device *pdev;
 151        struct axp20x_chrg_pdata *pdata;
 152        struct regmap *regmap;
 153        struct regmap_irq_chip_data *regmap_irqc;
 154        int irq[CHRG_INTR_END];
 155        struct power_supply *psy_usb;
 156        struct mutex lock;
 157
 158        /* OTG/Host mode */
 159        struct {
 160                struct work_struct work;
 161                struct extcon_specific_cable_nb cable;
 162                struct notifier_block id_nb;
 163                bool id_short;
 164        } otg;
 165
 166        /* SDP/CDP/DCP USB charging cable notifications */
 167        struct {
 168                struct extcon_dev *edev;
 169                bool connected;
 170                enum power_supply_type chg_type;
 171                struct notifier_block nb;
 172                struct work_struct work;
 173        } cable;
 174
 175        int health;
 176        int inlmt;
 177        int cc;
 178        int cv;
 179        int max_cc;
 180        int max_cv;
 181        bool online;
 182        bool present;
 183        bool enable_charger;
 184        bool is_charger_enabled;
 185};
 186
 187static inline int axp288_charger_set_cc(struct axp288_chrg_info *info, int cc)
 188{
 189        u8 reg_val;
 190        int ret;
 191
 192        if (cc < CHRG_CCCV_CC_OFFSET)
 193                cc = CHRG_CCCV_CC_OFFSET;
 194        else if (cc > info->max_cc)
 195                cc = info->max_cc;
 196
 197        reg_val = (cc - CHRG_CCCV_CC_OFFSET) / CHRG_CCCV_CC_LSB_RES;
 198        cc = (reg_val * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
 199        reg_val = reg_val << CHRG_CCCV_CC_BIT_POS;
 200
 201        ret = regmap_update_bits(info->regmap,
 202                                AXP20X_CHRG_CTRL1,
 203                                CHRG_CCCV_CC_MASK, reg_val);
 204        if (ret >= 0)
 205                info->cc = cc;
 206
 207        return ret;
 208}
 209
 210static inline int axp288_charger_set_cv(struct axp288_chrg_info *info, int cv)
 211{
 212        u8 reg_val;
 213        int ret;
 214
 215        if (cv <= CV_4100MV) {
 216                reg_val = CHRG_CCCV_CV_4100MV;
 217                cv = CV_4100MV;
 218        } else if (cv <= CV_4150MV) {
 219                reg_val = CHRG_CCCV_CV_4150MV;
 220                cv = CV_4150MV;
 221        } else if (cv <= CV_4200MV) {
 222                reg_val = CHRG_CCCV_CV_4200MV;
 223                cv = CV_4200MV;
 224        } else {
 225                reg_val = CHRG_CCCV_CV_4350MV;
 226                cv = CV_4350MV;
 227        }
 228
 229        reg_val = reg_val << CHRG_CCCV_CV_BIT_POS;
 230
 231        ret = regmap_update_bits(info->regmap,
 232                                AXP20X_CHRG_CTRL1,
 233                                CHRG_CCCV_CV_MASK, reg_val);
 234
 235        if (ret >= 0)
 236                info->cv = cv;
 237
 238        return ret;
 239}
 240
 241static inline int axp288_charger_set_vbus_inlmt(struct axp288_chrg_info *info,
 242                                           int inlmt)
 243{
 244        int ret;
 245        unsigned int val;
 246        u8 reg_val;
 247
 248        /* Read in limit register */
 249        ret = regmap_read(info->regmap, AXP20X_CHRG_BAK_CTRL, &val);
 250        if (ret < 0)
 251                goto set_inlmt_fail;
 252
 253        if (inlmt <= ILIM_100MA) {
 254                reg_val = CHRG_VBUS_ILIM_100MA;
 255                inlmt = ILIM_100MA;
 256        } else if (inlmt <= ILIM_500MA) {
 257                reg_val = CHRG_VBUS_ILIM_500MA;
 258                inlmt = ILIM_500MA;
 259        } else if (inlmt <= ILIM_900MA) {
 260                reg_val = CHRG_VBUS_ILIM_900MA;
 261                inlmt = ILIM_900MA;
 262        } else if (inlmt <= ILIM_1500MA) {
 263                reg_val = CHRG_VBUS_ILIM_1500MA;
 264                inlmt = ILIM_1500MA;
 265        } else if (inlmt <= ILIM_2000MA) {
 266                reg_val = CHRG_VBUS_ILIM_2000MA;
 267                inlmt = ILIM_2000MA;
 268        } else if (inlmt <= ILIM_2500MA) {
 269                reg_val = CHRG_VBUS_ILIM_2500MA;
 270                inlmt = ILIM_2500MA;
 271        } else {
 272                reg_val = CHRG_VBUS_ILIM_3000MA;
 273                inlmt = ILIM_3000MA;
 274        }
 275
 276        reg_val = (val & ~CHRG_VBUS_ILIM_MASK)
 277                        | (reg_val << CHRG_VBUS_ILIM_BIT_POS);
 278        ret = regmap_write(info->regmap, AXP20X_CHRG_BAK_CTRL, reg_val);
 279        if (ret >= 0)
 280                info->inlmt = inlmt;
 281        else
 282                dev_err(&info->pdev->dev, "charger BAK control %d\n", ret);
 283
 284
 285set_inlmt_fail:
 286        return ret;
 287}
 288
 289static int axp288_charger_vbus_path_select(struct axp288_chrg_info *info,
 290                                                                bool enable)
 291{
 292        int ret;
 293
 294        if (enable)
 295                ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
 296                                        VBUS_ISPOUT_VBUS_PATH_DIS, 0);
 297        else
 298                ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
 299                        VBUS_ISPOUT_VBUS_PATH_DIS, VBUS_ISPOUT_VBUS_PATH_DIS);
 300
 301        if (ret < 0)
 302                dev_err(&info->pdev->dev, "axp288 vbus path select %d\n", ret);
 303
 304
 305        return ret;
 306}
 307
 308static int axp288_charger_enable_charger(struct axp288_chrg_info *info,
 309                                                                bool enable)
 310{
 311        int ret;
 312
 313        if (enable)
 314                ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
 315                                CHRG_CCCV_CHG_EN, CHRG_CCCV_CHG_EN);
 316        else
 317                ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
 318                                CHRG_CCCV_CHG_EN, 0);
 319        if (ret < 0)
 320                dev_err(&info->pdev->dev, "axp288 enable charger %d\n", ret);
 321        else
 322                info->is_charger_enabled = enable;
 323
 324        return ret;
 325}
 326
 327static int axp288_charger_is_present(struct axp288_chrg_info *info)
 328{
 329        int ret, present = 0;
 330        unsigned int val;
 331
 332        ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
 333        if (ret < 0)
 334                return ret;
 335
 336        if (val & PS_STAT_VBUS_PRESENT)
 337                present = 1;
 338        return present;
 339}
 340
 341static int axp288_charger_is_online(struct axp288_chrg_info *info)
 342{
 343        int ret, online = 0;
 344        unsigned int val;
 345
 346        ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
 347        if (ret < 0)
 348                return ret;
 349
 350        if (val & PS_STAT_VBUS_VALID)
 351                online = 1;
 352        return online;
 353}
 354
 355static int axp288_get_charger_health(struct axp288_chrg_info *info)
 356{
 357        int ret, pwr_stat, chrg_stat;
 358        int health = POWER_SUPPLY_HEALTH_UNKNOWN;
 359        unsigned int val;
 360
 361        ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
 362        if ((ret < 0) || !(val & PS_STAT_VBUS_PRESENT))
 363                goto health_read_fail;
 364        else
 365                pwr_stat = val;
 366
 367        ret = regmap_read(info->regmap, AXP20X_PWR_OP_MODE, &val);
 368        if (ret < 0)
 369                goto health_read_fail;
 370        else
 371                chrg_stat = val;
 372
 373        if (!(pwr_stat & PS_STAT_VBUS_VALID))
 374                health = POWER_SUPPLY_HEALTH_DEAD;
 375        else if (chrg_stat & CHRG_STAT_PMIC_OTP)
 376                health = POWER_SUPPLY_HEALTH_OVERHEAT;
 377        else if (chrg_stat & CHRG_STAT_BAT_SAFE_MODE)
 378                health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
 379        else
 380                health = POWER_SUPPLY_HEALTH_GOOD;
 381
 382health_read_fail:
 383        return health;
 384}
 385
 386static int axp288_charger_usb_set_property(struct power_supply *psy,
 387                                    enum power_supply_property psp,
 388                                    const union power_supply_propval *val)
 389{
 390        struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
 391        int ret = 0;
 392        int scaled_val;
 393
 394        mutex_lock(&info->lock);
 395
 396        switch (psp) {
 397        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 398                scaled_val = min(val->intval, info->max_cc);
 399                scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
 400                ret = axp288_charger_set_cc(info, scaled_val);
 401                if (ret < 0)
 402                        dev_warn(&info->pdev->dev, "set charge current failed\n");
 403                break;
 404        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 405                scaled_val = min(val->intval, info->max_cv);
 406                scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
 407                ret = axp288_charger_set_cv(info, scaled_val);
 408                if (ret < 0)
 409                        dev_warn(&info->pdev->dev, "set charge voltage failed\n");
 410                break;
 411        default:
 412                ret = -EINVAL;
 413        }
 414
 415        mutex_unlock(&info->lock);
 416        return ret;
 417}
 418
 419static int axp288_charger_usb_get_property(struct power_supply *psy,
 420                                    enum power_supply_property psp,
 421                                    union power_supply_propval *val)
 422{
 423        struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
 424        int ret = 0;
 425
 426        mutex_lock(&info->lock);
 427
 428        switch (psp) {
 429        case POWER_SUPPLY_PROP_PRESENT:
 430                /* Check for OTG case first */
 431                if (info->otg.id_short) {
 432                        val->intval = 0;
 433                        break;
 434                }
 435                ret = axp288_charger_is_present(info);
 436                if (ret < 0)
 437                        goto psy_get_prop_fail;
 438                info->present = ret;
 439                val->intval = info->present;
 440                break;
 441        case POWER_SUPPLY_PROP_ONLINE:
 442                /* Check for OTG case first */
 443                if (info->otg.id_short) {
 444                        val->intval = 0;
 445                        break;
 446                }
 447                ret = axp288_charger_is_online(info);
 448                if (ret < 0)
 449                        goto psy_get_prop_fail;
 450                info->online = ret;
 451                val->intval = info->online;
 452                break;
 453        case POWER_SUPPLY_PROP_HEALTH:
 454                val->intval = axp288_get_charger_health(info);
 455                break;
 456        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 457                val->intval = info->cc * 1000;
 458                break;
 459        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
 460                val->intval = info->max_cc * 1000;
 461                break;
 462        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 463                val->intval = info->cv * 1000;
 464                break;
 465        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
 466                val->intval = info->max_cv * 1000;
 467                break;
 468        case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
 469                val->intval = info->inlmt * 1000;
 470                break;
 471        default:
 472                ret = -EINVAL;
 473                goto psy_get_prop_fail;
 474        }
 475
 476psy_get_prop_fail:
 477        mutex_unlock(&info->lock);
 478        return ret;
 479}
 480
 481static int axp288_charger_property_is_writeable(struct power_supply *psy,
 482                enum power_supply_property psp)
 483{
 484        int ret;
 485
 486        switch (psp) {
 487        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 488        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 489                ret = 1;
 490                break;
 491        default:
 492                ret = 0;
 493        }
 494
 495        return ret;
 496}
 497
 498static enum power_supply_property axp288_usb_props[] = {
 499        POWER_SUPPLY_PROP_PRESENT,
 500        POWER_SUPPLY_PROP_ONLINE,
 501        POWER_SUPPLY_PROP_TYPE,
 502        POWER_SUPPLY_PROP_HEALTH,
 503        POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
 504        POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
 505        POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
 506        POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
 507        POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
 508};
 509
 510static const struct power_supply_desc axp288_charger_desc = {
 511        .name                   = "axp288_charger",
 512        .type                   = POWER_SUPPLY_TYPE_USB,
 513        .properties             = axp288_usb_props,
 514        .num_properties         = ARRAY_SIZE(axp288_usb_props),
 515        .get_property           = axp288_charger_usb_get_property,
 516        .set_property           = axp288_charger_usb_set_property,
 517        .property_is_writeable  = axp288_charger_property_is_writeable,
 518};
 519
 520static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev)
 521{
 522        struct axp288_chrg_info *info = dev;
 523        int i;
 524
 525        for (i = 0; i < CHRG_INTR_END; i++) {
 526                if (info->irq[i] == irq)
 527                        break;
 528        }
 529
 530        if (i >= CHRG_INTR_END) {
 531                dev_warn(&info->pdev->dev, "spurious interrupt!!\n");
 532                return IRQ_NONE;
 533        }
 534
 535        switch (i) {
 536        case VBUS_OV_IRQ:
 537                dev_dbg(&info->pdev->dev, "VBUS Over Voltage INTR\n");
 538                break;
 539        case CHARGE_DONE_IRQ:
 540                dev_dbg(&info->pdev->dev, "Charging Done INTR\n");
 541                break;
 542        case CHARGE_CHARGING_IRQ:
 543                dev_dbg(&info->pdev->dev, "Start Charging IRQ\n");
 544                break;
 545        case BAT_SAFE_QUIT_IRQ:
 546                dev_dbg(&info->pdev->dev,
 547                        "Quit Safe Mode(restart timer) Charging IRQ\n");
 548                break;
 549        case BAT_SAFE_ENTER_IRQ:
 550                dev_dbg(&info->pdev->dev,
 551                        "Enter Safe Mode(timer expire) Charging IRQ\n");
 552                break;
 553        case QCBTU_IRQ:
 554                dev_dbg(&info->pdev->dev,
 555                        "Quit Battery Under Temperature(CHRG) INTR\n");
 556                break;
 557        case CBTU_IRQ:
 558                dev_dbg(&info->pdev->dev,
 559                        "Hit Battery Under Temperature(CHRG) INTR\n");
 560                break;
 561        case QCBTO_IRQ:
 562                dev_dbg(&info->pdev->dev,
 563                        "Quit Battery Over Temperature(CHRG) INTR\n");
 564                break;
 565        case CBTO_IRQ:
 566                dev_dbg(&info->pdev->dev,
 567                        "Hit Battery Over Temperature(CHRG) INTR\n");
 568                break;
 569        default:
 570                dev_warn(&info->pdev->dev, "Spurious Interrupt!!!\n");
 571                goto out;
 572        }
 573
 574        power_supply_changed(info->psy_usb);
 575out:
 576        return IRQ_HANDLED;
 577}
 578
 579static void axp288_charger_extcon_evt_worker(struct work_struct *work)
 580{
 581        struct axp288_chrg_info *info =
 582            container_of(work, struct axp288_chrg_info, cable.work);
 583        int ret, current_limit;
 584        bool changed = false;
 585        struct extcon_dev *edev = info->cable.edev;
 586        bool old_connected = info->cable.connected;
 587
 588        /* Determine cable/charger type */
 589        if (extcon_get_cable_state(edev, AXP288_EXTCON_SLOW_CHARGER) > 0) {
 590                dev_dbg(&info->pdev->dev, "USB SDP charger  is connected");
 591                info->cable.connected = true;
 592                info->cable.chg_type = POWER_SUPPLY_TYPE_USB;
 593        } else if (extcon_get_cable_state(edev,
 594                                AXP288_EXTCON_DOWNSTREAM_CHARGER) > 0) {
 595                dev_dbg(&info->pdev->dev, "USB CDP charger is connected");
 596                info->cable.connected = true;
 597                info->cable.chg_type = POWER_SUPPLY_TYPE_USB_CDP;
 598        } else if (extcon_get_cable_state(edev,
 599                                        AXP288_EXTCON_FAST_CHARGER) > 0) {
 600                dev_dbg(&info->pdev->dev, "USB DCP charger is connected");
 601                info->cable.connected = true;
 602                info->cable.chg_type = POWER_SUPPLY_TYPE_USB_DCP;
 603        } else {
 604                if (old_connected)
 605                        dev_dbg(&info->pdev->dev, "USB charger disconnected");
 606                info->cable.connected = false;
 607                info->cable.chg_type = POWER_SUPPLY_TYPE_USB;
 608        }
 609
 610        /* Cable status changed */
 611        if (old_connected != info->cable.connected)
 612                changed = true;
 613
 614        if (!changed)
 615                return;
 616
 617        mutex_lock(&info->lock);
 618
 619        if (info->is_charger_enabled && !info->cable.connected) {
 620                info->enable_charger = false;
 621                ret = axp288_charger_enable_charger(info, info->enable_charger);
 622                if (ret < 0)
 623                        dev_err(&info->pdev->dev,
 624                                "cannot disable charger (%d)", ret);
 625
 626        } else if (!info->is_charger_enabled && info->cable.connected) {
 627                switch (info->cable.chg_type) {
 628                case POWER_SUPPLY_TYPE_USB:
 629                        current_limit = ILIM_500MA;
 630                        break;
 631                case POWER_SUPPLY_TYPE_USB_CDP:
 632                        current_limit = ILIM_1500MA;
 633                        break;
 634                case POWER_SUPPLY_TYPE_USB_DCP:
 635                        current_limit = ILIM_2000MA;
 636                        break;
 637                default:
 638                        /* Unknown */
 639                        current_limit = 0;
 640                        break;
 641                }
 642
 643                /* Set vbus current limit first, then enable charger */
 644                ret = axp288_charger_set_vbus_inlmt(info, current_limit);
 645                if (ret < 0) {
 646                        dev_err(&info->pdev->dev,
 647                                "error setting current limit (%d)", ret);
 648                } else {
 649                        info->enable_charger = (current_limit > 0);
 650                        ret = axp288_charger_enable_charger(info,
 651                                                        info->enable_charger);
 652                        if (ret < 0)
 653                                dev_err(&info->pdev->dev,
 654                                        "cannot enable charger (%d)", ret);
 655                }
 656        }
 657
 658        if (changed)
 659                info->health = axp288_get_charger_health(info);
 660
 661        mutex_unlock(&info->lock);
 662
 663        if (changed)
 664                power_supply_changed(info->psy_usb);
 665}
 666
 667static int axp288_charger_handle_cable_evt(struct notifier_block *nb,
 668                                          unsigned long event, void *param)
 669{
 670        struct axp288_chrg_info *info =
 671            container_of(nb, struct axp288_chrg_info, cable.nb);
 672
 673        schedule_work(&info->cable.work);
 674
 675        return NOTIFY_OK;
 676}
 677
 678static void axp288_charger_otg_evt_worker(struct work_struct *work)
 679{
 680        struct axp288_chrg_info *info =
 681            container_of(work, struct axp288_chrg_info, otg.work);
 682        int ret;
 683
 684        /* Disable VBUS path before enabling the 5V boost */
 685        ret = axp288_charger_vbus_path_select(info, !info->otg.id_short);
 686        if (ret < 0)
 687                dev_warn(&info->pdev->dev, "vbus path disable failed\n");
 688}
 689
 690static int axp288_charger_handle_otg_evt(struct notifier_block *nb,
 691                                   unsigned long event, void *param)
 692{
 693        struct axp288_chrg_info *info =
 694            container_of(nb, struct axp288_chrg_info, otg.id_nb);
 695        struct extcon_dev *edev = param;
 696        int usb_host = extcon_get_cable_state(edev, "USB-Host");
 697
 698        dev_dbg(&info->pdev->dev, "external connector USB-Host is %s\n",
 699                                usb_host ? "attached" : "detached");
 700
 701        /*
 702         * Set usb_id_short flag to avoid running charger detection logic
 703         * in case usb host.
 704         */
 705        info->otg.id_short = usb_host;
 706        schedule_work(&info->otg.work);
 707
 708        return NOTIFY_OK;
 709}
 710
 711static void charger_init_hw_regs(struct axp288_chrg_info *info)
 712{
 713        int ret, cc, cv;
 714        unsigned int val;
 715
 716        /* Program temperature thresholds */
 717        ret = regmap_write(info->regmap, AXP20X_V_LTF_CHRG, CHRG_VLTFC_0C);
 718        if (ret < 0)
 719                dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
 720                                                        AXP20X_V_LTF_CHRG, ret);
 721
 722        ret = regmap_write(info->regmap, AXP20X_V_HTF_CHRG, CHRG_VHTFC_45C);
 723        if (ret < 0)
 724                dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
 725                                                        AXP20X_V_HTF_CHRG, ret);
 726
 727        /* Do not turn-off charger o/p after charge cycle ends */
 728        ret = regmap_update_bits(info->regmap,
 729                                AXP20X_CHRG_CTRL2,
 730                                CNTL2_CHG_OUT_TURNON, 1);
 731        if (ret < 0)
 732                dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
 733                                                AXP20X_CHRG_CTRL2, ret);
 734
 735        /* Enable interrupts */
 736        ret = regmap_update_bits(info->regmap,
 737                                AXP20X_IRQ2_EN,
 738                                BAT_IRQ_CFG_BAT_MASK, 1);
 739        if (ret < 0)
 740                dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
 741                                                AXP20X_IRQ2_EN, ret);
 742
 743        ret = regmap_update_bits(info->regmap, AXP20X_IRQ3_EN,
 744                                TEMP_IRQ_CFG_MASK, 1);
 745        if (ret < 0)
 746                dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
 747                                                AXP20X_IRQ3_EN, ret);
 748
 749        /* Setup ending condition for charging to be 10% of I(chrg) */
 750        ret = regmap_update_bits(info->regmap,
 751                                AXP20X_CHRG_CTRL1,
 752                                CHRG_CCCV_ITERM_20P, 0);
 753        if (ret < 0)
 754                dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
 755                                                AXP20X_CHRG_CTRL1, ret);
 756
 757        /* Disable OCV-SOC curve calibration */
 758        ret = regmap_update_bits(info->regmap,
 759                                AXP20X_CC_CTRL,
 760                                FG_CNTL_OCV_ADJ_EN, 0);
 761        if (ret < 0)
 762                dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n",
 763                                                AXP20X_CC_CTRL, ret);
 764
 765        /* Init charging current and voltage */
 766        info->max_cc = info->pdata->max_cc;
 767        info->max_cv = info->pdata->max_cv;
 768
 769        /* Read current charge voltage and current limit */
 770        ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val);
 771        if (ret < 0) {
 772                /* Assume default if cannot read */
 773                info->cc = info->pdata->def_cc;
 774                info->cv = info->pdata->def_cv;
 775        } else {
 776                /* Determine charge voltage */
 777                cv = (val & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS;
 778                switch (cv) {
 779                case CHRG_CCCV_CV_4100MV:
 780                        info->cv = CV_4100MV;
 781                        break;
 782                case CHRG_CCCV_CV_4150MV:
 783                        info->cv = CV_4150MV;
 784                        break;
 785                case CHRG_CCCV_CV_4200MV:
 786                        info->cv = CV_4200MV;
 787                        break;
 788                case CHRG_CCCV_CV_4350MV:
 789                        info->cv = CV_4350MV;
 790                        break;
 791                default:
 792                        info->cv = INT_MAX;
 793                        break;
 794                }
 795
 796                /* Determine charge current limit */
 797                cc = (ret & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS;
 798                cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
 799                info->cc = cc;
 800
 801                /* Program default charging voltage and current */
 802                cc = min(info->pdata->def_cc, info->max_cc);
 803                cv = min(info->pdata->def_cv, info->max_cv);
 804
 805                ret = axp288_charger_set_cc(info, cc);
 806                if (ret < 0)
 807                        dev_warn(&info->pdev->dev,
 808                                        "error(%d) in setting CC\n", ret);
 809
 810                ret = axp288_charger_set_cv(info, cv);
 811                if (ret < 0)
 812                        dev_warn(&info->pdev->dev,
 813                                        "error(%d) in setting CV\n", ret);
 814        }
 815}
 816
 817static int axp288_charger_probe(struct platform_device *pdev)
 818{
 819        int ret, i, pirq;
 820        struct axp288_chrg_info *info;
 821        struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
 822        struct power_supply_config charger_cfg = {};
 823
 824        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 825        if (!info)
 826                return -ENOMEM;
 827
 828        info->pdev = pdev;
 829        info->regmap = axp20x->regmap;
 830        info->regmap_irqc = axp20x->regmap_irqc;
 831        info->pdata = pdev->dev.platform_data;
 832
 833        if (!info->pdata) {
 834                /* Try ACPI provided pdata via device properties */
 835                if (!device_property_present(&pdev->dev,
 836                                                "axp288_charger_data\n"))
 837                        dev_err(&pdev->dev, "failed to get platform data\n");
 838                return -ENODEV;
 839        }
 840
 841        info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME);
 842        if (info->cable.edev == NULL) {
 843                dev_dbg(&pdev->dev, "%s is not ready, probe deferred\n",
 844                        AXP288_EXTCON_DEV_NAME);
 845                return -EPROBE_DEFER;
 846        }
 847
 848        /* Register for extcon notification */
 849        INIT_WORK(&info->cable.work, axp288_charger_extcon_evt_worker);
 850        info->cable.nb.notifier_call = axp288_charger_handle_cable_evt;
 851        ret = extcon_register_notifier(info->cable.edev, EXTCON_NONE, &info->cable.nb);
 852        if (ret) {
 853                dev_err(&info->pdev->dev,
 854                        "failed to register extcon notifier %d\n", ret);
 855                return ret;
 856        }
 857
 858        platform_set_drvdata(pdev, info);
 859        mutex_init(&info->lock);
 860
 861        /* Register with power supply class */
 862        charger_cfg.drv_data = info;
 863        info->psy_usb = power_supply_register(&pdev->dev, &axp288_charger_desc,
 864                                                &charger_cfg);
 865        if (IS_ERR(info->psy_usb)) {
 866                dev_err(&pdev->dev, "failed to register power supply charger\n");
 867                ret = PTR_ERR(info->psy_usb);
 868                goto psy_reg_failed;
 869        }
 870
 871        /* Register for OTG notification */
 872        INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker);
 873        info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt;
 874        ret = extcon_register_interest(&info->otg.cable, NULL, "USB-Host",
 875                                       &info->otg.id_nb);
 876        if (ret)
 877                dev_warn(&pdev->dev, "failed to register otg notifier\n");
 878
 879        if (info->otg.cable.edev)
 880                info->otg.id_short = extcon_get_cable_state(
 881                                        info->otg.cable.edev, "USB-Host");
 882
 883        /* Register charger interrupts */
 884        for (i = 0; i < CHRG_INTR_END; i++) {
 885                pirq = platform_get_irq(info->pdev, i);
 886                info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
 887                if (info->irq[i] < 0) {
 888                        dev_warn(&info->pdev->dev,
 889                                "failed to get virtual interrupt=%d\n", pirq);
 890                        ret = info->irq[i];
 891                        goto intr_reg_failed;
 892                }
 893                ret = devm_request_threaded_irq(&info->pdev->dev, info->irq[i],
 894                                        NULL, axp288_charger_irq_thread_handler,
 895                                        IRQF_ONESHOT, info->pdev->name, info);
 896                if (ret) {
 897                        dev_err(&pdev->dev, "failed to request interrupt=%d\n",
 898                                                                info->irq[i]);
 899                        goto intr_reg_failed;
 900                }
 901        }
 902
 903        charger_init_hw_regs(info);
 904
 905        return 0;
 906
 907intr_reg_failed:
 908        if (info->otg.cable.edev)
 909                extcon_unregister_interest(&info->otg.cable);
 910        power_supply_unregister(info->psy_usb);
 911psy_reg_failed:
 912        extcon_unregister_notifier(info->cable.edev, EXTCON_NONE, &info->cable.nb);
 913        return ret;
 914}
 915
 916static int axp288_charger_remove(struct platform_device *pdev)
 917{
 918        struct axp288_chrg_info *info =  dev_get_drvdata(&pdev->dev);
 919
 920        if (info->otg.cable.edev)
 921                extcon_unregister_interest(&info->otg.cable);
 922
 923        extcon_unregister_notifier(info->cable.edev, EXTCON_NONE, &info->cable.nb);
 924        power_supply_unregister(info->psy_usb);
 925
 926        return 0;
 927}
 928
 929static struct platform_driver axp288_charger_driver = {
 930        .probe = axp288_charger_probe,
 931        .remove = axp288_charger_remove,
 932        .driver = {
 933                .name = "axp288_charger",
 934        },
 935};
 936
 937module_platform_driver(axp288_charger_driver);
 938
 939MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
 940MODULE_DESCRIPTION("X-power AXP288 Charger Driver");
 941MODULE_LICENSE("GPL v2");
 942