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