STM32F: Remove support for this family

There are no boards left that use this family of STM32 parts.  If we
add one later we can resurect support.

Signed-off-by: Anton Staaf <robotboy@chromium.org>

BRANCH=None
BUG=None
TEST=make buildall -j

Change-Id: If985a9e9f93c935e98c93f33c075ce00cb9a91ac
Reviewed-on: https://chromium-review.googlesource.com/282532
Tested-by: Anton Staaf <robotboy@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Commit-Queue: Anton Staaf <robotboy@chromium.org>
Trybot-Ready: Anton Staaf <robotboy@chromium.org>
This commit is contained in:
Anton Staaf
2015-06-17 12:20:43 -07:00
committed by ChromeOS Commit Bot
parent e881d99fde
commit ebdad6b0f2
21 changed files with 478 additions and 2035 deletions

View File

@@ -1,307 +0,0 @@
/* Copyright (c) 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 "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 const struct dma_option dma_adc_option = {
STM32_DMAC_ADC, (void *)&STM32_ADC_DR,
STM32_DMA_CCR_MSIZE_16_BIT | STM32_DMA_CCR_PSIZE_16_BIT,
};
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 &= ~(1 << 8);
/* Disable scan mode */
STM32_ADC_CR1 &= ~(1 << 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 |= (1 << 8);
/* Enable scan mode */
STM32_ADC_CR1 |= (1 << 8);
}
static inline int adc_powered(void)
{
return STM32_ADC_CR2 & (1 << 0);
}
static inline int adc_conversion_ended(void)
{
return STM32_ADC_SR & (1 << 1);
}
static int adc_watchdog_enabled(void)
{
return STM32_ADC_CR1 & (1 << 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 |= (1 << 9) | (1 << 8) | (1 << 6) | (1 << 23);
/* Disable DMA */
STM32_ADC_CR2 &= ~(1 << 8);
/* CONT=1 */
STM32_ADC_CR2 |= (1 << 1);
/* Start conversion */
STM32_ADC_CR2 |= (1 << 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 &= ~(1 << 23) & ~(1 << 6);
/* CONT=0 */
STM32_ADC_CR2 &= ~(1 << 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 &= ~(1 << 1);
/* Start conversion */
STM32_ADC_CR2 |= (1 << 0); /* ADON */
/* 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;
}
int adc_read_all_channels(int *data)
{
int i;
int16_t raw_data[ADC_CH_COUNT];
const struct adc_t *adc;
int restore_watchdog = 0;
int ret = EC_SUCCESS;
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_all();
dma_clear_isr(STM32_DMAC_ADC);
dma_start_rx(&dma_adc_option, ADC_CH_COUNT, raw_data);
/* Start conversion */
STM32_ADC_CR2 |= (1 << 0); /* ADON */
if (dma_wait(STM32_DMAC_ADC)) {
ret = EC_ERROR_UNKNOWN;
goto exit_all_channels;
}
for (i = 0; i < ADC_CH_COUNT; ++i) {
adc = adc_channels + i;
data[i] = raw_data[i] * adc->factor_mul / adc->factor_div +
adc->shift;
}
exit_all_channels:
dma_disable(STM32_DMAC_ADC);
if (restore_watchdog)
adc_enable_watchdog_no_lock();
mutex_unlock(&adc_lock);
return ret;
}
static void adc_init(void)
{
/*
* Enable ADC clock.
* APB2 clock is 16MHz. ADC clock prescaler is /2.
* So the ADC clock is 8MHz.
*/
STM32_RCC_APB2ENR |= (1 << 9);
/*
* 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 |= (1 << 0); /* ADON */
/* Reset calibration */
STM32_ADC_CR2 |= (1 << 3); /* RSTCAL */
while (STM32_ADC_CR2 & (1 << 3))
;
/* A/D Calibrate */
STM32_ADC_CR2 |= (1 << 2); /* CAL */
while (STM32_ADC_CR2 & (1 << 2))
;
}
/* Set right alignment */
STM32_ADC_CR2 &= ~(1 << 11);
/* 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_DEFAULT);

View File

@@ -1 +0,0 @@
adc-stm32f.c

307
chip/stm32/adc-stm32f3.c Normal file
View File

@@ -0,0 +1,307 @@
/* Copyright (c) 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 "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 const struct dma_option dma_adc_option = {
STM32_DMAC_ADC, (void *)&STM32_ADC_DR,
STM32_DMA_CCR_MSIZE_16_BIT | STM32_DMA_CCR_PSIZE_16_BIT,
};
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 &= ~(1 << 8);
/* Disable scan mode */
STM32_ADC_CR1 &= ~(1 << 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 |= (1 << 8);
/* Enable scan mode */
STM32_ADC_CR1 |= (1 << 8);
}
static inline int adc_powered(void)
{
return STM32_ADC_CR2 & (1 << 0);
}
static inline int adc_conversion_ended(void)
{
return STM32_ADC_SR & (1 << 1);
}
static int adc_watchdog_enabled(void)
{
return STM32_ADC_CR1 & (1 << 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 |= (1 << 9) | (1 << 8) | (1 << 6) | (1 << 23);
/* Disable DMA */
STM32_ADC_CR2 &= ~(1 << 8);
/* CONT=1 */
STM32_ADC_CR2 |= (1 << 1);
/* Start conversion */
STM32_ADC_CR2 |= (1 << 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 &= ~(1 << 23) & ~(1 << 6);
/* CONT=0 */
STM32_ADC_CR2 &= ~(1 << 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 &= ~(1 << 1);
/* Start conversion */
STM32_ADC_CR2 |= (1 << 0); /* ADON */
/* 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;
}
int adc_read_all_channels(int *data)
{
int i;
int16_t raw_data[ADC_CH_COUNT];
const struct adc_t *adc;
int restore_watchdog = 0;
int ret = EC_SUCCESS;
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_all();
dma_clear_isr(STM32_DMAC_ADC);
dma_start_rx(&dma_adc_option, ADC_CH_COUNT, raw_data);
/* Start conversion */
STM32_ADC_CR2 |= (1 << 0); /* ADON */
if (dma_wait(STM32_DMAC_ADC)) {
ret = EC_ERROR_UNKNOWN;
goto exit_all_channels;
}
for (i = 0; i < ADC_CH_COUNT; ++i) {
adc = adc_channels + i;
data[i] = raw_data[i] * adc->factor_mul / adc->factor_div +
adc->shift;
}
exit_all_channels:
dma_disable(STM32_DMAC_ADC);
if (restore_watchdog)
adc_enable_watchdog_no_lock();
mutex_unlock(&adc_lock);
return ret;
}
static void adc_init(void)
{
/*
* Enable ADC clock.
* APB2 clock is 16MHz. ADC clock prescaler is /2.
* So the ADC clock is 8MHz.
*/
STM32_RCC_APB2ENR |= (1 << 9);
/*
* 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 |= (1 << 0); /* ADON */
/* Reset calibration */
STM32_ADC_CR2 |= (1 << 3); /* RSTCAL */
while (STM32_ADC_CR2 & (1 << 3))
;
/* A/D Calibrate */
STM32_ADC_CR2 |= (1 << 2); /* CAL */
while (STM32_ADC_CR2 & (1 << 2))
;
}
/* Set right alignment */
STM32_ADC_CR2 &= ~(1 << 11);
/* 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_DEFAULT);

View File

@@ -42,7 +42,6 @@ chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
chip-$(HAS_TASK_POWERLED)+=power_led.o
chip-$(CONFIG_FLASH)+=flash-$(CHIP_FAMILY).o
ifdef CONFIG_FLASH
chip-$(CHIP_FAMILY_STM32F)+=flash-f.o
chip-$(CHIP_FAMILY_STM32F0)+=flash-f.o
chip-$(CHIP_FAMILY_STM32F3)+=flash-f.o
endif

View File

@@ -1,304 +0,0 @@
/* Copyright (c) 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.
*/
/* Clocks and power management settings */
#include "atomic.h"
#include "clock.h"
#include "common.h"
#include "console.h"
#include "cpu.h"
#include "hwtimer.h"
#include "registers.h"
#include "system.h"
#include "task.h"
#include "timer.h"
#include "util.h"
/* Allow serial console to wake up the EC from STOP mode */
/* #define CONFIG_FORCE_CONSOLE_RESUME */
/*
* minimum delay to enter stop mode
* STOP mode wakeup time with regulator in low power mode is 5 us.
* PLL locking time is 200us.
*/
#define STOP_MODE_LATENCY 300 /* us */
/*
* RTC clock frequency (connected to LSI clock)
*
* TODO(crosbug.com/p/12281): Calibrate LSI frequency on a per-chip basis. The
* LSI on any given chip can be between 30 kHz to 60 kHz. Without calibration,
* LSI frequency may be off by as much as 50%. Fortunately, we don't do any
* high-precision delays based solely on LSI.
*/
#define RTC_FREQ 40000 /* Hz */
#define US_PER_RTC_TICK (1000000 / RTC_FREQ)
static void wait_rtc_ready(void)
{
/* wait for Registers Synchronized Flag */
while (!(STM32_RTC_CRL & (1 << 3)))
;
}
static void prepare_rtc_write(void)
{
/* wait for RTOFF */
while (!(STM32_RTC_CRL & (1 << 5)))
;
/* set CNF bit */
STM32_RTC_CRL |= (1 << 4);
}
static void finalize_rtc_write(void)
{
/* reset CNF bit */
STM32_RTC_CRL &= ~(1 << 4);
/* wait for RTOFF */
while (!(STM32_RTC_CRL & (1 << 5)))
;
}
uint32_t set_rtc_alarm(unsigned delay_s, unsigned delay_us)
{
unsigned rtc_t0, rtc_t1;
rtc_t0 = ((uint32_t)STM32_RTC_CNTH << 16) | STM32_RTC_CNTL;
rtc_t1 = rtc_t0 + delay_us / US_PER_RTC_TICK + delay_s * RTC_FREQ;
prepare_rtc_write();
/* set RTC alarm timestamp (using the 40kHz counter ) */
STM32_RTC_ALRH = rtc_t1 >> 16;
STM32_RTC_ALRL = rtc_t1 & 0xffff;
/* clear RTC alarm */
STM32_RTC_CRL &= ~2;
/* enable RTC alarm interrupt */
STM32_RTC_CRL |= 2;
finalize_rtc_write();
/* remove synchro flag */
STM32_RTC_CRL &= ~(1 << 3);
return rtc_t0;
}
uint32_t reset_rtc_alarm(void)
{
uint32_t rtc_stamp;
wait_rtc_ready();
prepare_rtc_write();
/* clear RTC alarm */
STM32_RTC_CRL &= ~2;
finalize_rtc_write();
STM32_EXTI_PR = (1 << 17);
rtc_stamp = ((uint32_t)STM32_RTC_CNTH << 16) | STM32_RTC_CNTL;
return rtc_stamp;
}
void __rtc_wakeup_irq(void)
{
reset_rtc_alarm();
}
DECLARE_IRQ(STM32_IRQ_RTC_WAKEUP, __rtc_wakeup_irq, 1);
void __rtc_alarm_irq(void)
{
reset_rtc_alarm();
}
DECLARE_IRQ(STM32_IRQ_RTC_ALARM, __rtc_alarm_irq, 1);
/*
* These were the clock settings we used for the STM32F103 reference, but
* they'll need updating for use on some other board.
*
* HSI = 8MHz, no prescaler, no MCO
* PLLSRC = HSI/2, PLLMUL = x12 => PLLCLK = 48MHz
* USB clock = PLLCLK
*/
#define DESIRED_CPU_CLOCK 48000000
#define RCC_CFGR 0x00680000
#error "Need board-specific clock settings"
BUILD_ASSERT(CPU_CLOCK == DESIRED_CPU_CLOCK);
static void config_hispeed_clock(void)
{
/* Ensure that HSI is ON */
if (!(STM32_RCC_CR & (1 << 1))) {
/* Enable HSI */
STM32_RCC_CR |= 1 << 0;
/* Wait for HSI to be ready */
while (!(STM32_RCC_CR & (1 << 1)))
;
}
STM32_RCC_CFGR = RCC_CFGR;
/* Enable the PLL */
STM32_RCC_CR |= 1 << 24;
/* Wait for the PLL to lock */
while (!(STM32_RCC_CR & (1 << 25)))
;
/* switch to SYSCLK to the PLL */
STM32_RCC_CFGR = RCC_CFGR | 0x02;
/* wait until the PLL is the clock source */
while ((STM32_RCC_CFGR & 0xc) != 0x8)
;
}
#ifdef CONFIG_HIBERNATE
void __enter_hibernate(uint32_t seconds, uint32_t microseconds)
{
if (seconds || microseconds)
set_rtc_alarm(seconds, microseconds);
/* interrupts off now */
asm volatile("cpsid i");
/* enable the wake up pin */
STM32_PWR_CSR |= STM32_PWR_CSR_EWUP;
STM32_PWR_CR |= 0xe;
CPU_SCB_SYSCTRL |= 0x4;
/* go to Standby mode */
asm("wfi");
/* we should never reach that point */
while (1)
;
}
#endif
#ifdef CONFIG_LOW_POWER_IDLE
void clock_refresh_console_in_use(void)
{
}
#ifdef CONFIG_FORCE_CONSOLE_RESUME
static void enable_serial_wakeup(int enable)
{
static uint32_t save_exticr;
if (enable) {
/**
* allow to wake up from serial port (RX on pin PA10)
* by setting it as a GPIO with an external interrupt.
*/
save_exticr = STM32_AFIO_EXTICR(10 / 4);
STM32_AFIO_EXTICR(10 / 4) = (save_exticr & ~(0xf << 8));
} else {
/* serial port wake up : don't go back to sleep */
if (STM32_EXTI_PR & (1 << 10))
disable_sleep(SLEEP_MASK_FORCE_NO_DSLEEP);
/* restore keyboard external IT on PC10 */
STM32_AFIO_EXTICR(10 / 4) = save_exticr;
}
}
#else
static void enable_serial_wakeup(int enable)
{
}
#endif
/* Idle task. Executed when no tasks are ready to be scheduled. */
void __idle(void)
{
timestamp_t t0, t1;
int next_delay;
uint32_t rtc_t0, rtc_t1;
while (1) {
asm volatile("cpsid i");
t0 = get_time();
next_delay = __hw_clock_event_get() - t0.le.lo;
if (DEEP_SLEEP_ALLOWED && (next_delay > STOP_MODE_LATENCY)) {
/* deep-sleep in STOP mode */
enable_serial_wakeup(1);
/* set deep sleep bit */
CPU_SCB_SYSCTRL |= 0x4;
rtc_t0 = set_rtc_alarm(0,
next_delay - STOP_MODE_LATENCY);
asm("wfi");
CPU_SCB_SYSCTRL &= ~0x4;
enable_serial_wakeup(0);
/* re-lock the PLL */
config_hispeed_clock();
/* fast forward timer according to RTC counter */
rtc_t1 = reset_rtc_alarm();
t1.val = t0.val + (rtc_t1 - rtc_t0) * US_PER_RTC_TICK;
force_time(t1);
} else {
/* normal idle : only CPU clock stopped */
asm("wfi");
}
asm volatile("cpsie i");
}
}
#endif /* CONFIG_LOW_POWER_IDLE */
int clock_get_freq(void)
{
return CPU_CLOCK;
}
void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles)
{
volatile uint32_t dummy __attribute__((unused));
if (bus == BUS_AHB) {
while (cycles--)
dummy = STM32_DMA1_REGS->isr;
} else { /* APB */
while (cycles--)
dummy = STM32_USART_BRR(STM32_USART1_BASE);
}
}
void clock_init(void)
{
/*
* The initial state :
* SYSCLK from HSI (=8MHz), no divider on AHB, APB1, APB2
* PLL unlocked, RTC enabled on LSE
*/
config_hispeed_clock();
/* configure RTC clock */
wait_rtc_ready();
prepare_rtc_write();
/* set RTC divider to /1 */
STM32_RTC_PRLH = 0;
STM32_RTC_PRLL = 0;
finalize_rtc_write();
/* setup RTC EXTINT17 to wake up us from STOP mode */
STM32_EXTI_IMR |= (1 << 17);
STM32_EXTI_RTSR |= (1 << 17);
/*
* Our deep sleep mode is STOP mode.
* clear PDDS (stop mode) , set LDDS (regulator in low power mode)
*/
STM32_PWR_CR = (STM32_PWR_CR & ~2) | 1;
/* Enable RTC interrupts */
task_enable_irq(STM32_IRQ_RTC_WAKEUP);
task_enable_irq(STM32_IRQ_RTC_ALARM);
}

View File

@@ -1,24 +0,0 @@
/* Copyright (c) 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.
*/
/* Memory mapping */
#define CONFIG_FLASH_BASE 0x08000000
#define CONFIG_FLASH_PHYSICAL_SIZE 0x00020000
#define CONFIG_FLASH_BANK_SIZE 0x1000
#define CONFIG_FLASH_ERASE_SIZE 0x0400 /* erase bank size */
#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */
/* No page mode on STM32F, so no benefit to larger write sizes */
#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0002
#define CONFIG_RAM_BASE 0x20000000
#define CONFIG_RAM_SIZE 0x00002000
/* Number of IRQ vectors on the NVIC */
#define CONFIG_IRQ_COUNT 61
/* Reduced history because of limited RAM */
#undef CONFIG_CONSOLE_HISTORY
#define CONFIG_CONSOLE_HISTORY 3

View File

@@ -1,20 +0,0 @@
/* Copyright (c) 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.
*/
/* Memory mapping */
#define CONFIG_FLASH_BASE 0x08000000
#define CONFIG_FLASH_PHYSICAL_SIZE 0x00020000
#define CONFIG_FLASH_BANK_SIZE 0x1000
#define CONFIG_FLASH_ERASE_SIZE 0x0400 /* erase bank size */
#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */
/* No page mode on STM32F, so no benefit to larger write sizes */
#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0002
#define CONFIG_RAM_BASE 0x20000000
#define CONFIG_RAM_SIZE (10 * 1024)
/* Number of IRQ vectors on the NVIC */
#define CONFIG_IRQ_COUNT 68

View File

@@ -24,12 +24,6 @@
#include "config-stm32l100.h"
#elif defined(CHIP_VARIANT_STM32F373)
#include "config-stm32f373.h"
#elif defined(CHIP_VARIANT_STM32F100)
/* STM32F100xx is currently the only outlier in the STM32F series */
#include "config-stm32f100.h"
#elif defined(CHIP_VARIANT_STM32F10X)
/* STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx, and STM32F107xx */
#include "config-stm32f10x.h"
#elif defined(CHIP_VARIANT_STM32F09X)
/* STM32F09xx */
#include "config-stm32f09x.h"

View File

@@ -1,130 +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.
*/
/* Flash memory module for Chrome EC */
#include "common.h"
#include "flash.h"
#include "hooks.h"
#include "registers.h"
#include "system.h"
#include "panic.h"
/* Flag indicating whether we have locked down entire flash */
static int entire_flash_locked;
#define FLASH_SYSJUMP_TAG 0x5750 /* "WP" - Write Protect */
#define FLASH_HOOK_VERSION 1
/* The previous write protect state before sys jump */
/*
* TODO(crosbug.com/p/23798): check if STM32L code works here too - that is,
* check if entire flash is locked by attempting to lock it rather than keeping
* a global variable.
*/
struct flash_wp_state {
int entire_flash_locked;
};
/*****************************************************************************/
/* Physical layer APIs */
int flash_physical_get_protect(int block)
{
return entire_flash_locked || !(STM32_FLASH_WRPR & (1 << block));
}
uint32_t flash_physical_get_protect_flags(void)
{
uint32_t flags = 0;
/* Read all-protected state from our shadow copy */
if (entire_flash_locked)
flags |= EC_FLASH_PROTECT_ALL_NOW;
return flags;
}
int flash_physical_protect_now(int all)
{
if (all) {
/*
* Lock by writing a wrong key to FLASH_KEYR. This triggers a
* bus fault, so we need to disable bus fault handler while
* doing this.
*/
ignore_bus_fault(1);
STM32_FLASH_KEYR = 0xffffffff;
ignore_bus_fault(0);
entire_flash_locked = 1;
return EC_SUCCESS;
} else {
/* No way to protect just the RO flash until next boot */
return EC_ERROR_INVAL;
}
}
uint32_t flash_physical_get_valid_flags(void)
{
return EC_FLASH_PROTECT_RO_AT_BOOT |
EC_FLASH_PROTECT_RO_NOW |
EC_FLASH_PROTECT_ALL_NOW;
}
uint32_t flash_physical_get_writable_flags(uint32_t cur_flags)
{
uint32_t ret = 0;
/* If RO protection isn't enabled, its at-boot state can be changed. */
if (!(cur_flags & EC_FLASH_PROTECT_RO_NOW))
ret |= EC_FLASH_PROTECT_RO_AT_BOOT;
/*
* If entire flash isn't protected at this boot, it can be enabled if
* the WP GPIO is asserted.
*/
if (!(cur_flags & EC_FLASH_PROTECT_ALL_NOW) &&
(cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED))
ret |= EC_FLASH_PROTECT_ALL_NOW;
return ret;
}
int flash_physical_restore_state(void)
{
uint32_t reset_flags = system_get_reset_flags();
int version, size;
const struct flash_wp_state *prev;
/*
* If we have already jumped between images, an earlier image could
* have applied write protection. Nothing additional needs to be done.
*/
if (reset_flags & RESET_FLAG_SYSJUMP) {
prev = (const struct flash_wp_state *)system_get_jump_tag(
FLASH_SYSJUMP_TAG, &version, &size);
if (prev && version == FLASH_HOOK_VERSION &&
size == sizeof(*prev))
entire_flash_locked = prev->entire_flash_locked;
return 1;
}
return 0;
}
/*****************************************************************************/
/* Hooks */
static void flash_preserve_state(void)
{
struct flash_wp_state state;
state.entire_flash_locked = entire_flash_locked;
system_add_jump_tag(FLASH_SYSJUMP_TAG, FLASH_HOOK_VERSION,
sizeof(state), &state);
}
DECLARE_HOOK(HOOK_SYSJUMP, flash_preserve_state, HOOK_PRIO_DEFAULT);

View File

@@ -1 +0,0 @@
flash-stm32f.c

130
chip/stm32/flash-stm32f3.c Normal file
View File

@@ -0,0 +1,130 @@
/* 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.
*/
/* Flash memory module for Chrome EC */
#include "common.h"
#include "flash.h"
#include "hooks.h"
#include "registers.h"
#include "system.h"
#include "panic.h"
/* Flag indicating whether we have locked down entire flash */
static int entire_flash_locked;
#define FLASH_SYSJUMP_TAG 0x5750 /* "WP" - Write Protect */
#define FLASH_HOOK_VERSION 1
/* The previous write protect state before sys jump */
/*
* TODO(crosbug.com/p/23798): check if STM32L code works here too - that is,
* check if entire flash is locked by attempting to lock it rather than keeping
* a global variable.
*/
struct flash_wp_state {
int entire_flash_locked;
};
/*****************************************************************************/
/* Physical layer APIs */
int flash_physical_get_protect(int block)
{
return entire_flash_locked || !(STM32_FLASH_WRPR & (1 << block));
}
uint32_t flash_physical_get_protect_flags(void)
{
uint32_t flags = 0;
/* Read all-protected state from our shadow copy */
if (entire_flash_locked)
flags |= EC_FLASH_PROTECT_ALL_NOW;
return flags;
}
int flash_physical_protect_now(int all)
{
if (all) {
/*
* Lock by writing a wrong key to FLASH_KEYR. This triggers a
* bus fault, so we need to disable bus fault handler while
* doing this.
*/
ignore_bus_fault(1);
STM32_FLASH_KEYR = 0xffffffff;
ignore_bus_fault(0);
entire_flash_locked = 1;
return EC_SUCCESS;
} else {
/* No way to protect just the RO flash until next boot */
return EC_ERROR_INVAL;
}
}
uint32_t flash_physical_get_valid_flags(void)
{
return EC_FLASH_PROTECT_RO_AT_BOOT |
EC_FLASH_PROTECT_RO_NOW |
EC_FLASH_PROTECT_ALL_NOW;
}
uint32_t flash_physical_get_writable_flags(uint32_t cur_flags)
{
uint32_t ret = 0;
/* If RO protection isn't enabled, its at-boot state can be changed. */
if (!(cur_flags & EC_FLASH_PROTECT_RO_NOW))
ret |= EC_FLASH_PROTECT_RO_AT_BOOT;
/*
* If entire flash isn't protected at this boot, it can be enabled if
* the WP GPIO is asserted.
*/
if (!(cur_flags & EC_FLASH_PROTECT_ALL_NOW) &&
(cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED))
ret |= EC_FLASH_PROTECT_ALL_NOW;
return ret;
}
int flash_physical_restore_state(void)
{
uint32_t reset_flags = system_get_reset_flags();
int version, size;
const struct flash_wp_state *prev;
/*
* If we have already jumped between images, an earlier image could
* have applied write protection. Nothing additional needs to be done.
*/
if (reset_flags & RESET_FLAG_SYSJUMP) {
prev = (const struct flash_wp_state *)system_get_jump_tag(
FLASH_SYSJUMP_TAG, &version, &size);
if (prev && version == FLASH_HOOK_VERSION &&
size == sizeof(*prev))
entire_flash_locked = prev->entire_flash_locked;
return 1;
}
return 0;
}
/*****************************************************************************/
/* Hooks */
static void flash_preserve_state(void)
{
struct flash_wp_state state;
state.entire_flash_locked = entire_flash_locked;
system_add_jump_tag(FLASH_SYSJUMP_TAG, FLASH_HOOK_VERSION,
sizeof(state), &state);
}
DECLARE_HOOK(HOOK_SYSJUMP, flash_preserve_state, HOOK_PRIO_DEFAULT);

View File

@@ -1,149 +0,0 @@
/* Copyright (c) 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.
*/
/* GPIO module for Chrome EC */
#include "clock.h"
#include "common.h"
#include "gpio.h"
#include "hooks.h"
#include "registers.h"
#include "task.h"
#include "util.h"
/**
* Helper function for generating bitmasks for STM32 GPIO config registers
*/
static void gpio_config_info(uint32_t port, uint32_t mask, uint32_t *addr,
uint32_t *mode, uint32_t *cnf) {
/*
* 2-bit config followed by 2-bit mode for each pin, each
* successive pin raises the exponent for the lowest bit
* set by an order of 4, e.g. 2^0, 2^4, 2^8, etc.
*/
if (mask & 0xff) {
*addr = port; /* GPIOx_CRL */
*mode = mask;
} else {
*addr = port + 0x04; /* GPIOx_CRH */
*mode = mask >> 8;
}
*mode = *mode * *mode * *mode * *mode;
*mode |= *mode << 1;
*cnf = *mode << 2;
}
void gpio_set_flags_by_mask(uint32_t port, uint32_t pmask, uint32_t flags)
{
uint32_t addr, cnf, mode, mask;
gpio_config_info(port, pmask, &addr, &mode, &cnf);
mask = REG32(addr) & ~(cnf | mode);
/*
* For STM32, the port configuration field changes meaning
* depending on whether the port is an input, analog input,
* output, or alternate function.
*/
if (flags & GPIO_OUTPUT) {
/*
* This sets output max speed to 10MHz. That should be
* sufficient for most GPIO needs; the only thing that needs to
* go faster is SPI, which overrides the port speed on its own.
*/
mask |= 0x11111111 & mode;
if (flags & GPIO_OPEN_DRAIN)
mask |= 0x44444444 & cnf;
} else {
/*
* GPIOx_ODR determines which resistor to activate in
* input mode, see Table 16 (datasheet rm0041)
*/
if (flags & GPIO_ANALOG) {
/* Analog input, MODE=00 CNF=00 */
/* the 4 bits in mask are already reset above */
} else if (flags & GPIO_PULL_UP) {
mask |= 0x88888888 & cnf;
STM32_GPIO_BSRR(port) = pmask;
} else if (flags & GPIO_PULL_DOWN) {
mask |= 0x88888888 & cnf;
STM32_GPIO_BSRR(port) = pmask << 16;
} else {
mask |= 0x44444444 & cnf;
}
}
REG32(addr) = mask;
if (flags & GPIO_OUTPUT) {
/*
* Set pin level after port has been set up as to avoid
* potential damage, e.g. driving an open-drain output high
* before it has been configured as such.
*/
if (flags & GPIO_HIGH)
STM32_GPIO_BSRR(port) = pmask;
else if (flags & GPIO_LOW)
STM32_GPIO_BSRR(port) = pmask << 16;
}
/* Set up interrupts if necessary */
ASSERT(!(flags & (GPIO_INT_F_LOW | GPIO_INT_F_HIGH)));
if (flags & GPIO_INT_F_RISING)
STM32_EXTI_RTSR |= pmask;
if (flags & GPIO_INT_F_FALLING)
STM32_EXTI_FTSR |= pmask;
/* Interrupt is enabled by gpio_enable_interrupt() */
}
int gpio_is_reboot_warm(void)
{
return (STM32_RCC_APB1ENR & 1);
}
void gpio_enable_clocks(void)
{
/*
* Enable all GPIOs clocks
*
* TODO(crosbug.com/p/23770): only enable the banks we need to,
* and support disabling some of them in low-power idle.
*/
#ifdef CHIP_VARIANT_STM32TS60
STM32_RCC_APB2ENR |= 0x7fd;
#else
STM32_RCC_APB2ENR |= 0x1fd;
#endif
/* Delay 1 APB clock cycle after the clock is enabled */
clock_wait_bus_cycles(BUS_APB, 1);
}
void gpio_set_alternate_function(uint32_t port, uint32_t mask, int func)
{
/* TODO(crosbug.com/p/21618): implement me! */
}
static void gpio_init(void)
{
/* Enable IRQs now that pins are set up */
task_enable_irq(STM32_IRQ_EXTI0);
task_enable_irq(STM32_IRQ_EXTI1);
task_enable_irq(STM32_IRQ_EXTI2);
task_enable_irq(STM32_IRQ_EXTI3);
task_enable_irq(STM32_IRQ_EXTI4);
task_enable_irq(STM32_IRQ_EXTI9_5);
task_enable_irq(STM32_IRQ_EXTI15_10);
}
DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT);
DECLARE_IRQ(STM32_IRQ_EXTI0, gpio_interrupt, 1);
DECLARE_IRQ(STM32_IRQ_EXTI1, gpio_interrupt, 1);
DECLARE_IRQ(STM32_IRQ_EXTI2, gpio_interrupt, 1);
DECLARE_IRQ(STM32_IRQ_EXTI3, gpio_interrupt, 1);
DECLARE_IRQ(STM32_IRQ_EXTI4, gpio_interrupt, 1);
DECLARE_IRQ(STM32_IRQ_EXTI9_5, gpio_interrupt, 1);
DECLARE_IRQ(STM32_IRQ_EXTI15_10, gpio_interrupt, 1);

View File

@@ -96,17 +96,8 @@ int gpio_enable_interrupt(enum gpio_signal signal)
shift = (bit % 4) * 4;
bank = (g->port - STM32_GPIOA_BASE) / 0x400;
#if defined(CHIP_FAMILY_STM32F)
STM32_AFIO_EXTICR(group) = (STM32_AFIO_EXTICR(group) &
~(0xF << shift)) | (bank << shift);
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32L) || \
defined(CHIP_FAMILY_STM32F3)
STM32_SYSCFG_EXTICR(group) = (STM32_SYSCFG_EXTICR(group) &
~(0xF << shift)) | (bank << shift);
#else
#error "Unsupported chip family"
#endif
~(0xF << shift)) | (bank << shift);
STM32_EXTI_IMR |= g->mask;
return EC_SUCCESS;

View File

@@ -238,7 +238,7 @@ void __hw_timer_enable_clock(int n, int enable)
* Mapping of timers to reg/mask is split into a few different ranges,
* some specific to individual chips.
*/
#if defined(CHIP_FAMILY_STM32F) || defined(CHIP_FAMILY_STM32F0)
#if defined(CHIP_FAMILY_STM32F0)
if (n == 1) {
reg = &STM32_RCC_APB2ENR;
mask = STM32_RCC_PB2_TIM1;

View File

@@ -72,7 +72,7 @@ void __hw_timer_enable_clock(int n, int enable)
* Mapping of timers to reg/mask is split into a few different ranges,
* some specific to individual chips.
*/
#if defined(CHIP_FAMILY_STM32F) || defined(CHIP_FAMILY_STM32F0)
#if defined(CHIP_FAMILY_STM32F0)
if (n == 1) {
reg = &STM32_RCC_APB2ENR;
mask = STM32_RCC_PB2_TIM1;

View File

@@ -1,769 +0,0 @@
/* Copyright (c) 2013 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 "chipset.h"
#include "clock.h"
#include "common.h"
#include "console.h"
#include "dma.h"
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
#include "i2c.h"
#include "i2c_arbitration.h"
#include "registers.h"
#include "task.h"
#include "timer.h"
#include "util.h"
/* Console output macros */
#define CPUTS(outstr) cputs(CC_I2C, outstr)
#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args)
#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args)
/* 8-bit I2C slave address */
#define I2C_ADDRESS 0x3c
/* I2C bus frequency */
#define I2C_FREQ 100000 /* Hz */
/* I2C bit period in microseconds */
#define I2C_PERIOD_US (SECOND / I2C_FREQ)
/* Clock divider for I2C controller */
#define I2C_CCR (CPU_CLOCK / (2 * I2C_FREQ))
/*
* Transmit timeout in microseconds
*
* In theory we shouldn't have a timeout here (at least when we're in slave
* mode). The slave is supposed to wait forever for the master to read bytes.
* ...but we're going to keep the timeout to make sure we're robust. It may in
* fact be needed if the host resets itself mid-read.
*
* NOTE: One case where this timeout is useful is when the battery
* flips out. The battery may flip out and hold lines low for up to
* 25ms. If we just wait it will eventually let them go.
*/
#define I2C_TX_TIMEOUT_SLAVE (100 * MSEC)
#define I2C_TX_TIMEOUT_MASTER (30 * MSEC)
/*
* We delay 5us in bitbang mode. That gives us 5us low and 5us high or
* a frequency of 100kHz.
*
* Note that the code takes a little time to run so we don't actually get
* 100kHz, but that's OK.
*/
#define I2C_BITBANG_DELAY_US 5
#define I2C1 STM32_I2C1_PORT
#define I2C2 STM32_I2C2_PORT
/* Select the DMA channels matching the board configuration */
#define DMAC_SLAVE_TX \
((I2C_PORT_SLAVE) ? STM32_DMAC_I2C2_TX : STM32_DMAC_I2C1_TX)
#define DMAC_SLAVE_RX \
((I2C_PORT_SLAVE) ? STM32_DMAC_I2C2_RX : STM32_DMAC_I2C1_RX)
#define DMAC_MASTER_TX \
((I2C_PORT_MASTER) ? STM32_DMAC_I2C2_TX : STM32_DMAC_I2C1_TX)
#define DMAC_MASTER_RX \
((I2C_PORT_MASTER) ? STM32_DMAC_I2C2_RX : STM32_DMAC_I2C1_RX)
enum {
/*
* A stop condition should take 2 clocks, but the process may need more
* time to notice if it is preempted, so we poll repeatedly for 8
* clocks, before backing off and only check once every
* STOP_SENT_RETRY_US for up to TIMEOUT_STOP_SENT clocks before giving
* up.
*/
SLOW_STOP_SENT_US = I2C_PERIOD_US * 8,
TIMEOUT_STOP_SENT_US = I2C_PERIOD_US * 200,
STOP_SENT_RETRY_US = 150,
};
static const struct dma_option dma_tx_option[I2C_PORT_COUNT] = {
{STM32_DMAC_I2C1_TX, (void *)&STM32_I2C_DR(I2C1),
STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_16_BIT},
{STM32_DMAC_I2C2_TX, (void *)&STM32_I2C_DR(I2C2),
STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_16_BIT},
};
static const struct dma_option dma_rx_option[I2C_PORT_COUNT] = {
{STM32_DMAC_I2C1_RX, (void *)&STM32_I2C_DR(I2C1),
STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_16_BIT},
{STM32_DMAC_I2C2_RX, (void *)&STM32_I2C_DR(I2C2),
STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_16_BIT},
};
static uint16_t i2c_sr1[I2C_PORT_COUNT];
/* Buffer for host commands (including version, error code and checksum) */
static uint8_t host_buffer[EC_PROTO2_MAX_REQUEST_SIZE];
static struct host_cmd_handler_args host_cmd_args;
static uint8_t i2c_old_response; /* Send an old-style response */
/* Flag indicating if a command is currently in the buffer */
static uint8_t rx_pending;
static inline void disable_i2c_interrupt(int port)
{
STM32_I2C_CR2(port) &= ~(3 << 8);
}
static inline void enable_i2c_interrupt(int port)
{
STM32_I2C_CR2(port) |= 3 << 8;
}
static inline void enable_ack(int port)
{
STM32_I2C_CR1(port) |= (1 << 10);
}
static inline void disable_ack(int port)
{
STM32_I2C_CR1(port) &= ~(1 << 10);
}
static void i2c_init_port(unsigned int port);
static int i2c_write_raw_slave(int port, void *buf, int len)
{
stm32_dma_chan_t *chan;
int rv;
/* we don't want to race with TxE interrupt event */
disable_i2c_interrupt(port);
/* Configuring DMA1 channel DMAC_SLAVE_TX */
enable_ack(port);
chan = dma_get_channel(DMAC_SLAVE_TX);
dma_prepare_tx(dma_tx_option + port, len, buf);
/* Start the DMA */
dma_go(chan);
/* Configuring i2c to use DMA */
STM32_I2C_CR2(port) |= (1 << 11);
if (in_interrupt_context()) {
/* Poll for the transmission complete flag */
dma_wait(DMAC_SLAVE_TX);
dma_clear_isr(DMAC_SLAVE_TX);
} else {
/* Wait for the transmission complete Interrupt */
dma_enable_tc_interrupt(DMAC_SLAVE_TX);
rv = task_wait_event(DMA_TRANSFER_TIMEOUT_US);
dma_disable_tc_interrupt(DMAC_SLAVE_TX);
if (!(rv & TASK_EVENT_WAKE)) {
CPRINTS("Slave timeout, resetting i2c");
i2c_init_port(port);
}
}
dma_disable(DMAC_SLAVE_TX);
STM32_I2C_CR2(port) &= ~(1 << 11);
enable_i2c_interrupt(port);
return len;
}
static void i2c_send_response(struct host_cmd_handler_args *args)
{
const uint8_t *data = args->response;
int size = args->response_size;
uint8_t *out = host_buffer;
int sum = 0, i;
*out++ = args->result;
if (!i2c_old_response) {
*out++ = size;
sum = args->result + size;
}
for (i = 0; i < size; i++, data++, out++) {
if (data != out)
*out = *data;
sum += *data;
}
*out++ = sum & 0xff;
/* send the answer to the AP */
i2c_write_raw_slave(I2C2, host_buffer, out - host_buffer);
}
/* Process the command in the i2c host buffer */
static void i2c_process_command(void)
{
struct host_cmd_handler_args *args = &host_cmd_args;
char *buff = host_buffer;
args->command = *buff;
args->result = EC_RES_SUCCESS;
if (args->command >= EC_CMD_VERSION0) {
int csum, i;
/* Read version and data size */
args->version = args->command - EC_CMD_VERSION0;
args->command = buff[1];
args->params_size = buff[2];
/* Verify checksum */
for (csum = i = 0; i < args->params_size + 3; i++)
csum += buff[i];
if ((uint8_t)csum != buff[i])
args->result = EC_RES_INVALID_CHECKSUM;
buff += 3;
i2c_old_response = 0;
} else {
/*
* Old style (version 1) command.
*
* TODO(crosbug.com/p/23765): Nothing sends these anymore,
* since this was superseded by version 2 before snow launched.
* This code should be safe to remove.
*/
args->version = 0;
args->params_size = EC_PROTO2_MAX_PARAM_SIZE; /* unknown */
buff++;
i2c_old_response = 1;
}
/* we have an available command : execute it */
args->send_response = i2c_send_response;
args->params = buff;
/* skip room for error code, arglen */
args->response = host_buffer + 2;
args->response_max = EC_PROTO2_MAX_PARAM_SIZE;
args->response_size = 0;
host_command_received(args);
}
static void i2c_event_handler(int port)
{
/* save and clear status */
i2c_sr1[port] = STM32_I2C_SR1(port);
STM32_I2C_SR1(port) = 0;
/* Confirm that you are not in master mode */
if (STM32_I2C_SR2(port) & (1 << 0)) {
CPRINTS("slave ISR triggered in master mode, ignoring");
return;
}
/* transfer matched our slave address */
if (i2c_sr1[port] & (1 << 1)) {
/* If it's a receiver slave */
if (!(STM32_I2C_SR2(port) & (1 << 2))) {
dma_start_rx(dma_rx_option + port, sizeof(host_buffer),
host_buffer);
STM32_I2C_CR2(port) |= (1 << 11);
rx_pending = 1;
}
/* cleared by reading SR1 followed by reading SR2 */
STM32_I2C_SR1(port);
STM32_I2C_SR2(port);
} else if (i2c_sr1[port] & (1 << 4)) {
/* If it's a receiver slave */
if (!(STM32_I2C_SR2(port) & (1 << 2))) {
/* Disable, and clear the DMA transfer complete flag */
dma_disable(DMAC_SLAVE_RX);
dma_clear_isr(DMAC_SLAVE_RX);
/* Turn off i2c's DMA flag */
STM32_I2C_CR2(port) &= ~(1 << 11);
}
/* clear STOPF bit by reading SR1 and then writing CR1 */
STM32_I2C_SR1(port);
STM32_I2C_CR1(port) = STM32_I2C_CR1(port);
}
/* TxE event */
if (i2c_sr1[port] & (1 << 7)) {
if (port == I2C2) { /* AP is waiting for EC response */
if (rx_pending) {
i2c_process_command();
/* reset host buffer after end of transfer */
rx_pending = 0;
} else {
/* spurious read : return dummy value */
STM32_I2C_DR(port) = 0xec;
}
}
}
}
void i2c2_event_interrupt(void) { i2c_event_handler(I2C2); }
DECLARE_IRQ(STM32_IRQ_I2C2_EV, i2c2_event_interrupt, 3);
static void i2c_error_handler(int port)
{
i2c_sr1[port] = STM32_I2C_SR1(port);
if (i2c_sr1[port] & 1 << 10) {
/* ACK failed (NACK); expected when AP reads final byte.
* Software must clear AF bit. */
} else {
CPRINTS("%s: I2C_SR1(%d): 0x%04x",
__func__, port, i2c_sr1[port]);
CPRINTS("%s: I2C_SR2(%d): 0x%04x",
__func__, port, STM32_I2C_SR2(port));
}
STM32_I2C_SR1(port) &= ~0xdf00;
}
void i2c2_error_interrupt(void) { i2c_error_handler(I2C2); }
DECLARE_IRQ(STM32_IRQ_I2C2_ER, i2c2_error_interrupt, 2);
/* board-specific setup for post-I2C module init */
void __board_i2c_post_init(int port)
{
}
void board_i2c_post_init(int port)
__attribute__((weak, alias("__board_i2c_post_init")));
static void i2c_init_port(unsigned int port)
{
const int i2c_clock_bit[] = {21, 22};
if (!(STM32_RCC_APB1ENR & (1 << i2c_clock_bit[port]))) {
/* Only unwedge the bus if the clock is off */
if (i2c_claim(port) == EC_SUCCESS) {
i2c_release(port);
}
/* enable I2C2 clock */
STM32_RCC_APB1ENR |= 1 << i2c_clock_bit[port];
/* Delay 1 APB clock cycle after the clock is enabled */
clock_wait_bus_cycles(BUS_APB, 1);
}
/* force reset of the i2c peripheral */
STM32_I2C_CR1(port) = 0x8000;
STM32_I2C_CR1(port) = 0x0000;
/* set clock configuration : standard mode (100kHz) */
STM32_I2C_CCR(port) = I2C_CCR;
/* set slave address */
if (port == I2C2)
STM32_I2C_OAR1(port) = I2C_ADDRESS;
/* configuration : I2C mode / Periphal enabled, ACK enabled */
STM32_I2C_CR1(port) = (1 << 10) | (1 << 0);
/* error and event interrupts enabled / input clock is 16Mhz */
STM32_I2C_CR2(port) = (1 << 9) | (1 << 8) | 0x10;
/* clear status */
STM32_I2C_SR1(port) = 0;
board_i2c_post_init(port);
}
static void i2c_init(void)
{
/*
* TODO(crosbug.com/p/23763): Add config options to determine which
* channels to init.
*/
i2c_init_port(I2C1);
i2c_init_port(I2C2);
/* Enable event and error interrupts */
task_enable_irq(STM32_IRQ_I2C2_EV);
task_enable_irq(STM32_IRQ_I2C2_ER);
}
DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_INIT_I2C);
/*****************************************************************************/
/* STM32 Host I2C */
#define SR1_SB (1 << 0) /* Start bit sent */
#define SR1_ADDR (1 << 1) /* Address sent */
#define SR1_BTF (1 << 2) /* Byte transfered */
#define SR1_ADD10 (1 << 3) /* 10bit address sent */
#define SR1_STOPF (1 << 4) /* Stop detected */
#define SR1_RxNE (1 << 6) /* Data reg not empty */
#define SR1_TxE (1 << 7) /* Data reg empty */
#define SR1_BERR (1 << 8) /* Buss error */
#define SR1_ARLO (1 << 9) /* Arbitration lost */
#define SR1_AF (1 << 10) /* Ack failure */
#define SR1_OVR (1 << 11) /* Overrun/underrun */
#define SR1_PECERR (1 << 12) /* PEC err in reception */
#define SR1_TIMEOUT (1 << 14) /* Timeout : 25ms */
#define CR2_DMAEN (1 << 11) /* DMA enable */
#define CR2_LAST (1 << 12) /* Next EOT is last EOT */
static inline void dump_i2c_reg(int port)
{
#ifdef CONFIG_I2C_DEBUG
CPRINTF("CR1 : %016b\n", STM32_I2C_CR1(port));
CPRINTF("CR2 : %016b\n", STM32_I2C_CR2(port));
CPRINTF("SR2 : %016b\n", STM32_I2C_SR2(port));
CPRINTF("SR1 : %016b\n", STM32_I2C_SR1(port));
CPRINTF("OAR1 : %016b\n", STM32_I2C_OAR1(port));
CPRINTF("OAR2 : %016b\n", STM32_I2C_OAR2(port));
CPRINTF("DR : %016b\n", STM32_I2C_DR(port));
CPRINTF("CCR : %016b\n", STM32_I2C_CCR(port));
CPRINTF("TRISE: %016b\n", STM32_I2C_TRISE(port));
#endif /* CONFIG_I2C_DEBUG */
}
enum wait_t {
WAIT_NONE,
WAIT_MASTER_START,
WAIT_ADDR_READY,
WAIT_XMIT_TXE,
WAIT_XMIT_FINAL_TXE,
WAIT_XMIT_BTF,
WAIT_XMIT_STOP,
WAIT_RX_NE,
WAIT_RX_NE_FINAL,
WAIT_RX_NE_STOP,
WAIT_RX_NE_STOP_SIZE2,
};
/**
* Wait for a specific i2c event
*
* This function waits until the bit(s) corresponding to mask in
* the specified port's I2C SR1 register is/are set. It may
* return a timeout or success.
*
* @param port Port to wait on
* @param mask A mask specifying which bits in SR1 to wait to be set
* @param wait A wait code to be returned with the timeout error code if that
* occurs, to help with debugging.
* @return EC_SUCCESS, or EC_ERROR_TIMEOUT with the wait code OR'd onto the
* bits 8-16 to indicate what it timed out waiting for.
*/
static int wait_status(int port, uint32_t mask, enum wait_t wait)
{
uint32_t r;
timestamp_t t1, t2;
t1 = t2 = get_time();
r = STM32_I2C_SR1(port);
while (mask ? ((r & mask) != mask) : r) {
t2 = get_time();
if (t2.val - t1.val > I2C_TX_TIMEOUT_MASTER)
return EC_ERROR_TIMEOUT | (wait << 8);
else if (t2.val - t1.val > 150)
usleep(100);
r = STM32_I2C_SR1(port);
}
return EC_SUCCESS;
}
static inline uint32_t read_clear_status(int port)
{
uint32_t sr1, sr2;
sr1 = STM32_I2C_SR1(port);
sr2 = STM32_I2C_SR2(port);
return (sr2 << 16) | (sr1 & 0xffff);
}
static int master_start(int port, int slave_addr)
{
int rv;
/* Change to master send mode, reset stop bit, send start bit */
STM32_I2C_CR1(port) = (STM32_I2C_CR1(port) & ~(1 << 9)) | (1 << 8);
/* Wait for start bit sent event */
rv = wait_status(port, SR1_SB, WAIT_MASTER_START);
if (rv)
return rv;
/* Send address */
STM32_I2C_DR(port) = slave_addr;
/* Wait for addr ready */
rv = wait_status(port, SR1_ADDR, WAIT_ADDR_READY);
if (rv)
return rv;
read_clear_status(port);
return EC_SUCCESS;
}
static void master_stop(int port)
{
STM32_I2C_CR1(port) |= (1 << 9);
}
static int wait_until_stop_sent(int port)
{
timestamp_t deadline;
timestamp_t slow_cutoff;
uint8_t is_slow;
deadline = slow_cutoff = get_time();
deadline.val += TIMEOUT_STOP_SENT_US;
slow_cutoff.val += SLOW_STOP_SENT_US;
while (STM32_I2C_CR1(port) & (1 << 9)) {
if (timestamp_expired(deadline, NULL)) {
ccprintf("Stop event deadline passed:\ttask=%d"
"\tCR1=%016b\n",
(int)task_get_current(), STM32_I2C_CR1(port));
return EC_ERROR_TIMEOUT;
}
if (is_slow) {
/* If we haven't gotten a fast response, sleep */
usleep(STOP_SENT_RETRY_US);
} else {
/* Check to see if this request is taking a while */
if (timestamp_expired(slow_cutoff, NULL)) {
ccprintf("Stop event taking a while: task=%d",
(int)task_get_current());
is_slow = 1;
}
}
}
return EC_SUCCESS;
}
static void handle_i2c_error(int port, int rv)
{
timestamp_t t1, t2;
uint32_t r;
/* We have not used the bus, just exit */
if (rv == EC_ERROR_BUSY)
return;
/* EC_ERROR_TIMEOUT may have a code specifying where the timeout was */
if ((rv & 0xff) == EC_ERROR_TIMEOUT) {
#ifdef CONFIG_I2C_DEBUG
CPRINTS("Wait_status() timeout type: %d", (rv >> 8));
#endif
rv = EC_ERROR_TIMEOUT;
}
if (rv)
dump_i2c_reg(port);
/* Clear rc_w0 bits */
STM32_I2C_SR1(port) = 0;
/* Clear seq read status bits */
r = STM32_I2C_SR1(port);
r = STM32_I2C_SR2(port);
/* Clear busy state */
t1 = get_time();
if (rv == EC_ERROR_TIMEOUT && (STM32_I2C_CR1(port) & (1 << 8))) {
/*
* If it failed while just trying to send the start bit then
* something is wrong with the internal state of the i2c,
* (Probably a stray pulse on the line got it out of sync with
* the actual bytes) so reset it.
*/
CPRINTS("Unable to send START, resetting i2c");
i2c_init_port(port);
goto cr_cleanup;
} else if (rv == EC_ERROR_TIMEOUT && !(r & 2)) {
/*
* If the BUSY bit is faulty, send a stop bit just to be sure.
* It seems that this can be happen very briefly while sending
* a 1. We've not actually seen this, but just to be safe.
*/
CPRINTS("Bad BUSY bit detected");
master_stop(port);
}
/* Try to send stop bits until the bus becomes idle */
while (r & 2) {
t2 = get_time();
if (t2.val - t1.val > I2C_TX_TIMEOUT_MASTER) {
dump_i2c_reg(port);
/* Reset the i2c periph to get it back to slave mode */
i2c_init_port(port);
goto cr_cleanup;
}
/* Send stop */
master_stop(port);
usleep(1000);
r = STM32_I2C_SR2(port);
}
cr_cleanup:
/*
* Reset control register to the default state :
* I2C mode / Periphal enabled, ACK enabled
*/
STM32_I2C_CR1(port) = (1 << 10) | (1 << 0);
}
static int i2c_master_transmit(int port, int slave_addr, const uint8_t *data,
int size, int stop)
{
int rv, rv_start;
disable_ack(port);
/* Configure DMA channel for TX to host */
dma_prepare_tx(dma_tx_option + port, size, data);
dma_enable_tc_interrupt(DMAC_MASTER_TX);
/* Start the DMA */
dma_go(dma_get_channel(DMAC_MASTER_TX));
/* Configuring i2c2 to use DMA */
STM32_I2C_CR2(port) |= CR2_DMAEN;
/* Initialise i2c communication by sending START and ADDR */
rv_start = master_start(port, slave_addr);
/* If it started, wait for the transmission complete Interrupt */
if (!rv_start)
rv = task_wait_event(DMA_TRANSFER_TIMEOUT_US);
dma_disable(DMAC_MASTER_TX);
dma_disable_tc_interrupt(DMAC_MASTER_TX);
STM32_I2C_CR2(port) &= ~CR2_DMAEN;
if (rv_start)
return rv_start;
if (!(rv & TASK_EVENT_WAKE))
return EC_ERROR_TIMEOUT;
rv = wait_status(port, SR1_BTF, WAIT_XMIT_BTF);
if (rv)
return rv;
if (stop) {
master_stop(port);
return wait_status(port, 0, WAIT_XMIT_STOP);
}
return EC_SUCCESS;
}
static int i2c_master_receive(int port, int slave_addr, uint8_t *data,
int size)
{
int rv, rv_start;
if (data == NULL || size < 1)
return EC_ERROR_INVAL;
/* Master receive only supports DMA for payloads > 1 byte */
if (size > 1) {
enable_ack(port);
dma_start_rx(dma_rx_option + port, size, data);
dma_enable_tc_interrupt(DMAC_MASTER_RX);
STM32_I2C_CR2(port) |= CR2_DMAEN;
STM32_I2C_CR2(port) |= CR2_LAST;
rv_start = master_start(port, slave_addr | 1);
if (!rv_start)
rv = task_wait_event(DMA_TRANSFER_TIMEOUT_US);
dma_disable(DMAC_MASTER_RX);
dma_disable_tc_interrupt(DMAC_MASTER_RX);
STM32_I2C_CR2(port) &= ~CR2_DMAEN;
disable_ack(port);
if (rv_start)
return rv_start;
if (!(rv & TASK_EVENT_WAKE))
return EC_ERROR_TIMEOUT;
master_stop(port);
} else {
disable_ack(port);
rv = master_start(port, slave_addr | 1);
if (rv)
return rv;
master_stop(port);
rv = wait_status(port, SR1_RxNE, WAIT_RX_NE_STOP_SIZE2);
if (rv)
return rv;
data[0] = STM32_I2C_DR(port);
}
return wait_until_stop_sent(port);
}
int chip_i2c_xfer(int port, int slave_addr, const uint8_t *out, int out_bytes,
uint8_t *in, int in_bytes, int flags)
{
int rv;
/* TODO(crosbug.com/p/23569): support start/stop flags */
ASSERT(out || !out_bytes);
ASSERT(in || !in_bytes);
if (i2c_claim(port))
return EC_ERROR_BUSY;
/* If the port appears to be wedged, then try to unwedge it. */
if (!i2c_raw_get_scl(port) || !i2c_raw_get_sda(port)) {
i2c_unwedge(port);
/* Reset the i2c port. */
i2c_init_port(port);
}
disable_i2c_interrupt(port);
rv = i2c_master_transmit(port, slave_addr, out, out_bytes,
in_bytes ? 0 : 1);
if (!rv && in_bytes)
rv = i2c_master_receive(port, slave_addr, in, in_bytes);
handle_i2c_error(port, rv);
enable_i2c_interrupt(port);
i2c_release(port);
return rv;
}
int i2c_raw_get_scl(int port)
{
enum gpio_signal g;
if (get_scl_from_i2c_port(port, &g) == EC_SUCCESS)
return gpio_get_level(g);
/* If no SCL pin defined for this port, then return 1 to appear idle. */
return 1;
}
int i2c_raw_get_sda(int port)
{
enum gpio_signal g;
if (get_sda_from_i2c_port(port, &g) == EC_SUCCESS)
return gpio_get_level(g);
/* If no SDA pin defined for this port, then return 1 to appear idle. */
return 1;
}
int i2c_get_line_levels(int port)
{
return (i2c_raw_get_sda(port) ? I2C_LINE_SDA_HIGH : 0) |
(i2c_raw_get_scl(port) ? I2C_LINE_SCL_HIGH : 0);
}

View File

@@ -1,14 +0,0 @@
/* Copyright (c) 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.
*/
/* Settings to enable JTAG debugging */
#include "jtag.h"
#include "registers.h"
void jtag_pre_init(void)
{
/* stop TIM1-4 and watchdogs when the JTAG stops the CPU */
STM32_DBGMCU_CR |= 0x00003f00;
}

View File

@@ -38,32 +38,11 @@ static void pwm_configure(enum pwm_channel ch)
const struct gpio_info *gpio = gpio_list + pwm->pin;
timer_ctlr_t *tim = (timer_ctlr_t *)(pwm->tim.base);
volatile unsigned *ccmr = NULL;
#ifdef CHIP_FAMILY_STM32F
int mask = gpio->mask;
volatile uint32_t *gpio_cr = NULL;
uint32_t val;
#endif
if (using_pwm[ch])
return;
#if defined(CHIP_FAMILY_STM32F)
if (mask < 0x100) {
gpio_cr = &STM32_GPIO_CRL(gpio->port);
} else {
gpio_cr = &STM32_GPIO_CRH(gpio->port);
mask >>= 8;
}
/* Expand mask from 8-bit to 32-bit */
mask = mask * mask;
mask = mask * mask;
/* Set alternate function */
val = *gpio_cr & ~(mask * 0xf);
val |= mask * 0x9;
*gpio_cr = val;
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
gpio_set_alternate_function(gpio->port, gpio->mask, pwm->gpio_alt_func);
#else /* stm32l */
gpio_set_alternate_function(gpio->port, gpio->mask,

View File

@@ -72,8 +72,6 @@
#ifdef CHIP_VARIANT_STM32TS60
#define STM32_IRQ_ADC_1 21
#else
#define STM32_IRQ_ADC_1 18 /* ADC1 and ADC2 interrupt on STM32F10x */
#endif
#ifdef CHIP_VARIANT_STM32F373
@@ -84,10 +82,10 @@
#define STM32_IRQ_USB_LP 20
#endif
#define STM32_IRQ_CAN_TX 19 /* STM32F10x/373 only */
#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F10x/373 only */
#define STM32_IRQ_CAN_TX 19 /* STM32F373 only */
#define STM32_IRQ_USB_LP_CAN_RX 20 /* STM32F373 only */
#define STM32_IRQ_DAC 21
#define STM32_IRQ_CAN_RX1 21 /* STM32F10x/373 only */
#define STM32_IRQ_CAN_RX1 21 /* STM32F373 only */
#ifdef CHIP_VARIANT_STM32F373
#define STM32_IRQ_COMP 64
@@ -95,23 +93,18 @@
#define STM32_IRQ_COMP 22
#endif
#define STM32_IRQ_CAN_SCE 22 /* STM32F10x/373 only */
#define STM32_IRQ_CAN_SCE 22 /* STM32F373 only */
#define STM32_IRQ_ADC_2 22 /* STM32TS60 only */
#define STM32_IRQ_EXTI9_5 23
#define STM32_IRQ_LCD 24 /* STM32L15X only */
#define STM32_IRQ_TIM1_BRK_TIM15 24 /* TIM15 interrupt on STM32F100 only */
#define STM32_IRQ_PMAD 24 /* STM32TS60 only */
#define STM32_IRQ_TIM15 24 /* STM32F373 only */
#define STM32_IRQ_TIM9 25 /* STM32L15X only */
#define STM32_IRQ_TIM1_UP_TIM16 25 /* TIM16 interrupt on STM32F100 only */
#define STM32_IRQ_PMSE 25 /* STM32TS60 only */
#define STM32_IRQ_TIM16 25 /* STM32F373 only */
#define STM32_IRQ_TIM10 26 /* STM32L15X only */
#define STM32_IRQ_TIM1_TRG_TIM17 26 /* STM32F100 only */
#define STM32_IRQ_TIM1_TRG_COM 26 /* STM32F10x only */
#define STM32_IRQ_TIM17 26 /* STM32F373 only */
#define STM32_IRQ_TIM11 27 /* STM32L15X only */
#define STM32_IRQ_TIM1_CC 27 /* STM32F100 and STM32F10x */
#define STM32_IRQ_TIM18_DAC2 27 /* STM32F373 only */
#define STM32_IRQ_TIM2 28
#define STM32_IRQ_TIM3 29
@@ -127,34 +120,23 @@
#define STM32_IRQ_USART3 39
#define STM32_IRQ_EXTI15_10 40
#define STM32_IRQ_RTC_ALARM 41
#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X and STM32F10x */
#define STM32_IRQ_CEC 42 /* STM32F100/373 only */
#define STM32_IRQ_USB_FS_WAKEUP 42 /* STM32L15X */
#define STM32_IRQ_CEC 42 /* STM32F373 only */
#define STM32_IRQ_TIM6_BASIC 43 /* STM32L15X only */
#define STM32_IRQ_TIM12 43 /* STM32F100/373 only */
#define STM32_IRQ_TIM8_BRK 43 /* STM32F10x only */
#define STM32_IRQ_TIM12 43 /* STM32F373 only */
#define STM32_IRQ_TIM7_BASIC 44 /* STM32L15X only */
#define STM32_IRQ_TIM13 44 /* STM32F100/373 only */
#define STM32_IRQ_TIM8_UP 44 /* STM32F10x only */
#define STM32_IRQ_TIM14 45 /* STM32F100/373 only */
#define STM32_IRQ_TIM8_TRG_COM 45 /* STM32F10x only */
#define STM32_IRQ_TIM8_CC 46 /* STM32F10x only */
#define STM32_IRQ_ADC3 47 /* STM32F10x only */
#define STM32_IRQ_FSMC 48 /* STM32F100 and STM32F10x */
#define STM32_IRQ_SDIO 49 /* STM32F10x only */
#define STM32_IRQ_TIM5 50 /* STM32F100, STM32F10x, and STM32F373 */
#define STM32_IRQ_SPI3 51 /* STM32F100, STM32F10x, and STM32F373 */
#define STM32_IRQ_UART4 52 /* STM32F100 and STM32F10x */
#define STM32_IRQ_UART5 53 /* STM32F100 and STM32F10x */
#define STM32_IRQ_TIM6_DAC 54 /* STM32F100 and STM32F373 */
#define STM32_IRQ_TIM6 54 /* STM32F10x only */
#define STM32_IRQ_TIM7 55 /* STM32F100, STM32F10x, and STM32F373 */
#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F100, STM32F10x, and STM32F373 */
#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F100, STM32F10x, and STM32F373 */
#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F100, STM32F10x, and STM32F373 */
#define STM32_IRQ_DMA2_CHANNEL4_5 59 /* STM32F100 and STM32F10x */
#define STM32_IRQ_TIM13 44 /* STM32F373 only */
#define STM32_IRQ_TIM14 45 /* STM32F373 only */
#define STM32_IRQ_TIM5 50 /* STM32F373 */
#define STM32_IRQ_SPI3 51 /* STM32F373 */
#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */
#define STM32_IRQ_TIM7 55 /* STM32F373 */
#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */
#define STM32_IRQ_DMA2_CHANNEL2 57 /* STM32F373 */
#define STM32_IRQ_DMA2_CHANNEL3 58 /* STM32F373 */
#define STM32_IRQ_DMA2_CHANNEL4 59 /* STM32F373 only */
/* if MISC_REMAP bits are set */
#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F100 and STM32F373 */
#define STM32_IRQ_DMA2_CHANNEL5 60 /* STM32F373 */
#define STM32_IRQ_SDADC1 61 /* STM32F373 only */
#define STM32_IRQ_SDADC2 62 /* STM32F373 only */
#define STM32_IRQ_SDADC3 63 /* STM32F373 only */
@@ -239,29 +221,24 @@
#define STM32_IRQ_USART(n) CONCAT2(STM32_IRQ_USART, n)
/* --- TIMERS --- */
#define STM32_TIM1_BASE 0x40012c00 /* STM32F100 and STM32F10x */
#define STM32_TIM1_BASE 0x40012c00 /* STM32F373 */
#define STM32_TIM2_BASE 0x40000000
#define STM32_TIM3_BASE 0x40000400
#define STM32_TIM4_BASE 0x40000800
#define STM32_TIM5_BASE 0x40000c00 /* STM32F1xx and STM32F373 */
#define STM32_TIM5_BASE 0x40000c00 /* STM32F373 */
#define STM32_TIM6_BASE 0x40001000
#define STM32_TIM7_BASE 0x40001400
#define STM32_TIM8_BASE 0x40013400 /* STM32F10x only */
#if defined(CHIP_FAMILY_STM32L)
#define STM32_TIM9_BASE 0x40010800 /* STM32L15X only */
#define STM32_TIM10_BASE 0x40010C00 /* STM32L15X only */
#define STM32_TIM11_BASE 0x40011000 /* STM32L15X only */
#elif defined(CHIP_VARIANT_STM32F10X)
#define STM32_TIM9_BASE 0x40014C00 /* STM32F10x only */
#define STM32_TIM10_BASE 0x40015000 /* STM32F10x only */
#define STM32_TIM11_BASE 0x40015400 /* STM32F10x only */
#endif /* TIM9-11 */
#define STM32_TIM12_BASE 0x40001800 /* STM32F1xx and STM32F373 */
#define STM32_TIM13_BASE 0x40001c00 /* STM32F1xx and STM32F373 */
#define STM32_TIM14_BASE 0x40002000 /* STM32F1xx and STM32F373 */
#define STM32_TIM15_BASE 0x40014000 /* STM32F100 only */
#define STM32_TIM16_BASE 0x40014400 /* STM32F100 only */
#define STM32_TIM17_BASE 0x40014800 /* STM32F100 only */
#define STM32_TIM12_BASE 0x40001800 /* STM32F373 */
#define STM32_TIM13_BASE 0x40001c00 /* STM32F373 */
#define STM32_TIM14_BASE 0x40002000 /* STM32F373 */
#define STM32_TIM15_BASE 0x40014000
#define STM32_TIM16_BASE 0x40014400
#define STM32_TIM17_BASE 0x40014800
#define STM32_TIM18_BASE 0x40009c00 /* STM32F373 only */
#define STM32_TIM19_BASE 0x40015c00 /* STM32F373 only */
@@ -403,31 +380,6 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define GPIO_ALT_F4 0x4
#define GPIO_ALT_F5 0x5
#elif defined(CHIP_FAMILY_STM32F)
#define STM32_GPIOA_BASE 0x40010800
#define STM32_GPIOB_BASE 0x40010c00
#define STM32_GPIOC_BASE 0x40011000
#define STM32_GPIOD_BASE 0x40011400
#define STM32_GPIOE_BASE 0x40011800
#define STM32_GPIOF_BASE 0x4001c000
#define STM32_GPIOG_BASE 0x40012000
#define STM32_GPIOH_BASE 0x40012400 /* STM32TS only */
#define STM32_GPIOI_BASE 0x40012800 /* STM32TS only */
#define STM32_GPIO_CRL(b) REG32((b) + 0x00)
#define STM32_GPIO_CRH(b) REG32((b) + 0x04)
#define STM32_GPIO_IDR(b) REG16((b) + 0x08)
#define STM32_GPIO_ODR(b) REG16((b) + 0x0c)
#define STM32_GPIO_BSRR(b) REG32((b) + 0x10)
#define STM32_GPIO_BRR(b) REG32((b) + 0x14)
#define STM32_GPIO_LCKR(b) REG32((b) + 0x18)
#define STM32_AFIO_BASE 0x40010000
#define STM32_AFIO_EXTICR(n) REG32(STM32_AFIO_BASE + 8 + 4 * (n))
#define STM32_GPIO_AFIO_EVCR REG32(STM32_AFIO_BASE + 0x00)
#define STM32_GPIO_AFIO_MAPR REG32(STM32_AFIO_BASE + 0x04)
#define STM32_GPIO_AFIO_MAPR2 REG32(STM32_AFIO_BASE + 0x1c)
#else
#error Unsupported chip variant
#endif
@@ -531,9 +483,7 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_PWR_CR REG32(STM32_PWR_BASE + 0x00)
#define STM32_PWR_CR_LPSDSR (1 << 0)
#define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04)
#if defined(CHIP_FAMILY_STM32F)
#define STM32_PWR_CSR_EWUP (1 << 8)
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
#define STM32_PWR_CSR_EWUP1 (1 << 8)
#define STM32_PWR_CSR_EWUP2 (1 << 9)
#define STM32_PWR_CSR_EWUP3 (1 << 10)
@@ -594,8 +544,7 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_SYSCFG_PMC REG32(STM32_SYSCFG_BASE + 0x04)
#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n))
#elif defined(CHIP_FAMILY_STM32F) || defined(CHIP_FAMILY_STM32F0) || \
defined(CHIP_FAMILY_STM32F3)
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
#define STM32_RCC_BASE 0x40021000
#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00)
@@ -608,7 +557,7 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x1c)
#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x20)
#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x24)
/* STM32F100 and STM32F373 */
/* STM32F373 */
#define STM32_RCC_CFGR2 REG32(STM32_RCC_BASE + 0x2c)
/* STM32F0XX and STM32F373 */
#define STM32_RCC_CFGR3 REG32(STM32_RCC_BASE + 0x30)
@@ -716,36 +665,6 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_BKP_ENTRIES 20
#endif
#elif defined(CHIP_FAMILY_STM32F)
#define STM32_RTC_CRH REG32(STM32_RTC_BASE + 0x00)
#define STM32_RTC_CRL REG32(STM32_RTC_BASE + 0x04)
#define STM32_RTC_PRLH REG32(STM32_RTC_BASE + 0x08)
#define STM32_RTC_PRLL REG16(STM32_RTC_BASE + 0x0c)
#define STM32_RTC_DIVH REG16(STM32_RTC_BASE + 0x10)
#define STM32_RTC_DIVL REG16(STM32_RTC_BASE + 0x14)
#define STM32_RTC_CNTH REG16(STM32_RTC_BASE + 0x18)
#define STM32_RTC_CNTL REG16(STM32_RTC_BASE + 0x1c)
#define STM32_RTC_ALRH REG16(STM32_RTC_BASE + 0x20)
#define STM32_RTC_ALRL REG16(STM32_RTC_BASE + 0x24)
/* --- Backup Registers --- */
#define STM32_BKP_BASE 0x40006c00
#if defined(CHIP_VARIANT_STM32F10X)
#define STM32_BKP_ENTRIES 42
#define STM32_BKP_DATA(n) \
REG16(STM32_BKP_BASE + (n < 11 ? 0x4 : 0x40) + 4 * (n))
#else
#define STM32_BKP_ENTRIES 10
#define STM32_BKP_DATA(n) REG16(STM32_BKP_BASE + 0x4 + 4 * (n))
#endif
#define STM32_BKP_RTCCR REG16(STM32_BKP_BASE + 0x2c)
#define STM32_BKP_CR REG16(STM32_BKP_BASE + 0x30)
#define STM32_BKP_CSR REG16(STM32_BKP_BASE + 0x34)
#define STM32_RTC_BACKUP(n) STM32_BKP_DATA(n)
#else
#error Unsupported chip variant
#endif
@@ -753,7 +672,7 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
/* --- SPI --- */
#define STM32_SPI1_BASE 0x40013000
#define STM32_SPI2_BASE 0x40003800
#define STM32_SPI3_BASE 0x40003c00 /* STM32F100 and STM32F373 */
#define STM32_SPI3_BASE 0x40003c00 /* STM32F373 */
#define STM32_SPI1_PORT 0
#define STM32_SPI2_PORT 1
@@ -771,8 +690,8 @@ struct stm32_spi_regs {
unsigned crcpr;
unsigned rxcrcr;
unsigned txcrcr;
unsigned i2scfgr; /* STM32F10x and STM32L only */
unsigned i2spr; /* STM32F10x and STM32L only */
unsigned i2scfgr; /* STM32L only */
unsigned i2spr; /* STM32L only */
};
/* Must be volatile, or compiler optimizes out repeated accesses */
typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
@@ -861,8 +780,7 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
#define STM32_OPTB_WRP3L 0x18
#define STM32_OPTB_WRP3H 0x1c
#elif defined(CHIP_FAMILY_STM32F) || defined(CHIP_FAMILY_STM32F0) || \
defined(CHIP_FAMILY_STM32F3)
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
#define STM32_FLASH_REGS_BASE 0x40022000
#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00)
@@ -915,11 +833,9 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
#else /* !CHIP_VARIANT_STM32TS60 */
#define STM32_ADC1_BASE 0x40012400
#define STM32_ADC_BASE 0x40012700 /* STM32L15X only */
#define STM32_ADC2_BASE 0x40012800 /* STM32F10x only */
#define STM32_ADC3_BASE 0x40013C00 /* STM32F10x only */
#endif
#if defined(CHIP_VARIANT_STM32F100) || defined(CHIP_VARIANT_STM32F373)
#if defined(CHIP_VARIANT_STM32F373)
#define STM32_ADC_SR REG32(STM32_ADC1_BASE + 0x00)
#define STM32_ADC_CR1 REG32(STM32_ADC1_BASE + 0x04)
#define STM32_ADC_CR2 REG32(STM32_ADC1_BASE + 0x08)
@@ -1183,8 +1099,7 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
#if defined(CHIP_FAMILY_STM32L)
#define STM32_DMA1_BASE 0x40026000
#elif defined(CHIP_FAMILY_STM32F) || defined(CHIP_FAMILY_STM32F0) || \
defined(CHIP_FAMILY_STM32F3)
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
#define STM32_DMA1_BASE 0x40020000
#else
#error Unsupported chip variant
@@ -1236,7 +1151,7 @@ enum dma_channel {
STM32_DMAC_SPI2_TX = STM32_DMAC_CH7,
#endif
/* Only DMA1 (with 7 channels) is present on STM32F100 and STM32L151x */
/* Only DMA1 (with 7 channels) is present on STM32L151x */
STM32_DMAC_COUNT = 7,
#else /* stm32f03x and stm32f05x have only 5 channels */
@@ -1386,14 +1301,8 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t;
/* --- MISC --- */
#define STM32_UNIQUE_ID 0x1ffff7ac
#define STM32_CEC_BASE 0x40007800 /* STM32F100 and STM32F373 */
#define STM32_CEC_BASE 0x40007800 /* STM32F373 */
#define STM32_LCD_BASE 0x40002400
#define STM32_FSMC_BASE 0xA0000000 /* STM32F10x only */
#define STM32_USB_OTG_FS_BASE 0x50000000 /* STM32F10x only */
#define STM32_ETHERNET_BASE 0x40028000 /* STM32F10x only */
#define STM32_SDIO_BASE 0x40018000 /* STM32F10x only */
#define STM32_BXCAN1_BASE 0x40006400 /* STM32F10x only */
#define STM32_BXCAN2_BASE 0x40006800 /* STM32F10x only */
#endif /* !__ASSEMBLER__ */

View File

@@ -195,8 +195,7 @@ void system_pre_init(void)
/* Enable RTC and use LSI as clock source */
STM32_RCC_CSR = (STM32_RCC_CSR & ~0x00C30000) | 0x00420000;
}
#elif defined(CHIP_FAMILY_STM32F) || defined(CHIP_FAMILY_STM32F0) || \
defined(CHIP_FAMILY_STM32F3)
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
if ((STM32_RCC_BDCR & 0x00018300) != 0x00008200) {
/* the RTC settings are bad, we need to reset it */
STM32_RCC_BDCR |= 0x00010000;

View File

@@ -1,115 +0,0 @@
/* Copyright (c) 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 "usart-stm32f.h"
#include "clock.h"
#include "common.h"
#include "hooks.h"
#include "registers.h"
#include "task.h"
#include "util.h"
/*
* This configs array stores the currently active usart_config structure for
* each USART, an entry will be NULL if no USART driver is initialized for the
* corresponding hardware instance.
*/
static struct usart_config const *configs[STM32_USARTS_MAX];
static void usart_variant_enable(struct usart_config const *config)
{
/*
* Make sure we register this config before enabling the HW.
* If we did it the other way around the FREQ_CHANGE hook could be
* called before we update the configs array and we would miss the
* clock frequency change event, leaving our baud rate divisor wrong.
*/
configs[config->hw->index] = config;
usart_set_baud_f(config, clock_get_freq());
task_enable_irq(config->hw->irq);
}
static void usart_variant_disable(struct usart_config const *config)
{
task_disable_irq(config->hw->irq);
configs[config->hw->index] = NULL;
}
static usart_hw_ops const struct usart_variant_hw_ops = {
.enable = usart_variant_enable,
.disable = usart_variant_disable,
};
static void freq_change(void)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(configs); ++i)
if (configs[i])
usart_set_baud_f(configs[i], clock_get_freq());
}
DECLARE_HOOK(HOOK_FREQ_CHANGE, freq_change, HOOK_PRIO_DEFAULT);
/*
* USART interrupt bindings. These functions can not be defined as static or
* they will be removed by the linker because of the way that DECLARE_IRQ works.
*/
#if defined(CONFIG_STREAM_USART1)
struct usart_hw_config const usart1_hw = {
.index = 0,
.base = STM32_USART1_BASE,
.irq = STM32_IRQ_USART1,
.clock_register = &STM32_RCC_APB2ENR,
.clock_enable = STM32_RCC_PB2_USART1,
.ops = &usart_variant_hw_ops,
};
void usart1_interrupt(void)
{
usart_interrupt(configs[0]);
}
DECLARE_IRQ(STM32_IRQ_USART1, usart1_interrupt, 2);
#endif
#if defined(CONFIG_STREAM_USART2)
struct usart_hw_config const usart2_hw = {
.index = 1,
.base = STM32_USART2_BASE,
.irq = STM32_IRQ_USART2,
.clock_register = &STM32_RCC_APB1ENR,
.clock_enable = STM32_RCC_PB1_USART2,
.ops = &usart_variant_hw_ops,
};
void usart2_interrupt(void)
{
usart_interrupt(configs[1]);
}
DECLARE_IRQ(STM32_IRQ_USART2, usart2_interrupt, 2);
#endif
#if defined(CONFIG_STREAM_USART3)
struct usart_hw_config const usart3_hw = {
.index = 2,
.base = STM32_USART3_BASE,
.irq = STM32_IRQ_USART3_4,
.clock_register = &STM32_RCC_APB1ENR,
.clock_enable = STM32_RCC_PB1_USART3,
.ops = &usart_variant_hw_ops,
};
void usart3_interrupt(void)
{
usart_interrupt(configs[2]);
}
DECLARE_IRQ(STM32_IRQ_USART3, usart3_interrupt, 2);
#endif

View File

@@ -1,20 +0,0 @@
/* Copyright (c) 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.
*/
#ifndef __CROS_EC_USART_STM32F_H
#define __CROS_EC_USART_STM32F_H
#include "usart.h"
#define STM32_USARTS_MAX 3
/*
* The STM32F series can have as many as three UARTS. These are the HW configs
* for those UARTS. They can be used to initialize STM32 generic UART configs.
*/
extern struct usart_hw_config const usart1_hw;
extern struct usart_hw_config const usart2_hw;
extern struct usart_hw_config const usart3_hw;
#endif /* __CROS_EC_USART_STM32F_H */

View File

@@ -711,19 +711,8 @@ static void scan_bus(int port, const char *desc)
watchdog_reload(); /* Otherwise a full scan trips watchdog */
ccputs(".");
#ifdef CHIP_FAMILY_STM32F
/*
* TODO(crosbug.com/p/23569): The i2c_xfer() implementation on
* STM32F can't read a byte without writing one first. So
* write a byte and hope nothing bad happens. Remove this
* workaround when STM32F is fixed.
*/
tmp = 0;
if (!i2c_xfer(port, a, &tmp, 1, &tmp, 1, I2C_XFER_SINGLE))
#else
/* Do a single read */
if (!i2c_xfer(port, a, NULL, 0, &tmp, 1, I2C_XFER_SINGLE))
#endif
ccprintf("\n 0x%02x", a);
}