Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * axp288_charger.c - X-power AXP288 PMIC Charger driver
0004  *
0005  * Copyright (C) 2016-2017 Hans de Goede <hdegoede@redhat.com>
0006  * Copyright (C) 2014 Intel Corporation
0007  * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
0008  */
0009 
0010 #include <linux/acpi.h>
0011 #include <linux/bitops.h>
0012 #include <linux/module.h>
0013 #include <linux/device.h>
0014 #include <linux/regmap.h>
0015 #include <linux/workqueue.h>
0016 #include <linux/delay.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/usb/otg.h>
0019 #include <linux/notifier.h>
0020 #include <linux/power_supply.h>
0021 #include <linux/property.h>
0022 #include <linux/mfd/axp20x.h>
0023 #include <linux/extcon.h>
0024 #include <linux/dmi.h>
0025 #include <asm/iosf_mbi.h>
0026 
0027 #define PS_STAT_VBUS_TRIGGER        BIT(0)
0028 #define PS_STAT_BAT_CHRG_DIR        BIT(2)
0029 #define PS_STAT_VBAT_ABOVE_VHOLD    BIT(3)
0030 #define PS_STAT_VBUS_VALID      BIT(4)
0031 #define PS_STAT_VBUS_PRESENT        BIT(5)
0032 
0033 #define CHRG_STAT_BAT_SAFE_MODE     BIT(3)
0034 #define CHRG_STAT_BAT_VALID     BIT(4)
0035 #define CHRG_STAT_BAT_PRESENT       BIT(5)
0036 #define CHRG_STAT_CHARGING      BIT(6)
0037 #define CHRG_STAT_PMIC_OTP      BIT(7)
0038 
0039 #define VBUS_ISPOUT_CUR_LIM_MASK    0x03
0040 #define VBUS_ISPOUT_CUR_LIM_BIT_POS 0
0041 #define VBUS_ISPOUT_CUR_LIM_900MA   0x0 /* 900mA */
0042 #define VBUS_ISPOUT_CUR_LIM_1500MA  0x1 /* 1500mA */
0043 #define VBUS_ISPOUT_CUR_LIM_2000MA  0x2 /* 2000mA */
0044 #define VBUS_ISPOUT_CUR_NO_LIM      0x3 /* 2500mA */
0045 #define VBUS_ISPOUT_VHOLD_SET_MASK  0x38
0046 #define VBUS_ISPOUT_VHOLD_SET_BIT_POS   0x3
0047 #define VBUS_ISPOUT_VHOLD_SET_OFFSET    4000    /* 4000mV */
0048 #define VBUS_ISPOUT_VHOLD_SET_LSB_RES   100 /* 100mV */
0049 #define VBUS_ISPOUT_VHOLD_SET_4400MV    0x4 /* 4400mV */
0050 #define VBUS_ISPOUT_VBUS_PATH_DIS   BIT(7)
0051 
0052 #define CHRG_CCCV_CC_MASK       0xf     /* 4 bits */
0053 #define CHRG_CCCV_CC_BIT_POS        0
0054 #define CHRG_CCCV_CC_OFFSET     200     /* 200mA */
0055 #define CHRG_CCCV_CC_LSB_RES        200     /* 200mA */
0056 #define CHRG_CCCV_ITERM_20P     BIT(4)      /* 20% of CC */
0057 #define CHRG_CCCV_CV_MASK       0x60        /* 2 bits */
0058 #define CHRG_CCCV_CV_BIT_POS        5
0059 #define CHRG_CCCV_CV_4100MV     0x0     /* 4.10V */
0060 #define CHRG_CCCV_CV_4150MV     0x1     /* 4.15V */
0061 #define CHRG_CCCV_CV_4200MV     0x2     /* 4.20V */
0062 #define CHRG_CCCV_CV_4350MV     0x3     /* 4.35V */
0063 #define CHRG_CCCV_CHG_EN        BIT(7)
0064 
0065 #define CNTL2_CC_TIMEOUT_MASK       0x3 /* 2 bits */
0066 #define CNTL2_CC_TIMEOUT_OFFSET     6   /* 6 Hrs */
0067 #define CNTL2_CC_TIMEOUT_LSB_RES    2   /* 2 Hrs */
0068 #define CNTL2_CC_TIMEOUT_12HRS      0x3 /* 12 Hrs */
0069 #define CNTL2_CHGLED_TYPEB      BIT(4)
0070 #define CNTL2_CHG_OUT_TURNON        BIT(5)
0071 #define CNTL2_PC_TIMEOUT_MASK       0xC0
0072 #define CNTL2_PC_TIMEOUT_OFFSET     40  /* 40 mins */
0073 #define CNTL2_PC_TIMEOUT_LSB_RES    10  /* 10 mins */
0074 #define CNTL2_PC_TIMEOUT_70MINS     0x3
0075 
0076 #define CHRG_ILIM_TEMP_LOOP_EN      BIT(3)
0077 #define CHRG_VBUS_ILIM_MASK     0xf0
0078 #define CHRG_VBUS_ILIM_BIT_POS      4
0079 #define CHRG_VBUS_ILIM_100MA        0x0 /* 100mA */
0080 #define CHRG_VBUS_ILIM_500MA        0x1 /* 500mA */
0081 #define CHRG_VBUS_ILIM_900MA        0x2 /* 900mA */
0082 #define CHRG_VBUS_ILIM_1500MA       0x3 /* 1500mA */
0083 #define CHRG_VBUS_ILIM_2000MA       0x4 /* 2000mA */
0084 #define CHRG_VBUS_ILIM_2500MA       0x5 /* 2500mA */
0085 #define CHRG_VBUS_ILIM_3000MA       0x6 /* 3000mA */
0086 #define CHRG_VBUS_ILIM_3500MA       0x7 /* 3500mA */
0087 #define CHRG_VBUS_ILIM_4000MA       0x8 /* 4000mA */
0088 
0089 #define CHRG_VLTFC_0C           0xA5    /* 0 DegC */
0090 #define CHRG_VHTFC_45C          0x1F    /* 45 DegC */
0091 
0092 #define FG_CNTL_OCV_ADJ_EN      BIT(3)
0093 
0094 #define CV_4100MV           4100    /* 4100mV */
0095 #define CV_4150MV           4150    /* 4150mV */
0096 #define CV_4200MV           4200    /* 4200mV */
0097 #define CV_4350MV           4350    /* 4350mV */
0098 
0099 #define AXP288_REG_UPDATE_INTERVAL  (60 * HZ)
0100 
0101 #define AXP288_EXTCON_DEV_NAME      "axp288_extcon"
0102 #define USB_HOST_EXTCON_HID     "INT3496"
0103 #define USB_HOST_EXTCON_NAME        "INT3496:00"
0104 
0105 enum {
0106     VBUS_OV_IRQ = 0,
0107     CHARGE_DONE_IRQ,
0108     CHARGE_CHARGING_IRQ,
0109     BAT_SAFE_QUIT_IRQ,
0110     BAT_SAFE_ENTER_IRQ,
0111     QCBTU_IRQ,
0112     CBTU_IRQ,
0113     QCBTO_IRQ,
0114     CBTO_IRQ,
0115     CHRG_INTR_END,
0116 };
0117 
0118 struct axp288_chrg_info {
0119     struct platform_device *pdev;
0120     struct regmap *regmap;
0121     struct regmap_irq_chip_data *regmap_irqc;
0122     int irq[CHRG_INTR_END];
0123     struct power_supply *psy_usb;
0124     struct mutex lock;
0125 
0126     /* OTG/Host mode */
0127     struct {
0128         struct work_struct work;
0129         struct extcon_dev *cable;
0130         struct notifier_block id_nb;
0131         bool id_short;
0132     } otg;
0133 
0134     /* SDP/CDP/DCP USB charging cable notifications */
0135     struct {
0136         struct extcon_dev *edev;
0137         struct notifier_block nb;
0138         struct work_struct work;
0139     } cable;
0140 
0141     int cc;
0142     int cv;
0143     int max_cc;
0144     int max_cv;
0145 
0146     unsigned long last_updated;
0147     unsigned int input_status;
0148     unsigned int op_mode;
0149     unsigned int backend_control;
0150     bool valid;
0151 };
0152 
0153 static inline int axp288_charger_set_cc(struct axp288_chrg_info *info, int cc)
0154 {
0155     u8 reg_val;
0156     int ret;
0157 
0158     if (cc < CHRG_CCCV_CC_OFFSET)
0159         cc = CHRG_CCCV_CC_OFFSET;
0160     else if (cc > info->max_cc)
0161         cc = info->max_cc;
0162 
0163     reg_val = (cc - CHRG_CCCV_CC_OFFSET) / CHRG_CCCV_CC_LSB_RES;
0164     cc = (reg_val * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
0165     reg_val = reg_val << CHRG_CCCV_CC_BIT_POS;
0166 
0167     ret = regmap_update_bits(info->regmap,
0168                 AXP20X_CHRG_CTRL1,
0169                 CHRG_CCCV_CC_MASK, reg_val);
0170     if (ret >= 0)
0171         info->cc = cc;
0172 
0173     return ret;
0174 }
0175 
0176 static inline int axp288_charger_set_cv(struct axp288_chrg_info *info, int cv)
0177 {
0178     u8 reg_val;
0179     int ret;
0180 
0181     if (cv <= CV_4100MV) {
0182         reg_val = CHRG_CCCV_CV_4100MV;
0183         cv = CV_4100MV;
0184     } else if (cv <= CV_4150MV) {
0185         reg_val = CHRG_CCCV_CV_4150MV;
0186         cv = CV_4150MV;
0187     } else if (cv <= CV_4200MV) {
0188         reg_val = CHRG_CCCV_CV_4200MV;
0189         cv = CV_4200MV;
0190     } else {
0191         reg_val = CHRG_CCCV_CV_4350MV;
0192         cv = CV_4350MV;
0193     }
0194 
0195     reg_val = reg_val << CHRG_CCCV_CV_BIT_POS;
0196 
0197     ret = regmap_update_bits(info->regmap,
0198                 AXP20X_CHRG_CTRL1,
0199                 CHRG_CCCV_CV_MASK, reg_val);
0200 
0201     if (ret >= 0)
0202         info->cv = cv;
0203 
0204     return ret;
0205 }
0206 
0207 static int axp288_charger_get_vbus_inlmt(struct axp288_chrg_info *info)
0208 {
0209     unsigned int val;
0210 
0211     val = info->backend_control;
0212 
0213     val >>= CHRG_VBUS_ILIM_BIT_POS;
0214     switch (val) {
0215     case CHRG_VBUS_ILIM_100MA:
0216         return 100000;
0217     case CHRG_VBUS_ILIM_500MA:
0218         return 500000;
0219     case CHRG_VBUS_ILIM_900MA:
0220         return 900000;
0221     case CHRG_VBUS_ILIM_1500MA:
0222         return 1500000;
0223     case CHRG_VBUS_ILIM_2000MA:
0224         return 2000000;
0225     case CHRG_VBUS_ILIM_2500MA:
0226         return 2500000;
0227     case CHRG_VBUS_ILIM_3000MA:
0228         return 3000000;
0229     case CHRG_VBUS_ILIM_3500MA:
0230         return 3500000;
0231     default:
0232         /* All b1xxx values map to 4000 mA */
0233         return 4000000;
0234     }
0235 }
0236 
0237 static inline int axp288_charger_set_vbus_inlmt(struct axp288_chrg_info *info,
0238                        int inlmt)
0239 {
0240     int ret;
0241     u8 reg_val;
0242 
0243     if (inlmt >= 4000000)
0244         reg_val = CHRG_VBUS_ILIM_4000MA << CHRG_VBUS_ILIM_BIT_POS;
0245     else if (inlmt >= 3500000)
0246         reg_val = CHRG_VBUS_ILIM_3500MA << CHRG_VBUS_ILIM_BIT_POS;
0247     else if (inlmt >= 3000000)
0248         reg_val = CHRG_VBUS_ILIM_3000MA << CHRG_VBUS_ILIM_BIT_POS;
0249     else if (inlmt >= 2500000)
0250         reg_val = CHRG_VBUS_ILIM_2500MA << CHRG_VBUS_ILIM_BIT_POS;
0251     else if (inlmt >= 2000000)
0252         reg_val = CHRG_VBUS_ILIM_2000MA << CHRG_VBUS_ILIM_BIT_POS;
0253     else if (inlmt >= 1500000)
0254         reg_val = CHRG_VBUS_ILIM_1500MA << CHRG_VBUS_ILIM_BIT_POS;
0255     else if (inlmt >= 900000)
0256         reg_val = CHRG_VBUS_ILIM_900MA << CHRG_VBUS_ILIM_BIT_POS;
0257     else if (inlmt >= 500000)
0258         reg_val = CHRG_VBUS_ILIM_500MA << CHRG_VBUS_ILIM_BIT_POS;
0259     else
0260         reg_val = CHRG_VBUS_ILIM_100MA << CHRG_VBUS_ILIM_BIT_POS;
0261 
0262     ret = regmap_update_bits(info->regmap, AXP20X_CHRG_BAK_CTRL,
0263                  CHRG_VBUS_ILIM_MASK, reg_val);
0264     if (ret < 0)
0265         dev_err(&info->pdev->dev, "charger BAK control %d\n", ret);
0266 
0267     return ret;
0268 }
0269 
0270 static int axp288_charger_vbus_path_select(struct axp288_chrg_info *info,
0271                                 bool enable)
0272 {
0273     int ret;
0274 
0275     if (enable)
0276         ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
0277                     VBUS_ISPOUT_VBUS_PATH_DIS, 0);
0278     else
0279         ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
0280             VBUS_ISPOUT_VBUS_PATH_DIS, VBUS_ISPOUT_VBUS_PATH_DIS);
0281 
0282     if (ret < 0)
0283         dev_err(&info->pdev->dev, "axp288 vbus path select %d\n", ret);
0284 
0285     return ret;
0286 }
0287 
0288 static int axp288_charger_enable_charger(struct axp288_chrg_info *info,
0289                                 bool enable)
0290 {
0291     int ret;
0292 
0293     if (enable)
0294         ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
0295                 CHRG_CCCV_CHG_EN, CHRG_CCCV_CHG_EN);
0296     else
0297         ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1,
0298                 CHRG_CCCV_CHG_EN, 0);
0299     if (ret < 0)
0300         dev_err(&info->pdev->dev, "axp288 enable charger %d\n", ret);
0301 
0302     return ret;
0303 }
0304 
0305 static int axp288_get_charger_health(struct axp288_chrg_info *info)
0306 {
0307     if (!(info->input_status & PS_STAT_VBUS_PRESENT))
0308         return POWER_SUPPLY_HEALTH_UNKNOWN;
0309 
0310     if (!(info->input_status & PS_STAT_VBUS_VALID))
0311         return POWER_SUPPLY_HEALTH_DEAD;
0312     else if (info->op_mode & CHRG_STAT_PMIC_OTP)
0313         return POWER_SUPPLY_HEALTH_OVERHEAT;
0314     else if (info->op_mode & CHRG_STAT_BAT_SAFE_MODE)
0315         return POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
0316     else
0317         return POWER_SUPPLY_HEALTH_GOOD;
0318 }
0319 
0320 static int axp288_charger_usb_set_property(struct power_supply *psy,
0321                     enum power_supply_property psp,
0322                     const union power_supply_propval *val)
0323 {
0324     struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
0325     int ret = 0;
0326     int scaled_val;
0327 
0328     mutex_lock(&info->lock);
0329     switch (psp) {
0330     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
0331         scaled_val = min(val->intval, info->max_cc);
0332         scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
0333         ret = axp288_charger_set_cc(info, scaled_val);
0334         if (ret < 0) {
0335             dev_warn(&info->pdev->dev, "set charge current failed\n");
0336             goto out;
0337         }
0338         break;
0339     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
0340         scaled_val = min(val->intval, info->max_cv);
0341         scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
0342         ret = axp288_charger_set_cv(info, scaled_val);
0343         if (ret < 0) {
0344             dev_warn(&info->pdev->dev, "set charge voltage failed\n");
0345             goto out;
0346         }
0347         break;
0348     case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0349         ret = axp288_charger_set_vbus_inlmt(info, val->intval);
0350         if (ret < 0) {
0351             dev_warn(&info->pdev->dev, "set input current limit failed\n");
0352             goto out;
0353         }
0354         info->valid = false;
0355         break;
0356     default:
0357         ret = -EINVAL;
0358     }
0359 
0360 out:
0361     mutex_unlock(&info->lock);
0362     return ret;
0363 }
0364 
0365 static int axp288_charger_reg_readb(struct axp288_chrg_info *info, int reg, unsigned int *ret_val)
0366 {
0367     int ret;
0368 
0369     ret = regmap_read(info->regmap, reg, ret_val);
0370     if (ret < 0) {
0371         dev_err(&info->pdev->dev, "Error %d on reading value from register 0x%04x\n",
0372             ret,
0373             reg);
0374         return ret;
0375     }
0376     return 0;
0377 }
0378 
0379 static int axp288_charger_usb_update_property(struct axp288_chrg_info *info)
0380 {
0381     int ret = 0;
0382 
0383     if (info->valid && time_before(jiffies, info->last_updated + AXP288_REG_UPDATE_INTERVAL))
0384         return 0;
0385 
0386     dev_dbg(&info->pdev->dev, "Charger updating register values...\n");
0387 
0388     ret = iosf_mbi_block_punit_i2c_access();
0389     if (ret < 0)
0390         return ret;
0391 
0392     ret = axp288_charger_reg_readb(info, AXP20X_PWR_INPUT_STATUS, &info->input_status);
0393     if (ret < 0)
0394         goto out;
0395 
0396     ret = axp288_charger_reg_readb(info, AXP20X_PWR_OP_MODE, &info->op_mode);
0397     if (ret < 0)
0398         goto out;
0399 
0400     ret = axp288_charger_reg_readb(info, AXP20X_CHRG_BAK_CTRL, &info->backend_control);
0401     if (ret < 0)
0402         goto out;
0403 
0404     info->last_updated = jiffies;
0405     info->valid = true;
0406 out:
0407     iosf_mbi_unblock_punit_i2c_access();
0408     return ret;
0409 }
0410 
0411 static int axp288_charger_usb_get_property(struct power_supply *psy,
0412                     enum power_supply_property psp,
0413                     union power_supply_propval *val)
0414 {
0415     struct axp288_chrg_info *info = power_supply_get_drvdata(psy);
0416     int ret;
0417 
0418     mutex_lock(&info->lock);
0419     ret = axp288_charger_usb_update_property(info);
0420     if (ret < 0)
0421         goto out;
0422 
0423     switch (psp) {
0424     case POWER_SUPPLY_PROP_PRESENT:
0425         /* Check for OTG case first */
0426         if (info->otg.id_short) {
0427             val->intval = 0;
0428             break;
0429         }
0430         val->intval = (info->input_status & PS_STAT_VBUS_PRESENT) ? 1 : 0;
0431         break;
0432     case POWER_SUPPLY_PROP_ONLINE:
0433         /* Check for OTG case first */
0434         if (info->otg.id_short) {
0435             val->intval = 0;
0436             break;
0437         }
0438         val->intval = (info->input_status & PS_STAT_VBUS_VALID) ? 1 : 0;
0439         break;
0440     case POWER_SUPPLY_PROP_HEALTH:
0441         val->intval = axp288_get_charger_health(info);
0442         break;
0443     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
0444         val->intval = info->cc * 1000;
0445         break;
0446     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
0447         val->intval = info->max_cc * 1000;
0448         break;
0449     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
0450         val->intval = info->cv * 1000;
0451         break;
0452     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
0453         val->intval = info->max_cv * 1000;
0454         break;
0455     case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0456         val->intval = axp288_charger_get_vbus_inlmt(info);
0457         break;
0458     default:
0459         ret = -EINVAL;
0460     }
0461 
0462 out:
0463     mutex_unlock(&info->lock);
0464     return ret;
0465 }
0466 
0467 static int axp288_charger_property_is_writeable(struct power_supply *psy,
0468         enum power_supply_property psp)
0469 {
0470     int ret;
0471 
0472     switch (psp) {
0473     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
0474     case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
0475     case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0476         ret = 1;
0477         break;
0478     default:
0479         ret = 0;
0480     }
0481 
0482     return ret;
0483 }
0484 
0485 static enum power_supply_property axp288_usb_props[] = {
0486     POWER_SUPPLY_PROP_PRESENT,
0487     POWER_SUPPLY_PROP_ONLINE,
0488     POWER_SUPPLY_PROP_TYPE,
0489     POWER_SUPPLY_PROP_HEALTH,
0490     POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
0491     POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
0492     POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
0493     POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
0494     POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
0495 };
0496 
0497 static const struct power_supply_desc axp288_charger_desc = {
0498     .name           = "axp288_charger",
0499     .type           = POWER_SUPPLY_TYPE_USB,
0500     .properties     = axp288_usb_props,
0501     .num_properties     = ARRAY_SIZE(axp288_usb_props),
0502     .get_property       = axp288_charger_usb_get_property,
0503     .set_property       = axp288_charger_usb_set_property,
0504     .property_is_writeable  = axp288_charger_property_is_writeable,
0505 };
0506 
0507 static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev)
0508 {
0509     struct axp288_chrg_info *info = dev;
0510     int i;
0511 
0512     for (i = 0; i < CHRG_INTR_END; i++) {
0513         if (info->irq[i] == irq)
0514             break;
0515     }
0516 
0517     if (i >= CHRG_INTR_END) {
0518         dev_warn(&info->pdev->dev, "spurious interrupt!!\n");
0519         return IRQ_NONE;
0520     }
0521 
0522     switch (i) {
0523     case VBUS_OV_IRQ:
0524         dev_dbg(&info->pdev->dev, "VBUS Over Voltage INTR\n");
0525         break;
0526     case CHARGE_DONE_IRQ:
0527         dev_dbg(&info->pdev->dev, "Charging Done INTR\n");
0528         break;
0529     case CHARGE_CHARGING_IRQ:
0530         dev_dbg(&info->pdev->dev, "Start Charging IRQ\n");
0531         break;
0532     case BAT_SAFE_QUIT_IRQ:
0533         dev_dbg(&info->pdev->dev,
0534             "Quit Safe Mode(restart timer) Charging IRQ\n");
0535         break;
0536     case BAT_SAFE_ENTER_IRQ:
0537         dev_dbg(&info->pdev->dev,
0538             "Enter Safe Mode(timer expire) Charging IRQ\n");
0539         break;
0540     case QCBTU_IRQ:
0541         dev_dbg(&info->pdev->dev,
0542             "Quit Battery Under Temperature(CHRG) INTR\n");
0543         break;
0544     case CBTU_IRQ:
0545         dev_dbg(&info->pdev->dev,
0546             "Hit Battery Under Temperature(CHRG) INTR\n");
0547         break;
0548     case QCBTO_IRQ:
0549         dev_dbg(&info->pdev->dev,
0550             "Quit Battery Over Temperature(CHRG) INTR\n");
0551         break;
0552     case CBTO_IRQ:
0553         dev_dbg(&info->pdev->dev,
0554             "Hit Battery Over Temperature(CHRG) INTR\n");
0555         break;
0556     default:
0557         dev_warn(&info->pdev->dev, "Spurious Interrupt!!!\n");
0558         goto out;
0559     }
0560     mutex_lock(&info->lock);
0561     info->valid = false;
0562     mutex_unlock(&info->lock);
0563     power_supply_changed(info->psy_usb);
0564 out:
0565     return IRQ_HANDLED;
0566 }
0567 
0568 /*
0569  * The HP Pavilion x2 10 series comes in a number of variants:
0570  * Bay Trail SoC    + AXP288 PMIC, Micro-USB, DMI_BOARD_NAME: "8021"
0571  * Bay Trail SoC    + AXP288 PMIC, Type-C,    DMI_BOARD_NAME: "815D"
0572  * Cherry Trail SoC + AXP288 PMIC, Type-C,    DMI_BOARD_NAME: "813E"
0573  * Cherry Trail SoC + TI PMIC,     Type-C,    DMI_BOARD_NAME: "827C" or "82F4"
0574  *
0575  * The variants with the AXP288 + Type-C connector are all kinds of special:
0576  *
0577  * 1. They use a Type-C connector which the AXP288 does not support, so when
0578  * using a Type-C charger it is not recognized. Unlike most AXP288 devices,
0579  * this model actually has mostly working ACPI AC / Battery code, the ACPI code
0580  * "solves" this by simply setting the input_current_limit to 3A.
0581  * There are still some issues with the ACPI code, so we use this native driver,
0582  * and to solve the charging not working (500mA is not enough) issue we hardcode
0583  * the 3A input_current_limit like the ACPI code does.
0584  *
0585  * 2. If no charger is connected the machine boots with the vbus-path disabled.
0586  * Normally this is done when a 5V boost converter is active to avoid the PMIC
0587  * trying to charge from the 5V boost converter's output. This is done when
0588  * an OTG host cable is inserted and the ID pin on the micro-B receptacle is
0589  * pulled low and the ID pin has an ACPI event handler associated with it
0590  * which re-enables the vbus-path when the ID pin is pulled high when the
0591  * OTG host cable is removed. The Type-C connector has no ID pin, there is
0592  * no ID pin handler and there appears to be no 5V boost converter, so we
0593  * end up not charging because the vbus-path is disabled, until we unplug
0594  * the charger which automatically clears the vbus-path disable bit and then
0595  * on the second plug-in of the adapter we start charging. To solve the not
0596  * charging on first charger plugin we unconditionally enable the vbus-path at
0597  * probe on this model, which is safe since there is no 5V boost converter.
0598  */
0599 static const struct dmi_system_id axp288_hp_x2_dmi_ids[] = {
0600     {
0601         .matches = {
0602             DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
0603             DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
0604             DMI_EXACT_MATCH(DMI_BOARD_NAME, "815D"),
0605         },
0606     },
0607     {
0608         .matches = {
0609             DMI_EXACT_MATCH(DMI_SYS_VENDOR, "HP"),
0610             DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
0611             DMI_EXACT_MATCH(DMI_BOARD_NAME, "813E"),
0612         },
0613     },
0614     {} /* Terminating entry */
0615 };
0616 
0617 static void axp288_charger_extcon_evt_worker(struct work_struct *work)
0618 {
0619     struct axp288_chrg_info *info =
0620         container_of(work, struct axp288_chrg_info, cable.work);
0621     int ret, current_limit;
0622     struct extcon_dev *edev = info->cable.edev;
0623     unsigned int val;
0624 
0625     ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
0626     if (ret < 0) {
0627         dev_err(&info->pdev->dev, "Error reading status (%d)\n", ret);
0628         return;
0629     }
0630 
0631     /* Offline? Disable charging and bail */
0632     if (!(val & PS_STAT_VBUS_VALID)) {
0633         dev_dbg(&info->pdev->dev, "USB charger disconnected\n");
0634         axp288_charger_enable_charger(info, false);
0635         mutex_lock(&info->lock);
0636         info->valid = false;
0637         mutex_unlock(&info->lock);
0638         power_supply_changed(info->psy_usb);
0639         return;
0640     }
0641 
0642     /* Determine cable/charger type */
0643     if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
0644         /* See comment above axp288_hp_x2_dmi_ids declaration */
0645         dev_dbg(&info->pdev->dev, "HP X2 with Type-C, setting inlmt to 3A\n");
0646         current_limit = 3000000;
0647     } else if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
0648         dev_dbg(&info->pdev->dev, "USB SDP charger is connected\n");
0649         current_limit = 500000;
0650     } else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
0651         dev_dbg(&info->pdev->dev, "USB CDP charger is connected\n");
0652         current_limit = 1500000;
0653     } else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {
0654         dev_dbg(&info->pdev->dev, "USB DCP charger is connected\n");
0655         current_limit = 2000000;
0656     } else {
0657         /* Charger type detection still in progress, bail. */
0658         return;
0659     }
0660 
0661     /* Set vbus current limit first, then enable charger */
0662     ret = axp288_charger_set_vbus_inlmt(info, current_limit);
0663     if (ret == 0)
0664         axp288_charger_enable_charger(info, true);
0665     else
0666         dev_err(&info->pdev->dev,
0667             "error setting current limit (%d)\n", ret);
0668 
0669     mutex_lock(&info->lock);
0670     info->valid = false;
0671     mutex_unlock(&info->lock);
0672     power_supply_changed(info->psy_usb);
0673 }
0674 
0675 static int axp288_charger_handle_cable_evt(struct notifier_block *nb,
0676                        unsigned long event, void *param)
0677 {
0678     struct axp288_chrg_info *info =
0679         container_of(nb, struct axp288_chrg_info, cable.nb);
0680     schedule_work(&info->cable.work);
0681     return NOTIFY_OK;
0682 }
0683 
0684 static void axp288_charger_otg_evt_worker(struct work_struct *work)
0685 {
0686     struct axp288_chrg_info *info =
0687         container_of(work, struct axp288_chrg_info, otg.work);
0688     struct extcon_dev *edev = info->otg.cable;
0689     int ret, usb_host = extcon_get_state(edev, EXTCON_USB_HOST);
0690 
0691     dev_dbg(&info->pdev->dev, "external connector USB-Host is %s\n",
0692                 usb_host ? "attached" : "detached");
0693 
0694     /*
0695      * Set usb_id_short flag to avoid running charger detection logic
0696      * in case usb host.
0697      */
0698     info->otg.id_short = usb_host;
0699 
0700     /* Disable VBUS path before enabling the 5V boost */
0701     ret = axp288_charger_vbus_path_select(info, !info->otg.id_short);
0702     if (ret < 0)
0703         dev_warn(&info->pdev->dev, "vbus path disable failed\n");
0704 }
0705 
0706 static int axp288_charger_handle_otg_evt(struct notifier_block *nb,
0707                    unsigned long event, void *param)
0708 {
0709     struct axp288_chrg_info *info =
0710         container_of(nb, struct axp288_chrg_info, otg.id_nb);
0711 
0712     schedule_work(&info->otg.work);
0713 
0714     return NOTIFY_OK;
0715 }
0716 
0717 static int charger_init_hw_regs(struct axp288_chrg_info *info)
0718 {
0719     int ret, cc, cv;
0720     unsigned int val;
0721 
0722     /* Program temperature thresholds */
0723     ret = regmap_write(info->regmap, AXP20X_V_LTF_CHRG, CHRG_VLTFC_0C);
0724     if (ret < 0) {
0725         dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
0726                             AXP20X_V_LTF_CHRG, ret);
0727         return ret;
0728     }
0729 
0730     ret = regmap_write(info->regmap, AXP20X_V_HTF_CHRG, CHRG_VHTFC_45C);
0731     if (ret < 0) {
0732         dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
0733                             AXP20X_V_HTF_CHRG, ret);
0734         return ret;
0735     }
0736 
0737     /* Do not turn-off charger o/p after charge cycle ends */
0738     ret = regmap_update_bits(info->regmap,
0739                 AXP20X_CHRG_CTRL2,
0740                 CNTL2_CHG_OUT_TURNON, CNTL2_CHG_OUT_TURNON);
0741     if (ret < 0) {
0742         dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
0743                         AXP20X_CHRG_CTRL2, ret);
0744         return ret;
0745     }
0746 
0747     /* Setup ending condition for charging to be 10% of I(chrg) */
0748     ret = regmap_update_bits(info->regmap,
0749                 AXP20X_CHRG_CTRL1,
0750                 CHRG_CCCV_ITERM_20P, 0);
0751     if (ret < 0) {
0752         dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
0753                         AXP20X_CHRG_CTRL1, ret);
0754         return ret;
0755     }
0756 
0757     /* Disable OCV-SOC curve calibration */
0758     ret = regmap_update_bits(info->regmap,
0759                 AXP20X_CC_CTRL,
0760                 FG_CNTL_OCV_ADJ_EN, 0);
0761     if (ret < 0) {
0762         dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
0763                         AXP20X_CC_CTRL, ret);
0764         return ret;
0765     }
0766 
0767     if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
0768         /* See comment above axp288_hp_x2_dmi_ids declaration */
0769         ret = axp288_charger_vbus_path_select(info, true);
0770         if (ret < 0)
0771             return ret;
0772     } else {
0773         /* Set Vhold to the factory default / recommended 4.4V */
0774         val = VBUS_ISPOUT_VHOLD_SET_4400MV << VBUS_ISPOUT_VHOLD_SET_BIT_POS;
0775         ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
0776                      VBUS_ISPOUT_VHOLD_SET_MASK, val);
0777         if (ret < 0) {
0778             dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
0779                 AXP20X_VBUS_IPSOUT_MGMT, ret);
0780             return ret;
0781         }
0782     }
0783 
0784     /* Read current charge voltage and current limit */
0785     ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val);
0786     if (ret < 0) {
0787         dev_err(&info->pdev->dev, "register(%x) read error(%d)\n",
0788             AXP20X_CHRG_CTRL1, ret);
0789         return ret;
0790     }
0791 
0792     /* Determine charge voltage */
0793     cv = (val & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS;
0794     switch (cv) {
0795     case CHRG_CCCV_CV_4100MV:
0796         info->cv = CV_4100MV;
0797         break;
0798     case CHRG_CCCV_CV_4150MV:
0799         info->cv = CV_4150MV;
0800         break;
0801     case CHRG_CCCV_CV_4200MV:
0802         info->cv = CV_4200MV;
0803         break;
0804     case CHRG_CCCV_CV_4350MV:
0805         info->cv = CV_4350MV;
0806         break;
0807     }
0808 
0809     /* Determine charge current limit */
0810     cc = (val & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS;
0811     cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
0812     info->cc = cc;
0813 
0814     /*
0815      * Do not allow the user to configure higher settings then those
0816      * set by the firmware
0817      */
0818     info->max_cv = info->cv;
0819     info->max_cc = info->cc;
0820 
0821     return 0;
0822 }
0823 
0824 static void axp288_charger_cancel_work(void *data)
0825 {
0826     struct axp288_chrg_info *info = data;
0827 
0828     cancel_work_sync(&info->otg.work);
0829     cancel_work_sync(&info->cable.work);
0830 }
0831 
0832 static int axp288_charger_probe(struct platform_device *pdev)
0833 {
0834     int ret, i, pirq;
0835     struct axp288_chrg_info *info;
0836     struct device *dev = &pdev->dev;
0837     struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
0838     struct power_supply_config charger_cfg = {};
0839     unsigned int val;
0840 
0841     /*
0842      * Normally the native AXP288 fg/charger drivers are preferred but
0843      * on some devices the ACPI drivers should be used instead.
0844      */
0845     if (!acpi_quirk_skip_acpi_ac_and_battery())
0846         return -ENODEV;
0847 
0848     /*
0849      * On some devices the fuelgauge and charger parts of the axp288 are
0850      * not used, check that the fuelgauge is enabled (CC_CTRL != 0).
0851      */
0852     ret = regmap_read(axp20x->regmap, AXP20X_CC_CTRL, &val);
0853     if (ret < 0)
0854         return ret;
0855     if (val == 0)
0856         return -ENODEV;
0857 
0858     info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
0859     if (!info)
0860         return -ENOMEM;
0861 
0862     mutex_init(&info->lock);
0863     info->pdev = pdev;
0864     info->regmap = axp20x->regmap;
0865     info->regmap_irqc = axp20x->regmap_irqc;
0866 
0867     info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME);
0868     if (IS_ERR(info->cable.edev)) {
0869         dev_err_probe(dev, PTR_ERR(info->cable.edev),
0870                   "extcon_get_extcon_dev(%s) failed\n",
0871                   AXP288_EXTCON_DEV_NAME);
0872         return PTR_ERR(info->cable.edev);
0873     }
0874 
0875     if (acpi_dev_present(USB_HOST_EXTCON_HID, NULL, -1)) {
0876         info->otg.cable = extcon_get_extcon_dev(USB_HOST_EXTCON_NAME);
0877         if (IS_ERR(info->otg.cable)) {
0878             dev_err_probe(dev, PTR_ERR(info->otg.cable),
0879                       "extcon_get_extcon_dev(%s) failed\n",
0880                       USB_HOST_EXTCON_NAME);
0881             return PTR_ERR(info->otg.cable);
0882         }
0883         dev_info(dev, "Using " USB_HOST_EXTCON_HID " extcon for usb-id\n");
0884     }
0885 
0886     platform_set_drvdata(pdev, info);
0887 
0888     ret = charger_init_hw_regs(info);
0889     if (ret)
0890         return ret;
0891 
0892     /* Register with power supply class */
0893     charger_cfg.drv_data = info;
0894     info->psy_usb = devm_power_supply_register(dev, &axp288_charger_desc,
0895                            &charger_cfg);
0896     if (IS_ERR(info->psy_usb)) {
0897         ret = PTR_ERR(info->psy_usb);
0898         dev_err(dev, "failed to register power supply: %d\n", ret);
0899         return ret;
0900     }
0901 
0902     /* Cancel our work on cleanup, register this before the notifiers */
0903     ret = devm_add_action(dev, axp288_charger_cancel_work, info);
0904     if (ret)
0905         return ret;
0906 
0907     /* Register for extcon notification */
0908     INIT_WORK(&info->cable.work, axp288_charger_extcon_evt_worker);
0909     info->cable.nb.notifier_call = axp288_charger_handle_cable_evt;
0910     ret = devm_extcon_register_notifier_all(dev, info->cable.edev,
0911                         &info->cable.nb);
0912     if (ret) {
0913         dev_err(dev, "failed to register cable extcon notifier\n");
0914         return ret;
0915     }
0916     schedule_work(&info->cable.work);
0917 
0918     /* Register for OTG notification */
0919     INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker);
0920     info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt;
0921     if (info->otg.cable) {
0922         ret = devm_extcon_register_notifier(dev, info->otg.cable,
0923                     EXTCON_USB_HOST, &info->otg.id_nb);
0924         if (ret) {
0925             dev_err(dev, "failed to register EXTCON_USB_HOST notifier\n");
0926             return ret;
0927         }
0928         schedule_work(&info->otg.work);
0929     }
0930 
0931     /* Register charger interrupts */
0932     for (i = 0; i < CHRG_INTR_END; i++) {
0933         pirq = platform_get_irq(info->pdev, i);
0934         if (pirq < 0)
0935             return pirq;
0936 
0937         info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
0938         if (info->irq[i] < 0) {
0939             dev_warn(&info->pdev->dev,
0940                 "failed to get virtual interrupt=%d\n", pirq);
0941             return info->irq[i];
0942         }
0943         ret = devm_request_threaded_irq(&info->pdev->dev, info->irq[i],
0944                     NULL, axp288_charger_irq_thread_handler,
0945                     IRQF_ONESHOT, info->pdev->name, info);
0946         if (ret) {
0947             dev_err(dev, "failed to request interrupt=%d\n",
0948                                 info->irq[i]);
0949             return ret;
0950         }
0951     }
0952 
0953     return 0;
0954 }
0955 
0956 static const struct platform_device_id axp288_charger_id_table[] = {
0957     { .name = "axp288_charger" },
0958     {},
0959 };
0960 MODULE_DEVICE_TABLE(platform, axp288_charger_id_table);
0961 
0962 static struct platform_driver axp288_charger_driver = {
0963     .probe = axp288_charger_probe,
0964     .id_table = axp288_charger_id_table,
0965     .driver = {
0966         .name = "axp288_charger",
0967     },
0968 };
0969 
0970 module_platform_driver(axp288_charger_driver);
0971 
0972 MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
0973 MODULE_DESCRIPTION("X-power AXP288 Charger Driver");
0974 MODULE_LICENSE("GPL v2");