stm32h7: refactor clock init to target-specific callback

Given the myriad of clocking options the STM32H7 family
provides, it is easiest to let targets simply implement
what they need.

Change-Id: I9cceed40a2d638998e8b583651f73557d2ffbd46
This commit is contained in:
Aidan MacDonald 2025-12-26 21:18:40 +00:00 committed by Solomon Peachy
parent 37b90baa5f
commit 23448a13d1
4 changed files with 180 additions and 121 deletions

View file

@ -2034,6 +2034,7 @@ target/arm/stm32/usb-stm32h7.c
target/arm/stm32/echoplayer/audiohw-echoplayer.c
target/arm/stm32/echoplayer/backlight-echoplayer.c
target/arm/stm32/echoplayer/button-echoplayer.c
target/arm/stm32/echoplayer/clock-echoplayer.c
target/arm/stm32/echoplayer/lcd-echoplayer.c
target/arm/stm32/echoplayer/power-echoplayer.c
target/arm/stm32/echoplayer/system-echoplayer.c

View file

@ -0,0 +1,33 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2025 Aidan MacDonald
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __CLOCK_STM32H7_H__
#define __CLOCK_STM32H7_H__
#include "system.h"
/*
* Implemented by the target to initialize all oscillators,
* system, CPU, and bus clocks that need to be enabled from
* early boot.
*/
void stm_target_clock_init(void) INIT_ATTR;
#endif /* __CLOCK_STM32H7_H__ */

View file

@ -0,0 +1,143 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2025 Aidan MacDonald
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "clock-stm32h7.h"
#include "panic.h"
#include "regs/stm32h743/flash.h"
#include "regs/stm32h743/fmc.h"
#include "regs/stm32h743/pwr.h"
#include "regs/stm32h743/rcc.h"
#include "regs/stm32h743/syscfg.h"
/* Flag to use VOS0 */
#define STM32H743_USE_VOS0 (CPU_FREQ > 400000000)
static void init_hse(void)
{
reg_writef(RCC_CR, HSEON(1));
while (!reg_readf(RCC_CR, HSERDY));
}
static void init_pll(void)
{
/* Select HSE/4 input for PLL1 (6 MHz) */
reg_writef(RCC_PLLCKSELR,
PLLSRC_V(HSE),
DIVM1(4),
DIVM2(0),
DIVM3(0));
/* Enable PLL1P and PLL1Q */
reg_writef(RCC_PLLCFGR,
DIVP1EN(1),
DIVQ1EN(1),
DIVR1EN(0),
DIVP2EN(0),
DIVQ2EN(0),
DIVR2EN(0),
DIVP3EN(0),
DIVQ3EN(0),
DIVR3EN(0),
PLL1RGE_V(4_8MHZ),
PLL1VCOSEL_V(WIDE));
reg_writef(RCC_PLL1DIVR,
DIVN(80 - 1), /* 6 * 80 = 480 MHz */
DIVP(1 - 1), /* 480 / 1 = 480 MHz */
DIVQ(8 - 1), /* 480 / 8 = 60 MHz */
DIVR(1 - 1));
reg_writef(RCC_CR, PLL1ON(1));
while (!reg_readf(RCC_CR, PLL1RDY));
}
static void init_vos(void)
{
reg_writef(PWR_D3CR, VOS_V(VOS1));
while (!reg_readf(PWR_D3CR, VOSRDY));
if (STM32H743_USE_VOS0)
{
reg_writef(RCC_APB4ENR, SYSCFGEN(1));
/* Set ODEN bit to enter VOS0 */
reg_writef(SYSCFG_PWRCFG, ODEN(1));
while (!reg_readf(PWR_D3CR, VOSRDY));
reg_writef(RCC_APB4ENR, SYSCFGEN(0));
}
}
static void init_system_clock(void)
{
/* Enable HCLK /2 divider (CPU is at 480 MHz, HCLK limit is 240 MHz) */
reg_writef(RCC_D1CFGR, HPRE(8));
while (reg_readf(RCC_D1CFGR, HPRE) != 8);
/* Enable ABP /2 dividers (HCLK/2, APB limit is 120 MHz) */
reg_writef(RCC_D1CFGR, D1PPRE(4));
reg_writef(RCC_D2CFGR, D2PPRE1(4), D2PPRE2(4));
reg_writef(RCC_D3CFGR, D3PPRE(4));
/* Switch to PLL1P system clock source */
reg_writef(RCC_CFGR, SW_V(PLL1P));
while (reg_readf(RCC_CFGR, SWS) != BV_RCC_CFGR_SWS_PLL1P);
/* Reduce flash access latency */
reg_writef(FLASH_ACR, LATENCY(4), WRHIGHFREQ(2));
while (reg_readf(FLASH_ACR, LATENCY) != 4);
}
static void init_lse(void)
{
/*
* Skip if LSE and RTC are already enabled.
*/
if (reg_readf(RCC_BDCR, LSERDY) &&
reg_readf(RCC_BDCR, RTCEN))
return;
/*
* Enable LSE and set it as RTC clock source,
* then re-enable backup domain write protection.
*/
reg_writef(PWR_CR1, DBP(1));
/* Reset backup domain */
reg_writef(RCC_BDCR, BDRST(1));
reg_writef(RCC_BDCR, BDRST(0));
reg_writef(RCC_BDCR, LSEON(1), LSEDRV(3));
while (!reg_readf(RCC_BDCR, LSERDY));
reg_writef(RCC_BDCR, RTCEN(1), RTCSEL_V(LSE));
reg_writef(PWR_CR1, DBP(0));
}
void stm_target_clock_init(void)
{
init_hse();
init_pll();
init_vos();
init_system_clock();
init_lse();
}

View file

@ -20,13 +20,10 @@
****************************************************************************/
#include "system.h"
#include "tick.h"
#include "clock-stm32h7.h"
#include "gpio-stm32h7.h"
#include "regs/cortex-m/cm_scb.h"
#include "regs/cortex-m/cm_systick.h"
#include "regs/stm32h743/rcc.h"
#include "regs/stm32h743/pwr.h"
#include "regs/stm32h743/syscfg.h"
#include "regs/stm32h743/flash.h"
#include "regs/stm32h743/dbgmcu.h"
/* EXT timer is 1/8th of CPU clock */
@ -38,9 +35,6 @@
#define SYSTICK_DELAY_MAX_US (1000000 / HZ / 2)
#define SYSTICK_DELAY_MAX_MS (SYSTICK_DELAY_MAX_US / 1000)
/* Flag to use VOS0 */
#define STM32H743_USE_VOS0 (CPU_FREQ > 400000000)
/* Base address of vector table */
extern char __vectors_arm[];
@ -61,112 +55,6 @@ static void stm_enable_caches(void)
arm_isb();
}
static void stm_init_hse(void)
{
reg_writef(RCC_CR, HSEON(1));
while (!reg_readf(RCC_CR, HSERDY));
}
static void stm_init_pll(void)
{
/* TODO - this should be determined by the target in some way. */
/* Select HSE/4 input for PLL1 (6 MHz) */
reg_writef(RCC_PLLCKSELR,
PLLSRC_V(HSE),
DIVM1(4),
DIVM2(0),
DIVM3(0));
/* Enable PLL1P and PLL1Q */
reg_writef(RCC_PLLCFGR,
DIVP1EN(1),
DIVQ1EN(1),
DIVR1EN(0),
DIVP2EN(0),
DIVQ2EN(0),
DIVR2EN(0),
DIVP3EN(0),
DIVQ3EN(0),
DIVR3EN(0),
PLL1RGE_V(4_8MHZ),
PLL1VCOSEL_V(WIDE));
reg_writef(RCC_PLL1DIVR,
DIVN(80 - 1), /* 6 * 80 = 480 MHz */
DIVP(1 - 1), /* 480 / 1 = 480 MHz */
DIVQ(8 - 1), /* 480 / 8 = 60 MHz */
DIVR(1 - 1));
reg_writef(RCC_CR, PLL1ON(1));
while (!reg_readf(RCC_CR, PLL1RDY));
}
static void stm_init_vos(void)
{
reg_writef(PWR_D3CR, VOS_V(VOS1));
while (!reg_readf(PWR_D3CR, VOSRDY));
if (STM32H743_USE_VOS0)
{
reg_writef(RCC_APB4ENR, SYSCFGEN(1));
/* Set ODEN bit to enter VOS0 */
reg_writef(SYSCFG_PWRCFG, ODEN(1));
while (!reg_readf(PWR_D3CR, VOSRDY));
reg_writef(RCC_APB4ENR, SYSCFGEN(0));
}
}
static void stm_init_system_clock(void)
{
/* Enable HCLK /2 divider (CPU is at 480 MHz, HCLK limit is 240 MHz) */
reg_writef(RCC_D1CFGR, HPRE(8));
while (reg_readf(RCC_D1CFGR, HPRE) != 8);
/* Enable ABP /2 dividers (HCLK/2, APB limit is 120 MHz) */
reg_writef(RCC_D1CFGR, D1PPRE(4));
reg_writef(RCC_D2CFGR, D2PPRE1(4), D2PPRE2(4));
reg_writef(RCC_D3CFGR, D3PPRE(4));
/* Switch to PLL1P system clock source */
reg_writef(RCC_CFGR, SW_V(PLL1P));
while (reg_readf(RCC_CFGR, SWS) != BV_RCC_CFGR_SWS_PLL1P);
/* Reduce flash access latency */
reg_writef(FLASH_ACR, LATENCY(4), WRHIGHFREQ(2));
while (reg_readf(FLASH_ACR, LATENCY) != 4);
}
static void stm_init_lse(void)
{
/*
* Skip if LSE and RTC are already enabled.
*/
if (reg_readf(RCC_BDCR, LSERDY) &&
reg_readf(RCC_BDCR, RTCEN))
return;
/*
* Enable LSE and set it as RTC clock source,
* then re-enable backup domain write protection.
*/
reg_writef(PWR_CR1, DBP(1));
/* Reset backup domain */
reg_writef(RCC_BDCR, BDRST(1));
reg_writef(RCC_BDCR, BDRST(0));
reg_writef(RCC_BDCR, LSEON(1), LSEDRV(3));
while (!reg_readf(RCC_BDCR, LSERDY));
reg_writef(RCC_BDCR, RTCEN(1), RTCSEL_V(LSE));
reg_writef(PWR_CR1, DBP(0));
}
void system_init(void)
{
#if defined(DEBUG)
@ -180,14 +68,8 @@ void system_init(void)
/* Enable CPU caches */
stm_enable_caches();
/* Start up clocks and get running at max CPU frequency */
stm_init_hse();
stm_init_pll();
stm_init_vos();
stm_init_system_clock();
/* Start up LSE and RTC if necessary so backup domain works */
stm_init_lse();
/* Initialize system clocks */
stm_target_clock_init();
/* TODO: move this */
systick_init(1000/HZ);