stm32f0: fix potential hang in adc initialization

Fix bug that can cause ADC initialization to hang and eventually
watchdog. Problem was that you need at least 4 ADC clock cycles
between end of ADC calibration and enabling ADC (setting ADEN).
Fix is to (1) move some ADC configuration to between end of cal
and setting ADEN, and then just to be safe, (2) continually set
ADEN until we see ADRDY (ADC ready).

See bug report for more information.

BUG=chrome-os-partner:32561
BRANCH=samus
TEST=load onto a samus that regularly has ADC problems on boot.
Using power+refresh verify that without this change PD hangs
some of the time, and with this change it never hangs.

Change-Id: Ifa4c3240ad7e1612647cc74e2105e6545ed19db4
Signed-off-by: Alec Berg <alecaberg@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/221984
Reviewed-by: Vic Yang <victoryang@chromium.org>
This commit is contained in:
Alec Berg
2014-10-07 14:42:41 -07:00
committed by chrome-internal-fetch
parent ac261c00c1
commit 1eec1e3cd4
2 changed files with 18 additions and 16 deletions

View File

@@ -109,18 +109,20 @@ static void adc_init(void)
while (STM32_ADC_CR & STM32_ADC_CR_ADCAL)
;
}
/* As per ST recommendation, ensure two cycles before setting ADEN */
asm volatile("nop; nop;");
/* ADC enabled */
STM32_ADC_CR = STM32_ADC_ISR_ADRDY;
while (!(STM32_ADC_ISR & STM32_ADC_ISR_ADRDY))
;
/* Single conversion, right aligned, 12-bit */
STM32_ADC_CFGR1 = 1 << 12; /* (1 << 15) => AUTOOFF */;
/* clock is ADCCLK */
/* clock is ADCCLK (ADEN must be off when writing this reg) */
STM32_ADC_CFGR2 = 0;
/* Sampling time : 71.5 ADC clock cycles, about 5us */
STM32_ADC_SMPR = 6;
/*
* ADC enable (note: takes 4 ADC clocks between end of calibration
* and setting ADEN).
*/
STM32_ADC_CR = STM32_ADC_CR_ADEN;
while (!(STM32_ADC_ISR & STM32_ADC_ISR_ADRDY))
STM32_ADC_CR = STM32_ADC_CR_ADEN;
/* Disable interrupts */
STM32_ADC_IER = 0;
/* Analog watchdog IRQ */

View File

@@ -294,19 +294,19 @@ static void adc_init(void)
while (STM32_ADC_CR & STM32_ADC_CR_ADCAL)
;
/* As per ST recommendation, ensure two cycles before setting ADEN */
asm volatile("nop; nop;");
/* ADC enabled */
STM32_ADC_CR = STM32_ADC_CR_ADEN;
while (!(STM32_ADC_ISR & STM32_ADC_ISR_ADRDY))
;
/* Single conversion, right aligned, 12-bit */
STM32_ADC_CFGR1 = 1 << 12; /* (1 << 15) => AUTOOFF */;
/* clock is ADCCLK */
/* clock is ADCCLK (ADEN must be off when writing this reg) */
STM32_ADC_CFGR2 = 0;
/* Sampling time : 13.5 ADC clock cycles. */
STM32_ADC_SMPR = 2;
/*
* ADC enable (note: takes 4 ADC clocks between end of calibration
* and setting ADEN).
*/
STM32_ADC_CR = STM32_ADC_CR_ADEN;
while (!(STM32_ADC_ISR & STM32_ADC_ISR_ADRDY))
STM32_ADC_CR = STM32_ADC_CR_ADEN;
}
DECLARE_HOOK(HOOK_INIT, adc_init, HOOK_PRIO_DEFAULT);