Commit 82f75ed3 authored by Katsuhiro Suzuki's avatar Katsuhiro Suzuki Committed by Christopher Friedt
Browse files

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: default avatarKatsuhiro Suzuki <katsuhiro@katsuster.net>
parent 763428d5
Loading
Loading
Loading
Loading
+172 −0
Original line number Diff line number Diff line
/*
 * 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>;
		};
	};
};
+2 −1
Original line number Diff line number Diff line
# SPDX-License-Identifier: Apache-2.0

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)
+5 −0
Original line number Diff line number Diff line
@@ -11,4 +11,9 @@ config SOC_RISCV_SIFIVE_FREEDOM
	bool "SiFive Freedom SOC implementation"
	select ATOMIC_OPERATIONS_C

config SOC_RISCV_SIFIVE_FU540
	bool "SiFive Freedom U540 SOC implementation"
	select ATOMIC_OPERATIONS_C
	select 64BIT

endchoice
+34 −0
Original line number Diff line number Diff line
/*
 * 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);
+42 −0
Original line number Diff line number Diff line
/*
 * 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 */
Loading