1 /* 2 * Battery and Power Management code for the Sharp SL-C7xx and SL-Cxx00 3 * series of PDAs 4 * 5 * Copyright (c) 2004-2005 Richard Purdie 6 * 7 * Based on code written by Sharp for 2.4 kernels 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 */ 14 15 #undef DEBUG 16 17 #include <linux/module.h> 18 #include <linux/kernel.h> 19 #include <linux/interrupt.h> 20 #include <linux/platform_device.h> 21 #include <linux/apm-emulation.h> 22 #include <linux/timer.h> 23 #include <linux/delay.h> 24 #include <linux/leds.h> 25 #include <linux/suspend.h> 26 #include <linux/gpio.h> 27 28 #include <asm/mach-types.h> 29 #include <mach/pm.h> 30 #include <mach/pxa2xx-regs.h> 31 #include <mach/pxa2xx-gpio.h> 32 #include <mach/regs-rtc.h> 33 #include <mach/sharpsl.h> 34 #include <mach/sharpsl_pm.h> 35 36 #include "sharpsl.h" 37 38 /* 39 * Constants 40 */ 41 #define SHARPSL_CHARGE_ON_TIME_INTERVAL (msecs_to_jiffies(1*60*1000)) /* 1 min */ 42 #define SHARPSL_CHARGE_FINISH_TIME (msecs_to_jiffies(10*60*1000)) /* 10 min */ 43 #define SHARPSL_BATCHK_TIME (msecs_to_jiffies(15*1000)) /* 15 sec */ 44 #define SHARPSL_BATCHK_TIME_SUSPEND (60*10) /* 10 min */ 45 46 #define SHARPSL_WAIT_CO_TIME 15 /* 15 sec */ 47 #define SHARPSL_WAIT_DISCHARGE_ON 100 /* 100 msec */ 48 #define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 10 /* 10 msec */ 49 #define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 10 /* 10 msec */ 50 #define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN 10 /* 10 msec */ 51 #define SHARPSL_CHARGE_WAIT_TIME 15 /* 15 msec */ 52 #define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */ 53 #define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */ 54 55 /* 56 * Prototypes 57 */ 58 #ifdef CONFIG_PM 59 static int sharpsl_off_charge_battery(void); 60 static int sharpsl_check_battery_voltage(void); 61 static int sharpsl_fatal_check(void); 62 #endif 63 static int sharpsl_check_battery_temp(void); 64 static int sharpsl_ac_check(void); 65 static int sharpsl_average_value(int ad); 66 static void sharpsl_average_clear(void); 67 static void sharpsl_charge_toggle(struct work_struct *private_); 68 static void sharpsl_battery_thread(struct work_struct *private_); 69 70 71 /* 72 * Variables 73 */ 74 struct sharpsl_pm_status sharpsl_pm; 75 static DECLARE_DELAYED_WORK(toggle_charger, sharpsl_charge_toggle); 76 static DECLARE_DELAYED_WORK(sharpsl_bat, sharpsl_battery_thread); 77 DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger); 78 79 80 81 struct battery_thresh sharpsl_battery_levels_acin[] = { 82 { 213, 100}, 83 { 212, 98}, 84 { 211, 95}, 85 { 210, 93}, 86 { 209, 90}, 87 { 208, 88}, 88 { 207, 85}, 89 { 206, 83}, 90 { 205, 80}, 91 { 204, 78}, 92 { 203, 75}, 93 { 202, 73}, 94 { 201, 70}, 95 { 200, 68}, 96 { 199, 65}, 97 { 198, 63}, 98 { 197, 60}, 99 { 196, 58}, 100 { 195, 55}, 101 { 194, 53}, 102 { 193, 50}, 103 { 192, 48}, 104 { 192, 45}, 105 { 191, 43}, 106 { 191, 40}, 107 { 190, 38}, 108 { 190, 35}, 109 { 189, 33}, 110 { 188, 30}, 111 { 187, 28}, 112 { 186, 25}, 113 { 185, 23}, 114 { 184, 20}, 115 { 183, 18}, 116 { 182, 15}, 117 { 181, 13}, 118 { 180, 10}, 119 { 179, 8}, 120 { 178, 5}, 121 { 0, 0}, 122 }; 123 124 struct battery_thresh sharpsl_battery_levels_noac[] = { 125 { 213, 100}, 126 { 212, 98}, 127 { 211, 95}, 128 { 210, 93}, 129 { 209, 90}, 130 { 208, 88}, 131 { 207, 85}, 132 { 206, 83}, 133 { 205, 80}, 134 { 204, 78}, 135 { 203, 75}, 136 { 202, 73}, 137 { 201, 70}, 138 { 200, 68}, 139 { 199, 65}, 140 { 198, 63}, 141 { 197, 60}, 142 { 196, 58}, 143 { 195, 55}, 144 { 194, 53}, 145 { 193, 50}, 146 { 192, 48}, 147 { 191, 45}, 148 { 190, 43}, 149 { 189, 40}, 150 { 188, 38}, 151 { 187, 35}, 152 { 186, 33}, 153 { 185, 30}, 154 { 184, 28}, 155 { 183, 25}, 156 { 182, 23}, 157 { 181, 20}, 158 { 180, 18}, 159 { 179, 15}, 160 { 178, 13}, 161 { 177, 10}, 162 { 176, 8}, 163 { 175, 5}, 164 { 0, 0}, 165 }; 166 167 /* MAX1111 Commands */ 168 #define MAXCTRL_PD0 (1u << 0) 169 #define MAXCTRL_PD1 (1u << 1) 170 #define MAXCTRL_SGL (1u << 2) 171 #define MAXCTRL_UNI (1u << 3) 172 #define MAXCTRL_SEL_SH 4 173 #define MAXCTRL_STR (1u << 7) 174 175 /* 176 * Read MAX1111 ADC 177 */ 178 int sharpsl_pm_pxa_read_max1111(int channel) 179 { 180 /* Ugly, better move this function into another module */ 181 if (machine_is_tosa()) 182 return 0; 183 184 #ifdef CONFIG_CORGI_SSP_DEPRECATED 185 return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1 186 | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR); 187 #else 188 extern int max1111_read_channel(int); 189 190 /* max1111 accepts channels from 0-3, however, 191 * it is encoded from 0-7 here in the code. 192 */ 193 return max1111_read_channel(channel >> 1); 194 #endif 195 } 196 197 static int get_percentage(int voltage) 198 { 199 int i = sharpsl_pm.machinfo->bat_levels - 1; 200 int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0; 201 struct battery_thresh *thresh; 202 203 if (sharpsl_pm.charge_mode == CHRG_ON) 204 thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin; 205 else 206 thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac; 207 208 while (i > 0 && (voltage > thresh[i].voltage)) 209 i--; 210 211 return thresh[i].percentage; 212 } 213 214 static int get_apm_status(int voltage) 215 { 216 int low_thresh, high_thresh; 217 218 if (sharpsl_pm.charge_mode == CHRG_ON) { 219 high_thresh = sharpsl_pm.machinfo->status_high_acin; 220 low_thresh = sharpsl_pm.machinfo->status_low_acin; 221 } else { 222 high_thresh = sharpsl_pm.machinfo->status_high_noac; 223 low_thresh = sharpsl_pm.machinfo->status_low_noac; 224 } 225 226 if (voltage >= high_thresh) 227 return APM_BATTERY_STATUS_HIGH; 228 if (voltage >= low_thresh) 229 return APM_BATTERY_STATUS_LOW; 230 return APM_BATTERY_STATUS_CRITICAL; 231 } 232 233 void sharpsl_battery_kick(void) 234 { 235 schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125)); 236 } 237 EXPORT_SYMBOL(sharpsl_battery_kick); 238 239 240 static void sharpsl_battery_thread(struct work_struct *private_) 241 { 242 int voltage, percent, apm_status, i; 243 244 if (!sharpsl_pm.machinfo) 245 return; 246 247 sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE); 248 249 /* Corgi cannot confirm when battery fully charged so periodically kick! */ 250 if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON) 251 && time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_ON_TIME_INTERVAL)) 252 schedule_delayed_work(&toggle_charger, 0); 253 254 for (i = 0; i < 5; i++) { 255 voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT); 256 if (voltage > 0) 257 break; 258 } 259 if (voltage <= 0) { 260 voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage; 261 dev_warn(sharpsl_pm.dev, "Warning: Cannot read main battery!\n"); 262 } 263 264 voltage = sharpsl_average_value(voltage); 265 apm_status = get_apm_status(voltage); 266 percent = get_percentage(voltage); 267 268 /* At low battery voltages, the voltage has a tendency to start 269 creeping back up so we try to avoid this here */ 270 if ((sharpsl_pm.battstat.ac_status == APM_AC_ONLINE) 271 || (apm_status == APM_BATTERY_STATUS_HIGH) 272 || percent <= sharpsl_pm.battstat.mainbat_percent) { 273 sharpsl_pm.battstat.mainbat_voltage = voltage; 274 sharpsl_pm.battstat.mainbat_status = apm_status; 275 sharpsl_pm.battstat.mainbat_percent = percent; 276 } 277 278 dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %ld\n", voltage, 279 sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies); 280 281 #ifdef CONFIG_BACKLIGHT_CORGI 282 /* If battery is low. limit backlight intensity to save power. */ 283 if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE) 284 && ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) 285 || (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) { 286 if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) { 287 sharpsl_pm.machinfo->backlight_limit(1); 288 sharpsl_pm.flags |= SHARPSL_BL_LIMIT; 289 } 290 } else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) { 291 sharpsl_pm.machinfo->backlight_limit(0); 292 sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT; 293 } 294 #endif 295 296 /* Suspend if critical battery level */ 297 if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE) 298 && (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL) 299 && !(sharpsl_pm.flags & SHARPSL_APM_QUEUED)) { 300 sharpsl_pm.flags |= SHARPSL_APM_QUEUED; 301 dev_err(sharpsl_pm.dev, "Fatal Off\n"); 302 apm_queue_event(APM_CRITICAL_SUSPEND); 303 } 304 305 schedule_delayed_work(&sharpsl_bat, SHARPSL_BATCHK_TIME); 306 } 307 308 void sharpsl_pm_led(int val) 309 { 310 if (val == SHARPSL_LED_ERROR) { 311 dev_err(sharpsl_pm.dev, "Charging Error!\n"); 312 } else if (val == SHARPSL_LED_ON) { 313 dev_dbg(sharpsl_pm.dev, "Charge LED On\n"); 314 led_trigger_event(sharpsl_charge_led_trigger, LED_FULL); 315 } else { 316 dev_dbg(sharpsl_pm.dev, "Charge LED Off\n"); 317 led_trigger_event(sharpsl_charge_led_trigger, LED_OFF); 318 } 319 } 320 321 static void sharpsl_charge_on(void) 322 { 323 dev_dbg(sharpsl_pm.dev, "Turning Charger On\n"); 324 325 sharpsl_pm.full_count = 0; 326 sharpsl_pm.charge_mode = CHRG_ON; 327 schedule_delayed_work(&toggle_charger, msecs_to_jiffies(250)); 328 schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(500)); 329 } 330 331 static void sharpsl_charge_off(void) 332 { 333 dev_dbg(sharpsl_pm.dev, "Turning Charger Off\n"); 334 335 sharpsl_pm.machinfo->charge(0); 336 sharpsl_pm_led(SHARPSL_LED_OFF); 337 sharpsl_pm.charge_mode = CHRG_OFF; 338 339 schedule_delayed_work(&sharpsl_bat, 0); 340 } 341 342 static void sharpsl_charge_error(void) 343 { 344 sharpsl_pm_led(SHARPSL_LED_ERROR); 345 sharpsl_pm.machinfo->charge(0); 346 sharpsl_pm.charge_mode = CHRG_ERROR; 347 } 348 349 static void sharpsl_charge_toggle(struct work_struct *private_) 350 { 351 dev_dbg(sharpsl_pm.dev, "Toggling Charger at time: %lx\n", jiffies); 352 353 if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) { 354 sharpsl_charge_off(); 355 return; 356 } else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) { 357 sharpsl_charge_error(); 358 return; 359 } 360 361 sharpsl_pm_led(SHARPSL_LED_ON); 362 sharpsl_pm.machinfo->charge(0); 363 mdelay(SHARPSL_CHARGE_WAIT_TIME); 364 sharpsl_pm.machinfo->charge(1); 365 366 sharpsl_pm.charge_start_time = jiffies; 367 } 368 369 static void sharpsl_ac_timer(unsigned long data) 370 { 371 int acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN); 372 373 dev_dbg(sharpsl_pm.dev, "AC Status: %d\n", acin); 374 375 sharpsl_average_clear(); 376 if (acin && (sharpsl_pm.charge_mode != CHRG_ON)) 377 sharpsl_charge_on(); 378 else if (sharpsl_pm.charge_mode == CHRG_ON) 379 sharpsl_charge_off(); 380 381 schedule_delayed_work(&sharpsl_bat, 0); 382 } 383 384 385 static irqreturn_t sharpsl_ac_isr(int irq, void *dev_id) 386 { 387 /* Delay the event slightly to debounce */ 388 /* Must be a smaller delay than the chrg_full_isr below */ 389 mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250)); 390 391 return IRQ_HANDLED; 392 } 393 394 static void sharpsl_chrg_full_timer(unsigned long data) 395 { 396 dev_dbg(sharpsl_pm.dev, "Charge Full at time: %lx\n", jiffies); 397 398 sharpsl_pm.full_count++; 399 400 if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) { 401 dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n"); 402 if (sharpsl_pm.charge_mode == CHRG_ON) 403 sharpsl_charge_off(); 404 } else if (sharpsl_pm.full_count < 2) { 405 dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n"); 406 schedule_delayed_work(&toggle_charger, 0); 407 } else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) { 408 dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n"); 409 schedule_delayed_work(&toggle_charger, 0); 410 } else { 411 sharpsl_charge_off(); 412 sharpsl_pm.charge_mode = CHRG_DONE; 413 dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n"); 414 } 415 } 416 417 /* Charging Finished Interrupt (Not present on Corgi) */ 418 /* Can trigger at the same time as an AC status change so 419 delay until after that has been processed */ 420 static irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id) 421 { 422 if (sharpsl_pm.flags & SHARPSL_SUSPENDED) 423 return IRQ_HANDLED; 424 425 /* delay until after any ac interrupt */ 426 mod_timer(&sharpsl_pm.chrg_full_timer, jiffies + msecs_to_jiffies(500)); 427 428 return IRQ_HANDLED; 429 } 430 431 static irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id) 432 { 433 int is_fatal = 0; 434 435 if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) { 436 dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n"); 437 is_fatal = 1; 438 } 439 440 if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL)) { 441 dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n"); 442 is_fatal = 1; 443 } 444 445 if (!(sharpsl_pm.flags & SHARPSL_APM_QUEUED) && is_fatal) { 446 sharpsl_pm.flags |= SHARPSL_APM_QUEUED; 447 apm_queue_event(APM_CRITICAL_SUSPEND); 448 } 449 450 return IRQ_HANDLED; 451 } 452 453 /* 454 * Maintain an average of the last 10 readings 455 */ 456 #define SHARPSL_CNV_VALUE_NUM 10 457 static int sharpsl_ad_index; 458 459 static void sharpsl_average_clear(void) 460 { 461 sharpsl_ad_index = 0; 462 } 463 464 static int sharpsl_average_value(int ad) 465 { 466 int i, ad_val = 0; 467 static int sharpsl_ad[SHARPSL_CNV_VALUE_NUM+1]; 468 469 if (sharpsl_pm.battstat.mainbat_status != APM_BATTERY_STATUS_HIGH) { 470 sharpsl_ad_index = 0; 471 return ad; 472 } 473 474 sharpsl_ad[sharpsl_ad_index] = ad; 475 sharpsl_ad_index++; 476 if (sharpsl_ad_index >= SHARPSL_CNV_VALUE_NUM) { 477 for (i = 0; i < (SHARPSL_CNV_VALUE_NUM-1); i++) 478 sharpsl_ad[i] = sharpsl_ad[i+1]; 479 sharpsl_ad_index = SHARPSL_CNV_VALUE_NUM - 1; 480 } 481 for (i = 0; i < sharpsl_ad_index; i++) 482 ad_val += sharpsl_ad[i]; 483 484 return ad_val / sharpsl_ad_index; 485 } 486 487 /* 488 * Take an array of 5 integers, remove the maximum and minimum values 489 * and return the average. 490 */ 491 static int get_select_val(int *val) 492 { 493 int i, j, k, temp, sum = 0; 494 495 /* Find MAX val */ 496 temp = val[0]; 497 j = 0; 498 for (i = 1; i < 5; i++) { 499 if (temp < val[i]) { 500 temp = val[i]; 501 j = i; 502 } 503 } 504 505 /* Find MIN val */ 506 temp = val[4]; 507 k = 4; 508 for (i = 3; i >= 0; i--) { 509 if (temp > val[i]) { 510 temp = val[i]; 511 k = i; 512 } 513 } 514 515 for (i = 0; i < 5; i++) 516 if (i != j && i != k) 517 sum += val[i]; 518 519 dev_dbg(sharpsl_pm.dev, "Average: %d from values: %d, %d, %d, %d, %d\n", sum/3, val[0], val[1], val[2], val[3], val[4]); 520 521 return sum/3; 522 } 523 524 static int sharpsl_check_battery_temp(void) 525 { 526 int val, i, buff[5]; 527 528 /* Check battery temperature */ 529 for (i = 0; i < 5; i++) { 530 mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); 531 sharpsl_pm.machinfo->measure_temp(1); 532 mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); 533 buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_TEMP); 534 sharpsl_pm.machinfo->measure_temp(0); 535 } 536 537 val = get_select_val(buff); 538 539 dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val); 540 if (val > sharpsl_pm.machinfo->charge_on_temp) { 541 printk(KERN_WARNING "Not charging: temperature out of limits.\n"); 542 return -1; 543 } 544 545 return 0; 546 } 547 548 #ifdef CONFIG_PM 549 static int sharpsl_check_battery_voltage(void) 550 { 551 int val, i, buff[5]; 552 553 /* disable charge, enable discharge */ 554 sharpsl_pm.machinfo->charge(0); 555 sharpsl_pm.machinfo->discharge(1); 556 mdelay(SHARPSL_WAIT_DISCHARGE_ON); 557 558 if (sharpsl_pm.machinfo->discharge1) 559 sharpsl_pm.machinfo->discharge1(1); 560 561 /* Check battery voltage */ 562 for (i = 0; i < 5; i++) { 563 buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT); 564 mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); 565 } 566 567 if (sharpsl_pm.machinfo->discharge1) 568 sharpsl_pm.machinfo->discharge1(0); 569 570 sharpsl_pm.machinfo->discharge(0); 571 572 val = get_select_val(buff); 573 dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val); 574 575 if (val < sharpsl_pm.machinfo->charge_on_volt) 576 return -1; 577 578 return 0; 579 } 580 #endif 581 582 static int sharpsl_ac_check(void) 583 { 584 int temp, i, buff[5]; 585 586 for (i = 0; i < 5; i++) { 587 buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_ACIN_VOLT); 588 mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN); 589 } 590 591 temp = get_select_val(buff); 592 dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n", temp); 593 594 if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) { 595 dev_err(sharpsl_pm.dev, "Error: AC check failed: voltage %d.\n", temp); 596 return -1; 597 } 598 599 return 0; 600 } 601 602 #ifdef CONFIG_PM 603 static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state) 604 { 605 sharpsl_pm.flags |= SHARPSL_SUSPENDED; 606 flush_scheduled_work(); 607 608 if (sharpsl_pm.charge_mode == CHRG_ON) 609 sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; 610 else 611 sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; 612 613 return 0; 614 } 615 616 static int sharpsl_pm_resume(struct platform_device *pdev) 617 { 618 /* Clear the reset source indicators as they break the bootloader upon reboot */ 619 RCSR = 0x0f; 620 sharpsl_average_clear(); 621 sharpsl_pm.flags &= ~SHARPSL_APM_QUEUED; 622 sharpsl_pm.flags &= ~SHARPSL_SUSPENDED; 623 624 return 0; 625 } 626 627 static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state) 628 { 629 dev_dbg(sharpsl_pm.dev, "Time is: %08x\n", RCNR); 630 631 dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n", sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG); 632 /* not charging and AC-IN! */ 633 634 if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN))) { 635 dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n"); 636 sharpsl_pm.charge_mode = CHRG_OFF; 637 sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; 638 sharpsl_off_charge_battery(); 639 } 640 641 sharpsl_pm.machinfo->presuspend(); 642 643 PEDR = 0xffffffff; /* clear it */ 644 645 sharpsl_pm.flags &= ~SHARPSL_ALARM_ACTIVE; 646 if ((sharpsl_pm.charge_mode == CHRG_ON) && ((alarm_enable && ((alarm_time - RCNR) > (SHARPSL_BATCHK_TIME_SUSPEND + 30))) || !alarm_enable)) { 647 RTSR &= RTSR_ALE; 648 RTAR = RCNR + SHARPSL_BATCHK_TIME_SUSPEND; 649 dev_dbg(sharpsl_pm.dev, "Charging alarm at: %08x\n", RTAR); 650 sharpsl_pm.flags |= SHARPSL_ALARM_ACTIVE; 651 } else if (alarm_enable) { 652 RTSR &= RTSR_ALE; 653 RTAR = alarm_time; 654 dev_dbg(sharpsl_pm.dev, "User alarm at: %08x\n", RTAR); 655 } else { 656 dev_dbg(sharpsl_pm.dev, "No alarms set.\n"); 657 } 658 659 pxa_pm_enter(state); 660 661 sharpsl_pm.machinfo->postsuspend(); 662 663 dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n", PEDR); 664 } 665 666 static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state) 667 { 668 if (!sharpsl_pm.machinfo->should_wakeup(!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE) && alarm_enable)) { 669 if (!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE)) { 670 dev_dbg(sharpsl_pm.dev, "No user triggered wakeup events and not charging. Strange. Suspend.\n"); 671 corgi_goto_sleep(alarm_time, alarm_enable, state); 672 return 1; 673 } 674 if (sharpsl_off_charge_battery()) { 675 dev_dbg(sharpsl_pm.dev, "Charging. Suspend...\n"); 676 corgi_goto_sleep(alarm_time, alarm_enable, state); 677 return 1; 678 } 679 dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n"); 680 } 681 682 if ((!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) || 683 (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL))) { 684 dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n"); 685 corgi_goto_sleep(alarm_time, alarm_enable, state); 686 return 1; 687 } 688 689 return 0; 690 } 691 692 static int corgi_pxa_pm_enter(suspend_state_t state) 693 { 694 unsigned long alarm_time = RTAR; 695 unsigned int alarm_status = ((RTSR & RTSR_ALE) != 0); 696 697 dev_dbg(sharpsl_pm.dev, "SharpSL suspending for first time.\n"); 698 699 corgi_goto_sleep(alarm_time, alarm_status, state); 700 701 while (corgi_enter_suspend(alarm_time, alarm_status, state)) 702 {} 703 704 if (sharpsl_pm.machinfo->earlyresume) 705 sharpsl_pm.machinfo->earlyresume(); 706 707 dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n"); 708 709 return 0; 710 } 711 712 /* 713 * Check for fatal battery errors 714 * Fatal returns -1 715 */ 716 static int sharpsl_fatal_check(void) 717 { 718 int buff[5], temp, i, acin; 719 720 dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n"); 721 722 /* Check AC-Adapter */ 723 acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN); 724 725 if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { 726 sharpsl_pm.machinfo->charge(0); 727 udelay(100); 728 sharpsl_pm.machinfo->discharge(1); /* enable discharge */ 729 mdelay(SHARPSL_WAIT_DISCHARGE_ON); 730 } 731 732 if (sharpsl_pm.machinfo->discharge1) 733 sharpsl_pm.machinfo->discharge1(1); 734 735 /* Check battery : check inserting battery ? */ 736 for (i = 0; i < 5; i++) { 737 buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT); 738 mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); 739 } 740 741 if (sharpsl_pm.machinfo->discharge1) 742 sharpsl_pm.machinfo->discharge1(0); 743 744 if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { 745 udelay(100); 746 sharpsl_pm.machinfo->charge(1); 747 sharpsl_pm.machinfo->discharge(0); 748 } 749 750 temp = get_select_val(buff); 751 dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %ld\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT)); 752 753 if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) || 754 (!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt))) 755 return -1; 756 return 0; 757 } 758 759 static int sharpsl_off_charge_error(void) 760 { 761 dev_err(sharpsl_pm.dev, "Offline Charger: Error occurred.\n"); 762 sharpsl_pm.machinfo->charge(0); 763 sharpsl_pm_led(SHARPSL_LED_ERROR); 764 sharpsl_pm.charge_mode = CHRG_ERROR; 765 return 1; 766 } 767 768 /* 769 * Charging Control while suspended 770 * Return 1 - go straight to sleep 771 * Return 0 - sleep or wakeup depending on other factors 772 */ 773 static int sharpsl_off_charge_battery(void) 774 { 775 int time; 776 777 dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode); 778 779 if (sharpsl_pm.charge_mode == CHRG_OFF) { 780 dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n"); 781 782 /* AC Check */ 783 if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0)) 784 return sharpsl_off_charge_error(); 785 786 /* Start Charging */ 787 sharpsl_pm_led(SHARPSL_LED_ON); 788 sharpsl_pm.machinfo->charge(0); 789 mdelay(SHARPSL_CHARGE_WAIT_TIME); 790 sharpsl_pm.machinfo->charge(1); 791 792 sharpsl_pm.charge_mode = CHRG_ON; 793 sharpsl_pm.full_count = 0; 794 795 return 1; 796 } else if (sharpsl_pm.charge_mode != CHRG_ON) { 797 return 1; 798 } 799 800 if (sharpsl_pm.full_count == 0) { 801 int time; 802 803 dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n"); 804 805 if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0)) 806 return sharpsl_off_charge_error(); 807 808 sharpsl_pm.machinfo->charge(0); 809 mdelay(SHARPSL_CHARGE_WAIT_TIME); 810 sharpsl_pm.machinfo->charge(1); 811 sharpsl_pm.charge_mode = CHRG_ON; 812 813 mdelay(SHARPSL_CHARGE_CO_CHECK_TIME); 814 815 time = RCNR; 816 while (1) { 817 /* Check if any wakeup event had occurred */ 818 if (sharpsl_pm.machinfo->charger_wakeup() != 0) 819 return 0; 820 /* Check for timeout */ 821 if ((RCNR - time) > SHARPSL_WAIT_CO_TIME) 822 return 1; 823 if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) { 824 dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occurred. Retrying to check\n"); 825 sharpsl_pm.full_count++; 826 sharpsl_pm.machinfo->charge(0); 827 mdelay(SHARPSL_CHARGE_WAIT_TIME); 828 sharpsl_pm.machinfo->charge(1); 829 return 1; 830 } 831 } 832 } 833 834 dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 3\n"); 835 836 mdelay(SHARPSL_CHARGE_CO_CHECK_TIME); 837 838 time = RCNR; 839 while (1) { 840 /* Check if any wakeup event had occurred */ 841 if (sharpsl_pm.machinfo->charger_wakeup()) 842 return 0; 843 /* Check for timeout */ 844 if ((RCNR-time) > SHARPSL_WAIT_CO_TIME) { 845 if (sharpsl_pm.full_count > SHARPSL_CHARGE_RETRY_CNT) { 846 dev_dbg(sharpsl_pm.dev, "Offline Charger: Not charged sufficiently. Retrying.\n"); 847 sharpsl_pm.full_count = 0; 848 } 849 sharpsl_pm.full_count++; 850 return 1; 851 } 852 if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) { 853 dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n"); 854 sharpsl_pm_led(SHARPSL_LED_OFF); 855 sharpsl_pm.machinfo->charge(0); 856 sharpsl_pm.charge_mode = CHRG_DONE; 857 return 1; 858 } 859 } 860 } 861 #else 862 #define sharpsl_pm_suspend NULL 863 #define sharpsl_pm_resume NULL 864 #endif 865 866 static ssize_t battery_percentage_show(struct device *dev, struct device_attribute *attr, char *buf) 867 { 868 return sprintf(buf, "%d\n", sharpsl_pm.battstat.mainbat_percent); 869 } 870 871 static ssize_t battery_voltage_show(struct device *dev, struct device_attribute *attr, char *buf) 872 { 873 return sprintf(buf, "%d\n", sharpsl_pm.battstat.mainbat_voltage); 874 } 875 876 static DEVICE_ATTR(battery_percentage, 0444, battery_percentage_show, NULL); 877 static DEVICE_ATTR(battery_voltage, 0444, battery_voltage_show, NULL); 878 879 extern void (*apm_get_power_status)(struct apm_power_info *); 880 881 static void sharpsl_apm_get_power_status(struct apm_power_info *info) 882 { 883 info->ac_line_status = sharpsl_pm.battstat.ac_status; 884 885 if (sharpsl_pm.charge_mode == CHRG_ON) 886 info->battery_status = APM_BATTERY_STATUS_CHARGING; 887 else 888 info->battery_status = sharpsl_pm.battstat.mainbat_status; 889 890 info->battery_flag = (1 << info->battery_status); 891 info->battery_life = sharpsl_pm.battstat.mainbat_percent; 892 } 893 894 #ifdef CONFIG_PM 895 static struct platform_suspend_ops sharpsl_pm_ops = { 896 .prepare = pxa_pm_prepare, 897 .finish = pxa_pm_finish, 898 .enter = corgi_pxa_pm_enter, 899 .valid = suspend_valid_only_mem, 900 }; 901 #endif 902 903 static int __init sharpsl_pm_probe(struct platform_device *pdev) 904 { 905 int ret; 906 907 if (!pdev->dev.platform_data) 908 return -EINVAL; 909 910 sharpsl_pm.dev = &pdev->dev; 911 sharpsl_pm.machinfo = pdev->dev.platform_data; 912 sharpsl_pm.charge_mode = CHRG_OFF; 913 sharpsl_pm.flags = 0; 914 915 init_timer(&sharpsl_pm.ac_timer); 916 sharpsl_pm.ac_timer.function = sharpsl_ac_timer; 917 918 init_timer(&sharpsl_pm.chrg_full_timer); 919 sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer; 920 921 led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger); 922 923 sharpsl_pm.machinfo->init(); 924 925 gpio_request(sharpsl_pm.machinfo->gpio_acin, "AC IN"); 926 gpio_direction_input(sharpsl_pm.machinfo->gpio_acin); 927 gpio_request(sharpsl_pm.machinfo->gpio_batfull, "Battery Full"); 928 gpio_direction_input(sharpsl_pm.machinfo->gpio_batfull); 929 gpio_request(sharpsl_pm.machinfo->gpio_batlock, "Battery Lock"); 930 gpio_direction_input(sharpsl_pm.machinfo->gpio_batlock); 931 932 /* Register interrupt handlers */ 933 if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "AC Input Detect", sharpsl_ac_isr)) { 934 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin)); 935 } 936 937 if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Battery Cover", sharpsl_fatal_isr)) { 938 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock)); 939 } 940 941 if (sharpsl_pm.machinfo->gpio_fatal) { 942 if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Fatal Battery", sharpsl_fatal_isr)) { 943 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal)); 944 } 945 } 946 947 if (sharpsl_pm.machinfo->batfull_irq) { 948 /* Register interrupt handler. */ 949 if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING, "CO", sharpsl_chrg_full_isr)) { 950 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull)); 951 } 952 } 953 954 ret = device_create_file(&pdev->dev, &dev_attr_battery_percentage); 955 ret |= device_create_file(&pdev->dev, &dev_attr_battery_voltage); 956 if (ret != 0) 957 dev_warn(&pdev->dev, "Failed to register attributes (%d)\n", ret); 958 959 apm_get_power_status = sharpsl_apm_get_power_status; 960 961 #ifdef CONFIG_PM 962 suspend_set_ops(&sharpsl_pm_ops); 963 #endif 964 965 mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250)); 966 967 return 0; 968 } 969 970 static int sharpsl_pm_remove(struct platform_device *pdev) 971 { 972 suspend_set_ops(NULL); 973 974 device_remove_file(&pdev->dev, &dev_attr_battery_percentage); 975 device_remove_file(&pdev->dev, &dev_attr_battery_voltage); 976 977 led_trigger_unregister_simple(sharpsl_charge_led_trigger); 978 979 free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr); 980 free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr); 981 982 if (sharpsl_pm.machinfo->gpio_fatal) 983 free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr); 984 985 if (sharpsl_pm.machinfo->batfull_irq) 986 free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr); 987 988 gpio_free(sharpsl_pm.machinfo->gpio_batlock); 989 gpio_free(sharpsl_pm.machinfo->gpio_batfull); 990 gpio_free(sharpsl_pm.machinfo->gpio_acin); 991 992 if (sharpsl_pm.machinfo->exit) 993 sharpsl_pm.machinfo->exit(); 994 995 del_timer_sync(&sharpsl_pm.chrg_full_timer); 996 del_timer_sync(&sharpsl_pm.ac_timer); 997 998 return 0; 999 } 1000 1001 static struct platform_driver sharpsl_pm_driver = { 1002 .probe = sharpsl_pm_probe, 1003 .remove = sharpsl_pm_remove, 1004 .suspend = sharpsl_pm_suspend, 1005 .resume = sharpsl_pm_resume, 1006 .driver = { 1007 .name = "sharpsl-pm", 1008 }, 1009 }; 1010 1011 static int __devinit sharpsl_pm_init(void) 1012 { 1013 return platform_driver_register(&sharpsl_pm_driver); 1014 } 1015 1016 static void sharpsl_pm_exit(void) 1017 { 1018 platform_driver_unregister(&sharpsl_pm_driver); 1019 } 1020 1021 late_initcall(sharpsl_pm_init); 1022 module_exit(sharpsl_pm_exit); 1023