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)
This commit is contained in:
Tom Rini
2026-06-10 09:18:15 -06:00
47 changed files with 2125 additions and 28 deletions

View File

@@ -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 \

View File

@@ -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

View File

@@ -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";
};

View File

@@ -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>;
};
};

View File

@@ -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>;

View File

@@ -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

View File

@@ -2,4 +2,4 @@
#
# Copyright (C) 2016 Stefan Roese <sr@denx.de>
obj-y = cpu.o cache_llc.o dram.o
obj-y = cpu.o cache_llc.o dram.o soc_info.o

View File

@@ -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;
}

View File

@@ -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)" : "");
}

View File

@@ -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_ */

View File

@@ -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 */

View File

@@ -2,4 +2,4 @@
#
# Copyright (C) 2021 Phil Sutter <phil@nwl.cc>
obj-$(SUPPORT_PASSING_ATAGS) += legacy.o
obj-$(CONFIG_SUPPORT_PASSING_ATAGS) += legacy.o

View File

@@ -10,6 +10,7 @@
#include <vsprintf.h>
#include <env.h>
#include <net.h>
#include <asm/io.h>
#include <asm/setup.h>
#include "legacy.h"

View File

@@ -0,0 +1 @@
binary.0 binary

1
board/alliedtelesis/x220/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
kwbimage.cfg

View File

@@ -0,0 +1,8 @@
x220 BOARD
M: Chris Packham <chris.packham@alliedtelesis.co.nz>
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

View File

@@ -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)

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,6 @@
NBX10G BOARD
M: Vincent Jardin <vjardin@free.fr>
S: Maintained
F: board/freebox/nbx10g/
F: configs/mvebu_nbx_88f8040_defconfig
F: arch/arm/dts/armada-8040-nbx*

View File

@@ -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

View File

@@ -0,0 +1,53 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017-2018 Freebox SA
* Copyright (C) 2026 Free Mobile, Vincent Jardin <vjardin@free.fr>
*
* 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;
}

View File

@@ -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)"
);

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2014-2023 Tony Dinh <mibodhi@gmail.com>
* Copyright (C) 2014-2025 Tony Dinh <mibodhi@gmail.com>
*
* Based on
* Copyright (C) 2014 Jason Plum <jplum@archlinuxarm.org>
@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

76
configs/x220_defconfig Normal file
View File

@@ -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

View File

@@ -0,0 +1,11 @@
.. SPDX-License-Identifier: GPL-2.0+
.. Copyright (C) 2026 Allied Telesis Labs
Allied Telesis
==============
.. toctree::
:maxdepth: 2
x220

View File

@@ -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

View File

@@ -10,6 +10,7 @@ Board-specific doc
actions/index
advantech/index
andestech/index
alliedtelesis/index
allwinner/index
amlogic/index
anbernic/index

View File

@@ -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);

View File

@@ -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;

View File

@@ -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,

View File

@@ -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

View File

@@ -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;

29
include/configs/nbx10g.h Normal file
View File

@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2017-2018 Freebox SA
* Copyright (C) 2026 Free Mobile, Vincent Jardin <vjardin@free.fr>
*
* 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 */

20
include/configs/x220.h Normal file
View File

@@ -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 */