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