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 spitz_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 spitz_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 if (machine_is_tosa()) // Ugly, better move this function into another module 181 return 0; 182 183 #ifdef CONFIG_CORGI_SSP_DEPRECATED 184 return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1 185 | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR); 186 #else 187 extern int max1111_read_channel(int); 188 189 /* max1111 accepts channels from 0-3, however, 190 * it is encoded from 0-7 here in the code. 191 */ 192 return max1111_read_channel(channel >> 1); 193 #endif 194 } 195 196 static int get_percentage(int voltage) 197 { 198 int i = sharpsl_pm.machinfo->bat_levels - 1; 199 int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0; 200 struct battery_thresh *thresh; 201 202 if (sharpsl_pm.charge_mode == CHRG_ON) 203 thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin; 204 else 205 thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac; 206 207 while (i > 0 && (voltage > thresh[i].voltage)) 208 i--; 209 210 return thresh[i].percentage; 211 } 212 213 static int get_apm_status(int voltage) 214 { 215 int low_thresh, high_thresh; 216 217 if (sharpsl_pm.charge_mode == CHRG_ON) { 218 high_thresh = sharpsl_pm.machinfo->status_high_acin; 219 low_thresh = sharpsl_pm.machinfo->status_low_acin; 220 } else { 221 high_thresh = sharpsl_pm.machinfo->status_high_noac; 222 low_thresh = sharpsl_pm.machinfo->status_low_noac; 223 } 224 225 if (voltage >= high_thresh) 226 return APM_BATTERY_STATUS_HIGH; 227 if (voltage >= low_thresh) 228 return APM_BATTERY_STATUS_LOW; 229 return APM_BATTERY_STATUS_CRITICAL; 230 } 231 232 void sharpsl_battery_kick(void) 233 { 234 schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125)); 235 } 236 EXPORT_SYMBOL(sharpsl_battery_kick); 237 238 239 static void sharpsl_battery_thread(struct work_struct *private_) 240 { 241 int voltage, percent, apm_status, i = 0; 242 243 if (!sharpsl_pm.machinfo) 244 return; 245 246 sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE); 247 248 /* Corgi cannot confirm when battery fully charged so periodically kick! */ 249 if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON) 250 && time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_ON_TIME_INTERVAL)) 251 schedule_delayed_work(&toggle_charger, 0); 252 253 while(1) { 254 voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT); 255 256 if (voltage > 0) break; 257 if (i++ > 5) { 258 voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage; 259 dev_warn(sharpsl_pm.dev, "Warning: Cannot read main battery!\n"); 260 break; 261 } 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) || (apm_status == APM_BATTERY_STATUS_HIGH) || percent <= sharpsl_pm.battstat.mainbat_percent) { 271 sharpsl_pm.battstat.mainbat_voltage = voltage; 272 sharpsl_pm.battstat.mainbat_status = apm_status; 273 sharpsl_pm.battstat.mainbat_percent = percent; 274 } 275 276 dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %ld\n", voltage, 277 sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies); 278 279 #ifdef CONFIG_BACKLIGHT_CORGI 280 /* If battery is low. limit backlight intensity to save power. */ 281 if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE) 282 && ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) || 283 (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) { 284 if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) { 285 sharpsl_pm.machinfo->backlight_limit(1); 286 sharpsl_pm.flags |= SHARPSL_BL_LIMIT; 287 } 288 } else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) { 289 sharpsl_pm.machinfo->backlight_limit(0); 290 sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT; 291 } 292 #endif 293 294 /* Suspend if critical battery level */ 295 if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE) 296 && (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL) 297 && !(sharpsl_pm.flags & SHARPSL_APM_QUEUED)) { 298 sharpsl_pm.flags |= SHARPSL_APM_QUEUED; 299 dev_err(sharpsl_pm.dev, "Fatal Off\n"); 300 apm_queue_event(APM_CRITICAL_SUSPEND); 301 } 302 303 schedule_delayed_work(&sharpsl_bat, SHARPSL_BATCHK_TIME); 304 } 305 306 void sharpsl_pm_led(int val) 307 { 308 if (val == SHARPSL_LED_ERROR) { 309 dev_err(sharpsl_pm.dev, "Charging Error!\n"); 310 } else if (val == SHARPSL_LED_ON) { 311 dev_dbg(sharpsl_pm.dev, "Charge LED On\n"); 312 led_trigger_event(sharpsl_charge_led_trigger, LED_FULL); 313 } else { 314 dev_dbg(sharpsl_pm.dev, "Charge LED Off\n"); 315 led_trigger_event(sharpsl_charge_led_trigger, LED_OFF); 316 } 317 } 318 319 static void sharpsl_charge_on(void) 320 { 321 dev_dbg(sharpsl_pm.dev, "Turning Charger On\n"); 322 323 sharpsl_pm.full_count = 0; 324 sharpsl_pm.charge_mode = CHRG_ON; 325 schedule_delayed_work(&toggle_charger, msecs_to_jiffies(250)); 326 schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(500)); 327 } 328 329 static void sharpsl_charge_off(void) 330 { 331 dev_dbg(sharpsl_pm.dev, "Turning Charger Off\n"); 332 333 sharpsl_pm.machinfo->charge(0); 334 sharpsl_pm_led(SHARPSL_LED_OFF); 335 sharpsl_pm.charge_mode = CHRG_OFF; 336 337 schedule_delayed_work(&sharpsl_bat, 0); 338 } 339 340 static void sharpsl_charge_error(void) 341 { 342 sharpsl_pm_led(SHARPSL_LED_ERROR); 343 sharpsl_pm.machinfo->charge(0); 344 sharpsl_pm.charge_mode = CHRG_ERROR; 345 } 346 347 static void sharpsl_charge_toggle(struct work_struct *private_) 348 { 349 dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies); 350 351 if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) { 352 sharpsl_charge_off(); 353 return; 354 } else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) { 355 sharpsl_charge_error(); 356 return; 357 } 358 359 sharpsl_pm_led(SHARPSL_LED_ON); 360 sharpsl_pm.machinfo->charge(0); 361 mdelay(SHARPSL_CHARGE_WAIT_TIME); 362 sharpsl_pm.machinfo->charge(1); 363 364 sharpsl_pm.charge_start_time = jiffies; 365 } 366 367 static void sharpsl_ac_timer(unsigned long data) 368 { 369 int acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN); 370 371 dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin); 372 373 sharpsl_average_clear(); 374 if (acin && (sharpsl_pm.charge_mode != CHRG_ON)) 375 sharpsl_charge_on(); 376 else if (sharpsl_pm.charge_mode == CHRG_ON) 377 sharpsl_charge_off(); 378 379 schedule_delayed_work(&sharpsl_bat, 0); 380 } 381 382 383 static irqreturn_t sharpsl_ac_isr(int irq, void *dev_id) 384 { 385 /* Delay the event slightly to debounce */ 386 /* Must be a smaller delay than the chrg_full_isr below */ 387 mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250)); 388 389 return IRQ_HANDLED; 390 } 391 392 static void sharpsl_chrg_full_timer(unsigned long data) 393 { 394 dev_dbg(sharpsl_pm.dev, "Charge Full at time: %lx\n", jiffies); 395 396 sharpsl_pm.full_count++; 397 398 if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) { 399 dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n"); 400 if (sharpsl_pm.charge_mode == CHRG_ON) 401 sharpsl_charge_off(); 402 } else if (sharpsl_pm.full_count < 2) { 403 dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n"); 404 schedule_delayed_work(&toggle_charger, 0); 405 } else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) { 406 dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n"); 407 schedule_delayed_work(&toggle_charger, 0); 408 } else { 409 sharpsl_charge_off(); 410 sharpsl_pm.charge_mode = CHRG_DONE; 411 dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n"); 412 } 413 } 414 415 /* Charging Finished Interrupt (Not present on Corgi) */ 416 /* Can trigger at the same time as an AC status change so 417 delay until after that has been processed */ 418 static irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id) 419 { 420 if (sharpsl_pm.flags & SHARPSL_SUSPENDED) 421 return IRQ_HANDLED; 422 423 /* delay until after any ac interrupt */ 424 mod_timer(&sharpsl_pm.chrg_full_timer, jiffies + msecs_to_jiffies(500)); 425 426 return IRQ_HANDLED; 427 } 428 429 static irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id) 430 { 431 int is_fatal = 0; 432 433 if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) { 434 dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n"); 435 is_fatal = 1; 436 } 437 438 if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL)) { 439 dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n"); 440 is_fatal = 1; 441 } 442 443 if (!(sharpsl_pm.flags & SHARPSL_APM_QUEUED) && is_fatal) { 444 sharpsl_pm.flags |= SHARPSL_APM_QUEUED; 445 apm_queue_event(APM_CRITICAL_SUSPEND); 446 } 447 448 return IRQ_HANDLED; 449 } 450 451 /* 452 * Maintain an average of the last 10 readings 453 */ 454 #define SHARPSL_CNV_VALUE_NUM 10 455 static int sharpsl_ad_index; 456 457 static void sharpsl_average_clear(void) 458 { 459 sharpsl_ad_index = 0; 460 } 461 462 static int sharpsl_average_value(int ad) 463 { 464 int i, ad_val = 0; 465 static int sharpsl_ad[SHARPSL_CNV_VALUE_NUM+1]; 466 467 if (sharpsl_pm.battstat.mainbat_status != APM_BATTERY_STATUS_HIGH) { 468 sharpsl_ad_index = 0; 469 return ad; 470 } 471 472 sharpsl_ad[sharpsl_ad_index] = ad; 473 sharpsl_ad_index++; 474 if (sharpsl_ad_index >= SHARPSL_CNV_VALUE_NUM) { 475 for (i=0; i < (SHARPSL_CNV_VALUE_NUM-1); i++) 476 sharpsl_ad[i] = sharpsl_ad[i+1]; 477 sharpsl_ad_index = SHARPSL_CNV_VALUE_NUM - 1; 478 } 479 for (i=0; i < sharpsl_ad_index; i++) 480 ad_val += sharpsl_ad[i]; 481 482 return (ad_val / sharpsl_ad_index); 483 } 484 485 /* 486 * Take an array of 5 integers, remove the maximum and minimum values 487 * and return the average. 488 */ 489 static int get_select_val(int *val) 490 { 491 int i, j, k, temp, sum = 0; 492 493 /* Find MAX val */ 494 temp = val[0]; 495 j=0; 496 for (i=1; i<5; i++) { 497 if (temp < val[i]) { 498 temp = val[i]; 499 j = i; 500 } 501 } 502 503 /* Find MIN val */ 504 temp = val[4]; 505 k=4; 506 for (i=3; i>=0; i--) { 507 if (temp > val[i]) { 508 temp = val[i]; 509 k = i; 510 } 511 } 512 513 for (i=0; i<5; i++) 514 if (i != j && i != k ) 515 sum += val[i]; 516 517 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]); 518 519 return (sum/3); 520 } 521 522 static int sharpsl_check_battery_temp(void) 523 { 524 int val, i, buff[5]; 525 526 /* Check battery temperature */ 527 for (i=0; i<5; i++) { 528 mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); 529 sharpsl_pm.machinfo->measure_temp(1); 530 mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); 531 buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_TEMP); 532 sharpsl_pm.machinfo->measure_temp(0); 533 } 534 535 val = get_select_val(buff); 536 537 dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val); 538 if (val > sharpsl_pm.machinfo->charge_on_temp) { 539 printk(KERN_WARNING "Not charging: temperature out of limits.\n"); 540 return -1; 541 } 542 543 return 0; 544 } 545 546 #ifdef CONFIG_PM 547 static int sharpsl_check_battery_voltage(void) 548 { 549 int val, i, buff[5]; 550 551 /* disable charge, enable discharge */ 552 sharpsl_pm.machinfo->charge(0); 553 sharpsl_pm.machinfo->discharge(1); 554 mdelay(SHARPSL_WAIT_DISCHARGE_ON); 555 556 if (sharpsl_pm.machinfo->discharge1) 557 sharpsl_pm.machinfo->discharge1(1); 558 559 /* Check battery voltage */ 560 for (i=0; i<5; i++) { 561 buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT); 562 mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); 563 } 564 565 if (sharpsl_pm.machinfo->discharge1) 566 sharpsl_pm.machinfo->discharge1(0); 567 568 sharpsl_pm.machinfo->discharge(0); 569 570 val = get_select_val(buff); 571 dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val); 572 573 if (val < sharpsl_pm.machinfo->charge_on_volt) 574 return -1; 575 576 return 0; 577 } 578 #endif 579 580 static int sharpsl_ac_check(void) 581 { 582 int temp, i, buff[5]; 583 584 for (i=0; i<5; i++) { 585 buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_ACIN_VOLT); 586 mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN); 587 } 588 589 temp = get_select_val(buff); 590 dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp); 591 592 if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) { 593 dev_err(sharpsl_pm.dev, "Error: AC check failed.\n"); 594 return -1; 595 } 596 597 return 0; 598 } 599 600 #ifdef CONFIG_PM 601 static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state) 602 { 603 sharpsl_pm.flags |= SHARPSL_SUSPENDED; 604 flush_scheduled_work(); 605 606 if (sharpsl_pm.charge_mode == CHRG_ON) 607 sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; 608 else 609 sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; 610 611 return 0; 612 } 613 614 static int sharpsl_pm_resume(struct platform_device *pdev) 615 { 616 /* Clear the reset source indicators as they break the bootloader upon reboot */ 617 RCSR = 0x0f; 618 sharpsl_average_clear(); 619 sharpsl_pm.flags &= ~SHARPSL_APM_QUEUED; 620 sharpsl_pm.flags &= ~SHARPSL_SUSPENDED; 621 622 return 0; 623 } 624 625 static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state) 626 { 627 dev_dbg(sharpsl_pm.dev, "Time is: %08x\n",RCNR); 628 629 dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG); 630 /* not charging and AC-IN! */ 631 632 if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN))) { 633 dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n"); 634 sharpsl_pm.charge_mode = CHRG_OFF; 635 sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; 636 sharpsl_off_charge_battery(); 637 } 638 639 sharpsl_pm.machinfo->presuspend(); 640 641 PEDR = 0xffffffff; /* clear it */ 642 643 sharpsl_pm.flags &= ~SHARPSL_ALARM_ACTIVE; 644 if ((sharpsl_pm.charge_mode == CHRG_ON) && ((alarm_enable && ((alarm_time - RCNR) > (SHARPSL_BATCHK_TIME_SUSPEND + 30))) || !alarm_enable)) { 645 RTSR &= RTSR_ALE; 646 RTAR = RCNR + SHARPSL_BATCHK_TIME_SUSPEND; 647 dev_dbg(sharpsl_pm.dev, "Charging alarm at: %08x\n",RTAR); 648 sharpsl_pm.flags |= SHARPSL_ALARM_ACTIVE; 649 } else if (alarm_enable) { 650 RTSR &= RTSR_ALE; 651 RTAR = alarm_time; 652 dev_dbg(sharpsl_pm.dev, "User alarm at: %08x\n",RTAR); 653 } else { 654 dev_dbg(sharpsl_pm.dev, "No alarms set.\n"); 655 } 656 657 pxa_pm_enter(state); 658 659 sharpsl_pm.machinfo->postsuspend(); 660 661 dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n",PEDR); 662 } 663 664 static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state) 665 { 666 if (!sharpsl_pm.machinfo->should_wakeup(!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE) && alarm_enable) ) 667 { 668 if (!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE)) { 669 dev_dbg(sharpsl_pm.dev, "No user triggered wakeup events and not charging. Strange. Suspend.\n"); 670 corgi_goto_sleep(alarm_time, alarm_enable, state); 671 return 1; 672 } 673 if(sharpsl_off_charge_battery()) { 674 dev_dbg(sharpsl_pm.dev, "Charging. Suspend...\n"); 675 corgi_goto_sleep(alarm_time, alarm_enable, state); 676 return 1; 677 } 678 dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n"); 679 } 680 681 if ((!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) || (sharpsl_fatal_check() < 0) ) 682 { 683 dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n"); 684 corgi_goto_sleep(alarm_time, alarm_enable, state); 685 return 1; 686 } 687 688 return 0; 689 } 690 691 static int corgi_pxa_pm_enter(suspend_state_t state) 692 { 693 unsigned long alarm_time = RTAR; 694 unsigned int alarm_status = ((RTSR & RTSR_ALE) != 0); 695 696 dev_dbg(sharpsl_pm.dev, "SharpSL suspending for first time.\n"); 697 698 corgi_goto_sleep(alarm_time, alarm_status, state); 699 700 while (corgi_enter_suspend(alarm_time,alarm_status,state)) 701 {} 702 703 if (sharpsl_pm.machinfo->earlyresume) 704 sharpsl_pm.machinfo->earlyresume(); 705 706 dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n"); 707 708 return 0; 709 } 710 711 /* 712 * Check for fatal battery errors 713 * Fatal returns -1 714 */ 715 static int sharpsl_fatal_check(void) 716 { 717 int buff[5], temp, i, acin; 718 719 dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n"); 720 721 /* Check AC-Adapter */ 722 acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN); 723 724 if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { 725 sharpsl_pm.machinfo->charge(0); 726 udelay(100); 727 sharpsl_pm.machinfo->discharge(1); /* enable discharge */ 728 mdelay(SHARPSL_WAIT_DISCHARGE_ON); 729 } 730 731 if (sharpsl_pm.machinfo->discharge1) 732 sharpsl_pm.machinfo->discharge1(1); 733 734 /* Check battery : check inserting battery ? */ 735 for (i=0; i<5; i++) { 736 buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT); 737 mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); 738 } 739 740 if (sharpsl_pm.machinfo->discharge1) 741 sharpsl_pm.machinfo->discharge1(0); 742 743 if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { 744 udelay(100); 745 sharpsl_pm.machinfo->charge(1); 746 sharpsl_pm.machinfo->discharge(0); 747 } 748 749 temp = get_select_val(buff); 750 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)); 751 752 if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) || 753 (!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt))) 754 return -1; 755 return 0; 756 } 757 758 static int sharpsl_off_charge_error(void) 759 { 760 dev_err(sharpsl_pm.dev, "Offline Charger: Error occurred.\n"); 761 sharpsl_pm.machinfo->charge(0); 762 sharpsl_pm_led(SHARPSL_LED_ERROR); 763 sharpsl_pm.charge_mode = CHRG_ERROR; 764 return 1; 765 } 766 767 /* 768 * Charging Control while suspended 769 * Return 1 - go straight to sleep 770 * Return 0 - sleep or wakeup depending on other factors 771 */ 772 static int sharpsl_off_charge_battery(void) 773 { 774 int time; 775 776 dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode); 777 778 if (sharpsl_pm.charge_mode == CHRG_OFF) { 779 dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n"); 780 781 /* AC Check */ 782 if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0)) 783 return sharpsl_off_charge_error(); 784 785 /* Start Charging */ 786 sharpsl_pm_led(SHARPSL_LED_ON); 787 sharpsl_pm.machinfo->charge(0); 788 mdelay(SHARPSL_CHARGE_WAIT_TIME); 789 sharpsl_pm.machinfo->charge(1); 790 791 sharpsl_pm.charge_mode = CHRG_ON; 792 sharpsl_pm.full_count = 0; 793 794 return 1; 795 } else if (sharpsl_pm.charge_mode != CHRG_ON) { 796 return 1; 797 } 798 799 if (sharpsl_pm.full_count == 0) { 800 int time; 801 802 dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n"); 803 804 if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0)) 805 return sharpsl_off_charge_error(); 806 807 sharpsl_pm.machinfo->charge(0); 808 mdelay(SHARPSL_CHARGE_WAIT_TIME); 809 sharpsl_pm.machinfo->charge(1); 810 sharpsl_pm.charge_mode = CHRG_ON; 811 812 mdelay(SHARPSL_CHARGE_CO_CHECK_TIME); 813 814 time = RCNR; 815 while(1) { 816 /* Check if any wakeup event had occurred */ 817 if (sharpsl_pm.machinfo->charger_wakeup() != 0) 818 return 0; 819 /* Check for timeout */ 820 if ((RCNR - time) > SHARPSL_WAIT_CO_TIME) 821 return 1; 822 if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) { 823 dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occurred. Retrying to check\n"); 824 sharpsl_pm.full_count++; 825 sharpsl_pm.machinfo->charge(0); 826 mdelay(SHARPSL_CHARGE_WAIT_TIME); 827 sharpsl_pm.machinfo->charge(1); 828 return 1; 829 } 830 } 831 } 832 833 dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 3\n"); 834 835 mdelay(SHARPSL_CHARGE_CO_CHECK_TIME); 836 837 time = RCNR; 838 while(1) { 839 /* Check if any wakeup event had occurred */ 840 if (sharpsl_pm.machinfo->charger_wakeup() != 0) 841 return 0; 842 /* Check for timeout */ 843 if ((RCNR-time) > SHARPSL_WAIT_CO_TIME) { 844 if (sharpsl_pm.full_count > SHARPSL_CHARGE_RETRY_CNT) { 845 dev_dbg(sharpsl_pm.dev, "Offline Charger: Not charged sufficiently. Retrying.\n"); 846 sharpsl_pm.full_count = 0; 847 } 848 sharpsl_pm.full_count++; 849 return 1; 850 } 851 if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) { 852 dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n"); 853 sharpsl_pm_led(SHARPSL_LED_OFF); 854 sharpsl_pm.machinfo->charge(0); 855 sharpsl_pm.charge_mode = CHRG_DONE; 856 return 1; 857 } 858 } 859 } 860 #else 861 #define sharpsl_pm_suspend NULL 862 #define sharpsl_pm_resume NULL 863 #endif 864 865 static ssize_t battery_percentage_show(struct device *dev, struct device_attribute *attr, char *buf) 866 { 867 return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_percent); 868 } 869 870 static ssize_t battery_voltage_show(struct device *dev, struct device_attribute *attr, char *buf) 871 { 872 return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_voltage); 873 } 874 875 static DEVICE_ATTR(battery_percentage, 0444, battery_percentage_show, NULL); 876 static DEVICE_ATTR(battery_voltage, 0444, battery_voltage_show, NULL); 877 878 extern void (*apm_get_power_status)(struct apm_power_info *); 879 880 static void sharpsl_apm_get_power_status(struct apm_power_info *info) 881 { 882 info->ac_line_status = sharpsl_pm.battstat.ac_status; 883 884 if (sharpsl_pm.charge_mode == CHRG_ON) 885 info->battery_status = APM_BATTERY_STATUS_CHARGING; 886 else 887 info->battery_status = sharpsl_pm.battstat.mainbat_status; 888 889 info->battery_flag = (1 << info->battery_status); 890 info->battery_life = sharpsl_pm.battstat.mainbat_percent; 891 } 892 893 #ifdef CONFIG_PM 894 static struct platform_suspend_ops sharpsl_pm_ops = { 895 .prepare = pxa_pm_prepare, 896 .finish = pxa_pm_finish, 897 .enter = corgi_pxa_pm_enter, 898 .valid = suspend_valid_only_mem, 899 }; 900 #endif 901 902 static int __init sharpsl_pm_probe(struct platform_device *pdev) 903 { 904 int ret; 905 906 if (!pdev->dev.platform_data) 907 return -EINVAL; 908 909 sharpsl_pm.dev = &pdev->dev; 910 sharpsl_pm.machinfo = pdev->dev.platform_data; 911 sharpsl_pm.charge_mode = CHRG_OFF; 912 sharpsl_pm.flags = 0; 913 914 init_timer(&sharpsl_pm.ac_timer); 915 sharpsl_pm.ac_timer.function = sharpsl_ac_timer; 916 917 init_timer(&sharpsl_pm.chrg_full_timer); 918 sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer; 919 920 led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger); 921 922 sharpsl_pm.machinfo->init(); 923 924 gpio_request(sharpsl_pm.machinfo->gpio_acin, "AC IN"); 925 gpio_direction_input(sharpsl_pm.machinfo->gpio_acin); 926 gpio_request(sharpsl_pm.machinfo->gpio_batfull, "Battery Full"); 927 gpio_direction_input(sharpsl_pm.machinfo->gpio_batfull); 928 gpio_request(sharpsl_pm.machinfo->gpio_batlock, "Battery Lock"); 929 gpio_direction_input(sharpsl_pm.machinfo->gpio_batlock); 930 931 /* Register interrupt handlers */ 932 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)) { 933 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin)); 934 } 935 936 if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Battery Cover", sharpsl_fatal_isr)) { 937 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock)); 938 } 939 940 if (sharpsl_pm.machinfo->gpio_fatal) { 941 if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Fatal Battery", sharpsl_fatal_isr)) { 942 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal)); 943 } 944 } 945 946 if (sharpsl_pm.machinfo->batfull_irq) 947 { 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