stm32f446e-eval: add support for stm32f446

This adds basic support for the stm32f446.
This consists of:
* New DMA model for stm32f4
* New clock domain support.
* MCO oscillator gpio export support.
* Flash support for irregular blocks.

BUG=chromium:608039
TEST=boots w/ correct clock, stm32f0 also boots.
BRANCH=None

Change-Id: I1c5cf6ddca09009c9dac60da8a3d0c5ceedfcf4d
Signed-off-by: Nick Sanders <nsanders@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/363992
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
This commit is contained in:
Nick Sanders
2016-07-26 13:17:09 -07:00
committed by chrome-bot
parent 6fad4f8588
commit 6fcd163da5
27 changed files with 2187 additions and 212 deletions

View File

@@ -0,0 +1,58 @@
/* Copyright 2016 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 "common.h"
#include "dma.h"
#include "ec_version.h"
#include "gpio.h"
#include "gpio_list.h"
#include "hooks.h"
#include "registers.h"
#include "stm32-dma.h"
#define GPIO_SET_HS(bank, number) \
(STM32_GPIO_OSPEEDR(GPIO_##bank) |= (0x3 << (number * 2)))
void board_config_post_gpio_init(void)
{
/* We use MCO2 clock passthrough to provide a clock to USB HS */
gpio_config_module(MODULE_MCO, 1);
/* GPIO PC9 to high speed */
GPIO_SET_HS(C, 9);
/* Set USB GPIO to high speed */
GPIO_SET_HS(A, 11);
GPIO_SET_HS(A, 12);
GPIO_SET_HS(C, 3);
GPIO_SET_HS(C, 2);
GPIO_SET_HS(C, 0);
GPIO_SET_HS(A, 5);
GPIO_SET_HS(B, 5);
GPIO_SET_HS(B, 13);
GPIO_SET_HS(B, 12);
GPIO_SET_HS(B, 2);
GPIO_SET_HS(B, 10);
GPIO_SET_HS(B, 1);
GPIO_SET_HS(B, 0);
GPIO_SET_HS(A, 3);
/* Set I2C GPIO to HS */
GPIO_SET_HS(B, 6);
GPIO_SET_HS(B, 7);
GPIO_SET_HS(F, 1);
GPIO_SET_HS(F, 0);
GPIO_SET_HS(A, 8);
GPIO_SET_HS(B, 4);
GPIO_SET_HS(C, 6);
GPIO_SET_HS(C, 7);
}
static void board_init(void)
{
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);

View File

@@ -0,0 +1,54 @@
/* Copyright 2016 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.
*/
/* STM32F446E-Eval board configuration */
#ifndef __CROS_EC_BOARD_H
#define __CROS_EC_BOARD_H
/* Use external clock */
#define CONFIG_STM32_CLOCK_HSE_HZ 8000000
/* Optional features */
#undef CONFIG_WATCHDOG_HELP
#undef CONFIG_LID_SWITCH
#define CONFIG_BOARD_POST_GPIO_INIT
/* Enable console recasting of GPIO type. */
#define CONFIG_CMD_GPIO_EXTENDED
/* The UART console is on USART1 (PA9/PA10) */
#undef CONFIG_UART_CONSOLE
#define CONFIG_UART_CONSOLE 1
#undef CONFIG_UART_TX_BUF_SIZE
#define CONFIG_UART_TX_BUF_SIZE 4096
#define CONFIG_UART_TX_REQ_CH 4
#define CONFIG_UART_RX_REQ_CH 4
/* This is not actually an EC so disable some features. */
#undef CONFIG_WATCHDOG_HELP
#undef CONFIG_LID_SWITCH
#undef CONFIG_WATCHDOG
/* Optional features */
#define CONFIG_STM_HWTIMER32
#define CONFIG_DMA_HELP
/*
* Allow dangerous commands all the time, since we don't have a write protect
* switch.
*/
#define CONFIG_SYSTEM_UNLOCKED
#ifndef __ASSEMBLER__
#undef CONFIG_FLASH
/* Timer selection */
#define TIM_CLOCK32 5
#include "gpio_signal.h"
#endif /* !__ASSEMBLER__ */
#endif /* __CROS_EC_BOARD_H */

View File

@@ -0,0 +1,12 @@
# -*- makefile -*-
# Copyright 2016 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.
#
# Board specific files build
CHIP:=stm32
CHIP_FAMILY:=stm32f4
CHIP_VARIANT:=stm32f446
board-y=board.o

View File

@@ -0,0 +1,21 @@
/* Copyright 2016 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.
*/
/**
* List of enabled tasks in the priority order
*
* The first one has the lowest priority.
*
* For each task, use the macro TASK_ALWAYS(n, r, d, s) for base tasks and
* TASK_NOTEST(n, r, d, s) for tasks that can be excluded in test binaries,
* where :
* 'n' in the name of the task
* 'r' in the main routine of the task
* 'd' in an opaque parameter passed to the routine at startup
* 's' is the stack size in bytes; must be a multiple of 8
*/
#define CONFIG_TASK_LIST \
TASK_ALWAYS(HOOKS, hook_task, NULL, TASK_STACK_SIZE) \
TASK_ALWAYS(CONSOLE, console_task, NULL, VENTI_TASK_STACK_SIZE)

View File

@@ -0,0 +1,62 @@
/* -*- mode:c -*-
*
* Copyright 2016 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.
*/
/* Declare symbolic names for all the GPIOs that we care about.
* Note: Those with interrupt handlers must be declared first. */
/* Outputs */
GPIO(PD11, PIN(D, 11), GPIO_OUT_HIGH)
GPIO(I2C1_SCL, PIN(B, 8), GPIO_INPUT)
GPIO(I2C1_SDA, PIN(B, 9), GPIO_INPUT)
GPIO(FMPI2C_SCL, PIN(C, 6), GPIO_INPUT)
GPIO(FMPI2C_SDA, PIN(C, 7), GPIO_INPUT)
/* USART3 TX/RX */
GPIO(MCU_UART1_TX, PIN(A, 9), GPIO_INPUT)
GPIO(MCU_UART1_RX, PIN(A, 10), GPIO_INPUT)
GPIO(MCU_UART3_TX, PIN(C, 10), GPIO_INPUT)
GPIO(MCU_UART3_RX, PIN(C, 11), GPIO_INPUT)
GPIO(USB_FS_DM, PIN(A, 11), GPIO_INPUT)
GPIO(USB_FS_DP, PIN(A, 12), GPIO_INPUT)
GPIO(USB_HS_ULPI_NXT, PIN(C, 3), GPIO_INPUT)
GPIO(USB_HS_ULPI_DIR, PIN(C, 2), GPIO_INPUT)
GPIO(USB_HS_ULPI_STP, PIN(C, 0), GPIO_INPUT)
GPIO(USB_HS_ULPI_CK, PIN(A, 5), GPIO_INPUT)
GPIO(USB_HS_ULPI_D7, PIN(B, 5), GPIO_INPUT)
GPIO(USB_HS_ULPI_D6, PIN(B,13), GPIO_INPUT)
GPIO(USB_HS_ULPI_D5, PIN(B,12), GPIO_INPUT)
GPIO(USB_HS_ULPI_D4, PIN(B, 2), GPIO_INPUT)
GPIO(USB_HS_ULPI_D3, PIN(B,10), GPIO_INPUT)
GPIO(USB_HS_ULPI_D2, PIN(B, 1), GPIO_INPUT)
GPIO(USB_HS_ULPI_D1, PIN(B, 0), GPIO_INPUT)
GPIO(USB_HS_ULPI_D0, PIN(A, 3), GPIO_INPUT)
/* Unimplemented signals since this is a dev board */
UNIMPLEMENTED(ENTERING_RW)
UNIMPLEMENTED(WP_L)
ALTERNATE(PIN_MASK(A, 0x0600), 7, MODULE_UART, 0) /* USART1: PA9/PA10 - Console */
ALTERNATE(PIN_MASK(C, 0x0C00), 7, MODULE_USART, 0) /* USART3: PC10/PC11 - NOT Console */
ALTERNATE(PIN_MASK(A, 0x0100), 0, MODULE_MCO, 0) /* MCO1: PA8 */
ALTERNATE(PIN_MASK(C, 0x0200), 0, MODULE_MCO, 0) /* MCO2: PC9 */
ALTERNATE(PIN_MASK(B, 0x0300), 4, MODULE_I2C, GPIO_ODR_HIGH | GPIO_PULL_UP) /* I2C1: PB8-9 */
ALTERNATE(PIN_MASK(C, 0x00c0), 4, MODULE_I2C, GPIO_ODR_HIGH | GPIO_PULL_UP) /* FMPI2C MASTER:PC6/7 */
ALTERNATE(PIN_MASK(A, 0x1800), 10, MODULE_USB, 0) /* DWC USB OTG: PA11/12 */
/* OTG HS */
ALTERNATE(PIN_MASK(A, 0x0028), 10, MODULE_USB, 0) /* DWC USB OTG HS */
ALTERNATE(PIN_MASK(B, 0x3427), 10, MODULE_USB, 0) /* DWC USB OTG HS */
ALTERNATE(PIN_MASK(C, 0x000d), 10, MODULE_USB, 0) /* DWC USB OTG HS */

View File

@@ -28,8 +28,6 @@
/* PECI Time-out */
#define PECI_DONE_TIMEOUT_US (10*MSEC)
/* Task Event for PECI */
#define TASK_EVENT_PECI_DONE TASK_EVENT_CUSTOM(1<<26)
#define NULL_PENDING_TASK_ID 0xFFFFFFFF
#define PECI_MAX_FIFO_SIZE 16

View File

@@ -11,7 +11,7 @@ ifeq ($(CHIP_FAMILY),stm32f0)
CORE:=cortex-m0
# Force ARMv6-M ISA used by the Cortex-M0
CFLAGS_CPU+=-march=armv6-m -mcpu=cortex-m0
else ifeq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),stm32f3 stm32l4))
else ifeq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),stm32f3 stm32l4 stm32f4))
# STM32F3xx and STM32L4xx sub-family has a Cortex-M4 ARM core
CORE:=cortex-m
# Allow the full Cortex-M4 instruction set
@@ -25,10 +25,14 @@ endif
# Select between 16-bit and 32-bit timer for clock source
TIMER_TYPE=$(if $(CONFIG_STM_HWTIMER32),32,)
DMA_TYPE=$(if $(CHIP_FAMILY_STM32F4),-stm32f4,)
chip-y=dma.o
chip-$(CONFIG_DMA)+=dma$(DMA_TYPE).o
chip-$(CONFIG_COMMON_RUNTIME)+=system.o
chip-y+=jtag-$(CHIP_FAMILY).o clock-$(CHIP_FAMILY).o
ifeq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),stm32f0 stm32f3 stm32f4))
chip-y+=clock-f.o
endif
chip-$(CONFIG_SPI)+=spi.o
chip-$(CONFIG_SPI_MASTER)+=spi_master.o
chip-$(CONFIG_COMMON_GPIO)+=gpio.o gpio-$(CHIP_FAMILY).o

209
chip/stm32/clock-f.c Normal file
View File

@@ -0,0 +1,209 @@
/* Copyright 2016 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 "chipset.h"
#include "clock.h"
#include "clock-f.h"
#include "common.h"
#include "console.h"
#include "cpu.h"
#include "hooks.h"
#include "hwtimer.h"
#include "registers.h"
#include "system.h"
#include "task.h"
#include "timer.h"
#include "util.h"
/* Console output macros */
#define CPUTS(outstr) cputs(CC_CLOCK, outstr)
#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args)
/* Convert between RTC regs in BCD and seconds */
uint32_t rtc_to_sec(uint32_t rtc)
{
uint32_t sec;
/* convert the hours field */
sec = (((rtc & 0x300000) >> 20) * 10 + ((rtc & 0xf0000) >> 16)) * 3600;
/* convert the minutes field */
sec += (((rtc & 0x7000) >> 12) * 10 + ((rtc & 0xf00) >> 8)) * 60;
/* convert the seconds field */
sec += ((rtc & 0x70) >> 4) * 10 + (rtc & 0xf);
return sec;
}
uint32_t sec_to_rtc(uint32_t sec)
{
uint32_t rtc;
/* convert the hours field */
rtc = ((sec / 36000) << 20) | (((sec / 3600) % 10) << 16);
/* convert the minutes field */
rtc |= (((sec % 3600) / 600) << 12) | (((sec % 600) / 60) << 8);
/* convert the seconds field */
rtc |= (((sec % 60) / 10) << 4) | (sec % 10);
return rtc;
}
/* Return time diff between two rtc readings */
int32_t get_rtc_diff(uint32_t rtc0, uint32_t rtc0ss,
uint32_t rtc1, uint32_t rtc1ss)
{
int32_t diff;
/* Note: this only looks at the diff mod 10 seconds */
diff = ((rtc1 & 0xf) * SECOND +
rtcss_to_us(rtc1ss)) -
((rtc0 & 0xf) * SECOND +
rtcss_to_us(rtc0ss));
return (diff < 0) ? (diff + 10*SECOND) : diff;
}
void rtc_read(uint32_t *rtc, uint32_t *rtcss)
{
/* Read current time synchronously */
do {
*rtc = STM32_RTC_TR;
/*
* RTC_SSR must be read twice with identical values because
* glitches may occur for reads close to the RTCCLK edge.
*/
do {
*rtcss = STM32_RTC_SSR;
} while (*rtcss != STM32_RTC_SSR);
} while (*rtc != STM32_RTC_TR);
}
void set_rtc_alarm(uint32_t delay_s, uint32_t delay_us,
uint32_t *rtc, uint32_t *rtcss)
{
uint32_t alarm_sec, alarm_us;
/* Alarm must be within 1 day (86400 seconds) */
ASSERT((delay_s + delay_us / SECOND) < 86400);
rtc_unlock_regs();
/* Make sure alarm is disabled */
STM32_RTC_CR &= ~STM32_RTC_CR_ALRAE;
while (!(STM32_RTC_ISR & STM32_RTC_ISR_ALRAWF))
;
STM32_RTC_ISR &= ~STM32_RTC_ISR_ALRAF;
rtc_read(rtc, rtcss);
/* Calculate alarm time */
alarm_sec = rtc_to_sec(*rtc) + delay_s;
alarm_us = rtcss_to_us(*rtcss) + delay_us;
alarm_sec = alarm_sec + alarm_us / SECOND;
alarm_us = alarm_us % 1000000;
/*
* If seconds is greater than 1 day, subtract by 1 day to deal with
* 24-hour rollover.
*/
if (alarm_sec >= 86400)
alarm_sec -= 86400;
/* Set alarm time */
STM32_RTC_ALRMAR = sec_to_rtc(alarm_sec);
STM32_RTC_ALRMASSR = us_to_rtcss(alarm_us);
/* Check for match on hours, minutes, seconds, and subsecond */
STM32_RTC_ALRMAR |= 0xc0000000;
STM32_RTC_ALRMASSR |= 0x0f000000;
/* Enable alarm and alarm interrupt */
STM32_EXTI_PR = EXTI_RTC_ALR_EVENT;
STM32_EXTI_IMR |= EXTI_RTC_ALR_EVENT;
STM32_RTC_CR |= STM32_RTC_CR_ALRAE;
rtc_lock_regs();
}
void reset_rtc_alarm(uint32_t *rtc, uint32_t *rtcss)
{
rtc_unlock_regs();
/* Disable alarm */
STM32_RTC_CR &= ~STM32_RTC_CR_ALRAE;
STM32_RTC_ISR &= ~STM32_RTC_ISR_ALRAF;
/* Disable RTC alarm interrupt */
STM32_EXTI_IMR &= ~EXTI_RTC_ALR_EVENT;
STM32_EXTI_PR = EXTI_RTC_ALR_EVENT;
/* Read current time */
rtc_read(rtc, rtcss);
rtc_lock_regs();
}
void __rtc_alarm_irq(void)
{
uint32_t rtc, rtcss;
reset_rtc_alarm(&rtc, &rtcss);
}
DECLARE_IRQ(STM32_IRQ_RTC_ALARM, __rtc_alarm_irq, 1);
void clock_init(void)
{
/*
* The initial state :
* SYSCLK from HSI (=8MHz), no divider on AHB, APB1, APB2
* PLL unlocked, RTC enabled on LSE
*/
/*
* put 1 Wait-State for flash access to ensure proper reads at 48Mhz
* and enable prefetch buffer.
*/
/* Enable data and instruction cache. */
STM32_FLASH_ACR = STM32_FLASH_ACR_LATENCY | STM32_FLASH_ACR_PRFTEN;
config_hispeed_clock();
rtc_init();
}
/*****************************************************************************/
/* Console commands */
#ifdef CONFIG_CMD_RTC_ALARM
static int command_rtc_alarm_test(int argc, char **argv)
{
int s = 1, us = 0;
uint32_t rtc, rtcss;
char *e;
ccprintf("Setting RTC alarm\n");
if (argc > 1) {
s = strtoi(argv[1], &e, 10);
if (*e)
return EC_ERROR_PARAM1;
}
if (argc > 2) {
us = strtoi(argv[2], &e, 10);
if (*e)
return EC_ERROR_PARAM2;
}
set_rtc_alarm(s, us, &rtc, &rtcss);
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(rtc_alarm, command_rtc_alarm_test,
"[seconds [microseconds]]",
"Test alarm",
NULL);
#endif /* CONFIG_CMD_RTC_ALARM */

70
chip/stm32/clock-f.h Normal file
View File

@@ -0,0 +1,70 @@
/* Copyright 2016 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 */
#ifndef __CROS_EC_CLOCK_F_H
#define __CROS_EC_CLOCK_F_H
#include "chipset.h"
#include "clock.h"
#include "common.h"
#include "console.h"
#include "cpu.h"
#include "hooks.h"
#include "hwtimer.h"
#include "registers.h"
#include "system.h"
#include "task.h"
#include "timer.h"
#include "util.h"
/* Lock and unlock RTC write access */
static inline void rtc_lock_regs(void)
{
STM32_RTC_WPR = 0xff;
}
static inline void rtc_unlock_regs(void)
{
STM32_RTC_WPR = 0xca;
STM32_RTC_WPR = 0x53;
}
/* Convert between RTC regs in BCD and seconds */
uint32_t rtc_to_sec(uint32_t rtc);
/* Convert between seconds and RTC regs */
uint32_t sec_to_rtc(uint32_t sec);
/* Calculate microseconds from rtc clocks. */
int32_t rtcss_to_us(uint32_t rtcss);
/* Calculate rtc clocks from microseconds. */
uint32_t us_to_rtcss(int32_t us);
/* Return time diff between two rtc readings */
int32_t get_rtc_diff(uint32_t rtc0, uint32_t rtc0ss,
uint32_t rtc1, uint32_t rtc1ss);
/* Read RTC values */
void rtc_read(uint32_t *rtc, uint32_t *rtcss);
/* Set RTC wakeup */
void set_rtc_alarm(uint32_t delay_s, uint32_t delay_us,
uint32_t *rtc, uint32_t *rtcss);
/* Clear RTC wakeup */
void reset_rtc_alarm(uint32_t *rtc, uint32_t *rtcss);
/* RTC init */
void rtc_init(void);
/* Init clock blocks and finctionality */
void clock_init(void);
/* Init high speed clock config */
void config_hispeed_clock(void);
#endif /* __CROS_EC_CLOCK_F_H */

View File

@@ -7,6 +7,7 @@
#include "chipset.h"
#include "clock.h"
#include "clock-f.h"
#include "common.h"
#include "console.h"
#include "cpu.h"
@@ -74,147 +75,19 @@ static int dsleep_recovery_margin_us = 1000000;
#define RTC_PREDIV_A 1
#define US_PER_RTC_TICK (1000000 / RTC_FREQ)
/* Lock and unlock RTC write access */
static inline void rtc_lock_regs(void)
int32_t rtcss_to_us(uint32_t rtcss)
{
STM32_RTC_WPR = 0xff;
}
static inline void rtc_unlock_regs(void)
{
STM32_RTC_WPR = 0xca;
STM32_RTC_WPR = 0x53;
return ((RTC_PREDIV_S - rtcss) * US_PER_RTC_TICK);
}
/* Convert between RTC regs in BCD and seconds */
static inline uint32_t rtc_to_sec(uint32_t rtc)
uint32_t us_to_rtcss(int32_t us)
{
uint32_t sec;
/* convert the hours field */
sec = (((rtc & 0x300000) >> 20) * 10 + ((rtc & 0xf0000) >> 16)) * 3600;
/* convert the minutes field */
sec += (((rtc & 0x7000) >> 12) * 10 + ((rtc & 0xf00) >> 8)) * 60;
/* convert the seconds field */
sec += ((rtc & 0x70) >> 4) * 10 + (rtc & 0xf);
return sec;
}
static inline uint32_t sec_to_rtc(uint32_t sec)
{
uint32_t rtc;
/* convert the hours field */
rtc = ((sec / 36000) << 20) | (((sec / 3600) % 10) << 16);
/* convert the minutes field */
rtc |= (((sec % 3600) / 600) << 12) | (((sec % 600) / 60) << 8);
/* convert the seconds field */
rtc |= (((sec % 60) / 10) << 4) | (sec % 10);
return rtc;
return (RTC_PREDIV_S - (us / US_PER_RTC_TICK));
}
/* Return time diff between two rtc readings */
int32_t get_rtc_diff(uint32_t rtc0, uint32_t rtc0ss,
uint32_t rtc1, uint32_t rtc1ss)
{
int32_t diff;
/* Note: this only looks at the diff mod 10 seconds */
diff = ((rtc1 & 0xf) * SECOND +
(RTC_PREDIV_S - rtc1ss) * US_PER_RTC_TICK) -
((rtc0 & 0xf) * SECOND +
(RTC_PREDIV_S - rtc0ss) * US_PER_RTC_TICK);
return (diff < 0) ? (diff + 10*SECOND) : diff;
}
static inline void rtc_read(uint32_t *rtc, uint32_t *rtcss)
{
/* Read current time synchronously */
do {
*rtc = STM32_RTC_TR;
/*
* RTC_SSR must be read twice with identical values because
* glitches may occur for reads close to the RTCCLK edge.
*/
do {
*rtcss = STM32_RTC_SSR;
} while (*rtcss != STM32_RTC_SSR);
} while (*rtc != STM32_RTC_TR);
}
void set_rtc_alarm(uint32_t delay_s, uint32_t delay_us,
uint32_t *rtc, uint32_t *rtcss)
{
uint32_t alarm_sec, alarm_us;
/* Alarm must be within 1 day (86400 seconds) */
ASSERT((delay_s + delay_us / SECOND) < 86400);
rtc_unlock_regs();
/* Make sure alarm is disabled */
STM32_RTC_CR &= ~STM32_RTC_CR_ALRAE;
while (!(STM32_RTC_ISR & STM32_RTC_ISR_ALRAWF))
;
STM32_RTC_ISR &= ~STM32_RTC_ISR_ALRAF;
rtc_read(rtc, rtcss);
/* Calculate alarm time */
alarm_sec = rtc_to_sec(*rtc) + delay_s;
alarm_us = (RTC_PREDIV_S - *rtcss) * US_PER_RTC_TICK + delay_us;
alarm_sec = alarm_sec + alarm_us / SECOND;
alarm_us = alarm_us % 1000000;
/*
* If seconds is greater than 1 day, subtract by 1 day to deal with
* 24-hour rollover.
*/
if (alarm_sec >= 86400)
alarm_sec -= 86400;
/* Set alarm time */
STM32_RTC_ALRMAR = sec_to_rtc(alarm_sec);
STM32_RTC_ALRMASSR = RTC_PREDIV_S - (alarm_us / US_PER_RTC_TICK);
/* Check for match on hours, minutes, seconds, and subsecond */
STM32_RTC_ALRMAR |= 0xc0000000;
STM32_RTC_ALRMASSR |= 0x0f000000;
/* Enable alarm and alarm interrupt */
STM32_EXTI_PR = EXTI_RTC_ALR_EVENT;
STM32_EXTI_IMR |= EXTI_RTC_ALR_EVENT;
STM32_RTC_CR |= STM32_RTC_CR_ALRAE;
rtc_lock_regs();
}
void reset_rtc_alarm(uint32_t *rtc, uint32_t *rtcss)
{
rtc_unlock_regs();
/* Disable alarm */
STM32_RTC_CR &= ~STM32_RTC_CR_ALRAE;
STM32_RTC_ISR &= ~STM32_RTC_ISR_ALRAF;
/* Disable RTC alarm interrupt */
STM32_EXTI_IMR &= ~EXTI_RTC_ALR_EVENT;
STM32_EXTI_PR = EXTI_RTC_ALR_EVENT;
/* Read current time */
rtc_read(rtc, rtcss);
rtc_lock_regs();
}
void __rtc_alarm_irq(void)
{
uint32_t rtc, rtcss;
reset_rtc_alarm(&rtc, &rtcss);
}
DECLARE_IRQ(STM32_IRQ_RTC_ALARM, __rtc_alarm_irq, 1);
static void config_hispeed_clock(void)
void config_hispeed_clock(void)
{
#ifdef CHIP_FAMILY_STM32F3
/* Ensure that HSE is ON */
@@ -517,58 +390,6 @@ void rtc_init(void)
rtc_lock_regs();
}
void clock_init(void)
{
/*
* The initial state :
* SYSCLK from HSI (=8MHz), no divider on AHB, APB1, APB2
* PLL unlocked, RTC enabled on LSE
*/
/*
* put 1 Wait-State for flash access to ensure proper reads at 48Mhz
* and enable prefetch buffer.
*/
STM32_FLASH_ACR = STM32_FLASH_ACR_LATENCY | STM32_FLASH_ACR_PRFTEN;
config_hispeed_clock();
rtc_init();
}
/*****************************************************************************/
/* Console commands */
#ifdef CONFIG_CMD_RTC_ALARM
static int command_rtc_alarm_test(int argc, char **argv)
{
int s = 1, us = 0;
uint32_t rtc, rtcss;
char *e;
ccprintf("Setting RTC alarm\n");
if (argc > 1) {
s = strtoi(argv[1], &e, 10);
if (*e)
return EC_ERROR_PARAM1;
}
if (argc > 2) {
us = strtoi(argv[2], &e, 10);
if (*e)
return EC_ERROR_PARAM2;
}
set_rtc_alarm(s, us, &rtc, &rtcss);
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(rtc_alarm, command_rtc_alarm_test,
"[seconds [microseconds]]",
"Test alarm",
NULL);
#endif /* CONFIG_CMD_RTC_ALARM */
#if defined(CONFIG_LOW_POWER_IDLE) && defined(CONFIG_COMMON_RUNTIME)
#ifdef CONFIG_CMD_IDLE_STATS
@@ -595,4 +416,3 @@ DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats,
NULL);
#endif /* CONFIG_CMD_IDLE_STATS */
#endif

254
chip/stm32/clock-stm32f4.c Normal file
View File

@@ -0,0 +1,254 @@
/* Copyright 2016 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 "chipset.h"
#include "clock.h"
#include "clock-f.h"
#include "common.h"
#include "console.h"
#include "cpu.h"
#include "hooks.h"
#include "hwtimer.h"
#include "registers.h"
#include "system.h"
#include "task.h"
#include "timer.h"
#include "util.h"
/* Console output macros */
#define CPUTS(outstr) cputs(CC_CLOCK, outstr)
#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args)
#ifdef CONFIG_STM32_CLOCK_HSE_HZ
#define RTC_PREDIV_A 39
#define RTC_FREQ ((STM32F4_RTC_REQ) / (RTC_PREDIV_A + 1)) /* Hz */
#else
/* LSI clock is 40kHz-ish */
#define RTC_PREDIV_A 1
#define RTC_FREQ (40000 / (RTC_PREDIV_A + 1)) /* Hz */
#endif
#define RTC_PREDIV_S (RTC_FREQ - 1)
#define US_PER_RTC_TICK (1000000 / RTC_FREQ)
int32_t rtcss_to_us(uint32_t rtcss)
{
return ((RTC_PREDIV_S - rtcss) * US_PER_RTC_TICK);
}
uint32_t us_to_rtcss(int32_t us)
{
return (RTC_PREDIV_S - (us / US_PER_RTC_TICK));
}
static void wait_for_ready(volatile uint32_t *cr_reg,
uint32_t enable, uint32_t ready)
{
/* Ensure that clock source is ON */
if (!(*cr_reg & ready)) {
/* Enable clock */
*cr_reg |= enable;
/* Wait for ready */
while (!(*cr_reg & ready))
;
}
}
void config_hispeed_clock(void)
{
#ifdef CONFIG_STM32_CLOCK_HSE_HZ
int srcclock = CONFIG_STM32_CLOCK_HSE_HZ;
int clk_check_mask = STM32_RCC_CR_HSERDY;
int clk_enable_mask = STM32_RCC_CR_HSEON;
#else
int srcclock = STM32F4_HSI_CLOCK;
int clk_check_mask = STM32_RCC_CR_HSIRDY;
int clk_enable_mask = STM32_RCC_CR_HSION;
#endif
int plldiv, pllinputclock;
int pllmult, vcoclock;
int systemdivq, systemclock;
int usbdiv;
int i2sdiv;
int ahbpre, apb1pre, apb2pre;
int rtcdiv = 0;
/* If PLL is the clock source, PLL has already been set up. */
if ((STM32_RCC_CFGR & STM32_RCC_CFGR_SWS_MASK) ==
STM32_RCC_CFGR_SWS_PLL)
return;
/* Ensure that HSE/HSI is ON */
wait_for_ready(&(STM32_RCC_CR), clk_enable_mask, clk_check_mask);
/* PLL input must be between 1-2MHz, near 2 */
/* Valid values 2-63 */
plldiv = (srcclock + STM32F4_PLL_REQ - 1) / STM32F4_PLL_REQ;
pllinputclock = srcclock / plldiv;
/* PLL output clock: Must be 100-432MHz */
/* Valid values 50-432, we'll get 336MHz */
pllmult = (STM32F4_VCO_CLOCK + (pllinputclock / 2)) / pllinputclock;
vcoclock = pllinputclock * pllmult;
/* CPU/System clock: Below 180MHz */
/* We'll do 84MHz */
systemclock = vcoclock / 4;
systemdivq = 1;
/* USB clock = 48MHz exactly */
usbdiv = (vcoclock + (STM32F4_USB_REQ / 2)) / STM32F4_USB_REQ;
/* SYSTEM/I2S: same system clock */
i2sdiv = (vcoclock + (systemclock / 2)) / systemclock;
/* All IO clocks at 42MHz */
/* AHB Prescalar */
ahbpre = 0x8; /* AHB = system clock / 2*/
/* NOTE: If apbXpre is not 0, timers are x2 clocked. RM0390 Fig. 13 */
apb1pre = 0; /* APB1 = AHB */
apb2pre = 0; /* APB2 = AHB */
#ifdef CONFIG_STM32_CLOCK_HSE_HZ
/* RTC clock = 1MHz */
rtcdiv = (CONFIG_STM32_CLOCK_HSE_HZ + (STM32F4_RTC_REQ / 2))
/ STM32F4_RTC_REQ;
#endif
/* Switch SYSCLK to PLL, setup prescalars.
* EC codebase doesn't understand multiple clock domains
* so we enforce a clock config that keeps AHB = APB1 = APB2
* allowing ec codebase assumptions about consistent clock
* rates to remain true.
*
* NOTE: Sweetberry requires MCO2 <- HSE @ 24MHz
* MCO outputs are selected here but are not changeable later.
* A CONFIG may be needed if other boards have different MCO
* requirements.
*/
STM32_RCC_CFGR =
(2 << 30) | /* MCO2 <- HSE */
(0 << 27) | /* MCO2 div / 4 */
(6 << 24) | /* MCO1 div / 4 */
(3 << 21) | /* MCO1 <- PLL */
CFGR_RTCPRE(rtcdiv) |
CFGR_PPRE2(apb2pre) |
CFGR_PPRE1(apb1pre) |
CFGR_HPRE(ahbpre) |
STM32_RCC_CFGR_SW_PLL;
/* Set up PLL */
STM32_RCC_PLLCFGR =
PLLCFGR_PLLM(plldiv) |
PLLCFGR_PLLN(pllmult) |
PLLCFGR_PLLP(systemdivq) |
#if defined(CONFIG_STM32_CLOCK_HSE_HZ)
PLLCFGR_PLLSRC_HSE |
#else
PLLCFGR_PLLSRC_HSI |
#endif
PLLCFGR_PLLQ(usbdiv) |
PLLCFGR_PLLR(i2sdiv);
wait_for_ready(&(STM32_RCC_CR),
STM32_RCC_CR_PLLON, STM32_RCC_CR_PLLRDY);
/* Wait until the PLL is the clock source */
if ((STM32_RCC_CFGR & STM32_RCC_CFGR_SWS_MASK) ==
STM32_RCC_CFGR_SWS_PLL)
;
/* Setup RTC Clock input */
STM32_RCC_BDCR |= STM32_RCC_BDCR_BDRST;
#ifdef CONFIG_STM32_CLOCK_HSE_HZ
STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BCDR_RTCSEL(BDCR_SRC_HSE);
#else
/* Ensure that LSI is ON */
wait_for_ready(&(STM32_RCC_CSR),
STM32_RCC_CSR_LSION, STM32_RCC_CSR_LSIRDY);
STM32_RCC_BDCR = STM32_RCC_BDCR_RTCEN | BCDR_RTCSEL(BDCR_SRC_LSI);
#endif
}
int clock_get_freq(void)
{
return STM32F4_IO_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_DMA_GET_ISR(0);
} else { /* APB */
while (cycles--)
dummy = STM32_USART_BRR(STM32_USART1_BASE);
}
}
void clock_enable_module(enum module_id module, int enable)
{
if (module == MODULE_USB) {
if (enable) {
STM32_RCC_AHB2ENR |= STM32_RCC_AHB2ENR_OTGFSEN;
STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_OTGHSEN |
STM32_RCC_AHB1ENR_OTGHSULPIEN;
} else {
STM32_RCC_AHB2ENR &= ~STM32_RCC_AHB2ENR_OTGFSEN;
STM32_RCC_AHB1ENR &= ~STM32_RCC_AHB1ENR_OTGHSEN &
~STM32_RCC_AHB1ENR_OTGHSULPIEN;
}
return;
} else if (module == MODULE_I2C) {
if (enable) {
/* Enable clocks to I2C modules if necessary */
STM32_RCC_APB1ENR |=
STM32_RCC_I2C1EN | STM32_RCC_I2C2EN
| STM32_RCC_I2C3EN | STM32_RCC_FMPI2C4EN;
STM32_RCC_DCKCFGR2 =
(STM32_RCC_DCKCFGR2 & ~DCKCFGR2_FMPI2C1SEL_MASK)
| DCKCFGR2_FMPI2C1SEL(FMPI2C1SEL_APB);
} else {
STM32_RCC_APB1ENR &=
~(STM32_RCC_I2C1EN | STM32_RCC_I2C2EN |
STM32_RCC_I2C3EN | STM32_RCC_FMPI2C4EN);
}
return;
}
CPRINTS("Module %d is not supported for clock %s\n",
module, enable ? "enable" : "disable");
}
void rtc_init(void)
{
rtc_unlock_regs();
/* Enter RTC initialize mode */
STM32_RTC_ISR |= STM32_RTC_ISR_INIT;
while (!(STM32_RTC_ISR & STM32_RTC_ISR_INITF))
;
/* Set clock prescalars: Needs two separate writes. */
STM32_RTC_PRER =
(STM32_RTC_PRER & ~STM32_RTC_PRER_S_MASK) | RTC_PREDIV_S;
STM32_RTC_PRER =
(STM32_RTC_PRER & ~STM32_RTC_PRER_A_MASK)
| (RTC_PREDIV_A << 16);
/* Start RTC timer */
STM32_RTC_ISR &= ~STM32_RTC_ISR_INIT;
while (STM32_RTC_ISR & STM32_RTC_ISR_INITF)
;
/* Enable RTC alarm interrupt */
STM32_RTC_CR |= STM32_RTC_CR_ALRAIE | STM32_RTC_CR_BYPSHAD;
STM32_EXTI_RTSR |= EXTI_RTC_ALR_EVENT;
task_enable_irq(STM32_IRQ_RTC_ALARM);
rtc_lock_regs();
}

View File

@@ -0,0 +1,63 @@
/* Copyright 2016 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 */
/* Flash physical size is: (512 * 1024)
* We are limiting the ec.bin size to 128k to reduce flashing time.
*/
#define CONFIG_FLASH_SIZE (128 * 1024)
#define CONFIG_FLASH_BANK_SIZE (16 * 1024)
/*
* 8 "erase" sectors : 16KB/16KB/16KB/16KB/64KB/128KB/128KB/128KB
* We won't use CONFIG_FLASH_ERASE_SIZE, it will be programmatically
* set in flash-stm32f4.c. However it must be set or the common flash
* code won't build. So we'll set it here.
*/
#define CONFIG_FLASH_ERASE_SIZE (16 * 1024)
/* minimum write size for 3.3V. 1 for 1.8V */
#define FLASH_WRITE_SIZE_1800 0x0001
#define FLASH_WS_DIV_1800 16000000
#define FLASH_WRITE_SIZE_3300 0x0004
#define FLASH_WS_DIV_3300 30000000
#define FLASH_WRITE_SIZE 0x0004
#define CONFIG_FLASH_WRITE_SIZE FLASH_WRITE_SIZE
/* No page mode on STM32F, so no benefit to larger write sizes */
#define CONFIG_FLASH_WRITE_IDEAL_SIZE FLASH_WRITE_SIZE
#define CONFIG_RAM_BASE 0x20000000
#define CONFIG_RAM_SIZE 0x00020000
#define CONFIG_RO_MEM_OFF 0
#define CONFIG_RO_SIZE (48 * 1024)
#define CONFIG_RW_MEM_OFF (64 * 1024)
#define CONFIG_RW_SIZE (64 * 1024)
#define CONFIG_RO_STORAGE_OFF 0
#define CONFIG_RW_STORAGE_OFF 0
#define CONFIG_EC_PROTECTED_STORAGE_OFF 0
#define CONFIG_EC_PROTECTED_STORAGE_SIZE CONFIG_RW_MEM_OFF
#define CONFIG_EC_WRITABLE_STORAGE_OFF CONFIG_RW_MEM_OFF
#define CONFIG_EC_WRITABLE_STORAGE_SIZE \
(CONFIG_FLASH_SIZE - CONFIG_EC_WRITABLE_STORAGE_OFF)
#define CONFIG_WP_STORAGE_OFF CONFIG_EC_PROTECTED_STORAGE_OFF
#define CONFIG_WP_STORAGE_SIZE CONFIG_EC_PROTECTED_STORAGE_SIZE
/* PSTATE lives in one of the smaller blocks. */
#define CONFIG_FLASH_PSTATE
#define CONFIG_FW_PSTATE_SIZE (16 * 1024)
#define CONFIG_FW_PSTATE_OFF (CONFIG_RO_SIZE)
#undef I2C_PORT_COUNT
#define I2C_PORT_COUNT 4
/* Number of IRQ vectors on the NVIC */
#define CONFIG_IRQ_COUNT 97

View File

@@ -23,12 +23,17 @@
#define CHIP_VARIANT_STM32F03X
#endif
/* Number of I2C ports, can be overridden in variant */
#define I2C_PORT_COUNT 2
#if defined(CHIP_VARIANT_STM32L476)
#include "config-stm32l476.h"
#elif defined(CHIP_VARIANT_STM32L15X)
#include "config-stm32l15x.h"
#elif defined(CHIP_VARIANT_STM32L100)
#include "config-stm32l100.h"
#elif defined(CHIP_VARIANT_STM32F446)
#include "config-stm32f446.h"
#elif defined(CHIP_VARIANT_STM32F373)
#include "config-stm32f373.h"
#elif defined(CHIP_VARIANT_STM32F09X)
@@ -56,8 +61,10 @@
/* Program is run directly from storage */
#define CONFIG_MAPPED_STORAGE_BASE CONFIG_PROGRAM_MEMORY_BASE
#if !defined(CHIP_VARIANT_STM32F446)
/* Compute the rest of the flash params from these */
#include "config_std_internal_flash.h"
#endif
/* System stack size */
#if defined(CHIP_VARIANT_STM32F05X)
@@ -85,9 +92,6 @@
#define HOOK_TICK_INTERVAL_MS 500
#define HOOK_TICK_INTERVAL (HOOK_TICK_INTERVAL_MS * MSEC)
/* Number of I2C ports */
#define I2C_PORT_COUNT 2
/*
* Use a timer to print a watchdog warning event before the actual watchdog
* timer fires. This is needed on STM32, where the independent watchdog has no

308
chip/stm32/dma-stm32f4.c Normal file
View File

@@ -0,0 +1,308 @@
/* Copyright 2016 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 "common.h"
#include "console.h"
#include "dma.h"
#include "hooks.h"
#include "registers.h"
#include "task.h"
#include "timer.h"
#include "util.h"
/* Console output macros */
#define CPUTS(outstr) cputs(CC_DMA, outstr)
#define CPRINTF(format, args...) cprintf(CC_DMA, format, ## args)
stm32_dma_regs_t *STM32_DMA_REGS[] = { STM32_DMA1_REGS, STM32_DMA2_REGS };
/* Callback data to use when IRQ fires */
static struct {
void (*cb)(void *); /* Callback function to call */
void *cb_data; /* Callback data for callback function */
} dma_irq[STM32_DMAS_TOTAL_COUNT];
/**
* Return the IRQ for the DMA stream
*
* @param stream stream number
* @return IRQ for the stream
*/
static int dma_get_irq(enum dma_channel stream)
{
if (stream < STM32_DMA1_STREAM6)
return STM32_IRQ_DMA1_STREAM0 + stream;
if (stream == STM32_DMA1_STREAM7)
return STM32_IRQ_DMA1_STREAM7;
if (stream < STM32_DMA2_STREAM5)
return STM32_IRQ_DMA2_STREAM0 + stream - STM32_DMA2_STREAM0;
else
return STM32_IRQ_DMA2_STREAM5 + stream - STM32_DMA2_STREAM5;
}
stm32_dma_regs_t *dma_get_ctrl(enum dma_channel stream)
{
return STM32_DMA_REGS[stream / STM32_DMAS_COUNT];
}
stm32_dma_stream_t *dma_get_channel(enum dma_channel stream)
{
stm32_dma_regs_t *dma = dma_get_ctrl(stream);
return &dma->stream[stream % STM32_DMAS_COUNT];
}
void dma_disable(enum dma_channel ch)
{
stm32_dma_stream_t *stream = dma_get_channel(ch);
if (stream->scr & STM32_DMA_CCR_EN) {
stream->scr &= ~STM32_DMA_CCR_EN;
while (stream->scr & STM32_DMA_CCR_EN)
;
}
}
void dma_disable_all(void)
{
int ch;
for (ch = 0; ch < STM32_DMAS_TOTAL_COUNT; ch++)
dma_disable(ch);
}
/**
* Prepare a stream for use and start it
*
* @param stream stream to read
* @param count Number of bytes to transfer
* @param periph Pointer to peripheral data register
* @param memory Pointer to memory address for receive/transmit
* @param flags DMA flags for the control register.
*/
static void prepare_stream(enum dma_channel stream, unsigned count,
void *periph, void *memory, unsigned flags)
{
stm32_dma_stream_t *dma_stream = dma_get_channel(stream);
uint32_t ccr = STM32_DMA_CCR_PL_VERY_HIGH;
dma_disable(stream);
dma_clear_isr(stream);
/* Following the order in DocID026448 Rev 1 (RM0383) p181 */
dma_stream->spar = (uint32_t)periph;
dma_stream->sm0ar = (uint32_t)memory;
dma_stream->sndtr = count;
dma_stream->scr = ccr;
ccr |= flags & STM32_DMA_CCR_CHANNEL_MASK;
dma_stream->scr = ccr;
dma_stream->sfcr &= ~STM32_DMA_SFCR_DMDIS;
ccr |= flags;
dma_stream->scr = ccr;
}
void dma_go(stm32_dma_stream_t *stream)
{
/* Flush data in write buffer so that DMA can get the lastest data */
asm volatile("dsb;");
/* Fire it up */
stream->scr |= STM32_DMA_CCR_EN;
}
void dma_prepare_tx(const struct dma_option *option, unsigned count,
const void *memory)
{
/*
* Cast away const for memory pointer; this is ok because we know
* we're preparing the stream for transmit.
*/
prepare_stream(option->channel, count, option->periph, (void *)memory,
STM32_DMA_CCR_MINC | STM32_DMA_CCR_DIR_M2P |
option->flags);
}
void dma_start_rx(const struct dma_option *option, unsigned count,
void *memory)
{
stm32_dma_stream_t *stream = dma_get_channel(option->channel);
prepare_stream(option->channel, count, option->periph, memory,
STM32_DMA_CCR_MINC | STM32_DMA_CCR_DIR_P2M |
option->flags);
dma_go(stream);
}
int dma_bytes_done(stm32_dma_stream_t *stream, int orig_count)
{
if (!(stream->scr & STM32_DMA_CCR_EN))
return 0;
return orig_count - stream->sndtr;
}
#ifdef CONFIG_DMA_HELP
void dma_dump(enum dma_channel stream)
{
stm32_dma_stream_t *dma_stream = dma_get_channel(stream);
CPRINTF("scr=%x, sndtr=%x, spar=%x, sm0ar=%x, sfcr=%x\n",
dma_stream->scr, dma_stream->sndtr, dma_stream->spar,
dma_stream->sm0ar, dma_stream->sfcr);
CPRINTF("stream %d, isr=%x, ifcr=%x\n",
stream,
STM32_DMA_GET_ISR(stream),
STM32_DMA_GET_IFCR(stream));
}
void dma_check(enum dma_channel stream, char *buf)
{
stm32_dma_stream_t *dma_stream = dma_get_channel(stream);
int count;
int i;
count = dma_stream->sndtr;
CPRINTF("c=%d\n", count);
udelay(100 * MSEC);
CPRINTF("c=%d\n", dma_stream->sndtr);
for (i = 0; i < count; i++)
CPRINTF("%02x ", buf[i]);
udelay(100 * MSEC);
CPRINTF("c=%d\n", dma_stream->sndtr);
for (i = 0; i < count; i++)
CPRINTF("%02x ", buf[i]);
}
/* Run a check of memory-to-memory DMA */
void dma_test(enum dma_channel stream)
{
stm32_dma_stream_t *dma_stream = dma_get_channel(stream);
uint32_t ctrl;
char periph[32], memory[32];
unsigned count = sizeof(periph);
int i;
memset(memory, '\0', sizeof(memory));
for (i = 0; i < count; i++)
periph[i] = 10 + i;
dma_clear_isr(stream);
/* Following the order in Doc ID 15965 Rev 5 p194 */
dma_stream->spar = (uint32_t)periph;
dma_stream->sm0ar = (uint32_t)memory;
dma_stream->sndtr = count;
dma_stream->sfcr &= ~STM32_DMA_SFCR_DMDIS;
ctrl = STM32_DMA_CCR_PL_MEDIUM;
dma_stream->scr = ctrl;
ctrl |= STM32_DMA_CCR_MINC;
ctrl |= STM32_DMA_CCR_DIR_M2M;
ctrl |= STM32_DMA_CCR_PINC;
dma_stream->scr = ctrl;
dma_dump(stream);
dma_stream->scr = ctrl | STM32_DMA_CCR_EN;
for (i = 0; i < count; i++)
CPRINTF("%d/%d ", periph[i], memory[i]);
CPRINTF("\ncount=%d\n", dma_stream->sndtr);
dma_dump(stream);
}
#endif /* CONFIG_DMA_HELP */
void dma_init(void)
{
STM32_RCC_AHB1ENR |= STM32_RCC_HB1_DMA1 | STM32_RCC_HB1_DMA2;
}
int dma_wait(enum dma_channel stream)
{
timestamp_t deadline;
deadline.val = get_time().val + DMA_TRANSFER_TIMEOUT_US;
while ((STM32_DMA_GET_ISR(stream) & STM32_DMA_TCIF) == 0) {
if (deadline.val <= get_time().val)
return EC_ERROR_TIMEOUT;
udelay(DMA_POLLING_INTERVAL_US);
}
return EC_SUCCESS;
}
static inline void _dma_wake_callback(void *cb_data)
{
task_id_t id = (task_id_t)(int)cb_data;
if (id != TASK_ID_INVALID)
task_set_event(id, TASK_EVENT_DMA_TC, 0);
}
void dma_enable_tc_interrupt(enum dma_channel stream)
{
dma_enable_tc_interrupt_callback(stream, _dma_wake_callback,
(void *)(int)task_get_current());
}
void dma_enable_tc_interrupt_callback(enum dma_channel stream,
void (*callback)(void *),
void *callback_data)
{
stm32_dma_stream_t *dma_stream = dma_get_channel(stream);
dma_irq[stream].cb = callback;
dma_irq[stream].cb_data = callback_data;
dma_stream->scr |= STM32_DMA_CCR_TCIE;
task_enable_irq(dma_get_irq(stream));
}
void dma_disable_tc_interrupt(enum dma_channel stream)
{
stm32_dma_stream_t *dma_stream = dma_get_channel(stream);
dma_stream->scr &= ~STM32_DMA_CCR_TCIE;
task_disable_irq(dma_get_irq(stream));
dma_irq[stream].cb = NULL;
dma_irq[stream].cb_data = NULL;
}
void dma_clear_isr(enum dma_channel stream)
{
STM32_DMA_SET_IFCR(stream, STM32_DMA_ALL);
}
#ifdef CONFIG_DMA_DEFAULT_HANDLERS
#define STM32_DMA_IDX(dma, x) CONCAT4(STM32_DMA, dma, _STREAM, x)
#define STM32_DMA_FCT(dma, x) CONCAT4(dma_, dma, _event_interrupt_stream_, x)
#define DECLARE_DMA_IRQ(dma, x) \
void STM32_DMA_FCT(dma, x)(void) \
{ \
dma_clear_isr(STM32_DMA_IDX(dma, x)); \
if (dma_irq[STM32_DMA_IDX(dma, x)].cb != NULL) \
(*dma_irq[STM32_DMA_IDX(dma, x)].cb) \
(dma_irq[STM32_DMA_IDX(dma, x)].cb_data); \
} \
DECLARE_IRQ(CONCAT4(STM32_IRQ_DMA, dma, _STREAM, x), \
STM32_DMA_FCT(dma, x), 1);
DECLARE_DMA_IRQ(1, 0);
DECLARE_DMA_IRQ(1, 1);
DECLARE_DMA_IRQ(1, 2);
DECLARE_DMA_IRQ(1, 3);
DECLARE_DMA_IRQ(1, 4);
DECLARE_DMA_IRQ(1, 5);
DECLARE_DMA_IRQ(1, 6);
DECLARE_DMA_IRQ(1, 7);
DECLARE_DMA_IRQ(2, 0);
DECLARE_DMA_IRQ(2, 1);
DECLARE_DMA_IRQ(2, 2);
DECLARE_DMA_IRQ(2, 3);
DECLARE_DMA_IRQ(2, 4);
DECLARE_DMA_IRQ(2, 5);
DECLARE_DMA_IRQ(2, 6);
DECLARE_DMA_IRQ(2, 7);
#endif /* CONFIG_DMA_DEFAULT_HANDLERS */

View File

@@ -73,6 +73,20 @@ void dma_select_channel(enum dma_channel channel, unsigned char stream)
val = STM32_DMA_CSELR(channel) & ~(mask << ch * shift);
STM32_DMA_CSELR(channel) = val | (stream << ch * shift);
}
#elif defined(CHIP_FAMILY_STM32F4)
void dma_select_channel(enum dma_channel channel, unsigned char stream)
{
stm32_dma_chan_t *chan = dma_get_channel(channel);
uint32_t val;
ASSERT(channel < STM32_DMAC_COUNT);
ASSERT(stream < STM32_DMA_MAX_STREAMS);
/* Set stream input for channel */
val = chan->ccr &
~(STM32_DMA_CCR_CHMASK << STM32_DMA_CCR_CHOFF);
chan->ccr = val | (stream << STM32_DMA_CCR_CHOFF);
}
#endif
void dma_disable(enum dma_channel channel)
@@ -230,7 +244,7 @@ void dma_test(enum dma_channel channel)
void dma_init(void)
{
#ifdef CHIP_FAMILY_STM32L4
#if defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32F4)
STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_DMA1EN|STM32_RCC_AHB1ENR_DMA2EN;
#else
STM32_RCC_AHBENR |= STM32_RCC_HB_DMA1;
@@ -244,6 +258,19 @@ void dma_init(void)
int dma_wait(enum dma_channel channel)
{
#if defined(CHIP_FAMILY_STM32F4)
timestamp_t deadline;
deadline.val = get_time().val + DMA_TRANSFER_TIMEOUT_US;
/* Wait for TCIF completion */
while ((STM32_DMA_GET_ISR(channel) & STM32_DMA_TCIF) == 0) {
if (deadline.val <= get_time().val)
return EC_ERROR_TIMEOUT;
udelay(DMA_POLLING_INTERVAL_US);
}
#else
stm32_dma_regs_t *dma = STM32_DMA_REGS(channel);
const uint32_t mask = STM32_DMA_ISR_TCIF(channel);
timestamp_t deadline;
@@ -255,6 +282,7 @@ int dma_wait(enum dma_channel channel)
udelay(DMA_POLLING_INTERVAL_US);
}
#endif
return EC_SUCCESS;
}
@@ -297,9 +325,13 @@ void dma_disable_tc_interrupt(enum dma_channel channel)
void dma_clear_isr(enum dma_channel channel)
{
#if defined(CHIP_FAMILY_STM32F4)
STM32_DMA_SET_IFCR(channel, STM32_DMA_ALL);
#else
stm32_dma_regs_t *dma = STM32_DMA_REGS(channel);
dma->ifcr |= STM32_DMA_ISR_ALL(channel);
#endif
}
#ifdef CONFIG_DMA_DEFAULT_HANDLERS

View File

@@ -7,6 +7,7 @@
#include "battery.h"
#include "console.h"
#include "clock.h"
#include "flash.h"
#include "hooks.h"
#include "registers.h"
@@ -25,8 +26,6 @@
/* Flash page programming timeout. This is 2x the datasheet max. */
#define FLASH_TIMEOUT_US 16000
#define FLASH_TIMEOUT_LOOP \
(FLASH_TIMEOUT_US * (CPU_CLOCK / SECOND) / CYCLE_PER_FLASH_LOOP)
/* Flash unlocking keys */
#define KEY1 0x45670123
@@ -44,9 +43,15 @@
static int write_optb(int byte, uint8_t value);
static inline int calculate_flash_timeout(void)
{
return (FLASH_TIMEOUT_US *
(clock_get_freq() / SECOND) / CYCLE_PER_FLASH_LOOP);
}
static int wait_busy(void)
{
int timeout = FLASH_TIMEOUT_LOOP;
int timeout = calculate_flash_timeout();
while (STM32_FLASH_SR & (1 << 0) && timeout-- > 0)
udelay(CYCLE_PER_FLASH_LOOP);
return (timeout > 0) ? EC_SUCCESS : EC_ERROR_TIMEOUT;
@@ -207,6 +212,7 @@ int flash_physical_write(int offset, int size, const char *data)
{
uint16_t *address = (uint16_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset);
int res = EC_SUCCESS;
int timeout = calculate_flash_timeout();
int i;
if (unlock(PRG_LOCK) != EC_SUCCESS) {
@@ -228,7 +234,7 @@ int flash_physical_write(int offset, int size, const char *data)
watchdog_reload();
/* wait to be ready */
for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP);
for (i = 0; (STM32_FLASH_SR & 1) && (i < timeout);
i++)
;
@@ -237,7 +243,7 @@ int flash_physical_write(int offset, int size, const char *data)
data += 2;
/* Wait for writes to complete */
for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP);
for (i = 0; (STM32_FLASH_SR & 1) && (i < timeout);
i++)
;

384
chip/stm32/flash-stm32f4.c Normal file
View File

@@ -0,0 +1,384 @@
/* Copyright 2016 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 stm32f4 */
#include "clock.h"
#include "compile_time_macros.h"
#include "console.h"
#include "common.h"
#include "flash.h"
#include "hooks.h"
#include "registers.h"
#include "system.h"
#include "panic.h"
#include "watchdog.h"
#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args)
/*
* Approximate number of CPU cycles per iteration of the loop when polling
* the flash status
*/
#define CYCLE_PER_FLASH_LOOP 10
/* Flash page programming timeout. This is 2x the datasheet max. */
#define FLASH_TIMEOUT_US 16000
static inline int calculate_flash_timeout(void)
{
return (FLASH_TIMEOUT_US *
(clock_get_freq() / SECOND) / CYCLE_PER_FLASH_LOOP);
}
/* 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 */
struct flash_wp_state {
int entire_flash_locked;
};
/*****************************************************************************/
/* Physical layer APIs */
/* Flash unlocking keys */
#define PRG_LOCK 0
#define KEY1 0x45670123
#define KEY2 0xCDEF89AB
static int unlock(void)
{
/*
* We may have already locked the flash module and get a bus fault
* in the attempt to unlock. Need to disable bus fault handler now.
*/
ignore_bus_fault(1);
/* unlock CR if needed */
if (STM32_FLASH_CR & FLASH_CR_LOCK) {
STM32_FLASH_KEYR = KEY1;
STM32_FLASH_KEYR = KEY2;
}
/* Re-enable bus fault handler */
ignore_bus_fault(0);
return (STM32_FLASH_CR & FLASH_CR_LOCK) ?
EC_ERROR_UNKNOWN : EC_SUCCESS;
}
static void lock(void)
{
STM32_FLASH_CR = FLASH_CR_LOCK;
}
int flash_physical_get_protect(int block)
{
/* TODO: not sure if write protect can be implemented like this. */
return 0;
}
uint32_t flash_physical_get_protect_flags(void)
{
return entire_flash_locked ? EC_FLASH_PROTECT_ALL_NOW : 0;
}
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.
*
* This incorrect key fault causes the flash to become
* permanenlty locked until reset, a correct keyring write
* will not unlock it. In this way we can implement system
* write protect.
*/
ignore_bus_fault(1);
STM32_FLASH_KEYR = 0xffffffff;
ignore_bus_fault(0);
entire_flash_locked = 1;
/* Check if lock happened */
if (STM32_FLASH_CR & FLASH_CR_LOCK)
return EC_SUCCESS;
}
/* 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;
}
static int flash_idle(void)
{
timestamp_t deadline;
deadline.val = get_time().val + FLASH_TIMEOUT_US;
/* Wait for flash op to complete.
* This function is used for both reads and writes, so
* we need a long timeout, but a relatively short poll interval.
*/
while ((STM32_FLASH_SR & FLASH_SR_BUSY) &&
(get_time().val < deadline.val)) {
usleep(1);
}
if (STM32_FLASH_SR & FLASH_SR_BUSY)
return EC_ERROR_TIMEOUT;
return EC_SUCCESS;
}
static void clear_flash_errors(void)
{
/* Clear previous error status */
STM32_FLASH_SR = FLASH_SR_ERR_MASK;
}
/*****************************************************************************/
/* Physical layer APIs */
int flash_physical_protect_at_boot(enum flash_wp_range range)
{
return EC_SUCCESS;
}
int flash_physical_write(int offset, int size, const char *data)
{
uint32_t *address = (uint32_t *)(CONFIG_MAPPED_STORAGE_BASE + offset);
int res = EC_SUCCESS;
if (unlock() != EC_SUCCESS) {
res = EC_ERROR_UNKNOWN;
goto exit_wr;
}
/* Wait for busy to clear */
res = flash_idle();
if (res)
goto exit_wr;
clear_flash_errors();
/* set PG bit */
STM32_FLASH_CR &= ~FLASH_CR_PSIZE_MASK;
STM32_FLASH_CR |= FLASH_CR_PSIZE(FLASH_CR_PSIZE_32);
STM32_FLASH_CR |= FLASH_CR_PG;
for (; size > 0; size -= sizeof(uint32_t)) {
/*
* Reload the watchdog timer to avoid watchdog reset when doing
* long writing with interrupt disabled.
*/
watchdog_reload();
res = flash_idle();
if (res)
goto exit_wr;
/* write the word */
*address = data[0] + (data[1] << 8) +
(data[2] << 16) + (data[3] << 24);
address++;
data += sizeof(uint32_t);
res = flash_idle();
if (res)
goto exit_wr;
if (STM32_FLASH_SR & FLASH_SR_BUSY) {
res = EC_ERROR_TIMEOUT;
goto exit_wr;
}
/* Check for error conditions - erase failed, voltage error,
* protection error.
*/
if (STM32_FLASH_SR & FLASH_SR_ERR_MASK) {
res = EC_ERROR_UNKNOWN;
goto exit_wr;
}
}
exit_wr:
/* Disable PG bit */
STM32_FLASH_CR &= ~FLASH_CR_PG;
lock();
return res;
}
/* "@Internal Flash /0x08000000/04*016Kg,01*064Kg,03*128Kg" */
struct flash_sector {
int base;
int size;
};
static const struct flash_sector sectors[] = {
{(0 * 1024), (16 * 1024)},
{(16 * 1024), (16 * 1024)},
{(32 * 1024), (16 * 1024)},
{(48 * 1024), (16 * 1024)},
{(64 * 1024), (64 * 1024)},
{(128 * 1024), (128 * 1024)},
{(256 * 1024), (128 * 1024)},
{(384 * 1024), (128 * 1024)}
};
static const int num_sectors = ARRAY_SIZE(sectors);
int flash_physical_erase(int offset, int size)
{
int res = EC_SUCCESS;
int start_sector;
int end_sector;
/* Check that offset/size align with sectors. */
for (start_sector = 0; start_sector < num_sectors; start_sector++)
if (offset == sectors[start_sector].base)
break;
for (end_sector = start_sector; end_sector < num_sectors; end_sector++)
if ((offset + size) ==
(sectors[end_sector].base + sectors[end_sector].size))
break;
/* We can only erase on sector boundaries. */
if ((start_sector >= num_sectors) || (end_sector >= num_sectors))
return EC_ERROR_PARAM1;
if (unlock() != EC_SUCCESS)
return EC_ERROR_UNKNOWN;
res = flash_idle();
if (res)
goto exit_er;
clear_flash_errors();
for (; start_sector <= end_sector; start_sector++) {
/* Do nothing if already erased */
if (flash_is_erased(sectors[start_sector].base,
sectors[start_sector].size))
continue;
res = flash_idle();
if (res)
goto exit_er;
/* set Sector Erase bit and select sector */
STM32_FLASH_CR = (STM32_FLASH_CR & ~FLASH_CR_SNB_MASK) |
FLASH_CR_SER | FLASH_CR_SNB(start_sector);
/* set STRT bit : start erase */
STM32_FLASH_CR |= FLASH_CR_STRT;
/*
* Reload the watchdog timer to avoid watchdog reset during a
* long erase operation.
*/
watchdog_reload();
/* Wait for erase to complete, this will be awhile */
res = flash_idle();
if (res)
goto exit_er;
/*
* Check for error conditions - erase failed, voltage error,
* protection error
*/
if (STM32_FLASH_SR & FLASH_SR_ERR_MASK) {
res = EC_ERROR_UNKNOWN;
goto exit_er;
}
}
exit_er:
/* reset PER bit */
STM32_FLASH_CR &= ~FLASH_CR_SER;
lock();
return res;
}
/*****************************************************************************/
/* High-level APIs */
int flash_pre_init(void)
{
return EC_SUCCESS;
}
/*****************************************************************************/
/* 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);

26
chip/stm32/gpio-stm32f4.c Normal file
View File

@@ -0,0 +1,26 @@
/* Copyright 2016 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 "registers.h"
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.
*/
STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_GPIOMASK;
/* Delay 1 AHB clock cycle after the clock is enabled */
clock_wait_bus_cycles(BUS_AHB, 1);
}
#include "gpio-f0-l.c"

View File

@@ -27,7 +27,7 @@ void gpio_pre_init(void)
int i;
/* Required to configure external IRQ lines (SYSCFG_EXTICRn) */
STM32_RCC_APB2ENR |= 1 << 0;
STM32_RCC_APB2ENR |= STM32_RCC_SYSCFGEN;
/* Delay 1 APB clock cycle after the clock is enabled */
clock_wait_bus_cycles(BUS_APB, 1);

17
chip/stm32/jtag-stm32f4.c Normal file
View File

@@ -0,0 +1,17 @@
/* Copyright 2016 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 all timers we might use (TIM1-8) and watchdogs when
* the JTAG stops the CPU.
*/
/* TODO(nsanders): Implement this if someone needs jtag. */
}

View File

@@ -121,6 +121,8 @@
#define STM32_IRQ_TIM14 45 /* STM32F373 only */
#define STM32_IRQ_TIM5 50 /* STM32F373 */
#define STM32_IRQ_SPI3 51 /* STM32F373 */
#define STM32_IRQ_USART4 52 /* STM32F446 only */
#define STM32_IRQ_USART5 53 /* STM32F446 only */
#define STM32_IRQ_TIM6_DAC 54 /* STM32F373 */
#define STM32_IRQ_TIM7 55 /* STM32F373 */
#define STM32_IRQ_DMA2_CHANNEL1 56 /* STM32F373 */
@@ -136,6 +138,9 @@
#define STM32_IRQ_DMA2_CHANNEL7 69 /* STM32L4 only */
#define STM32_IRQ_LPUART 70 /* STM32L4 only */
#define STM32_IRQ_USART9 70 /* STM32L4 only */
#define STM32_IRQ_USART6 71 /* STM32F446 only */
#define STM32_IRQ_I2C3_EV 72 /* STM32F446 only */
#define STM32_IRQ_I2C3_ER 73 /* STM32F446 only */
#define STM32_IRQ_USB_WAKEUP 76 /* STM32F373 only */
#define STM32_IRQ_TIM19 78 /* STM32F373 only */
#define STM32_IRQ_FPU 81 /* STM32F373 only */
@@ -149,16 +154,57 @@
/* aliases for easier code sharing */
#define STM32_IRQ_I2C1 STM32_IRQ_I2C1_EV
#define STM32_IRQ_I2C2 STM32_IRQ_I2C2_EV
#define STM32_IRQ_I2C3 STM32_IRQ_I2C3_EV
#endif /* !CHIP_FAMILY_STM32F0 */
#ifdef CHIP_FAMILY_STM32F4
/*
* STM32F4 introduces a concept of DMA stream to allow
* fine allocation of a stream to a channel.
*/
#define STM32_IRQ_DMA1_STREAM0 11
#define STM32_IRQ_DMA1_STREAM1 12
#define STM32_IRQ_DMA1_STREAM2 13
#define STM32_IRQ_DMA1_STREAM3 14
#define STM32_IRQ_DMA1_STREAM4 15
#define STM32_IRQ_DMA1_STREAM5 16
#define STM32_IRQ_DMA1_STREAM6 17
#define STM32_IRQ_DMA1_STREAM7 47
#define STM32_IRQ_DMA2_STREAM0 56
#define STM32_IRQ_DMA2_STREAM1 57
#define STM32_IRQ_DMA2_STREAM2 58
#define STM32_IRQ_DMA2_STREAM3 59
#define STM32_IRQ_DMA2_STREAM4 60
#define STM32_IRQ_DMA2_STREAM5 68
#define STM32_IRQ_DMA2_STREAM6 69
#define STM32_IRQ_DMA2_STREAM7 70
#define STM32_IRQ_OTG_HS_WKUP 76
#define STM32_IRQ_OTG_HS_EP1_IN 75
#define STM32_IRQ_OTG_HS_EP1_OUT 74
#define STM32_IRQ_OTG_HS 77
#define STM32_IRQ_OTG_FS 67
#define STM32_IRQ_OTG_FS_WKUP 42
#endif
#ifndef __ASSEMBLER__
/* --- USART --- */
#if defined(CHIP_FAMILY_STM32F4)
#define STM32_USART1_BASE 0x40011000
#define STM32_USART2_BASE 0x40004400
#define STM32_USART3_BASE 0x40004800
#define STM32_USART4_BASE 0x40004c00
#define STM32_USART5_BASE 0x40005000
#define STM32_USART6_BASE 0x40011400
#else
#define STM32_USART1_BASE 0x40013800
#define STM32_USART2_BASE 0x40004400
#define STM32_USART3_BASE 0x40004800
#define STM32_USART4_BASE 0x40004c00
#define STM32_USART9_BASE 0x40008000 /* LPUART */
#endif
#define STM32_USART_BASE(n) CONCAT3(STM32_USART, n, _BASE)
#define STM32_USART_REG(base, offset) REG32((base) + (offset))
@@ -218,6 +264,7 @@
#define STM32_USART_CR1_OVER8 (1 << 15) /* STM32L only */
#define STM32_USART_CR2(base) STM32_USART_REG(base, 0x10)
#define STM32_USART_CR3(base) STM32_USART_REG(base, 0x14)
#define STM32_USART_CR3_EIE (1 << 0)
#define STM32_USART_CR3_DMAR (1 << 6)
#define STM32_USART_CR3_DMAT (1 << 7)
#define STM32_USART_CR3_ONEBIT (1 << 11) /* STM32L only */
@@ -403,6 +450,28 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define GPIO_ALT_FE 0xE
#define GPIO_ALT_FF 0xF
#elif defined(CHIP_FAMILY_STM32F4)
#define STM32_GPIOA_BASE 0x40020000
#define STM32_GPIOB_BASE 0x40020400
#define STM32_GPIOC_BASE 0x40020800
#define STM32_GPIOD_BASE 0x40020C00
#define STM32_GPIOE_BASE 0x40021000
#define STM32_GPIOF_BASE 0x40021400
#define STM32_GPIOG_BASE 0x40021800
#define STM32_GPIOH_BASE 0x40021C00
#define STM32_GPIO_MODER(b) REG32((b) + 0x00)
#define STM32_GPIO_OTYPER(b) REG16((b) + 0x04)
#define STM32_GPIO_OSPEEDR(b) REG32((b) + 0x08)
#define STM32_GPIO_PUPDR(b) REG32((b) + 0x0C)
#define STM32_GPIO_IDR(b) REG16((b) + 0x10)
#define STM32_GPIO_ODR(b) REG16((b) + 0x14)
#define STM32_GPIO_BSRR(b) REG32((b) + 0x18)
#define STM32_GPIO_LCKR(b) REG32((b) + 0x1C)
#define STM32_GPIO_AFRL(b) REG32((b) + 0x20)
#define STM32_GPIO_AFRH(b) REG32((b) + 0x24)
#else
#error Unsupported chip variant
#endif
@@ -410,9 +479,13 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
/* --- I2C --- */
#define STM32_I2C1_BASE 0x40005400
#define STM32_I2C2_BASE 0x40005800
#define STM32_I2C3_BASE 0x40005C00
#define STM32_I2C4_BASE 0x40006000
#define STM32_I2C1_PORT 0
#define STM32_I2C2_PORT 1
#define STM32_I2C3_PORT 2
#define STM32_FMPI2C4_PORT 3
#define stm32_i2c_reg(port, offset) \
((uint16_t *)((STM32_I2C1_BASE + ((port) * 0x400)) + (offset)))
@@ -477,6 +550,8 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_I2C_CR1_POS (1 << 11)
#define STM32_I2C_CR1_SWRST (1 << 15)
#define STM32_I2C_CR2(n) REG16(stm32_i2c_reg(n, 0x04))
#define STM32_I2C_CR2_LAST (1 << 12)
#define STM32_I2C_CR2_DMAEN (1 << 11)
#define STM32_I2C_OAR1(n) REG16(stm32_i2c_reg(n, 0x08))
#define STM32_I2C_OAR2(n) REG16(stm32_i2c_reg(n, 0x0C))
#define STM32_I2C_DR(n) REG16(stm32_i2c_reg(n, 0x10))
@@ -494,9 +569,58 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_I2C_SR2_BUSY (1 << 1)
#define STM32_I2C_CCR(n) REG16(stm32_i2c_reg(n, 0x1C))
#define STM32_I2C_CCR_DUTY (1 << 14)
#define STM32_I2C_CCR_FM (1 << 15)
#define STM32_I2C_TRISE(n) REG16(stm32_i2c_reg(n, 0x20))
#endif /* !CHIP_FAMILY_STM32F0 && !CHIP_FAMILY_STM32F3 */
#if defined(CHIP_FAMILY_STM32F4)
#define STM32_FMPI2C_CR1(n) REG32(stm32_i2c_reg(n, 0x00))
#define FMPI2C_CR1_PE (1 << 0)
#define FMPI2C_CR1_TXDMAEN (1 << 14)
#define FMPI2C_CR1_RXDMAEN (1 << 15)
#define STM32_FMPI2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04))
#define FMPI2C_CR2_RD_WRN (1 << 10)
#define FMPI2C_READ 1
#define FMPI2C_WRITE 0
#define FMPI2C_CR2_START (1 << 13)
#define FMPI2C_CR2_STOP (1 << 14)
#define FMPI2C_CR2_NACK (1 << 15)
#define FMPI2C_CR2_RELOAD (1 << 24)
#define FMPI2C_CR2_AUTOEND (1 << 25)
#define FMPI2C_CR2_SADD(addr) ((addr) & 0x3ff)
#define FMPI2C_CR2_SADD_MASK FMPI2C_CR2_SADD(0x3ff)
#define FMPI2C_CR2_SIZE(size) (((size) & 0xff) << 16)
#define FMPI2C_CR2_SIZE_MASK FMPI2C_CR2_SIZE(0xf)
#define STM32_FMPI2C_OAR1(n) REG32(stm32_i2c_reg(n, 0x08))
#define STM32_FMPI2C_OAR2(n) REG32(stm32_i2c_reg(n, 0x0C))
#define STM32_FMPI2C_TIMINGR(n) REG32(stm32_i2c_reg(n, 0x10))
#define TIMINGR_THE_RIGHT_VALUE 0xC0000E12
#define FMPI2C_TIMINGR_PRESC(val) (((val) & 0xf) << 28)
#define FMPI2C_TIMINGR_SCLDEL(val) (((val) & 0xf) << 20)
#define FMPI2C_TIMINGR_SDADEL(val) (((val) & 0xf) << 16)
#define FMPI2C_TIMINGR_SCLH(val) (((val) & 0xff) << 8)
#define FMPI2C_TIMINGR_SCLL(val) (((val) & 0xff) << 0)
#define STM32_FMPI2C_TIMEOUTR(n) REG32(stm32_i2c_reg(n, 0x14))
#define STM32_FMPI2C_ISR(n) REG32(stm32_i2c_reg(n, 0x18))
#define FMPI2C_ISR_TXE (1 << 0)
#define FMPI2C_ISR_TXIS (1 << 1)
#define FMPI2C_ISR_RXNE (1 << 2)
#define FMPI2C_ISR_ADDR (1 << 3)
#define FMPI2C_ISR_NACKF (1 << 4)
#define FMPI2C_ISR_STOPF (1 << 5)
#define FMPI2C_ISR_BERR (1 << 8)
#define FMPI2C_ISR_ARLO (1 << 9)
#define FMPI2C_ISR_BUSY (1 << 15)
#define STM32_FMPI2C_ICR(n) REG32(stm32_i2c_reg(n, 0x1C))
#define STM32_FMPI2C_PECR(n) REG32(stm32_i2c_reg(n, 0x20))
#define STM32_FMPI2C_RXDR(n) REG32(stm32_i2c_reg(n, 0x24))
#define STM32_FMPI2C_TXDR(n) REG32(stm32_i2c_reg(n, 0x28))
#endif
/* --- Power / Reset / Clocks --- */
#define STM32_PWR_BASE 0x40007000
@@ -551,7 +675,11 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x18)
#define STM32_RCC_AHBENR REG32(STM32_RCC_BASE + 0x1C)
#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x20)
#define STM32_RCC_SYSCFGEN (1 << 0)
#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x24)
#define STM32_RCC_PWREN (1 << 28)
#define STM32_RCC_AHBLPENR REG32(STM32_RCC_BASE + 0x28)
#define STM32_RCC_APB2LPENR REG32(STM32_RCC_BASE + 0x2C)
#define STM32_RCC_APB1LPENR REG32(STM32_RCC_BASE + 0x30)
@@ -624,10 +752,13 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_RCC_AHB2ENR_GPIOMASK (0xff << 0)
#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x58)
#define STM32_RCC_PWREN (1 << 28)
#define STM32_RCC_APB1ENR2 REG32(STM32_RCC_BASE + 0x5C)
#define STM32_RCC_APB1ENR2_LPUART1EN (1 << 0)
#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x60)
#define STM32_RCC_SYSCFGEN (1 << 0)
#define STM32_RCC_CCIPR REG32(STM32_RCC_BASE + 0x88)
#define STM32_RCC_CCIPR_PCLK 0
@@ -659,7 +790,11 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x10)
#define STM32_RCC_AHBENR REG32(STM32_RCC_BASE + 0x14)
#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x18)
#define STM32_RCC_SYSCFGEN (1 << 0)
#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x1c)
#define STM32_RCC_PWREN (1 << 28)
#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x20)
#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x24)
/* STM32F373 */
@@ -690,6 +825,142 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n))
#define STM32_SYSCFG_CFGR2 REG32(STM32_SYSCFG_BASE + 0x18)
#elif defined(CHIP_FAMILY_STM32F4)
#define STM32_RCC_BASE 0x40023800
#define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00)
#define STM32_RCC_CR_HSION (1 << 0)
#define STM32_RCC_CR_HSIRDY (1 << 1)
#define STM32_RCC_CR_HSEON (1 << 16)
#define STM32_RCC_CR_HSERDY (1 << 17)
#define STM32_RCC_CR_PLLON (1 << 24)
#define STM32_RCC_CR_PLLRDY (1 << 25)
/* Required or recommended clocks for stm32f446 */
#define STM32F4_PLL_REQ 2000000
#define STM32F4_RTC_REQ 1000000
#define STM32F4_IO_CLOCK 42000000
#define STM32F4_USB_REQ 48000000
#define STM32F4_VCO_CLOCK 336000000
#define STM32F4_HSI_CLOCK 16000000
#define STM32F4_LSI_CLOCK 32000
#define STM32_RCC_PLLCFGR REG32(STM32_RCC_BASE + 0x04)
/* PLL Division factor */
#define PLLCFGR_PLLM_OFF 0
#define PLLCFGR_PLLM(val) (((val) & 0x1f) << PLLCFGR_PLLM_OFF)
/* PLL Multiplication factor */
#define PLLCFGR_PLLN_OFF 6
#define PLLCFGR_PLLN(val) (((val) & 0x1ff) << PLLCFGR_PLLN_OFF)
/* Main CPU Clock */
#define PLLCFGR_PLLP_OFF 16
#define PLLCFGR_PLLP(val) (((val) & 0x3) << PLLCFGR_PLLP_OFF)
#define PLLCFGR_PLLSRC_HSI (0 << 22)
#define PLLCFGR_PLLSRC_HSE (1 << 22)
/* USB OTG FS: Must equal 48MHz */
#define PLLCFGR_PLLQ_OFF 24
#define PLLCFGR_PLLQ(val) (((val) & 0xf) << PLLCFGR_PLLQ_OFF)
/* SYSTEM */
#define PLLCFGR_PLLR_OFF 28
#define PLLCFGR_PLLR(val) (((val) & 0x7) << PLLCFGR_PLLR_OFF)
#define STM32_RCC_CFGR REG32(STM32_RCC_BASE + 0x08)
#define STM32_RCC_CFGR_SW_HSI (0 << 0)
#define STM32_RCC_CFGR_SW_HSE (1 << 0)
#define STM32_RCC_CFGR_SW_PLL (2 << 0)
#define STM32_RCC_CFGR_SW_PLL_R (3 << 0)
#define STM32_RCC_CFGR_SW_MASK (3 << 0)
#define STM32_RCC_CFGR_SWS_HSI (0 << 2)
#define STM32_RCC_CFGR_SWS_HSE (1 << 2)
#define STM32_RCC_CFGR_SWS_PLL (2 << 2)
#define STM32_RCC_CFGR_SWS_PLL_R (3 << 2)
#define STM32_RCC_CFGR_SWS_MASK (3 << 2)
/* AHB Prescalar: nonlinear values, look up in RM0390 */
#define CFGR_HPRE_OFF 4
#define CFGR_HPRE(val) (((val) & 0xf) << CFGR_HPRE_OFF)
/* APB1 Low Speed Prescalar < 45MHz */
#define CFGR_PPRE1_OFF 10
#define CFGR_PPRE1(val) (((val) & 0x7) << CFGR_PPRE1_OFF)
/* APB2 High Speed Prescalar < 90MHz */
#define CFGR_PPRE2_OFF 13
#define CFGR_PPRE2(val) (((val) & 0x7) << CFGR_PPRE2_OFF)
/* RTC CLock: Must equal 1MHz */
#define CFGR_RTCPRE_OFF 16
#define CFGR_RTCPRE(val) (((val) & 0x1f) << CFGR_RTCPRE_OFF)
#define STM32_RCC_CIR REG32(STM32_RCC_BASE + 0x0C)
#define STM32_RCC_AHB1RSTR REG32(STM32_RCC_BASE + 0x10)
#define RCC_AHB1RSTR_OTGHSRST (1 << 29)
#define STM32_RCC_AHB2RSTR REG32(STM32_RCC_BASE + 0x14)
#define STM32_RCC_AHB3RSTR REG32(STM32_RCC_BASE + 0x18)
#define STM32_RCC_APB1RSTR REG32(STM32_RCC_BASE + 0x20)
#define STM32_RCC_APB2RSTR REG32(STM32_RCC_BASE + 0x24)
#define STM32_RCC_AHB1ENR REG32(STM32_RCC_BASE + 0x30)
#define STM32_RCC_AHB1ENR_GPIOMASK (0xff << 0)
#define STM32_RCC_AHB1ENR_BKPSRAMEN (1 << 18)
#define STM32_RCC_AHB1ENR_DMA1EN (1 << 21)
#define STM32_RCC_AHB1ENR_DMA2EN (1 << 22)
/* TODO(nsanders): normalize naming.*/
#define STM32_RCC_HB1_DMA1 (1 << 21)
#define STM32_RCC_HB1_DMA2 (1 << 22)
#define STM32_RCC_AHB1ENR_OTGHSEN (1 << 29)
#define STM32_RCC_AHB1ENR_OTGHSULPIEN (1 << 30)
#define STM32_RCC_AHB2ENR REG32(STM32_RCC_BASE + 0x34)
#define STM32_RCC_AHB2ENR_OTGFSEN (1 << 7)
#define STM32_RCC_AHB3ENR REG32(STM32_RCC_BASE + 0x38)
#define STM32_RCC_APB1ENR REG32(STM32_RCC_BASE + 0x40)
#define STM32_RCC_PWREN (1 << 28)
#define STM32_RCC_I2C1EN (1 << 21)
#define STM32_RCC_I2C2EN (1 << 22)
#define STM32_RCC_I2C3EN (1 << 23)
#define STM32_RCC_FMPI2C4EN (1 << 24)
#define STM32_RCC_APB2ENR REG32(STM32_RCC_BASE + 0x44)
#define STM32_RCC_PB2_USART6 (1 << 5)
#define STM32_RCC_SYSCFGEN (1 << 14)
#define STM32_RCC_AHB1LPENR REG32(STM32_RCC_BASE + 0x50)
#define STM32_RCC_AHB2LPENR REG32(STM32_RCC_BASE + 0x54)
#define STM32_RCC_AHB3LPENR REG32(STM32_RCC_BASE + 0x58)
#define STM32_RCC_APB1LPENR REG32(STM32_RCC_BASE + 0x60)
#define STM32_RCC_APB2LPENR REG32(STM32_RCC_BASE + 0x64)
#define STM32_RCC_BDCR REG32(STM32_RCC_BASE + 0x70)
#define STM32_RCC_BDCR_BDRST (1 << 16)
#define STM32_RCC_BDCR_RTCEN (1 << 15)
#define BCDR_RTCSEL(source) (((source) & 0x3) << 8)
#define BDCR_SRC_HSE 0x3
#define BDCR_SRC_LSI 0x2
#define STM32_RCC_CSR REG32(STM32_RCC_BASE + 0x74)
#define STM32_RCC_CSR_LSION (1 << 0)
#define STM32_RCC_CSR_LSIRDY (1 << 1)
#define STM32_RCC_HB_DMA1 (1 << 24)
#define STM32_RCC_PB2_TIM9 (1 << 2)
#define STM32_RCC_PB2_TIM10 (1 << 3)
#define STM32_RCC_PB2_TIM11 (1 << 4)
#define STM32_RCC_PB1_USB (1 << 23)
#define STM32_RCC_DCKCFGR2 REG32(STM32_RCC_BASE + 0x94)
#define DCKCFGR2_FMPI2C1SEL(val) (((val) & 0x3) << 22)
#define DCKCFGR2_FMPI2C1SEL_MASK (0x3 << 22)
#define FMPI2C1SEL_APB 0x0
#define STM32_SYSCFG_BASE 0x40013800
#define STM32_SYSCFG_MEMRMP REG32(STM32_SYSCFG_BASE + 0x00)
#define STM32_SYSCFG_PMC REG32(STM32_SYSCFG_BASE + 0x04)
#define STM32_SYSCFG_EXTICR(n) REG32(STM32_SYSCFG_BASE + 8 + 4 * (n))
#define STM32_SYSCFG_CMPCR REG32(STM32_SYSCFG_BASE + 0x20)
#define STM32_SYSCFG_CFGR REG32(STM32_SYSCFG_BASE + 0x2C)
#else
#error Unsupported chip variant
#endif
@@ -711,7 +982,11 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_RCC_PB1_USART4 (1 << 19)
#define STM32_RCC_PB1_USART5 (1 << 20)
#define STM32_RCC_PB2_SPI1 (1 << 12)
#if defined(CHIP_FAMILY_STM32F4)
#define STM32_RCC_PB2_USART1 (1 << 4)
#else
#define STM32_RCC_PB2_USART1 (1 << 14)
#endif
/* --- Watchdogs --- */
@@ -740,7 +1015,8 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_RTC_BASE 0x40002800
#if defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32F0) || \
defined(CHIP_FAMILY_STM32F3) || defined(CHIP_FAMILY_STM32L4)
defined(CHIP_FAMILY_STM32F3) || defined(CHIP_FAMILY_STM32L4) || \
defined(CHIP_FAMILY_STM32F4)
#define STM32_RTC_TR REG32(STM32_RTC_BASE + 0x00)
#define STM32_RTC_DR REG32(STM32_RTC_BASE + 0x04)
#define STM32_RTC_CR REG32(STM32_RTC_BASE + 0x08)
@@ -754,6 +1030,8 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_RTC_ISR_INIT (1 << 7)
#define STM32_RTC_ISR_ALRAF (1 << 8)
#define STM32_RTC_PRER REG32(STM32_RTC_BASE + 0x10)
#define STM32_RTC_PRER_A_MASK (0x7f << 16)
#define STM32_RTC_PRER_S_MASK (0x7fff << 0)
#define STM32_RTC_WUTR REG32(STM32_RTC_BASE + 0x14)
#define STM32_RTC_CALIBR REG32(STM32_RTC_BASE + 0x18)
#define STM32_RTC_ALRMAR REG32(STM32_RTC_BASE + 0x1C)
@@ -915,12 +1193,53 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
#define STM32_OPTB_COMPL_SHIFT 8
#elif defined(CHIP_FAMILY_STM32F4)
#define STM32_FLASH_REGS_BASE 0x40023c00
#define STM32_FLASH_ACR REG32(STM32_FLASH_REGS_BASE + 0x00)
#define STM32_FLASH_ACR_LATENCY (1 << 0)
#define STM32_FLASH_ACR_PRFTEN (1 << 8)
#define STM32_FLASH_ACR_ICEN (1 << 9)
#define STM32_FLASH_ACR_DCEN (1 << 10)
#define STM32_FLASH_KEYR REG32(STM32_FLASH_REGS_BASE + 0x04)
#define STM32_FLASH_OPTKEYR REG32(STM32_FLASH_REGS_BASE + 0x08)
#define STM32_FLASH_SR REG32(STM32_FLASH_REGS_BASE + 0x0c)
#define FLASH_SR_BUSY (1 << 16)
#define FLASH_SR_ERR_MASK (0x1f3)
#define STM32_FLASH_CR REG32(STM32_FLASH_REGS_BASE + 0x10)
#define FLASH_CR_PG (1 << 0)
#define FLASH_CR_SER (1 << 1)
#define FLASH_CR_STRT (1 << 16)
#define FLASH_CR_LOCK (1 << 31)
#define FLASH_CR_PSIZE(size) (((size) & 0x3) << 8)
#define FLASH_CR_PSIZE_16 (1)
#define FLASH_CR_PSIZE_32 (2)
#define FLASH_CR_PSIZE_MASK FLASH_CR_PSIZE(0x3)
#define FLASH_CR_SNB(sec) (((sec) & 0xf) << 3)
#define FLASH_CR_SNB_MASK FLASH_CR_SNB(0xf)
#define STM32_FLASH_OPTCR REG32(STM32_FLASH_REGS_BASE + 0x14)
#define STM32_OPTB_BASE 0x1FFFC000
#define STM32_OPTB_RDP_OFF 0x00
#define STM32_OPTB_USER_OFF 0x02
#define STM32_OPTB_WRP_OFF(n) (0x08 + (n&3) * 2)
#define STM32_OPTB_WRP01 0x08
#define STM32_OPTB_WRP23 0x0c
#define STM32_OPTB_COMPL_SHIFT 8
#else
#error Unsupported chip variant
#endif
/* --- External Interrupts --- */
#if defined(CHIP_FAMILY_STM32F4)
#define STM32_EXTI_BASE 0x40013C00
#else
#define STM32_EXTI_BASE 0x40010400
#endif
#define STM32_EXTI_IMR REG32(STM32_EXTI_BASE + 0x00)
#define STM32_EXTI_EMR REG32(STM32_EXTI_BASE + 0x04)
@@ -929,15 +1248,21 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
#define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10)
#define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14)
#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3)
#if defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) || \
defined(CHIP_FAMILY_STM32F4)
#define EXTI_RTC_ALR_EVENT (1 << 17)
#endif
/* --- ADC --- */
#if defined(CHIP_FAMILY_STM32F4)
#define STM32_ADC1_BASE 0x40012000
#define STM32_ADC_BASE 0x40012300
#else
#define STM32_ADC1_BASE 0x40012400
#define STM32_ADC_BASE 0x40012700 /* STM32L15X only */
#endif
#if defined(CHIP_VARIANT_STM32F373)
#if defined(CHIP_VARIANT_STM32F373) || defined(CHIP_FAMILY_STM32F4)
#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)
@@ -1241,10 +1566,107 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
defined(CHIP_FAMILY_STM32L4)
#define STM32_DMA1_BASE 0x40020000
#define STM32_DMA2_BASE 0x40020400
#elif defined(CHIP_FAMILY_STM32F4)
#define STM32_DMA1_BASE 0x40026000
#define STM32_DMA2_BASE 0x40026400
#else
#error Unsupported chip variant
#endif
#if defined(CHIP_FAMILY_STM32F4)
/*
* Available DMA streams, numbered from 0.
*
* Named channel to respect older interface, but a stream can serve
* any channels, as long as they are in the same DMA controller.
*
* Stream 0 - 7 are managed by controller DMA1, 8 - 15 DMA2.
*/
enum dma_channel {
/* Channel numbers */
STM32_DMA1_STREAM0 = 0,
STM32_DMA1_STREAM1 = 1,
STM32_DMA1_STREAM2 = 2,
STM32_DMA1_STREAM3 = 3,
STM32_DMA1_STREAM4 = 4,
STM32_DMA1_STREAM5 = 5,
STM32_DMA1_STREAM6 = 6,
STM32_DMA1_STREAM7 = 7,
STM32_DMAS_COUNT = 8,
STM32_DMA2_STREAM0 = 8,
STM32_DMA2_STREAM1 = 9,
STM32_DMA2_STREAM2 = 10,
STM32_DMA2_STREAM3 = 11,
STM32_DMA2_STREAM4 = 12,
STM32_DMA2_STREAM5 = 13,
STM32_DMA2_STREAM6 = 14,
STM32_DMA2_STREAM7 = 15,
STM32_DMAS_USART1_TX = STM32_DMA2_STREAM7,
STM32_DMAS_USART1_RX = STM32_DMA2_STREAM5,
/* Legacy naming for uart.c */
STM32_DMAC_USART1_TX = STM32_DMAS_USART1_TX,
STM32_DMAC_USART1_RX = STM32_DMAS_USART1_RX,
STM32_DMAC_I2C1_TX = STM32_DMA1_STREAM6,
STM32_DMAC_I2C1_RX = STM32_DMA1_STREAM0,
STM32_DMAC_I2C2_TX = STM32_DMA1_STREAM7,
STM32_DMAC_I2C2_RX = STM32_DMA1_STREAM3,
STM32_DMAC_I2C3_TX = STM32_DMA1_STREAM4,
STM32_DMAC_I2C3_RX = STM32_DMA1_STREAM1,
STM32_DMAC_FMPI2C4_TX = STM32_DMA1_STREAM5,
STM32_DMAC_FMPI2C4_RX = STM32_DMA1_STREAM2,
};
#define STM32_REQ_USART1_TX 4
#define STM32_REQ_USART1_RX 4
#define STM32_REQ_USART2_TX 4
#define STM32_REQ_USART2_RX 4
#define STM32_I2C1_TX_REQ_CH 1
#define STM32_I2C1_RX_REQ_CH 1
#define STM32_I2C2_TX_REQ_CH 7
#define STM32_I2C2_RX_REQ_CH 7
#define STM32_I2C3_TX_REQ_CH 3
#define STM32_I2C3_RX_REQ_CH 1
#define STM32_FMPI2C4_TX_REQ_CH 2
#define STM32_FMPI2C4_RX_REQ_CH 2
#define STM32_DMAS_TOTAL_COUNT 16
/* Registers for a single stream of a DMA controller */
struct stm32_dma_stream {
uint32_t scr; /* Control */
uint32_t sndtr; /* Number of data to transfer */
uint32_t spar; /* Peripheral address */
uint32_t sm0ar; /* Memory address 0 */
uint32_t sm1ar; /* address 1 for double buffer */
uint32_t sfcr; /* FIFO control */
};
/* Always use stm32_dma_stream_t so volatile keyword is included! */
typedef volatile struct stm32_dma_stream stm32_dma_stream_t;
/* Common code and header file must use this */
typedef stm32_dma_stream_t dma_chan_t;
struct stm32_dma_regs {
uint32_t isr[2];
uint32_t ifcr[2];
stm32_dma_stream_t stream[STM32_DMAS_COUNT];
};
#else /* CHIP_FAMILY_STM32F4 */
/*
* Available DMA channels, numbered from 0.
*
@@ -1338,12 +1760,93 @@ struct stm32_dma_regs {
uint32_t ifcr;
stm32_dma_chan_t chan[STM32_DMAC_COUNT];
};
#endif /* CHIP_FAMILY_STM32F4 */
/* Always use stm32_dma_regs_t so volatile keyword is included! */
typedef volatile struct stm32_dma_regs stm32_dma_regs_t;
#define STM32_DMA1_REGS ((stm32_dma_regs_t *)STM32_DMA1_BASE)
#if defined(CHIP_FAMILY_STM32F4)
#define STM32_DMA2_REGS ((stm32_dma_regs_t *)STM32_DMA2_BASE)
#define STM32_DMA_REGS(channel) \
((channel) < STM32_DMAS_COUNT ? STM32_DMA1_REGS : STM32_DMA2_REGS)
#define STM32_DMA_CCR_EN (1 << 0)
#define STM32_DMA_CCR_DMEIE (1 << 1)
#define STM32_DMA_CCR_TEIE (1 << 2)
#define STM32_DMA_CCR_HTIE (1 << 3)
#define STM32_DMA_CCR_TCIE (1 << 4)
#define STM32_DMA_CCR_PFCTRL (1 << 5)
#define STM32_DMA_CCR_DIR_P2M (0 << 6)
#define STM32_DMA_CCR_DIR_M2P (1 << 6)
#define STM32_DMA_CCR_DIR_M2M (2 << 6)
#define STM32_DMA_CCR_CIRC (1 << 8)
#define STM32_DMA_CCR_PINC (1 << 9)
#define STM32_DMA_CCR_MINC (1 << 10)
#define STM32_DMA_CCR_PSIZE_8_BIT (0 << 11)
#define STM32_DMA_CCR_PSIZE_16_BIT (1 << 11)
#define STM32_DMA_CCR_PSIZE_32_BIT (2 << 11)
#define STM32_DMA_CCR_MSIZE_8_BIT (0 << 13)
#define STM32_DMA_CCR_MSIZE_16_BIT (1 << 13)
#define STM32_DMA_CCR_MSIZE_32_BIT (2 << 13)
#define STM32_DMA_CCR_PINCOS (1 << 15)
#define STM32_DMA_CCR_PL_LOW (0 << 16)
#define STM32_DMA_CCR_PL_MEDIUM (1 << 16)
#define STM32_DMA_CCR_PL_HIGH (2 << 16)
#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 16)
#define STM32_DMA_CCR_DBM (1 << 18)
#define STM32_DMA_CCR_CT (1 << 19)
#define STM32_DMA_CCR_PBURST(b_len) ((((b_len) - 4) / 4) << 21)
#define STM32_DMA_CCR_MBURST(b_len) ((((b_len) - 4) / 4) << 21)
#define STM32_DMA_CCR_CHANNEL_MASK (0x7 << 25)
#define STM32_DMA_CCR_CHANNEL(channel) ((channel) << 25)
#define STM32_DMA_CCR_RSVD_MASK (0xF0100000)
#define STM32_DMA_SFCR_DMDIS (1 << 2)
#define STM32_DMA_SFCR_FTH(level) (((level) - 1) << 0)
#define STM32_DMA_CH_LOCAL(channel) ((channel) % STM32_DMAS_COUNT)
#define STM32_DMA_CH_LH(channel) \
((STM32_DMA_CH_LOCAL(channel) < 4) ? 0 : 1)
#define STM32_DMA_CH_OFFSET(channel) \
(((STM32_DMA_CH_LOCAL(channel) % 4) * 6) + \
(((STM32_DMA_CH_LOCAL(channel) % 4) >= 2) ? 4 : 0))
#define STM32_DMA_CH_GETBITS(channel, val) \
(((val) >> STM32_DMA_CH_OFFSET(channel)) & 0x3f)
#define STM32_DMA_GET_IFCR(channel) \
(STM32_DMA_CH_GETBITS(channel, \
STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)]))
#define STM32_DMA_GET_ISR(channel) \
(STM32_DMA_CH_GETBITS(channel, \
STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)]))
#define STM32_DMA_SET_IFCR(channel, val) \
(STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] = \
(STM32_DMA_REGS(channel)->ifcr[STM32_DMA_CH_LH(channel)] & \
~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \
(((val) & 0x3f) << STM32_DMA_CH_OFFSET(channel)))
#define STM32_DMA_SET_ISR(channel, val) \
(STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] = \
(STM32_DMA_REGS(channel)->isr[STM32_DMA_CH_LH(channel)] & \
~(0x3f << STM32_DMA_CH_OFFSET(channel))) | \
(((val) & 0x3f) << STM32_DMA_CH_OFFSET(channel)))
#define STM32_DMA_FEIF (1 << 0)
#define STM32_DMA_DMEIF (1 << 2)
#define STM32_DMA_TEIF (1 << 3)
#define STM32_DMA_HTIF (1 << 4)
#define STM32_DMA_TCIF (1 << 5)
#define STM32_DMA_ALL 0x3d
#else /* !CHIP_FAMILY_STM32F4 */
#define STM32_DMA_CCR_CHANNEL(channel) (0)
#if defined(CHIP_FAMILY_STM32F3) || defined(CHIP_FAMILY_STM32L4)
#define STM32_DMA2_REGS ((stm32_dma_regs_t *)STM32_DMA2_BASE)
#define STM32_DMA_REGS(channel) \
@@ -1356,14 +1859,39 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t;
#endif
/* Bits for DMA controller regs (isr and ifcr) */
#define STM32_DMA_CH_OFFSET(channel) (4 * ((channel) % STM32_DMAC_PER_CTLR))
#define STM32_DMA_ISR_MASK(channel, mask) \
((mask) << (4 * ((channel) % STM32_DMAC_PER_CTLR)))
((mask) << STM32_DMA_CH_OFFSET(channel))
#define STM32_DMA_ISR_GIF(channel) STM32_DMA_ISR_MASK(channel, 1 << 0)
#define STM32_DMA_ISR_TCIF(channel) STM32_DMA_ISR_MASK(channel, 1 << 1)
#define STM32_DMA_ISR_HTIF(channel) STM32_DMA_ISR_MASK(channel, 1 << 2)
#define STM32_DMA_ISR_TEIF(channel) STM32_DMA_ISR_MASK(channel, 1 << 3)
#define STM32_DMA_ISR_ALL(channel) STM32_DMA_ISR_MASK(channel, 0x0f)
#define STM32_DMA_GIF (1 << 0)
#define STM32_DMA_TCIF (1 << 1)
#define STM32_DMA_HTIF (1 << 2)
#define STM32_DMA_TEIF (1 << 3)
#define STM32_DMA_ALL 0xf
#define STM32_DMA_GET_ISR(channel) \
((STM32_DMA_REGS(channel)->isr >> STM32_DMA_CH_OFFSET(channel)) \
& STM32_DMA_ALL)
#define STM32_DMA_SET_ISR(channel, val) \
(STM32_DMA_REGS(channel)->isr = \
((STM32_DMA_REGS(channel)->isr & \
~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \
(((val) & STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel))))
#define STM32_DMA_GET_IFCR(channel) \
((STM32_DMA_REGS(channel)->ifcr >> STM32_DMA_CH_OFFSET(channel)) \
& STM32_DMA_ALL)
#define STM32_DMA_SET_IFCR(channel, val) \
(STM32_DMA_REGS(channel)->ifcr = \
((STM32_DMA_REGS(channel)->ifcr & \
~(STM32_DMA_ALL << STM32_DMA_CH_OFFSET(channel))) | \
(((val) & STM32_DMA_ALL) << STM32_DMA_CH_OFFSET(channel))))
/* Bits for DMA channel regs */
#define STM32_DMA_CCR_EN (1 << 0)
#define STM32_DMA_CCR_TCIE (1 << 1)
@@ -1384,6 +1912,7 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t;
#define STM32_DMA_CCR_PL_HIGH (2 << 12)
#define STM32_DMA_CCR_PL_VERY_HIGH (3 << 12)
#define STM32_DMA_CCR_MEM2MEM (1 << 14)
#endif /* !CHIP_FAMILY_STM32F4 */
/* --- CRC --- */
#define STM32_CRC_BASE 0x40023000

View File

@@ -186,9 +186,14 @@ void system_pre_init(void)
#endif
/* enable clock on Power module */
STM32_RCC_APB1ENR |= 1 << 28;
STM32_RCC_APB1ENR |= STM32_RCC_PWREN;
#if defined(CHIP_FAMILY_STM32F4)
/* enable backup registers */
STM32_RCC_AHB1ENR |= STM32_RCC_AHB1ENR_BKPSRAMEN;
#else
/* enable backup registers */
STM32_RCC_APB1ENR |= 1 << 27;
#endif
/* Delay 1 APB clock cycle after the clock is enabled */
clock_wait_bus_cycles(BUS_APB, 1);
/* Enable access to RCC CSR register and RTC backup registers */
@@ -212,7 +217,7 @@ void system_pre_init(void)
STM32_RCC_CSR = (STM32_RCC_CSR & ~0x00C30000) | 0x00420000;
}
#elif defined(CHIP_FAMILY_STM32F0) || defined(CHIP_FAMILY_STM32F3) || \
defined(CHIP_FAMILY_STM32L4)
defined(CHIP_FAMILY_STM32L4) || defined(CHIP_FAMILY_STM32F4)
if ((STM32_RCC_BDCR & 0x00018300) != 0x00008200) {
/* the RTC settings are bad, we need to reset it */
STM32_RCC_BDCR |= 0x00010000;
@@ -404,5 +409,8 @@ int system_is_reboot_warm(void)
#elif defined(CHIP_FAMILY_STM32L4)
return ((STM32_RCC_AHB2ENR & STM32_RCC_AHB2ENR_GPIOMASK)
== STM32_RCC_AHB2ENR_GPIOMASK);
#elif defined(CHIP_FAMILY_STM32F4)
return ((STM32_RCC_AHB1ENR & STM32_RCC_AHB1ENR_GPIOMASK)
== STM32_RCC_AHB1ENR_GPIOMASK);
#endif
}

View File

@@ -32,6 +32,9 @@
static const struct dma_option dma_tx_option = {
CONFIG_UART_TX_DMA_CH, (void *)&STM32_USART_TDR(UARTN_BASE),
STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT
#ifdef CHIP_FAMILY_STM32F4
| STM32_DMA_CCR_CHANNEL(CONFIG_UART_TX_REQ_CH)
#endif
};
#else
@@ -47,6 +50,9 @@ static const struct dma_option dma_tx_option = {
static const struct dma_option dma_rx_option = {
CONFIG_UART_RX_DMA_CH, (void *)&STM32_USART_RDR(UARTN_BASE),
STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT |
#ifdef CHIP_FAMILY_STM32F4
STM32_DMA_CCR_CHANNEL(CONFIG_UART_RX_REQ_CH) |
#endif
STM32_DMA_CCR_CIRC
};
@@ -167,7 +173,11 @@ void uart_interrupt(void)
STM32_USART_CR1(UARTN_BASE) &= ~STM32_USART_CR1_TCIE;
enable_sleep(SLEEP_MASK_UART);
}
#if defined(CHIP_FAMILY_STM32F4)
STM32_USART_SR(UARTN_BASE) &= ~STM32_USART_SR_TC;
#else
STM32_USART_ICR(UARTN_BASE) |= STM32_USART_SR_TC;
#endif
if (!(STM32_USART_SR(UARTN_BASE) & ~STM32_USART_SR_TC))
return;
}
@@ -234,7 +244,8 @@ static void uart_freq_change(void)
#endif
#if defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32F0) || \
defined(CHIP_FAMILY_STM32F3) || defined(CHIP_FAMILY_STM32L4)
defined(CHIP_FAMILY_STM32F3) || defined(CHIP_FAMILY_STM32L4) || \
defined(CHIP_FAMILY_STM32F4)
if (div / 16 > 0) {
/*
* CPU clock is high enough to support x16 oversampling.
@@ -279,6 +290,8 @@ void uart_init(void)
/* Enable USART clock */
#if (UARTN == 1)
STM32_RCC_APB2ENR |= STM32_RCC_PB2_USART1;
#elif (UARTN == 6)
STM32_RCC_APB2ENR |= STM32_RCC_PB2_USART6;
#elif (UARTN == 9)
STM32_RCC_APB1ENR2 |= STM32_RCC_APB1ENR2_LPUART1EN;
#else
@@ -340,7 +353,7 @@ void uart_init(void)
STM32_USART_CR1(UARTN_BASE) |= STM32_USART_CR1_RXNEIE;
#endif
#ifdef CHIP_FAMILY_STM32L
#if defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32F4)
/* Use single-bit sampling */
STM32_USART_CR3(UARTN_BASE) |= STM32_USART_CR3_ONEBIT;
#endif

View File

@@ -524,6 +524,9 @@
*/
#undef CONFIG_CLOCK_CRYSTAL
/* Indicate if a clock source is connected to stm32f4's "HSE" specific input */
#undef CONFIG_STM32_CLOCK_HSE_HZ
/*****************************************************************************/
/* PMIC config */
@@ -1870,6 +1873,11 @@
/* The DMA peripheral request signal for UART TX. STM32 only. */
#undef CONFIG_UART_TX_DMA_PH
/* The DMA channel mapping config for stm32f4. */
#undef CONFIG_UART_TX_REQ_CH
#undef CONFIG_UART_RX_REQ_CH
/*****************************************************************************/
/* USB PD config */

View File

@@ -49,6 +49,7 @@ enum module_id {
MODULE_USB_PORT_POWER, /* 35 */
MODULE_USB_SWITCH,
MODULE_VBOOT,
MODULE_MCO,
/* Module count; not an actual module */
MODULE_COUNT

View File

@@ -13,13 +13,26 @@
/* Task event bitmasks */
/* Tasks may use the bits in TASK_EVENT_CUSTOM for their own events */
#define TASK_EVENT_CUSTOM(x) (x & 0x03ffffff)
#define TASK_EVENT_CUSTOM(x) (x & 0x0007ffff)
/* npcx peci event */
#define TASK_EVENT_PECI_DONE (1 << 19)
/* I2C tx/rx interrupt handler completion event. */
#define TASK_EVENT_I2C_COMPLETION(port) \
(1 << ((port) + 20))
#define TASK_EVENT_I2C_IDLE (TASK_EVENT_I2C_COMPLETION(0))
#define TASK_EVENT_MAX_I2C 6
#ifdef I2C_PORT_COUNT
#if (I2C_PORT_COUNT > TASK_EVENT_MAX_I2C)
#error "Too many i2c ports for i2c events"
#endif
#endif
/* DMA transmit complete event */
#define TASK_EVENT_DMA_TC (1 << 26)
/* ADC interrupt handler event */
#define TASK_EVENT_ADC_DONE (1 << 27)
/* I2C interrupt handler event */
#define TASK_EVENT_I2C_IDLE (1 << 28)
/* task_wake() called on task */
#define TASK_EVENT_WAKE (1 << 29)
/* Mutex unlocking */

View File

@@ -88,6 +88,7 @@ BOARDS_STM32_DFU=(
discovery
servo_v4
servo_micro
stm32f446e-eval
)
BOARDS_NPCX_5M5G_JTAG=(