Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
corgi_pm.c
Go to the documentation of this file.
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/gpio-pxa.h>
19 #include <linux/interrupt.h>
20 #include <linux/platform_device.h>
21 #include <linux/apm-emulation.h>
22 #include <linux/io.h>
23 
24 #include <asm/irq.h>
25 #include <asm/mach-types.h>
26 #include <mach/hardware.h>
27 
28 #include <mach/corgi.h>
29 #include <mach/pxa2xx-regs.h>
30 #include <mach/sharpsl_pm.h>
31 
32 #include "generic.h"
33 
34 #define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */
35 #define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */
36 #define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */
37 #define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */
38 #define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */
39 #define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */
40 
41 static struct gpio charger_gpios[] = {
42  { CORGI_GPIO_ADC_TEMP_ON, GPIOF_OUT_INIT_LOW, "ADC Temp On" },
43  { CORGI_GPIO_CHRG_ON, GPIOF_OUT_INIT_LOW, "Charger On" },
44  { CORGI_GPIO_CHRG_UKN, GPIOF_OUT_INIT_LOW, "Charger Unknown" },
45  { CORGI_GPIO_AC_IN, GPIOF_IN, "Charger Detection" },
46  { CORGI_GPIO_KEY_INT, GPIOF_IN, "Key Interrupt" },
47  { CORGI_GPIO_WAKEUP, GPIOF_IN, "System wakeup notification" },
48 };
49 
50 static void corgi_charger_init(void)
51 {
52  gpio_request_array(ARRAY_AND_SIZE(charger_gpios));
53 }
54 
55 static void corgi_measure_temp(int on)
56 {
58 }
59 
60 static void corgi_charge(int on)
61 {
62  if (on) {
63  if (machine_is_corgi() && (sharpsl_pm.flags & SHARPSL_SUSPENDED)) {
66  } else {
69  }
70  } else {
73  }
74 }
75 
76 static void corgi_discharge(int on)
77 {
79 }
80 
81 static void corgi_presuspend(void)
82 {
83 }
84 
85 static void corgi_postsuspend(void)
86 {
87 }
88 
89 /*
90  * Check what brought us out of the suspend.
91  * Return: 0 to sleep, otherwise wake
92  */
93 static int corgi_should_wakeup(unsigned int resume_on_alarm)
94 {
95  int is_resume = 0;
96 
97  dev_dbg(sharpsl_pm.dev, "PEDR = %x, GPIO_AC_IN = %d, "
98  "GPIO_CHRG_FULL = %d, GPIO_KEY_INT = %d, GPIO_WAKEUP = %d\n",
103 
104  if ((PEDR & GPIO_bit(CORGI_GPIO_AC_IN))) {
105  if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
106  /* charge on */
107  dev_dbg(sharpsl_pm.dev, "ac insert\n");
109  } else {
110  /* charge off */
111  dev_dbg(sharpsl_pm.dev, "ac remove\n");
113  sharpsl_pm.machinfo->charge(0);
114  sharpsl_pm.charge_mode = CHRG_OFF;
115  }
116  }
117 
119  dev_dbg(sharpsl_pm.dev, "Charge full interrupt\n");
120 
122  is_resume |= GPIO_bit(CORGI_GPIO_KEY_INT);
123 
125  is_resume |= GPIO_bit(CORGI_GPIO_WAKEUP);
126 
127  if (resume_on_alarm && (PEDR & PWER_RTC))
128  is_resume |= PWER_RTC;
129 
130  dev_dbg(sharpsl_pm.dev, "is_resume: %x\n",is_resume);
131  return is_resume;
132 }
133 
134 static unsigned long corgi_charger_wakeup(void)
135 {
136  unsigned long ret;
137 
143  return ret;
144 }
145 
146 unsigned long corgipm_read_devdata(int type)
147 {
148  switch(type) {
149  case SHARPSL_STATUS_ACIN:
151  case SHARPSL_STATUS_LOCK:
152  return gpio_get_value(sharpsl_pm.machinfo->gpio_batlock);
154  return gpio_get_value(sharpsl_pm.machinfo->gpio_batfull);
156  return gpio_get_value(sharpsl_pm.machinfo->gpio_fatal);
157  case SHARPSL_ACIN_VOLT:
159  case SHARPSL_BATT_TEMP:
161  case SHARPSL_BATT_VOLT:
162  default:
164  }
165 }
166 
167 static struct sharpsl_charger_machinfo corgi_pm_machinfo = {
168  .init = corgi_charger_init,
169  .exit = NULL,
170  .gpio_batlock = CORGI_GPIO_BAT_COVER,
171  .gpio_acin = CORGI_GPIO_AC_IN,
172  .gpio_batfull = CORGI_GPIO_CHRG_FULL,
173  .discharge = corgi_discharge,
174  .charge = corgi_charge,
175  .measure_temp = corgi_measure_temp,
176  .presuspend = corgi_presuspend,
177  .postsuspend = corgi_postsuspend,
178  .read_devdata = corgipm_read_devdata,
179  .charger_wakeup = corgi_charger_wakeup,
180  .should_wakeup = corgi_should_wakeup,
181 #if defined(CONFIG_LCD_CORGI)
182  .backlight_limit = corgi_lcd_limit_intensity,
183 #endif
184  .charge_on_volt = SHARPSL_CHARGE_ON_VOLT,
185  .charge_on_temp = SHARPSL_CHARGE_ON_TEMP,
186  .charge_acin_high = SHARPSL_CHARGE_ON_ACIN_HIGH,
187  .charge_acin_low = SHARPSL_CHARGE_ON_ACIN_LOW,
188  .fatal_acin_volt = SHARPSL_FATAL_ACIN_VOLT,
189  .fatal_noacin_volt= SHARPSL_FATAL_NOACIN_VOLT,
190  .bat_levels = 40,
191  .bat_levels_noac = sharpsl_battery_levels_noac,
192  .bat_levels_acin = sharpsl_battery_levels_acin,
193  .status_high_acin = 188,
194  .status_low_acin = 178,
195  .status_high_noac = 185,
196  .status_low_noac = 175,
197 };
198 
199 static struct platform_device *corgipm_device;
200 
201 static int __devinit corgipm_init(void)
202 {
203  int ret;
204 
205  if (!machine_is_corgi() && !machine_is_shepherd()
206  && !machine_is_husky())
207  return -ENODEV;
208 
209  corgipm_device = platform_device_alloc("sharpsl-pm", -1);
210  if (!corgipm_device)
211  return -ENOMEM;
212 
213  if (!machine_is_corgi())
214  corgi_pm_machinfo.batfull_irq = 1;
215 
216  corgipm_device->dev.platform_data = &corgi_pm_machinfo;
217  ret = platform_device_add(corgipm_device);
218 
219  if (ret)
220  platform_device_put(corgipm_device);
221 
222  return ret;
223 }
224 
225 static void corgipm_exit(void)
226 {
227  platform_device_unregister(corgipm_device);
228 }
229 
230 module_init(corgipm_init);
231 module_exit(corgipm_exit);