mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
103 lines
3.3 KiB
C
103 lines
3.3 KiB
C
/*
|
|
* Copyright (C) 2017, 2019 Ken Rabold, JP Bonn
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
|
|
/**
|
|
* @ingroup cpu_fe310
|
|
* @{
|
|
*
|
|
* @file cpu.c
|
|
* @brief Implementation of the clock initialization for SiFive FE310
|
|
*
|
|
* @author Ken Rabold
|
|
* @}
|
|
*/
|
|
|
|
#include "clk.h"
|
|
#include "cpu.h"
|
|
#include "periph_conf.h"
|
|
|
|
#include "vendor/prci_driver.h"
|
|
|
|
#if IS_ACTIVE(CONFIG_USE_CLOCK_HFROSC) || IS_ACTIVE(CONFIG_USE_CLOCK_HFROSC_PLL)
|
|
uint32_t cpu_coreclk = 0;
|
|
#endif
|
|
|
|
void fe310_clock_init(void)
|
|
{
|
|
/* Ensure that we aren't running off the PLL before we mess with it. */
|
|
if (PRCI_REG(PRCI_PLLCFG) & PLL_SEL(1)) {
|
|
/* Make sure the HFROSC is running at its default setting */
|
|
/* It is OK to change this even if we are running off of it.*/
|
|
PRCI_REG(PRCI_HFROSCCFG) = (ROSC_DIV(4) | ROSC_TRIM(16) | ROSC_EN(1));
|
|
|
|
/* Wait for HFROSC to be ready */
|
|
while ((PRCI_REG(PRCI_HFROSCCFG) & ROSC_RDY(1)) == 0) {}
|
|
|
|
/* Don't use PLL clock source */
|
|
PRCI_REG(PRCI_PLLCFG) &= ~PLL_SEL(PLL_SEL_PLL);
|
|
}
|
|
|
|
if (IS_ACTIVE(CONFIG_USE_CLOCK_HFXOSC) ||
|
|
IS_ACTIVE(CONFIG_USE_CLOCK_HFXOSC_PLL)) {
|
|
/* Ensure HFXOSC is enabled */
|
|
PRCI_REG(PRCI_HFXOSCCFG) = XOSC_EN(1);
|
|
|
|
/* Wait for HFXOSC to become ready */
|
|
while ((PRCI_REG(PRCI_HFXOSCCFG) & XOSC_RDY(1)) == 0) {}
|
|
|
|
/* Select HFXOSC as reference frequency and bypass PLL */
|
|
PRCI_REG(PRCI_PLLCFG) = PLL_REFSEL(PLL_REFSEL_HFXOSC) | PLL_BYPASS(1);
|
|
|
|
if (IS_ACTIVE(CONFIG_USE_CLOCK_HFXOSC_PLL)) {
|
|
/* Divide final output frequency by 1 */
|
|
PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));
|
|
|
|
/* Configure PLL */
|
|
PRCI_REG(PRCI_PLLCFG) |= PLL_R(CONFIG_CLOCK_PLL_R) | PLL_F(
|
|
CONFIG_CLOCK_PLL_F) | PLL_Q(CONFIG_CLOCK_PLL_Q);
|
|
|
|
/* Disable PLL Bypass */
|
|
PRCI_REG(PRCI_PLLCFG) &= ~PLL_BYPASS(1);
|
|
|
|
/* Now it is safe to check for PLL Lock */
|
|
while ((PRCI_REG(PRCI_PLLCFG) & PLL_LOCK(1)) == 0) {}
|
|
}
|
|
|
|
/* Switch over to PLL Clock source */
|
|
PRCI_REG(PRCI_PLLCFG) |= PLL_SEL(PLL_SEL_PLL);
|
|
|
|
/* Turn off the HFROSC */
|
|
PRCI_REG(PRCI_HFROSCCFG) &= ~ROSC_EN(1);
|
|
}
|
|
else if (IS_ACTIVE(CONFIG_USE_CLOCK_HFROSC_PLL)) {
|
|
PRCI_set_hfrosctrim_for_f_cpu(CONFIG_CLOCK_DESIRED_FREQUENCY,
|
|
PRCI_FREQ_UNDERSHOOT);
|
|
}
|
|
else { /* Clock HFROSC */
|
|
/* Disable Bypass */
|
|
PRCI_REG(PRCI_PLLCFG) &= ~PLL_BYPASS(1);
|
|
|
|
/* Configure trim and divider values of HFROSC */
|
|
PRCI_REG(PRCI_HFROSCCFG) =
|
|
(ROSC_DIV(CONFIG_CLOCK_HFROSC_DIV) |
|
|
ROSC_TRIM(CONFIG_CLOCK_HFROSC_TRIM) | ROSC_EN(1));
|
|
|
|
/* Wait for HFROSC to be ready */
|
|
while ((PRCI_REG(PRCI_HFROSCCFG) & ROSC_RDY(1)) == 0) {}
|
|
|
|
/* Don't use PLL clock source */
|
|
PRCI_REG(PRCI_PLLCFG) &= ~PLL_SEL(PLL_SEL_PLL);
|
|
}
|
|
|
|
#if IS_ACTIVE(CONFIG_USE_CLOCK_HFROSC) || IS_ACTIVE(CONFIG_USE_CLOCK_HFROSC_PLL)
|
|
/* Ignore the first run (for icache reasons) */
|
|
cpu_coreclk = PRCI_measure_mcycle_freq(3000, RTC_FREQ);
|
|
cpu_coreclk = PRCI_measure_mcycle_freq(3000, RTC_FREQ);
|
|
#endif
|
|
}
|