summaryrefslogtreecommitdiff
path: root/chip/stm32/adc-stm32f0.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/stm32/adc-stm32f0.c')
-rw-r--r--chip/stm32/adc-stm32f0.c346
1 files changed, 0 insertions, 346 deletions
diff --git a/chip/stm32/adc-stm32f0.c b/chip/stm32/adc-stm32f0.c
deleted file mode 100644
index b0654132cd..0000000000
--- a/chip/stm32/adc-stm32f0.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/* Copyright 2014 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 "clock.h"
-#include "common.h"
-#include "console.h"
-#include "dma.h"
-#include "hooks.h"
-#include "hwtimer.h"
-#include "registers.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-struct mutex adc_lock;
-
-struct adc_profile_t {
- /* Register values. */
- uint32_t cfgr1_reg;
- uint32_t cfgr2_reg;
- uint32_t smpr_reg; /* Default Sampling Rate */
- uint32_t ier_reg;
- /* DMA config. */
- const struct dma_option *dma_option;
- /* Size of DMA buffer, in units of ADC_CH_COUNT. */
- int dma_buffer_size;
-};
-
-#ifdef CONFIG_ADC_PROFILE_SINGLE
-static const struct dma_option dma_single = {
- STM32_DMAC_ADC, (void *)&STM32_ADC_DR,
- STM32_DMA_CCR_MSIZE_32_BIT | STM32_DMA_CCR_PSIZE_32_BIT,
-};
-
-#ifndef CONFIG_ADC_SAMPLE_TIME
-#define CONFIG_ADC_SAMPLE_TIME STM32_ADC_SMPR_13_5_CY
-#endif
-
-static const struct adc_profile_t profile = {
- /* Sample all channels once using DMA */
- .cfgr1_reg = STM32_ADC_CFGR1_OVRMOD,
- .cfgr2_reg = 0,
- .smpr_reg = CONFIG_ADC_SAMPLE_TIME,
- .ier_reg = 0,
- .dma_option = &dma_single,
- .dma_buffer_size = 1,
-};
-#endif
-
-#ifdef CONFIG_ADC_PROFILE_FAST_CONTINUOUS
-
-#ifndef CONFIG_ADC_SAMPLE_TIME
-#define CONFIG_ADC_SAMPLE_TIME STM32_ADC_SMPR_1_5_CY
-#endif
-
-static const struct dma_option dma_continuous = {
- STM32_DMAC_ADC, (void *)&STM32_ADC_DR,
- STM32_DMA_CCR_MSIZE_32_BIT | STM32_DMA_CCR_PSIZE_32_BIT |
- STM32_DMA_CCR_CIRC,
-};
-
-static const struct adc_profile_t profile = {
- /* Sample all channels continuously using DMA */
- .cfgr1_reg = STM32_ADC_CFGR1_OVRMOD |
- STM32_ADC_CFGR1_CONT |
- STM32_ADC_CFGR1_DMACFG,
- .cfgr2_reg = 0,
- .smpr_reg = CONFIG_ADC_SAMPLE_TIME,
- /* Fire interrupt at end of sequence. */
- .ier_reg = STM32_ADC_IER_EOSEQIE,
- .dma_option = &dma_continuous,
- /* Double-buffer our samples. */
- .dma_buffer_size = 2,
-};
-#endif
-
-static void adc_init(const struct adc_t *adc)
-{
- /*
- * 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 & BIT(9) && (STM32_ADC_CR & STM32_ADC_CR_ADEN))
- return;
-
- /* Enable ADC clock */
- clock_enable_module(MODULE_ADC, 1);
- /* check HSI14 in RCC ? ON by default */
-
- /* ADC calibration (done with ADEN = 0) */
- STM32_ADC_CR = STM32_ADC_CR_ADCAL; /* set ADCAL = 1, ADC off */
- /* wait for the end of calibration */
- while (STM32_ADC_CR & STM32_ADC_CR_ADCAL)
- ;
-
- /* Single conversion, right aligned, 12-bit */
- STM32_ADC_CFGR1 = profile.cfgr1_reg;
- /* clock is ADCCLK (ADEN must be off when writing this reg) */
- STM32_ADC_CFGR2 = profile.cfgr2_reg;
-
- /*
- * 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;
-}
-
-static void adc_configure(int ain_id, enum stm32_adc_smpr sample_rate)
-{
- /* Sampling time */
- if (sample_rate == STM32_ADC_SMPR_DEFAULT ||
- sample_rate >= STM32_ADC_SMPR_COUNT)
- STM32_ADC_SMPR = profile.smpr_reg;
- else
- STM32_ADC_SMPR = STM32_ADC_SMPR_SMP(sample_rate);
-
- /* Select channel to convert */
- STM32_ADC_CHSELR = BIT(ain_id);
-
- /* Disable DMA */
- STM32_ADC_CFGR1 &= ~STM32_ADC_CFGR1_DMAEN;
-}
-
-#ifdef CONFIG_ADC_WATCHDOG
-
-static int watchdog_ain_id;
-static int watchdog_delay_ms;
-
-static void adc_continuous_read(int ain_id)
-{
- adc_configure(ain_id, STM32_ADC_SMPR_DEFAULT);
-
- /* CONT=1 -> continuous mode on */
- STM32_ADC_CFGR1 |= STM32_ADC_CFGR1_CONT;
-
- /* Start continuous conversion */
- STM32_ADC_CR |= BIT(2); /* ADSTART */
-}
-
-static void adc_continuous_stop(void)
-{
- /* Stop on-going conversion */
- STM32_ADC_CR |= BIT(4); /* ADSTP */
-
- /* Wait for conversion to stop */
- while (STM32_ADC_CR & BIT(4))
- ;
-
- /* CONT=0 -> continuous mode off */
- STM32_ADC_CFGR1 &= ~STM32_ADC_CFGR1_CONT;
-}
-
-static void adc_interval_read(int ain_id, int interval_ms)
-{
- adc_configure(ain_id, STM32_ADC_SMPR_DEFAULT);
-
- /* EXTEN=01 -> hardware trigger detection on rising edge */
- STM32_ADC_CFGR1 = (STM32_ADC_CFGR1 & ~STM32_ADC_CFGR1_EXTEN_MASK)
- | STM32_ADC_CFGR1_EXTEN_RISE;
-
- /* EXTSEL=TRG3 -> Trigger on TIM3_TRGO */
- STM32_ADC_CFGR1 = (STM32_ADC_CFGR1 & ~STM32_ADC_CFGR1_TRG_MASK) |
- STM32_ADC_CFGR1_TRG3;
-
- __hw_timer_enable_clock(TIM_ADC, 1);
-
- /* Upcounter, counter disabled, update event only on underflow */
- STM32_TIM_CR1(TIM_ADC) = 0x0004;
-
- /* TRGO on update event */
- STM32_TIM_CR2(TIM_ADC) = 0x0020;
- STM32_TIM_SMCR(TIM_ADC) = 0x0000;
-
- /* Auto-reload value */
- STM32_TIM_ARR(TIM_ADC) = interval_ms & 0xffff;
-
- /* Set prescaler to tick per millisecond */
- STM32_TIM_PSC(TIM_ADC) = (clock_get_freq() / MSEC) - 1;
-
- /* Start counting */
- STM32_TIM_CR1(TIM_ADC) |= 1;
-
- /* Start ADC conversion */
- STM32_ADC_CR |= BIT(2); /* ADSTART */
-}
-
-static void adc_interval_stop(void)
-{
- /* EXTEN=00 -> hardware trigger detection disabled */
- STM32_ADC_CFGR1 &= ~STM32_ADC_CFGR1_EXTEN_MASK;
-
- /* Set ADSTP to clear ADSTART */
- STM32_ADC_CR |= BIT(4); /* ADSTP */
-
- /* Wait for conversion to stop */
- while (STM32_ADC_CR & BIT(4))
- ;
-
- /* Stop the timer */
- STM32_TIM_CR1(TIM_ADC) &= ~0x1;
-}
-
-static int adc_watchdog_enabled(void)
-{
- return STM32_ADC_CFGR1 & STM32_ADC_CFGR1_AWDEN;
-}
-
-static int adc_enable_watchdog_no_lock(void)
-{
- /* Select channel */
- STM32_ADC_CFGR1 = (STM32_ADC_CFGR1 & ~STM32_ADC_CFGR1_AWDCH_MASK) |
- (watchdog_ain_id << 26);
- adc_configure(watchdog_ain_id, STM32_ADC_SMPR_DEFAULT);
-
- /* Clear AWD interrupt flag */
- STM32_ADC_ISR = 0x80;
- /* Set Watchdog enable bit on a single channel */
- STM32_ADC_CFGR1 |= STM32_ADC_CFGR1_AWDEN | STM32_ADC_CFGR1_AWDSGL;
- /* Enable interrupt */
- STM32_ADC_IER |= STM32_ADC_IER_AWDIE;
-
- if (watchdog_delay_ms)
- adc_interval_read(watchdog_ain_id, watchdog_delay_ms);
- else
- adc_continuous_read(watchdog_ain_id);
-
- return EC_SUCCESS;
-}
-
-int adc_enable_watchdog(int ain_id, int high, int low)
-{
- int ret;
-
- mutex_lock(&adc_lock);
-
- watchdog_ain_id = ain_id;
-
- /* Set thresholds */
- STM32_ADC_TR = ((high & 0xfff) << 16) | (low & 0xfff);
-
- ret = adc_enable_watchdog_no_lock();
- mutex_unlock(&adc_lock);
- return ret;
-}
-
-static int adc_disable_watchdog_no_lock(void)
-{
- if (watchdog_delay_ms)
- adc_interval_stop();
- else
- adc_continuous_stop();
-
- /* Clear Watchdog enable bit */
- STM32_ADC_CFGR1 &= ~STM32_ADC_CFGR1_AWDEN;
-
- return EC_SUCCESS;
-}
-
-int adc_disable_watchdog(void)
-{
- int ret;
-
- mutex_lock(&adc_lock);
- ret = adc_disable_watchdog_no_lock();
- mutex_unlock(&adc_lock);
-
- return ret;
-}
-
-int adc_set_watchdog_delay(int delay_ms)
-{
- int resume_watchdog = 0;
-
- mutex_lock(&adc_lock);
- if (adc_watchdog_enabled()) {
- resume_watchdog = 1;
- adc_disable_watchdog_no_lock();
- }
-
- watchdog_delay_ms = delay_ms;
-
- if (resume_watchdog)
- adc_enable_watchdog_no_lock();
- mutex_unlock(&adc_lock);
-
- return EC_SUCCESS;
-}
-
-#else /* CONFIG_ADC_WATCHDOG */
-
-static int adc_watchdog_enabled(void) { return 0; }
-static int adc_enable_watchdog_no_lock(void) { return 0; }
-static int adc_disable_watchdog_no_lock(void) { return 0; }
-
-#endif /* CONFIG_ADC_WATCHDOG */
-
-int adc_read_channel(enum adc_channel ch)
-{
- const struct adc_t *adc = adc_channels + ch;
- int value;
- int restore_watchdog = 0;
-
- mutex_lock(&adc_lock);
-
- adc_init(adc);
-
- if (adc_watchdog_enabled()) {
- restore_watchdog = 1;
- adc_disable_watchdog_no_lock();
- }
-
- adc_configure(adc->channel, adc->sample_rate);
-
- /* Clear flags */
- STM32_ADC_ISR = 0xe;
-
- /* Start conversion */
- STM32_ADC_CR |= BIT(2); /* ADSTART */
-
- /* Wait for end of conversion */
- while (!(STM32_ADC_ISR & BIT(2)))
- ;
- /* read converted value */
- value = STM32_ADC_DR;
-
- if (restore_watchdog)
- adc_enable_watchdog_no_lock();
- mutex_unlock(&adc_lock);
-
- return value * adc->factor_mul / adc->factor_div + adc->shift;
-}
-
-void adc_disable(void)
-{
- STM32_ADC_CR |= STM32_ADC_CR_ADDIS;
- /*
- * Note that the ADC is not in OFF state immediately.
- * Once the ADC is effectively put into OFF state,
- * STM32_ADC_CR_ADDIS bit will be cleared by hardware.
- */
-}