blob: a9b8efdafb8f8ae81de0769bae2fcfc724c60667 [file] [log] [blame]
Arun Murthy1668f812012-02-29 21:54:25 +05301/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Charging algorithm driver for abx500 variants
5 *
6 * License Terms: GNU General Public License v2
7 * Authors:
8 * Johan Palsson <johan.palsson@stericsson.com>
9 * Karl Komierowski <karl.komierowski@stericsson.com>
10 * Arun R Murthy <arun.murthy@stericsson.com>
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/interrupt.h>
17#include <linux/delay.h>
18#include <linux/slab.h>
19#include <linux/platform_device.h>
20#include <linux/power_supply.h>
21#include <linux/completion.h>
22#include <linux/workqueue.h>
23#include <linux/kobject.h>
Rajanikanth H.Va12810a2012-10-31 15:40:33 +000024#include <linux/of.h>
25#include <linux/mfd/core.h>
Arun Murthy1668f812012-02-29 21:54:25 +053026#include <linux/mfd/abx500.h>
27#include <linux/mfd/abx500/ux500_chargalg.h>
28#include <linux/mfd/abx500/ab8500-bm.h>
Lee Jones88917162013-02-13 11:39:19 +000029#include <linux/notifier.h>
Arun Murthy1668f812012-02-29 21:54:25 +053030
31/* Watchdog kick interval */
32#define CHG_WD_INTERVAL (6 * HZ)
33
34/* End-of-charge criteria counter */
35#define EOC_COND_CNT 10
36
Lee Jonesdb43e6c2013-02-14 12:39:15 +000037/* Plus margin for the low battery threshold */
38#define BAT_PLUS_MARGIN (100)
39
Arun Murthy1668f812012-02-29 21:54:25 +053040#define to_abx500_chargalg_device_info(x) container_of((x), \
41 struct abx500_chargalg, chargalg_psy);
42
43enum abx500_chargers {
44 NO_CHG,
45 AC_CHG,
46 USB_CHG,
47};
48
49struct abx500_chargalg_charger_info {
50 enum abx500_chargers conn_chg;
51 enum abx500_chargers prev_conn_chg;
52 enum abx500_chargers online_chg;
53 enum abx500_chargers prev_online_chg;
54 enum abx500_chargers charger_type;
55 bool usb_chg_ok;
56 bool ac_chg_ok;
57 int usb_volt;
58 int usb_curr;
59 int ac_volt;
60 int ac_curr;
61 int usb_vset;
62 int usb_iset;
63 int ac_vset;
64 int ac_iset;
65};
66
67struct abx500_chargalg_suspension_status {
68 bool suspended_change;
69 bool ac_suspended;
70 bool usb_suspended;
71};
72
73struct abx500_chargalg_battery_data {
74 int temp;
75 int volt;
76 int avg_curr;
77 int inst_curr;
78 int percent;
79};
80
81enum abx500_chargalg_states {
82 STATE_HANDHELD_INIT,
83 STATE_HANDHELD,
84 STATE_CHG_NOT_OK_INIT,
85 STATE_CHG_NOT_OK,
86 STATE_HW_TEMP_PROTECT_INIT,
87 STATE_HW_TEMP_PROTECT,
88 STATE_NORMAL_INIT,
Lee Jonesdb43e6c2013-02-14 12:39:15 +000089 STATE_USB_PP_PRE_CHARGE,
Arun Murthy1668f812012-02-29 21:54:25 +053090 STATE_NORMAL,
91 STATE_WAIT_FOR_RECHARGE_INIT,
92 STATE_WAIT_FOR_RECHARGE,
93 STATE_MAINTENANCE_A_INIT,
94 STATE_MAINTENANCE_A,
95 STATE_MAINTENANCE_B_INIT,
96 STATE_MAINTENANCE_B,
97 STATE_TEMP_UNDEROVER_INIT,
98 STATE_TEMP_UNDEROVER,
99 STATE_TEMP_LOWHIGH_INIT,
100 STATE_TEMP_LOWHIGH,
101 STATE_SUSPENDED_INIT,
102 STATE_SUSPENDED,
103 STATE_OVV_PROTECT_INIT,
104 STATE_OVV_PROTECT,
105 STATE_SAFETY_TIMER_EXPIRED_INIT,
106 STATE_SAFETY_TIMER_EXPIRED,
107 STATE_BATT_REMOVED_INIT,
108 STATE_BATT_REMOVED,
109 STATE_WD_EXPIRED_INIT,
110 STATE_WD_EXPIRED,
111};
112
113static const char *states[] = {
114 "HANDHELD_INIT",
115 "HANDHELD",
116 "CHG_NOT_OK_INIT",
117 "CHG_NOT_OK",
118 "HW_TEMP_PROTECT_INIT",
119 "HW_TEMP_PROTECT",
120 "NORMAL_INIT",
Lee Jonesdb43e6c2013-02-14 12:39:15 +0000121 "USB_PP_PRE_CHARGE",
Arun Murthy1668f812012-02-29 21:54:25 +0530122 "NORMAL",
123 "WAIT_FOR_RECHARGE_INIT",
124 "WAIT_FOR_RECHARGE",
125 "MAINTENANCE_A_INIT",
126 "MAINTENANCE_A",
127 "MAINTENANCE_B_INIT",
128 "MAINTENANCE_B",
129 "TEMP_UNDEROVER_INIT",
130 "TEMP_UNDEROVER",
131 "TEMP_LOWHIGH_INIT",
132 "TEMP_LOWHIGH",
133 "SUSPENDED_INIT",
134 "SUSPENDED",
135 "OVV_PROTECT_INIT",
136 "OVV_PROTECT",
137 "SAFETY_TIMER_EXPIRED_INIT",
138 "SAFETY_TIMER_EXPIRED",
139 "BATT_REMOVED_INIT",
140 "BATT_REMOVED",
141 "WD_EXPIRED_INIT",
142 "WD_EXPIRED",
143};
144
145struct abx500_chargalg_events {
146 bool batt_unknown;
147 bool mainextchnotok;
148 bool batt_ovv;
149 bool batt_rem;
150 bool btemp_underover;
151 bool btemp_lowhigh;
152 bool main_thermal_prot;
153 bool usb_thermal_prot;
154 bool main_ovv;
155 bool vbus_ovv;
156 bool usbchargernotok;
157 bool safety_timer_expired;
158 bool maintenance_timer_expired;
159 bool ac_wd_expired;
160 bool usb_wd_expired;
161 bool ac_cv_active;
162 bool usb_cv_active;
163 bool vbus_collapsed;
164};
165
166/**
167 * struct abx500_charge_curr_maximization - Charger maximization parameters
168 * @original_iset: the non optimized/maximised charger current
169 * @current_iset: the charging current used at this moment
170 * @test_delta_i: the delta between the current we want to charge and the
171 current that is really going into the battery
172 * @condition_cnt: number of iterations needed before a new charger current
173 is set
174 * @max_current: maximum charger current
175 * @wait_cnt: to avoid too fast current step down in case of charger
176 * voltage collapse, we insert this delay between step
177 * down
178 * @level: tells in how many steps the charging current has been
179 increased
180 */
181struct abx500_charge_curr_maximization {
182 int original_iset;
183 int current_iset;
184 int test_delta_i;
185 int condition_cnt;
186 int max_current;
187 int wait_cnt;
188 u8 level;
189};
190
191enum maxim_ret {
192 MAXIM_RET_NOACTION,
193 MAXIM_RET_CHANGE,
194 MAXIM_RET_IBAT_TOO_HIGH,
195};
196
197/**
198 * struct abx500_chargalg - abx500 Charging algorithm device information
199 * @dev: pointer to the structure device
200 * @charge_status: battery operating status
201 * @eoc_cnt: counter used to determine end-of_charge
Arun Murthy1668f812012-02-29 21:54:25 +0530202 * @maintenance_chg: indicate if maintenance charge is active
203 * @t_hyst_norm temperature hysteresis when the temperature has been
204 * over or under normal limits
205 * @t_hyst_lowhigh temperature hysteresis when the temperature has been
206 * over or under the high or low limits
207 * @charge_state: current state of the charging algorithm
208 * @ccm charging current maximization parameters
209 * @chg_info: information about connected charger types
210 * @batt_data: data of the battery
211 * @susp_status: current charger suspension status
Lee Jonesb0284de2012-11-30 10:09:42 +0000212 * @bm: Platform specific battery management information
Lee Jones330b7eb2013-02-15 10:53:57 +0000213 * @parent: pointer to the struct abx500
Arun Murthy1668f812012-02-29 21:54:25 +0530214 * @chargalg_psy: structure that holds the battery properties exposed by
215 * the charging algorithm
216 * @events: structure for information about events triggered
217 * @chargalg_wq: work queue for running the charging algorithm
218 * @chargalg_periodic_work: work to run the charging algorithm periodically
219 * @chargalg_wd_work: work to kick the charger watchdog periodically
220 * @chargalg_work: work to run the charging algorithm instantly
221 * @safety_timer: charging safety timer
222 * @maintenance_timer: maintenance charging timer
223 * @chargalg_kobject: structure of type kobject
224 */
225struct abx500_chargalg {
226 struct device *dev;
227 int charge_status;
228 int eoc_cnt;
Arun Murthy1668f812012-02-29 21:54:25 +0530229 bool maintenance_chg;
230 int t_hyst_norm;
231 int t_hyst_lowhigh;
232 enum abx500_chargalg_states charge_state;
233 struct abx500_charge_curr_maximization ccm;
234 struct abx500_chargalg_charger_info chg_info;
235 struct abx500_chargalg_battery_data batt_data;
236 struct abx500_chargalg_suspension_status susp_status;
Lee Jones330b7eb2013-02-15 10:53:57 +0000237 struct ab8500 *parent;
Lee Jonesb0284de2012-11-30 10:09:42 +0000238 struct abx500_bm_data *bm;
Arun Murthy1668f812012-02-29 21:54:25 +0530239 struct power_supply chargalg_psy;
240 struct ux500_charger *ac_chg;
241 struct ux500_charger *usb_chg;
242 struct abx500_chargalg_events events;
243 struct workqueue_struct *chargalg_wq;
244 struct delayed_work chargalg_periodic_work;
245 struct delayed_work chargalg_wd_work;
246 struct work_struct chargalg_work;
247 struct timer_list safety_timer;
248 struct timer_list maintenance_timer;
249 struct kobject chargalg_kobject;
250};
251
Lee Jones88917162013-02-13 11:39:19 +0000252/*External charger prepare notifier*/
253BLOCKING_NOTIFIER_HEAD(charger_notifier_list);
254
Arun Murthy1668f812012-02-29 21:54:25 +0530255/* Main battery properties */
256static enum power_supply_property abx500_chargalg_props[] = {
257 POWER_SUPPLY_PROP_STATUS,
258 POWER_SUPPLY_PROP_HEALTH,
259};
260
261/**
262 * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer
263 * @data: pointer to the abx500_chargalg structure
264 *
265 * This function gets called when the safety timer for the charger
266 * expires
267 */
268static void abx500_chargalg_safety_timer_expired(unsigned long data)
269{
270 struct abx500_chargalg *di = (struct abx500_chargalg *) data;
271 dev_err(di->dev, "Safety timer expired\n");
272 di->events.safety_timer_expired = true;
273
274 /* Trigger execution of the algorithm instantly */
275 queue_work(di->chargalg_wq, &di->chargalg_work);
276}
277
278/**
279 * abx500_chargalg_maintenance_timer_expired() - Expiration of
280 * the maintenance timer
281 * @i: pointer to the abx500_chargalg structure
282 *
283 * This function gets called when the maintenence timer
284 * expires
285 */
286static void abx500_chargalg_maintenance_timer_expired(unsigned long data)
287{
288
289 struct abx500_chargalg *di = (struct abx500_chargalg *) data;
290 dev_dbg(di->dev, "Maintenance timer expired\n");
291 di->events.maintenance_timer_expired = true;
292
293 /* Trigger execution of the algorithm instantly */
294 queue_work(di->chargalg_wq, &di->chargalg_work);
295}
296
297/**
298 * abx500_chargalg_state_to() - Change charge state
299 * @di: pointer to the abx500_chargalg structure
300 *
301 * This function gets called when a charge state change should occur
302 */
303static void abx500_chargalg_state_to(struct abx500_chargalg *di,
304 enum abx500_chargalg_states state)
305{
306 dev_dbg(di->dev,
307 "State changed: %s (From state: [%d] %s =to=> [%d] %s )\n",
308 di->charge_state == state ? "NO" : "YES",
309 di->charge_state,
310 states[di->charge_state],
311 state,
312 states[state]);
313
314 di->charge_state = state;
315}
316
Lee Jones4dcdf572013-02-14 09:24:10 +0000317static int abx500_chargalg_check_charger_enable(struct abx500_chargalg *di)
318{
319 switch (di->charge_state) {
320 case STATE_NORMAL:
321 case STATE_MAINTENANCE_A:
322 case STATE_MAINTENANCE_B:
323 break;
324 default:
325 return 0;
326 }
327
328 if (di->chg_info.charger_type & USB_CHG) {
329 return di->usb_chg->ops.check_enable(di->usb_chg,
330 di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
331 di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
332 } else if ((di->chg_info.charger_type & AC_CHG) &&
333 !(di->ac_chg->external)) {
334 return di->ac_chg->ops.check_enable(di->ac_chg,
335 di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
336 di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
337 }
338 return 0;
339}
340
Arun Murthy1668f812012-02-29 21:54:25 +0530341/**
342 * abx500_chargalg_check_charger_connection() - Check charger connection change
343 * @di: pointer to the abx500_chargalg structure
344 *
345 * This function will check if there is a change in the charger connection
346 * and change charge state accordingly. AC has precedence over USB.
347 */
348static int abx500_chargalg_check_charger_connection(struct abx500_chargalg *di)
349{
350 if (di->chg_info.conn_chg != di->chg_info.prev_conn_chg ||
351 di->susp_status.suspended_change) {
352 /*
353 * Charger state changed or suspension
354 * has changed since last update
355 */
356 if ((di->chg_info.conn_chg & AC_CHG) &&
357 !di->susp_status.ac_suspended) {
358 dev_dbg(di->dev, "Charging source is AC\n");
359 if (di->chg_info.charger_type != AC_CHG) {
360 di->chg_info.charger_type = AC_CHG;
361 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
362 }
363 } else if ((di->chg_info.conn_chg & USB_CHG) &&
364 !di->susp_status.usb_suspended) {
365 dev_dbg(di->dev, "Charging source is USB\n");
366 di->chg_info.charger_type = USB_CHG;
367 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
368 } else if (di->chg_info.conn_chg &&
369 (di->susp_status.ac_suspended ||
370 di->susp_status.usb_suspended)) {
371 dev_dbg(di->dev, "Charging is suspended\n");
372 di->chg_info.charger_type = NO_CHG;
373 abx500_chargalg_state_to(di, STATE_SUSPENDED_INIT);
374 } else {
375 dev_dbg(di->dev, "Charging source is OFF\n");
376 di->chg_info.charger_type = NO_CHG;
377 abx500_chargalg_state_to(di, STATE_HANDHELD_INIT);
378 }
379 di->chg_info.prev_conn_chg = di->chg_info.conn_chg;
380 di->susp_status.suspended_change = false;
381 }
382 return di->chg_info.conn_chg;
383}
384
385/**
386 * abx500_chargalg_start_safety_timer() - Start charging safety timer
387 * @di: pointer to the abx500_chargalg structure
388 *
389 * The safety timer is used to avoid overcharging of old or bad batteries.
390 * There are different timers for AC and USB
391 */
392static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di)
393{
394 unsigned long timer_expiration = 0;
395
396 switch (di->chg_info.charger_type) {
397 case AC_CHG:
398 timer_expiration =
399 round_jiffies(jiffies +
Lee Jonesb0284de2012-11-30 10:09:42 +0000400 (di->bm->main_safety_tmr_h * 3600 * HZ));
Arun Murthy1668f812012-02-29 21:54:25 +0530401 break;
402
403 case USB_CHG:
404 timer_expiration =
405 round_jiffies(jiffies +
Lee Jonesb0284de2012-11-30 10:09:42 +0000406 (di->bm->usb_safety_tmr_h * 3600 * HZ));
Arun Murthy1668f812012-02-29 21:54:25 +0530407 break;
408
409 default:
410 dev_err(di->dev, "Unknown charger to charge from\n");
411 break;
412 }
413
414 di->events.safety_timer_expired = false;
415 di->safety_timer.expires = timer_expiration;
416 if (!timer_pending(&di->safety_timer))
417 add_timer(&di->safety_timer);
418 else
419 mod_timer(&di->safety_timer, timer_expiration);
420}
421
422/**
423 * abx500_chargalg_stop_safety_timer() - Stop charging safety timer
424 * @di: pointer to the abx500_chargalg structure
425 *
426 * The safety timer is stopped whenever the NORMAL state is exited
427 */
428static void abx500_chargalg_stop_safety_timer(struct abx500_chargalg *di)
429{
430 di->events.safety_timer_expired = false;
431 del_timer(&di->safety_timer);
432}
433
434/**
435 * abx500_chargalg_start_maintenance_timer() - Start charging maintenance timer
436 * @di: pointer to the abx500_chargalg structure
437 * @duration: duration of ther maintenance timer in hours
438 *
439 * The maintenance timer is used to maintain the charge in the battery once
440 * the battery is considered full. These timers are chosen to match the
441 * discharge curve of the battery
442 */
443static void abx500_chargalg_start_maintenance_timer(struct abx500_chargalg *di,
444 int duration)
445{
446 unsigned long timer_expiration;
447
448 /* Convert from hours to jiffies */
449 timer_expiration = round_jiffies(jiffies + (duration * 3600 * HZ));
450
451 di->events.maintenance_timer_expired = false;
452 di->maintenance_timer.expires = timer_expiration;
453 if (!timer_pending(&di->maintenance_timer))
454 add_timer(&di->maintenance_timer);
455 else
456 mod_timer(&di->maintenance_timer, timer_expiration);
457}
458
459/**
460 * abx500_chargalg_stop_maintenance_timer() - Stop maintenance timer
461 * @di: pointer to the abx500_chargalg structure
462 *
463 * The maintenance timer is stopped whenever maintenance ends or when another
464 * state is entered
465 */
466static void abx500_chargalg_stop_maintenance_timer(struct abx500_chargalg *di)
467{
468 di->events.maintenance_timer_expired = false;
469 del_timer(&di->maintenance_timer);
470}
471
472/**
473 * abx500_chargalg_kick_watchdog() - Kick charger watchdog
474 * @di: pointer to the abx500_chargalg structure
475 *
476 * The charger watchdog have to be kicked periodically whenever the charger is
477 * on, else the ABB will reset the system
478 */
479static int abx500_chargalg_kick_watchdog(struct abx500_chargalg *di)
480{
481 /* Check if charger exists and kick watchdog if charging */
482 if (di->ac_chg && di->ac_chg->ops.kick_wd &&
Loic Pallardye07a5642012-05-10 15:33:56 +0200483 di->chg_info.online_chg & AC_CHG) {
484 /*
485 * If AB charger watchdog expired, pm2xxx charging
486 * gets disabled. To be safe, kick both AB charger watchdog
487 * and pm2xxx watchdog.
488 */
489 if (di->ac_chg->external &&
490 di->usb_chg && di->usb_chg->ops.kick_wd)
491 di->usb_chg->ops.kick_wd(di->usb_chg);
492
Arun Murthy1668f812012-02-29 21:54:25 +0530493 return di->ac_chg->ops.kick_wd(di->ac_chg);
Loic Pallardye07a5642012-05-10 15:33:56 +0200494 }
Arun Murthy1668f812012-02-29 21:54:25 +0530495 else if (di->usb_chg && di->usb_chg->ops.kick_wd &&
496 di->chg_info.online_chg & USB_CHG)
497 return di->usb_chg->ops.kick_wd(di->usb_chg);
498
499 return -ENXIO;
500}
501
502/**
503 * abx500_chargalg_ac_en() - Turn on/off the AC charger
504 * @di: pointer to the abx500_chargalg structure
505 * @enable: charger on/off
506 * @vset: requested charger output voltage
507 * @iset: requested charger output current
508 *
509 * The AC charger will be turned on/off with the requested charge voltage and
510 * current
511 */
512static int abx500_chargalg_ac_en(struct abx500_chargalg *di, int enable,
513 int vset, int iset)
514{
Lee Jones88917162013-02-13 11:39:19 +0000515 static int abx500_chargalg_ex_ac_enable_toggle;
516
Arun Murthy1668f812012-02-29 21:54:25 +0530517 if (!di->ac_chg || !di->ac_chg->ops.enable)
518 return -ENXIO;
519
520 /* Select maximum of what both the charger and the battery supports */
521 if (di->ac_chg->max_out_volt)
522 vset = min(vset, di->ac_chg->max_out_volt);
523 if (di->ac_chg->max_out_curr)
524 iset = min(iset, di->ac_chg->max_out_curr);
525
526 di->chg_info.ac_iset = iset;
527 di->chg_info.ac_vset = vset;
528
Lee Jones88917162013-02-13 11:39:19 +0000529 /* Enable external charger */
530 if (enable && di->ac_chg->external &&
531 !abx500_chargalg_ex_ac_enable_toggle) {
532 blocking_notifier_call_chain(&charger_notifier_list,
533 0, di->dev);
534 abx500_chargalg_ex_ac_enable_toggle++;
535 }
536
Arun Murthy1668f812012-02-29 21:54:25 +0530537 return di->ac_chg->ops.enable(di->ac_chg, enable, vset, iset);
538}
539
540/**
541 * abx500_chargalg_usb_en() - Turn on/off the USB charger
542 * @di: pointer to the abx500_chargalg structure
543 * @enable: charger on/off
544 * @vset: requested charger output voltage
545 * @iset: requested charger output current
546 *
547 * The USB charger will be turned on/off with the requested charge voltage and
548 * current
549 */
550static int abx500_chargalg_usb_en(struct abx500_chargalg *di, int enable,
551 int vset, int iset)
552{
553 if (!di->usb_chg || !di->usb_chg->ops.enable)
554 return -ENXIO;
555
556 /* Select maximum of what both the charger and the battery supports */
557 if (di->usb_chg->max_out_volt)
558 vset = min(vset, di->usb_chg->max_out_volt);
559 if (di->usb_chg->max_out_curr)
560 iset = min(iset, di->usb_chg->max_out_curr);
561
562 di->chg_info.usb_iset = iset;
563 di->chg_info.usb_vset = vset;
564
565 return di->usb_chg->ops.enable(di->usb_chg, enable, vset, iset);
566}
567
Lee Jonesdb43e6c2013-02-14 12:39:15 +0000568 /**
569 * ab8540_chargalg_usb_pp_en() - Enable/ disable USB power path
570 * @di: pointer to the abx500_chargalg structure
571 * @enable: power path enable/disable
572 *
573 * The USB power path will be enable/ disable
574 */
575static int ab8540_chargalg_usb_pp_en(struct abx500_chargalg *di, bool enable)
576{
577 if (!di->usb_chg || !di->usb_chg->ops.pp_enable)
578 return -ENXIO;
579
580 return di->usb_chg->ops.pp_enable(di->usb_chg, enable);
581}
582
583/**
584 * ab8540_chargalg_usb_pre_chg_en() - Enable/ disable USB pre-charge
585 * @di: pointer to the abx500_chargalg structure
586 * @enable: USB pre-charge enable/disable
587 *
588 * The USB USB pre-charge will be enable/ disable
589 */
590static int ab8540_chargalg_usb_pre_chg_en(struct abx500_chargalg *di,
591 bool enable)
592{
593 if (!di->usb_chg || !di->usb_chg->ops.pre_chg_enable)
594 return -ENXIO;
595
596 return di->usb_chg->ops.pre_chg_enable(di->usb_chg, enable);
597}
598
Arun Murthy1668f812012-02-29 21:54:25 +0530599/**
600 * abx500_chargalg_update_chg_curr() - Update charger current
601 * @di: pointer to the abx500_chargalg structure
602 * @iset: requested charger output current
603 *
604 * The charger output current will be updated for the charger
605 * that is currently in use
606 */
607static int abx500_chargalg_update_chg_curr(struct abx500_chargalg *di,
608 int iset)
609{
610 /* Check if charger exists and update current if charging */
611 if (di->ac_chg && di->ac_chg->ops.update_curr &&
612 di->chg_info.charger_type & AC_CHG) {
613 /*
614 * Select maximum of what both the charger
615 * and the battery supports
616 */
617 if (di->ac_chg->max_out_curr)
618 iset = min(iset, di->ac_chg->max_out_curr);
619
620 di->chg_info.ac_iset = iset;
621
622 return di->ac_chg->ops.update_curr(di->ac_chg, iset);
623 } else if (di->usb_chg && di->usb_chg->ops.update_curr &&
624 di->chg_info.charger_type & USB_CHG) {
625 /*
626 * Select maximum of what both the charger
627 * and the battery supports
628 */
629 if (di->usb_chg->max_out_curr)
630 iset = min(iset, di->usb_chg->max_out_curr);
631
632 di->chg_info.usb_iset = iset;
633
634 return di->usb_chg->ops.update_curr(di->usb_chg, iset);
635 }
636
637 return -ENXIO;
638}
639
640/**
641 * abx500_chargalg_stop_charging() - Stop charging
642 * @di: pointer to the abx500_chargalg structure
643 *
644 * This function is called from any state where charging should be stopped.
645 * All charging is disabled and all status parameters and timers are changed
646 * accordingly
647 */
648static void abx500_chargalg_stop_charging(struct abx500_chargalg *di)
649{
650 abx500_chargalg_ac_en(di, false, 0, 0);
651 abx500_chargalg_usb_en(di, false, 0, 0);
652 abx500_chargalg_stop_safety_timer(di);
653 abx500_chargalg_stop_maintenance_timer(di);
654 di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
655 di->maintenance_chg = false;
656 cancel_delayed_work(&di->chargalg_wd_work);
657 power_supply_changed(&di->chargalg_psy);
658}
659
660/**
661 * abx500_chargalg_hold_charging() - Pauses charging
662 * @di: pointer to the abx500_chargalg structure
663 *
664 * This function is called in the case where maintenance charging has been
665 * disabled and instead a battery voltage mode is entered to check when the
666 * battery voltage has reached a certain recharge voltage
667 */
668static void abx500_chargalg_hold_charging(struct abx500_chargalg *di)
669{
670 abx500_chargalg_ac_en(di, false, 0, 0);
671 abx500_chargalg_usb_en(di, false, 0, 0);
672 abx500_chargalg_stop_safety_timer(di);
673 abx500_chargalg_stop_maintenance_timer(di);
674 di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
675 di->maintenance_chg = false;
676 cancel_delayed_work(&di->chargalg_wd_work);
677 power_supply_changed(&di->chargalg_psy);
678}
679
680/**
681 * abx500_chargalg_start_charging() - Start the charger
682 * @di: pointer to the abx500_chargalg structure
683 * @vset: requested charger output voltage
684 * @iset: requested charger output current
685 *
686 * A charger will be enabled depending on the requested charger type that was
687 * detected previously.
688 */
689static void abx500_chargalg_start_charging(struct abx500_chargalg *di,
690 int vset, int iset)
691{
Lee Jones3edebfc2013-01-17 13:40:32 +0000692 bool start_chargalg_wd = true;
693
Arun Murthy1668f812012-02-29 21:54:25 +0530694 switch (di->chg_info.charger_type) {
695 case AC_CHG:
696 dev_dbg(di->dev,
697 "AC parameters: Vset %d, Ich %d\n", vset, iset);
698 abx500_chargalg_usb_en(di, false, 0, 0);
699 abx500_chargalg_ac_en(di, true, vset, iset);
700 break;
701
702 case USB_CHG:
703 dev_dbg(di->dev,
704 "USB parameters: Vset %d, Ich %d\n", vset, iset);
705 abx500_chargalg_ac_en(di, false, 0, 0);
706 abx500_chargalg_usb_en(di, true, vset, iset);
707 break;
708
709 default:
710 dev_err(di->dev, "Unknown charger to charge from\n");
Lee Jones3edebfc2013-01-17 13:40:32 +0000711 start_chargalg_wd = false;
Arun Murthy1668f812012-02-29 21:54:25 +0530712 break;
713 }
Lee Jones3edebfc2013-01-17 13:40:32 +0000714
715 if (start_chargalg_wd && !delayed_work_pending(&di->chargalg_wd_work))
716 queue_delayed_work(di->chargalg_wq, &di->chargalg_wd_work, 0);
Arun Murthy1668f812012-02-29 21:54:25 +0530717}
718
719/**
720 * abx500_chargalg_check_temp() - Check battery temperature ranges
721 * @di: pointer to the abx500_chargalg structure
722 *
723 * The battery temperature is checked against the predefined limits and the
724 * charge state is changed accordingly
725 */
726static void abx500_chargalg_check_temp(struct abx500_chargalg *di)
727{
Lee Jonesb0284de2012-11-30 10:09:42 +0000728 if (di->batt_data.temp > (di->bm->temp_low + di->t_hyst_norm) &&
729 di->batt_data.temp < (di->bm->temp_high - di->t_hyst_norm)) {
Arun Murthy1668f812012-02-29 21:54:25 +0530730 /* Temp OK! */
731 di->events.btemp_underover = false;
732 di->events.btemp_lowhigh = false;
733 di->t_hyst_norm = 0;
734 di->t_hyst_lowhigh = 0;
735 } else {
Lee Jonesb0284de2012-11-30 10:09:42 +0000736 if (((di->batt_data.temp >= di->bm->temp_high) &&
Arun Murthy1668f812012-02-29 21:54:25 +0530737 (di->batt_data.temp <
Lee Jonesb0284de2012-11-30 10:09:42 +0000738 (di->bm->temp_over - di->t_hyst_lowhigh))) ||
Arun Murthy1668f812012-02-29 21:54:25 +0530739 ((di->batt_data.temp >
Lee Jonesb0284de2012-11-30 10:09:42 +0000740 (di->bm->temp_under + di->t_hyst_lowhigh)) &&
741 (di->batt_data.temp <= di->bm->temp_low))) {
Arun Murthy1668f812012-02-29 21:54:25 +0530742 /* TEMP minor!!!!! */
743 di->events.btemp_underover = false;
744 di->events.btemp_lowhigh = true;
Lee Jonesb0284de2012-11-30 10:09:42 +0000745 di->t_hyst_norm = di->bm->temp_hysteresis;
Arun Murthy1668f812012-02-29 21:54:25 +0530746 di->t_hyst_lowhigh = 0;
Lee Jonesb0284de2012-11-30 10:09:42 +0000747 } else if (di->batt_data.temp <= di->bm->temp_under ||
748 di->batt_data.temp >= di->bm->temp_over) {
Arun Murthy1668f812012-02-29 21:54:25 +0530749 /* TEMP major!!!!! */
750 di->events.btemp_underover = true;
751 di->events.btemp_lowhigh = false;
752 di->t_hyst_norm = 0;
Lee Jonesb0284de2012-11-30 10:09:42 +0000753 di->t_hyst_lowhigh = di->bm->temp_hysteresis;
Arun Murthy1668f812012-02-29 21:54:25 +0530754 } else {
755 /* Within hysteresis */
756 dev_dbg(di->dev, "Within hysteresis limit temp: %d "
757 "hyst_lowhigh %d, hyst normal %d\n",
758 di->batt_data.temp, di->t_hyst_lowhigh,
759 di->t_hyst_norm);
760 }
761 }
762}
763
764/**
765 * abx500_chargalg_check_charger_voltage() - Check charger voltage
766 * @di: pointer to the abx500_chargalg structure
767 *
768 * Charger voltage is checked against maximum limit
769 */
770static void abx500_chargalg_check_charger_voltage(struct abx500_chargalg *di)
771{
Lee Jonesb0284de2012-11-30 10:09:42 +0000772 if (di->chg_info.usb_volt > di->bm->chg_params->usb_volt_max)
Arun Murthy1668f812012-02-29 21:54:25 +0530773 di->chg_info.usb_chg_ok = false;
774 else
775 di->chg_info.usb_chg_ok = true;
776
Lee Jonesb0284de2012-11-30 10:09:42 +0000777 if (di->chg_info.ac_volt > di->bm->chg_params->ac_volt_max)
Arun Murthy1668f812012-02-29 21:54:25 +0530778 di->chg_info.ac_chg_ok = false;
779 else
780 di->chg_info.ac_chg_ok = true;
781
782}
783
784/**
785 * abx500_chargalg_end_of_charge() - Check if end-of-charge criteria is fulfilled
786 * @di: pointer to the abx500_chargalg structure
787 *
788 * End-of-charge criteria is fulfilled when the battery voltage is above a
789 * certain limit and the battery current is below a certain limit for a
790 * predefined number of consecutive seconds. If true, the battery is full
791 */
792static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di)
793{
794 if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
795 di->charge_state == STATE_NORMAL &&
796 !di->maintenance_chg && (di->batt_data.volt >=
Lee Jonesb0284de2012-11-30 10:09:42 +0000797 di->bm->bat_type[di->bm->batt_id].termination_vol ||
Arun Murthy1668f812012-02-29 21:54:25 +0530798 di->events.usb_cv_active || di->events.ac_cv_active) &&
799 di->batt_data.avg_curr <
Lee Jonesb0284de2012-11-30 10:09:42 +0000800 di->bm->bat_type[di->bm->batt_id].termination_curr &&
Arun Murthy1668f812012-02-29 21:54:25 +0530801 di->batt_data.avg_curr > 0) {
802 if (++di->eoc_cnt >= EOC_COND_CNT) {
803 di->eoc_cnt = 0;
Lee Jonesdb43e6c2013-02-14 12:39:15 +0000804 if ((di->chg_info.charger_type & USB_CHG) &&
805 (di->usb_chg->power_path))
806 ab8540_chargalg_usb_pp_en(di, true);
Arun Murthy1668f812012-02-29 21:54:25 +0530807 di->charge_status = POWER_SUPPLY_STATUS_FULL;
808 di->maintenance_chg = true;
809 dev_dbg(di->dev, "EOC reached!\n");
810 power_supply_changed(&di->chargalg_psy);
811 } else {
812 dev_dbg(di->dev,
813 " EOC limit reached for the %d"
814 " time, out of %d before EOC\n",
815 di->eoc_cnt,
816 EOC_COND_CNT);
817 }
818 } else {
819 di->eoc_cnt = 0;
820 }
821}
822
823static void init_maxim_chg_curr(struct abx500_chargalg *di)
824{
825 di->ccm.original_iset =
Lee Jonesb0284de2012-11-30 10:09:42 +0000826 di->bm->bat_type[di->bm->batt_id].normal_cur_lvl;
Arun Murthy1668f812012-02-29 21:54:25 +0530827 di->ccm.current_iset =
Lee Jonesb0284de2012-11-30 10:09:42 +0000828 di->bm->bat_type[di->bm->batt_id].normal_cur_lvl;
829 di->ccm.test_delta_i = di->bm->maxi->charger_curr_step;
830 di->ccm.max_current = di->bm->maxi->chg_curr;
831 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
Arun Murthy1668f812012-02-29 21:54:25 +0530832 di->ccm.level = 0;
833}
834
835/**
836 * abx500_chargalg_chg_curr_maxim - increases the charger current to
837 * compensate for the system load
838 * @di pointer to the abx500_chargalg structure
839 *
840 * This maximization function is used to raise the charger current to get the
841 * battery current as close to the optimal value as possible. The battery
842 * current during charging is affected by the system load
843 */
844static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
845{
846 int delta_i;
847
Lee Jonesb0284de2012-11-30 10:09:42 +0000848 if (!di->bm->maxi->ena_maxi)
Arun Murthy1668f812012-02-29 21:54:25 +0530849 return MAXIM_RET_NOACTION;
850
851 delta_i = di->ccm.original_iset - di->batt_data.inst_curr;
852
853 if (di->events.vbus_collapsed) {
854 dev_dbg(di->dev, "Charger voltage has collapsed %d\n",
855 di->ccm.wait_cnt);
856 if (di->ccm.wait_cnt == 0) {
857 dev_dbg(di->dev, "lowering current\n");
858 di->ccm.wait_cnt++;
Lee Jonesb0284de2012-11-30 10:09:42 +0000859 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
Arun Murthy1668f812012-02-29 21:54:25 +0530860 di->ccm.max_current =
861 di->ccm.current_iset - di->ccm.test_delta_i;
862 di->ccm.current_iset = di->ccm.max_current;
863 di->ccm.level--;
864 return MAXIM_RET_CHANGE;
865 } else {
866 dev_dbg(di->dev, "waiting\n");
867 /* Let's go in here twice before lowering curr again */
868 di->ccm.wait_cnt = (di->ccm.wait_cnt + 1) % 3;
869 return MAXIM_RET_NOACTION;
870 }
871 }
872
873 di->ccm.wait_cnt = 0;
874
875 if ((di->batt_data.inst_curr > di->ccm.original_iset)) {
876 dev_dbg(di->dev, " Maximization Ibat (%dmA) too high"
877 " (limit %dmA) (current iset: %dmA)!\n",
878 di->batt_data.inst_curr, di->ccm.original_iset,
879 di->ccm.current_iset);
880
881 if (di->ccm.current_iset == di->ccm.original_iset)
882 return MAXIM_RET_NOACTION;
883
Lee Jonesb0284de2012-11-30 10:09:42 +0000884 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
Arun Murthy1668f812012-02-29 21:54:25 +0530885 di->ccm.current_iset = di->ccm.original_iset;
886 di->ccm.level = 0;
887
888 return MAXIM_RET_IBAT_TOO_HIGH;
889 }
890
891 if (delta_i > di->ccm.test_delta_i &&
892 (di->ccm.current_iset + di->ccm.test_delta_i) <
893 di->ccm.max_current) {
894 if (di->ccm.condition_cnt-- == 0) {
895 /* Increse the iset with cco.test_delta_i */
Lee Jonesb0284de2012-11-30 10:09:42 +0000896 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
Arun Murthy1668f812012-02-29 21:54:25 +0530897 di->ccm.current_iset += di->ccm.test_delta_i;
898 di->ccm.level++;
899 dev_dbg(di->dev, " Maximization needed, increase"
900 " with %d mA to %dmA (Optimal ibat: %d)"
901 " Level %d\n",
902 di->ccm.test_delta_i,
903 di->ccm.current_iset,
904 di->ccm.original_iset,
905 di->ccm.level);
906 return MAXIM_RET_CHANGE;
907 } else {
908 return MAXIM_RET_NOACTION;
909 }
910 } else {
Lee Jonesb0284de2012-11-30 10:09:42 +0000911 di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
Arun Murthy1668f812012-02-29 21:54:25 +0530912 return MAXIM_RET_NOACTION;
913 }
914}
915
916static void handle_maxim_chg_curr(struct abx500_chargalg *di)
917{
918 enum maxim_ret ret;
919 int result;
920
921 ret = abx500_chargalg_chg_curr_maxim(di);
922 switch (ret) {
923 case MAXIM_RET_CHANGE:
924 result = abx500_chargalg_update_chg_curr(di,
925 di->ccm.current_iset);
926 if (result)
927 dev_err(di->dev, "failed to set chg curr\n");
928 break;
929 case MAXIM_RET_IBAT_TOO_HIGH:
930 result = abx500_chargalg_update_chg_curr(di,
Lee Jonesb0284de2012-11-30 10:09:42 +0000931 di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
Arun Murthy1668f812012-02-29 21:54:25 +0530932 if (result)
933 dev_err(di->dev, "failed to set chg curr\n");
934 break;
935
936 case MAXIM_RET_NOACTION:
937 default:
938 /* Do nothing..*/
939 break;
940 }
941}
942
943static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
944{
945 struct power_supply *psy;
946 struct power_supply *ext;
947 struct abx500_chargalg *di;
948 union power_supply_propval ret;
949 int i, j;
950 bool psy_found = false;
Marcus Cooperea402402013-01-11 13:12:54 +0000951 bool capacity_updated = false;
Arun Murthy1668f812012-02-29 21:54:25 +0530952
953 psy = (struct power_supply *)data;
954 ext = dev_get_drvdata(dev);
955 di = to_abx500_chargalg_device_info(psy);
956 /* For all psy where the driver name appears in any supplied_to */
957 for (i = 0; i < ext->num_supplicants; i++) {
958 if (!strcmp(ext->supplied_to[i], psy->name))
959 psy_found = true;
960 }
961 if (!psy_found)
962 return 0;
963
Marcus Cooperea402402013-01-11 13:12:54 +0000964 /*
965 * If external is not registering 'POWER_SUPPLY_PROP_CAPACITY' to its
966 * property because of handling that sysfs entry on its own, this is
967 * the place to get the battery capacity.
968 */
969 if (!ext->get_property(ext, POWER_SUPPLY_PROP_CAPACITY, &ret)) {
970 di->batt_data.percent = ret.intval;
971 capacity_updated = true;
972 }
973
Arun Murthy1668f812012-02-29 21:54:25 +0530974 /* Go through all properties for the psy */
975 for (j = 0; j < ext->num_properties; j++) {
976 enum power_supply_property prop;
977 prop = ext->properties[j];
978
979 /* Initialize chargers if not already done */
980 if (!di->ac_chg &&
981 ext->type == POWER_SUPPLY_TYPE_MAINS)
982 di->ac_chg = psy_to_ux500_charger(ext);
983 else if (!di->usb_chg &&
984 ext->type == POWER_SUPPLY_TYPE_USB)
985 di->usb_chg = psy_to_ux500_charger(ext);
986
987 if (ext->get_property(ext, prop, &ret))
988 continue;
989 switch (prop) {
990 case POWER_SUPPLY_PROP_PRESENT:
991 switch (ext->type) {
992 case POWER_SUPPLY_TYPE_BATTERY:
993 /* Battery present */
994 if (ret.intval)
995 di->events.batt_rem = false;
996 /* Battery removed */
997 else
998 di->events.batt_rem = true;
999 break;
1000 case POWER_SUPPLY_TYPE_MAINS:
1001 /* AC disconnected */
1002 if (!ret.intval &&
1003 (di->chg_info.conn_chg & AC_CHG)) {
1004 di->chg_info.prev_conn_chg =
1005 di->chg_info.conn_chg;
1006 di->chg_info.conn_chg &= ~AC_CHG;
1007 }
1008 /* AC connected */
1009 else if (ret.intval &&
1010 !(di->chg_info.conn_chg & AC_CHG)) {
1011 di->chg_info.prev_conn_chg =
1012 di->chg_info.conn_chg;
1013 di->chg_info.conn_chg |= AC_CHG;
1014 }
1015 break;
1016 case POWER_SUPPLY_TYPE_USB:
1017 /* USB disconnected */
1018 if (!ret.intval &&
1019 (di->chg_info.conn_chg & USB_CHG)) {
1020 di->chg_info.prev_conn_chg =
1021 di->chg_info.conn_chg;
1022 di->chg_info.conn_chg &= ~USB_CHG;
1023 }
1024 /* USB connected */
1025 else if (ret.intval &&
1026 !(di->chg_info.conn_chg & USB_CHG)) {
1027 di->chg_info.prev_conn_chg =
1028 di->chg_info.conn_chg;
1029 di->chg_info.conn_chg |= USB_CHG;
1030 }
1031 break;
1032 default:
1033 break;
1034 }
1035 break;
1036
1037 case POWER_SUPPLY_PROP_ONLINE:
1038 switch (ext->type) {
1039 case POWER_SUPPLY_TYPE_BATTERY:
1040 break;
1041 case POWER_SUPPLY_TYPE_MAINS:
1042 /* AC offline */
1043 if (!ret.intval &&
1044 (di->chg_info.online_chg & AC_CHG)) {
1045 di->chg_info.prev_online_chg =
1046 di->chg_info.online_chg;
1047 di->chg_info.online_chg &= ~AC_CHG;
1048 }
1049 /* AC online */
1050 else if (ret.intval &&
1051 !(di->chg_info.online_chg & AC_CHG)) {
1052 di->chg_info.prev_online_chg =
1053 di->chg_info.online_chg;
1054 di->chg_info.online_chg |= AC_CHG;
1055 queue_delayed_work(di->chargalg_wq,
1056 &di->chargalg_wd_work, 0);
1057 }
1058 break;
1059 case POWER_SUPPLY_TYPE_USB:
1060 /* USB offline */
1061 if (!ret.intval &&
1062 (di->chg_info.online_chg & USB_CHG)) {
1063 di->chg_info.prev_online_chg =
1064 di->chg_info.online_chg;
1065 di->chg_info.online_chg &= ~USB_CHG;
1066 }
1067 /* USB online */
1068 else if (ret.intval &&
1069 !(di->chg_info.online_chg & USB_CHG)) {
1070 di->chg_info.prev_online_chg =
1071 di->chg_info.online_chg;
1072 di->chg_info.online_chg |= USB_CHG;
1073 queue_delayed_work(di->chargalg_wq,
1074 &di->chargalg_wd_work, 0);
1075 }
1076 break;
1077 default:
1078 break;
1079 }
1080 break;
1081
1082 case POWER_SUPPLY_PROP_HEALTH:
1083 switch (ext->type) {
1084 case POWER_SUPPLY_TYPE_BATTERY:
1085 break;
1086 case POWER_SUPPLY_TYPE_MAINS:
1087 switch (ret.intval) {
1088 case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE:
1089 di->events.mainextchnotok = true;
1090 di->events.main_thermal_prot = false;
1091 di->events.main_ovv = false;
1092 di->events.ac_wd_expired = false;
1093 break;
1094 case POWER_SUPPLY_HEALTH_DEAD:
1095 di->events.ac_wd_expired = true;
1096 di->events.mainextchnotok = false;
1097 di->events.main_ovv = false;
1098 di->events.main_thermal_prot = false;
1099 break;
1100 case POWER_SUPPLY_HEALTH_COLD:
1101 case POWER_SUPPLY_HEALTH_OVERHEAT:
1102 di->events.main_thermal_prot = true;
1103 di->events.mainextchnotok = false;
1104 di->events.main_ovv = false;
1105 di->events.ac_wd_expired = false;
1106 break;
1107 case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
1108 di->events.main_ovv = true;
1109 di->events.mainextchnotok = false;
1110 di->events.main_thermal_prot = false;
1111 di->events.ac_wd_expired = false;
1112 break;
1113 case POWER_SUPPLY_HEALTH_GOOD:
1114 di->events.main_thermal_prot = false;
1115 di->events.mainextchnotok = false;
1116 di->events.main_ovv = false;
1117 di->events.ac_wd_expired = false;
1118 break;
1119 default:
1120 break;
1121 }
1122 break;
1123
1124 case POWER_SUPPLY_TYPE_USB:
1125 switch (ret.intval) {
1126 case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE:
1127 di->events.usbchargernotok = true;
1128 di->events.usb_thermal_prot = false;
1129 di->events.vbus_ovv = false;
1130 di->events.usb_wd_expired = false;
1131 break;
1132 case POWER_SUPPLY_HEALTH_DEAD:
1133 di->events.usb_wd_expired = true;
1134 di->events.usbchargernotok = false;
1135 di->events.usb_thermal_prot = false;
1136 di->events.vbus_ovv = false;
1137 break;
1138 case POWER_SUPPLY_HEALTH_COLD:
1139 case POWER_SUPPLY_HEALTH_OVERHEAT:
1140 di->events.usb_thermal_prot = true;
1141 di->events.usbchargernotok = false;
1142 di->events.vbus_ovv = false;
1143 di->events.usb_wd_expired = false;
1144 break;
1145 case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
1146 di->events.vbus_ovv = true;
1147 di->events.usbchargernotok = false;
1148 di->events.usb_thermal_prot = false;
1149 di->events.usb_wd_expired = false;
1150 break;
1151 case POWER_SUPPLY_HEALTH_GOOD:
1152 di->events.usbchargernotok = false;
1153 di->events.usb_thermal_prot = false;
1154 di->events.vbus_ovv = false;
1155 di->events.usb_wd_expired = false;
1156 break;
1157 default:
1158 break;
1159 }
1160 default:
1161 break;
1162 }
1163 break;
1164
1165 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
1166 switch (ext->type) {
1167 case POWER_SUPPLY_TYPE_BATTERY:
1168 di->batt_data.volt = ret.intval / 1000;
1169 break;
1170 case POWER_SUPPLY_TYPE_MAINS:
1171 di->chg_info.ac_volt = ret.intval / 1000;
1172 break;
1173 case POWER_SUPPLY_TYPE_USB:
1174 di->chg_info.usb_volt = ret.intval / 1000;
1175 break;
1176 default:
1177 break;
1178 }
1179 break;
1180
1181 case POWER_SUPPLY_PROP_VOLTAGE_AVG:
1182 switch (ext->type) {
1183 case POWER_SUPPLY_TYPE_MAINS:
1184 /* AVG is used to indicate when we are
1185 * in CV mode */
1186 if (ret.intval)
1187 di->events.ac_cv_active = true;
1188 else
1189 di->events.ac_cv_active = false;
1190
1191 break;
1192 case POWER_SUPPLY_TYPE_USB:
1193 /* AVG is used to indicate when we are
1194 * in CV mode */
1195 if (ret.intval)
1196 di->events.usb_cv_active = true;
1197 else
1198 di->events.usb_cv_active = false;
1199
1200 break;
1201 default:
1202 break;
1203 }
1204 break;
1205
1206 case POWER_SUPPLY_PROP_TECHNOLOGY:
1207 switch (ext->type) {
1208 case POWER_SUPPLY_TYPE_BATTERY:
1209 if (ret.intval)
1210 di->events.batt_unknown = false;
1211 else
1212 di->events.batt_unknown = true;
1213
1214 break;
1215 default:
1216 break;
1217 }
1218 break;
1219
1220 case POWER_SUPPLY_PROP_TEMP:
1221 di->batt_data.temp = ret.intval / 10;
1222 break;
1223
1224 case POWER_SUPPLY_PROP_CURRENT_NOW:
1225 switch (ext->type) {
1226 case POWER_SUPPLY_TYPE_MAINS:
1227 di->chg_info.ac_curr =
1228 ret.intval / 1000;
1229 break;
1230 case POWER_SUPPLY_TYPE_USB:
1231 di->chg_info.usb_curr =
1232 ret.intval / 1000;
1233 break;
1234 case POWER_SUPPLY_TYPE_BATTERY:
1235 di->batt_data.inst_curr = ret.intval / 1000;
1236 break;
1237 default:
1238 break;
1239 }
1240 break;
1241
1242 case POWER_SUPPLY_PROP_CURRENT_AVG:
1243 switch (ext->type) {
1244 case POWER_SUPPLY_TYPE_BATTERY:
1245 di->batt_data.avg_curr = ret.intval / 1000;
1246 break;
1247 case POWER_SUPPLY_TYPE_USB:
1248 if (ret.intval)
1249 di->events.vbus_collapsed = true;
1250 else
1251 di->events.vbus_collapsed = false;
1252 break;
1253 default:
1254 break;
1255 }
1256 break;
1257 case POWER_SUPPLY_PROP_CAPACITY:
Marcus Cooperea402402013-01-11 13:12:54 +00001258 if (!capacity_updated)
1259 di->batt_data.percent = ret.intval;
Arun Murthy1668f812012-02-29 21:54:25 +05301260 break;
1261 default:
1262 break;
1263 }
1264 }
1265 return 0;
1266}
1267
1268/**
1269 * abx500_chargalg_external_power_changed() - callback for power supply changes
1270 * @psy: pointer to the structure power_supply
1271 *
1272 * This function is the entry point of the pointer external_power_changed
1273 * of the structure power_supply.
1274 * This function gets executed when there is a change in any external power
1275 * supply that this driver needs to be notified of.
1276 */
1277static void abx500_chargalg_external_power_changed(struct power_supply *psy)
1278{
1279 struct abx500_chargalg *di = to_abx500_chargalg_device_info(psy);
1280
1281 /*
1282 * Trigger execution of the algorithm instantly and read
1283 * all power_supply properties there instead
1284 */
1285 queue_work(di->chargalg_wq, &di->chargalg_work);
1286}
1287
1288/**
1289 * abx500_chargalg_algorithm() - Main function for the algorithm
1290 * @di: pointer to the abx500_chargalg structure
1291 *
1292 * This is the main control function for the charging algorithm.
1293 * It is called periodically or when something happens that will
1294 * trigger a state change
1295 */
1296static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
1297{
1298 int charger_status;
Lee Jones4dcdf572013-02-14 09:24:10 +00001299 int ret;
Arun Murthy1668f812012-02-29 21:54:25 +05301300
1301 /* Collect data from all power_supply class devices */
1302 class_for_each_device(power_supply_class, NULL,
1303 &di->chargalg_psy, abx500_chargalg_get_ext_psy_data);
1304
1305 abx500_chargalg_end_of_charge(di);
1306 abx500_chargalg_check_temp(di);
1307 abx500_chargalg_check_charger_voltage(di);
1308
1309 charger_status = abx500_chargalg_check_charger_connection(di);
Lee Jones4dcdf572013-02-14 09:24:10 +00001310
1311 if (is_ab8500(di->parent)) {
1312 ret = abx500_chargalg_check_charger_enable(di);
1313 if (ret < 0)
1314 dev_err(di->dev, "Checking charger is enabled error"
1315 ": Returned Value %d\n", ret);
1316 }
1317
Arun Murthy1668f812012-02-29 21:54:25 +05301318 /*
1319 * First check if we have a charger connected.
1320 * Also we don't allow charging of unknown batteries if configured
1321 * this way
1322 */
1323 if (!charger_status ||
Lee Jonesb0284de2012-11-30 10:09:42 +00001324 (di->events.batt_unknown && !di->bm->chg_unknown_bat)) {
Arun Murthy1668f812012-02-29 21:54:25 +05301325 if (di->charge_state != STATE_HANDHELD) {
1326 di->events.safety_timer_expired = false;
1327 abx500_chargalg_state_to(di, STATE_HANDHELD_INIT);
1328 }
1329 }
1330
1331 /* If suspended, we should not continue checking the flags */
1332 else if (di->charge_state == STATE_SUSPENDED_INIT ||
1333 di->charge_state == STATE_SUSPENDED) {
1334 /* We don't do anything here, just don,t continue */
1335 }
1336
1337 /* Safety timer expiration */
1338 else if (di->events.safety_timer_expired) {
1339 if (di->charge_state != STATE_SAFETY_TIMER_EXPIRED)
1340 abx500_chargalg_state_to(di,
1341 STATE_SAFETY_TIMER_EXPIRED_INIT);
1342 }
1343 /*
1344 * Check if any interrupts has occured
1345 * that will prevent us from charging
1346 */
1347
1348 /* Battery removed */
1349 else if (di->events.batt_rem) {
1350 if (di->charge_state != STATE_BATT_REMOVED)
1351 abx500_chargalg_state_to(di, STATE_BATT_REMOVED_INIT);
1352 }
1353 /* Main or USB charger not ok. */
1354 else if (di->events.mainextchnotok || di->events.usbchargernotok) {
1355 /*
1356 * If vbus_collapsed is set, we have to lower the charger
1357 * current, which is done in the normal state below
1358 */
1359 if (di->charge_state != STATE_CHG_NOT_OK &&
1360 !di->events.vbus_collapsed)
1361 abx500_chargalg_state_to(di, STATE_CHG_NOT_OK_INIT);
1362 }
1363 /* VBUS, Main or VBAT OVV. */
1364 else if (di->events.vbus_ovv ||
1365 di->events.main_ovv ||
1366 di->events.batt_ovv ||
1367 !di->chg_info.usb_chg_ok ||
1368 !di->chg_info.ac_chg_ok) {
1369 if (di->charge_state != STATE_OVV_PROTECT)
1370 abx500_chargalg_state_to(di, STATE_OVV_PROTECT_INIT);
1371 }
1372 /* USB Thermal, stop charging */
1373 else if (di->events.main_thermal_prot ||
1374 di->events.usb_thermal_prot) {
1375 if (di->charge_state != STATE_HW_TEMP_PROTECT)
1376 abx500_chargalg_state_to(di,
1377 STATE_HW_TEMP_PROTECT_INIT);
1378 }
1379 /* Battery temp over/under */
1380 else if (di->events.btemp_underover) {
1381 if (di->charge_state != STATE_TEMP_UNDEROVER)
1382 abx500_chargalg_state_to(di,
1383 STATE_TEMP_UNDEROVER_INIT);
1384 }
1385 /* Watchdog expired */
1386 else if (di->events.ac_wd_expired ||
1387 di->events.usb_wd_expired) {
1388 if (di->charge_state != STATE_WD_EXPIRED)
1389 abx500_chargalg_state_to(di, STATE_WD_EXPIRED_INIT);
1390 }
1391 /* Battery temp high/low */
1392 else if (di->events.btemp_lowhigh) {
1393 if (di->charge_state != STATE_TEMP_LOWHIGH)
1394 abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH_INIT);
1395 }
1396
1397 dev_dbg(di->dev,
1398 "[CHARGALG] Vb %d Ib_avg %d Ib_inst %d Tb %d Cap %d Maint %d "
1399 "State %s Active_chg %d Chg_status %d AC %d USB %d "
1400 "AC_online %d USB_online %d AC_CV %d USB_CV %d AC_I %d "
1401 "USB_I %d AC_Vset %d AC_Iset %d USB_Vset %d USB_Iset %d\n",
1402 di->batt_data.volt,
1403 di->batt_data.avg_curr,
1404 di->batt_data.inst_curr,
1405 di->batt_data.temp,
1406 di->batt_data.percent,
1407 di->maintenance_chg,
1408 states[di->charge_state],
1409 di->chg_info.charger_type,
1410 di->charge_status,
1411 di->chg_info.conn_chg & AC_CHG,
1412 di->chg_info.conn_chg & USB_CHG,
1413 di->chg_info.online_chg & AC_CHG,
1414 di->chg_info.online_chg & USB_CHG,
1415 di->events.ac_cv_active,
1416 di->events.usb_cv_active,
1417 di->chg_info.ac_curr,
1418 di->chg_info.usb_curr,
1419 di->chg_info.ac_vset,
1420 di->chg_info.ac_iset,
1421 di->chg_info.usb_vset,
1422 di->chg_info.usb_iset);
1423
1424 switch (di->charge_state) {
1425 case STATE_HANDHELD_INIT:
1426 abx500_chargalg_stop_charging(di);
1427 di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
1428 abx500_chargalg_state_to(di, STATE_HANDHELD);
1429 /* Intentional fallthrough */
1430
1431 case STATE_HANDHELD:
1432 break;
1433
1434 case STATE_SUSPENDED_INIT:
1435 if (di->susp_status.ac_suspended)
1436 abx500_chargalg_ac_en(di, false, 0, 0);
1437 if (di->susp_status.usb_suspended)
1438 abx500_chargalg_usb_en(di, false, 0, 0);
1439 abx500_chargalg_stop_safety_timer(di);
1440 abx500_chargalg_stop_maintenance_timer(di);
1441 di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
1442 di->maintenance_chg = false;
1443 abx500_chargalg_state_to(di, STATE_SUSPENDED);
1444 power_supply_changed(&di->chargalg_psy);
1445 /* Intentional fallthrough */
1446
1447 case STATE_SUSPENDED:
1448 /* CHARGING is suspended */
1449 break;
1450
1451 case STATE_BATT_REMOVED_INIT:
1452 abx500_chargalg_stop_charging(di);
1453 abx500_chargalg_state_to(di, STATE_BATT_REMOVED);
1454 /* Intentional fallthrough */
1455
1456 case STATE_BATT_REMOVED:
1457 if (!di->events.batt_rem)
1458 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
1459 break;
1460
1461 case STATE_HW_TEMP_PROTECT_INIT:
1462 abx500_chargalg_stop_charging(di);
1463 abx500_chargalg_state_to(di, STATE_HW_TEMP_PROTECT);
1464 /* Intentional fallthrough */
1465
1466 case STATE_HW_TEMP_PROTECT:
1467 if (!di->events.main_thermal_prot &&
1468 !di->events.usb_thermal_prot)
1469 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
1470 break;
1471
1472 case STATE_OVV_PROTECT_INIT:
1473 abx500_chargalg_stop_charging(di);
1474 abx500_chargalg_state_to(di, STATE_OVV_PROTECT);
1475 /* Intentional fallthrough */
1476
1477 case STATE_OVV_PROTECT:
1478 if (!di->events.vbus_ovv &&
1479 !di->events.main_ovv &&
1480 !di->events.batt_ovv &&
1481 di->chg_info.usb_chg_ok &&
1482 di->chg_info.ac_chg_ok)
1483 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
1484 break;
1485
1486 case STATE_CHG_NOT_OK_INIT:
1487 abx500_chargalg_stop_charging(di);
1488 abx500_chargalg_state_to(di, STATE_CHG_NOT_OK);
1489 /* Intentional fallthrough */
1490
1491 case STATE_CHG_NOT_OK:
1492 if (!di->events.mainextchnotok &&
1493 !di->events.usbchargernotok)
1494 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
1495 break;
1496
1497 case STATE_SAFETY_TIMER_EXPIRED_INIT:
1498 abx500_chargalg_stop_charging(di);
1499 abx500_chargalg_state_to(di, STATE_SAFETY_TIMER_EXPIRED);
1500 /* Intentional fallthrough */
1501
1502 case STATE_SAFETY_TIMER_EXPIRED:
1503 /* We exit this state when charger is removed */
1504 break;
1505
1506 case STATE_NORMAL_INIT:
Lee Jonesdb43e6c2013-02-14 12:39:15 +00001507 if ((di->chg_info.charger_type & USB_CHG) &&
1508 di->usb_chg->power_path) {
1509 if (di->batt_data.volt >
1510 (di->bm->fg_params->lowbat_threshold +
1511 BAT_PLUS_MARGIN)) {
1512 ab8540_chargalg_usb_pre_chg_en(di, false);
1513 ab8540_chargalg_usb_pp_en(di, false);
1514 } else {
1515 ab8540_chargalg_usb_pp_en(di, true);
1516 ab8540_chargalg_usb_pre_chg_en(di, true);
1517 abx500_chargalg_state_to(di,
1518 STATE_USB_PP_PRE_CHARGE);
1519 break;
1520 }
1521 }
1522
Arun Murthy1668f812012-02-29 21:54:25 +05301523 abx500_chargalg_start_charging(di,
Lee Jonesb0284de2012-11-30 10:09:42 +00001524 di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
1525 di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
Arun Murthy1668f812012-02-29 21:54:25 +05301526 abx500_chargalg_state_to(di, STATE_NORMAL);
1527 abx500_chargalg_start_safety_timer(di);
1528 abx500_chargalg_stop_maintenance_timer(di);
1529 init_maxim_chg_curr(di);
1530 di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
1531 di->eoc_cnt = 0;
1532 di->maintenance_chg = false;
1533 power_supply_changed(&di->chargalg_psy);
1534
1535 break;
1536
Lee Jonesdb43e6c2013-02-14 12:39:15 +00001537 case STATE_USB_PP_PRE_CHARGE:
1538 if (di->batt_data.volt >
1539 (di->bm->fg_params->lowbat_threshold +
1540 BAT_PLUS_MARGIN))
1541 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
1542 break;
1543
Arun Murthy1668f812012-02-29 21:54:25 +05301544 case STATE_NORMAL:
1545 handle_maxim_chg_curr(di);
1546 if (di->charge_status == POWER_SUPPLY_STATUS_FULL &&
1547 di->maintenance_chg) {
Lee Jonesb0284de2012-11-30 10:09:42 +00001548 if (di->bm->no_maintenance)
Arun Murthy1668f812012-02-29 21:54:25 +05301549 abx500_chargalg_state_to(di,
1550 STATE_WAIT_FOR_RECHARGE_INIT);
1551 else
1552 abx500_chargalg_state_to(di,
1553 STATE_MAINTENANCE_A_INIT);
1554 }
1555 break;
1556
1557 /* This state will be used when the maintenance state is disabled */
1558 case STATE_WAIT_FOR_RECHARGE_INIT:
1559 abx500_chargalg_hold_charging(di);
1560 abx500_chargalg_state_to(di, STATE_WAIT_FOR_RECHARGE);
Arun Murthy1668f812012-02-29 21:54:25 +05301561 /* Intentional fallthrough */
1562
1563 case STATE_WAIT_FOR_RECHARGE:
Marcus Cooperea402402013-01-11 13:12:54 +00001564 if (di->batt_data.percent <=
1565 di->bm->bat_type[di->bm->batt_id].
1566 recharge_cap)
1567 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
Arun Murthy1668f812012-02-29 21:54:25 +05301568 break;
1569
1570 case STATE_MAINTENANCE_A_INIT:
1571 abx500_chargalg_stop_safety_timer(di);
1572 abx500_chargalg_start_maintenance_timer(di,
Lee Jonesb0284de2012-11-30 10:09:42 +00001573 di->bm->bat_type[
1574 di->bm->batt_id].maint_a_chg_timer_h);
Arun Murthy1668f812012-02-29 21:54:25 +05301575 abx500_chargalg_start_charging(di,
Lee Jonesb0284de2012-11-30 10:09:42 +00001576 di->bm->bat_type[
1577 di->bm->batt_id].maint_a_vol_lvl,
1578 di->bm->bat_type[
1579 di->bm->batt_id].maint_a_cur_lvl);
Arun Murthy1668f812012-02-29 21:54:25 +05301580 abx500_chargalg_state_to(di, STATE_MAINTENANCE_A);
1581 power_supply_changed(&di->chargalg_psy);
1582 /* Intentional fallthrough*/
1583
1584 case STATE_MAINTENANCE_A:
1585 if (di->events.maintenance_timer_expired) {
1586 abx500_chargalg_stop_maintenance_timer(di);
1587 abx500_chargalg_state_to(di, STATE_MAINTENANCE_B_INIT);
1588 }
1589 break;
1590
1591 case STATE_MAINTENANCE_B_INIT:
1592 abx500_chargalg_start_maintenance_timer(di,
Lee Jonesb0284de2012-11-30 10:09:42 +00001593 di->bm->bat_type[
1594 di->bm->batt_id].maint_b_chg_timer_h);
Arun Murthy1668f812012-02-29 21:54:25 +05301595 abx500_chargalg_start_charging(di,
Lee Jonesb0284de2012-11-30 10:09:42 +00001596 di->bm->bat_type[
1597 di->bm->batt_id].maint_b_vol_lvl,
1598 di->bm->bat_type[
1599 di->bm->batt_id].maint_b_cur_lvl);
Arun Murthy1668f812012-02-29 21:54:25 +05301600 abx500_chargalg_state_to(di, STATE_MAINTENANCE_B);
1601 power_supply_changed(&di->chargalg_psy);
1602 /* Intentional fallthrough*/
1603
1604 case STATE_MAINTENANCE_B:
1605 if (di->events.maintenance_timer_expired) {
1606 abx500_chargalg_stop_maintenance_timer(di);
1607 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
1608 }
1609 break;
1610
1611 case STATE_TEMP_LOWHIGH_INIT:
1612 abx500_chargalg_start_charging(di,
Lee Jonesb0284de2012-11-30 10:09:42 +00001613 di->bm->bat_type[
1614 di->bm->batt_id].low_high_vol_lvl,
1615 di->bm->bat_type[
1616 di->bm->batt_id].low_high_cur_lvl);
Arun Murthy1668f812012-02-29 21:54:25 +05301617 abx500_chargalg_stop_maintenance_timer(di);
1618 di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
1619 abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH);
1620 power_supply_changed(&di->chargalg_psy);
1621 /* Intentional fallthrough */
1622
1623 case STATE_TEMP_LOWHIGH:
1624 if (!di->events.btemp_lowhigh)
1625 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
1626 break;
1627
1628 case STATE_WD_EXPIRED_INIT:
1629 abx500_chargalg_stop_charging(di);
1630 abx500_chargalg_state_to(di, STATE_WD_EXPIRED);
1631 /* Intentional fallthrough */
1632
1633 case STATE_WD_EXPIRED:
1634 if (!di->events.ac_wd_expired &&
1635 !di->events.usb_wd_expired)
1636 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
1637 break;
1638
1639 case STATE_TEMP_UNDEROVER_INIT:
1640 abx500_chargalg_stop_charging(di);
1641 abx500_chargalg_state_to(di, STATE_TEMP_UNDEROVER);
1642 /* Intentional fallthrough */
1643
1644 case STATE_TEMP_UNDEROVER:
1645 if (!di->events.btemp_underover)
1646 abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
1647 break;
1648 }
1649
1650 /* Start charging directly if the new state is a charge state */
1651 if (di->charge_state == STATE_NORMAL_INIT ||
1652 di->charge_state == STATE_MAINTENANCE_A_INIT ||
1653 di->charge_state == STATE_MAINTENANCE_B_INIT)
1654 queue_work(di->chargalg_wq, &di->chargalg_work);
1655}
1656
1657/**
1658 * abx500_chargalg_periodic_work() - Periodic work for the algorithm
1659 * @work: pointer to the work_struct structure
1660 *
1661 * Work queue function for the charging algorithm
1662 */
1663static void abx500_chargalg_periodic_work(struct work_struct *work)
1664{
1665 struct abx500_chargalg *di = container_of(work,
1666 struct abx500_chargalg, chargalg_periodic_work.work);
1667
1668 abx500_chargalg_algorithm(di);
1669
1670 /*
1671 * If a charger is connected then the battery has to be monitored
1672 * frequently, else the work can be delayed.
1673 */
1674 if (di->chg_info.conn_chg)
1675 queue_delayed_work(di->chargalg_wq,
1676 &di->chargalg_periodic_work,
Lee Jonesb0284de2012-11-30 10:09:42 +00001677 di->bm->interval_charging * HZ);
Arun Murthy1668f812012-02-29 21:54:25 +05301678 else
1679 queue_delayed_work(di->chargalg_wq,
1680 &di->chargalg_periodic_work,
Lee Jonesb0284de2012-11-30 10:09:42 +00001681 di->bm->interval_not_charging * HZ);
Arun Murthy1668f812012-02-29 21:54:25 +05301682}
1683
1684/**
1685 * abx500_chargalg_wd_work() - periodic work to kick the charger watchdog
1686 * @work: pointer to the work_struct structure
1687 *
1688 * Work queue function for kicking the charger watchdog
1689 */
1690static void abx500_chargalg_wd_work(struct work_struct *work)
1691{
1692 int ret;
1693 struct abx500_chargalg *di = container_of(work,
1694 struct abx500_chargalg, chargalg_wd_work.work);
1695
1696 dev_dbg(di->dev, "abx500_chargalg_wd_work\n");
1697
1698 ret = abx500_chargalg_kick_watchdog(di);
1699 if (ret < 0)
1700 dev_err(di->dev, "failed to kick watchdog\n");
1701
1702 queue_delayed_work(di->chargalg_wq,
1703 &di->chargalg_wd_work, CHG_WD_INTERVAL);
1704}
1705
1706/**
1707 * abx500_chargalg_work() - Work to run the charging algorithm instantly
1708 * @work: pointer to the work_struct structure
1709 *
1710 * Work queue function for calling the charging algorithm
1711 */
1712static void abx500_chargalg_work(struct work_struct *work)
1713{
1714 struct abx500_chargalg *di = container_of(work,
1715 struct abx500_chargalg, chargalg_work);
1716
1717 abx500_chargalg_algorithm(di);
1718}
1719
1720/**
1721 * abx500_chargalg_get_property() - get the chargalg properties
1722 * @psy: pointer to the power_supply structure
1723 * @psp: pointer to the power_supply_property structure
1724 * @val: pointer to the power_supply_propval union
1725 *
1726 * This function gets called when an application tries to get the
1727 * chargalg properties by reading the sysfs files.
1728 * status: charging/discharging/full/unknown
1729 * health: health of the battery
1730 * Returns error code in case of failure else 0 on success
1731 */
1732static int abx500_chargalg_get_property(struct power_supply *psy,
1733 enum power_supply_property psp,
1734 union power_supply_propval *val)
1735{
1736 struct abx500_chargalg *di;
1737
1738 di = to_abx500_chargalg_device_info(psy);
1739
1740 switch (psp) {
1741 case POWER_SUPPLY_PROP_STATUS:
1742 val->intval = di->charge_status;
1743 break;
1744 case POWER_SUPPLY_PROP_HEALTH:
1745 if (di->events.batt_ovv) {
1746 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1747 } else if (di->events.btemp_underover) {
Lee Jonesb0284de2012-11-30 10:09:42 +00001748 if (di->batt_data.temp <= di->bm->temp_under)
Arun Murthy1668f812012-02-29 21:54:25 +05301749 val->intval = POWER_SUPPLY_HEALTH_COLD;
1750 else
1751 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
Lee Jonesd80108f2013-01-17 13:49:45 +00001752 } else if (di->charge_state == STATE_SAFETY_TIMER_EXPIRED ||
1753 di->charge_state == STATE_SAFETY_TIMER_EXPIRED_INIT) {
1754 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
Arun Murthy1668f812012-02-29 21:54:25 +05301755 } else {
1756 val->intval = POWER_SUPPLY_HEALTH_GOOD;
1757 }
1758 break;
1759 default:
1760 return -EINVAL;
1761 }
1762 return 0;
1763}
1764
1765/* Exposure to the sysfs interface */
1766
1767/**
Lee Jonesc9ade0f2013-01-21 11:22:56 +00001768 * abx500_chargalg_sysfs_show() - sysfs show operations
1769 * @kobj: pointer to the struct kobject
1770 * @attr: pointer to the struct attribute
1771 * @buf: buffer that holds the parameter to send to userspace
1772 *
1773 * Returns a buffer to be displayed in user space
1774 */
1775static ssize_t abx500_chargalg_sysfs_show(struct kobject *kobj,
1776 struct attribute *attr, char *buf)
1777{
1778 struct abx500_chargalg *di = container_of(kobj,
1779 struct abx500_chargalg, chargalg_kobject);
1780
1781 return sprintf(buf, "%d\n",
1782 di->susp_status.ac_suspended &&
1783 di->susp_status.usb_suspended);
1784}
1785
1786/**
Arun Murthy1668f812012-02-29 21:54:25 +05301787 * abx500_chargalg_sysfs_charger() - sysfs store operations
1788 * @kobj: pointer to the struct kobject
1789 * @attr: pointer to the struct attribute
1790 * @buf: buffer that holds the parameter passed from userspace
1791 * @length: length of the parameter passed
1792 *
1793 * Returns length of the buffer(input taken from user space) on success
1794 * else error code on failure
1795 * The operation to be performed on passing the parameters from the user space.
1796 */
1797static ssize_t abx500_chargalg_sysfs_charger(struct kobject *kobj,
1798 struct attribute *attr, const char *buf, size_t length)
1799{
1800 struct abx500_chargalg *di = container_of(kobj,
1801 struct abx500_chargalg, chargalg_kobject);
1802 long int param;
1803 int ac_usb;
1804 int ret;
1805 char entry = *attr->name;
1806
1807 switch (entry) {
1808 case 'c':
1809 ret = strict_strtol(buf, 10, &param);
1810 if (ret < 0)
1811 return ret;
1812
1813 ac_usb = param;
1814 switch (ac_usb) {
1815 case 0:
1816 /* Disable charging */
1817 di->susp_status.ac_suspended = true;
1818 di->susp_status.usb_suspended = true;
1819 di->susp_status.suspended_change = true;
1820 /* Trigger a state change */
1821 queue_work(di->chargalg_wq,
1822 &di->chargalg_work);
1823 break;
1824 case 1:
1825 /* Enable AC Charging */
1826 di->susp_status.ac_suspended = false;
1827 di->susp_status.suspended_change = true;
1828 /* Trigger a state change */
1829 queue_work(di->chargalg_wq,
1830 &di->chargalg_work);
1831 break;
1832 case 2:
1833 /* Enable USB charging */
1834 di->susp_status.usb_suspended = false;
1835 di->susp_status.suspended_change = true;
1836 /* Trigger a state change */
1837 queue_work(di->chargalg_wq,
1838 &di->chargalg_work);
1839 break;
1840 default:
1841 dev_info(di->dev, "Wrong input\n"
1842 "Enter 0. Disable AC/USB Charging\n"
1843 "1. Enable AC charging\n"
1844 "2. Enable USB Charging\n");
1845 };
1846 break;
1847 };
1848 return strlen(buf);
1849}
1850
1851static struct attribute abx500_chargalg_en_charger = \
1852{
1853 .name = "chargalg",
Lee Jonesc9ade0f2013-01-21 11:22:56 +00001854 .mode = S_IRUGO | S_IWUSR,
Arun Murthy1668f812012-02-29 21:54:25 +05301855};
1856
1857static struct attribute *abx500_chargalg_chg[] = {
1858 &abx500_chargalg_en_charger,
1859 NULL
1860};
1861
Anton Vorontsov64eb9b02012-03-14 04:43:11 +04001862static const struct sysfs_ops abx500_chargalg_sysfs_ops = {
Lee Jonesc9ade0f2013-01-21 11:22:56 +00001863 .show = abx500_chargalg_sysfs_show,
Arun Murthy1668f812012-02-29 21:54:25 +05301864 .store = abx500_chargalg_sysfs_charger,
1865};
1866
1867static struct kobj_type abx500_chargalg_ktype = {
1868 .sysfs_ops = &abx500_chargalg_sysfs_ops,
1869 .default_attrs = abx500_chargalg_chg,
1870};
1871
1872/**
1873 * abx500_chargalg_sysfs_exit() - de-init of sysfs entry
1874 * @di: pointer to the struct abx500_chargalg
1875 *
1876 * This function removes the entry in sysfs.
1877 */
1878static void abx500_chargalg_sysfs_exit(struct abx500_chargalg *di)
1879{
1880 kobject_del(&di->chargalg_kobject);
1881}
1882
1883/**
1884 * abx500_chargalg_sysfs_init() - init of sysfs entry
1885 * @di: pointer to the struct abx500_chargalg
1886 *
1887 * This function adds an entry in sysfs.
1888 * Returns error code in case of failure else 0(on success)
1889 */
1890static int abx500_chargalg_sysfs_init(struct abx500_chargalg *di)
1891{
1892 int ret = 0;
1893
1894 ret = kobject_init_and_add(&di->chargalg_kobject,
1895 &abx500_chargalg_ktype,
1896 NULL, "abx500_chargalg");
1897 if (ret < 0)
1898 dev_err(di->dev, "failed to create sysfs entry\n");
1899
1900 return ret;
1901}
1902/* Exposure to the sysfs interface <<END>> */
1903
1904#if defined(CONFIG_PM)
1905static int abx500_chargalg_resume(struct platform_device *pdev)
1906{
1907 struct abx500_chargalg *di = platform_get_drvdata(pdev);
1908
1909 /* Kick charger watchdog if charging (any charger online) */
1910 if (di->chg_info.online_chg)
1911 queue_delayed_work(di->chargalg_wq, &di->chargalg_wd_work, 0);
1912
1913 /*
1914 * Run the charging algorithm directly to be sure we don't
1915 * do it too seldom
1916 */
1917 queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0);
1918
1919 return 0;
1920}
1921
1922static int abx500_chargalg_suspend(struct platform_device *pdev,
1923 pm_message_t state)
1924{
1925 struct abx500_chargalg *di = platform_get_drvdata(pdev);
1926
1927 if (di->chg_info.online_chg)
1928 cancel_delayed_work_sync(&di->chargalg_wd_work);
1929
1930 cancel_delayed_work_sync(&di->chargalg_periodic_work);
1931
1932 return 0;
1933}
1934#else
1935#define abx500_chargalg_suspend NULL
1936#define abx500_chargalg_resume NULL
1937#endif
1938
Bill Pemberton415ec692012-11-19 13:26:07 -05001939static int abx500_chargalg_remove(struct platform_device *pdev)
Arun Murthy1668f812012-02-29 21:54:25 +05301940{
1941 struct abx500_chargalg *di = platform_get_drvdata(pdev);
1942
1943 /* sysfs interface to enable/disbale charging from user space */
1944 abx500_chargalg_sysfs_exit(di);
1945
1946 /* Delete the work queue */
1947 destroy_workqueue(di->chargalg_wq);
1948
1949 flush_scheduled_work();
1950 power_supply_unregister(&di->chargalg_psy);
1951 platform_set_drvdata(pdev, NULL);
Arun Murthy1668f812012-02-29 21:54:25 +05301952
1953 return 0;
1954}
1955
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001956static char *supply_interface[] = {
1957 "ab8500_fg",
1958};
1959
Bill Pembertonc8afa642012-11-19 13:22:23 -05001960static int abx500_chargalg_probe(struct platform_device *pdev)
Arun Murthy1668f812012-02-29 21:54:25 +05301961{
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001962 struct device_node *np = pdev->dev.of_node;
Lee Jonesbdc56b42012-11-30 10:57:14 +00001963 struct abx500_bm_data *plat = pdev->dev.platform_data;
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001964 struct abx500_chargalg *di;
Arun Murthy1668f812012-02-29 21:54:25 +05301965 int ret = 0;
1966
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001967 di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
1968 if (!di) {
1969 dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__);
Arun Murthy1668f812012-02-29 21:54:25 +05301970 return -ENOMEM;
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001971 }
Lee Jonesbdc56b42012-11-30 10:57:14 +00001972
1973 if (!plat) {
1974 dev_err(&pdev->dev, "no battery management data supplied\n");
1975 return -EINVAL;
1976 }
1977 di->bm = plat;
1978
1979 if (np) {
1980 ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
1981 if (ret) {
1982 dev_err(&pdev->dev, "failed to get battery information\n");
1983 return ret;
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001984 }
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001985 }
Arun Murthy1668f812012-02-29 21:54:25 +05301986
Lee Jones330b7eb2013-02-15 10:53:57 +00001987 /* get device struct and parent */
Arun Murthy1668f812012-02-29 21:54:25 +05301988 di->dev = &pdev->dev;
Lee Jones330b7eb2013-02-15 10:53:57 +00001989 di->parent = dev_get_drvdata(pdev->dev.parent);
Arun Murthy1668f812012-02-29 21:54:25 +05301990
1991 /* chargalg supply */
1992 di->chargalg_psy.name = "abx500_chargalg";
1993 di->chargalg_psy.type = POWER_SUPPLY_TYPE_BATTERY;
1994 di->chargalg_psy.properties = abx500_chargalg_props;
1995 di->chargalg_psy.num_properties = ARRAY_SIZE(abx500_chargalg_props);
1996 di->chargalg_psy.get_property = abx500_chargalg_get_property;
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00001997 di->chargalg_psy.supplied_to = supply_interface;
1998 di->chargalg_psy.num_supplicants = ARRAY_SIZE(supply_interface),
Arun Murthy1668f812012-02-29 21:54:25 +05301999 di->chargalg_psy.external_power_changed =
2000 abx500_chargalg_external_power_changed;
2001
2002 /* Initilialize safety timer */
2003 init_timer(&di->safety_timer);
2004 di->safety_timer.function = abx500_chargalg_safety_timer_expired;
2005 di->safety_timer.data = (unsigned long) di;
2006
2007 /* Initilialize maintenance timer */
2008 init_timer(&di->maintenance_timer);
2009 di->maintenance_timer.function =
2010 abx500_chargalg_maintenance_timer_expired;
2011 di->maintenance_timer.data = (unsigned long) di;
2012
2013 /* Create a work queue for the chargalg */
2014 di->chargalg_wq =
2015 create_singlethread_workqueue("abx500_chargalg_wq");
2016 if (di->chargalg_wq == NULL) {
2017 dev_err(di->dev, "failed to create work queue\n");
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00002018 return -ENOMEM;
Arun Murthy1668f812012-02-29 21:54:25 +05302019 }
2020
2021 /* Init work for chargalg */
Tejun Heo203b42f2012-08-21 13:18:23 -07002022 INIT_DEFERRABLE_WORK(&di->chargalg_periodic_work,
Arun Murthy1668f812012-02-29 21:54:25 +05302023 abx500_chargalg_periodic_work);
Tejun Heo203b42f2012-08-21 13:18:23 -07002024 INIT_DEFERRABLE_WORK(&di->chargalg_wd_work,
Arun Murthy1668f812012-02-29 21:54:25 +05302025 abx500_chargalg_wd_work);
2026
2027 /* Init work for chargalg */
2028 INIT_WORK(&di->chargalg_work, abx500_chargalg_work);
2029
2030 /* To detect charger at startup */
2031 di->chg_info.prev_conn_chg = -1;
2032
2033 /* Register chargalg power supply class */
2034 ret = power_supply_register(di->dev, &di->chargalg_psy);
2035 if (ret) {
2036 dev_err(di->dev, "failed to register chargalg psy\n");
2037 goto free_chargalg_wq;
2038 }
2039
2040 platform_set_drvdata(pdev, di);
2041
2042 /* sysfs interface to enable/disable charging from user space */
2043 ret = abx500_chargalg_sysfs_init(di);
2044 if (ret) {
2045 dev_err(di->dev, "failed to create sysfs entry\n");
2046 goto free_psy;
2047 }
2048
2049 /* Run the charging algorithm */
2050 queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0);
2051
2052 dev_info(di->dev, "probe success\n");
2053 return ret;
2054
2055free_psy:
2056 power_supply_unregister(&di->chargalg_psy);
2057free_chargalg_wq:
2058 destroy_workqueue(di->chargalg_wq);
Arun Murthy1668f812012-02-29 21:54:25 +05302059 return ret;
2060}
2061
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00002062static const struct of_device_id ab8500_chargalg_match[] = {
2063 { .compatible = "stericsson,ab8500-chargalg", },
2064 { },
2065};
2066
Arun Murthy1668f812012-02-29 21:54:25 +05302067static struct platform_driver abx500_chargalg_driver = {
2068 .probe = abx500_chargalg_probe,
Bill Pemberton28ea73f2012-11-19 13:20:40 -05002069 .remove = abx500_chargalg_remove,
Arun Murthy1668f812012-02-29 21:54:25 +05302070 .suspend = abx500_chargalg_suspend,
2071 .resume = abx500_chargalg_resume,
2072 .driver = {
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00002073 .name = "ab8500-chargalg",
Arun Murthy1668f812012-02-29 21:54:25 +05302074 .owner = THIS_MODULE,
Rajanikanth H.Va12810a2012-10-31 15:40:33 +00002075 .of_match_table = ab8500_chargalg_match,
Arun Murthy1668f812012-02-29 21:54:25 +05302076 },
2077};
2078
2079static int __init abx500_chargalg_init(void)
2080{
2081 return platform_driver_register(&abx500_chargalg_driver);
2082}
2083
2084static void __exit abx500_chargalg_exit(void)
2085{
2086 platform_driver_unregister(&abx500_chargalg_driver);
2087}
2088
2089module_init(abx500_chargalg_init);
2090module_exit(abx500_chargalg_exit);
2091
2092MODULE_LICENSE("GPL v2");
2093MODULE_AUTHOR("Johan Palsson, Karl Komierowski");
2094MODULE_ALIAS("platform:abx500-chargalg");
2095MODULE_DESCRIPTION("abx500 battery charging algorithm");