mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-28 10:45:22 +00:00
stm32f0: fix rare ADC initialization bug
Fix potential bug in ADC initialization. After setting ADEN bit to enable ADC module, we must wait for ADRDY (ADC ready) bit before continuing. This bug only affects a few chips, and only some of the time. BUG=chrome-os-partner:31978 BRANCH=none TEST=Used a samus board where the PD MCU fails ADC initialization quite often. Without this fix, if you reboot the PD MCU, it will sometimes come up with all ADC's reading 0 and ADEN reading 0. With this fix, it always boots with the ADC's working Change-Id: Iba1d0e56006ba1ad6d9f0eee964a70ef2d0f8dcf Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/219522 Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Vic Yang <victoryang@chromium.org>
This commit is contained in:
committed by
chrome-internal-fetch
parent
fb5ff7b1bb
commit
9c62920f96
@@ -104,13 +104,17 @@ static void adc_init(void)
|
||||
/* Only do the calibration if the ADC is off */
|
||||
if (!(STM32_ADC_CR & 1)) {
|
||||
/* ADC calibration */
|
||||
STM32_ADC_CR = 1 << 31; /* set ADCAL = 1, ADC off */
|
||||
STM32_ADC_CR = STM32_ADC_CR_ADCAL; /* set ADCAL = 1, ADC off */
|
||||
/* wait for the end of calibration */
|
||||
while (STM32_ADC_CR & (1 << 31))
|
||||
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 = 1 << 0;
|
||||
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 */
|
||||
|
||||
@@ -278,10 +278,10 @@ fail:
|
||||
static void adc_init(void)
|
||||
{
|
||||
/*
|
||||
* If clock is already enabled, then this is a warm reboot and
|
||||
* ADC is already initialized.
|
||||
* If clock is already enabled, and ADC module is enabled
|
||||
* then this is a warm reboot and ADC is already initialized.
|
||||
*/
|
||||
if (STM32_RCC_APB2ENR & (1 << 9))
|
||||
if (STM32_RCC_APB2ENR & (1 << 9) && (STM32_ADC_CR & STM32_ADC_CR_ADEN))
|
||||
return;
|
||||
|
||||
/* Enable ADC clock */
|
||||
@@ -289,13 +289,18 @@ static void adc_init(void)
|
||||
/* check HSI14 in RCC ? ON by default */
|
||||
|
||||
/* ADC calibration (done with ADEN = 0) */
|
||||
STM32_ADC_CR = 1 << 31; /* set ADCAL = 1, ADC off */
|
||||
STM32_ADC_CR = STM32_ADC_CR_ADCAL; /* set ADCAL = 1, ADC off */
|
||||
/* wait for the end of calibration */
|
||||
while (STM32_ADC_CR & (1 << 31))
|
||||
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 = 1 << 0;
|
||||
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 */;
|
||||
|
||||
@@ -887,8 +887,11 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
|
||||
#define STM32_ADC_DR(x) REG32(STM32_ADC_BASE(x) + 0x4c)
|
||||
#elif defined(CHIP_FAMILY_STM32F0)
|
||||
#define STM32_ADC_ISR REG32(STM32_ADC1_BASE + 0x00)
|
||||
#define STM32_ADC_ISR_ADRDY (1 << 0)
|
||||
#define STM32_ADC_IER REG32(STM32_ADC1_BASE + 0x04)
|
||||
#define STM32_ADC_CR REG32(STM32_ADC1_BASE + 0x08)
|
||||
#define STM32_ADC_CR_ADEN (1 << 0)
|
||||
#define STM32_ADC_CR_ADCAL (1 << 31)
|
||||
#define STM32_ADC_CFGR1 REG32(STM32_ADC1_BASE + 0x0C)
|
||||
#define STM32_ADC_CFGR2 REG32(STM32_ADC1_BASE + 0x10)
|
||||
#define STM32_ADC_SMPR REG32(STM32_ADC1_BASE + 0x14)
|
||||
|
||||
Reference in New Issue
Block a user