hh.org updates
[hh.org.git] / arch / arm / mach-pxa / h5400 / h5400_battery.c
bloba7b615e0e5bf14bdbd9ab67fc644297850c8a6fd
1 /*
2 * Battery driver for iPAQ h5400
4 * Copyright 2005 Phil Blundell
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 */
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/tty.h>
15 #include <linux/sched.h>
16 #include <linux/delay.h>
17 #include <linux/pm.h>
18 #include <linux/err.h>
19 #include <linux/interrupt.h>
20 #include <linux/platform_device.h>
22 #include <asm/mach-types.h>
23 #include <asm/hardware.h>
24 #include <asm/apm.h>
26 #include <asm/mach/arch.h>
28 #include <asm/arch/pxa-regs.h>
29 #include <asm/arch/h5400-asic.h>
30 #include <asm/arch/h5400-gpio.h>
32 #include <asm/hardware/samcop_base.h>
34 #define POWER_NONE 0
35 #define POWER_AC 1
36 #define POWER_USB 2
38 static int power_status;
40 static inline int
41 h5400_power_status (void)
43 int val = samcop_get_gpio_a (&h5400_samcop.dev);
45 if (val & SAMCOP_GPIO_GPA_ADP_IN_STATUS)
46 return POWER_AC;
48 if (val & SAMCOP_GPIO_GPA_USB_DETECT)
49 return POWER_USB;
51 return POWER_NONE;
54 static void
55 h5400_apm_get_power_status (struct apm_power_info *info)
57 info->ac_line_status = (power_status != POWER_NONE) ? APM_AC_ONLINE : APM_AC_OFFLINE;
60 static irqreturn_t
61 h5400_ac_in_isr (int irq, void *dev_id, struct pt_regs *regs)
63 SET_H5400_GPIO (CHG_EN, 0);
64 SET_H5400_GPIO (USB_CHG_RATE, 0);
65 SET_H5400_GPIO (EXT_CHG_RATE, 0);
67 power_status = h5400_power_status ();
69 switch (power_status) {
70 case POWER_AC:
71 printk (KERN_DEBUG "h5400_battery: charger on (AC)\n");
72 SET_H5400_GPIO (EXT_CHG_RATE, 1);
73 SET_H5400_GPIO (CHG_EN, 1);
74 break;
75 case POWER_USB:
76 printk (KERN_DEBUG "h5400_battery: charger on (USB)\n");
77 SET_H5400_GPIO (USB_CHG_RATE, 1);
78 SET_H5400_GPIO (CHG_EN, 1);
79 break;
80 case POWER_NONE:
81 printk (KERN_DEBUG "h5400_battery: charger off\n");
82 break;
85 return IRQ_HANDLED;
88 static int
89 h5400_battery_init (void)
91 int result, irq_base;
93 if (! machine_is_h5400 ())
94 return -ENODEV;
96 irq_base = samcop_irq_base (&h5400_samcop.dev);
98 result = request_irq (irq_base + _IRQ_SAMCOP_WAKEUP2, h5400_ac_in_isr,
99 SA_INTERRUPT | SA_SAMPLE_RANDOM, "AC presence", NULL);
100 if (result) {
101 printk (KERN_CRIT "%s: unable to grab AC in IRQ\n", __FUNCTION__);
102 return result;
105 result = request_irq (irq_base + _IRQ_SAMCOP_WAKEUP3, h5400_ac_in_isr,
106 SA_INTERRUPT | SA_SAMPLE_RANDOM, "USB presence", NULL);
107 if (result) {
108 printk (KERN_CRIT "%s: unable to grab AC in IRQ\n", __FUNCTION__);
109 return result;
112 h5400_ac_in_isr (0, NULL, NULL);
114 apm_get_power_status = h5400_apm_get_power_status;
116 return 0;
119 static void
120 h5400_battery_exit (void)
122 int irq_base;
124 irq_base = samcop_irq_base (&h5400_samcop.dev);
126 free_irq (irq_base + _IRQ_SAMCOP_WAKEUP2, NULL);
127 free_irq (irq_base + _IRQ_SAMCOP_WAKEUP3, NULL);
128 apm_get_power_status = NULL;
131 module_init (h5400_battery_init)
132 module_exit (h5400_battery_exit)