diff options
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/Kconfig | 6 | ||||
-rw-r--r-- | drivers/power/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/apm_power.c | 2 | ||||
-rw-r--r-- | drivers/power/ds2760_battery.c | 2 | ||||
-rw-r--r-- | drivers/power/palmtx_battery.c | 198 | ||||
-rw-r--r-- | drivers/power/pda_power.c | 2 | ||||
-rw-r--r-- | drivers/power/power_supply_core.c | 10 | ||||
-rw-r--r-- | drivers/power/power_supply_sysfs.c | 2 |
8 files changed, 215 insertions, 8 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index e3a9c37d08f..9ce55850271 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -56,4 +56,10 @@ config BATTERY_TOSA Say Y to enable support for the battery on the Sharp Zaurus SL-6000 (tosa) models. +config BATTERY_PALMTX + tristate "Palm T|X battery" + depends on MACH_PALMTX + help + Say Y to enable support for the battery in Palm T|X. + endif # POWER_SUPPLY diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 1e408fa268c..4706bf8ff45 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -21,3 +21,4 @@ obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o +obj-$(CONFIG_BATTERY_PALMTX) += palmtx_battery.o diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c index a4892275659..936bae560fa 100644 --- a/drivers/power/apm_power.c +++ b/drivers/power/apm_power.c @@ -78,7 +78,7 @@ static void find_main_battery(void) main_battery = NULL; bp.main = main_battery; - error = class_for_each_device(power_supply_class, &bp, + error = class_for_each_device(power_supply_class, NULL, &bp, __find_main_battery); if (error) { main_battery = bp.main; diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c index 71be36f1870..308ddb201b6 100644 --- a/drivers/power/ds2760_battery.c +++ b/drivers/power/ds2760_battery.c @@ -433,6 +433,8 @@ static int ds2760_battery_resume(struct platform_device *pdev) #endif /* CONFIG_PM */ +MODULE_ALIAS("platform:ds2760-battery"); + static struct platform_driver ds2760_battery_driver = { .driver = { .name = "ds2760-battery", diff --git a/drivers/power/palmtx_battery.c b/drivers/power/palmtx_battery.c new file mode 100644 index 00000000000..244bb273a63 --- /dev/null +++ b/drivers/power/palmtx_battery.c @@ -0,0 +1,198 @@ +/* + * linux/drivers/power/palmtx_battery.c + * + * Battery measurement code for Palm T|X Handheld computer + * + * based on tosa_battery.c + * + * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/power_supply.h> +#include <linux/wm97xx.h> +#include <linux/delay.h> +#include <linux/spinlock.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> + +#include <asm/mach-types.h> +#include <asm/arch/palmtx.h> + +static DEFINE_MUTEX(bat_lock); +static struct work_struct bat_work; +struct mutex work_lock; +int bat_status = POWER_SUPPLY_STATUS_DISCHARGING; + +static unsigned long palmtx_read_bat(struct power_supply *bat_ps) +{ + return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data, + WM97XX_AUX_ID3) * 1000 / 414; +} + +static unsigned long palmtx_read_temp(struct power_supply *bat_ps) +{ + return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data, + WM97XX_AUX_ID2); +} + +static int palmtx_bat_get_property(struct power_supply *bat_ps, + enum power_supply_property psp, + union power_supply_propval *val) +{ + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + val->intval = bat_status; + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = palmtx_read_bat(bat_ps); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: + val->intval = PALMTX_BAT_MAX_VOLTAGE; + break; + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: + val->intval = PALMTX_BAT_MIN_VOLTAGE; + break; + case POWER_SUPPLY_PROP_TEMP: + val->intval = palmtx_read_temp(bat_ps); + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = 1; + break; + default: + return -EINVAL; + } + return 0; +} + +static void palmtx_bat_external_power_changed(struct power_supply *bat_ps) +{ + schedule_work(&bat_work); +} + +static char *status_text[] = { + [POWER_SUPPLY_STATUS_UNKNOWN] = "Unknown", + [POWER_SUPPLY_STATUS_CHARGING] = "Charging", + [POWER_SUPPLY_STATUS_DISCHARGING] = "Discharging", +}; + +static void palmtx_bat_update(struct power_supply *bat_ps) +{ + int old_status = bat_status; + + mutex_lock(&work_lock); + + bat_status = gpio_get_value(GPIO_NR_PALMTX_POWER_DETECT) ? + POWER_SUPPLY_STATUS_CHARGING : + POWER_SUPPLY_STATUS_DISCHARGING; + + if (old_status != bat_status) { + pr_debug("%s %s -> %s\n", bat_ps->name, + status_text[old_status], + status_text[bat_status]); + power_supply_changed(bat_ps); + } + + mutex_unlock(&work_lock); +} + +static enum power_supply_property palmtx_bat_main_props[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_VOLTAGE_MAX, + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_PRESENT, +}; + +struct power_supply bat_ps = { + .name = "main-battery", + .type = POWER_SUPPLY_TYPE_BATTERY, + .properties = palmtx_bat_main_props, + .num_properties = ARRAY_SIZE(palmtx_bat_main_props), + .get_property = palmtx_bat_get_property, + .external_power_changed = palmtx_bat_external_power_changed, + .use_for_apm = 1, +}; + +static void palmtx_bat_work(struct work_struct *work) +{ + palmtx_bat_update(&bat_ps); +} + +#ifdef CONFIG_PM +static int palmtx_bat_suspend(struct platform_device *dev, pm_message_t state) +{ + flush_scheduled_work(); + return 0; +} + +static int palmtx_bat_resume(struct platform_device *dev) +{ + schedule_work(&bat_work); + return 0; +} +#else +#define palmtx_bat_suspend NULL +#define palmtx_bat_resume NULL +#endif + +static int __devinit palmtx_bat_probe(struct platform_device *dev) +{ + int ret = 0; + + if (!machine_is_palmtx()) + return -ENODEV; + + mutex_init(&work_lock); + + INIT_WORK(&bat_work, palmtx_bat_work); + + ret = power_supply_register(&dev->dev, &bat_ps); + if (!ret) + schedule_work(&bat_work); + + return ret; +} + +static int __devexit palmtx_bat_remove(struct platform_device *dev) +{ + power_supply_unregister(&bat_ps); + return 0; +} + +static struct platform_driver palmtx_bat_driver = { + .driver.name = "wm97xx-battery", + .driver.owner = THIS_MODULE, + .probe = palmtx_bat_probe, + .remove = __devexit_p(palmtx_bat_remove), + .suspend = palmtx_bat_suspend, + .resume = palmtx_bat_resume, +}; + +static int __init palmtx_bat_init(void) +{ + return platform_driver_register(&palmtx_bat_driver); +} + +static void __exit palmtx_bat_exit(void) +{ + platform_driver_unregister(&palmtx_bat_driver); +} + +module_init(palmtx_bat_init); +module_exit(palmtx_bat_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); +MODULE_DESCRIPTION("Palm T|X battery driver"); diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c index 82810b7bff9..0471ec743ab 100644 --- a/drivers/power/pda_power.c +++ b/drivers/power/pda_power.c @@ -362,6 +362,8 @@ static int pda_power_resume(struct platform_device *pdev) #define pda_power_resume NULL #endif /* CONFIG_PM */ +MODULE_ALIAS("platform:pda-power"); + static struct platform_driver pda_power_pdrv = { .driver = { .name = "pda-power", diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 138dd76ee34..cb1ccb47292 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c @@ -41,7 +41,7 @@ static void power_supply_changed_work(struct work_struct *work) dev_dbg(psy->dev, "%s\n", __func__); - class_for_each_device(power_supply_class, psy, + class_for_each_device(power_supply_class, NULL, psy, __power_supply_changed_work); power_supply_update_leds(psy); @@ -79,7 +79,7 @@ int power_supply_am_i_supplied(struct power_supply *psy) { int error; - error = class_for_each_device(power_supply_class, psy, + error = class_for_each_device(power_supply_class, NULL, psy, __power_supply_am_i_supplied); dev_dbg(psy->dev, "%s %d\n", __func__, error); @@ -91,15 +91,13 @@ int power_supply_register(struct device *parent, struct power_supply *psy) { int rc = 0; - psy->dev = device_create(power_supply_class, parent, 0, - "%s", psy->name); + psy->dev = device_create_drvdata(power_supply_class, parent, 0, + psy, "%s", psy->name); if (IS_ERR(psy->dev)) { rc = PTR_ERR(psy->dev); goto dev_create_failed; } - dev_set_drvdata(psy->dev, psy); - INIT_WORK(&psy->changed_work, power_supply_changed_work); rc = power_supply_create_attrs(psy); diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 82e1246eeb0..fe2aeb11939 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -202,7 +202,7 @@ int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env) dev_dbg(dev, "uevent\n"); - if (!psy) { + if (!psy || !psy->dev) { dev_dbg(dev, "No power supply yet\n"); return ret; } |