android_battery.c revision 1e34b11bc23cb33c285455d750852ee7a5df1ef1
1/*
2 *  android_battery.c
3 *  Android Battery Driver
4 *
5 * Copyright (C) 2012 Google, Inc.
6 * Copyright (C) 2012 Samsung Electronics
7 *
8 * Based on work by himihee.seo@samsung.com, ms925.kim@samsung.com, and
9 * joshua.chang@samsung.com.
10 *
11 * This software is licensed under the terms of the GNU General Public
12 * License version 2, as published by the Free Software Foundation, and
13 * may be copied, distributed, and modified under those terms.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 */
20
21#include <linux/types.h>
22#include <linux/module.h>
23#include <linux/delay.h>
24#include <linux/err.h>
25#include <linux/init.h>
26#include <linux/interrupt.h>
27#include <linux/io.h>
28#include <linux/jiffies.h>
29#include <linux/platform_device.h>
30#include <linux/power_supply.h>
31#include <linux/slab.h>
32#include <linux/wakelock.h>
33#include <linux/workqueue.h>
34#include <linux/timer.h>
35#include <linux/platform_data/android_battery.h>
36
37struct android_bat_data {
38	struct android_bat_platform_data *pdata;
39	struct android_bat_callbacks callbacks;
40
41	struct device		*dev;
42
43	struct power_supply	psy_bat;
44
45	struct wake_lock	monitor_wake_lock;
46	struct wake_lock	charger_wake_lock;
47
48	int			charge_source;
49
50	int			batt_temp;
51	int			batt_current;
52	unsigned int		batt_health;
53	unsigned int		batt_vcell;
54	unsigned int		batt_soc;
55	unsigned int		charging_status;
56
57	struct workqueue_struct *monitor_wqueue;
58	struct delayed_work	monitor_work;
59	struct work_struct	charger_work;
60
61	bool		slow_poll;
62	ktime_t		last_poll;
63};
64
65static enum power_supply_property android_battery_props[] = {
66	POWER_SUPPLY_PROP_STATUS,
67	POWER_SUPPLY_PROP_HEALTH,
68	POWER_SUPPLY_PROP_PRESENT,
69	POWER_SUPPLY_PROP_TEMP,
70	POWER_SUPPLY_PROP_ONLINE,
71	POWER_SUPPLY_PROP_VOLTAGE_NOW,
72	POWER_SUPPLY_PROP_CAPACITY,
73	POWER_SUPPLY_PROP_TECHNOLOGY,
74	POWER_SUPPLY_PROP_CURRENT_NOW,
75};
76
77static void android_bat_update_data(struct android_bat_data *battery);
78
79static char *charge_source_str(int charge_source)
80{
81	switch (charge_source) {
82	case CHARGE_SOURCE_NONE:
83		return "none";
84	case CHARGE_SOURCE_AC:
85		return "ac";
86	case CHARGE_SOURCE_USB:
87		return "usb";
88	default:
89		break;
90	}
91
92	return "?";
93}
94
95static int android_bat_get_property(struct power_supply *ps,
96				enum power_supply_property psp,
97				union power_supply_propval *val)
98{
99	struct android_bat_data *battery =
100		container_of(ps, struct android_bat_data, psy_bat);
101
102	switch (psp) {
103	case POWER_SUPPLY_PROP_STATUS:
104		val->intval = battery->charging_status;
105		break;
106	case POWER_SUPPLY_PROP_HEALTH:
107		val->intval = battery->batt_health;
108		break;
109	case POWER_SUPPLY_PROP_PRESENT:
110		val->intval = 1;
111		break;
112	case POWER_SUPPLY_PROP_TEMP:
113		val->intval = battery->batt_temp;
114		break;
115	case POWER_SUPPLY_PROP_ONLINE:
116		val->intval = 1;
117		break;
118	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
119		android_bat_update_data(battery);
120		val->intval = battery->batt_vcell;
121		if (val->intval == -1)
122			return -EINVAL;
123		break;
124	case POWER_SUPPLY_PROP_CAPACITY:
125		val->intval = battery->batt_soc;
126		if (val->intval == -1)
127			return -EINVAL;
128		break;
129	case POWER_SUPPLY_PROP_TECHNOLOGY:
130		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
131		break;
132	case POWER_SUPPLY_PROP_CURRENT_NOW:
133		android_bat_update_data(battery);
134		val->intval = battery->batt_current;
135		break;
136	default:
137		return -EINVAL;
138	}
139	return 0;
140}
141
142static void android_bat_get_temp(struct android_bat_data *battery)
143{
144	int batt_temp = 25000;
145	int health = battery->batt_health;
146
147	if (battery->pdata->get_temperature)
148		battery->pdata->get_temperature(&batt_temp);
149
150	if (batt_temp >= battery->pdata->temp_high_threshold) {
151		if (health != POWER_SUPPLY_HEALTH_OVERHEAT &&
152				health != POWER_SUPPLY_HEALTH_UNSPEC_FAILURE) {
153			pr_info("battery overheat (%d>=%d), charging unavailable\n",
154				batt_temp, battery->pdata->temp_high_threshold);
155			battery->batt_health = POWER_SUPPLY_HEALTH_OVERHEAT;
156		}
157	} else if (batt_temp <= battery->pdata->temp_high_recovery &&
158			batt_temp >= battery->pdata->temp_low_recovery) {
159		if (health == POWER_SUPPLY_HEALTH_OVERHEAT ||
160				health == POWER_SUPPLY_HEALTH_COLD) {
161			pr_info("battery recovery (%d,%d~%d), charging available\n",
162				batt_temp, battery->pdata->temp_low_recovery,
163				battery->pdata->temp_high_recovery);
164			battery->batt_health = POWER_SUPPLY_HEALTH_GOOD;
165		}
166	} else if (batt_temp <= battery->pdata->temp_low_threshold) {
167		if (health != POWER_SUPPLY_HEALTH_COLD &&
168				health != POWER_SUPPLY_HEALTH_UNSPEC_FAILURE) {
169			pr_info("battery cold (%d <= %d), charging unavailable\n",
170				batt_temp, battery->pdata->temp_low_threshold);
171			battery->batt_health = POWER_SUPPLY_HEALTH_COLD;
172		}
173	}
174
175	battery->batt_temp = batt_temp/1000;
176}
177
178static void android_bat_update_data(struct android_bat_data *battery)
179{
180	int ret;
181	int v;
182
183	if (battery->pdata->poll_charge_source)
184		battery->charge_source = battery->pdata->poll_charge_source();
185
186	if (battery->pdata->get_voltage_now) {
187		ret = battery->pdata->get_voltage_now();
188		battery->batt_vcell = ret >= 0 ? ret : -1;
189	}
190
191	if (battery->pdata->get_capacity) {
192		ret = battery->pdata->get_capacity();
193		battery->batt_soc = ret >= 0 ? ret : -1;
194	}
195
196	if (battery->pdata->get_current_now) {
197		ret = battery->pdata->get_current_now(&v);
198
199		if (!ret)
200			battery->batt_current = v;
201	}
202
203	android_bat_get_temp(battery);
204}
205
206static int android_bat_enable_charging(struct android_bat_data *battery,
207				       bool enable)
208{
209	if (enable && (battery->batt_health != POWER_SUPPLY_HEALTH_GOOD)) {
210		battery->charging_status =
211		    POWER_SUPPLY_STATUS_NOT_CHARGING;
212		return -EPERM;
213	}
214
215	if (enable) {
216		if (battery->pdata && battery->pdata->set_charging_current)
217			battery->pdata->set_charging_current
218			(battery->charge_source);
219	}
220
221	if (battery->pdata && battery->pdata->set_charging_enable)
222		battery->pdata->set_charging_enable(enable);
223
224	pr_info("battery: enable=%d charger: %s\n", enable,
225		charge_source_str(battery->charge_source));
226
227	return 0;
228}
229
230static void android_bat_charge_source_changed(struct android_bat_callbacks *ptr,
231					      int charge_source)
232{
233	struct android_bat_data *battery;
234
235	battery = container_of(ptr, struct android_bat_data, callbacks);
236	wake_lock(&battery->charger_wake_lock);
237	battery->charge_source = charge_source;
238
239	pr_info("battery: charge source type was changed: %s\n",
240		charge_source_str(battery->charge_source));
241
242	queue_work(battery->monitor_wqueue, &battery->charger_work);
243}
244
245static void android_bat_charger_work(struct work_struct *work)
246{
247	struct android_bat_data *battery =
248		container_of(work, struct android_bat_data, charger_work);
249
250	switch (battery->charge_source) {
251	case CHARGE_SOURCE_NONE:
252		battery->charging_status = POWER_SUPPLY_STATUS_DISCHARGING;
253		android_bat_enable_charging(battery, false);
254		if (battery->batt_health == POWER_SUPPLY_HEALTH_OVERVOLTAGE)
255			battery->batt_health = POWER_SUPPLY_HEALTH_GOOD;
256		break;
257	case CHARGE_SOURCE_USB:
258	case CHARGE_SOURCE_AC:
259		battery->charging_status = POWER_SUPPLY_STATUS_CHARGING;
260		android_bat_enable_charging(battery, true);
261		break;
262	default:
263		pr_err("%s: Invalid charger type\n", __func__);
264		break;
265	}
266
267	wake_lock_timeout(&battery->charger_wake_lock, HZ * 2);
268}
269
270static void android_bat_monitor_work(struct work_struct *work)
271{
272	struct android_bat_data *battery;
273	battery = container_of(work, struct android_bat_data,
274			       monitor_work.work);
275
276	wake_lock(&battery->monitor_wake_lock);
277	android_bat_update_data(battery);
278
279	switch (battery->charging_status) {
280	case POWER_SUPPLY_STATUS_FULL:
281	case POWER_SUPPLY_STATUS_DISCHARGING:
282		break;
283	case POWER_SUPPLY_STATUS_CHARGING:
284		switch (battery->batt_health) {
285		case POWER_SUPPLY_HEALTH_OVERHEAT:
286		case POWER_SUPPLY_HEALTH_COLD:
287		case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
288		case POWER_SUPPLY_HEALTH_DEAD:
289		case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE:
290			battery->charging_status =
291				POWER_SUPPLY_STATUS_NOT_CHARGING;
292			android_bat_enable_charging(battery, false);
293
294			pr_info("battery: Not charging, health=%d\n",
295				battery->batt_health);
296			break;
297		default:
298			break;
299		}
300		break;
301	case POWER_SUPPLY_STATUS_NOT_CHARGING:
302		if (battery->batt_health == POWER_SUPPLY_HEALTH_GOOD) {
303			pr_info("battery: battery health recovered\n");
304			if (battery->charge_source != CHARGE_SOURCE_NONE) {
305				android_bat_enable_charging(battery, true);
306				battery->charging_status
307					= POWER_SUPPLY_STATUS_CHARGING;
308			} else
309				battery->charging_status
310					= POWER_SUPPLY_STATUS_DISCHARGING;
311		}
312		break;
313	default:
314		wake_unlock(&battery->monitor_wake_lock);
315		pr_err("%s: Undefined battery status: %d\n", __func__,
316		       battery->charging_status);
317		return;
318	}
319
320	pr_info("battery: l=%d v=%d c=%d temp=%d h=%d st=%d type=%s\n",
321		battery->batt_soc, battery->batt_vcell/1000,
322		battery->batt_current, battery->batt_temp, battery->batt_health,
323		battery->charging_status,
324		charge_source_str(battery->charge_source));
325	power_supply_changed(&battery->psy_bat);
326	queue_delayed_work(battery->monitor_wqueue,
327		&battery->monitor_work, msecs_to_jiffies(50000));
328	wake_unlock(&battery->monitor_wake_lock);
329
330	return;
331}
332
333static __devinit int android_bat_probe(struct platform_device *pdev)
334{
335	struct android_bat_platform_data *pdata = dev_get_platdata(&pdev->dev);
336	struct android_bat_data *battery;
337	int ret = 0;
338
339	dev_info(&pdev->dev, "Android Battery Driver\n");
340	battery = kzalloc(sizeof(*battery), GFP_KERNEL);
341	if (!battery)
342		return -ENOMEM;
343
344	battery->pdata = pdata;
345	if (!battery->pdata) {
346		pr_err("%s : No platform data\n", __func__);
347		ret = -EINVAL;
348		goto err_pdata;
349	}
350
351	battery->dev = &pdev->dev;
352	platform_set_drvdata(pdev, battery);
353	battery->batt_health = POWER_SUPPLY_HEALTH_GOOD;
354
355	battery->psy_bat.name = "android-battery",
356	battery->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY,
357	battery->psy_bat.properties = android_battery_props,
358	battery->psy_bat.num_properties = ARRAY_SIZE(android_battery_props),
359	battery->psy_bat.get_property = android_bat_get_property,
360
361	battery->batt_vcell = -1;
362	battery->batt_soc = -1;
363
364	wake_lock_init(&battery->monitor_wake_lock, WAKE_LOCK_SUSPEND,
365			"android-battery-monitor");
366	wake_lock_init(&battery->charger_wake_lock, WAKE_LOCK_SUSPEND,
367			"android-chargerdetect");
368
369	ret = power_supply_register(&pdev->dev, &battery->psy_bat);
370	if (ret) {
371		dev_err(battery->dev, "%s: failed to register psy_bat\n",
372			__func__);
373		goto err_psy_reg;
374	}
375
376	battery->monitor_wqueue =
377		create_singlethread_workqueue(dev_name(&pdev->dev));
378	if (!battery->monitor_wqueue) {
379		dev_err(battery->dev, "%s: fail to create workqueue\n",
380				__func__);
381		goto err_wq;
382	}
383
384	INIT_DELAYED_WORK_DEFERRABLE(&battery->monitor_work,
385		android_bat_monitor_work);
386	INIT_WORK(&battery->charger_work, android_bat_charger_work);
387
388	battery->callbacks.charge_source_changed =
389		android_bat_charge_source_changed;
390	if (battery->pdata && battery->pdata->register_callbacks)
391		battery->pdata->register_callbacks(&battery->callbacks);
392
393	/* get initial charger status */
394	if (battery->pdata->poll_charge_source)
395		battery->charge_source = battery->pdata->poll_charge_source();
396
397	wake_lock(&battery->charger_wake_lock);
398	queue_work(battery->monitor_wqueue, &battery->charger_work);
399
400	queue_delayed_work(battery->monitor_wqueue,
401		&battery->monitor_work, msecs_to_jiffies(0));
402	return 0;
403
404
405err_wq:
406	power_supply_unregister(&battery->psy_bat);
407err_psy_reg:
408	wake_lock_destroy(&battery->monitor_wake_lock);
409	wake_lock_destroy(&battery->charger_wake_lock);
410err_pdata:
411	kfree(battery);
412
413	return ret;
414}
415
416static int __devexit android_bat_remove(struct platform_device *pdev)
417{
418	struct android_bat_data *battery = platform_get_drvdata(pdev);
419
420	flush_workqueue(battery->monitor_wqueue);
421	destroy_workqueue(battery->monitor_wqueue);
422	power_supply_unregister(&battery->psy_bat);
423	wake_lock_destroy(&battery->monitor_wake_lock);
424	wake_lock_destroy(&battery->charger_wake_lock);
425	kfree(battery);
426	return 0;
427}
428
429static int android_bat_suspend(struct device *dev)
430{
431	struct android_bat_data *battery = dev_get_drvdata(dev);
432
433	cancel_delayed_work_sync(&battery->monitor_work);
434	return 0;
435}
436
437static int android_bat_resume(struct device *dev)
438{
439	struct android_bat_data *battery = dev_get_drvdata(dev);
440
441	queue_delayed_work(battery->monitor_wqueue,
442		&battery->monitor_work, msecs_to_jiffies(0));
443	return 0;
444}
445
446static const struct dev_pm_ops android_bat_pm_ops = {
447	.suspend	= android_bat_suspend,
448	.resume = android_bat_resume,
449};
450
451static struct platform_driver android_bat_driver = {
452	.driver = {
453		.name = "android-battery",
454		.owner = THIS_MODULE,
455		.pm = &android_bat_pm_ops,
456	},
457	.probe = android_bat_probe,
458	.remove = __devexit_p(android_bat_remove),
459};
460
461static int __init android_bat_init(void)
462{
463	return platform_driver_register(&android_bat_driver);
464}
465
466static void __exit android_bat_exit(void)
467{
468	platform_driver_unregister(&android_bat_driver);
469}
470
471late_initcall(android_bat_init);
472module_exit(android_bat_exit);
473
474MODULE_DESCRIPTION("Android battery driver");
475MODULE_LICENSE("GPL");
476