soc: riscv: sifive-freedom: fe310: Support custom coreclk rate in DTS.
Allow coreclk to be configured up to 320 MHz from DTS. Signed-off-by: Shawn Nematbakhsh <shawn@rivosinc.com>
This commit is contained in:
parent
c74526919d
commit
a8ffd19281
2 changed files with 42 additions and 6 deletions
|
@ -71,6 +71,11 @@
|
|||
};
|
||||
};
|
||||
|
||||
&coreclk {
|
||||
clock-frequency = <DT_FREQ_M(16)>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
|
|
@ -8,19 +8,50 @@
|
|||
#include <init.h>
|
||||
#include "fe310_prci.h"
|
||||
|
||||
BUILD_ASSERT(MHZ(16) == DT_PROP(DT_NODELABEL(coreclk), clock_frequency),
|
||||
"Unsupported CORECLK frequency");
|
||||
#define CORECLK_HZ (DT_PROP(DT_NODELABEL(coreclk), clock_frequency))
|
||||
BUILD_ASSERT(DT_PROP(DT_NODELABEL(tlclk), clock_div) == 1,
|
||||
"Unsupported TLCLK divider");
|
||||
|
||||
/* Selects the 16MHz oscillator on the HiFive1 board, which provides a clock
|
||||
* that's accurate enough to actually drive serial ports off of.
|
||||
*/
|
||||
static int fe310_clock_init(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
PRCI_REG(PRCI_PLLCFG) = PLL_REFSEL(1) | PLL_BYPASS(1);
|
||||
/*
|
||||
* HFXOSC (16 MHz) is used to produce coreclk (and therefore tlclk /
|
||||
* peripheral clock). This code supports the following frequencies:
|
||||
* - 16 MHz (bypass HFPLL).
|
||||
* - 48 MHz - 320 MHz, in 8 MHz steps (use HFPLL).
|
||||
*/
|
||||
BUILD_ASSERT(MHZ(16) == CORECLK_HZ ||
|
||||
(MHZ(48) <= CORECLK_HZ && MHZ(320) >= CORECLK_HZ &&
|
||||
(CORECLK_HZ % MHZ(8)) == 0),
|
||||
"Unsupported CORECLK frequency");
|
||||
|
||||
uint32_t prci;
|
||||
|
||||
if (MHZ(16) == CORECLK_HZ) {
|
||||
/* Bypass HFPLL. */
|
||||
prci = PLL_REFSEL(1) | PLL_BYPASS(1);
|
||||
} else {
|
||||
/* refr = 8 MHz. */
|
||||
const int pll_r = 0x1;
|
||||
int pll_q;
|
||||
|
||||
/* Select Q divisor to produce vco on [384 MHz, 768 MHz]. */
|
||||
if (MHZ(768) / 8 >= CORECLK_HZ) {
|
||||
pll_q = 0x3;
|
||||
} else if (MHZ(768) / 4 >= CORECLK_HZ) {
|
||||
pll_q = 0x2;
|
||||
} else {
|
||||
pll_q = 0x1;
|
||||
}
|
||||
/* Select F multiplier to produce vco target. */
|
||||
const int pll_f = ((CORECLK_HZ / MHZ(1)) >> (4 - pll_q)) - 1;
|
||||
|
||||
prci = PLL_REFSEL(1) | PLL_R(pll_r) | PLL_F(pll_f) | PLL_Q(pll_q);
|
||||
}
|
||||
|
||||
PRCI_REG(PRCI_PLLCFG) = prci;
|
||||
PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));
|
||||
PRCI_REG(PRCI_PLLCFG) |= PLL_SEL(1);
|
||||
PRCI_REG(PRCI_HFROSCCFG) &= ~ROSC_EN(1);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue