Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[ARM] 5248/1: wm97xx generic battery driver

This patch adds generic battery driver for wm97xx chips.

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Marek Vašut and committed by
Russell King
4e9687d9 c49e1e63

+323 -203
+20
arch/arm/mach-pxa/palmtx.c
··· 25 25 #include <linux/pda_power.h> 26 26 #include <linux/pwm_backlight.h> 27 27 #include <linux/gpio.h> 28 + #include <linux/wm97xx_batt.h> 29 + #include <linux/power_supply.h> 28 30 29 31 #include <asm/mach-types.h> 30 32 #include <asm/mach/arch.h> ··· 342 340 }; 343 341 344 342 /****************************************************************************** 343 + * WM97xx battery 344 + ******************************************************************************/ 345 + static struct wm97xx_batt_info wm97xx_batt_pdata = { 346 + .batt_aux = WM97XX_AUX_ID3, 347 + .temp_aux = WM97XX_AUX_ID2, 348 + .charge_gpio = -1, 349 + .max_voltage = PALMTX_BAT_MAX_VOLTAGE, 350 + .min_voltage = PALMTX_BAT_MIN_VOLTAGE, 351 + .batt_mult = 1000, 352 + .batt_div = 414, 353 + .temp_mult = 1, 354 + .temp_div = 1, 355 + .batt_tech = POWER_SUPPLY_TECHNOLOGY_LIPO, 356 + .batt_name = "main-batt", 357 + }; 358 + 359 + /****************************************************************************** 345 360 * Framebuffer 346 361 ******************************************************************************/ 347 362 static struct pxafb_mode_info palmtx_lcd_modes[] = { ··· 420 401 pxa_set_ac97_info(NULL); 421 402 pxa_set_ficp_info(&palmtx_ficp_platform_data); 422 403 pxa_set_keypad_info(&palmtx_keypad_platform_data); 404 + wm97xx_bat_set_pdata(&wm97xx_batt_pdata); 423 405 424 406 platform_add_devices(devices, ARRAY_SIZE(devices)); 425 407 }
+4 -4
drivers/power/Kconfig
··· 56 56 Say Y to enable support for the battery on the Sharp Zaurus 57 57 SL-6000 (tosa) models. 58 58 59 - config BATTERY_PALMTX 60 - tristate "Palm T|X battery" 61 - depends on MACH_PALMTX 59 + config BATTERY_WM97XX 60 + bool "WM97xx generic battery driver" 61 + depends on TOUCHSCREEN_WM97XX 62 62 help 63 - Say Y to enable support for the battery in Palm T|X. 63 + Say Y to enable support for battery measured by WM97xx aux port. 64 64 65 65 endif # POWER_SUPPLY
+1 -1
drivers/power/Makefile
··· 21 21 obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o 22 22 obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o 23 23 obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o 24 - obj-$(CONFIG_BATTERY_PALMTX) += palmtx_battery.o 24 + obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
-198
drivers/power/palmtx_battery.c
··· 1 - /* 2 - * linux/drivers/power/palmtx_battery.c 3 - * 4 - * Battery measurement code for Palm T|X Handheld computer 5 - * 6 - * based on tosa_battery.c 7 - * 8 - * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com> 9 - * 10 - * This program is free software; you can redistribute it and/or modify 11 - * it under the terms of the GNU General Public License version 2 as 12 - * published by the Free Software Foundation. 13 - * 14 - */ 15 - #include <linux/kernel.h> 16 - #include <linux/module.h> 17 - #include <linux/power_supply.h> 18 - #include <linux/wm97xx.h> 19 - #include <linux/delay.h> 20 - #include <linux/spinlock.h> 21 - #include <linux/interrupt.h> 22 - #include <linux/gpio.h> 23 - 24 - #include <asm/mach-types.h> 25 - #include <mach/palmtx.h> 26 - 27 - static DEFINE_MUTEX(bat_lock); 28 - static struct work_struct bat_work; 29 - struct mutex work_lock; 30 - int bat_status = POWER_SUPPLY_STATUS_DISCHARGING; 31 - 32 - static unsigned long palmtx_read_bat(struct power_supply *bat_ps) 33 - { 34 - return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data, 35 - WM97XX_AUX_ID3) * 1000 / 414; 36 - } 37 - 38 - static unsigned long palmtx_read_temp(struct power_supply *bat_ps) 39 - { 40 - return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data, 41 - WM97XX_AUX_ID2); 42 - } 43 - 44 - static int palmtx_bat_get_property(struct power_supply *bat_ps, 45 - enum power_supply_property psp, 46 - union power_supply_propval *val) 47 - { 48 - switch (psp) { 49 - case POWER_SUPPLY_PROP_STATUS: 50 - val->intval = bat_status; 51 - break; 52 - case POWER_SUPPLY_PROP_TECHNOLOGY: 53 - val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO; 54 - break; 55 - case POWER_SUPPLY_PROP_VOLTAGE_NOW: 56 - val->intval = palmtx_read_bat(bat_ps); 57 - break; 58 - case POWER_SUPPLY_PROP_VOLTAGE_MAX: 59 - case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 60 - val->intval = PALMTX_BAT_MAX_VOLTAGE; 61 - break; 62 - case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 63 - val->intval = PALMTX_BAT_MIN_VOLTAGE; 64 - break; 65 - case POWER_SUPPLY_PROP_TEMP: 66 - val->intval = palmtx_read_temp(bat_ps); 67 - break; 68 - case POWER_SUPPLY_PROP_PRESENT: 69 - val->intval = 1; 70 - break; 71 - default: 72 - return -EINVAL; 73 - } 74 - return 0; 75 - } 76 - 77 - static void palmtx_bat_external_power_changed(struct power_supply *bat_ps) 78 - { 79 - schedule_work(&bat_work); 80 - } 81 - 82 - static char *status_text[] = { 83 - [POWER_SUPPLY_STATUS_UNKNOWN] = "Unknown", 84 - [POWER_SUPPLY_STATUS_CHARGING] = "Charging", 85 - [POWER_SUPPLY_STATUS_DISCHARGING] = "Discharging", 86 - }; 87 - 88 - static void palmtx_bat_update(struct power_supply *bat_ps) 89 - { 90 - int old_status = bat_status; 91 - 92 - mutex_lock(&work_lock); 93 - 94 - bat_status = gpio_get_value(GPIO_NR_PALMTX_POWER_DETECT) ? 95 - POWER_SUPPLY_STATUS_CHARGING : 96 - POWER_SUPPLY_STATUS_DISCHARGING; 97 - 98 - if (old_status != bat_status) { 99 - pr_debug("%s %s -> %s\n", bat_ps->name, 100 - status_text[old_status], 101 - status_text[bat_status]); 102 - power_supply_changed(bat_ps); 103 - } 104 - 105 - mutex_unlock(&work_lock); 106 - } 107 - 108 - static enum power_supply_property palmtx_bat_main_props[] = { 109 - POWER_SUPPLY_PROP_STATUS, 110 - POWER_SUPPLY_PROP_TECHNOLOGY, 111 - POWER_SUPPLY_PROP_VOLTAGE_NOW, 112 - POWER_SUPPLY_PROP_VOLTAGE_MAX, 113 - POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 114 - POWER_SUPPLY_PROP_TEMP, 115 - POWER_SUPPLY_PROP_PRESENT, 116 - }; 117 - 118 - struct power_supply bat_ps = { 119 - .name = "main-battery", 120 - .type = POWER_SUPPLY_TYPE_BATTERY, 121 - .properties = palmtx_bat_main_props, 122 - .num_properties = ARRAY_SIZE(palmtx_bat_main_props), 123 - .get_property = palmtx_bat_get_property, 124 - .external_power_changed = palmtx_bat_external_power_changed, 125 - .use_for_apm = 1, 126 - }; 127 - 128 - static void palmtx_bat_work(struct work_struct *work) 129 - { 130 - palmtx_bat_update(&bat_ps); 131 - } 132 - 133 - #ifdef CONFIG_PM 134 - static int palmtx_bat_suspend(struct platform_device *dev, pm_message_t state) 135 - { 136 - flush_scheduled_work(); 137 - return 0; 138 - } 139 - 140 - static int palmtx_bat_resume(struct platform_device *dev) 141 - { 142 - schedule_work(&bat_work); 143 - return 0; 144 - } 145 - #else 146 - #define palmtx_bat_suspend NULL 147 - #define palmtx_bat_resume NULL 148 - #endif 149 - 150 - static int __devinit palmtx_bat_probe(struct platform_device *dev) 151 - { 152 - int ret = 0; 153 - 154 - if (!machine_is_palmtx()) 155 - return -ENODEV; 156 - 157 - mutex_init(&work_lock); 158 - 159 - INIT_WORK(&bat_work, palmtx_bat_work); 160 - 161 - ret = power_supply_register(&dev->dev, &bat_ps); 162 - if (!ret) 163 - schedule_work(&bat_work); 164 - 165 - return ret; 166 - } 167 - 168 - static int __devexit palmtx_bat_remove(struct platform_device *dev) 169 - { 170 - power_supply_unregister(&bat_ps); 171 - return 0; 172 - } 173 - 174 - static struct platform_driver palmtx_bat_driver = { 175 - .driver.name = "wm97xx-battery", 176 - .driver.owner = THIS_MODULE, 177 - .probe = palmtx_bat_probe, 178 - .remove = __devexit_p(palmtx_bat_remove), 179 - .suspend = palmtx_bat_suspend, 180 - .resume = palmtx_bat_resume, 181 - }; 182 - 183 - static int __init palmtx_bat_init(void) 184 - { 185 - return platform_driver_register(&palmtx_bat_driver); 186 - } 187 - 188 - static void __exit palmtx_bat_exit(void) 189 - { 190 - platform_driver_unregister(&palmtx_bat_driver); 191 - } 192 - 193 - module_init(palmtx_bat_init); 194 - module_exit(palmtx_bat_exit); 195 - 196 - MODULE_LICENSE("GPL"); 197 - MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); 198 - MODULE_DESCRIPTION("Palm T|X battery driver");
+272
drivers/power/wm97xx_battery.c
··· 1 + /* 2 + * linux/drivers/power/wm97xx_battery.c 3 + * 4 + * Battery measurement code for WM97xx 5 + * 6 + * based on tosa_battery.c 7 + * 8 + * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com> 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License version 2 as 12 + * published by the Free Software Foundation. 13 + * 14 + */ 15 + 16 + #include <linux/init.h> 17 + #include <linux/kernel.h> 18 + #include <linux/module.h> 19 + #include <linux/platform_device.h> 20 + #include <linux/power_supply.h> 21 + #include <linux/wm97xx.h> 22 + #include <linux/spinlock.h> 23 + #include <linux/interrupt.h> 24 + #include <linux/gpio.h> 25 + #include <linux/wm97xx_batt.h> 26 + 27 + static DEFINE_MUTEX(bat_lock); 28 + static struct work_struct bat_work; 29 + struct mutex work_lock; 30 + static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN; 31 + static struct wm97xx_batt_info *pdata; 32 + static enum power_supply_property *prop; 33 + 34 + static unsigned long wm97xx_read_bat(struct power_supply *bat_ps) 35 + { 36 + return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data, 37 + pdata->batt_aux) * pdata->batt_mult / 38 + pdata->batt_div; 39 + } 40 + 41 + static unsigned long wm97xx_read_temp(struct power_supply *bat_ps) 42 + { 43 + return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data, 44 + pdata->temp_aux) * pdata->temp_mult / 45 + pdata->temp_div; 46 + } 47 + 48 + static int wm97xx_bat_get_property(struct power_supply *bat_ps, 49 + enum power_supply_property psp, 50 + union power_supply_propval *val) 51 + { 52 + switch (psp) { 53 + case POWER_SUPPLY_PROP_STATUS: 54 + val->intval = bat_status; 55 + break; 56 + case POWER_SUPPLY_PROP_TECHNOLOGY: 57 + val->intval = pdata->batt_tech; 58 + break; 59 + case POWER_SUPPLY_PROP_VOLTAGE_NOW: 60 + if (pdata->batt_aux >= 0) 61 + val->intval = wm97xx_read_bat(bat_ps); 62 + else 63 + return -EINVAL; 64 + break; 65 + case POWER_SUPPLY_PROP_TEMP: 66 + if (pdata->temp_aux >= 0) 67 + val->intval = wm97xx_read_temp(bat_ps); 68 + else 69 + return -EINVAL; 70 + break; 71 + case POWER_SUPPLY_PROP_VOLTAGE_MAX: 72 + if (pdata->max_voltage >= 0) 73 + val->intval = pdata->max_voltage; 74 + else 75 + return -EINVAL; 76 + break; 77 + case POWER_SUPPLY_PROP_VOLTAGE_MIN: 78 + if (pdata->min_voltage >= 0) 79 + val->intval = pdata->min_voltage; 80 + else 81 + return -EINVAL; 82 + break; 83 + case POWER_SUPPLY_PROP_PRESENT: 84 + val->intval = 1; 85 + break; 86 + default: 87 + return -EINVAL; 88 + } 89 + return 0; 90 + } 91 + 92 + static void wm97xx_bat_external_power_changed(struct power_supply *bat_ps) 93 + { 94 + schedule_work(&bat_work); 95 + } 96 + 97 + static void wm97xx_bat_update(struct power_supply *bat_ps) 98 + { 99 + int old_status = bat_status; 100 + 101 + mutex_lock(&work_lock); 102 + 103 + bat_status = (pdata->charge_gpio >= 0) ? 104 + (gpio_get_value(pdata->charge_gpio) ? 105 + POWER_SUPPLY_STATUS_DISCHARGING : 106 + POWER_SUPPLY_STATUS_CHARGING) : 107 + POWER_SUPPLY_STATUS_UNKNOWN; 108 + 109 + if (old_status != bat_status) { 110 + pr_debug("%s: %i -> %i\n", bat_ps->name, old_status, 111 + bat_status); 112 + power_supply_changed(bat_ps); 113 + } 114 + 115 + mutex_unlock(&work_lock); 116 + } 117 + 118 + static struct power_supply bat_ps = { 119 + .type = POWER_SUPPLY_TYPE_BATTERY, 120 + .get_property = wm97xx_bat_get_property, 121 + .external_power_changed = wm97xx_bat_external_power_changed, 122 + .use_for_apm = 1, 123 + }; 124 + 125 + static void wm97xx_bat_work(struct work_struct *work) 126 + { 127 + wm97xx_bat_update(&bat_ps); 128 + } 129 + 130 + #ifdef CONFIG_PM 131 + static int wm97xx_bat_suspend(struct platform_device *dev, pm_message_t state) 132 + { 133 + flush_scheduled_work(); 134 + return 0; 135 + } 136 + 137 + static int wm97xx_bat_resume(struct platform_device *dev) 138 + { 139 + schedule_work(&bat_work); 140 + return 0; 141 + } 142 + #else 143 + #define wm97xx_bat_suspend NULL 144 + #define wm97xx_bat_resume NULL 145 + #endif 146 + 147 + static int __devinit wm97xx_bat_probe(struct platform_device *dev) 148 + { 149 + int ret = 0; 150 + int props = 1; /* POWER_SUPPLY_PROP_PRESENT */ 151 + int i = 0; 152 + 153 + if (dev->id != -1) 154 + return -EINVAL; 155 + 156 + mutex_init(&work_lock); 157 + 158 + if (!pdata) { 159 + dev_err(&dev->dev, "Please use wm97xx_bat_set_pdata\n"); 160 + return -EINVAL; 161 + } 162 + 163 + if (pdata->charge_gpio >= 0 && gpio_is_valid(pdata->charge_gpio)) { 164 + ret = gpio_request(pdata->charge_gpio, "BATT CHRG"); 165 + if (ret) 166 + goto err; 167 + ret = gpio_direction_input(pdata->charge_gpio); 168 + if (ret) 169 + goto err2; 170 + props++; /* POWER_SUPPLY_PROP_STATUS */ 171 + } 172 + 173 + if (pdata->batt_tech >= 0) 174 + props++; /* POWER_SUPPLY_PROP_TECHNOLOGY */ 175 + if (pdata->temp_aux >= 0) 176 + props++; /* POWER_SUPPLY_PROP_TEMP */ 177 + if (pdata->batt_aux >= 0) 178 + props++; /* POWER_SUPPLY_PROP_VOLTAGE_NOW */ 179 + if (pdata->max_voltage >= 0) 180 + props++; /* POWER_SUPPLY_PROP_VOLTAGE_MAX */ 181 + if (pdata->min_voltage >= 0) 182 + props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */ 183 + 184 + prop = kzalloc(props * sizeof(*prop), GFP_KERNEL); 185 + if (!prop) 186 + goto err2; 187 + 188 + prop[i++] = POWER_SUPPLY_PROP_PRESENT; 189 + if (pdata->charge_gpio >= 0) 190 + prop[i++] = POWER_SUPPLY_PROP_STATUS; 191 + if (pdata->batt_tech >= 0) 192 + prop[i++] = POWER_SUPPLY_PROP_TECHNOLOGY; 193 + if (pdata->temp_aux >= 0) 194 + prop[i++] = POWER_SUPPLY_PROP_TEMP; 195 + if (pdata->batt_aux >= 0) 196 + prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_NOW; 197 + if (pdata->max_voltage >= 0) 198 + prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_MAX; 199 + if (pdata->min_voltage >= 0) 200 + prop[i++] = POWER_SUPPLY_PROP_VOLTAGE_MIN; 201 + 202 + INIT_WORK(&bat_work, wm97xx_bat_work); 203 + 204 + if (!pdata->batt_name) { 205 + dev_info(&dev->dev, "Please consider setting proper battery " 206 + "name in platform definition file, falling " 207 + "back to name \"wm97xx-batt\"\n"); 208 + bat_ps.name = "wm97xx-batt"; 209 + } else 210 + bat_ps.name = pdata->batt_name; 211 + 212 + bat_ps.properties = prop; 213 + bat_ps.num_properties = props; 214 + 215 + ret = power_supply_register(&dev->dev, &bat_ps); 216 + if (!ret) 217 + schedule_work(&bat_work); 218 + else 219 + goto err3; 220 + 221 + return 0; 222 + err3: 223 + kfree(prop); 224 + err2: 225 + gpio_free(pdata->charge_gpio); 226 + err: 227 + return ret; 228 + } 229 + 230 + static int __devexit wm97xx_bat_remove(struct platform_device *dev) 231 + { 232 + if (pdata && pdata->charge_gpio && pdata->charge_gpio >= 0) 233 + gpio_free(pdata->charge_gpio); 234 + flush_scheduled_work(); 235 + power_supply_unregister(&bat_ps); 236 + kfree(prop); 237 + return 0; 238 + } 239 + 240 + static struct platform_driver wm97xx_bat_driver = { 241 + .driver = { 242 + .name = "wm97xx-battery", 243 + .owner = THIS_MODULE, 244 + }, 245 + .probe = wm97xx_bat_probe, 246 + .remove = __devexit_p(wm97xx_bat_remove), 247 + .suspend = wm97xx_bat_suspend, 248 + .resume = wm97xx_bat_resume, 249 + }; 250 + 251 + static int __init wm97xx_bat_init(void) 252 + { 253 + return platform_driver_register(&wm97xx_bat_driver); 254 + } 255 + 256 + static void __exit wm97xx_bat_exit(void) 257 + { 258 + platform_driver_unregister(&wm97xx_bat_driver); 259 + } 260 + 261 + void __init wm97xx_bat_set_pdata(struct wm97xx_batt_info *data) 262 + { 263 + pdata = data; 264 + } 265 + EXPORT_SYMBOL_GPL(wm97xx_bat_set_pdata); 266 + 267 + module_init(wm97xx_bat_init); 268 + module_exit(wm97xx_bat_exit); 269 + 270 + MODULE_LICENSE("GPL"); 271 + MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); 272 + MODULE_DESCRIPTION("WM97xx battery driver");
+26
include/linux/wm97xx_batt.h
··· 1 + #ifndef _LINUX_WM97XX_BAT_H 2 + #define _LINUX_WM97XX_BAT_H 3 + 4 + #include <linux/wm97xx.h> 5 + 6 + struct wm97xx_batt_info { 7 + int batt_aux; 8 + int temp_aux; 9 + int charge_gpio; 10 + int min_voltage; 11 + int max_voltage; 12 + int batt_div; 13 + int batt_mult; 14 + int temp_div; 15 + int temp_mult; 16 + int batt_tech; 17 + char *batt_name; 18 + }; 19 + 20 + #ifdef CONFIG_BATTERY_WM97XX 21 + void __init wm97xx_bat_set_pdata(struct wm97xx_batt_info *data); 22 + #else 23 + static inline void wm97xx_bat_set_pdata(struct wm97xx_batt_info *data) {} 24 + #endif 25 + 26 + #endif