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