diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2010-04-07 19:59:26 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2010-04-07 19:59:26 +0000 |
commit | b3d44fcb57173b7995bf67a88aa24aa447f74f52 (patch) | |
tree | ff576a5be237c00eb6ac6f2221d89a7e9909c5bb /firmware/target/arm/imx31 | |
parent | 94b63c5b19552a31b9f7906eb2ef9ac81b897a4a (diff) |
Gigabeat S: Add some sanity checks for a strange charging anomaly that I have personally witnessed twice-- no, I don't have photos or a YT video but it did happen. Details are given in a comment in powermgmt-imx31.c. If it happens again, the checks may serve to reveal the true cause.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25524 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/imx31')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c | 91 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/powermgmt-target.h | 4 |
2 files changed, 72 insertions, 23 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c b/firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c index 6986a0605d..bb9b8c23af 100644 --- a/firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c @@ -379,42 +379,77 @@ static bool adjust_charger_current(void) if (charger_setting != 0) { - charging_set_thread_priority(true); + if ((charger_setting & MC13783_VCHRG) > BATTERY_VCHARGING || + (charger_setting & MC13783_ICHRG) > BATTERY_IFAST) + { + /* Table is corrupted somehow. We shouldn't run at all. + * + * Explanation: On two occasions, even though this driver monitors + * the regulator register settings on each step and + * ensures that only valid table indexes are used, + * the current and voltage seem to be misregulated, + * resulting in excessively high battery voltage that + * will trip the battery protection. After careful + * review it seems that two possibilities exist: + * This code or data got trashed at some point or + * there really is a hardware bug of some sort. So + * far the cause is unknown. Voltage is also + * monitored in the CHARGING case for that reason. + * The solution for data or code corruption is to + * just panic and refuse to run the device. The + * solution for overvoltage due to hardware bug is to + * disable the charging. The action taken will reveal + * the true cause, thus _who_ is responsible. + * "Burning lithium is baaaad", so sayeth The Council + * of Seven Ascended Masters. */ + charge_state = CHARGE_STATE_DISABLED; + service_wdt = false; + } + else + { + /* Turn on 5K pulldown. */ + i = mc13783_set(MC13783_CHARGER, MC13783_CHRGRAWPDEN); - /* Turn regulator logically ON. Hardware may still override. */ - i = mc13783_write_masked(MC13783_CHARGER, - charger_setting | MC13783_CHRGRAWPDEN, - MC13783_ICHRG | MC13783_VCHRG | - MC13783_CHRGRAWPDEN); + if (i != MC13783_DATA_ERROR) + { + charging_set_thread_priority(true); - if (i != MC13783_DATA_ERROR) - { - int icharger; + /* Turn regulator logically ON. Hardware may still override. + */ + i = mc13783_write_masked(MC13783_CHARGER, charger_setting, + MC13783_ICHRG | MC13783_VCHRG); - /* Enable charge current conversion */ - adc_enable_channel(ADC_CHARGER_CURRENT, true); + if (i != MC13783_DATA_ERROR) + { + int icharger; - /* Charge path regulator turn on takes ~100ms max. */ - sleep(HZ/10); + /* Enable charge current conversion */ + adc_enable_channel(ADC_CHARGER_CURRENT, true); - icharger = stat_battery_reading(ADC_CHARGER_CURRENT); + /* Charge path regulator turn on takes ~100ms max. */ + sleep(HZ/10); - if (icharger != INT_MIN) - { - icharger_ave = icharger * ICHARGER_AVE_SAMPLES; + icharger = stat_battery_reading(ADC_CHARGER_CURRENT); + + if (icharger != INT_MIN) + { + icharger_ave = icharger * ICHARGER_AVE_SAMPLES; - if (update_filtered_battery_voltage()) - return true; + if (update_filtered_battery_voltage()) + return true; + } + } } - } - /* Force regulator OFF. */ - charge_state = CHARGE_STATE_ERROR; + /* Force regulator OFF. */ + charge_state = CHARGE_STATE_ERROR; + } } /* Turn regulator OFF. */ icharger_ave = 0; - i = mc13783_write_masked(MC13783_CHARGER, charger_bits[0][0], + i = mc13783_write_masked(MC13783_CHARGER, + MC13783_ICHRG_0MA | MC13783_VCHRG_4_050V, MC13783_ICHRG | MC13783_VCHRG | MC13783_CHRGRAWPDEN); @@ -535,6 +570,16 @@ static bool charging_ok(void) { if (ok) { + /* Protect against any conceivable overcharge/voltage condition + * before hardware protection must intervene. Disable charger + * until reboot. */ + ok = battery_voltage() < BATT_TOO_HIGH; + if (!ok) + charge_state = CHARGE_STATE_DISABLED; + } + + if (ok) + { /* Watch to not overheat FET (nothing should go over about 1012.7mW). * Trying a higher voltage AC adapter can work (up to 6.90V) but * we'll just reject that. Reducing current for adapters that bring diff --git a/firmware/target/arm/imx31/gigabeat-s/powermgmt-target.h b/firmware/target/arm/imx31/gigabeat-s/powermgmt-target.h index 86278bce73..02d94015a1 100644 --- a/firmware/target/arm/imx31/gigabeat-s/powermgmt-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/powermgmt-target.h @@ -59,6 +59,10 @@ #define BATT_USB_VSTOP 4140 /* When to "stop" when USB only */ #define BATT_TOO_LOW 2400 /* No battery? Short? Can't read below 2400mV. */ +#define BATT_TOO_HIGH 4220 /* Extra care. Don't totally + rely upon battery protection + circutry. Stop it early if too + high. */ #define CHARGER_TOTAL_TIMER 300 /* minutes */ /* Temperature readings - w/hysteresis */ |