summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-06-10 09:18:15 -0600
committerTom Rini <[email protected]>2026-06-10 09:18:15 -0600
commit953653936cfc9e12f52df1165080fa6c7cbae1bc (patch)
tree407487ab8999b482dfe367b0561347c0f22f261a
parent45cfba58dba911685700d6574b01f39329dce99c (diff)
parenteab66c3a9085e07b227847b0c442ee8d2efb241d (diff)
Merge tag 'u-boot-marvell-next-20260610' of https://source.denx.de/u-boot/custodians/u-boot-marvell into next
CI: https://source.denx.de/u-boot/custodians/u-boot-marvell/-/pipelines/30414 u-boot-marvell changes 2026-06-10: - arm: kirkwood: Remove unnecessary watchdog GPIO for ZyXEL NSA325 board (Tony) - net: mvpp2: fix NULL pointer dereference in mvpp2_phy_connect (Vincent) - mtd: nand: pxa3xx: Pass valid dev to dev_err() (Chris) - arm: mvebu: db-xc3-24g4xg: Remove marvell, nand-keep-config (Chris) - arm: mvebu: Add Allied Telesis x220 (Chris) - board: Synology: legacy.c: Include asm/io.h (Phil) - board: Synology: common: Fix typo in Makefile (Phil) - serial: serial_octeon_bootcmd.c: use correct Kconfig symbol (Heinrich) - arm: mvebu: Drop unnecessary BOARD_EARLY_INIT_F usage (Tom) - pinctrl: armada-38x: Staticize and constify driver ops (Marek) - arm: mach-mvebu: armada8k: cpuinfo and SAR (Vincent) - board: freebox: add Nodebox 10G board support (Vincent) - board: freebox: nbx10g: add emmcboot for dual-bank eMMC boot (Vincent) - board: freebox: nbx10g: add device serial and MAC address initialization (Vincent) - arm: dts: armada-8040-nbx: add U-Boot dtsi for conditional OP-TEE (Vincent) - timer: orion: Use dev_remap_addr_index() (Peng)
-rw-r--r--arch/arm/dts/Makefile2
-rw-r--r--arch/arm/dts/armada-8040-nbx-u-boot.dtsi15
-rw-r--r--arch/arm/dts/armada-8040-nbx.dts259
-rw-r--r--arch/arm/dts/armada-xp-atl-x220.dts162
-rw-r--r--arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi1
-rw-r--r--arch/arm/mach-mvebu/Kconfig16
-rw-r--r--arch/arm/mach-mvebu/armada8k/Makefile2
-rw-r--r--arch/arm/mach-mvebu/armada8k/cpu.c12
-rw-r--r--arch/arm/mach-mvebu/armada8k/soc_info.c194
-rw-r--r--arch/arm/mach-mvebu/armada8k/soc_info.h14
-rw-r--r--board/Marvell/mvebu_armada-37xx/board.c5
-rw-r--r--board/Synology/common/Makefile2
-rw-r--r--board/Synology/common/legacy.c1
-rw-r--r--board/alliedtelesis/x220/.gitattributes1
-rw-r--r--board/alliedtelesis/x220/.gitignore1
-rw-r--r--board/alliedtelesis/x220/MAINTAINERS8
-rw-r--r--board/alliedtelesis/x220/Makefile14
-rw-r--r--board/alliedtelesis/x220/binary.011
-rw-r--r--board/alliedtelesis/x220/kwbimage.cfg.in12
-rw-r--r--board/alliedtelesis/x220/x220.c67
-rw-r--r--board/freebox/nbx10g/Kconfig94
-rw-r--r--board/freebox/nbx10g/MAINTAINERS6
-rw-r--r--board/freebox/nbx10g/Makefile5
-rw-r--r--board/freebox/nbx10g/board.c53
-rw-r--r--board/freebox/nbx10g/nbx_emmcboot.c357
-rw-r--r--board/freebox/nbx10g/nbx_fbxserial.c286
-rw-r--r--board/freebox/nbx10g/nbx_fbxserial.h156
-rw-r--r--board/freebox/nbx10g/nbx_imagetag.h78
-rw-r--r--board/freebox/nbx10g/nbx_nrboot.h34
-rw-r--r--board/zyxel/nsa325/nsa325.c7
-rw-r--r--configs/eDPU_defconfig1
-rw-r--r--configs/mvebu_db-88f3720_defconfig1
-rw-r--r--configs/mvebu_espressobin-88f3720_defconfig1
-rw-r--r--configs/mvebu_espressobin_ultra-88f3720_defconfig1
-rw-r--r--configs/mvebu_nbx_88f8040_defconfig75
-rw-r--r--configs/uDPU_defconfig1
-rw-r--r--configs/x220_defconfig76
-rw-r--r--doc/board/alliedtelesis/index.rst11
-rw-r--r--doc/board/alliedtelesis/x220.rst39
-rw-r--r--doc/board/index.rst1
-rw-r--r--drivers/mtd/nand/raw/pxa3xx_nand.c11
-rw-r--r--drivers/net/mvpp2.c4
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-38x.c2
-rw-r--r--drivers/serial/Kconfig2
-rw-r--r--drivers/timer/orion-timer.c3
-rw-r--r--include/configs/nbx10g.h29
-rw-r--r--include/configs/x220.h20
47 files changed, 2125 insertions, 28 deletions
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index b75f3ee4386..c647379c5ac 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -137,6 +137,7 @@ dtb-$(CONFIG_ARCH_MVEBU) += \
armada-388-gp.dtb \
armada-388-helios4.dtb \
armada-38x-controlcenterdc.dtb \
+ armada-xp-atl-x220.dtb \
armada-xp-crs305-1g-4s.dtb \
armada-xp-crs305-1g-4s-bit.dtb \
armada-xp-crs326-24g-2s.dtb \
@@ -162,6 +163,7 @@ dtb-$(CONFIG_ARCH_MVEBU) += \
armada-8040-clearfog-gt-8k.dtb \
armada-8040-db.dtb \
armada-8040-mcbin.dtb \
+ armada-8040-nbx.dtb \
armada-8040-puzzle-m801.dtb \
cn9130-db-A.dtb \
cn9130-db-B.dtb \
diff --git a/arch/arm/dts/armada-8040-nbx-u-boot.dtsi b/arch/arm/dts/armada-8040-nbx-u-boot.dtsi
new file mode 100644
index 00000000000..dec473b7156
--- /dev/null
+++ b/arch/arm/dts/armada-8040-nbx-u-boot.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2026 Free Mobile, Vincent Jardin
+ */
+
+#ifdef CONFIG_OPTEE
+/ {
+ firmware {
+ optee {
+ compatible = "linaro,optee-tz";
+ method = "smc";
+ };
+ };
+};
+#endif
diff --git a/arch/arm/dts/armada-8040-nbx.dts b/arch/arm/dts/armada-8040-nbx.dts
new file mode 100644
index 00000000000..b8b7298b4f5
--- /dev/null
+++ b/arch/arm/dts/armada-8040-nbx.dts
@@ -0,0 +1,259 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Device Tree file for NBX board (Freebox Nodebox10G)
+ * Based on Marvell Armada 8040 SoC
+ *
+ * Copyright (C) 2024
+ */
+
+#include "armada-8040.dtsi"
+
+/ {
+ model = "NBX Armada 8040";
+ compatible = "nbx,armada8040", "marvell,armada8040";
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ aliases {
+ i2c0 = &cp0_i2c0;
+ i2c1 = &cp0_i2c1;
+ gpio0 = &ap_gpio0;
+ gpio1 = &cp0_gpio0;
+ gpio2 = &cp0_gpio1;
+ };
+
+ memory@00000000 {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x80000000>; /* 2GB */
+ };
+};
+
+/* AP806 UART - active */
+&uart0 {
+ status = "okay";
+};
+
+/* AP806 pinctrl */
+&ap_pinctl {
+ /*
+ * MPP Bus:
+ * eMMC [0-10]
+ * UART0 [11,19]
+ */
+ /* 0 1 2 3 4 5 6 7 8 9 */
+ pin-func = < 1 1 1 1 1 1 1 1 1 1
+ 1 3 0 0 0 0 0 0 0 3 >;
+};
+
+/* AP806 on-board eMMC */
+&ap_sdhci0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ap_emmc_pins>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+/* CP0 pinctrl */
+&cp0_pinctl {
+ /*
+ * MPP Bus:
+ * [0-31] = 0xff: Keep default CP0_shared_pins
+ * [32,34] GE_MDIO/MDC
+ * [35-36] I2C1
+ * [37-38] I2C0
+ * [57-58] MSS I2C
+ */
+ /* 0 1 2 3 4 5 6 7 8 9 */
+ pin-func = < 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+ 0xff 0xff 7 0 7 2 2 2 2 0
+ 0 0 0 0 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 2 2 0
+ 0 0 0 >;
+
+ cp0_smi_pins: cp0-smi-pins {
+ marvell,pins = <32 34>;
+ marvell,function = <7>;
+ };
+};
+
+/* CP0 I2C0 */
+&cp0_i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_i2c0_pins>;
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+/* CP0 I2C1 */
+&cp0_i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_i2c1_pins>;
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+/* CP0 MSS I2C0 - Management SubSystem I2C (pins 57-58, func 2) */
+&cp0_mss_i2c0 {
+ status = "okay";
+};
+
+/* CP0 MDIO for PHY */
+&cp0_mdio {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_smi_pins>;
+
+ nbx_phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+};
+
+/* CP0 ComPhy - SerDes configuration */
+&cp0_comphy {
+ /*
+ * CP0 Serdes Configuration:
+ * Lane 0-3: Unconnected
+ * Lane 4: SFI (10G Ethernet)
+ * Lane 5: SGMII2 (1G Ethernet)
+ */
+ phy0 {
+ phy-type = <COMPHY_TYPE_UNCONNECTED>;
+ };
+ phy1 {
+ phy-type = <COMPHY_TYPE_UNCONNECTED>;
+ };
+ phy2 {
+ phy-type = <COMPHY_TYPE_UNCONNECTED>;
+ };
+ phy3 {
+ phy-type = <COMPHY_TYPE_UNCONNECTED>;
+ };
+ phy4 {
+ phy-type = <COMPHY_TYPE_SFI0>;
+ phy-speed = <COMPHY_SPEED_10_3125G>;
+ };
+ phy5 {
+ phy-type = <COMPHY_TYPE_SGMII2>;
+ phy-speed = <COMPHY_SPEED_1_25G>;
+ };
+};
+
+/* CP0 Ethernet - only eth2 (MAC3) is active via SGMII */
+&cp0_ethernet {
+ status = "okay";
+};
+
+&cp0_eth2 {
+ status = "okay";
+ phy = <&nbx_phy0>;
+ phy-mode = "sgmii";
+};
+
+/* CP0 UTMI PHY for USB */
+&cp0_utmi {
+ status = "okay";
+};
+
+&cp0_utmi0 {
+ status = "okay";
+};
+
+&cp0_utmi1 {
+ status = "okay";
+};
+
+/* CP0 USB3 Host controllers */
+&cp0_usb3_0 {
+ status = "okay";
+};
+
+&cp0_usb3_1 {
+ status = "okay";
+};
+
+/* CP1 pinctrl */
+&cp1_pinctl {
+ /*
+ * MPP Bus:
+ * [0-26] = Unconfigured
+ * [27-28] GE_MDIO/MDC
+ * [29-30] MSS I2C
+ * [31] = Unconfigured
+ * [32-62] = 0xff: Keep default CP1_shared_pins
+ */
+ /* 0 1 2 3 4 5 6 7 8 9 */
+ pin-func = < 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
+ 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
+ 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x8 0x8 0x8
+ 0x8 0x0 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+ 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
+ 0xff 0xff 0xff>;
+
+ cp1_mss_i2c_pins: cp1-mss-i2c-pins {
+ marvell,pins = <29 30>;
+ marvell,function = <8>;
+ };
+};
+
+/* CP1 MSS I2C0 - Management SubSystem I2C (pins 29-30, func 8) */
+&cp1_mss_i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_mss_i2c_pins>;
+};
+
+/* CP1 ComPhy - SerDes configuration */
+&cp1_comphy {
+ /*
+ * CP1 Serdes Configuration:
+ * Lane 0: PCIe x1
+ * Lane 1: USB3 Host
+ * Lane 2-3: Unconnected
+ * Lane 4: SFI (10G Ethernet)
+ * Lane 5: Unconnected
+ */
+ phy0 {
+ phy-type = <COMPHY_TYPE_PEX0>;
+ };
+ phy1 {
+ phy-type = <COMPHY_TYPE_USB3_HOST0>;
+ };
+ phy2 {
+ phy-type = <COMPHY_TYPE_UNCONNECTED>;
+ };
+ phy3 {
+ phy-type = <COMPHY_TYPE_UNCONNECTED>;
+ };
+ phy4 {
+ phy-type = <COMPHY_TYPE_SFI0>;
+ phy-speed = <COMPHY_SPEED_10_3125G>;
+ };
+ phy5 {
+ phy-type = <COMPHY_TYPE_UNCONNECTED>;
+ };
+};
+
+/* CP1 PCIe x1 on lane 0 */
+&cp1_pcie0 {
+ status = "okay";
+};
+
+/* CP1 USB3 Host on lane 1 */
+&cp1_usb3_0 {
+ status = "okay";
+};
+
+/* CP1 UTMI PHY for USB */
+&cp1_utmi {
+ status = "okay";
+};
+
+&cp1_utmi0 {
+ status = "okay";
+};
diff --git a/arch/arm/dts/armada-xp-atl-x220.dts b/arch/arm/dts/armada-xp-atl-x220.dts
new file mode 100644
index 00000000000..5b3307ed288
--- /dev/null
+++ b/arch/arm/dts/armada-xp-atl-x220.dts
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree file for x220 board
+ *
+ * Copyright (C) 2025 Allied Telesis Labs
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-xp-98dx3236.dtsi"
+#include "mvebu-u-boot.dtsi"
+
+/ {
+ model = "x220";
+ compatible = "marvell,armadaxp-98dx3236", "marvell,armadaxp-mv78260",
+ "marvell,armadaxp", "marvell,armada-370-xp";
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ bootargs = "console=ttyS0,115200";
+ };
+
+ aliases {
+ i2c0 = &i2c0;
+ spi0 = &spi0;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+ };
+};
+
+&L2 {
+ arm,parity-enable;
+ marvell,ecc-enable;
+};
+
+&devbus_bootcs {
+ status = "okay";
+
+ /* Device Bus parameters are required */
+
+ /* Read parameters */
+ devbus,bus-width = <16>;
+ devbus,turn-off-ps = <60000>;
+ devbus,badr-skew-ps = <0>;
+ devbus,acc-first-ps = <124000>;
+ devbus,acc-next-ps = <248000>;
+ devbus,rd-setup-ps = <0>;
+ devbus,rd-hold-ps = <0>;
+
+ /* Write parameters */
+ devbus,sync-enable = <0>;
+ devbus,wr-high-ps = <60000>;
+ devbus,wr-low-ps = <60000>;
+ devbus,ale-wr-ps = <60000>;
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&i2c0 {
+ clock-frequency = <100000>;
+ status = "okay";
+
+ rtc@68 {
+ compatible = "dallas,ds1340";
+ reg = <0x68>;
+ };
+
+ adt7476a@2e {
+ compatible = "adi,adt7476";
+ reg = <0x2e>;
+ };
+
+ sfpgpio: gpio@27 {
+ #address-cells = <2>;
+ #size-cells = <0>;
+ compatible = "nxp,pca9555";
+ reg = <0x27>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ systemgpio: gpio@25 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "nxp,pca9555";
+ reg = <0x25>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ nand-protect {
+ gpio-hog;
+ gpios = <6 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "nand-protect";
+ };
+
+ usb-enable {
+ gpio-hog;
+ gpios = <9 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "usb-enable";
+ };
+
+ phy-reset {
+ gpio-hog;
+ gpios = <5 GPIO_ACTIVE_LOW>;
+ output-high;
+ line-name = "phy-reset";
+ };
+
+ led-enable {
+ gpio-hog;
+ gpios = <13 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "led-enable";
+ };
+ };
+};
+
+&watchdog {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+
+ spi-flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-flash", "jedec,spi-nor";
+ reg = <0>; /* Chip select 0 */
+ spi-max-frequency = <20000000>;
+ };
+};
+
+&nand_controller {
+ compatible = "marvell,armada370-nand-controller";
+ label = "pxa3xx_nand-0";
+ status = "okay";
+ nand-rb = <0>;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+};
+
+&{/} {
+ boot-board {
+ compatible = "atl,boot-board";
+ present-gpio = <&systemgpio 12 GPIO_ACTIVE_HIGH>;
+ override-gpio = <&gpio0 31 GPIO_ACTIVE_HIGH>;
+ };
+};
+
diff --git a/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi b/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi
index dc20643bfa3..ad64813e770 100644
--- a/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi
+++ b/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi
@@ -5,7 +5,6 @@
status = "okay";
label = "pxa3xx_nand-0";
nand-rb = <0>;
- marvell,nand-keep-config;
nand-on-flash-bbt;
nand-ecc-strength = <4>;
nand-ecc-step-size = <512>;
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 4afaee234ea..3465ccfc151 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -166,6 +166,14 @@ config TARGET_MVEBU_ARMADA_8K
select BOARD_LATE_INIT
imply SCSI
+config TARGET_NBX10G
+ bool "Support Freebox Nodebox 10G"
+ select ARMADA_8K
+ select BOARD_LATE_INIT
+ help
+ Enable support for the Freebox Nodebox 10G board based on the
+ Marvell Armada 8040 SoC with dual CP110 companion chips.
+
config TARGET_MVEBU_ALLEYCAT5
bool "Support AlleyCat 5 platforms"
select ALLEYCAT_5
@@ -226,6 +234,10 @@ config TARGET_X240
select ALLEYCAT_5
imply BOOTSTD_DEFAULTS
+config TARGET_X220
+ bool "Support Allied Telesis x220"
+ select 98DX3336
+
config TARGET_DB_XC3_24G4XG
bool "Support DB-XC3-24G4XG"
select 98DX3336
@@ -310,6 +322,7 @@ config SYS_BOARD
default "x530" if TARGET_X530
default "x250" if TARGET_X250
default "x240" if TARGET_X240
+ default "x220" if TARGET_X220
default "db-xc3-24g4xg" if TARGET_DB_XC3_24G4XG
default "crs3xx-98dx3236" if TARGET_CRS3XX_98DX3236
default "mvebu_alleycat-5" if TARGET_MVEBU_ALLEYCAT5
@@ -335,6 +348,7 @@ config SYS_CONFIG_NAME
default "x530" if TARGET_X530
default "x250" if TARGET_X250
default "x240" if TARGET_X240
+ default "x220" if TARGET_X220
default "db-xc3-24g4xg" if TARGET_DB_XC3_24G4XG
default "crs3xx-98dx3236" if TARGET_CRS3XX_98DX3236
default "mvebu_alleycat-5" if TARGET_MVEBU_ALLEYCAT5
@@ -360,6 +374,7 @@ config SYS_VENDOR
default "alliedtelesis" if TARGET_X530
default "alliedtelesis" if TARGET_X250
default "alliedtelesis" if TARGET_X240
+ default "alliedtelesis" if TARGET_X220
default "mikrotik" if TARGET_CRS3XX_98DX3236
default "Marvell" if TARGET_MVEBU_ALLEYCAT5
@@ -508,5 +523,6 @@ config ARMADA_32BIT_SYSCON_SYSRESET
source "board/solidrun/clearfog/Kconfig"
source "board/kobol/helios4/Kconfig"
+source "board/freebox/nbx10g/Kconfig"
endif
diff --git a/arch/arm/mach-mvebu/armada8k/Makefile b/arch/arm/mach-mvebu/armada8k/Makefile
index 0a4756717a3..723239d9894 100644
--- a/arch/arm/mach-mvebu/armada8k/Makefile
+++ b/arch/arm/mach-mvebu/armada8k/Makefile
@@ -2,4 +2,4 @@
#
# Copyright (C) 2016 Stefan Roese <[email protected]>
-obj-y = cpu.o cache_llc.o dram.o
+obj-y = cpu.o cache_llc.o dram.o soc_info.o
diff --git a/arch/arm/mach-mvebu/armada8k/cpu.c b/arch/arm/mach-mvebu/armada8k/cpu.c
index 3eb93c82387..220b32dd025 100644
--- a/arch/arm/mach-mvebu/armada8k/cpu.c
+++ b/arch/arm/mach-mvebu/armada8k/cpu.c
@@ -15,6 +15,8 @@
#include <asm/armv8/mmu.h>
#include <mach/fw_info.h>
+#include "soc_info.h"
+
/* Armada 7k/8k */
#define MVEBU_RFU_BASE (MVEBU_REGISTER(0x6f0000))
#define RFU_GLOBAL_SW_RST (MVEBU_RFU_BASE + 0x84)
@@ -111,3 +113,13 @@ int mmc_get_env_dev(void)
return CONFIG_ENV_MMC_DEVICE_INDEX;
}
+
+int print_cpuinfo(void)
+{
+ if (!IS_ENABLED(CONFIG_DISPLAY_CPUINFO))
+ return 0;
+
+ soc_print_clock_info();
+ soc_print_soc_info();
+ return 0;
+}
diff --git a/arch/arm/mach-mvebu/armada8k/soc_info.c b/arch/arm/mach-mvebu/armada8k/soc_info.c
new file mode 100644
index 00000000000..18cc083c0db
--- /dev/null
+++ b/arch/arm/mach-mvebu/armada8k/soc_info.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Marvell International Ltd.
+ *
+ * Marvell Armada 8K SoC info: SAR, Clock frequencies, LLC status
+ * Ported from Marvell U-Boot 2015.01 to mainline U-Boot.
+ */
+
+#include <config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <stdio.h>
+#include <asm/io.h>
+#include <asm/arch/soc.h>
+
+/* Clock frequency units */
+#define KHz 1000
+#define MHz 1000000
+#define GHz 1000000000
+
+/* AP806 SAR (Sample-At-Reset) register */
+#define AP806_SAR_REG_BASE (SOC_REGS_PHY_BASE + 0x6F4400)
+#define SAR_CLOCK_FREQ_MODE_OFFSET 0
+#define SAR_CLOCK_FREQ_MODE_MASK (0x1f << SAR_CLOCK_FREQ_MODE_OFFSET)
+
+/* LLC (Last Level Cache) registers */
+#define LLC_BASE (SOC_REGS_PHY_BASE + 0x8000)
+#define LLC_CTRL 0x100
+#define LLC_CTRL_EN 0x1
+#define LLC_EXCLUSIVE_EN 0x100
+
+/* MSS clock is fixed at 200MHz on AP806 */
+#define AP806_MSS_CLOCK (200 * MHz)
+
+/* Clock ID indices in PLL frequency table */
+#define CPU_CLOCK_ID 0
+#define DDR_CLOCK_ID 1
+#define RING_CLOCK_ID 2
+
+/* Clocking options (SAR field values) */
+enum clocking_options {
+ CPU_2000_DDR_1200_RCLK_1200 = 0x0,
+ CPU_2000_DDR_1050_RCLK_1050 = 0x1,
+ CPU_1600_DDR_800_RCLK_800 = 0x4,
+ CPU_1800_DDR_1200_RCLK_1200 = 0x6,
+ CPU_1800_DDR_1050_RCLK_1050 = 0x7,
+ CPU_1600_DDR_900_RCLK_900 = 0x0b,
+ CPU_1600_DDR_1050_RCLK_1050 = 0x0d,
+ CPU_1600_DDR_900_RCLK_900_2 = 0x0e,
+ CPU_1000_DDR_650_RCLK_650 = 0x13,
+ CPU_1300_DDR_800_RCLK_800 = 0x14,
+ CPU_1300_DDR_650_RCLK_650 = 0x17,
+ CPU_1200_DDR_800_RCLK_800 = 0x19,
+ CPU_1400_DDR_800_RCLK_800 = 0x1a,
+ CPU_600_DDR_800_RCLK_800 = 0x1b,
+ CPU_800_DDR_800_RCLK_800 = 0x1c,
+ CPU_1000_DDR_800_RCLK_800 = 0x1d,
+};
+
+/*
+ * PLL frequency table: maps SAR clock mode to actual frequencies.
+ * Format: { CPU_freq, DDR_freq, RING_freq, SAR_value }
+ */
+static const u32 pll_freq_tbl[16][4] = {
+ /* CPU */ /* DDR */ /* Ring */
+ {2000 * MHz, 1200 * MHz, 1200 * MHz, CPU_2000_DDR_1200_RCLK_1200},
+ {2000 * MHz, 1050 * MHz, 1050 * MHz, CPU_2000_DDR_1050_RCLK_1050},
+ {1800 * MHz, 1200 * MHz, 1200 * MHz, CPU_1800_DDR_1200_RCLK_1200},
+ {1800 * MHz, 1050 * MHz, 1050 * MHz, CPU_1800_DDR_1050_RCLK_1050},
+ {1600 * MHz, 1050 * MHz, 1050 * MHz, CPU_1600_DDR_1050_RCLK_1050},
+ {1600 * MHz, 900 * MHz, 900 * MHz, CPU_1600_DDR_900_RCLK_900_2},
+ {1300 * MHz, 800 * MHz, 800 * MHz, CPU_1300_DDR_800_RCLK_800},
+ {1300 * MHz, 650 * MHz, 650 * MHz, CPU_1300_DDR_650_RCLK_650},
+ {1600 * MHz, 800 * MHz, 800 * MHz, CPU_1600_DDR_800_RCLK_800},
+ {1600 * MHz, 900 * MHz, 900 * MHz, CPU_1600_DDR_900_RCLK_900},
+ {1000 * MHz, 650 * MHz, 650 * MHz, CPU_1000_DDR_650_RCLK_650},
+ {1200 * MHz, 800 * MHz, 800 * MHz, CPU_1200_DDR_800_RCLK_800},
+ {1400 * MHz, 800 * MHz, 800 * MHz, CPU_1400_DDR_800_RCLK_800},
+ {600 * MHz, 800 * MHz, 800 * MHz, CPU_600_DDR_800_RCLK_800},
+ {800 * MHz, 800 * MHz, 800 * MHz, CPU_800_DDR_800_RCLK_800},
+ {1000 * MHz, 800 * MHz, 800 * MHz, CPU_1000_DDR_800_RCLK_800}
+};
+
+/*
+ * Get the clock frequency mode index from SAR register.
+ * Returns index into pll_freq_tbl, or -1 if not found.
+ */
+static int sar_get_clock_freq_mode(void)
+{
+ u32 i;
+ u32 clock_freq;
+
+ clock_freq = (readl(AP806_SAR_REG_BASE) & SAR_CLOCK_FREQ_MODE_MASK)
+ >> SAR_CLOCK_FREQ_MODE_OFFSET;
+
+ for (i = 0; i < ARRAY_SIZE(pll_freq_tbl); i++) {
+ if (pll_freq_tbl[i][3] == clock_freq)
+ return i;
+ }
+
+ pr_err("SAR: unsupported clock freq mode %d\n", clock_freq);
+ return -1;
+}
+
+/*
+ * Get CPU clock frequency in Hz.
+ */
+static u32 soc_cpu_clk_get(void)
+{
+ int mode = sar_get_clock_freq_mode();
+
+ if (mode < 0)
+ return 0;
+ return pll_freq_tbl[mode][CPU_CLOCK_ID];
+}
+
+/*
+ * Get DDR clock frequency in Hz.
+ */
+static u32 soc_ddr_clk_get(void)
+{
+ int mode = sar_get_clock_freq_mode();
+
+ if (mode < 0)
+ return 0;
+ return pll_freq_tbl[mode][DDR_CLOCK_ID];
+}
+
+/*
+ * Get Ring (Fabric) clock frequency in Hz.
+ */
+static u32 soc_ring_clk_get(void)
+{
+ int mode = sar_get_clock_freq_mode();
+
+ if (mode < 0)
+ return 0;
+ return pll_freq_tbl[mode][RING_CLOCK_ID];
+}
+
+/*
+ * Get MSS clock frequency in Hz.
+ */
+static u32 soc_mss_clk_get(void)
+{
+ return AP806_MSS_CLOCK;
+}
+
+/*
+ * Get LLC status and mode.
+ * Returns 1 if LLC is enabled, 0 otherwise.
+ * If excl_mode is not NULL, sets it to 1 if exclusive mode is enabled.
+ */
+static int llc_mode_get(int *excl_mode)
+{
+ u32 val;
+ int ret = 0, excl = 0;
+
+ val = readl(LLC_BASE + LLC_CTRL);
+ if (val & LLC_CTRL_EN) {
+ ret = 1;
+ if (val & LLC_EXCLUSIVE_EN)
+ excl = 1;
+ }
+ if (excl_mode)
+ *excl_mode = excl;
+
+ return ret;
+}
+
+/*
+ * Print SoC clock information.
+ */
+void soc_print_clock_info(void)
+{
+ printf("Clock: CPU %-4d [MHz]\n", soc_cpu_clk_get() / MHz);
+ printf("\tDDR %-4d [MHz]\n", soc_ddr_clk_get() / MHz);
+ printf("\tFABRIC %-4d [MHz]\n", soc_ring_clk_get() / MHz);
+ printf("\tMSS %-4d [MHz]\n", soc_mss_clk_get() / MHz);
+}
+
+/*
+ * Print SoC-specific information: DDR width and LLC status.
+ */
+void soc_print_soc_info(void)
+{
+ int llc_en, llc_excl_mode;
+
+ printf("\tDDR 64 Bit width\n");
+
+ llc_en = llc_mode_get(&llc_excl_mode);
+ printf("\tLLC %s%s\n", llc_en ? "Enabled" : "Disabled",
+ llc_excl_mode ? " (Exclusive Mode)" : "");
+}
diff --git a/arch/arm/mach-mvebu/armada8k/soc_info.h b/arch/arm/mach-mvebu/armada8k/soc_info.h
new file mode 100644
index 00000000000..41afe7a2508
--- /dev/null
+++ b/arch/arm/mach-mvebu/armada8k/soc_info.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2015 Marvell International Ltd.
+ *
+ * Marvell Armada 8K SoC info functions
+ */
+
+#ifndef _ARMADA8K_SOC_INFO_H_
+#define _ARMADA8K_SOC_INFO_H_
+
+void soc_print_clock_info(void);
+void soc_print_soc_info(void);
+
+#endif /* _ARMADA8K_SOC_INFO_H_ */
diff --git a/board/Marvell/mvebu_armada-37xx/board.c b/board/Marvell/mvebu_armada-37xx/board.c
index e44b713f96d..c30fca6cffd 100644
--- a/board/Marvell/mvebu_armada-37xx/board.c
+++ b/board/Marvell/mvebu_armada-37xx/board.c
@@ -102,11 +102,6 @@ static bool is_edpu_plus(void)
return false;
}
-int board_early_init_f(void)
-{
- return 0;
-}
-
int board_init(void)
{
/* adress of boot parameters */
diff --git a/board/Synology/common/Makefile b/board/Synology/common/Makefile
index f688b549063..87be53321ee 100644
--- a/board/Synology/common/Makefile
+++ b/board/Synology/common/Makefile
@@ -2,4 +2,4 @@
#
# Copyright (C) 2021 Phil Sutter <[email protected]>
-obj-$(SUPPORT_PASSING_ATAGS) += legacy.o
+obj-$(CONFIG_SUPPORT_PASSING_ATAGS) += legacy.o
diff --git a/board/Synology/common/legacy.c b/board/Synology/common/legacy.c
index 2e3aa660eaa..5b7d07bc2ee 100644
--- a/board/Synology/common/legacy.c
+++ b/board/Synology/common/legacy.c
@@ -10,6 +10,7 @@
#include <vsprintf.h>
#include <env.h>
#include <net.h>
+#include <asm/io.h>
#include <asm/setup.h>
#include "legacy.h"
diff --git a/board/alliedtelesis/x220/.gitattributes b/board/alliedtelesis/x220/.gitattributes
new file mode 100644
index 00000000000..2aeb4eee641
--- /dev/null
+++ b/board/alliedtelesis/x220/.gitattributes
@@ -0,0 +1 @@
+binary.0 binary
diff --git a/board/alliedtelesis/x220/.gitignore b/board/alliedtelesis/x220/.gitignore
new file mode 100644
index 00000000000..775b9346b85
--- /dev/null
+++ b/board/alliedtelesis/x220/.gitignore
@@ -0,0 +1 @@
+kwbimage.cfg
diff --git a/board/alliedtelesis/x220/MAINTAINERS b/board/alliedtelesis/x220/MAINTAINERS
new file mode 100644
index 00000000000..63da2725f71
--- /dev/null
+++ b/board/alliedtelesis/x220/MAINTAINERS
@@ -0,0 +1,8 @@
+x220 BOARD
+M: Chris Packham <[email protected]>
+S: Maintained
+F: board/alliedtelesis/x220
+F: include/configs/x220.h
+F: configs/x220_defconfig
+F: arch/arm/dts/armada-xp-atl-x220.dts
+F: doc/board/alliedtelesis/x220.rst
diff --git a/board/alliedtelesis/x220/Makefile b/board/alliedtelesis/x220/Makefile
new file mode 100644
index 00000000000..a74f0a76948
--- /dev/null
+++ b/board/alliedtelesis/x220/Makefile
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2025 Allied Telesis Labs
+
+obj-y := x220.o
+extra-y := kwbimage.cfg
+
+quiet_cmd_sed = SED $@
+ cmd_sed = sed $(SEDFLAGS_$(@F)) $< >$(dir $@)$(@F)
+
+SEDFLAGS_kwbimage.cfg =-e "s|^BINARY.*|BINARY $(srctree)/$(@D)/binary.0 0000005b 00000068|"
+$(obj)/kwbimage.cfg: $(src)/kwbimage.cfg.in include/autoconf.mk \
+ include/config/auto.conf
+ $(call if_changed,sed)
diff --git a/board/alliedtelesis/x220/binary.0 b/board/alliedtelesis/x220/binary.0
new file mode 100644
index 00000000000..8dd687286a0
--- /dev/null
+++ b/board/alliedtelesis/x220/binary.0
@@ -0,0 +1,11 @@
+--------
+WARNING:
+--------
+This file should contain the bin_hdr generated by the original Marvell
+U-Boot implementation. As this is currently not included in this
+U-Boot version, we have added this placeholder, so that the U-Boot
+image can be generated without errors.
+
+If you have a known to be working bin_hdr for your board, then you
+just need to replace this text file here with the binary header
+and recompile U-Boot.
diff --git a/board/alliedtelesis/x220/kwbimage.cfg.in b/board/alliedtelesis/x220/kwbimage.cfg.in
new file mode 100644
index 00000000000..8beda907ba4
--- /dev/null
+++ b/board/alliedtelesis/x220/kwbimage.cfg.in
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2025 Allied Telesis Labs
+#
+
+# Armada XP uses version 1 image format
+VERSION 1
+
+# Boot Media configurations
+BOOT_FROM spi
+
+# Binary Header (bin_hdr) with DDR3 training code
+BINARY board/alliedtelesis/x220/binary.0 0000005b 00000068
diff --git a/board/alliedtelesis/x220/x220.c b/board/alliedtelesis/x220/x220.c
new file mode 100644
index 00000000000..7c9a73de9a2
--- /dev/null
+++ b/board/alliedtelesis/x220/x220.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025 Allied Telesis Labs
+ */
+
+#include <i2c.h>
+#include <init.h>
+#include <asm/global_data.h>
+#include <asm/gpio.h>
+#include <linux/bitops.h>
+#include <linux/mbus.h>
+#include <linux/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define X220_GPP_OUT_ENA_LOW (~(BIT(12) | BIT(17) | BIT(18) | BIT(31)))
+#define X220_GPP_OUT_ENA_MID (~(0))
+#define X220_GPP_OUT_VAL_LOW (BIT(12) | BIT(18))
+#define X220_GPP_OUT_VAL_MID 0x0
+#define X220_GPP_POL_LOW 0x0
+#define X220_GPP_POL_MID 0x0
+
+int board_early_init_f(void)
+{
+ /* Configure MPP */
+ writel(0x44042222, MVEBU_MPP_BASE + 0x00);
+ writel(0x11000004, MVEBU_MPP_BASE + 0x04);
+ writel(0x44444004, MVEBU_MPP_BASE + 0x08);
+ writel(0x04444444, MVEBU_MPP_BASE + 0x0c);
+ writel(0x00000004, MVEBU_MPP_BASE + 0x10);
+
+ /* Set GPP Out value */
+ writel(X220_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
+ writel(X220_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00);
+
+ /* Set GPP Polarity */
+ writel(X220_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c);
+ writel(X220_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c);
+
+ /* Set GPP Out Enable */
+ writel(X220_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
+ writel(X220_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04);
+
+ return 0;
+}
+
+int board_init(void)
+{
+ /* address of boot parameters */
+ gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+
+ /* Disable MBUS Err Prop - in order to avoid data aborts */
+ clrbits_le32(MVEBU_CPU_WIN_BASE + 0x200, (1 << 8));
+
+ return 0;
+}
+
+#ifdef CONFIG_DISPLAY_BOARDINFO
+int checkboard(void)
+{
+ puts("Board: Allied Telesis x220\n");
+
+ return 0;
+}
+#endif
diff --git a/board/freebox/nbx10g/Kconfig b/board/freebox/nbx10g/Kconfig
new file mode 100644
index 00000000000..958c8fdd4c3
--- /dev/null
+++ b/board/freebox/nbx10g/Kconfig
@@ -0,0 +1,94 @@
+if TARGET_NBX10G
+
+config SYS_BOARD
+ default "nbx10g"
+
+config SYS_VENDOR
+ default "freebox"
+
+config SYS_CONFIG_NAME
+ default "nbx10g"
+
+config CMD_NBX_EMMCBOOT
+ bool "emmcboot command"
+ depends on MMC_SDHCI_XENON
+ help
+ Enable the emmcboot command for dual-bank boot from eMMC.
+ This is a legacy boot format used on this board for many years.
+ It implements a boot system with two image banks and automatic
+ fallback on boot failures. The boot order depends on a reboot
+ tracking counter (nrboot):
+ - If healthy: try Bank1 (newer) first, then Bank0 (stable)
+ - If degraded (>= 4 failures): try Bank0 first, then Bank1
+
+ Requires image_addr and fdt_addr environment variables to be set.
+
+if CMD_NBX_EMMCBOOT
+
+config NBX_MMC_PART_NRBOOT_OFFSET
+ hex "NRBoot counter offset in eMMC"
+ default 0x802000
+ help
+ Byte offset in eMMC where the reboot tracking counter is stored.
+ Default: 0x802000 (8MB + 8KB)
+
+config NBX_MMC_PART_BANK0_OFFSET
+ hex "Bank0 image offset in eMMC"
+ default 0x804000
+ help
+ Byte offset in eMMC where the stable (Bank0) boot image starts.
+ Default: 0x804000 (8MB + 16KB)
+
+config NBX_MMC_PART_BANK0_SIZE
+ hex "Bank0 image maximum size"
+ default 0x10000000
+ help
+ Maximum size of the Bank0 boot image.
+ Default: 0x10000000 (256MB)
+
+config NBX_MMC_PART_BANK1_OFFSET
+ hex "Bank1 image offset in eMMC"
+ default 0x10804000
+ help
+ Byte offset in eMMC where the newer (Bank1) boot image starts.
+ Default: 0x10804000 (264MB + 16KB)
+
+config NBX_MMC_PART_BANK1_SIZE
+ hex "Bank1 image maximum size"
+ default 0x10000000
+ help
+ Maximum size of the Bank1 boot image.
+ Default: 0x10000000 (256MB)
+
+endif
+
+config CMD_NBX_FBXSERIAL
+ bool "fbxserial command"
+ depends on MMC_SDHCI_XENON
+ help
+ Enable the fbxserial command to read and display device
+ serial information from eMMC. This includes:
+ - Device serial number (type, version, manufacturer, date, number)
+ - MAC address (used to set ethaddr environment variables)
+ - Bundle information (if present)
+
+ The serial info is stored at a fixed offset in the eMMC user area.
+
+ Subcommands:
+ - fbxserial show: display serial info (default)
+ - fbxserial init: initialize ethaddr from serial info
+
+ Use CONFIG_PREBOOT="fbxserial init" to auto-initialize at boot.
+
+if CMD_NBX_FBXSERIAL
+
+config NBX_MMC_PART_SERIAL_OFFSET
+ hex "Serial info offset in eMMC"
+ default 0x800000
+ help
+ Byte offset in eMMC where the serial info structure is stored.
+ Default: 0x800000 (8MB)
+
+endif
+
+endif
diff --git a/board/freebox/nbx10g/MAINTAINERS b/board/freebox/nbx10g/MAINTAINERS
new file mode 100644
index 00000000000..2e31eed45b9
--- /dev/null
+++ b/board/freebox/nbx10g/MAINTAINERS
@@ -0,0 +1,6 @@
+NBX10G BOARD
+M: Vincent Jardin <[email protected]>
+S: Maintained
+F: board/freebox/nbx10g/
+F: configs/mvebu_nbx_88f8040_defconfig
+F: arch/arm/dts/armada-8040-nbx*
diff --git a/board/freebox/nbx10g/Makefile b/board/freebox/nbx10g/Makefile
new file mode 100644
index 00000000000..4b70d94e14d
--- /dev/null
+++ b/board/freebox/nbx10g/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y := board.o
+obj-$(CONFIG_CMD_NBX_EMMCBOOT) += nbx_emmcboot.o
+obj-$(CONFIG_CMD_NBX_FBXSERIAL) += nbx_fbxserial.o
diff --git a/board/freebox/nbx10g/board.c b/board/freebox/nbx10g/board.c
new file mode 100644
index 00000000000..7d16010ec7e
--- /dev/null
+++ b/board/freebox/nbx10g/board.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017-2018 Freebox SA
+ * Copyright (C) 2026 Free Mobile, Vincent Jardin <[email protected]>
+ *
+ * Freebox Nodebox 10G board support
+ */
+
+#include <init.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+
+/* Management PHY reset GPIO */
+#define NBX_PHY_RESET_GPIO 83
+
+/* Nodebox 10G ASCII art logo */
+static const char * const nbx_logo =
+ " _ _ _ _ __ ___ _____\n"
+ " | \\ | | | | | | /_ |/ _ \\ / ____|\n"
+ " | \\| | ___ __| | ___| |__ _____ __ | | | | | | __\n"
+ " | . ` |/ _ \\ / _` |/ _ \\ '_ \\ / _ \\ \\/ / | | | | | | |_ |\n"
+ " | |\\ | (_) | (_| | __/ |_) | (_) > < | | |_| | |__| |\n"
+ " |_| \\_|\\___/ \\__,_|\\___|_.__/ \\___/_/\\_\\ |_|\\___/ \\_____|\n";
+
+int checkboard(void)
+{
+ printf("%s\n", nbx_logo);
+ return 0;
+}
+
+int board_init(void)
+{
+ return 0;
+}
+
+int board_late_init(void)
+{
+ int ret;
+
+ /* Reset the management PHY */
+ ret = gpio_request(NBX_PHY_RESET_GPIO, "phy-reset");
+ if (ret) {
+ printf("Failed to request PHY reset GPIO: %d\n", ret);
+ return 0;
+ }
+
+ gpio_direction_output(NBX_PHY_RESET_GPIO, 0);
+ mdelay(100);
+ gpio_set_value(NBX_PHY_RESET_GPIO, 1);
+ mdelay(100);
+
+ return 0;
+}
diff --git a/board/freebox/nbx10g/nbx_emmcboot.c b/board/freebox/nbx10g/nbx_emmcboot.c
new file mode 100644
index 00000000000..0bea96fadd9
--- /dev/null
+++ b/board/freebox/nbx10g/nbx_emmcboot.c
@@ -0,0 +1,357 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Nodebox 10G dual-bank eMMC boot command with automatic fallback
+ *
+ * Copyright (C) 2026 Free Mobile, Freebox
+ *
+ * This implements a dual-bank boot system with automatic fallback:
+ * - Bank0: Stable/fallback boot image
+ * - Bank1: Newer/test boot image
+ *
+ * The boot order depends on the reboot tracking counter (nrboot):
+ * - If healthy: try Bank1 first, then Bank0
+ * - If degraded (>= 4 failures): try Bank0 first, then Bank1
+ */
+
+#include <command.h>
+#include <env.h>
+#include <mmc.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <vsprintf.h>
+#include <u-boot/crc.h>
+#include <u-boot/schedule.h>
+#include <asm/byteorder.h>
+#include <linux/errno.h>
+#include "nbx_imagetag.h"
+#include "nbx_nrboot.h"
+
+/* Partition offsets defined in Kconfig (CONFIG_NBX_MMC_PART_*) */
+
+/* Image Tag Functions */
+
+static int mvebu_imagetag_check(struct mvebu_image_tag *tag,
+ unsigned long maxsize, const char *name)
+{
+ if (be32_to_cpu(tag->magic) != MVEBU_IMAGE_TAG_MAGIC) {
+ if (name)
+ printf("%s: invalid TAG magic: %.8x\n", name,
+ be32_to_cpu(tag->magic));
+ return -EINVAL;
+ }
+
+ if (be32_to_cpu(tag->version) != MVEBU_IMAGE_TAG_VERSION) {
+ if (name)
+ printf("%s: invalid TAG version: %.8x\n", name,
+ be32_to_cpu(tag->version));
+ return -EINVAL;
+ }
+
+ if (be32_to_cpu(tag->total_size) < sizeof(*tag)) {
+ if (name)
+ printf("%s: tag size is too small!\n", name);
+ return -EINVAL;
+ }
+
+ if (be32_to_cpu(tag->total_size) > maxsize) {
+ if (name)
+ printf("%s: tag size is too big!\n", name);
+ return -EINVAL;
+ }
+
+ if (be32_to_cpu(tag->device_tree_offset) < sizeof(*tag) ||
+ be32_to_cpu(tag->device_tree_offset) +
+ be32_to_cpu(tag->device_tree_size) > maxsize) {
+ if (name)
+ printf("%s: bogus device tree offset/size!\n", name);
+ return -EINVAL;
+ }
+
+ if (be32_to_cpu(tag->kernel_offset) < sizeof(*tag) ||
+ be32_to_cpu(tag->kernel_offset) +
+ be32_to_cpu(tag->kernel_size) > maxsize) {
+ if (name)
+ printf("%s: bogus kernel offset/size!\n", name);
+ return -EINVAL;
+ }
+
+ if (be32_to_cpu(tag->rootfs_offset) < sizeof(*tag) ||
+ be32_to_cpu(tag->rootfs_offset) +
+ be32_to_cpu(tag->rootfs_size) > maxsize) {
+ if (name)
+ printf("%s: bogus rootfs offset/size!\n", name);
+ return -EINVAL;
+ }
+
+ if (name) {
+ /*
+ * Ensure null-termination within the 32-byte fields
+ * before printing to avoid displaying garbage.
+ */
+ tag->image_name[sizeof(tag->image_name) - 1] = '\0';
+ tag->build_date[sizeof(tag->build_date) - 1] = '\0';
+ tag->build_user[sizeof(tag->build_user) - 1] = '\0';
+
+ printf("%s: Found valid tag: %s / %s / %s\n", name,
+ tag->image_name, tag->build_date, tag->build_user);
+ }
+
+ return 0;
+}
+
+static int mvebu_imagetag_crc(struct mvebu_image_tag *tag, const char *name)
+{
+ u32 crc = ~0;
+
+ crc = crc32(crc, ((unsigned char *)tag) + 4,
+ be32_to_cpu(tag->total_size) - 4);
+
+ if (be32_to_cpu(tag->crc) != crc) {
+ if (name)
+ printf("%s: invalid tag CRC!\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* NRBoot (Reboot Tracking) Functions */
+
+struct mvebu_nrboot {
+ u16 nrboot;
+ u16 nrsuccess;
+};
+
+#define MVEBU_MAX_FAILURE 4
+
+static int mvebu_count_bits(u16 val)
+{
+ int i, found = 0;
+
+ for (i = 0; i < 16; i++) {
+ if (val & (1 << i))
+ found++;
+ }
+ return found;
+}
+
+int mvebu_check_nrboot(struct mmc *mmc, unsigned long offset)
+{
+ struct blk_desc *bd = mmc_get_blk_desc(mmc);
+ struct mvebu_nrboot *nr;
+ uint blk_start = ALIGN(offset, bd->blksz) / bd->blksz;
+ uint blk_cnt = ALIGN(sizeof(*nr), bd->blksz) / bd->blksz;
+ uint n;
+
+ ALLOC_CACHE_ALIGN_BUFFER(char, buf, blk_cnt * bd->blksz);
+ nr = (void *)buf;
+
+ n = blk_dread(bd, blk_start, blk_cnt, buf);
+ if (n != blk_cnt)
+ return 0;
+
+ printf(" - nr.nrboot = %04x\n", nr->nrboot);
+ printf(" - nr.nrsuccess = %04x\n", nr->nrsuccess);
+
+ /* Sanity check on values */
+ if (mvebu_count_bits(~nr->nrboot + 1) <= 1 &&
+ mvebu_count_bits(~nr->nrsuccess + 1) <= 1) {
+ int boot, success;
+
+ boot = 16 - mvebu_count_bits(nr->nrboot);
+ success = 16 - mvebu_count_bits(nr->nrsuccess);
+
+ printf(" - Nrboot: %d / Nrsuccess: %d\n", boot, success);
+
+ if (boot == 16 || boot < success ||
+ boot - success >= MVEBU_MAX_FAILURE) {
+ printf(" - Nrboot exceeded\n");
+ return 0;
+ }
+
+ /* Increment boot attempt counter */
+ boot++;
+ nr->nrboot = ~((1 << boot) - 1);
+
+ printf(" - Setting Nrboot to %d\n", boot);
+
+ n = blk_dwrite(bd, blk_start, blk_cnt, buf);
+ if (n != blk_cnt)
+ return 0;
+
+ return 1;
+ }
+
+ printf(" - Invalid NR values\n");
+
+ return 0;
+}
+
+/* emmcboot Command */
+
+static void mvebu_try_emmcboot(struct mmc *mmc, unsigned long offset,
+ unsigned long maxsize, const char *bank)
+{
+ struct blk_desc *bd = mmc_get_blk_desc(mmc);
+ struct mvebu_image_tag *tag;
+ ulong image_addr = 0;
+ ulong fdt_addr = 0;
+ ulong tag_addr;
+ uint tag_blk_start = ALIGN(offset, bd->blksz) / bd->blksz;
+ uint tag_blk_cnt = ALIGN(sizeof(*tag), bd->blksz) / bd->blksz;
+ uint n;
+
+ ALLOC_CACHE_ALIGN_BUFFER(char, tag_buf, tag_blk_cnt * bd->blksz);
+ tag = (void *)tag_buf;
+
+ schedule();
+
+ printf("## Trying %s boot...\n", bank);
+
+ /* Load tag header */
+ n = blk_dread(bd, tag_blk_start, tag_blk_cnt, tag_buf);
+ if (n != tag_blk_cnt) {
+ printf("%s: failed to read tag header\n", bank);
+ return;
+ }
+
+ if (mvebu_imagetag_check(tag, maxsize, bank) != 0)
+ return;
+
+ if (tag->rootfs_size != 0) {
+ printf("%s: rootfs in tag not supported\n", bank);
+ return;
+ }
+
+ /* Get image and device tree load addresses from environment */
+ image_addr = env_get_ulong("image_addr", 16, 0);
+ if (!image_addr) {
+ puts("emmcboot needs image_addr\n");
+ return;
+ }
+
+ fdt_addr = env_get_ulong("fdt_addr", 16, 0);
+ if (!fdt_addr) {
+ puts("emmcboot needs fdt_addr\n");
+ return;
+ }
+
+ tag_addr = image_addr;
+
+ /* Load full image, temporarily reuse image_addr for this */
+ {
+ uint data_blk_start = ALIGN(offset, bd->blksz) / bd->blksz;
+ uint data_blk_cnt = ALIGN(mvebu_imagetag_total_size(tag),
+ bd->blksz) / bd->blksz;
+
+ n = blk_dread(bd, data_blk_start, data_blk_cnt, (void *)tag_addr);
+ if (n != data_blk_cnt) {
+ printf("%s: failed to read full image\n", bank);
+ return;
+ }
+
+ if (mvebu_imagetag_crc((void *)tag_addr, bank) != 0)
+ return;
+ }
+
+ schedule();
+
+ /* Copy image and device tree to the right addresses */
+ /* We assume that image_addr + tag_size < fdt_addr */
+ {
+ tag = (void *)tag_addr;
+ memcpy((void *)fdt_addr,
+ ((void *)tag_addr) + mvebu_imagetag_device_tree_offset(tag),
+ mvebu_imagetag_device_tree_size(tag));
+ memmove((void *)image_addr,
+ ((void *)tag_addr) + mvebu_imagetag_kernel_offset(tag),
+ mvebu_imagetag_kernel_size(tag));
+ }
+
+ schedule();
+
+ /* Set bootargs and boot */
+ {
+ char bootargs[256];
+ char *console_env;
+
+ console_env = env_get("console");
+ if (console_env)
+ snprintf(bootargs, sizeof(bootargs), "%s bank=%s",
+ console_env, bank);
+ else
+ snprintf(bootargs, sizeof(bootargs), "bank=%s", bank);
+
+ env_set("bootargs", bootargs);
+
+ printf("## Booting kernel from %s...\n", bank);
+ printf(" Image addr: 0x%lx\n", image_addr);
+ printf(" FDT addr: 0x%lx\n", fdt_addr);
+
+ /* Build and run booti command */
+ {
+ char cmd[128];
+
+ snprintf(cmd, sizeof(cmd), "booti 0x%lx - 0x%lx",
+ image_addr, fdt_addr);
+ run_command(cmd, 0);
+ }
+ }
+
+ printf("## %s boot failed\n", bank);
+}
+
+static int do_emmcboot(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int dev;
+ struct mmc *mmc;
+
+ dev = 0;
+ if (argc >= 2)
+ dev = dectoul(argv[1], NULL);
+
+ mmc = find_mmc_device(dev);
+ if (!mmc) {
+ printf("No MMC device %d found\n", dev);
+ return CMD_RET_FAILURE;
+ }
+
+ if (mmc_init(mmc)) {
+ puts("MMC init failed\n");
+ return CMD_RET_FAILURE;
+ }
+
+ /* Switch to partition 0 (user data area) */
+ if (blk_select_hwpart_devnum(UCLASS_MMC, dev, 0)) {
+ puts("MMC partition switch failed\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (mvebu_check_nrboot(mmc, CONFIG_NBX_MMC_PART_NRBOOT_OFFSET)) {
+ /* System is healthy: try newer bank first */
+ mvebu_try_emmcboot(mmc, CONFIG_NBX_MMC_PART_BANK1_OFFSET,
+ CONFIG_NBX_MMC_PART_BANK1_SIZE, "bank1");
+ mvebu_try_emmcboot(mmc, CONFIG_NBX_MMC_PART_BANK0_OFFSET,
+ CONFIG_NBX_MMC_PART_BANK0_SIZE, "bank0");
+ } else {
+ /* System is degraded: use stable bank first */
+ mvebu_try_emmcboot(mmc, CONFIG_NBX_MMC_PART_BANK0_OFFSET,
+ CONFIG_NBX_MMC_PART_BANK0_SIZE, "bank0");
+ mvebu_try_emmcboot(mmc, CONFIG_NBX_MMC_PART_BANK1_OFFSET,
+ CONFIG_NBX_MMC_PART_BANK1_SIZE, "bank1");
+ }
+
+ puts("emmcboot: all boot attempts failed\n");
+ return CMD_RET_FAILURE;
+}
+
+U_BOOT_CMD(
+ emmcboot, 2, 0, do_emmcboot,
+ "boot from MVEBU eMMC image banks",
+ "[dev]\n"
+ " - Boot from eMMC device <dev> (default 0)\n"
+ " - Requires image_addr and fdt_addr environment variables\n"
+ " - Uses dual-bank boot with automatic fallback\n"
+ " - Bank selection based on reboot tracking (nrboot)"
+);
diff --git a/board/freebox/nbx10g/nbx_fbxserial.c b/board/freebox/nbx10g/nbx_fbxserial.c
new file mode 100644
index 00000000000..088133a9496
--- /dev/null
+++ b/board/freebox/nbx10g/nbx_fbxserial.c
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * NBX Freebox Serial Info Support
+ *
+ * Copyright (C) 2025 Free Mobile, Freebox
+ *
+ * Reads device serial number and MAC address from eMMC.
+ * The serial info is stored at a fixed offset in the eMMC user area.
+ *
+ * Serial format: TTTT-VV-M-(YY)WW-NN-NNNNN / FLAGS
+ * Where:
+ * TTTT = Device type (e.g., 9018)
+ * VV = Board version
+ * M = Manufacturer code (ASCII)
+ * YY = Year (BCD)
+ * WW = Week (1-53)
+ * NNNNN = Serial number
+ * FLAGS = Feature flags
+ */
+
+#include <command.h>
+#include <dm/device.h>
+#include <env.h>
+#include <event.h>
+#include <mmc.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <vsprintf.h>
+#include <u-boot/crc.h>
+#include <asm/byteorder.h>
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include "nbx_fbxserial.h"
+
+/* Partition offset defined in Kconfig (CONFIG_NBX_MMC_PART_SERIAL_OFFSET) */
+
+/*
+ * Validate serial info structure
+ */
+static int nbx_fbx_check_serial(struct nbx_fbx_serial *fs)
+{
+ unsigned int sum, len;
+
+ /* Check magic first */
+ if (be32_to_cpu(fs->magic) != NBX_FBXSERIAL_MAGIC) {
+ printf("Invalid magic for serial info (%08x != %08x)!\n",
+ be32_to_cpu(fs->magic), NBX_FBXSERIAL_MAGIC);
+ return -EINVAL;
+ }
+
+ /* Check struct version */
+ if (be32_to_cpu(fs->struct_version) > NBX_FBXSERIAL_VERSION) {
+ printf("Version too big for fbxserial info (0x%08x)!\n",
+ be32_to_cpu(fs->struct_version));
+ return -EINVAL;
+ }
+
+ /* Check for silly len */
+ len = be32_to_cpu(fs->len);
+ if (len > NBX_FBXSERIAL_MAX_SIZE) {
+ printf("Silly len for serial info (%d)\n", len);
+ return -EINVAL;
+ }
+
+ /* Validate CRC (crc32_no_comp: no one's complement) */
+ sum = crc32_no_comp(0, (void *)fs + 4, len - 4);
+ if (be32_to_cpu(fs->crc32) != sum) {
+ printf("Invalid checksum for serial info (%08x != %08x)\n",
+ sum, be32_to_cpu(fs->crc32));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int nbx_fbx_read_serial(int dev_num, unsigned long offset,
+ struct nbx_fbx_serial *fs)
+{
+ struct mmc *mmc;
+ struct blk_desc *bd;
+ uint blk_start, blk_cnt;
+ uint n;
+
+ ALLOC_CACHE_ALIGN_BUFFER(char, buf, ALIGN(sizeof(*fs), 512));
+ mmc = find_mmc_device(dev_num);
+ if (!mmc) {
+ printf("No MMC device %d found\n", dev_num);
+ nbx_fbxserial_set_default(fs);
+ return -ENODEV;
+ }
+
+ if (mmc_init(mmc)) {
+ puts("MMC init failed\n");
+ nbx_fbxserial_set_default(fs);
+ return -EIO;
+ }
+
+ /* Switch to partition 0 (user data area) */
+ if (blk_select_hwpart_devnum(UCLASS_MMC, dev_num, 0)) {
+ puts("MMC partition switch failed\n");
+ nbx_fbxserial_set_default(fs);
+ return -EIO;
+ }
+
+ bd = mmc_get_blk_desc(mmc);
+ if (!bd) {
+ puts("Failed to get MMC block descriptor\n");
+ nbx_fbxserial_set_default(fs);
+ return -EIO;
+ }
+
+ blk_start = ALIGN(offset, bd->blksz) / bd->blksz;
+ blk_cnt = ALIGN(sizeof(*fs), bd->blksz) / bd->blksz;
+
+ memset(fs, 0x42, sizeof(*fs));
+
+ n = blk_dread(bd, blk_start, blk_cnt, buf);
+ if (n != blk_cnt) {
+ printf("Failed to read serial info from MMC\n");
+ nbx_fbxserial_set_default(fs);
+ return -EIO;
+ }
+
+ memcpy(fs, buf, sizeof(*fs));
+
+ if (nbx_fbx_check_serial(fs) != 0) {
+ nbx_fbxserial_set_default(fs);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void nbx_fbx_dump_serial(struct nbx_fbx_serial *fs)
+{
+ int i;
+
+ printf("Serial: %04u-%02u-%c-(%02u)%02u-%02u-%05u / %08x\n",
+ ntohs(fs->type),
+ fs->version,
+ isprint(fs->manufacturer) ? fs->manufacturer : '?',
+ ntohs(fs->year) / 100,
+ ntohs(fs->year) % 100,
+ fs->week,
+ ntohl(fs->number),
+ ntohl(fs->flags));
+
+ printf("Mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ fs->mac_addr_base[0],
+ fs->mac_addr_base[1],
+ fs->mac_addr_base[2],
+ fs->mac_addr_base[3],
+ fs->mac_addr_base[4],
+ fs->mac_addr_base[5]);
+
+ /* Show bundle info */
+ for (i = 0; i < be32_to_cpu(fs->extinfo_count); i++) {
+ struct nbx_serial_extinfo *p;
+
+ if (i >= NBX_EXTINFO_MAX_COUNT)
+ break;
+
+ p = &fs->extinfos[i];
+ if (be32_to_cpu(p->type) == NBX_EXTINFO_TYPE_EXTDEV &&
+ be32_to_cpu(p->u.extdev.type) == NBX_EXTDEV_TYPE_BUNDLE) {
+ /* Ensure null termination */
+ p->u.extdev.serial[sizeof(p->u.extdev.serial) - 1] = 0;
+ printf("Bundle: %s\n", p->u.extdev.serial);
+ }
+ }
+
+ printf("\n");
+}
+
+int nbx_fbx_init_ethaddr(int dev_num, unsigned long offset)
+{
+ struct nbx_fbx_serial fs;
+ char mac[32];
+ int ret;
+
+ ret = nbx_fbx_read_serial(dev_num, offset, &fs);
+
+ /* Even on error, fs has default values set */
+ snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
+ fs.mac_addr_base[0], fs.mac_addr_base[1],
+ fs.mac_addr_base[2], fs.mac_addr_base[3],
+ fs.mac_addr_base[4], fs.mac_addr_base[5]);
+
+ nbx_fbx_dump_serial(&fs);
+
+ env_set("ethaddr", mac);
+ env_set("eth1addr", mac);
+ env_set("eth2addr", mac);
+
+ return ret;
+}
+
+/*
+ * fbxserial show - display serial info from eMMC
+ */
+static int do_fbxserial_show(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct nbx_fbx_serial fs;
+ int dev = 0;
+ unsigned long offset = CONFIG_NBX_MMC_PART_SERIAL_OFFSET;
+
+ if (argc >= 1)
+ dev = dectoul(argv[0], NULL);
+
+ if (argc >= 2)
+ offset = hextoul(argv[1], NULL);
+
+ if (nbx_fbx_read_serial(dev, offset, &fs) != 0)
+ printf("Warning: Using default serial info\n");
+
+ nbx_fbx_dump_serial(&fs);
+
+ return CMD_RET_SUCCESS;
+}
+
+/*
+ * fbxserial init - initialize ethaddr from serial info
+ */
+static int do_fbxserial_init(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ int dev = 0;
+ unsigned long offset = CONFIG_NBX_MMC_PART_SERIAL_OFFSET;
+
+ if (argc >= 1)
+ dev = dectoul(argv[0], NULL);
+
+ if (argc >= 2)
+ offset = hextoul(argv[1], NULL);
+
+ return nbx_fbx_init_ethaddr(dev, offset);
+}
+
+static struct cmd_tbl cmd_fbxserial_sub[] = {
+ U_BOOT_CMD_MKENT(show, 3, 0, do_fbxserial_show, "", ""),
+ U_BOOT_CMD_MKENT(init, 3, 0, do_fbxserial_init, "", ""),
+};
+
+static int do_fbxserial(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct cmd_tbl *cp;
+
+ /* Default to 'show' if no subcommand */
+ if (argc < 2)
+ return do_fbxserial_show(cmdtp, flag, 0, NULL);
+
+ cp = find_cmd_tbl(argv[1], cmd_fbxserial_sub,
+ ARRAY_SIZE(cmd_fbxserial_sub));
+
+ if (!cp)
+ return CMD_RET_USAGE;
+
+ return cp->cmd(cmdtp, flag, argc - 2, argv + 2);
+}
+
+U_BOOT_CMD(
+ fbxserial, 5, 0, do_fbxserial,
+ "NBX serial info and MAC address initialization",
+ "show [dev] [offset] - display serial info from eMMC\n"
+ "fbxserial init [dev] [offset] - initialize ethaddr from serial info\n"
+ " dev - MMC device number (default 0)\n"
+ " offset - offset in eMMC in hex (default from Kconfig)"
+);
+
+/*
+ * Early init hook: Set MAC address from eMMC serial info before
+ * network driver probes. EVT_SETTINGS_R is triggered after MMC
+ * is available but before initr_net().
+ */
+static int nbx_fbx_settings_r(void)
+{
+ if (!of_machine_is_compatible("nbx,armada8040"))
+ return 0;
+
+ nbx_fbx_init_ethaddr(0, CONFIG_NBX_MMC_PART_SERIAL_OFFSET);
+ return 0;
+}
+
+EVENT_SPY_SIMPLE(EVT_SETTINGS_R, nbx_fbx_settings_r);
diff --git a/board/freebox/nbx10g/nbx_fbxserial.h b/board/freebox/nbx10g/nbx_fbxserial.h
new file mode 100644
index 00000000000..7bcaef09fe3
--- /dev/null
+++ b/board/freebox/nbx10g/nbx_fbxserial.h
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * NBX Freebox Serial Info Support
+ *
+ * Copyright (C) 2025 Free Mobile, Freebox
+ *
+ * Reads device serial number and MAC address from eMMC.
+ * Used to identify the board and set network MAC addresses.
+ */
+
+#ifndef NBX_FBXSERIAL_H
+#define NBX_FBXSERIAL_H
+
+#include <linux/types.h>
+
+/*
+ * Extended info structure - variable data depending on type
+ */
+#define NBX_EXTINFO_SIZE 128
+#define NBX_EXTINFO_MAX_COUNT 16
+
+/* Extended info types */
+#define NBX_EXTINFO_TYPE_EXTDEV 1
+
+/* Extended device types */
+#define NBX_EXTDEV_TYPE_BUNDLE 1
+#define NBX_EXTDEV_TYPE_MAX 2
+
+struct nbx_serial_extinfo {
+ u32 type;
+
+ union {
+ /* extdev */
+ struct {
+ u32 type;
+ u32 model;
+ char serial[64];
+ } extdev;
+
+ /* raw access */
+ unsigned char data[NBX_EXTINFO_SIZE];
+ } u;
+} __packed;
+
+/*
+ * Master serial structure
+ */
+#define NBX_FBXSERIAL_VERSION 1
+#define NBX_FBXSERIAL_MAGIC 0x2d9521ab
+
+#define NBX_MAC_ADDR_SIZE 6
+#define NBX_RANDOM_DATA_SIZE 32
+
+/* Maximum size for CRC validation */
+#define NBX_FBXSERIAL_MAX_SIZE 8192
+
+struct nbx_fbx_serial {
+ u32 crc32;
+ u32 magic;
+ u32 struct_version;
+ u32 len;
+
+ /* Board serial */
+ u16 type;
+ u8 version;
+ u8 manufacturer;
+ u16 year;
+ u8 week;
+ u32 number;
+ u32 flags;
+
+ /* MAC address base */
+ u8 mac_addr_base[NBX_MAC_ADDR_SIZE];
+
+ /* MAC address count */
+ u8 mac_count;
+
+ /* Random data used to derive keys */
+ u8 random_data[NBX_RANDOM_DATA_SIZE];
+
+ /* Last update of data (seconds since epoch) */
+ u32 last_modified;
+
+ /* Count of following extinfo tags */
+ u32 extinfo_count;
+
+ /* Beginning of extended info */
+ struct nbx_serial_extinfo extinfos[NBX_EXTINFO_MAX_COUNT];
+} __packed;
+
+/**
+ * nbx_fbxserial_set_default() - Initialize serial structure with defaults
+ * @serial: Pointer to serial structure to initialize
+ *
+ * Sets the serial structure to default values (Freebox OUI, type 9018).
+ * Used as fallback when serial info cannot be read from eMMC.
+ */
+static inline void nbx_fbxserial_set_default(struct nbx_fbx_serial *serial)
+{
+ static const struct nbx_fbx_serial def = {
+ .crc32 = 0,
+ .magic = NBX_FBXSERIAL_MAGIC,
+ .struct_version = NBX_FBXSERIAL_VERSION,
+ .len = sizeof(struct nbx_fbx_serial),
+ .type = 9018,
+ .version = 0,
+ .manufacturer = '_',
+ .year = 0,
+ .week = 0,
+ .number = 0,
+ .flags = 0,
+ .mac_addr_base = { 0x00, 0x07, 0xCB, 0x00, 0x00, 0xFD },
+ .mac_count = 1,
+ .random_data = { 0 },
+ .last_modified = 0,
+ .extinfo_count = 0,
+ };
+
+ memcpy(serial, &def, sizeof(def));
+}
+
+/**
+ * nbx_fbx_read_serial() - Read serial info from eMMC
+ * @dev_num: MMC device number
+ * @offset: Byte offset in eMMC where serial info is stored
+ * @fs: Pointer to serial structure to fill
+ *
+ * Reads and validates the serial info from eMMC. On failure,
+ * the structure is filled with default values.
+ *
+ * Return: 0 on success, negative on error (defaults still set)
+ */
+int nbx_fbx_read_serial(int dev_num, unsigned long offset,
+ struct nbx_fbx_serial *fs);
+
+/**
+ * nbx_fbx_dump_serial() - Print serial info to console
+ * @fs: Pointer to serial structure to display
+ *
+ * Prints the serial number, MAC address, and bundle info (if present).
+ */
+void nbx_fbx_dump_serial(struct nbx_fbx_serial *fs);
+
+/**
+ * nbx_fbx_init_ethaddr() - Initialize Ethernet addresses from serial info
+ * @dev_num: MMC device number
+ * @offset: Byte offset in eMMC where serial info is stored
+ *
+ * Reads serial info and sets ethaddr, eth1addr, eth2addr environment
+ * variables from the MAC address in the serial structure.
+ *
+ * Return: 0 on success, negative on error
+ */
+int nbx_fbx_init_ethaddr(int dev_num, unsigned long offset);
+
+#endif /* NBX_FBXSERIAL_H */
diff --git a/board/freebox/nbx10g/nbx_imagetag.h b/board/freebox/nbx10g/nbx_imagetag.h
new file mode 100644
index 00000000000..999293dd58a
--- /dev/null
+++ b/board/freebox/nbx10g/nbx_imagetag.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * MVEBU Image Tag header
+ *
+ * Copyright (C) 2026 Free Mobile, Freebox
+ */
+
+#ifndef __MVEBU_IMAGETAG_H
+#define __MVEBU_IMAGETAG_H
+
+#include <linux/types.h>
+
+#define MVEBU_IMAGE_TAG_MAGIC 0x8d7c90bc
+#define MVEBU_IMAGE_TAG_VERSION 1
+
+/**
+ * struct mvebu_image_tag - MVEBU boot image tag structure
+ *
+ * All multi-byte fields are stored in big-endian format.
+ */
+struct mvebu_image_tag {
+ u32 crc; /* CRC32-LE checksum (from offset 4) */
+ u32 magic; /* Magic: 0x8d7c90bc */
+ u32 version; /* Version: 1 */
+ u32 total_size; /* Total image size including tag */
+ u32 flags; /* Feature flags (reserved) */
+
+ u32 device_tree_offset; /* Offset from tag start to DTB */
+ u32 device_tree_size; /* DTB size in bytes */
+
+ u32 kernel_offset; /* Offset from tag start to kernel */
+ u32 kernel_size; /* Kernel size in bytes */
+
+ u32 rootfs_offset; /* Offset from tag start to rootfs */
+ u32 rootfs_size; /* Rootfs size (must be 0) */
+
+ char image_name[32]; /* Image name (null-terminated) */
+ char build_user[32]; /* Build user info */
+ char build_date[32]; /* Build date info */
+};
+
+/* Accessor functions for big-endian fields */
+static inline u32 mvebu_imagetag_device_tree_offset(struct mvebu_image_tag *tag)
+{
+ return be32_to_cpu(tag->device_tree_offset);
+}
+
+static inline u32 mvebu_imagetag_device_tree_size(struct mvebu_image_tag *tag)
+{
+ return be32_to_cpu(tag->device_tree_size);
+}
+
+static inline u32 mvebu_imagetag_kernel_offset(struct mvebu_image_tag *tag)
+{
+ return be32_to_cpu(tag->kernel_offset);
+}
+
+static inline u32 mvebu_imagetag_kernel_size(struct mvebu_image_tag *tag)
+{
+ return be32_to_cpu(tag->kernel_size);
+}
+
+static inline u32 mvebu_imagetag_rootfs_offset(struct mvebu_image_tag *tag)
+{
+ return be32_to_cpu(tag->rootfs_offset);
+}
+
+static inline u32 mvebu_imagetag_rootfs_size(struct mvebu_image_tag *tag)
+{
+ return be32_to_cpu(tag->rootfs_size);
+}
+
+static inline u32 mvebu_imagetag_total_size(struct mvebu_image_tag *tag)
+{
+ return be32_to_cpu(tag->total_size);
+}
+
+#endif /* __MVEBU_IMAGETAG_H */
diff --git a/board/freebox/nbx10g/nbx_nrboot.h b/board/freebox/nbx10g/nbx_nrboot.h
new file mode 100644
index 00000000000..91c9fb2e57b
--- /dev/null
+++ b/board/freebox/nbx10g/nbx_nrboot.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * MVEBU NRBoot (Number of Reboots) tracking header
+ *
+ * Copyright (C) 2026 Free Mobile, Freebox
+ */
+
+#ifndef __MVEBU_NRBOOT_H
+#define __MVEBU_NRBOOT_H
+
+#include <mmc.h>
+
+/**
+ * mvebu_check_nrboot() - Check and update reboot tracking counter
+ * @mmc: MMC device
+ * @offset: Byte offset in MMC where nrboot data is stored
+ *
+ * This function reads the reboot tracking counter, checks if we've
+ * exceeded the maximum number of failed boots (4), and updates the
+ * counter for the current boot attempt.
+ *
+ * The counter uses a bit-field encoding:
+ * - nrboot: Running count of boot attempts
+ * - nrsuccess: Count of successful boots
+ *
+ * If boot - success >= MAX_FAILURE (4), the system is considered
+ * degraded and should use the fallback boot bank.
+ *
+ * Return: 1 if system is healthy (try newer bank first),
+ * 0 if system is degraded (use stable bank first)
+ */
+int mvebu_check_nrboot(struct mmc *mmc, unsigned long offset);
+
+#endif /* __MVEBU_NRBOOT_H */
diff --git a/board/zyxel/nsa325/nsa325.c b/board/zyxel/nsa325/nsa325.c
index 38340b33c8b..894c2ef293c 100644
--- a/board/zyxel/nsa325/nsa325.c
+++ b/board/zyxel/nsa325/nsa325.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2014-2023 Tony Dinh <[email protected]>
+ * Copyright (C) 2014-2025 Tony Dinh <[email protected]>
*
* Based on
* Copyright (C) 2014 Jason Plum <[email protected]>
@@ -51,11 +51,10 @@ DECLARE_GLOBAL_DATA_PTR;
#define HDD1_GREEN_LED BIT(9)
#define HDD1_RED_LED BIT(10)
#define HDD2_POWER BIT(15)
-#define WATCHDOG_SIGNAL BIT(14)
#define NSA325_OE_HIGH (~(COPY_GREEN_LED | COPY_RED_LED | \
- HDD1_GREEN_LED | HDD1_RED_LED | HDD2_POWER | WATCHDOG_SIGNAL))
-#define NSA325_VAL_HIGH (WATCHDOG_SIGNAL | HDD2_POWER)
+ HDD1_GREEN_LED | HDD1_RED_LED | HDD2_POWER))
+#define NSA325_VAL_HIGH (HDD2_POWER)
#define BTN_POWER 46
#define BTN_RESET 36
diff --git a/configs/eDPU_defconfig b/configs/eDPU_defconfig
index 9bc08cd05e9..e227dba5a42 100644
--- a/configs/eDPU_defconfig
+++ b/configs/eDPU_defconfig
@@ -23,7 +23,6 @@ CONFIG_SYS_PBSIZE=1048
# CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_DISPLAY_BOARDINFO_LATE=y
-CONFIG_BOARD_EARLY_INIT_F=y
CONFIG_SYS_PROMPT="eDPU>> "
CONFIG_SYS_MAXARGS=32
# CONFIG_CMD_ELF is not set
diff --git a/configs/mvebu_db-88f3720_defconfig b/configs/mvebu_db-88f3720_defconfig
index 14862e4d60c..ff0f412b6d0 100644
--- a/configs/mvebu_db-88f3720_defconfig
+++ b/configs/mvebu_db-88f3720_defconfig
@@ -22,7 +22,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
# CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_DISPLAY_BOARDINFO_LATE=y
-CONFIG_BOARD_EARLY_INIT_F=y
CONFIG_SYS_MAXARGS=32
CONFIG_CMD_FUSE=y
CONFIG_CMD_GPIO=y
diff --git a/configs/mvebu_espressobin-88f3720_defconfig b/configs/mvebu_espressobin-88f3720_defconfig
index c6574ebe8d9..9f5eda244ac 100644
--- a/configs/mvebu_espressobin-88f3720_defconfig
+++ b/configs/mvebu_espressobin-88f3720_defconfig
@@ -24,7 +24,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
# CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_DISPLAY_BOARDINFO_LATE=y
-CONFIG_BOARD_EARLY_INIT_F=y
CONFIG_BOARD_LATE_INIT=y
CONFIG_SYS_MAXARGS=32
CONFIG_CMD_FUSE=y
diff --git a/configs/mvebu_espressobin_ultra-88f3720_defconfig b/configs/mvebu_espressobin_ultra-88f3720_defconfig
index b37d2b5907e..16e0e54f657 100644
--- a/configs/mvebu_espressobin_ultra-88f3720_defconfig
+++ b/configs/mvebu_espressobin_ultra-88f3720_defconfig
@@ -23,7 +23,6 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
# CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_DISPLAY_BOARDINFO_LATE=y
-CONFIG_BOARD_EARLY_INIT_F=y
CONFIG_BOARD_LATE_INIT=y
CONFIG_SYS_MAXARGS=32
CONFIG_CMD_FUSE=y
diff --git a/configs/mvebu_nbx_88f8040_defconfig b/configs/mvebu_nbx_88f8040_defconfig
new file mode 100644
index 00000000000..85a3086d6a0
--- /dev/null
+++ b/configs/mvebu_nbx_88f8040_defconfig
@@ -0,0 +1,75 @@
+CONFIG_ARM=y
+CONFIG_ARCH_CPU_INIT=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_TEXT_BASE=0x00000000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xff0000
+CONFIG_TARGET_NBX10G=y
+CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x180000
+CONFIG_DM_GPIO=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-8040-nbx"
+CONFIG_FIT=y
+CONFIG_SYS_BOOTM_LEN=0x1000000
+CONFIG_SYS_LOAD_ADDR=0x800000
+CONFIG_PCI=y
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+# CONFIG_EFI_LOADER is not set
+CONFIG_USE_PREBOOT=y
+CONFIG_PREBOOT="echo (CRC warning is normal: no env saved yet)"
+CONFIG_SYS_PBSIZE=1048
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_LAST_STAGE_INIT=y
+CONFIG_SYS_PROMPT="nodebox10G>> "
+CONFIG_SYS_MAXARGS=32
+CONFIG_CMD_BOOTZ=y
+# CONFIG_BOOTM_VXWORKS is not set
+# CONFIG_CMD_ELF is not set
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MISC=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
+# CONFIG_CMD_SF is not set
+CONFIG_CMD_USB=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_NBX_EMMCBOOT=y
+CONFIG_CMD_NBX_FBXSERIAL=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_EFI_PARTITION=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_ENV_RELOC_GD_ENV_ADDR=y
+CONFIG_ARP_TIMEOUT=200
+CONFIG_NET_RETRY_COUNT=50
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MVTWSI=y
+CONFIG_I2C_MUX=y
+CONFIG_MISC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_XENON=y
+# CONFIG_SPI_FLASH is not set
+CONFIG_PHY_MARVELL=y
+CONFIG_PHY_GIGE=y
+CONFIG_MVPP2=y
+CONFIG_PCIE_DW_MVEBU=y
+CONFIG_PHY=y
+CONFIG_MVEBU_COMPHY_SUPPORT=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_ARMADA_8K=y
+CONFIG_SYS_NS16550=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_STORAGE=y
diff --git a/configs/uDPU_defconfig b/configs/uDPU_defconfig
index 93f7e709ce6..7c83ff17b9c 100644
--- a/configs/uDPU_defconfig
+++ b/configs/uDPU_defconfig
@@ -22,7 +22,6 @@ CONFIG_SYS_PBSIZE=1048
# CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_DISPLAY_BOARDINFO_LATE=y
-CONFIG_BOARD_EARLY_INIT_F=y
CONFIG_SYS_PROMPT="uDPU>> "
CONFIG_SYS_MAXARGS=32
# CONFIG_CMD_ELF is not set
diff --git a/configs/x220_defconfig b/configs/x220_defconfig
new file mode 100644
index 00000000000..4318f5e6ef1
--- /dev/null
+++ b/configs/x220_defconfig
@@ -0,0 +1,76 @@
+CONFIG_ARM=y
+CONFIG_ARCH_CPU_INIT=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_SYS_KWD_CONFIG="board/alliedtelesis/x220/kwbimage.cfg"
+CONFIG_TEXT_BASE=0x00800000
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xff0000
+CONFIG_TARGET_X220=y
+CONFIG_ENV_SIZE=0x10000
+CONFIG_ENV_OFFSET=0x100000
+CONFIG_ENV_SECT_SIZE=0x40000
+CONFIG_DEFAULT_DEVICE_TREE="armada-xp-atl-x220"
+CONFIG_SYS_LOAD_ADDR=0x800000
+CONFIG_PCI=y
+CONFIG_SYS_MEMTEST_START=0x00800000
+CONFIG_SYS_MEMTEST_END=0x00ffffff
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_BEST_MATCH=y
+CONFIG_USE_PREBOOT=y
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_SYS_MAXARGS=96
+CONFIG_CMD_MEMTEST=y
+CONFIG_SYS_ALT_MEMTEST=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_MTDIDS_DEFAULT="nand0=nand"
+CONFIG_MTDPARTS_DEFAULT="mtdparts=nand:112M(user),8M(errlog),8M(nand-bbt)"
+CONFIG_CMD_UBI=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_ENV_RELOC_GD_ENV_ADDR=y
+CONFIG_ARP_TIMEOUT=200
+CONFIG_NET_RETRY_COUNT=50
+CONFIG_GPIO_HOG=y
+CONFIG_DM_PCA953X=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MVTWSI=y
+# CONFIG_MMC is not set
+CONFIG_MTD_RAW_NAND=y
+CONFIG_SYS_NAND_USE_FLASH_BBT=y
+CONFIG_NAND_PXA3XX=y
+CONFIG_SYS_NAND_ONFI_DETECTION=y
+CONFIG_SPI_FLASH_SFDP_SUPPORT=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
+CONFIG_PCI_MVEBU=y
+CONFIG_SYS_NS16550=y
+CONFIG_KIRKWOOD_SPI=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_ASIX88179=y
+CONFIG_USB_ETHER_MCS7830=y
+CONFIG_USB_ETHER_RTL8152=y
+CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_WDT=y
+CONFIG_WDT_ORION=y
diff --git a/doc/board/alliedtelesis/index.rst b/doc/board/alliedtelesis/index.rst
new file mode 100644
index 00000000000..a8de2986609
--- /dev/null
+++ b/doc/board/alliedtelesis/index.rst
@@ -0,0 +1,11 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright (C) 2026 Allied Telesis Labs
+
+Allied Telesis
+==============
+
+.. toctree::
+ :maxdepth: 2
+
+ x220
+
diff --git a/doc/board/alliedtelesis/x220.rst b/doc/board/alliedtelesis/x220.rst
new file mode 100644
index 00000000000..6ca5f61ec4e
--- /dev/null
+++ b/doc/board/alliedtelesis/x220.rst
@@ -0,0 +1,39 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright (C) 2026 Allied Telesis Labs
+
+x220 Platforms
+==============
+
+Introduction
+------------
+
+The x220 has is a range of L2+ switches using the Marvell AlleyCat3 switch with
+integrated ARMv7 CPU. It is also sold under some different brands for different
+markets.
+
+- x220-52GP
+- x220-52GT
+- x220-28GS
+- GS980M/52PS
+- GS980M/52
+- x230-52
+
+DDR Traning (binhdr)
+--------------------
+
+The AlleyCat3 uses a binary blob for it's DDR training. This is launched by
+the built-in bootloader prior to U-Boot starting.
+
+To generate binary.0 from Marvell's bin_hdr.elf use the following command
+
+.. prompt:: bash $
+
+ arm-softfloat-linux-gnueabi-objcopy -S -O binary bin_hdr.elf \
+ board/alliedtelesis/x220/binary.0
+
+Alternatively, it is possible to extract the binary.0 from an existing U-Boot
+image
+
+.. prompt:: bash $
+
+ ./tools/dumpimage -T kwbimage -p 1 -o board/alliedtelesis/x220/binary.0 u-boot.kwb
diff --git a/doc/board/index.rst b/doc/board/index.rst
index fcb4224bae3..4103fef8d8f 100644
--- a/doc/board/index.rst
+++ b/doc/board/index.rst
@@ -10,6 +10,7 @@ Board-specific doc
actions/index
advantech/index
andestech/index
+ alliedtelesis/index
allwinner/index
amlogic/index
anbernic/index
diff --git a/drivers/mtd/nand/raw/pxa3xx_nand.c b/drivers/mtd/nand/raw/pxa3xx_nand.c
index 7324dc72e0a..ef01d48acc0 100644
--- a/drivers/mtd/nand/raw/pxa3xx_nand.c
+++ b/drivers/mtd/nand/raw/pxa3xx_nand.c
@@ -184,6 +184,7 @@ struct pxa3xx_nand_host {
struct pxa3xx_nand_info {
struct nand_hw_control controller;
struct pxa3xx_nand_platform_data *pdata;
+ struct udevice *dev;
struct clk *clk;
void __iomem *mmio_base;
@@ -585,8 +586,7 @@ static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len)
ts = get_timer(0);
while (!(nand_readl(info, NDSR) & NDSR_RDDREQ)) {
if (get_timer(ts) > TIMEOUT_DRAIN_FIFO) {
- dev_err(info->controller.active->mtd.dev,
- "Timeout on RDDREQ while draining the FIFO\n");
+ dev_err(info->dev, "Timeout on RDDREQ while draining the FIFO\n");
return;
}
}
@@ -638,8 +638,7 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
DIV_ROUND_UP(info->step_spare_size, 4));
break;
default:
- dev_err(info->controller.active->mtd.dev,
- "%s: invalid state %d\n", __func__, info->state);
+ dev_err(info->dev, "%s: invalid state %d\n", __func__, info->state);
BUG();
}
@@ -1557,8 +1556,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
ecc->size = 512;
if (ecc_stepsize != 512 || !(nfc_layouts[i].strength)) {
- dev_err(info->controller.active->mtd.dev,
- "ECC strength %d at page size %d is not supported\n",
+ dev_err(info->dev, "ECC strength %d at page size %d is not supported\n",
strength, page_size);
return -ENODEV;
}
@@ -1799,6 +1797,7 @@ static int pxa3xx_nand_probe(struct udevice *dev)
if (ret)
return ret;
+ info->dev = dev;
pdata = info->pdata;
ret = alloc_nand_resource(dev, info);
diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index fc137df14c4..ae5920a0201 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -4528,7 +4528,7 @@ static void mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port)
*/
if (phy_dev &&
phy_dev->drv->uid == 0xffffffff) {/* Generic phy */
- dev_warn(port->phy_dev->dev,
+ dev_warn(dev,
"Marking phy as invalid, link will not be checked\n");
/* set phy_addr to invalid value */
port->phyaddr = PHY_MAX_ADDR;
@@ -4540,7 +4540,7 @@ static void mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port)
port->phy_dev = phy_dev;
if (!phy_dev) {
- dev_err(port->phy_dev->dev, "cannot connect to phy\n");
+ dev_err(dev, "cannot connect to phy\n");
return;
}
phy_dev->supported &= PHY_GBIT_FEATURES;
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
index 78184d2860a..c18afe958dc 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-38x.c
@@ -550,7 +550,7 @@ static int armada_38x_pinctrl_probe(struct udevice *dev)
return 0;
}
-struct pinctrl_ops armada_37xx_pinctrl_ops = {
+static const struct pinctrl_ops armada_37xx_pinctrl_ops = {
.get_pins_count = armada_38x_pinctrl_get_pins_count,
.get_pin_name = armada_38x_pinctrl_get_pin_name,
.get_functions_count = armada_38x_pinctrl_get_functions_count,
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 5f8b98f0704..c6e457572b1 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1024,7 +1024,7 @@ config OCTEON_SERIAL_BOOTCMD
bool "MIPS Octeon PCI remote bootcmd input"
depends on ARCH_OCTEON
depends on DM_SERIAL
- select SYS_IS_IN_ENV
+ select SYS_CONSOLE_IS_IN_ENV
select CONSOLE_MUX
help
This driver supports remote input over the PCIe bus from a host
diff --git a/drivers/timer/orion-timer.c b/drivers/timer/orion-timer.c
index 821b681a232..4d1c6b5cef2 100644
--- a/drivers/timer/orion-timer.c
+++ b/drivers/timer/orion-timer.c
@@ -2,6 +2,7 @@
#include <asm/io.h>
#include <config.h>
#include <div64.h>
+#include <dm.h>
#include <dm/device.h>
#include <dm/fdtaddr.h>
#include <timer.h>
@@ -113,7 +114,7 @@ static int orion_timer_probe(struct udevice *dev)
enum input_clock_type type = dev_get_driver_data(dev);
struct orion_timer_priv *priv = dev_get_priv(dev);
- priv->base = devfdt_remap_addr_index(dev, 0);
+ priv->base = dev_remap_addr_index(dev, 0);
if (!priv->base) {
debug("unable to map registers\n");
return -ENOMEM;
diff --git a/include/configs/nbx10g.h b/include/configs/nbx10g.h
new file mode 100644
index 00000000000..bd083b7e7d8
--- /dev/null
+++ b/include/configs/nbx10g.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2017-2018 Freebox SA
+ * Copyright (C) 2026 Free Mobile, Vincent Jardin <[email protected]>
+ *
+ * Configuration for Freebox Nodebox 10G
+ */
+
+#ifndef _CONFIG_NBX10G_H
+#define _CONFIG_NBX10G_H
+
+#include "mvebu_armada-8k.h"
+
+/* Override environment settings for NBX */
+#undef CFG_EXTRA_ENV_SETTINGS
+#define CFG_EXTRA_ENV_SETTINGS \
+ "hostname=nodebox10G\0" \
+ "ethrotate=no\0" \
+ "image_addr=0x7000000\0" \
+ "image_name=Image.nodebox10G\0" \
+ "fdt_addr=0x6f00000\0" \
+ "fdt_name=nodebox10G.dtb\0" \
+ "console=ttyS0,115200\0" \
+ "tftpboot=setenv bootargs console=${console} bank=tftp; " \
+ "dhcp ${image_addr} ${image_name}; " \
+ "tftp ${fdt_addr} ${fdt_name}; " \
+ "booti ${image_addr} - ${fdt_addr}\0"
+
+#endif /* _CONFIG_NBX10G_H */
diff --git a/include/configs/x220.h b/include/configs/x220.h
new file mode 100644
index 00000000000..3022ad491b7
--- /dev/null
+++ b/include/configs/x220.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2025 Allied Telesis Labs
+ */
+
+#ifndef _CONFIG_X220_H
+#define _CONFIG_X220_H
+
+/* Keep device tree and initrd in lower memory so the kernel can access them */
+#define CFG_EXTRA_ENV_SETTINGS \
+ "fdt_high=0x10000000\0" \
+ "initrd_high=0x10000000\0"
+
+/*
+ * mv-common.h should be defined after CMD configs since it used them
+ * to enable certain macros
+ */
+#include "mv-common.h"
+
+#endif /* _CONFIG_X220_H */