All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/1] Add support for the Purism Librem5 Phone
@ 2022-01-07 16:34 Angus Ainslie
  2022-01-07 16:34 ` [PATCH 1/1] board: purism: librem5: add the Librem5 phone files Angus Ainslie
  0 siblings, 1 reply; 2+ messages in thread
From: Angus Ainslie @ 2022-01-07 16:34 UTC (permalink / raw)
  To: kernel
  Cc: Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Andre Przywara, Neil Armstrong, Jagan Teki, Peter Robinson,
	Tim Harvey, Christian Hewitt, Lokesh Vutla, Peng Fan,
	Teresa Remmet, Heiko Schocher, Marcel Ziswiler, Ilko Iliev,
	u-boot, Angus Ainslie

This is all of the code required to boot the Librem5 Phone. I wasn't sure
if a single large patch including all of the code would be better or
multiple patches, here it is all at once.

It can boot the phone in uuu mode or directly from the eMMC

Angus Ainslie (1):
  board: purism: librem5: add the Librem5 phone files

 MAINTAINERS                                  |    8 +
 arch/arm/dts/Makefile                        |    3 +-
 arch/arm/dts/imx8mq-librem5-u-boot.dtsi      |  134 ++
 arch/arm/dts/imx8mq-librem5.dts              |  593 ++++++++
 arch/arm/mach-imx/imx8m/Kconfig              |    9 +
 board/purism/librem5/Kconfig                 |   15 +
 board/purism/librem5/MAINTAINERS             |    7 +
 board/purism/librem5/Makefile                |   13 +
 board/purism/librem5/imximage-8mq-lpddr4.cfg |    9 +
 board/purism/librem5/librem5.c               |  710 ++++++++++
 board/purism/librem5/librem5.h               |  176 +++
 board/purism/librem5/lpddr4_timing.c         | 1324 ++++++++++++++++++
 board/purism/librem5/lpddr4_timing_b0.c      | 1191 ++++++++++++++++
 board/purism/librem5/spl.c                   |  481 +++++++
 configs/librem5_defconfig                    |  120 ++
 doc/board/purism/librem5/librem5.rst         |   60 +
 include/configs/librem5.h                    |  173 +++
 17 files changed, 5025 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/dts/imx8mq-librem5-u-boot.dtsi
 create mode 100644 arch/arm/dts/imx8mq-librem5.dts
 create mode 100644 board/purism/librem5/Kconfig
 create mode 100644 board/purism/librem5/MAINTAINERS
 create mode 100644 board/purism/librem5/Makefile
 create mode 100644 board/purism/librem5/imximage-8mq-lpddr4.cfg
 create mode 100644 board/purism/librem5/librem5.c
 create mode 100644 board/purism/librem5/librem5.h
 create mode 100644 board/purism/librem5/lpddr4_timing.c
 create mode 100644 board/purism/librem5/lpddr4_timing_b0.c
 create mode 100644 board/purism/librem5/spl.c
 create mode 100644 configs/librem5_defconfig
 create mode 100644 doc/board/purism/librem5/librem5.rst
 create mode 100644 include/configs/librem5.h

-- 
2.25.1


^ permalink raw reply	[flat|nested] 2+ messages in thread

* [PATCH 1/1] board: purism: librem5: add the Librem5 phone files
  2022-01-07 16:34 [PATCH 0/1] Add support for the Purism Librem5 Phone Angus Ainslie
@ 2022-01-07 16:34 ` Angus Ainslie
  0 siblings, 0 replies; 2+ messages in thread
From: Angus Ainslie @ 2022-01-07 16:34 UTC (permalink / raw)
  To: kernel
  Cc: Stefano Babic, Fabio Estevam, NXP i.MX U-Boot Team,
	Andre Przywara, Neil Armstrong, Jagan Teki, Peter Robinson,
	Tim Harvey, Christian Hewitt, Lokesh Vutla, Peng Fan,
	Teresa Remmet, Heiko Schocher, Marcel Ziswiler, Ilko Iliev,
	u-boot, Angus Ainslie, Sebastian Krzyszkowiak

Initial commit of librem5 spl and u-boot based on the imx8mq_evk
u-boot

Signed-off-by: Angus Ainslie <angus@akkea.ca>
Co-authored-by: Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
Signed-off-by: Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>

---
 MAINTAINERS                                  |    8 +
 arch/arm/dts/Makefile                        |    3 +-
 arch/arm/dts/imx8mq-librem5-u-boot.dtsi      |  134 ++
 arch/arm/dts/imx8mq-librem5.dts              |  593 ++++++++
 arch/arm/mach-imx/imx8m/Kconfig              |    9 +
 board/purism/librem5/Kconfig                 |   15 +
 board/purism/librem5/MAINTAINERS             |    7 +
 board/purism/librem5/Makefile                |   13 +
 board/purism/librem5/imximage-8mq-lpddr4.cfg |    9 +
 board/purism/librem5/librem5.c               |  710 ++++++++++
 board/purism/librem5/librem5.h               |  176 +++
 board/purism/librem5/lpddr4_timing.c         | 1324 ++++++++++++++++++
 board/purism/librem5/lpddr4_timing_b0.c      | 1191 ++++++++++++++++
 board/purism/librem5/spl.c                   |  481 +++++++
 configs/librem5_defconfig                    |  120 ++
 doc/board/purism/librem5/librem5.rst         |   60 +
 include/configs/librem5.h                    |  173 +++
 17 files changed, 5025 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/dts/imx8mq-librem5-u-boot.dtsi
 create mode 100644 arch/arm/dts/imx8mq-librem5.dts
 create mode 100644 board/purism/librem5/Kconfig
 create mode 100644 board/purism/librem5/MAINTAINERS
 create mode 100644 board/purism/librem5/Makefile
 create mode 100644 board/purism/librem5/imximage-8mq-lpddr4.cfg
 create mode 100644 board/purism/librem5/librem5.c
 create mode 100644 board/purism/librem5/librem5.h
 create mode 100644 board/purism/librem5/lpddr4_timing.c
 create mode 100644 board/purism/librem5/lpddr4_timing_b0.c
 create mode 100644 board/purism/librem5/spl.c
 create mode 100644 configs/librem5_defconfig
 create mode 100644 doc/board/purism/librem5/librem5.rst
 create mode 100644 include/configs/librem5.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 90666ce376..6ac916dfaf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1057,6 +1057,14 @@ S:	Maintained
 T:	git https://source.denx.de/u-boot/custodians/u-boot-mpc85xx.git
 F:	arch/powerpc/cpu/mpc85xx/
 
+PURISM LIBREM5 PHONE
+M:	Angus Ainslie <angus@akkea.ca>
+R:	kernel@puri.sm
+S:	Supported
+F:	board/purism/librem5/
+F:	configs/librem5_defconfig
+F:	include/configs/librem5.h
+
 RISC-V
 M:	Rick Chen <rick@andestech.com>
 M:	Leo <ycliang@andestech.com>
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 7f622fedbd..eef3955785 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -908,7 +908,8 @@ dtb-$(CONFIG_ARCH_IMX8M) += \
 	imx8mq-phanbell.dtb \
 	imx8mp-evk.dtb \
 	imx8mp-phyboard-pollux-rdk.dtb \
-	imx8mq-pico-pi.dtb
+	imx8mq-pico-pi.dtb \
+	imx8mq-librem5.dtb
 
 dtb-$(CONFIG_ARCH_IMXRT) += imxrt1050-evk.dtb \
 	imxrt1020-evk.dtb
diff --git a/arch/arm/dts/imx8mq-librem5-u-boot.dtsi b/arch/arm/dts/imx8mq-librem5-u-boot.dtsi
new file mode 100644
index 0000000000..e3f780ca75
--- /dev/null
+++ b/arch/arm/dts/imx8mq-librem5-u-boot.dtsi
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+/ {
+	binman: binman {
+		multiple-images;
+	};
+};
+
+&binman {
+	u-boot-spl-ddr {
+		filename = "u-boot-spl-ddr.bin";
+		pad-byte = <0xff>;
+		align-size = <4>;
+		align = <4>;
+
+		u-boot-spl {
+			align-end = <4>;
+		};
+
+		blob_1: blob-ext@1 {
+			filename = "lpddr4_pmu_train_1d_imem.bin";
+			size = <0x8000>;
+		};
+
+		blob_2: blob-ext@2 {
+			filename = "lpddr4_pmu_train_1d_dmem.bin";
+			size = <0x4000>;
+		};
+
+		blob_3: blob-ext@3 {
+			filename = "lpddr4_pmu_train_2d_imem.bin";
+			size = <0x8000>;
+		};
+
+		blob_4: blob-ext@4 {
+			filename = "lpddr4_pmu_train_2d_dmem.bin";
+			size = <0x4000>;
+		};
+	};
+
+	spl {
+		filename = "spl.bin";
+
+		mkimage {
+			args = "-n spl/u-boot-spl.cfgout -T imx8mimage -e 0x7e1000";
+
+			blob {
+				filename = "u-boot-spl-ddr.bin";
+			};
+		};
+	};
+
+	itb {
+		filename = "u-boot.itb";
+
+		fit {
+			description = "Configuration to load ATF before U-Boot";
+			#address-cells = <1>;
+			fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+
+			images {
+				uboot {
+					description = "U-Boot (64-bit)";
+					type = "standalone";
+					arch = "arm64";
+					compression = "none";
+					load = <CONFIG_SYS_TEXT_BASE>;
+
+					uboot_blob: blob-ext {
+						filename = "u-boot-nodtb.bin";
+					};
+				};
+
+				atf {
+					description = "ARM Trusted Firmware";
+					type = "firmware";
+					arch = "arm64";
+					compression = "none";
+					load = <0x910000>;
+					entry = <0x910000>;
+
+					atf_blob: blob-ext {
+						filename = "bl31.bin";
+					};
+				};
+
+				fdt {
+					description = "NAME";
+					type = "flat_dt";
+					compression = "none";
+
+					uboot_fdt_blob: blob-ext {
+						filename = "u-boot.dtb";
+					};
+				};
+			};
+
+			configurations {
+				default = "conf";
+
+				conf {
+					description = "NAME";
+					firmware = "uboot";
+					loadables = "atf";
+					fdt = "fdt";
+				};
+			};
+		};
+	};
+
+	imx-boot {
+		filename = "flash.bin";
+		pad-byte = <0x00>;
+
+		spl: blob-ext@1 {
+			offset = <0x0>;
+			filename = "spl.bin";
+		};
+
+		uboot: blob-ext@2 {
+			offset = <0x57c00>;
+			filename = "u-boot.itb";
+		};
+	};
+};
+
+&usdhc1 {
+	mmc-hs400-1_8v;
+};
+
+&usdhc2 {
+	sd-uhs-sdr104;
+	sd-uhs-ddr50;
+};
diff --git a/arch/arm/dts/imx8mq-librem5.dts b/arch/arm/dts/imx8mq-librem5.dts
new file mode 100644
index 0000000000..93939df18f
--- /dev/null
+++ b/arch/arm/dts/imx8mq-librem5.dts
@@ -0,0 +1,593 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ * Copyright (C) 2021 Purism SPC
+ *
+ */
+
+/dts-v1/;
+
+#include "imx8mq.dtsi"
+
+/ {
+	model = "Librem 5";
+	compatible = "purism,librem5", "fsl,imx8mq";
+
+	chosen {
+		bootargs = "console=ttymxc0,115200 earlycon=ec_imx6q,0x30860000,115200";
+		stdout-path = &uart1;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg_usdhc2_vmmc: usdhc2_vmmc {
+			u-boot,dm-spl;
+			compatible = "regulator-fixed";
+			regulator-name = "VSD_3V3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pinctrl_led>;
+
+		ledr {
+			label = "LED_R";
+			gpios = <&gpio5 3 0>;
+		};
+		ledg {
+			label = "LED_G";
+			gpios = <&gpio5 2 0>;
+		};
+		ledb {
+			label = "LED_B";
+			gpios = <&gpio1 13 0>;
+		};
+	};
+};
+
+&iomuxc {
+	pinctrl_hog1: hoggrp1 {
+		fsl,pins = <
+			MX8MQ_IOMUXC_GPIO1_IO00_GPIO1_IO0	0x83 /*	CAMERA_PWR_EN_3V3 */
+			MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3	0x83 /*	TF_PWR_3V3_EN */
+			MX8MQ_IOMUXC_GPIO1_IO04_GPIO1_IO4	0x83 /*	AUDIO_POWER_EN_3V3 */
+			MX8MQ_IOMUXC_GPIO1_IO05_GPIO1_IO5	0x83 /*	DSI_EN_3V3 */
+			MX8MQ_IOMUXC_GPIO1_IO11_GPIO1_IO11	0x3f
+			MX8MQ_IOMUXC_GPIO1_IO12_GPIO1_IO12	0x3f
+			MX8MQ_IOMUXC_GPIO1_IO14_GPIO1_IO14	0x83 /* HUB_PWR_3V3_EN */
+			MX8MQ_IOMUXC_ENET_MDC_GPIO1_IO16	0xC0
+			MX8MQ_IOMUXC_ENET_MDIO_GPIO1_IO17	0xC0
+			MX8MQ_IOMUXC_ENET_TD1_GPIO1_IO20	0x83 /*	DSI_BIAS_EN */
+			MX8MQ_IOMUXC_ENET_TXC_GPIO1_IO23	0x83 /*	FLASH_EN */
+		>;
+	};
+
+	pinctrl_hog3: hoggrp3 {
+		fsl,pins = <
+			MX8MQ_IOMUXC_NAND_CE1_B_GPIO3_IO2		0x3 /* CHG_EN */
+			MX8MQ_IOMUXC_NAND_CE3_B_GPIO3_IO4		0x3 /* CHG_OTG_OUT_EN */
+			MX8MQ_IOMUXC_NAND_DATA04_GPIO3_IO10		0x83 /* WIFI3V3_EN */
+			MX8MQ_IOMUXC_NAND_DATA06_GPIO3_IO12		0x83 /* GPS3V3_EN */
+			MX8MQ_IOMUXC_NAND_DQS_GPIO3_IO14		0x83 /* BACKLINGE_EN */
+			MX8MQ_IOMUXC_NAND_WP_B_GPIO3_IO18		0x83 /* 4G_PWR_EN */
+			MX8MQ_IOMUXC_SAI5_RXD3_GPIO3_IO24		0x83 /* TPS_RESET */
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL			0x4000003f
+			MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA			0x4000003f
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL			0x4000001f
+			MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA			0x4000001f
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_I2C3_SCL_I2C3_SCL			0x4000001f
+			MX8MQ_IOMUXC_I2C3_SDA_I2C3_SDA			0x4000001f
+		>;
+	};
+
+	pinctrl_i2c4: i2c4grp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_I2C4_SCL_I2C4_SCL			0x4000003f
+			MX8MQ_IOMUXC_I2C4_SDA_I2C4_SDA			0x4000003f
+		>;
+	};
+
+	pinctrl_ecspi1: ecspi1grp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_ECSPI1_SCLK_ECSPI1_SCLK    0x82
+			MX8MQ_IOMUXC_ECSPI1_SS0_GPIO5_IO9	0x19
+			MX8MQ_IOMUXC_ECSPI1_MOSI_ECSPI1_MOSI    0x82
+			MX8MQ_IOMUXC_ECSPI1_MISO_ECSPI1_MISO    0x80
+		>;
+	};
+
+	pinctrl_led: ledgrp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_SPDIF_TX_GPIO5_IO3		0x16 /* LED_R */
+			MX8MQ_IOMUXC_SAI3_MCLK_GPIO5_IO2	0x16 /* LED_G */
+			MX8MQ_IOMUXC_GPIO1_IO13_GPIO1_IO13	0x16 /* LED_B */
+		>;
+	};
+
+	pinctrl_pmic: pmicgrp {
+		fsl,pins = <
+			 MX8MQ_IOMUXC_GPIO1_IO07_GPIO1_IO7       0x80 /* PMIC_NINT */
+		>;
+	};
+
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_SPDIF_EXT_CLK_GPIO5_IO5     0x83 /* MOTO */
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX		0x79
+			MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX		0x79
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+	       fsl,pins = <
+		       MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX		0x49
+		       MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX		0x49
+	       >;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_UART3_TXD_UART3_DCE_TX		0x79
+			MX8MQ_IOMUXC_UART3_RXD_UART3_DCE_RX		0x79
+			MX8MQ_IOMUXC_NAND_CLE_GPIO3_IO5			0x19
+		>;
+	};
+
+	pinctrl_uart4: uart4grp {
+	       fsl,pins = <
+		       MX8MQ_IOMUXC_ECSPI2_SCLK_UART4_DCE_RX		0x49
+		       MX8MQ_IOMUXC_ECSPI2_MOSI_UART4_DCE_TX		0x49
+		       MX8MQ_IOMUXC_ECSPI2_MISO_UART4_DCE_CTS_B		0x49
+		       MX8MQ_IOMUXC_ECSPI2_SS0_UART4_DCE_RTS_B		0x49
+	       >;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK			0x83
+			MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD			0xc3
+			MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0		0xc3
+			MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1		0xc3
+			MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2		0xc3
+			MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3		0xc3
+			MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4		0xc3
+			MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5		0xc3
+			MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6		0xc3
+			MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7		0xc3
+			MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE		0x83
+			MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B		0xc1
+		>;
+	};
+
+	pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+		fsl,pins = <
+			MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK			0x8d
+			MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD			0xcd
+			MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0		0xcd
+			MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1		0xcd
+			MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2		0xcd
+			MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3		0xcd
+			MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4		0xcd
+			MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5		0xcd
+			MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6		0xcd
+			MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7		0xcd
+			MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE		0x8d
+			MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B		0xc1
+		>;
+	};
+
+	pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+		fsl,pins = <
+			MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK			0x8f
+			MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD			0xcf
+			MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0		0xcf
+			MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1		0xcf
+			MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2		0xcf
+			MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3		0xcf
+			MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4		0xcf
+			MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5		0xcf
+			MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6		0xcf
+			MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7		0xcf
+			MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE		0x8f
+			MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B		0xc1
+		>;
+	};
+
+	pinctrl_usdhc2_gpio: usdhc2grpgpio {
+		fsl,pins = <
+			MX8MQ_IOMUXC_SD2_RESET_B_GPIO2_IO19             0x41    /* WIFI_nRST */
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK			0x83
+			MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD			0xc3
+			MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0		0xc3
+			MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1		0xc3
+			MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2		0xc3
+			MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3		0xc3
+			MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT		0xc1
+		>;
+	};
+
+	pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+		fsl,pins = <
+			MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK			0x8d
+			MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD			0xcd
+			MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0		0xcd
+			MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1		0xcd
+			MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2		0xcd
+			MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3		0xcd
+			MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT		0xc1
+		>;
+	};
+
+	pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+		fsl,pins = <
+			MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK			0x8f
+			MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD			0xcf
+			MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0		0xcf
+			MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1		0xcf
+			MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2		0xcf
+			MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3		0xcf
+			MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT		0xc1
+		>;
+	};
+
+	pinctrl_sai2: sai2grp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_SAI2_TXFS_SAI2_TX_SYNC	0xd6
+			MX8MQ_IOMUXC_SAI2_TXC_SAI2_TX_BCLK	0xd6
+			MX8MQ_IOMUXC_SAI2_MCLK_SAI2_MCLK	0xd6
+			MX8MQ_IOMUXC_SAI2_TXD0_SAI2_TX_DATA0	0xd6
+			MX8MQ_IOMUXC_GPIO1_IO08_GPIO1_IO8	0xd6
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+		>;
+	};
+};
+
+&gpio1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog1>;
+
+	csi_en {
+		gpio-hog;
+		output-low;
+		gpios = <0 GPIO_ACTIVE_HIGH>;
+		line-name = "csi_en";
+	};
+	sdcard_pwr {
+		gpio-hog;
+		output-high;
+		gpios = <3 GPIO_ACTIVE_HIGH>;
+	};
+	audio_pwr {
+		gpio-hog;
+		output-high;
+		gpios = <4 GPIO_ACTIVE_HIGH>;
+	};
+	hub_nreset {
+		gpio-hog;
+		output-high;
+		gpios = <12 GPIO_ACTIVE_HIGH>;
+		line-name = "hub_nreset";
+	};
+	hub_pwr {
+		gpio-hog;
+		output-high;
+		gpios = <14 GPIO_ACTIVE_HIGH>;
+		line-name = "hub_pwr";
+	};
+};
+
+&gpio3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog3>;
+	status = "okay";
+
+	chg_en {
+		gpio-hog;
+		output-low;
+		gpios = <17 GPIO_ACTIVE_HIGH>;
+	};
+	tps_reset {
+		gpio-hog;
+		output-low;
+		gpios = <24 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+	u-boot,dm-pre-reloc;
+
+	pmic@4b {
+		compatible = "rohm,bd71837";
+		reg = <0x4b>;
+		pinctrl-0 = <&pinctrl_pmic>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <7 GPIO_ACTIVE_LOW>;
+		rohm,reset-snvs-powered;
+		u-boot,dm-pre-reloc;
+		regulators {
+			buck1_reg: BUCK1 {
+				regulator-name = "buck1";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-boot-on;
+				regulator-ramp-delay = <1250>;
+				rohm,dvs-run-voltage = <900000>;
+				rohm,dvs-idle-voltage = <850000>;
+				rohm,dvs-suspend-voltage = <800000>;
+				regulator-always-on;
+			};
+
+			buck2_reg: BUCK2 {
+				regulator-name = "buck2";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-boot-on;
+				regulator-ramp-delay = <1250>;
+				rohm,dvs-run-voltage = <1000000>;
+				rohm,dvs-idle-voltage = <900000>;
+				regulator-always-on;
+			};
+
+			buck3_reg: BUCK3 {
+				regulator-name = "buck3";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-boot-on;
+				rohm,dvs-run-voltage = <900000>;
+				regulator-always-on;
+			};
+
+			buck4_reg: BUCK4 {
+				regulator-name = "buck4";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1300000>;
+				rohm,dvs-run-voltage = <1000000>;
+			};
+
+			buck5_reg: BUCK5 {
+				regulator-name = "buck5";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck6_reg: BUCK6 {
+				regulator-name = "buck6";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck7_reg: BUCK7 {
+				regulator-name = "buck7";
+				regulator-min-microvolt = <1605000>;
+				regulator-max-microvolt = <1995000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck8_reg: BUCK8 {
+				regulator-name = "buck8";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo1_reg: LDO1 {
+				regulator-name = "ldo1";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				/* leave on for snvs power button */
+				regulator-always-on;
+			};
+
+			ldo2_reg: LDO2 {
+				regulator-name = "ldo2";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-boot-on;
+				/* leave on for snvs power button */
+				regulator-always-on;
+			};
+
+			ldo3_reg: LDO3 {
+				regulator-name = "ldo3";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo4_reg: LDO4 {
+				regulator-name = "ldo4";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo5_reg: LDO5 {
+				/* VDD_PHY_0V9 - MIPI and HDMI domains */
+				regulator-name = "ldo5";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			ldo6_reg: LDO6 {
+				/* VDD_PHY_0V9 - MIPI, HDMI and USB domains */
+				regulator-name = "ldo6";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo7_reg: LDO7 {
+				/* VDD_PHY_3V3 - USB domain */
+				regulator-name = "ldo7";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+};
+
+&i2c4 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c4>;
+	status = "okay";
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
+	status = "okay";
+
+	flash0: winbond@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <29000000>;
+	};
+};
+
+&uart1 { /* console */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	assigned-clocks = <&clk IMX8MQ_CLK_UART1_ROOT>;
+	assigned-clock-parents = <&clk IMX8MQ_CLK_25M>;
+	status = "okay";
+};
+
+&uart3 { /* BT */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	assigned-clocks = <&clk IMX8MQ_CLK_UART3_ROOT>;
+	assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_80M>;
+	fsl,uart-has-rtscts;
+	status = "disabled";
+};
+
+&usdhc1 {
+	u-boot,dm-pre-reloc;
+	u-boot,dm-spl;
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+	bus-width = <8>;
+	non-removable;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+	bus-width = <4>;
+	broken-cd;
+	vmmc-supply = <&reg_usdhc2_vmmc>;
+	status = "okay";
+};
+
+&usb3_phy0 {
+	u-boot,dm-pre-reloc;
+	u-boot,dm-spl;
+	status = "okay";
+};
+
+&usb_dwc3_0 {
+	compatible = "snps,dwc3-gadget";
+	u-boot,dm-pre-reloc;
+	u-boot,dm-spl;
+	status = "okay";
+	dr_mode = "peripheral";
+	snps,dis_u2_susphy_quirk;
+	snps,dis_u3_susphy_quirk;
+	maximum-speed = "high-speed";
+};
+
+&usb3_phy1 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&usb_dwc3_1 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+	dr_mode = "host";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+	status = "okay";
+};
diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig
index 276b8bd974..424ed5b2e3 100644
--- a/arch/arm/mach-imx/imx8m/Kconfig
+++ b/arch/arm/mach-imx/imx8m/Kconfig
@@ -154,6 +154,14 @@ config TARGET_IMX8MM_CL_IOT_GATE_OPTEE
 	select IMX8MM
 	select SUPPORT_SPL
 	select IMX8M_LPDDR4
+
+config TARGET_LIBREM5
+	bool "Purism Librem5 Phone"
+	select BINMAN
+	select IMX8MQ
+	select SUPPORT_SPL
+	select IMX8M_LPDDR4
+
 endchoice
 
 source "board/beacon/imx8mm/Kconfig"
@@ -169,6 +177,7 @@ source "board/google/imx8mq_phanbell/Kconfig"
 source "board/kontron/sl-mx8mm/Kconfig"
 source "board/phytec/phycore_imx8mm/Kconfig"
 source "board/phytec/phycore_imx8mp/Kconfig"
+source "board/purism/librem5/Kconfig"
 source "board/ronetix/imx8mq-cm/Kconfig"
 source "board/technexion/pico-imx8mq/Kconfig"
 source "board/toradex/verdin-imx8mm/Kconfig"
diff --git a/board/purism/librem5/Kconfig b/board/purism/librem5/Kconfig
new file mode 100644
index 0000000000..cf0f303683
--- /dev/null
+++ b/board/purism/librem5/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_LIBREM5
+
+config SYS_BOARD
+	default "librem5"
+
+config SYS_VENDOR
+	default "purism"
+
+config SYS_CONFIG_NAME
+	default "librem5"
+
+config IMX_CONFIG
+	default "board/purism/librem5/imximage-8mq-lpddr4.cfg"
+
+endif
diff --git a/board/purism/librem5/MAINTAINERS b/board/purism/librem5/MAINTAINERS
new file mode 100644
index 0000000000..818e185030
--- /dev/null
+++ b/board/purism/librem5/MAINTAINERS
@@ -0,0 +1,7 @@
+PURISM LIBREM5 PHONE
+M:	Angus Ainslie <angus@akkea.ca>
+R:	kernel@puri.sm
+S:	Supported
+F:	board/purism/librem5/
+F:	configs/librem5_defconfig
+F:	include/configs/librem5.h
diff --git a/board/purism/librem5/Makefile b/board/purism/librem5/Makefile
new file mode 100644
index 0000000000..47f25f047b
--- /dev/null
+++ b/board/purism/librem5/Makefile
@@ -0,0 +1,13 @@
+#
+# Copyright 2017 NXP
+# Copyright 2019 Purism
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-y += librem5.o
+
+ifdef CONFIG_SPL_BUILD
+obj-y += spl.o
+obj-$(CONFIG_IMX8M_LPDDR4) += lpddr4_timing.o lpddr4_timing_b0.o
+endif
diff --git a/board/purism/librem5/imximage-8mq-lpddr4.cfg b/board/purism/librem5/imximage-8mq-lpddr4.cfg
new file mode 100644
index 0000000000..90573be5fd
--- /dev/null
+++ b/board/purism/librem5/imximage-8mq-lpddr4.cfg
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 NXP
+ */
+
+#define __ASSEMBLY__
+
+BOOT_FROM	sd
+LOADER		u-boot-spl-ddr.bin	0x7E1000
diff --git a/board/purism/librem5/librem5.c b/board/purism/librem5/librem5.c
new file mode 100644
index 0000000000..93c2ac0630
--- /dev/null
+++ b/board/purism/librem5/librem5.c
@@ -0,0 +1,710 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ * Copyright 2021 Purism
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <miiphy.h>
+#include <asm/mach-imx/iomux-v3.h>
+#include <asm-generic/gpio.h>
+#include <asm/arch/sys_proto.h>
+#include <fsl_esdhc.h>
+#include <mmc.h>
+#include <asm/arch/imx8mq_pins.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/mach-imx/gpio.h>
+#include <asm/mach-imx/mxc_i2c.h>
+#include <asm/arch/clock.h>
+#include <asm/mach-imx/video.h>
+#include <fuse.h>
+#include <i2c.h>
+#include <spl.h>
+#include <usb.h>
+#include <dwc3-uboot.h>
+#include <linux/delay.h>
+#include <linux/bitfield.h>
+#include <usb/xhci.h>
+#include "librem5.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ENABLE_TPS_RESET
+
+#define WDOG_PAD_CTRL	(PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE)
+
+static const iomux_v3_cfg_t wdog_pads[] = {
+	IMX8MQ_PAD_GPIO1_IO02__WDOG1_WDOG_B | MUX_PAD_CTRL(WDOG_PAD_CTRL),
+};
+
+int board_early_init_f(void)
+{
+	struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
+
+	log_debug("%s: starting\n", __func__);
+
+	imx_iomux_v3_setup_multiple_pads(wdog_pads, ARRAY_SIZE(wdog_pads));
+	set_wdog_reset(wdog);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF_BOARD_SETUP
+int ft_board_setup(void *blob, struct bd_info *bd)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_BOARD_POSTCLK_INIT
+int board_postclk_init(void)
+{
+	/* TODO */
+	return 0;
+}
+#endif
+
+#ifndef CONFIG_DM_USB
+int usb_gadget_handle_interrupts(void)
+{
+	dwc3_uboot_handle_interrupt(0);
+	return 0;
+}
+
+#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_IMX8M)
+static void dwc3_nxp_usb_phy_init(struct dwc3_device *dwc3)
+{
+	u32 RegData;
+
+	RegData = readl(dwc3->base + USB_PHY_CTRL1);
+	RegData &= ~(USB_PHY_CTRL1_VDATSRCENB0 | USB_PHY_CTRL1_VDATDETENB0 |
+			USB_PHY_CTRL1_COMMONONN);
+	RegData |= USB_PHY_CTRL1_RESET | USB_PHY_CTRL1_ATERESET;
+	writel(RegData, dwc3->base + USB_PHY_CTRL1);
+
+	RegData = readl(dwc3->base + USB_PHY_CTRL0);
+	RegData |= USB_PHY_CTRL0_REF_SSP_EN;
+	writel(RegData, dwc3->base + USB_PHY_CTRL0);
+
+	RegData = readl(dwc3->base + USB_PHY_CTRL2);
+	RegData |= USB_PHY_CTRL2_TXENABLEN0;
+	writel(RegData, dwc3->base + USB_PHY_CTRL2);
+
+	RegData = readl(dwc3->base + USB_PHY_CTRL1);
+	RegData &= ~(USB_PHY_CTRL1_RESET | USB_PHY_CTRL1_ATERESET);
+	writel(RegData, dwc3->base + USB_PHY_CTRL1);
+}
+
+static struct dwc3_device dwc3_device0_data = {
+#ifdef CONFIG_SPL_BUILD
+	.maximum_speed = USB_SPEED_HIGH,
+#else
+	.maximum_speed = USB_SPEED_SUPER,
+#endif
+	.base = USB1_BASE_ADDR,
+	.dr_mode = USB_DR_MODE_PERIPHERAL,
+	.index = 0,
+	.dis_u2_susphy_quirk = 1,
+};
+
+static struct dwc3_device dwc3_device1_data = {
+#ifdef CONFIG_SPL_BUILD
+	.maximum_speed = USB_SPEED_HIGH,
+#else
+	.maximum_speed = USB_SPEED_SUPER,
+#endif
+	.base = USB2_BASE_ADDR,
+	.dr_mode = USB_DR_MODE_HOST,
+	.index = 1,
+	.dis_u2_susphy_quirk = 1,
+};
+
+int board_usb_init(int index, enum usb_init_type init)
+{
+	int ret = 0;
+
+	log_debug("%s: starting %d %d %d\n", __func__, index, init);
+
+	imx8m_usb_power(index, true);
+
+	if (index == 0 && init == USB_INIT_DEVICE) {
+		dwc3_nxp_usb_phy_init(&dwc3_device0_data);
+		ret = dwc3_uboot_init(&dwc3_device0_data);
+	}
+	if (index == 1 && init == USB_INIT_HOST) {
+		dwc3_nxp_usb_phy_init(&dwc3_device1_data);
+		ret = dwc3_uboot_init(&dwc3_device1_data);
+	}
+
+	log_debug("%s: ending %d\n", __func__, ret);
+
+	return ret;
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+	int ret = 0;
+
+	if (index == 0 && init == USB_INIT_DEVICE)
+		dwc3_uboot_exit(index);
+
+	if (index == 1 && init == USB_INIT_HOST)
+		dwc3_uboot_exit(index);
+
+	imx8m_usb_power(index, false);
+
+	return ret;
+}
+#endif
+
+int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
+{
+	return 0;
+}
+
+void xhci_hcd_stop(int index)
+{
+}
+#endif
+
+#ifdef CONFIG_LOAD_ENV_FROM_MMC_BOOT_PARTITION
+uint board_mmc_get_env_part(struct mmc *mmc)
+{
+	log_debug("%s: starting\n", __func__);
+	uint part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
+
+	if (part == 7)
+		part = 0;
+	return part;
+}
+#endif
+
+#define SPI_FLASH_CS IMX_GPIO_NR(5, 9)
+
+int board_spi_cs_gpio(unsigned int bus, unsigned int cs)
+{
+	return (bus == 0 && cs == 0) ? (SPI_FLASH_CS) : -1;
+}
+
+#define ECSPI_PAD_CTRL	(PAD_CTL_DSE2 | PAD_CTL_HYS)
+
+static const iomux_v3_cfg_t ecspi_pads[] = {
+	IMX8MQ_PAD_ECSPI1_SCLK__ECSPI1_SCLK | MUX_PAD_CTRL(ECSPI_PAD_CTRL),
+	IMX8MQ_PAD_ECSPI1_SS0__GPIO5_IO9 | MUX_PAD_CTRL(ECSPI_PAD_CTRL),
+	IMX8MQ_PAD_ECSPI1_MOSI__ECSPI1_MOSI | MUX_PAD_CTRL(ECSPI_PAD_CTRL),
+	IMX8MQ_PAD_ECSPI1_MISO__ECSPI1_MISO | MUX_PAD_CTRL(ECSPI_PAD_CTRL),
+};
+
+/* used if we reset the TPS65982 */
+static const iomux_v3_cfg_t ecspi_pads_hiz[] = {
+	IMX8MQ_PAD_ECSPI1_SCLK__GPIO5_IO6,
+	IMX8MQ_PAD_ECSPI1_MOSI__GPIO5_IO7,
+	IMX8MQ_PAD_ECSPI1_MISO__GPIO5_IO8,
+	IMX8MQ_PAD_ECSPI1_SS0__GPIO5_IO9,
+};
+
+extern int set_clk_ecspi(int);
+
+int board_ecspi_init(void)
+{
+	log_debug("%s: starting\n", __func__);
+
+	imx_iomux_v3_setup_multiple_pads(ecspi_pads, ARRAY_SIZE(ecspi_pads));
+
+	set_clk_ecspi(1);
+
+	return 0;
+}
+
+void ecspi_hiz(void)
+{
+	log_debug("%s: starting\n", __func__);
+
+	imx_iomux_v3_setup_multiple_pads(ecspi_pads_hiz, ARRAY_SIZE(ecspi_pads_hiz));
+
+	gpio_direction_input(SPI1_SCLK);
+	gpio_direction_input(SPI1_MISO);
+	gpio_direction_input(SPI1_MOSI);
+	gpio_direction_input(SPI1_SS0);
+}
+
+int bq_read_reg(int reg_index)
+{
+	struct udevice *udev, *bus;
+	u8 reg;
+	int ret;
+
+	ret = uclass_get_device_by_seq(UCLASS_I2C, 3, &bus);
+	if (ret) {
+		log_err("%s: No bus %d\n", __func__, 3);
+		return -ENODEV;
+	}
+
+	ret = i2c_get_chip(bus, 0x6a, 1, &udev);
+	if (ret) {
+		log_err("%s: setting chip offset failed %d\n", __func__, ret);
+		return -EINVAL;
+	}
+
+	dm_i2c_read(udev, reg_index, &reg, 1);
+
+	return reg;
+}
+
+int bq_write_reg(int reg_index, u8 val)
+{
+	struct udevice *udev, *bus;
+	int ret;
+
+	ret = uclass_get_device_by_seq(UCLASS_I2C, 3, &bus);
+	if (ret) {
+		log_err("%s: No bus %d\n", __func__, 3);
+		return 1;
+	}
+
+	ret = i2c_get_chip(bus, 0x6a, 1, &udev);
+	if (ret) {
+		log_err("%s: setting chip offset failed %d\n", __func__, ret);
+		return 1;
+	}
+
+	dm_i2c_write(udev, reg_index, &val, 1);
+
+	return 0;
+}
+
+int read_vbat(void)
+{
+	u8 reg02, reg03, reg0e;
+	int timeout = 1000; // ms
+
+	/* disable the charger and enable BAT_LOADEN to discharge the decoupling
+	 * CAP
+	 * https://e2e.ti.com/support/power-management/f/196/t/567401
+	 */
+	reg03 = bq_read_reg(0x03);
+	bq_write_reg(0x03, (reg03 | 0x80) & ~0x10);
+
+	mdelay(10);
+
+	/* force a conversion */
+	reg02 = bq_read_reg(0x02);
+	bq_write_reg(0x02, (reg02 | 0x80) & ~0x40);
+
+	do {
+		mdelay(10);
+		timeout -= 10;
+	} while ((bq_read_reg(0x02) & 0x80) && (timeout > 0));
+
+	reg0e = bq_read_reg(0x0e);
+
+	/* return the charger to it's original state */
+	bq_write_reg(0x03, reg03);
+	bq_write_reg(0x02, reg02);
+
+	return (reg0e & 0x7f) * 20 + 2304;
+}
+
+int tps65982_wait_for_app(int timeout, int timeout_step)
+{
+	int ret;
+	char response[6];
+#ifdef CONFIG_DM_I2C
+	struct udevice *udev, *bus;
+#endif
+
+	log_debug("%s: starting\n", __func__);
+
+	/* Set the i2c bus */
+#ifndef CONFIG_DM_I2C
+	log_debug("%s: using i2c device mode\n", __func__);
+	i2c_set_bus_num(0);
+#else
+	ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &bus);
+	if (ret) {
+		log_err("%s: No bus %d\n", __func__, 0);
+		return 1;
+	}
+
+	ret = i2c_get_chip(bus, 0x3f, 1, &udev);
+	if (ret) {
+		log_err("%s: setting chip offset failed %d\n", __func__, ret);
+		return 1;
+	}
+#endif
+
+	while (timeout > 0) {
+#ifndef CONFIG_DM_I2C
+		ret = i2c_read(0x3f, 0x03, 1, (u8 *)response, 5);
+#else
+		ret = dm_i2c_read(udev, 0x03, (u8 *)response, 5);
+#endif
+		log_debug("tps65982 mode %s\n", response);
+		if (response[1] == 'A')
+			return 0;
+		mdelay(timeout_step);
+		timeout -= timeout_step;
+		log_debug("tps65982 waited %d ms %c\n", timeout_step, response[1]);
+	}
+
+	return 1;
+}
+
+#define TPS_POWER_STATUS_PWROPMODE(x)	    FIELD_GET(GENMASK(3, 2), x)
+
+#define TPS_PDO_CONTRACT_TYPE(x)	FIELD_GET(GENMASK(31, 30), x)
+#define TPS_PDO_CONTRACT_FIXED	0
+#define TPS_PDO_CONTRACT_BATTERY	1
+#define TPS_PDO_CONTRACT_VARIABLE	2
+
+#define TPS_TYPEC_PWR_MODE_USB	0
+#define TPS_TYPEC_PWR_MODE_1_5A	1
+#define TPS_TYPEC_PWR_MODE_3_0A	2
+#define TPS_TYPEC_PWR_MODE_PD	3
+
+#define TPS_PDO_FIXED_CONTRACT_MAX_CURRENT(x)	(FIELD_GET(GENMASK(9, 0), x) * 10)
+#define TPS_PDO_VAR_CONTRACT_MAX_CURRENT(x)	(FIELD_GET(GENMASK(9, 0), x) * 10)
+#define TPS_PDO_BAT_CONTRACT_MAX_VOLTAGE(x)	(FIELD_GET(GENMASK(29, 20), x) * 50)
+#define TPS_PDO_BAT_CONTRACT_MAX_POWER(x)	(FIELD_GET(GENMASK(9, 0), x) * 250)
+
+int tps65982_get_max_current(void)
+{
+	int ret;
+	u8 buf[7];
+	u8 pwr_status;
+	u32 contract;
+	int type, mode;
+	struct udevice *udev, *bus;
+
+	log_debug("%s: starting\n", __func__);
+
+	/* Set the i2c bus */
+	ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &bus);
+	if (ret) {
+		log_debug("%s: No bus %d\n", __func__, 0);
+		return -1;
+	}
+
+	ret = i2c_get_chip(bus, 0x3f, 1, &udev);
+	if (ret) {
+		log_debug("%s: setting chip offset failed %d\n", __func__, ret);
+		return -1;
+	}
+
+	ret = dm_i2c_read(udev, 0x3f, buf, 3);
+	if (ret) {
+		log_debug("%s: reading pwr_status failed %d\n", __func__, ret);
+		return -1;
+	}
+
+	pwr_status = buf[1];
+
+	if (!(pwr_status & 1))
+		return 0;
+
+	mode = TPS_POWER_STATUS_PWROPMODE(pwr_status);
+	switch (mode) {
+	case TPS_TYPEC_PWR_MODE_1_5A:
+		return 1500;
+	case TPS_TYPEC_PWR_MODE_3_0A:
+		return 3000;
+	case TPS_TYPEC_PWR_MODE_PD:
+		ret = dm_i2c_read(udev, 0x34, buf, 7);
+		if (ret) {
+			log_debug("%s: reading active contract failed %d\n", __func__, ret);
+			return -1;
+		}
+
+		contract = buf[1] + (buf[2] << 8) + (buf[3] << 16) + (buf[4] << 24);
+
+		type = TPS_PDO_CONTRACT_TYPE(contract);
+
+		switch (type) {
+		case TPS_PDO_CONTRACT_FIXED:
+			return TPS_PDO_FIXED_CONTRACT_MAX_CURRENT(contract);
+		case TPS_PDO_CONTRACT_BATTERY:
+			return 1000 * TPS_PDO_BAT_CONTRACT_MAX_POWER(contract)
+				/ TPS_PDO_BAT_CONTRACT_MAX_VOLTAGE(contract);
+		case TPS_PDO_CONTRACT_VARIABLE:
+			return TPS_PDO_VAR_CONTRACT_MAX_CURRENT(contract);
+		default:
+			log_debug("Unknown contract type: %d\n", type);
+			return -1;
+		}
+	case TPS_TYPEC_PWR_MODE_USB:
+		return 500;
+	default:
+		log_debug("Unknown power mode: %d\n", mode);
+		return -1;
+	}
+}
+
+int init_tps65982(void)
+{
+	int vbat;
+
+	log_debug("%s: starting\n", __func__);
+
+	if (tps65982_wait_for_app(500, 100)) {
+		/* check that VBAT is present and greater than 3000 mV. resetting the
+		 * tps65982 disconnects VBUS so we need a different power source.
+		 * Battery voltage greater than 4.15V likely means the battery is not
+		 * present.
+		 */
+		vbat = read_vbat();
+#ifdef ENABLE_TPS_RESET
+		if (vbat > 3000 && vbat < 4150)	{
+			log_info("tps65982 attempting reset - %d mV\n", vbat);
+			ecspi_hiz();
+
+			gpio_direction_output(TPS_RESET, 0);
+			mdelay(3);
+			gpio_direction_output(TPS_RESET, 1);
+			mdelay(2);
+			gpio_direction_output(TPS_RESET, 0);
+			mdelay(100);
+
+			if (tps65982_wait_for_app(1000, 250)) {
+				log_err("tps65982 failed to boot\n");
+				board_ecspi_init();
+				gpio_direction_output(LED_G, 0);
+				gpio_direction_output(LED_R, 1);
+				return 1;
+			}
+
+			board_ecspi_init();
+		} else {
+			log_err("vbat out of range to reset tps65982 %d mV\n", vbat);
+			return 1;
+		}
+#else
+		log_err("tps65982 APP boot failed %d mV\n", vbat);
+		return 1;
+#endif
+	}
+
+	log_info("tps65982 boot successful\n");
+	return 0;
+}
+
+int bq25896_set_iinlim(int current)
+{
+	u8 val, iinlim;
+	int ret;
+	struct udevice *udev, *bus;
+
+	/* Set the i2c bus */
+	ret = uclass_get_device_by_seq(UCLASS_I2C, 3, &bus);
+	if (ret) {
+		log_err("%s: No bus 3\n", __func__);
+		return ret;
+	}
+
+	ret = i2c_get_chip(bus, 0x6a, 1, &udev);
+	if (ret) {
+		log_err("%s: setting chip offset failed %d\n", __func__, ret);
+		return ret;
+	}
+
+	if (current > 3250)
+		current = 3250;
+	if (current < 100)
+		current = 100;
+
+	val = dm_i2c_reg_read(udev, 0x00);
+	iinlim = ((current - 100) / 50) & 0x3f;
+	val = (val & 0xc0) | iinlim;
+	dm_i2c_reg_write(udev, 0x00, val);
+	log_debug("REG00 0x%x\n", val);
+
+	return 0;
+}
+
+/*
+ * set some safe defaults for the battery charger
+ */
+int init_charger_bq25896(void)
+{
+	u8 val;
+	int iinlim, vbat, ret;
+	struct udevice *udev, *bus;
+
+	/* Set the i2c bus */
+	ret = uclass_get_device_by_seq(UCLASS_I2C, 3, &bus);
+	if (ret) {
+		log_debug("%s: No bus 3\n", __func__);
+		return ret;
+	}
+
+	ret = i2c_get_chip(bus, 0x6a, 1, &udev);
+	if (ret) {
+		log_debug("%s: setting chip offset failed %d\n", __func__, ret);
+		return ret;
+	}
+
+	/* enable automatic DC conversions */
+	val = dm_i2c_reg_read(udev, 0x02);
+	log_debug("REG0B 0x%x\n", val);
+	val = (val & ~0xc0) | 0x40;
+	dm_i2c_reg_write(udev, 0x02, val);
+
+	/* check VBUS good */
+	val = dm_i2c_reg_read(udev, 0x11);
+	log_debug("VBUS good %d\n", (val >> 7) & 1);
+	log_debug("VBUS mV %d\n", (val & 0x7f) * 100 + 2600);
+
+	val = dm_i2c_reg_read(udev, 0x0b);
+	log_debug("REG0B 0x%x\n", val);
+
+	log_debug("VBUS_STAT 0x%x\n", val >> 5);
+	switch (val >> 5) {
+	case 0:
+		log_debug("VBUS not detected\n");
+		break;
+	case 1:
+		log_debug("USB SDP IINLIM 500mA\n");
+		break;
+	case 2:
+		log_debug("USB CDP IINLIM 1500mA\n");
+		break;
+	case 3:
+		log_debug("USB DCP IINLIM 3500mA\n");
+		break;
+	case 4:
+		log_debug("MAXCHARGE IINLIM 1500mA\n");
+		break;
+	case 5:
+		log_debug("Unknown IINLIM 500mA\n");
+		break;
+	case 6:
+		log_debug("DIVIDER IINLIM > 1000mA\n");
+		break;
+	case 7:
+		log_debug("OTG\n");
+		break;
+	};
+
+	log_debug("CHRG_STAT 0x%x\n", (val >> 3) & 0x3);
+	log_debug("PG_STAT 0x%x\n", (val >> 2) & 1);
+	log_debug("SDP_STAT 0x%x\n", (val >> 1) & 1);
+	log_debug("VSYS_STAT 0x%x\n", val & 1);
+
+	val = dm_i2c_reg_read(udev, 0x00);
+	log_debug("REG00 0x%x\n", val);
+	iinlim = 100 + (val & 0x3f) * 50;
+	log_debug("IINLIM %d mA\n", iinlim);
+	log_debug("EN_HIZ 0x%x\n", (val >> 7) & 1);
+	log_debug("EN_ILIM 0x%x\n", (val >> 6) & 1);
+
+	/* check VBAT */
+	vbat = read_vbat();
+	log_debug("VBAT mV %d\n", vbat);
+
+	if (vbat < 2800 && iinlim <= 500) {
+		/* battery voltage too low and
+		 * insufficient current to boot linux.
+		 */
+		gpio_direction_output(LED_R, 1);
+		log_err("%s: voltage and current too low linux probably won't boot\n", __func__);
+	}
+
+	/* set 1.6A charge limit */
+	dm_i2c_reg_write(udev, 0x04, 0x19);
+
+	/* re-enable charger */
+	val = dm_i2c_reg_read(udev, 0x03);
+	val = val | 0x10;
+	dm_i2c_reg_write(udev, 0x03, val);
+
+	/* limit the VINDPM to 3.9V  */
+	dm_i2c_reg_write(udev, 0x0d, 0x8d);
+
+	/* set the max voltage to 4.192V */
+	val = dm_i2c_reg_read(udev, 0x6);
+	val = (val & ~0xFC) | 0x16 << 2;
+	dm_i2c_reg_write(udev, 0x6, val);
+
+	/* set the SYS_MIN to 3.7V */
+	val = dm_i2c_reg_read(udev, 0x3);
+	val = val | 0xE;
+	dm_i2c_reg_write(udev, 0x3, val);
+
+	return 0;
+}
+
+void init_usb_clk(void);
+
+int board_init(void)
+{
+	int tps_ret;
+
+	log_debug("%s: starting %d mV\n", __func__, read_vbat());
+
+	init_pinmux();
+
+#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_IMX8M)
+	log_debug("%s: initializing USB clk\n", __func__);
+	init_usb_clk();
+#endif
+
+	tps_ret = init_tps65982();
+	init_charger_bq25896();
+
+	if (!tps_ret) {
+		int current = tps65982_get_max_current();
+
+		if (current > 500)
+			bq25896_set_iinlim(current);
+	}
+
+	return 0;
+}
+
+#define VOL_DOWN IMX_GPIO_NR(1, 17)
+
+int fastboot_key_pressed(void)
+{
+	int val;
+
+	gpio_direction_input(VOL_DOWN);
+
+	val = gpio_get_value(VOL_DOWN);
+	log_debug("%s : %d\n", __func__, val);
+
+	return !val;
+}
+
+int board_late_init(void)
+{
+#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+	u32 vid, rev;
+	char rev_str[3];
+
+	env_set("board_name", "librem5");
+	if (fuse_read(8, 2, &vid) || fuse_read(14, 0, &rev)) {
+		env_set("board_rev", BOARD_REV_ERROR);
+	} else if (vid == 0) {
+		env_set("board_rev", BOARD_REV_UNKNOWN);
+	} else if (vid == (PURISM_PID << 16 | PURISM_VID)) {
+		sprintf(rev_str, "%u", rev);
+		env_set("board_rev", rev_str);
+	}
+
+	printf("Board name: %s\n", env_get("board_name"));
+	printf("Board rev:  %s\n", env_get("board_rev"));
+#endif
+
+	if (is_usb_boot()) {
+		puts("USB Boot\n");
+		env_set("bootcmd", "fastboot 0");
+	} else if (fastboot_key_pressed()) {
+		log_debug("stop in u-boot\n");
+		env_set("bootcmd", "");
+	}
+
+	return 0;
+}
+
diff --git a/board/purism/librem5/librem5.h b/board/purism/librem5/librem5.h
new file mode 100644
index 0000000000..54e8f5adf2
--- /dev/null
+++ b/board/purism/librem5/librem5.h
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2021 Purism
+ */
+
+#ifndef __LIBREM5_H__
+#define __LIBREM5_H__
+
+#define CAMERA_EN IMX_GPIO_NR(1, 0)
+#define SD_EN IMX_GPIO_NR(1, 3)
+#define AUDIO_EN IMX_GPIO_NR(1, 4)
+#define DSI_EN IMX_GPIO_NR(1, 5)
+#define SMC_EN IMX_GPIO_NR(1, 6)
+#define TYPEC_MUX_EN IMX_GPIO_NR(1, 11)
+#define HUB_NRESET IMX_GPIO_NR(1, 12)
+#define HUB_EN IMX_GPIO_NR(1, 14)
+#define VOL_UP IMX_GPIO_NR(1, 16)
+#define VOL_DOWN IMX_GPIO_NR(1, 17)
+#define DSI_BIAS_EN IMX_GPIO_NR(1, 20)
+#define FLASH_EN IMX_GPIO_NR(1, 23)
+#define WWAN_NRESET IMX_GPIO_NR(3, 1)
+#define CHG_EN IMX_GPIO_NR(3, 2)
+#define CHG_OTG_OUT_EN IMX_GPIO_NR(3, 4)
+#define WIFI_EN IMX_GPIO_NR(3, 10)
+#define GPS_EN IMX_GPIO_NR(3, 12)
+#define BL_EN IMX_GPIO_NR(3, 14)
+#define WWAN_EN IMX_GPIO_NR(3, 18)
+#define NFC_EN IMX_GPIO_NR(4, 28)
+#define LED_G IMX_GPIO_NR(5, 2)
+#define LED_R IMX_GPIO_NR(5, 3)
+#define LED_B IMX_GPIO_NR(1, 13)
+#define MOTO IMX_GPIO_NR(5, 5)
+#define SPI1_SCLK IMX_GPIO_NR(5, 6)
+#define SPI1_MOSI IMX_GPIO_NR(5, 7)
+#define SPI1_MISO IMX_GPIO_NR(5, 8)
+#define SPI1_SS0 IMX_GPIO_NR(5, 9)
+
+#define UART1_TX IMX_GPIO_NR(5, 23)
+#define UART1_RX IMX_GPIO_NR(5, 22)
+#define UART2_TX IMX_GPIO_NR(5, 25)
+#define UART2_RX IMX_GPIO_NR(5, 24)
+#define UART3_TX IMX_GPIO_NR(5, 27)
+#define UART3_RX IMX_GPIO_NR(5, 26)
+#define UART4_TX IMX_GPIO_NR(5, 11)
+#define UART4_RX IMX_GPIO_NR(5, 10)
+
+#define TPS_RESET IMX_GPIO_NR(3, 24)
+
+#define PURISM_VID	0x316d
+#define PURISM_PID	0x4c05
+
+#define BOARD_REV_ERROR		"unknown"
+#define BOARD_REV_BIRCH		"1"
+#define BOARD_REV_CHESTNUT	"2"
+#define BOARD_REV_DOGWOOD	"3"
+/* Could be ASPEN, BIRCH or CHESTNUT. assume CHESTNUT */
+#define BOARD_REV_UNKNOWN	BOARD_REV_CHESTNUT
+
+#ifdef CONFIG_DM_GPIO
+static inline void init_pinmux(void)
+{
+	gpio_request(WIFI_EN, "WIFI_EN");
+#ifdef CONSOLE_ON_UART4
+	gpio_direction_output(WIFI_EN, 1);
+#else
+	gpio_direction_output(WIFI_EN, 0);
+#endif /* CONSOLE_ON_UART4 */
+}
+#else
+static const iomux_v3_cfg_t configure_pads[] = {
+	IMX8MQ_PAD_GPIO1_IO00__GPIO1_IO0 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_GPIO1_IO03__GPIO1_IO3 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_GPIO1_IO04__GPIO1_IO4 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_GPIO1_IO05__GPIO1_IO5 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_GPIO1_IO06__GPIO1_IO6 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_GPIO1_IO11__GPIO1_IO11 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_GPIO1_IO12__GPIO1_IO12 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_GPIO1_IO14__GPIO1_IO14 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_ENET_MDC__GPIO1_IO16 | MUX_PAD_CTRL(PAD_CTL_PUE),
+	IMX8MQ_PAD_ENET_MDIO__GPIO1_IO17 | MUX_PAD_CTRL(PAD_CTL_PUE),
+	IMX8MQ_PAD_ENET_TD1__GPIO1_IO20 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_ENET_TXC__GPIO1_IO23 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_NAND_CE0_B__GPIO3_IO1 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_NAND_CE1_B__GPIO3_IO2 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_NAND_CE3_B__GPIO3_IO4 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_NAND_DATA04__GPIO3_IO10 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_NAND_DATA06__GPIO3_IO12 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_NAND_DQS__GPIO3_IO14 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_NAND_WP_B__GPIO3_IO18 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_SAI3_RXFS__GPIO4_IO28 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_SAI3_MCLK__GPIO5_IO2 | MUX_PAD_CTRL(PAD_CTL_DSE6),
+	IMX8MQ_PAD_SAI5_RXD3__GPIO3_IO24,
+};
+
+static inline void init_pinmux(void)
+{
+	imx_iomux_v3_setup_multiple_pads(configure_pads, ARRAY_SIZE(configure_pads));
+
+	gpio_request(LED_R, "LED_R");
+	gpio_request(LED_G, "LED_G");
+	gpio_request(LED_B, "LED_B");
+	gpio_request(VOL_UP, "VOL_UP");
+	gpio_request(VOL_DOWN, "VOL_DOWN");
+
+	gpio_request(NFC_EN, "NFC_EN");
+	gpio_request(CHG_EN, "CHG_EN");
+	gpio_request(CHG_OTG_OUT_EN, "CHG_OTG_OUT_EN");
+
+	gpio_request(TYPEC_MUX_EN, "TYPEC_MUX_EN");
+
+	gpio_request(TPS_RESET, "TPS_RESET");
+
+	gpio_request(WWAN_EN, "WWAN_EN");
+	gpio_request(WWAN_NRESET, "WWAN_NRESET");
+
+	gpio_request(HUB_EN, "HUB_EN");
+	gpio_request(HUB_NRESET, "HUB_NRESET");
+	gpio_request(SD_EN, "SD_EN");
+	gpio_request(AUDIO_EN, "AUDIO_EN");
+	gpio_request(DSI_EN, "DSI_EN");
+	gpio_request(SMC_EN, "SMC_EN");
+	gpio_request(CAMERA_EN, "CAMERA_EN");
+	gpio_request(FLASH_EN, "FLASH_EN");
+	gpio_request(DSI_BIAS_EN, "DSI_BIAS_EN");
+	gpio_request(GPS_EN, "GPS_EN");
+	gpio_request(BL_EN, "BL_EN");
+#ifndef CONSOLE_ON_UART4
+	gpio_request(WIFI_EN, "WIFI_EN");
+	gpio_direction_output(WIFI_EN, 0);
+#endif /* CONSOLE_ON_UART4 */
+	gpio_direction_input(VOL_UP);
+	gpio_direction_input(VOL_DOWN);
+
+	/* ensure charger is in the automated mode */
+	gpio_direction_output(NFC_EN, 0);
+	gpio_direction_output(CHG_EN, 0);
+	gpio_direction_output(CHG_OTG_OUT_EN, 0);
+
+	gpio_direction_input(TYPEC_MUX_EN);
+
+	gpio_direction_output(TPS_RESET, 0);
+
+	gpio_direction_output(WWAN_EN, 0);
+	gpio_direction_output(WWAN_NRESET, 1);
+
+	gpio_direction_output(HUB_EN, 0);
+	gpio_direction_output(HUB_NRESET, 1);
+	gpio_direction_output(SD_EN, 0);
+	gpio_direction_output(AUDIO_EN, 1);
+	gpio_direction_output(DSI_EN, 0);
+	gpio_direction_output(SMC_EN, 0);
+	gpio_direction_output(CAMERA_EN, 0);
+	gpio_direction_output(FLASH_EN, 0);
+	gpio_direction_output(DSI_BIAS_EN, 0);
+	gpio_direction_output(GPS_EN, 0);
+	gpio_direction_output(BL_EN, 0);
+}
+#endif /* CONFIG_DM_GPIO */
+
+#define USB_PHY_CTRL0			0xF0040
+#define USB_PHY_CTRL0_REF_SSP_EN	BIT(2)
+
+#define USB_PHY_CTRL1			0xF0044
+#define USB_PHY_CTRL1_RESET		BIT(0)
+#define USB_PHY_CTRL1_COMMONONN		BIT(1)
+#define USB_PHY_CTRL1_ATERESET		BIT(3)
+#define USB_PHY_CTRL1_VDATSRCENB0	BIT(19)
+#define USB_PHY_CTRL1_VDATDETENB0	BIT(20)
+
+#define USB_PHY_CTRL2			0xF0048
+#define USB_PHY_CTRL2_TXENABLEN0	BIT(8)
+
+extern struct dram_timing_info dram_timing_b0;
+extern int board_ecspi_init(void);
+
+#endif
diff --git a/board/purism/librem5/lpddr4_timing.c b/board/purism/librem5/lpddr4_timing.c
new file mode 100644
index 0000000000..46bc7f8591
--- /dev/null
+++ b/board/purism/librem5/lpddr4_timing.c
@@ -0,0 +1,1324 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <linux/kernel.h>
+#include <common.h>
+#include <asm/arch/ddr.h>
+#include <asm/arch/lpddr4_define.h>
+
+#define WR_POST_EXT_3200	/* recommened to define */
+
+struct dram_cfg_param lpddr4_ddrc_cfg[] = {
+	/* Start to config, default 3200mbps */
+	{ DDRC_DBG1(0), 0x00000001 },
+	{ DDRC_PWRCTL(0), 0x00000001 },
+	{ DDRC_MSTR(0), 0xa3080020 },
+	{ DDRC_MSTR2(0), 0x00000000 },
+	{ DDRC_RFSHTMG(0), 0x006100E0 },
+	{ DDRC_INIT0(0), 0xC003061B },
+	{ DDRC_INIT1(0), 0x009D0000 },
+	{ DDRC_INIT3(0), 0x00D4002D },
+#ifdef WR_POST_EXT_3200
+	{ DDRC_INIT4(0), 0x00330008 },
+#else
+	{ DDRC_INIT4(0), 0x00310008 },
+#endif
+	{ DDRC_INIT6(0), 0x0066004a },
+	{ DDRC_INIT7(0), 0x0006004a },
+
+	{ DDRC_DRAMTMG0(0), 0x1A201B22 },
+	{ DDRC_DRAMTMG1(0), 0x00060633 },
+	{ DDRC_DRAMTMG3(0), 0x00C0C000 },
+	{ DDRC_DRAMTMG4(0), 0x0F04080F },
+	{ DDRC_DRAMTMG5(0), 0x02040C0C },
+	{ DDRC_DRAMTMG6(0), 0x01010007 },
+	{ DDRC_DRAMTMG7(0), 0x00000401 },
+	{ DDRC_DRAMTMG12(0), 0x00020600 },
+	{ DDRC_DRAMTMG13(0), 0x0C100002 },
+	{ DDRC_DRAMTMG14(0), 0x000000E6 },
+	{ DDRC_DRAMTMG17(0), 0x00A00050 },
+
+	{ DDRC_ZQCTL0(0), 0x03200018 },
+	{ DDRC_ZQCTL1(0), 0x028061A8 },
+	{ DDRC_ZQCTL2(0), 0x00000000 },
+
+	{ DDRC_DFITMG0(0), 0x0497820A },
+	{ DDRC_DFITMG1(0), 0x00080303 },
+	{ DDRC_DFIUPD0(0), 0xE0400018 },
+	{ DDRC_DFIUPD1(0), 0x00DF00E4 },
+	{ DDRC_DFIUPD2(0), 0x80000000 },
+	{ DDRC_DFIMISC(0), 0x00000011 },
+	{ DDRC_DFITMG2(0), 0x0000170A },
+
+	{ DDRC_DBICTL(0), 0x00000001 },
+	{ DDRC_DFIPHYMSTR(0), 0x00000001 },
+	{ DDRC_RANKCTL(0), 0x00000c99 },
+	{ DDRC_DRAMTMG2(0), 0x070E171a },
+
+	/* address mapping */
+	{ DDRC_ADDRMAP0(0), 0x00000015 },
+	{ DDRC_ADDRMAP3(0), 0x00000000 },
+	{ DDRC_ADDRMAP4(0), 0x00001F1F },
+	/* bank interleave */
+	{ DDRC_ADDRMAP1(0), 0x00080808 },
+	{ DDRC_ADDRMAP5(0), 0x07070707 },
+	{ DDRC_ADDRMAP6(0), 0x08080707 },
+
+	/* performance setting */
+	{ DDRC_ODTCFG(0), 0x0b060908 },
+	{ DDRC_ODTMAP(0), 0x00000000 },
+	{ DDRC_SCHED(0), 0x29511505 },
+	{ DDRC_SCHED1(0), 0x0000002c },
+	{ DDRC_PERFHPR1(0), 0x5900575b },
+	/* 150T starve and 0x90 max tran len */
+	{ DDRC_PERFLPR1(0), 0x90000096 },
+	/* 300T starve and 0x10 max tran len */
+	{ DDRC_PERFWR1(0), 0x1000012c },
+	{ DDRC_DBG0(0), 0x00000016 },
+	{ DDRC_DBG1(0), 0x00000000 },
+	{ DDRC_DBGCMD(0), 0x00000000 },
+	{ DDRC_SWCTL(0), 0x00000001 },
+	{ DDRC_POISONCFG(0), 0x00000011 },
+	{ DDRC_PCCFG(0), 0x00000111 },
+	{ DDRC_PCFGR_0(0), 0x000010f3 },
+	{ DDRC_PCFGW_0(0), 0x000072ff },
+	{ DDRC_PCTRL_0(0), 0x00000001 },
+	/* disable Read Qos*/
+	{ DDRC_PCFGQOS0_0(0), 0x00000e00 },
+	{ DDRC_PCFGQOS1_0(0), 0x0062ffff },
+	/* disable Write Qos*/
+	{ DDRC_PCFGWQOS0_0(0), 0x00000e00 },
+	{ DDRC_PCFGWQOS1_0(0), 0x0000ffff },
+
+	/* Frequency 1: 400mbps */
+	{ DDRC_FREQ1_DRAMTMG0(0), 0x0d0b010c },
+	{ DDRC_FREQ1_DRAMTMG1(0), 0x00030410 },
+	{ DDRC_FREQ1_DRAMTMG2(0), 0x0305090c },
+	{ DDRC_FREQ1_DRAMTMG3(0), 0x00505006 },
+	{ DDRC_FREQ1_DRAMTMG4(0), 0x05040305 },
+	{ DDRC_FREQ1_DRAMTMG5(0), 0x0d0e0504 },
+	{ DDRC_FREQ1_DRAMTMG6(0), 0x0a060004 },
+	{ DDRC_FREQ1_DRAMTMG7(0), 0x0000090e },
+	{ DDRC_FREQ1_DRAMTMG14(0), 0x00000032 },
+	{ DDRC_FREQ1_DRAMTMG15(0), 0x00000000 },
+	{ DDRC_FREQ1_DRAMTMG17(0), 0x0036001b },
+	{ DDRC_FREQ1_DERATEINT(0), 0x7e9fbeb1 },
+	{ DDRC_FREQ1_DFITMG0(0), 0x03818200 },
+	{ DDRC_FREQ1_DFITMG2(0), 0x00000000 },
+	{ DDRC_FREQ1_RFSHTMG(0), 0x000C001c },
+	{ DDRC_FREQ1_INIT3(0), 0x00840000 },
+	{ DDRC_FREQ1_INIT4(0), 0x00310008 },
+	{ DDRC_FREQ1_INIT6(0), 0x0066004a },
+	{ DDRC_FREQ1_INIT7(0), 0x0006004a },
+
+	/* Frequency 2: 100mbps */
+	{ DDRC_FREQ2_DRAMTMG0(0), 0x0d0b010c },
+	{ DDRC_FREQ2_DRAMTMG1(0), 0x00030410 },
+	{ DDRC_FREQ2_DRAMTMG2(0), 0x0305090c },
+	{ DDRC_FREQ2_DRAMTMG3(0), 0x00505006 },
+	{ DDRC_FREQ2_DRAMTMG4(0), 0x05040305 },
+	{ DDRC_FREQ2_DRAMTMG5(0), 0x0d0e0504 },
+	{ DDRC_FREQ2_DRAMTMG6(0), 0x0a060004 },
+	{ DDRC_FREQ2_DRAMTMG7(0), 0x0000090e },
+	{ DDRC_FREQ2_DRAMTMG14(0), 0x00000032 },
+	{ DDRC_FREQ2_DRAMTMG17(0), 0x0036001b },
+	{ DDRC_FREQ2_DERATEINT(0), 0x7e9fbeb1 },
+	{ DDRC_FREQ2_DFITMG0(0), 0x03818200 },
+	{ DDRC_FREQ2_DFITMG2(0), 0x00000000 },
+	{ DDRC_FREQ2_RFSHTMG(0), 0x00030007 },
+	{ DDRC_FREQ2_INIT3(0), 0x00840000 },
+	{ DDRC_FREQ2_INIT4(0), 0x00310008 },
+	{ DDRC_FREQ2_INIT6(0), 0x0066004a },
+	{ DDRC_FREQ2_INIT7(0), 0x0006004a },
+};
+
+/* PHY Initialize Configuration */
+struct dram_cfg_param lpddr4_ddrphy_cfg[] = {
+	{ 0x20110, 0x02 },
+	{ 0x20111, 0x03 },
+	{ 0x20112, 0x04 },
+	{ 0x20113, 0x05 },
+	{ 0x20114, 0x00 },
+	{ 0x20115, 0x01 },
+
+	{ 0x1005f, 0x1ff },
+	{ 0x1015f, 0x1ff },
+	{ 0x1105f, 0x1ff },
+	{ 0x1115f, 0x1ff },
+	{ 0x1205f, 0x1ff },
+	{ 0x1215f, 0x1ff },
+	{ 0x1305f, 0x1ff },
+	{ 0x1315f, 0x1ff },
+
+	{ 0x11005f, 0x1ff },
+	{ 0x11015f, 0x1ff },
+	{ 0x11105f, 0x1ff },
+	{ 0x11115f, 0x1ff },
+	{ 0x11205f, 0x1ff },
+	{ 0x11215f, 0x1ff },
+	{ 0x11305f, 0x1ff },
+	{ 0x11315f, 0x1ff },
+
+	{ 0x21005f, 0x1ff },
+	{ 0x21015f, 0x1ff },
+	{ 0x21105f, 0x1ff },
+	{ 0x21115f, 0x1ff },
+	{ 0x21205f, 0x1ff },
+	{ 0x21215f, 0x1ff },
+	{ 0x21305f, 0x1ff },
+	{ 0x21315f, 0x1ff },
+
+	{ 0x55, 0x1ff },
+	{ 0x1055, 0x1ff },
+	{ 0x2055, 0x1ff },
+	{ 0x3055, 0x1ff },
+	{ 0x4055, 0x1ff },
+	{ 0x5055, 0x1ff },
+	{ 0x6055, 0x1ff },
+	{ 0x7055, 0x1ff },
+	{ 0x8055, 0x1ff },
+	{ 0x9055, 0x1ff },
+
+	{ 0x200c5, 0x19 },
+	{ 0x1200c5, 0x7 },
+	{ 0x2200c5, 0x7 },
+
+	{ 0x2002e, 0x2 },
+	{ 0x12002e, 0x2 },
+	{ 0x22002e, 0x2 },
+
+	{ 0x90204, 0x0 },
+	{ 0x190204, 0x0 },
+	{ 0x290204, 0x0 },
+
+#ifdef WR_POST_EXT_3200
+	{ 0x20024, 0xeb },
+#else
+	{ 0x20024, 0xab },
+#endif
+	{ 0x2003a, 0x0 },
+	{ 0x120024, 0xab },
+	{ 0x2003a, 0x0 },
+	{ 0x220024, 0xab },
+	{ 0x2003a, 0x0 },
+	{ 0x20056, 0x3 },
+	{ 0x120056, 0xa },
+	{ 0x220056, 0xa },
+	{ 0x1004d, 0xe00 },
+	{ 0x1014d, 0xe00 },
+	{ 0x1104d, 0xe00 },
+	{ 0x1114d, 0xe00 },
+	{ 0x1204d, 0xe00 },
+	{ 0x1214d, 0xe00 },
+	{ 0x1304d, 0xe00 },
+	{ 0x1314d, 0xe00 },
+	{ 0x11004d, 0xe00 },
+	{ 0x11014d, 0xe00 },
+	{ 0x11104d, 0xe00 },
+	{ 0x11114d, 0xe00 },
+	{ 0x11204d, 0xe00 },
+	{ 0x11214d, 0xe00 },
+	{ 0x11304d, 0xe00 },
+	{ 0x11314d, 0xe00 },
+	{ 0x21004d, 0xe00 },
+	{ 0x21014d, 0xe00 },
+	{ 0x21104d, 0xe00 },
+	{ 0x21114d, 0xe00 },
+	{ 0x21204d, 0xe00 },
+	{ 0x21214d, 0xe00 },
+	{ 0x21304d, 0xe00 },
+	{ 0x21314d, 0xe00 },
+
+	{ 0x10049, 0xfbe },
+	{ 0x10149, 0xfbe },
+	{ 0x11049, 0xfbe },
+	{ 0x11149, 0xfbe },
+	{ 0x12049, 0xfbe },
+	{ 0x12149, 0xfbe },
+	{ 0x13049, 0xfbe },
+	{ 0x13149, 0xfbe },
+	{ 0x110049, 0xfbe },
+	{ 0x110149, 0xfbe },
+	{ 0x111049, 0xfbe },
+	{ 0x111149, 0xfbe },
+	{ 0x112049, 0xfbe },
+	{ 0x112149, 0xfbe },
+	{ 0x113049, 0xfbe },
+	{ 0x113149, 0xfbe },
+	{ 0x210049, 0xfbe },
+	{ 0x210149, 0xfbe },
+	{ 0x211049, 0xfbe },
+	{ 0x211149, 0xfbe },
+	{ 0x212049, 0xfbe },
+	{ 0x212149, 0xfbe },
+	{ 0x213049, 0xfbe },
+	{ 0x213149, 0xfbe },
+
+	{ 0x43, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) },
+	{ 0x1043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) },
+	{ 0x2043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) },
+	{ 0x3043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) },
+	{ 0x4043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) },
+	{ 0x5043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) },
+	{ 0x6043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) },
+	{ 0x7043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) },
+	{ 0x8043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) },
+	{ 0x9043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) },
+
+	{ 0x20018, 0x3 },
+	{ 0x20075, 0x4 },
+	{ 0x20050, 0x0 },
+	{ 0x20008, 0x320 },
+	{ 0x120008, 0x64 },
+	{ 0x220008, 0x19 },
+	{ 0x20088, 0x9 },
+	{ 0x200b2, 0x104 },
+	{ 0x10043, 0x5a1 },
+	{ 0x10143, 0x5a1 },
+	{ 0x11043, 0x5a1 },
+	{ 0x11143, 0x5a1 },
+	{ 0x12043, 0x5a1 },
+	{ 0x12143, 0x5a1 },
+	{ 0x13043, 0x5a1 },
+	{ 0x13143, 0x5a1 },
+	{ 0x1200b2, 0x104 },
+	{ 0x110043, 0x5a1 },
+	{ 0x110143, 0x5a1 },
+	{ 0x111043, 0x5a1 },
+	{ 0x111143, 0x5a1 },
+	{ 0x112043, 0x5a1 },
+	{ 0x112143, 0x5a1 },
+	{ 0x113043, 0x5a1 },
+	{ 0x113143, 0x5a1 },
+	{ 0x2200b2, 0x104 },
+	{ 0x210043, 0x5a1 },
+	{ 0x210143, 0x5a1 },
+	{ 0x211043, 0x5a1 },
+	{ 0x211143, 0x5a1 },
+	{ 0x212043, 0x5a1 },
+	{ 0x212143, 0x5a1 },
+	{ 0x213043, 0x5a1 },
+	{ 0x213143, 0x5a1 },
+	{ 0x200fa, 0x1 },
+	{ 0x1200fa, 0x1 },
+	{ 0x2200fa, 0x1 },
+	{ 0x20019, 0x1 },
+	{ 0x120019, 0x1 },
+	{ 0x220019, 0x1 },
+	{ 0x200f0, 0x660 },
+	{ 0x200f1, 0x0 },
+	{ 0x200f2, 0x4444 },
+	{ 0x200f3, 0x8888 },
+	{ 0x200f4, 0x5665 },
+	{ 0x200f5, 0x0 },
+	{ 0x200f6, 0x0 },
+	{ 0x200f7, 0xf000 },
+	{ 0x20025, 0x0 },
+	{ 0x2002d, 0x0 },
+	{ 0x12002d, 0x0 },
+	{ 0x22002d, 0x0 },
+
+	{ 0x200c7, 0x80 },
+	{ 0x1200c7, 0x80 },
+	{ 0x2200c7, 0x80 },
+	{ 0x200ca, 0x106 },
+	{ 0x1200ca, 0x106 },
+	{ 0x2200ca, 0x106 },
+};
+
+/* P0 message block paremeter for training firmware */
+struct dram_cfg_param lpddr4_fsp0_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54000, 0x0 },
+	{ 0x54001, 0x0 },
+	{ 0x54002, 0x0 },
+	{ 0x54003, 0xc80 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT) }, /* PHY Ron/Rtt */
+	{ 0x54006, LPDDR4_PHY_VREF_VALUE },
+	{ 0x54007, 0x0 },
+	{ 0x54008, 0x131f },
+	{ 0x54009, LPDDR4_HDT_CTL_3200_1D },
+	{ 0x5400a, 0x0 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400c, 0x0 },
+	{ 0x5400d, (LPDDR4_CATRAIN_3200_1d << 8) },
+	{ 0x5400e, 0x0 },
+	{ 0x5400f, 0x0 },
+	{ 0x54010, 0x0 },
+	{ 0x54011, 0x0 },
+	{ 0x54012, 0x310 },
+	{ 0x54013, 0x0 },
+	{ 0x54014, 0x0 },
+	{ 0x54015, 0x0 },
+	{ 0x54016, 0x0 },
+	{ 0x54017, 0x0 },
+	{ 0x54018, 0x0 },
+
+	{ 0x54019, 0x2dd4 },
+#ifdef WR_POST_EXT_3200
+	{ 0x5401a, (((LPDDR4_RON) << 3) | 0x3) },
+#else
+	{ 0x5401a, (((LPDDR4_RON) << 3) | 0x1) },
+#endif
+	{ 0x5401b, ((LPDDR4_VREF_VALUE_CA << 8) |
+		    (LPDDR4_RTT_CA_BANK0 << 4) | LPDDR4_RTT_DQ) },
+	{ 0x5401c, ((LPDDR4_VREF_VALUE_DQ_RANK0 << 8) | 0x08) },
+	{ 0x5401d, 0x0 },
+	{ 0x5401e, LPDDR4_MR22_RANK0 },
+	{ 0x5401f, 0x2dd4 },
+#ifdef WR_POST_EXT_3200
+	{ 0x54020, (((LPDDR4_RON) << 3) | 0x3) },
+#else
+	{ 0x54020, (((LPDDR4_RON) << 3) | 0x1) },
+#endif
+	{ 0x54021, ((LPDDR4_VREF_VALUE_CA << 8) |
+		    (LPDDR4_RTT_CA_BANK1 << 4) | LPDDR4_RTT_DQ) },
+	{ 0x54022, ((LPDDR4_VREF_VALUE_DQ_RANK1 << 8) | 0x08) },
+	{ 0x54023, 0x0 },
+	{ 0x54024, LPDDR4_MR22_RANK1 },
+
+	{ 0x54025, 0x0 },
+	{ 0x54026, 0x0 },
+	{ 0x54027, 0x0 },
+	{ 0x54028, 0x0 },
+	{ 0x54029, 0x0 },
+	{ 0x5402a, 0x0 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x5402d, 0x0 },
+	{ 0x5402e, 0x0 },
+	{ 0x5402f, 0x0 },
+	{ 0x54030, 0x0 },
+	{ 0x54031, 0x0 },
+	{ 0x54032, 0xd400 },
+	/* MR3/MR2 */
+#ifdef WR_POST_EXT_3200
+	{ 0x54033, ((((LPDDR4_RON) << 3) | 0x3) << 8) | 0x2d /*0x312d*/ },
+#else
+	{ 0x54033, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x2d/*0x312d*/ },
+#endif
+	/* MR11/MR4 */
+	{ 0x54034, (((LPDDR4_RTT_CA_BANK0 << 4) | LPDDR4_RTT_DQ) << 8) },
+	/* self:0x284d//MR13/MR12 */
+	{ 0x54035, (0x0800 | LPDDR4_VREF_VALUE_CA)/*0x084d*/ },
+	/* MR16/MR14*/
+	{ 0x54036, LPDDR4_VREF_VALUE_DQ_RANK0/*0x4d*/ },
+	{ 0x54037, (LPDDR4_MR22_RANK0 << 8)/*0x500*/ },
+	/* MR1 */
+	{ 0x54038, 0xd400 },
+	/* MR3/MR2 */
+#ifdef WR_POST_EXT_3200
+	{ 0x54039, ((((LPDDR4_RON) << 3) | 0x3) << 8) | 0x2d/*0x312d*/ },
+#else
+	{ 0x54039, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x2d/*0x312d*/ },
+#endif
+	/* MR11/MR4 */
+	{ 0x5403a, (((LPDDR4_RTT_CA_BANK1 << 4) | LPDDR4_RTT_DQ) << 8) },
+	/* self:0x284d//MR13/MR12 */
+	{ 0x5403b, (0x0800 | LPDDR4_VREF_VALUE_CA)/*0x084d*/ },
+	/* MR16/MR14 */
+	{ 0x5403c, LPDDR4_VREF_VALUE_DQ_RANK1/*0x4d*/ },
+	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8)/*0x500*/ },
+	/* { 0x5403d, 0x500 } */
+	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8)/*0x500*/ },
+	{ 0x5403e, 0x0 },
+	{ 0x5403f, 0x0 },
+	{ 0x54040, 0x0 },
+	{ 0x54041, 0x0 },
+	{ 0x54042, 0x0 },
+	{ 0x54043, 0x0 },
+	{ 0x54044, 0x0 },
+	{ 0xd0000, 0x1 },
+};
+
+/* P1 message block paremeter for training firmware */
+struct dram_cfg_param lpddr4_fsp1_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54000, 0x0 },
+	{ 0x54001, 0x0 },
+	{ 0x54002, 0x101 },
+	{ 0x54003, 0x190 },
+	{ 0x54004, 0x2 },
+	/* PHY Ron/Rtt */
+	{ 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT)/*0x2828*/ },
+	{ 0x54006, LPDDR4_PHY_VREF_VALUE },
+	{ 0x54007, 0x0 },
+	{ 0x54008, LPDDR4_TRAIN_SEQ_400 },
+	{ 0x54009, LPDDR4_HDT_CTL_400_1D },
+	{ 0x5400a, 0x0 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400c, 0x0 },
+	{ 0x5400d, (LPDDR4_CATRAIN_400 << 8) },
+	{ 0x5400e, 0x0 },
+	{ 0x5400f, 0x0 },
+	{ 0x54010, 0x0 },
+	{ 0x54011, 0x0 },
+	{ 0x54012, 0x310 },
+	{ 0x54013, 0x0 },
+	{ 0x54014, 0x0 },
+	{ 0x54015, 0x0 },
+	{ 0x54016, 0x0 },
+	{ 0x54017, 0x0 },
+	{ 0x54018, 0x0 },
+	{ 0x54019, 0x84 },
+	/* MR4/MR3 */
+	{ 0x5401a, (((LPDDR4_RON) << 3) | 0x1)/*0x31*/ },
+	/* MR12/MR11 */
+	{ 0x5401b, ((LPDDR4_VREF_VALUE_CA << 8) | (LPDDR4_RTT_CA << 4) |
+		    LPDDR4_RTT_DQ)/*0x4d46*/ },
+	/* self:0x4d28//MR14/MR13 */
+	{ 0x5401c, ((LPDDR4_VREF_VALUE_DQ_RANK0 << 8) | 0x08)/*0x4d08*/ },
+	{ 0x5401d, 0x0 },
+	{ 0x5401e, LPDDR4_MR22_RANK0/*0x5*/ },
+	{ 0x5401f, 0x84 },
+	{ 0x54020, (((LPDDR4_RON) << 3) | 0x1)/*0x31*/ }, /* MR4/MR3 */
+	{ 0x54021, ((LPDDR4_VREF_VALUE_CA << 8) | (LPDDR4_RTT_CA << 4) |
+		    LPDDR4_RTT_DQ)/*0x4d46*/ },/* MR12/MR11 */
+	/* self:0x4d28//MR14/MR13 */
+	{ 0x54022, ((LPDDR4_VREF_VALUE_DQ_RANK1 << 8) | 0x08)/*0x4d08*/ },
+	{ 0x54023, 0x0 },
+	{ 0x54024, LPDDR4_MR22_RANK1 },
+	{ 0x54025, 0x0 },
+	{ 0x54026, 0x0 },
+	{ 0x54027, 0x0 },
+	{ 0x54028, 0x0 },
+	{ 0x54029, 0x0 },
+	{ 0x5402a, 0x0 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x5402d, 0x0 },
+	{ 0x5402e, 0x0 },
+	{ 0x5402f, 0x0 },
+	{ 0x54030, 0x0 },
+	{ 0x54031, 0x0 },
+	{ 0x54032, 0x8400 },
+	{ 0x54033, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x00 },
+	{ 0x54034, (((LPDDR4_RTT_CA << 4) | LPDDR4_RTT_DQ) << 8) },
+	{ 0x54035, (0x0800 | LPDDR4_VREF_VALUE_CA) },
+	{ 0x54036, LPDDR4_VREF_VALUE_DQ_RANK0 },
+	{ 0x54037, (LPDDR4_MR22_RANK0 << 8) },
+	{ 0x54038, 0x8400 },
+	{ 0x54039, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x00 },
+	{ 0x5403a, (((LPDDR4_RTT_CA << 4) | LPDDR4_RTT_DQ) << 8) },
+	{ 0x5403b, (0x0800 | LPDDR4_VREF_VALUE_CA) },
+	{ 0x5403c, LPDDR4_VREF_VALUE_DQ_RANK1 },
+	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8) },
+	{ 0x5403e, 0x0 },
+	{ 0x5403f, 0x0 },
+	{ 0x54040, 0x0 },
+	{ 0x54041, 0x0 },
+	{ 0x54042, 0x0 },
+	{ 0x54043, 0x0 },
+	{ 0x54044, 0x0 },
+	{ 0xd0000, 0x1 },
+};
+
+/* P2 message block paremeter for training firmware */
+struct dram_cfg_param lpddr4_fsp2_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54000, 0x0 },
+	{ 0x54001, 0x0 },
+	{ 0x54002, 0x102 },
+	{ 0x54003, 0x64 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT) },
+	{ 0x54006, LPDDR4_PHY_VREF_VALUE },
+	{ 0x54007, 0x0 },
+	{ 0x54008, LPDDR4_TRAIN_SEQ_100 },
+	{ 0x54009, LPDDR4_HDT_CTL_100_1D },
+	{ 0x5400a, 0x0 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400c, 0x0 },
+	{ 0x5400d, (LPDDR4_CATRAIN_100 << 8) },
+	{ 0x5400e, 0x0 },
+	{ 0x5400f, 0x0 },
+	{ 0x54010, 0x0 },
+	{ 0x54011, 0x0 },
+	{ 0x54012, 0x310 },
+	{ 0x54013, 0x0 },
+	{ 0x54014, 0x0 },
+	{ 0x54015, 0x0 },
+	{ 0x54016, 0x0 },
+	{ 0x54017, 0x0 },
+	{ 0x54018, 0x0 },
+	{ 0x54019, 0x84 },
+	{ 0x5401a, (((LPDDR4_RON) << 3) | 0x1) },
+	{ 0x5401b, ((LPDDR4_VREF_VALUE_CA << 8) | (LPDDR4_RTT_CA << 4) |
+		    LPDDR4_RTT_DQ) },
+	{ 0x5401c, ((LPDDR4_VREF_VALUE_DQ_RANK0 << 8) | 0x08) },
+	{ 0x5401d, 0x0 },
+	{ 0x5401e, LPDDR4_MR22_RANK0 },
+	{ 0x5401f, 0x84 },
+	{ 0x54020, (((LPDDR4_RON) << 3) | 0x1) },
+	{ 0x54021, ((LPDDR4_VREF_VALUE_CA << 8) | (LPDDR4_RTT_CA << 4) |
+		    LPDDR4_RTT_DQ) },
+	{ 0x54022, ((LPDDR4_VREF_VALUE_DQ_RANK1 << 8) | 0x08) },
+	{ 0x54023, 0x0 },
+	{ 0x54024, LPDDR4_MR22_RANK1 },
+	{ 0x54025, 0x0 },
+	{ 0x54026, 0x0 },
+	{ 0x54027, 0x0 },
+	{ 0x54028, 0x0 },
+	{ 0x54029, 0x0 },
+	{ 0x5402a, 0x0 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x5402d, 0x0 },
+	{ 0x5402e, 0x0 },
+	{ 0x5402f, 0x0 },
+	{ 0x54030, 0x0 },
+	{ 0x54031, 0x0 },
+	{ 0x54032, 0x8400 },
+	{ 0x54033, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x00 },
+	{ 0x54034, (((LPDDR4_RTT_CA << 4) | LPDDR4_RTT_DQ) << 8) },
+	{ 0x54035, (0x0800 | LPDDR4_VREF_VALUE_CA) },
+	{ 0x54036, LPDDR4_VREF_VALUE_DQ_RANK0 },
+	{ 0x54037, (LPDDR4_MR22_RANK0 << 8) },
+	{ 0x54038, 0x8400 },
+	{ 0x54039, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x00 },
+	{ 0x5403a, (((LPDDR4_RTT_CA << 4) | LPDDR4_RTT_DQ) << 8) },
+	{ 0x5403b, (0x0800 | LPDDR4_VREF_VALUE_CA) },
+	{ 0x5403c, LPDDR4_VREF_VALUE_DQ_RANK1 },
+	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8) },
+	{ 0x5403e, 0x0 },
+	{ 0x5403f, 0x0 },
+	{ 0x54040, 0x0 },
+	{ 0x54041, 0x0 },
+	{ 0x54042, 0x0 },
+	{ 0x54043, 0x0 },
+	{ 0x54044, 0x0 },
+	{ 0xd0000, 0x1 },
+};
+
+/* P0 2D message block paremeter for training firmware */
+struct dram_cfg_param lpddr4_fsp0_2d_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54000, 0x0 },
+	{ 0x54001, 0x0 },
+	{ 0x54002, 0x0 },
+	{ 0x54003, 0xc80 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT) },
+	{ 0x54006, LPDDR4_PHY_VREF_VALUE },
+	{ 0x54007, 0x0 },
+	{ 0x54008, 0x61 },
+	{ 0x54009, LPDDR4_HDT_CTL_2D },
+	{ 0x5400a, 0x0 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400c, 0x0 },
+	{ 0x5400d, (LPDDR4_CATRAIN_3200_2d << 8) },
+	{ 0x5400e, 0x0 },
+	{ 0x5400f, (LPDDR4_2D_SHARE << 8) | 0x00 },
+	{ 0x54010, LPDDR4_2D_WEIGHT },
+	{ 0x54011, 0x0 },
+	{ 0x54012, 0x310 },
+	{ 0x54013, 0x0 },
+	{ 0x54014, 0x0 },
+	{ 0x54015, 0x0 },
+	{ 0x54016, 0x0 },
+	{ 0x54017, 0x0 },
+	{ 0x54018, 0x0 },
+	{ 0x54019, 0x2dd4 },
+#ifdef WR_POST_EXT_3200
+	{ 0x5401a, (((LPDDR4_RON) << 3) | 0x3) },
+#else
+	{ 0x5401a, (((LPDDR4_RON) << 3) | 0x1) },
+#endif
+	{ 0x5401b, ((LPDDR4_VREF_VALUE_CA << 8) |
+		    (LPDDR4_RTT_CA_BANK0 << 4) | LPDDR4_RTT_DQ) },
+	{ 0x5401c, ((LPDDR4_VREF_VALUE_DQ_RANK0 << 8) | 0x08) },
+	{ 0x5401d, 0x0 },
+	{ 0x5401e, LPDDR4_MR22_RANK0 },
+	{ 0x5401f, 0x2dd4 },
+#ifdef WR_POST_EXT_3200
+	{ 0x54020, (((LPDDR4_RON) << 3) | 0x3) },
+#else
+	{ 0x54020, (((LPDDR4_RON) << 3) | 0x1) },
+#endif
+	{ 0x54021, ((LPDDR4_VREF_VALUE_CA << 8) |
+		    (LPDDR4_RTT_CA_BANK1 << 4) | LPDDR4_RTT_DQ) },
+	{ 0x54022, ((LPDDR4_VREF_VALUE_DQ_RANK1 << 8) | 0x08) },
+	{ 0x54023, 0x0 },
+	{ 0x54024, LPDDR4_MR22_RANK1 },
+	{ 0x54025, 0x0 },
+	{ 0x54026, 0x0 },
+	{ 0x54027, 0x0 },
+	{ 0x54028, 0x0 },
+	{ 0x54029, 0x0 },
+	{ 0x5402a, 0x0 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x5402d, 0x0 },
+	{ 0x5402e, 0x0 },
+	{ 0x5402f, 0x0 },
+	{ 0x54030, 0x0 },
+	{ 0x54031, 0x0 },
+
+	{ 0x54032, 0xd400 },
+#ifdef WR_POST_EXT_3200
+	{ 0x54033, ((((LPDDR4_RON) << 3) | 0x3) << 8) | 0x2d },
+#else
+	{ 0x54033, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x2d },
+#endif
+	{ 0x54034, (((LPDDR4_RTT_CA_BANK0 << 4) | LPDDR4_RTT_DQ) << 8) },
+	{ 0x54035, (0x0800 | LPDDR4_VREF_VALUE_CA) },
+	{ 0x54036, LPDDR4_VREF_VALUE_DQ_RANK0 },
+	{ 0x54037, (LPDDR4_MR22_RANK0 << 8) },
+	{ 0x54038, 0xd400 },
+#ifdef WR_POST_EXT_3200
+	{ 0x54039, ((((LPDDR4_RON) << 3) | 0x3) << 8) | 0x2d },
+#else
+	{ 0x54039, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x2d },
+#endif
+	{ 0x5403a, (((LPDDR4_RTT_CA_BANK1 << 4) | LPDDR4_RTT_DQ) << 8) },
+	{ 0x5403b, (0x0800 | LPDDR4_VREF_VALUE_CA) },
+	{ 0x5403c, LPDDR4_VREF_VALUE_DQ_RANK1 },
+	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8) },
+	{ 0x5403e, 0x0 },
+	{ 0x5403f, 0x0 },
+	{ 0x54040, 0x0 },
+	{ 0x54041, 0x0 },
+	{ 0x54042, 0x0 },
+	{ 0x54043, 0x0 },
+	{ 0x54044, 0x0 },
+	{ 0xd0000, 0x1 },
+};
+
+/* DRAM PHY init engine image */
+struct dram_cfg_param lpddr4_phy_pie[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x90000, 0x10 },
+	{ 0x90001, 0x400 },
+	{ 0x90002, 0x10e },
+	{ 0x90003, 0x0 },
+	{ 0x90004, 0x0 },
+	{ 0x90005, 0x8 },
+	{ 0x90029, 0xb },
+	{ 0x9002a, 0x480 },
+	{ 0x9002b, 0x109 },
+	{ 0x9002c, 0x8 },
+	{ 0x9002d, 0x448 },
+	{ 0x9002e, 0x139 },
+	{ 0x9002f, 0x8 },
+	{ 0x90030, 0x478 },
+	{ 0x90031, 0x109 },
+	{ 0x90032, 0x0 },
+	{ 0x90033, 0xe8 },
+	{ 0x90034, 0x109 },
+	{ 0x90035, 0x2 },
+	{ 0x90036, 0x10 },
+	{ 0x90037, 0x139 },
+	{ 0x90038, 0xf },
+	{ 0x90039, 0x7c0 },
+	{ 0x9003a, 0x139 },
+	{ 0x9003b, 0x44 },
+	{ 0x9003c, 0x630 },
+	{ 0x9003d, 0x159 },
+	{ 0x9003e, 0x14f },
+	{ 0x9003f, 0x630 },
+	{ 0x90040, 0x159 },
+	{ 0x90041, 0x47 },
+	{ 0x90042, 0x630 },
+	{ 0x90043, 0x149 },
+	{ 0x90044, 0x4f },
+	{ 0x90045, 0x630 },
+	{ 0x90046, 0x179 },
+	{ 0x90047, 0x8 },
+	{ 0x90048, 0xe0 },
+	{ 0x90049, 0x109 },
+	{ 0x9004a, 0x0 },
+	{ 0x9004b, 0x7c8 },
+	{ 0x9004c, 0x109 },
+	{ 0x9004d, 0x0 },
+	{ 0x9004e, 0x1 },
+	{ 0x9004f, 0x8 },
+	{ 0x90050, 0x0 },
+	{ 0x90051, 0x45a },
+	{ 0x90052, 0x9 },
+	{ 0x90053, 0x0 },
+	{ 0x90054, 0x448 },
+	{ 0x90055, 0x109 },
+	{ 0x90056, 0x40 },
+	{ 0x90057, 0x630 },
+	{ 0x90058, 0x179 },
+	{ 0x90059, 0x1 },
+	{ 0x9005a, 0x618 },
+	{ 0x9005b, 0x109 },
+	{ 0x9005c, 0x40c0 },
+	{ 0x9005d, 0x630 },
+	{ 0x9005e, 0x149 },
+	{ 0x9005f, 0x8 },
+	{ 0x90060, 0x4 },
+	{ 0x90061, 0x48 },
+	{ 0x90062, 0x4040 },
+	{ 0x90063, 0x630 },
+	{ 0x90064, 0x149 },
+	{ 0x90065, 0x0 },
+	{ 0x90066, 0x4 },
+	{ 0x90067, 0x48 },
+	{ 0x90068, 0x40 },
+	{ 0x90069, 0x630 },
+	{ 0x9006a, 0x149 },
+	{ 0x9006b, 0x10 },
+	{ 0x9006c, 0x4 },
+	{ 0x9006d, 0x18 },
+	{ 0x9006e, 0x0 },
+	{ 0x9006f, 0x4 },
+	{ 0x90070, 0x78 },
+	{ 0x90071, 0x549 },
+	{ 0x90072, 0x630 },
+	{ 0x90073, 0x159 },
+	{ 0x90074, 0xd49 },
+	{ 0x90075, 0x630 },
+	{ 0x90076, 0x159 },
+	{ 0x90077, 0x94a },
+	{ 0x90078, 0x630 },
+	{ 0x90079, 0x159 },
+	{ 0x9007a, 0x441 },
+	{ 0x9007b, 0x630 },
+	{ 0x9007c, 0x149 },
+	{ 0x9007d, 0x42 },
+	{ 0x9007e, 0x630 },
+	{ 0x9007f, 0x149 },
+	{ 0x90080, 0x1 },
+	{ 0x90081, 0x630 },
+	{ 0x90082, 0x149 },
+	{ 0x90083, 0x0 },
+	{ 0x90084, 0xe0 },
+	{ 0x90085, 0x109 },
+	{ 0x90086, 0xa },
+	{ 0x90087, 0x10 },
+	{ 0x90088, 0x109 },
+	{ 0x90089, 0x9 },
+	{ 0x9008a, 0x3c0 },
+	{ 0x9008b, 0x149 },
+	{ 0x9008c, 0x9 },
+	{ 0x9008d, 0x3c0 },
+	{ 0x9008e, 0x159 },
+	{ 0x9008f, 0x18 },
+	{ 0x90090, 0x10 },
+	{ 0x90091, 0x109 },
+	{ 0x90092, 0x0 },
+	{ 0x90093, 0x3c0 },
+	{ 0x90094, 0x109 },
+	{ 0x90095, 0x18 },
+	{ 0x90096, 0x4 },
+	{ 0x90097, 0x48 },
+	{ 0x90098, 0x18 },
+	{ 0x90099, 0x4 },
+	{ 0x9009a, 0x58 },
+	{ 0x9009b, 0xa },
+	{ 0x9009c, 0x10 },
+	{ 0x9009d, 0x109 },
+	{ 0x9009e, 0x2 },
+	{ 0x9009f, 0x10 },
+	{ 0x900a0, 0x109 },
+	{ 0x900a1, 0x5 },
+	{ 0x900a2, 0x7c0 },
+	{ 0x900a3, 0x109 },
+	{ 0x900a4, 0x10 },
+	{ 0x900a5, 0x10 },
+	{ 0x900a6, 0x109 },
+	{ 0x40000, 0x811 },
+	{ 0x40020, 0x880 },
+	{ 0x40040, 0x0 },
+	{ 0x40060, 0x0 },
+	{ 0x40001, 0x4008 },
+	{ 0x40021, 0x83 },
+	{ 0x40041, 0x4f },
+	{ 0x40061, 0x0 },
+	{ 0x40002, 0x4040 },
+	{ 0x40022, 0x83 },
+	{ 0x40042, 0x51 },
+	{ 0x40062, 0x0 },
+	{ 0x40003, 0x811 },
+	{ 0x40023, 0x880 },
+	{ 0x40043, 0x0 },
+	{ 0x40063, 0x0 },
+	{ 0x40004, 0x720 },
+	{ 0x40024, 0xf },
+	{ 0x40044, 0x1740 },
+	{ 0x40064, 0x0 },
+	{ 0x40005, 0x16 },
+	{ 0x40025, 0x83 },
+	{ 0x40045, 0x4b },
+	{ 0x40065, 0x0 },
+	{ 0x40006, 0x716 },
+	{ 0x40026, 0xf },
+	{ 0x40046, 0x2001 },
+	{ 0x40066, 0x0 },
+	{ 0x40007, 0x716 },
+	{ 0x40027, 0xf },
+	{ 0x40047, 0x2800 },
+	{ 0x40067, 0x0 },
+	{ 0x40008, 0x716 },
+	{ 0x40028, 0xf },
+	{ 0x40048, 0xf00 },
+	{ 0x40068, 0x0 },
+	{ 0x40009, 0x720 },
+	{ 0x40029, 0xf },
+	{ 0x40049, 0x1400 },
+	{ 0x40069, 0x0 },
+	{ 0x4000a, 0xe08 },
+	{ 0x4002a, 0xc15 },
+	{ 0x4004a, 0x0 },
+	{ 0x4006a, 0x0 },
+	{ 0x4000b, 0x623 },
+	{ 0x4002b, 0x15 },
+	{ 0x4004b, 0x0 },
+	{ 0x4006b, 0x0 },
+	{ 0x4000c, 0x4028 },
+	{ 0x4002c, 0x80 },
+	{ 0x4004c, 0x0 },
+	{ 0x4006c, 0x0 },
+	{ 0x4000d, 0xe08 },
+	{ 0x4002d, 0xc1a },
+	{ 0x4004d, 0x0 },
+	{ 0x4006d, 0x0 },
+	{ 0x4000e, 0x623 },
+	{ 0x4002e, 0x1a },
+	{ 0x4004e, 0x0 },
+	{ 0x4006e, 0x0 },
+	{ 0x4000f, 0x4040 },
+	{ 0x4002f, 0x80 },
+	{ 0x4004f, 0x0 },
+	{ 0x4006f, 0x0 },
+	{ 0x40010, 0x2604 },
+	{ 0x40030, 0x15 },
+	{ 0x40050, 0x0 },
+	{ 0x40070, 0x0 },
+	{ 0x40011, 0x708 },
+	{ 0x40031, 0x5 },
+	{ 0x40051, 0x0 },
+	{ 0x40071, 0x2002 },
+	{ 0x40012, 0x8 },
+	{ 0x40032, 0x80 },
+	{ 0x40052, 0x0 },
+	{ 0x40072, 0x0 },
+	{ 0x40013, 0x2604 },
+	{ 0x40033, 0x1a },
+	{ 0x40053, 0x0 },
+	{ 0x40073, 0x0 },
+	{ 0x40014, 0x708 },
+	{ 0x40034, 0xa },
+	{ 0x40054, 0x0 },
+	{ 0x40074, 0x2002 },
+	{ 0x40015, 0x4040 },
+	{ 0x40035, 0x80 },
+	{ 0x40055, 0x0 },
+	{ 0x40075, 0x0 },
+	{ 0x40016, 0x60a },
+	{ 0x40036, 0x15 },
+	{ 0x40056, 0x1200 },
+	{ 0x40076, 0x0 },
+	{ 0x40017, 0x61a },
+	{ 0x40037, 0x15 },
+	{ 0x40057, 0x1300 },
+	{ 0x40077, 0x0 },
+	{ 0x40018, 0x60a },
+	{ 0x40038, 0x1a },
+	{ 0x40058, 0x1200 },
+	{ 0x40078, 0x0 },
+	{ 0x40019, 0x642 },
+	{ 0x40039, 0x1a },
+	{ 0x40059, 0x1300 },
+	{ 0x40079, 0x0 },
+	{ 0x4001a, 0x4808 },
+	{ 0x4003a, 0x880 },
+	{ 0x4005a, 0x0 },
+	{ 0x4007a, 0x0 },
+	{ 0x900a7, 0x0 },
+	{ 0x900a8, 0x790 },
+	{ 0x900a9, 0x11a },
+	{ 0x900aa, 0x8 },
+	{ 0x900ab, 0x7aa },
+	{ 0x900ac, 0x2a },
+	{ 0x900ad, 0x10 },
+	{ 0x900ae, 0x7b2 },
+	{ 0x900af, 0x2a },
+	{ 0x900b0, 0x0 },
+	{ 0x900b1, 0x7c8 },
+	{ 0x900b2, 0x109 },
+	{ 0x900b3, 0x10 },
+	{ 0x900b4, 0x2a8 },
+	{ 0x900b5, 0x129 },
+	{ 0x900b6, 0x8 },
+	{ 0x900b7, 0x370 },
+	{ 0x900b8, 0x129 },
+	{ 0x900b9, 0xa },
+	{ 0x900ba, 0x3c8 },
+	{ 0x900bb, 0x1a9 },
+	{ 0x900bc, 0xc },
+	{ 0x900bd, 0x408 },
+	{ 0x900be, 0x199 },
+	{ 0x900bf, 0x14 },
+	{ 0x900c0, 0x790 },
+	{ 0x900c1, 0x11a },
+	{ 0x900c2, 0x8 },
+	{ 0x900c3, 0x4 },
+	{ 0x900c4, 0x18 },
+	{ 0x900c5, 0xe },
+	{ 0x900c6, 0x408 },
+	{ 0x900c7, 0x199 },
+	{ 0x900c8, 0x8 },
+	{ 0x900c9, 0x8568 },
+	{ 0x900ca, 0x108 },
+	{ 0x900cb, 0x18 },
+	{ 0x900cc, 0x790 },
+	{ 0x900cd, 0x16a },
+	{ 0x900ce, 0x8 },
+	{ 0x900cf, 0x1d8 },
+	{ 0x900d0, 0x169 },
+	{ 0x900d1, 0x10 },
+	{ 0x900d2, 0x8558 },
+	{ 0x900d3, 0x168 },
+	{ 0x900d4, 0x70 },
+	{ 0x900d5, 0x788 },
+	{ 0x900d6, 0x16a },
+	{ 0x900d7, 0x1ff8 },
+	{ 0x900d8, 0x85a8 },
+	{ 0x900d9, 0x1e8 },
+	{ 0x900da, 0x50 },
+	{ 0x900db, 0x798 },
+	{ 0x900dc, 0x16a },
+	{ 0x900dd, 0x60 },
+	{ 0x900de, 0x7a0 },
+	{ 0x900df, 0x16a },
+	{ 0x900e0, 0x8 },
+	{ 0x900e1, 0x8310 },
+	{ 0x900e2, 0x168 },
+	{ 0x900e3, 0x8 },
+	{ 0x900e4, 0xa310 },
+	{ 0x900e5, 0x168 },
+	{ 0x900e6, 0xa },
+	{ 0x900e7, 0x408 },
+	{ 0x900e8, 0x169 },
+	{ 0x900e9, 0x6e },
+	{ 0x900ea, 0x0 },
+	{ 0x900eb, 0x68 },
+	{ 0x900ec, 0x0 },
+	{ 0x900ed, 0x408 },
+	{ 0x900ee, 0x169 },
+	{ 0x900ef, 0x0 },
+	{ 0x900f0, 0x8310 },
+	{ 0x900f1, 0x168 },
+	{ 0x900f2, 0x0 },
+	{ 0x900f3, 0xa310 },
+	{ 0x900f4, 0x168 },
+	{ 0x900f5, 0x1ff8 },
+	{ 0x900f6, 0x85a8 },
+	{ 0x900f7, 0x1e8 },
+	{ 0x900f8, 0x68 },
+	{ 0x900f9, 0x798 },
+	{ 0x900fa, 0x16a },
+	{ 0x900fb, 0x78 },
+	{ 0x900fc, 0x7a0 },
+	{ 0x900fd, 0x16a },
+	{ 0x900fe, 0x68 },
+	{ 0x900ff, 0x790 },
+	{ 0x90100, 0x16a },
+	{ 0x90101, 0x8 },
+	{ 0x90102, 0x8b10 },
+	{ 0x90103, 0x168 },
+	{ 0x90104, 0x8 },
+	{ 0x90105, 0xab10 },
+	{ 0x90106, 0x168 },
+	{ 0x90107, 0xa },
+	{ 0x90108, 0x408 },
+	{ 0x90109, 0x169 },
+	{ 0x9010a, 0x58 },
+	{ 0x9010b, 0x0 },
+	{ 0x9010c, 0x68 },
+	{ 0x9010d, 0x0 },
+	{ 0x9010e, 0x408 },
+	{ 0x9010f, 0x169 },
+	{ 0x90110, 0x0 },
+	{ 0x90111, 0x8b10 },
+	{ 0x90112, 0x168 },
+	{ 0x90113, 0x0 },
+	{ 0x90114, 0xab10 },
+	{ 0x90115, 0x168 },
+	{ 0x90116, 0x0 },
+	{ 0x90117, 0x1d8 },
+	{ 0x90118, 0x169 },
+	{ 0x90119, 0x80 },
+	{ 0x9011a, 0x790 },
+	{ 0x9011b, 0x16a },
+	{ 0x9011c, 0x18 },
+	{ 0x9011d, 0x7aa },
+	{ 0x9011e, 0x6a },
+	{ 0x9011f, 0xa },
+	{ 0x90120, 0x0 },
+	{ 0x90121, 0x1e9 },
+	{ 0x90122, 0x8 },
+	{ 0x90123, 0x8080 },
+	{ 0x90124, 0x108 },
+	{ 0x90125, 0xf },
+	{ 0x90126, 0x408 },
+	{ 0x90127, 0x169 },
+	{ 0x90128, 0xc },
+	{ 0x90129, 0x0 },
+	{ 0x9012a, 0x68 },
+	{ 0x9012b, 0x9 },
+	{ 0x9012c, 0x0 },
+	{ 0x9012d, 0x1a9 },
+	{ 0x9012e, 0x0 },
+	{ 0x9012f, 0x408 },
+	{ 0x90130, 0x169 },
+	{ 0x90131, 0x0 },
+	{ 0x90132, 0x8080 },
+	{ 0x90133, 0x108 },
+	{ 0x90134, 0x8 },
+	{ 0x90135, 0x7aa },
+	{ 0x90136, 0x6a },
+	{ 0x90137, 0x0 },
+	{ 0x90138, 0x8568 },
+	{ 0x90139, 0x108 },
+	{ 0x9013a, 0xb7 },
+	{ 0x9013b, 0x790 },
+	{ 0x9013c, 0x16a },
+	{ 0x9013d, 0x1f },
+	{ 0x9013e, 0x0 },
+	{ 0x9013f, 0x68 },
+	{ 0x90140, 0x8 },
+	{ 0x90141, 0x8558 },
+	{ 0x90142, 0x168 },
+	{ 0x90143, 0xf },
+	{ 0x90144, 0x408 },
+	{ 0x90145, 0x169 },
+	{ 0x90146, 0xc },
+	{ 0x90147, 0x0 },
+	{ 0x90148, 0x68 },
+	{ 0x90149, 0x0 },
+	{ 0x9014a, 0x408 },
+	{ 0x9014b, 0x169 },
+	{ 0x9014c, 0x0 },
+	{ 0x9014d, 0x8558 },
+	{ 0x9014e, 0x168 },
+	{ 0x9014f, 0x8 },
+	{ 0x90150, 0x3c8 },
+	{ 0x90151, 0x1a9 },
+	{ 0x90152, 0x3 },
+	{ 0x90153, 0x370 },
+	{ 0x90154, 0x129 },
+	{ 0x90155, 0x20 },
+	{ 0x90156, 0x2aa },
+	{ 0x90157, 0x9 },
+	{ 0x90158, 0x0 },
+	{ 0x90159, 0x400 },
+	{ 0x9015a, 0x10e },
+	{ 0x9015b, 0x8 },
+	{ 0x9015c, 0xe8 },
+	{ 0x9015d, 0x109 },
+	{ 0x9015e, 0x0 },
+	{ 0x9015f, 0x8140 },
+	{ 0x90160, 0x10c },
+	{ 0x90161, 0x10 },
+	{ 0x90162, 0x8138 },
+	{ 0x90163, 0x10c },
+	{ 0x90164, 0x8 },
+	{ 0x90165, 0x7c8 },
+	{ 0x90166, 0x101 },
+	{ 0x90167, 0x8 },
+	{ 0x90168, 0x0 },
+	{ 0x90169, 0x8 },
+	{ 0x9016a, 0x8 },
+	{ 0x9016b, 0x448 },
+	{ 0x9016c, 0x109 },
+	{ 0x9016d, 0xf },
+	{ 0x9016e, 0x7c0 },
+	{ 0x9016f, 0x109 },
+	{ 0x90170, 0x0 },
+	{ 0x90171, 0xe8 },
+	{ 0x90172, 0x109 },
+	{ 0x90173, 0x47 },
+	{ 0x90174, 0x630 },
+	{ 0x90175, 0x109 },
+	{ 0x90176, 0x8 },
+	{ 0x90177, 0x618 },
+	{ 0x90178, 0x109 },
+	{ 0x90179, 0x8 },
+	{ 0x9017a, 0xe0 },
+	{ 0x9017b, 0x109 },
+	{ 0x9017c, 0x0 },
+	{ 0x9017d, 0x7c8 },
+	{ 0x9017e, 0x109 },
+	{ 0x9017f, 0x8 },
+	{ 0x90180, 0x8140 },
+	{ 0x90181, 0x10c },
+	{ 0x90182, 0x0 },
+	{ 0x90183, 0x1 },
+	{ 0x90184, 0x8 },
+	{ 0x90185, 0x8 },
+	{ 0x90186, 0x4 },
+	{ 0x90187, 0x8 },
+	{ 0x90188, 0x8 },
+	{ 0x90189, 0x7c8 },
+	{ 0x9018a, 0x101 },
+	{ 0x90006, 0x0 },
+	{ 0x90007, 0x0 },
+	{ 0x90008, 0x8 },
+	{ 0x90009, 0x0 },
+	{ 0x9000a, 0x0 },
+	{ 0x9000b, 0x0 },
+	{ 0xd00e7, 0x400 },
+	{ 0x90017, 0x0 },
+	{ 0x9001f, 0x2a },
+	{ 0x90026, 0x6a },
+	{ 0x400d0, 0x0 },
+	{ 0x400d1, 0x101 },
+	{ 0x400d2, 0x105 },
+	{ 0x400d3, 0x107 },
+	{ 0x400d4, 0x10f },
+	{ 0x400d5, 0x202 },
+	{ 0x400d6, 0x20a },
+	{ 0x400d7, 0x20b },
+	{ 0x2003a, 0x2 },
+	{ 0x2000b, 0x64 },
+	{ 0x2000c, 0xc8 },
+	{ 0x2000d, 0x7d0 },
+	{ 0x2000e, 0x2c },
+	{ 0x12000b, 0xc },
+	{ 0x12000c, 0x19 },
+	{ 0x12000d, 0xfa },
+	{ 0x12000e, 0x10 },
+	{ 0x22000b, 0x3 },
+	{ 0x22000c, 0x6 },
+	{ 0x22000d, 0x3e },
+	{ 0x22000e, 0x10 },
+	{ 0x9000c, 0x0 },
+	{ 0x9000d, 0x173 },
+	{ 0x9000e, 0x60 },
+	{ 0x9000f, 0x6110 },
+	{ 0x90010, 0x2152 },
+	{ 0x90011, 0xdfbd },
+	{ 0x90012, 0x60 },
+	{ 0x90013, 0x6152 },
+	{ 0x20010, 0x5a },
+	{ 0x20011, 0x3 },
+	{ 0x40080, 0xe0 },
+	{ 0x40081, 0x12 },
+	{ 0x40082, 0xe0 },
+	{ 0x40083, 0x12 },
+	{ 0x40084, 0xe0 },
+	{ 0x40085, 0x12 },
+	{ 0x140080, 0xe0 },
+	{ 0x140081, 0x12 },
+	{ 0x140082, 0xe0 },
+	{ 0x140083, 0x12 },
+	{ 0x140084, 0xe0 },
+	{ 0x140085, 0x12 },
+	{ 0x240080, 0xe0 },
+	{ 0x240081, 0x12 },
+	{ 0x240082, 0xe0 },
+	{ 0x240083, 0x12 },
+	{ 0x240084, 0xe0 },
+	{ 0x240085, 0x12 },
+	{ 0x400fd, 0xf },
+	{ 0x10011, 0x1 },
+	{ 0x10012, 0x1 },
+	{ 0x10013, 0x180 },
+	{ 0x10018, 0x1 },
+	{ 0x10002, 0x6209 },
+	{ 0x100b2, 0x1 },
+	{ 0x101b4, 0x1 },
+	{ 0x102b4, 0x1 },
+	{ 0x103b4, 0x1 },
+	{ 0x104b4, 0x1 },
+	{ 0x105b4, 0x1 },
+	{ 0x106b4, 0x1 },
+	{ 0x107b4, 0x1 },
+	{ 0x108b4, 0x1 },
+	{ 0x11011, 0x1 },
+	{ 0x11012, 0x1 },
+	{ 0x11013, 0x180 },
+	{ 0x11018, 0x1 },
+	{ 0x11002, 0x6209 },
+	{ 0x110b2, 0x1 },
+	{ 0x111b4, 0x1 },
+	{ 0x112b4, 0x1 },
+	{ 0x113b4, 0x1 },
+	{ 0x114b4, 0x1 },
+	{ 0x115b4, 0x1 },
+	{ 0x116b4, 0x1 },
+	{ 0x117b4, 0x1 },
+	{ 0x118b4, 0x1 },
+	{ 0x12011, 0x1 },
+	{ 0x12012, 0x1 },
+	{ 0x12013, 0x180 },
+	{ 0x12018, 0x1 },
+	{ 0x12002, 0x6209 },
+	{ 0x120b2, 0x1 },
+	{ 0x121b4, 0x1 },
+	{ 0x122b4, 0x1 },
+	{ 0x123b4, 0x1 },
+	{ 0x124b4, 0x1 },
+	{ 0x125b4, 0x1 },
+	{ 0x126b4, 0x1 },
+	{ 0x127b4, 0x1 },
+	{ 0x128b4, 0x1 },
+	{ 0x13011, 0x1 },
+	{ 0x13012, 0x1 },
+	{ 0x13013, 0x180 },
+	{ 0x13018, 0x1 },
+	{ 0x13002, 0x6209 },
+	{ 0x130b2, 0x1 },
+	{ 0x131b4, 0x1 },
+	{ 0x132b4, 0x1 },
+	{ 0x133b4, 0x1 },
+	{ 0x134b4, 0x1 },
+	{ 0x135b4, 0x1 },
+	{ 0x136b4, 0x1 },
+	{ 0x137b4, 0x1 },
+	{ 0x138b4, 0x1 },
+	{ 0x2003a, 0x2 },
+	{ 0xc0080, 0x2 },
+	{ 0xd0000, 0x1 },
+};
+
+struct dram_fsp_msg lpddr4_dram_fsp_msg[] = {
+	{
+		/* P0 3200mts 1D */
+		.drate = 3200,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = lpddr4_fsp0_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp0_cfg),
+	},
+	{
+		/* P1 400mts 1D */
+		.drate = 400,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = lpddr4_fsp1_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp1_cfg),
+	},
+	{
+		/* P1 100mts 1D */
+		.drate = 100,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = lpddr4_fsp2_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp2_cfg),
+	},
+	{
+		/* P0 3200mts 2D */
+		.drate = 3200,
+		.fw_type = FW_2D_IMAGE,
+		.fsp_cfg = lpddr4_fsp0_2d_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp0_2d_cfg),
+	},
+};
+
+/* lpddr4 timing config params on EVK board */
+struct dram_timing_info dram_timing = {
+	.ddrc_cfg = lpddr4_ddrc_cfg,
+	.ddrc_cfg_num = ARRAY_SIZE(lpddr4_ddrc_cfg),
+	.ddrphy_cfg = lpddr4_ddrphy_cfg,
+	.ddrphy_cfg_num = ARRAY_SIZE(lpddr4_ddrphy_cfg),
+	.fsp_msg = lpddr4_dram_fsp_msg,
+	.fsp_msg_num = ARRAY_SIZE(lpddr4_dram_fsp_msg),
+	.ddrphy_pie = lpddr4_phy_pie,
+	.ddrphy_pie_num = ARRAY_SIZE(lpddr4_phy_pie),
+	.fsp_table = { 3200, 400, 100, },
+};
diff --git a/board/purism/librem5/lpddr4_timing_b0.c b/board/purism/librem5/lpddr4_timing_b0.c
new file mode 100644
index 0000000000..ec68edaf69
--- /dev/null
+++ b/board/purism/librem5/lpddr4_timing_b0.c
@@ -0,0 +1,1191 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <linux/kernel.h>
+#include <common.h>
+#include <asm/arch/ddr.h>
+#include <asm/arch/lpddr4_define.h>
+
+#define WR_POST_EXT_3200  /* recommened to define */
+
+static struct dram_cfg_param lpddr4_ddrc_cfg[] = {
+	/* Start to config, default 3200mbps */
+	/* dis_dq=1, indicates no reads or writes are issued to SDRAM */
+	{ DDRC_DBG1(0), 0x00000001 },
+	/* selfref_en=1, SDRAM enter self-refresh state */
+	{ DDRC_PWRCTL(0), 0x00000001 },
+	{ DDRC_MSTR(0), 0xa3080020 },
+	{ DDRC_MSTR2(0), 0x00000000 },
+	{ DDRC_RFSHTMG(0), 0x006100E0 },
+	{ DDRC_INIT0(0), 0xC003061B },
+	{ DDRC_INIT1(0), 0x009D0000 },
+	{ DDRC_INIT3(0), 0x00D4002D },
+#ifdef WR_POST_EXT_3200  /* recommened to define */
+	{ DDRC_INIT4(0), 0x00330008 },
+#else
+	{ DDRC_INIT4(0), 0x00310008 },
+#endif
+	{ DDRC_INIT6(0), 0x0066004a },
+	{ DDRC_INIT7(0), 0x0006004a },
+
+	{ DDRC_DRAMTMG0(0), 0x1A201B22 },
+	{ DDRC_DRAMTMG1(0), 0x00060633 },
+	{ DDRC_DRAMTMG3(0), 0x00C0C000 },
+	{ DDRC_DRAMTMG4(0), 0x0F04080F },
+	{ DDRC_DRAMTMG5(0), 0x02040C0C },
+	{ DDRC_DRAMTMG6(0), 0x01010007 },
+	{ DDRC_DRAMTMG7(0), 0x00000401 },
+	{ DDRC_DRAMTMG12(0), 0x00020600 },
+	{ DDRC_DRAMTMG13(0), 0x0C100002 },
+	{ DDRC_DRAMTMG14(0), 0x000000E6 },
+	{ DDRC_DRAMTMG17(0), 0x00A00050 },
+
+	{ DDRC_ZQCTL0(0), 0x03200018 },
+	{ DDRC_ZQCTL1(0), 0x028061A8 },
+	{ DDRC_ZQCTL2(0), 0x00000000 },
+
+	{ DDRC_DFITMG0(0), 0x0497820A },
+	{ DDRC_DFITMG1(0), 0x00080303 },
+	{ DDRC_DFIUPD0(0), 0xE0400018 },
+	{ DDRC_DFIUPD1(0), 0x00DF00E4 },
+	{ DDRC_DFIUPD2(0), 0x80000000 },
+	{ DDRC_DFIMISC(0), 0x00000011 },
+	{ DDRC_DFITMG2(0), 0x0000170A },
+
+	{ DDRC_DBICTL(0), 0x00000001 },
+	{ DDRC_DFIPHYMSTR(0), 0x00000001 },
+
+	/* need be refined by ddrphy trained value */
+	{ DDRC_RANKCTL(0), 0x00000c99 },
+	{ DDRC_DRAMTMG2(0), 0x070E171a },
+
+	/* address mapping */
+	/* Address map is from MSB 29: r15, r14, cs, r13-r0, b2-b0, c9-c0 */
+	{ DDRC_ADDRMAP0(0), 0x00000015 },
+	{ DDRC_ADDRMAP3(0), 0x00000000 },
+	/* addrmap_col_b10 addrmap_col_b11 set to de-activated (5-bit width) */
+	{ DDRC_ADDRMAP4(0), 0x00001F1F },
+	/* bank interleave */
+	/* addrmap_bank_b2, addrmap_bank_b1, addrmap_bank_b0 */
+	{ DDRC_ADDRMAP1(0), 0x00080808 },
+	/* addrmap_row_b11 addrmap_row_b10_b2 addrmap_row_b1 addrmap_row_b0 */
+	{ DDRC_ADDRMAP5(0), 0x07070707 },
+	/* addrmap_row_b15 addrmap_row_b14 addrmap_row_b13 addrmap_row_b12 */
+	{ DDRC_ADDRMAP6(0), 0x08080707 },
+
+	/* 667mts frequency setting */
+	{ DDRC_FREQ1_DERATEEN(0), 0x0000000 },
+	{ DDRC_FREQ1_DERATEINT(0), 0x0800000 },
+	{ DDRC_FREQ1_RFSHCTL0(0), 0x0210000 },
+	{ DDRC_FREQ1_RFSHTMG(0), 0x014001E },
+	{ DDRC_FREQ1_INIT3(0), 0x0140009 },
+	{ DDRC_FREQ1_INIT4(0), 0x00310008 },
+	{ DDRC_FREQ1_INIT6(0), 0x0066004a },
+	{ DDRC_FREQ1_INIT7(0), 0x0006004a },
+	{ DDRC_FREQ1_DRAMTMG0(0), 0xB070A07 },
+	{ DDRC_FREQ1_DRAMTMG1(0), 0x003040A },
+	{ DDRC_FREQ1_DRAMTMG2(0), 0x305080C },
+	{ DDRC_FREQ1_DRAMTMG3(0), 0x0505000 },
+	{ DDRC_FREQ1_DRAMTMG4(0), 0x3040203 },
+	{ DDRC_FREQ1_DRAMTMG5(0), 0x2030303 },
+	{ DDRC_FREQ1_DRAMTMG6(0), 0x2020004 },
+	{ DDRC_FREQ1_DRAMTMG7(0), 0x0000302 },
+	{ DDRC_FREQ1_DRAMTMG12(0), 0x0020310 },
+	{ DDRC_FREQ1_DRAMTMG13(0), 0xA100002 },
+	{ DDRC_FREQ1_DRAMTMG14(0), 0x0000020 },
+	{ DDRC_FREQ1_DRAMTMG17(0), 0x0220011 },
+	{ DDRC_FREQ1_ZQCTL0(0), 0x0A70005 },
+	{ DDRC_FREQ1_DFITMG0(0), 0x3858202 },
+	{ DDRC_FREQ1_DFITMG1(0), 0x0000404 },
+	{ DDRC_FREQ1_DFITMG2(0), 0x0000502 },
+
+	/* performance setting */
+	{ DDRC_ODTCFG(0), 0x0b060908 },
+	{ DDRC_ODTMAP(0), 0x00000000 },
+	{ DDRC_SCHED(0), 0x29511505 },
+	{ DDRC_SCHED1(0), 0x0000002c },
+	{ DDRC_PERFHPR1(0), 0x5900575b },
+	/* 150T starve and 0x90 max tran len */
+	{ DDRC_PERFLPR1(0), 0x90000096 },
+	/* 300T starve and 0x10 max tran len */
+	{ DDRC_PERFWR1(0), 0x1000012c },
+	{ DDRC_DBG0(0), 0x00000016 },
+	{ DDRC_DBG1(0), 0x00000000 },
+	{ DDRC_DBGCMD(0), 0x00000000 },
+	{ DDRC_SWCTL(0), 0x00000001 },
+	{ DDRC_POISONCFG(0), 0x00000011 },
+	{ DDRC_PCCFG(0), 0x00000111 },
+	{ DDRC_PCFGR_0(0), 0x000010f3 },
+	{ DDRC_PCFGW_0(0), 0x000072ff },
+	{ DDRC_PCTRL_0(0), 0x00000001 },
+	/* disable Read Qos*/
+	{ DDRC_PCFGQOS0_0(0), 0x00000e00 },
+	{ DDRC_PCFGQOS1_0(0), 0x0062ffff },
+	/* disable Write Qos*/
+	{ DDRC_PCFGWQOS0_0(0), 0x00000e00 },
+	{ DDRC_PCFGWQOS1_0(0), 0x0000ffff },
+	{ DDRC_FREQ1_DERATEEN(0), 0x00000202 },
+	{ DDRC_FREQ1_DERATEINT(0), 0xec78f4b5 },
+	{ DDRC_FREQ1_RFSHCTL0(0), 0x00618040 },
+	{ DDRC_FREQ1_RFSHTMG(0), 0x00610090 },
+};
+
+/* PHY Initialize Configuration */
+static struct dram_cfg_param lpddr4_ddrphy_cfg[] = {
+	{ 0x20110, 0x02 }, /* MapCAB0toDFI */
+	{ 0x20111, 0x03 }, /* MapCAB1toDFI */
+	{ 0x20112, 0x04 }, /* MapCAB2toDFI */
+	{ 0x20113, 0x05 }, /* MapCAB3toDFI */
+	{ 0x20114, 0x00 }, /* MapCAB4toDFI */
+	{ 0x20115, 0x01 }, /* MapCAB5toDFI */
+
+	/* Initialize PHY Configuration */
+	{ 0x1005f, 0x1ff },
+	{ 0x1015f, 0x1ff },
+	{ 0x1105f, 0x1ff },
+	{ 0x1115f, 0x1ff },
+	{ 0x1205f, 0x1ff },
+	{ 0x1215f, 0x1ff },
+	{ 0x1305f, 0x1ff },
+	{ 0x1315f, 0x1ff },
+
+	{ 0x11005f, 0x1ff },
+	{ 0x11015f, 0x1ff },
+	{ 0x11105f, 0x1ff },
+	{ 0x11115f, 0x1ff },
+	{ 0x11205f, 0x1ff },
+	{ 0x11215f, 0x1ff },
+	{ 0x11305f, 0x1ff },
+	{ 0x11315f, 0x1ff },
+
+	{ 0x21005f, 0x1ff },
+	{ 0x21015f, 0x1ff },
+	{ 0x21105f, 0x1ff },
+	{ 0x21115f, 0x1ff },
+	{ 0x21205f, 0x1ff },
+	{ 0x21215f, 0x1ff },
+	{ 0x21305f, 0x1ff },
+	{ 0x21315f, 0x1ff },
+
+	{ 0x55, 0x1ff },
+	{ 0x1055, 0x1ff },
+	{ 0x2055, 0x1ff },
+	{ 0x3055, 0x1ff },
+	{ 0x4055, 0x1ff },
+	{ 0x5055, 0x1ff },
+	{ 0x6055, 0x1ff },
+	{ 0x7055, 0x1ff },
+	{ 0x8055, 0x1ff },
+	{ 0x9055, 0x1ff },
+	{ 0x200c5, 0x19 },
+	{ 0x1200c5, 0x7 },
+	{ 0x2200c5, 0x7 },
+	{ 0x2002e, 0x2 },
+	{ 0x12002e, 0x1 },
+	{ 0x22002e, 0x2 },
+	{ 0x90204, 0x0 },
+	{ 0x190204, 0x0 },
+	{ 0x290204, 0x0 },
+
+	{ 0x20024, 0xe3 },
+	{ 0x2003a, 0x2 },
+	{ 0x120024, 0xa3 },
+	{ 0x2003a, 0x2 },
+	{ 0x220024, 0xa3 },
+	{ 0x2003a, 0x2 },
+
+	{ 0x20056, 0x3 },
+	{ 0x120056, 0xa },
+	{ 0x220056, 0xa },
+
+	{ 0x1004d, 0xe00 },
+	{ 0x1014d, 0xe00 },
+	{ 0x1104d, 0xe00 },
+	{ 0x1114d, 0xe00 },
+	{ 0x1204d, 0xe00 },
+	{ 0x1214d, 0xe00 },
+	{ 0x1304d, 0xe00 },
+	{ 0x1314d, 0xe00 },
+	{ 0x11004d, 0xe00 },
+	{ 0x11014d, 0xe00 },
+	{ 0x11104d, 0xe00 },
+	{ 0x11114d, 0xe00 },
+	{ 0x11204d, 0xe00 },
+	{ 0x11214d, 0xe00 },
+	{ 0x11304d, 0xe00 },
+	{ 0x11314d, 0xe00 },
+	{ 0x21004d, 0xe00 },
+	{ 0x21014d, 0xe00 },
+	{ 0x21104d, 0xe00 },
+	{ 0x21114d, 0xe00 },
+	{ 0x21204d, 0xe00 },
+	{ 0x21214d, 0xe00 },
+	{ 0x21304d, 0xe00 },
+	{ 0x21314d, 0xe00 },
+
+	{ 0x10049, 0xfbe },
+	{ 0x10149, 0xfbe },
+	{ 0x11049, 0xfbe },
+	{ 0x11149, 0xfbe },
+	{ 0x12049, 0xfbe },
+	{ 0x12149, 0xfbe },
+	{ 0x13049, 0xfbe },
+	{ 0x13149, 0xfbe },
+
+	{ 0x110049, 0xfbe },
+	{ 0x110149, 0xfbe },
+	{ 0x111049, 0xfbe },
+	{ 0x111149, 0xfbe },
+	{ 0x112049, 0xfbe },
+	{ 0x112149, 0xfbe },
+	{ 0x113049, 0xfbe },
+	{ 0x113149, 0xfbe },
+
+	{ 0x210049, 0xfbe },
+	{ 0x210149, 0xfbe },
+	{ 0x211049, 0xfbe },
+	{ 0x211149, 0xfbe },
+	{ 0x212049, 0xfbe },
+	{ 0x212149, 0xfbe },
+	{ 0x213049, 0xfbe },
+	{ 0x213149, 0xfbe },
+
+	{ 0x43, 0x63 },
+	{ 0x1043, 0x63 },
+	{ 0x2043, 0x63 },
+	{ 0x3043, 0x63 },
+	{ 0x4043, 0x63 },
+	{ 0x5043, 0x63 },
+	{ 0x6043, 0x63 },
+	{ 0x7043, 0x63 },
+	{ 0x8043, 0x63 },
+	{ 0x9043, 0x63 },
+
+	{ 0x20018, 0x3 },
+	{ 0x20075, 0x4 },
+	{ 0x20050, 0x0 },
+	{ 0x20008, 0x320 },
+	{ 0x120008, 0xa7 },
+	{ 0x220008, 0x19 },
+	{ 0x20088, 0x9 },
+	{ 0x200b2, 0x104 },
+	{ 0x10043, 0x5a1 },
+	{ 0x10143, 0x5a1 },
+	{ 0x11043, 0x5a1 },
+	{ 0x11143, 0x5a1 },
+	{ 0x12043, 0x5a1 },
+	{ 0x12143, 0x5a1 },
+	{ 0x13043, 0x5a1 },
+	{ 0x13143, 0x5a1 },
+	{ 0x1200b2, 0x104 },
+	{ 0x110043, 0x5a1 },
+	{ 0x110143, 0x5a1 },
+	{ 0x111043, 0x5a1 },
+	{ 0x111143, 0x5a1 },
+	{ 0x112043, 0x5a1 },
+	{ 0x112143, 0x5a1 },
+	{ 0x113043, 0x5a1 },
+	{ 0x113143, 0x5a1 },
+	{ 0x2200b2, 0x104 },
+	{ 0x210043, 0x5a1 },
+	{ 0x210143, 0x5a1 },
+	{ 0x211043, 0x5a1 },
+	{ 0x211143, 0x5a1 },
+	{ 0x212043, 0x5a1 },
+	{ 0x212143, 0x5a1 },
+	{ 0x213043, 0x5a1 },
+	{ 0x213143, 0x5a1 },
+	{ 0x200fa, 0x1 },
+	{ 0x1200fa, 0x1 },
+	{ 0x2200fa, 0x1 },
+	{ 0x20019, 0x1 },
+	{ 0x120019, 0x1 },
+	{ 0x220019, 0x1 },
+	{ 0x200f0, 0x600 },
+	{ 0x200f1, 0x0 },
+	{ 0x200f2, 0x4444 },
+	{ 0x200f3, 0x8888 },
+	{ 0x200f4, 0x5655 },
+	{ 0x200f5, 0x0 },
+	{ 0x200f6, 0x0 },
+	{ 0x200f7, 0xf000 },
+	{ 0x20025, 0x0 },
+	{ 0x2002d, 0x0 },
+	{ 0x12002d, 0x0 },
+	{ 0x22002d, 0x0 },
+};
+
+/* P0 message block paremeter for training firmware */
+static struct dram_cfg_param lpddr4_fsp0_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54000, 0x0 },
+	{ 0x54001, 0x0 },
+	{ 0x54002, 0x0 },
+	{ 0x54003, 0xc80 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT) },
+	{ 0x54006, LPDDR4_PHY_VREF_VALUE },
+	{ 0x54007, 0x0 },
+	{ 0x54008, 0x131f },
+	{ 0x54009, LPDDR4_HDT_CTL_3200_1D },
+	{ 0x5400a, 0x0 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400c, 0x0 },
+	{ 0x5400d, (LPDDR4_CATRAIN_3200_1d << 8) },
+	{ 0x5400e, 0x0 },
+	{ 0x5400f, 0x0 },
+	{ 0x54010, 0x0 },
+	{ 0x54011, 0x0 },
+	{ 0x54012, 0x310 },
+	{ 0x54013, 0x0 },
+	{ 0x54014, 0x0 },
+	{ 0x54015, 0x0 },
+	{ 0x54016, 0x0 },
+	{ 0x54017, 0x0 },
+	{ 0x54018, 0x0 },
+	{ 0x54019, 0x2dd4 },
+	{ 0x5401a, (((LPDDR4_RON) << 3) | 0x3) },
+	{ 0x5401b, ((LPDDR4_VREF_VALUE_CA << 8) |
+		    (LPDDR4_RTT_CA_BANK0 << 4) | LPDDR4_RTT_DQ) },
+	{ 0x5401c, ((LPDDR4_VREF_VALUE_DQ_RANK0 << 8) | 0x08) },
+	{ 0x5401d, 0x0 },
+	{ 0x5401e, LPDDR4_MR22_RANK0 },
+	{ 0x5401f, 0x2dd4 },
+	{ 0x54020, (((LPDDR4_RON) << 3) | 0x3) },
+	{ 0x54021, ((LPDDR4_VREF_VALUE_CA << 8) |
+		    (LPDDR4_RTT_CA_BANK1 << 4) | LPDDR4_RTT_DQ) },
+	{ 0x54022, ((LPDDR4_VREF_VALUE_DQ_RANK1 << 8) | 0x08) },
+	{ 0x54023, 0x0 },
+	{ 0x54024, LPDDR4_MR22_RANK1 },
+	{ 0x54025, 0x0 },
+	{ 0x54026, 0x0 },
+	{ 0x54027, 0x0 },
+	{ 0x54028, 0x0 },
+	{ 0x54029, 0x0 },
+	{ 0x5402a, 0x0 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x5402d, 0x0 },
+	{ 0x5402e, 0x0 },
+	{ 0x5402f, 0x0 },
+	{ 0x54030, 0x0 },
+	{ 0x54031, 0x0 },
+	{ 0x54032, 0xd400 },
+	{ 0x54033, ((((LPDDR4_RON) << 3) | 0x3) << 8) | 0x2d },
+	{ 0x54034, (((LPDDR4_RTT_CA_BANK0 << 4) | LPDDR4_RTT_DQ) << 8) },
+	{ 0x54035, (0x0800 | LPDDR4_VREF_VALUE_CA) },
+	{ 0x54036, LPDDR4_VREF_VALUE_DQ_RANK0 },
+	{ 0x54037, (LPDDR4_MR22_RANK0 << 8) },
+	{ 0x54038, 0xd400 },
+	{ 0x54039, ((((LPDDR4_RON) << 3) | 0x3) << 8) | 0x2d },
+	{ 0x5403a, (((LPDDR4_RTT_CA_BANK1 << 4) | LPDDR4_RTT_DQ) << 8) },
+	{ 0x5403b, (0x0800 | LPDDR4_VREF_VALUE_CA) },
+	{ 0x5403c, LPDDR4_VREF_VALUE_DQ_RANK1 },
+	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8) },
+	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8) },
+	{ 0x5403e, 0x0 },
+	{ 0x5403f, 0x0 },
+	{ 0x54040, 0x0 },
+	{ 0x54041, 0x0 },
+	{ 0x54042, 0x0 },
+	{ 0x54043, 0x0 },
+	{ 0x54044, 0x0 },
+	{ 0xd0000, 0x1 },
+};
+
+/* P1 message block paremeter for training firmware */
+static struct dram_cfg_param lpddr4_fsp1_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54000, 0x0 },
+	{ 0x54001, 0x0 },
+	{ 0x54002, 0x1 },
+	{ 0x54003, 0x29c },
+	{ 0x54004, 0x2 },
+	{ 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT) },
+	{ 0x54006, LPDDR4_PHY_VREF_VALUE },
+	{ 0x54007, 0x0 },
+	{ 0x54008, 0x121f },
+	{ 0x54009, 0xc8 },
+	{ 0x5400a, 0x0 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400c, 0x0 },
+	{ 0x5400d, 0x0 },
+	{ 0x5400e, 0x0 },
+	{ 0x5400f, 0x0 },
+	{ 0x54010, 0x0 },
+	{ 0x54011, 0x0 },
+	{ 0x54012, 0x310 },
+	{ 0x54013, 0x0 },
+	{ 0x54014, 0x0 },
+	{ 0x54015, 0x0 },
+	{ 0x54016, 0x0 },
+	{ 0x54017, 0x0 },
+	{ 0x54018, 0x0 },
+	{ 0x54019, 0x914 },
+	{ 0x5401a, (((LPDDR4_RON) << 3) | 0x1) },
+	{ 0x5401b, ((LPDDR4_VREF_VALUE_CA << 8) |
+		    (LPDDR4_RTT_CA_BANK0 << 4) | LPDDR4_RTT_DQ) },
+	{ 0x5401c, ((LPDDR4_VREF_VALUE_DQ_RANK0 << 8) | 0x08) },
+	{ 0x5401e, 0x6 },
+	{ 0x5401f, 0x914 },
+	{ 0x54020, (((LPDDR4_RON) << 3) | 0x1) },
+	{ 0x54021, ((LPDDR4_VREF_VALUE_CA << 8) |
+		    (LPDDR4_RTT_CA_BANK1 << 4) | LPDDR4_RTT_DQ) },
+	{ 0x54022, ((LPDDR4_VREF_VALUE_DQ_RANK1 << 8) | 0x08) },
+	{ 0x54023, 0x0 },
+	{ 0x54024, LPDDR4_MR22_RANK1 },
+	{ 0x54025, 0x0 },
+	{ 0x54026, 0x0 },
+	{ 0x54027, 0x0 },
+	{ 0x54028, 0x0 },
+	{ 0x54029, 0x0 },
+	{ 0x5402a, 0x0 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x5402d, 0x0 },
+	{ 0x5402e, 0x0 },
+	{ 0x5402f, 0x0 },
+	{ 0x54030, 0x0 },
+	{ 0x54031, 0x0 },
+	{ 0x54032, 0x1400 },
+	{ 0x54033, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x09 },
+	{ 0x54034, (((LPDDR4_RTT_CA_BANK0 << 4) | LPDDR4_RTT_DQ) << 8) },
+	{ 0x54035, (0x0800 | LPDDR4_VREF_VALUE_CA) },
+	{ 0x54036, LPDDR4_VREF_VALUE_DQ_RANK0 },
+	{ 0x54037, 0x600 },
+	{ 0x54038, 0x1400 },
+	{ 0x54039, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x09 },
+	{ 0x5403a, (((LPDDR4_RTT_CA_BANK1 << 4) | LPDDR4_RTT_DQ) << 8) },
+	{ 0x5403b, (0x0800 | LPDDR4_VREF_VALUE_CA) },
+	{ 0x5403c, LPDDR4_VREF_VALUE_DQ_RANK1 },
+	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8) },
+	{ 0x5403e, 0x0 },
+	{ 0x5403f, 0x0 },
+	{ 0x54040, 0x0 },
+	{ 0x54041, 0x0 },
+	{ 0x54042, 0x0 },
+	{ 0x54043, 0x0 },
+	{ 0xd0000, 0x1 },
+
+};
+
+/* P0 2D message block paremeter for training firmware */
+static struct dram_cfg_param lpddr4_fsp0_2d_cfg[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x54000, 0x0 },
+	{ 0x54001, 0x0 },
+	{ 0x54002, 0x0 },
+	{ 0x54003, 0xc80 },
+	{ 0x54004, 0x2 },
+	{ 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT) },
+	{ 0x54006, LPDDR4_PHY_VREF_VALUE },
+	{ 0x54007, 0x0 },
+	{ 0x54008, 0x61 },
+	{ 0x54009, LPDDR4_HDT_CTL_2D },
+	{ 0x5400a, 0x0 },
+	{ 0x5400b, 0x2 },
+	{ 0x5400c, 0x0 },
+	{ 0x5400d, (LPDDR4_CATRAIN_3200_2d << 8) },
+	{ 0x5400e, 0x0 },
+	{ 0x5400f, (LPDDR4_2D_SHARE << 8) | 0x00 },
+	{ 0x54010, LPDDR4_2D_WEIGHT },
+	{ 0x54011, 0x0 },
+	{ 0x54012, 0x310 },
+	{ 0x54013, 0x0 },
+	{ 0x54014, 0x0 },
+	{ 0x54015, 0x0 },
+	{ 0x54016, 0x0 },
+	{ 0x54017, 0x0 },
+	{ 0x54018, 0x0 },
+	{ 0x54024, 0x5 },
+	{ 0x54019, 0x2dd4 },
+	{ 0x5401a, (((LPDDR4_RON) << 3) | 0x3) },
+	{ 0x5401b, ((LPDDR4_VREF_VALUE_CA << 8) |
+		    (LPDDR4_RTT_CA_BANK0 << 4) | LPDDR4_RTT_DQ) },
+	{ 0x5401c, ((LPDDR4_VREF_VALUE_DQ_RANK0 << 8) | 0x08) },
+	{ 0x5401d, 0x0 },
+	{ 0x5401e, LPDDR4_MR22_RANK0 },
+	{ 0x5401f, 0x2dd4 },
+	{ 0x54020, (((LPDDR4_RON) << 3) | 0x3) },
+	{ 0x54021, ((LPDDR4_VREF_VALUE_CA << 8) |
+		    (LPDDR4_RTT_CA_BANK1 << 4) | LPDDR4_RTT_DQ) },
+	{ 0x54022, ((LPDDR4_VREF_VALUE_DQ_RANK1 << 8) | 0x08) },
+	{ 0x54023, 0x0 },
+	{ 0x54024, LPDDR4_MR22_RANK1 },
+	{ 0x54025, 0x0 },
+	{ 0x54026, 0x0 },
+	{ 0x54027, 0x0 },
+	{ 0x54028, 0x0 },
+	{ 0x54029, 0x0 },
+	{ 0x5402a, 0x0 },
+	{ 0x5402b, 0x1000 },
+	{ 0x5402c, 0x3 },
+	{ 0x5402d, 0x0 },
+	{ 0x5402e, 0x0 },
+	{ 0x5402f, 0x0 },
+	{ 0x54030, 0x0 },
+	{ 0x54031, 0x0 },
+	{ 0x54032, 0xd400 },
+	{ 0x54033, ((((LPDDR4_RON) << 3) | 0x3) << 8) | 0x2d },
+	{ 0x54034, (((LPDDR4_RTT_CA_BANK0 << 4) | LPDDR4_RTT_DQ) << 8) },
+	{ 0x54035, (0x0800 | LPDDR4_VREF_VALUE_CA) },
+	{ 0x54036, LPDDR4_VREF_VALUE_DQ_RANK0 },
+	{ 0x54037, (LPDDR4_MR22_RANK0 << 8) },
+	{ 0x54038, 0xd400 },
+	{ 0x54039, ((((LPDDR4_RON) << 3) | 0x3) << 8) | 0x2d },
+	{ 0x5403a, (((LPDDR4_RTT_CA_BANK1 << 4) | LPDDR4_RTT_DQ) << 8) },
+	{ 0x5403b, (0x0800 | LPDDR4_VREF_VALUE_CA) },
+	{ 0x5403c, LPDDR4_VREF_VALUE_DQ_RANK1 },
+	{ 0x5403d, (LPDDR4_MR22_RANK1 << 8) },
+	{ 0x5403e, 0x0 },
+	{ 0x5403f, 0x0 },
+	{ 0x54040, 0x0 },
+	{ 0x54041, 0x0 },
+	{ 0x54042, 0x0 },
+	{ 0x54043, 0x0 },
+	{ 0x54044, 0x0 },
+	{ 0xd0000, 0x1 },
+
+};
+
+/* DRAM PHY init engine image */
+static struct dram_cfg_param lpddr4_phy_pie[] = {
+	{ 0xd0000, 0x0 },
+	{ 0x90000, 0x10 },
+	{ 0x90001, 0x400 },
+	{ 0x90002, 0x10e },
+	{ 0x90003, 0x0 },
+	{ 0x90004, 0x0 },
+	{ 0x90005, 0x8 },
+	{ 0x90029, 0xb },
+	{ 0x9002a, 0x480 },
+	{ 0x9002b, 0x109 },
+	{ 0x9002c, 0x8 },
+	{ 0x9002d, 0x448 },
+	{ 0x9002e, 0x139 },
+	{ 0x9002f, 0x8 },
+	{ 0x90030, 0x478 },
+	{ 0x90031, 0x109 },
+	{ 0x90032, 0x0 },
+	{ 0x90033, 0xe8 },
+	{ 0x90034, 0x109 },
+	{ 0x90035, 0x2 },
+	{ 0x90036, 0x10 },
+	{ 0x90037, 0x139 },
+	{ 0x90038, 0xb },
+	{ 0x90039, 0x7c0 },
+	{ 0x9003a, 0x139 },
+	{ 0x9003b, 0x44 },
+	{ 0x9003c, 0x630 },
+	{ 0x9003d, 0x159 },
+	{ 0x9003e, 0x14f },
+	{ 0x9003f, 0x630 },
+	{ 0x90040, 0x159 },
+	{ 0x90041, 0x47 },
+	{ 0x90042, 0x630 },
+	{ 0x90043, 0x149 },
+	{ 0x90044, 0x4f },
+	{ 0x90045, 0x630 },
+	{ 0x90046, 0x179 },
+	{ 0x90047, 0x8 },
+	{ 0x90048, 0xe0 },
+	{ 0x90049, 0x109 },
+	{ 0x9004a, 0x0 },
+	{ 0x9004b, 0x7c8 },
+	{ 0x9004c, 0x109 },
+	{ 0x9004d, 0x0 },
+	{ 0x9004e, 0x1 },
+	{ 0x9004f, 0x8 },
+	{ 0x90050, 0x0 },
+	{ 0x90051, 0x45a },
+	{ 0x90052, 0x9 },
+	{ 0x90053, 0x0 },
+	{ 0x90054, 0x448 },
+	{ 0x90055, 0x109 },
+	{ 0x90056, 0x40 },
+	{ 0x90057, 0x630 },
+	{ 0x90058, 0x179 },
+	{ 0x90059, 0x1 },
+	{ 0x9005a, 0x618 },
+	{ 0x9005b, 0x109 },
+	{ 0x9005c, 0x40c0 },
+	{ 0x9005d, 0x630 },
+	{ 0x9005e, 0x149 },
+	{ 0x9005f, 0x8 },
+	{ 0x90060, 0x4 },
+	{ 0x90061, 0x48 },
+	{ 0x90062, 0x4040 },
+	{ 0x90063, 0x630 },
+	{ 0x90064, 0x149 },
+	{ 0x90065, 0x0 },
+	{ 0x90066, 0x4 },
+	{ 0x90067, 0x48 },
+	{ 0x90068, 0x40 },
+	{ 0x90069, 0x630 },
+	{ 0x9006a, 0x149 },
+	{ 0x9006b, 0x10 },
+	{ 0x9006c, 0x4 },
+	{ 0x9006d, 0x18 },
+	{ 0x9006e, 0x0 },
+	{ 0x9006f, 0x4 },
+	{ 0x90070, 0x78 },
+	{ 0x90071, 0x549 },
+	{ 0x90072, 0x630 },
+	{ 0x90073, 0x159 },
+	{ 0x90074, 0xd49 },
+	{ 0x90075, 0x630 },
+	{ 0x90076, 0x159 },
+	{ 0x90077, 0x94a },
+	{ 0x90078, 0x630 },
+	{ 0x90079, 0x159 },
+	{ 0x9007a, 0x441 },
+	{ 0x9007b, 0x630 },
+	{ 0x9007c, 0x149 },
+	{ 0x9007d, 0x42 },
+	{ 0x9007e, 0x630 },
+	{ 0x9007f, 0x149 },
+	{ 0x90080, 0x1 },
+	{ 0x90081, 0x630 },
+	{ 0x90082, 0x149 },
+	{ 0x90083, 0x0 },
+	{ 0x90084, 0xe0 },
+	{ 0x90085, 0x109 },
+	{ 0x90086, 0xa },
+	{ 0x90087, 0x10 },
+	{ 0x90088, 0x109 },
+	{ 0x90089, 0x9 },
+	{ 0x9008a, 0x3c0 },
+	{ 0x9008b, 0x149 },
+	{ 0x9008c, 0x9 },
+	{ 0x9008d, 0x3c0 },
+	{ 0x9008e, 0x159 },
+	{ 0x9008f, 0x18 },
+	{ 0x90090, 0x10 },
+	{ 0x90091, 0x109 },
+	{ 0x90092, 0x0 },
+	{ 0x90093, 0x3c0 },
+	{ 0x90094, 0x109 },
+	{ 0x90095, 0x18 },
+	{ 0x90096, 0x4 },
+	{ 0x90097, 0x48 },
+	{ 0x90098, 0x18 },
+	{ 0x90099, 0x4 },
+	{ 0x9009a, 0x58 },
+	{ 0x9009b, 0xa },
+	{ 0x9009c, 0x10 },
+	{ 0x9009d, 0x109 },
+	{ 0x9009e, 0x2 },
+	{ 0x9009f, 0x10 },
+	{ 0x900a0, 0x109 },
+	{ 0x900a1, 0x5 },
+	{ 0x900a2, 0x7c0 },
+	{ 0x900a3, 0x109 },
+	{ 0x900a4, 0xd },
+	{ 0x900a5, 0x7c0 },
+	{ 0x900a6, 0x109 },
+	{ 0x900a7, 0x4 },
+	{ 0x900a8, 0x7c0 },
+	{ 0x900a9, 0x109 },
+	{ 0x40000, 0x811 },
+	{ 0x40020, 0x880 },
+	{ 0x40040, 0x0 },
+	{ 0x40060, 0x0 },
+	{ 0x40001, 0x4008 },
+	{ 0x40021, 0x83 },
+	{ 0x40041, 0x4f },
+	{ 0x40061, 0x0 },
+	{ 0x40002, 0x4040 },
+	{ 0x40022, 0x83 },
+	{ 0x40042, 0x51 },
+	{ 0x40062, 0x0 },
+	{ 0x40003, 0x811 },
+	{ 0x40023, 0x880 },
+	{ 0x40043, 0x0 },
+	{ 0x40063, 0x0 },
+	{ 0x40004, 0x720 },
+	{ 0x40024, 0xf },
+	{ 0x40044, 0x1740 },
+	{ 0x40064, 0x0 },
+	{ 0x40005, 0x16 },
+	{ 0x40025, 0x83 },
+	{ 0x40045, 0x4b },
+	{ 0x40065, 0x0 },
+	{ 0x40006, 0x716 },
+	{ 0x40026, 0xf },
+	{ 0x40046, 0x2001 },
+	{ 0x40066, 0x0 },
+	{ 0x40007, 0x716 },
+	{ 0x40027, 0xf },
+	{ 0x40047, 0x2800 },
+	{ 0x40067, 0x0 },
+	{ 0x40008, 0x716 },
+	{ 0x40028, 0xf },
+	{ 0x40048, 0xf00 },
+	{ 0x40068, 0x0 },
+	{ 0x40009, 0x720 },
+	{ 0x40029, 0xf },
+	{ 0x40049, 0x1400 },
+	{ 0x40069, 0x0 },
+	{ 0x4000a, 0xe08 },
+	{ 0x4002a, 0xc15 },
+	{ 0x4004a, 0x0 },
+	{ 0x4006a, 0x0 },
+	{ 0x4000b, 0x623 },
+	{ 0x4002b, 0x15 },
+	{ 0x4004b, 0x0 },
+	{ 0x4006b, 0x0 },
+	{ 0x4000c, 0x4028 },
+	{ 0x4002c, 0x80 },
+	{ 0x4004c, 0x0 },
+	{ 0x4006c, 0x0 },
+	{ 0x4000d, 0xe08 },
+	{ 0x4002d, 0xc1a },
+	{ 0x4004d, 0x0 },
+	{ 0x4006d, 0x0 },
+	{ 0x4000e, 0x623 },
+	{ 0x4002e, 0x1a },
+	{ 0x4004e, 0x0 },
+	{ 0x4006e, 0x0 },
+	{ 0x4000f, 0x4040 },
+	{ 0x4002f, 0x80 },
+	{ 0x4004f, 0x0 },
+	{ 0x4006f, 0x0 },
+	{ 0x40010, 0x2604 },
+	{ 0x40030, 0x15 },
+	{ 0x40050, 0x0 },
+	{ 0x40070, 0x0 },
+	{ 0x40011, 0x708 },
+	{ 0x40031, 0x5 },
+	{ 0x40051, 0x0 },
+	{ 0x40071, 0x2002 },
+	{ 0x40012, 0x8 },
+	{ 0x40032, 0x80 },
+	{ 0x40052, 0x0 },
+	{ 0x40072, 0x0 },
+	{ 0x40013, 0x2604 },
+	{ 0x40033, 0x1a },
+	{ 0x40053, 0x0 },
+	{ 0x40073, 0x0 },
+	{ 0x40014, 0x708 },
+	{ 0x40034, 0xa },
+	{ 0x40054, 0x0 },
+	{ 0x40074, 0x2002 },
+	{ 0x40015, 0x4040 },
+	{ 0x40035, 0x80 },
+	{ 0x40055, 0x0 },
+	{ 0x40075, 0x0 },
+	{ 0x40016, 0x60a },
+	{ 0x40036, 0x15 },
+	{ 0x40056, 0x1200 },
+	{ 0x40076, 0x0 },
+	{ 0x40017, 0x61a },
+	{ 0x40037, 0x15 },
+	{ 0x40057, 0x1300 },
+	{ 0x40077, 0x0 },
+	{ 0x40018, 0x60a },
+	{ 0x40038, 0x1a },
+	{ 0x40058, 0x1200 },
+	{ 0x40078, 0x0 },
+	{ 0x40019, 0x642 },
+	{ 0x40039, 0x1a },
+	{ 0x40059, 0x1300 },
+	{ 0x40079, 0x0 },
+	{ 0x4001a, 0x4808 },
+	{ 0x4003a, 0x880 },
+	{ 0x4005a, 0x0 },
+	{ 0x4007a, 0x0 },
+	{ 0x900aa, 0x0 },
+	{ 0x900ab, 0x790 },
+	{ 0x900ac, 0x11a },
+	{ 0x900ad, 0x8 },
+	{ 0x900ae, 0x7aa },
+	{ 0x900af, 0x2a },
+	{ 0x900b0, 0x10 },
+	{ 0x900b1, 0x7b2 },
+	{ 0x900b2, 0x2a },
+	{ 0x900b3, 0x0 },
+	{ 0x900b4, 0x7c8 },
+	{ 0x900b5, 0x109 },
+	{ 0x900b6, 0x10 },
+	{ 0x900b7, 0x10 },
+	{ 0x900b8, 0x109 },
+	{ 0x900b9, 0x10 },
+	{ 0x900ba, 0x2a8 },
+	{ 0x900bb, 0x129 },
+	{ 0x900bc, 0x8 },
+	{ 0x900bd, 0x370 },
+	{ 0x900be, 0x129 },
+	{ 0x900bf, 0xa },
+	{ 0x900c0, 0x3c8 },
+	{ 0x900c1, 0x1a9 },
+	{ 0x900c2, 0xc },
+	{ 0x900c3, 0x408 },
+	{ 0x900c4, 0x199 },
+	{ 0x900c5, 0x14 },
+	{ 0x900c6, 0x790 },
+	{ 0x900c7, 0x11a },
+	{ 0x900c8, 0x8 },
+	{ 0x900c9, 0x4 },
+	{ 0x900ca, 0x18 },
+	{ 0x900cb, 0xe },
+	{ 0x900cc, 0x408 },
+	{ 0x900cd, 0x199 },
+	{ 0x900ce, 0x8 },
+	{ 0x900cf, 0x8568 },
+	{ 0x900d0, 0x108 },
+	{ 0x900d1, 0x18 },
+	{ 0x900d2, 0x790 },
+	{ 0x900d3, 0x16a },
+	{ 0x900d4, 0x8 },
+	{ 0x900d5, 0x1d8 },
+	{ 0x900d6, 0x169 },
+	{ 0x900d7, 0x10 },
+	{ 0x900d8, 0x8558 },
+	{ 0x900d9, 0x168 },
+	{ 0x900da, 0x70 },
+	{ 0x900db, 0x788 },
+	{ 0x900dc, 0x16a },
+	{ 0x900dd, 0x1ff8 },
+	{ 0x900de, 0x85a8 },
+	{ 0x900df, 0x1e8 },
+	{ 0x900e0, 0x50 },
+	{ 0x900e1, 0x798 },
+	{ 0x900e2, 0x16a },
+	{ 0x900e3, 0x60 },
+	{ 0x900e4, 0x7a0 },
+	{ 0x900e5, 0x16a },
+	{ 0x900e6, 0x8 },
+	{ 0x900e7, 0x8310 },
+	{ 0x900e8, 0x168 },
+	{ 0x900e9, 0x8 },
+	{ 0x900ea, 0xa310 },
+	{ 0x900eb, 0x168 },
+	{ 0x900ec, 0xa },
+	{ 0x900ed, 0x408 },
+	{ 0x900ee, 0x169 },
+	{ 0x900ef, 0x6e },
+	{ 0x900f0, 0x0 },
+	{ 0x900f1, 0x68 },
+	{ 0x900f2, 0x0 },
+	{ 0x900f3, 0x408 },
+	{ 0x900f4, 0x169 },
+	{ 0x900f5, 0x0 },
+	{ 0x900f6, 0x8310 },
+	{ 0x900f7, 0x168 },
+	{ 0x900f8, 0x0 },
+	{ 0x900f9, 0xa310 },
+	{ 0x900fa, 0x168 },
+	{ 0x900fb, 0x1ff8 },
+	{ 0x900fc, 0x85a8 },
+	{ 0x900fd, 0x1e8 },
+	{ 0x900fe, 0x68 },
+	{ 0x900ff, 0x798 },
+	{ 0x90100, 0x16a },
+	{ 0x90101, 0x78 },
+	{ 0x90102, 0x7a0 },
+	{ 0x90103, 0x16a },
+	{ 0x90104, 0x68 },
+	{ 0x90105, 0x790 },
+	{ 0x90106, 0x16a },
+	{ 0x90107, 0x8 },
+	{ 0x90108, 0x8b10 },
+	{ 0x90109, 0x168 },
+	{ 0x9010a, 0x8 },
+	{ 0x9010b, 0xab10 },
+	{ 0x9010c, 0x168 },
+	{ 0x9010d, 0xa },
+	{ 0x9010e, 0x408 },
+	{ 0x9010f, 0x169 },
+	{ 0x90110, 0x58 },
+	{ 0x90111, 0x0 },
+	{ 0x90112, 0x68 },
+	{ 0x90113, 0x0 },
+	{ 0x90114, 0x408 },
+	{ 0x90115, 0x169 },
+	{ 0x90116, 0x0 },
+	{ 0x90117, 0x8b10 },
+	{ 0x90118, 0x168 },
+	{ 0x90119, 0x0 },
+	{ 0x9011a, 0xab10 },
+	{ 0x9011b, 0x168 },
+	{ 0x9011c, 0x0 },
+	{ 0x9011d, 0x1d8 },
+	{ 0x9011e, 0x169 },
+	{ 0x9011f, 0x80 },
+	{ 0x90120, 0x790 },
+	{ 0x90121, 0x16a },
+	{ 0x90122, 0x18 },
+	{ 0x90123, 0x7aa },
+	{ 0x90124, 0x6a },
+	{ 0x90125, 0xa },
+	{ 0x90126, 0x0 },
+	{ 0x90127, 0x1e9 },
+	{ 0x90128, 0x8 },
+	{ 0x90129, 0x8080 },
+	{ 0x9012a, 0x108 },
+	{ 0x9012b, 0xf },
+	{ 0x9012c, 0x408 },
+	{ 0x9012d, 0x169 },
+	{ 0x9012e, 0xc },
+	{ 0x9012f, 0x0 },
+	{ 0x90130, 0x68 },
+	{ 0x90131, 0x9 },
+	{ 0x90132, 0x0 },
+	{ 0x90133, 0x1a9 },
+	{ 0x90134, 0x0 },
+	{ 0x90135, 0x408 },
+	{ 0x90136, 0x169 },
+	{ 0x90137, 0x0 },
+	{ 0x90138, 0x8080 },
+	{ 0x90139, 0x108 },
+	{ 0x9013a, 0x8 },
+	{ 0x9013b, 0x7aa },
+	{ 0x9013c, 0x6a },
+	{ 0x9013d, 0x0 },
+	{ 0x9013e, 0x8568 },
+	{ 0x9013f, 0x108 },
+	{ 0x90140, 0xb7 },
+	{ 0x90141, 0x790 },
+	{ 0x90142, 0x16a },
+	{ 0x90143, 0x1f },
+	{ 0x90144, 0x0 },
+	{ 0x90145, 0x68 },
+	{ 0x90146, 0x8 },
+	{ 0x90147, 0x8558 },
+	{ 0x90148, 0x168 },
+	{ 0x90149, 0xf },
+	{ 0x9014a, 0x408 },
+	{ 0x9014b, 0x169 },
+	{ 0x9014c, 0xc },
+	{ 0x9014d, 0x0 },
+	{ 0x9014e, 0x68 },
+	{ 0x9014f, 0x0 },
+	{ 0x90150, 0x408 },
+	{ 0x90151, 0x169 },
+	{ 0x90152, 0x0 },
+	{ 0x90153, 0x8558 },
+	{ 0x90154, 0x168 },
+	{ 0x90155, 0x8 },
+	{ 0x90156, 0x3c8 },
+	{ 0x90157, 0x1a9 },
+	{ 0x90158, 0x3 },
+	{ 0x90159, 0x370 },
+	{ 0x9015a, 0x129 },
+	{ 0x9015b, 0x20 },
+	{ 0x9015c, 0x2aa },
+	{ 0x9015d, 0x9 },
+	{ 0x9015e, 0x0 },
+	{ 0x9015f, 0x400 },
+	{ 0x90160, 0x10e },
+	{ 0x90161, 0x8 },
+	{ 0x90162, 0xe8 },
+	{ 0x90163, 0x109 },
+	{ 0x90164, 0x0 },
+	{ 0x90165, 0x8140 },
+	{ 0x90166, 0x10c },
+	{ 0x90167, 0x10 },
+	{ 0x90168, 0x8138 },
+	{ 0x90169, 0x10c },
+	{ 0x9016a, 0x8 },
+	{ 0x9016b, 0x7c8 },
+	{ 0x9016c, 0x101 },
+	{ 0x9016d, 0x8 },
+	{ 0x9016e, 0x0 },
+	{ 0x9016f, 0x8 },
+	{ 0x90170, 0x8 },
+	{ 0x90171, 0x448 },
+	{ 0x90172, 0x109 },
+	{ 0x90173, 0xf },
+	{ 0x90174, 0x7c0 },
+	{ 0x90175, 0x109 },
+	{ 0x90176, 0x0 },
+	{ 0x90177, 0xe8 },
+	{ 0x90178, 0x109 },
+	{ 0x90179, 0x47 },
+	{ 0x9017a, 0x630 },
+	{ 0x9017b, 0x109 },
+	{ 0x9017c, 0x8 },
+	{ 0x9017d, 0x618 },
+	{ 0x9017e, 0x109 },
+	{ 0x9017f, 0x8 },
+	{ 0x90180, 0xe0 },
+	{ 0x90181, 0x109 },
+	{ 0x90182, 0x0 },
+	{ 0x90183, 0x7c8 },
+	{ 0x90184, 0x109 },
+	{ 0x90185, 0x8 },
+	{ 0x90186, 0x8140 },
+	{ 0x90187, 0x10c },
+	{ 0x90188, 0x0 },
+	{ 0x90189, 0x1 },
+	{ 0x9018a, 0x8 },
+	{ 0x9018b, 0x8 },
+	{ 0x9018c, 0x4 },
+	{ 0x9018d, 0x8 },
+	{ 0x9018e, 0x8 },
+	{ 0x9018f, 0x7c8 },
+	{ 0x90190, 0x101 },
+	{ 0x90006, 0x0 },
+	{ 0x90007, 0x0 },
+	{ 0x90008, 0x8 },
+	{ 0x90009, 0x0 },
+	{ 0x9000a, 0x0 },
+	{ 0x9000b, 0x0 },
+	{ 0xd00e7, 0x400 },
+	{ 0x90017, 0x0 },
+	{ 0x9001f, 0x2b },
+	{ 0x90026, 0x6c },
+	{ 0x400d0, 0x0 },
+	{ 0x400d1, 0x101 },
+	{ 0x400d2, 0x105 },
+	{ 0x400d3, 0x107 },
+	{ 0x400d4, 0x10f },
+	{ 0x400d5, 0x202 },
+	{ 0x400d6, 0x20a },
+	{ 0x400d7, 0x20b },
+	{ 0x2003a, 0x2 },
+	{ 0x2000b, 0x64 },
+	{ 0x2000c, 0xc8 },
+	{ 0x2000d, 0x7d0 },
+	{ 0x2000e, 0x2c },
+	{ 0x12000b, 0x14 },
+	{ 0x12000c, 0x29 },
+	{ 0x12000d, 0x1a1 },
+	{ 0x12000e, 0x10 },
+	{ 0x22000b, 0x3 },
+	{ 0x22000c, 0x6 },
+	{ 0x22000d, 0x3e },
+	{ 0x22000e, 0x10 },
+	{ 0x9000c, 0x0 },
+	{ 0x9000d, 0x173 },
+	{ 0x9000e, 0x60 },
+	{ 0x9000f, 0x6110 },
+	{ 0x90010, 0x2152 },
+	{ 0x90011, 0xdfbd },
+	{ 0x90012, 0x60 },
+	{ 0x90013, 0x6152 },
+	{ 0x20010, 0x5a },
+	{ 0x20011, 0x3 },
+	{ 0x40080, 0xe0 },
+	{ 0x40081, 0x12 },
+	{ 0x40082, 0xe0 },
+	{ 0x40083, 0x12 },
+	{ 0x40084, 0xe0 },
+	{ 0x40085, 0x12 },
+	{ 0x140080, 0xe0 },
+	{ 0x140081, 0x12 },
+	{ 0x140082, 0xe0 },
+	{ 0x140083, 0x12 },
+	{ 0x140084, 0xe0 },
+	{ 0x140085, 0x12 },
+	{ 0x240080, 0xe0 },
+	{ 0x240081, 0x12 },
+	{ 0x240082, 0xe0 },
+	{ 0x240083, 0x12 },
+	{ 0x240084, 0xe0 },
+	{ 0x240085, 0x12 },
+	{ 0x400fd, 0xf },
+	{ 0x10011, 0x1 },
+	{ 0x10012, 0x1 },
+	{ 0x10013, 0x180 },
+	{ 0x10018, 0x1 },
+	{ 0x10002, 0x6209 },
+	{ 0x100b2, 0x1 },
+	{ 0x101b4, 0x1 },
+	{ 0x102b4, 0x1 },
+	{ 0x103b4, 0x1 },
+	{ 0x104b4, 0x1 },
+	{ 0x105b4, 0x1 },
+	{ 0x106b4, 0x1 },
+	{ 0x107b4, 0x1 },
+	{ 0x108b4, 0x1 },
+	{ 0x11011, 0x1 },
+	{ 0x11012, 0x1 },
+	{ 0x11013, 0x180 },
+	{ 0x11018, 0x1 },
+	{ 0x11002, 0x6209 },
+	{ 0x110b2, 0x1 },
+	{ 0x111b4, 0x1 },
+	{ 0x112b4, 0x1 },
+	{ 0x113b4, 0x1 },
+	{ 0x114b4, 0x1 },
+	{ 0x115b4, 0x1 },
+	{ 0x116b4, 0x1 },
+	{ 0x117b4, 0x1 },
+	{ 0x118b4, 0x1 },
+	{ 0x12011, 0x1 },
+	{ 0x12012, 0x1 },
+	{ 0x12013, 0x180 },
+	{ 0x12018, 0x1 },
+	{ 0x12002, 0x6209 },
+	{ 0x120b2, 0x1 },
+	{ 0x121b4, 0x1 },
+	{ 0x122b4, 0x1 },
+	{ 0x123b4, 0x1 },
+	{ 0x124b4, 0x1 },
+	{ 0x125b4, 0x1 },
+	{ 0x126b4, 0x1 },
+	{ 0x127b4, 0x1 },
+	{ 0x128b4, 0x1 },
+	{ 0x13011, 0x1 },
+	{ 0x13012, 0x1 },
+	{ 0x13013, 0x180 },
+	{ 0x13018, 0x1 },
+	{ 0x13002, 0x6209 },
+	{ 0x130b2, 0x1 },
+	{ 0x131b4, 0x1 },
+	{ 0x132b4, 0x1 },
+	{ 0x133b4, 0x1 },
+	{ 0x134b4, 0x1 },
+	{ 0x135b4, 0x1 },
+	{ 0x136b4, 0x1 },
+	{ 0x137b4, 0x1 },
+	{ 0x138b4, 0x1 },
+	{ 0x20089, 0x1 },
+	{ 0x20088, 0x19 },
+	{ 0xc0080, 0x2 },
+	{ 0xd0000, 0x1 },
+};
+
+static struct dram_fsp_msg lpddr4_dram_fsp_msg[] = {
+	{
+		/* P0 3200mts 1D */
+		.drate = 3200,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = lpddr4_fsp0_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp0_cfg),
+	},
+	{
+		/* P1 667mts 1D */
+		.drate = 667,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = lpddr4_fsp1_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp1_cfg),
+	},
+	{
+		/* P0 3200mts 2D */
+		.drate = 3200,
+		.fw_type = FW_2D_IMAGE,
+		.fsp_cfg = lpddr4_fsp0_2d_cfg,
+		.fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp0_2d_cfg),
+	},
+};
+
+/* lpddr4 timing config params on EVK board */
+struct dram_timing_info dram_timing_b0 = {
+	.ddrc_cfg = lpddr4_ddrc_cfg,
+	.ddrc_cfg_num = ARRAY_SIZE(lpddr4_ddrc_cfg),
+	.ddrphy_cfg = lpddr4_ddrphy_cfg,
+	.ddrphy_cfg_num = ARRAY_SIZE(lpddr4_ddrphy_cfg),
+	.fsp_msg = lpddr4_dram_fsp_msg,
+	.fsp_msg_num = ARRAY_SIZE(lpddr4_dram_fsp_msg),
+	.ddrphy_pie = lpddr4_phy_pie,
+	.ddrphy_pie_num = ARRAY_SIZE(lpddr4_phy_pie),
+	/*
+	 * this table must be initialized if DDRPHY bypass mode is
+	 * not used: all fsp drate > 666MTS.
+	 */
+	.fsp_table = { 3200, 667, },
+};
diff --git a/board/purism/librem5/spl.c b/board/purism/librem5/spl.c
new file mode 100644
index 0000000000..976033a6e5
--- /dev/null
+++ b/board/purism/librem5/spl.c
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ * Copyright 2021 Purism
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/ddr.h>
+#include <asm/arch/imx8mq_pins.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/clock.h>
+#include <asm/mach-imx/boot_mode.h>
+#include <asm/mach-imx/iomux-v3.h>
+#include <asm/mach-imx/gpio.h>
+#include <asm/mach-imx/mxc_i2c.h>
+#include <fsl_esdhc_imx.h>
+#include <mmc.h>
+#include <power/pmic.h>
+#include <power/bd71837.h>
+#include <hang.h>
+#include <init.h>
+#include <spl.h>
+#include <usb.h>
+#include <dwc3-uboot.h>
+#include <linux/delay.h>
+#include "librem5.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void spl_dram_init(void)
+{
+	/* ddr init */
+	if ((get_cpu_rev() & 0xfff) == CHIP_REV_2_1)
+		ddr_init(&dram_timing);
+	else
+		ddr_init(&dram_timing_b0);
+}
+
+int spl_board_boot_device(enum boot_device boot_dev_spl)
+{
+	log_debug("%s : starting\n", __func__);
+
+	switch (boot_dev_spl) {
+	case SD1_BOOT:
+	case MMC1_BOOT:
+		return BOOT_DEVICE_MMC1;
+	case USB_BOOT:
+		return BOOT_DEVICE_BOARD;
+	default:
+		return BOOT_DEVICE_NONE;
+	}
+}
+
+#define I2C_PAD_CTRL	(PAD_CTL_PUE | PAD_CTL_ODE | PAD_CTL_DSE7 | PAD_CTL_FSEL3)
+#define PC MUX_PAD_CTRL(I2C_PAD_CTRL)
+struct i2c_pads_info i2c_pad_info1 = {
+	.scl = {
+		.i2c_mode = IMX8MQ_PAD_I2C1_SCL__I2C1_SCL | PC,
+		.gpio_mode = IMX8MQ_PAD_I2C1_SCL__GPIO5_IO14 | PC,
+		.gp = IMX_GPIO_NR(5, 14),
+	},
+	.sda = {
+		.i2c_mode = IMX8MQ_PAD_I2C1_SDA__I2C1_SDA | PC,
+		.gpio_mode = IMX8MQ_PAD_I2C1_SDA__GPIO5_IO15 | PC,
+		.gp = IMX_GPIO_NR(5, 15),
+	},
+};
+
+struct i2c_pads_info i2c_pad_info2 = {
+	.scl = {
+		.i2c_mode = IMX8MQ_PAD_I2C2_SCL__I2C2_SCL | PC,
+		.gpio_mode = IMX8MQ_PAD_I2C2_SCL__GPIO5_IO16 | PC,
+		.gp = IMX_GPIO_NR(5, 16),
+	},
+	.sda = {
+		.i2c_mode = IMX8MQ_PAD_I2C2_SDA__I2C2_SDA | PC,
+		.gpio_mode = IMX8MQ_PAD_I2C2_SDA__GPIO5_IO17 | PC,
+		.gp = IMX_GPIO_NR(5, 17),
+	},
+};
+
+struct i2c_pads_info i2c_pad_info3 = {
+	.scl = {
+		.i2c_mode = IMX8MQ_PAD_I2C3_SCL__I2C3_SCL | PC,
+		.gpio_mode = IMX8MQ_PAD_I2C3_SCL__GPIO5_IO18 | PC,
+		.gp = IMX_GPIO_NR(5, 18),
+	},
+	.sda = {
+		.i2c_mode = IMX8MQ_PAD_I2C3_SDA__I2C3_SDA | PC,
+		.gpio_mode = IMX8MQ_PAD_I2C3_SDA__GPIO5_IO19 | PC,
+		.gp = IMX_GPIO_NR(5, 19),
+	},
+};
+
+struct i2c_pads_info i2c_pad_info4 = {
+	.scl = {
+		.i2c_mode = IMX8MQ_PAD_I2C4_SCL__I2C4_SCL | PC,
+		.gpio_mode = IMX8MQ_PAD_I2C4_SCL__GPIO5_IO20 | PC,
+		.gp = IMX_GPIO_NR(5, 20),
+	},
+	.sda = {
+		.i2c_mode = IMX8MQ_PAD_I2C4_SDA__I2C4_SDA | PC,
+		.gpio_mode = IMX8MQ_PAD_I2C4_SDA__GPIO5_IO21 | PC,
+		.gp = IMX_GPIO_NR(5, 21),
+	},
+};
+
+#define UART_PAD_CTRL	(PAD_CTL_DSE6 | PAD_CTL_FSEL1)
+
+static const iomux_v3_cfg_t uart_pads[] = {
+	IMX8MQ_PAD_UART1_RXD__UART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
+	IMX8MQ_PAD_UART1_TXD__UART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
+	IMX8MQ_PAD_UART2_RXD__UART2_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
+	IMX8MQ_PAD_UART2_TXD__UART2_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
+	IMX8MQ_PAD_UART3_RXD__UART3_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
+	IMX8MQ_PAD_UART3_TXD__UART3_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
+	IMX8MQ_PAD_ECSPI2_SCLK__UART4_RX | MUX_PAD_CTRL(UART_PAD_CTRL),
+	IMX8MQ_PAD_ECSPI2_MOSI__UART4_TX | MUX_PAD_CTRL(UART_PAD_CTRL),
+};
+
+#define USDHC1_PWR_GPIO IMX_GPIO_NR(2, 10)
+#define USDHC2_PWR_GPIO IMX_GPIO_NR(2, 19)
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+	struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
+	int ret = 0;
+
+	switch (cfg->esdhc_base) {
+	case USDHC1_BASE_ADDR:
+		ret = 1;
+		break;
+	case USDHC2_BASE_ADDR:
+		ret = 1;
+		break;
+	}
+
+	return ret;
+}
+
+#define USDHC_PAD_CTRL	(PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE | \
+			 PAD_CTL_FSEL1)
+#define USDHC_GPIO_PAD_CTRL (PAD_CTL_PUE | PAD_CTL_DSE1)
+
+static const iomux_v3_cfg_t usdhc1_pads[] = {
+	IMX8MQ_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	IMX8MQ_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	IMX8MQ_PAD_SD1_DATA0__USDHC1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	IMX8MQ_PAD_SD1_DATA1__USDHC1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	IMX8MQ_PAD_SD1_DATA2__USDHC1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	IMX8MQ_PAD_SD1_DATA3__USDHC1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	IMX8MQ_PAD_SD1_DATA4__USDHC1_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	IMX8MQ_PAD_SD1_DATA5__USDHC1_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	IMX8MQ_PAD_SD1_DATA6__USDHC1_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	IMX8MQ_PAD_SD1_DATA7__USDHC1_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL),
+	IMX8MQ_PAD_SD1_RESET_B__GPIO2_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
+static const iomux_v3_cfg_t usdhc2_pads[] = {
+	IMX8MQ_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
+	IMX8MQ_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
+	IMX8MQ_PAD_SD2_DATA0__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
+	IMX8MQ_PAD_SD2_DATA1__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
+	IMX8MQ_PAD_SD2_DATA2__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0x16 */
+	IMX8MQ_PAD_SD2_DATA3__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */
+	IMX8MQ_PAD_SD2_RESET_B__GPIO2_IO19 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL),
+};
+
+static struct fsl_esdhc_cfg usdhc_cfg[2] = {
+	{USDHC1_BASE_ADDR, 0, 8},
+#ifndef CONFIG_SPL_BUILD
+	{USDHC2_BASE_ADDR, 0, 4},
+#endif
+};
+
+int board_mmc_init(struct bd_info *bis)
+{
+	int i, ret;
+	/*
+	 * According to the board_mmc_init() the following map is done:
+	 * (U-Boot device node)    (Physical Port)
+	 * mmc0                    USDHC1
+	 * mmc1                    USDHC2
+	 */
+	for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) {
+		log_debug("Initializing FSL USDHC port %d\n", i);
+		switch (i) {
+		case 0:
+			init_clk_usdhc(0);
+			usdhc_cfg[0].sdhc_clk = mxc_get_clock(USDHC1_CLK_ROOT);
+			imx_iomux_v3_setup_multiple_pads(usdhc1_pads,
+							 ARRAY_SIZE(usdhc1_pads));
+			gpio_request(USDHC1_PWR_GPIO, "usdhc1_reset");
+			gpio_direction_output(USDHC1_PWR_GPIO, 0);
+			udelay(500);
+			gpio_direction_output(USDHC1_PWR_GPIO, 1);
+			break;
+		case 1:
+			init_clk_usdhc(1);
+			usdhc_cfg[1].sdhc_clk = mxc_get_clock(USDHC2_CLK_ROOT);
+			imx_iomux_v3_setup_multiple_pads(usdhc2_pads,
+							 ARRAY_SIZE(usdhc2_pads));
+			gpio_request(USDHC2_PWR_GPIO, "usdhc2_reset");
+			gpio_direction_output(USDHC2_PWR_GPIO, 0);
+			udelay(500);
+			gpio_direction_output(USDHC2_PWR_GPIO, 1);
+			break;
+		default:
+			log_err("Warning: USDHC controller(%d) not supported\n", i + 1);
+			return -EINVAL;
+		}
+
+		ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+#define LDO_VOLT_EN                     BIT(6)
+
+/*
+ * Disable the charger - it will be re-enabled in u-boot
+ */
+void disable_charger_bq25896(void)
+{
+	u8 val;
+	int timeout = 1000; // ms
+
+	/* Set the i2c bus */
+	i2c_set_bus_num(3);
+
+	/* disable ship mode if BATFET_DLY is set */
+	val = i2c_reg_read(0x6a, 0x09);
+	log_debug("REG09 0x%x\n", val);
+	if (val & 0x28) {
+		val = val & ~0x28;
+		i2c_reg_write(0x6a, 0x09, val);
+	}
+
+	/* disable and trigger DPDM, ICO, HVDCP and MaxCharge */
+	val = i2c_reg_read(0x6a, 0x02);
+	log_debug("REG02 0x%x\n", val);
+	val &= 0xe0;
+	i2c_reg_write(0x6a, 0x02, val);
+
+	/* disable charger and enable BAT_LOADEN */
+	val = i2c_reg_read(0x6a, 0x03);
+	log_debug("REG03 0x%x\n", val);
+	val = (val | 0x80) & ~0x10;
+	i2c_reg_write(0x6a, 0x03, val);
+
+	mdelay(10);
+
+	/* force ADC conversions */
+	val = i2c_reg_read(0x6a, 0x02);
+	log_debug("REG02 0x%x\n", val);
+	val = (val | 0x80) & ~0x40;
+	i2c_reg_write(0x6a, 0x02, val);
+
+	do {
+		mdelay(10);
+		timeout -= 10;
+	} while ((i2c_reg_read(0x6a, 0x02) & 0x80) && (timeout > 0));
+
+	/* enable STAT pin */
+	val = i2c_reg_read(0x6a, 0x07);
+	log_debug("REG07 0x%x\n", val);
+	val = val & ~0x40;
+	i2c_reg_write(0x6a, 0x07, val);
+
+	/* check VBUS */
+	val = i2c_reg_read(0x6a, 0x11);
+	log_debug("VBUS good %d\n", (val >> 7) & 1);
+	log_debug("VBUS mV %d\n", (val & 0x7f) * 100 + 2600);
+
+	/* check VBAT */
+	val = i2c_reg_read(0x6a, 0x0e);
+	log_debug("VBAT mV %d\n", (val & 0x7f) * 20 + 2304);
+
+	/* limit the VINDPM to 3.9V  */
+	i2c_reg_write(0x6a, 0x0d, 0x8d);
+
+	/* set the max voltage to 4.192V */
+	val = i2c_reg_read(0x6a, 0x6);
+	val = (val & ~0xFC) | 0x16 << 2;
+	i2c_reg_write(0x6a, 0x6, val);
+
+	/* set the SYS_MIN to 3.7V */
+	val = i2c_reg_read(0x6a, 0x3);
+	val = val | 0xE;
+	i2c_reg_write(0x6a, 0x3, val);
+
+	/* disable BAT_LOADEN */
+	val = i2c_reg_read(0x6a, 0x03);
+	log_debug("REG03 0x%x\n", val);
+	val = val & ~0x80;
+	i2c_reg_write(0x6a, 0x03, val);
+}
+
+#define I2C_PMIC	0
+
+int power_bd71837_init(unsigned char bus)
+{
+	static const char name[] = BD718XX_REGULATOR_DRIVER;
+	struct pmic *p = pmic_alloc();
+
+	if (!p) {
+		log_err("%s: POWER allocation error!\n", __func__);
+		return -ENOMEM;
+	}
+
+	p->name = name;
+	p->interface = I2C_PMIC;
+	p->number_of_regs = BD718XX_MAX_REGISTER;
+	p->hw.i2c.addr = CONFIG_POWER_BD71837_I2C_ADDR;
+	p->hw.i2c.tx_num = 1;
+	p->bus = bus;
+
+	return 0;
+}
+
+int power_init_board(void)
+{
+	struct pmic *p;
+	int ldo[] = {BD718XX_LDO5_VOLT, BD718XX_LDO6_VOLT,
+		     BD71837_LDO7_VOLT};
+	u32 val;
+	int i, rv;
+
+	/* Set the i2c bus */
+	setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
+
+	/*
+	 * Init PMIC
+	 */
+	rv = power_bd71837_init(CONFIG_POWER_BD71837_I2C_BUS);
+	if (rv) {
+		log_err("%s: power_bd71837_init(%d) error %d\n", __func__,
+			CONFIG_POWER_BD71837_I2C_BUS, rv);
+		goto out;
+	}
+
+	p = pmic_get(BD718XX_REGULATOR_DRIVER);
+	if (!p) {
+		log_err("%s: pmic_get(%s) failed\n", __func__, BD718XX_REGULATOR_DRIVER);
+		rv = -ENODEV;
+		goto out;
+	}
+
+	rv = pmic_probe(p);
+	if (rv) {
+		log_err("%s: pmic_probe() error %d\n", __func__, rv);
+		goto out;
+	}
+
+	/*
+	 * Unlock all regs
+	 */
+	pmic_reg_write(p, BD718XX_REGLOCK, 0);
+
+	/* find the reset cause */
+	pmic_reg_read(p, 0x29, &val);
+	log_debug("%s: reset cause %d\n", __func__, val);
+
+	/*
+	 * Reconfigure default voltages and disable:
+	 * - BUCK3: VDD_GPU_0V9 (1.00 -> 0.90)
+	 * - BUCK4: VDD_VPU_0V9 (1.00 -> 0.90)
+	 */
+	pmic_reg_write(p, BD71837_BUCK3_VOLT_RUN, 0x14);
+	pmic_reg_write(p, BD71837_BUCK4_VOLT_RUN, 0x14);
+
+	/*
+	 * Enable PHYs voltages: LDO5-7
+	 */
+	for (i = 0; i < ARRAY_SIZE(ldo); i++) {
+		rv = pmic_reg_read(p, ldo[i], &val);
+		if (rv) {
+			log_err("%s: pmic_read(%x) error %d\n", __func__,
+				ldo[i], rv);
+			continue;
+		}
+
+		pmic_reg_write(p, ldo[i], val | LDO_VOLT_EN);
+	}
+
+	udelay(500);
+
+	rv = 0;
+out:
+	return rv;
+}
+
+void spl_board_init(void)
+{
+	init_usb_clk();
+
+	if (is_usb_boot())
+		puts("USB Boot\n");
+	else
+		puts("Normal Boot\n");
+}
+
+void board_boot_order(u32 *spl_boot_list)
+{
+	if (is_usb_boot())
+		spl_boot_list[0] = BOOT_DEVICE_BOARD;
+	else
+		spl_boot_list[0] = BOOT_DEVICE_MMC1;
+}
+
+int board_fit_config_name_match(const char *name)
+{
+	/* Just empty function now - can't decide what to choose */
+	return 0;
+}
+
+void board_init_f(ulong dummy)
+{
+	int ret;
+
+	/* Clear global data */
+	memset((void *)gd, 0, sizeof(gd_t));
+
+	arch_cpu_init();
+
+	init_uart_clk(CONSOLE_UART_CLK);
+	imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads));
+
+#ifdef CONSOLE_ON_UART4
+	gpio_request(WIFI_EN, "WIFI_EN");
+	gpio_direction_output(WIFI_EN, 1);
+#endif
+
+	board_early_init_f();
+
+	timer_init();
+
+	preloader_console_init();
+
+	/* Clear the BSS. */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	ret = spl_init();
+	if (ret) {
+		log_err("spl_init() failed: %d\n", ret);
+		hang();
+	}
+
+	enable_tzc380();
+
+	printf("Initializing pinmux\n");
+	init_pinmux();
+	gpio_direction_output(LED_G, 1);
+	gpio_direction_output(MOTO, 1);
+	mdelay(50);
+	gpio_direction_output(MOTO, 0);
+
+	/* Enable and configure i2c buses not used below */
+	setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info2);
+	setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info3);
+	setup_i2c(3, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info4);
+
+	power_init_board();
+
+	disable_charger_bq25896();
+
+	/* initialize this for M4 even if u-boot doesn't have SF_CMD */
+	printf("Initializing ECSPI\n");
+	board_ecspi_init();
+
+	/* DDR initialization */
+	printf("Initializing DRAM\n");
+	spl_dram_init();
+}
+
diff --git a/configs/librem5_defconfig b/configs/librem5_defconfig
new file mode 100644
index 0000000000..23f4260403
--- /dev/null
+++ b/configs/librem5_defconfig
@@ -0,0 +1,120 @@
+CONFIG_ARM=y
+CONFIG_ARCH_IMX8M=y
+CONFIG_SYS_TEXT_BASE=0x40200000
+CONFIG_SPL_GPIO=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_ENV_SIZE=0x2000
+CONFIG_ENV_OFFSET=0x3FE000
+CONFIG_SYS_I2C_MXC_I2C1=y
+CONFIG_SYS_I2C_MXC_I2C2=y
+CONFIG_SYS_I2C_MXC_I2C3=y
+CONFIG_SYS_I2C_MXC_I2C4=y
+CONFIG_DM_GPIO=y
+CONFIG_DEFAULT_DEVICE_TREE="imx8mq-librem5"
+CONFIG_SPL_TEXT_BASE=0x7E1000
+CONFIG_TARGET_LIBREM5=y
+CONFIG_SPL_MMC=y
+CONFIG_SPL_SERIAL=y
+CONFIG_SPL_DRIVERS_MISC=y
+CONFIG_SPL=y
+CONFIG_IMX_BOOTAUX=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_SYS_LOAD_ADDR=0x40480000
+CONFIG_FIT=y
+CONFIG_FIT_EXTERNAL_OFFSET=0x3000
+CONFIG_SPL_LOAD_FIT=y
+# CONFIG_USE_SPL_FIT_GENERATOR is not set
+CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_ARCH_MISC_INIT=y
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_BOARD_LATE_INIT=y
+CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_SEPARATE_BSS=y
+CONFIG_SPL_I2C=y
+CONFIG_SPL_POWER=y
+CONFIG_SPL_USB_GADGET=y
+CONFIG_SPL_USB_SDP_SUPPORT=y
+CONFIG_SPL_WATCHDOG=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_FUSE=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_SDP=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_OF_CONTROL=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
+CONFIG_SPL_DM=y
+CONFIG_SPL_DM_WARN=y
+# CONFIG_SPL_BLK is not set
+CONFIG_SAVED_DRAM_TIMING_BASE=0x40000000
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x43000000
+CONFIG_FASTBOOT_BUF_SIZE=0x40000000
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_UUU_SUPPORT=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_FASTBOOT_MMC_BOOT_SUPPORT=y
+CONFIG_FASTBOOT_MMC_USER_SUPPORT=y
+CONFIG_FASTBOOT_CMD_OEM_PARTCONF=y
+CONFIG_FASTBOOT_CMD_OEM_BOOTBUS=y
+# CONFIG_SPL_DM_GPIO is not set
+CONFIG_GPIO_HOG=y
+CONFIG_DM_GPIO_LOOKUP_LABEL=y
+CONFIG_MXC_GPIO=y
+CONFIG_DM_I2C=y
+# CONFIG_SPL_DM_I2C is not set
+CONFIG_SPL_SYS_I2C_LEGACY=y
+CONFIG_SYS_I2C_EARLY_INIT=y
+CONFIG_SYS_MXC_I2C1_SPEED=50000
+CONFIG_SYS_MXC_I2C2_SPEED=50000
+CONFIG_SYS_MXC_I2C3_SPEED=50000
+CONFIG_SYS_MXC_I2C4_SPEED=50000
+CONFIG_SYS_I2C_SPEED=50000
+CONFIG_LED=y
+CONFIG_LED_BLINK=y
+CONFIG_LED_GPIO=y
+CONFIG_MISC=y
+# CONFIG_SPL_DM_MMC is not set
+CONFIG_SUPPORT_EMMC_BOOT=y
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_FSL_USDHC=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_DM_ETH=y
+CONFIG_PHY=y
+CONFIG_PHY_IMX8MQ_USB=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_IMX8M=y
+CONFIG_POWER_LEGACY=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_IMX8M_POWER_DOMAIN=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_POWER_I2C=y
+CONFIG_DM_RESET=y
+CONFIG_MXC_UART=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_MXC_SPI=y
+CONFIG_DM_THERMAL=y
+CONFIG_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_GENERIC=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Purism"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0525
+CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
+CONFIG_SDP_LOADADDR=0x40400000
diff --git a/doc/board/purism/librem5/librem5.rst b/doc/board/purism/librem5/librem5.rst
new file mode 100644
index 0000000000..d380d48c71
--- /dev/null
+++ b/doc/board/purism/librem5/librem5.rst
@@ -0,0 +1,60 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Librem5
+==========
+
+U-Boot for the Purism Librem5 phone
+
+Quick Start
+-----------
+
+- Build the ARM Trusted firmware binary
+- Get ddr and hdmi firmware
+- Build U-Boot
+
+Get and Build the ARM Trusted firmware
+--------------------------------------
+
+Note: srctree is U-Boot source directory
+Get ATF from: https://source.puri.sm/Librem5/arm-trusted-firmware
+branch: librem5
+
+.. code-block:: bash
+
+   $ make PLAT=imx8mq bl31
+   $ cp build/imx8mq/release/bl31.bin $(builddir)
+
+Get the ddr and hdmi firmware
+-----------------------------
+
+.. code-block:: bash
+
+   $ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.10.bin
+   $ chmod +x firmware-imx-8.10.bin
+   $ ./firmware-imx-8.10.bin
+   $ cp firmware-imx-8.10/firmware/hdmi/cadence/signed_hdmi_imx8m.bin $(builddir)
+   $ cp firmware-imx-8.10/firmware/ddr/synopsys/lpddr4*.bin $(builddir)
+
+Build U-Boot
+------------
+
+.. code-block:: bash
+
+   $ export CROSS_COMPILE=aarch64-linux-gnu
+   $ make librem5_defconfig
+   $ make flash.bin
+
+Burn the flash.bin
+------------------
+
+Use uuu to burn flash.bin. Power on the phone while holding vol+ to get it
+into uuu mode.
+
+.. code-block:: bash
+
+   $ git clone https://source.puri.sm/Librem5/librem5-devkit-tools.git
+   $ cd librem5-devkit-tools
+   $ cp $(builddir)/flash.bin files/
+   $ uuu uuu_scripts/u-boot_flash_librem5.lst
+
+Reboot the phone.
diff --git a/include/configs/librem5.h b/include/configs/librem5.h
new file mode 100644
index 0000000000..aca157d6dc
--- /dev/null
+++ b/include/configs/librem5.h
@@ -0,0 +1,173 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2017 NXP
+ * Copyright 2018 Emcraft Systems
+ * Copyright 2019 Purism
+ *
+ */
+
+#ifndef __LIBREM5_H
+#define __LIBREM5_H
+
+/* #define DEBUG */
+
+#include <version.h>
+#include <linux/sizes.h>
+#include <asm/arch/imx-regs.h>
+
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_CSF_SIZE			0x2000 /* 8K region */
+#endif
+
+#define CONFIG_SPL_MAX_SIZE		(148 * 1024)
+#define CONFIG_SYS_MONITOR_LEN		(512 * 1024)
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR	0x300
+#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION	1
+
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SPL_THERM_SUPPORT
+#define CONFIG_SPL_WATCHDOG_SUPPORT
+#define CONFIG_SPL_DRIVERS_MISC_SUPPORT
+#define CONFIG_SPL_LDSCRIPT		"arch/arm/cpu/armv8/u-boot-spl.lds"
+#define CONFIG_SPL_STACK		0x187FF0
+#define CONFIG_SPL_GPIO_SUPPORT
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SPL_BSS_START_ADDR      0x00180000
+#define CONFIG_SPL_BSS_MAX_SIZE        0x2000	/* 8 KB */
+#define CONFIG_SPL_STACK_R_ADDR		0x42300000
+#define CONFIG_SPL_STACK_R
+#define CONFIG_SYS_SPL_MALLOC_START    0x42200000
+#define CONFIG_SYS_SPL_MALLOC_SIZE     0x80000	/* 512 KB */
+#define CONFIG_SYS_ICACHE_OFF
+#define CONFIG_SYS_DCACHE_OFF
+
+#define CONFIG_MALLOC_F_ADDR		0x182000 /* malloc f used before GD_FLG_FULL_MALLOC_INIT */
+
+#define CONFIG_SPL_ABORT_ON_RAW_IMAGE /* For RAW image gives a error info not panic */
+
+#undef CONFIG_SPL_DM_PMIC
+#undef CONFIG_SPL_DM_I2C
+#undef CONFIG_SPL_DM_PMIC_BD71837
+#undef CONFIG_DM_USB
+#undef CONFIG_SPL_DM_USB
+#undef CONFIG_USB_DWC3_GENERIC
+#undef CONFIG_DEVRES
+
+#define CONFIG_SYS_I2C
+
+#define CONFIG_POWER_BD71837
+#define CONFIG_POWER_BD71837_I2C_BUS	0
+#define CONFIG_POWER_BD71837_I2C_ADDR	0x4B
+
+#define CONFIG_SPL_DMA_SUPPORT
+
+#define CONFIG_SYS_FSL_USDHC_NUM	1
+
+#else /* CONFIG_SPL_BUILD*/
+
+#define CONFIG_SYS_FSL_USDHC_NUM	2
+
+#define CONFIG_USB_MAX_CONTROLLER_COUNT         1
+
+#define CONFIG_USBD_HS
+
+#define CONFIG_USB_GADGET_VBUS_DRAW 2
+
+#endif /* CONFIG_SPL_BUILD*/
+
+#define CONSOLE_ON_UART1
+#define CONFIG_BAUDRATE			115200
+
+#ifdef CONSOLE_ON_UART1
+#define CONFIG_MXC_UART_BASE		UART1_BASE_ADDR
+#define CONSOLE_UART_CLK		0
+#define CONSOLE		"ttymxc0"
+#elif defined(CONSOLE_ON_UART2)
+#define CONFIG_MXC_UART_BASE		UART2_BASE_ADDR
+#define CONSOLE_UART_CLK		1
+#define CONSOLE		"ttymxc1"
+#elif defined(CONSOLE_ON_UART3)
+#define CONFIG_MXC_UART_BASE		UART3_BASE_ADDR
+#define CONSOLE_UART_CLK		2
+#define CONSOLE		"ttymxc2"
+#elif defined(CONSOLE_ON_UART4)
+#define CONFIG_MXC_UART_BASE		UART4_BASE_ADDR
+#define CONSOLE_UART_CLK		3
+#define CONSOLE		"ttymxc3"
+#else
+#define CONFIG_MXC_UART_BASE		UART1_BASE_ADDR
+#define CONSOLE_UART_CLK		0
+#define CONSOLE		"ttymxc0"
+#endif
+
+#define CONFIG_REMAKE_ELF
+
+#define CONFIG_BOARD_POSTCLK_INIT
+
+/* Flat Device Tree Definitions */
+#define CONFIG_OF_BOARD_SETUP
+
+#ifndef CONFIG_SPL_BUILD
+#define BOOT_TARGET_DEVICES(func) \
+	func(MMC, mmc, 0) \
+	func(MMC, mmc, 1) \
+	func(USB, usb, 0) \
+	func(PXE, pxe, na) \
+	func(DHCP, dhcp, na)
+#include <config_distro_bootcmd.h>
+#else
+#define BOOTENV
+#endif
+
+/* Initial environment variables */
+#define CONFIG_EXTRA_ENV_SETTINGS		\
+	"scriptaddr=0x80000000\0" \
+	"pxefile_addr_r=0x80100000\0" \
+	"kernel_addr_r=0x80800000\0" \
+	"fdt_addr_r=0x83000000\0" \
+	"ramdisk_addr_r=0x83800000\0" \
+	"console=" CONSOLE ",115200\0" \
+	"bootargs=u_boot_version=" PLAIN_VERSION "\0" \
+	"stdin=nc,serial\0" \
+	"stdout=nc,serial\0" \
+	"stderr=nc,serial\0" \
+	BOOTENV
+
+/* Link Definitions */
+#define CONFIG_SYS_TEXT_BASE		0x40200000
+
+#define CONFIG_SYS_INIT_RAM_ADDR        0x40000000
+#define CONFIG_SYS_INIT_RAM_SIZE        0x80000
+#define CONFIG_SYS_INIT_SP_OFFSET \
+	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
+	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+
+#define CONFIG_ENV_OVERWRITE
+#define CONFIG_MMCROOT			"/dev/mmcblk0p2"  /* USDHC1 */
+
+#define CONFIG_SYS_SDRAM_BASE           0x40000000
+#define PHYS_SDRAM                      0x40000000
+#define PHYS_SDRAM_SIZE			0xc0000000 /* 3GB LPDDR4 one Rank */
+
+#define CONFIG_SYS_ALT_MEMTEST
+
+/* Monitor Command Prompt */
+#undef CONFIG_SYS_PROMPT
+#define CONFIG_SYS_PROMPT		"u-boot=> "
+#define CONFIG_SYS_PROMPT_HUSH_PS2     "> "
+#define CONFIG_SYS_CBSIZE              1024
+#define CONFIG_SYS_MAXARGS             64
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
+					sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_FSL_ESDHC_ADDR       0
+
+#define CONFIG_SYS_MMC_IMG_LOAD_PART	1
+
+#ifdef CONFIG_CMD_SF
+#define CONFIG_SF_DEFAULT_BUS	0
+#define CONFIG_SF_DEFAULT_CS	0
+#endif
+#endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-01-07 19:16 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-07 16:34 [PATCH 0/1] Add support for the Purism Librem5 Phone Angus Ainslie
2022-01-07 16:34 ` [PATCH 1/1] board: purism: librem5: add the Librem5 phone files Angus Ainslie

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.