diff options
Diffstat (limited to 'chip/stm32/adc-stm32f3.c')
-rw-r--r-- | chip/stm32/adc-stm32f3.c | 260 |
1 files changed, 0 insertions, 260 deletions
diff --git a/chip/stm32/adc-stm32f3.c b/chip/stm32/adc-stm32f3.c deleted file mode 100644 index 180dc05c3b..0000000000 --- a/chip/stm32/adc-stm32f3.c +++ /dev/null @@ -1,260 +0,0 @@ -/* Copyright 2012 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "adc.h" -#include "adc_chip.h" -#include "clock.h" -#include "common.h" -#include "console.h" -#include "dma.h" -#include "hooks.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#define ADC_SINGLE_READ_TIMEOUT 3000 /* 3 ms */ - -#define SMPR1_EXPAND(v) ((v) | ((v) << 3) | ((v) << 6) | ((v) << 9) | \ - ((v) << 12) | ((v) << 15) | ((v) << 18) | \ - ((v) << 21)) -#define SMPR2_EXPAND(v) (SMPR1_EXPAND(v) | ((v) << 24) | ((v) << 27)) - -/* Default ADC sample time = 13.5 cycles */ -#ifndef CONFIG_ADC_SAMPLE_TIME -#define CONFIG_ADC_SAMPLE_TIME 2 -#endif - -struct mutex adc_lock; - -static int watchdog_ain_id; - -static inline void adc_set_channel(int sample_id, int channel) -{ - uint32_t mask, val; - volatile uint32_t *sqr_reg; - - if (sample_id < 6) { - mask = 0x1f << (sample_id * 5); - val = channel << (sample_id * 5); - sqr_reg = &STM32_ADC_SQR3; - } else if (sample_id < 12) { - mask = 0x1f << ((sample_id - 6) * 5); - val = channel << ((sample_id - 6) * 5); - sqr_reg = &STM32_ADC_SQR2; - } else { - mask = 0x1f << ((sample_id - 12) * 5); - val = channel << ((sample_id - 12) * 5); - sqr_reg = &STM32_ADC_SQR1; - } - - *sqr_reg = (*sqr_reg & ~mask) | val; -} - -static void adc_configure(int ain_id) -{ - /* Set ADC channel */ - adc_set_channel(0, ain_id); - - /* Disable DMA */ - STM32_ADC_CR2 &= ~BIT(8); - - /* Disable scan mode */ - STM32_ADC_CR1 &= ~BIT(8); -} - -static void __attribute__((unused)) adc_configure_all(void) -{ - int i; - - /* Set ADC channels */ - STM32_ADC_SQR1 = (ADC_CH_COUNT - 1) << 20; - for (i = 0; i < ADC_CH_COUNT; ++i) - adc_set_channel(i, adc_channels[i].channel); - - /* Enable DMA */ - STM32_ADC_CR2 |= BIT(8); - - /* Enable scan mode */ - STM32_ADC_CR1 |= BIT(8); -} - -static inline int adc_powered(void) -{ - return STM32_ADC_CR2 & BIT(0); -} - -static inline int adc_conversion_ended(void) -{ - return STM32_ADC_SR & BIT(1); -} - -static int adc_watchdog_enabled(void) -{ - return STM32_ADC_CR1 & BIT(23); -} - -static int adc_enable_watchdog_no_lock(void) -{ - /* Fail if watchdog already enabled */ - if (adc_watchdog_enabled()) - return EC_ERROR_UNKNOWN; - - /* Set channel */ - STM32_ADC_SQR3 = watchdog_ain_id; - STM32_ADC_SQR1 = 0; - STM32_ADC_CR1 = (STM32_ADC_CR1 & ~0x1f) | watchdog_ain_id; - - /* Clear interrupt bit */ - STM32_ADC_SR &= ~0x1; - - /* AWDSGL=1, SCAN=1, AWDIE=1, AWDEN=1 */ - STM32_ADC_CR1 |= BIT(9) | BIT(8) | BIT(6) | BIT(23); - - /* Disable DMA */ - STM32_ADC_CR2 &= ~BIT(8); - - /* CONT=1 */ - STM32_ADC_CR2 |= BIT(1); - - /* Start conversion */ - STM32_ADC_CR2 |= BIT(0); - - return EC_SUCCESS; -} - -int adc_enable_watchdog(int ain_id, int high, int low) -{ - int ret; - - if (!adc_powered()) - return EC_ERROR_UNKNOWN; - - mutex_lock(&adc_lock); - - watchdog_ain_id = ain_id; - - /* Set thresholds */ - STM32_ADC_HTR = high & 0xfff; - STM32_ADC_LTR = low & 0xfff; - - ret = adc_enable_watchdog_no_lock(); - mutex_unlock(&adc_lock); - return ret; -} - -static int adc_disable_watchdog_no_lock(void) -{ - /* Fail if watchdog not running */ - if (!adc_watchdog_enabled()) - return EC_ERROR_UNKNOWN; - - /* AWDEN=0, AWDIE=0 */ - STM32_ADC_CR1 &= ~BIT(23) & ~BIT(6); - - /* CONT=0 */ - STM32_ADC_CR2 &= ~BIT(1); - - return EC_SUCCESS; -} - -int adc_disable_watchdog(void) -{ - int ret; - - if (!adc_powered()) - return EC_ERROR_UNKNOWN; - - mutex_lock(&adc_lock); - ret = adc_disable_watchdog_no_lock(); - mutex_unlock(&adc_lock); - return ret; -} - -int adc_read_channel(enum adc_channel ch) -{ - const struct adc_t *adc = adc_channels + ch; - int value; - int restore_watchdog = 0; - timestamp_t deadline; - - if (!adc_powered()) - return EC_ERROR_UNKNOWN; - - mutex_lock(&adc_lock); - - if (adc_watchdog_enabled()) { - restore_watchdog = 1; - adc_disable_watchdog_no_lock(); - } - - adc_configure(adc->channel); - - /* Clear EOC bit */ - STM32_ADC_SR &= ~BIT(1); - - /* Start conversion (Note: For now only confirmed on F4) */ -#if defined(CHIP_FAMILY_STM32F4) - STM32_ADC_CR2 |= STM32_ADC_CR2_ADON | STM32_ADC_CR2_SWSTART; -#else - STM32_ADC_CR2 |= STM32_ADC_CR2_ADON; -#endif - - /* Wait for EOC bit set */ - deadline.val = get_time().val + ADC_SINGLE_READ_TIMEOUT; - value = ADC_READ_ERROR; - do { - if (adc_conversion_ended()) { - value = STM32_ADC_DR & ADC_READ_MAX; - break; - } - } while (!timestamp_expired(deadline, NULL)); - - if (restore_watchdog) - adc_enable_watchdog_no_lock(); - - mutex_unlock(&adc_lock); - return (value == ADC_READ_ERROR) ? ADC_READ_ERROR : - value * adc->factor_mul / adc->factor_div + adc->shift; -} - -static void adc_init(void) -{ - /* - * Enable ADC clock. - * APB2 clock is 16MHz. ADC clock prescaler is /2. - * So the ADC clock is 8MHz. - */ - clock_enable_module(MODULE_ADC, 1); - - /* - * ADC clock is divided with respect to AHB, so no delay needed - * here. If ADC clock is the same as AHB, a dummy read on ADC - * register is needed here. - */ - - if (!adc_powered()) { - /* Power on ADC module */ - STM32_ADC_CR2 |= STM32_ADC_CR2_ADON; - - /* Reset calibration */ - STM32_ADC_CR2 |= STM32_ADC_CR2_RSTCAL; - while (STM32_ADC_CR2 & STM32_ADC_CR2_RSTCAL) - ; - - /* A/D Calibrate */ - STM32_ADC_CR2 |= STM32_ADC_CR2_CAL; - while (STM32_ADC_CR2 & STM32_ADC_CR2_CAL) - ; - } - - /* Set right alignment */ - STM32_ADC_CR2 &= ~STM32_ADC_CR2_ALIGN; - - /* Set sample time of all channels */ - STM32_ADC_SMPR1 = SMPR1_EXPAND(CONFIG_ADC_SAMPLE_TIME); - STM32_ADC_SMPR2 = SMPR2_EXPAND(CONFIG_ADC_SAMPLE_TIME); -} -DECLARE_HOOK(HOOK_INIT, adc_init, HOOK_PRIO_INIT_ADC); |