|
From: <mis...@us...> - 2007-09-26 14:42:20
|
Revision: 1341
http://hackndev.svn.sourceforge.net/hackndev/?rev=1341&view=rev
Author: miska_tx
Date: 2007-09-26 07:42:12 -0700 (Wed, 26 Sep 2007)
Log Message:
-----------
All: Model independent Palm battery driver
Signed-off-by: Michal Hrusecky <Mic...@se...>
Modified Paths:
--------------
linux4palm/linux/trunk/drivers/power/Kconfig
linux4palm/linux/trunk/drivers/power/Makefile
Added Paths:
-----------
linux4palm/linux/trunk/drivers/power/palm_battery.c
linux4palm/linux/trunk/include/asm-arm/arch-pxa/palm-battery.h
Modified: linux4palm/linux/trunk/drivers/power/Kconfig
===================================================================
--- linux4palm/linux/trunk/drivers/power/Kconfig 2007-09-24 18:33:52 UTC (rev 1340)
+++ linux4palm/linux/trunk/drivers/power/Kconfig 2007-09-26 14:42:12 UTC (rev 1341)
@@ -28,6 +28,14 @@
Say Y here to enable support APM status emulation using
battery class devices.
+config BATTERY_PALM
+ tristate "Palm battery driver"
+ select TOUCHSCREEN_WM97XX
+ depends on APM_POWER
+ default m
+ help
+ Say Y here to enable support for batteries in Palm devices.
+
config BATTERY_DS2760
tristate "DS2760 battery driver (HP iPAQ & others)"
select W1
Modified: linux4palm/linux/trunk/drivers/power/Makefile
===================================================================
--- linux4palm/linux/trunk/drivers/power/Makefile 2007-09-24 18:33:52 UTC (rev 1340)
+++ linux4palm/linux/trunk/drivers/power/Makefile 2007-09-26 14:42:12 UTC (rev 1341)
@@ -18,6 +18,7 @@
obj-$(CONFIG_APM_POWER) += apm_power.o
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
+obj-$(CONFIG_BATTERY_PALM) += palm_battery.o
obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
Added: linux4palm/linux/trunk/drivers/power/palm_battery.c
===================================================================
--- linux4palm/linux/trunk/drivers/power/palm_battery.c (rev 0)
+++ linux4palm/linux/trunk/drivers/power/palm_battery.c 2007-09-26 14:42:12 UTC (rev 1341)
@@ -0,0 +1,269 @@
+/************************************************************************
+ * drivers/power/palm_battery.c *
+ * Battery driver for Palm devices *
+ * *
+ * Author: Michal Hrusecky <Mic...@se...> *
+ * *
+ * Based on code for Palm TX by *
+ * *
+ * Authors: Jan Herman <2h...@se...> *
+ * *
+ ************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/power_supply.h>
+#include <linux/apm-emulation.h>
+#include <linux/wm97xx.h>
+
+#include <asm/delay.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irqs.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <asm/arch/palm-battery.h>
+
+extern struct palm_battery_data palm_battery_info;
+
+struct palm_battery_dev
+{
+ struct wm97xx * wm;
+ int battery_registered;
+ int current_voltage;
+ int previous_voltage;
+ u32 last_battery_update;
+};
+
+struct palm_battery_dev bat;
+
+#if defined(CONFIG_APM_EMULATION) || defined(CONFIG_APM_MODULE)
+/* original APM hook */
+static void (*apm_get_power_status_orig)(struct apm_power_info *info);
+#endif
+
+/*
+ This formula is based on battery life of my battery 1100mAh. Original battery in Zire72 is Li-On 920mAh
+ V_batt = ADCSEL_BMON * 1,889 + 767,8 [mV]
+*/
+
+int palm_battery_get_voltage(struct power_supply *b)
+{
+ if (bat.battery_registered) {
+ bat.previous_voltage = bat.current_voltage;
+ bat.current_voltage = wm97xx_read_aux_adc(bat.wm, WM97XX_AUX_ID3);
+ bat.last_battery_update = jiffies;
+ return bat.current_voltage * 1889/1000 + 7678/10;
+ } else {
+ printk("palm_battery: cannot get voltage -> battery driver unregistered\n");
+ return 0;
+ }
+}
+
+int palm_battery_get_capacity(struct power_supply *b)
+{
+ if (bat.battery_registered)
+ return (((palm_battery_get_voltage(b)-palm_battery_info.bat_min_voltage)
+ /(palm_battery_info.bat_max_voltage-palm_battery_info.bat_min_voltage))*100);
+ else{
+ printk("palm_battery: cannot get capacity -> battery driver unregistered\n");
+ return 0;
+ }
+}
+
+int palm_battery_get_status(struct power_supply *b)
+{
+ if ( palm_battery_info.ac_connected() &&
+ ( ( bat.current_voltage > bat.previous_voltage ) ||
+ (bat.current_voltage <= palm_battery_info.bat_max_voltage) ) )
+ return POWER_SUPPLY_STATUS_CHARGING;
+ else
+ return POWER_SUPPLY_STATUS_NOT_CHARGING;
+}
+
+static int palm_battery_get_property(struct power_supply *b,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ val->intval = palm_battery_info.bat_max_voltage;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = palm_battery_info.bat_min_voltage;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ val->intval = 100;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ val->intval = palm_battery_get_capacity(b);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = palm_battery_get_voltage(b);
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = palm_battery_get_status(b);
+ break;
+ default:
+ break;
+ };
+
+ return 0;
+}
+
+static enum power_supply_property palm_battery_props[] = {
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_STATUS,
+};
+
+struct power_supply palm_battery = {
+ .name = "palm_battery",
+ .get_property = palm_battery_get_property,
+ .properties = palm_battery_props,
+ .num_properties = ARRAY_SIZE(palm_battery_props),
+};
+
+static int palm_wm97xx_probe(struct device *dev)
+{
+ struct wm97xx *wm = dev->driver_data;
+ bat.wm = wm;
+ return 0;
+}
+
+static int palm_wm97xx_remove(struct device *dev)
+{
+ return 0;
+}
+
+static void
+palm_wm97xx_shutdown(struct device *dev)
+{
+#if defined(CONFIG_APM_EMULATION) || defined(CONFIG_APM_MODULE)
+ apm_get_power_status = apm_get_power_status_orig;
+#endif
+}
+
+static int
+palm_wm97xx_suspend(struct device *dev, pm_message_t state)
+{
+ return 0;
+}
+
+static int
+palm_wm97xx_resume(struct device *dev)
+{
+ return 0;
+}
+
+
+static struct device_driver palm_wm97xx_driver = {
+ .name = "wm97xx-touchscreen",
+ .bus = &wm97xx_bus_type,
+ .owner = THIS_MODULE,
+ .probe = palm_wm97xx_probe,
+ .remove = palm_wm97xx_remove,
+ .suspend = palm_wm97xx_suspend,
+ .resume = palm_wm97xx_resume,
+ .shutdown = palm_wm97xx_shutdown
+};
+
+
+#if defined(CONFIG_APM_EMULATION) || defined(CONFIG_APM_MODULE)
+
+/* APM status query callback implementation */
+static void palm_apm_get_power_status(struct apm_power_info *info)
+{
+ int min, max, curr, percent;
+
+ curr = palm_battery_get_voltage(&palm_battery);
+ min = palm_battery_info.bat_min_voltage;
+ max = palm_battery_info.bat_max_voltage;
+
+ curr = curr - min;
+ if (curr < 0) curr = 0;
+ max = max - min;
+
+ percent = curr*100/max;
+
+ info->battery_life = percent;
+
+ info->ac_line_status = palm_battery_info.ac_connected() ? APM_AC_ONLINE : APM_AC_OFFLINE;
+
+ if (info->ac_line_status)
+ info->battery_status = APM_BATTERY_STATUS_CHARGING;
+ else {
+ if (percent > 50)
+ info->battery_status = APM_BATTERY_STATUS_HIGH;
+ else if (percent < 5)
+ info->battery_status = APM_BATTERY_STATUS_CRITICAL;
+ else
+ info->battery_status = APM_BATTERY_STATUS_LOW;
+ }
+
+ info->time = percent * palm_battery_info.bat_max_life_mins/100;
+ info->units = APM_UNITS_MINS;
+}
+#endif
+static int __init palm_wm97xx_init(void)
+{
+#ifndef MODULE
+ int ret;
+#endif
+
+ /* register battery to APM layer */
+ bat.battery_registered = 0;
+
+ if(power_supply_register(NULL, &palm_battery))
+ printk(KERN_ERR "palm_ac97_probe: could not register battery class\n");
+ else {
+ bat.battery_registered = 1;
+ printk("Battery registered\n");
+ }
+#if defined(CONFIG_APM_EMULATION) || defined(CONFIG_APM_MODULE)
+ apm_get_power_status_orig = apm_get_power_status;
+ apm_get_power_status = palm_apm_get_power_status;
+#endif
+#ifndef MODULE
+ /* If we're in kernel, we could accidentally be run before wm97xx
+ and thus have panic */
+ if((ret = bus_register(&wm97xx_bus_type)) < 0)
+ return ret;
+#endif
+ return driver_register(&palm_wm97xx_driver);
+}
+
+static void __exit palm_wm97xx_exit(void)
+{
+ /* TODO - recover APM callback to original state */
+ power_supply_unregister(&palm_battery);
+ driver_unregister(&palm_wm97xx_driver);
+}
+
+module_init(palm_wm97xx_init);
+module_exit(palm_wm97xx_exit);
+
+/* Module information */
+MODULE_AUTHOR("Michal Hrusecky <Mic...@se...>");
+MODULE_DESCRIPTION("Universal battery driver for Palm devices");
+MODULE_LICENSE("GPL");
Added: linux4palm/linux/trunk/include/asm-arm/arch-pxa/palm-battery.h
===================================================================
--- linux4palm/linux/trunk/include/asm-arm/arch-pxa/palm-battery.h (rev 0)
+++ linux4palm/linux/trunk/include/asm-arm/arch-pxa/palm-battery.h 2007-09-26 14:42:12 UTC (rev 1341)
@@ -0,0 +1,10 @@
+/*
+ * Palm battery info structure.
+ */
+
+struct palm_battery_data {
+ int bat_min_voltage;
+ int bat_max_voltage;
+ int bat_max_life_mins;
+ int (*ac_connected)();
+};
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|