linux/drivers/power/supply/axp288_charger.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * axp288_charger.c - X-power AXP288 PMIC Charger driver
   4 *
   5 * Copyright (C) 2016-2017 Hans de Goede <hdegoede@redhat.com>
   6 * Copyright (C) 2014 Intel Corporation
   7 * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
   8 */
   9
  10#include <linux/acpi.h>
  11#include <linux/bitops.h>
  12#include <linux/module.h>
  13#include <linux/device.h>
  14#include <linux/regmap.h>
  15#include <linux/workqueue.h>
  16#include <linux/delay.h>
  17#include <linux/platform_device.h>
  18#include <linux/usb/otg.h>
  19#include <linux/notifier.h>
  20#include <linux/power_supply.h>
  21#include <linux/property.h>
  22#include <linux/mfd/axp20x.h>
  23#include <linux/extcon.h>
  24#include <linux/dmi.h>
  25
  26#define PS_STAT_VBUS_TRIGGER            BIT(0)
  27#define PS_STAT_BAT_CHRG_DIR            BIT(2)
  28#define PS_STAT_VBAT_ABOVE_VHOLD        BIT(3)
  29#define PS_STAT_VBUS_VALID              BIT(4)
  30#define PS_STAT_VBUS_PRESENT            BIT(5)
  31
  32#define CHRG_STAT_BAT_SAFE_MODE         BIT(3)
  33#define CHRG_STAT_BAT_VALID             BIT(4)
  34#define CHRG_STAT_BAT_PRESENT           BIT(5)
  35#define CHRG_STAT_CHARGING              BIT(6)
  36#define CHRG_STAT_PMIC_OTP              BIT(7)
  37
  38#define VBUS_ISPOUT_CUR_LIM_MASK        0x03
  39#define VBUS_ISPOUT_CUR_LIM_BIT_POS     0
  40#define VBUS_ISPOUT_CUR_LIM_900MA       0x0     /* 900mA */
  41#define VBUS_ISPOUT_CUR_LIM_1500MA      0x1     /* 1500mA */
  42#define VBUS_ISPOUT_CUR_LIM_2000MA      0x2     /* 2000mA */
  43#define VBUS_ISPOUT_CUR_NO_LIM          0x3     /* 2500mA */
  44#define VBUS_ISPOUT_VHOLD_SET_MASK      0x31
  45#define VBUS_ISPOUT_VHOLD_SET_BIT_POS   0x3
  46#define VBUS_ISPOUT_VHOLD_SET_OFFSET    4000    /* 4000mV */
  47#define VBUS_ISPOUT_VHOLD_SET_LSB_RES   100     /* 100mV */
  48#define VBUS_ISPOUT_VHOLD_SET_4300MV    0x3     /* 4300mV */
  49#define VBUS_ISPOUT_VBUS_PATH_DIS       BIT(7)
  50
  51#define CHRG_CCCV_CC_MASK               0xf             /* 4 bits */
  52#define CHRG_CCCV_CC_BIT_POS            0
  53#define CHRG_CCCV_CC_OFFSET             200             /* 200mA */
  54#define CHRG_CCCV_CC_LSB_RES            200             /* 200mA */
  55#define CHRG_CCCV_ITERM_20P             BIT(4)          /* 20% of CC */
  56#define CHRG_CCCV_CV_MASK               0x60            /* 2 bits */
  57#define CHRG_CCCV_CV_BIT_POS            5
  58#define CHRG_CCCV_CV_4100MV             0x0             /* 4.10V */
  59#define CHRG_CCCV_CV_4150MV             0x1             /* 4.15V */
  60#define CHRG_CCCV_CV_4200MV             0x2             /* 4.20V */
  61#define CHRG_CCCV_CV_4350MV             0x3             /* 4.35V */
  62#define CHRG_CCCV_CHG_EN                BIT(7)
  63
  64#define CNTL2_CC_TIMEOUT_MASK           0x3     /* 2 bits */
  65#define CNTL2_CC_TIMEOUT_OFFSET         6       /* 6 Hrs */
  66#define CNTL2_CC_TIMEOUT_LSB_RES        2       /* 2 Hrs */
  67#define CNTL2_CC_TIMEOUT_12HRS          0x3     /* 12 Hrs */
  68#define CNTL2_CHGLED_TYPEB              BIT(4)
  69#define CNTL2_CHG_OUT_TURNON            BIT(5)
  70#define CNTL2_PC_TIMEOUT_MASK           0xC0
  71#define CNTL2_PC_TIMEOUT_OFFSET         40      /* 40 mins */
  72#define CNTL2_PC_TIMEOUT_LSB_RES        10      /* 10 mins */
  73#define CNTL2_PC_TIMEOUT_70MINS         0x3
  74
  75#define CHRG_ILIM_TEMP_LOOP_EN          BIT(3)
  76#define CHRG_VBUS_ILIM_MASK             0xf0
  77#define CHRG_VBUS_ILIM_BIT_POS          4
  78#define CHRG_VBUS_ILIM_100MA            0x0     /* 100mA */
  79#define CHRG_VBUS_ILIM_500MA            0x1     /* 500mA */
  80#define CHRG_VBUS_ILIM_900MA            0x2     /* 900mA */
  81#define CHRG_VBUS_ILIM_1500MA           0x3     /* 1500mA */
  82#define CHRG_VBUS_ILIM_2000MA           0x4     /* 2000mA */
  83#define CHRG_VBUS_ILIM_2500MA           0x5     /* 2500mA */
  84#define CHRG_VBUS_ILIM_3000MA           0x6     /* 3000mA */
  85#define CHRG_VBUS_ILIM_3500MA           0x7     /* 3500mA */
  86#define CHRG_VBUS_ILIM_4000MA           0x8     /* 4000mA */
  87
  88#define CHRG_VLTFC_0C                   0xA5    /* 0 DegC */
  89#define CHRG_VHTFC_45C                  0x1F    /* 45 DegC */
  90
  91#define FG_CNTL_OCV_ADJ_EN              BIT(3)
  92
  93#define CV_4100MV                       4100    /* 4100mV */
  94#define CV_4150MV                       4150    /* 4150mV */
  95#define CV_4200MV                       4200    /* 4200mV */
  96#define CV_4350MV                       4350    /* 4350mV */
  97
  98#define AXP288_EXTCON_DEV_NAME          "axp288_extcon"
  99#define USB_HOST_EXTCON_HID             "INT3496"
 100#define USB_HOST_EXTCON_NAME            "INT3496:00"
 101
 102enum {
 103        VBUS_OV_IRQ = 0,
 104        CHARGE_DONE_IRQ,
 105        CHARGE_CHARGING_IRQ,
 106        BAT_SAFE_QUIT_IRQ,
 107        BAT_SAFE_ENTER_IRQ,
 108        QCBTU_IRQ,
 109        CBTU_IRQ,
 110        QCBTO_IRQ,
 111        CBTO_IRQ,
 112        CHRG_INTR_END,
 113};
 114
 115struct axp288_chrg_info {
 116        struct platform_device *pdev;
 117        struct regmap *regmap;
 118        struct regmap_irq_chip_data *regmap_irqc;
 119        int irq[CHRG_INTR_END];
 120        struct power_supply *psy_usb;
 121
 122        /* OTG/Host mode */
 123        struct {
 124                struct work_struct work;
 125                struct extcon_dev *cable;
 126                struct notifier_block id_nb;
 127                bool id_short;
 128        } otg;
 129
 130        /* SDP/CDP/DCP USB charging cable notifications */
 131        struct {
 132                struct extcon_dev *edev;
 133                struct notifier_block nb;
 134                struct work_struct work;
 135        } cable;
 136
 137        int cc;
 138        int cv;
 139        int max_cc;
 140        int max_cv;
 141};
 142
 143static inline int axp288_charger_set_cc(struct axp288_chrg_info *info, int cc)
 144{
 145        u8 reg_val;
 146        int ret;
 147
 148        if (cc < CHRG_CCCV_CC_OFFSET)
 149                cc = CHRG_CCCV_CC_OFFSET;
 150        else if (cc > info->max_cc)
 151                cc = info->max_cc;
 152
 153        reg_val = (cc - CHRG_CCCV_CC_OFFSET) / CHRG_CCCV_CC_LSB_RES;
 154        cc = (reg_val * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
 155        reg_val = reg_val << CHRG_CCCV_CC_BIT_POS;
 156
 157        ret = regmap_update_bits(info->regmap,
 158                                AXP20X_CHRG_CTRL1,
 159                                CHRG_CCCV_CC_MASK, reg_val);
 160        if (ret >= 0)
 161                info->cc = cc;
 162
 163        return ret;
 164}
 165
 166static inline int axp288_charger_set_cv(struct axp288_chrg_info *info, int cv)
 167{
 168        u8 reg_val;
 169        int ret;
 170
 171        if (cv <= CV_4100MV) {
 172                reg_val = CHRG_CCCV_CV_4100MV;
 173                cv = CV_4100MV;
 174        } else if (cv <= CV_4150MV) {
 175                reg_val = CHRG_CCCV_CV_4150MV;
 176                cv = CV_4150MV;
 177        } else if (cv <= CV_4200MV) {
 178                reg_val = CHRG_CCCV_CV_4200MV;
 179                cv = CV_4200MV;
 180        } else {
 181                reg_val = CHRG_CCCV_CV_4350MV;
 182                cv = CV_4350MV;
 183        }
 184
 185        reg_val = reg_val << CHRG_CCCV_CV_BIT_POS;
 186
 187        ret = regmap_update_bits(info->regmap,
 188                                AXP20X_CHRG_CTRL1,
 189                                CHRG_CCCV_CV_MASK, reg_val);
 190
 191        if (ret >= 0)
 192                info->cv = cv;
 193
 194        return ret;
 195}
 196
 197static int axp288_charger_get_vbus_inlmt(struct axp288_chrg_info *info)
 198{
 199        unsigned int val;
 200        int ret;
 201
 202        ret = regmap_read(info->regmap, AXP20X_CHRG_BAK_CTRL, &val);
 203        if (ret < 0)
 204                return ret;
 205
 206        val >>= CHRG_VBUS_ILIM_BIT_POS;
 207        switch (val) {
 208        case CHRG_VBUS_ILIM_100MA:
 209                return 100000;
 210        case CHRG_VBUS_ILIM_500MA:
 211                return 500000;
 212        case CHRG_VBUS_ILIM_900MA:
 213                return 900000;
 214        case CHRG_VBUS_ILIM_1500MA:
 215                return 1500000;
 216        case CHRG_VBUS_ILIM_2000MA:
 217                return 2000000;
 218        case CHRG_VBUS_ILIM_2500MA:
 219                return 2500000;
 220        case CHRG_VBUS_ILIM_3000MA:
 221                return 3000000;
 222        case CHRG_VBUS_ILIM_3500MA:
 223                return 3500000;
 224        default:
 225                /* All b1xxx values map to 4000 mA */
 226                return 4000000;
 227        }
 228}
 229
 230static inline int axp288_charger_set_vbus_inlmt(struct axp288_chrg_info *info,
 231                                           int inlmt)
 232{
 233        int ret;
 234        u8 reg_val;
 235
 236        if (inlmt >= 4000000)
 237                reg_val = CHRG_VBUS_ILIM_4000MA << CHRG_VBUS_ILIM_BIT_POS;
 238        else if (inlmt >= 3500000)
 239                reg_val = CHRG_VBUS_ILIM_3500MA << CHRG_VBUS_ILIM_BIT_POS;
 240        else if (inlmt >= 3000000)
 241                reg_val = CHRG_VBUS_ILIM_3000MA << CHRG_VBUS_ILIM_BIT_POS;
 242        else if (inlmt >= 2500000)
 243                reg_val = CHRG_VBUS_ILIM_2500MA << CHRG_VBUS_ILIM_BIT_POS;
 244        else if (inlmt >= 2000000)
 245                reg_val = CHRG_VBUS_ILIM_2000MA << CHRG_VBUS_ILIM_BIT_POS;
 246        else if (inlmt >= 1500000)
 247                reg_val = CHRG_VBUS_ILIM_1500MA << CHRG_VBUS_ILIM_BIT_POS;
 248        else if (inlmt >= 900000)
 249                reg_val = CHRG_VBUS_ILIM_900MA << CHRG_VBUS_ILIM_BIT_POS;
 250        else if (inlmt >= 500000)
 251                reg_val = CHRG_VBUS_ILIM_500MA << CHRG_VBUS_ILIM_BIT_POS;
 252        else
 253                reg_val = CHRG_VBUS_ILIM_100MA << CHRG_VBUS_ILIM_BIT_POS;
 254
 255        ret = regmap_update_bits(info->regmap, AXP20X_CHRG_BAK_CTRL,
 256                                 CHRG_VBUS_ILIM_MASK, reg_val);
 257        if (ret < 0)
 258                dev_err(&info->pdev->dev, "charger BAK control %d\n", ret);
 259
 260        return ret;
 261}
 262
 263static int axp288_charger_vbus_path_select(struct axp288_chrg_info *info,
 264                                                                bool enable)
 265{
 266        int ret;
 267
 268        if (enable)
 269                ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
 270                                        VBUS_ISPOUT_VBUS_PATH_DIS, 0);
 271        else
 272                ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
 273                        VBUS_ISPOUT_VBUS_PATH_DIS, VBUS_ISPOUT_VBUS_PATH_DIS);
 274
 275        if (ret < 0)
 276                dev_err(&info->pdev->dev, "axp288 vbus path select %d\n", ret);
 277
 278        return ret;
 279}
 280
 281static int axp288_charger_enable_charger(struct axp288_chrg_info *info,
 282                                                                bool enable)
 283{
 284        int ret;
 285
 286        if (enable)
 287                ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
 288                                CHRG_CCCV_CHG_EN, CHRG_CCCV_CHG_EN);
 289        else
 290                ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
 291                                CHRG_CCCV_CHG_EN, 0);
 292        if (ret < 0)
 293                dev_err(&info->pdev->dev, "axp288 enable charger %d\n", ret);
 294
 295        return ret;
 296}
 297
 298static int axp288_charger_is_present(struct axp288_chrg_info *info)
 299{
 300        int ret, present = 0;
 301        unsigned int val;
 302
 303        ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
 304        if (ret < 0)
 305                return ret;
 306
 307        if (val & PS_STAT_VBUS_PRESENT)
 308                present = 1;
 309        return present;
 310}
 311
 312static int axp288_charger_is_online(struct axp288_chrg_info *info)
 313{
 314        int ret, online = 0;
 315        unsigned int val;
 316
 317        ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
 318        if (ret < 0)
 319                return ret;
 320
 321        if (val & PS_STAT_VBUS_VALID)
 322                online = 1;
 323        return online;
 324}
 325
 326static int axp288_get_charger_health(struct axp288_chrg_info *info)
 327{
 328        int ret, pwr_stat, chrg_stat;
 329        int health = POWER_SUPPLY_HEALTH_UNKNOWN;
 330        unsigned int val;
 331
 332        ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
 333        if ((ret < 0) || !(val & PS_STAT_VBUS_PRESENT))
 334                goto health_read_fail;
 335        else
 336                pwr_stat = val;
 337
 338        ret = regmap_read(info->regmap, AXP20X_PWR_OP_MODE, &val);
 339        if (ret < 0)
 340                goto health_read_fail;
 341        else
 342                chrg_stat = val;
 343
 344        if (!(pwr_stat & PS_STAT_VBUS_VALID))
 345                health = POWER_SUPPLY_HEALTH_DEAD;
 346        else if (chrg_stat & CHRG_STAT_PMIC_OTP)
 347                health = POWER_SUPPLY_HEALTH_OVERHEAT;
 348        else if (chrg_stat & CHRG_STAT_BAT_SAFE_MODE)
 349                health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
 350        else
 351                health = POWER_SUPPLY_HEALTH_GOOD;
 352
 353health_read_fail:
 354        return health;
 355}
 356
 357static int axp288_charger_usb_set_property(struct power_supply *psy,
 358                                    enum power_supply_property psp,
 359                                    const union power_supply_propval *val)
 360{
 361        struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
 362        int ret = 0;
 363        int scaled_val;
 364
 365        switch (psp) {
 366        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 367                scaled_val = min(val->intval, info->max_cc);
 368                scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
 369                ret = axp288_charger_set_cc(info, scaled_val);
 370                if (ret < 0)
 371                        dev_warn(&info->pdev->dev, "set charge current failed\n");
 372                break;
 373        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 374                scaled_val = min(val->intval, info->max_cv);
 375                scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
 376                ret = axp288_charger_set_cv(info, scaled_val);
 377                if (ret < 0)
 378                        dev_warn(&info->pdev->dev, "set charge voltage failed\n");
 379                break;
 380        case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
 381                ret = axp288_charger_set_vbus_inlmt(info, val->intval);
 382                if (ret < 0)
 383                        dev_warn(&info->pdev->dev, "set input current limit failed\n");
 384                break;
 385        default:
 386                ret = -EINVAL;
 387        }
 388
 389        return ret;
 390}
 391
 392static int axp288_charger_usb_get_property(struct power_supply *psy,
 393                                    enum power_supply_property psp,
 394                                    union power_supply_propval *val)
 395{
 396        struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
 397        int ret;
 398
 399        switch (psp) {
 400        case POWER_SUPPLY_PROP_PRESENT:
 401                /* Check for OTG case first */
 402                if (info->otg.id_short) {
 403                        val->intval = 0;
 404                        break;
 405                }
 406                ret = axp288_charger_is_present(info);
 407                if (ret < 0)
 408                        return ret;
 409                val->intval = ret;
 410                break;
 411        case POWER_SUPPLY_PROP_ONLINE:
 412                /* Check for OTG case first */
 413                if (info->otg.id_short) {
 414                        val->intval = 0;
 415                        break;
 416                }
 417                ret = axp288_charger_is_online(info);
 418                if (ret < 0)
 419                        return ret;
 420                val->intval = ret;
 421                break;
 422        case POWER_SUPPLY_PROP_HEALTH:
 423                val->intval = axp288_get_charger_health(info);
 424                break;
 425        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 426                val->intval = info->cc * 1000;
 427                break;
 428        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
 429                val->intval = info->max_cc * 1000;
 430                break;
 431        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 432                val->intval = info->cv * 1000;
 433                break;
 434        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
 435                val->intval = info->max_cv * 1000;
 436                break;
 437        case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
 438                ret = axp288_charger_get_vbus_inlmt(info);
 439                if (ret < 0)
 440                        return ret;
 441                val->intval = ret;
 442                break;
 443        default:
 444                return -EINVAL;
 445        }
 446
 447        return 0;
 448}
 449
 450static int axp288_charger_property_is_writeable(struct power_supply *psy,
 451                enum power_supply_property psp)
 452{
 453        int ret;
 454
 455        switch (psp) {
 456        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 457        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 458        case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
 459                ret = 1;
 460                break;
 461        default:
 462                ret = 0;
 463        }
 464
 465        return ret;
 466}
 467
 468static enum power_supply_property axp288_usb_props[] = {
 469        POWER_SUPPLY_PROP_PRESENT,
 470        POWER_SUPPLY_PROP_ONLINE,
 471        POWER_SUPPLY_PROP_TYPE,
 472        POWER_SUPPLY_PROP_HEALTH,
 473        POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
 474        POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
 475        POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
 476        POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
 477        POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
 478};
 479
 480static const struct power_supply_desc axp288_charger_desc = {
 481        .name                   = "axp288_charger",
 482        .type                   = POWER_SUPPLY_TYPE_USB,
 483        .properties             = axp288_usb_props,
 484        .num_properties         = ARRAY_SIZE(axp288_usb_props),
 485        .get_property           = axp288_charger_usb_get_property,
 486        .set_property           = axp288_charger_usb_set_property,
 487        .property_is_writeable  = axp288_charger_property_is_writeable,
 488};
 489
 490static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev)
 491{
 492        struct axp288_chrg_info *info = dev;
 493        int i;
 494
 495        for (i = 0; i < CHRG_INTR_END; i++) {
 496                if (info->irq[i] == irq)
 497                        break;
 498        }
 499
 500        if (i >= CHRG_INTR_END) {
 501                dev_warn(&info->pdev->dev, "spurious interrupt!!\n");
 502                return IRQ_NONE;
 503        }
 504
 505        switch (i) {
 506        case VBUS_OV_IRQ:
 507                dev_dbg(&info->pdev->dev, "VBUS Over Voltage INTR\n");
 508                break;
 509        case CHARGE_DONE_IRQ:
 510                dev_dbg(&info->pdev->dev, "Charging Done INTR\n");
 511                break;
 512        case CHARGE_CHARGING_IRQ:
 513                dev_dbg(&info->pdev->dev, "Start Charging IRQ\n");
 514                break;
 515        case BAT_SAFE_QUIT_IRQ:
 516                dev_dbg(&info->pdev->dev,
 517                        "Quit Safe Mode(restart timer) Charging IRQ\n");
 518                break;
 519        case BAT_SAFE_ENTER_IRQ:
 520                dev_dbg(&info->pdev->dev,
 521                        "Enter Safe Mode(timer expire) Charging IRQ\n");
 522                break;
 523        case QCBTU_IRQ:
 524                dev_dbg(&info->pdev->dev,
 525                        "Quit Battery Under Temperature(CHRG) INTR\n");
 526                break;
 527        case CBTU_IRQ:
 528                dev_dbg(&info->pdev->dev,
 529                        "Hit Battery Under Temperature(CHRG) INTR\n");
 530                break;
 531        case QCBTO_IRQ:
 532                dev_dbg(&info->pdev->dev,
 533                        "Quit Battery Over Temperature(CHRG) INTR\n");
 534                break;
 535        case CBTO_IRQ:
 536                dev_dbg(&info->pdev->dev,
 537                        "Hit Battery Over Temperature(CHRG) INTR\n");
 538                break;
 539        default:
 540                dev_warn(&info->pdev->dev, "Spurious Interrupt!!!\n");
 541                goto out;
 542        }
 543
 544        power_supply_changed(info->psy_usb);
 545out:
 546        return IRQ_HANDLED;
 547}
 548
 549/*
 550 * The HP Pavilion x2 10 series comes in a number of variants:
 551 * Bay Trail SoC    + AXP288 PMIC, DMI_BOARD_NAME: "815D"
 552 * Cherry Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "813E"
 553 * Cherry Trail SoC + TI PMIC,     DMI_BOARD_NAME: "827C" or "82F4"
 554 *
 555 * The variants with the AXP288 PMIC are all kinds of special:
 556 *
 557 * 1. All variants use a Type-C connector which the AXP288 does not support, so
 558 * when using a Type-C charger it is not recognized. Unlike most AXP288 devices,
 559 * this model actually has mostly working ACPI AC / Battery code, the ACPI code
 560 * "solves" this by simply setting the input_current_limit to 3A.
 561 * There are still some issues with the ACPI code, so we use this native driver,
 562 * and to solve the charging not working (500mA is not enough) issue we hardcode
 563 * the 3A input_current_limit like the ACPI code does.
 564 *
 565 * 2. If no charger is connected the machine boots with the vbus-path disabled.
 566 * Normally this is done when a 5V boost converter is active to avoid the PMIC
 567 * trying to charge from the 5V boost converter's output. This is done when
 568 * an OTG host cable is inserted and the ID pin on the micro-B receptacle is
 569 * pulled low and the ID pin has an ACPI event handler associated with it
 570 * which re-enables the vbus-path when the ID pin is pulled high when the
 571 * OTG host cable is removed. The Type-C connector has no ID pin, there is
 572 * no ID pin handler and there appears to be no 5V boost converter, so we
 573 * end up not charging because the vbus-path is disabled, until we unplug
 574 * the charger which automatically clears the vbus-path disable bit and then
 575 * on the second plug-in of the adapter we start charging. To solve the not
 576 * charging on first charger plugin we unconditionally enable the vbus-path at
 577 * probe on this model, which is safe since there is no 5V boost converter.
 578 */
 579static const struct dmi_system_id axp288_hp_x2_dmi_ids[] = {
 580        {
 581                /*
 582                 * Bay Trail model has "Hewlett-Packard" as sys_vendor, Cherry
 583                 * Trail model has "HP", so we only match on product_name.
 584                 */
 585                .matches = {
 586                        DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
 587                },
 588        },
 589        {} /* Terminating entry */
 590};
 591
 592static void axp288_charger_extcon_evt_worker(struct work_struct *work)
 593{
 594        struct axp288_chrg_info *info =
 595            container_of(work, struct axp288_chrg_info, cable.work);
 596        int ret, current_limit;
 597        struct extcon_dev *edev = info->cable.edev;
 598        unsigned int val;
 599
 600        ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
 601        if (ret < 0) {
 602                dev_err(&info->pdev->dev, "Error reading status (%d)\n", ret);
 603                return;
 604        }
 605
 606        /* Offline? Disable charging and bail */
 607        if (!(val & PS_STAT_VBUS_VALID)) {
 608                dev_dbg(&info->pdev->dev, "USB charger disconnected\n");
 609                axp288_charger_enable_charger(info, false);
 610                power_supply_changed(info->psy_usb);
 611                return;
 612        }
 613
 614        /* Determine cable/charger type */
 615        if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
 616                /* See comment above axp288_hp_x2_dmi_ids declaration */
 617                dev_dbg(&info->pdev->dev, "HP X2 with Type-C, setting inlmt to 3A\n");
 618                current_limit = 3000000;
 619        } else if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
 620                dev_dbg(&info->pdev->dev, "USB SDP charger is connected\n");
 621                current_limit = 500000;
 622        } else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
 623                dev_dbg(&info->pdev->dev, "USB CDP charger is connected\n");
 624                current_limit = 1500000;
 625        } else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {
 626                dev_dbg(&info->pdev->dev, "USB DCP charger is connected\n");
 627                current_limit = 2000000;
 628        } else {
 629                /* Charger type detection still in progress, bail. */
 630                return;
 631        }
 632
 633        /* Set vbus current limit first, then enable charger */
 634        ret = axp288_charger_set_vbus_inlmt(info, current_limit);
 635        if (ret == 0)
 636                axp288_charger_enable_charger(info, true);
 637        else
 638                dev_err(&info->pdev->dev,
 639                        "error setting current limit (%d)\n", ret);
 640
 641        power_supply_changed(info->psy_usb);
 642}
 643
 644static int axp288_charger_handle_cable_evt(struct notifier_block *nb,
 645                                           unsigned long event, void *param)
 646{
 647        struct axp288_chrg_info *info =
 648                container_of(nb, struct axp288_chrg_info, cable.nb);
 649        schedule_work(&info->cable.work);
 650        return NOTIFY_OK;
 651}
 652
 653static void axp288_charger_otg_evt_worker(struct work_struct *work)
 654{
 655        struct axp288_chrg_info *info =
 656            container_of(work, struct axp288_chrg_info, otg.work);
 657        struct extcon_dev *edev = info->otg.cable;
 658        int ret, usb_host = extcon_get_state(edev, EXTCON_USB_HOST);
 659
 660        dev_dbg(&info->pdev->dev, "external connector USB-Host is %s\n",
 661                                usb_host ? "attached" : "detached");
 662
 663        /*
 664         * Set usb_id_short flag to avoid running charger detection logic
 665         * in case usb host.
 666         */
 667        info->otg.id_short = usb_host;
 668
 669        /* Disable VBUS path before enabling the 5V boost */
 670        ret = axp288_charger_vbus_path_select(info, !info->otg.id_short);
 671        if (ret < 0)
 672                dev_warn(&info->pdev->dev, "vbus path disable failed\n");
 673}
 674
 675static int axp288_charger_handle_otg_evt(struct notifier_block *nb,
 676                                   unsigned long event, void *param)
 677{
 678        struct axp288_chrg_info *info =
 679            container_of(nb, struct axp288_chrg_info, otg.id_nb);
 680
 681        schedule_work(&info->otg.work);
 682
 683        return NOTIFY_OK;
 684}
 685
 686static int charger_init_hw_regs(struct axp288_chrg_info *info)
 687{
 688        int ret, cc, cv;
 689        unsigned int val;
 690
 691        /* Program temperature thresholds */
 692        ret = regmap_write(info->regmap, AXP20X_V_LTF_CHRG, CHRG_VLTFC_0C);
 693        if (ret < 0) {
 694                dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
 695                                                        AXP20X_V_LTF_CHRG, ret);
 696                return ret;
 697        }
 698
 699        ret = regmap_write(info->regmap, AXP20X_V_HTF_CHRG, CHRG_VHTFC_45C);
 700        if (ret < 0) {
 701                dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
 702                                                        AXP20X_V_HTF_CHRG, ret);
 703                return ret;
 704        }
 705
 706        /* Do not turn-off charger o/p after charge cycle ends */
 707        ret = regmap_update_bits(info->regmap,
 708                                AXP20X_CHRG_CTRL2,
 709                                CNTL2_CHG_OUT_TURNON, CNTL2_CHG_OUT_TURNON);
 710        if (ret < 0) {
 711                dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
 712                                                AXP20X_CHRG_CTRL2, ret);
 713                return ret;
 714        }
 715
 716        /* Setup ending condition for charging to be 10% of I(chrg) */
 717        ret = regmap_update_bits(info->regmap,
 718                                AXP20X_CHRG_CTRL1,
 719                                CHRG_CCCV_ITERM_20P, 0);
 720        if (ret < 0) {
 721                dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
 722                                                AXP20X_CHRG_CTRL1, ret);
 723                return ret;
 724        }
 725
 726        /* Disable OCV-SOC curve calibration */
 727        ret = regmap_update_bits(info->regmap,
 728                                AXP20X_CC_CTRL,
 729                                FG_CNTL_OCV_ADJ_EN, 0);
 730        if (ret < 0) {
 731                dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
 732                                                AXP20X_CC_CTRL, ret);
 733                return ret;
 734        }
 735
 736        if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
 737                /* See comment above axp288_hp_x2_dmi_ids declaration */
 738                ret = axp288_charger_vbus_path_select(info, true);
 739                if (ret < 0)
 740                        return ret;
 741        }
 742
 743        /* Read current charge voltage and current limit */
 744        ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val);
 745        if (ret < 0) {
 746                dev_err(&info->pdev->dev, "register(%x) read error(%d)\n",
 747                        AXP20X_CHRG_CTRL1, ret);
 748                return ret;
 749        }
 750
 751        /* Determine charge voltage */
 752        cv = (val & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS;
 753        switch (cv) {
 754        case CHRG_CCCV_CV_4100MV:
 755                info->cv = CV_4100MV;
 756                break;
 757        case CHRG_CCCV_CV_4150MV:
 758                info->cv = CV_4150MV;
 759                break;
 760        case CHRG_CCCV_CV_4200MV:
 761                info->cv = CV_4200MV;
 762                break;
 763        case CHRG_CCCV_CV_4350MV:
 764                info->cv = CV_4350MV;
 765                break;
 766        }
 767
 768        /* Determine charge current limit */
 769        cc = (val & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS;
 770        cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
 771        info->cc = cc;
 772
 773        /*
 774         * Do not allow the user to configure higher settings then those
 775         * set by the firmware
 776         */
 777        info->max_cv = info->cv;
 778        info->max_cc = info->cc;
 779
 780        return 0;
 781}
 782
 783static void axp288_charger_cancel_work(void *data)
 784{
 785        struct axp288_chrg_info *info = data;
 786
 787        cancel_work_sync(&info->otg.work);
 788        cancel_work_sync(&info->cable.work);
 789}
 790
 791static int axp288_charger_probe(struct platform_device *pdev)
 792{
 793        int ret, i, pirq;
 794        struct axp288_chrg_info *info;
 795        struct device *dev = &pdev->dev;
 796        struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
 797        struct power_supply_config charger_cfg = {};
 798        unsigned int val;
 799
 800        /*
 801         * On some devices the fuelgauge and charger parts of the axp288 are
 802         * not used, check that the fuelgauge is enabled (CC_CTRL != 0).
 803         */
 804        ret = regmap_read(axp20x->regmap, AXP20X_CC_CTRL, &val);
 805        if (ret < 0)
 806                return ret;
 807        if (val == 0)
 808                return -ENODEV;
 809
 810        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 811        if (!info)
 812                return -ENOMEM;
 813
 814        info->pdev = pdev;
 815        info->regmap = axp20x->regmap;
 816        info->regmap_irqc = axp20x->regmap_irqc;
 817
 818        info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME);
 819        if (info->cable.edev == NULL) {
 820                dev_dbg(&pdev->dev, "%s is not ready, probe deferred\n",
 821                        AXP288_EXTCON_DEV_NAME);
 822                return -EPROBE_DEFER;
 823        }
 824
 825        if (acpi_dev_present(USB_HOST_EXTCON_HID, NULL, -1)) {
 826                info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_NAME);
 827                if (info->otg.cable == NULL) {
 828                        dev_dbg(dev, "EXTCON_USB_HOST is not ready, probe deferred\n");
 829                        return -EPROBE_DEFER;
 830                }
 831                dev_info(&pdev->dev,
 832                         "Using " USB_HOST_EXTCON_HID " extcon for usb-id\n");
 833        }
 834
 835        platform_set_drvdata(pdev, info);
 836
 837        ret = charger_init_hw_regs(info);
 838        if (ret)
 839                return ret;
 840
 841        /* Register with power supply class */
 842        charger_cfg.drv_data = info;
 843        info->psy_usb = devm_power_supply_register(dev, &axp288_charger_desc,
 844                                                   &charger_cfg);
 845        if (IS_ERR(info->psy_usb)) {
 846                ret = PTR_ERR(info->psy_usb);
 847                dev_err(dev, "failed to register power supply: %d\n", ret);
 848                return ret;
 849        }
 850
 851        /* Cancel our work on cleanup, register this before the notifiers */
 852        ret = devm_add_action(dev, axp288_charger_cancel_work, info);
 853        if (ret)
 854                return ret;
 855
 856        /* Register for extcon notification */
 857        INIT_WORK(&info->cable.work, axp288_charger_extcon_evt_worker);
 858        info->cable.nb.notifier_call = axp288_charger_handle_cable_evt;
 859        ret = devm_extcon_register_notifier_all(dev, info->cable.edev,
 860                                                &info->cable.nb);
 861        if (ret) {
 862                dev_err(dev, "failed to register cable extcon notifier\n");
 863                return ret;
 864        }
 865        schedule_work(&info->cable.work);
 866
 867        /* Register for OTG notification */
 868        INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker);
 869        info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt;
 870        if (info->otg.cable) {
 871                ret = devm_extcon_register_notifier(&pdev->dev, info->otg.cable,
 872                                        EXTCON_USB_HOST, &info->otg.id_nb);
 873                if (ret) {
 874                        dev_err(dev, "failed to register EXTCON_USB_HOST notifier\n");
 875                        return ret;
 876                }
 877                schedule_work(&info->otg.work);
 878        }
 879
 880        /* Register charger interrupts */
 881        for (i = 0; i < CHRG_INTR_END; i++) {
 882                pirq = platform_get_irq(info->pdev, i);
 883                if (pirq < 0)
 884                        return pirq;
 885
 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                        return info->irq[i];
 891                }
 892                ret = devm_request_threaded_irq(&info->pdev->dev, info->irq[i],
 893                                        NULL, axp288_charger_irq_thread_handler,
 894                                        IRQF_ONESHOT, info->pdev->name, info);
 895                if (ret) {
 896                        dev_err(&pdev->dev, "failed to request interrupt=%d\n",
 897                                                                info->irq[i]);
 898                        return ret;
 899                }
 900        }
 901
 902        return 0;
 903}
 904
 905static const struct platform_device_id axp288_charger_id_table[] = {
 906        { .name = "axp288_charger" },
 907        {},
 908};
 909MODULE_DEVICE_TABLE(platform, axp288_charger_id_table);
 910
 911static struct platform_driver axp288_charger_driver = {
 912        .probe = axp288_charger_probe,
 913        .id_table = axp288_charger_id_table,
 914        .driver = {
 915                .name = "axp288_charger",
 916        },
 917};
 918
 919module_platform_driver(axp288_charger_driver);
 920
 921MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
 922MODULE_DESCRIPTION("X-power AXP288 Charger Driver");
 923MODULE_LICENSE("GPL v2");
 924