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