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