Gigabeat S: Use longer battery filter; lag is not a problem with voltage for charging...
[kugel-rb.git] / firmware / target / arm / imx31 / gigabeat-s / powermgmt-gigabeat-s.c
blobdc00b1ede660683e0cb093a23874afe2b4c6e9f8
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (c) 2008 by Michael Sevakis
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include <stdlib.h>
22 #include "config.h"
23 #include "system.h"
24 #include "thread.h"
25 #include "mc13783.h"
26 #include "adc.h"
27 #include "powermgmt.h"
28 #include "power.h"
29 #include "power-gigabeat-s.h"
31 const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
33 3659
36 const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
38 3650
41 /* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
42 const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
44 /* Toshiba Gigabeat S Li Ion 700mAH figured from discharge curve */
45 { 3659, 3719, 3745, 3761, 3785, 3813, 3856, 3926, 3984, 4040, 4121 },
48 /* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
49 const unsigned short percent_to_volt_charge[11] =
51 /* Toshiba Gigabeat S Li Ion 700mAH figured from charge curve */
52 4028, 4063, 4087, 4111, 4135, 4156, 4173, 4185, 4194, 4202, 4208
55 /* Returns battery voltage from ADC [millivolts] */
56 unsigned int battery_adc_voltage(void)
58 /* ADC reading 0-1023 = 2400mV-4700mV */
59 return ((adc_read(ADC_BATTERY) * 2303) >> 10) + 2400;
62 /* Returns the application supply voltage from ADC [millvolts] */
63 unsigned int application_supply_adc_voltage(void)
65 return ((adc_read(ADC_APPLICATION_SUPPLY) * 2303) >> 10) + 2400;
68 unsigned int chrgraw_adc_voltage(void)
70 return (adc_read(ADC_CHARGER_VOLTAGE) * 23023) >> 10;
73 /* Returns battery charge current from ADC [milliamps] */
74 int battery_adc_charge_current(void)
76 /* Positive reading = charger to battery
77 * Negative reading = battery to charger terminal
78 * ADC reading -512-511 = -2875mA-2875mA */
79 unsigned int value = adc_read(ADC_CHARGER_CURRENT);
80 int I;
82 if (value == ADC_READ_ERROR)
83 return INT_MIN;
85 I = ((((int32_t)value << 22) >> 22) * 2881) >> 9;
86 return ILEVEL_ADJUST_IN(I);
89 /* Estimate power dissipation in the charge path regulator in mW. */
90 unsigned int cccv_regulator_dissipation(void)
92 /* BATTISNS is shorted to BATT so we don't need to use the
93 * battery current reading. */
94 int chrgraw = (adc_read(ADC_CHARGER_VOLTAGE) * 230225) >> 10;
95 int batt = ((adc_read(ADC_BATTERY) * 23023) >> 10) + 24000;
96 int ichrgsn = adc_read(ADC_CHARGER_CURRENT);
97 ichrgsn = ((((int32_t)ichrgsn << 22) >> 22) * 2881) >> 9;
98 ichrgsn = abs(ichrgsn);
100 return (chrgraw - ichrgsn - batt)*ILEVEL_ADJUST_IN(ichrgsn) / 10000;
103 /* Returns battery temperature from ADC [deg-C] */
104 int battery_adc_temp(void)
106 /* E[volts] = value * 2.3V / 1023
107 * R[ohms] = E/I = E[volts] / 0.00002[A] (Thermistor bias current source)
109 * Steinhart-Hart thermistor equation:
110 * [A + B*ln(R) + D*ln^3(R)] = 1 / T[°K]
112 * Coeffients that fit experimental data (one thermistor so far, one run):
113 * A = 0.0013002631685462800
114 * B = 0.0002000841932612330
115 * D = 0.0000000640446750919
117 static const unsigned short ntc_table[] =
119 #if 0 /* These have degree deltas > 1 (except the final two) so leave them
120 * out. 70 deg C upper limit is quite sufficient. */
121 0, /* INF */ 1, /* 171 */ 2, /* 145 */ 3, /* 130 */
122 4, /* 121 */ 5, /* 114 */ 6, /* 108 */ 7, /* 104 */
123 8, /* 100 */ 9, /* 96 */ 10, /* 93 */ 11, /* 91 */
124 12, /* 88 */ 13, /* 86 */ 14, /* 84 */ 15, /* 82 */
125 16, /* 81 */ 17, /* 79 */ 18, /* 78 */ 19, /* 76 */
126 20, /* 75 */ 21, /* 74 */ 22, /* 72 */ 23, /* 71 */
127 #endif
128 24, /* 70 */ 25, /* 69 */ 26, /* 68 */ 27, /* 67 */
129 28, /* 66 */ 30, /* 65 */ 31, /* 64 */ 32, /* 63 */
130 33, /* 62 */ 35, /* 61 */ 36, /* 60 */ 38, /* 59 */
131 39, /* 58 */ 41, /* 57 */ 43, /* 56 */ 45, /* 55 */
132 47, /* 54 */ 49, /* 53 */ 51, /* 52 */ 53, /* 51 */
133 56, /* 50 */ 58, /* 49 */ 61, /* 48 */ 63, /* 47 */
134 66, /* 46 */ 69, /* 45 */ 73, /* 44 */ 76, /* 43 */
135 80, /* 42 */ 83, /* 41 */ 87, /* 40 */ 92, /* 39 */
136 96, /* 38 */ 101, /* 37 */ 106, /* 36 */ 111, /* 35 */
137 116, /* 34 */ 122, /* 33 */ 128, /* 32 */ 135, /* 31 */
138 142, /* 30 */ 149, /* 29 */ 156, /* 28 */ 164, /* 27 */
139 173, /* 26 */ 182, /* 25 */ 192, /* 24 */ 202, /* 23 */
140 212, /* 22 */ 224, /* 21 */ 236, /* 20 */ 249, /* 19 */
141 262, /* 18 */ 277, /* 17 */ 292, /* 16 */ 308, /* 15 */
142 325, /* 14 */ 344, /* 13 */ 363, /* 12 */ 384, /* 11 */
143 406, /* 10 */ 429, /* 9 */ 454, /* 8 */ 480, /* 7 */
144 509, /* 6 */ 539, /* 5 */ 571, /* 4 */ 605, /* 3 */
145 641, /* 2 */ 680, /* 1 */ 722, /* 0 */ 766, /* -1 */
146 813, /* -2 */ 864, /* -3 */ 918, /* -4 */ 976, /* -5 */
149 unsigned int value = adc_read(ADC_BATTERY_TEMP);
151 if (value > 0)
153 unsigned i;
155 for (i = 1; i < ARRAYLEN(ntc_table); i++)
157 if (ntc_table[i] > value)
158 break;
161 return 71 - i;
164 return INT_MIN;
167 /** Charger control **/
169 /* All code has a preference for the main charger being connected over
170 * USB. USB is considered in the algorithm only if it is the sole source. */
171 static uint32_t int_sense0 = 0; /* Interrupt Sense 0 bits */
172 static unsigned int last_inputs = POWER_INPUT_NONE; /* Detect input changes */
173 static int charger_total_timer = 0; /* Total allowed charging time */
174 static int icharger_ave = 0; /* Filtered charging current */
175 static bool charger_close = false; /* Shutdown notification */
176 static bool service_wdt = true; /* Service the watchdog timer, if things
177 go very wrong, cease and shut down. */
178 static uint32_t charger_setting = 0; /* Current ICHRG and VCHRG regulator
179 * setting (register bits) */
180 #define CHARGER_ADJUST ((uint32_t)-1)/* Force change in regulator setting */
181 static int autorecharge_counter = 0 ; /* Battery < threshold debounce */
182 static int chgcurr_timer = 0; /* Countdown to CHGCURR error */
183 #define AUTORECHARGE_COUNTDOWN (10*2) /* 10s debounce */
184 #define WATCHDOG_TIMEOUT (10*2) /* If not serviced, poweroff in 10s */
185 #define CHGCURR_TIMEOUT (4*2) /* 4s debounce */
187 /* Temperature monitoring */
188 static enum
190 TEMP_STATE_NORMAL = 0, /* Within range */
191 TEMP_STATE_WAIT = 1, /* Went out of range, wait to come back */
192 TEMP_LOW_LIMIT = 0, /* Min temp */
193 TEMP_HIGH_LIMIT = 1, /* Max temp */
194 } temp_state = TEMP_STATE_NORMAL;
196 /* Set power thread priority for charging mode or not */
197 static inline void charging_set_thread_priority(bool charging)
199 #ifdef HAVE_PRIORITY_SCHEDULING
200 thread_set_priority(THREAD_ID_CURRENT,
201 charging ? PRIORITY_REALTIME : PRIORITY_SYSTEM);
202 #endif
203 (void)charging;
206 /* Update filtered charger current - exponential moving average */
207 static bool charger_current_filter_step(void)
209 int value = battery_adc_charge_current();
211 if (value == ADC_READ_ERROR)
212 return false;
214 icharger_ave += value - (icharger_ave / ICHARGER_AVE_SAMPLES);
215 return true;
218 /* Return true if the main charger is connected. */
219 static bool main_charger_connected(void)
221 return (last_inputs &
222 POWER_INPUT_MAIN_CHARGER &
223 POWER_INPUT_CHARGER) != 0;
226 /* Return the voltage level which should automatically trigger
227 * another recharge cycle based upon which power source is available.
228 * Assumes at least one is. */
229 static unsigned int auto_recharge_voltage(void)
231 if (main_charger_connected())
232 return BATT_VAUTO_RECHARGE;
233 else
234 return BATT_USB_VAUTO_RECHARGE;
237 /* Return greater of supply (BP) or filtered battery voltage. */
238 unsigned int input_millivolts(void)
240 unsigned int app_millivolts = application_supply_adc_voltage();
241 unsigned int bat_millivolts = battery_voltage();
243 return MAX(app_millivolts, bat_millivolts);
246 /* Get smoothed readings for initializing filtered data. */
247 static int stat_battery_reading(int type)
249 int high = INT_MIN, low = INT_MAX;
250 int value = 0;
251 int i;
253 for (i = 0; i < 7; i++)
255 int reading = ADC_READ_ERROR;
257 sleep(2); /* Get unique readings */
259 switch (type)
261 case ADC_BATTERY:
262 reading = battery_adc_voltage();
263 break;
265 case ADC_CHARGER_CURRENT:
266 reading = battery_adc_charge_current();
267 break;
270 if (reading == ADC_READ_ERROR)
271 return INT_MIN;
273 if (reading > high)
274 high = reading;
276 if (reading < low)
277 low = reading;
279 value += reading;
282 /* Discard extremes */
283 return (value - high - low) / 5;
286 /* Update filtered battery voltage instead of waiting for filter
287 * decay. */
288 static bool update_filtered_battery_voltage(void)
290 int millivolts = stat_battery_reading(ADC_BATTERY);
292 if (millivolts != INT_MIN)
294 reset_battery_filter(millivolts);
295 return true;
298 return false;
301 /* Sets the charge current limit based upon state. charge_state should be
302 * set before calling. */
303 static bool adjust_charger_current(void)
305 static const uint8_t charger_bits[][2] =
307 [DISCHARGING] =
309 /* These are actually zeros but reflect this setting */
310 MC13783_ICHRG_0MA | MC13783_VCHRG_4_050V,
311 MC13783_ICHRG_0MA | MC13783_VCHRG_4_050V,
313 /* Main(+USB): Charge slowly from the adapter until voltage is
314 * sufficient for normal charging.
316 * USB: The truth is that things will probably not make it this far.
317 * Cover the case, just in case the disk isn't used and it is
318 * manageable. */
319 [TRICKLE] =
321 BATTERY_ITRICKLE | BATTERY_VCHARGING,
322 BATTERY_ITRICKLE_USB | BATTERY_VCHARGING
324 [TOPOFF] =
326 BATTERY_IFAST | BATTERY_VCHARGING,
327 BATTERY_IFAST_USB | BATTERY_VCHARGING
329 [CHARGING] =
331 BATTERY_IFAST | BATTERY_VCHARGING,
332 BATTERY_IFAST_USB | BATTERY_VCHARGING
334 /* Must maintain battery when on USB power only - utterly nasty
335 * but true and something retailos does (it will even end up charging
336 * the battery but not reporting that it is doing so).
337 * Float lower than MAX - could end up slightly discharging after
338 * a full charge but this is safer than maxing it out. */
339 [CHARGING+1] =
341 BATTERY_IFLOAT_USB | BATTERY_VFLOAT_USB,
342 BATTERY_IMAINTAIN_USB | BATTERY_VMAINTAIN_USB
344 #if 0
345 /* Slower settings to so that the linear regulator doesn't dissipate
346 * an excessive amount of power when coming out of precharge state. */
347 [CHARGING+2] =
349 BATTERY_ISLOW | BATTERY_VCHARGING,
350 BATTERY_ISLOW_USB | BATTEYR_VCHARGING
352 #endif
355 bool success = false;
356 int usb_select;
357 uint32_t i;
359 usb_select = ((last_inputs & POWER_INPUT) == POWER_INPUT_USB)
360 ? 1 : 0;
362 if (charge_state == DISCHARGING && usb_select == 1)
364 /* USB-only, DISCHARGING, = maintaining battery */
365 int select = (last_inputs & POWER_INPUT_CHARGER) ? 0 : 1;
366 charger_setting = charger_bits[CHARGING+1][select];
368 else
370 /* Take very good care not to write garbage. */
371 int state = charge_state;
373 if (state < DISCHARGING || state > CHARGING)
374 state = DISCHARGING;
376 charger_setting = charger_bits[state][usb_select];
379 if (charger_setting != 0)
381 if ((charger_setting & MC13783_VCHRG) > BATTERY_VCHARGING ||
382 (charger_setting & MC13783_ICHRG) > BATTERY_IFAST)
384 /* Table is corrupted somehow. We shouldn't run at all.
386 * Explanation: On two occasions, even though this driver monitors
387 * the regulator register settings on each step and
388 * ensures that only valid table indexes are used,
389 * the current and voltage seem to be misregulated,
390 * resulting in excessively high battery voltage that
391 * will trip the battery protection. After careful
392 * review it seems that two possibilities exist:
393 * This code or data got trashed at some point or
394 * there really is a hardware bug of some sort. So
395 * far the cause is unknown. Voltage is also
396 * monitored in the CHARGING case for that reason.
397 * The solution for data or code corruption is to
398 * just panic and refuse to run the device. The
399 * solution for overvoltage due to hardware bug is to
400 * disable the charging. The action taken will reveal
401 * the true cause, thus _who_ is responsible.
402 * "Burning lithium is baaaad", so sayeth The Council
403 * of Seven Ascended Masters. */
404 charge_state = CHARGE_STATE_DISABLED;
405 service_wdt = false;
407 else
409 /* Turn on 5K pulldown. */
410 i = mc13783_set(MC13783_CHARGER, MC13783_CHRGRAWPDEN);
412 if (i != MC13783_DATA_ERROR)
414 charging_set_thread_priority(true);
416 /* Turn regulator logically ON. Hardware may still override.
418 i = mc13783_write_masked(MC13783_CHARGER, charger_setting,
419 MC13783_ICHRG | MC13783_VCHRG);
421 if (i != MC13783_DATA_ERROR)
423 int icharger;
425 /* Enable charge current conversion */
426 adc_enable_channel(ADC_CHARGER_CURRENT, true);
428 /* Charge path regulator turn on takes ~100ms max. */
429 sleep(HZ/10);
431 icharger = stat_battery_reading(ADC_CHARGER_CURRENT);
433 if (icharger != INT_MIN)
435 icharger_ave = icharger * ICHARGER_AVE_SAMPLES;
437 if (update_filtered_battery_voltage())
438 return true;
443 /* Force regulator OFF. */
444 charge_state = CHARGE_STATE_ERROR;
448 /* Turn regulator OFF. */
449 icharger_ave = 0;
450 i = mc13783_write_masked(MC13783_CHARGER,
451 MC13783_ICHRG_0MA | MC13783_VCHRG_4_050V,
452 MC13783_ICHRG | MC13783_VCHRG |
453 MC13783_CHRGRAWPDEN);
455 if (MC13783_DATA_ERROR == i)
457 /* Failed. Force poweroff by not servicing the watchdog. */
458 service_wdt = false;
460 else if (0 == charger_setting)
462 /* Here because OFF was requested state */
463 success = true;
466 charger_setting = 0;
468 adc_enable_channel(ADC_CHARGER_CURRENT, false);
469 update_filtered_battery_voltage();
470 charging_set_thread_priority(false);
472 return success;
475 /* Stop the charger - if USB only then the regulator will not really be
476 * turned off. ERROR or DISABLED will turn it off however. */
477 static void stop_charger(void)
479 charger_total_timer = 0;
481 if (charge_state > DISCHARGING)
482 charge_state = DISCHARGING;
484 adjust_charger_current();
487 /* Return OK if it is acceptable to start the regulator. */
488 static bool charging_ok(void)
490 bool ok = charge_state >= DISCHARGING; /* Not an error condition? */
492 if (ok)
494 /* Is the battery even connected? */
495 ok = (last_inputs & POWER_INPUT_BATTERY) != 0;
498 if (ok)
500 /* No tolerance for any over/under temp - wait for it to
501 * come back into safe range. */
502 static const signed char temp_ranges[2][2] =
504 /* Temperature range before beginning charging */
505 { BATTERY_CHARGE_MIN,
506 BATTERY_CHARGE_MAX },
507 /* Temperature range after out-of-range detected -
508 charging will self-resume */
509 { BATTERY_CHARGE_RESTART_MIN,
510 BATTERY_CHARGE_RESTART_MAX },
513 int temp = battery_adc_temp();
514 const signed char *range = temp_ranges[temp_state];
516 ok = temp >= range[TEMP_LOW_LIMIT] &&
517 temp <= range[TEMP_HIGH_LIMIT];
519 switch (temp_state)
521 case TEMP_STATE_NORMAL:
522 if (!ok)
523 temp_state = TEMP_STATE_WAIT;
524 break;
526 case TEMP_STATE_WAIT:
527 if (ok)
528 temp_state = TEMP_STATE_NORMAL;
529 break;
531 default:
532 break;
536 if (ok)
538 /* Any events that should stop the regulator? */
540 /* Overvoltage at CHRGRAW? */
541 ok = (int_sense0 & MC13783_CHGOVS) == 0;
543 if (ok)
545 /* CHGCURR sensed? */
546 ok = (int_sense0 & MC13783_CHGCURRS) != 0;
548 if (!ok)
550 /* Debounce transient states */
551 if (chgcurr_timer > 0)
553 chgcurr_timer--;
554 ok = true;
557 else
559 chgcurr_timer = CHGCURR_TIMEOUT;
563 /* Charger may need to be reinserted */
564 if (!ok)
565 charge_state = CHARGE_STATE_ERROR;
568 if (charger_setting != 0)
570 if (ok)
572 /* Protect against any conceivable overcharge/voltage condition
573 * before hardware protection must intervene. Disable charger
574 * until reboot. */
575 ok = battery_voltage() < BATT_TOO_HIGH;
576 if (!ok)
577 charge_state = CHARGE_STATE_DISABLED;
580 if (ok)
582 /* Watch to not overheat FET (nothing should go over about 1012.7mW).
583 * Trying a higher voltage AC adapter can work (up to 6.90V) but
584 * we'll just reject that. Reducing current for adapters that bring
585 * CHRGRAW to > 4.900V is another possible action. */
586 ok = cccv_regulator_dissipation() < 1150;
587 if (!ok)
588 charge_state = CHARGE_STATE_ERROR;
591 if (!ok)
593 int state = charge_state;
595 if (state > DISCHARGING)
596 state = DISCHARGING;
598 /* Force off for all states including maintaining the battery level
599 * on USB. */
600 charge_state = CHARGE_STATE_ERROR;
601 stop_charger();
602 charge_state = state;
606 return ok;
609 void powermgmt_init_target(void)
611 last_inputs = power_thread_inputs;
613 #ifdef IMX31_ALLOW_CHARGING
614 const uint32_t regval_w =
615 MC13783_VCHRG_4_050V | MC13783_ICHRG_0MA |
616 MC13783_ICHRGTR_0MA | MC13783_OVCTRL_6_90V;
618 /* Use watchdog to shut system down if we lose control of the charging
619 * hardware. */
620 watchdog_init(WATCHDOG_TIMEOUT);
622 mc13783_write(MC13783_CHARGER, regval_w);
624 if (mc13783_read(MC13783_CHARGER) == regval_w)
626 /* Divide CHRGRAW input by 10 */
627 mc13783_clear(MC13783_ADC0, MC13783_CHRGRAWDIV);
628 /* Turn off BATTDETB. It's worthless on MESx0V since the battery
629 * isn't removable (nor the thermistor). */
630 mc13783_clear(MC13783_POWER_CONTROL0, MC13783_BATTDETEN);
632 else
634 /* Register has the wrong value - set error condition and disable
635 * since something is wrong. */
636 charge_state = CHARGE_STATE_DISABLED;
637 stop_charger();
639 #else
640 /* Disable charger use */
641 charge_state = CHARGE_STATE_DISABLED;
642 #endif
645 /* Returns true if the unit is charging the batteries. */
646 bool charging_state(void)
648 switch (charge_state)
650 case TRICKLE:
651 case TOPOFF:
652 case CHARGING:
653 return true;
654 default:
655 return false;
659 /* Filtered battery charge current */
660 int battery_charge_current(void)
662 return icharger_ave / ICHARGER_AVE_SAMPLES;
665 static void charger_plugged(void)
667 adc_enable_channel(ADC_BATTERY_TEMP, true);
668 autorecharge_counter = -1;
671 static void charger_unplugged(void)
673 /* Charger pulled - turn off current sources (though hardware
674 * will have done that anyway). */
675 if (charge_state > CHARGE_STATE_DISABLED)
677 /* Reset state and clear any error. If disabled, the charger
678 * will not have been started or will have been stopped already. */
679 stop_charger();
680 charge_state = DISCHARGING;
683 /* Might need to reevaluate these bits in charger_none. */
684 last_inputs &= ~(POWER_INPUT | POWER_INPUT_CHARGER);
685 temp_state = TEMP_STATE_NORMAL;
686 autorecharge_counter = 0;
687 chgcurr_timer = 0;
689 adc_enable_channel(ADC_BATTERY_TEMP, false);
692 static void charger_none(void)
694 unsigned int pwr = power_thread_inputs;
696 if (last_inputs != pwr)
698 last_inputs = pwr;
700 if (charge_state == CHARGE_STATE_DISABLED)
701 return;
703 if ((pwr & (POWER_INPUT | POWER_INPUT_CHARGER)) == POWER_INPUT_USB)
705 /* USB connected but not configured. Maintain battery to the
706 * greatest degree possible. It probably won't be enough but the
707 * discharge won't be so severe. */
708 charger_plugged();
709 charger_setting = CHARGER_ADJUST;
711 else
713 charger_unplugged();
714 last_inputs = pwr; /* Restore status */
717 else if (charger_setting != 0)
719 /* Maintaining - keep filter going and check charge state */
720 int_sense0 = mc13783_read(MC13783_INTERRUPT_SENSE0);
722 if (!charger_current_filter_step())
724 /* Failed to read current */
725 charge_state = CHARGE_STATE_ERROR;
728 charging_ok();
732 static void charger_control(void)
734 unsigned int pwr = power_thread_inputs;
736 if (last_inputs != pwr)
738 unsigned int changed = last_inputs ^ pwr;
740 last_inputs = pwr;
742 if (charger_setting != 0)
743 charger_setting = CHARGER_ADJUST;
745 if (charge_state == DISCHARGING)
747 if (main_charger_connected())
749 /* If main is connected, ignore USB plugs. */
750 if (changed & POWER_INPUT_MAIN_CHARGER)
752 /* Main charger plugged - try charge */
753 autorecharge_counter = -1;
756 else if (pwr & POWER_INPUT_USB_CHARGER
757 & POWER_INPUT_CHARGER)
759 /* USB power only */
760 if (changed & POWER_INPUT_USB_CHARGER)
762 /* USB charger plugged - try charge */
763 autorecharge_counter = -1;
765 else if (changed & POWER_INPUT_MAIN_CHARGER)
767 /* Main charger pulled - go to battery maintenence. */
768 charger_setting = CHARGER_ADJUST;
774 if (charger_setting != 0 && !charger_current_filter_step())
776 /* Failed to read current */
777 charge_state = CHARGE_STATE_ERROR;
780 int_sense0 = mc13783_read(MC13783_INTERRUPT_SENSE0);
782 if (!charging_ok())
783 return;
785 switch (charge_state)
787 case DISCHARGING:
789 /* Battery voltage may have dropped and a charge cycle should
790 * start again. Debounced. */
791 if (autorecharge_counter < 0 &&
792 battery_adc_voltage() < BATT_FULL_VOLTAGE)
794 /* Try starting a cycle now if battery isn't already topped
795 * off to allow user to ensure the battery is full. */
797 else if (battery_voltage() > auto_recharge_voltage())
799 /* Still above threshold - reset counter */
800 autorecharge_counter = AUTORECHARGE_COUNTDOWN;
801 break;
803 else if (autorecharge_counter > 0)
805 /* Coundown to restart */
806 autorecharge_counter--;
807 break;
810 autorecharge_counter = 0;
812 charging_set_thread_priority(true);
814 if (stat_battery_reading(ADC_BATTERY) < BATT_VTRICKLE_CHARGE)
816 /* Battery is deeply discharged - precharge at lower current. */
817 charge_state = TRICKLE;
819 else
821 /* Ok for fast charge */
822 charge_state = CHARGING;
825 charger_setting = CHARGER_ADJUST;
826 charger_total_timer = CHARGER_TOTAL_TIMER*60*2;
827 break;
828 } /* DISCHARGING: */
830 case TRICKLE: /* Very low - precharge */
832 if (battery_voltage() <= BATT_VTRICKLE_CHARGE)
833 break;
835 /* Switch to normal charge mode. */
836 charge_state = CHARGING;
837 charger_setting = CHARGER_ADJUST;
838 break;
839 } /* TRICKLE: */
841 case CHARGING: /* Constant-current stage */
842 case TOPOFF: /* Constant-voltage stage */
844 /* Reg. mode is more informative than an operational necessity. */
845 charge_state = (int_sense0 & MC13783_CCCVS) ? TOPOFF : CHARGING;
847 if (main_charger_connected())
849 /* Monitor and stop if current drops below threshold. */
850 if (battery_charge_current() > BATTERY_ICHARGE_COMPLETE)
851 break;
853 else
855 /* Accurate I-level can't be determined since device also
856 * powers through the I sense. This simply stops the reporting
857 * of charging but the regulator remains on. */
858 if (battery_voltage() <= BATT_USB_VSTOP)
859 break;
862 stop_charger();
863 break;
864 } /* CHARGING: TOPOFF: */
866 default:
867 break;
868 } /* switch */
870 /* Check if charger timer expired and stop it if so. */
871 if (charger_total_timer > 0 && --charger_total_timer == 0)
873 charge_state = CHARGE_STATE_ERROR;
874 stop_charger(); /* Time ran out - error */
878 /* Main charging algorithm - called from powermgmt.c */
879 void charging_algorithm_step(void)
881 #ifdef IMX31_ALLOW_CHARGING
882 if (service_wdt)
883 watchdog_service();
884 #endif
886 /* Switch by input state */
887 switch (charger_input_state)
889 case NO_CHARGER:
890 charger_none();
891 break;
893 case CHARGER_PLUGGED:
894 charger_plugged();
895 break;
897 case CHARGER:
898 charger_control();
899 break;
901 case CHARGER_UNPLUGGED:
902 charger_unplugged();
903 break;
904 } /* switch */
906 if (charger_close)
908 if (charge_state != CHARGE_STATE_DISABLED)
910 /* Disable starts while shutting down */
911 charge_state = CHARGE_STATE_DISABLED;
912 stop_charger();
915 charger_close = false;
916 return;
919 if (charger_setting != 0)
921 if ((mc13783_read(MC13783_CHARGER) & (MC13783_ICHRG | MC13783_VCHRG)) !=
922 charger_setting)
924 /* The hardware setting doesn't match. It could have turned the
925 * charger off in a race of plugging/unplugging or the setting
926 * was changed in one of the calls. */
927 adjust_charger_current();
932 /* Disable the charger and prepare for poweroff - called off-thread so we
933 * signal the charging thread to prepare to quit. */
934 void charging_algorithm_close(void)
936 charger_close = true;
938 /* Power management thread will set it false again */
939 while (charger_close)
940 sleep(HZ/10);