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