diff options
| author | Tom Rini <[email protected]> | 2026-06-10 09:18:15 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-06-10 09:18:15 -0600 |
| commit | 953653936cfc9e12f52df1165080fa6c7cbae1bc (patch) | |
| tree | 407487ab8999b482dfe367b0561347c0f22f261a | |
| parent | 45cfba58dba911685700d6574b01f39329dce99c (diff) | |
| parent | eab66c3a9085e07b227847b0c442ee8d2efb241d (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)
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 */ |
