1 /* 2 * Battery charger driver for Dialog Semiconductor DA9030 3 * 4 * Copyright (C) 2008 Compulab, Ltd. 5 * Mike Rapoport <mike@compulab.co.il> 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/kernel.h> 13 #include <linux/slab.h> 14 #include <linux/init.h> 15 #include <linux/types.h> 16 #include <linux/device.h> 17 #include <linux/workqueue.h> 18 #include <linux/module.h> 19 #include <linux/platform_device.h> 20 #include <linux/power_supply.h> 21 #include <linux/mfd/da903x.h> 22 23 #include <linux/debugfs.h> 24 #include <linux/seq_file.h> 25 #include <linux/notifier.h> 26 27 #define DA9030_FAULT_LOG 0x0a 28 #define DA9030_FAULT_LOG_OVER_TEMP (1 << 7) 29 #define DA9030_FAULT_LOG_VBAT_OVER (1 << 4) 30 31 #define DA9030_CHARGE_CONTROL 0x28 32 #define DA9030_CHRG_CHARGER_ENABLE (1 << 7) 33 34 #define DA9030_ADC_MAN_CONTROL 0x30 35 #define DA9030_ADC_TBATREF_ENABLE (1 << 5) 36 #define DA9030_ADC_LDO_INT_ENABLE (1 << 4) 37 38 #define DA9030_ADC_AUTO_CONTROL 0x31 39 #define DA9030_ADC_TBAT_ENABLE (1 << 5) 40 #define DA9030_ADC_VBAT_IN_TXON (1 << 4) 41 #define DA9030_ADC_VCH_ENABLE (1 << 3) 42 #define DA9030_ADC_ICH_ENABLE (1 << 2) 43 #define DA9030_ADC_VBAT_ENABLE (1 << 1) 44 #define DA9030_ADC_AUTO_SLEEP_ENABLE (1 << 0) 45 46 #define DA9030_VBATMON 0x32 47 #define DA9030_VBATMONTXON 0x33 48 #define DA9030_TBATHIGHP 0x34 49 #define DA9030_TBATHIGHN 0x35 50 #define DA9030_TBATLOW 0x36 51 52 #define DA9030_VBAT_RES 0x41 53 #define DA9030_VBATMIN_RES 0x42 54 #define DA9030_VBATMINTXON_RES 0x43 55 #define DA9030_ICHMAX_RES 0x44 56 #define DA9030_ICHMIN_RES 0x45 57 #define DA9030_ICHAVERAGE_RES 0x46 58 #define DA9030_VCHMAX_RES 0x47 59 #define DA9030_VCHMIN_RES 0x48 60 #define DA9030_TBAT_RES 0x49 61 62 struct da9030_adc_res { 63 uint8_t vbat_res; 64 uint8_t vbatmin_res; 65 uint8_t vbatmintxon; 66 uint8_t ichmax_res; 67 uint8_t ichmin_res; 68 uint8_t ichaverage_res; 69 uint8_t vchmax_res; 70 uint8_t vchmin_res; 71 uint8_t tbat_res; 72 uint8_t adc_in4_res; 73 uint8_t adc_in5_res; 74 }; 75 76 struct da9030_battery_thresholds { 77 int tbat_low; 78 int tbat_high; 79 int tbat_restart; 80 81 int vbat_low; 82 int vbat_crit; 83 int vbat_charge_start; 84 int vbat_charge_stop; 85 int vbat_charge_restart; 86 87 int vcharge_min; 88 int vcharge_max; 89 }; 90 91 struct da9030_charger { 92 struct power_supply *psy; 93 struct power_supply_desc psy_desc; 94 95 struct device *master; 96 97 struct da9030_adc_res adc; 98 struct delayed_work work; 99 unsigned int interval; 100 101 struct power_supply_info *battery_info; 102 103 struct da9030_battery_thresholds thresholds; 104 105 unsigned int charge_milliamp; 106 unsigned int charge_millivolt; 107 108 /* charger status */ 109 bool chdet; 110 uint8_t fault; 111 int mA; 112 int mV; 113 bool is_on; 114 115 struct notifier_block nb; 116 117 /* platform callbacks for battery low and critical events */ 118 void (*battery_low)(void); 119 void (*battery_critical)(void); 120 121 struct dentry *debug_file; 122 }; 123 124 static inline int da9030_reg_to_mV(int reg) 125 { 126 return ((reg * 2650) >> 8) + 2650; 127 } 128 129 static inline int da9030_millivolt_to_reg(int mV) 130 { 131 return ((mV - 2650) << 8) / 2650; 132 } 133 134 static inline int da9030_reg_to_mA(int reg) 135 { 136 return ((reg * 24000) >> 8) / 15; 137 } 138 139 #ifdef CONFIG_DEBUG_FS 140 static int bat_debug_show(struct seq_file *s, void *data) 141 { 142 struct da9030_charger *charger = s->private; 143 144 seq_printf(s, "charger is %s\n", charger->is_on ? "on" : "off"); 145 if (charger->chdet) { 146 seq_printf(s, "iset = %dmA, vset = %dmV\n", 147 charger->mA, charger->mV); 148 } 149 150 seq_printf(s, "vbat_res = %d (%dmV)\n", 151 charger->adc.vbat_res, 152 da9030_reg_to_mV(charger->adc.vbat_res)); 153 seq_printf(s, "vbatmin_res = %d (%dmV)\n", 154 charger->adc.vbatmin_res, 155 da9030_reg_to_mV(charger->adc.vbatmin_res)); 156 seq_printf(s, "vbatmintxon = %d (%dmV)\n", 157 charger->adc.vbatmintxon, 158 da9030_reg_to_mV(charger->adc.vbatmintxon)); 159 seq_printf(s, "ichmax_res = %d (%dmA)\n", 160 charger->adc.ichmax_res, 161 da9030_reg_to_mV(charger->adc.ichmax_res)); 162 seq_printf(s, "ichmin_res = %d (%dmA)\n", 163 charger->adc.ichmin_res, 164 da9030_reg_to_mA(charger->adc.ichmin_res)); 165 seq_printf(s, "ichaverage_res = %d (%dmA)\n", 166 charger->adc.ichaverage_res, 167 da9030_reg_to_mA(charger->adc.ichaverage_res)); 168 seq_printf(s, "vchmax_res = %d (%dmV)\n", 169 charger->adc.vchmax_res, 170 da9030_reg_to_mA(charger->adc.vchmax_res)); 171 seq_printf(s, "vchmin_res = %d (%dmV)\n", 172 charger->adc.vchmin_res, 173 da9030_reg_to_mV(charger->adc.vchmin_res)); 174 175 return 0; 176 } 177 178 static int debug_open(struct inode *inode, struct file *file) 179 { 180 return single_open(file, bat_debug_show, inode->i_private); 181 } 182 183 static const struct file_operations bat_debug_fops = { 184 .open = debug_open, 185 .read = seq_read, 186 .llseek = seq_lseek, 187 .release = single_release, 188 }; 189 190 static struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger) 191 { 192 charger->debug_file = debugfs_create_file("charger", 0666, NULL, 193 charger, &bat_debug_fops); 194 return charger->debug_file; 195 } 196 197 static void da9030_bat_remove_debugfs(struct da9030_charger *charger) 198 { 199 debugfs_remove(charger->debug_file); 200 } 201 #else 202 static inline struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger) 203 { 204 return NULL; 205 } 206 static inline void da9030_bat_remove_debugfs(struct da9030_charger *charger) 207 { 208 } 209 #endif 210 211 static inline void da9030_read_adc(struct da9030_charger *charger, 212 struct da9030_adc_res *adc) 213 { 214 da903x_reads(charger->master, DA9030_VBAT_RES, 215 sizeof(*adc), (uint8_t *)adc); 216 } 217 218 static void da9030_charger_update_state(struct da9030_charger *charger) 219 { 220 uint8_t val; 221 222 da903x_read(charger->master, DA9030_CHARGE_CONTROL, &val); 223 charger->is_on = (val & DA9030_CHRG_CHARGER_ENABLE) ? 1 : 0; 224 charger->mA = ((val >> 3) & 0xf) * 100; 225 charger->mV = (val & 0x7) * 50 + 4000; 226 227 da9030_read_adc(charger, &charger->adc); 228 da903x_read(charger->master, DA9030_FAULT_LOG, &charger->fault); 229 charger->chdet = da903x_query_status(charger->master, 230 DA9030_STATUS_CHDET); 231 } 232 233 static void da9030_set_charge(struct da9030_charger *charger, int on) 234 { 235 uint8_t val; 236 237 if (on) { 238 val = DA9030_CHRG_CHARGER_ENABLE; 239 val |= (charger->charge_milliamp / 100) << 3; 240 val |= (charger->charge_millivolt - 4000) / 50; 241 charger->is_on = 1; 242 } else { 243 val = 0; 244 charger->is_on = 0; 245 } 246 247 da903x_write(charger->master, DA9030_CHARGE_CONTROL, val); 248 249 power_supply_changed(charger->psy); 250 } 251 252 static void da9030_charger_check_state(struct da9030_charger *charger) 253 { 254 da9030_charger_update_state(charger); 255 256 /* we wake or boot with external power on */ 257 if (!charger->is_on) { 258 if ((charger->chdet) && 259 (charger->adc.vbat_res < 260 charger->thresholds.vbat_charge_start)) { 261 da9030_set_charge(charger, 1); 262 } 263 } else { 264 /* Charger has been pulled out */ 265 if (!charger->chdet) { 266 da9030_set_charge(charger, 0); 267 return; 268 } 269 270 if (charger->adc.vbat_res >= 271 charger->thresholds.vbat_charge_stop) { 272 da9030_set_charge(charger, 0); 273 da903x_write(charger->master, DA9030_VBATMON, 274 charger->thresholds.vbat_charge_restart); 275 } else if (charger->adc.vbat_res > 276 charger->thresholds.vbat_low) { 277 /* we are charging and passed LOW_THRESH, 278 so upate DA9030 VBAT threshold 279 */ 280 da903x_write(charger->master, DA9030_VBATMON, 281 charger->thresholds.vbat_low); 282 } 283 if (charger->adc.vchmax_res > charger->thresholds.vcharge_max || 284 charger->adc.vchmin_res < charger->thresholds.vcharge_min || 285 /* Tempreture readings are negative */ 286 charger->adc.tbat_res < charger->thresholds.tbat_high || 287 charger->adc.tbat_res > charger->thresholds.tbat_low) { 288 /* disable charger */ 289 da9030_set_charge(charger, 0); 290 } 291 } 292 } 293 294 static void da9030_charging_monitor(struct work_struct *work) 295 { 296 struct da9030_charger *charger; 297 298 charger = container_of(work, struct da9030_charger, work.work); 299 300 da9030_charger_check_state(charger); 301 302 /* reschedule for the next time */ 303 schedule_delayed_work(&charger->work, charger->interval); 304 } 305 306 static enum power_supply_property da9030_battery_props[] = { 307 POWER_SUPPLY_PROP_MODEL_NAME, 308 POWER_SUPPLY_PROP_STATUS, 309 POWER_SUPPLY_PROP_HEALTH, 310 POWER_SUPPLY_PROP_TECHNOLOGY, 311 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 312 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 313 POWER_SUPPLY_PROP_VOLTAGE_NOW, 314 POWER_SUPPLY_PROP_CURRENT_AVG, 315 }; 316 317 static void da9030_battery_check_status(struct da9030_charger *charger, 318 union power_supply_propval *val) 319 { 320 if (charger->chdet) { 321 if (charger->is_on) 322 val->intval = POWER_SUPPLY_STATUS_CHARGING; 323 else 324 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 325 } else { 326 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 327 } 328 } 329 330 static void da9030_battery_check_health(struct da9030_charger *charger, 331 union power_supply_propval *val) 332 { 333 if (charger->fault & DA9030_FAULT_LOG_OVER_TEMP) 334 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; 335 else if (charger->fault & DA9030_FAULT_LOG_VBAT_OVER) 336 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 337 else 338 val->intval = POWER_SUPPLY_HEALTH_GOOD; 339 } 340 341 static int da9030_battery_get_property(struct power_supply *psy, 342 enum power_supply_property psp, 343 union power_supply_propval *val) 344 { 345 struct da9030_charger *charger = power_supply_get_drvdata(psy); 346 347 switch (psp) { 348 case POWER_SUPPLY_PROP_STATUS: 349 da9030_battery_check_status(charger, val); 350 break; 351 case POWER_SUPPLY_PROP_HEALTH: 352 da9030_battery_check_health(charger, val); 353 break; 354 case POWER_SUPPLY_PROP_TECHNOLOGY: 355 val->intval = charger->battery_info->technology; 356 break; 357 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 358 val->intval = charger->battery_info->voltage_max_design; 359 break; 360 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 361 val->intval = charger->battery_info->voltage_min_design; 362 break; 363 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 364 val->intval = da9030_reg_to_mV(charger->adc.vbat_res) * 1000; 365 break; 366 case POWER_SUPPLY_PROP_CURRENT_AVG: 367 val->intval = 368 da9030_reg_to_mA(charger->adc.ichaverage_res) * 1000; 369 break; 370 case POWER_SUPPLY_PROP_MODEL_NAME: 371 val->strval = charger->battery_info->name; 372 break; 373 default: 374 break; 375 } 376 377 return 0; 378 } 379 380 static void da9030_battery_vbat_event(struct da9030_charger *charger) 381 { 382 da9030_read_adc(charger, &charger->adc); 383 384 if (charger->is_on) 385 return; 386 387 if (charger->adc.vbat_res < charger->thresholds.vbat_low) { 388 /* set VBAT threshold for critical */ 389 da903x_write(charger->master, DA9030_VBATMON, 390 charger->thresholds.vbat_crit); 391 if (charger->battery_low) 392 charger->battery_low(); 393 } else if (charger->adc.vbat_res < 394 charger->thresholds.vbat_crit) { 395 /* notify the system of battery critical */ 396 if (charger->battery_critical) 397 charger->battery_critical(); 398 } 399 } 400 401 static int da9030_battery_event(struct notifier_block *nb, unsigned long event, 402 void *data) 403 { 404 struct da9030_charger *charger = 405 container_of(nb, struct da9030_charger, nb); 406 407 switch (event) { 408 case DA9030_EVENT_CHDET: 409 cancel_delayed_work_sync(&charger->work); 410 schedule_work(&charger->work.work); 411 break; 412 case DA9030_EVENT_VBATMON: 413 da9030_battery_vbat_event(charger); 414 break; 415 case DA9030_EVENT_CHIOVER: 416 case DA9030_EVENT_TBAT: 417 da9030_set_charge(charger, 0); 418 break; 419 } 420 421 return 0; 422 } 423 424 static void da9030_battery_convert_thresholds(struct da9030_charger *charger, 425 struct da9030_battery_info *pdata) 426 { 427 charger->thresholds.tbat_low = pdata->tbat_low; 428 charger->thresholds.tbat_high = pdata->tbat_high; 429 charger->thresholds.tbat_restart = pdata->tbat_restart; 430 431 charger->thresholds.vbat_low = 432 da9030_millivolt_to_reg(pdata->vbat_low); 433 charger->thresholds.vbat_crit = 434 da9030_millivolt_to_reg(pdata->vbat_crit); 435 charger->thresholds.vbat_charge_start = 436 da9030_millivolt_to_reg(pdata->vbat_charge_start); 437 charger->thresholds.vbat_charge_stop = 438 da9030_millivolt_to_reg(pdata->vbat_charge_stop); 439 charger->thresholds.vbat_charge_restart = 440 da9030_millivolt_to_reg(pdata->vbat_charge_restart); 441 442 charger->thresholds.vcharge_min = 443 da9030_millivolt_to_reg(pdata->vcharge_min); 444 charger->thresholds.vcharge_max = 445 da9030_millivolt_to_reg(pdata->vcharge_max); 446 } 447 448 static void da9030_battery_setup_psy(struct da9030_charger *charger) 449 { 450 struct power_supply_desc *psy_desc = &charger->psy_desc; 451 struct power_supply_info *info = charger->battery_info; 452 453 psy_desc->name = info->name; 454 psy_desc->use_for_apm = info->use_for_apm; 455 psy_desc->type = POWER_SUPPLY_TYPE_BATTERY; 456 psy_desc->get_property = da9030_battery_get_property; 457 458 psy_desc->properties = da9030_battery_props; 459 psy_desc->num_properties = ARRAY_SIZE(da9030_battery_props); 460 }; 461 462 static int da9030_battery_charger_init(struct da9030_charger *charger) 463 { 464 char v[5]; 465 int ret; 466 467 v[0] = v[1] = charger->thresholds.vbat_low; 468 v[2] = charger->thresholds.tbat_high; 469 v[3] = charger->thresholds.tbat_restart; 470 v[4] = charger->thresholds.tbat_low; 471 472 ret = da903x_writes(charger->master, DA9030_VBATMON, 5, v); 473 if (ret) 474 return ret; 475 476 /* 477 * Enable reference voltage supply for ADC from the LDO_INTERNAL 478 * regulator. Must be set before ADC measurements can be made. 479 */ 480 ret = da903x_write(charger->master, DA9030_ADC_MAN_CONTROL, 481 DA9030_ADC_LDO_INT_ENABLE | 482 DA9030_ADC_TBATREF_ENABLE); 483 if (ret) 484 return ret; 485 486 /* enable auto ADC measuremnts */ 487 return da903x_write(charger->master, DA9030_ADC_AUTO_CONTROL, 488 DA9030_ADC_TBAT_ENABLE | DA9030_ADC_VBAT_IN_TXON | 489 DA9030_ADC_VCH_ENABLE | DA9030_ADC_ICH_ENABLE | 490 DA9030_ADC_VBAT_ENABLE | 491 DA9030_ADC_AUTO_SLEEP_ENABLE); 492 } 493 494 static int da9030_battery_probe(struct platform_device *pdev) 495 { 496 struct da9030_charger *charger; 497 struct power_supply_config psy_cfg = {}; 498 struct da9030_battery_info *pdata = pdev->dev.platform_data; 499 int ret; 500 501 if (pdata == NULL) 502 return -EINVAL; 503 504 if (pdata->charge_milliamp >= 1500 || 505 pdata->charge_millivolt < 4000 || 506 pdata->charge_millivolt > 4350) 507 return -EINVAL; 508 509 charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL); 510 if (charger == NULL) 511 return -ENOMEM; 512 513 charger->master = pdev->dev.parent; 514 515 /* 10 seconds between monitor runs unless platform defines other 516 interval */ 517 charger->interval = msecs_to_jiffies( 518 (pdata->batmon_interval ? : 10) * 1000); 519 520 charger->charge_milliamp = pdata->charge_milliamp; 521 charger->charge_millivolt = pdata->charge_millivolt; 522 charger->battery_info = pdata->battery_info; 523 charger->battery_low = pdata->battery_low; 524 charger->battery_critical = pdata->battery_critical; 525 526 da9030_battery_convert_thresholds(charger, pdata); 527 528 ret = da9030_battery_charger_init(charger); 529 if (ret) 530 goto err_charger_init; 531 532 INIT_DELAYED_WORK(&charger->work, da9030_charging_monitor); 533 schedule_delayed_work(&charger->work, charger->interval); 534 535 charger->nb.notifier_call = da9030_battery_event; 536 ret = da903x_register_notifier(charger->master, &charger->nb, 537 DA9030_EVENT_CHDET | 538 DA9030_EVENT_VBATMON | 539 DA9030_EVENT_CHIOVER | 540 DA9030_EVENT_TBAT); 541 if (ret) 542 goto err_notifier; 543 544 da9030_battery_setup_psy(charger); 545 psy_cfg.drv_data = charger; 546 charger->psy = power_supply_register(&pdev->dev, &charger->psy_desc, 547 &psy_cfg); 548 if (IS_ERR(charger->psy)) { 549 ret = PTR_ERR(charger->psy); 550 goto err_ps_register; 551 } 552 553 charger->debug_file = da9030_bat_create_debugfs(charger); 554 platform_set_drvdata(pdev, charger); 555 return 0; 556 557 err_ps_register: 558 da903x_unregister_notifier(charger->master, &charger->nb, 559 DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON | 560 DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT); 561 err_notifier: 562 cancel_delayed_work(&charger->work); 563 564 err_charger_init: 565 return ret; 566 } 567 568 static int da9030_battery_remove(struct platform_device *dev) 569 { 570 struct da9030_charger *charger = platform_get_drvdata(dev); 571 572 da9030_bat_remove_debugfs(charger); 573 574 da903x_unregister_notifier(charger->master, &charger->nb, 575 DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON | 576 DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT); 577 cancel_delayed_work_sync(&charger->work); 578 da9030_set_charge(charger, 0); 579 power_supply_unregister(charger->psy); 580 581 return 0; 582 } 583 584 static struct platform_driver da903x_battery_driver = { 585 .driver = { 586 .name = "da903x-battery", 587 }, 588 .probe = da9030_battery_probe, 589 .remove = da9030_battery_remove, 590 }; 591 592 module_platform_driver(da903x_battery_driver); 593 594 MODULE_DESCRIPTION("DA9030 battery charger driver"); 595 MODULE_AUTHOR("Mike Rapoport, CompuLab"); 596 MODULE_LICENSE("GPL"); 597