root/arch/arm/mach-pxa/sharpsl_pm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sharpsl_pm_pxa_read_max1111
  2. get_percentage
  3. get_apm_status
  4. sharpsl_battery_kick
  5. sharpsl_battery_thread
  6. sharpsl_pm_led
  7. sharpsl_charge_on
  8. sharpsl_charge_off
  9. sharpsl_charge_error
  10. sharpsl_charge_toggle
  11. sharpsl_ac_timer
  12. sharpsl_ac_isr
  13. sharpsl_chrg_full_timer
  14. sharpsl_chrg_full_isr
  15. sharpsl_fatal_isr
  16. sharpsl_average_clear
  17. sharpsl_average_value
  18. get_select_val
  19. sharpsl_check_battery_temp
  20. sharpsl_check_battery_voltage
  21. sharpsl_ac_check
  22. sharpsl_pm_suspend
  23. sharpsl_pm_resume
  24. corgi_goto_sleep
  25. corgi_enter_suspend
  26. corgi_pxa_pm_enter
  27. sharpsl_off_charge_error
  28. sharpsl_off_charge_battery
  29. battery_percentage_show
  30. battery_voltage_show
  31. sharpsl_apm_get_power_status
  32. sharpsl_pm_probe
  33. sharpsl_pm_remove
  34. sharpsl_pm_init
  35. sharpsl_pm_exit

   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
  52 static int sharpsl_off_charge_battery(void);
  53 static int sharpsl_check_battery_voltage(void);
  54 #endif
  55 static int sharpsl_check_battery_temp(void);
  56 static int sharpsl_ac_check(void);
  57 static int sharpsl_average_value(int ad);
  58 static void sharpsl_average_clear(void);
  59 static void sharpsl_charge_toggle(struct work_struct *private_);
  60 static void sharpsl_battery_thread(struct work_struct *private_);
  61 
  62 
  63 /*
  64  * Variables
  65  */
  66 struct sharpsl_pm_status sharpsl_pm;
  67 static DECLARE_DELAYED_WORK(toggle_charger, sharpsl_charge_toggle);
  68 static DECLARE_DELAYED_WORK(sharpsl_bat, sharpsl_battery_thread);
  69 DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger);
  70 
  71 
  72 
  73 struct 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 
 116 struct 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 
 167 extern int max1111_read_channel(int);
 168 /*
 169  * Read MAX1111 ADC
 170  */
 171 int 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 
 183 static 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 
 200 static 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 
 219 void sharpsl_battery_kick(void)
 220 {
 221         schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125));
 222 }
 223 EXPORT_SYMBOL(sharpsl_battery_kick);
 224 
 225 
 226 static 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 
 279 void 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 
 292 static 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 
 302 static 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 
 313 static 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 
 320 static 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 
 340 static 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 
 356 static 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 
 365 static 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 */
 391 static 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 
 402 static 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
 428 static int sharpsl_ad_index;
 429 
 430 static void sharpsl_average_clear(void)
 431 {
 432         sharpsl_ad_index = 0;
 433 }
 434 
 435 static 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  */
 462 static 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 
 495 static 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
 520 static 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 
 553 static 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
 574 static 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 
 588 static 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 
 599 static 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 
 638 static 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 
 664 static 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 
 684 static 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  */
 698 static 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 
 791 static 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 
 796 static 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 
 801 static DEVICE_ATTR_RO(battery_percentage);
 802 static DEVICE_ATTR_RO(battery_voltage);
 803 
 804 extern void (*apm_get_power_status)(struct apm_power_info *);
 805 
 806 static 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
 820 static 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 
 828 static 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 
 897 static 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 
 928 static 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 
 938 static int sharpsl_pm_init(void)
 939 {
 940         return platform_driver_register(&sharpsl_pm_driver);
 941 }
 942 
 943 static void sharpsl_pm_exit(void)
 944 {
 945         platform_driver_unregister(&sharpsl_pm_driver);
 946 }
 947 
 948 late_initcall(sharpsl_pm_init);
 949 module_exit(sharpsl_pm_exit);

/* [<][>][^][v][top][bottom][index][help] */