Merge commit 'v2.6.28-rc2' into core/locking
[linux-2.6] / arch / arm / mach-pxa / sharpsl_pm.c
1 /*
2  * Battery and Power Management code for the Sharp SL-C7xx and SL-Cxx00
3  * series of PDAs
4  *
5  * Copyright (c) 2004-2005 Richard Purdie
6  *
7  * Based on code written by Sharp for 2.4 kernels
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  */
14
15 #undef DEBUG
16
17 #include <linux/module.h>
18 #include <linux/init.h>
19 #include <linux/kernel.h>
20 #include <linux/interrupt.h>
21 #include <linux/irq.h>
22 #include <linux/platform_device.h>
23 #include <linux/apm-emulation.h>
24
25 #include <mach/hardware.h>
26 #include <asm/mach-types.h>
27 #include <mach/pm.h>
28 #include <mach/pxa-regs.h>
29 #include <mach/pxa2xx-gpio.h>
30 #include <mach/sharpsl.h>
31 #include "sharpsl.h"
32
33 struct battery_thresh spitz_battery_levels_acin[] = {
34         { 213, 100},
35         { 212,  98},
36         { 211,  95},
37         { 210,  93},
38         { 209,  90},
39         { 208,  88},
40         { 207,  85},
41         { 206,  83},
42         { 205,  80},
43         { 204,  78},
44         { 203,  75},
45         { 202,  73},
46         { 201,  70},
47         { 200,  68},
48         { 199,  65},
49         { 198,  63},
50         { 197,  60},
51         { 196,  58},
52         { 195,  55},
53         { 194,  53},
54         { 193,  50},
55         { 192,  48},
56         { 192,  45},
57         { 191,  43},
58         { 191,  40},
59         { 190,  38},
60         { 190,  35},
61         { 189,  33},
62         { 188,  30},
63         { 187,  28},
64         { 186,  25},
65         { 185,  23},
66         { 184,  20},
67         { 183,  18},
68         { 182,  15},
69         { 181,  13},
70         { 180,  10},
71         { 179,   8},
72         { 178,   5},
73         {   0,   0},
74 };
75
76 struct battery_thresh  spitz_battery_levels_noac[] = {
77         { 213, 100},
78         { 212,  98},
79         { 211,  95},
80         { 210,  93},
81         { 209,  90},
82         { 208,  88},
83         { 207,  85},
84         { 206,  83},
85         { 205,  80},
86         { 204,  78},
87         { 203,  75},
88         { 202,  73},
89         { 201,  70},
90         { 200,  68},
91         { 199,  65},
92         { 198,  63},
93         { 197,  60},
94         { 196,  58},
95         { 195,  55},
96         { 194,  53},
97         { 193,  50},
98         { 192,  48},
99         { 191,  45},
100         { 190,  43},
101         { 189,  40},
102         { 188,  38},
103         { 187,  35},
104         { 186,  33},
105         { 185,  30},
106         { 184,  28},
107         { 183,  25},
108         { 182,  23},
109         { 181,  20},
110         { 180,  18},
111         { 179,  15},
112         { 178,  13},
113         { 177,  10},
114         { 176,   8},
115         { 175,   5},
116         {   0,   0},
117 };
118
119 /* MAX1111 Commands */
120 #define MAXCTRL_PD0      1u << 0
121 #define MAXCTRL_PD1      1u << 1
122 #define MAXCTRL_SGL      1u << 2
123 #define MAXCTRL_UNI      1u << 3
124 #define MAXCTRL_SEL_SH   4
125 #define MAXCTRL_STR      1u << 7
126
127 /*
128  * Read MAX1111 ADC
129  */
130 int sharpsl_pm_pxa_read_max1111(int channel)
131 {
132         if (machine_is_tosa()) // Ugly, better move this function into another module
133             return 0;
134
135 #ifdef CONFIG_CORGI_SSP_DEPRECATED
136         return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1
137                         | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR);
138 #else
139         extern int max1111_read_channel(int);
140
141         /* max1111 accepts channels from 0-3, however,
142          * it is encoded from 0-7 here in the code.
143          */
144         return max1111_read_channel(channel >> 1);
145 #endif
146 }
147
148 void sharpsl_pm_pxa_init(void)
149 {
150         pxa_gpio_mode(sharpsl_pm.machinfo->gpio_acin | GPIO_IN);
151         pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batfull | GPIO_IN);
152         pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batlock | GPIO_IN);
153
154         /* Register interrupt handlers */
155         if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED, "AC Input Detect", sharpsl_ac_isr)) {
156                 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin));
157         }
158         else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin),IRQ_TYPE_EDGE_BOTH);
159
160         if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED, "Battery Cover", sharpsl_fatal_isr)) {
161                 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock));
162         }
163         else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock),IRQ_TYPE_EDGE_FALLING);
164
165         if (sharpsl_pm.machinfo->gpio_fatal) {
166                 if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED, "Fatal Battery", sharpsl_fatal_isr)) {
167                         dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal));
168                 }
169                 else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQ_TYPE_EDGE_FALLING);
170         }
171
172         if (sharpsl_pm.machinfo->batfull_irq)
173         {
174                 /* Register interrupt handler. */
175                 if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED, "CO", sharpsl_chrg_full_isr)) {
176                         dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull));
177                 }
178                 else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQ_TYPE_EDGE_RISING);
179         }
180 }
181
182 void sharpsl_pm_pxa_remove(void)
183 {
184         free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr);
185         free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr);
186
187         if (sharpsl_pm.machinfo->gpio_fatal)
188                 free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr);
189
190         if (sharpsl_pm.machinfo->batfull_irq)
191                 free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr);
192 }