Commit | Line | Data |
---|---|---|
d4b19c42 MV |
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> | |
a09e64fb | 25 | #include <mach/palmtx.h> |
d4b19c42 MV |
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"); |