soc/sifive/fu540: Switch clock to 1GHz in romstage
Invoke clock_init in romstage for SiFive Unleashed. Change-Id: Ib869762d557e8fdf4c83a53698102df116d80389 Signed-off-by: Philipp Hug <philipp@hug.cx> Reviewed-on: https://review.coreboot.org/28602 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
parent
c014ef5919
commit
374d992fc8
|
@ -13,8 +13,13 @@
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <cbmem.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
|
#include <console/streams.h>
|
||||||
|
#include <console/uart.h>
|
||||||
#include <program_loading.h>
|
#include <program_loading.h>
|
||||||
|
#include <soc/clock.h>
|
||||||
|
#include <soc/sdram.h>
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
|
@ -22,5 +27,18 @@ void main(void)
|
||||||
|
|
||||||
/* TODO: Follow Section 6.3 (FSBL) of the FU540 manual */
|
/* TODO: Follow Section 6.3 (FSBL) of the FU540 manual */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flush console before changing clock/UART divisor to prevent garbage
|
||||||
|
* being printed.
|
||||||
|
*/
|
||||||
|
console_tx_flush();
|
||||||
|
|
||||||
|
clock_init();
|
||||||
|
|
||||||
|
// re-initialize UART
|
||||||
|
#if (IS_ENABLED(CONFIG_CONSOLE_SERIAL))
|
||||||
|
uart_init(CONFIG_UART_FOR_CONSOLE);
|
||||||
|
#endif
|
||||||
|
|
||||||
run_ramstage();
|
run_ramstage();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ romstage-y += uart.c
|
||||||
romstage-y += media.c
|
romstage-y += media.c
|
||||||
romstage-y += sdram.c
|
romstage-y += sdram.c
|
||||||
romstage-y += otp.c
|
romstage-y += otp.c
|
||||||
|
romstage-y += clock.c
|
||||||
|
|
||||||
ramstage-y += uart.c
|
ramstage-y += uart.c
|
||||||
ramstage-y += clint.c
|
ramstage-y += clint.c
|
||||||
|
@ -29,6 +30,7 @@ ramstage-y += media.c
|
||||||
ramstage-y += sdram.c
|
ramstage-y += sdram.c
|
||||||
ramstage-y += cbmem.c
|
ramstage-y += cbmem.c
|
||||||
ramstage-y += otp.c
|
ramstage-y += otp.c
|
||||||
|
ramstage-y += clock.c
|
||||||
|
|
||||||
CPPFLAGS_common += -Isrc/soc/sifive/fu540/include
|
CPPFLAGS_common += -Isrc/soc/sifive/fu540/include
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,8 @@ static struct prci_ctlr *prci = (void *)FU540_PRCI;
|
||||||
// 33.33 Mhz after reset
|
// 33.33 Mhz after reset
|
||||||
#define FU540_BASE_FQY 33330
|
#define FU540_BASE_FQY 33330
|
||||||
|
|
||||||
|
#if ENV_ROMSTAGE
|
||||||
|
|
||||||
static void init_coreclk(void)
|
static void init_coreclk(void)
|
||||||
{
|
{
|
||||||
// switch coreclk to input reference frequency before modifying PLL
|
// switch coreclk to input reference frequency before modifying PLL
|
||||||
|
@ -178,28 +180,32 @@ static void init_pll_ddr(void)
|
||||||
write32(&prci->ddrpllcfg1, cfg1);
|
write32(&prci->ddrpllcfg1, cfg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int clock_get_coreclk_khz(void)
|
#define FU540_UART_DEVICES 2
|
||||||
|
#define FU540_UART_REG_DIV 0x18
|
||||||
|
#define FU540_UART_DIV_VAL 4
|
||||||
|
|
||||||
|
#define FU540_SPI_DIV 0x00
|
||||||
|
#define FU540_SPI_DIV_VAL 4
|
||||||
|
|
||||||
|
|
||||||
|
static void update_peripheral_clock_dividers(void)
|
||||||
{
|
{
|
||||||
if (read32(&prci->coreclksel) & PRCI_CORECLK_MASK)
|
write32((uint32_t *)(FU540_QSPI0 + FU540_SPI_DIV), FU540_SPI_DIV_VAL);
|
||||||
return FU540_BASE_FQY;
|
write32((uint32_t *)(FU540_QSPI1 + FU540_SPI_DIV), FU540_SPI_DIV_VAL);
|
||||||
|
write32((uint32_t *)(FU540_QSPI2 + FU540_SPI_DIV), FU540_SPI_DIV_VAL);
|
||||||
|
|
||||||
u32 cfg = read32(&prci->corepllcfg0);
|
for (size_t i = 0; i < FU540_UART_DEVICES; i++)
|
||||||
u32 divr = (cfg & PRCI_COREPLLCFG0_DIVR_MASK)
|
write32((uint32_t *)(FU540_UART(i) + FU540_UART_REG_DIV), FU540_UART_DIV_VAL);
|
||||||
>> PRCI_COREPLLCFG0_DIVR_SHIFT;
|
|
||||||
u32 divf = (cfg & PRCI_COREPLLCFG0_DIVF_MASK)
|
|
||||||
>> PRCI_COREPLLCFG0_DIVF_SHIFT;
|
|
||||||
u32 divq = (cfg & PRCI_COREPLLCFG0_DIVQ_MASK)
|
|
||||||
>> PRCI_COREPLLCFG0_DIVQ_SHIFT;
|
|
||||||
|
|
||||||
printk(BIOS_SPEW, "clk: r=%d f=%d q=%d\n", divr, divf, divq);
|
|
||||||
return FU540_BASE_FQY
|
|
||||||
* 2 * (divf + 1)
|
|
||||||
/ (divr + 1)
|
|
||||||
/ (1ul << divq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clock_init(void)
|
void clock_init(void)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Update the peripheral clock dividers of UART, SPI and I2C to safe
|
||||||
|
* values as we can't put them in reset before changing frequency.
|
||||||
|
*/
|
||||||
|
update_peripheral_clock_dividers();
|
||||||
|
|
||||||
init_coreclk();
|
init_coreclk();
|
||||||
|
|
||||||
// put DDR and ethernet in reset
|
// put DDR and ethernet in reset
|
||||||
|
@ -234,3 +240,25 @@ void clock_init(void)
|
||||||
for (int i = 0; i < 256; i++)
|
for (int i = 0; i < 256; i++)
|
||||||
asm volatile ("nop");
|
asm volatile ("nop");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int clock_get_coreclk_khz(void)
|
||||||
|
{
|
||||||
|
if (read32(&prci->coreclksel) & PRCI_CORECLK_MASK)
|
||||||
|
return FU540_BASE_FQY;
|
||||||
|
|
||||||
|
u32 cfg = read32(&prci->corepllcfg0);
|
||||||
|
u32 divr = (cfg & PRCI_COREPLLCFG0_DIVR_MASK)
|
||||||
|
>> PRCI_COREPLLCFG0_DIVR_SHIFT;
|
||||||
|
u32 divf = (cfg & PRCI_COREPLLCFG0_DIVF_MASK)
|
||||||
|
>> PRCI_COREPLLCFG0_DIVF_SHIFT;
|
||||||
|
u32 divq = (cfg & PRCI_COREPLLCFG0_DIVQ_MASK)
|
||||||
|
>> PRCI_COREPLLCFG0_DIVQ_SHIFT;
|
||||||
|
|
||||||
|
printk(BIOS_SPEW, "clk: r=%d f=%d q=%d\n", divr, divf, divq);
|
||||||
|
return FU540_BASE_FQY
|
||||||
|
* 2 * (divf + 1)
|
||||||
|
/ (divr + 1)
|
||||||
|
/ (1ul << divq);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue