Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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