soc/sifive/fu740: Add FU740 SOC

Signed-off-by: Maximilian Brune <maximilian.brune@9elements.com>
Change-Id: I4a8fe02ef0adcb939aa65377a35874715c5ee58a
Reviewed-on: https://review.coreboot.org/c/coreboot/+/76689
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: ron minnich <rminnich@gmail.com>
diff --git a/src/soc/sifive/fu540/include/soc/spi.h b/src/soc/sifive/fu540/include/soc/spi.h
index 3be5baf..1399620 100644
--- a/src/soc/sifive/fu540/include/soc/spi.h
+++ b/src/soc/sifive/fu540/include/soc/spi.h
@@ -2,6 +2,7 @@
 
 #ifndef __SOC_SIFIVE_HIFIVE_U_SPI_H__
 #define __SOC_SIFIVE_HIFIVE_U_SPI_H__
+
 #include <spi-generic.h>
 
 /* Data Pins: MOSI MISO */
diff --git a/src/soc/sifive/fu740/Kconfig b/src/soc/sifive/fu740/Kconfig
new file mode 100644
index 0000000..0c62e1e
--- /dev/null
+++ b/src/soc/sifive/fu740/Kconfig
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config SOC_SIFIVE_FU740
+	bool
+	select ARCH_RISCV_RV64
+	select ARCH_RISCV_S
+	select ARCH_RISCV_U
+	select ARCH_RISCV_PMP
+	select ARCH_BOOTBLOCK_RISCV
+	select ARCH_VERSTAGE_RISCV
+	select ARCH_ROMSTAGE_RISCV
+	select ARCH_RAMSTAGE_RISCV
+	select DRIVERS_UART_SIFIVE
+	select RISCV_USE_ARCH_TIMER
+	select UART_OVERRIDE_REFCLK
+	select RISCV_HAS_OPENSBI
+
+config SEPARATE_ROMSTAGE
+	default n if SOC_SIFIVE_FU740
+
+if SOC_SIFIVE_FU740
+
+config MEMLAYOUT_LD_FILE
+	string
+	default "src/soc/sifive/fu740/memlayout.ld"
+
+config RISCV_ARCH
+	string
+	default "rv64imac"
+
+config RISCV_ABI
+	string
+	default "lp64"
+
+config RISCV_CODEMODEL
+	string
+	default "medany"
+
+# 4x U7 cores (RV64IMAFDC) + 1x S7 core (RV64IMAC)
+config MAX_CPUS
+	int
+	default 5
+
+config RISCV_WORKING_HARTID
+	int
+	default 1 # use U7 core as S7 core does not support supervisor mode
+
+config OPENSBI_PLATFORM
+	string
+	default "generic"
+
+config OPENSBI_TEXT_START
+	hex
+	default 0x80000000
+
+config OPENSBI_FW_DYNAMIC_BOOT_HART
+	int
+	default 1
+	help
+	  Choose the first U74 core as boot hart since
+	  hart 0 is the S7 which does not support Supervisor mode
+
+endif
diff --git a/src/soc/sifive/fu740/Makefile.inc b/src/soc/sifive/fu740/Makefile.inc
new file mode 100644
index 0000000..86c90df
--- /dev/null
+++ b/src/soc/sifive/fu740/Makefile.inc
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+ifeq ($(CONFIG_SOC_SIFIVE_FU740),y)
+
+CPPFLAGS_common += -Isrc/soc/sifive/fu740/include
+
+bootblock-y += uart.c
+bootblock-y += clint.c
+bootblock-y += spi.c
+bootblock-y += sdram.c
+bootblock-y += cbmem.c
+bootblock-y += otp.c
+bootblock-y += clock.c
+bootblock-y += ddrregs.c
+bootblock-y += chip.c
+bootblock-y += gpio.c
+
+
+ramstage-y += uart.c
+ramstage-y += clint.c
+ramstage-y += spi.c
+ramstage-y += sdram.c
+ramstage-y += cbmem.c
+ramstage-y += otp.c
+ramstage-y += clock.c
+ramstage-y += chip.c
+
+$(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin
+	@printf "    GPT        $(notdir $(@))\n"
+	@util/riscv/sifive-gpt.py $< $@
+
+endif
diff --git a/src/soc/sifive/fu740/TODO b/src/soc/sifive/fu740/TODO
new file mode 100644
index 0000000..6e38653
--- /dev/null
+++ b/src/soc/sifive/fu740/TODO
@@ -0,0 +1,51 @@
+1. refactor SPI code. It works but there are quite some TODO left and it also currently only supports 1 MSEL configuration
+2. sometimes PCIe is not working with the following error message in Linux:
+[    0.619711] shpchp: Standard Hot Plug PCI Controller Driver version: 0.4
+[    0.621521] fu740-pcie e00000000.pcie: host bridge /soc/pcie@e00000000 ranges:
+[    0.621603] fu740-pcie e00000000.pcie:       IO 0x0060080000..0x006008ffff -> 0x0060080000
+[    0.621659] fu740-pcie e00000000.pcie:      MEM 0x0060090000..0x007fffffff -> 0x0060090000
+[    0.621685] fu740-pcie e00000000.pcie:      MEM 0x2000000000..0x3fffffffff -> 0x2000000000
+[    0.727890] fu740-pcie e00000000.pcie: iATU: unroll T, 8 ob, 8 ib, align 4K, limit 4096G
+[    0.828041] fu740-pcie e00000000.pcie: PCIe Gen.1 x8 link up
+[    1.828944] fu740-pcie e00000000.pcie: Phy link never came up
+[    1.828961] fu740-pcie e00000000.pcie: error: link did not start at new speed
+[    1.829142] ------------[ cut here ]------------
+[    1.829152] WARNING: CPU: 2 PID: 1 at drivers/pci/controller/dwc/pcie-fu740.c:232 fu740_pcie_start_link+0x1b4/0x1ce
+[    1.829191] Modules linked in:
+[    1.829205] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 6.5.0-9-generic #9.1-Ubuntu
+[    1.829215] Hardware name: SiFive HiFive Unmatched A00 (DT)
+[    1.829221] epc : fu740_pcie_start_link+0x1b4/0x1ce
+[    1.829234]  ra : fu740_pcie_start_link+0x1ca/0x1ce
+[    1.829247] epc : ffffffff806fa1ac ra : ffffffff806fa1c2 sp : ffffffc800023b30
+[    1.829256]  gp : ffffffff822602d8 tp : ffffffd88027b600 t0 : ffffffff82029670
+[    1.829263]  t1 : 0000000000000000 t2 : 0000000000000000 s0 : ffffffc800023b70
+[    1.829270]  s1 : ffffffd88095d840 a0 : 0000000000000000 a1 : 0000000000000000
+[    1.829276]  a2 : 0000000000000000 a3 : 0000000000000000 a4 : 0000000000000000
+[    1.829282]  a5 : 0000000000000000 a6 : 0000000000000000 a7 : 0000000000000000
+[    1.829288]  s2 : ffffffffffffff92 s3 : 0000000000716c81 s4 : ffffffd8802b2c10
+[    1.829295]  s5 : 0000000000000003 s6 : ffffffffffffff92 s7 : ffffffff8108b448
+[    1.829301]  s8 : 0000000000000008 s9 : ffffffff80e00106 s10: 0000000000000000
+[    1.829307]  s11: 0000000000000000 t3 : 0000000000000000 t4 : 0000000000000000
+[    1.829313]  t5 : 0000000000000000 t6 : 0000000000000000
+[    1.829317] status: 0000000200000120 badaddr: ffffffffffffff92 cause: 0000000000000003
+[    1.829326] [<ffffffff806fa1ac>] fu740_pcie_start_link+0x1b4/0x1ce
+[    1.829341] [<ffffffff806f8692>] dw_pcie_host_init+0x21e/0x2cc
+[    1.829355] [<ffffffff806fa2ca>] fu740_pcie_probe+0x104/0x15a
+[    1.829366] [<ffffffff8083e510>] platform_probe+0x5e/0xc6
+[    1.829388] [<ffffffff8083a7b4>] call_driver_probe+0x22/0x142
+[    1.829400] [<ffffffff8083b36e>] really_probe+0x9a/0x2a2
+[    1.829413] [<ffffffff8083b5f4>] __driver_probe_device+0x7e/0x146
+[    1.829425] [<ffffffff8083b6f4>] driver_probe_device+0x38/0xd0
+[    1.829436] [<ffffffff8083b966>] __driver_attach+0xee/0x1e8
+[    1.829448] [<ffffffff80838e78>] bus_for_each_dev+0x6c/0xc4
+[    1.829460] [<ffffffff8083acbe>] driver_attach+0x26/0x34
+[    1.829471] [<ffffffff8083a1fe>] bus_add_driver+0x112/0x21e
+[    1.829483] [<ffffffff8083cb12>] driver_register+0x52/0x106
+[    1.829497] [<ffffffff8083e0b6>] __platform_driver_register+0x28/0x34
+[    1.829511] [<ffffffff80e3322e>] fu740_pcie_driver_init+0x22/0x2c
+[    1.829528] [<ffffffff80002962>] do_one_initcall+0x5c/0x1e2
+[    1.829542] [<ffffffff80e01836>] kernel_init_freeable+0x286/0x300
+[    1.829560] [<ffffffff80ce5b40>] kernel_init+0x2a/0x16e
+[    1.829584] [<ffffffff80003f82>] ret_from_fork+0xe/0x20
+[    1.829597] ---[ end trace 0000000000000000 ]---
+[    1.829635] fu740-pcie: probe of e00000000.pcie failed with error -110
diff --git a/src/soc/sifive/fu740/cbmem.c b/src/soc/sifive/fu740/cbmem.c
new file mode 100644
index 0000000..e3ccf3a
--- /dev/null
+++ b/src/soc/sifive/fu740/cbmem.c
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <cbmem.h>
+#include <commonlib/helpers.h>
+#include <soc/addressmap.h>
+#include <soc/sdram.h>
+#include <symbols.h>
+
+uintptr_t cbmem_top_chipset(void)
+{
+#define FU740_MAXDRAM 0x800000000ULL // 32 GiB
+	return MIN((uintptr_t)FU740_DRAM + sdram_size(), FU740_MAXDRAM);
+}
diff --git a/src/soc/sifive/fu740/chip.c b/src/soc/sifive/fu740/chip.c
new file mode 100644
index 0000000..cd5052b
--- /dev/null
+++ b/src/soc/sifive/fu740/chip.c
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <cbmem.h>
+#include <device/device.h>
+#include <soc/addressmap.h>
+#include <symbols.h>
+
+static void fu740_init(struct device *dev)
+{
+	int index = 0;
+	ram_from_to(dev, index++, FU740_DRAM, (uintptr_t)cbmem_top());
+}
+
+struct chip_operations soc_sifive_fu740_ops = {
+	.name = "SIFIVE FU740",
+	.enable_dev = fu740_init,
+};
diff --git a/src/soc/sifive/fu740/clint.c b/src/soc/sifive/fu740/clint.c
new file mode 100644
index 0000000..818b628
--- /dev/null
+++ b/src/soc/sifive/fu740/clint.c
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <mcall.h>
+#include <stdint.h>
+#include <device/mmio.h>
+#include <soc/addressmap.h>
+
+#define CLINT_MTIME 0xBFF8
+#define CLINT_MTIMECMP 0x4000
+
+void mtime_init(void)
+{
+	long hart_id = read_csr(mhartid);
+	HLS()->time = (uint64_t *)(FU740_CLINT + CLINT_MTIME);
+	HLS()->timecmp = (uint64_t *)(FU740_CLINT + CLINT_MTIMECMP + 8 * hart_id);
+}
+
+void set_msip(int hartid, int val)
+{
+	write32((void *)(FU740_CLINT + 4 * (uintptr_t)hartid), !!val);
+}
diff --git a/src/soc/sifive/fu740/clock.c b/src/soc/sifive/fu740/clock.c
new file mode 100644
index 0000000..419a0e2
--- /dev/null
+++ b/src/soc/sifive/fu740/clock.c
@@ -0,0 +1,448 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+// This file is used for setting up clocks and get devices out of reset
+// For more Information see FU740-C000 Manual Chapter 7 Clocking and Reset
+
+#include <console/console.h>
+#include <delay.h>
+#include <device/mmio.h>
+#include <soc/addressmap.h>
+#include <soc/clock.h>
+#include <soc/gpio.h>
+#include <gpio.h>
+#include <stdint.h>
+
+// Clock frequencies for the cores, ddr and the peripherals are all derived from the hfclk (high frequency clock) and it is always 26 MHz
+#define FU740_HFCLK_FREQ (26 * MHz)
+
+struct prci_ctlr {
+	u32 hfxosccfg;              // offset 0x00
+	u32 core_pllcfg;            // offset 0x04
+	u32 core_plloutdiv;         // offset 0x08
+	u32 ddr_pllcfg;             // offset 0x0c
+	u32 ddr_plloutdiv;          // offset 0x10
+	u32 pcieaux_plloutdiv;      // offset 0x14 (undocumented)
+	u32 reserved18;             // offset 0x18
+	u32 gemgxl_pllcfg;          // offset 0x1c
+	u32 gemgxl_plloutdiv;       // offset 0x20
+	u32 core_clk_sel_reg;       // offset 0x24
+	u32 devices_reset_n;        // offset 0x28
+	u32 clk_mux_status;         // offset 0x2C
+	u32 cltx_pllcfg;            // offset 0x30 chiplink (undocumented)
+	u32 cltx_plloutdiv;         // offset 0x34 chiplink (undocumented)
+	u32 dvfs_core_pllcfg;       // offset 0x38
+	u32 dvfs_core_plloutdiv;    // offset 0x3C
+	u32 corepllsel;             // offset 0x40 (undocumented, but probably same as last gen)
+	u8 reserved44[12];          // offset 0x44
+	u32 hfpclk_pllcfg;          // offset 0x50
+	u32 hfpclk_plloutdiv;       // offset 0x54
+	u32 hfpclkpllsel;           // offset 0x58 (undocumented, but probably same as last gen)
+	u32 hfpclk_div_reg;         // offset 0x5C
+	u8 reserved60[128];         // offset 0x60
+	u32 prci_plls;              // offset 0xE0
+	u8 reservedE4[12];          // offset 0xE4
+	u32 procmoncfg_core_clock;  // offset 0xF0 (undocumented)
+} __packed;
+
+static struct prci_ctlr *prci = (void *)FU740_PRCI;
+
+// =================================
+// clock selections
+// =================================
+
+#define PRCI_COREPLLSEL_MASK 1
+#define PRCI_COREPLLSEL_COREPLL 0
+#define PRCI_COREPLLSEL_DVFSCOREPLL 1
+
+#define PRCI_CORECLKSEL_MASK 1
+#define PRCI_CORECLKSEL_CORECLKPLL 0
+#define PRCI_CORECLKSEL_HFCLK 1
+
+#define PRCI_HFPCLKSEL_MASK 1
+#define PRCI_HFPCLKSEL_PLL 0
+#define PRCI_HFPCLKSEL_HFCLK 1
+
+// ===================================
+// pllcfg register format is used by all PLLs
+// ===================================
+
+#define PRCI_PLLCFG_DIVR_SHIFT       0
+#define PRCI_PLLCFG_DIVF_SHIFT       6
+#define PRCI_PLLCFG_DIVQ_SHIFT      15
+#define PRCI_PLLCFG_RANGE_SHIFT     18
+#define PRCI_PLLCFG_BYPASS_SHIFT    24
+#define PRCI_PLLCFG_FSEBYPASS_SHIFT 25
+#define PRCI_PLLCFG_LOCK_SHIFT      31
+
+#define PRCI_PLLCFG_DIVR_MASK      (0x03f << PRCI_PLLCFG_DIVR_SHIFT)
+#define PRCI_PLLCFG_DIVF_MASK      (0x1ff << PRCI_PLLCFG_DIVF_SHIFT)
+#define PRCI_PLLCFG_DIVQ_MASK      (0x007 << PRCI_PLLCFG_DIVQ_SHIFT)
+#define PRCI_PLLCFG_RANGE_MASK     (0x007 << PRCI_PLLCFG_RANGE_SHIFT)
+#define PRCI_PLLCFG_BYPASS_MASK    (0x001 << PRCI_PLLCFG_BYPASS_SHIFT)
+#define PRCI_PLLCFG_FSEBYPASS_MASK (0x001 << PRCI_PLLCFG_FSEBYPASS_SHIFT)
+#define PRCI_PLLCFG_LOCK_MASK      (0x001 << PRCI_PLLCFG_LOCK_SHIFT)
+
+// ===================================
+// plloutdiv register formats
+// ===================================
+
+// registered are used to enable/disable PLLs
+#define PRCI_DVFSCORE_PLLOUTDIV_MASK (1 << 24) // Note: u-boot and fu740 manual differ here ...
+#define PRCI_HFPCLK_PLLOUTDIV_MASK   (1 << 31) // Note: according to u-boot it is (1 << 24) but if I use that it gets stuck
+#define PRCI_DDR_PLLOUTDIV_MASK      (1 << 31)
+#define PRCI_GEMGXL_PLLOUTDIV_MASK   (1 << 31)
+#define PRCI_CLTX_PLLOUTDIV_MASK     (1 << 24) // undocumented (chiplink tx)
+#define PRCI_PCIEAUX_PLLOUTDIV_MASK  (1 <<  0) // undocumented
+#define PRCI_CORE_PLLOUTDIV_MASK     (1 << 31) // undocumented
+
+// ===================================
+// devicereset register formats
+// ===================================
+
+// used to get devices in or out of reset
+#define PRCI_DEVICES_RESET_DDR_CTRL_RST (1 << 0) // DDR Controller
+#define PRCI_DEVICES_RESET_DDR_AXI_RST  (1 << 1) // DDR Controller AXI Interface
+#define PRCI_DEVICES_RESET_DDR_AHB_RST  (1 << 2) // DDR Controller AHB Interface
+#define PRCI_DEVICES_RESET_DDR_PHY_RST  (1 << 3) // DDR PHY
+#define PRCI_DEVICES_RESET_PCIEAUX_RST  (1 << 4)
+#define PRCI_DEVICES_RESET_GEMGXL_RST   (1 << 5) // Gigabit Ethernet Subsystem
+#define PRCI_DEVICES_RESET_CLTX_RST     (1 << 6) // chiplink reset (undocumented)
+
+// ===================================
+// prci_plls register format
+// ===================================
+
+// used to check if certain PLLs are present in the SOC
+#define PRCI_PLLS_CLTXPLL     (1 << 0)
+#define PRCI_PLLS_GEMGXLPLL   (1 << 1)
+#define PRCI_PLLS_DDRPLL      (1 << 2)
+#define PRCI_PLLS_HFPCLKPLL   (1 << 3)
+#define PRCI_PLLS_DVFSCOREPLL (1 << 4)
+#define PRCI_PLLS_COREPLL     (1 << 5)
+
+// ===================================
+// clk_mux_status register format
+// ===================================
+
+// read only register which is used to set some clock multiplex settings
+// the value of this register depends on the state of pins connected to the FU740 SOC
+// on the hifive-unmatched board the state of the pins is set by a hardware switch
+#define PRCI_CLK_MUX_STATUS_CORECLKPLLSEL (1 << 0)
+        // 0 - HFCLK or CORECLK
+        // 1 - only HFCLK
+#define PRCI_CLK_MUX_STATUS_TLCLKSEL      (1 << 1)
+        // 0 - CORECLK/2
+        // 1 - CORECLK
+#define PRCI_CLK_MUX_STATUS_RTCXSEL       (1 << 2)
+        // 0 - use HFXCLK for RTC
+        // 1 - use RTCXALTCLKIN for RTC
+#define PRCI_CLK_MUX_STATUS_DDRCTRLCLKSEL (1 << 3)
+#define PRCI_CLK_MUX_STATUS_DDRPHYCLKSEL  (1 << 4)
+#define PRCI_CLK_MUX_STATUS_RESERVED      (1 << 5)
+#define PRCI_CLK_MUX_STATUS_GEMGXLCLKSEL  (1 << 6)
+#define PRCI_CLK_MUX_STATUS_MAINMEMCLKSEL (1 << 7)
+
+// ===================================
+// hfxosccfg register format
+// ===================================
+
+#define PRCI_HFXOSCCFG_HFXOSEN   (1 << 30) // Crystal oscillator enable
+        // Note: I guess (it is not documented)
+        // 0 - XTAL PADS
+        // 1 - OSC PADS
+#define PRCI_HFXOSCCFG_HFXOSCRDY (1 << 31) // Crystal oscillator ready
+
+struct pll_settings {
+	unsigned int divr:6; // divider before PLL loop (reference), equal to divr + 1
+	unsigned int divf:9; // VCO feedback divider value, equal to 2 * (divf + 1)
+	unsigned int divq:3; // divider after PLL loop, equal to 2^divq
+	// PLL filter range (TODO documentation is not really clear on how to set it)
+	unsigned int range:3;
+	unsigned int bypass:1; // probably used to bypass the PLL
+	// internal or external input path (internal = 1, external = 0)
+	//WARN this is only a guess since it is undocumented
+	unsigned int fsebypass:1;
+};
+
+static void configure_pll(u32 *reg, const struct pll_settings *s)
+{
+	// Write the settings to the register
+	u32 c = read32(reg);
+	clrsetbits32(&c, PRCI_PLLCFG_DIVR_MASK
+		       | PRCI_PLLCFG_DIVF_MASK
+		       | PRCI_PLLCFG_DIVQ_MASK
+		       | PRCI_PLLCFG_RANGE_MASK
+		       | PRCI_PLLCFG_BYPASS_MASK
+		       | PRCI_PLLCFG_FSEBYPASS_MASK,
+		         (s->divr << PRCI_PLLCFG_DIVR_SHIFT)
+		       | (s->divf << PRCI_PLLCFG_DIVF_SHIFT)
+		       | (s->divq << PRCI_PLLCFG_DIVQ_SHIFT)
+		       | (s->range << PRCI_PLLCFG_RANGE_SHIFT)
+		       | (s->bypass << PRCI_PLLCFG_BYPASS_SHIFT)
+		       | (s->fsebypass << PRCI_PLLCFG_FSEBYPASS_SHIFT));
+	write32(reg, c);
+
+	// Wait for PLL lock
+	while (!(read32(reg) & PRCI_PLLCFG_LOCK_MASK))
+		;
+}
+
+/*
+ * Section 7.1 recommends a frequency of 1.0 GHz (up to 1.5 GHz is possible)
+ * Section 7.4.2 provides the necessary values
+ *
+ * COREPLL is set up for ~1 GHz output frequency.
+ * divr = 0 (x1), divf = 76 (x154) => (4004 MHz VCO), divq = 2 (/4 Output divider)
+ */
+static const struct pll_settings corepll_settings = {
+	.divr = 0,
+	.divf = 76,
+	.divq = 2,
+	.range = 4,
+	.bypass = 0,
+	.fsebypass = 1, // external feedback mode is not supported
+};
+
+/*
+ * Section 7.4.3: DDR and Ethernet Subsystem Clocking and Reset
+ *
+ * DDRPLL is set up for 933 MHz output frequency.
+ * divr = 0 (x1), divf = 71 (x144) => (3744 MHz VCO), divq = 2 (/4 output divider)
+ */
+static const struct pll_settings ddrpll_settings = {
+	.divr = 0,
+	.divf = 71,
+	.divq = 2,
+	.range = 4,
+	.bypass = 0,
+	.fsebypass = 1, // external feedback mode is not supported
+};
+
+/*
+ * GEMGXLPLL is set up for 125 MHz output frequency.
+ * divr = 0 (x1), divf = 76 (x154) => (4004 MHz VCO), divq = 5 (/32 output divider)
+ */
+static const struct pll_settings gemgxlpll_settings = {
+	.divr = 0,
+	.divf = 76,
+	.divq = 5,
+	.range = 4,
+	.bypass = 0,
+	.fsebypass = 1, // external feedback mode is not supported
+};
+
+/*
+ * HFPCLKPLL is set up for 520 MHz output frequency.
+ * TODO a lower value should also suffice as well as safe some power
+ * divr = 1 (/2), divf = 39 (x80) => (2080 MHz VCO), divq = 2 (/4 output divider)
+ */
+static const struct pll_settings hfpclkpll_settings = {
+	.divr = 1,
+	//.divf = 122,
+	.divf = 39,
+	.divq = 2,
+	.range = 4,
+	.bypass = 0,
+	.fsebypass = 1, // external feedback mode is not supported
+};
+
+/*
+ * CLTXCLKPLL is set up for 520 MHz output frequency.
+ * divr = 1 (/2), divf = 122 (x154) => (4004 MHz VCO), divq = 2 (/4 output divider)
+ */
+static const struct pll_settings cltxpll_settings = {
+	.divr = 1,
+	.divf = 39,
+	.divq = 2,
+	.range = 4,
+	.bypass = 0,
+	.fsebypass = 1, // external feedback mode is not supported
+};
+
+static void init_coreclk(void)
+{
+	// we can't modify the coreclk PLL while we are running on it, so let coreclk devise
+	// its clock from hfclk before modifying PLL
+	clrsetbits32(&prci->core_clk_sel_reg, PRCI_CORECLKSEL_MASK, PRCI_CORECLKSEL_HFCLK);
+
+	// only configure pll if it is present
+	if (!(read32(&prci->prci_plls) & PRCI_PLLS_COREPLL)) {
+		return;
+	}
+
+	configure_pll(&prci->core_pllcfg, &corepll_settings);
+
+	// switch coreclk multiplexer to use corepll as clock source again
+	clrsetbits32(&prci->core_clk_sel_reg, PRCI_CORECLKSEL_MASK, PRCI_CORECLKSEL_CORECLKPLL);
+}
+
+static void init_ddrclk(void)
+{
+	// only configure pll if it is present
+	if (!(read32(&prci->prci_plls) & PRCI_PLLS_DDRPLL)) {
+		return;
+	}
+
+	// disable ddr clock output before reconfiguring the PLL
+	u32 cfg1 = read32(&prci->ddr_plloutdiv);
+	clrbits32(&cfg1, PRCI_DDR_PLLOUTDIV_MASK);
+	write32(&prci->ddr_plloutdiv, cfg1);
+
+	configure_pll(&prci->ddr_pllcfg, &ddrpll_settings);
+
+	// PLL is ready/locked so enable it (its gated)
+	setbits32(&cfg1, PRCI_DDR_PLLOUTDIV_MASK);
+	write32(&prci->ddr_plloutdiv, cfg1);
+}
+
+static void init_gemgxlclk(void)
+{
+	// only configure pll if it is present
+	if (!(read32(&prci->prci_plls) & PRCI_PLLS_GEMGXLPLL)) {
+		return;
+	}
+
+	// disable gemgxl clock output before reconfiguring the PLL
+	u32 cfg1 = read32(&prci->gemgxl_plloutdiv);
+	clrbits32(&cfg1, PRCI_GEMGXL_PLLOUTDIV_MASK);
+	write32(&prci->gemgxl_plloutdiv, cfg1);
+
+	configure_pll(&prci->gemgxl_pllcfg, &gemgxlpll_settings);
+
+	// PLL is ready/locked so enable it (its gated)
+	setbits32(&cfg1, PRCI_GEMGXL_PLLOUTDIV_MASK);
+	write32(&prci->gemgxl_plloutdiv, cfg1);
+}
+
+/*
+ * Configure High Frequency peripheral clock which is used by
+ * UART, SPI, GPIO, I2C and PWM subsystem
+ */
+static void init_hfpclk(void)
+{
+	// we can't modify the hfpclk PLL while we are running on it, so let pclk devise
+	// its clock from hfclk before modifying PLL
+	u32 hfpclksel = read32(&prci->hfpclkpllsel);
+	hfpclksel |= PRCI_HFPCLKSEL_HFCLK;
+	write32(&prci->hfpclkpllsel, hfpclksel);
+
+	configure_pll(&prci->hfpclk_pllcfg, &hfpclkpll_settings);
+
+	// PLL is ready/locked so enable it (its gated)
+	u32 hfpclk_plloutdiv = read32(&prci->hfpclk_plloutdiv);
+	hfpclk_plloutdiv |=  PRCI_HFPCLK_PLLOUTDIV_MASK;
+	write32(&prci->hfpclk_plloutdiv, hfpclk_plloutdiv);
+
+	mdelay(1);
+
+	// switch to using PLL for hfpclk
+	clrbits32(&prci->hfpclkpllsel, PRCI_HFPCLKSEL_MASK);
+
+	udelay(70);
+}
+
+static void reset_deassert(u8 reset_index)
+{
+	u32 device_reset = read32(&prci->devices_reset_n);
+	device_reset |= reset_index;
+	write32(&prci->devices_reset_n, device_reset);
+}
+
+static void init_cltx(void)
+{
+	// disable hfpclkpll before configuring it
+	u32 cfg1 = read32(&prci->cltx_plloutdiv);
+	clrbits32(&cfg1, PRCI_CLTX_PLLOUTDIV_MASK);
+	write32(&prci->cltx_plloutdiv, cfg1);
+
+	configure_pll(&prci->cltx_pllcfg, &cltxpll_settings);
+
+	// PLL is ready/locked so enable it (its gated)
+	setbits32(&cfg1, PRCI_CLTX_PLLOUTDIV_MASK);
+	write32(&prci->cltx_plloutdiv, cfg1);
+
+	// get chiplink out of reset
+	reset_deassert(PRCI_DEVICES_RESET_CLTX_RST);
+
+	udelay(70);
+}
+
+void clock_init(void)
+{
+	// first configure the coreclk (used by HARTs) to get maximum speed early on
+	init_coreclk();
+
+	// put all devices in reset (e.g. DDR, ethernet, pcie) before configuring their clocks
+	write32(&prci->devices_reset_n, 0);
+
+	// initialize clock used by DDR subsystem
+	init_ddrclk();
+
+	// get DDR controller out of reset
+	reset_deassert(PRCI_DEVICES_RESET_DDR_CTRL_RST);
+
+	// wait at least one full DDR controller clock cycle
+	asm volatile ("fence");
+
+	// get DDR controller (register interface) out of reset
+	// get DDR subsystem PHY out of reset
+	reset_deassert(PRCI_DEVICES_RESET_DDR_AXI_RST |
+	               PRCI_DEVICES_RESET_DDR_AHB_RST |
+	               PRCI_DEVICES_RESET_DDR_PHY_RST);
+
+	// we need to wait 256 full ddrctrl clock cycles until we can interact with the DDR subsystem
+	for (int i = 0; i < 256; i++)
+		asm volatile ("nop");
+
+	if (read32(&prci->prci_plls) & PRCI_PLLS_HFPCLKPLL) {
+		// set hfclk as reference for peripheral clock since we don't have the PLL
+		//clrsetbits32(&prci->hfpclkpllsel, PRCI_HFPCLKSEL_MASK, PRCI_HFPCLKSEL_HFCLK);
+		init_hfpclk();
+	} else if (read32(&prci->prci_plls) & PRCI_PLLS_CLTXPLL) {
+		// Note: this path has never been tested since the platforms tested with
+		// always have HFPCLKPLL
+		init_cltx();
+		// get chiplink out of reset
+		reset_deassert(PRCI_DEVICES_RESET_CLTX_RST);
+	}
+
+	// GEMGXL init VSC8541 PHY reset sequence;
+	gpio_set_direction(GEMGXL_RST, GPIO_OUTPUT);
+	gpio_set(GEMGXL_RST, 1);
+
+	udelay(1);
+
+	/* Reset PHY again to enter unmanaged mode */
+	gpio_set(GEMGXL_RST, 0);
+	udelay(1);
+	gpio_set(GEMGXL_RST, 1);
+	mdelay(15);
+
+	init_gemgxlclk();
+
+	// get ethernet out of reset
+	reset_deassert(PRCI_DEVICES_RESET_GEMGXL_RST);
+}
+
+// get the peripheral clock frequency used by UART (probably also SPI, GPIO, I2C and PWM)
+int clock_get_pclk(void)
+{
+	u64 pclk = FU740_HFCLK_FREQ;
+
+	// check if hfpclkpll is present and
+	// check if hfpclkpll is selected in the multiplexer TODO
+	// check if hpfclkpll is enabled
+	if ((read32(&prci->prci_plls) & PRCI_PLLS_HFPCLKPLL) &&
+	    (read32(&prci->hfpclk_plloutdiv) & PRCI_HFPCLK_PLLOUTDIV_MASK)) {
+		int hfpclk_pllcfg = read32(&prci->hfpclk_pllcfg);
+		int divr = (hfpclk_pllcfg & PRCI_PLLCFG_DIVR_MASK) >> PRCI_PLLCFG_DIVR_SHIFT;
+		int divf = (hfpclk_pllcfg & PRCI_PLLCFG_DIVF_MASK) >> PRCI_PLLCFG_DIVF_SHIFT;
+		int divq = (hfpclk_pllcfg & PRCI_PLLCFG_DIVQ_MASK) >> PRCI_PLLCFG_DIVQ_SHIFT;
+		pclk /= (divr + 1); // reference divider
+		pclk *= (2 * (divf + 1)); // feedback divider
+		pclk /= (1 << divq); // output divider
+	}
+
+	// divider value before pclk seems to be (hfpclkdiv + 2). Not mentioned in fu740 manual though.
+	return pclk / (read32(&prci->hfpclk_div_reg) + 2);
+}
diff --git a/src/soc/sifive/fu740/ddrregs.c b/src/soc/sifive/fu740/ddrregs.c
new file mode 100644
index 0000000..f6d5ea7
--- /dev/null
+++ b/src/soc/sifive/fu740/ddrregs.c
@@ -0,0 +1,1496 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <stdint.h>
+
+/*
+ * Only a very small amount of registers is documented inside the FU740-C000 Manual and the
+ * rest are basically magic values
+ * source: u-boot
+ * (C) Copyright 2020 SiFive, Inc
+ */
+
+const uint32_t denali_ddr_phy_data[1215] = {
+	0x01375642, // DENALI_PHY_00_DATA
+	0x0004c008, // DENALI_PHY_01_DATA
+	0x000000da, // DENALI_PHY_02_DATA
+	0x00000000, // DENALI_PHY_03_DATA
+	0x00000000, // DENALI_PHY_04_DATA
+	0x00010000, // DENALI_PHY_05_DATA
+	0x01DDDD90, // DENALI_PHY_06_DATA
+	0x01DDDD90, // DENALI_PHY_07_DATA
+	0x01030001, // DENALI_PHY_08_DATA
+	0x01000000, // DENALI_PHY_09_DATA
+	0x00c00000, // DENALI_PHY_10_DATA
+	0x00000007, // DENALI_PHY_11_DATA
+	0x00000000, // DENALI_PHY_12_DATA
+	0x00000000, // DENALI_PHY_13_DATA
+	0x04000408, // DENALI_PHY_14_DATA
+	0x00000408, // DENALI_PHY_15_DATA
+	0x00e4e400, // DENALI_PHY_16_DATA
+	0x00000000, // DENALI_PHY_17_DATA
+	0x00000000, // DENALI_PHY_18_DATA
+	0x00000000, // DENALI_PHY_19_DATA
+	0x00000000, // DENALI_PHY_20_DATA
+	0x00000000, // DENALI_PHY_21_DATA
+	0x00000000, // DENALI_PHY_22_DATA
+	0x00000000, // DENALI_PHY_23_DATA
+	0x00000000, // DENALI_PHY_24_DATA
+	0x00000000, // DENALI_PHY_25_DATA
+	0x00000000, // DENALI_PHY_26_DATA
+	0x00000000, // DENALI_PHY_27_DATA
+	0x00000000, // DENALI_PHY_28_DATA
+	0x00000000, // DENALI_PHY_29_DATA
+	0x00000000, // DENALI_PHY_30_DATA
+	0x00000000, // DENALI_PHY_31_DATA
+	0x00000000, // DENALI_PHY_32_DATA
+	0x00200000, // DENALI_PHY_33_DATA
+	0x00000000, // DENALI_PHY_34_DATA
+	0x00000000, // DENALI_PHY_35_DATA
+	0x00000000, // DENALI_PHY_36_DATA
+	0x00000000, // DENALI_PHY_37_DATA
+	0x00000000, // DENALI_PHY_38_DATA
+	0x00000000, // DENALI_PHY_39_DATA
+	0x02800280, // DENALI_PHY_40_DATA
+	0x02800280, // DENALI_PHY_41_DATA
+	0x02800280, // DENALI_PHY_42_DATA
+	0x02800280, // DENALI_PHY_43_DATA
+	0x00000280, // DENALI_PHY_44_DATA
+	0x00000000, // DENALI_PHY_45_DATA
+	0x00000000, // DENALI_PHY_46_DATA
+	0x00000000, // DENALI_PHY_47_DATA
+	0x00000000, // DENALI_PHY_48_DATA
+	0x00000000, // DENALI_PHY_49_DATA
+	0x00800080, // DENALI_PHY_50_DATA
+	0x00800080, // DENALI_PHY_51_DATA
+	0x00800080, // DENALI_PHY_52_DATA
+	0x00800080, // DENALI_PHY_53_DATA
+	0x00800080, // DENALI_PHY_54_DATA
+	0x00800080, // DENALI_PHY_55_DATA
+	0x00800080, // DENALI_PHY_56_DATA
+	0x00800080, // DENALI_PHY_57_DATA
+	0x00800080, // DENALI_PHY_58_DATA
+	0x000100da, // DENALI_PHY_59_DATA
+	0x01ff0010, // DENALI_PHY_60_DATA
+	0x00000000, // DENALI_PHY_61_DATA
+	0x00000000, // DENALI_PHY_62_DATA
+	0x00000002, // DENALI_PHY_63_DATA
+	0x51313152, // DENALI_PHY_64_DATA
+	0x80013130, // DENALI_PHY_65_DATA
+	0x02000080, // DENALI_PHY_66_DATA
+	0x00100001, // DENALI_PHY_67_DATA
+	0x0c064208, // DENALI_PHY_68_DATA
+	0x000f0c0f, // DENALI_PHY_69_DATA
+	0x01000140, // DENALI_PHY_70_DATA
+	0x0000000c, // DENALI_PHY_71_DATA
+	0x00000000, // DENALI_PHY_72_DATA
+	0x00000000, // DENALI_PHY_73_DATA
+	0x00000000, // DENALI_PHY_74_DATA
+	0x00000000, // DENALI_PHY_75_DATA
+	0x00000000, // DENALI_PHY_76_DATA
+	0x00000000, // DENALI_PHY_77_DATA
+	0x00000000, // DENALI_PHY_78_DATA
+	0x00000000, // DENALI_PHY_79_DATA
+	0x00000000, // DENALI_PHY_80_DATA
+	0x00000000, // DENALI_PHY_81_DATA
+	0x00000000, // DENALI_PHY_82_DATA
+	0x00000000, // DENALI_PHY_83_DATA
+	0x00000000, // DENALI_PHY_84_DATA
+	0x00000000, // DENALI_PHY_85_DATA
+	0x00000000, // DENALI_PHY_86_DATA
+	0x00000000, // DENALI_PHY_87_DATA
+	0x00000000, // DENALI_PHY_88_DATA
+	0x00000000, // DENALI_PHY_89_DATA
+	0x00000000, // DENALI_PHY_90_DATA
+	0x00000000, // DENALI_PHY_91_DATA
+	0x00000000, // DENALI_PHY_92_DATA
+	0x00000000, // DENALI_PHY_93_DATA
+	0x00000000, // DENALI_PHY_94_DATA
+	0x00000000, // DENALI_PHY_95_DATA
+	0x00000000, // DENALI_PHY_96_DATA
+	0x00000000, // DENALI_PHY_97_DATA
+	0x00000000, // DENALI_PHY_98_DATA
+	0x00000000, // DENALI_PHY_99_DATA
+	0x00000000, // DENALI_PHY_100_DATA
+	0x00000000, // DENALI_PHY_101_DATA
+	0x00000000, // DENALI_PHY_102_DATA
+	0x00000000, // DENALI_PHY_103_DATA
+	0x00000000, // DENALI_PHY_104_DATA
+	0x00000000, // DENALI_PHY_105_DATA
+	0x00000000, // DENALI_PHY_106_DATA
+	0x00000000, // DENALI_PHY_107_DATA
+	0x00000000, // DENALI_PHY_108_DATA
+	0x00000000, // DENALI_PHY_109_DATA
+	0x00000000, // DENALI_PHY_110_DATA
+	0x00000000, // DENALI_PHY_111_DATA
+	0x00000000, // DENALI_PHY_112_DATA
+	0x00000000, // DENALI_PHY_113_DATA
+	0x00000000, // DENALI_PHY_114_DATA
+	0x00000000, // DENALI_PHY_115_DATA
+	0x00000000, // DENALI_PHY_116_DATA
+	0x00000000, // DENALI_PHY_117_DATA
+	0x00000000, // DENALI_PHY_118_DATA
+	0x00000000, // DENALI_PHY_119_DATA
+	0x00000000, // DENALI_PHY_120_DATA
+	0x00000000, // DENALI_PHY_121_DATA
+	0x00000000, // DENALI_PHY_122_DATA
+	0x00000000, // DENALI_PHY_123_DATA
+	0x00000000, // DENALI_PHY_124_DATA
+	0x00000000, // DENALI_PHY_125_DATA
+	0x00000000, // DENALI_PHY_126_DATA
+	0x00000000, // DENALI_PHY_127_DATA
+	0x40263571, // DENALI_PHY_128_DATA
+	0x0004c008, // DENALI_PHY_129_DATA
+	0x000000da, // DENALI_PHY_130_DATA
+	0x00000000, // DENALI_PHY_131_DATA
+	0x00000000, // DENALI_PHY_132_DATA
+	0x00010000, // DENALI_PHY_133_DATA
+	0x01DDDD90, // DENALI_PHY_134_DATA
+	0x01DDDD90, // DENALI_PHY_135_DATA
+	0x01030001, // DENALI_PHY_136_DATA
+	0x01000000, // DENALI_PHY_137_DATA
+	0x00c00000, // DENALI_PHY_138_DATA
+	0x00000007, // DENALI_PHY_139_DATA
+	0x00000000, // DENALI_PHY_140_DATA
+	0x00000000, // DENALI_PHY_141_DATA
+	0x04000408, // DENALI_PHY_142_DATA
+	0x00000408, // DENALI_PHY_143_DATA
+	0x00e4e400, // DENALI_PHY_144_DATA
+	0x00000000, // DENALI_PHY_145_DATA
+	0x00000000, // DENALI_PHY_146_DATA
+	0x00000000, // DENALI_PHY_147_DATA
+	0x00000000, // DENALI_PHY_148_DATA
+	0x00000000, // DENALI_PHY_149_DATA
+	0x00000000, // DENALI_PHY_150_DATA
+	0x00000000, // DENALI_PHY_151_DATA
+	0x00000000, // DENALI_PHY_152_DATA
+	0x00000000, // DENALI_PHY_153_DATA
+	0x00000000, // DENALI_PHY_154_DATA
+	0x00000000, // DENALI_PHY_155_DATA
+	0x00000000, // DENALI_PHY_156_DATA
+	0x00000000, // DENALI_PHY_157_DATA
+	0x00000000, // DENALI_PHY_158_DATA
+	0x00000000, // DENALI_PHY_159_DATA
+	0x00000000, // DENALI_PHY_160_DATA
+	0x00200000, // DENALI_PHY_161_DATA
+	0x00000000, // DENALI_PHY_162_DATA
+	0x00000000, // DENALI_PHY_163_DATA
+	0x00000000, // DENALI_PHY_164_DATA
+	0x00000000, // DENALI_PHY_165_DATA
+	0x00000000, // DENALI_PHY_166_DATA
+	0x00000000, // DENALI_PHY_167_DATA
+	0x02800280, // DENALI_PHY_168_DATA
+	0x02800280, // DENALI_PHY_169_DATA
+	0x02800280, // DENALI_PHY_170_DATA
+	0x02800280, // DENALI_PHY_171_DATA
+	0x00000280, // DENALI_PHY_172_DATA
+	0x00000000, // DENALI_PHY_173_DATA
+	0x00000000, // DENALI_PHY_174_DATA
+	0x00000000, // DENALI_PHY_175_DATA
+	0x00000000, // DENALI_PHY_176_DATA
+	0x00000000, // DENALI_PHY_177_DATA
+	0x00800080, // DENALI_PHY_178_DATA
+	0x00800080, // DENALI_PHY_179_DATA
+	0x00800080, // DENALI_PHY_180_DATA
+	0x00800080, // DENALI_PHY_181_DATA
+	0x00800080, // DENALI_PHY_182_DATA
+	0x00800080, // DENALI_PHY_183_DATA
+	0x00800080, // DENALI_PHY_184_DATA
+	0x00800080, // DENALI_PHY_185_DATA
+	0x00800080, // DENALI_PHY_186_DATA
+	0x000100da, // DENALI_PHY_187_DATA
+	0x01ff0010, // DENALI_PHY_188_DATA
+	0x00000000, // DENALI_PHY_189_DATA
+	0x00000000, // DENALI_PHY_190_DATA
+	0x00000002, // DENALI_PHY_191_DATA
+	0x51313152, // DENALI_PHY_192_DATA
+	0x80013130, // DENALI_PHY_193_DATA
+	0x02000080, // DENALI_PHY_194_DATA
+	0x00100001, // DENALI_PHY_195_DATA
+	0x0c064208, // DENALI_PHY_196_DATA
+	0x000f0c0f, // DENALI_PHY_197_DATA
+	0x01000140, // DENALI_PHY_198_DATA
+	0x0000000c, // DENALI_PHY_199_DATA
+	0x00000000, // DENALI_PHY_200_DATA
+	0x00000000, // DENALI_PHY_201_DATA
+	0x00000000, // DENALI_PHY_202_DATA
+	0x00000000, // DENALI_PHY_203_DATA
+	0x00000000, // DENALI_PHY_204_DATA
+	0x00000000, // DENALI_PHY_205_DATA
+	0x00000000, // DENALI_PHY_206_DATA
+	0x00000000, // DENALI_PHY_207_DATA
+	0x00000000, // DENALI_PHY_208_DATA
+	0x00000000, // DENALI_PHY_209_DATA
+	0x00000000, // DENALI_PHY_210_DATA
+	0x00000000, // DENALI_PHY_211_DATA
+	0x00000000, // DENALI_PHY_212_DATA
+	0x00000000, // DENALI_PHY_213_DATA
+	0x00000000, // DENALI_PHY_214_DATA
+	0x00000000, // DENALI_PHY_215_DATA
+	0x00000000, // DENALI_PHY_216_DATA
+	0x00000000, // DENALI_PHY_217_DATA
+	0x00000000, // DENALI_PHY_218_DATA
+	0x00000000, // DENALI_PHY_219_DATA
+	0x00000000, // DENALI_PHY_220_DATA
+	0x00000000, // DENALI_PHY_221_DATA
+	0x00000000, // DENALI_PHY_222_DATA
+	0x00000000, // DENALI_PHY_223_DATA
+	0x00000000, // DENALI_PHY_224_DATA
+	0x00000000, // DENALI_PHY_225_DATA
+	0x00000000, // DENALI_PHY_226_DATA
+	0x00000000, // DENALI_PHY_227_DATA
+	0x00000000, // DENALI_PHY_228_DATA
+	0x00000000, // DENALI_PHY_229_DATA
+	0x00000000, // DENALI_PHY_230_DATA
+	0x00000000, // DENALI_PHY_231_DATA
+	0x00000000, // DENALI_PHY_232_DATA
+	0x00000000, // DENALI_PHY_233_DATA
+	0x00000000, // DENALI_PHY_234_DATA
+	0x00000000, // DENALI_PHY_235_DATA
+	0x00000000, // DENALI_PHY_236_DATA
+	0x00000000, // DENALI_PHY_237_DATA
+	0x00000000, // DENALI_PHY_238_DATA
+	0x00000000, // DENALI_PHY_239_DATA
+	0x00000000, // DENALI_PHY_240_DATA
+	0x00000000, // DENALI_PHY_241_DATA
+	0x00000000, // DENALI_PHY_242_DATA
+	0x00000000, // DENALI_PHY_243_DATA
+	0x00000000, // DENALI_PHY_244_DATA
+	0x00000000, // DENALI_PHY_245_DATA
+	0x00000000, // DENALI_PHY_246_DATA
+	0x00000000, // DENALI_PHY_247_DATA
+	0x00000000, // DENALI_PHY_248_DATA
+	0x00000000, // DENALI_PHY_249_DATA
+	0x00000000, // DENALI_PHY_250_DATA
+	0x00000000, // DENALI_PHY_251_DATA
+	0x00000000, // DENALI_PHY_252_DATA
+	0x00000000, // DENALI_PHY_253_DATA
+	0x00000000, // DENALI_PHY_254_DATA
+	0x00000000, // DENALI_PHY_255_DATA
+	0x46052371, // DENALI_PHY_256_DATA
+	0x0004c008, // DENALI_PHY_257_DATA
+	0x000000da, // DENALI_PHY_258_DATA
+	0x00000000, // DENALI_PHY_259_DATA
+	0x00000000, // DENALI_PHY_260_DATA
+	0x00010000, // DENALI_PHY_261_DATA
+	0x01DDDD90, // DENALI_PHY_262_DATA
+	0x01DDDD90, // DENALI_PHY_263_DATA
+	0x01030001, // DENALI_PHY_264_DATA
+	0x01000000, // DENALI_PHY_265_DATA
+	0x00c00000, // DENALI_PHY_266_DATA
+	0x00000007, // DENALI_PHY_267_DATA
+	0x00000000, // DENALI_PHY_268_DATA
+	0x00000000, // DENALI_PHY_269_DATA
+	0x04000408, // DENALI_PHY_270_DATA
+	0x00000408, // DENALI_PHY_271_DATA
+	0x00e4e400, // DENALI_PHY_272_DATA
+	0x00000000, // DENALI_PHY_273_DATA
+	0x00000000, // DENALI_PHY_274_DATA
+	0x00000000, // DENALI_PHY_275_DATA
+	0x00000000, // DENALI_PHY_276_DATA
+	0x00000000, // DENALI_PHY_277_DATA
+	0x00000000, // DENALI_PHY_278_DATA
+	0x00000000, // DENALI_PHY_279_DATA
+	0x00000000, // DENALI_PHY_280_DATA
+	0x00000000, // DENALI_PHY_281_DATA
+	0x00000000, // DENALI_PHY_282_DATA
+	0x00000000, // DENALI_PHY_283_DATA
+	0x00000000, // DENALI_PHY_284_DATA
+	0x00000000, // DENALI_PHY_285_DATA
+	0x00000000, // DENALI_PHY_286_DATA
+	0x00000000, // DENALI_PHY_287_DATA
+	0x00000000, // DENALI_PHY_288_DATA
+	0x00200000, // DENALI_PHY_289_DATA
+	0x00000000, // DENALI_PHY_290_DATA
+	0x00000000, // DENALI_PHY_291_DATA
+	0x00000000, // DENALI_PHY_292_DATA
+	0x00000000, // DENALI_PHY_293_DATA
+	0x00000000, // DENALI_PHY_294_DATA
+	0x00000000, // DENALI_PHY_295_DATA
+	0x02800280, // DENALI_PHY_296_DATA
+	0x02800280, // DENALI_PHY_297_DATA
+	0x02800280, // DENALI_PHY_298_DATA
+	0x02800280, // DENALI_PHY_299_DATA
+	0x00000280, // DENALI_PHY_300_DATA
+	0x00000000, // DENALI_PHY_301_DATA
+	0x00000000, // DENALI_PHY_302_DATA
+	0x00000000, // DENALI_PHY_303_DATA
+	0x00000000, // DENALI_PHY_304_DATA
+	0x00000000, // DENALI_PHY_305_DATA
+	0x00800080, // DENALI_PHY_306_DATA
+	0x00800080, // DENALI_PHY_307_DATA
+	0x00800080, // DENALI_PHY_308_DATA
+	0x00800080, // DENALI_PHY_309_DATA
+	0x00800080, // DENALI_PHY_310_DATA
+	0x00800080, // DENALI_PHY_311_DATA
+	0x00800080, // DENALI_PHY_312_DATA
+	0x00800080, // DENALI_PHY_313_DATA
+	0x00800080, // DENALI_PHY_314_DATA
+	0x000100da, // DENALI_PHY_315_DATA
+	0x01ff0010, // DENALI_PHY_316_DATA
+	0x00000000, // DENALI_PHY_317_DATA
+	0x00000000, // DENALI_PHY_318_DATA
+	0x00000002, // DENALI_PHY_319_DATA
+	0x51313152, // DENALI_PHY_320_DATA
+	0x80013130, // DENALI_PHY_321_DATA
+	0x02000080, // DENALI_PHY_322_DATA
+	0x00100001, // DENALI_PHY_323_DATA
+	0x0c064208, // DENALI_PHY_324_DATA
+	0x000f0c0f, // DENALI_PHY_325_DATA
+	0x01000140, // DENALI_PHY_326_DATA
+	0x0000000c, // DENALI_PHY_327_DATA
+	0x00000000, // DENALI_PHY_328_DATA
+	0x00000000, // DENALI_PHY_329_DATA
+	0x00000000, // DENALI_PHY_330_DATA
+	0x00000000, // DENALI_PHY_331_DATA
+	0x00000000, // DENALI_PHY_332_DATA
+	0x00000000, // DENALI_PHY_333_DATA
+	0x00000000, // DENALI_PHY_334_DATA
+	0x00000000, // DENALI_PHY_335_DATA
+	0x00000000, // DENALI_PHY_336_DATA
+	0x00000000, // DENALI_PHY_337_DATA
+	0x00000000, // DENALI_PHY_338_DATA
+	0x00000000, // DENALI_PHY_339_DATA
+	0x00000000, // DENALI_PHY_340_DATA
+	0x00000000, // DENALI_PHY_341_DATA
+	0x00000000, // DENALI_PHY_342_DATA
+	0x00000000, // DENALI_PHY_343_DATA
+	0x00000000, // DENALI_PHY_344_DATA
+	0x00000000, // DENALI_PHY_345_DATA
+	0x00000000, // DENALI_PHY_346_DATA
+	0x00000000, // DENALI_PHY_347_DATA
+	0x00000000, // DENALI_PHY_348_DATA
+	0x00000000, // DENALI_PHY_349_DATA
+	0x00000000, // DENALI_PHY_350_DATA
+	0x00000000, // DENALI_PHY_351_DATA
+	0x00000000, // DENALI_PHY_352_DATA
+	0x00000000, // DENALI_PHY_353_DATA
+	0x00000000, // DENALI_PHY_354_DATA
+	0x00000000, // DENALI_PHY_355_DATA
+	0x00000000, // DENALI_PHY_356_DATA
+	0x00000000, // DENALI_PHY_357_DATA
+	0x00000000, // DENALI_PHY_358_DATA
+	0x00000000, // DENALI_PHY_359_DATA
+	0x00000000, // DENALI_PHY_360_DATA
+	0x00000000, // DENALI_PHY_361_DATA
+	0x00000000, // DENALI_PHY_362_DATA
+	0x00000000, // DENALI_PHY_363_DATA
+	0x00000000, // DENALI_PHY_364_DATA
+	0x00000000, // DENALI_PHY_365_DATA
+	0x00000000, // DENALI_PHY_366_DATA
+	0x00000000, // DENALI_PHY_367_DATA
+	0x00000000, // DENALI_PHY_368_DATA
+	0x00000000, // DENALI_PHY_369_DATA
+	0x00000000, // DENALI_PHY_370_DATA
+	0x00000000, // DENALI_PHY_371_DATA
+	0x00000000, // DENALI_PHY_372_DATA
+	0x00000000, // DENALI_PHY_373_DATA
+	0x00000000, // DENALI_PHY_374_DATA
+	0x00000000, // DENALI_PHY_375_DATA
+	0x00000000, // DENALI_PHY_376_DATA
+	0x00000000, // DENALI_PHY_377_DATA
+	0x00000000, // DENALI_PHY_378_DATA
+	0x00000000, // DENALI_PHY_379_DATA
+	0x00000000, // DENALI_PHY_380_DATA
+	0x00000000, // DENALI_PHY_381_DATA
+	0x00000000, // DENALI_PHY_382_DATA
+	0x00000000, // DENALI_PHY_383_DATA
+	0x37651240, // DENALI_PHY_384_DATA
+	0x0004c008, // DENALI_PHY_385_DATA
+	0x000000da, // DENALI_PHY_386_DATA
+	0x00000000, // DENALI_PHY_387_DATA
+	0x00000000, // DENALI_PHY_388_DATA
+	0x00010000, // DENALI_PHY_389_DATA
+	0x01DDDD90, // DENALI_PHY_390_DATA
+	0x01DDDD90, // DENALI_PHY_391_DATA
+	0x01030001, // DENALI_PHY_392_DATA
+	0x01000000, // DENALI_PHY_393_DATA
+	0x00c00000, // DENALI_PHY_394_DATA
+	0x00000007, // DENALI_PHY_395_DATA
+	0x00000000, // DENALI_PHY_396_DATA
+	0x00000000, // DENALI_PHY_397_DATA
+	0x04000408, // DENALI_PHY_398_DATA
+	0x00000408, // DENALI_PHY_399_DATA
+	0x00e4e400, // DENALI_PHY_400_DATA
+	0x00000000, // DENALI_PHY_401_DATA
+	0x00000000, // DENALI_PHY_402_DATA
+	0x00000000, // DENALI_PHY_403_DATA
+	0x00000000, // DENALI_PHY_404_DATA
+	0x00000000, // DENALI_PHY_405_DATA
+	0x00000000, // DENALI_PHY_406_DATA
+	0x00000000, // DENALI_PHY_407_DATA
+	0x00000000, // DENALI_PHY_408_DATA
+	0x00000000, // DENALI_PHY_409_DATA
+	0x00000000, // DENALI_PHY_410_DATA
+	0x00000000, // DENALI_PHY_411_DATA
+	0x00000000, // DENALI_PHY_412_DATA
+	0x00000000, // DENALI_PHY_413_DATA
+	0x00000000, // DENALI_PHY_414_DATA
+	0x00000000, // DENALI_PHY_415_DATA
+	0x00000000, // DENALI_PHY_416_DATA
+	0x00200000, // DENALI_PHY_417_DATA
+	0x00000000, // DENALI_PHY_418_DATA
+	0x00000000, // DENALI_PHY_419_DATA
+	0x00000000, // DENALI_PHY_420_DATA
+	0x00000000, // DENALI_PHY_421_DATA
+	0x00000000, // DENALI_PHY_422_DATA
+	0x00000000, // DENALI_PHY_423_DATA
+	0x02800280, // DENALI_PHY_424_DATA
+	0x02800280, // DENALI_PHY_425_DATA
+	0x02800280, // DENALI_PHY_426_DATA
+	0x02800280, // DENALI_PHY_427_DATA
+	0x00000280, // DENALI_PHY_428_DATA
+	0x00000000, // DENALI_PHY_429_DATA
+	0x00000000, // DENALI_PHY_430_DATA
+	0x00000000, // DENALI_PHY_431_DATA
+	0x00000000, // DENALI_PHY_432_DATA
+	0x00000000, // DENALI_PHY_433_DATA
+	0x00800080, // DENALI_PHY_434_DATA
+	0x00800080, // DENALI_PHY_435_DATA
+	0x00800080, // DENALI_PHY_436_DATA
+	0x00800080, // DENALI_PHY_437_DATA
+	0x00800080, // DENALI_PHY_438_DATA
+	0x00800080, // DENALI_PHY_439_DATA
+	0x00800080, // DENALI_PHY_440_DATA
+	0x00800080, // DENALI_PHY_441_DATA
+	0x00800080, // DENALI_PHY_442_DATA
+	0x000100da, // DENALI_PHY_443_DATA
+	0x01ff0010, // DENALI_PHY_444_DATA
+	0x00000000, // DENALI_PHY_445_DATA
+	0x00000000, // DENALI_PHY_446_DATA
+	0x00000002, // DENALI_PHY_447_DATA
+	0x51313152, // DENALI_PHY_448_DATA
+	0x80013130, // DENALI_PHY_449_DATA
+	0x02000080, // DENALI_PHY_450_DATA
+	0x00100001, // DENALI_PHY_451_DATA
+	0x0c064208, // DENALI_PHY_452_DATA
+	0x000f0c0f, // DENALI_PHY_453_DATA
+	0x01000140, // DENALI_PHY_454_DATA
+	0x0000000c, // DENALI_PHY_455_DATA
+	0x00000000, // DENALI_PHY_456_DATA
+	0x00000000, // DENALI_PHY_457_DATA
+	0x00000000, // DENALI_PHY_458_DATA
+	0x00000000, // DENALI_PHY_459_DATA
+	0x00000000, // DENALI_PHY_460_DATA
+	0x00000000, // DENALI_PHY_461_DATA
+	0x00000000, // DENALI_PHY_462_DATA
+	0x00000000, // DENALI_PHY_463_DATA
+	0x00000000, // DENALI_PHY_464_DATA
+	0x00000000, // DENALI_PHY_465_DATA
+	0x00000000, // DENALI_PHY_466_DATA
+	0x00000000, // DENALI_PHY_467_DATA
+	0x00000000, // DENALI_PHY_468_DATA
+	0x00000000, // DENALI_PHY_469_DATA
+	0x00000000, // DENALI_PHY_470_DATA
+	0x00000000, // DENALI_PHY_471_DATA
+	0x00000000, // DENALI_PHY_472_DATA
+	0x00000000, // DENALI_PHY_473_DATA
+	0x00000000, // DENALI_PHY_474_DATA
+	0x00000000, // DENALI_PHY_475_DATA
+	0x00000000, // DENALI_PHY_476_DATA
+	0x00000000, // DENALI_PHY_477_DATA
+	0x00000000, // DENALI_PHY_478_DATA
+	0x00000000, // DENALI_PHY_479_DATA
+	0x00000000, // DENALI_PHY_480_DATA
+	0x00000000, // DENALI_PHY_481_DATA
+	0x00000000, // DENALI_PHY_482_DATA
+	0x00000000, // DENALI_PHY_483_DATA
+	0x00000000, // DENALI_PHY_484_DATA
+	0x00000000, // DENALI_PHY_485_DATA
+	0x00000000, // DENALI_PHY_486_DATA
+	0x00000000, // DENALI_PHY_487_DATA
+	0x00000000, // DENALI_PHY_488_DATA
+	0x00000000, // DENALI_PHY_489_DATA
+	0x00000000, // DENALI_PHY_490_DATA
+	0x00000000, // DENALI_PHY_491_DATA
+	0x00000000, // DENALI_PHY_492_DATA
+	0x00000000, // DENALI_PHY_493_DATA
+	0x00000000, // DENALI_PHY_494_DATA
+	0x00000000, // DENALI_PHY_495_DATA
+	0x00000000, // DENALI_PHY_496_DATA
+	0x00000000, // DENALI_PHY_497_DATA
+	0x00000000, // DENALI_PHY_498_DATA
+	0x00000000, // DENALI_PHY_499_DATA
+	0x00000000, // DENALI_PHY_500_DATA
+	0x00000000, // DENALI_PHY_501_DATA
+	0x00000000, // DENALI_PHY_502_DATA
+	0x00000000, // DENALI_PHY_503_DATA
+	0x00000000, // DENALI_PHY_504_DATA
+	0x00000000, // DENALI_PHY_505_DATA
+	0x00000000, // DENALI_PHY_506_DATA
+	0x00000000, // DENALI_PHY_507_DATA
+	0x00000000, // DENALI_PHY_508_DATA
+	0x00000000, // DENALI_PHY_509_DATA
+	0x00000000, // DENALI_PHY_510_DATA
+	0x00000000, // DENALI_PHY_511_DATA
+	0x34216750, // DENALI_PHY_512_DATA
+	0x0004c008, // DENALI_PHY_513_DATA
+	0x000000da, // DENALI_PHY_514_DATA
+	0x00000000, // DENALI_PHY_515_DATA
+	0x00000000, // DENALI_PHY_516_DATA
+	0x00010000, // DENALI_PHY_517_DATA
+	0x01DDDD90, // DENALI_PHY_518_DATA
+	0x01DDDD90, // DENALI_PHY_519_DATA
+	0x01030001, // DENALI_PHY_520_DATA
+	0x01000000, // DENALI_PHY_521_DATA
+	0x00c00000, // DENALI_PHY_522_DATA
+	0x00000007, // DENALI_PHY_523_DATA
+	0x00000000, // DENALI_PHY_524_DATA
+	0x00000000, // DENALI_PHY_525_DATA
+	0x04000408, // DENALI_PHY_526_DATA
+	0x00000408, // DENALI_PHY_527_DATA
+	0x00e4e400, // DENALI_PHY_528_DATA
+	0x00000000, // DENALI_PHY_529_DATA
+	0x00000000, // DENALI_PHY_530_DATA
+	0x00000000, // DENALI_PHY_531_DATA
+	0x00000000, // DENALI_PHY_532_DATA
+	0x00000000, // DENALI_PHY_533_DATA
+	0x00000000, // DENALI_PHY_534_DATA
+	0x00000000, // DENALI_PHY_535_DATA
+	0x00000000, // DENALI_PHY_536_DATA
+	0x00000000, // DENALI_PHY_537_DATA
+	0x00000000, // DENALI_PHY_538_DATA
+	0x00000000, // DENALI_PHY_539_DATA
+	0x00000000, // DENALI_PHY_540_DATA
+	0x00000000, // DENALI_PHY_541_DATA
+	0x00000000, // DENALI_PHY_542_DATA
+	0x00000000, // DENALI_PHY_543_DATA
+	0x00000000, // DENALI_PHY_544_DATA
+	0x00200000, // DENALI_PHY_545_DATA
+	0x00000000, // DENALI_PHY_546_DATA
+	0x00000000, // DENALI_PHY_547_DATA
+	0x00000000, // DENALI_PHY_548_DATA
+	0x00000000, // DENALI_PHY_549_DATA
+	0x00000000, // DENALI_PHY_550_DATA
+	0x00000000, // DENALI_PHY_551_DATA
+	0x02800280, // DENALI_PHY_552_DATA
+	0x02800280, // DENALI_PHY_553_DATA
+	0x02800280, // DENALI_PHY_554_DATA
+	0x02800280, // DENALI_PHY_555_DATA
+	0x00000280, // DENALI_PHY_556_DATA
+	0x00000000, // DENALI_PHY_557_DATA
+	0x00000000, // DENALI_PHY_558_DATA
+	0x00000000, // DENALI_PHY_559_DATA
+	0x00000000, // DENALI_PHY_560_DATA
+	0x00000000, // DENALI_PHY_561_DATA
+	0x00800080, // DENALI_PHY_562_DATA
+	0x00800080, // DENALI_PHY_563_DATA
+	0x00800080, // DENALI_PHY_564_DATA
+	0x00800080, // DENALI_PHY_565_DATA
+	0x00800080, // DENALI_PHY_566_DATA
+	0x00800080, // DENALI_PHY_567_DATA
+	0x00800080, // DENALI_PHY_568_DATA
+	0x00800080, // DENALI_PHY_569_DATA
+	0x00800080, // DENALI_PHY_570_DATA
+	0x000100da, // DENALI_PHY_571_DATA
+	0x01ff0010, // DENALI_PHY_572_DATA
+	0x00000000, // DENALI_PHY_573_DATA
+	0x00000000, // DENALI_PHY_574_DATA
+	0x00000002, // DENALI_PHY_575_DATA
+	0x51313152, // DENALI_PHY_576_DATA
+	0x80013130, // DENALI_PHY_577_DATA
+	0x02000080, // DENALI_PHY_578_DATA
+	0x00100001, // DENALI_PHY_579_DATA
+	0x0c064208, // DENALI_PHY_580_DATA
+	0x000f0c0f, // DENALI_PHY_581_DATA
+	0x01000140, // DENALI_PHY_582_DATA
+	0x0000000c, // DENALI_PHY_583_DATA
+	0x00000000, // DENALI_PHY_584_DATA
+	0x00000000, // DENALI_PHY_585_DATA
+	0x00000000, // DENALI_PHY_586_DATA
+	0x00000000, // DENALI_PHY_587_DATA
+	0x00000000, // DENALI_PHY_588_DATA
+	0x00000000, // DENALI_PHY_589_DATA
+	0x00000000, // DENALI_PHY_590_DATA
+	0x00000000, // DENALI_PHY_591_DATA
+	0x00000000, // DENALI_PHY_592_DATA
+	0x00000000, // DENALI_PHY_593_DATA
+	0x00000000, // DENALI_PHY_594_DATA
+	0x00000000, // DENALI_PHY_595_DATA
+	0x00000000, // DENALI_PHY_596_DATA
+	0x00000000, // DENALI_PHY_597_DATA
+	0x00000000, // DENALI_PHY_598_DATA
+	0x00000000, // DENALI_PHY_599_DATA
+	0x00000000, // DENALI_PHY_600_DATA
+	0x00000000, // DENALI_PHY_601_DATA
+	0x00000000, // DENALI_PHY_602_DATA
+	0x00000000, // DENALI_PHY_603_DATA
+	0x00000000, // DENALI_PHY_604_DATA
+	0x00000000, // DENALI_PHY_605_DATA
+	0x00000000, // DENALI_PHY_606_DATA
+	0x00000000, // DENALI_PHY_607_DATA
+	0x00000000, // DENALI_PHY_608_DATA
+	0x00000000, // DENALI_PHY_609_DATA
+	0x00000000, // DENALI_PHY_610_DATA
+	0x00000000, // DENALI_PHY_611_DATA
+	0x00000000, // DENALI_PHY_612_DATA
+	0x00000000, // DENALI_PHY_613_DATA
+	0x00000000, // DENALI_PHY_614_DATA
+	0x00000000, // DENALI_PHY_615_DATA
+	0x00000000, // DENALI_PHY_616_DATA
+	0x00000000, // DENALI_PHY_617_DATA
+	0x00000000, // DENALI_PHY_618_DATA
+	0x00000000, // DENALI_PHY_619_DATA
+	0x00000000, // DENALI_PHY_620_DATA
+	0x00000000, // DENALI_PHY_621_DATA
+	0x00000000, // DENALI_PHY_622_DATA
+	0x00000000, // DENALI_PHY_623_DATA
+	0x00000000, // DENALI_PHY_624_DATA
+	0x00000000, // DENALI_PHY_625_DATA
+	0x00000000, // DENALI_PHY_626_DATA
+	0x00000000, // DENALI_PHY_627_DATA
+	0x00000000, // DENALI_PHY_628_DATA
+	0x00000000, // DENALI_PHY_629_DATA
+	0x00000000, // DENALI_PHY_630_DATA
+	0x00000000, // DENALI_PHY_631_DATA
+	0x00000000, // DENALI_PHY_632_DATA
+	0x00000000, // DENALI_PHY_633_DATA
+	0x00000000, // DENALI_PHY_634_DATA
+	0x00000000, // DENALI_PHY_635_DATA
+	0x00000000, // DENALI_PHY_636_DATA
+	0x00000000, // DENALI_PHY_637_DATA
+	0x00000000, // DENALI_PHY_638_DATA
+	0x00000000, // DENALI_PHY_639_DATA
+	0x35176402, // DENALI_PHY_640_DATA
+	0x0004c008, // DENALI_PHY_641_DATA
+	0x000000da, // DENALI_PHY_642_DATA
+	0x00000000, // DENALI_PHY_643_DATA
+	0x00000000, // DENALI_PHY_644_DATA
+	0x00010000, // DENALI_PHY_645_DATA
+	0x01DDDD90, // DENALI_PHY_646_DATA
+	0x01DDDD90, // DENALI_PHY_647_DATA
+	0x01030001, // DENALI_PHY_648_DATA
+	0x01000000, // DENALI_PHY_649_DATA
+	0x00c00000, // DENALI_PHY_650_DATA
+	0x00000007, // DENALI_PHY_651_DATA
+	0x00000000, // DENALI_PHY_652_DATA
+	0x00000000, // DENALI_PHY_653_DATA
+	0x04000408, // DENALI_PHY_654_DATA
+	0x00000408, // DENALI_PHY_655_DATA
+	0x00e4e400, // DENALI_PHY_656_DATA
+	0x00000000, // DENALI_PHY_657_DATA
+	0x00000000, // DENALI_PHY_658_DATA
+	0x00000000, // DENALI_PHY_659_DATA
+	0x00000000, // DENALI_PHY_660_DATA
+	0x00000000, // DENALI_PHY_661_DATA
+	0x00000000, // DENALI_PHY_662_DATA
+	0x00000000, // DENALI_PHY_663_DATA
+	0x00000000, // DENALI_PHY_664_DATA
+	0x00000000, // DENALI_PHY_665_DATA
+	0x00000000, // DENALI_PHY_666_DATA
+	0x00000000, // DENALI_PHY_667_DATA
+	0x00000000, // DENALI_PHY_668_DATA
+	0x00000000, // DENALI_PHY_669_DATA
+	0x00000000, // DENALI_PHY_670_DATA
+	0x00000000, // DENALI_PHY_671_DATA
+	0x00000000, // DENALI_PHY_672_DATA
+	0x00200000, // DENALI_PHY_673_DATA
+	0x00000000, // DENALI_PHY_674_DATA
+	0x00000000, // DENALI_PHY_675_DATA
+	0x00000000, // DENALI_PHY_676_DATA
+	0x00000000, // DENALI_PHY_677_DATA
+	0x00000000, // DENALI_PHY_678_DATA
+	0x00000000, // DENALI_PHY_679_DATA
+	0x02800280, // DENALI_PHY_680_DATA
+	0x02800280, // DENALI_PHY_681_DATA
+	0x02800280, // DENALI_PHY_682_DATA
+	0x02800280, // DENALI_PHY_683_DATA
+	0x00000280, // DENALI_PHY_684_DATA
+	0x00000000, // DENALI_PHY_685_DATA
+	0x00000000, // DENALI_PHY_686_DATA
+	0x00000000, // DENALI_PHY_687_DATA
+	0x00000000, // DENALI_PHY_688_DATA
+	0x00000000, // DENALI_PHY_689_DATA
+	0x00800080, // DENALI_PHY_690_DATA
+	0x00800080, // DENALI_PHY_691_DATA
+	0x00800080, // DENALI_PHY_692_DATA
+	0x00800080, // DENALI_PHY_693_DATA
+	0x00800080, // DENALI_PHY_694_DATA
+	0x00800080, // DENALI_PHY_695_DATA
+	0x00800080, // DENALI_PHY_696_DATA
+	0x00800080, // DENALI_PHY_697_DATA
+	0x00800080, // DENALI_PHY_698_DATA
+	0x000100da, // DENALI_PHY_699_DATA
+	0x01ff0010, // DENALI_PHY_700_DATA
+	0x00000000, // DENALI_PHY_701_DATA
+	0x00000000, // DENALI_PHY_702_DATA
+	0x00000002, // DENALI_PHY_703_DATA
+	0x51313152, // DENALI_PHY_704_DATA
+	0x80013130, // DENALI_PHY_705_DATA
+	0x02000080, // DENALI_PHY_706_DATA
+	0x00100001, // DENALI_PHY_707_DATA
+	0x0c064208, // DENALI_PHY_708_DATA
+	0x000f0c0f, // DENALI_PHY_709_DATA
+	0x01000140, // DENALI_PHY_710_DATA
+	0x0000000c, // DENALI_PHY_711_DATA
+	0x00000000, // DENALI_PHY_712_DATA
+	0x00000000, // DENALI_PHY_713_DATA
+	0x00000000, // DENALI_PHY_714_DATA
+	0x00000000, // DENALI_PHY_715_DATA
+	0x00000000, // DENALI_PHY_716_DATA
+	0x00000000, // DENALI_PHY_717_DATA
+	0x00000000, // DENALI_PHY_718_DATA
+	0x00000000, // DENALI_PHY_719_DATA
+	0x00000000, // DENALI_PHY_720_DATA
+	0x00000000, // DENALI_PHY_721_DATA
+	0x00000000, // DENALI_PHY_722_DATA
+	0x00000000, // DENALI_PHY_723_DATA
+	0x00000000, // DENALI_PHY_724_DATA
+	0x00000000, // DENALI_PHY_725_DATA
+	0x00000000, // DENALI_PHY_726_DATA
+	0x00000000, // DENALI_PHY_727_DATA
+	0x00000000, // DENALI_PHY_728_DATA
+	0x00000000, // DENALI_PHY_729_DATA
+	0x00000000, // DENALI_PHY_730_DATA
+	0x00000000, // DENALI_PHY_731_DATA
+	0x00000000, // DENALI_PHY_732_DATA
+	0x00000000, // DENALI_PHY_733_DATA
+	0x00000000, // DENALI_PHY_734_DATA
+	0x00000000, // DENALI_PHY_735_DATA
+	0x00000000, // DENALI_PHY_736_DATA
+	0x00000000, // DENALI_PHY_737_DATA
+	0x00000000, // DENALI_PHY_738_DATA
+	0x00000000, // DENALI_PHY_739_DATA
+	0x00000000, // DENALI_PHY_740_DATA
+	0x00000000, // DENALI_PHY_741_DATA
+	0x00000000, // DENALI_PHY_742_DATA
+	0x00000000, // DENALI_PHY_743_DATA
+	0x00000000, // DENALI_PHY_744_DATA
+	0x00000000, // DENALI_PHY_745_DATA
+	0x00000000, // DENALI_PHY_746_DATA
+	0x00000000, // DENALI_PHY_747_DATA
+	0x00000000, // DENALI_PHY_748_DATA
+	0x00000000, // DENALI_PHY_749_DATA
+	0x00000000, // DENALI_PHY_750_DATA
+	0x00000000, // DENALI_PHY_751_DATA
+	0x00000000, // DENALI_PHY_752_DATA
+	0x00000000, // DENALI_PHY_753_DATA
+	0x00000000, // DENALI_PHY_754_DATA
+	0x00000000, // DENALI_PHY_755_DATA
+	0x00000000, // DENALI_PHY_756_DATA
+	0x00000000, // DENALI_PHY_757_DATA
+	0x00000000, // DENALI_PHY_758_DATA
+	0x00000000, // DENALI_PHY_759_DATA
+	0x00000000, // DENALI_PHY_760_DATA
+	0x00000000, // DENALI_PHY_761_DATA
+	0x00000000, // DENALI_PHY_762_DATA
+	0x00000000, // DENALI_PHY_763_DATA
+	0x00000000, // DENALI_PHY_764_DATA
+	0x00000000, // DENALI_PHY_765_DATA
+	0x00000000, // DENALI_PHY_766_DATA
+	0x00000000, // DENALI_PHY_767_DATA
+	0x10526347, // DENALI_PHY_768_DATA
+	0x0004c008, // DENALI_PHY_769_DATA
+	0x000000da, // DENALI_PHY_770_DATA
+	0x00000000, // DENALI_PHY_771_DATA
+	0x00000000, // DENALI_PHY_772_DATA
+	0x00010000, // DENALI_PHY_773_DATA
+	0x01DDDD90, // DENALI_PHY_774_DATA
+	0x01DDDD90, // DENALI_PHY_775_DATA
+	0x01030001, // DENALI_PHY_776_DATA
+	0x01000000, // DENALI_PHY_777_DATA
+	0x00c00000, // DENALI_PHY_778_DATA
+	0x00000007, // DENALI_PHY_779_DATA
+	0x00000000, // DENALI_PHY_780_DATA
+	0x00000000, // DENALI_PHY_781_DATA
+	0x04000408, // DENALI_PHY_782_DATA
+	0x00000408, // DENALI_PHY_783_DATA
+	0x00e4e400, // DENALI_PHY_784_DATA
+	0x00000000, // DENALI_PHY_785_DATA
+	0x00000000, // DENALI_PHY_786_DATA
+	0x00000000, // DENALI_PHY_787_DATA
+	0x00000000, // DENALI_PHY_788_DATA
+	0x00000000, // DENALI_PHY_789_DATA
+	0x00000000, // DENALI_PHY_790_DATA
+	0x00000000, // DENALI_PHY_791_DATA
+	0x00000000, // DENALI_PHY_792_DATA
+	0x00000000, // DENALI_PHY_793_DATA
+	0x00000000, // DENALI_PHY_794_DATA
+	0x00000000, // DENALI_PHY_795_DATA
+	0x00000000, // DENALI_PHY_796_DATA
+	0x00000000, // DENALI_PHY_797_DATA
+	0x00000000, // DENALI_PHY_798_DATA
+	0x00000000, // DENALI_PHY_799_DATA
+	0x00000000, // DENALI_PHY_800_DATA
+	0x00200000, // DENALI_PHY_801_DATA
+	0x00000000, // DENALI_PHY_802_DATA
+	0x00000000, // DENALI_PHY_803_DATA
+	0x00000000, // DENALI_PHY_804_DATA
+	0x00000000, // DENALI_PHY_805_DATA
+	0x00000000, // DENALI_PHY_806_DATA
+	0x00000000, // DENALI_PHY_807_DATA
+	0x02800280, // DENALI_PHY_808_DATA
+	0x02800280, // DENALI_PHY_809_DATA
+	0x02800280, // DENALI_PHY_810_DATA
+	0x02800280, // DENALI_PHY_811_DATA
+	0x00000280, // DENALI_PHY_812_DATA
+	0x00000000, // DENALI_PHY_813_DATA
+	0x00000000, // DENALI_PHY_814_DATA
+	0x00000000, // DENALI_PHY_815_DATA
+	0x00000000, // DENALI_PHY_816_DATA
+	0x00000000, // DENALI_PHY_817_DATA
+	0x00800080, // DENALI_PHY_818_DATA
+	0x00800080, // DENALI_PHY_819_DATA
+	0x00800080, // DENALI_PHY_820_DATA
+	0x00800080, // DENALI_PHY_821_DATA
+	0x00800080, // DENALI_PHY_822_DATA
+	0x00800080, // DENALI_PHY_823_DATA
+	0x00800080, // DENALI_PHY_824_DATA
+	0x00800080, // DENALI_PHY_825_DATA
+	0x00800080, // DENALI_PHY_826_DATA
+	0x000100da, // DENALI_PHY_827_DATA
+	0x01ff0010, // DENALI_PHY_828_DATA
+	0x00000000, // DENALI_PHY_829_DATA
+	0x00000000, // DENALI_PHY_830_DATA
+	0x00000002, // DENALI_PHY_831_DATA
+	0x51313152, // DENALI_PHY_832_DATA
+	0x80013130, // DENALI_PHY_833_DATA
+	0x02000080, // DENALI_PHY_834_DATA
+	0x00100001, // DENALI_PHY_835_DATA
+	0x0c064208, // DENALI_PHY_836_DATA
+	0x000f0c0f, // DENALI_PHY_837_DATA
+	0x01000140, // DENALI_PHY_838_DATA
+	0x0000000c, // DENALI_PHY_839_DATA
+	0x00000000, // DENALI_PHY_840_DATA
+	0x00000000, // DENALI_PHY_841_DATA
+	0x00000000, // DENALI_PHY_842_DATA
+	0x00000000, // DENALI_PHY_843_DATA
+	0x00000000, // DENALI_PHY_844_DATA
+	0x00000000, // DENALI_PHY_845_DATA
+	0x00000000, // DENALI_PHY_846_DATA
+	0x00000000, // DENALI_PHY_847_DATA
+	0x00000000, // DENALI_PHY_848_DATA
+	0x00000000, // DENALI_PHY_849_DATA
+	0x00000000, // DENALI_PHY_850_DATA
+	0x00000000, // DENALI_PHY_851_DATA
+	0x00000000, // DENALI_PHY_852_DATA
+	0x00000000, // DENALI_PHY_853_DATA
+	0x00000000, // DENALI_PHY_854_DATA
+	0x00000000, // DENALI_PHY_855_DATA
+	0x00000000, // DENALI_PHY_856_DATA
+	0x00000000, // DENALI_PHY_857_DATA
+	0x00000000, // DENALI_PHY_858_DATA
+	0x00000000, // DENALI_PHY_859_DATA
+	0x00000000, // DENALI_PHY_860_DATA
+	0x00000000, // DENALI_PHY_861_DATA
+	0x00000000, // DENALI_PHY_862_DATA
+	0x00000000, // DENALI_PHY_863_DATA
+	0x00000000, // DENALI_PHY_864_DATA
+	0x00000000, // DENALI_PHY_865_DATA
+	0x00000000, // DENALI_PHY_866_DATA
+	0x00000000, // DENALI_PHY_867_DATA
+	0x00000000, // DENALI_PHY_868_DATA
+	0x00000000, // DENALI_PHY_869_DATA
+	0x00000000, // DENALI_PHY_870_DATA
+	0x00000000, // DENALI_PHY_871_DATA
+	0x00000000, // DENALI_PHY_872_DATA
+	0x00000000, // DENALI_PHY_873_DATA
+	0x00000000, // DENALI_PHY_874_DATA
+	0x00000000, // DENALI_PHY_875_DATA
+	0x00000000, // DENALI_PHY_876_DATA
+	0x00000000, // DENALI_PHY_877_DATA
+	0x00000000, // DENALI_PHY_878_DATA
+	0x00000000, // DENALI_PHY_879_DATA
+	0x00000000, // DENALI_PHY_880_DATA
+	0x00000000, // DENALI_PHY_881_DATA
+	0x00000000, // DENALI_PHY_882_DATA
+	0x00000000, // DENALI_PHY_883_DATA
+	0x00000000, // DENALI_PHY_884_DATA
+	0x00000000, // DENALI_PHY_885_DATA
+	0x00000000, // DENALI_PHY_886_DATA
+	0x00000000, // DENALI_PHY_887_DATA
+	0x00000000, // DENALI_PHY_888_DATA
+	0x00000000, // DENALI_PHY_889_DATA
+	0x00000000, // DENALI_PHY_890_DATA
+	0x00000000, // DENALI_PHY_891_DATA
+	0x00000000, // DENALI_PHY_892_DATA
+	0x00000000, // DENALI_PHY_893_DATA
+	0x00000000, // DENALI_PHY_894_DATA
+	0x00000000, // DENALI_PHY_895_DATA
+	0x41753260, // DENALI_PHY_896_DATA
+	0x0004c008, // DENALI_PHY_897_DATA
+	0x000000da, // DENALI_PHY_898_DATA
+	0x00000000, // DENALI_PHY_899_DATA
+	0x00000000, // DENALI_PHY_900_DATA
+	0x00010000, // DENALI_PHY_901_DATA
+	0x01DDDD90, // DENALI_PHY_902_DATA
+	0x01DDDD90, // DENALI_PHY_903_DATA
+	0x01030001, // DENALI_PHY_904_DATA
+	0x01000000, // DENALI_PHY_905_DATA
+	0x00c00000, // DENALI_PHY_906_DATA
+	0x00000007, // DENALI_PHY_907_DATA
+	0x00000000, // DENALI_PHY_908_DATA
+	0x00000000, // DENALI_PHY_909_DATA
+	0x04000408, // DENALI_PHY_910_DATA
+	0x00000408, // DENALI_PHY_911_DATA
+	0x00e4e400, // DENALI_PHY_912_DATA
+	0x00000000, // DENALI_PHY_913_DATA
+	0x00000000, // DENALI_PHY_914_DATA
+	0x00000000, // DENALI_PHY_915_DATA
+	0x00000000, // DENALI_PHY_916_DATA
+	0x00000000, // DENALI_PHY_917_DATA
+	0x00000000, // DENALI_PHY_918_DATA
+	0x00000000, // DENALI_PHY_919_DATA
+	0x00000000, // DENALI_PHY_920_DATA
+	0x00000000, // DENALI_PHY_921_DATA
+	0x00000000, // DENALI_PHY_922_DATA
+	0x00000000, // DENALI_PHY_923_DATA
+	0x00000000, // DENALI_PHY_924_DATA
+	0x00000000, // DENALI_PHY_925_DATA
+	0x00000000, // DENALI_PHY_926_DATA
+	0x00000000, // DENALI_PHY_927_DATA
+	0x00000000, // DENALI_PHY_928_DATA
+	0x00200000, // DENALI_PHY_929_DATA
+	0x00000000, // DENALI_PHY_930_DATA
+	0x00000000, // DENALI_PHY_931_DATA
+	0x00000000, // DENALI_PHY_932_DATA
+	0x00000000, // DENALI_PHY_933_DATA
+	0x00000000, // DENALI_PHY_934_DATA
+	0x00000000, // DENALI_PHY_935_DATA
+	0x02800280, // DENALI_PHY_936_DATA
+	0x02800280, // DENALI_PHY_937_DATA
+	0x02800280, // DENALI_PHY_938_DATA
+	0x02800280, // DENALI_PHY_939_DATA
+	0x00000280, // DENALI_PHY_940_DATA
+	0x00000000, // DENALI_PHY_941_DATA
+	0x00000000, // DENALI_PHY_942_DATA
+	0x00000000, // DENALI_PHY_943_DATA
+	0x00000000, // DENALI_PHY_944_DATA
+	0x00000000, // DENALI_PHY_945_DATA
+	0x00800080, // DENALI_PHY_946_DATA
+	0x00800080, // DENALI_PHY_947_DATA
+	0x00800080, // DENALI_PHY_948_DATA
+	0x00800080, // DENALI_PHY_949_DATA
+	0x00800080, // DENALI_PHY_950_DATA
+	0x00800080, // DENALI_PHY_951_DATA
+	0x00800080, // DENALI_PHY_952_DATA
+	0x00800080, // DENALI_PHY_953_DATA
+	0x00800080, // DENALI_PHY_954_DATA
+	0x000100da, // DENALI_PHY_955_DATA
+	0x01ff0010, // DENALI_PHY_956_DATA
+	0x00000000, // DENALI_PHY_957_DATA
+	0x00000000, // DENALI_PHY_958_DATA
+	0x00000002, // DENALI_PHY_959_DATA
+	0x51313152, // DENALI_PHY_960_DATA
+	0x80013130, // DENALI_PHY_961_DATA
+	0x02000080, // DENALI_PHY_962_DATA
+	0x00100001, // DENALI_PHY_963_DATA
+	0x0c064208, // DENALI_PHY_964_DATA
+	0x000f0c0f, // DENALI_PHY_965_DATA
+	0x01000140, // DENALI_PHY_966_DATA
+	0x0000000c, // DENALI_PHY_967_DATA
+	0x00000000, // DENALI_PHY_968_DATA
+	0x00000000, // DENALI_PHY_969_DATA
+	0x00000000, // DENALI_PHY_970_DATA
+	0x00000000, // DENALI_PHY_971_DATA
+	0x00000000, // DENALI_PHY_972_DATA
+	0x00000000, // DENALI_PHY_973_DATA
+	0x00000000, // DENALI_PHY_974_DATA
+	0x00000000, // DENALI_PHY_975_DATA
+	0x00000000, // DENALI_PHY_976_DATA
+	0x00000000, // DENALI_PHY_977_DATA
+	0x00000000, // DENALI_PHY_978_DATA
+	0x00000000, // DENALI_PHY_979_DATA
+	0x00000000, // DENALI_PHY_980_DATA
+	0x00000000, // DENALI_PHY_981_DATA
+	0x00000000, // DENALI_PHY_982_DATA
+	0x00000000, // DENALI_PHY_983_DATA
+	0x00000000, // DENALI_PHY_984_DATA
+	0x00000000, // DENALI_PHY_985_DATA
+	0x00000000, // DENALI_PHY_986_DATA
+	0x00000000, // DENALI_PHY_987_DATA
+	0x00000000, // DENALI_PHY_988_DATA
+	0x00000000, // DENALI_PHY_989_DATA
+	0x00000000, // DENALI_PHY_990_DATA
+	0x00000000, // DENALI_PHY_991_DATA
+	0x00000000, // DENALI_PHY_992_DATA
+	0x00000000, // DENALI_PHY_993_DATA
+	0x00000000, // DENALI_PHY_994_DATA
+	0x00000000, // DENALI_PHY_995_DATA
+	0x00000000, // DENALI_PHY_996_DATA
+	0x00000000, // DENALI_PHY_997_DATA
+	0x00000000, // DENALI_PHY_998_DATA
+	0x00000000, // DENALI_PHY_999_DATA
+	0x00000000, // DENALI_PHY_1000_DATA
+	0x00000000, // DENALI_PHY_1001_DATA
+	0x00000000, // DENALI_PHY_1002_DATA
+	0x00000000, // DENALI_PHY_1003_DATA
+	0x00000000, // DENALI_PHY_1004_DATA
+	0x00000000, // DENALI_PHY_1005_DATA
+	0x00000000, // DENALI_PHY_1006_DATA
+	0x00000000, // DENALI_PHY_1007_DATA
+	0x00000000, // DENALI_PHY_1008_DATA
+	0x00000000, // DENALI_PHY_1009_DATA
+	0x00000000, // DENALI_PHY_1010_DATA
+	0x00000000, // DENALI_PHY_1011_DATA
+	0x00000000, // DENALI_PHY_1012_DATA
+	0x00000000, // DENALI_PHY_1013_DATA
+	0x00000000, // DENALI_PHY_1014_DATA
+	0x00000000, // DENALI_PHY_1015_DATA
+	0x00000000, // DENALI_PHY_1016_DATA
+	0x00000000, // DENALI_PHY_1017_DATA
+	0x00000000, // DENALI_PHY_1018_DATA
+	0x00000000, // DENALI_PHY_1019_DATA
+	0x00000000, // DENALI_PHY_1020_DATA
+	0x00000000, // DENALI_PHY_1021_DATA
+	0x00000000, // DENALI_PHY_1022_DATA
+	0x00000000, // DENALI_PHY_1023_DATA
+	0x76543210, // DENALI_PHY_1024_DATA
+	0x0004c008, // DENALI_PHY_1025_DATA
+	0x000000da, // DENALI_PHY_1026_DATA
+	0x00000000, // DENALI_PHY_1027_DATA
+	0x00000000, // DENALI_PHY_1028_DATA
+	0x00010000, // DENALI_PHY_1029_DATA
+	0x01665555, // DENALI_PHY_1030_DATA
+	0x01665555, // DENALI_PHY_1031_DATA
+	0x01030001, // DENALI_PHY_1032_DATA
+	0x01000000, // DENALI_PHY_1033_DATA
+	0x00c00000, // DENALI_PHY_1034_DATA
+	0x00000007, // DENALI_PHY_1035_DATA
+	0x00000000, // DENALI_PHY_1036_DATA
+	0x00000000, // DENALI_PHY_1037_DATA
+	0x04000408, // DENALI_PHY_1038_DATA
+	0x00000408, // DENALI_PHY_1039_DATA
+	0x00e4e400, // DENALI_PHY_1040_DATA
+	0x00000000, // DENALI_PHY_1041_DATA
+	0x00000000, // DENALI_PHY_1042_DATA
+	0x00000000, // DENALI_PHY_1043_DATA
+	0x00000000, // DENALI_PHY_1044_DATA
+	0x00000000, // DENALI_PHY_1045_DATA
+	0x00000000, // DENALI_PHY_1046_DATA
+	0x00000000, // DENALI_PHY_1047_DATA
+	0x00000000, // DENALI_PHY_1048_DATA
+	0x00000000, // DENALI_PHY_1049_DATA
+	0x00000000, // DENALI_PHY_1050_DATA
+	0x00000000, // DENALI_PHY_1051_DATA
+	0x00000000, // DENALI_PHY_1052_DATA
+	0x00000000, // DENALI_PHY_1053_DATA
+	0x00000000, // DENALI_PHY_1054_DATA
+	0x00000000, // DENALI_PHY_1055_DATA
+	0x00000000, // DENALI_PHY_1056_DATA
+	0x00200000, // DENALI_PHY_1057_DATA
+	0x00000000, // DENALI_PHY_1058_DATA
+	0x00000000, // DENALI_PHY_1059_DATA
+	0x00000000, // DENALI_PHY_1060_DATA
+	0x00000000, // DENALI_PHY_1061_DATA
+	0x00000000, // DENALI_PHY_1062_DATA
+	0x00000000, // DENALI_PHY_1063_DATA
+	0x02800280, // DENALI_PHY_1064_DATA
+	0x02800280, // DENALI_PHY_1065_DATA
+	0x02800280, // DENALI_PHY_1066_DATA
+	0x02800280, // DENALI_PHY_1067_DATA
+	0x00000280, // DENALI_PHY_1068_DATA
+	0x00000000, // DENALI_PHY_1069_DATA
+	0x00000000, // DENALI_PHY_1070_DATA
+	0x00000000, // DENALI_PHY_1071_DATA
+	0x00000000, // DENALI_PHY_1072_DATA
+	0x00000000, // DENALI_PHY_1073_DATA
+	0x00800080, // DENALI_PHY_1074_DATA
+	0x00800080, // DENALI_PHY_1075_DATA
+	0x00800080, // DENALI_PHY_1076_DATA
+	0x00800080, // DENALI_PHY_1077_DATA
+	0x00800080, // DENALI_PHY_1078_DATA
+	0x00800080, // DENALI_PHY_1079_DATA
+	0x00800080, // DENALI_PHY_1080_DATA
+	0x00800080, // DENALI_PHY_1081_DATA
+	0x00800080, // DENALI_PHY_1082_DATA
+	0x000100da, // DENALI_PHY_1083_DATA
+	0x01ff0010, // DENALI_PHY_1084_DATA
+	0x00000000, // DENALI_PHY_1085_DATA
+	0x00000000, // DENALI_PHY_1086_DATA
+	0x00000002, // DENALI_PHY_1087_DATA
+	0x51313152, // DENALI_PHY_1088_DATA
+	0x80013130, // DENALI_PHY_1089_DATA
+	0x02000080, // DENALI_PHY_1090_DATA
+	0x00100001, // DENALI_PHY_1091_DATA
+	0x0c064208, // DENALI_PHY_1092_DATA
+	0x000f0c0f, // DENALI_PHY_1093_DATA
+	0x01000140, // DENALI_PHY_1094_DATA
+	0x0000000c, // DENALI_PHY_1095_DATA
+	0x00000000, // DENALI_PHY_1096_DATA
+	0x00000000, // DENALI_PHY_1097_DATA
+	0x00000000, // DENALI_PHY_1098_DATA
+	0x00000000, // DENALI_PHY_1099_DATA
+	0x00000000, // DENALI_PHY_1100_DATA
+	0x00000000, // DENALI_PHY_1101_DATA
+	0x00000000, // DENALI_PHY_1102_DATA
+	0x00000000, // DENALI_PHY_1103_DATA
+	0x00000000, // DENALI_PHY_1104_DATA
+	0x00000000, // DENALI_PHY_1105_DATA
+	0x00000000, // DENALI_PHY_1106_DATA
+	0x00000000, // DENALI_PHY_1107_DATA
+	0x00000000, // DENALI_PHY_1108_DATA
+	0x00000000, // DENALI_PHY_1109_DATA
+	0x00000000, // DENALI_PHY_1110_DATA
+	0x00000000, // DENALI_PHY_1111_DATA
+	0x00000000, // DENALI_PHY_1112_DATA
+	0x00000000, // DENALI_PHY_1113_DATA
+	0x00000000, // DENALI_PHY_1114_DATA
+	0x00000000, // DENALI_PHY_1115_DATA
+	0x00000000, // DENALI_PHY_1116_DATA
+	0x00000000, // DENALI_PHY_1117_DATA
+	0x00000000, // DENALI_PHY_1118_DATA
+	0x00000000, // DENALI_PHY_1119_DATA
+	0x00000000, // DENALI_PHY_1120_DATA
+	0x00000000, // DENALI_PHY_1121_DATA
+	0x00000000, // DENALI_PHY_1122_DATA
+	0x00000000, // DENALI_PHY_1123_DATA
+	0x00000000, // DENALI_PHY_1124_DATA
+	0x00000000, // DENALI_PHY_1125_DATA
+	0x00000000, // DENALI_PHY_1126_DATA
+	0x00000000, // DENALI_PHY_1127_DATA
+	0x00000000, // DENALI_PHY_1128_DATA
+	0x00000000, // DENALI_PHY_1129_DATA
+	0x00000000, // DENALI_PHY_1130_DATA
+	0x00000000, // DENALI_PHY_1131_DATA
+	0x00000000, // DENALI_PHY_1132_DATA
+	0x00000000, // DENALI_PHY_1133_DATA
+	0x00000000, // DENALI_PHY_1134_DATA
+	0x00000000, // DENALI_PHY_1135_DATA
+	0x00000000, // DENALI_PHY_1136_DATA
+	0x00000000, // DENALI_PHY_1137_DATA
+	0x00000000, // DENALI_PHY_1138_DATA
+	0x00000000, // DENALI_PHY_1139_DATA
+	0x00000000, // DENALI_PHY_1140_DATA
+	0x00000000, // DENALI_PHY_1141_DATA
+	0x00000000, // DENALI_PHY_1142_DATA
+	0x00000000, // DENALI_PHY_1143_DATA
+	0x00000000, // DENALI_PHY_1144_DATA
+	0x00000000, // DENALI_PHY_1145_DATA
+	0x00000000, // DENALI_PHY_1146_DATA
+	0x00000000, // DENALI_PHY_1147_DATA
+	0x00000000, // DENALI_PHY_1148_DATA
+	0x00000000, // DENALI_PHY_1149_DATA
+	0x00000000, // DENALI_PHY_1150_DATA
+	0x00000000, // DENALI_PHY_1151_DATA
+	0x00000000, // DENALI_PHY_1152_DATA
+	0x00000000, // DENALI_PHY_1153_DATA
+	0x00050000, // DENALI_PHY_1154_DATA
+	0x00000000, // DENALI_PHY_1155_DATA
+	0x00000000, // DENALI_PHY_1156_DATA
+	0x00000000, // DENALI_PHY_1157_DATA
+	0x00000100, // DENALI_PHY_1158_DATA
+	0x00000000, // DENALI_PHY_1159_DATA
+	0x00000000, // DENALI_PHY_1160_DATA
+	0x00506401, // DENALI_PHY_1161_DATA
+	0x01221102, // DENALI_PHY_1162_DATA
+	0x00000122, // DENALI_PHY_1163_DATA
+	0x00000000, // DENALI_PHY_1164_DATA
+	0x000B1F00, // DENALI_PHY_1165_DATA
+	0x0B1F0B1F, // DENALI_PHY_1166_DATA
+	0x0B1F0B1F, // DENALI_PHY_1167_DATA
+	0x0B1F0B1F, // DENALI_PHY_1168_DATA
+	0x0B1F0B1F, // DENALI_PHY_1169_DATA
+	0x00000B00, // DENALI_PHY_1170_DATA
+	0x42080010, // DENALI_PHY_1171_DATA
+	0x01000100, // DENALI_PHY_1172_DATA
+	0x01000100, // DENALI_PHY_1173_DATA
+	0x01000100, // DENALI_PHY_1174_DATA
+	0x01000100, // DENALI_PHY_1175_DATA
+	0x00000000, // DENALI_PHY_1176_DATA
+	0x00000000, // DENALI_PHY_1177_DATA
+	0x00000000, // DENALI_PHY_1178_DATA
+	0x00000000, // DENALI_PHY_1179_DATA
+	0x00000000, // DENALI_PHY_1180_DATA
+	0x00000803, // DENALI_PHY_1181_DATA
+	0x223FFF00, // DENALI_PHY_1182_DATA
+	0x000008FF, // DENALI_PHY_1183_DATA
+	0x0000057F, // DENALI_PHY_1184_DATA
+	0x0000057F, // DENALI_PHY_1185_DATA
+	0x00037FFF, // DENALI_PHY_1186_DATA
+	0x00037FFF, // DENALI_PHY_1187_DATA
+	0x00004410, // DENALI_PHY_1188_DATA
+	0x00004410, // DENALI_PHY_1189_DATA
+	0x00004410, // DENALI_PHY_1190_DATA
+	0x00004410, // DENALI_PHY_1191_DATA
+	0x00004410, // DENALI_PHY_1192_DATA
+	0x00000111, // DENALI_PHY_1193_DATA
+	0x00000111, // DENALI_PHY_1194_DATA
+	0x00000000, // DENALI_PHY_1195_DATA
+	0x00000000, // DENALI_PHY_1196_DATA
+	0x00000000, // DENALI_PHY_1197_DATA
+	0x04000000, // DENALI_PHY_1198_DATA
+	0x00000000, // DENALI_PHY_1199_DATA
+	0x00000000, // DENALI_PHY_1200_DATA
+	0x00000108, // DENALI_PHY_1201_DATA
+	0x00000000, // DENALI_PHY_1202_DATA
+	0x00000000, // DENALI_PHY_1203_DATA
+	0x00000000, // DENALI_PHY_1204_DATA
+	0x00000001, // DENALI_PHY_1205_DATA
+	0x00000000, // DENALI_PHY_1206_DATA
+	0x00000000, // DENALI_PHY_1207_DATA
+	0x00000000, // DENALI_PHY_1208_DATA
+	0x00000000, // DENALI_PHY_1209_DATA
+	0x00000000, // DENALI_PHY_1210_DATA
+	0x00000000, // DENALI_PHY_1211_DATA
+	0x00020100, // DENALI_PHY_1212_DATA
+	0x00000000, // DENALI_PHY_1213_DATA
+	0x00000000, // DENALI_PHY_1214_DATA
+};
+
+const uint32_t denali_ddr_ctl_data[265] = {
+	0x00000a00, // DENALI_CTL_00_DATA
+	0x00000000, // DENALI_CTL_01_DATA
+	0x00000000, // DENALI_CTL_02_DATA
+	0x00000000, // DENALI_CTL_03_DATA
+	0x00000000, // DENALI_CTL_04_DATA
+	0x00000000, // DENALI_CTL_05_DATA
+	0x0000000a, // DENALI_CTL_06_DATA
+	0x0002d362, // DENALI_CTL_07_DATA
+	0x00071073, // DENALI_CTL_08_DATA
+	0x0a1c0255, // DENALI_CTL_09_DATA
+	0x1c1c0400, // DENALI_CTL_10_DATA
+	0x0404c90b, // DENALI_CTL_11_DATA
+	0x2b050405, // DENALI_CTL_12_DATA
+	0x0d0c081e, // DENALI_CTL_13_DATA
+	0x08090914, // DENALI_CTL_14_DATA
+	0x00fde718, // DENALI_CTL_15_DATA
+	0x00180a05, // DENALI_CTL_16_DATA
+	0x008b130d, // DENALI_CTL_17_DATA
+	0x01000118, // DENALI_CTL_18_DATA
+	0x0d032001, // DENALI_CTL_19_DATA
+	0x00000000, // DENALI_CTL_20_DATA
+	0x00000101, // DENALI_CTL_21_DATA
+	0x00000000, // DENALI_CTL_22_DATA
+	0x0a000000, // DENALI_CTL_23_DATA
+	0x00000000, // DENALI_CTL_24_DATA
+	0x01450100, // DENALI_CTL_25_DATA
+	0x00001c36, // DENALI_CTL_26_DATA
+	0x00000005, // DENALI_CTL_27_DATA
+	0x00170006, // DENALI_CTL_28_DATA
+	0x014e0400, // DENALI_CTL_29_DATA
+	0x03010000, // DENALI_CTL_30_DATA
+	0x000a0e00, // DENALI_CTL_31_DATA
+	0x04030200, // DENALI_CTL_32_DATA
+	0x0000031f, // DENALI_CTL_33_DATA
+	0x00070004, // DENALI_CTL_34_DATA
+	0x00000000, // DENALI_CTL_35_DATA
+	0x00000000, // DENALI_CTL_36_DATA
+	0x00000000, // DENALI_CTL_37_DATA
+	0x00000000, // DENALI_CTL_38_DATA
+	0x00000000, // DENALI_CTL_39_DATA
+	0x00000000, // DENALI_CTL_40_DATA
+	0x00000000, // DENALI_CTL_41_DATA
+	0x00000000, // DENALI_CTL_42_DATA
+	0x00000000, // DENALI_CTL_43_DATA
+	0x00000000, // DENALI_CTL_44_DATA
+	0x00000000, // DENALI_CTL_45_DATA
+	0x00000000, // DENALI_CTL_46_DATA
+	0x00000000, // DENALI_CTL_47_DATA
+	0x00000000, // DENALI_CTL_48_DATA
+	0x00000000, // DENALI_CTL_49_DATA
+	0x00000000, // DENALI_CTL_50_DATA
+	0x00000000, // DENALI_CTL_51_DATA
+	0x00000000, // DENALI_CTL_52_DATA
+	0x00000000, // DENALI_CTL_53_DATA
+	0x00000000, // DENALI_CTL_54_DATA
+	0x00000000, // DENALI_CTL_55_DATA
+	0x00000000, // DENALI_CTL_56_DATA
+	0x00000000, // DENALI_CTL_57_DATA
+	0x00000000, // DENALI_CTL_58_DATA
+	0x00000000, // DENALI_CTL_59_DATA
+	0x00000424, // DENALI_CTL_60_DATA
+	0x00000201, // DENALI_CTL_61_DATA
+	0x00001008, // DENALI_CTL_62_DATA
+	0x00000000, // DENALI_CTL_63_DATA
+	0x00000200, // DENALI_CTL_64_DATA
+	0x00000800, // DENALI_CTL_65_DATA
+	0x00000481, // DENALI_CTL_66_DATA
+	0x00000400, // DENALI_CTL_67_DATA
+	0x00000424, // DENALI_CTL_68_DATA
+	0x00000201, // DENALI_CTL_69_DATA
+	0x00001008, // DENALI_CTL_70_DATA
+	0x00000000, // DENALI_CTL_71_DATA
+	0x00000200, // DENALI_CTL_72_DATA
+	0x00000800, // DENALI_CTL_73_DATA
+	0x00000481, // DENALI_CTL_74_DATA
+	0x00000400, // DENALI_CTL_75_DATA
+	0x01010000, // DENALI_CTL_76_DATA
+	0x00000000, // DENALI_CTL_77_DATA
+	0x00000000, // DENALI_CTL_78_DATA
+	0x00000000, // DENALI_CTL_79_DATA
+	0x00000000, // DENALI_CTL_80_DATA
+	0x00000000, // DENALI_CTL_81_DATA
+	0x00000000, // DENALI_CTL_82_DATA
+	0x00000000, // DENALI_CTL_83_DATA
+	0x00000000, // DENALI_CTL_84_DATA
+	0x00000000, // DENALI_CTL_85_DATA
+	0x00000000, // DENALI_CTL_86_DATA
+	0x00000000, // DENALI_CTL_87_DATA
+	0x00000000, // DENALI_CTL_88_DATA
+	0x00000000, // DENALI_CTL_89_DATA
+	0x00000000, // DENALI_CTL_90_DATA
+	0x00000000, // DENALI_CTL_91_DATA
+	0x00000000, // DENALI_CTL_92_DATA
+	0x00000000, // DENALI_CTL_93_DATA
+	0x00000000, // DENALI_CTL_94_DATA
+	0x00000000, // DENALI_CTL_95_DATA
+	0x00000000, // DENALI_CTL_96_DATA
+	0x00000000, // DENALI_CTL_97_DATA
+	0x00000000, // DENALI_CTL_98_DATA
+	0x00000000, // DENALI_CTL_99_DATA
+	0x00000000, // DENALI_CTL_100_DATA
+	0x00000000, // DENALI_CTL_101_DATA
+	0x00000000, // DENALI_CTL_102_DATA
+	0x00000000, // DENALI_CTL_103_DATA
+	0x00000000, // DENALI_CTL_104_DATA
+	0x00000003, // DENALI_CTL_105_DATA
+	0x00000000, // DENALI_CTL_106_DATA
+	0x00000000, // DENALI_CTL_107_DATA
+	0x00000000, // DENALI_CTL_108_DATA
+	0x00000000, // DENALI_CTL_109_DATA
+	0x01000000, // DENALI_CTL_110_DATA
+	0x00040000, // DENALI_CTL_111_DATA
+	0x00800200, // DENALI_CTL_112_DATA
+	0x00000200, // DENALI_CTL_113_DATA
+	0x00000040, // DENALI_CTL_114_DATA
+	0x01000100, // DENALI_CTL_115_DATA
+	0x0a000002, // DENALI_CTL_116_DATA
+	0x0101ffff, // DENALI_CTL_117_DATA
+	0x01010101, // DENALI_CTL_118_DATA
+	0x01010101, // DENALI_CTL_119_DATA
+	0x0000010b, // DENALI_CTL_120_DATA
+	0x00000c03, // DENALI_CTL_121_DATA
+	0x00000000, // DENALI_CTL_122_DATA
+	0x00000000, // DENALI_CTL_123_DATA
+	0x00000000, // DENALI_CTL_124_DATA
+	0x00000000, // DENALI_CTL_125_DATA
+	0x00030300, // DENALI_CTL_126_DATA
+	0x00000000, // DENALI_CTL_127_DATA
+	0x00010101, // DENALI_CTL_128_DATA
+	0x00000000, // DENALI_CTL_129_DATA
+	0x00000000, // DENALI_CTL_130_DATA
+	0x00000000, // DENALI_CTL_131_DATA
+	0x00000000, // DENALI_CTL_132_DATA
+	0x00000000, // DENALI_CTL_133_DATA
+	0x00000000, // DENALI_CTL_134_DATA
+	0x00000000, // DENALI_CTL_135_DATA
+	0x00000000, // DENALI_CTL_136_DATA
+	0x00000000, // DENALI_CTL_137_DATA
+	0x00000000, // DENALI_CTL_138_DATA
+	0x00000000, // DENALI_CTL_139_DATA
+	0x00000000, // DENALI_CTL_140_DATA
+	0x00000000, // DENALI_CTL_141_DATA
+	0x00000000, // DENALI_CTL_142_DATA
+	0x00000000, // DENALI_CTL_143_DATA
+	0x00000000, // DENALI_CTL_144_DATA
+	0x00000000, // DENALI_CTL_145_DATA
+	0x00000000, // DENALI_CTL_146_DATA
+	0x00000000, // DENALI_CTL_147_DATA
+	0x00000000, // DENALI_CTL_148_DATA
+	0x00000000, // DENALI_CTL_149_DATA
+	0x00000000, // DENALI_CTL_150_DATA
+	0x00000000, // DENALI_CTL_151_DATA
+	0x00000000, // DENALI_CTL_152_DATA
+	0x00000000, // DENALI_CTL_153_DATA
+	0x00000000, // DENALI_CTL_154_DATA
+	0x00000000, // DENALI_CTL_155_DATA
+	0x00000000, // DENALI_CTL_156_DATA
+	0x00000000, // DENALI_CTL_157_DATA
+	0x00000000, // DENALI_CTL_158_DATA
+	0x00000000, // DENALI_CTL_159_DATA
+	0x00000000, // DENALI_CTL_160_DATA
+	0x02010102, // DENALI_CTL_161_DATA
+	0x0108070d, // DENALI_CTL_162_DATA
+	0x05050300, // DENALI_CTL_163_DATA
+	0x04000503, // DENALI_CTL_164_DATA
+	0x00000000, // DENALI_CTL_165_DATA
+	0x00000000, // DENALI_CTL_166_DATA
+	0x00000000, // DENALI_CTL_167_DATA
+	0x00000000, // DENALI_CTL_168_DATA
+	0x280d0000, // DENALI_CTL_169_DATA
+	0x01000000, // DENALI_CTL_170_DATA
+	0x00000000, // DENALI_CTL_171_DATA
+	0x00030001, // DENALI_CTL_172_DATA
+	0x00000000, // DENALI_CTL_173_DATA
+	0x00000000, // DENALI_CTL_174_DATA
+	0x00000000, // DENALI_CTL_175_DATA
+	0x00000000, // DENALI_CTL_176_DATA
+	0x00000000, // DENALI_CTL_177_DATA
+	0x00000000, // DENALI_CTL_178_DATA
+	0x00000000, // DENALI_CTL_179_DATA
+	0x00000000, // DENALI_CTL_180_DATA
+	0x01000000, // DENALI_CTL_181_DATA
+	0x00000001, // DENALI_CTL_182_DATA
+	0x00000100, // DENALI_CTL_183_DATA
+	0x00010303, // DENALI_CTL_184_DATA
+	0x67676701, // DENALI_CTL_185_DATA
+	0x67676767, // DENALI_CTL_186_DATA
+	0x67676767, // DENALI_CTL_187_DATA
+	0x67676767, // DENALI_CTL_188_DATA
+	0x67676767, // DENALI_CTL_189_DATA
+	0x67676767, // DENALI_CTL_190_DATA
+	0x67676767, // DENALI_CTL_191_DATA
+	0x67676767, // DENALI_CTL_192_DATA
+	0x67676767, // DENALI_CTL_193_DATA
+	0x01000067, // DENALI_CTL_194_DATA
+	0x00000001, // DENALI_CTL_195_DATA
+	0x00000101, // DENALI_CTL_196_DATA
+	0x00000000, // DENALI_CTL_197_DATA
+	0x00000000, // DENALI_CTL_198_DATA
+	0x00000000, // DENALI_CTL_199_DATA
+	0x00000000, // DENALI_CTL_200_DATA
+	0x00000000, // DENALI_CTL_201_DATA
+	0x00000000, // DENALI_CTL_202_DATA
+	0x00000000, // DENALI_CTL_203_DATA
+	0x00000000, // DENALI_CTL_204_DATA
+	0x00000000, // DENALI_CTL_205_DATA
+	0x00000000, // DENALI_CTL_206_DATA
+	0x00000000, // DENALI_CTL_207_DATA
+	0x00000001, // DENALI_CTL_208_DATA
+	0x00000000, // DENALI_CTL_209_DATA
+	0x007fffff, // DENALI_CTL_210_DATA
+	0x00000000, // DENALI_CTL_211_DATA
+	0x007fffff, // DENALI_CTL_212_DATA
+	0x00000000, // DENALI_CTL_213_DATA
+	0x007fffff, // DENALI_CTL_214_DATA
+	0x00000000, // DENALI_CTL_215_DATA
+	0x007fffff, // DENALI_CTL_216_DATA
+	0x00000000, // DENALI_CTL_217_DATA
+	0x007fffff, // DENALI_CTL_218_DATA
+	0x00000000, // DENALI_CTL_219_DATA
+	0x007fffff, // DENALI_CTL_220_DATA
+	0x00000000, // DENALI_CTL_221_DATA
+	0x007fffff, // DENALI_CTL_222_DATA
+	0x00000000, // DENALI_CTL_223_DATA
+	0x037fffff, // DENALI_CTL_224_DATA
+	0xffffffff, // DENALI_CTL_225_DATA
+	0x000f000f, // DENALI_CTL_226_DATA
+	0x00ffff03, // DENALI_CTL_227_DATA
+	0x000fffff, // DENALI_CTL_228_DATA
+	0x0003000f, // DENALI_CTL_229_DATA
+	0xffffffff, // DENALI_CTL_230_DATA
+	0x000f000f, // DENALI_CTL_231_DATA
+	0x00ffff03, // DENALI_CTL_232_DATA
+	0x000fffff, // DENALI_CTL_233_DATA
+	0x0003000f, // DENALI_CTL_234_DATA
+	0xffffffff, // DENALI_CTL_235_DATA
+	0x000f000f, // DENALI_CTL_236_DATA
+	0x00ffff03, // DENALI_CTL_237_DATA
+	0x000fffff, // DENALI_CTL_238_DATA
+	0x0003000f, // DENALI_CTL_239_DATA
+	0xffffffff, // DENALI_CTL_240_DATA
+	0x000f000f, // DENALI_CTL_241_DATA
+	0x00ffff03, // DENALI_CTL_242_DATA
+	0x000fffff, // DENALI_CTL_243_DATA
+	0x6407000f, // DENALI_CTL_244_DATA
+	0x01640001, // DENALI_CTL_245_DATA
+	0x00000000, // DENALI_CTL_246_DATA
+	0x00000000, // DENALI_CTL_247_DATA
+	0x00001800, // DENALI_CTL_248_DATA
+	0x00386c05, // DENALI_CTL_249_DATA
+	0x02000200, // DENALI_CTL_250_DATA
+	0x02000200, // DENALI_CTL_251_DATA
+	0x0000386c, // DENALI_CTL_252_DATA
+	0x00023438, // DENALI_CTL_253_DATA
+	0x02020d0f, // DENALI_CTL_254_DATA
+	0x00140303, // DENALI_CTL_255_DATA
+	0x00000000, // DENALI_CTL_256_DATA
+	0x00000000, // DENALI_CTL_257_DATA
+	0x00001403, // DENALI_CTL_258_DATA
+	0x00000000, // DENALI_CTL_259_DATA
+	0x00000000, // DENALI_CTL_260_DATA
+	0x00000000, // DENALI_CTL_261_DATA
+	0x00000000, // DENALI_CTL_262_DATA
+	0x0c010000, // DENALI_CTL_263_DATA
+	0x00000008, // DENALI_CTL_264_DATA
+};
diff --git a/src/soc/sifive/fu740/gpio.c b/src/soc/sifive/fu740/gpio.c
new file mode 100644
index 0000000..167844d
--- /dev/null
+++ b/src/soc/sifive/fu740/gpio.c
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <console/console.h>
+#include <soc/addressmap.h>
+#include <soc/gpio.h>
+#include <stdint.h>
+#include <arch/mmio.h>
+#include <delay.h>
+#include <assert.h>
+#include <device/mmio.h>
+#include <gpio.h>
+
+#define SIFIVE_GPIO_INPUT_VAL  (FU740_GPIO + 0x00)
+#define SIFIVE_GPIO_INPUT_EN   (FU740_GPIO + 0x04)
+#define SIFIVE_GPIO_OUTPUT_EN  (FU740_GPIO + 0x08)
+#define SIFIVE_GPIO_OUTPUT_VAL (FU740_GPIO + 0x0C)
+#define SIFIVE_GPIO_PUE        (FU740_GPIO + 0x10)
+#define SIFIVE_GPIO_DS         (FU740_GPIO + 0x14)
+#define SIFIVE_GPIO_RISE_IE    (FU740_GPIO + 0x18)
+#define SIFIVE_GPIO_RISE_IP    (FU740_GPIO + 0x1C)
+#define SIFIVE_GPIO_FALL_IE    (FU740_GPIO + 0x20)
+#define SIFIVE_GPIO_FALL_IP    (FU740_GPIO + 0x24)
+#define SIFIVE_GPIO_HIGH_IE    (FU740_GPIO + 0x28)
+#define SIFIVE_GPIO_HIGH_IP    (FU740_GPIO + 0x2C)
+#define SIFIVE_GPIO_LOW_IE     (FU740_GPIO + 0x30)
+#define SIFIVE_GPIO_LOW_IP     (FU740_GPIO + 0x34)
+#define SIFIVE_GPIO_IOF_EN     (FU740_GPIO + 0x38)
+#define SIFIVE_GPIO_IOF_SEL    (FU740_GPIO + 0x3C)
+#define SIFIVE_GPIO_OUT_XOR    (FU740_GPIO + 0x40)
+
+void gpio_set(gpio_t gpio, int value)
+{
+	uint32_t output_val = read32((void *)SIFIVE_GPIO_OUTPUT_VAL);
+
+	if (value)
+		output_val |= (1 << gpio);
+	else
+		output_val &= ~(1 << gpio);
+
+	write32((void *)SIFIVE_GPIO_OUTPUT_VAL, output_val);
+}
+
+int gpio_get(gpio_t gpio)
+{
+	uint32_t input_val = read32((void *)SIFIVE_GPIO_INPUT_VAL);
+	return !!(input_val & (1 << gpio));
+}
+
+void gpio_set_direction(gpio_t gpio, enum gpio_direction gpio_dir)
+{
+	uint32_t input_en  = read32((void *)SIFIVE_GPIO_INPUT_EN);
+	uint32_t output_en = read32((void *)SIFIVE_GPIO_OUTPUT_EN);
+
+	if (gpio_dir == GPIO_OUTPUT) {
+		input_en  &= ~(1 << gpio);
+		output_en |=  (1 << gpio);
+	} else if (gpio_dir == GPIO_INPUT) {
+		input_en  |=  (1 << gpio);
+		output_en &= ~(1 << gpio);
+	}
+
+	write32((void *)SIFIVE_GPIO_INPUT_EN, input_en);
+	write32((void *)SIFIVE_GPIO_OUTPUT_EN, output_en);
+}
diff --git a/src/soc/sifive/fu740/include/soc/addressmap.h b/src/soc/sifive/fu740/include/soc/addressmap.h
new file mode 100644
index 0000000..e2aa731
--- /dev/null
+++ b/src/soc/sifive/fu740/include/soc/addressmap.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+// reference: fu740-c000 manual chapter 5: Memory Map
+// Table 15: (TODO: subject for common code: none of these changed compared to fu540)
+#define FU740_ROM        0x00001000
+#define FU740_DTIM       0x01000000
+#define FU740_CLINT      0x02000000
+#define FU740_L2LIM      0x08000000
+#define FU740_PRCI       0x10000000
+#define FU740_UART0      0x10010000
+#define FU740_UART1      0x10011000
+#define FU740_QSPI0      0x10040000
+#define FU740_QSPI1      0x10041000
+#define FU740_QSPI2      0x10050000 // in unmatched board schematics it's called SPI0
+#define FU740_GPIO       0x10060000
+#define FU740_OTP        0x10070000
+#define FU740_PINCTRL    0x10080000
+#define FU740_QSPI0FLASH 0x20000000
+#define FU740_QSPI1FLASH 0x30000000
+#define FU740_DRAM       0x80000000
+
+#define PCIE_MGMT   0x100D0000
+#define PCIE_CONFIG 0x000DF0000000
+#define PCIE_DBI    0x000E00000000
+
+#define FU740_I2C_0 0x10030000
+#define FU740_I2C_1 0x10031000
+
+// Reset Vector - 4
+#define FU740_ROM1 0x00001000
+// After reset vector it will jump directly to this address if ZSBL is used (ZSBL code)
+#define FU740_ROM2 0x00010000
+#define FU740_MSEL FU740_ROM // mode select is always at start of ROM
+
+// naming changed a bit between FU540 and FU740 manuals
+// Ethernet MAC -> Ethernet
+// Ethernet Management -> GEMGXL MGMT
+#define SIFIVE_ETHERNET_MAC  0x10090000
+#define SIFIVE_ETHERNET_MGMT 0x100A0000
+
+#define FU740_UART(i) (FU740_UART0 + 0x1000 * i)
diff --git a/src/soc/sifive/fu740/include/soc/clock.h b/src/soc/sifive/fu740/include/soc/clock.h
new file mode 100644
index 0000000..01cb1b3
--- /dev/null
+++ b/src/soc/sifive/fu740/include/soc/clock.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_SIFIVE_FU740_CLOCK_H__
+#define __SOC_SIFIVE_FU740_CLOCK_H__
+
+void clock_init(void);
+int clock_get_pclk(void);
+
+#endif /* __SOC_SIFIVE_FU740_CLOCK_H__ */
diff --git a/src/soc/sifive/fu740/include/soc/gpio.h b/src/soc/sifive/fu740/include/soc/gpio.h
new file mode 100644
index 0000000..b0466cc
--- /dev/null
+++ b/src/soc/sifive/fu740/include/soc/gpio.h
@@ -0,0 +1,36 @@
+#ifndef _SOC_SIFIVE_FU740_GPIO_H_
+#define _SOC_SIFIVE_FU740_GPIO_H_
+
+#include <stdint.h>
+
+//TODO these are mainboard specific
+enum gpio {
+	J29_1,
+	PMICINTB,
+	PMICSHDN,
+	J8_1,
+	J8_3,
+	PCIE_PWREN, // connected to power rails of PCIe connectors
+	THERM,
+	UBRDG_RSTN,
+	PCIE_PERSTN, // connected to PERST pin of PCIe connectors
+	ULPI_RSTN,
+	J8_2,
+	UHUB_RSTN,
+	GEMGXL_RST,
+	J8_4,
+	EN_VDD_SD,
+	SD_CD,
+};
+
+// this is to satisfy src/include/gpio.h
+typedef enum gpio gpio_t;
+
+enum gpio_direction {
+	GPIO_INPUT,
+	GPIO_OUTPUT,
+};
+
+void gpio_set_direction(gpio_t gpio, enum gpio_direction gpio_dir);
+
+#endif // _SOC_SIFIVE_FU740_GPIO_H_
diff --git a/src/soc/sifive/fu740/include/soc/otp.h b/src/soc/sifive/fu740/include/soc/otp.h
new file mode 100644
index 0000000..0405fda
--- /dev/null
+++ b/src/soc/sifive/fu740/include/soc/otp.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_SIFIVE_FU740_OTP_H__
+#define __SOC_SIFIVE_FU740_OTP_H__
+
+#include <stdint.h>
+
+u32 otp_read_word(u16 idx);
+u32 otp_read_serial(void);
+
+#endif /* __SOC_SIFIVE_FU740_OTP_H__ */
diff --git a/src/soc/sifive/fu740/include/soc/sdram.h b/src/soc/sifive/fu740/include/soc/sdram.h
new file mode 100644
index 0000000..8848d1a
--- /dev/null
+++ b/src/soc/sifive/fu740/include/soc/sdram.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef SIFIVE_COMMON_SDRAM_H
+#define SIFIVE_COMMON_SDRAM_H
+
+#include <stdint.h>
+#include <types.h>
+
+void sdram_init(size_t dram_size);
+size_t sdram_size(void);
+
+#endif
diff --git a/src/soc/sifive/fu740/include/soc/spi.h b/src/soc/sifive/fu740/include/soc/spi.h
new file mode 100644
index 0000000..5c41019
--- /dev/null
+++ b/src/soc/sifive/fu740/include/soc/spi.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_SIFIVE_FU740_SPI_H__
+#define __SOC_SIFIVE_FU740_SPI_H__
+
+#include <spi-generic.h>
+
+// Frame Format Register (fmt)
+
+#define FU740_SPI_PROTO_S	0 // Data Pins: MOSI MISO
+#define FU740_SPI_PROTO_D	1 // Data Pins: DQ0 DQ1
+#define FU740_SPI_PROTO_Q	2 // Data Pins: DQ0 DQ1 DQ2 DQ3
+
+#define FU740_SPI_ENDIAN_BIG	0 // send MSB first
+#define FU740_SPI_ENDIAN_LITTLE	1 // send LSB first
+
+// Serial Clock Mode Register (sckmode)
+
+#define FU740_SPI_PHA_LOW	0 // inactive state of SCK is logical 0
+#define FU740_SPI_PHA_HIGH	1 // inactive state of SCK is logical 1
+
+#define FU740_SPI_POL_LEADING	0 // data is sampled on leading edge of sck
+#define FU740_SPI_POL_TRAILING	1 // data is sampled on trailing edge of sck
+
+// ffmt register (SPI Flash Instruction Format Register)
+struct fu740_spi_ffmt_config {
+	unsigned int cmd_en;     // enable sending of command
+	unsigned int addr_len;   // number of address bytes (0-4)
+	unsigned int pad_cnt;    // number of dummy cycles
+	unsigned int cmd_proto;  // protocol for transmitting command
+	unsigned int addr_proto; // protocol for transmitting address and padding
+	unsigned int data_proto; // protocol for receiving data bytes
+	unsigned int cmd_code;   // value of command byte
+	unsigned int pad_code;   // first 8 bits to transmit during dummy cycles
+};
+
+struct fu740_spi_fmt_config {
+	unsigned int protocol;   // FU740_SPI_PROTO_S, FU740_SPI_PROTO_D, FU740_SPI_PROTO_Q
+	unsigned int endianness; // 0 = MSB, 1 = LSB
+	unsigned int io_dir;     // Rx, Tx
+	unsigned int bits_per_frame; // up to 8bits
+};
+
+struct fu740_spi_config {
+	unsigned int freq; // speed of spi interface
+	unsigned int pha;  // serial clock phase
+	unsigned int pol;  // serial clock polarity
+	struct fu740_spi_fmt_config fmt_config;   // frame format config
+	struct fu740_spi_ffmt_config ffmt_config; // flash instruction format
+};
+
+extern struct fu740_spi_config fu740_spi_configs[];
+
+int fu740_spi_setup(const struct spi_slave *slave);
+
+#endif /* __SOC_SIFIVE_FU740_SPI_H__ */
diff --git a/src/soc/sifive/fu740/memlayout.ld b/src/soc/sifive/fu740/memlayout.ld
new file mode 100644
index 0000000..85d2b40
--- /dev/null
+++ b/src/soc/sifive/fu740/memlayout.ld
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <memlayout.h>
+#include <soc/addressmap.h>
+
+#include <arch/header.ld>
+
+SECTIONS
+{
+	SRAM_START(FU740_L2LIM)
+	/* The 64K size is not allocated. It's just for basic size checking. */
+	BOOTBLOCK(FU740_L2LIM, 64K)
+	CAR_STACK(FU740_L2LIM + 64K, 12K) // considering each harts stack is a pagesize (4K), we can potentially have up to 16 harts regarding stack space //TODO reduce it, since fu740 doesn't even have/support 16 harts
+	PRERAM_CBMEM_CONSOLE(FU740_L2LIM + 76K, 8K)
+	CBFS_MCACHE(FU740_L2LIM + 84K, 8K)
+	FMAP_CACHE(FU740_L2LIM + 92K, 2K)
+	PRERAM_CBFS_CACHE(FU740_L2LIM + 94K, 128K)
+	SRAM_END(FU740_L2LIM + 2M)
+
+	DRAM_START(FU740_DRAM)
+	OPENSBI(FU740_DRAM, 256K)
+	/* The 256K size is not allocated. It's just for basic size checking. */
+	RAMSTAGE(FU740_DRAM + 256K, 256K)
+	MEM_STACK(FU740_DRAM + 512K, 20K)
+	POSTRAM_CBFS_CACHE(FU740_DRAM + 532K, 32M - 532K)
+}
diff --git a/src/soc/sifive/fu740/otp.c b/src/soc/sifive/fu740/otp.c
new file mode 100644
index 0000000..e00086a
--- /dev/null
+++ b/src/soc/sifive/fu740/otp.c
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <delay.h>
+#include <device/mmio.h>
+#include <console/console.h>
+#include <console/uart.h>
+#include <soc/addressmap.h>
+#include <soc/otp.h>
+
+/*
+ * This is a driver for the eMemory EG004K32TQ028XW01 NeoFuse
+ * One-Time-Programmable (OTP) memory used within the SiFive FU740.
+ * It is documented in the FU740 manual here:
+ * https://www.sifive.com/documentation/chips/freedom-u740-c000-manual/
+ */
+
+struct sifive_otp_registers {
+	u32 pa;     /* Address input */
+	u32 paio;   /* Program address input */
+	u32 pas;    /* Program redundancy cell selection input */
+	u32 pce;    /* OTP Macro enable input */
+	u32 pclk;   /* Clock input */
+	u32 pdin;   /* Write data input */
+	u32 pdout;  /* Read data output */
+	u32 pdstb;  /* Deep standby mode enable input (active low) */
+	u32 pprog;  /* Program mode enable input */
+	u32 ptc;    /* Test column enable input */
+	u32 ptm;    /* Test mode enable input */
+	u32 ptm_rep;/* Repair function test mode enable input */
+	u32 ptr;    /* Test row enable input */
+	u32 ptrim;  /* Repair function enable input */
+	u32 pwe;    /* Write enable input (defines program cycle) */
+} __packed;
+
+/*
+ * Read a 32 bit value addressed by its index from the OTP.
+ * The FU740 stores 4096x32 bit (16KiB) values.
+ * Index 0x00-0xff are reserved for SiFive internal use. (first 1KiB)
+ */
+
+u32 otp_read_word(u16 idx)
+{
+	u32 w;
+
+	if (idx >= 0x1000)
+		die("otp: idx out of bounds");
+
+	struct sifive_otp_registers *regs = (void *)(FU740_OTP);
+
+	// wake up from stand-by
+	write32(&regs->pdstb, 0x01);
+
+	// enable repair function
+	write32(&regs->ptrim, 0x01);
+
+	// enable input
+	write32(&regs->pce, 0x01);
+
+	// address to read
+	write32(&regs->pa, idx);
+
+	// cycle clock to read
+	write32(&regs->pclk, 0x01);
+	mdelay(1);
+
+	write32(&regs->pclk, 0x00);
+	mdelay(1);
+
+	w = read32(&regs->pdout);
+
+	// shut down
+	write32(&regs->pce, 0x00);
+	write32(&regs->ptrim, 0x00);
+	write32(&regs->pdstb, 0x00);
+
+	return w;
+}
+
+u32 otp_read_serial(void)
+{
+	u32 serial = 0;
+	u32 serial_n = 0;
+	for (int i = 0xfe; i > 0; i -= 2) {
+		serial = otp_read_word(i);
+		serial_n = otp_read_word(i+1);
+		if (serial == ~serial_n)
+			break;
+	}
+	return serial;
+}
diff --git a/src/soc/sifive/fu740/sdram.c b/src/soc/sifive/fu740/sdram.c
new file mode 100644
index 0000000..167d5a4
--- /dev/null
+++ b/src/soc/sifive/fu740/sdram.c
@@ -0,0 +1,246 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* See the file LICENSE for further information */
+
+#ifndef _SIFIVE_SDRAM_H
+#define _SIFIVE_SDRAM_H
+
+#include <arch/mmio.h>
+#include <console/console.h>
+#include <device/mmio.h>
+#include <soc/addressmap.h>
+#include <soc/sdram.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#define DRAM_CLASS_OFFSET                 8
+#define DRAM_CLASS_DDR4                   0xA
+#define OPTIMAL_RMODW_EN_OFFSET           0
+#define DISABLE_RD_INTERLEAVE_OFFSET      16
+#define OUT_OF_RANGE_FLAG                 (1 << 1)
+#define MULTIPLE_OUT_OF_RANGE_FLAG        (1 << 2)
+#define PORT_COMMAND_CHANNEL_ERROR_FLAG   (1 << 7)
+#define MC_INIT_COMPLETE_FLAG             (1 << 8) // Memory Controller init complete
+#define LEVELING_OPERATION_COMPLETED_FLAG (1 << 22)
+#define DFI_PHY_WRLELV_MODE_OFFSET        24
+#define DFI_PHY_RDLVL_MODE_OFFSET         24
+#define DFI_PHY_RDLVL_GATE_MODE_OFFSET    0
+#define VREF_EN_OFFSET                    24
+#define PORT_ADDR_PROTECTION_EN_OFFSET    0
+#define AXI0_ADDRESS_RANGE_ENABLE_OFFSET  8
+#define AXI0_RANGE_PROT_BITS_0_OFFSET     24
+#define RDLVL_EN_OFFSET                   16
+#define RDLVL_GATE_EN_OFFSET              24
+#define WRLVL_EN_OFFSET                   0
+
+#define PHY_RX_CAL_DQ0_0_OFFSET           0
+#define PHY_RX_CAL_DQ1_0_OFFSET           16
+
+// reference:  fu740-c000 manual chapter 32: DDR Subsystem
+// Cahpter 32.2: Memory Map
+#define FU740_DDRCTRL         0x100b0000
+#define FU740_DDRPHY          0x100b2000
+#define FU740_PHYSICAL_FILTER 0x100b8000  // formerly called DDRBUSBLOCKER (FU540)
+#define FU740_DDRMGMT         0x100c0000
+
+static void phy_reset(u32 *ddrphyreg, const u32 *physettings)
+{
+	for (int i = 1152; i <= 1214; i++)
+		write32(&ddrphyreg[i], physettings[i]);
+
+	for (int i = 0; i <= 1151; i++)
+		write32(&ddrphyreg[i], physettings[i]);
+}
+
+static void ux00ddr_writeregmap(u32 *ahbregaddr, const u32 *ctlsettings, const u32 *physettings)
+{
+	u32 *ddrctlreg = (u32 *) ahbregaddr;
+	u32 *ddrphyreg = ((u32 *) ahbregaddr) + (0x2000 / sizeof(u32)); //TODO use FU740_DDRPHY instead
+
+	for (int i = 0; i <= 264; i++)
+		write32((void *)&ddrctlreg[i], ctlsettings[i]);
+
+	phy_reset(ddrphyreg, physettings);
+}
+
+static void ux00ddr_start(u32 *ahbregaddr, u64 *filteraddr, uint64_t ddrend)
+{
+	// start calibration and training operation
+	setbits32(ahbregaddr, 0x1);
+
+	// wait for memory initialization complete
+	// bit 8 of INT_STATUS (DENALI_CTL_132) 0x210
+	while (!(read32(&ahbregaddr[132]) & MC_INIT_COMPLETE_FLAG))
+		;
+
+	// Disable the BusBlocker in front of the controller AXI slave ports
+	write64(filteraddr, 0x0f00000000000000UL | (ddrend >> 2));
+//                             ^ RWX + TOR
+}
+
+static void ux00ddr_mask_mc_init_complete_interrupt(u32 *ahbregaddr)
+{
+	// Mask off Bit 8 of Interrupt Status
+	// Bit [8] The MC initialization has been completed
+	setbits32(&ahbregaddr[136], MC_INIT_COMPLETE_FLAG);
+}
+
+static void ux00ddr_mask_outofrange_interrupts(u32 *ahbregaddr)
+{
+	// Mask off Bit 8, Bit 2 and Bit 1 of Interrupt Status
+	// Bit [2] Multiple accesses outside the defined PHYSICAL memory space have occurred
+	// Bit [1] A memory access outside the defined PHYSICAL memory space has occurred
+	setbits32(&ahbregaddr[136], OUT_OF_RANGE_FLAG | MULTIPLE_OUT_OF_RANGE_FLAG);
+}
+
+static void ux00ddr_mask_port_command_error_interrupt(u32 *ahbregaddr)
+{
+	// Mask off Bit 7 of Interrupt Status
+	// Bit [7] An error occurred on the port command channel
+	setbits32(&ahbregaddr[136], PORT_COMMAND_CHANNEL_ERROR_FLAG);
+}
+
+static void ux00ddr_mask_leveling_completed_interrupt(u32 *ahbregaddr)
+{
+	// Mask off Bit 22 of Interrupt Status
+	// Bit [22] The leveling operation has completed
+	setbits32(&ahbregaddr[136], LEVELING_OPERATION_COMPLETED_FLAG);
+}
+
+static void ux00ddr_setuprangeprotection(u32 *ahbregaddr, size_t size)
+{
+	write32(&ahbregaddr[209], 0x0);
+	u32 size_16Kblocks = ((size >> 14) & 0x7FFFFF) - 1;
+	write32(&ahbregaddr[210], size_16Kblocks);
+	write32(&ahbregaddr[212], 0x0);
+	write32(&ahbregaddr[214], 0x0);
+	write32(&ahbregaddr[216], 0x0);
+	setbits32(&ahbregaddr[224], (0x3  <<  AXI0_RANGE_PROT_BITS_0_OFFSET));
+	write32(&ahbregaddr[225], 0xFFFFFFFF);
+	setbits32(&ahbregaddr[208], (1  <<  AXI0_ADDRESS_RANGE_ENABLE_OFFSET));
+	setbits32(&ahbregaddr[208], (1  <<  PORT_ADDR_PROTECTION_EN_OFFSET));
+}
+
+static void ux00ddr_disableaxireadinterleave(u32 *ahbregaddr)
+{
+	setbits32(&ahbregaddr[120], (1 << DISABLE_RD_INTERLEAVE_OFFSET));
+}
+
+static void ux00ddr_disableoptimalrmodw(u32 *ahbregaddr)
+{
+	clrbits32(&ahbregaddr[21], (1 << OPTIMAL_RMODW_EN_OFFSET));
+}
+
+static void ux00ddr_enablewriteleveling(u32 *ahbregaddr)
+{
+	setbits32(&ahbregaddr[170], (1 << WRLVL_EN_OFFSET) | (1 << DFI_PHY_WRLELV_MODE_OFFSET));
+}
+
+static void ux00ddr_enablereadleveling(u32 *ahbregaddr)
+{
+	setbits32(&ahbregaddr[181], (1 << DFI_PHY_RDLVL_MODE_OFFSET));
+	setbits32(&ahbregaddr[260], (1 << RDLVL_EN_OFFSET));
+}
+
+static void ux00ddr_enablereadlevelinggate(u32 *ahbregaddr)
+{
+	setbits32(&ahbregaddr[260], (1 << RDLVL_GATE_EN_OFFSET));
+	setbits32(&ahbregaddr[182], (1 << DFI_PHY_RDLVL_GATE_MODE_OFFSET));
+}
+
+static void ux00ddr_enablevreftraining(u32 *ahbregaddr)
+{
+	setbits32(&ahbregaddr[184], (1 << VREF_EN_OFFSET));
+}
+
+static u32 ux00ddr_getdramclass(u32 *ahbregaddr)
+{
+	return ((read32(ahbregaddr) >> DRAM_CLASS_OFFSET) & 0xF);
+}
+
+static void ux00ddr_phy_fixup(void *ahbregaddr)
+{
+	void *ddrphyreg = ahbregaddr + 0x2000;
+
+	// bitmask of failed lanes
+	uint64_t fails = 0;
+	u32 slicebase = 0;
+	u32 dq = 0;
+
+	// check errata condition
+	for (u32 slice = 0; slice < 8; slice++) {
+		u32 regbase = slicebase + 34;
+		for (u32 reg = 0 ; reg < 4; reg++) {
+			u32 updownreg = read32(ddrphyreg + ((regbase+reg) << 2));
+			for (u32 bit = 0; bit < 2; bit++) {
+				u32 phy_rx_cal_dqn_0_offset;
+
+				if (bit == 0)
+					phy_rx_cal_dqn_0_offset = PHY_RX_CAL_DQ0_0_OFFSET;
+				else
+					phy_rx_cal_dqn_0_offset = PHY_RX_CAL_DQ1_0_OFFSET;
+
+				u32 down = (updownreg >>  phy_rx_cal_dqn_0_offset)      & 0x3F;
+				u32 up =   (updownreg >> (phy_rx_cal_dqn_0_offset + 6)) & 0x3F;
+
+				uint8_t failc0 = ((down == 0) && (up == 0x3F));
+				uint8_t failc1 = ((up == 0) && (down == 0x3F));
+
+				// print error message on failure
+				if (failc0 || failc1) {
+					fails |= (1 << dq);
+
+					char slicelsc = '0';
+					char slicemsc = '0';
+					slicelsc += (dq % 10);
+					slicemsc += (dq / 10);
+					printk(BIOS_ERR, "S %c%c%c\n", slicelsc, slicemsc, failc0 ? 'U' : 'D');
+				}
+				dq++;
+			}
+		}
+		slicebase += 128;
+	}
+	if (fails)
+		printk(BIOS_ERR, "DDR error in fixing up: %llx\n", fails);
+}
+
+extern const u32 denali_ddr_phy_data[1215];
+extern const u32 denali_ddr_ctl_data[265];
+
+void sdram_init(size_t dram_size)
+{
+	u32 *ddrctrl = (u32 *)FU740_DDRCTRL;
+	u64 *ddr_physical_filter = (u64 *)FU740_PHYSICAL_FILTER;
+	ux00ddr_writeregmap(ddrctrl, denali_ddr_ctl_data, denali_ddr_phy_data);
+	ux00ddr_disableaxireadinterleave(ddrctrl);
+
+	ux00ddr_disableoptimalrmodw(ddrctrl);
+
+	ux00ddr_enablewriteleveling(ddrctrl);
+	ux00ddr_enablereadleveling(ddrctrl);
+	ux00ddr_enablereadlevelinggate(ddrctrl);
+	if (ux00ddr_getdramclass(ddrctrl) == DRAM_CLASS_DDR4)
+		ux00ddr_enablevreftraining(ddrctrl);
+
+	// mask off interrupts for leveling completion
+	ux00ddr_mask_leveling_completed_interrupt(ddrctrl);
+
+	ux00ddr_mask_mc_init_complete_interrupt(ddrctrl);
+	ux00ddr_mask_outofrange_interrupts(ddrctrl);
+	ux00ddr_setuprangeprotection(ddrctrl, dram_size);
+	ux00ddr_mask_port_command_error_interrupt(ddrctrl);
+
+	ux00ddr_start(ddrctrl, ddr_physical_filter, FU740_DRAM + dram_size);
+
+	ux00ddr_phy_fixup(ddrctrl);
+}
+
+// sdram_init MUST be called before sdram_size
+size_t sdram_size(void)
+{
+	u64 devicepmp0 = read64((u64 *)FU740_PHYSICAL_FILTER);
+	return ((devicepmp0 & 0xFFFFFFFFFFFFFF) << 2) - FU740_DRAM;
+}
+
+#endif
diff --git a/src/soc/sifive/fu740/spi.c b/src/soc/sifive/fu740/spi.c
new file mode 100644
index 0000000..908e6ca
--- /dev/null
+++ b/src/soc/sifive/fu740/spi.c
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+//TODO needs work
+
+#include <device/mmio.h>
+#include <soc/spi.h>
+#include <soc/clock.h>
+#include <soc/addressmap.h>
+#include <delay.h>
+#include <lib.h>
+
+#include "spi_internal.h"
+
+static struct fu740_spi_ctrl *fu740_spi_ctrls[] = {
+	(struct fu740_spi_ctrl *)FU740_QSPI0,
+	(struct fu740_spi_ctrl *)FU740_QSPI1,
+	(struct fu740_spi_ctrl *)FU740_QSPI2
+};
+
+// Wait until SPI is ready for transmission and transmit byte.
+static void fu740_spi_tx(volatile struct fu740_spi_ctrl *spictrl_reg, uint8_t in)
+{
+#if __riscv_atomic
+	int32_t r;
+	do {
+		asm volatile (
+			"amoor.w %0, %2, %1\n"
+			: "=r" (r), "+A" (spictrl_reg->txdata.raw_bits)
+			: "r" (in)
+		);
+	} while (r < 0);
+#else
+	while ((int32_t) spictrl_reg->txdata.raw_bits < 0)
+		;
+	spictrl_reg->txdata.data = in;
+#endif
+}
+
+// Wait until SPI receive queue has data and read byte.
+static uint8_t fu740_spi_rx(volatile struct fu740_spi_ctrl *spictrl_reg)
+{
+	int32_t out;
+	while ((out = (int32_t) spictrl_reg->rxdata.raw_bits) < 0)
+		;
+	return (uint8_t) out;
+}
+
+static int fu740_spi_xfer(const struct spi_slave *slave,
+			  const void *dout, size_t bytesout,
+			  void *din, size_t bytesin)
+{
+	printk(BIOS_DEBUG, "%s 0, bytesin: %zu, bytesout: %zu, din: %p\n", __func__, bytesin, bytesout, din);
+	hexdump(dout, bytesout);
+	struct fu740_spi_ctrl *spictrl_reg = fu740_spi_ctrls[slave->bus];
+	union fu740_spi_reg_fmt fmt;
+	fmt.raw_bits = read32(&spictrl_reg->fmt.raw_bits);
+	if (fmt.proto == FU740_SPI_PROTO_S) {
+		// working in full-duplex mode
+		// receiving data needs to be triggered by sending data
+		while (bytesout || bytesin) {
+			uint8_t in, out = 0;
+			if (bytesout) {
+				out = *(uint8_t *)dout++;
+				bytesout--;
+			}
+			fu740_spi_tx(spictrl_reg, out);
+			in = fu740_spi_rx(spictrl_reg);
+			if (bytesin) {
+				*(uint8_t *)din++ = in;
+				bytesin--;
+			}
+		}
+	} else {
+		// Working in half duplex
+		// send and receive can be done separately
+		if (dout && din)
+			return -1;
+
+		if (dout) {
+			while (bytesout) {
+				fu740_spi_tx(spictrl_reg, *(uint8_t *)dout++);
+				bytesout--;
+			}
+		}
+
+		if (din) {
+			while (bytesin) {
+				*(uint8_t *)din++ = fu740_spi_rx(spictrl_reg);
+				bytesin--;
+			}
+		}
+	}
+	return 0;
+}
+
+static int fu740_spi_claim_bus(const struct spi_slave *slave)
+{
+	struct fu740_spi_ctrl *spictrl = fu740_spi_ctrls[slave->bus];
+	union fu740_spi_reg_csmode csmode;
+	csmode.raw_bits = 0;
+	csmode.mode = FU740_SPI_CSMODE_HOLD;
+	write32(&spictrl->csmode.raw_bits, csmode.raw_bits);
+	return 0;
+}
+
+static void fu740_spi_release_bus(const struct spi_slave *slave)
+{
+	struct fu740_spi_ctrl *spictrl = fu740_spi_ctrls[slave->bus];
+	union fu740_spi_reg_csmode csmode;
+	csmode.raw_bits = 0;
+	csmode.mode = FU740_SPI_CSMODE_OFF;
+	write32(&spictrl->csmode.raw_bits, csmode.raw_bits);
+}
+
+// reset spi flash chip
+static void fu740_spi_reset(volatile struct fu740_spi_ctrl *spictrl_reg)
+{
+	fu740_spi_tx(spictrl_reg, 0x66);
+	fu740_spi_tx(spictrl_reg, 0x99);
+}
+
+// setup the ffmt (SPI flash instruction format) register
+__maybe_unused static int fu740_spi_setup_ffmt(volatile struct fu740_spi_ctrl *spictrl_reg,
+			 const struct fu740_spi_config *config)
+{
+	//union fu740_spi_reg_fctrl fctrl;
+	union fu740_spi_reg_ffmt ffmt;
+
+	printk(BIOS_DEBUG, "config->data_proto: %d, config->cmd_code: %d\n",
+			config->ffmt_config.data_proto,
+			config->ffmt_config.cmd_code);
+
+	//TODO test without this here
+	fu740_spi_reset(spictrl_reg);
+
+	ffmt.raw_bits   = 0;
+	ffmt.cmd_en     = 1; // enable sending of command
+	ffmt.addr_len   = 3; // number of address bytes (0-4)
+	ffmt.pad_cnt    = 0; // number of dummy cycles TODO maybe not working
+	ffmt.cmd_proto  = FU740_SPI_PROTO_S; // protocol for transmitting command
+	ffmt.addr_proto = FU740_SPI_PROTO_S; // protocol for transmitting address and padding
+	ffmt.data_proto = config->ffmt_config.data_proto; // protocol for receiving data bytes
+	ffmt.cmd_code   = config->ffmt_config.cmd_code;   // value of command byte
+	ffmt.pad_code   = 0; // First 8 bits to transmit during dummy cycles
+	write32(&spictrl_reg->ffmt.raw_bits, ffmt.raw_bits);
+
+	return 0;
+}
+
+int fu740_spi_setup(const struct spi_slave *slave)
+{
+	union fu740_spi_reg_csmode csmode;
+	union fu740_spi_reg_fctrl fctrl;
+
+	struct fu740_spi_ctrl *spictrl_reg = fu740_spi_ctrls[slave->bus];
+	struct fu740_spi_config *config = &fu740_spi_configs[slave->bus];
+
+	if ((config->pha > 1)
+		|| (config->pol > 1)
+		|| (config->fmt_config.protocol > 2)
+		|| (config->fmt_config.endianness > 1)
+		|| (config->fmt_config.bits_per_frame > 8))
+		return -1;
+
+	write32(&spictrl_reg->sckdiv, fu740_spi_min_clk_divisor(clock_get_pclk(), config->freq));
+
+	/* disable direct memory-mapped spi flash mode */
+	//TODO test if we need to disable it before changing the settings
+	fctrl.raw_bits = 0;
+	fctrl.en = 0;
+	write32(&spictrl_reg->fctrl.raw_bits, fctrl.raw_bits);
+
+	csmode.raw_bits = 0;
+	csmode.mode = FU740_SPI_CSMODE_HOLD;
+	write32(&spictrl_reg->csmode.raw_bits, csmode.raw_bits);
+	char din[10];
+	char dout[10] = { 0x66 };
+	slave->ctrlr->xfer(slave, dout, 1, din, 0);
+	dout[0] = 0x99;
+	slave->ctrlr->xfer(slave, dout, 1, din, 0);
+	int addr = 0x200;
+	dout[0] = 0x03;
+	dout[1] = (addr >> 16) & 0xFF;
+	dout[2] = (addr >> 8) & 0xFF;
+	dout[3] = addr & 0xFF;
+	slave->ctrlr->xfer(slave, dout, 4, din, 10);
+	csmode.mode = FU740_SPI_CSMODE_AUTO;
+	write32(&spictrl_reg->csmode.raw_bits, csmode.raw_bits);
+	din[9] = 0;
+	return 0;
+}
+
+struct spi_ctrlr fu740_spi_ctrlr = {
+	.xfer  = fu740_spi_xfer,
+	.setup = fu740_spi_setup,
+	.claim_bus = fu740_spi_claim_bus,
+	.release_bus = fu740_spi_release_bus,
+	.max_xfer_size = SPI_CTRLR_DEFAULT_MAX_XFER_SIZE,
+};
+
+const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
+	{
+		.bus_start = 0,
+		.bus_end = 2,
+		.ctrlr = &fu740_spi_ctrlr,
+	}
+};
+
+const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);
diff --git a/src/soc/sifive/fu740/spi_internal.h b/src/soc/sifive/fu740/spi_internal.h
new file mode 100644
index 0000000..461ec6e
--- /dev/null
+++ b/src/soc/sifive/fu740/spi_internal.h
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __SOC_SIFIVE_HIFIVE_U_SPI_INTERNAL_H__
+#define __SOC_SIFIVE_HIFIVE_U_SPI_INTERNAL_H__
+
+#include <stdint.h>
+
+#define _ASSERT_SIZEOF(type, size) _Static_assert( \
+		sizeof(type) == (size), \
+		#type " must be " #size " bytes wide")
+
+// Chip Select Mode Register (csmode)
+
+#define FU740_SPI_CSMODE_AUTO 0
+#define FU740_SPI_CSMODE_HOLD 2
+#define FU740_SPI_CSMODE_OFF  3
+
+union fu740_spi_reg_sckmode {
+	struct {
+		uint32_t pha : 1;
+		uint32_t pol : 1;
+		uint32_t reserved : 30;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_sckmode, 4);
+
+union fu740_spi_reg_csmode {
+	struct {
+		uint32_t mode : 2;
+		uint32_t reserved : 30;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_csmode, 4);
+
+union fu740_spi_reg_delay0 {
+	struct {
+		uint32_t cssck : 8;
+		uint32_t reserved0 : 8;
+		uint32_t sckcs : 8;
+		uint32_t reserved1 : 8;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_delay0, 4);
+
+union fu740_spi_reg_delay1 {
+	struct {
+		uint32_t intercs : 8;
+		uint32_t reserved0 : 8;
+		uint32_t interxfr : 8;
+		uint32_t reserved1 : 8;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_delay1, 4);
+
+union fu740_spi_reg_fmt {
+	struct {
+		uint32_t proto : 2;
+		uint32_t endian : 1;
+		uint32_t dir : 1;
+		uint32_t reserved0 : 12;
+		uint32_t len : 4;
+		uint32_t reserved1 : 12;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_fmt, 4);
+
+union fu740_spi_reg_txdata {
+	struct {
+		uint32_t data : 8;
+		uint32_t reserved : 23;
+		uint32_t full : 1;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_txdata, 4);
+
+union fu740_spi_reg_rxdata {
+	struct {
+		uint32_t data : 8;
+		uint32_t reserved : 23;
+		uint32_t empty : 1;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_rxdata, 4);
+
+union fu740_spi_reg_txmark {
+	struct {
+		uint32_t txmark : 3;
+		uint32_t reserved : 29;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_txmark, 4);
+
+union fu740_spi_reg_rxmark {
+	struct {
+		uint32_t rxmark : 3;
+		uint32_t reserved : 29;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_rxmark, 4);
+
+union fu740_spi_reg_fctrl {
+	struct {
+		uint32_t en : 1;
+		uint32_t reserved : 31;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_fctrl, 4);
+
+union fu740_spi_reg_ffmt {
+	struct {
+		uint32_t cmd_en : 1;
+		uint32_t addr_len : 3;
+		uint32_t pad_cnt : 4;
+		uint32_t cmd_proto : 2;
+		uint32_t addr_proto : 2;
+		uint32_t data_proto : 2;
+		uint32_t reserved : 2;
+		uint32_t cmd_code : 8;
+		uint32_t pad_code : 8;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_ffmt, 4);
+
+union fu740_spi_reg_ie {
+	struct {
+		uint32_t txwm : 1;
+		uint32_t rxwm : 1;
+		uint32_t reserved : 30;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_ie, 4);
+
+union fu740_spi_reg_ip {
+	struct {
+		uint32_t txwm : 1;
+		uint32_t rxwm : 1;
+		uint32_t reserved : 30;
+	};
+	uint32_t raw_bits;
+};
+_ASSERT_SIZEOF(union fu740_spi_reg_ip, 4);
+
+#undef _ASSERT_SIZEOF
+
+/**
+ * SPI control register memory map.
+ *
+ * All functions take a pointer to a SPI device's control registers.
+ */
+struct fu740_spi_ctrl {
+	uint32_t sckdiv;
+	union fu740_spi_reg_sckmode sckmode;
+	uint32_t reserved08;
+	uint32_t reserved0c;
+
+	uint32_t csid;
+	uint32_t csdef;
+	union fu740_spi_reg_csmode csmode;
+	uint32_t reserved1c;
+
+	uint32_t reserved20;
+	uint32_t reserved24;
+	union fu740_spi_reg_delay0 delay0;
+	union fu740_spi_reg_delay1 delay1;
+
+	uint32_t reserved30;
+	uint32_t reserved34;
+	uint32_t reserved38;
+	uint32_t reserved3c;
+
+	union fu740_spi_reg_fmt fmt;
+	uint32_t reserved44;
+	union fu740_spi_reg_txdata txdata;
+	union fu740_spi_reg_rxdata rxdata;
+
+	union fu740_spi_reg_txmark txmark;
+	union fu740_spi_reg_rxmark rxmark;
+	uint32_t reserved58;
+	uint32_t reserved5c;
+
+	union fu740_spi_reg_fctrl fctrl;
+	union fu740_spi_reg_ffmt ffmt;
+	uint32_t reserved68;
+	uint32_t reserved6c;
+
+	union fu740_spi_reg_ie ie;
+	union fu740_spi_reg_ip ip;
+};
+
+/**
+ * Get smallest clock divisor that divides input_khz to a quotient less than or
+ * equal to max_target_khz;
+ */
+static inline unsigned int
+fu740_spi_min_clk_divisor(unsigned int input_khz, unsigned int max_target_khz)
+{
+	// f_sck = f_in / (2 * (div + 1)) => div = (f_in / (2*f_sck)) - 1
+	//
+	// The nearest integer solution for div requires rounding up as to not
+	// exceed max_target_khz.
+	//
+	// div = ceil(f_in / (2*f_sck)) - 1
+	//     = floor((f_in - 1 + 2*f_sck) / (2*f_sck)) - 1
+	//
+	// This should not overflow as long as (f_in - 1 + 2*f_sck) does not
+	// exceed 2^32 - 1, which is unlikely since we represent frequencies
+	// in kHz.
+	unsigned int quotient =
+		(input_khz + 2 * max_target_khz - 1) / (2 * max_target_khz);
+	// Avoid underflow
+	if (quotient == 0)
+		return 0;
+	return quotient - 1;
+}
+
+#endif /* __SOC_SIFIVE_HIFIVE_U_SPI_INTERNAL_H__ */
diff --git a/src/soc/sifive/fu740/uart.c b/src/soc/sifive/fu740/uart.c
new file mode 100644
index 0000000..94a6d2d
--- /dev/null
+++ b/src/soc/sifive/fu740/uart.c
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <stdint.h>
+#include <console/uart.h>
+#include <commonlib/bsd/helpers.h>
+#include <soc/addressmap.h>
+#include <soc/clock.h>
+
+uintptr_t uart_platform_base(unsigned int idx)
+{
+	if (idx < 2)
+		return FU740_UART(idx);
+	else
+		return 0;
+}
+
+unsigned int uart_platform_refclk(void)
+{
+	// peripheral clock is attached to UART subsystem
+	return clock_get_pclk();
+}