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/pxa2xx-gpio.h> 29 #include <mach/sharpsl.h> 30 #include "sharpsl.h" 31 32 struct battery_thresh spitz_battery_levels_acin[] = { 33 { 213, 100}, 34 { 212, 98}, 35 { 211, 95}, 36 { 210, 93}, 37 { 209, 90}, 38 { 208, 88}, 39 { 207, 85}, 40 { 206, 83}, 41 { 205, 80}, 42 { 204, 78}, 43 { 203, 75}, 44 { 202, 73}, 45 { 201, 70}, 46 { 200, 68}, 47 { 199, 65}, 48 { 198, 63}, 49 { 197, 60}, 50 { 196, 58}, 51 { 195, 55}, 52 { 194, 53}, 53 { 193, 50}, 54 { 192, 48}, 55 { 192, 45}, 56 { 191, 43}, 57 { 191, 40}, 58 { 190, 38}, 59 { 190, 35}, 60 { 189, 33}, 61 { 188, 30}, 62 { 187, 28}, 63 { 186, 25}, 64 { 185, 23}, 65 { 184, 20}, 66 { 183, 18}, 67 { 182, 15}, 68 { 181, 13}, 69 { 180, 10}, 70 { 179, 8}, 71 { 178, 5}, 72 { 0, 0}, 73 }; 74 75 struct battery_thresh spitz_battery_levels_noac[] = { 76 { 213, 100}, 77 { 212, 98}, 78 { 211, 95}, 79 { 210, 93}, 80 { 209, 90}, 81 { 208, 88}, 82 { 207, 85}, 83 { 206, 83}, 84 { 205, 80}, 85 { 204, 78}, 86 { 203, 75}, 87 { 202, 73}, 88 { 201, 70}, 89 { 200, 68}, 90 { 199, 65}, 91 { 198, 63}, 92 { 197, 60}, 93 { 196, 58}, 94 { 195, 55}, 95 { 194, 53}, 96 { 193, 50}, 97 { 192, 48}, 98 { 191, 45}, 99 { 190, 43}, 100 { 189, 40}, 101 { 188, 38}, 102 { 187, 35}, 103 { 186, 33}, 104 { 185, 30}, 105 { 184, 28}, 106 { 183, 25}, 107 { 182, 23}, 108 { 181, 20}, 109 { 180, 18}, 110 { 179, 15}, 111 { 178, 13}, 112 { 177, 10}, 113 { 176, 8}, 114 { 175, 5}, 115 { 0, 0}, 116 }; 117 118 /* MAX1111 Commands */ 119 #define MAXCTRL_PD0 1u << 0 120 #define MAXCTRL_PD1 1u << 1 121 #define MAXCTRL_SGL 1u << 2 122 #define MAXCTRL_UNI 1u << 3 123 #define MAXCTRL_SEL_SH 4 124 #define MAXCTRL_STR 1u << 7 125 126 /* 127 * Read MAX1111 ADC 128 */ 129 int sharpsl_pm_pxa_read_max1111(int channel) 130 { 131 if (machine_is_tosa()) // Ugly, better move this function into another module 132 return 0; 133 134 #ifdef CONFIG_CORGI_SSP_DEPRECATED 135 return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1 136 | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR); 137 #else 138 extern int max1111_read_channel(int); 139 140 /* max1111 accepts channels from 0-3, however, 141 * it is encoded from 0-7 here in the code. 142 */ 143 return max1111_read_channel(channel >> 1); 144 #endif 145 } 146 147 void sharpsl_pm_pxa_init(void) 148 { 149 pxa_gpio_mode(sharpsl_pm.machinfo->gpio_acin | GPIO_IN); 150 pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batfull | GPIO_IN); 151 pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batlock | GPIO_IN); 152 153 /* Register interrupt handlers */ 154 if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED, "AC Input Detect", sharpsl_ac_isr)) { 155 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin)); 156 } 157 else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin),IRQ_TYPE_EDGE_BOTH); 158 159 if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED, "Battery Cover", sharpsl_fatal_isr)) { 160 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock)); 161 } 162 else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock),IRQ_TYPE_EDGE_FALLING); 163 164 if (sharpsl_pm.machinfo->gpio_fatal) { 165 if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED, "Fatal Battery", sharpsl_fatal_isr)) { 166 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal)); 167 } 168 else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQ_TYPE_EDGE_FALLING); 169 } 170 171 if (sharpsl_pm.machinfo->batfull_irq) 172 { 173 /* Register interrupt handler. */ 174 if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED, "CO", sharpsl_chrg_full_isr)) { 175 dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull)); 176 } 177 else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQ_TYPE_EDGE_RISING); 178 } 179 } 180 181 void sharpsl_pm_pxa_remove(void) 182 { 183 free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr); 184 free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr); 185 186 if (sharpsl_pm.machinfo->gpio_fatal) 187 free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr); 188 189 if (sharpsl_pm.machinfo->batfull_irq) 190 free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr); 191 } 192