From 2249e4e1278dd6d434ce1612213afde4c77be362 Mon Sep 17 00:00:00 2001 From: Charlie Mooney Date: Mon, 17 Sep 2012 16:36:48 -0700 Subject: Snow: Retry accesses to PMU before hard reset Previously, after the first error when trying to reset the pmu over i2c, the ec would immediately give up and force a hard reset. Since i2c can be a little flaky from time to time, to prevent unneeded resets this allows the EC 3 attempts to configure it nicely it before it forces the whole system to reset. BUG=chrome-os-partner:14156 TEST=Boot machine successfully multiple times. Add a line in to force a failure whenever the pmu is accessed to simulate a total failure and check the EC logs, it should try 3 times on startup and on shutdown before finally resorting to a hard reset. If you add a fake failure that only triggers once, the machine should still turn out without incident. Without any fake failures, everything should work as normal. BRANCH=snow Change-Id: I1f453e9a6acc59d63e4cc80cffb58684f104ca6d Signed-off-by: Charlie Mooney Reviewed-on: https://gerrit.chromium.org/gerrit/33466 Reviewed-by: Simon Glass Reviewed-by: David Hendricks --- common/gaia_power.c | 9 ++++++- common/pmu_tps65090.c | 67 ++++++++++++++++++++++++++++----------------------- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/common/gaia_power.c b/common/gaia_power.c index 1b3cc61a2a..441f46f634 100644 --- a/common/gaia_power.c +++ b/common/gaia_power.c @@ -437,6 +437,8 @@ static int react_to_xpshold(unsigned int timeout_us) */ static void power_off(void) { + int pmu_shutdown_retries = 3; + /* Call hooks before we drop power rails */ hook_notify(HOOK_CHIPSET_SHUTDOWN, 0); /* switch off all rails */ @@ -449,7 +451,12 @@ static void power_off(void) lid_changed = 0; enable_sleep(SLEEP_MASK_AP_RUN); powerled_set_state(POWERLED_STATE_OFF); - if (pmu_shutdown()) + + while (--pmu_shutdown_retries >= 0) { + if (!pmu_shutdown()) + break; + } + if (pmu_shutdown_retries < 0) board_hard_reset(); CPUTS("Shutdown complete.\n"); } diff --git a/common/pmu_tps65090.c b/common/pmu_tps65090.c index 23027cd6a1..8d6d27a170 100644 --- a/common/pmu_tps65090.c +++ b/common/pmu_tps65090.c @@ -473,50 +473,57 @@ DECLARE_HOOK(HOOK_CHIPSET_PRE_INIT, pmu_init_registers, HOOK_PRIO_DEFAULT); void pmu_init(void) { - int failure = 0; + int failure = 0, retries_remaining = 3; + while (--retries_remaining >= 0) { + failure = 0; #ifdef CONFIG_PMU_BOARD_INIT - if (!failure) - failure = board_pmu_init(); + if (!failure) + failure = board_pmu_init(); #else - /* Init configuration - * Fast charge timer : 2 hours - * Charger : disable - * External pin control : enable - * - * TODO: move settings to battery pack specific init - */ - if (!failure) - failure = pmu_write(CG_CTRL0, 2); - /* Limit full charge current to 50% - * TODO: remove this temporary hack. - */ - if (!failure) - failure = pmu_write(CG_CTRL3, 0xbb); + /* Init configuration + * Fast charge timer : 2 hours + * Charger : disable + * External pin control : enable + * + * TODO: move settings to battery pack specific init + */ + if (!failure) + failure = pmu_write(CG_CTRL0, 2); + /* Limit full charge current to 50% + * TODO: remove this temporary hack. + */ + if (!failure) + failure = pmu_write(CG_CTRL3, 0xbb); #endif - /* Enable interrupts */ - if (!failure) { - failure = pmu_write(IRQ1MASK, + /* Enable interrupts */ + if (!failure) { + failure = pmu_write(IRQ1MASK, EVENT_VACG | /* AC voltage good */ EVENT_VSYSG | /* System voltage good */ EVENT_VBATG | /* Battery voltage good */ EVENT_CGACT | /* Charging status */ EVENT_CGCPL); /* Charging complete */ - } - if (!failure) - failure = pmu_write(IRQ2MASK, 0); - if (!failure) - failure = pmu_clear_irq(); + } + if (!failure) + failure = pmu_write(IRQ2MASK, 0); + if (!failure) + failure = pmu_clear_irq(); - /* Enable charger interrupt. */ - if (!failure) - failure = gpio_enable_interrupt(GPIO_CHARGER_INT); + /* Enable charger interrupt. */ + if (!failure) + failure = gpio_enable_interrupt(GPIO_CHARGER_INT); #ifdef CONFIG_AC_POWER_STATUS - if (!failure) - failure = gpio_set_flags(GPIO_AC_STATUS, GPIO_OUT_HIGH); + if (!failure) + failure = gpio_set_flags(GPIO_AC_STATUS, GPIO_OUT_HIGH); #endif + /* Exit the retry loop if there was no failure */ + if (!failure) + break; + } + if (failure) board_hard_reset(); } -- cgit v1.2.1