root/drivers/power/supply/axp288_charger.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. axp288_charger_set_cc
  2. axp288_charger_set_cv
  3. axp288_charger_get_vbus_inlmt
  4. axp288_charger_set_vbus_inlmt
  5. axp288_charger_vbus_path_select
  6. axp288_charger_enable_charger
  7. axp288_charger_is_present
  8. axp288_charger_is_online
  9. axp288_get_charger_health
  10. axp288_charger_usb_set_property
  11. axp288_charger_usb_get_property
  12. axp288_charger_property_is_writeable
  13. axp288_charger_irq_thread_handler
  14. axp288_charger_extcon_evt_worker
  15. axp288_charger_handle_cable_evt
  16. axp288_charger_otg_evt_worker
  17. axp288_charger_handle_otg_evt
  18. charger_init_hw_regs
  19. axp288_charger_cancel_work
  20. axp288_charger_probe

   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 
 102 enum {
 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 
 115 struct 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 
 143 static 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 
 166 static 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 
 197 static 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 
 230 static 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 
 263 static 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 
 281 static 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 
 298 static 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 
 312 static 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 
 326 static 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 
 353 health_read_fail:
 354         return health;
 355 }
 356 
 357 static 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 
 392 static 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 
 450 static 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 
 468 static 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 
 480 static 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 
 490 static 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);
 545 out:
 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  */
 579 static 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 
 592 static 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 
 644 static 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 
 653 static 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 
 675 static 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 
 686 static 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 
 783 static 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 
 791 static 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                         dev_err(&pdev->dev, "Failed to get IRQ: %d\n", pirq);
 885                         return pirq;
 886                 }
 887                 info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
 888                 if (info->irq[i] < 0) {
 889                         dev_warn(&info->pdev->dev,
 890                                 "failed to get virtual interrupt=%d\n", pirq);
 891                         return info->irq[i];
 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                         return ret;
 900                 }
 901         }
 902 
 903         return 0;
 904 }
 905 
 906 static const struct platform_device_id axp288_charger_id_table[] = {
 907         { .name = "axp288_charger" },
 908         {},
 909 };
 910 MODULE_DEVICE_TABLE(platform, axp288_charger_id_table);
 911 
 912 static struct platform_driver axp288_charger_driver = {
 913         .probe = axp288_charger_probe,
 914         .id_table = axp288_charger_id_table,
 915         .driver = {
 916                 .name = "axp288_charger",
 917         },
 918 };
 919 
 920 module_platform_driver(axp288_charger_driver);
 921 
 922 MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
 923 MODULE_DESCRIPTION("X-power AXP288 Charger Driver");
 924 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */