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