soc: riscv: add initial support for SiFive Freedom U740
This patch adds support for SiFive Freedom U740 SoC. First version is minimum only using UART, SPI and L2-LIM area. Signed-off-by: Katsuhiro Suzuki <katsuhiro@katsuster.net>
This commit is contained in:
parent
ae355cce56
commit
ca853af0b9
6 changed files with 276 additions and 1 deletions
143
dts/riscv/riscv64-fu740.dtsi
Normal file
143
dts/riscv/riscv64-fu740.dtsi
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* 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,FU740-C000", "fu740-dev", "sifive-dev";
|
||||
model = "sifive,FU740";
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu: cpu@0 {
|
||||
compatible = "sifive,s7", "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";
|
||||
};
|
||||
|
||||
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 0x200000>;
|
||||
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>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -3,3 +3,4 @@
|
|||
zephyr_sources()
|
||||
zephyr_sources_ifdef(CONFIG_SOC_RISCV_SIFIVE_FREEDOM fe310_clock.c)
|
||||
zephyr_sources_ifdef(CONFIG_SOC_RISCV_SIFIVE_FU540 fu540_clock.c)
|
||||
zephyr_sources_ifdef(CONFIG_SOC_RISCV_SIFIVE_FU740 fu740_clock.c)
|
||||
|
|
|
@ -16,4 +16,9 @@ config SOC_RISCV_SIFIVE_FU540
|
|||
select ATOMIC_OPERATIONS_C
|
||||
select 64BIT
|
||||
|
||||
config SOC_RISCV_SIFIVE_FU740
|
||||
bool "SiFive Freedom U740 SOC implementation"
|
||||
select ATOMIC_OPERATIONS_C
|
||||
select 64BIT
|
||||
|
||||
endchoice
|
||||
|
|
53
soc/riscv/riscv-privilege/sifive-freedom/fu740_clock.c
Normal file
53
soc/riscv/riscv-privilege/sifive-freedom/fu740_clock.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Katsuhiro Suzuki
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <init.h>
|
||||
#include "fu740_prci.h"
|
||||
|
||||
/*
|
||||
* Switch the clock source
|
||||
* - core: to 1GHz PLL (CORE_PLL) from 26MHz oscilator (HFCLK)
|
||||
* - peri: to 250MHz PLL (HFPCLKPLL) from HFCLK
|
||||
* on the HiFive Unmatched board.
|
||||
*
|
||||
* Note: Valid PLL VCO range is 2400MHz to 4800MHz
|
||||
*/
|
||||
static int fu740_clock_init(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
PRCI_REG(PRCI_COREPLLCFG) =
|
||||
PLL_R(0) | /* input divider: Fin / (0 + 1) = 26MHz */
|
||||
PLL_F(76) | /* VCO: 2 x (76 + 1) = 154 = 4004MHz */
|
||||
PLL_Q(2) | /* output divider: VCO / 2^2 = 1001MHz */
|
||||
PLL_RANGE(PLL_RANGE_18MHZ) | /* 18MHz <= post divr(= 26MHz) < 30MHz */
|
||||
PLL_BYPASS(PLL_BYPASS_DISABLE) |
|
||||
PLL_FSE(PLL_FSE_INTERNAL);
|
||||
while ((PRCI_REG(PRCI_COREPLLCFG) & PLL_LOCK(1)) == 0)
|
||||
;
|
||||
|
||||
/* Switch CORE_CLK to CORE_PLL from HFCLK */
|
||||
PRCI_REG(PRCI_COREPLLSEL) = COREPLLSEL_SEL(COREPLLSEL_COREPLL);
|
||||
PRCI_REG(PRCI_CORECLKSEL) = CLKSEL_SEL(CLKSEL_PLL);
|
||||
|
||||
PRCI_REG(PRCI_HFPCLKPLLCFG) =
|
||||
PLL_R(0) | /* input divider: Fin / (0 + 1) = 26MHz */
|
||||
PLL_F(76) | /* VCO: 2 x (76 + 1) = 154 = 4004MHz */
|
||||
PLL_Q(4) | /* output divider: VCO / 2^4 = 250.25MHz */
|
||||
PLL_RANGE(PLL_RANGE_18MHZ) | /* 18MHz <= post divr(= 26MHz) < 30MHz */
|
||||
PLL_BYPASS(PLL_BYPASS_DISABLE) |
|
||||
PLL_FSE(PLL_FSE_INTERNAL);
|
||||
while ((PRCI_REG(PRCI_HFPCLKPLLCFG) & PLL_LOCK(1)) == 0)
|
||||
;
|
||||
|
||||
/* Switch PCLK to HFPCLKPLL/2 from HFCLK/2 */
|
||||
PRCI_REG(PRCI_HFPCLKPLLOUTDIV) = OUTDIV_PLLCKE(OUTDIV_PLLCKE_ENA);
|
||||
PRCI_REG(PRCI_HFPCLKPLLSEL) = CLKSEL_SEL(CLKSEL_PLL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(fu740_clock_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
73
soc/riscv/riscv-privilege/sifive-freedom/fu740_prci.h
Normal file
73
soc/riscv/riscv-privilege/sifive-freedom/fu740_prci.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Katsuhiro Suzuki
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _SIFIVE_FU740_PRCI_H
|
||||
#define _SIFIVE_FU740_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_COREPLLCFG (0x0004)
|
||||
#define PRCI_COREPLLOUTDIV (0x0008)
|
||||
#define PRCI_DDRPLLCFG (0x000c)
|
||||
#define PRCI_DDRPLLOUTDIV (0x0010)
|
||||
#define PRCI_GEMGXLPLLCFG (0x001c)
|
||||
#define PRCI_GEMGXLPLLOUTDIV (0x0020)
|
||||
#define PRCI_CORECLKSEL (0x0024)
|
||||
#define PRCI_DEVICESRESETN (0x0028)
|
||||
#define PRCI_CLKMUXSTATUS (0x002c)
|
||||
#define PRCI_COREPLLSEL (0x0040)
|
||||
#define PRCI_HFPCLKPLLCFG (0x0050)
|
||||
#define PRCI_HFPCLKPLLOUTDIV (0x0054)
|
||||
#define PRCI_HFPCLKPLLSEL (0x0058)
|
||||
|
||||
#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_RESET 0
|
||||
#define PLL_RANGE_0MHZ 1
|
||||
#define PLL_RANGE_11MHZ 2
|
||||
#define PLL_RANGE_18MHZ 3
|
||||
#define PLL_RANGE_30MHZ 4
|
||||
#define PLL_RANGE_50MHZ 5
|
||||
#define PLL_RANGE_80MHZ 6
|
||||
#define PLL_RANGE_130MHZ 7
|
||||
#define PLL_BYPASS_DISABLE 0
|
||||
#define PLL_BYPASS_ENABLE 1
|
||||
#define PLL_FSE_INTERNAL 1
|
||||
|
||||
#define OUTDIV_PLLCKE(x) (((x) & 0x1) << 31)
|
||||
|
||||
#define OUTDIV_PLLCKE_DIS 0
|
||||
#define OUTDIV_PLLCKE_ENA 1
|
||||
|
||||
#define CLKSEL_SEL(x) (((x) & 0x1) << 0)
|
||||
|
||||
#define CLKSEL_PLL 0
|
||||
#define CLKSEL_HFCLK 1
|
||||
|
||||
#define CLKMUXSTATUS_CORECLKPLLSEL_OFF 0
|
||||
#define CLKMUXSTATUS_TLCLKSEL_OFF 1
|
||||
#define CLKMUXSTATUS_RTCXSEL_OFF 2
|
||||
#define CLKMUXSTATUS_DDRCTRLCLKSEL_OFF 3
|
||||
#define CLKMUXSTATUS_DDRPHYCLKSEL_OFF 4
|
||||
#define CLKMUXSTATUS_GEMGXLCLKSEL_OFF 6
|
||||
#define CLKMUXSTATUS_MAINMEMCLKSEL_OFF 7
|
||||
|
||||
#define COREPLLSEL_SEL(x) (((x) & 0x1) << 0)
|
||||
|
||||
#define COREPLLSEL_COREPLL 0
|
||||
#define COREPLLSEL_DVFSCOREPLL 1
|
||||
|
||||
#endif /* _SIFIVE_FU740_PRCI_H */
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
#define SIFIVE_BACKUP_REG_BASE 0x10000080
|
||||
|
||||
#elif defined(CONFIG_SOC_RISCV_SIFIVE_FU540)
|
||||
#elif defined(CONFIG_SOC_RISCV_SIFIVE_FU540) || defined(CONFIG_SOC_RISCV_SIFIVE_FU740)
|
||||
|
||||
/* Clock controller. */
|
||||
#define PRCI_BASE_ADDR 0x10000000
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue