nuttx/arch/arm/src/stm32h7/stm32h7x7xx_rcc.c
Nathan Hartman 9b9d1fc7ca arch/stm32h7: Extend support to all STM32H7x3xx
All parts in the STM32H7x3xx family have the same pinmap, etc.,
so extending support to all members of the family required only
minimal changes: Adding them to Kconfig, extending some
preprocessor logic, and minor code changes.

arch/arm/src/stm32h7/Kconfig:

    * Add explicit support for all microcontrollers in the
      STM32H7x3xx family by adding support for:
        - STM32H743AG
        - STM32H743AI
        - STM32H743BG
        - STM32H743BI
        - STM32H743IG
        - STM32H743II
        - STM32H743VG
        - STM32H743VI
        - STM32H743XG
        - STM32H743XI
        - STM32H743ZG
        - STM32H753AI
        - STM32H753BI
        - STM32H753VI
        - STM32H753XI
        - STM32H753ZI

    * Fix TODO items for IO_CONFIG (all STM32H7X3XX).

    * Because 100-pin parts lack GPIO ports F and G, but have
      port H, create the new hidden configs STM32H7_HAVE_GPIOF
      and STM32H7_HAVE_GPIOG.

    * STM32H7_STM32H7X3XX:
      - Select STM32H7_HAVE_GPIOF and STM32H7_HAVE_GPIOG only
        when not STM32H7_IO_CONFIG_V (100-pin part).
      - STM32H7_STM32H7X3XX: select STM32H7_HAVE_SPI5 for all
        IO configs except V (100-pin part), which doesn't expose
        SPI5 due to pin count.

    * STM32H7_STM32H7X7XX: Always select STM32H7_HAVE_GPIOF and
      STM32H7_HAVE_GPIOG because we aren't adding more part
      numbers in this family.

    * Remove extraneous (duplicate) "bool" and "default n"
      lines.

    * config STM32H7_FMC: Fix indent (contents were indented
      with spaces while rest of file uses tabs).

arch/arm/include/stm32h7/chip.h:

    * Extend preprocessor logic to add support for the new
      MCU part numbers.

    * Expand table of differences between family members.

    * Define STM32H7_NGPIO based on IO_CONFIGs decided in Kconfig.

    * If IO config is not known, issue compile-time #error
      with grep-friendly "CONFIG_STM32H7_IO_CONFIG_x Not Set."
      Suggested by davids5.

arch/arm/src/stm32h7/hardware/stm32h7x3xx_gpio.h:
arch/arm/src/stm32h7/stm32h7x3xx_rcc.c:
arch/arm/src/stm32h7/stm32h7x7xx_rcc.c:

    * When checking STM32H7_NGPIO > 5 or 6, check also
      CONFIG_STM32H7_HAVE_GPIOF or CONFIG_STM32H7_HAVE_GPIOG.

arch/arm/src/stm32h7/stm32_gpio.c:

    * stm32_configgpio(): When applicable, make sure we're not
      trying to configure one of the missing ports.

    * Fix nxstyle complains (wrong end of line comment position
      and several long lines). No functional changes.

    * g_gpiobase[]: Init base address for ports F and G according to
      CONFIG_STM32H7_HAVE_GPIOF and CONFIG_STM32H7_HAVE_GPIOG.

    * stm32_configgpio(): Replace complicated check with g_gpiobase[]
      null check. Suggested by davids5.

    * stm32_gpiowrite() and stm32_gpioread(): Add previously missing
      null check of g_gpiobase[].

arch/arm/src/stm32h7/stm32_gpio.h:

    * Wrap the defines GPIO_PORTA, GPIO_PORTB, GPIO_PORTC, GPIO_PORTD,
      GPIO_PORTE, GPIO_PORTF, GPIO_PORTG, GPIO_PORTH, GPIO_PORTI,
      GPIO_PORTJ, and GPIO_PORTK in conditional logic so that the
      compiler will prevent use of ports that do not exist on the
      target MCU.

    * Fix nxstyle complaints.

Documentation/NuttX.html:

    * Remove copy-and-pasted anchor for stm32f76xx77xx.

    * Correct link to README.txt for Nucleo-H743ZI board,
      formerly on BitBucket, now on GitHub.

    * Add list item for STMicro STM32H747I-DISCO board.

Co-Authored-By: David Sidrane <David.Sidrane@Nscdg.com>
2020-04-16 13:23:12 -06:00

957 lines
25 KiB
C

/****************************************************************************
* arch/arm/src/stm32h7/stm32h7x3xx_rcc.c
*
* Copyright (C) 2018, 2019 Gregory Nutt. All rights reserved.
* Authors: Gregory Nutt <gnutt@nuttx.org>
* David Sidrane <david.sidrane@nscdg.com>
* Mateusz Szafoni <raiden00@railab.me>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "stm32_pwr.h"
#include "hardware/stm32_axi.h"
#include "hardware/stm32_syscfg.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Allow up to 100 milliseconds for the high speed clock to become ready.
* that is a very long delay, but if the clock does not become ready we are
* hosed anyway. Normally this is very fast, but I have seen at least one
* board that required this long, long timeout for the HSE to be ready.
*/
#define HSERDY_TIMEOUT (100 * CONFIG_BOARD_LOOPSPERMSEC)
/* Same for HSI */
#define HSIRDY_TIMEOUT HSERDY_TIMEOUT
/* HSE divisor to yield ~1MHz RTC clock */
#define HSE_DIVISOR (STM32_HSE_FREQUENCY + 500000) / 1000000
/* FLASH wait states */
#if !defined(BOARD_FLASH_WAITSTATES)
# error BOARD_FLASH_WAITSTATES not defined
#elif BOARD_FLASH_WAITSTATES < 0 || BOARD_FLASH_WAITSTATES > 15
# error BOARD_FLASH_WAITSTATES is out of range
#endif
/* Voltage output scale (default to Scale 1 mode) */
#ifndef STM32_PWR_VOS_SCALE
# define STM32_PWR_VOS_SCALE PWR_D3CR_VOS_SCALE_1
#endif
#if !defined(BOARD_FLASH_PROGDELAY)
# if STM32_PWR_VOS_SCALE == PWR_D3CR_VOS_SCALE_1
# if STM32_SYSCLK_FREQUENCY <= 70000000 && BOARD_FLASH_WAITSTATES == 0
# define BOARD_FLASH_PROGDELAY 0
# elif STM32_SYSCLK_FREQUENCY <= 140000000 && BOARD_FLASH_WAITSTATES == 1
# define BOARD_FLASH_PROGDELAY 10
# elif STM32_SYSCLK_FREQUENCY <= 185000000 && BOARD_FLASH_WAITSTATES == 2
# define BOARD_FLASH_PROGDELAY 1
# elif STM32_SYSCLK_FREQUENCY <= 210000000 && BOARD_FLASH_WAITSTATES == 2
# define BOARD_FLASH_PROGDELAY 2
# elif STM32_SYSCLK_FREQUENCY <= 225000000 && BOARD_FLASH_WAITSTATES == 3
# define BOARD_FLASH_PROGDELAY 2
# else
# define BOARD_FLASH_PROGDELAY 2
# endif
# endif
#endif
/* PLL are only enabled if the P,Q or R outputs are enabled. */
#undef USE_PLL1
#if STM32_PLLCFG_PLL1CFG & (RCC_PLLCFGR_DIVP1EN | RCC_PLLCFGR_DIVQ1EN | \
RCC_PLLCFGR_DIVR1EN)
# define USE_PLL1
#endif
#undef USE_PLL2
#if STM32_PLLCFG_PLL2CFG & (RCC_PLLCFGR_DIVP2EN | RCC_PLLCFGR_DIVQ2EN | \
RCC_PLLCFGR_DIVR2EN)
# define USE_PLL2
#endif
#undef USE_PLL3
#if STM32_PLLCFG_PLL3CFG & (RCC_PLLCFGR_DIVP3EN | RCC_PLLCFGR_DIVQ3EN | \
RCC_PLLCFGR_DIVR3EN)
# define USE_PLL3
#endif
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: rcc_reset
*
* Description:
* Reset the RCC clock configuration to the default reset state
*
****************************************************************************/
static inline void rcc_reset(void)
{
uint32_t regval;
/* Enable the Internal High Speed clock (HSI) */
regval = getreg32(STM32_RCC_CR);
regval |= RCC_CR_HSION;
putreg32(regval, STM32_RCC_CR);
#if defined(CONFIG_STM32H7_AXI_SRAM_CORRUPTION_WAR)
/* Errata 2.2.9 Enable workaround for Reading from AXI SRAM may lead to
* data read corruption. See ES0392 Rev 6.
*/
putreg32(AXI_TARG_READ_ISS_OVERRIDE, STM32_AXI_TARG7_FN_MOD);
#endif
/* Reset CFGR register */
putreg32(0x00000000, STM32_RCC_CFGR);
/* Reset HSION, HSEON, CSSON and PLLON bits */
regval = getreg32(STM32_RCC_CR);
regval &= ~(RCC_CR_HSEON | RCC_CR_HSI48ON |
RCC_CR_CSION | RCC_CR_PLL1ON |
RCC_CR_PLL2ON | RCC_CR_PLL3ON |
RCC_CR_HSIDIV_MASK);
/* Set HSI predivider to default (4, 16MHz) */
regval |= RCC_CR_HSIDIV_4;
putreg32(regval, STM32_RCC_CR);
/* Reset PLLCFGR register to reset default */
putreg32(RCC_PLLCFGR_RESET, STM32_RCC_PLLCFGR);
/* Reset HSEBYP bit */
regval = getreg32(STM32_RCC_CR);
regval &= ~RCC_CR_HSEBYP;
putreg32(regval, STM32_RCC_CR);
/* Disable all interrupts */
putreg32(0x00000000, STM32_RCC_CIER);
}
/****************************************************************************
* Name: rcc_enableahb1
*
* Description:
* Enable selected AHB1 peripherals
*
****************************************************************************/
static inline void rcc_enableahb1(void)
{
uint32_t regval;
/* Set the appropriate bits in the AHB1ENR register to enabled the
* selected AHB1 peripherals.
*/
regval = getreg32(STM32_RCC_AHB1ENR);
#if defined(CONFIG_STM32H7_ADC1) || defined(CONFIG_STM32H7_ADC2)
/* ADC1 & 2 clock enable */
regval |= RCC_AHB1ENR_ADC12EN;
#endif
#ifdef CONFIG_STM32H7_DMA1
/* DMA 1 clock enable */
regval |= RCC_AHB1ENR_DMA1EN;
#endif
#ifdef CONFIG_STM32H7_DMA2
/* DMA 2 clock enable */
regval |= RCC_AHB1ENR_DMA2EN;
#endif
#ifdef CONFIG_STM32H7_OTGFS
/* USB OTG FS clock enable */
regval |= RCC_AHB1ENR_OTGFSEN;
#endif
#ifdef CONFIG_STM32H7_OTGHS
#ifdef BOARD_ENABLE_USBOTG_HSULPI
/* Enable clocking for USB OTG HS and external PHY */
regval |= (RCC_AHB1ENR_OTGHSEN | RCC_AHB1ENR_OTGHSULPIEN);
#else
/* Enable only clocking for USB OTG HS */
regval |= RCC_AHB1ENR_OTGHSEN;
#endif
#endif
#ifdef CONFIG_STM32H7_ETHMAC
/* Enable ethernet clocks */
regval |= (RCC_AHB1ENR_ETH1MACEN | RCC_AHB1ENR_ETH1TXEN |
RCC_AHB1ENR_ETH1RXEN);
#endif
putreg32(regval, STM32_RCC_AHB1ENR); /* Enable peripherals */
}
/****************************************************************************
* Name: rcc_enableahb2
*
* Description:
* Enable selected AHB2 peripherals
*
****************************************************************************/
static inline void rcc_enableahb2(void)
{
uint32_t regval;
/* Set the appropriate bits in the AHB2ENR register to enabled the
* selected AHB2 peripherals.
*/
regval = getreg32(STM32_RCC_AHB2ENR);
/* TODO: ... */
putreg32(regval, STM32_RCC_AHB2ENR); /* Enable peripherals */
}
/****************************************************************************
* Name: rcc_enableahb3
*
* Description:
* Enable selected AHB3 peripherals
*
****************************************************************************/
static inline void rcc_enableahb3(void)
{
uint32_t regval;
/* Set the appropriate bits in the AHB3ENR register to enabled the
* selected AHB3 peripherals.
*/
regval = getreg32(STM32_RCC_AHB3ENR);
#ifdef CONFIG_STM32H7_MDMA
/* MDMA clock enable */
regval |= RCC_AHB3ENR_MDMAEN;
#endif
#ifdef CONFIG_STM32H7_SDMMC1
/* SDMMC clock enable */
regval |= RCC_AHB3ENR_SDMMC1EN;
#endif
#ifdef CONFIG_STM32H7_FMC
/* Flexible static memory controller module clock enable */
regval |= RCC_AHB3ENR_FMCEN;
#endif
/* TODO: ... */
putreg32(regval, STM32_RCC_AHB3ENR); /* Enable peripherals */
}
/****************************************************************************
* Name: rcc_enableahb4
*
* Description:
* Enable selected AHB4 peripherals
*
****************************************************************************/
static inline void rcc_enableahb4(void)
{
uint32_t regval;
/* Set the appropriate bits in the AHB4ENR register to enabled the
* selected AHB4 peripherals.
*/
regval = getreg32(STM32_RCC_AHB4ENR);
#ifdef CONFIG_STM32H7_ADC3
/* ADC3 clock enable */
regval |= RCC_AHB4ENR_ADC3EN;
#endif
/* Enable GPIO, GPIOB, ... GPIOK */
#if STM32H7_NGPIO > 0
regval |= (RCC_AHB4ENR_GPIOAEN
#if STM32H7_NGPIO > 1
| RCC_AHB4ENR_GPIOBEN
#endif
#if STM32H7_NGPIO > 2
| RCC_AHB4ENR_GPIOCEN
#endif
#if STM32H7_NGPIO > 3
| RCC_AHB4ENR_GPIODEN
#endif
#if STM32H7_NGPIO > 4
| RCC_AHB4ENR_GPIOEEN
#endif
#if (STM32H7_NGPIO > 5) && (defined(CONFIG_STM32H7_HAVE_GPIOF))
| RCC_AHB4ENR_GPIOFEN
#endif
#if (STM32H7_NGPIO > 6) && (defined(CONFIG_STM32H7_HAVE_GPIOG))
| RCC_AHB4ENR_GPIOGEN
#endif
#if STM32H7_NGPIO > 7
| RCC_AHB4ENR_GPIOHEN
#endif
#if STM32H7_NGPIO > 8
| RCC_AHB4ENR_GPIOIEN
#endif
#if STM32H7_NGPIO > 9
| RCC_AHB4ENR_GPIOJEN
#endif
#if STM32H7_NGPIO > 10
| RCC_AHB4ENR_GPIOKEN
#endif
);
#endif
#ifdef CONFIG_STM32H7_BDMA
/* BDMA clock enable */
regval |= RCC_AHB4ENR_BDMAEN;
#endif
#ifdef CONFIG_STM32H7_CRC
/* CRC clock enable */
regval |= RCC_AHB4ENR_CRCEN;
#endif
#ifdef CONFIG_STM32H7_BKPSRAM
/* Backup SRAM clock enable */
regval |= RCC_AHB4ENR_BKPSRAMEN;
#endif
putreg32(regval, STM32_RCC_AHB4ENR); /* Enable peripherals */
}
/****************************************************************************
* Name: rcc_enableapb1
*
* Description:
* Enable selected APB1 peripherals
*
****************************************************************************/
static inline void rcc_enableapb1(void)
{
uint32_t regval;
/* Set the appropriate bits in the APB1L/HENR register to enabled the
* selected APB1 peripherals.
*/
regval = getreg32(STM32_RCC_APB1LENR);
#ifdef CONFIG_STM32H7_SPI2
/* SPI2 clock enable */
regval |= RCC_APB1LENR_SPI2EN;
#endif
#ifdef CONFIG_STM32H7_SPI3
/* SPI3 clock enable */
regval |= RCC_APB1LENR_SPI3EN;
#endif
#ifdef CONFIG_STM32H7_I2C1
/* I2C1 clock enable */
regval |= RCC_APB1LENR_I2C1EN;
#endif
#ifdef CONFIG_STM32H7_I2C2
/* I2C2 clock enable */
regval |= RCC_APB1LENR_I2C2EN;
#endif
#ifdef CONFIG_STM32H7_I2C3
/* I2C3 clock enable */
regval |= RCC_APB1LENR_I2C3EN;
#endif
/* TODO: ... */
putreg32(regval, STM32_RCC_APB1LENR); /* Enable APB1L peripherals */
regval = getreg32(STM32_RCC_APB1HENR);
/* TODO: ... */
putreg32(regval, STM32_RCC_APB1HENR); /* Enable APB1H peripherals */
}
/****************************************************************************
* Name: rcc_enableapb2
*
* Description:
* Enable selected APB2 peripherals
*
****************************************************************************/
static inline void rcc_enableapb2(void)
{
uint32_t regval;
/* Set the appropriate bits in the APB2ENR register to enabled the
* selected APB2 peripherals.
*/
regval = getreg32(STM32_RCC_APB2ENR);
#ifdef CONFIG_STM32H7_SPI1
/* SPI1 clock enable */
regval |= RCC_APB2ENR_SPI1EN;
#endif
#ifdef CONFIG_STM32H7_SPI4
/* SPI4 clock enable */
regval |= RCC_APB2ENR_SPI4EN;
#endif
#ifdef CONFIG_STM32H7_SPI5
/* SPI5 clock enable */
regval |= RCC_APB2ENR_SPI5EN;
#endif
#ifdef CONFIG_STM32H7_SDMMC2
/* SDMMC2 clock enable */
regval |= RCC_APB2ENR_SDMMC2EN;
#endif
putreg32(regval, STM32_RCC_APB2ENR); /* Enable peripherals */
}
/****************************************************************************
* Name: rcc_enableapb3
*
* Description:
* Enable selected APB3 peripherals
*
****************************************************************************/
static inline void rcc_enableapb3(void)
{
uint32_t regval;
/* Set the appropriate bits in the APB3ENR register to enabled the
* selected APB3 peripherals.
*/
regval = getreg32(STM32_RCC_APB3ENR);
/* TODO: ... */
putreg32(regval, STM32_RCC_APB3ENR); /* Enable peripherals */
}
/****************************************************************************
* Name: rcc_enableapb4
*
* Description:
* Enable selected APB4 peripherals
*
****************************************************************************/
static inline void rcc_enableapb4(void)
{
uint32_t regval;
/* Set the appropriate bits in the APB4ENR register to enabled the
* selected APB4 peripherals.
*/
regval = getreg32(STM32_RCC_APB4ENR);
#ifdef CONFIG_STM32H7_SYSCFG
/* System configuration controller clock enable */
regval |= RCC_APB4ENR_SYSCFGEN;
#endif
#ifdef CONFIG_STM32H7_I2C4
/* I2C4 clock enable */
regval |= RCC_APB4ENR_I2C4EN;
#endif
#ifdef CONFIG_STM32H7_SPI6
/* SPI6 clock enable */
regval |= RCC_APB4ENR_SPI6EN;
#endif
/* TODO: ... */
putreg32(regval, STM32_RCC_APB4ENR); /* Enable peripherals */
}
/****************************************************************************
* Name: stm32_stdclockconfig
*
* Description:
* Called to change to new clock based on settings in board.h
*
* NOTE: This logic would need to be extended if you need to select low-
* power clocking modes!
****************************************************************************/
#ifndef CONFIG_STM32H7_CUSTOM_CLOCKCONFIG
static void stm32_stdclockconfig(void)
{
uint32_t regval;
volatile int32_t timeout;
#ifdef STM32_BOARD_USEHSI
/* Enable Internal High-Speed Clock (HSI) */
regval = getreg32(STM32_RCC_CR);
regval |= RCC_CR_HSION; /* Enable HSI */
putreg32(regval, STM32_RCC_CR);
/* Wait until the HSI is ready (or until a timeout elapsed) */
for (timeout = HSIRDY_TIMEOUT; timeout > 0; timeout--)
{
/* Check if the HSIRDY flag is the set in the CR */
if ((getreg32(STM32_RCC_CR) & RCC_CR_HSIRDY) != 0)
{
/* If so, then break-out with timeout > 0 */
break;
}
}
#else /* if STM32_BOARD_USEHSE */
/* Enable External High-Speed Clock (HSE) */
regval = getreg32(STM32_RCC_CR);
#ifdef STM32_HSEBYP_ENABLE /* May be defined in board.h header file */
regval |= RCC_CR_HSEBYP; /* Enable HSE clock bypass */
#else
regval &= ~RCC_CR_HSEBYP; /* Disable HSE clock bypass */
#endif
regval |= RCC_CR_HSEON; /* Enable HSE */
putreg32(regval, STM32_RCC_CR);
/* Wait until the HSE is ready (or until a timeout elapsed) */
for (timeout = HSERDY_TIMEOUT; timeout > 0; timeout--)
{
/* Check if the HSERDY flag is the set in the CR */
if ((getreg32(STM32_RCC_CR) & RCC_CR_HSERDY) != 0)
{
/* If so, then break-out with timeout > 0 */
break;
}
}
#endif
#define CONFIG_STM32H7_HSI48
#ifdef CONFIG_STM32H7_HSI48
/* Enable HSI48 */
regval = getreg32(STM32_RCC_CR);
regval |= RCC_CR_HSI48ON;
putreg32(regval, STM32_RCC_CR);
/* Wait until the HSI48 is ready */
while ((getreg32(STM32_RCC_CR) & RCC_CR_HSI48RDY) == 0)
{
}
#endif
/* Check for a timeout. If this timeout occurs, then we are hosed. We
* have no real back-up plan, although the following logic makes it look
* as though we do.
*/
if (timeout > 0)
{
/* Set the D1 domain Core prescaler and the HCLK source/divider */
regval = getreg32(STM32_RCC_D1CFGR);
regval &= ~(RCC_D1CFGR_HPRE_MASK | RCC_D1CFGR_D1CPRE_MASK);
regval |= (STM32_RCC_D1CFGR_HPRE | STM32_RCC_D1CFGR_D1CPRE);
putreg32(regval, STM32_RCC_D1CFGR);
/* Set PCLK1 */
regval = getreg32(STM32_RCC_D2CFGR);
regval &= ~RCC_D2CFGR_D2PPRE2_MASK;
regval |= STM32_RCC_D2CFGR_D2PPRE1;
putreg32(regval, STM32_RCC_D2CFGR);
/* Set PCLK2 */
regval = getreg32(STM32_RCC_D2CFGR);
regval &= ~RCC_D2CFGR_D2PPRE2_MASK;
regval |= STM32_RCC_D2CFGR_D2PPRE2;
putreg32(regval, STM32_RCC_D2CFGR);
/* Set PCLK3 */
regval = getreg32(STM32_RCC_D1CFGR);
regval &= ~RCC_D1CFGR_D1PPRE_MASK;
regval |= STM32_RCC_D1CFGR_D1PPRE;
putreg32(regval, STM32_RCC_D1CFGR);
/* Set PCLK4 */
regval = getreg32(STM32_RCC_D3CFGR);
regval &= ~RCC_D3CFGR_D3PPRE_MASK;
regval |= STM32_RCC_D3CFGR_D3PPRE;
putreg32(regval, STM32_RCC_D3CFGR);
#ifdef CONFIG_STM32H7_RTC_HSECLOCK
/* Set the RTC clock divisor */
regval = getreg32(STM32_RCC_CFGR);
regval &= ~RCC_CFGR_RTCPRE_MASK;
regval |= RCC_CFGR_RTCPRE(HSE_DIVISOR);
putreg32(regval, STM32_RCC_CFGR);
#endif
/* Configure PLL123 clock source and multipiers */
#ifdef STM32_BOARD_USEHSI
regval = (RCC_PLLCKSELR_PLLSRC_HSI |
STM32_PLLCFG_PLL1M |
STM32_PLLCFG_PLL2M |
STM32_PLLCFG_PLL3M);
#else /* if STM32_BOARD_USEHSE */
regval = (RCC_PLLCKSELR_PLLSRC_HSE |
STM32_PLLCFG_PLL1M |
STM32_PLLCFG_PLL2M |
STM32_PLLCFG_PLL3M);
#endif
putreg32(regval, STM32_RCC_PLLCKSELR);
/* Each PLL offers 3 outputs with post-dividers (PLLxP/PLLxQ/PLLxR) */
/* Configure PLL1 dividers */
regval = (STM32_PLLCFG_PLL1N |
STM32_PLLCFG_PLL1P |
STM32_PLLCFG_PLL1Q |
STM32_PLLCFG_PLL1R);
putreg32(regval, STM32_RCC_PLL1DIVR);
/* Configure PLL2 dividers */
regval = (STM32_PLLCFG_PLL2N |
STM32_PLLCFG_PLL2P |
STM32_PLLCFG_PLL2Q |
STM32_PLLCFG_PLL2R);
putreg32(regval, STM32_RCC_PLL2DIVR);
/* Configure PLL3 dividers */
regval = (STM32_PLLCFG_PLL3N |
STM32_PLLCFG_PLL3P |
STM32_PLLCFG_PLL3Q |
STM32_PLLCFG_PLL3R);
putreg32(regval, STM32_RCC_PLL3DIVR);
/* Configure PLLs */
regval = (STM32_PLLCFG_PLL1CFG |
STM32_PLLCFG_PLL2CFG |
STM32_PLLCFG_PLL3CFG);
putreg32(regval, STM32_RCC_PLLCFGR);
regval = getreg32(STM32_RCC_CR);
#if defined(USE_PLL1)
/* Enable the PLL1 */
regval |= RCC_CR_PLL1ON;
#endif
#if defined(USE_PLL2)
/* Enable the PLL2 */
regval |= RCC_CR_PLL2ON;
#endif
#if defined(USE_PLL3)
/* Enable the PLL3 */
regval |= RCC_CR_PLL3ON;
#endif
putreg32(regval, STM32_RCC_CR);
#if defined(USE_PLL1)
/* Wait until the PLL1 is ready */
while ((getreg32(STM32_RCC_CR) & RCC_CR_PLL1RDY) == 0)
{
}
#endif
#if defined(USE_PLL2)
/* Wait until the PLL2 is ready */
while ((getreg32(STM32_RCC_CR) & RCC_CR_PLL2RDY) == 0)
{
}
#endif
#if defined(USE_PLL3)
/* Wait until the PLL3 is ready */
while ((getreg32(STM32_RCC_CR) & RCC_CR_PLL3RDY) == 0)
{
}
#endif
/* We must write the lower byte of the PWR_CR3 register is written once
* after POR and it shall be written before changing VOS level or
* ck_sys clock frequency. No limitation applies to the upper bytes.
*
* Programming data corresponding to an invalid combination of
* LDOEN and BYPASS bits will be ignored: data will not be written,
* the written-once mechanism will lock the register and any further
* write access will be ignored. The default supply configuration will
* be kept and the ACTVOSRDY bit in PWR control status register 1
* (PWR_CSR1) will go on indicating invalid voltage levels.
*
* N.B. The system shall be power cycled before writing a new value.
*/
regval = getreg32(STM32_PWR_CR3);
regval |= STM32_PWR_CR3_LDOEN | STM32_PWR_CR3_LDOESCUEN;
putreg32(regval, STM32_PWR_CR3);
#if 0
/* Set the voltage output scale */
regval = getreg32(STM32_PWR_D3CR);
regval &= ~STM32_PWR_D3CR_VOS_MASK;
regval |= STM32_PWR_VOS_SCALE;
putreg32(regval, STM32_PWR_D3CR);
while ((getreg32(STM32_PWR_D3CR) & STM32_PWR_D3CR_VOSRDY) == 0)
{
}
/* Over-drive is needed if
* - Voltage output scale 1 mode is selected and SYSCLK frequency is
* over 400 MHz.
*/
if ((STM32_PWR_VOS_SCALE == PWR_D3CR_VOS_SCALE_1) &&
STM32_SYSCLK_FREQUENCY > 400000000)
{
/* Enable System configuration controller clock to Enable ODEN */
regval = getreg32(STM32_RCC_APB4ENR);
regval |= RCC_APB4ENR_SYSCFGEN;
putreg32(regval, STM32_RCC_APB4ENR);
/* Enable Overdrive to extend the clock frequency up to 480 MHz. */
regval = getreg32(STM32_SYSCFG_PWRCR);
regval |= SYSCFG_PWRCR_ODEN;
putreg32(regval, STM32_SYSCFG_PWRCR);
while ((getreg32(STM32_PWR_D3CR) & STM32_PWR_D3CR_VOSRDY) == 0)
{
}
}
#endif
/* Configure FLASH wait states */
regval = FLASH_ACR_WRHIGHFREQ(BOARD_FLASH_PROGDELAY) |
FLASH_ACR_LATENCY(BOARD_FLASH_WAITSTATES);
putreg32(regval, STM32_FLASH_ACR);
/* Select the PLL1P as system clock source */
regval = getreg32(STM32_RCC_CFGR);
regval &= ~RCC_CFGR_SW_MASK;
regval |= RCC_CFGR_SW_PLL1;
putreg32(regval, STM32_RCC_CFGR);
/* Wait until the PLL source is used as the system clock source */
while ((getreg32(STM32_RCC_CFGR) & RCC_CFGR_SWS_MASK) !=
RCC_CFGR_SWS_PLL1)
{
}
/* Configure I2C source clock */
#if defined(STM32_RCC_D2CCIP2R_I2C123SRC)
regval = getreg32(STM32_RCC_D2CCIP2R);
regval &= ~RCC_D2CCIP2R_I2C123SEL_MASK;
regval |= STM32_RCC_D2CCIP2R_I2C123SRC;
putreg32(regval, STM32_RCC_D2CCIP2R);
#endif
#if defined(STM32_RCC_D3CCIPR_I2C4SRC)
regval = getreg32(STM32_RCC_D3CCIPR);
regval &= ~RCC_D3CCIPR_I2C4SEL_MASK;
regval |= STM32_RCC_D3CCIPR_I2C4SRC;
putreg32(regval, STM32_RCC_D3CCIPR);
#endif
/* Configure SPI source clock */
#if defined(STM32_RCC_D2CCIP1R_SPI123SRC)
regval = getreg32(STM32_RCC_D2CCIP1R);
regval &= ~RCC_D2CCIP1R_SPI123SEL_MASK;
regval |= STM32_RCC_D2CCIP1R_SPI123SRC;
putreg32(regval, STM32_RCC_D2CCIP1R);
#endif
#if defined(STM32_RCC_D2CCIP1R_SPI45SRC)
regval = getreg32(STM32_RCC_D2CCIP1R);
regval &= ~RCC_D2CCIP1R_SPI45SEL_MASK;
regval |= STM32_RCC_D2CCIP1R_SPI45SRC;
putreg32(regval, STM32_RCC_D2CCIP1R);
#endif
#if defined(STM32_RCC_D3CCIPR_SPI6SRC)
regval = getreg32(STM32_RCC_D3CCIPR);
regval &= ~RCC_D3CCIPR_SPI6SEL_MASK;
regval |= STM32_RCC_D3CCIPR_SPI6SRC;
putreg32(regval, STM32_RCC_D3CCIPR);
#endif
/* Configure USB source clock */
#if defined(STM32_RCC_D2CCIP2R_USBSRC)
regval = getreg32(STM32_RCC_D2CCIP2R);
regval &= ~RCC_D2CCIP2R_USBSEL_MASK;
regval |= STM32_RCC_D2CCIP2R_USBSRC;
putreg32(regval, STM32_RCC_D2CCIP2R);
#endif
/* Configure ADC source clock */
#if defined(STM32_RCC_D3CCIPR_ADCSEL)
regval = getreg32(STM32_RCC_D3CCIPR);
regval &= ~RCC_D3CCIPR_ADCSEL_MASK;
regval |= STM32_RCC_D3CCIPR_ADCSEL;
putreg32(regval, STM32_RCC_D3CCIPR);
#endif
#if defined(CONFIG_STM32H7_IWDG) || defined(CONFIG_STM32H7_RTC_LSICLOCK)
/* Low speed internal clock source LSI */
stm32_rcc_enablelsi();
#endif
#if defined(CONFIG_STM32H7_RTC_LSECLOCK)
/* Low speed external clock source LSE
*
* TODO: There is another case where the LSE needs to
* be enabled: if the MCO1 pin selects LSE as source.
*/
stm32_rcc_enablelse();
#endif
}
}
#endif
/****************************************************************************
* Name: rcc_enableperiphals
****************************************************************************/
static inline void rcc_enableperipherals(void)
{
rcc_enableahb1();
rcc_enableahb2();
rcc_enableahb3();
rcc_enableahb4();
rcc_enableapb1();
rcc_enableapb2();
rcc_enableapb3();
rcc_enableapb4();
}
/****************************************************************************
* Public Functions
****************************************************************************/