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

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: default avatarKatsuhiro Suzuki <katsuhiro@katsuster.net>
parent ae355cce
Loading
Loading
Loading
Loading
+143 −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,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>;
		};
	};
};
+1 −0
Original line number Diff line number Diff line
@@ -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)
+5 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
/*
 * 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 −0
Original line number Diff line number Diff line
/*
 * 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 */
Loading