soc: riscv: add initial support for SiFive Freedom U540

This patch adds support for SiFive Freedom U540 SoC.
First version is minimum only using UART, SPI and DDR memory area.

Signed-off-by: Katsuhiro Suzuki <katsuhiro@katsuster.net>
This commit is contained in:
Katsuhiro Suzuki 2021-06-09 18:33:12 +09:00 committed by Christopher Friedt
commit 82f75ed337
6 changed files with 268 additions and 5 deletions

View file

@ -0,0 +1,172 @@
/*
* Copyright (c) 2021 Katsuhiro Suzuki
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <dt-bindings/gpio/gpio.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "sifive,FU540-C000", "fu540-dev", "sifive-dev";
model = "sifive,FU540";
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu: cpu@0 {
compatible = "sifive,e51", "riscv";
device_type = "cpu";
reg = <0>;
riscv,isa = "rv64imac";
status = "okay";
hlic: interrupt-controller {
#interrupt-cells = <1>;
compatible = "riscv,cpu-intc";
interrupt-controller;
};
};
};
soc {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
modeselect: rom@1000 {
compatible = "sifive,modeselect0";
reg = <0x1000 0x1000>;
reg-names = "mem";
};
maskrom: rom@10000 {
compatible = "sifive,maskrom0";
reg = <0x10000 0x8000>;
reg-names = "mem";
};
dtim: dtim@1000000 {
compatible = "sifive,dtim0";
reg = <0x1000000 0x2000>;
reg-names = "mem";
};
itim0: itim0@1800000 {
compatible = "sifive,itim0";
reg = <0x1800000 0x2000>;
reg-names = "mem";
};
itim1: itim1@1808000 {
compatible = "sifive,itim0";
reg = <0x1808000 0x7000>;
reg-names = "mem";
};
itim2: itim2@1810000 {
compatible = "sifive,itim0";
reg = <0x1810000 0x7000>;
reg-names = "mem";
};
itim3: itim3@1818000 {
compatible = "sifive,itim0";
reg = <0x1818000 0x7000>;
reg-names = "mem";
};
itim4: itim4@1820000 {
compatible = "sifive,itim0";
reg = <0x1820000 0x7000>;
reg-names = "mem";
};
clint: clint@2000000 {
#interrupt-cells = <1>;
compatible = "riscv,clint0";
interrupt-controller;
interrupts-extended = <&hlic 3 &hlic 7>;
reg = <0x2000000 0x10000>;
reg-names = "control";
};
l2lim: l2lim@8000000 {
compatible = "sifive,l2lim0";
reg = <0x8000000 0x2000000>;
reg-names = "mem";
};
plic: interrupt-controller@c000000 {
#interrupt-cells = <2>;
compatible = "sifive,plic-1.0.0";
interrupt-controller;
interrupts-extended = <&hlic 11>;
reg = <0x0c000000 0x00002000
0x0c002000 0x001fe000
0x0c200000 0x03e00000>;
reg-names = "prio", "irq_en", "reg";
riscv,max-priority = <7>;
riscv,ndev = <52>;
};
uart0: serial@10010000 {
compatible = "sifive,uart0";
interrupt-parent = <&plic>;
interrupts = <4 1>;
reg = <0x10010000 0x1000>;
reg-names = "control";
label = "uart_0";
status = "disabled";
};
uart1: serial@10011000 {
compatible = "sifive,uart0";
interrupt-parent = <&plic>;
interrupts = <5 1>;
reg = <0x10011000 0x1000>;
reg-names = "control";
label = "uart_1";
status = "disabled";
};
spi0: spi@10040000 {
compatible = "sifive,spi0";
interrupt-parent = <&plic>;
interrupts = <51 1>;
reg = <0x10040000 0x1000 0x20000000 0x10000000>;
reg-names = "control", "mem";
label = "spi_0";
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
spi1: spi@10041000 {
compatible = "sifive,spi0";
interrupt-parent = <&plic>;
interrupts = <52 1>;
reg = <0x10041000 0x1000>;
reg-names = "control";
label = "spi_1";
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
spi2: spi@10050000 {
compatible = "sifive,spi0";
interrupt-parent = <&plic>;
interrupts = <6 1>;
reg = <0x10050000 0x1000>;
reg-names = "control";
label = "spi_2";
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
};
};
};

View file

@ -1,4 +1,5 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
zephyr_sources() zephyr_sources()
zephyr_sources(fe310_clock.c) zephyr_sources_ifdef(CONFIG_SOC_RISCV_SIFIVE_FREEDOM fe310_clock.c)
zephyr_sources_ifdef(CONFIG_SOC_RISCV_SIFIVE_FU540 fu540_clock.c)

View file

@ -11,4 +11,9 @@ config SOC_RISCV_SIFIVE_FREEDOM
bool "SiFive Freedom SOC implementation" bool "SiFive Freedom SOC implementation"
select ATOMIC_OPERATIONS_C select ATOMIC_OPERATIONS_C
config SOC_RISCV_SIFIVE_FU540
bool "SiFive Freedom U540 SOC implementation"
select ATOMIC_OPERATIONS_C
select 64BIT
endchoice endchoice

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2021 Katsuhiro Suzuki
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <init.h>
#include "fu540_prci.h"
/*
* Switch the clock source to 1GHz PLL from 33.333MHz oscilator on the HiFive
* Unleashed board.
*/
static int fu540_clock_init(const struct device *dev)
{
ARG_UNUSED(dev);
PRCI_REG(PRCI_COREPLLCFG0) =
PLL_R(0) | /* input divider: Fin / (0 + 1) = 33.33MHz */
PLL_F(59) | /* VCO: 2 x (59 + 1) = 120 = 3999.6MHz */
PLL_Q(2) | /* output divider: VCO / 2^2 = 999.9MHz */
PLL_RANGE(PLL_RANGE_33MHZ) |
PLL_BYPASS(PLL_BYPASS_DISABLE) |
PLL_FSE(PLL_FSE_INTERNAL);
while ((PRCI_REG(PRCI_COREPLLCFG0) & PLL_LOCK(1)) == 0)
;
/* Switch clock to COREPLL */
PRCI_REG(PRCI_CORECLKSEL) = CORECLKSEL_CORECLKSEL(CORECLKSEL_CORE_PLL);
return 0;
}
SYS_INIT(fu540_clock_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2021 Katsuhiro Suzuki
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _SIFIVE_FU540_PRCI_H
#define _SIFIVE_FU540_PRCI_H
#define Z_REG32(p, i) (*(volatile uint32_t *) ((p) + (i)))
#define PRCI_REG(offset) Z_REG32(PRCI_BASE_ADDR, offset)
/* Register offsets */
#define PRCI_HFXOSCCFG (0x0000)
#define PRCI_COREPLLCFG0 (0x0004)
#define PRCI_DDRPLLCFG0 (0x000c)
#define PRCI_DDRPLLCFG1 (0x0010)
#define PRCI_GEMGXLPLLCFG0 (0x001c)
#define PRCI_GEMGXLPLLCFG1 (0x0020)
#define PRCI_CORECLKSEL (0x0024)
#define PRCI_DEVICESRESETREG (0x0028)
#define PLL_R(x) (((x) & 0x3f) << 0)
#define PLL_F(x) (((x) & 0x1ff) << 6)
#define PLL_Q(x) (((x) & 0x7) << 15)
#define PLL_RANGE(x) (((x) & 0x7) << 18)
#define PLL_BYPASS(x) (((x) & 0x1) << 24)
#define PLL_FSE(x) (((x) & 0x1) << 25)
#define PLL_LOCK(x) (((x) & 0x1) << 31)
#define PLL_RANGE_33MHZ 4
#define PLL_BYPASS_DISABLE 0
#define PLL_BYPASS_ENABLE 1
#define PLL_FSE_INTERNAL 1
#define CORECLKSEL_CORECLKSEL(x) (((x) & 0x1) << 0)
#define CORECLKSEL_CORE_PLL 0
#define CORECLKSEL_HFCLK 1
#endif /* _SIFIVE_FU540_PRCI_H */

View file

@ -14,6 +14,8 @@
#include <soc_common.h> #include <soc_common.h>
#include <devicetree.h> #include <devicetree.h>
#if defined(CONFIG_SOC_RISCV_SIFIVE_FREEDOM)
/* PINMUX IO Hardware Functions */ /* PINMUX IO Hardware Functions */
#define SIFIVE_PINMUX_IOF0 0x00 #define SIFIVE_PINMUX_IOF0 0x00
#define SIFIVE_PINMUX_IOF1 0x01 #define SIFIVE_PINMUX_IOF1 0x01
@ -24,10 +26,6 @@
/* Clock controller. */ /* Clock controller. */
#define PRCI_BASE_ADDR 0x10008000 #define PRCI_BASE_ADDR 0x10008000
/* Timer configuration */
#define RISCV_MTIME_BASE 0x0200BFF8
#define RISCV_MTIMECMP_BASE 0x02004000
/* Always ON Domain */ /* Always ON Domain */
#define SIFIVE_PMUIE 0x10000140 #define SIFIVE_PMUIE 0x10000140
#define SIFIVE_PMUCAUSE 0x10000144 #define SIFIVE_PMUCAUSE 0x10000144
@ -37,6 +35,17 @@
#define SIFIVE_BACKUP_REG_BASE 0x10000080 #define SIFIVE_BACKUP_REG_BASE 0x10000080
#elif defined(CONFIG_SOC_RISCV_SIFIVE_FU540)
/* Clock controller. */
#define PRCI_BASE_ADDR 0x10000000
#endif
/* Timer configuration */
#define RISCV_MTIME_BASE 0x0200BFF8
#define RISCV_MTIMECMP_BASE 0x02004000
/* lib-c hooks required RAM defined variables */ /* lib-c hooks required RAM defined variables */
#define RISCV_RAM_BASE CONFIG_SRAM_BASE_ADDRESS #define RISCV_RAM_BASE CONFIG_SRAM_BASE_ADDRESS
#define RISCV_RAM_SIZE KB(CONFIG_SRAM_SIZE) #define RISCV_RAM_SIZE KB(CONFIG_SRAM_SIZE)