summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/cpu/armv8/Kconfig6
-rw-r--r--arch/arm/cpu/armv8/Makefile4
-rw-r--r--arch/arm/cpu/armv8/spl_data.c29
-rw-r--r--arch/arm/cpu/armv8/u-boot-spl.lds8
-rw-r--r--arch/arm/dts/Makefile4
-rw-r--r--arch/arm/dts/fsl-imx8dx.dtsi6
-rw-r--r--arch/arm/dts/fsl-imx8qm.dtsi6
-rw-r--r--arch/arm/dts/imx8mm-beacon-baseboard.dtsi285
-rw-r--r--arch/arm/dts/imx8mm-beacon-kit-u-boot.dtsi131
-rw-r--r--arch/arm/dts/imx8mm-beacon-kit.dts19
-rw-r--r--arch/arm/dts/imx8mm-beacon-som.dtsi390
-rw-r--r--arch/arm/dts/imx8mq-pico-pi.dts420
-rw-r--r--arch/arm/include/asm/arch-imx/cpu.h1
-rw-r--r--arch/arm/include/asm/arch-imx8/sys_proto.h9
-rw-r--r--arch/arm/include/asm/arch-imx8m/imx-regs.h41
-rw-r--r--arch/arm/include/asm/mach-imx/dma.h15
-rw-r--r--arch/arm/include/asm/mach-imx/imx-nandbcb.h4
-rw-r--r--arch/arm/include/asm/mach-imx/module_fuse.h127
-rw-r--r--arch/arm/include/asm/mach-imx/regs-apbh.h9
-rw-r--r--arch/arm/include/asm/mach-imx/regs-bch.h20
-rw-r--r--arch/arm/include/asm/mach-imx/sys_proto.h3
-rw-r--r--arch/arm/mach-imx/Kconfig9
-rw-r--r--arch/arm/mach-imx/cmd_nandbcb.c1241
-rw-r--r--arch/arm/mach-imx/cpu.c4
-rw-r--r--arch/arm/mach-imx/imx8/Kconfig10
-rw-r--r--arch/arm/mach-imx/imx8/cpu.c84
-rw-r--r--arch/arm/mach-imx/imx8/fdt.c18
-rw-r--r--arch/arm/mach-imx/imx8m/Kconfig13
-rw-r--r--arch/arm/mach-imx/imx8m/soc.c75
-rw-r--r--arch/arm/mach-imx/mx6/Makefile1
-rw-r--r--arch/arm/mach-imx/mx6/module_fuse.c322
-rw-r--r--arch/arm/mach-meson/board-gx.c3
32 files changed, 3120 insertions, 197 deletions
diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig
index 16c83e8614..3655990772 100644
--- a/arch/arm/cpu/armv8/Kconfig
+++ b/arch/arm/cpu/armv8/Kconfig
@@ -76,6 +76,12 @@ config SPL_ARMV8_SEC_FIRMWARE_SUPPORT
help
Say Y here to support this framework in SPL phase.
+config SPL_RECOVER_DATA_SECTION
+ bool "save/restore SPL data section"
+ help
+ Say Y here to save SPL data section for cold boot, and restore
+ at warm boot in SPL phase.
+
config SEC_FIRMWARE_ARMV8_PSCI
bool "PSCI implementation in secure monitor firmware"
depends on ARMV8_SEC_FIRMWARE_SUPPORT || SPL_ARMV8_SEC_FIRMWARE_SUPPORT
diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile
index b349b13f49..2e48df0eb9 100644
--- a/arch/arm/cpu/armv8/Makefile
+++ b/arch/arm/cpu/armv8/Makefile
@@ -30,6 +30,10 @@ obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o
endif
obj-$(CONFIG_$(SPL_)ARMV8_SEC_FIRMWARE_SUPPORT) += sec_firmware.o sec_firmware_asm.o
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SPL_RECOVER_DATA_SECTION) += spl_data.o
+endif
+
obj-$(CONFIG_FSL_LAYERSCAPE) += fsl-layerscape/
obj-$(CONFIG_S32V234) += s32v234/
obj-$(CONFIG_TARGET_HIKEY) += hisilicon/
diff --git a/arch/arm/cpu/armv8/spl_data.c b/arch/arm/cpu/armv8/spl_data.c
new file mode 100644
index 0000000000..8fd986a67a
--- /dev/null
+++ b/arch/arm/cpu/armv8/spl_data.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ */
+
+#include <common.h>
+#include <spl.h>
+
+char __data_save_start[0] __section(.__data_save_start);
+char __data_save_end[0] __section(.__data_save_end);
+
+u32 cold_reboot_flag = 1;
+
+void spl_save_restore_data(void)
+{
+ u32 data_size = __data_save_end - __data_save_start;
+
+ if (cold_reboot_flag == 1) {
+ /* Save data section to data_save section */
+ memcpy(__data_save_start, __data_save_start - data_size,
+ data_size);
+ } else {
+ /* Restore the data_save section to data section */
+ memcpy(__data_save_start - data_size, __data_save_start,
+ data_size);
+ }
+
+ cold_reboot_flag++;
+}
diff --git a/arch/arm/cpu/armv8/u-boot-spl.lds b/arch/arm/cpu/armv8/u-boot-spl.lds
index ccbf359bd1..0e67ab09d7 100644
--- a/arch/arm/cpu/armv8/u-boot-spl.lds
+++ b/arch/arm/cpu/armv8/u-boot-spl.lds
@@ -38,6 +38,14 @@ SECTIONS
*(.data*)
} >.sram
+#ifdef CONFIG_SPL_RECOVER_DATA_SECTION
+ .data_save : {
+ *(.__data_save_start)
+ . = SIZEOF(.data);
+ *(.__data_save_end)
+ } >.sram
+#endif
+
.u_boot_list : {
. = ALIGN(8);
KEEP(*(SORT(.u_boot_list*)));
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 559d3ab6a7..1325134bd4 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -736,8 +736,10 @@ dtb-$(CONFIG_ARCH_IMX8M) += \
imx8mm-verdin.dtb \
imx8mn-ddr4-evk.dtb \
imx8mq-evk.dtb \
+ imx8mm-beacon-kit.dtb \
imx8mq-phanbell.dtb \
- imx8mp-evk.dtb
+ imx8mp-evk.dtb \
+ imx8mq-pico-pi.dtb
dtb-$(CONFIG_ARCH_IMXRT) += imxrt1050-evk.dtb \
imxrt1020-evk.dtb
diff --git a/arch/arm/dts/fsl-imx8dx.dtsi b/arch/arm/dts/fsl-imx8dx.dtsi
index ae1d1f460b..7d95cf0b7d 100644
--- a/arch/arm/dts/fsl-imx8dx.dtsi
+++ b/arch/arm/dts/fsl-imx8dx.dtsi
@@ -131,7 +131,7 @@
pd_lsio: PD_LSIO {
compatible = "nxp,imx8-pd";
- reg = <SC_R_LAST>;
+ reg = <SC_R_NONE>;
#power-domain-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
@@ -180,7 +180,7 @@
pd_conn: PD_CONN {
compatible = "nxp,imx8-pd";
- reg = <SC_R_LAST>;
+ reg = <SC_R_NONE>;
#power-domain-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
@@ -214,7 +214,7 @@
pd_dma: PD_DMA {
compatible = "nxp,imx8-pd";
- reg = <SC_R_LAST>;
+ reg = <SC_R_NONE>;
#power-domain-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/dts/fsl-imx8qm.dtsi b/arch/arm/dts/fsl-imx8qm.dtsi
index 6808f68f9d..2e887add79 100644
--- a/arch/arm/dts/fsl-imx8qm.dtsi
+++ b/arch/arm/dts/fsl-imx8qm.dtsi
@@ -88,7 +88,7 @@
pd_lsio: PD_LSIO {
compatible = "nxp,imx8-pd";
- reg = <SC_R_LAST>;
+ reg = <SC_R_NONE>;
#power-domain-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
@@ -137,7 +137,7 @@
pd_conn: PD_CONN {
compatible = "nxp,imx8-pd";
- reg = <SC_R_LAST>;
+ reg = <SC_R_NONE>;
#power-domain-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
@@ -173,7 +173,7 @@
pd_dma: PD_DMA {
compatible = "nxp,imx8-pd";
- reg = <SC_R_LAST>;
+ reg = <SC_R_NONE>;
#power-domain-cells = <0>;
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/dts/imx8mm-beacon-baseboard.dtsi b/arch/arm/dts/imx8mm-beacon-baseboard.dtsi
new file mode 100644
index 0000000000..baa5f997d0
--- /dev/null
+++ b/arch/arm/dts/imx8mm-beacon-baseboard.dtsi
@@ -0,0 +1,285 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2020 Compass Electronics Group, LLC
+ */
+
+/ {
+ leds {
+ compatible = "gpio-leds";
+
+ led0 {
+ label = "gen_led0";
+ gpios = <&pca6416_1 4 GPIO_ACTIVE_HIGH>;
+ default-state = "none";
+ };
+
+ led1 {
+ label = "gen_led1";
+ gpios = <&pca6416_1 5 GPIO_ACTIVE_HIGH>;
+ default-state = "none";
+ };
+
+ led2 {
+ label = "gen_led2";
+ gpios = <&pca6416_1 6 GPIO_ACTIVE_HIGH>;
+ default-state = "none";
+ };
+
+ led3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_led3>;
+ label = "heartbeat";
+ gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ reg_audio: regulator-audio {
+ compatible = "regulator-fixed";
+ regulator-name = "3v3_aud";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&pca6416_1 11 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usdhc2_vmmc: regulator-usdhc2 {
+ compatible = "regulator-fixed";
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ sound {
+ compatible = "fsl,imx-audio-wm8962";
+ model = "wm8962-audio";
+ audio-cpu = <&sai3>;
+ audio-codec = <&wm8962>;
+ audio-routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "Ext Spk", "SPKOUTL",
+ "Ext Spk", "SPKOUTR",
+ "AMIC", "MICBIAS",
+ "IN3R", "AMIC";
+ };
+};
+
+&ecspi2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_espi2>;
+ cs-gpios = <&gpio5 9 0>;
+ status = "okay";
+
+ eeprom@0 {
+ compatible = "microchip,at25160bn", "atmel,at25";
+ reg = <0>;
+ spi-max-frequency = <5000000>;
+ spi-cpha;
+ spi-cpol;
+ pagesize = <32>;
+ size = <2048>;
+ address-width = <16>;
+ };
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+};
+
+&i2c4 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ status = "okay";
+
+ wm8962: audio-codec@1a {
+ compatible = "wlf,wm8962";
+ reg = <0x1a>;
+ clocks = <&clk IMX8MM_CLK_SAI3_ROOT>;
+ clock-names = "xclk";
+ DCVDD-supply = <&reg_audio>;
+ DBVDD-supply = <&reg_audio>;
+ AVDD-supply = <&reg_audio>;
+ CPVDD-supply = <&reg_audio>;
+ MICVDD-supply = <&reg_audio>;
+ PLLVDD-supply = <&reg_audio>;
+ SPKVDD1-supply = <&reg_audio>;
+ SPKVDD2-supply = <&reg_audio>;
+ gpio-cfg = <
+ 0x0000 /* 0:Default */
+ 0x0000 /* 1:Default */
+ 0x0000 /* 2:FN_DMICCLK */
+ 0x0000 /* 3:Default */
+ 0x0000 /* 4:FN_DMICCDAT */
+ 0x0000 /* 5:Default */
+ >;
+ };
+
+ pca6416_0: gpio@20 {
+ compatible = "nxp,pcal6416";
+ reg = <0x20>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcal6414>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ pca6416_1: gpio@21 {
+ compatible = "nxp,pcal6416";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&sai3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai3>;
+ assigned-clocks = <&clk IMX8MM_CLK_SAI3>;
+ assigned-clock-parents = <&clk IMX8MM_AUDIO_PLL1_OUT>;
+ assigned-clock-rates = <24576000>;
+ fsl,sai-mclk-direction-output;
+ status = "okay";
+};
+
+&snvs_pwrkey {
+ status = "okay";
+};
+
+&uart2 { /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ assigned-clocks = <&clk IMX8MM_CLK_UART3>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ bus-width = <4>;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_espi2: espi2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0x82
+ MX8MM_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI 0x82
+ MX8MM_IOMUXC_ECSPI2_MISO_ECSPI2_MISO 0x82
+ MX8MM_IOMUXC_ECSPI1_SS0_GPIO5_IO9 0x41
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C4_SDA_I2C4_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_led3: led3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x41
+ >;
+ };
+
+ pinctrl_pcal6414: pcal6414-gpio {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI2_MCLK_GPIO4_IO27 0x19
+ >;
+ };
+
+ pinctrl_sai3: sai3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI3_TXFS_SAI3_TX_SYNC 0xd6
+ MX8MM_IOMUXC_SAI3_TXC_SAI3_TX_BCLK 0xd6
+ MX8MM_IOMUXC_SAI3_MCLK_SAI3_MCLK 0xd6
+ MX8MM_IOMUXC_SAI3_TXD_SAI3_TX_DATA0 0xd6
+ MX8MM_IOMUXC_SAI3_RXD_SAI3_RX_DATA0 0xd6
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140
+ MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI1_SCLK_UART3_DCE_RX 0x40
+ MX8MM_IOMUXC_ECSPI1_MOSI_UART3_DCE_TX 0x40
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2grpgpio {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CD_B_USDHC2_CD_B 0x41
+ MX8MM_IOMUXC_SD2_RESET_B_GPIO2_IO19 0x41
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x190
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d0
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d0
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d0
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d0
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d0
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x194
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d4
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d4
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d4
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d4
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d4
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x196
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d6
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d6
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d6
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d6
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d6
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+};
diff --git a/arch/arm/dts/imx8mm-beacon-kit-u-boot.dtsi b/arch/arm/dts/imx8mm-beacon-kit-u-boot.dtsi
new file mode 100644
index 0000000000..fc1aebb2fe
--- /dev/null
+++ b/arch/arm/dts/imx8mm-beacon-kit-u-boot.dtsi
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 Compass Electronics Group, LLC
+ */
+
+/ {
+ wdt-reboot {
+ compatible = "wdt-reboot";
+ wdt = <&wdog1>;
+ u-boot,dm-spl;
+ };
+};
+
+&{/soc@0} {
+ u-boot,dm-pre-reloc;
+ u-boot,dm-spl;
+};
+
+&aips1 {
+ u-boot,dm-spl;
+ u-boot,dm-pre-reloc;
+};
+
+&aips2 {
+ u-boot,dm-spl;
+};
+
+&aips3 {
+ u-boot,dm-spl;
+};
+
+&clk {
+ u-boot,dm-spl;
+ u-boot,dm-pre-reloc;
+ /delete-property/ assigned-clocks;
+ /delete-property/ assigned-clock-parents;
+ /delete-property/ assigned-clock-rates;
+};
+
+&fec1 {
+ phy-reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>;
+};
+
+&gpio1 {
+ u-boot,dm-spl;
+};
+
+&gpio2 {
+ u-boot,dm-spl;
+};
+
+&gpio3 {
+ u-boot,dm-spl;
+};
+
+&gpio4 {
+ u-boot,dm-spl;
+};
+
+&gpio5 {
+ u-boot,dm-spl;
+};
+
+&iomuxc {
+ u-boot,dm-spl;
+};
+
+&osc_24m {
+ u-boot,dm-spl;
+ u-boot,dm-pre-reloc;
+};
+
+&pca6416_0 {
+ compatible = "ti,tca6416";
+};
+
+&pca6416_1 {
+ compatible = "ti,tca6416";
+};
+
+&pinctrl_i2c1 {
+ u-boot,dm-spl;
+};
+
+&pinctrl_pmic {
+ u-boot,dm-spl;
+};
+
+&pinctrl_uart2 {
+ u-boot,dm-spl;
+};
+
+&pinctrl_usdhc2_gpio {
+ u-boot,dm-spl;
+};
+
+&pinctrl_usdhc2 {
+ u-boot,dm-spl;
+};
+
+&pinctrl_usdhc3 {
+ u-boot,dm-spl;
+};
+
+&uart2 {
+ u-boot,dm-spl;
+};
+
+&usdhc2 {
+ u-boot,dm-spl;
+};
+
+&usdhc3 {
+ u-boot,dm-spl;
+};
+
+&i2c1 {
+ u-boot,dm-spl;
+};
+
+&{/soc@0/bus@30800000/i2c@30a20000/pmic@4b} {
+ u-boot,dm-spl;
+};
+
+&{/soc@0/bus@30800000/i2c@30a20000/pmic@4b/regulators} {
+ u-boot,dm-spl;
+};
+
+&wdog1 {
+ u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/imx8mm-beacon-kit.dts b/arch/arm/dts/imx8mm-beacon-kit.dts
new file mode 100644
index 0000000000..74a7b0cc10
--- /dev/null
+++ b/arch/arm/dts/imx8mm-beacon-kit.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2020 Compass Electronics Group, LLC
+ */
+
+/dts-v1/;
+
+#include "imx8mm.dtsi"
+#include "imx8mm-beacon-som.dtsi"
+#include "imx8mm-beacon-baseboard.dtsi"
+
+/ {
+ model = "Beacon EmbeddedWorks i.MX8M Mini Development Kit";
+ compatible = "beacon,imx8mm-beacon-kit", "fsl,imx8mm";
+
+ chosen {
+ stdout-path = &uart2;
+ };
+};
diff --git a/arch/arm/dts/imx8mm-beacon-som.dtsi b/arch/arm/dts/imx8mm-beacon-som.dtsi
new file mode 100644
index 0000000000..801bd02eae
--- /dev/null
+++ b/arch/arm/dts/imx8mm-beacon-som.dtsi
@@ -0,0 +1,390 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2020 Compass Electronics Group, LLC
+ */
+
+/ {
+ usdhc1_pwrseq: usdhc1_pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1_gpio>;
+ reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
+ clocks = <&osc_32k>;
+ clock-names = "ext_clock";
+ post-power-on-delay-ms = <80>;
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0x0 0x40000000 0 0x80000000>;
+ };
+};
+
+&A53_0 {
+ cpu-supply = <&buck2_reg>;
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0>;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic@4b {
+ compatible = "rohm,bd71847";
+ reg = <0x4b>;
+ pinctrl-0 = <&pinctrl_pmic>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <3 GPIO_ACTIVE_LOW>;
+ rohm,reset-snvs-powered;
+
+ regulators {
+ buck1_reg: BUCK1 {
+ regulator-name = "buck1";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-name = "buck2";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ rohm,dvs-run-voltage = <1000000>;
+ rohm,dvs-idle-voltage = <900000>;
+ };
+
+ buck3_reg: BUCK3 {
+ // BUCK5 in datasheet
+ regulator-name = "buck3";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck4_reg: BUCK4 {
+ // BUCK6 in datasheet
+ regulator-name = "buck4";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck5_reg: BUCK5 {
+ // BUCK7 in datasheet
+ regulator-name = "buck5";
+ regulator-min-microvolt = <1605000>;
+ regulator-max-microvolt = <1995000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck6_reg: BUCK6 {
+ // BUCK8 in datasheet
+ regulator-name = "buck6";
+ 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;
+ regulator-always-on;
+ };
+
+ ldo2_reg: LDO2 {
+ regulator-name = "ldo2";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ regulator-boot-on;
+ 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;
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-name = "ldo6";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&i2c3 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+
+ eeprom@50 {
+ compatible = "microchip, at24c64d", "atmel,24c64";
+ pagesize = <32>;
+ read-only; /* Manufacturing EEPROM programmed at factory */
+ reg = <0x50>;
+ };
+
+ rtc@51 {
+ compatible = "nxp,pcf85263";
+ reg = <0x51>;
+ };
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ assigned-clocks = <&clk IMX8MM_CLK_UART1>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm43438-bt";
+ shutdown-gpios = <&gpio2 6 GPIO_ACTIVE_HIGH>;
+ host-wakeup-gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>;
+ device-wakeup-gpios = <&gpio2 7 GPIO_ACTIVE_HIGH>;
+ clocks = <&osc_32k>;
+ clock-names = "extclk";
+ };
+};
+
+&usdhc1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ bus-width = <4>;
+ non-removable;
+ cap-power-off-card;
+ pm-ignore-notify;
+ keep-power-in-suspend;
+ mmc-pwrseq = <&usdhc1_pwrseq>;
+ status = "okay";
+
+ brcmf: bcrmf@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wlan>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "host-wake";
+ };
+};
+
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO 0x3
+ MX8MM_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MM_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MM_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MM_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MM_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ MX8MM_IOMUXC_SAI2_RXC_GPIO4_IO22 0x19
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_pmic: pmicirq {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART1_RXD_UART1_DCE_RX 0x140
+ MX8MM_IOMUXC_UART1_TXD_UART1_DCE_TX 0x140
+ MX8MM_IOMUXC_UART3_RXD_UART1_DCE_CTS_B 0x140
+ MX8MM_IOMUXC_UART3_TXD_UART1_DCE_RTS_B 0x140
+ MX8MM_IOMUXC_SD1_DATA4_GPIO2_IO6 0x19
+ MX8MM_IOMUXC_SD1_DATA5_GPIO2_IO7 0x19
+ MX8MM_IOMUXC_SD1_DATA6_GPIO2_IO8 0x19
+ MX8MM_IOMUXC_GPIO1_IO00_ANAMIX_REF_CLK_32K 0x141
+ >;
+ };
+
+ pinctrl_usdhc1_gpio: usdhc1grpgpio {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_RESET_B_GPIO2_IO10 0x41
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x190
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d0
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d0
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d0
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d0
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x194
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d4
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d4
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d4
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d4
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d4
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x196
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d6
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d6
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d6
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d6
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d6
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x190
+ MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d0
+ MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d0
+ MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d0
+ MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d0
+ MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d0
+ MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d0
+ MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d0
+ MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d0
+ MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d0
+ MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x190
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x194
+ MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d4
+ MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d4
+ MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d4
+ MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d4
+ MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d4
+ MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d4
+ MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d4
+ MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d4
+ MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d4
+ MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x194
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK 0x196
+ MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD 0x1d6
+ MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0 0x1d6
+ MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1 0x1d6
+ MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2 0x1d6
+ MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3 0x1d6
+ MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4 0x1d6
+ MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5 0x1d6
+ MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6 0x1d6
+ MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7 0x1d6
+ MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE 0x196
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+ >;
+ };
+
+ pinctrl_wlan: wlangrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_DATA7_GPIO2_IO9 0x111
+ >;
+ };
+};
diff --git a/arch/arm/dts/imx8mq-pico-pi.dts b/arch/arm/dts/imx8mq-pico-pi.dts
new file mode 100644
index 0000000000..d2af18ad0e
--- /dev/null
+++ b/arch/arm/dts/imx8mq-pico-pi.dts
@@ -0,0 +1,420 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Wandboard, Org.
+ * Copyright 2017 NXP
+ *
+ * Author: Richard Hu <hakahu@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "imx8mq.dtsi"
+
+/ {
+ model = "TechNexion PICO-PI-8M";
+ compatible = "technexion,pico-pi-imx8m", "fsl,imx8mq";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ pmic_osc: clock-pmic {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "pmic_osc";
+ };
+
+ reg_usb_otg_vbus: regulator-usb-otg-vbus {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_otg_vbus>;
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 14 GPIO_ACTIVE_LOW>;
+ };
+
+ reg_eth_phy: eth_phy {
+ compatible = "regulator-fixed";
+ regulator-name = "eth_phy_pwr";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ phy-supply = <&reg_eth_phy>;
+ phy-reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+ phy-reset-duration = <100>;
+ phy-reset-post-delay = <100>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pmic@4b {
+ reg = <0x4b>;
+ compatible = "rohm,bd71837";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pmic>;
+ clocks = <&pmic_osc>;
+ clock-names = "osc";
+ clock-output-names = "pmic_clk";
+ interrupt-parent = <&gpio1>;
+ interrupts = <3 GPIO_ACTIVE_LOW>;
+ interrupt-names = "irq";
+
+ regulators {
+ buck1: 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>;
+ };
+
+ buck2: 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>;
+ };
+
+ buck3: BUCK3 {
+ regulator-name = "buck3";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ rohm,dvs-run-voltage = <1000000>;
+ };
+
+ buck4: BUCK4 {
+ regulator-name = "buck4";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ rohm,dvs-run-voltage = <1000000>;
+ };
+
+ buck5: BUCK5 {
+ regulator-name = "buck5";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-boot-on;
+ };
+
+ buck6: BUCK6 {
+ regulator-name = "buck6";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ buck7: BUCK7 {
+ regulator-name = "buck7";
+ regulator-min-microvolt = <1605000>;
+ regulator-max-microvolt = <1995000>;
+ regulator-boot-on;
+ };
+
+ buck8: BUCK8 {
+ regulator-name = "buck8";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-boot-on;
+ };
+
+ ldo1: LDO1 {
+ regulator-name = "ldo1";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo2: LDO2 {
+ regulator-name = "ldo2";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo3: LDO3 {
+ regulator-name = "ldo3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ ldo4: LDO4 {
+ regulator-name = "ldo4";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+ ldo5: LDO5 {
+ regulator-name = "ldo5";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ ldo6: LDO6 {
+ regulator-name = "ldo6";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+ ldo7: LDO7 {
+ regulator-name = "ldo7";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+ };
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+};
+
+&uart1 { /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&usdhc1 {
+ 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>;
+ cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&usb3_phy0 {
+ status = "okay";
+};
+
+&usb3_phy1 {
+ status = "okay";
+};
+
+&usb_dwc3_1 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23
+ MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ MX8MQ_IOMUXC_GPIO1_IO00_GPIO1_IO0 0x19
+ MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_otg_vbus: otgvbusgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_NAND_DQS_GPIO3_IO14 0x19 /* USB OTG VBUS Enable */
+ >;
+ };
+
+ pinctrl_pmic: pmicirq {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49
+ MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX 0x49
+ MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX 0x49
+ MX8MQ_IOMUXC_UART4_RXD_UART2_DCE_CTS_B 0x49
+ MX8MQ_IOMUXC_UART4_TXD_UART2_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
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x85
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc5
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc5
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc5
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc5
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc5
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc5
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc5
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc5
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc5
+ MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x85
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x87
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc7
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc7
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc7
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc7
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc7
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc7
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc7
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc7
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc7
+ MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x87
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2grpgpio {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41
+ >;
+ };
+
+ 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 0x85
+ MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc5
+ MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc5
+ MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc5
+ MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc5
+ MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc5
+ MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x87
+ MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc7
+ MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc7
+ MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc7
+ MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc7
+ MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc7
+ MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+ >;
+ };
+};
diff --git a/arch/arm/include/asm/arch-imx/cpu.h b/arch/arm/include/asm/arch-imx/cpu.h
index b52565473d..e9c0078922 100644
--- a/arch/arm/include/asm/arch-imx/cpu.h
+++ b/arch/arm/include/asm/arch-imx/cpu.h
@@ -64,6 +64,7 @@
#define CHIP_REV_A 0x0
#define CHIP_REV_B 0x1
+#define CHIP_REV_C 0x2
#define BOARD_REV_1_0 0x0
#define BOARD_REV_2_0 0x1
diff --git a/arch/arm/include/asm/arch-imx8/sys_proto.h b/arch/arm/include/asm/arch-imx8/sys_proto.h
index 0e981ae950..6f1fc8f999 100644
--- a/arch/arm/include/asm/arch-imx8/sys_proto.h
+++ b/arch/arm/include/asm/arch-imx8/sys_proto.h
@@ -5,6 +5,11 @@
#include <asm/arch/sci/sci.h>
#include <asm/mach-imx/sys_proto.h>
+#include <asm/arch/power-domain.h>
+#include <dm/platdata.h>
+#include <dm/device-internal.h>
+#include <dm/device.h>
+#include <power-domain.h>
#include <linux/types.h>
struct pass_over_info_t {
@@ -21,3 +26,7 @@ void build_info(void);
enum boot_device get_boot_device(void);
int print_bootinfo(void);
int sc_pm_setup_uart(sc_rsrc_t uart_rsrc, sc_pm_clock_rate_t clk_rate);
+int imx8_power_domain_lookup_name(const char *name,
+ struct power_domain *power_domain);
+void imx8_power_off_pd_devices(const char *permanent_on_devices[], int size);
+bool m4_parts_booted(void);
diff --git a/arch/arm/include/asm/arch-imx8m/imx-regs.h b/arch/arm/include/asm/arch-imx8m/imx-regs.h
index 62640d996e..3cfa169c97 100644
--- a/arch/arm/include/asm/arch-imx8m/imx-regs.h
+++ b/arch/arm/include/asm/arch-imx8m/imx-regs.h
@@ -137,6 +137,40 @@ struct fuse_bank1_regs {
u32 rsvd3[3];
};
+struct fuse_bank3_regs {
+ u32 mem_trim0;
+ u32 rsvd0[3];
+ u32 mem_trim1;
+ u32 rsvd1[3];
+ u32 mem_trim2;
+ u32 rsvd2[3];
+ u32 ana0;
+ u32 rsvd3[3];
+};
+
+struct fuse_bank9_regs {
+ u32 mac_addr0;
+ u32 rsvd0[3];
+ u32 mac_addr1;
+ u32 rsvd1[11];
+};
+
+struct fuse_bank38_regs {
+ u32 ana_trim1; /* trim0 is at 0xD70, bank 37*/
+ u32 rsvd0[3];
+ u32 ana_trim2;
+ u32 rsvd1[3];
+ u32 ana_trim3;
+ u32 rsvd2[3];
+ u32 ana_trim4;
+ u32 rsvd3[3];
+};
+
+struct fuse_bank39_regs {
+ u32 ana_trim5;
+ u32 rsvd[15];
+};
+
#ifdef CONFIG_IMX8MQ
struct anamix_pll {
u32 audio_pll1_cfg0;
@@ -227,13 +261,6 @@ struct anamix_pll {
};
#endif
-struct fuse_bank9_regs {
- u32 mac_addr0;
- u32 rsvd0[3];
- u32 mac_addr1;
- u32 rsvd1[11];
-};
-
/* System Reset Controller (SRC) */
struct src {
u32 scr;
diff --git a/arch/arm/include/asm/mach-imx/dma.h b/arch/arm/include/asm/mach-imx/dma.h
index ca70731b9e..247a91afb0 100644
--- a/arch/arm/include/asm/mach-imx/dma.h
+++ b/arch/arm/include/asm/mach-imx/dma.h
@@ -7,6 +7,7 @@
*
* Based on code from LTIB:
* Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2020 NXP
*/
#ifndef __DMA_H__
@@ -53,7 +54,7 @@ enum {
MXS_DMA_CHANNEL_AHB_APBH_RESERVED1,
MXS_MAX_DMA_CHANNELS,
};
-#elif defined(CONFIG_MX6) || defined(CONFIG_MX7)
+#else
enum {
MXS_DMA_CHANNEL_AHB_APBH_GPMI0 = 0,
MXS_DMA_CHANNEL_AHB_APBH_GPMI1,
@@ -95,13 +96,13 @@ enum {
#define MXS_DMA_DESC_BYTES_OFFSET 16
struct mxs_dma_cmd {
- unsigned long next;
- unsigned long data;
+ u32 next;
+ u32 data;
union {
- dma_addr_t address;
- unsigned long alternate;
+ u32 address;
+ u32 alternate;
};
- unsigned long pio_words[DMA_PIO_WORDS];
+ u32 pio_words[DMA_PIO_WORDS];
};
/*
@@ -117,7 +118,7 @@ struct mxs_dma_cmd {
struct mxs_dma_desc {
struct mxs_dma_cmd cmd;
unsigned int flags;
- dma_addr_t address;
+ u32 address;
void *buffer;
struct list_head node;
} __aligned(MXS_DMA_ALIGNMENT);
diff --git a/arch/arm/include/asm/mach-imx/imx-nandbcb.h b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
index 907e7ed8f9..74c9031d4e 100644
--- a/arch/arm/include/asm/mach-imx/imx-nandbcb.h
+++ b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
@@ -9,9 +9,11 @@
#define FCB_FINGERPRINT 0x20424346 /* 'FCB' */
#define FCB_VERSION_1 0x01000000
+#define FCB_FINGERPRINT_OFF 0x4 /* FCB fingerprint offset*/
-#define DBBT_FINGERPRINT2 0x54424244 /* 'DBBT' */
+#define DBBT_FINGERPRINT 0x54424244 /* 'DBBT' */
#define DBBT_VERSION_1 0x01000000
+#define DBBT_FINGERPRINT_OFF 0x4 /* DBBT fingerprint offset*/
struct dbbt_block {
u32 checksum; /* reserved on i.MX6 */
diff --git a/arch/arm/include/asm/mach-imx/module_fuse.h b/arch/arm/include/asm/mach-imx/module_fuse.h
new file mode 100644
index 0000000000..a46fc3f1f8
--- /dev/null
+++ b/arch/arm/include/asm/mach-imx/module_fuse.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 NXP
+ */
+
+#ifndef __MODULE_FUSE_H__
+#define __MODULE_FUSE_H__
+
+enum fuse_module_type {
+ MODULE_TSC,
+ MODULE_ADC1,
+ MODULE_ADC2,
+ MODULE_SIM1,
+ MODULE_SIM2,
+ MODULE_FLEXCAN1,
+ MODULE_FLEXCAN2,
+ MODULE_SPDIF,
+ MODULE_EIM,
+ MODULE_SD1,
+ MODULE_SD2,
+ MODULE_SD3,
+ MODULE_SD4,
+ MODULE_QSPI1,
+ MODULE_QSPI2,
+ MODULE_GPMI,
+ MODULE_APBHDMA,
+ MODULE_LCDIF,
+ MODULE_PXP,
+ MODULE_CSI,
+ MODULE_ENET1,
+ MODULE_ENET2,
+ MODULE_CAAM,
+ MODULE_USB_OTG1,
+ MODULE_USB_OTG2,
+ MODULE_SAI2,
+ MODULE_SAI3,
+ MODULE_BEE,
+ MODULE_UART1,
+ MODULE_UART2,
+ MODULE_UART3,
+ MODULE_UART4,
+ MODULE_UART5,
+ MODULE_UART6,
+ MODULE_UART7,
+ MODULE_UART8,
+ MODULE_PWM5,
+ MODULE_PWM6,
+ MODULE_PWM7,
+ MODULE_PWM8,
+ MODULE_ECSPI1,
+ MODULE_ECSPI2,
+ MODULE_ECSPI3,
+ MODULE_ECSPI4,
+ MODULE_ECSPI5,
+ MODULE_I2C1,
+ MODULE_I2C2,
+ MODULE_I2C3,
+ MODULE_I2C4,
+ MODULE_GPT1,
+ MODULE_GPT2,
+ MODULE_EPIT1,
+ MODULE_EPIT2,
+ MODULE_EPDC,
+ MODULE_ESAI,
+ MODULE_DCP,
+ MODULE_DCP_CRYPTO,
+};
+
+struct fuse_entry_desc {
+ enum fuse_module_type module;
+ const char *node_path;
+ u32 fuse_word_offset;
+ u32 fuse_bit_offset;
+ u32 status;
+};
+
+#if !CONFIG_IS_ENABLED(IMX_MODULE_FUSE)
+static inline u32 check_module_fused(enum fuse_module_type module)
+{
+ return 0;
+};
+
+static inline u32 esdhc_fused(ulong base_addr)
+{
+ return 0;
+};
+
+static inline u32 ecspi_fused(ulong base_addr)
+{
+ return 0;
+};
+
+static inline u32 uart_fused(ulong base_addr)
+{
+ return 0;
+};
+
+static inline u32 usb_fused(ulong base_addr)
+{
+ return 0;
+};
+
+static inline u32 qspi_fused(ulong base_addr)
+{
+ return 0;
+};
+
+static inline u32 i2c_fused(ulong base_addr)
+{
+ return 0;
+};
+
+static inline u32 enet_fused(ulong base_addr)
+{
+ return 0;
+};
+#else
+u32 check_module_fused(enum fuse_module_type module);
+u32 esdhc_fused(ulong base_addr);
+u32 ecspi_fused(ulong base_addr);
+u32 uart_fused(ulong base_addr);
+u32 usb_fused(ulong base_addr);
+u32 qspi_fused(ulong base_addr);
+u32 i2c_fused(ulong base_addr);
+u32 enet_fused(ulong base_addr);
+#endif
+#endif /* __MODULE_FUSE_H__ */
diff --git a/arch/arm/include/asm/mach-imx/regs-apbh.h b/arch/arm/include/asm/mach-imx/regs-apbh.h
index d7baf13343..94c330c7f9 100644
--- a/arch/arm/include/asm/mach-imx/regs-apbh.h
+++ b/arch/arm/include/asm/mach-imx/regs-apbh.h
@@ -7,6 +7,7 @@
*
* Based on code from LTIB:
* Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2020 NXP
*/
#ifndef __REGS_APBH_H__
@@ -95,7 +96,7 @@ struct mxs_apbh_regs {
mxs_reg_32(hw_apbh_version)
};
-#elif (defined(CONFIG_MX28) || defined(CONFIG_MX6) || defined(CONFIG_MX7))
+#else
struct mxs_apbh_regs {
mxs_reg_32(hw_apbh_ctrl0)
mxs_reg_32(hw_apbh_ctrl1)
@@ -274,7 +275,7 @@ struct mxs_apbh_regs {
#define APBH_CTRL0_CLKGATE_CHANNEL_NAND7 0x0800
#define APBH_CTRL0_CLKGATE_CHANNEL_HSADC 0x1000
#define APBH_CTRL0_CLKGATE_CHANNEL_LCDIF 0x2000
-#elif (defined(CONFIG_MX6) || defined(CONFIG_MX7))
+#elif (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M))
#define APBH_CTRL0_CLKGATE_CHANNEL_OFFSET 0
#define APBH_CTRL0_CLKGATE_CHANNEL_NAND0 0x0001
#define APBH_CTRL0_CLKGATE_CHANNEL_NAND1 0x0002
@@ -357,7 +358,6 @@ struct mxs_apbh_regs {
#if defined(CONFIG_MX28)
#define APBH_CHANNEL_CTRL_RESET_CHANNEL_MASK (0xffff << 16)
-#define APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET 16
#define APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP0 (0x0001 << 16)
#define APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP1 (0x0002 << 16)
#define APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP2 (0x0004 << 16)
@@ -390,9 +390,8 @@ struct mxs_apbh_regs {
#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_LCDIF 0x2000
#endif
-#if (defined(CONFIG_MX6) || defined(CONFIG_MX7))
+/* Not on i.MX23 */
#define APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET 16
-#endif
#if defined(CONFIG_MX23)
#define APBH_DEVSEL_CH7_MASK (0xf << 28)
diff --git a/arch/arm/include/asm/mach-imx/regs-bch.h b/arch/arm/include/asm/mach-imx/regs-bch.h
index 39ac5f4d45..5a149002e2 100644
--- a/arch/arm/include/asm/mach-imx/regs-bch.h
+++ b/arch/arm/include/asm/mach-imx/regs-bch.h
@@ -6,7 +6,9 @@
* on behalf of DENX Software Engineering GmbH
*
* Based on code from LTIB:
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008-2010, 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2020 NXP
+ *
*/
#ifndef __MX28_REGS_BCH_H__
@@ -40,6 +42,7 @@ struct mxs_bch_regs {
mxs_reg_32(hw_bch_dbgahbmread)
mxs_reg_32(hw_bch_blockname)
mxs_reg_32(hw_bch_version)
+ mxs_reg_32(hw_bch_debug1)
};
#endif
@@ -75,6 +78,9 @@ struct mxs_bch_regs {
#define BCH_MODE_ERASE_THRESHOLD_MASK 0xff
#define BCH_MODE_ERASE_THRESHOLD_OFFSET 0
+#define BCH_MODE_ERASE_THRESHOLD(v) \
+ (((v) << BCH_MODE_ERASE_THRESHOLD_OFFSET) & \
+ BCH_MODE_ERASE_THRESHOLD_MASK)
#define BCH_ENCODEPTR_ADDR_MASK 0xffffffff
#define BCH_ENCODEPTR_ADDR_OFFSET 0
@@ -122,7 +128,7 @@ struct mxs_bch_regs {
#define BCH_FLASHLAYOUT0_NBLOCKS_OFFSET 24
#define BCH_FLASHLAYOUT0_META_SIZE_MASK (0xff << 16)
#define BCH_FLASHLAYOUT0_META_SIZE_OFFSET 16
-#if (defined(CONFIG_MX6) || defined(CONFIG_MX7))
+#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M))
#define BCH_FLASHLAYOUT0_ECC0_MASK (0x1f << 11)
#define BCH_FLASHLAYOUT0_ECC0_OFFSET 11
#else
@@ -146,14 +152,14 @@ struct mxs_bch_regs {
#define BCH_FLASHLAYOUT0_ECC0_ECC28 (0xe << 12)
#define BCH_FLASHLAYOUT0_ECC0_ECC30 (0xf << 12)
#define BCH_FLASHLAYOUT0_ECC0_ECC32 (0x10 << 12)
-#define BCH_FLASHLAYOUT0_GF13_0_GF14_1 (1 << 10)
+#define BCH_FLASHLAYOUT0_GF13_0_GF14_1_MASK BIT(10)
#define BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET 10
-#define BCH_FLASHLAYOUT0_DATA0_SIZE_MASK 0xfff
+#define BCH_FLASHLAYOUT0_DATA0_SIZE_MASK 0x3ff
#define BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET 0
#define BCH_FLASHLAYOUT1_PAGE_SIZE_MASK (0xffff << 16)
#define BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET 16
-#if (defined(CONFIG_MX6) || defined(CONFIG_MX7))
+#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M))
#define BCH_FLASHLAYOUT1_ECCN_MASK (0x1f << 11)
#define BCH_FLASHLAYOUT1_ECCN_OFFSET 11
#else
@@ -177,9 +183,9 @@ struct mxs_bch_regs {
#define BCH_FLASHLAYOUT1_ECCN_ECC28 (0xe << 12)
#define BCH_FLASHLAYOUT1_ECCN_ECC30 (0xf << 12)
#define BCH_FLASHLAYOUT1_ECCN_ECC32 (0x10 << 12)
-#define BCH_FLASHLAYOUT1_GF13_0_GF14_1 (1 << 10)
+#define BCH_FLASHLAYOUT1_GF13_0_GF14_1_MASK BIT(10)
#define BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET 10
-#define BCH_FLASHLAYOUT1_DATAN_SIZE_MASK 0xfff
+#define BCH_FLASHLAYOUT1_DATAN_SIZE_MASK 0x3ff
#define BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET 0
#define BCH_DEBUG0_RSVD1_MASK (0x1f << 27)
diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h
index 2a997f280d..927195f87a 100644
--- a/arch/arm/include/asm/mach-imx/sys_proto.h
+++ b/arch/arm/include/asm/mach-imx/sys_proto.h
@@ -9,6 +9,7 @@
#include <asm/io.h>
#include <asm/mach-imx/regs-common.h>
+#include <asm/mach-imx/module_fuse.h>
#include <common.h>
#include "../arch-imx/cpu.h"
@@ -197,4 +198,6 @@ unsigned long call_imx_sip(unsigned long id, unsigned long reg0,
unsigned long call_imx_sip_ret2(unsigned long id, unsigned long reg0,
unsigned long *reg1, unsigned long reg2,
unsigned long reg3);
+
+void imx_get_mac_from_fuse(int dev_id, unsigned char *mac);
#endif
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 329149900a..bed8cc7e88 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -27,6 +27,13 @@ config IMX_BOOTAUX
help
bootaux [addr] to boot auxiliary core.
+config IMX_MODULE_FUSE
+ bool "i.MX Module Fuse"
+ depends on ARCH_MX6
+ help
+ i.MX module fuse to runtime disable some driver, including
+ Linux OS device node.
+
config USE_IMXIMG_PLUGIN
bool "Use imximage plugin code"
depends on ARCH_MX7 || ARCH_MX6 || ARCH_MX7ULP
@@ -82,7 +89,7 @@ config CMD_NANDBCB
bool "i.MX6 NAND Boot Control Block(BCB) command"
depends on MTD_RAW_NAND && CMD_MTDPARTS
select BCH if MX6UL || MX6ULL
- default y if (ARCH_MX6 && NAND_MXS) || (ARCH_MX7 && NAND_MXS)
+ default y if ((ARCH_MX6 || ARCH_MX7 || ARCH_IMX8M) && NAND_MXS)
help
Unlike normal 'nand write/erase' commands, this command update
Boot Control Block(BCB) for i.MX6 platform NAND IP's.
diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
index b3e59b1b00..94cae146ce 100644
--- a/arch/arm/mach-imx/cmd_nandbcb.c
+++ b/arch/arm/mach-imx/cmd_nandbcb.c
@@ -1,11 +1,13 @@
/*
- * i.MX6 nand boot control block(bcb).
+ * i.MX nand boot control block(bcb).
*
* Based on the common/imx-bbu-nand-fcb.c from barebox and imx kobs-ng
*
* Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
* Copyright (C) 2016 Sergey Kubushyn <ksi@koi8.net>
*
+ * Reconstucted by Han Xu <han.xu@nxp.com>
+ *
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -25,11 +27,296 @@
#include <mxs_nand.h>
#include <linux/mtd/mtd.h>
#include <nand.h>
+#include <fuse.h>
#include "../../../cmd/legacy-mtd-utils.h"
-#define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET)
+/* FCB related flags */
+/* FCB layout with leading 12B reserved */
+#define FCB_LAYOUT_RESV_12B BIT(0)
+/* FCB layout with leading 32B meta data */
+#define FCB_LAYOUT_META_32B BIT(1)
+/* FCB encrypted by Hamming code */
+#define FCB_ENCODE_HAMMING BIT(2)
+/* FCB encrypted by 40bit BCH */
+#define FCB_ENCODE_BCH_40b BIT(3)
+/* FCB encrypted by 62bit BCH */
+#define FCB_ENCODE_BCH_62b BIT(4)
+/* FCB encrypted by BCH */
+#define FCB_ENCODE_BCH (FCB_ENCODE_BCH_40b | FCB_ENCODE_BCH_62b)
+/* FCB data was randomized */
+#define FCB_RANDON_ENABLED BIT(5)
+
+/* Firmware related flags */
+/* No 1K padding */
+#define FIRMWARE_NEED_PADDING BIT(8)
+/* Extra firmware*/
+#define FIRMWARE_EXTRA_ONE BIT(9)
+/* Secondary firmware on fixed address */
+#define FIRMWARE_SECONDARY_FIXED_ADDR BIT(10)
+
+/* Boot search related flags */
+#define BT_SEARCH_CNT_FROM_FUSE BIT(16)
+
+struct platform_config {
+ int misc_flags;
+};
+
+static struct platform_config plat_config;
+
+/* imx6q/dl/solo */
+static struct platform_config imx6qdl_plat_config = {
+ .misc_flags = FCB_LAYOUT_RESV_12B |
+ FCB_ENCODE_HAMMING |
+ FIRMWARE_NEED_PADDING,
+};
+
+static struct platform_config imx6sx_plat_config = {
+ .misc_flags = FCB_LAYOUT_META_32B |
+ FCB_ENCODE_BCH_62b |
+ FIRMWARE_NEED_PADDING |
+ FCB_RANDON_ENABLED,
+};
+
+static struct platform_config imx7d_plat_config = {
+ .misc_flags = FCB_LAYOUT_META_32B |
+ FCB_ENCODE_BCH_62b |
+ FIRMWARE_NEED_PADDING |
+ FCB_RANDON_ENABLED,
+};
+
+/* imx6ul/ull/ulz */
+static struct platform_config imx6ul_plat_config = {
+ .misc_flags = FCB_LAYOUT_META_32B |
+ FCB_ENCODE_BCH_40b |
+ FIRMWARE_NEED_PADDING,
+};
+
+static struct platform_config imx8mq_plat_config = {
+ .misc_flags = FCB_LAYOUT_META_32B |
+ FCB_ENCODE_BCH_62b |
+ FIRMWARE_NEED_PADDING |
+ FCB_RANDON_ENABLED |
+ FIRMWARE_EXTRA_ONE,
+};
+
+/* all other imx8mm */
+static struct platform_config imx8mm_plat_config = {
+ .misc_flags = FCB_LAYOUT_META_32B |
+ FCB_ENCODE_BCH_62b |
+ FIRMWARE_NEED_PADDING |
+ FCB_RANDON_ENABLED,
+};
+
+/* imx8mn */
+static struct platform_config imx8mn_plat_config = {
+ .misc_flags = FCB_LAYOUT_META_32B |
+ FCB_ENCODE_BCH_62b |
+ FCB_RANDON_ENABLED |
+ FIRMWARE_SECONDARY_FIXED_ADDR |
+ BT_SEARCH_CNT_FROM_FUSE,
+};
+
+/* imx8qx/qm */
+static struct platform_config imx8q_plat_config = {
+ .misc_flags = FCB_LAYOUT_META_32B |
+ FCB_ENCODE_BCH_62b |
+ FCB_RANDON_ENABLED |
+ FIRMWARE_SECONDARY_FIXED_ADDR |
+ BT_SEARCH_CNT_FROM_FUSE,
+};
+
+/* boot search related variables and definitions */
+static int g_boot_search_count = 4;
+static int g_boot_search_stride;
+static int g_pages_per_stride;
+
+/* mtd config structure */
+struct boot_config {
+ int dev;
+ struct mtd_info *mtd;
+ loff_t maxsize;
+ loff_t input_size;
+ loff_t offset;
+ loff_t boot_stream1_address;
+ loff_t boot_stream2_address;
+ size_t boot_stream1_size;
+ size_t boot_stream2_size;
+ size_t max_boot_stream_size;
+ int stride_size_in_byte;
+ int search_area_size_in_bytes;
+ int search_area_size_in_pages;
+ int secondary_boot_stream_off_in_MB;
+};
+
+/* boot_stream config structure */
+struct boot_stream_config {
+ char bs_label[32];
+ loff_t bs_addr;
+ size_t bs_size;
+ void *bs_buf;
+ loff_t next_bs_addr;
+ bool need_padding;
+};
+
+/* FW index */
+#define FW1_ONLY 1
+#define FW2_ONLY 2
+#define FW_ALL FW1_ONLY | FW2_ONLY
+#define FW_INX(x) (1 << (x))
+
+/* NAND convert macros */
+#define CONV_TO_PAGES(x) ((u32)(x) / (u32)(mtd->writesize))
+#define CONV_TO_BLOCKS(x) ((u32)(x) / (u32)(mtd->erasesize))
+
#define GETBIT(v, n) (((v) >> (n)) & 0x1)
+#define IMX8MQ_SPL_SZ 0x3e000
+#define IMX8MQ_HDMI_FW_SZ 0x19c00
+
+static int nandbcb_get_info(int argc, char * const argv[],
+ struct boot_config *boot_cfg)
+{
+ int dev;
+ struct mtd_info *mtd;
+
+ dev = nand_curr_device;
+ if (dev < 0) {
+ printf("failed to get nand_curr_device, run nand device\n");
+ return CMD_RET_FAILURE;
+ }
+
+ mtd = get_nand_dev_by_index(dev);
+ if (!mtd) {
+ printf("failed to get mtd info\n");
+ return CMD_RET_FAILURE;
+ }
+
+ boot_cfg->dev = dev;
+ boot_cfg->mtd = mtd;
+
+ return CMD_RET_SUCCESS;
+}
+
+static int nandbcb_get_size(int argc, char * const argv[], int num,
+ struct boot_config *boot_cfg)
+{
+ int dev;
+ loff_t offset, size, maxsize;
+ struct mtd_info *mtd;
+
+ dev = boot_cfg->dev;
+ mtd = boot_cfg->mtd;
+ size = 0;
+
+ if (mtd_arg_off_size(argc - num, argv + num, &dev, &offset, &size,
+ &maxsize, MTD_DEV_TYPE_NAND, mtd->size))
+ return CMD_RET_FAILURE;
+
+ boot_cfg->maxsize = maxsize;
+ boot_cfg->offset = offset;
+
+ debug("max: %llx, offset: %llx\n", maxsize, offset);
+
+ if (size && size != maxsize)
+ boot_cfg->input_size = size;
+
+ return CMD_RET_SUCCESS;
+}
+
+static int nandbcb_set_boot_config(int argc, char * const argv[],
+ struct boot_config *boot_cfg)
+{
+ struct mtd_info *mtd;
+ loff_t maxsize;
+ loff_t boot_stream1_address, boot_stream2_address, max_boot_stream_size;
+
+ if (!boot_cfg->mtd) {
+ printf("Didn't get the mtd info, quit\n");
+ return CMD_RET_FAILURE;
+ }
+ mtd = boot_cfg->mtd;
+
+ /*
+ * By default
+ * set the search count as 4
+ * set each FCB/DBBT/Firmware offset at the beginning of blocks
+ * customers may change the value as needed
+ */
+
+ /* if need more compact layout, change these values */
+ /* g_boot_search_count was set as 4 at the definition*/
+ /* g_pages_per_stride was set as block size */
+
+ g_pages_per_stride = mtd->erasesize / mtd->writesize;
+
+ g_boot_search_stride = mtd->writesize * g_pages_per_stride;
+
+ boot_cfg->stride_size_in_byte = g_boot_search_stride * mtd->writesize;
+ boot_cfg->search_area_size_in_bytes =
+ g_boot_search_count * g_boot_search_stride;
+ boot_cfg->search_area_size_in_pages =
+ boot_cfg->search_area_size_in_bytes / mtd->writesize;
+
+ /* after FCB/DBBT, split the rest of area for two Firmwares */
+ if (!boot_cfg->maxsize) {
+ printf("Didn't get the maxsize, quit\n");
+ return CMD_RET_FAILURE;
+ }
+ maxsize = boot_cfg->maxsize;
+ /* align to page boundary */
+ maxsize = ((u32)(maxsize + mtd->writesize - 1)) / (u32)mtd->writesize
+ * mtd->writesize;
+
+ boot_stream1_address = 2 * boot_cfg->search_area_size_in_bytes;
+ boot_stream2_address = ((maxsize - boot_stream1_address) / 2 +
+ boot_stream1_address);
+
+ if (boot_cfg->secondary_boot_stream_off_in_MB)
+ boot_stream2_address = boot_cfg->secondary_boot_stream_off_in_MB * 1024 * 1024;
+
+ max_boot_stream_size = boot_stream2_address - boot_stream1_address;
+
+ /* sanity check */
+ if (max_boot_stream_size <= 0) {
+ debug("st1_addr: %llx, st2_addr: %llx, max: %llx\n",
+ boot_stream1_address, boot_stream2_address,
+ max_boot_stream_size);
+ printf("something wrong with firmware address settings\n");
+ return CMD_RET_FAILURE;
+ }
+ boot_cfg->boot_stream1_address = boot_stream1_address;
+ boot_cfg->boot_stream2_address = boot_stream2_address;
+ boot_cfg->max_boot_stream_size = max_boot_stream_size;
+
+ /* set the boot_stream size as the input size now */
+ if (boot_cfg->input_size) {
+ boot_cfg->boot_stream1_size = boot_cfg->input_size;
+ boot_cfg->boot_stream2_size = boot_cfg->input_size;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int nandbcb_check_space(struct boot_config *boot_cfg)
+{
+ size_t maxsize = boot_cfg->maxsize;
+ size_t max_boot_stream_size = boot_cfg->max_boot_stream_size;
+ loff_t boot_stream2_address = boot_cfg->boot_stream2_address;
+
+ if (boot_cfg->boot_stream1_size &&
+ boot_cfg->boot_stream1_size > max_boot_stream_size) {
+ printf("boot stream1 doesn't fit, check partition size or settings\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (boot_cfg->boot_stream2_size &&
+ boot_cfg->boot_stream2_size > maxsize - boot_stream2_address) {
+ printf("boot stream2 doesn't fit, check partition size or settings\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
#if defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL)
static uint8_t reverse_bit(uint8_t b)
@@ -132,9 +419,9 @@ static u32 calc_chksum(void *buf, size_t size)
return ~chksum;
}
-static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd,
- u32 fw1_start, u32 fw2_start, u32 fw_pages)
+static void fill_fcb(struct fcb_block *fcb, struct boot_config *boot_cfg)
{
+ struct mtd_info *mtd = boot_cfg->mtd;
struct nand_chip *chip = mtd_to_nand(mtd);
struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
struct mxs_nand_layout l;
@@ -144,6 +431,11 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd,
fcb->fingerprint = FCB_FINGERPRINT;
fcb->version = FCB_VERSION_1;
+ fcb->datasetup = 80;
+ fcb->datahold = 60;
+ fcb->addr_setup = 25;
+ fcb->dsample_time = 6;
+
fcb->pagesize = mtd->writesize;
fcb->oob_pagesize = mtd->writesize + mtd->oobsize;
fcb->sectors = mtd->erasesize / mtd->writesize;
@@ -154,42 +446,27 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd,
fcb->ecc_level = l.ecc0;
fcb->ecc_size = l.datan_size;
fcb->ecc_type = l.eccn;
+ fcb->bchtype = l.gf_len;
- /* Also hardcoded in kobs-ng */
- if (is_mx6()) {
- fcb->datasetup = 80;
- fcb->datahold = 60;
- fcb->addr_setup = 25;
- fcb->dsample_time = 6;
- } else if (is_mx7()) {
- fcb->datasetup = 10;
- fcb->datahold = 7;
- fcb->addr_setup = 15;
- fcb->dsample_time = 6;
- }
-
- /* DBBT search area starts at second page on first block */
- fcb->dbbt_start = 1;
+ /* DBBT search area starts from the next block after all FCB */
+ fcb->dbbt_start = boot_cfg->search_area_size_in_pages;
fcb->bb_byte = nand_info->bch_geometry.block_mark_byte_offset;
fcb->bb_start_bit = nand_info->bch_geometry.block_mark_bit_offset;
fcb->phy_offset = mtd->writesize;
- fcb->nr_blocks = mtd->writesize / fcb->ecc_nr - 1;
-
fcb->disbbm = 0;
- fcb->disbbm_search = 0;
- fcb->fw1_start = fw1_start; /* Firmware image starts on this sector */
- fcb->fw2_start = fw2_start; /* Secondary FW Image starting Sector */
- fcb->fw1_pages = fw_pages; /* Number of sectors in firmware image */
- fcb->fw2_pages = fw_pages; /* Number of sector in secondary FW image */
+ fcb->fw1_start = CONV_TO_PAGES(boot_cfg->boot_stream1_address);
+ fcb->fw2_start = CONV_TO_PAGES(boot_cfg->boot_stream2_address);
+ fcb->fw1_pages = CONV_TO_PAGES(boot_cfg->boot_stream1_size);
+ fcb->fw2_pages = CONV_TO_PAGES(boot_cfg->boot_stream2_size);
fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
}
-static int dbbt_fill_data(struct mtd_info *mtd, void *buf, int num_blocks)
+static int fill_dbbt_data(struct mtd_info *mtd, void *buf, int num_blocks)
{
int n, n_bad_blocks = 0;
u32 *bb = buf + 0x8;
@@ -209,20 +486,92 @@ static int dbbt_fill_data(struct mtd_info *mtd, void *buf, int num_blocks)
return n_bad_blocks;
}
-static int write_fcb_dbbt(struct mtd_info *mtd, struct fcb_block *fcb,
- struct dbbt_block *dbbt, void *dbbt_data_page,
- loff_t off)
+/*
+ * return 1 - bad block
+ * return 0 - read successfully
+ * return < 0 - read failed
+ */
+static int read_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb,
+ loff_t off)
+{
+ struct mtd_info *mtd;
+ void *fcb_raw_page;
+ size_t size;
+ int ret = 0;
+
+ mtd = boot_cfg->mtd;
+ fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
+
+ if (mtd_block_isbad(mtd, off)) {
+ printf("Block %d is bad, skipped\n", (int)CONV_TO_BLOCKS(off));
+ return 1;
+ }
+
+ /*
+ * User BCH hardware to decode ECC for FCB
+ */
+ if (plat_config.misc_flags & FCB_ENCODE_BCH) {
+ size = sizeof(struct fcb_block);
+
+ /* switch nand BCH to FCB compatible settings */
+ if (plat_config.misc_flags & FCB_ENCODE_BCH_62b)
+ mxs_nand_mode_fcb_62bit(mtd);
+ else if (plat_config.misc_flags & FCB_ENCODE_BCH_40b)
+ mxs_nand_mode_fcb_40bit(mtd);
+
+ ret = nand_read(mtd, off, &size, (u_char *)fcb);
+
+ /* switch BCH back */
+ mxs_nand_mode_normal(mtd);
+ printf("NAND FCB read from 0x%llx offset 0x%zx read: %s\n",
+ off, size, ret ? "ERROR" : "OK");
+
+ } else if (plat_config.misc_flags & FCB_ENCODE_HAMMING) {
+ /* raw read*/
+ mtd_oob_ops_t ops = {
+ .datbuf = (u8 *)fcb_raw_page,
+ .oobbuf = ((u8 *)fcb_raw_page) + mtd->writesize,
+ .len = mtd->writesize,
+ .ooblen = mtd->oobsize,
+ .mode = MTD_OPS_RAW
+ };
+
+ ret = mtd_read_oob(mtd, off, &ops);
+ printf("NAND FCB read from 0x%llx offset 0x%zx read: %s\n",
+ off, ops.len, ret ? "ERROR" : "OK");
+ }
+
+ if (ret)
+ goto fcb_raw_page_err;
+
+ if ((plat_config.misc_flags & FCB_ENCODE_HAMMING) &&
+ (plat_config.misc_flags & FCB_LAYOUT_RESV_12B))
+ memcpy(fcb, fcb_raw_page + 12, sizeof(struct fcb_block));
+
+/* TODO: check if it can pass Hamming check */
+
+fcb_raw_page_err:
+ kfree(fcb_raw_page);
+
+ return ret;
+}
+
+static int write_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb)
{
- void *fcb_raw_page = 0;
+ struct mtd_info *mtd;
+ void *fcb_raw_page = NULL;
int i, ret;
- size_t dummy;
+ loff_t off;
+ size_t size;
+
+ mtd = boot_cfg->mtd;
/*
* We prepare raw page only for i.MX6, for i.MX7 we
* leverage BCH hw module instead
*/
- if (is_mx6()) {
- /* write fcb/dbbt */
+ if ((plat_config.misc_flags & FCB_ENCODE_HAMMING) &&
+ (plat_config.misc_flags & FCB_LAYOUT_RESV_12B)) {
fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize,
GFP_KERNEL);
if (!fcb_raw_page) {
@@ -250,29 +599,36 @@ static int write_fcb_dbbt(struct mtd_info *mtd, struct fcb_block *fcb,
*/
memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
}
- for (i = 0; i < 2; i++) {
+
+ /* start writing FCB from the very beginning */
+ off = 0;
+
+ for (i = 0; i < g_boot_search_count; i++) {
if (mtd_block_isbad(mtd, off)) {
printf("Block %d is bad, skipped\n", i);
continue;
}
/*
- * User BCH ECC hardware module for i.MX7
+ * User BCH hardware module to generate ECC for FCB
*/
- if (is_mx7()) {
- u32 off = i * mtd->erasesize;
- size_t rwsize = sizeof(*fcb);
-
- printf("Writing %d bytes to 0x%x: ", rwsize, off);
+ if (plat_config.misc_flags & FCB_ENCODE_BCH) {
+ size = sizeof(struct fcb_block);
/* switch nand BCH to FCB compatible settings */
- mxs_nand_mode_fcb(mtd);
- ret = nand_write(mtd, off, &rwsize,
- (unsigned char *)fcb);
+ if (plat_config.misc_flags & FCB_ENCODE_BCH_62b)
+ mxs_nand_mode_fcb_62bit(mtd);
+ else if (plat_config.misc_flags & FCB_ENCODE_BCH_40b)
+ mxs_nand_mode_fcb_40bit(mtd);
+
+ ret = nand_write(mtd, off, &size, (u_char *)fcb);
+
+ /* switch BCH back */
mxs_nand_mode_normal(mtd);
+ printf("NAND FCB write to 0x%zx offset 0x%llx written: %s\n",
+ size, off, ret ? "ERROR" : "OK");
- printf("%s\n", ret ? "ERROR" : "OK");
- } else if (is_mx6()) {
+ } else if (plat_config.misc_flags & FCB_ENCODE_HAMMING) {
/* raw write */
mtd_oob_ops_t ops = {
.datbuf = (u8 *)fcb_raw_page,
@@ -283,52 +639,327 @@ static int write_fcb_dbbt(struct mtd_info *mtd, struct fcb_block *fcb,
.mode = MTD_OPS_RAW
};
- ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
- if (ret)
- goto fcb_raw_page_err;
- debug("NAND fcb write: 0x%x offset 0x%x written: %s\n",
- mtd->erasesize * i, ops.len, ret ?
- "ERROR" : "OK");
+ ret = mtd_write_oob(mtd, off, &ops);
+ printf("NAND FCB write to 0x%llxx offset 0x%zx written: %s\n", off, ops.len, ret ? "ERROR" : "OK");
}
- ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,
- mtd->writesize, &dummy, (void *)dbbt);
if (ret)
goto fcb_raw_page_err;
- debug("NAND dbbt write: 0x%x offset, 0x%x bytes written: %s\n",
- mtd->erasesize * i + mtd->writesize, dummy,
- ret ? "ERROR" : "OK");
+
+ /* next writing location */
+ off += g_boot_search_stride;
+ }
+
+ return 0;
+
+fcb_raw_page_err:
+ kfree(fcb_raw_page);
+
+ return ret;
+}
+
+/*
+ * return 1 - bad block
+ * return 0 - read successfully
+ * return < 0 - read failed
+ */
+static int read_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
+ void *dbbt_data_page, loff_t off)
+{
+ size_t size;
+ struct mtd_info *mtd;
+ loff_t to;
+ int ret;
+
+ mtd = boot_cfg->mtd;
+
+ if (mtd_block_isbad(mtd, off)) {
+ printf("Block %d is bad, skipped\n",
+ (int)CONV_TO_BLOCKS(off));
+ return 1;
+ }
+
+ size = sizeof(struct dbbt_block);
+ ret = nand_read(mtd, off, &size, (u_char *)dbbt);
+ printf("NAND DBBT read from 0x%llx offset 0x%zx read: %s\n",
+ off, size, ret ? "ERROR" : "OK");
+ if (ret)
+ return ret;
+
+ /* dbbtpages == 0 if no bad blocks */
+ if (dbbt->dbbtpages > 0) {
+ to = off + 4 * mtd->writesize;
+ size = mtd->writesize;
+ ret = nand_read(mtd, to, &size, dbbt_data_page);
+ printf("DBBT data read from 0x%llx offset 0x%zx read: %s\n",
+ to, size, ret ? "ERROR" : "OK");
+
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int write_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
+ void *dbbt_data_page)
+{
+ int i;
+ loff_t off, to;
+ size_t size;
+ struct mtd_info *mtd;
+ int ret;
+
+ mtd = boot_cfg->mtd;
+
+ /* start writing DBBT after all FCBs */
+ off = boot_cfg->search_area_size_in_bytes;
+ size = mtd->writesize;
+
+ for (i = 0; i < g_boot_search_count; i++) {
+ if (mtd_block_isbad(mtd, off)) {
+ printf("Block %d is bad, skipped\n",
+ (int)(i + CONV_TO_BLOCKS(off)));
+ continue;
+ }
+
+ ret = nand_write(mtd, off, &size, (u_char *)dbbt);
+ printf("NAND DBBT write to 0x%llx offset 0x%zx written: %s\n",
+ off, size, ret ? "ERROR" : "OK");
+ if (ret)
+ return ret;
/* dbbtpages == 0 if no bad blocks */
if (dbbt->dbbtpages > 0) {
- loff_t to = (mtd->erasesize * i + mtd->writesize * 5);
+ to = off + 4 * mtd->writesize;
+ ret = nand_write(mtd, to, &size, dbbt_data_page);
+ printf("DBBT data write to 0x%llx offset 0x%zx written: %s\n",
+ to, size, ret ? "ERROR" : "OK");
- ret = mtd_write(mtd, to, mtd->writesize, &dummy,
- dbbt_data_page);
- if (ret)
- goto fcb_raw_page_err;
+ if (ret)
+ return ret;
}
+
+ /* next writing location */
+ off += g_boot_search_stride;
}
-fcb_raw_page_err:
- if (is_mx6())
- kfree(fcb_raw_page);
+ return 0;
+}
+
+/* reuse the check_skip_len from nand_util.c with minor change*/
+static int check_skip_length(struct boot_config *boot_cfg, loff_t offset,
+ size_t length, size_t *used)
+{
+ struct mtd_info *mtd = boot_cfg->mtd;
+ size_t maxsize = boot_cfg->maxsize;
+ size_t len_excl_bad = 0;
+ int ret = 0;
+
+ while (len_excl_bad < length) {
+ size_t block_len, block_off;
+ loff_t block_start;
+
+ if (offset >= maxsize)
+ return -1;
+
+ block_start = offset & ~(loff_t)(mtd->erasesize - 1);
+ block_off = offset & (mtd->erasesize - 1);
+ block_len = mtd->erasesize - block_off;
+
+ if (!nand_block_isbad(mtd, block_start))
+ len_excl_bad += block_len;
+ else
+ ret = 1;
+
+ offset += block_len;
+ *used += block_len;
+ }
+
+ /* If the length is not a multiple of block_len, adjust. */
+ if (len_excl_bad > length)
+ *used -= (len_excl_bad - length);
+
+ return ret;
+}
+
+static int nandbcb_get_next_good_blk_addr(struct boot_config *boot_cfg,
+ struct boot_stream_config *bs_cfg)
+{
+ struct mtd_info *mtd = boot_cfg->mtd;
+ loff_t offset = bs_cfg->bs_addr;
+ size_t length = bs_cfg->bs_size;
+ size_t used = 0;
+ int ret;
+
+ ret = check_skip_length(boot_cfg, offset, length, &used);
+
+ if (ret < 0)
+ return ret;
+
+ /* get next image address */
+ bs_cfg->next_bs_addr = (u32)(offset + used + mtd->erasesize - 1)
+ / (u32)mtd->erasesize * mtd->erasesize;
return ret;
}
-static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
- size_t maxsize, const u_char *buf)
+static int nandbcb_write_bs_skip_bad(struct boot_config *boot_cfg,
+ struct boot_stream_config *bs_cfg)
{
+ struct mtd_info *mtd;
+ void *buf;
+ loff_t offset, maxsize;
+ size_t size;
+ size_t length;
+ int ret;
+ bool padding_flag = false;
+
+ mtd = boot_cfg->mtd;
+ offset = bs_cfg->bs_addr;
+ maxsize = boot_cfg->maxsize;
+ size = bs_cfg->bs_size;
+
+ /* some boot images may need leading offset */
+ if (bs_cfg->need_padding &&
+ (plat_config.misc_flags & FIRMWARE_NEED_PADDING))
+ padding_flag = 1;
+
+ if (padding_flag)
+ length = ALIGN(size + FLASH_OFFSET_STANDARD, mtd->writesize);
+ else
+ length = ALIGN(size, mtd->writesize);
+
+ buf = kzalloc(length, GFP_KERNEL);
+ if (!buf) {
+ printf("failed to allocate buffer for firmware\n");
+ ret = -ENOMEM;
+ return ret;
+ }
+
+ if (padding_flag)
+ memcpy(buf + FLASH_OFFSET_STANDARD, bs_cfg->bs_buf, size);
+ else
+ memcpy(buf, bs_cfg->bs_buf, size);
+
+ ret = nand_write_skip_bad(mtd, offset, &length, NULL, maxsize,
+ (u_char *)buf, WITH_WR_VERIFY);
+ printf("Write %s @0x%llx offset, 0x%zx bytes written: %s\n",
+ bs_cfg->bs_label, offset, length, ret ? "ERROR" : "OK");
+
+ if (ret)
+ /* write image failed, quit */
+ goto err;
+
+ /* get next good blk address if needed */
+ if (bs_cfg->need_padding) {
+ ret = nandbcb_get_next_good_blk_addr(boot_cfg, bs_cfg);
+ if (ret < 0) {
+ printf("Next image cannot fit in NAND partition\n");
+ goto err;
+ }
+ }
+
+ /* now we know how the exact image size written to NAND */
+ bs_cfg->bs_size = length;
+ return 0;
+err:
+ kfree(buf);
+ return ret;
+}
+
+static int nandbcb_write_fw(struct boot_config *boot_cfg, u_char *buf,
+ int index)
+{
+ int i;
+ loff_t offset;
+ size_t size;
+ loff_t next_bs_addr;
+ struct boot_stream_config bs_cfg;
+ int ret;
+
+ for (i = 0; i < 2; ++i) {
+ if (!(FW_INX(i) & index))
+ continue;
+
+ if (i == 0) {
+ offset = boot_cfg->boot_stream1_address;
+ size = boot_cfg->boot_stream1_size;
+ } else {
+ offset = boot_cfg->boot_stream2_address;
+ size = boot_cfg->boot_stream2_size;
+ }
+
+ /* write Firmware*/
+ if (!(plat_config.misc_flags & FIRMWARE_EXTRA_ONE)) {
+ memset(&bs_cfg, 0, sizeof(struct boot_stream_config));
+ sprintf(bs_cfg.bs_label, "firmware%d", i);
+ bs_cfg.bs_addr = offset;
+ bs_cfg.bs_size = size;
+ bs_cfg.bs_buf = buf;
+ bs_cfg.need_padding = 1;
+
+ ret = nandbcb_write_bs_skip_bad(boot_cfg, &bs_cfg);
+ if (ret)
+ return ret;
+
+ /* update the boot stream size */
+ if (i == 0)
+ boot_cfg->boot_stream1_size = bs_cfg.bs_size;
+ else
+ boot_cfg->boot_stream2_size = bs_cfg.bs_size;
+
+ } else {
+ /* some platforms need extra firmware */
+ memset(&bs_cfg, 0, sizeof(struct boot_stream_config));
+ sprintf(bs_cfg.bs_label, "fw%d_part%d", i, 1);
+ bs_cfg.bs_addr = offset;
+ bs_cfg.bs_size = IMX8MQ_HDMI_FW_SZ;
+ bs_cfg.bs_buf = buf;
+ bs_cfg.need_padding = 1;
+
+ ret = nandbcb_write_bs_skip_bad(boot_cfg, &bs_cfg);
+ if (ret)
+ return ret;
+
+ /* update the boot stream size */
+ if (i == 0)
+ boot_cfg->boot_stream1_size = bs_cfg.bs_size;
+ else
+ boot_cfg->boot_stream2_size = bs_cfg.bs_size;
+
+ /* get next image address */
+ next_bs_addr = bs_cfg.next_bs_addr;
+
+ memset(&bs_cfg, 0, sizeof(struct boot_stream_config));
+ sprintf(bs_cfg.bs_label, "fw%d_part%d", i, 2);
+ bs_cfg.bs_addr = next_bs_addr;
+ bs_cfg.bs_size = IMX8MQ_SPL_SZ;
+ bs_cfg.bs_buf = (u_char *)(buf + IMX8MQ_HDMI_FW_SZ);
+ bs_cfg.need_padding = 0;
+
+ ret = nandbcb_write_bs_skip_bad(boot_cfg, &bs_cfg);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int nandbcb_init(struct boot_config *boot_cfg, u_char *buf)
+{
+ struct mtd_info *mtd;
nand_erase_options_t opts;
struct fcb_block *fcb;
struct dbbt_block *dbbt;
- loff_t fw1_off;
- void *fwbuf, *dbbt_page, *dbbt_data_page;
- u32 fw1_start, fw1_pages;
- int nr_blks, nr_blks_fcb, fw1_blk;
- size_t fwsize;
+ void *dbbt_page, *dbbt_data_page;
int ret;
+ loff_t maxsize, off;
+
+ mtd = boot_cfg->mtd;
+ maxsize = boot_cfg->maxsize;
+ off = boot_cfg->offset;
/* erase */
memset(&opts, 0, sizeof(opts));
@@ -358,42 +989,24 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
* - two firmware blocks, primary and secondary
* - first 4 block for FCB/DBBT
* - rest split in half for primary and secondary firmware
- * - same firmware will write two times
+ * - same firmware write twice
*/
- nr_blks_fcb = 2;
- nr_blks = maxsize / mtd->erasesize;
- fw1_blk = nr_blks_fcb;
-
- /* write fw */
- fwsize = ALIGN(size + FLASH_OFFSET_STANDARD + mtd->writesize,
- mtd->writesize);
- fwbuf = kzalloc(fwsize, GFP_KERNEL);
- if (!fwbuf) {
- debug("failed to allocate fwbuf\n");
- ret = -ENOMEM;
- goto err;
- }
- memcpy(fwbuf + FLASH_OFFSET_STANDARD, buf, size);
- fw1_off = fw1_blk * mtd->erasesize;
- ret = nand_write_skip_bad(mtd, fw1_off, &fwsize, NULL, maxsize,
- (u_char *)fwbuf, WITH_WR_VERIFY);
- printf("NAND fw write: 0x%llx offset, 0x%x bytes written: %s\n",
- fw1_off, fwsize, ret ? "ERROR" : "OK");
+ /* write Firmware*/
+ ret = nandbcb_write_fw(boot_cfg, buf, FW_ALL);
if (ret)
- goto fwbuf_err;
+ goto err;
/* fill fcb */
fcb = kzalloc(sizeof(*fcb), GFP_KERNEL);
if (!fcb) {
debug("failed to allocate fcb\n");
ret = -ENOMEM;
- goto fwbuf_err;
+ return ret;
}
+ fill_fcb(fcb, boot_cfg);
- fw1_start = (fw1_blk * mtd->erasesize) / mtd->writesize;
- fw1_pages = size / mtd->writesize + 1;
- fill_fcb(fcb, mtd, fw1_start, 0, fw1_pages);
+ ret = write_fcb(boot_cfg, fcb);
/* fill dbbt */
dbbt_page = kzalloc(mtd->writesize, GFP_KERNEL);
@@ -412,16 +1025,16 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
dbbt = dbbt_page;
dbbt->checksum = 0;
- dbbt->fingerprint = DBBT_FINGERPRINT2;
+ dbbt->fingerprint = DBBT_FINGERPRINT;
dbbt->version = DBBT_VERSION_1;
- ret = dbbt_fill_data(mtd, dbbt_data_page, nr_blks);
+ ret = fill_dbbt_data(mtd, dbbt_data_page, CONV_TO_BLOCKS(maxsize));
if (ret < 0)
goto dbbt_data_page_err;
else if (ret > 0)
dbbt->dbbtpages = 1;
- /* write fcb and dbbt to nand */
- ret = write_fcb_dbbt(mtd, fcb, dbbt, dbbt_data_page, off);
+ /* write dbbt */
+ ret = write_dbbt(boot_cfg, dbbt, dbbt_data_page);
if (ret < 0)
printf("failed to write FCB/DBBT\n");
@@ -431,8 +1044,6 @@ dbbt_page_err:
kfree(dbbt_page);
fcb_err:
kfree(fcb);
-fwbuf_err:
- kfree(fwbuf);
err:
return ret;
}
@@ -441,69 +1052,98 @@ static int do_nandbcb_bcbonly(int argc, char * const argv[])
{
struct fcb_block *fcb;
struct dbbt_block *dbbt;
- u32 fw_len, fw1_off, fw2_off;
struct mtd_info *mtd;
+ nand_erase_options_t opts;
+ size_t maxsize;
+ loff_t off;
void *dbbt_page, *dbbt_data_page;
- int dev, ret;
+ int ret;
+ struct boot_config cfg;
- dev = nand_curr_device;
- if ((dev < 0) || (dev >= CONFIG_SYS_MAX_NAND_DEVICE) ||
- (!get_nand_dev_by_index(dev))) {
- puts("No devices available\n");
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ memset(&cfg, 0, sizeof(struct boot_config));
+ if (nandbcb_get_info(argc, argv, &cfg))
return CMD_RET_FAILURE;
- }
- mtd = get_nand_dev_by_index(dev);
+ /* only get the partition info */
+ if (nandbcb_get_size(2, argv, 1, &cfg))
+ return CMD_RET_FAILURE;
- if (argc < 3)
+ if (nandbcb_set_boot_config(argc, argv, &cfg))
return CMD_RET_FAILURE;
- fw_len = simple_strtoul(argv[1], NULL, 16);
- fw1_off = simple_strtoul(argv[2], NULL, 16);
+ mtd = cfg.mtd;
- if (argc > 3)
- fw2_off = simple_strtoul(argv[3], NULL, 16);
- else
- fw2_off = fw1_off;
+ cfg.boot_stream1_address = simple_strtoul(argv[2], NULL, 16);
+ cfg.boot_stream1_size = simple_strtoul(argv[3], NULL, 16);
+ cfg.boot_stream1_size = ALIGN(cfg.boot_stream1_size, mtd->writesize);
+
+ if (argc > 5) {
+ cfg.boot_stream2_address = simple_strtoul(argv[4], NULL, 16);
+ cfg.boot_stream2_size = simple_strtoul(argv[5], NULL, 16);
+ cfg.boot_stream2_size = ALIGN(cfg.boot_stream2_size,
+ mtd->writesize);
+ }
+
+ /* sanity check */
+ nandbcb_check_space(&cfg);
+
+ maxsize = cfg.maxsize;
+ off = cfg.offset;
+
+ /* erase the previous FCB/DBBT */
+ memset(&opts, 0, sizeof(opts));
+ opts.offset = off;
+ opts.length = g_boot_search_stride * 2;
+ ret = nand_erase_opts(mtd, &opts);
+ if (ret) {
+ printf("%s: erase failed (ret = %d)\n", __func__, ret);
+ return CMD_RET_FAILURE;
+ }
/* fill fcb */
fcb = kzalloc(sizeof(*fcb), GFP_KERNEL);
if (!fcb) {
- debug("failed to allocate fcb\n");
+ printf("failed to allocate fcb\n");
ret = -ENOMEM;
return CMD_RET_FAILURE;
}
- fill_fcb(fcb, mtd, fw1_off / mtd->writesize,
- fw2_off / mtd->writesize, fw_len / mtd->writesize);
+ fill_fcb(fcb, &cfg);
+
+ /* write fcb */
+ ret = write_fcb(&cfg, fcb);
/* fill dbbt */
dbbt_page = kzalloc(mtd->writesize, GFP_KERNEL);
if (!dbbt_page) {
- debug("failed to allocate dbbt_page\n");
+ printf("failed to allocate dbbt_page\n");
ret = -ENOMEM;
goto fcb_err;
}
dbbt_data_page = kzalloc(mtd->writesize, GFP_KERNEL);
if (!dbbt_data_page) {
- debug("failed to allocate dbbt_data_page\n");
+ printf("failed to allocate dbbt_data_page\n");
ret = -ENOMEM;
goto dbbt_page_err;
}
dbbt = dbbt_page;
dbbt->checksum = 0;
- dbbt->fingerprint = DBBT_FINGERPRINT2;
+ dbbt->fingerprint = DBBT_FINGERPRINT;
dbbt->version = DBBT_VERSION_1;
- ret = dbbt_fill_data(mtd, dbbt_data_page, 0);
+ ret = fill_dbbt_data(mtd, dbbt_data_page, CONV_TO_BLOCKS(maxsize));
if (ret < 0)
goto dbbt_data_page_err;
else if (ret > 0)
dbbt->dbbtpages = 1;
- /* write fcb and dbbt to nand */
- ret = write_fcb_dbbt(mtd, fcb, dbbt, dbbt_data_page, 0);
+ /* write dbbt */
+ ret = write_dbbt(&cfg, dbbt, dbbt_data_page);
+
dbbt_data_page_err:
kfree(dbbt_data_page);
dbbt_page_err:
@@ -519,31 +1159,292 @@ fcb_err:
return CMD_RET_SUCCESS;
}
-static int do_nandbcb_update(int argc, char * const argv[])
+/* dump data which is read from NAND chip */
+void dump_structure(struct boot_config *boot_cfg, struct fcb_block *fcb,
+ struct dbbt_block *dbbt, void *dbbt_data_page)
+{
+ int i;
+ struct mtd_info *mtd = boot_cfg->mtd;
+
+ #define P1(x) printf(" %s = 0x%08x\n", #x, fcb->x)
+ printf("FCB\n");
+ P1(checksum);
+ P1(fingerprint);
+ P1(version);
+ #undef P1
+ #define P1(x) printf(" %s = %d\n", #x, fcb->x)
+ P1(datasetup);
+ P1(datahold);
+ P1(addr_setup);
+ P1(dsample_time);
+ P1(pagesize);
+ P1(oob_pagesize);
+ P1(sectors);
+ P1(nr_nand);
+ P1(nr_die);
+ P1(celltype);
+ P1(ecc_type);
+ P1(ecc_nr);
+ P1(ecc_size);
+ P1(ecc_level);
+ P1(meta_size);
+ P1(nr_blocks);
+ P1(ecc_type_sdk);
+ P1(ecc_nr_sdk);
+ P1(ecc_size_sdk);
+ P1(ecc_level_sdk);
+ P1(nr_blocks_sdk);
+ P1(meta_size_sdk);
+ P1(erase_th);
+ P1(bootpatch);
+ P1(patch_size);
+ P1(fw1_start);
+ P1(fw2_start);
+ P1(fw1_pages);
+ P1(fw2_pages);
+ P1(dbbt_start);
+ P1(bb_byte);
+ P1(bb_start_bit);
+ P1(phy_offset);
+ P1(bchtype);
+ P1(readlatency);
+ P1(predelay);
+ P1(cedelay);
+ P1(postdelay);
+ P1(cmdaddpause);
+ P1(datapause);
+ P1(tmspeed);
+ P1(busytimeout);
+ P1(disbbm);
+ P1(spare_offset);
+#if !defined(CONFIG_MX6) || defined(CONFIG_MX6SX) || \
+ defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL)
+ P1(onfi_sync_enable);
+ P1(onfi_sync_speed);
+ P1(onfi_sync_nand_data);
+ P1(disbbm_search);
+ P1(disbbm_search_limit);
+ P1(read_retry_enable);
+#endif
+ #undef P1
+ #define P1(x) printf(" %s = 0x%08x\n", #x, dbbt->x)
+ printf("DBBT :\n");
+ P1(checksum);
+ P1(fingerprint);
+ P1(version);
+ #undef P1
+ #define P1(x) printf(" %s = %d\n", #x, dbbt->x)
+ P1(dbbtpages);
+ #undef P1
+
+ for (i = 0; i < dbbt->dbbtpages; ++i)
+ printf("%d ", *((u32 *)(dbbt_data_page + i)));
+
+ if (!(plat_config.misc_flags & FIRMWARE_EXTRA_ONE)) {
+ printf("Firmware: image #0 @ 0x%x size 0x%x\n",
+ fcb->fw1_start, fcb->fw1_pages * mtd->writesize);
+ printf("Firmware: image #1 @ 0x%x size 0x%x\n",
+ fcb->fw2_start, fcb->fw2_pages * mtd->writesize);
+ } else {
+ printf("Firmware: image #0 @ 0x%x size 0x%x\n",
+ fcb->fw1_start, fcb->fw1_pages * mtd->writesize);
+ printf("Firmware: image #1 @ 0x%x size 0x%x\n",
+ fcb->fw2_start, fcb->fw2_pages * mtd->writesize);
+ /* TODO: Add extra image information */
+ }
+}
+
+static bool check_fingerprint(void *data, int fingerprint)
+{
+ int off = 4;
+
+ return (*(int *)(data + off) == fingerprint);
+}
+
+static int fuse_to_search_count(u32 bank, u32 word, u32 mask, u32 off)
+{
+ int err;
+ u32 val;
+ int ret;
+
+ /* by default, the boot search count from fuse should be 2 */
+ err = fuse_read(bank, word, &val);
+ if (err)
+ return 2;
+
+ val = (val & mask) >> off;
+
+ switch (val) {
+ case 0:
+ ret = 2;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ ret = 1 << val;
+ break;
+ default:
+ ret = 2;
+ }
+
+ return ret;
+}
+
+static int nandbcb_dump(struct boot_config *boot_cfg)
+{
+ int i;
+ loff_t off;
+ struct mtd_info *mtd = boot_cfg->mtd;
+ struct fcb_block fcb, fcb_copy;
+ struct dbbt_block dbbt, dbbt_copy;
+ void *dbbt_data_page, *dbbt_data_page_copy;
+ bool fcb_not_found, dbbt_not_found;
+ int ret = 0;
+
+ dbbt_data_page = kzalloc(mtd->writesize, GFP_KERNEL);
+ if (!dbbt_data_page) {
+ printf("failed to allocate dbbt_data_page\n");
+ ret = -ENOMEM;
+ return ret;
+ }
+
+ dbbt_data_page_copy = kzalloc(mtd->writesize, GFP_KERNEL);
+ if (!dbbt_data_page_copy) {
+ printf("failed to allocate dbbt_data_page\n");
+ ret = -ENOMEM;
+ goto dbbt_page_err;
+ }
+
+ /* read fcb */
+ fcb_not_found = 1;
+ off = 0;
+ for (i = 0; i < g_boot_search_count; ++i) {
+ if (fcb_not_found) {
+ ret = read_fcb(boot_cfg, &fcb, off);
+
+ if (ret < 0)
+ goto dbbt_page_copy_err;
+ else if (ret == 1)
+ continue;
+ else if (ret == 0)
+ if (check_fingerprint(&fcb, FCB_FINGERPRINT))
+ fcb_not_found = 0;
+ } else {
+ ret = read_fcb(boot_cfg, &fcb_copy, off);
+
+ if (ret < 0)
+ goto dbbt_page_copy_err;
+ if (memcmp(&fcb, &fcb_copy,
+ sizeof(struct fcb_block))) {
+ printf("FCB copies are not identical\n");
+ ret = -EINVAL;
+ goto dbbt_page_copy_err;
+ }
+ }
+
+ /* next read location */
+ off += g_boot_search_stride;
+ }
+
+ /* read dbbt*/
+ dbbt_not_found = 1;
+ off = boot_cfg->search_area_size_in_bytes;
+ for (i = 0; i < g_boot_search_count; ++i) {
+ if (dbbt_not_found) {
+ ret = read_dbbt(boot_cfg, &dbbt, dbbt_data_page, off);
+
+ if (ret < 0)
+ goto dbbt_page_copy_err;
+ else if (ret == 1)
+ continue;
+ else if (ret == 0)
+ if (check_fingerprint(&dbbt, DBBT_FINGERPRINT))
+ dbbt_not_found = 0;
+ } else {
+ ret = read_dbbt(boot_cfg, &dbbt_copy,
+ dbbt_data_page_copy, off);
+
+ if (ret < 0)
+ goto dbbt_page_copy_err;
+ if (memcmp(&dbbt, &dbbt_copy,
+ sizeof(struct dbbt_block))) {
+ printf("DBBT copies are not identical\n");
+ ret = -EINVAL;
+ goto dbbt_page_copy_err;
+ }
+ if (dbbt.dbbtpages > 0 &&
+ memcmp(dbbt_data_page, dbbt_data_page_copy,
+ mtd->writesize)) {
+ printf("DBBT data copies are not identical\n");
+ ret = -EINVAL;
+ goto dbbt_page_copy_err;
+ }
+ }
+
+ /* next read location */
+ off += g_boot_search_stride;
+ }
+
+ dump_structure(boot_cfg, &fcb, &dbbt, dbbt_data_page);
+
+dbbt_page_copy_err:
+ kfree(dbbt_data_page_copy);
+dbbt_page_err:
+ kfree(dbbt_data_page);
+
+ return ret;
+}
+
+static int do_nandbcb_dump(int argc, char * const argv[])
+{
+ struct boot_config cfg;
+ int ret;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ memset(&cfg, 0, sizeof(struct boot_config));
+ if (nandbcb_get_info(argc, argv, &cfg))
+ return CMD_RET_FAILURE;
+
+ if (nandbcb_get_size(argc, argv, 1, &cfg))
+ return CMD_RET_FAILURE;
+
+ if (nandbcb_set_boot_config(argc, argv, &cfg))
+ return CMD_RET_FAILURE;
+
+ ret = nandbcb_dump(&cfg);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static int do_nandbcb_init(int argc, char * const argv[])
{
- struct mtd_info *mtd;
- loff_t addr, offset, size, maxsize;
- char *endp;
u_char *buf;
- int dev;
+ size_t size;
+ loff_t addr;
+ char *endp;
int ret;
+ struct boot_config cfg;
if (argc != 4)
return CMD_RET_USAGE;
- dev = nand_curr_device;
- if (dev < 0) {
- printf("failed to get nand_curr_device, run nand device\n");
+ memset(&cfg, 0, sizeof(struct boot_config));
+ if (nandbcb_get_info(argc, argv, &cfg))
return CMD_RET_FAILURE;
- }
- addr = simple_strtoul(argv[1], &endp, 16);
- if (*argv[1] == 0 || *endp != 0)
+ if (nandbcb_get_size(argc, argv, 2, &cfg))
return CMD_RET_FAILURE;
+ size = cfg.boot_stream1_size;
- mtd = get_nand_dev_by_index(dev);
- if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &offset, &size,
- &maxsize, MTD_DEV_TYPE_NAND, mtd->size))
+ if (nandbcb_set_boot_config(argc, argv, &cfg))
+ return CMD_RET_FAILURE;
+
+ addr = simple_strtoul(argv[1], &endp, 16);
+ if (*argv[1] == 0 || *endp != 0)
return CMD_RET_FAILURE;
buf = map_physmem(addr, size, MAP_WRBACK);
@@ -552,7 +1453,7 @@ static int do_nandbcb_update(int argc, char * const argv[])
return CMD_RET_FAILURE;
}
- ret = nandbcb_update(mtd, offset, size, maxsize, buf);
+ ret = nandbcb_init(&cfg, buf);
return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
}
@@ -563,15 +1464,51 @@ static int do_nandbcb(cmd_tbl_t *cmdtp, int flag, int argc,
const char *cmd;
int ret = 0;
- if (argc < 5)
+ if (argc < 3)
goto usage;
+ /* check the platform config first */
+ if (is_mx6sx()) {
+ plat_config = imx6sx_plat_config;
+ } else if (is_mx7()) {
+ plat_config = imx7d_plat_config;
+ } else if (is_mx6ul() || is_mx6ull()) {
+ plat_config = imx6ul_plat_config;
+ } else if (is_mx6() && !is_mx6sx() && !is_mx6ul() && !is_mx6ull()) {
+ plat_config = imx6qdl_plat_config;
+ } else if (is_imx8mq()) {
+ plat_config = imx8mq_plat_config;
+ } else if (is_imx8mm()) {
+ plat_config = imx8mm_plat_config;
+ } else if (is_imx8mn()) {
+ plat_config = imx8mn_plat_config;
+ } else if (is_imx8qm() || is_imx8qxp()) {
+ plat_config = imx8q_plat_config;
+ } else {
+ printf("ERROR: Unknown platform\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (plat_config.misc_flags & BT_SEARCH_CNT_FROM_FUSE) {
+ if (is_imx8qxp()) {
+ g_boot_search_count = fuse_to_search_count(0, 720,
+ 0xc0, 6);
+ printf("search count set to %d from fuse\n",
+ g_boot_search_count);
+ }
+ }
+
cmd = argv[1];
--argc;
++argv;
- if (strcmp(cmd, "update") == 0) {
- ret = do_nandbcb_update(argc, argv);
+ if (strcmp(cmd, "init") == 0) {
+ ret = do_nandbcb_init(argc, argv);
+ goto done;
+ }
+
+ if (strcmp(cmd, "dump") == 0) {
+ ret = do_nandbcb_dump(argc, argv);
goto done;
}
@@ -589,17 +1526,19 @@ usage:
#ifdef CONFIG_SYS_LONGHELP
static char nandbcb_help_text[] =
- "update addr off|partition len - update 'len' bytes starting at\n"
+ "init addr off|partition len - update 'len' bytes starting at\n"
" 'off|part' to memory address 'addr', skipping bad blocks\n"
- "bcbonly fw-size fw1-off [fw2-off] - write only BCB (FCB and DBBT)\n"
- " where `fw-size` is fw sizes in bytes, `fw1-off`\n"
+ "nandbcb bcbonly off|partition fw1-off fw1-size [fw2-off fw2-size]\n"
+ " - write BCB only (FCB and DBBT)\n"
+ " where `fwx-size` is fw sizes in bytes, `fw1-off`\n"
" and `fw2-off` - firmware offsets\n"
" FIY, BCB isn't erased automatically, so mtd erase should\n"
" be called in advance before writing new BCB:\n"
- " > mtd erase mx7-bcb";
+ " > mtd erase mx7-bcb\n"
+ "nandbcb dump off|partition - dump/verify boot structures\n";
#endif
-U_BOOT_CMD(nandbcb, 5, 1, do_nandbcb,
- "i.MX6/i.MX7 NAND Boot Control Blocks write",
+U_BOOT_CMD(nandbcb, 7, 1, do_nandbcb,
+ "i.MX NAND Boot Control Blocks write",
nandbcb_help_text
);
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index e83f6934cd..515c1fea40 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -168,7 +168,7 @@ int print_cpuinfo(void)
cpurev = get_cpu_rev();
-#if defined(CONFIG_IMX_THERMAL)
+#if defined(CONFIG_IMX_THERMAL) || defined(CONFIG_IMX_TMU)
struct udevice *thermal_dev;
int cpu_tmp, minc, maxc, ret;
@@ -191,7 +191,7 @@ int print_cpuinfo(void)
mxc_get_clock(MXC_ARM_CLK) / 1000000);
#endif
-#if defined(CONFIG_IMX_THERMAL)
+#if defined(CONFIG_IMX_THERMAL) || defined(CONFIG_IMX_TMU)
puts("CPU: ");
switch (get_cpu_temp_grade(&minc, &maxc)) {
case TEMP_AUTOMOTIVE:
diff --git a/arch/arm/mach-imx/imx8/Kconfig b/arch/arm/mach-imx/imx8/Kconfig
index 1f8add015f..9d1f73dfc7 100644
--- a/arch/arm/mach-imx/imx8/Kconfig
+++ b/arch/arm/mach-imx/imx8/Kconfig
@@ -18,11 +18,13 @@ config MU_BASE_SPL
config IMX8QM
select IMX8
select SUPPORT_SPL
+ select SPL_RECOVER_DATA_SECTION
bool
config IMX8QXP
select IMX8
select SUPPORT_SPL
+ select SPL_RECOVER_DATA_SECTION
bool
config SYS_SOC
@@ -41,6 +43,14 @@ config IMX_CONTAINER_CFG
This is to specific the cfg file for generating container
image which will be loaded by SPL.
+config BOOTAUX_RESERVED_MEM_BASE
+ hex "i.MX auxiliary core dram memory base"
+ default 0
+
+config BOOTAUX_RESERVED_MEM_SIZE
+ hex "i.MX auxiliary core dram memory size"
+ default 0
+
choice
prompt "i.MX8 board select"
optional
diff --git a/arch/arm/mach-imx/imx8/cpu.c b/arch/arm/mach-imx/imx8/cpu.c
index 2110380957..6d7b17b464 100644
--- a/arch/arm/mach-imx/imx8/cpu.c
+++ b/arch/arm/mach-imx/imx8/cpu.c
@@ -13,13 +13,16 @@
#include <dm/lists.h>
#include <dm/uclass.h>
#include <errno.h>
+#include <spl.h>
#include <thermal.h>
#include <asm/arch/sci/sci.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch-imx/cpu.h>
#include <asm/armv8/cpu.h>
#include <asm/armv8/mmu.h>
+#include <asm/setup.h>
#include <asm/mach-imx/boot_mode.h>
+#include <spl.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -38,6 +41,10 @@ struct pass_over_info_t *get_pass_over_info(void)
int arch_cpu_init(void)
{
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_RECOVER_DATA_SECTION)
+ spl_save_restore_data();
+#endif
+
#ifdef CONFIG_SPL_BUILD
struct pass_over_info_t *pass_over;
@@ -162,6 +169,37 @@ enum boot_device get_boot_device(void)
return boot_dev;
}
+#ifdef CONFIG_SERIAL_TAG
+#define FUSE_UNIQUE_ID_WORD0 16
+#define FUSE_UNIQUE_ID_WORD1 17
+void get_board_serial(struct tag_serialnr *serialnr)
+{
+ sc_err_t err;
+ u32 val1 = 0, val2 = 0;
+ u32 word1, word2;
+
+ if (!serialnr)
+ return;
+
+ word1 = FUSE_UNIQUE_ID_WORD0;
+ word2 = FUSE_UNIQUE_ID_WORD1;
+
+ err = sc_misc_otp_fuse_read(-1, word1, &val1);
+ if (err != SC_ERR_NONE) {
+ printf("%s fuse %d read error: %d\n", __func__, word1, err);
+ return;
+ }
+
+ err = sc_misc_otp_fuse_read(-1, word2, &val2);
+ if (err != SC_ERR_NONE) {
+ printf("%s fuse %d read error: %d\n", __func__, word2, err);
+ return;
+ }
+ serialnr->low = val1;
+ serialnr->high = val2;
+}
+#endif /*CONFIG_SERIAL_TAG*/
+
#ifdef CONFIG_ENV_IS_IN_MMC
__weak int board_mmc_get_env_dev(int devno)
{
@@ -223,7 +261,7 @@ static int get_owned_memreg(sc_rm_mr_t mr, sc_faddr_t *addr_start,
phys_size_t get_effective_memsize(void)
{
sc_rm_mr_t mr;
- sc_faddr_t start, end, end1;
+ sc_faddr_t start, end, end1, start_aligned;
int err;
end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE;
@@ -231,9 +269,9 @@ phys_size_t get_effective_memsize(void)
for (mr = 0; mr < 64; mr++) {
err = get_owned_memreg(mr, &start, &end);
if (!err) {
- start = roundup(start, MEMSTART_ALIGNMENT);
+ start_aligned = roundup(start, MEMSTART_ALIGNMENT);
/* Too small memory region, not use it */
- if (start > end)
+ if (start_aligned > end)
continue;
/* Find the memory region runs the U-Boot */
@@ -537,3 +575,43 @@ u32 get_cpu_rev(void)
return (id << 12) | rev;
}
+void board_boot_order(u32 *spl_boot_list)
+{
+ spl_boot_list[0] = spl_boot_device();
+
+ if (spl_boot_list[0] == BOOT_DEVICE_SPI) {
+ /* Check whether we own the flexspi0, if not, use NOR boot */
+ if (!sc_rm_is_resource_owned(-1, SC_R_FSPI_0))
+ spl_boot_list[0] = BOOT_DEVICE_NOR;
+ }
+}
+
+bool m4_parts_booted(void)
+{
+ sc_rm_pt_t m4_parts[2];
+ int err;
+
+ err = sc_rm_get_resource_owner(-1, SC_R_M4_0_PID0, &m4_parts[0]);
+ if (err) {
+ printf("%s get resource [%d] owner error: %d\n", __func__,
+ SC_R_M4_0_PID0, err);
+ return false;
+ }
+
+ if (sc_pm_is_partition_started(-1, m4_parts[0]))
+ return true;
+
+ if (is_imx8qm()) {
+ err = sc_rm_get_resource_owner(-1, SC_R_M4_1_PID0, &m4_parts[1]);
+ if (err) {
+ printf("%s get resource [%d] owner error: %d\n",
+ __func__, SC_R_M4_1_PID0, err);
+ return false;
+ }
+
+ if (sc_pm_is_partition_started(-1, m4_parts[1]))
+ return true;
+ }
+
+ return false;
+}
diff --git a/arch/arm/mach-imx/imx8/fdt.c b/arch/arm/mach-imx/imx8/fdt.c
index 65c8ac1a7e..9a6822a929 100644
--- a/arch/arm/mach-imx/imx8/fdt.c
+++ b/arch/arm/mach-imx/imx8/fdt.c
@@ -8,6 +8,7 @@
#include <asm/arch/sys_proto.h>
#include <dm/ofnode.h>
#include <fdt_support.h>
+#include <linux/libfdt.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -105,13 +106,13 @@ static int config_smmu_resource_sid(int rsrc, int sid)
{
int err;
- if (!check_owned_resource(rsrc)) {
- printf("%s rsrc[%d] not owned\n", __func__, rsrc);
- return -1;
- }
err = sc_rm_set_master_sid(-1, rsrc, sid);
debug("set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err);
if (err != SC_ERR_NONE) {
+ if (!check_owned_resource(rsrc)) {
+ printf("%s rsrc[%d] not owned\n", __func__, rsrc);
+ return -1;
+ }
pr_err("fail set_master_sid rsrc=%d sid=0x%x err=%d\n", rsrc, sid, err);
return -EINVAL;
}
@@ -279,6 +280,15 @@ static int ft_add_optee_node(void *fdt, bd_t *bd)
int ft_system_setup(void *blob, bd_t *bd)
{
int ret;
+ int off;
+
+ if (CONFIG_BOOTAUX_RESERVED_MEM_BASE) {
+ off = fdt_add_mem_rsv(blob, CONFIG_BOOTAUX_RESERVED_MEM_BASE,
+ CONFIG_BOOTAUX_RESERVED_MEM_SIZE);
+ if (off < 0)
+ printf("Failed to reserve memory for bootaux: %s\n",
+ fdt_strerror(off));
+ }
update_fdt_with_owned_resources(blob);
diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig
index 895f903780..7771fc88af 100644
--- a/arch/arm/mach-imx/imx8m/Kconfig
+++ b/arch/arm/mach-imx/imx8m/Kconfig
@@ -55,12 +55,23 @@ config TARGET_IMX8MP_EVK
select SUPPORT_SPL
select IMX8M_LPDDR4
+config TARGET_PICO_IMX8MQ
+ bool "Support Technexion Pico iMX8MQ"
+ select IMX8MQ
+ select IMX8M_LPDDR4
+
config TARGET_VERDIN_IMX8MM
bool "Support Toradex Verdin iMX8M Mini module"
select IMX8MM
select SUPPORT_SPL
select IMX8M_LPDDR4
+config TARGET_IMX8MM_BEACON
+ bool "imx8mm Beacon Embedded devkit"
+ select IMX8MM
+ select SUPPORT_SPL
+ select IMX8M_LPDDR4
+
endchoice
source "board/freescale/imx8mq_evk/Kconfig"
@@ -68,6 +79,8 @@ source "board/freescale/imx8mm_evk/Kconfig"
source "board/freescale/imx8mn_evk/Kconfig"
source "board/freescale/imx8mp_evk/Kconfig"
source "board/google/imx8mq_phanbell/Kconfig"
+source "board/technexion/pico-imx8mq/Kconfig"
source "board/toradex/verdin-imx8mm/Kconfig"
+source "board/beacon/imx8mm/Kconfig"
endif
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c
index 89229da3b6..347fd6d0ad 100644
--- a/arch/arm/mach-imx/imx8m/soc.c
+++ b/arch/arm/mach-imx/imx8m/soc.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright 2017 NXP
+ * Copyright 2017-2019 NXP
*
* Peng Fan <peng.fan@nxp.com>
*/
@@ -448,3 +448,76 @@ int arch_misc_init(void)
return 0;
}
#endif
+
+void imx_tmu_arch_init(void *reg_base)
+{
+ if (is_imx8mm() || is_imx8mn()) {
+ /* Load TCALIV and TASR from fuses */
+ struct ocotp_regs *ocotp =
+ (struct ocotp_regs *)OCOTP_BASE_ADDR;
+ struct fuse_bank *bank = &ocotp->bank[3];
+ struct fuse_bank3_regs *fuse =
+ (struct fuse_bank3_regs *)bank->fuse_regs;
+
+ u32 tca_rt, tca_hr, tca_en;
+ u32 buf_vref, buf_slope;
+
+ tca_rt = fuse->ana0 & 0xFF;
+ tca_hr = (fuse->ana0 & 0xFF00) >> 8;
+ tca_en = (fuse->ana0 & 0x2000000) >> 25;
+
+ buf_vref = (fuse->ana0 & 0x1F00000) >> 20;
+ buf_slope = (fuse->ana0 & 0xF0000) >> 16;
+
+ writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
+ writel((tca_en << 31) | (tca_hr << 16) | tca_rt,
+ (ulong)reg_base + 0x30);
+ }
+#ifdef CONFIG_IMX8MP
+ /* Load TCALIV0/1/m40 and TRIM from fuses */
+ struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
+ struct fuse_bank *bank = &ocotp->bank[38];
+ struct fuse_bank38_regs *fuse =
+ (struct fuse_bank38_regs *)bank->fuse_regs;
+ struct fuse_bank *bank2 = &ocotp->bank[39];
+ struct fuse_bank39_regs *fuse2 =
+ (struct fuse_bank39_regs *)bank2->fuse_regs;
+ u32 buf_vref, buf_slope, bjt_cur, vlsb, bgr;
+ u32 reg;
+ u32 tca40[2], tca25[2], tca105[2];
+
+ /* For blank sample */
+ if (!fuse->ana_trim2 && !fuse->ana_trim3 &&
+ !fuse->ana_trim4 && !fuse2->ana_trim5) {
+ /* Use a default 25C binary codes */
+ tca25[0] = 1596;
+ tca25[1] = 1596;
+ writel(tca25[0], (ulong)reg_base + 0x30);
+ writel(tca25[1], (ulong)reg_base + 0x34);
+ return;
+ }
+
+ buf_vref = (fuse->ana_trim2 & 0xc0) >> 6;
+ buf_slope = (fuse->ana_trim2 & 0xF00) >> 8;
+ bjt_cur = (fuse->ana_trim2 & 0xF000) >> 12;
+ bgr = (fuse->ana_trim2 & 0xF0000) >> 16;
+ vlsb = (fuse->ana_trim2 & 0xF00000) >> 20;
+ writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
+
+ reg = (bgr << 28) | (bjt_cur << 20) | (vlsb << 12) | (1 << 7);
+ writel(reg, (ulong)reg_base + 0x3c);
+
+ tca40[0] = (fuse->ana_trim3 & 0xFFF0000) >> 16;
+ tca25[0] = (fuse->ana_trim3 & 0xF0000000) >> 28;
+ tca25[0] |= ((fuse->ana_trim4 & 0xFF) << 4);
+ tca105[0] = (fuse->ana_trim4 & 0xFFF00) >> 8;
+ tca40[1] = (fuse->ana_trim4 & 0xFFF00000) >> 20;
+ tca25[1] = fuse2->ana_trim5 & 0xFFF;
+ tca105[1] = (fuse2->ana_trim5 & 0xFFF000) >> 12;
+
+ /* use 25c for 1p calibration */
+ writel(tca25[0] | (tca105[0] << 16), (ulong)reg_base + 0x30);
+ writel(tca25[1] | (tca105[1] << 16), (ulong)reg_base + 0x34);
+ writel(tca40[0] | (tca40[1] << 16), (ulong)reg_base + 0x38);
+#endif
+}
diff --git a/arch/arm/mach-imx/mx6/Makefile b/arch/arm/mach-imx/mx6/Makefile
index 81e2913d14..7ea8f91e4f 100644
--- a/arch/arm/mach-imx/mx6/Makefile
+++ b/arch/arm/mach-imx/mx6/Makefile
@@ -6,6 +6,7 @@
# (C) Copyright 2011 Freescale Semiconductor, Inc.
obj-y := soc.o clock.o
+obj-$(CONFIG_IMX_MODULE_FUSE) += module_fuse.o
obj-$(CONFIG_SPL_BUILD) += ddr.o
obj-$(CONFIG_MP) += mp.o
obj-$(CONFIG_MX6UL_LITESOM) += litesom.o
diff --git a/arch/arm/mach-imx/mx6/module_fuse.c b/arch/arm/mach-imx/mx6/module_fuse.c
new file mode 100644
index 0000000000..3e94416065
--- /dev/null
+++ b/arch/arm/mach-imx/mx6/module_fuse.c
@@ -0,0 +1,322 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <fdt_support.h>
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/mach-imx/module_fuse.h>
+#include <linux/errno.h>
+
+static struct fuse_entry_desc mx6_fuse_descs[] = {
+#if defined(CONFIG_MX6ULL)
+ {MODULE_TSC, "/soc/aips-bus@2000000/tsc@2040000", 0x430, 22},
+ {MODULE_ADC2, "/soc/aips-bus@2100000/adc@219c000", 0x430, 23},
+ {MODULE_EPDC, "/soc/aips-bus@2200000/epdc@228c000", 0x430, 24},
+ {MODULE_ESAI, "/soc/aips-bus@2000000/spba-bus@2000000/esai@2024000", 0x430, 25},
+ {MODULE_FLEXCAN1, "/soc/aips-bus@2000000/can@2090000", 0x430, 26},
+ {MODULE_FLEXCAN2, "/soc/aips-bus@2000000/can@2094000", 0x430, 27},
+ {MODULE_SPDIF, "/soc/aips-bus@2000000/spba-bus@2000000/spdif@2004000", 0x440, 2},
+ {MODULE_EIM, "/soc/aips-bus@2100000/weim@21b8000", 0x440, 3},
+ {MODULE_SD1, "/soc/aips-bus@2100000/usdhc@2190000", 0x440, 4},
+ {MODULE_SD2, "/soc/aips-bus@2100000/usdhc@2194000", 0x440, 5},
+ {MODULE_QSPI1, "/soc/aips-bus@2100000/qspi@21e0000", 0x440, 6},
+ {MODULE_GPMI, "/soc/gpmi-nand@1806000", 0x440, 7},
+ {MODULE_APBHDMA, "/soc/dma-apbh@1804000", 0x440, 7},
+ {MODULE_LCDIF, "/soc/aips-bus@2100000/lcdif@21c8000", 0x440, 8},
+ {MODULE_PXP, "/soc/aips-bus@2100000/pxp@21cc000", 0x440, 9},
+ {MODULE_CSI, "/soc/aips-bus@2100000/csi@21c4000", 0x440, 10},
+ {MODULE_ADC1, "/soc/aips-bus@2100000/adc@2198000", 0x440, 11},
+ {MODULE_ENET1, "/soc/aips-bus@2100000/ethernet@2188000", 0x440, 12},
+ {MODULE_ENET2, "/soc/aips-bus@2000000/ethernet@20b4000", 0x440, 13},
+ {MODULE_DCP, "/soc/aips-bus@2200000/dcp@2280000", 0x440, 14},
+ {MODULE_USB_OTG2, "/soc/aips-bus@2100000/usb@2184200", 0x440, 15},
+ {MODULE_SAI2, "/soc/aips-bus@2000000/spba-bus@2000000/sai@202c000", 0x440, 24},
+ {MODULE_SAI3, "/soc/aips-bus@2000000/spba-bus@2000000/sai@2030000", 0x440, 24},
+ {MODULE_DCP_CRYPTO, "/soc/aips-bus@2200000/dcp@2280000", 0x440, 25},
+ {MODULE_UART5, "/soc/aips-bus@2100000/serial@21f4000", 0x440, 26},
+ {MODULE_UART6, "/soc/aips-bus@2100000/serial@21fc000", 0x440, 26},
+ {MODULE_UART7, "/soc/aips-bus@2000000/spba-bus@2000000/serial@2018000", 0x440, 26},
+ {MODULE_UART8, "/soc/aips-bus@2200000/serial@2288000", 0x440, 26},
+ {MODULE_PWM5, "/soc/aips-bus@2000000/pwm@20f0000", 0x440, 27},
+ {MODULE_PWM6, "/soc/aips-bus@2000000/pwm@20f4000", 0x440, 27},
+ {MODULE_PWM7, "/soc/aips-bus@2000000/pwm@20f8000", 0x440, 27},
+ {MODULE_PWM8, "/soc/aips-bus@2000000/pwm@20fc000", 0x440, 27},
+ {MODULE_ECSPI3, "/soc/aips-bus@2000000/spba-bus@2000000/ecspi@2010000", 0x440, 28},
+ {MODULE_ECSPI4, "/soc/aips-bus@2000000/spba-bus@2000000/ecspi@2014000", 0x440, 28},
+ {MODULE_I2C3, "/soc/aips-bus@2100000/i2c@21a8000", 0x440, 29},
+ {MODULE_I2C4, "/soc/aips-bus@2100000/i2c@21f8000", 0x440, 29},
+ {MODULE_GPT2, "/soc/aips-bus@2000000/gpt@20e8000", 0x440, 30},
+ {MODULE_EPIT2, "/soc/aips-bus@2000000/epit@20d4000", 0x440, 31},
+ /* Paths for older imx tree: */
+ {MODULE_TSC, "/soc/aips-bus@02000000/tsc@02040000", 0x430, 22},
+ {MODULE_ADC2, "/soc/aips-bus@02100000/adc@0219c000", 0x430, 23},
+ {MODULE_EPDC, "/soc/aips-bus@02200000/epdc@0228c000", 0x430, 24},
+ {MODULE_ESAI, "/soc/aips-bus@02000000/spba-bus@02000000/esai@02024000", 0x430, 25},
+ {MODULE_FLEXCAN1, "/soc/aips-bus@02000000/can@02090000", 0x430, 26},
+ {MODULE_FLEXCAN2, "/soc/aips-bus@02000000/can@02094000", 0x430, 27},
+ {MODULE_SPDIF, "/soc/aips-bus@02000000/spba-bus@02000000/spdif@02004000", 0x440, 2},
+ {MODULE_EIM, "/soc/aips-bus@02100000/weim@021b8000", 0x440, 3},
+ {MODULE_SD1, "/soc/aips-bus@02100000/usdhc@02190000", 0x440, 4},
+ {MODULE_SD2, "/soc/aips-bus@02100000/usdhc@02194000", 0x440, 5},
+ {MODULE_QSPI1, "/soc/aips-bus@02100000/qspi@021e0000", 0x440, 6},
+ {MODULE_GPMI, "/soc/gpmi-nand@01806000", 0x440, 7},
+ {MODULE_APBHDMA, "/soc/dma-apbh@01804000", 0x440, 7},
+ {MODULE_LCDIF, "/soc/aips-bus@02100000/lcdif@021c8000", 0x440, 8},
+ {MODULE_PXP, "/soc/aips-bus@02100000/pxp@021cc000", 0x440, 9},
+ {MODULE_CSI, "/soc/aips-bus@02100000/csi@021c4000", 0x440, 10},
+ {MODULE_ADC1, "/soc/aips-bus@02100000/adc@02198000", 0x440, 11},
+ {MODULE_ENET1, "/soc/aips-bus@02100000/ethernet@02188000", 0x440, 12},
+ {MODULE_ENET2, "/soc/aips-bus@02000000/ethernet@020b4000", 0x440, 13},
+ {MODULE_DCP, "/soc/aips-bus@02200000/dcp@02280000", 0x440, 14},
+ {MODULE_USB_OTG2, "/soc/aips-bus@02100000/usb@02184200", 0x440, 15},
+ {MODULE_SAI2, "/soc/aips-bus@02000000/spba-bus@02000000/sai@0202c000", 0x440, 24},
+ {MODULE_SAI3, "/soc/aips-bus@02000000/spba-bus@02000000/sai@02030000", 0x440, 24},
+ {MODULE_DCP_CRYPTO, "/soc/aips-bus@02200000/dcp@02280000", 0x440, 25},
+ {MODULE_UART5, "/soc/aips-bus@02100000/serial@021f4000", 0x440, 26},
+ {MODULE_UART6, "/soc/aips-bus@02100000/serial@021fc000", 0x440, 26},
+ {MODULE_UART7, "/soc/aips-bus@02000000/spba-bus@02000000/serial@02018000", 0x440, 26},
+ {MODULE_UART8, "/soc/aips-bus@02200000/serial@02288000", 0x440, 26},
+ {MODULE_PWM5, "/soc/aips-bus@02000000/pwm@020f0000", 0x440, 27},
+ {MODULE_PWM6, "/soc/aips-bus@02000000/pwm@020f4000", 0x440, 27},
+ {MODULE_PWM7, "/soc/aips-bus@02000000/pwm@020f8000", 0x440, 27},
+ {MODULE_PWM8, "/soc/aips-bus@02000000/pwm@020fc000", 0x440, 27},
+ {MODULE_ECSPI3, "/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02010000", 0x440, 28},
+ {MODULE_ECSPI4, "/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02014000", 0x440, 28},
+ {MODULE_I2C3, "/soc/aips-bus@02100000/i2c@021a8000", 0x440, 29},
+ {MODULE_I2C4, "/soc/aips-bus@02100000/i2c@021f8000", 0x440, 29},
+ {MODULE_GPT2, "/soc/aips-bus@02000000/gpt@020e8000", 0x440, 30},
+ {MODULE_EPIT2, "/soc/aips-bus@02000000/epit@020d4000", 0x440, 31},
+#elif defined(CONFIG_MX6UL)
+ {MODULE_TSC, "/soc/aips-bus@2000000/tsc@2040000", 0x430, 22},
+ {MODULE_ADC2, "/soc/aips-bus@2100000/adc@219c000", 0x430, 23},
+ {MODULE_SIM1, "/soc/aips-bus@2100000/sim@218c000", 0x430, 24},
+ {MODULE_SIM2, "/soc/aips-bus@2100000/sim@21b4000", 0x430, 25},
+ {MODULE_FLEXCAN1, "/soc/aips-bus@2000000/can@2090000", 0x430, 26},
+ {MODULE_FLEXCAN2, "/soc/aips-bus@2000000/can@2094000", 0x430, 27},
+ {MODULE_SPDIF, "/soc/aips-bus@2000000/spba-bus@2000000/spdif@2004000", 0x440, 2},
+ {MODULE_EIM, "/soc/aips-bus@2100000/weim@21b8000", 0x440, 3},
+ {MODULE_SD1, "/soc/aips-bus@2100000/usdhc@2190000", 0x440, 4},
+ {MODULE_SD2, "/soc/aips-bus@2100000/usdhc@2194000", 0x440, 5},
+ {MODULE_QSPI1, "/soc/aips-bus@2100000/qspi@21e0000", 0x440, 6},
+ {MODULE_GPMI, "/soc/gpmi-nand@1806000", 0x440, 7},
+ {MODULE_APBHDMA, "/soc/dma-apbh@1804000", 0x440, 7},
+ {MODULE_LCDIF, "/soc/aips-bus@2100000/lcdif@21c8000", 0x440, 8},
+ {MODULE_PXP, "/soc/aips-bus@2100000/pxp@21cc000", 0x440, 9},
+ {MODULE_CSI, "/soc/aips-bus@2100000/csi@21c4000", 0x440, 10},
+ {MODULE_ADC1, "/soc/aips-bus@2100000/adc@2198000", 0x440, 11},
+ {MODULE_ENET1, "/soc/aips-bus@2100000/ethernet@2188000", 0x440, 12},
+ {MODULE_ENET2, "/soc/aips-bus@2000000/ethernet@20b4000", 0x440, 13},
+ {MODULE_CAAM, "/soc/aips-bus@2100000/caam@2140000", 0x440, 14},
+ {MODULE_USB_OTG2, "/soc/aips-bus@2100000/usb@2184200", 0x440, 15},
+ {MODULE_SAI2, "/soc/aips-bus@2000000/spba-bus@2000000/sai@202c000", 0x440, 24},
+ {MODULE_SAI3, "/soc/aips-bus@2000000/spba-bus@2000000/sai@2030000", 0x440, 24},
+ {MODULE_BEE, "/soc/aips-bus@2000000/bee@2044000", 0x440, 25},
+ {MODULE_UART5, "/soc/aips-bus@2100000/serial@21f4000", 0x440, 26},
+ {MODULE_UART6, "/soc/aips-bus@2100000/serial@21fc000", 0x440, 26},
+ {MODULE_UART7, "/soc/aips-bus@2000000/spba-bus@2000000/serial@2018000", 0x440, 26},
+ {MODULE_UART8, "/soc/aips-bus@2000000/spba-bus@2000000/serial@2024000", 0x440, 26},
+ {MODULE_PWM5, "/soc/aips-bus@2000000/pwm@20f0000", 0x440, 27},
+ {MODULE_PWM6, "/soc/aips-bus@2000000/pwm@20f4000", 0x440, 27},
+ {MODULE_PWM7, "/soc/aips-bus@2000000/pwm@20f8000", 0x440, 27},
+ {MODULE_PWM8, "/soc/aips-bus@2000000/pwm@20fc000", 0x440, 27},
+ {MODULE_ECSPI3, "/soc/aips-bus@2000000/spba-bus@2000000/ecspi@2010000", 0x440, 28},
+ {MODULE_ECSPI4, "/soc/aips-bus@2000000/spba-bus@2000000/ecspi@2014000", 0x440, 28},
+ {MODULE_I2C3, "/soc/aips-bus@2100000/i2c@21a8000", 0x440, 29},
+ {MODULE_I2C4, "/soc/aips-bus@2100000/i2c@21f8000", 0x440, 29},
+ {MODULE_GPT2, "/soc/aips-bus@2000000/gpt@20e8000", 0x440, 30},
+ {MODULE_EPIT2, "/soc/aips-bus@2000000/epit@20d4000", 0x440, 31},
+ /* Paths for older imx tree: */
+ {MODULE_TSC, "/soc/aips-bus@02000000/tsc@02040000", 0x430, 22},
+ {MODULE_ADC2, "/soc/aips-bus@02100000/adc@0219c000", 0x430, 23},
+ {MODULE_SIM1, "/soc/aips-bus@02100000/sim@0218c000", 0x430, 24},
+ {MODULE_SIM2, "/soc/aips-bus@02100000/sim@021b4000", 0x430, 25},
+ {MODULE_FLEXCAN1, "/soc/aips-bus@02000000/can@02090000", 0x430, 26},
+ {MODULE_FLEXCAN2, "/soc/aips-bus@02000000/can@02094000", 0x430, 27},
+ {MODULE_SPDIF, "/soc/aips-bus@02000000/spba-bus@02000000/spdif@02004000", 0x440, 2},
+ {MODULE_EIM, "/soc/aips-bus@02100000/weim@021b8000", 0x440, 3},
+ {MODULE_SD1, "/soc/aips-bus@02100000/usdhc@02190000", 0x440, 4},
+ {MODULE_SD2, "/soc/aips-bus@02100000/usdhc@02194000", 0x440, 5},
+ {MODULE_QSPI1, "/soc/aips-bus@02100000/qspi@021e0000", 0x440, 6},
+ {MODULE_GPMI, "/soc/gpmi-nand@01806000", 0x440, 7},
+ {MODULE_APBHDMA, "/soc/dma-apbh@01804000", 0x440, 7},
+ {MODULE_LCDIF, "/soc/aips-bus@02100000/lcdif@021c8000", 0x440, 8},
+ {MODULE_PXP, "/soc/aips-bus@02100000/pxp@021cc000", 0x440, 9},
+ {MODULE_CSI, "/soc/aips-bus@02100000/csi@021c4000", 0x440, 10},
+ {MODULE_ADC1, "/soc/aips-bus@02100000/adc@02198000", 0x440, 11},
+ {MODULE_ENET1, "/soc/aips-bus@02100000/ethernet@02188000", 0x440, 12},
+ {MODULE_ENET2, "/soc/aips-bus@02000000/ethernet@020b4000", 0x440, 13},
+ {MODULE_CAAM, "/soc/aips-bus@02100000/caam@2140000", 0x440, 14},
+ {MODULE_USB_OTG2, "/soc/aips-bus@02100000/usb@02184200", 0x440, 15},
+ {MODULE_SAI2, "/soc/aips-bus@02000000/spba-bus@02000000/sai@0202c000", 0x440, 24},
+ {MODULE_SAI3, "/soc/aips-bus@02000000/spba-bus@02000000/sai@02030000", 0x440, 24},
+ {MODULE_BEE, "/soc/aips-bus@02000000/bee@02044000", 0x440, 25},
+ {MODULE_UART5, "/soc/aips-bus@02100000/serial@021f4000", 0x440, 26},
+ {MODULE_UART6, "/soc/aips-bus@02100000/serial@021fc000", 0x440, 26},
+ {MODULE_UART7, "/soc/aips-bus@02000000/spba-bus@02000000/serial@02018000", 0x440, 26},
+ {MODULE_UART8, "/soc/aips-bus@02000000/spba-bus@02000000/serial@02024000", 0x440, 26},
+ {MODULE_PWM5, "/soc/aips-bus@02000000/pwm@020f0000", 0x440, 27},
+ {MODULE_PWM6, "/soc/aips-bus@02000000/pwm@020f4000", 0x440, 27},
+ {MODULE_PWM7, "/soc/aips-bus@02000000/pwm@020f8000", 0x440, 27},
+ {MODULE_PWM8, "/soc/aips-bus@02000000/pwm@020fc000", 0x440, 27},
+ {MODULE_ECSPI3, "/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02010000", 0x440, 28},
+ {MODULE_ECSPI4, "/soc/aips-bus@02000000/spba-bus@02000000/ecspi@02014000", 0x440, 28},
+ {MODULE_I2C3, "/soc/aips-bus@02100000/i2c@021a8000", 0x440, 29},
+ {MODULE_I2C4, "/soc/aips-bus@02100000/i2c@021f8000", 0x440, 29},
+ {MODULE_GPT2, "/soc/aips-bus@02000000/gpt@020e8000", 0x440, 30},
+ {MODULE_EPIT2, "/soc/aips-bus@02000000/epit@020d4000", 0x440, 31},
+#endif
+};
+
+u32 check_module_fused(enum fuse_module_type module)
+{
+ u32 i, reg;
+
+ for (i = 0; i < ARRAY_SIZE(mx6_fuse_descs); i++) {
+ if (mx6_fuse_descs[i].module == module) {
+ reg = readl(OCOTP_BASE_ADDR +
+ mx6_fuse_descs[i].fuse_word_offset);
+ if (reg & BIT(mx6_fuse_descs[i].fuse_bit_offset))
+ return 1; /* disabled */
+ else
+ return 0; /* enabled */
+ }
+ }
+
+ return 0; /* Not has a fuse, always enabled */
+}
+
+#ifdef CONFIG_OF_SYSTEM_SETUP
+int ft_system_setup(void *blob, bd_t *bd)
+{
+ const char *status = "disabled";
+ u32 i, reg;
+ int rc, off;
+
+ for (i = 0; i < ARRAY_SIZE(mx6_fuse_descs); i++) {
+ reg = readl(OCOTP_BASE_ADDR +
+ mx6_fuse_descs[i].fuse_word_offset);
+ if (reg & BIT(mx6_fuse_descs[i].fuse_bit_offset)) {
+ off = fdt_path_offset(blob,
+ mx6_fuse_descs[i].node_path);
+
+ if (off < 0)
+ continue; /* Not found, skip it */
+add_status:
+ rc = fdt_setprop(blob, nodeoff, "status", status,
+ strlen(status) + 1);
+ if (rc) {
+ if (rc == -FDT_ERR_NOSPACE) {
+ rc = fdt_increase_size(blob, 512);
+ if (!rc)
+ goto add_status;
+ }
+ printf("Unable to update property %s:%s, err=%s\n", mx6_fuse_descs[i].node_path, "status", fdt_strerror(rc));
+ } else {
+ printf("Modify %s disabled\n", mx6_fuse_descs[i].node_path);
+ }
+ }
+ }
+
+ return 0;
+}
+#endif
+
+u32 esdhc_fused(ulong base_addr)
+{
+ switch (base_addr) {
+ case USDHC1_BASE_ADDR:
+ return check_module_fused(MODULE_SD1);
+ case USDHC2_BASE_ADDR:
+ return check_module_fused(MODULE_SD2);
+#ifdef USDHC3_BASE_ADDR
+ case USDHC3_BASE_ADDR:
+ return check_module_fused(MODULE_SD3);
+#endif
+#ifdef USDHC4_BASE_ADDR
+ case USDHC4_BASE_ADDR:
+ return check_module_fused(MODULE_SD4);
+#endif
+ default:
+ return 0;
+ }
+}
+
+u32 ecspi_fused(ulong base_addr)
+{
+ switch (base_addr) {
+ case ECSPI1_BASE_ADDR:
+ return check_module_fused(MODULE_ECSPI1);
+ case ECSPI2_BASE_ADDR:
+ return check_module_fused(MODULE_ECSPI2);
+ case ECSPI3_BASE_ADDR:
+ return check_module_fused(MODULE_ECSPI3);
+ case ECSPI4_BASE_ADDR:
+ return check_module_fused(MODULE_ECSPI4);
+#ifdef ECSPI5_BASE_ADDR
+ case ECSPI5_BASE_ADDR:
+ return check_module_fused(MODULE_ECSPI5);
+#endif
+ default:
+ return 0;
+ }
+}
+
+u32 usb_fused(ulong base_addr)
+{
+ int i = (base_addr - USB_BASE_ADDR) / 0x200;
+
+ return check_module_fused(MODULE_USB_OTG1 + i);
+}
+
+u32 qspi_fused(ulong base_addr)
+{
+ switch (base_addr) {
+#ifdef QSPI1_BASE_ADDR
+ case QSPI1_BASE_ADDR:
+ return check_module_fused(MODULE_QSPI1);
+#endif
+
+#ifdef QSPI2_BASE_ADDR
+ case QSPI2_BASE_ADDR:
+ return check_module_fused(MODULE_QSPI2);
+#endif
+ default:
+ return 0;
+ }
+}
+
+u32 i2c_fused(ulong base_addr)
+{
+ switch (base_addr) {
+ case I2C1_BASE_ADDR:
+ return check_module_fused(MODULE_I2C1);
+ case I2C2_BASE_ADDR:
+ return check_module_fused(MODULE_I2C2);
+ case I2C3_BASE_ADDR:
+ return check_module_fused(MODULE_I2C3);
+#ifdef I2C4_BASE_ADDR
+ case I2C4_BASE_ADDR:
+ return check_module_fused(MODULE_I2C4);
+#endif
+ }
+
+ return 0;
+}
+
+u32 enet_fused(ulong base_addr)
+{
+ switch (base_addr) {
+ case ENET_BASE_ADDR:
+ return check_module_fused(MODULE_ENET1);
+#ifdef ENET2_BASE_ADDR
+ case ENET2_BASE_ADDR:
+ return check_module_fused(MODULE_ENET2);
+#endif
+ default:
+ return 0;
+ }
+}
diff --git a/arch/arm/mach-meson/board-gx.c b/arch/arm/mach-meson/board-gx.c
index 3da99017a5..b591c924ea 100644
--- a/arch/arm/mach-meson/board-gx.c
+++ b/arch/arm/mach-meson/board-gx.c
@@ -183,7 +183,8 @@ int board_usb_init(int index, enum usb_init_type init)
/* get the PHYs */
for (i = 0; i < 2; i++) {
- ret = generic_phy_get_by_node(dwc2_node, i, &usb_phys[i]);
+ ret = generic_phy_get_by_index_nodev(dwc2_node, i,
+ &usb_phys[i]);
if (ret && ret != -ENOENT) {
pr_err("Failed to get USB PHY%d for %s\n",
i, ofnode_get_name(dwc2_node));