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