Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-pxa/corgi_pm.c
10817 views
1
/*
2
* Battery and Power Management code for the Sharp SL-C7xx
3
*
4
* Copyright (c) 2005 Richard Purdie
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
9
*
10
*/
11
12
#include <linux/module.h>
13
#include <linux/stat.h>
14
#include <linux/init.h>
15
#include <linux/kernel.h>
16
#include <linux/delay.h>
17
#include <linux/gpio.h>
18
#include <linux/interrupt.h>
19
#include <linux/platform_device.h>
20
#include <linux/apm-emulation.h>
21
22
#include <asm/irq.h>
23
#include <asm/mach-types.h>
24
#include <mach/hardware.h>
25
26
#include <mach/corgi.h>
27
#include <mach/pxa2xx-regs.h>
28
#include <mach/sharpsl_pm.h>
29
30
#include "generic.h"
31
32
#define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */
33
#define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */
34
#define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */
35
#define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */
36
#define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */
37
#define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */
38
39
static struct gpio charger_gpios[] = {
40
{ CORGI_GPIO_ADC_TEMP_ON, GPIOF_OUT_INIT_LOW, "ADC Temp On" },
41
{ CORGI_GPIO_CHRG_ON, GPIOF_OUT_INIT_LOW, "Charger On" },
42
{ CORGI_GPIO_CHRG_UKN, GPIOF_OUT_INIT_LOW, "Charger Unknown" },
43
{ CORGI_GPIO_KEY_INT, GPIOF_IN, "Key Interrupt" },
44
};
45
46
static void corgi_charger_init(void)
47
{
48
gpio_request_array(ARRAY_AND_SIZE(charger_gpios));
49
}
50
51
static void corgi_measure_temp(int on)
52
{
53
gpio_set_value(CORGI_GPIO_ADC_TEMP_ON, on);
54
}
55
56
static void corgi_charge(int on)
57
{
58
if (on) {
59
if (machine_is_corgi() && (sharpsl_pm.flags & SHARPSL_SUSPENDED)) {
60
gpio_set_value(CORGI_GPIO_CHRG_ON, 0);
61
gpio_set_value(CORGI_GPIO_CHRG_UKN, 1);
62
} else {
63
gpio_set_value(CORGI_GPIO_CHRG_ON, 1);
64
gpio_set_value(CORGI_GPIO_CHRG_UKN, 0);
65
}
66
} else {
67
gpio_set_value(CORGI_GPIO_CHRG_ON, 0);
68
gpio_set_value(CORGI_GPIO_CHRG_UKN, 0);
69
}
70
}
71
72
static void corgi_discharge(int on)
73
{
74
gpio_set_value(CORGI_GPIO_DISCHARGE_ON, on);
75
}
76
77
static void corgi_presuspend(void)
78
{
79
}
80
81
static void corgi_postsuspend(void)
82
{
83
}
84
85
/*
86
* Check what brought us out of the suspend.
87
* Return: 0 to sleep, otherwise wake
88
*/
89
static int corgi_should_wakeup(unsigned int resume_on_alarm)
90
{
91
int is_resume = 0;
92
93
dev_dbg(sharpsl_pm.dev, "GPLR0 = %x,%x\n", GPLR0, PEDR);
94
95
if ((PEDR & GPIO_bit(CORGI_GPIO_AC_IN))) {
96
if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
97
/* charge on */
98
dev_dbg(sharpsl_pm.dev, "ac insert\n");
99
sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
100
} else {
101
/* charge off */
102
dev_dbg(sharpsl_pm.dev, "ac remove\n");
103
sharpsl_pm_led(SHARPSL_LED_OFF);
104
sharpsl_pm.machinfo->charge(0);
105
sharpsl_pm.charge_mode = CHRG_OFF;
106
}
107
}
108
109
if ((PEDR & GPIO_bit(CORGI_GPIO_CHRG_FULL)))
110
dev_dbg(sharpsl_pm.dev, "Charge full interrupt\n");
111
112
if (PEDR & GPIO_bit(CORGI_GPIO_KEY_INT))
113
is_resume |= GPIO_bit(CORGI_GPIO_KEY_INT);
114
115
if (PEDR & GPIO_bit(CORGI_GPIO_WAKEUP))
116
is_resume |= GPIO_bit(CORGI_GPIO_WAKEUP);
117
118
if (resume_on_alarm && (PEDR & PWER_RTC))
119
is_resume |= PWER_RTC;
120
121
dev_dbg(sharpsl_pm.dev, "is_resume: %x\n",is_resume);
122
return is_resume;
123
}
124
125
static unsigned long corgi_charger_wakeup(void)
126
{
127
return ~GPLR0 & ( GPIO_bit(CORGI_GPIO_AC_IN) | GPIO_bit(CORGI_GPIO_KEY_INT) | GPIO_bit(CORGI_GPIO_WAKEUP) );
128
}
129
130
unsigned long corgipm_read_devdata(int type)
131
{
132
switch(type) {
133
case SHARPSL_STATUS_ACIN:
134
return ((GPLR(CORGI_GPIO_AC_IN) & GPIO_bit(CORGI_GPIO_AC_IN)) != 0);
135
case SHARPSL_STATUS_LOCK:
136
return gpio_get_value(sharpsl_pm.machinfo->gpio_batlock);
137
case SHARPSL_STATUS_CHRGFULL:
138
return gpio_get_value(sharpsl_pm.machinfo->gpio_batfull);
139
case SHARPSL_STATUS_FATAL:
140
return gpio_get_value(sharpsl_pm.machinfo->gpio_fatal);
141
case SHARPSL_ACIN_VOLT:
142
return sharpsl_pm_pxa_read_max1111(MAX1111_ACIN_VOLT);
143
case SHARPSL_BATT_TEMP:
144
return sharpsl_pm_pxa_read_max1111(MAX1111_BATT_TEMP);
145
case SHARPSL_BATT_VOLT:
146
default:
147
return sharpsl_pm_pxa_read_max1111(MAX1111_BATT_VOLT);
148
}
149
}
150
151
static struct sharpsl_charger_machinfo corgi_pm_machinfo = {
152
.init = corgi_charger_init,
153
.exit = NULL,
154
.gpio_batlock = CORGI_GPIO_BAT_COVER,
155
.gpio_acin = CORGI_GPIO_AC_IN,
156
.gpio_batfull = CORGI_GPIO_CHRG_FULL,
157
.discharge = corgi_discharge,
158
.charge = corgi_charge,
159
.measure_temp = corgi_measure_temp,
160
.presuspend = corgi_presuspend,
161
.postsuspend = corgi_postsuspend,
162
.read_devdata = corgipm_read_devdata,
163
.charger_wakeup = corgi_charger_wakeup,
164
.should_wakeup = corgi_should_wakeup,
165
#if defined(CONFIG_LCD_CORGI)
166
.backlight_limit = corgi_lcd_limit_intensity,
167
#endif
168
.charge_on_volt = SHARPSL_CHARGE_ON_VOLT,
169
.charge_on_temp = SHARPSL_CHARGE_ON_TEMP,
170
.charge_acin_high = SHARPSL_CHARGE_ON_ACIN_HIGH,
171
.charge_acin_low = SHARPSL_CHARGE_ON_ACIN_LOW,
172
.fatal_acin_volt = SHARPSL_FATAL_ACIN_VOLT,
173
.fatal_noacin_volt= SHARPSL_FATAL_NOACIN_VOLT,
174
.bat_levels = 40,
175
.bat_levels_noac = sharpsl_battery_levels_noac,
176
.bat_levels_acin = sharpsl_battery_levels_acin,
177
.status_high_acin = 188,
178
.status_low_acin = 178,
179
.status_high_noac = 185,
180
.status_low_noac = 175,
181
};
182
183
static struct platform_device *corgipm_device;
184
185
static int __devinit corgipm_init(void)
186
{
187
int ret;
188
189
if (!machine_is_corgi() && !machine_is_shepherd()
190
&& !machine_is_husky())
191
return -ENODEV;
192
193
corgipm_device = platform_device_alloc("sharpsl-pm", -1);
194
if (!corgipm_device)
195
return -ENOMEM;
196
197
if (!machine_is_corgi())
198
corgi_pm_machinfo.batfull_irq = 1;
199
200
corgipm_device->dev.platform_data = &corgi_pm_machinfo;
201
ret = platform_device_add(corgipm_device);
202
203
if (ret)
204
platform_device_put(corgipm_device);
205
206
return ret;
207
}
208
209
static void corgipm_exit(void)
210
{
211
platform_device_unregister(corgipm_device);
212
}
213
214
module_init(corgipm_init);
215
module_exit(corgipm_exit);
216
217