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 {
|
&gpio0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,19 +8,50 @@
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include "fe310_prci.h"
|
#include "fe310_prci.h"
|
||||||
|
|
||||||
BUILD_ASSERT(MHZ(16) == DT_PROP(DT_NODELABEL(coreclk), clock_frequency),
|
#define CORECLK_HZ (DT_PROP(DT_NODELABEL(coreclk), clock_frequency))
|
||||||
"Unsupported CORECLK frequency");
|
|
||||||
BUILD_ASSERT(DT_PROP(DT_NODELABEL(tlclk), clock_div) == 1,
|
BUILD_ASSERT(DT_PROP(DT_NODELABEL(tlclk), clock_div) == 1,
|
||||||
"Unsupported TLCLK divider");
|
"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)
|
static int fe310_clock_init(const struct device *dev)
|
||||||
{
|
{
|
||||||
ARG_UNUSED(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_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));
|
||||||
PRCI_REG(PRCI_PLLCFG) |= PLL_SEL(1);
|
PRCI_REG(PRCI_PLLCFG) |= PLL_SEL(1);
|
||||||
PRCI_REG(PRCI_HFROSCCFG) &= ~ROSC_EN(1);
|
PRCI_REG(PRCI_HFROSCCFG) &= ~ROSC_EN(1);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue