mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-04-12 00:47:49 -04:00
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:
parent
37b90baa5f
commit
23448a13d1
4 changed files with 180 additions and 121 deletions
|
|
@ -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
|
||||
|
|
|
|||
33
firmware/target/arm/stm32/clock-stm32h7.h
Normal file
33
firmware/target/arm/stm32/clock-stm32h7.h
Normal 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__ */
|
||||
143
firmware/target/arm/stm32/echoplayer/clock-echoplayer.c
Normal file
143
firmware/target/arm/stm32/echoplayer/clock-echoplayer.c
Normal 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();
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue