summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-04-07 19:59:26 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-04-07 19:59:26 +0000
commitb3d44fcb57173b7995bf67a88aa24aa447f74f52 (patch)
treeff576a5be237c00eb6ac6f2221d89a7e9909c5bb /firmware/target/arm/imx31
parent94b63c5b19552a31b9f7906eb2ef9ac81b897a4a (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.c91
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/powermgmt-target.h4
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 */