Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Battery and Power Management code for the Sharp SL-C7xx and SL-Cxx00
0004  * series of PDAs
0005  *
0006  * Copyright (c) 2004-2005 Richard Purdie
0007  *
0008  * Based on code written by Sharp for 2.4 kernels
0009  */
0010 
0011 #undef DEBUG
0012 
0013 #include <linux/module.h>
0014 #include <linux/kernel.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/apm-emulation.h>
0018 #include <linux/timer.h>
0019 #include <linux/delay.h>
0020 #include <linux/leds.h>
0021 #include <linux/suspend.h>
0022 #include <linux/gpio.h>
0023 #include <linux/io.h>
0024 
0025 #include <asm/mach-types.h>
0026 #include "pm.h"
0027 #include "pxa2xx-regs.h"
0028 #include "regs-rtc.h"
0029 #include "sharpsl_pm.h"
0030 
0031 /*
0032  * Constants
0033  */
0034 #define SHARPSL_CHARGE_ON_TIME_INTERVAL        (msecs_to_jiffies(1*60*1000))  /* 1 min */
0035 #define SHARPSL_CHARGE_FINISH_TIME             (msecs_to_jiffies(10*60*1000)) /* 10 min */
0036 #define SHARPSL_BATCHK_TIME                    (msecs_to_jiffies(15*1000))    /* 15 sec */
0037 #define SHARPSL_BATCHK_TIME_SUSPEND            (60*10)                        /* 10 min */
0038 
0039 #define SHARPSL_WAIT_CO_TIME                   15  /* 15 sec */
0040 #define SHARPSL_WAIT_DISCHARGE_ON              100 /* 100 msec */
0041 #define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP   10  /* 10 msec */
0042 #define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT   10  /* 10 msec */
0043 #define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN   10  /* 10 msec */
0044 #define SHARPSL_CHARGE_WAIT_TIME               15  /* 15 msec */
0045 #define SHARPSL_CHARGE_CO_CHECK_TIME           5   /* 5 msec */
0046 #define SHARPSL_CHARGE_RETRY_CNT               1   /* eqv. 10 min */
0047 
0048 /*
0049  * Prototypes
0050  */
0051 #ifdef CONFIG_PM
0052 static int sharpsl_off_charge_battery(void);
0053 static int sharpsl_check_battery_voltage(void);
0054 #endif
0055 static int sharpsl_check_battery_temp(void);
0056 static int sharpsl_ac_check(void);
0057 static int sharpsl_average_value(int ad);
0058 static void sharpsl_average_clear(void);
0059 static void sharpsl_charge_toggle(struct work_struct *private_);
0060 static void sharpsl_battery_thread(struct work_struct *private_);
0061 
0062 
0063 /*
0064  * Variables
0065  */
0066 struct sharpsl_pm_status sharpsl_pm;
0067 static DECLARE_DELAYED_WORK(toggle_charger, sharpsl_charge_toggle);
0068 static DECLARE_DELAYED_WORK(sharpsl_bat, sharpsl_battery_thread);
0069 DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger);
0070 
0071 
0072 
0073 struct battery_thresh sharpsl_battery_levels_acin[] = {
0074     { 213, 100},
0075     { 212,  98},
0076     { 211,  95},
0077     { 210,  93},
0078     { 209,  90},
0079     { 208,  88},
0080     { 207,  85},
0081     { 206,  83},
0082     { 205,  80},
0083     { 204,  78},
0084     { 203,  75},
0085     { 202,  73},
0086     { 201,  70},
0087     { 200,  68},
0088     { 199,  65},
0089     { 198,  63},
0090     { 197,  60},
0091     { 196,  58},
0092     { 195,  55},
0093     { 194,  53},
0094     { 193,  50},
0095     { 192,  48},
0096     { 192,  45},
0097     { 191,  43},
0098     { 191,  40},
0099     { 190,  38},
0100     { 190,  35},
0101     { 189,  33},
0102     { 188,  30},
0103     { 187,  28},
0104     { 186,  25},
0105     { 185,  23},
0106     { 184,  20},
0107     { 183,  18},
0108     { 182,  15},
0109     { 181,  13},
0110     { 180,  10},
0111     { 179,   8},
0112     { 178,   5},
0113     {   0,   0},
0114 };
0115 
0116 struct battery_thresh sharpsl_battery_levels_noac[] = {
0117     { 213, 100},
0118     { 212,  98},
0119     { 211,  95},
0120     { 210,  93},
0121     { 209,  90},
0122     { 208,  88},
0123     { 207,  85},
0124     { 206,  83},
0125     { 205,  80},
0126     { 204,  78},
0127     { 203,  75},
0128     { 202,  73},
0129     { 201,  70},
0130     { 200,  68},
0131     { 199,  65},
0132     { 198,  63},
0133     { 197,  60},
0134     { 196,  58},
0135     { 195,  55},
0136     { 194,  53},
0137     { 193,  50},
0138     { 192,  48},
0139     { 191,  45},
0140     { 190,  43},
0141     { 189,  40},
0142     { 188,  38},
0143     { 187,  35},
0144     { 186,  33},
0145     { 185,  30},
0146     { 184,  28},
0147     { 183,  25},
0148     { 182,  23},
0149     { 181,  20},
0150     { 180,  18},
0151     { 179,  15},
0152     { 178,  13},
0153     { 177,  10},
0154     { 176,   8},
0155     { 175,   5},
0156     {   0,   0},
0157 };
0158 
0159 /* MAX1111 Commands */
0160 #define MAXCTRL_PD0      (1u << 0)
0161 #define MAXCTRL_PD1      (1u << 1)
0162 #define MAXCTRL_SGL      (1u << 2)
0163 #define MAXCTRL_UNI      (1u << 3)
0164 #define MAXCTRL_SEL_SH   4
0165 #define MAXCTRL_STR      (1u << 7)
0166 
0167 extern int max1111_read_channel(int);
0168 /*
0169  * Read MAX1111 ADC
0170  */
0171 int sharpsl_pm_pxa_read_max1111(int channel)
0172 {
0173     /* Ugly, better move this function into another module */
0174     if (machine_is_tosa())
0175         return 0;
0176 
0177     /* max1111 accepts channels from 0-3, however,
0178      * it is encoded from 0-7 here in the code.
0179      */
0180     return max1111_read_channel(channel >> 1);
0181 }
0182 
0183 static int get_percentage(int voltage)
0184 {
0185     int i = sharpsl_pm.machinfo->bat_levels - 1;
0186     int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0;
0187     struct battery_thresh *thresh;
0188 
0189     if (sharpsl_pm.charge_mode == CHRG_ON)
0190         thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin;
0191     else
0192         thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac;
0193 
0194     while (i > 0 && (voltage > thresh[i].voltage))
0195         i--;
0196 
0197     return thresh[i].percentage;
0198 }
0199 
0200 static int get_apm_status(int voltage)
0201 {
0202     int low_thresh, high_thresh;
0203 
0204     if (sharpsl_pm.charge_mode == CHRG_ON) {
0205         high_thresh = sharpsl_pm.machinfo->status_high_acin;
0206         low_thresh = sharpsl_pm.machinfo->status_low_acin;
0207     } else {
0208         high_thresh = sharpsl_pm.machinfo->status_high_noac;
0209         low_thresh = sharpsl_pm.machinfo->status_low_noac;
0210     }
0211 
0212     if (voltage >= high_thresh)
0213         return APM_BATTERY_STATUS_HIGH;
0214     if (voltage >= low_thresh)
0215         return APM_BATTERY_STATUS_LOW;
0216     return APM_BATTERY_STATUS_CRITICAL;
0217 }
0218 
0219 void sharpsl_battery_kick(void)
0220 {
0221     schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125));
0222 }
0223 EXPORT_SYMBOL(sharpsl_battery_kick);
0224 
0225 
0226 static void sharpsl_battery_thread(struct work_struct *private_)
0227 {
0228     int voltage, percent, apm_status, i;
0229 
0230     if (!sharpsl_pm.machinfo)
0231         return;
0232 
0233     sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE);
0234 
0235     /* Corgi cannot confirm when battery fully charged so periodically kick! */
0236     if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON)
0237             && time_after(jiffies, sharpsl_pm.charge_start_time +  SHARPSL_CHARGE_ON_TIME_INTERVAL))
0238         schedule_delayed_work(&toggle_charger, 0);
0239 
0240     for (i = 0; i < 5; i++) {
0241         voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
0242         if (voltage > 0)
0243             break;
0244     }
0245     if (voltage <= 0) {
0246         voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage;
0247         dev_warn(sharpsl_pm.dev, "Warning: Cannot read main battery!\n");
0248     }
0249 
0250     voltage = sharpsl_average_value(voltage);
0251     apm_status = get_apm_status(voltage);
0252     percent = get_percentage(voltage);
0253 
0254     /* At low battery voltages, the voltage has a tendency to start
0255        creeping back up so we try to avoid this here */
0256     if ((sharpsl_pm.battstat.ac_status == APM_AC_ONLINE)
0257         || (apm_status == APM_BATTERY_STATUS_HIGH)
0258         || percent <= sharpsl_pm.battstat.mainbat_percent) {
0259         sharpsl_pm.battstat.mainbat_voltage = voltage;
0260         sharpsl_pm.battstat.mainbat_status = apm_status;
0261         sharpsl_pm.battstat.mainbat_percent = percent;
0262     }
0263 
0264     dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %ld\n", voltage,
0265             sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies);
0266 
0267     /* Suspend if critical battery level */
0268     if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
0269          && (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL)
0270          && !(sharpsl_pm.flags & SHARPSL_APM_QUEUED)) {
0271         sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
0272         dev_err(sharpsl_pm.dev, "Fatal Off\n");
0273         apm_queue_event(APM_CRITICAL_SUSPEND);
0274     }
0275 
0276     schedule_delayed_work(&sharpsl_bat, SHARPSL_BATCHK_TIME);
0277 }
0278 
0279 void sharpsl_pm_led(int val)
0280 {
0281     if (val == SHARPSL_LED_ERROR) {
0282         dev_err(sharpsl_pm.dev, "Charging Error!\n");
0283     } else if (val == SHARPSL_LED_ON) {
0284         dev_dbg(sharpsl_pm.dev, "Charge LED On\n");
0285         led_trigger_event(sharpsl_charge_led_trigger, LED_FULL);
0286     } else {
0287         dev_dbg(sharpsl_pm.dev, "Charge LED Off\n");
0288         led_trigger_event(sharpsl_charge_led_trigger, LED_OFF);
0289     }
0290 }
0291 
0292 static void sharpsl_charge_on(void)
0293 {
0294     dev_dbg(sharpsl_pm.dev, "Turning Charger On\n");
0295 
0296     sharpsl_pm.full_count = 0;
0297     sharpsl_pm.charge_mode = CHRG_ON;
0298     schedule_delayed_work(&toggle_charger, msecs_to_jiffies(250));
0299     schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(500));
0300 }
0301 
0302 static void sharpsl_charge_off(void)
0303 {
0304     dev_dbg(sharpsl_pm.dev, "Turning Charger Off\n");
0305 
0306     sharpsl_pm.machinfo->charge(0);
0307     sharpsl_pm_led(SHARPSL_LED_OFF);
0308     sharpsl_pm.charge_mode = CHRG_OFF;
0309 
0310     schedule_delayed_work(&sharpsl_bat, 0);
0311 }
0312 
0313 static void sharpsl_charge_error(void)
0314 {
0315     sharpsl_pm_led(SHARPSL_LED_ERROR);
0316     sharpsl_pm.machinfo->charge(0);
0317     sharpsl_pm.charge_mode = CHRG_ERROR;
0318 }
0319 
0320 static void sharpsl_charge_toggle(struct work_struct *private_)
0321 {
0322     dev_dbg(sharpsl_pm.dev, "Toggling Charger at time: %lx\n", jiffies);
0323 
0324     if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
0325         sharpsl_charge_off();
0326         return;
0327     } else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) {
0328         sharpsl_charge_error();
0329         return;
0330     }
0331 
0332     sharpsl_pm_led(SHARPSL_LED_ON);
0333     sharpsl_pm.machinfo->charge(0);
0334     mdelay(SHARPSL_CHARGE_WAIT_TIME);
0335     sharpsl_pm.machinfo->charge(1);
0336 
0337     sharpsl_pm.charge_start_time = jiffies;
0338 }
0339 
0340 static void sharpsl_ac_timer(struct timer_list *unused)
0341 {
0342     int acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
0343 
0344     dev_dbg(sharpsl_pm.dev, "AC Status: %d\n", acin);
0345 
0346     sharpsl_average_clear();
0347     if (acin && (sharpsl_pm.charge_mode != CHRG_ON))
0348         sharpsl_charge_on();
0349     else if (sharpsl_pm.charge_mode == CHRG_ON)
0350         sharpsl_charge_off();
0351 
0352     schedule_delayed_work(&sharpsl_bat, 0);
0353 }
0354 
0355 
0356 static irqreturn_t sharpsl_ac_isr(int irq, void *dev_id)
0357 {
0358     /* Delay the event slightly to debounce */
0359     /* Must be a smaller delay than the chrg_full_isr below */
0360     mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
0361 
0362     return IRQ_HANDLED;
0363 }
0364 
0365 static void sharpsl_chrg_full_timer(struct timer_list *unused)
0366 {
0367     dev_dbg(sharpsl_pm.dev, "Charge Full at time: %lx\n", jiffies);
0368 
0369     sharpsl_pm.full_count++;
0370 
0371     if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
0372         dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n");
0373         if (sharpsl_pm.charge_mode == CHRG_ON)
0374             sharpsl_charge_off();
0375     } else if (sharpsl_pm.full_count < 2) {
0376         dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n");
0377         schedule_delayed_work(&toggle_charger, 0);
0378     } else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) {
0379         dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n");
0380         schedule_delayed_work(&toggle_charger, 0);
0381     } else {
0382         sharpsl_charge_off();
0383         sharpsl_pm.charge_mode = CHRG_DONE;
0384         dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n");
0385     }
0386 }
0387 
0388 /* Charging Finished Interrupt (Not present on Corgi) */
0389 /* Can trigger at the same time as an AC status change so
0390    delay until after that has been processed */
0391 static irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id)
0392 {
0393     if (sharpsl_pm.flags & SHARPSL_SUSPENDED)
0394         return IRQ_HANDLED;
0395 
0396     /* delay until after any ac interrupt */
0397     mod_timer(&sharpsl_pm.chrg_full_timer, jiffies + msecs_to_jiffies(500));
0398 
0399     return IRQ_HANDLED;
0400 }
0401 
0402 static irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id)
0403 {
0404     int is_fatal = 0;
0405 
0406     if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) {
0407         dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n");
0408         is_fatal = 1;
0409     }
0410 
0411     if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL)) {
0412         dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n");
0413         is_fatal = 1;
0414     }
0415 
0416     if (!(sharpsl_pm.flags & SHARPSL_APM_QUEUED) && is_fatal) {
0417         sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
0418         apm_queue_event(APM_CRITICAL_SUSPEND);
0419     }
0420 
0421     return IRQ_HANDLED;
0422 }
0423 
0424 /*
0425  * Maintain an average of the last 10 readings
0426  */
0427 #define SHARPSL_CNV_VALUE_NUM    10
0428 static int sharpsl_ad_index;
0429 
0430 static void sharpsl_average_clear(void)
0431 {
0432     sharpsl_ad_index = 0;
0433 }
0434 
0435 static int sharpsl_average_value(int ad)
0436 {
0437     int i, ad_val = 0;
0438     static int sharpsl_ad[SHARPSL_CNV_VALUE_NUM+1];
0439 
0440     if (sharpsl_pm.battstat.mainbat_status != APM_BATTERY_STATUS_HIGH) {
0441         sharpsl_ad_index = 0;
0442         return ad;
0443     }
0444 
0445     sharpsl_ad[sharpsl_ad_index] = ad;
0446     sharpsl_ad_index++;
0447     if (sharpsl_ad_index >= SHARPSL_CNV_VALUE_NUM) {
0448         for (i = 0; i < (SHARPSL_CNV_VALUE_NUM-1); i++)
0449             sharpsl_ad[i] = sharpsl_ad[i+1];
0450         sharpsl_ad_index = SHARPSL_CNV_VALUE_NUM - 1;
0451     }
0452     for (i = 0; i < sharpsl_ad_index; i++)
0453         ad_val += sharpsl_ad[i];
0454 
0455     return ad_val / sharpsl_ad_index;
0456 }
0457 
0458 /*
0459  * Take an array of 5 integers, remove the maximum and minimum values
0460  * and return the average.
0461  */
0462 static int get_select_val(int *val)
0463 {
0464     int i, j, k, temp, sum = 0;
0465 
0466     /* Find MAX val */
0467     temp = val[0];
0468     j = 0;
0469     for (i = 1; i < 5; i++) {
0470         if (temp < val[i]) {
0471             temp = val[i];
0472             j = i;
0473         }
0474     }
0475 
0476     /* Find MIN val */
0477     temp = val[4];
0478     k = 4;
0479     for (i = 3; i >= 0; i--) {
0480         if (temp > val[i]) {
0481             temp = val[i];
0482             k = i;
0483         }
0484     }
0485 
0486     for (i = 0; i < 5; i++)
0487         if (i != j && i != k)
0488             sum += val[i];
0489 
0490     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]);
0491 
0492     return sum/3;
0493 }
0494 
0495 static int sharpsl_check_battery_temp(void)
0496 {
0497     int val, i, buff[5];
0498 
0499     /* Check battery temperature */
0500     for (i = 0; i < 5; i++) {
0501         mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
0502         sharpsl_pm.machinfo->measure_temp(1);
0503         mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
0504         buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_TEMP);
0505         sharpsl_pm.machinfo->measure_temp(0);
0506     }
0507 
0508     val = get_select_val(buff);
0509 
0510     dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val);
0511     if (val > sharpsl_pm.machinfo->charge_on_temp) {
0512         printk(KERN_WARNING "Not charging: temperature out of limits.\n");
0513         return -1;
0514     }
0515 
0516     return 0;
0517 }
0518 
0519 #ifdef CONFIG_PM
0520 static int sharpsl_check_battery_voltage(void)
0521 {
0522     int val, i, buff[5];
0523 
0524     /* disable charge, enable discharge */
0525     sharpsl_pm.machinfo->charge(0);
0526     sharpsl_pm.machinfo->discharge(1);
0527     mdelay(SHARPSL_WAIT_DISCHARGE_ON);
0528 
0529     if (sharpsl_pm.machinfo->discharge1)
0530         sharpsl_pm.machinfo->discharge1(1);
0531 
0532     /* Check battery voltage */
0533     for (i = 0; i < 5; i++) {
0534         buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
0535         mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
0536     }
0537 
0538     if (sharpsl_pm.machinfo->discharge1)
0539         sharpsl_pm.machinfo->discharge1(0);
0540 
0541     sharpsl_pm.machinfo->discharge(0);
0542 
0543     val = get_select_val(buff);
0544     dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val);
0545 
0546     if (val < sharpsl_pm.machinfo->charge_on_volt)
0547         return -1;
0548 
0549     return 0;
0550 }
0551 #endif
0552 
0553 static int sharpsl_ac_check(void)
0554 {
0555     int temp, i, buff[5];
0556 
0557     for (i = 0; i < 5; i++) {
0558         buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_ACIN_VOLT);
0559         mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN);
0560     }
0561 
0562     temp = get_select_val(buff);
0563     dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n", temp);
0564 
0565     if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) {
0566         dev_err(sharpsl_pm.dev, "Error: AC check failed: voltage %d.\n", temp);
0567         return -1;
0568     }
0569 
0570     return 0;
0571 }
0572 
0573 #ifdef CONFIG_PM
0574 static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state)
0575 {
0576     sharpsl_pm.flags |= SHARPSL_SUSPENDED;
0577     flush_delayed_work(&toggle_charger);
0578     flush_delayed_work(&sharpsl_bat);
0579 
0580     if (sharpsl_pm.charge_mode == CHRG_ON)
0581         sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
0582     else
0583         sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
0584 
0585     return 0;
0586 }
0587 
0588 static int sharpsl_pm_resume(struct platform_device *pdev)
0589 {
0590     /* Clear the reset source indicators as they break the bootloader upon reboot */
0591     RCSR = 0x0f;
0592     sharpsl_average_clear();
0593     sharpsl_pm.flags &= ~SHARPSL_APM_QUEUED;
0594     sharpsl_pm.flags &= ~SHARPSL_SUSPENDED;
0595 
0596     return 0;
0597 }
0598 
0599 static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
0600 {
0601     dev_dbg(sharpsl_pm.dev, "Time is: %08x\n", RCNR);
0602 
0603     dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n", sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG);
0604     /* not charging and AC-IN! */
0605 
0606     if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN))) {
0607         dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n");
0608         sharpsl_pm.charge_mode = CHRG_OFF;
0609         sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
0610         sharpsl_off_charge_battery();
0611     }
0612 
0613     sharpsl_pm.machinfo->presuspend();
0614 
0615     PEDR = 0xffffffff; /* clear it */
0616 
0617     sharpsl_pm.flags &= ~SHARPSL_ALARM_ACTIVE;
0618     if ((sharpsl_pm.charge_mode == CHRG_ON) && ((alarm_enable && ((alarm_time - RCNR) > (SHARPSL_BATCHK_TIME_SUSPEND + 30))) || !alarm_enable)) {
0619         RTSR &= RTSR_ALE;
0620         RTAR = RCNR + SHARPSL_BATCHK_TIME_SUSPEND;
0621         dev_dbg(sharpsl_pm.dev, "Charging alarm at: %08x\n", RTAR);
0622         sharpsl_pm.flags |= SHARPSL_ALARM_ACTIVE;
0623     } else if (alarm_enable) {
0624         RTSR &= RTSR_ALE;
0625         RTAR = alarm_time;
0626         dev_dbg(sharpsl_pm.dev, "User alarm at: %08x\n", RTAR);
0627     } else {
0628         dev_dbg(sharpsl_pm.dev, "No alarms set.\n");
0629     }
0630 
0631     pxa_pm_enter(state);
0632 
0633     sharpsl_pm.machinfo->postsuspend();
0634 
0635     dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n", PEDR);
0636 }
0637 
0638 static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
0639 {
0640     if (!sharpsl_pm.machinfo->should_wakeup(!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE) && alarm_enable)) {
0641         if (!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE)) {
0642             dev_dbg(sharpsl_pm.dev, "No user triggered wakeup events and not charging. Strange. Suspend.\n");
0643             corgi_goto_sleep(alarm_time, alarm_enable, state);
0644             return 1;
0645         }
0646         if (sharpsl_off_charge_battery()) {
0647             dev_dbg(sharpsl_pm.dev, "Charging. Suspend...\n");
0648             corgi_goto_sleep(alarm_time, alarm_enable, state);
0649             return 1;
0650         }
0651         dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n");
0652     }
0653 
0654     if ((!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) ||
0655         (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL))) {
0656         dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n");
0657         corgi_goto_sleep(alarm_time, alarm_enable, state);
0658         return 1;
0659     }
0660 
0661     return 0;
0662 }
0663 
0664 static int corgi_pxa_pm_enter(suspend_state_t state)
0665 {
0666     unsigned long alarm_time = RTAR;
0667     unsigned int alarm_status = ((RTSR & RTSR_ALE) != 0);
0668 
0669     dev_dbg(sharpsl_pm.dev, "SharpSL suspending for first time.\n");
0670 
0671     corgi_goto_sleep(alarm_time, alarm_status, state);
0672 
0673     while (corgi_enter_suspend(alarm_time, alarm_status, state))
0674         {}
0675 
0676     if (sharpsl_pm.machinfo->earlyresume)
0677         sharpsl_pm.machinfo->earlyresume();
0678 
0679     dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n");
0680 
0681     return 0;
0682 }
0683 
0684 static int sharpsl_off_charge_error(void)
0685 {
0686     dev_err(sharpsl_pm.dev, "Offline Charger: Error occurred.\n");
0687     sharpsl_pm.machinfo->charge(0);
0688     sharpsl_pm_led(SHARPSL_LED_ERROR);
0689     sharpsl_pm.charge_mode = CHRG_ERROR;
0690     return 1;
0691 }
0692 
0693 /*
0694  * Charging Control while suspended
0695  * Return 1 - go straight to sleep
0696  * Return 0 - sleep or wakeup depending on other factors
0697  */
0698 static int sharpsl_off_charge_battery(void)
0699 {
0700     int time;
0701 
0702     dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode);
0703 
0704     if (sharpsl_pm.charge_mode == CHRG_OFF) {
0705         dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n");
0706 
0707         /* AC Check */
0708         if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0))
0709             return sharpsl_off_charge_error();
0710 
0711         /* Start Charging */
0712         sharpsl_pm_led(SHARPSL_LED_ON);
0713         sharpsl_pm.machinfo->charge(0);
0714         mdelay(SHARPSL_CHARGE_WAIT_TIME);
0715         sharpsl_pm.machinfo->charge(1);
0716 
0717         sharpsl_pm.charge_mode = CHRG_ON;
0718         sharpsl_pm.full_count = 0;
0719 
0720         return 1;
0721     } else if (sharpsl_pm.charge_mode != CHRG_ON) {
0722         return 1;
0723     }
0724 
0725     if (sharpsl_pm.full_count == 0) {
0726         int time;
0727 
0728         dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n");
0729 
0730         if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0))
0731             return sharpsl_off_charge_error();
0732 
0733         sharpsl_pm.machinfo->charge(0);
0734         mdelay(SHARPSL_CHARGE_WAIT_TIME);
0735         sharpsl_pm.machinfo->charge(1);
0736         sharpsl_pm.charge_mode = CHRG_ON;
0737 
0738         mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
0739 
0740         time = RCNR;
0741         while (1) {
0742             /* Check if any wakeup event had occurred */
0743             if (sharpsl_pm.machinfo->charger_wakeup())
0744                 return 0;
0745             /* Check for timeout */
0746             if ((RCNR - time) > SHARPSL_WAIT_CO_TIME)
0747                 return 1;
0748             if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
0749                 dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occurred. Retrying to check\n");
0750                 sharpsl_pm.full_count++;
0751                 sharpsl_pm.machinfo->charge(0);
0752                 mdelay(SHARPSL_CHARGE_WAIT_TIME);
0753                 sharpsl_pm.machinfo->charge(1);
0754                 return 1;
0755             }
0756         }
0757     }
0758 
0759     dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 3\n");
0760 
0761     mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
0762 
0763     time = RCNR;
0764     while (1) {
0765         /* Check if any wakeup event had occurred */
0766         if (sharpsl_pm.machinfo->charger_wakeup())
0767             return 0;
0768         /* Check for timeout */
0769         if ((RCNR-time) > SHARPSL_WAIT_CO_TIME) {
0770             if (sharpsl_pm.full_count > SHARPSL_CHARGE_RETRY_CNT) {
0771                 dev_dbg(sharpsl_pm.dev, "Offline Charger: Not charged sufficiently. Retrying.\n");
0772                 sharpsl_pm.full_count = 0;
0773             }
0774             sharpsl_pm.full_count++;
0775             return 1;
0776         }
0777         if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
0778             dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n");
0779             sharpsl_pm_led(SHARPSL_LED_OFF);
0780             sharpsl_pm.machinfo->charge(0);
0781             sharpsl_pm.charge_mode = CHRG_DONE;
0782             return 1;
0783         }
0784     }
0785 }
0786 #else
0787 #define sharpsl_pm_suspend  NULL
0788 #define sharpsl_pm_resume   NULL
0789 #endif
0790 
0791 static ssize_t battery_percentage_show(struct device *dev, struct device_attribute *attr, char *buf)
0792 {
0793     return sprintf(buf, "%d\n", sharpsl_pm.battstat.mainbat_percent);
0794 }
0795 
0796 static ssize_t battery_voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
0797 {
0798     return sprintf(buf, "%d\n", sharpsl_pm.battstat.mainbat_voltage);
0799 }
0800 
0801 static DEVICE_ATTR_RO(battery_percentage);
0802 static DEVICE_ATTR_RO(battery_voltage);
0803 
0804 extern void (*apm_get_power_status)(struct apm_power_info *);
0805 
0806 static void sharpsl_apm_get_power_status(struct apm_power_info *info)
0807 {
0808     info->ac_line_status = sharpsl_pm.battstat.ac_status;
0809 
0810     if (sharpsl_pm.charge_mode == CHRG_ON)
0811         info->battery_status = APM_BATTERY_STATUS_CHARGING;
0812     else
0813         info->battery_status = sharpsl_pm.battstat.mainbat_status;
0814 
0815     info->battery_flag = (1 << info->battery_status);
0816     info->battery_life = sharpsl_pm.battstat.mainbat_percent;
0817 }
0818 
0819 #ifdef CONFIG_PM
0820 static const struct platform_suspend_ops sharpsl_pm_ops = {
0821     .prepare    = pxa_pm_prepare,
0822     .finish     = pxa_pm_finish,
0823     .enter      = corgi_pxa_pm_enter,
0824     .valid      = suspend_valid_only_mem,
0825 };
0826 #endif
0827 
0828 static int sharpsl_pm_probe(struct platform_device *pdev)
0829 {
0830     int ret, irq;
0831 
0832     if (!pdev->dev.platform_data)
0833         return -EINVAL;
0834 
0835     sharpsl_pm.dev = &pdev->dev;
0836     sharpsl_pm.machinfo = pdev->dev.platform_data;
0837     sharpsl_pm.charge_mode = CHRG_OFF;
0838     sharpsl_pm.flags = 0;
0839 
0840     timer_setup(&sharpsl_pm.ac_timer, sharpsl_ac_timer, 0);
0841 
0842     timer_setup(&sharpsl_pm.chrg_full_timer, sharpsl_chrg_full_timer, 0);
0843 
0844     led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger);
0845 
0846     sharpsl_pm.machinfo->init();
0847 
0848     gpio_request(sharpsl_pm.machinfo->gpio_acin, "AC IN");
0849     gpio_direction_input(sharpsl_pm.machinfo->gpio_acin);
0850     gpio_request(sharpsl_pm.machinfo->gpio_batfull, "Battery Full");
0851     gpio_direction_input(sharpsl_pm.machinfo->gpio_batfull);
0852     gpio_request(sharpsl_pm.machinfo->gpio_batlock, "Battery Lock");
0853     gpio_direction_input(sharpsl_pm.machinfo->gpio_batlock);
0854 
0855     /* Register interrupt handlers */
0856     irq = gpio_to_irq(sharpsl_pm.machinfo->gpio_acin);
0857     if (request_irq(irq, sharpsl_ac_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "AC Input Detect", sharpsl_ac_isr)) {
0858         dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", irq);
0859     }
0860 
0861     irq = gpio_to_irq(sharpsl_pm.machinfo->gpio_batlock);
0862     if (request_irq(irq, sharpsl_fatal_isr, IRQF_TRIGGER_FALLING, "Battery Cover", sharpsl_fatal_isr)) {
0863         dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", irq);
0864     }
0865 
0866     if (sharpsl_pm.machinfo->gpio_fatal) {
0867         irq = gpio_to_irq(sharpsl_pm.machinfo->gpio_fatal);
0868         if (request_irq(irq, sharpsl_fatal_isr, IRQF_TRIGGER_FALLING, "Fatal Battery", sharpsl_fatal_isr)) {
0869             dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", irq);
0870         }
0871     }
0872 
0873     if (sharpsl_pm.machinfo->batfull_irq) {
0874         /* Register interrupt handler. */
0875         irq = gpio_to_irq(sharpsl_pm.machinfo->gpio_batfull);
0876         if (request_irq(irq, sharpsl_chrg_full_isr, IRQF_TRIGGER_RISING, "CO", sharpsl_chrg_full_isr)) {
0877             dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", irq);
0878         }
0879     }
0880 
0881     ret = device_create_file(&pdev->dev, &dev_attr_battery_percentage);
0882     ret |= device_create_file(&pdev->dev, &dev_attr_battery_voltage);
0883     if (ret != 0)
0884         dev_warn(&pdev->dev, "Failed to register attributes (%d)\n", ret);
0885 
0886     apm_get_power_status = sharpsl_apm_get_power_status;
0887 
0888 #ifdef CONFIG_PM
0889     suspend_set_ops(&sharpsl_pm_ops);
0890 #endif
0891 
0892     mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
0893 
0894     return 0;
0895 }
0896 
0897 static int sharpsl_pm_remove(struct platform_device *pdev)
0898 {
0899     suspend_set_ops(NULL);
0900 
0901     device_remove_file(&pdev->dev, &dev_attr_battery_percentage);
0902     device_remove_file(&pdev->dev, &dev_attr_battery_voltage);
0903 
0904     led_trigger_unregister_simple(sharpsl_charge_led_trigger);
0905 
0906     free_irq(gpio_to_irq(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr);
0907     free_irq(gpio_to_irq(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr);
0908 
0909     if (sharpsl_pm.machinfo->gpio_fatal)
0910         free_irq(gpio_to_irq(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr);
0911 
0912     if (sharpsl_pm.machinfo->batfull_irq)
0913         free_irq(gpio_to_irq(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr);
0914 
0915     gpio_free(sharpsl_pm.machinfo->gpio_batlock);
0916     gpio_free(sharpsl_pm.machinfo->gpio_batfull);
0917     gpio_free(sharpsl_pm.machinfo->gpio_acin);
0918 
0919     if (sharpsl_pm.machinfo->exit)
0920         sharpsl_pm.machinfo->exit();
0921 
0922     del_timer_sync(&sharpsl_pm.chrg_full_timer);
0923     del_timer_sync(&sharpsl_pm.ac_timer);
0924 
0925     return 0;
0926 }
0927 
0928 static struct platform_driver sharpsl_pm_driver = {
0929     .probe      = sharpsl_pm_probe,
0930     .remove     = sharpsl_pm_remove,
0931     .suspend    = sharpsl_pm_suspend,
0932     .resume     = sharpsl_pm_resume,
0933     .driver     = {
0934         .name       = "sharpsl-pm",
0935     },
0936 };
0937 
0938 static int sharpsl_pm_init(void)
0939 {
0940     return platform_driver_register(&sharpsl_pm_driver);
0941 }
0942 
0943 static void sharpsl_pm_exit(void)
0944 {
0945     platform_driver_unregister(&sharpsl_pm_driver);
0946 }
0947 
0948 late_initcall(sharpsl_pm_init);
0949 module_exit(sharpsl_pm_exit);