1 /* 2 * Battery driver for Maxim MAX8925 3 * 4 * Copyright (c) 2009-2010 Marvell International Ltd. 5 * Haojian Zhuang <haojian.zhuang@marvell.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 12 #include <linux/module.h> 13 #include <linux/err.h> 14 #include <linux/slab.h> 15 #include <linux/of.h> 16 #include <linux/i2c.h> 17 #include <linux/interrupt.h> 18 #include <linux/platform_device.h> 19 #include <linux/power_supply.h> 20 #include <linux/mfd/max8925.h> 21 22 /* registers in GPM */ 23 #define MAX8925_OUT5VEN 0x54 24 #define MAX8925_OUT3VEN 0x58 25 #define MAX8925_CHG_CNTL1 0x7c 26 27 /* bits definition */ 28 #define MAX8925_CHG_STAT_VSYSLOW (1 << 0) 29 #define MAX8925_CHG_STAT_MODE_MASK (3 << 2) 30 #define MAX8925_CHG_STAT_EN_MASK (1 << 4) 31 #define MAX8925_CHG_MBDET (1 << 1) 32 #define MAX8925_CHG_AC_RANGE_MASK (3 << 6) 33 34 /* registers in ADC */ 35 #define MAX8925_ADC_RES_CNFG1 0x06 36 #define MAX8925_ADC_AVG_CNFG1 0x07 37 #define MAX8925_ADC_ACQ_CNFG1 0x08 38 #define MAX8925_ADC_ACQ_CNFG2 0x09 39 /* 2 bytes registers in below. MSB is 1st, LSB is 2nd. */ 40 #define MAX8925_ADC_AUX2 0x62 41 #define MAX8925_ADC_VCHG 0x64 42 #define MAX8925_ADC_VBBATT 0x66 43 #define MAX8925_ADC_VMBATT 0x68 44 #define MAX8925_ADC_ISNS 0x6a 45 #define MAX8925_ADC_THM 0x6c 46 #define MAX8925_ADC_TDIE 0x6e 47 #define MAX8925_CMD_AUX2 0xc8 48 #define MAX8925_CMD_VCHG 0xd0 49 #define MAX8925_CMD_VBBATT 0xd8 50 #define MAX8925_CMD_VMBATT 0xe0 51 #define MAX8925_CMD_ISNS 0xe8 52 #define MAX8925_CMD_THM 0xf0 53 #define MAX8925_CMD_TDIE 0xf8 54 55 enum { 56 MEASURE_AUX2, 57 MEASURE_VCHG, 58 MEASURE_VBBATT, 59 MEASURE_VMBATT, 60 MEASURE_ISNS, 61 MEASURE_THM, 62 MEASURE_TDIE, 63 MEASURE_MAX, 64 }; 65 66 struct max8925_power_info { 67 struct max8925_chip *chip; 68 struct i2c_client *gpm; 69 struct i2c_client *adc; 70 71 struct power_supply *ac; 72 struct power_supply *usb; 73 struct power_supply *battery; 74 int irq_base; 75 unsigned ac_online:1; 76 unsigned usb_online:1; 77 unsigned bat_online:1; 78 unsigned chg_mode:2; 79 unsigned batt_detect:1; /* detecing MB by ID pin */ 80 unsigned topoff_threshold:2; 81 unsigned fast_charge:3; 82 unsigned no_temp_support:1; 83 unsigned no_insert_detect:1; 84 85 int (*set_charger) (int); 86 }; 87 88 static int __set_charger(struct max8925_power_info *info, int enable) 89 { 90 struct max8925_chip *chip = info->chip; 91 if (enable) { 92 /* enable charger in platform */ 93 if (info->set_charger) 94 info->set_charger(1); 95 /* enable charger */ 96 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 0); 97 } else { 98 /* disable charge */ 99 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7); 100 if (info->set_charger) 101 info->set_charger(0); 102 } 103 dev_dbg(chip->dev, "%s\n", (enable) ? "Enable charger" 104 : "Disable charger"); 105 return 0; 106 } 107 108 static irqreturn_t max8925_charger_handler(int irq, void *data) 109 { 110 struct max8925_power_info *info = (struct max8925_power_info *)data; 111 struct max8925_chip *chip = info->chip; 112 113 switch (irq - chip->irq_base) { 114 case MAX8925_IRQ_VCHG_DC_R: 115 info->ac_online = 1; 116 __set_charger(info, 1); 117 dev_dbg(chip->dev, "Adapter inserted\n"); 118 break; 119 case MAX8925_IRQ_VCHG_DC_F: 120 info->ac_online = 0; 121 __set_charger(info, 0); 122 dev_dbg(chip->dev, "Adapter removed\n"); 123 break; 124 case MAX8925_IRQ_VCHG_THM_OK_F: 125 /* Battery is not ready yet */ 126 dev_dbg(chip->dev, "Battery temperature is out of range\n"); 127 /* Fall through */ 128 case MAX8925_IRQ_VCHG_DC_OVP: 129 dev_dbg(chip->dev, "Error detection\n"); 130 __set_charger(info, 0); 131 break; 132 case MAX8925_IRQ_VCHG_THM_OK_R: 133 /* Battery is ready now */ 134 dev_dbg(chip->dev, "Battery temperature is in range\n"); 135 break; 136 case MAX8925_IRQ_VCHG_SYSLOW_R: 137 /* VSYS is low */ 138 dev_info(chip->dev, "Sys power is too low\n"); 139 break; 140 case MAX8925_IRQ_VCHG_SYSLOW_F: 141 dev_dbg(chip->dev, "Sys power is above low threshold\n"); 142 break; 143 case MAX8925_IRQ_VCHG_DONE: 144 __set_charger(info, 0); 145 dev_dbg(chip->dev, "Charging is done\n"); 146 break; 147 case MAX8925_IRQ_VCHG_TOPOFF: 148 dev_dbg(chip->dev, "Charging in top-off mode\n"); 149 break; 150 case MAX8925_IRQ_VCHG_TMR_FAULT: 151 __set_charger(info, 0); 152 dev_dbg(chip->dev, "Safe timer is expired\n"); 153 break; 154 case MAX8925_IRQ_VCHG_RST: 155 __set_charger(info, 0); 156 dev_dbg(chip->dev, "Charger is reset\n"); 157 break; 158 } 159 return IRQ_HANDLED; 160 } 161 162 static int start_measure(struct max8925_power_info *info, int type) 163 { 164 unsigned char buf[2] = {0, 0}; 165 int meas_cmd; 166 int meas_reg = 0, ret; 167 168 switch (type) { 169 case MEASURE_VCHG: 170 meas_cmd = MAX8925_CMD_VCHG; 171 meas_reg = MAX8925_ADC_VCHG; 172 break; 173 case MEASURE_VBBATT: 174 meas_cmd = MAX8925_CMD_VBBATT; 175 meas_reg = MAX8925_ADC_VBBATT; 176 break; 177 case MEASURE_VMBATT: 178 meas_cmd = MAX8925_CMD_VMBATT; 179 meas_reg = MAX8925_ADC_VMBATT; 180 break; 181 case MEASURE_ISNS: 182 meas_cmd = MAX8925_CMD_ISNS; 183 meas_reg = MAX8925_ADC_ISNS; 184 break; 185 default: 186 return -EINVAL; 187 } 188 189 max8925_reg_write(info->adc, meas_cmd, 0); 190 max8925_bulk_read(info->adc, meas_reg, 2, buf); 191 ret = ((buf[0]<<8) | buf[1]) >> 4; 192 193 return ret; 194 } 195 196 static int max8925_ac_get_prop(struct power_supply *psy, 197 enum power_supply_property psp, 198 union power_supply_propval *val) 199 { 200 struct max8925_power_info *info = dev_get_drvdata(psy->dev.parent); 201 int ret = 0; 202 203 switch (psp) { 204 case POWER_SUPPLY_PROP_ONLINE: 205 val->intval = info->ac_online; 206 break; 207 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 208 if (info->ac_online) { 209 ret = start_measure(info, MEASURE_VCHG); 210 if (ret >= 0) { 211 val->intval = ret * 2000; /* unit is uV */ 212 goto out; 213 } 214 } 215 ret = -ENODATA; 216 break; 217 default: 218 ret = -ENODEV; 219 break; 220 } 221 out: 222 return ret; 223 } 224 225 static enum power_supply_property max8925_ac_props[] = { 226 POWER_SUPPLY_PROP_ONLINE, 227 POWER_SUPPLY_PROP_VOLTAGE_NOW, 228 }; 229 230 static int max8925_usb_get_prop(struct power_supply *psy, 231 enum power_supply_property psp, 232 union power_supply_propval *val) 233 { 234 struct max8925_power_info *info = dev_get_drvdata(psy->dev.parent); 235 int ret = 0; 236 237 switch (psp) { 238 case POWER_SUPPLY_PROP_ONLINE: 239 val->intval = info->usb_online; 240 break; 241 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 242 if (info->usb_online) { 243 ret = start_measure(info, MEASURE_VCHG); 244 if (ret >= 0) { 245 val->intval = ret * 2000; /* unit is uV */ 246 goto out; 247 } 248 } 249 ret = -ENODATA; 250 break; 251 default: 252 ret = -ENODEV; 253 break; 254 } 255 out: 256 return ret; 257 } 258 259 static enum power_supply_property max8925_usb_props[] = { 260 POWER_SUPPLY_PROP_ONLINE, 261 POWER_SUPPLY_PROP_VOLTAGE_NOW, 262 }; 263 264 static int max8925_bat_get_prop(struct power_supply *psy, 265 enum power_supply_property psp, 266 union power_supply_propval *val) 267 { 268 struct max8925_power_info *info = dev_get_drvdata(psy->dev.parent); 269 int ret = 0; 270 271 switch (psp) { 272 case POWER_SUPPLY_PROP_ONLINE: 273 val->intval = info->bat_online; 274 break; 275 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 276 if (info->bat_online) { 277 ret = start_measure(info, MEASURE_VMBATT); 278 if (ret >= 0) { 279 val->intval = ret * 2000; /* unit is uV */ 280 ret = 0; 281 break; 282 } 283 } 284 ret = -ENODATA; 285 break; 286 case POWER_SUPPLY_PROP_CURRENT_NOW: 287 if (info->bat_online) { 288 ret = start_measure(info, MEASURE_ISNS); 289 if (ret >= 0) { 290 /* assume r_sns is 0.02 */ 291 ret = ((ret * 6250) - 3125) /* uA */; 292 val->intval = 0; 293 if (ret > 0) 294 val->intval = ret; /* unit is mA */ 295 ret = 0; 296 break; 297 } 298 } 299 ret = -ENODATA; 300 break; 301 case POWER_SUPPLY_PROP_CHARGE_TYPE: 302 if (!info->bat_online) { 303 ret = -ENODATA; 304 break; 305 } 306 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS); 307 ret = (ret & MAX8925_CHG_STAT_MODE_MASK) >> 2; 308 switch (ret) { 309 case 1: 310 val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; 311 break; 312 case 0: 313 case 2: 314 val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 315 break; 316 case 3: 317 val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; 318 break; 319 } 320 ret = 0; 321 break; 322 case POWER_SUPPLY_PROP_STATUS: 323 if (!info->bat_online) { 324 ret = -ENODATA; 325 break; 326 } 327 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS); 328 if (info->usb_online || info->ac_online) { 329 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 330 if (ret & MAX8925_CHG_STAT_EN_MASK) 331 val->intval = POWER_SUPPLY_STATUS_CHARGING; 332 } else 333 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 334 ret = 0; 335 break; 336 default: 337 ret = -ENODEV; 338 break; 339 } 340 return ret; 341 } 342 343 static enum power_supply_property max8925_battery_props[] = { 344 POWER_SUPPLY_PROP_ONLINE, 345 POWER_SUPPLY_PROP_VOLTAGE_NOW, 346 POWER_SUPPLY_PROP_CURRENT_NOW, 347 POWER_SUPPLY_PROP_CHARGE_TYPE, 348 POWER_SUPPLY_PROP_STATUS, 349 }; 350 351 static const struct power_supply_desc ac_desc = { 352 .name = "max8925-ac", 353 .type = POWER_SUPPLY_TYPE_MAINS, 354 .properties = max8925_ac_props, 355 .num_properties = ARRAY_SIZE(max8925_ac_props), 356 .get_property = max8925_ac_get_prop, 357 }; 358 359 static const struct power_supply_desc usb_desc = { 360 .name = "max8925-usb", 361 .type = POWER_SUPPLY_TYPE_USB, 362 .properties = max8925_usb_props, 363 .num_properties = ARRAY_SIZE(max8925_usb_props), 364 .get_property = max8925_usb_get_prop, 365 }; 366 367 static const struct power_supply_desc battery_desc = { 368 .name = "max8925-battery", 369 .type = POWER_SUPPLY_TYPE_BATTERY, 370 .properties = max8925_battery_props, 371 .num_properties = ARRAY_SIZE(max8925_battery_props), 372 .get_property = max8925_bat_get_prop, 373 }; 374 375 #define REQUEST_IRQ(_irq, _name) \ 376 do { \ 377 ret = request_threaded_irq(chip->irq_base + _irq, NULL, \ 378 max8925_charger_handler, \ 379 IRQF_ONESHOT, _name, info); \ 380 if (ret) \ 381 dev_err(chip->dev, "Failed to request IRQ #%d: %d\n", \ 382 _irq, ret); \ 383 } while (0) 384 385 static int max8925_init_charger(struct max8925_chip *chip, 386 struct max8925_power_info *info) 387 { 388 int ret; 389 390 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp"); 391 if (!info->no_insert_detect) { 392 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove"); 393 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert"); 394 } 395 if (!info->no_temp_support) { 396 REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range"); 397 REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range"); 398 } 399 REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high"); 400 REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low"); 401 REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset"); 402 REQUEST_IRQ(MAX8925_IRQ_VCHG_DONE, "charger-done"); 403 REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff"); 404 REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire"); 405 406 info->usb_online = 0; 407 info->bat_online = 0; 408 409 /* check for power - can miss interrupt at boot time */ 410 if (start_measure(info, MEASURE_VCHG) * 2000 > 500000) 411 info->ac_online = 1; 412 else 413 info->ac_online = 0; 414 415 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS); 416 if (ret >= 0) { 417 /* 418 * If battery detection is enabled, ID pin of battery is 419 * connected to MBDET pin of MAX8925. It could be used to 420 * detect battery presence. 421 * Otherwise, we have to assume that battery is always on. 422 */ 423 if (info->batt_detect) 424 info->bat_online = (ret & MAX8925_CHG_MBDET) ? 0 : 1; 425 else 426 info->bat_online = 1; 427 if (ret & MAX8925_CHG_AC_RANGE_MASK) 428 info->ac_online = 1; 429 else 430 info->ac_online = 0; 431 } 432 /* disable charge */ 433 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7); 434 /* set charging current in charge topoff mode */ 435 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 3 << 5, 436 info->topoff_threshold << 5); 437 /* set charing current in fast charge mode */ 438 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 7, info->fast_charge); 439 440 return 0; 441 } 442 443 static int max8925_deinit_charger(struct max8925_power_info *info) 444 { 445 struct max8925_chip *chip = info->chip; 446 int irq; 447 448 irq = chip->irq_base + MAX8925_IRQ_VCHG_DC_OVP; 449 for (; irq <= chip->irq_base + MAX8925_IRQ_VCHG_TMR_FAULT; irq++) 450 free_irq(irq, info); 451 452 return 0; 453 } 454 455 #ifdef CONFIG_OF 456 static struct max8925_power_pdata * 457 max8925_power_dt_init(struct platform_device *pdev) 458 { 459 struct device_node *nproot = pdev->dev.parent->of_node; 460 struct device_node *np; 461 int batt_detect; 462 int topoff_threshold; 463 int fast_charge; 464 int no_temp_support; 465 int no_insert_detect; 466 struct max8925_power_pdata *pdata; 467 468 if (!nproot) 469 return pdev->dev.platform_data; 470 471 np = of_get_child_by_name(nproot, "charger"); 472 if (!np) { 473 dev_err(&pdev->dev, "failed to find charger node\n"); 474 return NULL; 475 } 476 477 pdata = devm_kzalloc(&pdev->dev, 478 sizeof(struct max8925_power_pdata), 479 GFP_KERNEL); 480 if (!pdata) 481 goto ret; 482 483 of_property_read_u32(np, "topoff-threshold", &topoff_threshold); 484 of_property_read_u32(np, "batt-detect", &batt_detect); 485 of_property_read_u32(np, "fast-charge", &fast_charge); 486 of_property_read_u32(np, "no-insert-detect", &no_insert_detect); 487 of_property_read_u32(np, "no-temp-support", &no_temp_support); 488 489 pdata->batt_detect = batt_detect; 490 pdata->fast_charge = fast_charge; 491 pdata->topoff_threshold = topoff_threshold; 492 pdata->no_insert_detect = no_insert_detect; 493 pdata->no_temp_support = no_temp_support; 494 495 ret: 496 of_node_put(np); 497 return pdata; 498 } 499 #else 500 static struct max8925_power_pdata * 501 max8925_power_dt_init(struct platform_device *pdev) 502 { 503 return pdev->dev.platform_data; 504 } 505 #endif 506 507 static int max8925_power_probe(struct platform_device *pdev) 508 { 509 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); 510 struct power_supply_config psy_cfg = {}; /* Only for ac and usb */ 511 struct max8925_power_pdata *pdata = NULL; 512 struct max8925_power_info *info; 513 int ret; 514 515 pdata = max8925_power_dt_init(pdev); 516 if (!pdata) { 517 dev_err(&pdev->dev, "platform data isn't assigned to " 518 "power supply\n"); 519 return -EINVAL; 520 } 521 522 info = devm_kzalloc(&pdev->dev, sizeof(struct max8925_power_info), 523 GFP_KERNEL); 524 if (!info) 525 return -ENOMEM; 526 info->chip = chip; 527 info->gpm = chip->i2c; 528 info->adc = chip->adc; 529 platform_set_drvdata(pdev, info); 530 531 psy_cfg.supplied_to = pdata->supplied_to; 532 psy_cfg.num_supplicants = pdata->num_supplicants; 533 534 info->ac = power_supply_register(&pdev->dev, &ac_desc, &psy_cfg); 535 if (IS_ERR(info->ac)) { 536 ret = PTR_ERR(info->ac); 537 goto out; 538 } 539 info->ac->dev.parent = &pdev->dev; 540 541 info->usb = power_supply_register(&pdev->dev, &usb_desc, &psy_cfg); 542 if (IS_ERR(info->usb)) { 543 ret = PTR_ERR(info->usb); 544 goto out_unregister_ac; 545 } 546 info->usb->dev.parent = &pdev->dev; 547 548 info->battery = power_supply_register(&pdev->dev, &battery_desc, NULL); 549 if (IS_ERR(info->battery)) { 550 ret = PTR_ERR(info->battery); 551 goto out_unregister_usb; 552 } 553 info->battery->dev.parent = &pdev->dev; 554 555 info->batt_detect = pdata->batt_detect; 556 info->topoff_threshold = pdata->topoff_threshold; 557 info->fast_charge = pdata->fast_charge; 558 info->set_charger = pdata->set_charger; 559 info->no_temp_support = pdata->no_temp_support; 560 info->no_insert_detect = pdata->no_insert_detect; 561 562 max8925_init_charger(chip, info); 563 return 0; 564 out_unregister_usb: 565 power_supply_unregister(info->usb); 566 out_unregister_ac: 567 power_supply_unregister(info->ac); 568 out: 569 return ret; 570 } 571 572 static int max8925_power_remove(struct platform_device *pdev) 573 { 574 struct max8925_power_info *info = platform_get_drvdata(pdev); 575 576 if (info) { 577 power_supply_unregister(info->ac); 578 power_supply_unregister(info->usb); 579 power_supply_unregister(info->battery); 580 max8925_deinit_charger(info); 581 } 582 return 0; 583 } 584 585 static struct platform_driver max8925_power_driver = { 586 .probe = max8925_power_probe, 587 .remove = max8925_power_remove, 588 .driver = { 589 .name = "max8925-power", 590 }, 591 }; 592 593 module_platform_driver(max8925_power_driver); 594 595 MODULE_LICENSE("GPL"); 596 MODULE_DESCRIPTION("Power supply driver for MAX8925"); 597 MODULE_ALIAS("platform:max8925-power"); 598