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