blob: f82df2a0d24b97facd44abcb03be09d1b74859d4 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/err.h>
17#include <linux/mfd/pmic8058.h>
18#include <linux/interrupt.h>
19#include <linux/power_supply.h>
20#include <linux/delay.h>
21#include <linux/bitops.h>
22#include <linux/debugfs.h>
23#include <linux/msm-charger.h>
24#include <linux/time.h>
25#include <linux/slab.h>
26#include <linux/wakelock.h>
27
28#include <asm/atomic.h>
29
30#include <mach/msm_hsusb.h>
31
32#define MSM_CHG_MAX_EVENTS 16
33#define CHARGING_TEOC_MS 9000000
34#define UPDATE_TIME_MS 60000
35#define RESUME_CHECK_PERIOD_MS 60000
36
37#define DEFAULT_BATT_MAX_V 4200
38#define DEFAULT_BATT_MIN_V 3200
39
40#define MSM_CHARGER_GAUGE_MISSING_VOLTS 3500
41#define MSM_CHARGER_GAUGE_MISSING_TEMP 35
42/**
43 * enum msm_battery_status
44 * @BATT_STATUS_ABSENT: battery not present
45 * @BATT_STATUS_ID_INVALID: battery present but the id is invalid
46 * @BATT_STATUS_DISCHARGING: battery is present and is discharging
47 * @BATT_STATUS_TRKL_CHARGING: battery is being trickle charged
48 * @BATT_STATUS_FAST_CHARGING: battery is being fast charged
49 * @BATT_STATUS_JUST_FINISHED_CHARGING: just finished charging,
50 * battery is fully charged. Do not begin charging untill the
51 * voltage falls below a threshold to avoid overcharging
52 * @BATT_STATUS_TEMPERATURE_OUT_OF_RANGE: battery present,
53 no charging, temp is hot/cold
54 */
55enum msm_battery_status {
56 BATT_STATUS_ABSENT,
57 BATT_STATUS_ID_INVALID,
58 BATT_STATUS_DISCHARGING,
59 BATT_STATUS_TRKL_CHARGING,
60 BATT_STATUS_FAST_CHARGING,
61 BATT_STATUS_JUST_FINISHED_CHARGING,
62 BATT_STATUS_TEMPERATURE_OUT_OF_RANGE,
63};
64
65struct msm_hardware_charger_priv {
66 struct list_head list;
67 struct msm_hardware_charger *hw_chg;
68 enum msm_hardware_charger_state hw_chg_state;
69 unsigned int max_source_current;
70 struct power_supply psy;
71};
72
73struct msm_charger_event {
74 enum msm_hardware_charger_event event;
75 struct msm_hardware_charger *hw_chg;
76};
77
78struct msm_charger_mux {
79 int inited;
80 struct list_head msm_hardware_chargers;
81 int count_chargers;
82 struct mutex msm_hardware_chargers_lock;
83
84 struct device *dev;
85
86 unsigned int max_voltage;
87 unsigned int min_voltage;
88
89 unsigned int safety_time;
90 struct delayed_work teoc_work;
91
92 unsigned int update_time;
93 int stop_update;
94 struct delayed_work update_heartbeat_work;
95
96 struct mutex status_lock;
97 enum msm_battery_status batt_status;
98 struct msm_hardware_charger_priv *current_chg_priv;
99 struct msm_hardware_charger_priv *current_mon_priv;
100
101 unsigned int (*get_batt_capacity_percent) (void);
102
103 struct msm_charger_event *queue;
104 int tail;
105 int head;
106 spinlock_t queue_lock;
107 int queue_count;
108 struct work_struct queue_work;
109 struct workqueue_struct *event_wq_thread;
110 struct wake_lock wl;
111};
112
113static struct msm_charger_mux msm_chg;
114
115static struct msm_battery_gauge *msm_batt_gauge;
116
117static int is_chg_capable_of_charging(struct msm_hardware_charger_priv *priv)
118{
119 if (priv->hw_chg_state == CHG_READY_STATE
120 || priv->hw_chg_state == CHG_CHARGING_STATE)
121 return 1;
122
123 return 0;
124}
125
126static int is_batt_status_capable_of_charging(void)
127{
128 if (msm_chg.batt_status == BATT_STATUS_ABSENT
129 || msm_chg.batt_status == BATT_STATUS_TEMPERATURE_OUT_OF_RANGE
130 || msm_chg.batt_status == BATT_STATUS_ID_INVALID
131 || msm_chg.batt_status == BATT_STATUS_JUST_FINISHED_CHARGING)
132 return 0;
133 return 1;
134}
135
136static int is_batt_status_charging(void)
137{
138 if (msm_chg.batt_status == BATT_STATUS_TRKL_CHARGING
139 || msm_chg.batt_status == BATT_STATUS_FAST_CHARGING)
140 return 1;
141 return 0;
142}
143
144static int is_battery_present(void)
145{
146 if (msm_batt_gauge && msm_batt_gauge->is_battery_present)
147 return msm_batt_gauge->is_battery_present();
148 else {
149 pr_err("msm-charger: no batt gauge batt=absent\n");
150 return 0;
151 }
152}
153
154static int is_battery_temp_within_range(void)
155{
156 if (msm_batt_gauge && msm_batt_gauge->is_battery_temp_within_range)
157 return msm_batt_gauge->is_battery_temp_within_range();
158 else {
159 pr_err("msm-charger no batt gauge batt=out_of_temperatur\n");
160 return 0;
161 }
162}
163
164static int is_battery_id_valid(void)
165{
166 if (msm_batt_gauge && msm_batt_gauge->is_battery_id_valid)
167 return msm_batt_gauge->is_battery_id_valid();
168 else {
169 pr_err("msm-charger no batt gauge batt=id_invalid\n");
170 return 0;
171 }
172}
173
174static int get_prop_battery_mvolts(void)
175{
176 if (msm_batt_gauge && msm_batt_gauge->get_battery_mvolts)
177 return msm_batt_gauge->get_battery_mvolts();
178 else {
179 pr_err("msm-charger no batt gauge assuming 3.5V\n");
180 return MSM_CHARGER_GAUGE_MISSING_VOLTS;
181 }
182}
183
184static int get_battery_temperature(void)
185{
186 if (msm_batt_gauge && msm_batt_gauge->get_battery_temperature)
187 return msm_batt_gauge->get_battery_temperature();
188 else {
189 pr_err("msm-charger no batt gauge assuming 35 deg G\n");
190 return MSM_CHARGER_GAUGE_MISSING_TEMP;
191 }
192}
193
194static int get_prop_batt_capacity(void)
195{
196 if (msm_batt_gauge && msm_batt_gauge->get_batt_remaining_capacity)
197 return msm_batt_gauge->get_batt_remaining_capacity();
198
199 return msm_chg.get_batt_capacity_percent();
200}
201
202static int get_prop_batt_health(void)
203{
204 int status = 0;
205
206 if (msm_chg.batt_status == BATT_STATUS_TEMPERATURE_OUT_OF_RANGE)
207 status = POWER_SUPPLY_HEALTH_OVERHEAT;
208 else
209 status = POWER_SUPPLY_HEALTH_GOOD;
210
211 return status;
212}
213
214static int get_prop_charge_type(void)
215{
216 int status = 0;
217
218 if (msm_chg.batt_status == BATT_STATUS_TRKL_CHARGING)
219 status = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
220 else if (msm_chg.batt_status == BATT_STATUS_FAST_CHARGING)
221 status = POWER_SUPPLY_CHARGE_TYPE_FAST;
222 else
223 status = POWER_SUPPLY_CHARGE_TYPE_NONE;
224
225 return status;
226}
227
228static int get_prop_batt_status(void)
229{
230 int status = 0;
231
232 if (msm_batt_gauge && msm_batt_gauge->get_battery_status) {
233 status = msm_batt_gauge->get_battery_status();
234 if (status == POWER_SUPPLY_STATUS_CHARGING ||
235 status == POWER_SUPPLY_STATUS_FULL ||
236 status == POWER_SUPPLY_STATUS_DISCHARGING)
237 return status;
238 }
239
240 if (is_batt_status_charging())
241 status = POWER_SUPPLY_STATUS_CHARGING;
242 else if (msm_chg.batt_status ==
243 BATT_STATUS_JUST_FINISHED_CHARGING
244 && msm_chg.current_chg_priv != NULL)
245 status = POWER_SUPPLY_STATUS_FULL;
246 else
247 status = POWER_SUPPLY_STATUS_DISCHARGING;
248
249 return status;
250}
251
252 /* This function should only be called within handle_event or resume */
253static void update_batt_status(void)
254{
255 if (is_battery_present()) {
256 if (is_battery_id_valid()) {
257 if (msm_chg.batt_status == BATT_STATUS_ABSENT
258 || msm_chg.batt_status
259 == BATT_STATUS_ID_INVALID) {
260 msm_chg.batt_status = BATT_STATUS_DISCHARGING;
261 }
262 } else
263 msm_chg.batt_status = BATT_STATUS_ID_INVALID;
264 } else
265 msm_chg.batt_status = BATT_STATUS_ABSENT;
266}
267
268static enum power_supply_property msm_power_props[] = {
269 POWER_SUPPLY_PROP_PRESENT,
270 POWER_SUPPLY_PROP_ONLINE,
271};
272
273static char *msm_power_supplied_to[] = {
274 "battery",
275};
276
277static int msm_power_get_property(struct power_supply *psy,
278 enum power_supply_property psp,
279 union power_supply_propval *val)
280{
281 struct msm_hardware_charger_priv *priv;
282
283 priv = container_of(psy, struct msm_hardware_charger_priv, psy);
284 switch (psp) {
285 case POWER_SUPPLY_PROP_PRESENT:
286 val->intval = !(priv->hw_chg_state == CHG_ABSENT_STATE);
287 break;
288 case POWER_SUPPLY_PROP_ONLINE:
289 val->intval = (priv->hw_chg_state == CHG_READY_STATE)
290 || (priv->hw_chg_state == CHG_CHARGING_STATE);
291 break;
292 default:
293 return -EINVAL;
294 }
295 return 0;
296}
297
298static enum power_supply_property msm_batt_power_props[] = {
299 POWER_SUPPLY_PROP_STATUS,
300 POWER_SUPPLY_PROP_CHARGE_TYPE,
301 POWER_SUPPLY_PROP_HEALTH,
302 POWER_SUPPLY_PROP_PRESENT,
303 POWER_SUPPLY_PROP_TECHNOLOGY,
304 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
305 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
306 POWER_SUPPLY_PROP_VOLTAGE_NOW,
307 POWER_SUPPLY_PROP_CAPACITY,
308};
309
310static int msm_batt_power_get_property(struct power_supply *psy,
311 enum power_supply_property psp,
312 union power_supply_propval *val)
313{
314 switch (psp) {
315 case POWER_SUPPLY_PROP_STATUS:
316 val->intval = get_prop_batt_status();
317 break;
318 case POWER_SUPPLY_PROP_CHARGE_TYPE:
319 val->intval = get_prop_charge_type();
320 break;
321 case POWER_SUPPLY_PROP_HEALTH:
322 val->intval = get_prop_batt_health();
323 break;
324 case POWER_SUPPLY_PROP_PRESENT:
325 val->intval = !(msm_chg.batt_status == BATT_STATUS_ABSENT);
326 break;
327 case POWER_SUPPLY_PROP_TECHNOLOGY:
328 val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH;
329 break;
330 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
331 val->intval = msm_chg.max_voltage * 1000;
332 break;
333 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
334 val->intval = msm_chg.min_voltage * 1000;
335 break;
336 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
337 val->intval = get_prop_battery_mvolts();
338 break;
339 case POWER_SUPPLY_PROP_CAPACITY:
340 val->intval = get_prop_batt_capacity();
341 break;
342 default:
343 return -EINVAL;
344 }
345 return 0;
346}
347
348static struct power_supply msm_psy_batt = {
349 .name = "battery",
350 .type = POWER_SUPPLY_TYPE_BATTERY,
351 .properties = msm_batt_power_props,
352 .num_properties = ARRAY_SIZE(msm_batt_power_props),
353 .get_property = msm_batt_power_get_property,
354};
355
356static int usb_chg_current;
357static struct msm_hardware_charger_priv *usb_hw_chg_priv;
358static void (*notify_vbus_state_func_ptr)(int);
359static int usb_notified_of_insertion;
360
361/* this is passed to the hsusb via platform_data msm_otg_pdata */
362int msm_charger_register_vbus_sn(void (*callback)(int))
363{
364 pr_debug(KERN_INFO "%s\n", __func__);
365 notify_vbus_state_func_ptr = callback;
366 return 0;
367}
368
369/* this is passed to the hsusb via platform_data msm_otg_pdata */
370void msm_charger_unregister_vbus_sn(void (*callback)(int))
371{
372 pr_debug(KERN_INFO "%s\n", __func__);
373 notify_vbus_state_func_ptr = NULL;
374}
375
376static void notify_usb_of_the_plugin_event(struct msm_hardware_charger_priv
377 *hw_chg, int plugin)
378{
379 plugin = !!plugin;
380 if (plugin == 1 && usb_notified_of_insertion == 0) {
381 usb_notified_of_insertion = 1;
382 if (notify_vbus_state_func_ptr) {
383 dev_dbg(msm_chg.dev, "%s notifying plugin\n", __func__);
384 (*notify_vbus_state_func_ptr) (plugin);
385 } else
386 dev_dbg(msm_chg.dev, "%s unable to notify plugin\n",
387 __func__);
388 usb_hw_chg_priv = hw_chg;
389 }
390 if (plugin == 0 && usb_notified_of_insertion == 1) {
391 if (notify_vbus_state_func_ptr) {
392 dev_dbg(msm_chg.dev, "%s notifying unplugin\n",
393 __func__);
394 (*notify_vbus_state_func_ptr) (plugin);
395 } else
396 dev_dbg(msm_chg.dev, "%s unable to notify unplugin\n",
397 __func__);
398 usb_notified_of_insertion = 0;
399 usb_hw_chg_priv = NULL;
400 }
401}
402
403static unsigned int msm_chg_get_batt_capacity_percent(void)
404{
405 unsigned int current_voltage = get_prop_battery_mvolts();
406 unsigned int low_voltage = msm_chg.min_voltage;
407 unsigned int high_voltage = msm_chg.max_voltage;
408
409 if (current_voltage <= low_voltage)
410 return 0;
411 else if (current_voltage >= high_voltage)
412 return 100;
413 else
414 return (current_voltage - low_voltage) * 100
415 / (high_voltage - low_voltage);
416}
417
418#ifdef DEBUG
419static inline void debug_print(const char *func,
420 struct msm_hardware_charger_priv *hw_chg_priv)
421{
422 dev_dbg(msm_chg.dev,
423 "%s current=(%s)(s=%d)(r=%d) new=(%s)(s=%d)(r=%d) batt=%d En\n",
424 func,
425 msm_chg.current_chg_priv ? msm_chg.current_chg_priv->
426 hw_chg->name : "none",
427 msm_chg.current_chg_priv ? msm_chg.
428 current_chg_priv->hw_chg_state : -1,
429 msm_chg.current_chg_priv ? msm_chg.current_chg_priv->
430 hw_chg->rating : -1,
431 hw_chg_priv ? hw_chg_priv->hw_chg->name : "none",
432 hw_chg_priv ? hw_chg_priv->hw_chg_state : -1,
433 hw_chg_priv ? hw_chg_priv->hw_chg->rating : -1,
434 msm_chg.batt_status);
435}
436#else
437static inline void debug_print(const char *func,
438 struct msm_hardware_charger_priv *hw_chg_priv)
439{
440}
441#endif
442
443static struct msm_hardware_charger_priv *find_best_charger(void)
444{
445 struct msm_hardware_charger_priv *hw_chg_priv;
446 struct msm_hardware_charger_priv *better;
447 int rating;
448
449 better = NULL;
450 rating = 0;
451
452 list_for_each_entry(hw_chg_priv, &msm_chg.msm_hardware_chargers, list) {
453 if (is_chg_capable_of_charging(hw_chg_priv)) {
454 if (hw_chg_priv->hw_chg->rating > rating) {
455 rating = hw_chg_priv->hw_chg->rating;
456 better = hw_chg_priv;
457 }
458 }
459 }
460
461 return better;
462}
463
464static int msm_charging_switched(struct msm_hardware_charger_priv *priv)
465{
466 int ret = 0;
467
468 if (priv->hw_chg->charging_switched)
469 ret = priv->hw_chg->charging_switched(priv->hw_chg);
470 return ret;
471}
472
473static int msm_stop_charging(struct msm_hardware_charger_priv *priv)
474{
475 int ret;
476
477 ret = priv->hw_chg->stop_charging(priv->hw_chg);
478 if (!ret)
479 wake_unlock(&msm_chg.wl);
480 return ret;
481}
482
483/* the best charger has been selected -start charging from current_chg_priv */
484static int msm_start_charging(void)
485{
486 int ret;
487 struct msm_hardware_charger_priv *priv;
488
489 priv = msm_chg.current_chg_priv;
490 wake_lock(&msm_chg.wl);
491 ret = priv->hw_chg->start_charging(priv->hw_chg, msm_chg.max_voltage,
492 priv->max_source_current);
493 if (ret) {
494 wake_unlock(&msm_chg.wl);
495 dev_err(msm_chg.dev, "%s couldnt start chg error = %d\n",
496 priv->hw_chg->name, ret);
497 } else
498 priv->hw_chg_state = CHG_CHARGING_STATE;
499
500 return ret;
501}
502
503static void handle_charging_done(struct msm_hardware_charger_priv *priv)
504{
505 if (msm_chg.current_chg_priv == priv) {
506 if (msm_chg.current_chg_priv->hw_chg_state ==
507 CHG_CHARGING_STATE)
508 if (msm_stop_charging(msm_chg.current_chg_priv)) {
509 dev_err(msm_chg.dev, "%s couldnt stop chg\n",
510 msm_chg.current_chg_priv->hw_chg->name);
511 }
512 msm_chg.current_chg_priv->hw_chg_state = CHG_READY_STATE;
513
514 msm_chg.batt_status = BATT_STATUS_JUST_FINISHED_CHARGING;
515 dev_info(msm_chg.dev, "%s: stopping safety timer work\n",
516 __func__);
517 cancel_delayed_work(&msm_chg.teoc_work);
518
519 if (msm_batt_gauge && msm_batt_gauge->monitor_for_recharging)
520 msm_batt_gauge->monitor_for_recharging();
521 else
522 dev_err(msm_chg.dev,
523 "%s: no batt gauge recharge monitor\n", __func__);
524 }
525}
526
527static void teoc(struct work_struct *work)
528{
529 /* we have been charging too long - stop charging */
530 dev_info(msm_chg.dev, "%s: safety timer work expired\n", __func__);
531
532 mutex_lock(&msm_chg.status_lock);
533 if (msm_chg.current_chg_priv != NULL
534 && msm_chg.current_chg_priv->hw_chg_state == CHG_CHARGING_STATE) {
535 handle_charging_done(msm_chg.current_chg_priv);
536 }
537 mutex_unlock(&msm_chg.status_lock);
538}
539
540static void handle_battery_inserted(void)
541{
542 /* if a charger is already present start charging */
543 if (msm_chg.current_chg_priv != NULL &&
544 is_batt_status_capable_of_charging() &&
545 !is_batt_status_charging()) {
546 if (msm_start_charging()) {
547 dev_err(msm_chg.dev, "%s couldnt start chg\n",
548 msm_chg.current_chg_priv->hw_chg->name);
549 return;
550 }
551 msm_chg.batt_status = BATT_STATUS_TRKL_CHARGING;
552
553 dev_info(msm_chg.dev, "%s: starting safety timer work\n",
554 __func__);
555 queue_delayed_work(msm_chg.event_wq_thread,
556 &msm_chg.teoc_work,
557 round_jiffies_relative(msecs_to_jiffies
558 (msm_chg.
559 safety_time)));
560 }
561}
562
563static void handle_battery_removed(void)
564{
565 /* if a charger is charging the battery stop it */
566 if (msm_chg.current_chg_priv != NULL
567 && msm_chg.current_chg_priv->hw_chg_state == CHG_CHARGING_STATE) {
568 if (msm_stop_charging(msm_chg.current_chg_priv)) {
569 dev_err(msm_chg.dev, "%s couldnt stop chg\n",
570 msm_chg.current_chg_priv->hw_chg->name);
571 }
572 msm_chg.current_chg_priv->hw_chg_state = CHG_READY_STATE;
573
574 dev_info(msm_chg.dev, "%s: stopping safety timer work\n",
575 __func__);
576 cancel_delayed_work(&msm_chg.teoc_work);
577 }
578}
579
580static void update_heartbeat(struct work_struct *work)
581{
582 int temperature;
583
584 if (msm_chg.batt_status == BATT_STATUS_ABSENT
585 || msm_chg.batt_status == BATT_STATUS_ID_INVALID) {
586 if (is_battery_present())
587 if (is_battery_id_valid()) {
588 msm_chg.batt_status = BATT_STATUS_DISCHARGING;
589 handle_battery_inserted();
590 }
591 } else {
592 if (!is_battery_present()) {
593 msm_chg.batt_status = BATT_STATUS_ABSENT;
594 handle_battery_removed();
595 }
596 /*
597 * check battery id because a good battery could be removed
598 * and replaced with a invalid battery.
599 */
600 if (!is_battery_id_valid()) {
601 msm_chg.batt_status = BATT_STATUS_ID_INVALID;
602 handle_battery_removed();
603 }
604 }
605 pr_debug("msm-charger %s batt_status= %d\n",
606 __func__, msm_chg.batt_status);
607
608 if (msm_chg.current_chg_priv
609 && msm_chg.current_chg_priv->hw_chg_state
610 == CHG_CHARGING_STATE) {
611 temperature = get_battery_temperature();
612 /* TODO implement JEITA SPEC*/
613 }
614
615 /* notify that the voltage has changed
616 * the read of the capacity will trigger a
617 * voltage read*/
618 power_supply_changed(&msm_psy_batt);
619
620 if (msm_chg.stop_update) {
621 msm_chg.stop_update = 0;
622 return;
623 }
624 queue_delayed_work(msm_chg.event_wq_thread,
625 &msm_chg.update_heartbeat_work,
626 round_jiffies_relative(msecs_to_jiffies
627 (msm_chg.update_time)));
628}
629
630/* set the charger state to READY before calling this */
631static void handle_charger_ready(struct msm_hardware_charger_priv *hw_chg_priv)
632{
633 debug_print(__func__, hw_chg_priv);
634
635 if (msm_chg.current_chg_priv != NULL
636 && hw_chg_priv->hw_chg->rating >
637 msm_chg.current_chg_priv->hw_chg->rating) {
638 if (msm_chg.current_chg_priv->hw_chg_state ==
639 CHG_CHARGING_STATE) {
640 if (msm_stop_charging(msm_chg.current_chg_priv)) {
641 dev_err(msm_chg.dev, "%s couldnt stop chg\n",
642 msm_chg.current_chg_priv->hw_chg->name);
643 return;
644 }
645 if (msm_charging_switched(msm_chg.current_chg_priv)) {
646 dev_err(msm_chg.dev, "%s couldnt stop chg\n",
647 msm_chg.current_chg_priv->hw_chg->name);
648 return;
649 }
650 }
651 msm_chg.current_chg_priv->hw_chg_state = CHG_READY_STATE;
652 msm_chg.current_chg_priv = NULL;
653 }
654
655 if (msm_chg.current_chg_priv == NULL) {
656 msm_chg.current_chg_priv = hw_chg_priv;
657 dev_info(msm_chg.dev,
658 "%s: best charger = %s\n", __func__,
659 msm_chg.current_chg_priv->hw_chg->name);
660
661 if (!is_batt_status_capable_of_charging())
662 return;
663
664 /* start charging from the new charger */
665 if (!msm_start_charging()) {
666 /* if we simply switched chg continue with teoc timer
667 * else we update the batt state and set the teoc
668 * timer */
669 if (!is_batt_status_charging()) {
670 dev_info(msm_chg.dev,
671 "%s: starting safety timer\n", __func__);
672 queue_delayed_work(msm_chg.event_wq_thread,
673 &msm_chg.teoc_work,
674 round_jiffies_relative
675 (msecs_to_jiffies
676 (msm_chg.safety_time)));
677 msm_chg.batt_status = BATT_STATUS_TRKL_CHARGING;
678 }
679 } else {
680 /* we couldnt start charging from the new readied
681 * charger */
682 if (is_batt_status_charging())
683 msm_chg.batt_status = BATT_STATUS_DISCHARGING;
684 }
685 }
686}
687
688static void handle_charger_removed(struct msm_hardware_charger_priv
689 *hw_chg_removed, int new_state)
690{
691 struct msm_hardware_charger_priv *hw_chg_priv;
692
693 debug_print(__func__, hw_chg_removed);
694
695 if (msm_chg.current_chg_priv == hw_chg_removed) {
696 if (msm_chg.current_chg_priv->hw_chg_state
697 == CHG_CHARGING_STATE) {
698 if (msm_stop_charging(hw_chg_removed)) {
699 dev_err(msm_chg.dev, "%s couldnt stop chg\n",
700 msm_chg.current_chg_priv->hw_chg->name);
701 }
702 }
703 msm_chg.current_chg_priv = NULL;
704 }
705
706 hw_chg_removed->hw_chg_state = new_state;
707
708 if (msm_chg.current_chg_priv == NULL) {
709 hw_chg_priv = find_best_charger();
710 if (hw_chg_priv == NULL) {
711 dev_info(msm_chg.dev, "%s: no chargers\n", __func__);
712 /* if the battery was Just finished charging
713 * we keep that state as is so that we dont rush
714 * in to charging the battery when a charger is
715 * plugged in shortly. */
716 if (is_batt_status_charging())
717 msm_chg.batt_status = BATT_STATUS_DISCHARGING;
718 } else {
719 msm_chg.current_chg_priv = hw_chg_priv;
720 dev_info(msm_chg.dev,
721 "%s: best charger = %s\n", __func__,
722 msm_chg.current_chg_priv->hw_chg->name);
723
724 if (!is_batt_status_capable_of_charging())
725 return;
726
727 if (msm_start_charging()) {
728 /* we couldnt start charging for some reason */
729 msm_chg.batt_status = BATT_STATUS_DISCHARGING;
730 }
731 }
732 }
733
734 /* if we arent charging stop the safety timer */
735 if (!is_batt_status_charging()) {
736 dev_info(msm_chg.dev, "%s: stopping safety timer work\n",
737 __func__);
738 cancel_delayed_work(&msm_chg.teoc_work);
739 }
740}
741
742static void handle_event(struct msm_hardware_charger *hw_chg, int event)
743{
744 struct msm_hardware_charger_priv *priv = NULL;
745
746 /*
747 * if hw_chg is NULL then this event comes from non-charger
748 * parties like battery gauge
749 */
750 if (hw_chg)
751 priv = hw_chg->charger_private;
752
753 mutex_lock(&msm_chg.status_lock);
754
755 switch (event) {
756 case CHG_INSERTED_EVENT:
757 if (priv->hw_chg_state != CHG_ABSENT_STATE) {
758 dev_info(msm_chg.dev,
759 "%s insertion detected when cbl present",
760 hw_chg->name);
761 break;
762 }
763 update_batt_status();
764 if (hw_chg->type == CHG_TYPE_USB) {
765 priv->hw_chg_state = CHG_PRESENT_STATE;
766 notify_usb_of_the_plugin_event(priv, 1);
767 if (usb_chg_current) {
768 priv->max_source_current = usb_chg_current;
769 usb_chg_current = 0;
770 /* usb has already indicated us to charge */
771 priv->hw_chg_state = CHG_READY_STATE;
772 handle_charger_ready(priv);
773 }
774 } else {
775 priv->hw_chg_state = CHG_READY_STATE;
776 handle_charger_ready(priv);
777 }
778 break;
779 case CHG_ENUMERATED_EVENT: /* only in USB types */
780 if (priv->hw_chg_state == CHG_ABSENT_STATE) {
781 dev_info(msm_chg.dev, "%s enum withuot presence\n",
782 hw_chg->name);
783 break;
784 }
785 update_batt_status();
786 dev_dbg(msm_chg.dev, "%s enum with %dmA to draw\n",
787 hw_chg->name, priv->max_source_current);
788 if (priv->max_source_current == 0) {
789 /* usb subsystem doesnt want us to draw
790 * charging current */
791 /* act as if the charge is removed */
792 if (priv->hw_chg_state != CHG_PRESENT_STATE)
793 handle_charger_removed(priv, CHG_PRESENT_STATE);
794 } else {
795 if (priv->hw_chg_state != CHG_READY_STATE) {
796 priv->hw_chg_state = CHG_READY_STATE;
797 handle_charger_ready(priv);
798 }
799 }
800 break;
801 case CHG_REMOVED_EVENT:
802 if (priv->hw_chg_state == CHG_ABSENT_STATE) {
803 dev_info(msm_chg.dev, "%s cable already removed\n",
804 hw_chg->name);
805 break;
806 }
807 update_batt_status();
808 if (hw_chg->type == CHG_TYPE_USB) {
809 usb_chg_current = 0;
810 notify_usb_of_the_plugin_event(priv, 0);
811 }
812 handle_charger_removed(priv, CHG_ABSENT_STATE);
813 break;
814 case CHG_DONE_EVENT:
815 if (priv->hw_chg_state == CHG_CHARGING_STATE)
816 handle_charging_done(priv);
817 break;
818 case CHG_BATT_BEGIN_FAST_CHARGING:
819 /* only update if we are TRKL charging */
820 if (msm_chg.batt_status == BATT_STATUS_TRKL_CHARGING)
821 msm_chg.batt_status = BATT_STATUS_FAST_CHARGING;
822 break;
823 case CHG_BATT_NEEDS_RECHARGING:
824 msm_chg.batt_status = BATT_STATUS_DISCHARGING;
825 handle_battery_inserted();
826 priv = msm_chg.current_chg_priv;
827 break;
828 case CHG_BATT_TEMP_OUTOFRANGE:
829 /* the batt_temp out of range can trigger
830 * when the battery is absent */
831 if (!is_battery_present()
832 && msm_chg.batt_status != BATT_STATUS_ABSENT) {
833 msm_chg.batt_status = BATT_STATUS_ABSENT;
834 handle_battery_removed();
835 break;
836 }
837 if (msm_chg.batt_status == BATT_STATUS_TEMPERATURE_OUT_OF_RANGE)
838 break;
839 msm_chg.batt_status = BATT_STATUS_TEMPERATURE_OUT_OF_RANGE;
840 handle_battery_removed();
841 break;
842 case CHG_BATT_TEMP_INRANGE:
843 if (msm_chg.batt_status != BATT_STATUS_TEMPERATURE_OUT_OF_RANGE)
844 break;
845 msm_chg.batt_status = BATT_STATUS_ID_INVALID;
846 /* check id */
847 if (!is_battery_id_valid())
848 break;
849 /* assume that we are discharging from the battery
850 * and act as if the battery was inserted
851 * if a charger is present charging will be resumed */
852 msm_chg.batt_status = BATT_STATUS_DISCHARGING;
853 handle_battery_inserted();
854 break;
855 case CHG_BATT_INSERTED:
856 if (msm_chg.batt_status != BATT_STATUS_ABSENT)
857 break;
858 /* debounce */
859 if (!is_battery_present())
860 break;
861 msm_chg.batt_status = BATT_STATUS_ID_INVALID;
862 if (!is_battery_id_valid())
863 break;
864 /* assume that we are discharging from the battery */
865 msm_chg.batt_status = BATT_STATUS_DISCHARGING;
866 /* check if a charger is present */
867 handle_battery_inserted();
868 break;
869 case CHG_BATT_REMOVED:
870 if (msm_chg.batt_status == BATT_STATUS_ABSENT)
871 break;
872 /* debounce */
873 if (is_battery_present())
874 break;
875 msm_chg.batt_status = BATT_STATUS_ABSENT;
876 handle_battery_removed();
877 break;
878 case CHG_BATT_STATUS_CHANGE:
879 /* TODO battery SOC like battery-alarm/charging-full features
880 can be added here for future improvement */
881 break;
882 }
883 dev_dbg(msm_chg.dev, "%s %d done batt_status=%d\n", __func__,
884 event, msm_chg.batt_status);
885
886 /* update userspace */
887 if (msm_batt_gauge)
888 power_supply_changed(&msm_psy_batt);
889 if (priv)
890 power_supply_changed(&priv->psy);
891
892 mutex_unlock(&msm_chg.status_lock);
893}
894
895static int msm_chg_dequeue_event(struct msm_charger_event **event)
896{
897 unsigned long flags;
898
899 spin_lock_irqsave(&msm_chg.queue_lock, flags);
900 if (msm_chg.queue_count == 0) {
901 spin_unlock_irqrestore(&msm_chg.queue_lock, flags);
902 return -EINVAL;
903 }
904 *event = &msm_chg.queue[msm_chg.head];
905 msm_chg.head = (msm_chg.head + 1) % MSM_CHG_MAX_EVENTS;
906 pr_debug("%s dequeueing %d\n", __func__, (*event)->event);
907 msm_chg.queue_count--;
908 spin_unlock_irqrestore(&msm_chg.queue_lock, flags);
909 return 0;
910}
911
912static int msm_chg_enqueue_event(struct msm_hardware_charger *hw_chg,
913 enum msm_hardware_charger_event event)
914{
915 unsigned long flags;
916
917 spin_lock_irqsave(&msm_chg.queue_lock, flags);
918 if (msm_chg.queue_count == MSM_CHG_MAX_EVENTS) {
919 spin_unlock_irqrestore(&msm_chg.queue_lock, flags);
920 pr_err("%s: queue full cannot enqueue %d\n",
921 __func__, event);
922 return -EAGAIN;
923 }
924 pr_debug("%s queueing %d\n", __func__, event);
925 msm_chg.queue[msm_chg.tail].event = event;
926 msm_chg.queue[msm_chg.tail].hw_chg = hw_chg;
927 msm_chg.tail = (msm_chg.tail + 1)%MSM_CHG_MAX_EVENTS;
928 msm_chg.queue_count++;
929 spin_unlock_irqrestore(&msm_chg.queue_lock, flags);
930 return 0;
931}
932
933static void process_events(struct work_struct *work)
934{
935 struct msm_charger_event *event;
936 int rc;
937
938 do {
939 rc = msm_chg_dequeue_event(&event);
940 if (!rc)
941 handle_event(event->hw_chg, event->event);
942 } while (!rc);
943}
944
945/* USB calls these to tell us how much charging current we should draw */
946void msm_charger_vbus_draw(unsigned int mA)
947{
948 if (usb_hw_chg_priv) {
949 usb_hw_chg_priv->max_source_current = mA;
950 msm_charger_notify_event(usb_hw_chg_priv->hw_chg,
951 CHG_ENUMERATED_EVENT);
952 } else
953 /* remember the current, to be used when charger is ready */
954 usb_chg_current = mA;
955}
956
957static int __init determine_initial_batt_status(void)
958{
959 int rc;
960
961 if (is_battery_present())
962 if (is_battery_id_valid())
963 if (is_battery_temp_within_range())
964 msm_chg.batt_status = BATT_STATUS_DISCHARGING;
965 else
966 msm_chg.batt_status
967 = BATT_STATUS_TEMPERATURE_OUT_OF_RANGE;
968 else
969 msm_chg.batt_status = BATT_STATUS_ID_INVALID;
970 else
971 msm_chg.batt_status = BATT_STATUS_ABSENT;
972
973 if (is_batt_status_capable_of_charging())
974 handle_battery_inserted();
975
976 rc = power_supply_register(msm_chg.dev, &msm_psy_batt);
977 if (rc < 0) {
978 dev_err(msm_chg.dev, "%s: power_supply_register failed"
979 " rc=%d\n", __func__, rc);
980 return rc;
981 }
982
983 /* start updaing the battery powersupply every msm_chg.update_time
984 * milliseconds */
985 queue_delayed_work(msm_chg.event_wq_thread,
986 &msm_chg.update_heartbeat_work,
987 round_jiffies_relative(msecs_to_jiffies
988 (msm_chg.update_time)));
989
990 pr_debug("%s:OK batt_status=%d\n", __func__, msm_chg.batt_status);
991 return 0;
992}
993
994static int __devinit msm_charger_probe(struct platform_device *pdev)
995{
996 msm_chg.dev = &pdev->dev;
997 if (pdev->dev.platform_data) {
998 unsigned int milli_secs;
999
1000 struct msm_charger_platform_data *pdata
1001 =
1002 (struct msm_charger_platform_data *)pdev->dev.platform_data;
1003
1004 milli_secs = pdata->safety_time * 60 * MSEC_PER_SEC;
1005 if (milli_secs > jiffies_to_msecs(MAX_JIFFY_OFFSET)) {
1006 dev_warn(&pdev->dev, "%s: safety time too large"
1007 "%dms\n", __func__, milli_secs);
1008 milli_secs = jiffies_to_msecs(MAX_JIFFY_OFFSET);
1009 }
1010 msm_chg.safety_time = milli_secs;
1011
1012 milli_secs = pdata->update_time * 60 * MSEC_PER_SEC;
1013 if (milli_secs > jiffies_to_msecs(MAX_JIFFY_OFFSET)) {
1014 dev_warn(&pdev->dev, "%s: safety time too large"
1015 "%dms\n", __func__, milli_secs);
1016 milli_secs = jiffies_to_msecs(MAX_JIFFY_OFFSET);
1017 }
1018 msm_chg.update_time = milli_secs;
1019
1020 msm_chg.max_voltage = pdata->max_voltage;
1021 msm_chg.min_voltage = pdata->min_voltage;
1022 msm_chg.get_batt_capacity_percent =
1023 pdata->get_batt_capacity_percent;
1024 }
1025 if (msm_chg.safety_time == 0)
1026 msm_chg.safety_time = CHARGING_TEOC_MS;
1027 if (msm_chg.update_time == 0)
1028 msm_chg.update_time = UPDATE_TIME_MS;
1029 if (msm_chg.max_voltage == 0)
1030 msm_chg.max_voltage = DEFAULT_BATT_MAX_V;
1031 if (msm_chg.min_voltage == 0)
1032 msm_chg.min_voltage = DEFAULT_BATT_MIN_V;
1033 if (msm_chg.get_batt_capacity_percent == NULL)
1034 msm_chg.get_batt_capacity_percent =
1035 msm_chg_get_batt_capacity_percent;
1036
1037 mutex_init(&msm_chg.status_lock);
1038 INIT_DELAYED_WORK(&msm_chg.teoc_work, teoc);
1039 INIT_DELAYED_WORK(&msm_chg.update_heartbeat_work, update_heartbeat);
1040
1041 wake_lock_init(&msm_chg.wl, WAKE_LOCK_SUSPEND, "msm_charger");
1042 return 0;
1043}
1044
1045static int __devexit msm_charger_remove(struct platform_device *pdev)
1046{
Abhijeet Dharmapurikar0f828242011-07-11 12:12:25 -07001047 wake_lock_destroy(&msm_chg.wl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001048 mutex_destroy(&msm_chg.status_lock);
1049 power_supply_unregister(&msm_psy_batt);
1050 return 0;
1051}
1052
1053int msm_charger_notify_event(struct msm_hardware_charger *hw_chg,
1054 enum msm_hardware_charger_event event)
1055{
1056 msm_chg_enqueue_event(hw_chg, event);
1057 queue_work(msm_chg.event_wq_thread, &msm_chg.queue_work);
1058 return 0;
1059}
1060EXPORT_SYMBOL(msm_charger_notify_event);
1061
1062int msm_charger_register(struct msm_hardware_charger *hw_chg)
1063{
1064 struct msm_hardware_charger_priv *priv;
1065 int rc = 0;
1066
1067 if (!msm_chg.inited) {
1068 pr_err("%s: msm_chg is NULL,Too early to register\n", __func__);
1069 return -EAGAIN;
1070 }
1071
1072 if (hw_chg->start_charging == NULL
1073 || hw_chg->stop_charging == NULL
1074 || hw_chg->name == NULL
1075 || hw_chg->rating == 0) {
1076 pr_err("%s: invalid hw_chg\n", __func__);
1077 return -EINVAL;
1078 }
1079
1080 priv = kzalloc(sizeof *priv, GFP_KERNEL);
1081 if (priv == NULL) {
1082 dev_err(msm_chg.dev, "%s kzalloc failed\n", __func__);
1083 return -ENOMEM;
1084 }
1085
1086 priv->psy.name = hw_chg->name;
1087 if (hw_chg->type == CHG_TYPE_USB)
1088 priv->psy.type = POWER_SUPPLY_TYPE_USB;
1089 else
1090 priv->psy.type = POWER_SUPPLY_TYPE_MAINS;
1091
1092 priv->psy.supplied_to = msm_power_supplied_to;
1093 priv->psy.num_supplicants = ARRAY_SIZE(msm_power_supplied_to);
1094 priv->psy.properties = msm_power_props;
1095 priv->psy.num_properties = ARRAY_SIZE(msm_power_props);
1096 priv->psy.get_property = msm_power_get_property;
1097
1098 rc = power_supply_register(NULL, &priv->psy);
1099 if (rc) {
1100 dev_err(msm_chg.dev, "%s power_supply_register failed\n",
1101 __func__);
1102 goto out;
1103 }
1104
1105 priv->hw_chg = hw_chg;
1106 priv->hw_chg_state = CHG_ABSENT_STATE;
1107 INIT_LIST_HEAD(&priv->list);
1108 mutex_lock(&msm_chg.msm_hardware_chargers_lock);
1109 list_add_tail(&priv->list, &msm_chg.msm_hardware_chargers);
1110 mutex_unlock(&msm_chg.msm_hardware_chargers_lock);
1111 hw_chg->charger_private = (void *)priv;
1112 return 0;
1113
1114out:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001115 kfree(priv);
1116 return rc;
1117}
1118EXPORT_SYMBOL(msm_charger_register);
1119
1120void msm_battery_gauge_register(struct msm_battery_gauge *batt_gauge)
1121{
1122 if (msm_batt_gauge) {
1123 msm_batt_gauge = batt_gauge;
1124 pr_err("msm-charger %s multiple battery gauge called\n",
1125 __func__);
1126 } else {
1127 msm_batt_gauge = batt_gauge;
1128 determine_initial_batt_status();
1129 }
1130}
1131EXPORT_SYMBOL(msm_battery_gauge_register);
1132
1133void msm_battery_gauge_unregister(struct msm_battery_gauge *batt_gauge)
1134{
1135 msm_batt_gauge = NULL;
1136}
1137EXPORT_SYMBOL(msm_battery_gauge_unregister);
1138
1139int msm_charger_unregister(struct msm_hardware_charger *hw_chg)
1140{
1141 struct msm_hardware_charger_priv *priv;
1142
1143 priv = (struct msm_hardware_charger_priv *)(hw_chg->charger_private);
1144 mutex_lock(&msm_chg.msm_hardware_chargers_lock);
1145 list_del(&priv->list);
1146 mutex_unlock(&msm_chg.msm_hardware_chargers_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001147 power_supply_unregister(&priv->psy);
1148 kfree(priv);
1149 return 0;
1150}
1151EXPORT_SYMBOL(msm_charger_unregister);
1152
1153static int msm_charger_suspend(struct device *dev)
1154{
1155 dev_dbg(msm_chg.dev, "%s suspended\n", __func__);
1156 msm_chg.stop_update = 1;
1157 cancel_delayed_work(&msm_chg.update_heartbeat_work);
1158 mutex_lock(&msm_chg.status_lock);
1159 handle_battery_removed();
1160 mutex_unlock(&msm_chg.status_lock);
1161 return 0;
1162}
1163
1164static int msm_charger_resume(struct device *dev)
1165{
1166 dev_dbg(msm_chg.dev, "%s resumed\n", __func__);
1167 msm_chg.stop_update = 0;
1168 /* start updaing the battery powersupply every msm_chg.update_time
1169 * milliseconds */
1170 queue_delayed_work(msm_chg.event_wq_thread,
1171 &msm_chg.update_heartbeat_work,
1172 round_jiffies_relative(msecs_to_jiffies
1173 (msm_chg.update_time)));
1174 mutex_lock(&msm_chg.status_lock);
1175 handle_battery_inserted();
1176 mutex_unlock(&msm_chg.status_lock);
1177 return 0;
1178}
1179
1180static SIMPLE_DEV_PM_OPS(msm_charger_pm_ops,
1181 msm_charger_suspend, msm_charger_resume);
1182
1183static struct platform_driver msm_charger_driver = {
1184 .probe = msm_charger_probe,
1185 .remove = __devexit_p(msm_charger_remove),
1186 .driver = {
1187 .name = "msm-charger",
1188 .owner = THIS_MODULE,
1189 .pm = &msm_charger_pm_ops,
1190 },
1191};
1192
1193static int __init msm_charger_init(void)
1194{
1195 int rc;
1196
1197 INIT_LIST_HEAD(&msm_chg.msm_hardware_chargers);
1198 msm_chg.count_chargers = 0;
1199 mutex_init(&msm_chg.msm_hardware_chargers_lock);
1200
1201 msm_chg.queue = kzalloc(sizeof(struct msm_charger_event)
1202 * MSM_CHG_MAX_EVENTS,
1203 GFP_KERNEL);
1204 if (!msm_chg.queue) {
1205 rc = -ENOMEM;
1206 goto out;
1207 }
1208 msm_chg.tail = 0;
1209 msm_chg.head = 0;
1210 spin_lock_init(&msm_chg.queue_lock);
1211 msm_chg.queue_count = 0;
1212 INIT_WORK(&msm_chg.queue_work, process_events);
1213 msm_chg.event_wq_thread = create_workqueue("msm_charger_eventd");
1214 if (!msm_chg.event_wq_thread) {
1215 rc = -ENOMEM;
1216 goto free_queue;
1217 }
1218 rc = platform_driver_register(&msm_charger_driver);
1219 if (rc < 0) {
1220 pr_err("%s: FAIL: platform_driver_register. rc = %d\n",
1221 __func__, rc);
1222 goto destroy_wq_thread;
1223 }
1224 msm_chg.inited = 1;
1225 return 0;
1226
1227destroy_wq_thread:
1228 destroy_workqueue(msm_chg.event_wq_thread);
1229free_queue:
1230 kfree(msm_chg.queue);
1231out:
1232 return rc;
1233}
1234
1235static void __exit msm_charger_exit(void)
1236{
1237 flush_workqueue(msm_chg.event_wq_thread);
1238 destroy_workqueue(msm_chg.event_wq_thread);
1239 kfree(msm_chg.queue);
1240 platform_driver_unregister(&msm_charger_driver);
1241}
1242
1243module_init(msm_charger_init);
1244module_exit(msm_charger_exit);
1245
1246MODULE_LICENSE("GPL v2");
1247MODULE_AUTHOR("Abhijeet Dharmapurikar <adharmap@codeaurora.org>");
1248MODULE_DESCRIPTION("Battery driver for Qualcomm MSM chipsets.");
1249MODULE_VERSION("1.0");