xref: /openbmc/linux/arch/arm/mach-pxa/sharpsl_pm.c (revision f15cbe6f1a4b4d9df59142fc8e4abb973302cf44)
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 <asm/hardware.h>
26 #include <asm/mach-types.h>
27 #include <asm/arch/pm.h>
28 #include <asm/arch/pxa-regs.h>
29 #include <asm/arch/pxa2xx-gpio.h>
30 #include <asm/arch/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 	return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1
136 			| MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR);
137 }
138 
139 void sharpsl_pm_pxa_init(void)
140 {
141 	pxa_gpio_mode(sharpsl_pm.machinfo->gpio_acin | GPIO_IN);
142 	pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batfull | GPIO_IN);
143 	pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batlock | GPIO_IN);
144 
145 	/* Register interrupt handlers */
146 	if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED, "AC Input Detect", sharpsl_ac_isr)) {
147 		dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin));
148 	}
149 	else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin),IRQ_TYPE_EDGE_BOTH);
150 
151 	if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED, "Battery Cover", sharpsl_fatal_isr)) {
152 		dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock));
153 	}
154 	else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock),IRQ_TYPE_EDGE_FALLING);
155 
156 	if (sharpsl_pm.machinfo->gpio_fatal) {
157 		if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED, "Fatal Battery", sharpsl_fatal_isr)) {
158 			dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal));
159 		}
160 		else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQ_TYPE_EDGE_FALLING);
161 	}
162 
163 	if (sharpsl_pm.machinfo->batfull_irq)
164 	{
165 		/* Register interrupt handler. */
166 		if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED, "CO", sharpsl_chrg_full_isr)) {
167 			dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull));
168 		}
169 		else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQ_TYPE_EDGE_RISING);
170 	}
171 }
172 
173 void sharpsl_pm_pxa_remove(void)
174 {
175 	free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr);
176 	free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr);
177 
178 	if (sharpsl_pm.machinfo->gpio_fatal)
179 		free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr);
180 
181 	if (sharpsl_pm.machinfo->batfull_irq)
182 		free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr);
183 }
184