hh.org updates
[hh.org.git] / arch / arm / mach-pxa / h1900 / h1900_power.c
blob4c194566b126a3d6da3a2f73f5873dabc8dd3d18
1 /*
2 * Power and APM status driver for iPAQ h1910/h1915
4 * Use consistent with the GNU GPL is permitted,
5 * provided that this copyright notice is
6 * preserved in its entirety in all copies and derived works.
8 * Copyright (C) 2005-2006 Pawel Kolodziejski
9 * Copyright (C) 2003 Joshua Wise
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/kernel.h>
16 #include <linux/tty.h>
17 #include <linux/sched.h>
18 #include <linux/delay.h>
19 #include <linux/pm.h>
20 #include <linux/bootmem.h>
21 #include <linux/lcd.h>
22 #include <linux/backlight.h>
23 #include <linux/fb.h>
24 #include <linux/platform_device.h>
25 #include <linux/soc/asic3_base.h>
26 #include <linux/soc/tmio_mmc.h>
28 #include <asm/irq.h>
29 #include <asm/mach-types.h>
30 #include <asm/hardware.h>
31 #include <asm/setup.h>
32 #include <asm/io.h>
34 #include <asm/mach/irq.h>
35 #include <asm/mach/arch.h>
36 #include <asm/mach/map.h>
37 #include <asm/mach/irda.h>
38 #include <asm/arch/h1900-asic.h>
39 #include <asm/arch/h1900-gpio.h>
40 #include <asm/arch/ipaq.h>
41 #include <asm/arch/udc.h>
42 #include <asm/arch/pxafb.h>
44 #include <asm/arch/pxa-regs.h>
45 #include <asm/arch/pxa-pm_ll.h>
46 #include <asm/arch/irq.h>
47 #include <asm/types.h>
48 #include <asm/apm.h>
50 #include "../generic.h"
52 int battery_power;
53 extern struct platform_device h1900_asic3;
54 #define asic3 &h1900_asic3.dev
56 static u32 *addr_sig;
57 static u32 save_sig;
59 unsigned long h1900_ssp_putget(ulong data);
60 void h1900_set_led(int color, int duty_time, int cycle_time);
62 static void h1900_pxa_ll_pm_suspend(unsigned long resume_addr)
64 save_sig = *addr_sig;
65 *addr_sig = 0x4C494E42; // LINB signature for bootloader while resume
68 static void h1900_pxa_ll_pm_resume(void)
70 *addr_sig = save_sig;
73 static struct pxa_ll_pm_ops h1900_ll_pm_ops = {
74 .suspend = h1900_pxa_ll_pm_suspend,
75 .resume = h1900_pxa_ll_pm_resume,
78 void h1900_ll_pm_init(void)
80 addr_sig = phys_to_virt(0xa0a00000);
81 pxa_pm_set_ll_ops(&h1900_ll_pm_ops);
84 static irqreturn_t h1900_charge(int irq, void *dev_id, struct pt_regs *regs)
86 int charge;
88 if (!(GPLR(GPIO_NR_H1900_AC_IN_N) & GPIO_bit(GPIO_NR_H1900_AC_IN_N)) &&
89 (GPLR(GPIO_NR_H1900_MBAT_IN) & GPIO_bit(GPIO_NR_H1900_MBAT_IN)) )
90 charge = 1;
91 else
92 charge = 0;
94 if (charge) {
95 int dtime;
97 if (GPLR(GPIO_NR_H1900_CHARGING) & GPIO_bit(GPIO_NR_H1900_CHARGING)) {
98 dtime = 0x80;
99 } else {
100 dtime = 0x101;
102 asic3_set_led(asic3, 1, dtime, 0x100);
103 asic3_set_led(asic3, 0, dtime, 0x100);
104 GPSR(GPIO_NR_H1900_CHARGER_EN) = GPIO_bit(GPIO_NR_H1900_CHARGER_EN);
105 } else {
106 asic3_set_led(asic3, 1, 0, 0x100);
107 asic3_set_led(asic3, 0, 0, 0x100);
108 GPCR(GPIO_NR_H1900_CHARGER_EN) = GPIO_bit(GPIO_NR_H1900_CHARGER_EN);
111 return IRQ_HANDLED;
114 static struct irqaction h1900_charge_irq = {
115 name: "h1910/h1915 charge",
116 handler: h1900_charge,
117 flags: SA_INTERRUPT
120 #ifdef CONFIG_PM
122 #define CTRL_START 0x80
123 #define CTRL_AUX_N 0x64
124 #define CTRL_PD0 0x01
126 static void h1900_battery(void)
128 int sample;
130 sample = h1900_ssp_putget(CTRL_PD0 | CTRL_START | CTRL_AUX_N); // main battery: max - 4096, min - 3300
131 h1900_ssp_putget(CTRL_START | CTRL_AUX_N);
133 battery_power = ((sample - 3300) * 100) / 796;
135 if (!!(GPLR(GPIO_NR_H1900_AC_IN_N) & GPIO_bit(GPIO_NR_H1900_AC_IN_N))) {
136 if (battery_power > 50) {
137 asic3_set_led(asic3, 1, 0, 0x100);
138 asic3_set_led(asic3, 0, 0, 0x100);
139 } else if ((battery_power < 50) && (battery_power > 10)) {
140 h1900_set_led(H1900_GREEN_LED, 0x101, 0x100);
141 } else if (battery_power < 10) {
142 h1900_set_led(H1900_RED_LED, 0x101, 0x100);
146 //printk("bat: %d\n", battery_power);
149 typedef void (*apm_get_power_status_t)(struct apm_power_info*);
151 static void h1900_apm_get_power_status(struct apm_power_info *info)
153 h1900_battery();
155 info->battery_life = battery_power;
157 if (!(GPLR(GPIO_NR_H1900_AC_IN_N) & GPIO_bit(GPIO_NR_H1900_AC_IN_N)))
158 info->ac_line_status = APM_AC_ONLINE;
159 else
160 info->ac_line_status = APM_AC_OFFLINE;
162 if (GPLR(GPIO_NR_H1900_CHARGING) & GPIO_bit(GPIO_NR_H1900_CHARGING))
163 info->battery_status = APM_BATTERY_STATUS_CHARGING;
164 else if (!(GPLR(GPIO_NR_H1900_MBAT_IN) & GPIO_bit(GPIO_NR_H1900_MBAT_IN)))
165 info->battery_status = APM_BATTERY_STATUS_NOT_PRESENT;
166 else {
167 if (battery_power > 50)
168 info->battery_status = APM_BATTERY_STATUS_HIGH;
169 else if (battery_power < 5)
170 info->battery_status = APM_BATTERY_STATUS_CRITICAL;
171 else
172 info->battery_status = APM_BATTERY_STATUS_LOW;
175 info->time = 0;
176 info->units = 0;
179 int set_apm_get_power_status(apm_get_power_status_t t)
181 apm_get_power_status = t;
183 return 0;
185 #endif
187 static int h1900_power_probe(struct device *dev)
189 h1900_charge(0, NULL, NULL);
191 set_irq_type(IRQ_GPIO(GPIO_NR_H1900_AC_IN_N), IRQT_BOTHEDGE);
192 set_irq_type(IRQ_GPIO(GPIO_NR_H1900_MBAT_IN), IRQT_BOTHEDGE);
193 set_irq_type(IRQ_GPIO(GPIO_NR_H1900_CHARGING), IRQT_BOTHEDGE);
194 setup_irq(IRQ_GPIO(GPIO_NR_H1900_AC_IN_N), &h1900_charge_irq);
195 setup_irq(IRQ_GPIO(GPIO_NR_H1900_MBAT_IN), &h1900_charge_irq);
196 setup_irq(IRQ_GPIO(GPIO_NR_H1900_CHARGING), &h1900_charge_irq);
198 #ifdef CONFIG_PM
199 set_apm_get_power_status(h1900_apm_get_power_status);
200 #endif
202 return 0;
205 #ifdef CONFIG_PM
206 static int h1900_power_suspend(struct device *dev, pm_message_t state)
208 asic3_set_led(asic3, 1, 0, 0x100);
209 asic3_set_led(asic3, 0, 0, 0x100);
211 disable_irq(IRQ_GPIO(GPIO_NR_H1900_AC_IN_N));
212 disable_irq(IRQ_GPIO(GPIO_NR_H1900_MBAT_IN));
213 disable_irq(IRQ_GPIO(GPIO_NR_H1900_CHARGING));
215 return 0;
218 static int h1900_power_resume(struct device *dev)
220 enable_irq(IRQ_GPIO(GPIO_NR_H1900_AC_IN_N));
221 enable_irq(IRQ_GPIO(GPIO_NR_H1900_MBAT_IN));
222 enable_irq(IRQ_GPIO(GPIO_NR_H1900_CHARGING));
224 return 0;
226 #endif
228 static struct device_driver h1900_power_driver = {
229 .name = "h1900-power",
230 .bus = &platform_bus_type,
231 .probe = h1900_power_probe,
232 #ifdef CONFIG_PM
233 .suspend = h1900_power_suspend,
234 .resume = h1900_power_resume,
235 #endif
238 static int __init h1900_power_init(void)
240 if (!machine_is_h1900())
241 return -ENODEV;
243 return driver_register(&h1900_power_driver);
246 static void __exit h1900_power_exit(void)
248 driver_unregister(&h1900_power_driver);
251 module_init(h1900_power_init);
252 module_exit(h1900_power_exit);
254 MODULE_AUTHOR("Joshua Wise, Pawel Kolodziejski");
255 MODULE_DESCRIPTION("HP iPAQ h1910/h1915 Power Driver");
256 MODULE_LICENSE("GPL");