1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/fe310/clock.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
}