mvebu: add support for Turris MOX
authorTomáš Macholda <[email protected]>
Thu, 18 Sep 2025 11:08:52 +0000 (13:08 +0200)
committerHauke Mehrtens <[email protected]>
Sun, 30 Nov 2025 23:32:14 +0000 (00:32 +0100)
Adds support for Turris MOX, a modular router extendable by board modules (MOX B-G).

You can explore the idea behind the modules at: https://mox-configurator.turris.cz/

More information about Turris MOX can be found here: https://docs.turris.cz/hw/mox/intro/

Also works with Turris Shield (Turris MOX A and C with a simplified OS UI).

Specifications:
-----------------------

MOX A
- SoC: Marvell Armada 3720
- RAM: 512/1024 MB, DDR3
- Memory:
    - 8 MB SPI NOR Flash for U-Boot and rescue system
    - SD card slot
- 1x RJ-45, 1Gbps
- 1x USB 3.0
- 1x activity LED
- 1x reset button
- SDIO header
- misc pin header (UART, GPIO, JTAG, ...)

MOX B, G
- 1x mPCIe slot
- 1x SIM slot

MOX C
- 4x RJ-45, 1Gbps

MOX D
- SFP, 2.5Gbps

MOX E
- 8x RJ-45, 1Gbps

MOX F
- 4x USB 3.0

Module support:
-----------------------

Additional packages are needed for some modules.

MOX A (core)
- works as is

MOX B, G (mPCIe, mPCIe passthrough)
- works as is

MOX C, E (4x, 8x RJ-45)
- kmod-dsa
- kmod-dsa-mv88e6xxx

MOX D (SFP)
- kmod-sfp
- kmod-phy-marvell-10g

MOX F (4x USB 3.0)
- works as is

Wi-Fi 5, 3x3 card (WLE900VX)
- kmod-ath10k
- ath10k-board-qca988x
- ath10k-firmware-qca988x

Wi-Fi 6, DBDC, 2x2 card (MT7915DAN)
- kmod-mt7915e
- kmod-mt7915-firmware

Interface naming:
-----------------------

- MOX A's RJ-45 is assigned to `eth0`.
- MOX C, E (4x, 8x RJ-45) are assigned to `lan<number>@eth1`
- If MOX D (SFP) is connected directly to MOX A, the resulting interface
  is `eth1`. If it's connected through MOX E (8x RJ-45), the resulting
  interface is `sfp@eth1`.

Quirks:
-----------------------

- MOX is sensitive to the order of connected modules. Verify that the
  confguration is valid at: https://mox-configurator.turris.cz/
- `CONFIG_MOXTET` and `CONFIG_GPIO_MOXTET` need to be enabled in kernel
  config. Moxtet is a bus protocol needed to discover and configure MOX
  modules. It must be compiled into the kernel for the modules to work.
  Though it's very small so it won't bloat up the kernel image.

Flashing instructions:
-----------------------

1. Download `openwrt-*-ext4-sdcard.img.gz` and `gunzip` it.
2. Insert an SD card and flash the image to it using dd:
   dd if=openwrt-*-ext4-sdcard.img.gz of=/dev/mmcblk0 bs=4096 conv=fsync
3. Plug the SD card into MOX.

Troubleshooting:
-----------------------

- https://docs.turris.cz/hw/serial/#turris-mox
- https://docs.turris.cz/hw/mox/rescue-modes/

Signed-off-by: Tomáš Macholda <[email protected]>
Link: https://github.com/openwrt/openwrt/pull/20356
Signed-off-by: Hauke Mehrtens <[email protected]>
package/boot/uboot-mvebu/Makefile
target/linux/mvebu/cortexa53/base-files/etc/board.d/01_leds
target/linux/mvebu/cortexa53/base-files/etc/board.d/02_network
target/linux/mvebu/cortexa53/config-6.12
target/linux/mvebu/image/cortexa53.mk
target/linux/mvebu/image/turris-mox.bootscript [new file with mode: 0644]

index f3009d0e7c927d41eeb41242180bd9511a6c5c03..85df6a22ce69a72afdb860cb67733c6e742004d9 100644 (file)
@@ -22,6 +22,13 @@ define U-Boot/Default
   HIDDEN:=1
 endef
 
+define U-Boot/mox
+  NAME:=CZ.NIC Turris Mox
+  BUILD_DEVICES:=cznic_turris-mox
+  BUILD_SUBTARGET:=cortexa53
+  UBOOT_CONFIG:=turris_mox
+endef
+
 define U-Boot/clearfog
   NAME:=SolidRun ClearFog A1
   BUILD_DEVICES:=solidrun_clearfog-base-a1 solidrun_clearfog-pro-a1
@@ -69,6 +76,7 @@ define U-Boot/rb5009
 endef
 
 UBOOT_TARGETS:= \
+       mox \
        clearfog \
        helios4 \
        omnia \
index 4dce204f140d4673d9b6452cb4eee89f3ce6819a..035fa4933bad9ed0738239c89b13c175073c07b1 100644 (file)
@@ -7,6 +7,9 @@ board_config_update
 board=$(board_name)
 
 case "$board" in
+cznic,turris-mox)
+        ucidef_set_led_heartbeat "wan" "MOX A" "mox:red:activity"
+        ;;
 glinet,gl-mv1000)
        ucidef_set_led_netdev "wan" "WAN" "green:wan" "wan"
        ;;
index 6789edb8613c33239458d21fa0a34bc032cfc009..c70af063cef61fcac31078219fc2edb649ad1767 100644 (file)
@@ -10,6 +10,18 @@ board_config_update
 board=$(board_name)
 
 case "$board" in
+cznic,turris-mox)
+       mox_lan_interfaces=""
+       for net in /sys/class/net/lan*; do
+               [ -e "$net" ] || continue
+               append mox_lan_interfaces "${net##*/}"
+       done
+       if [ -z "$mox_lan_interfaces" ]; then
+               ucidef_set_interface_lan "eth0"
+       else
+               ucidef_set_interfaces_lan_wan "$mox_lan_interfaces" "eth0"
+       fi
+       ;;
 glinet,gl-mv1000|\
 globalscale,espressobin|\
 globalscale,espressobin-emmc|\
index 253c441519aeb637d04274d2557e89b26b01d79c..15a63334a68139a5d39f48a7855f3baeca610070 100644 (file)
@@ -54,12 +54,14 @@ CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
 CONFIG_GENERIC_CSUM=y
 CONFIG_GENERIC_IOREMAP=y
 CONFIG_GENERIC_PINCONF=y
+CONFIG_GPIO_MOXTET=y
 CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
 CONFIG_MAILBOX=y
 # CONFIG_MAILBOX_TEST is not set
 CONFIG_MFD_SYSCON=y
 CONFIG_MMC_SDHCI_XENON=y
 CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_MOXTET=y
 CONFIG_MVEBU_GICP=y
 CONFIG_MVEBU_ICU=y
 CONFIG_MVEBU_ODMI=y
index 67bff6c0b24f37adc34d5ec169679a5a668b0041..25ec3d3f81e10c0b373a9b0b420b0108073ee5a4 100644 (file)
@@ -1,3 +1,13 @@
+define Device/cznic_turris-mox
+  $(call Device/Default-arm64)
+  DEVICE_VENDOR := CZ.NIC
+  DEVICE_MODEL := Turris MOX
+  DEVICE_PACKAGES := kmod-usb2 kmod-gpio-button-hotplug kmod-rtc-ds1307 kmod-i2c-pxa
+  SOC := armada-3720
+  BOOT_SCRIPT := turris-mox
+endef
+TARGET_DEVICES += cznic_turris-mox
+
 define Device/glinet_gl-mv1000
   $(call Device/Default-arm64)
   DEVICE_VENDOR := GL.iNet
diff --git a/target/linux/mvebu/image/turris-mox.bootscript b/target/linux/mvebu/image/turris-mox.bootscript
new file mode 100644 (file)
index 0000000..8cef275
--- /dev/null
@@ -0,0 +1,50 @@
+if part uuid ${devtype} ${devnum}:${distro_bootpart} bootuuid; then
+       if test "${bootfstype}" = "btrfs"; then
+               # Original BTRFS partition layout
+               rootdev="PARTUUID=${bootuuid}"
+               rootflags="commit=5,subvol=@"
+               bootpath="/@/boot"
+       else
+               # OpenWrt default ext4 bootpart + rootpart layout
+               rootdev="/dev/mmcblk0p2"
+               rootflags="commit=5"
+               bootpath="/"
+       fi
+
+       load ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} ${bootpath}/armada-3720-turris-mox.dtb
+       if test "$filesize" != "0"; then
+               has_dtb=1
+       else
+               setenv has_dtb 0
+               echo "Cannot find device tree binary!"
+       fi
+
+       if test $has_dtb -eq 1; then
+               load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} ${bootpath}/Image
+               if test "$filesize" = "0"; then
+                       echo "Failed to load ${bootpath}/Image"
+                       echo "Now trying ${bootpath}/Image.lzma"
+                       tmp_addr_r=0x10000000
+                       load ${devtype} ${devnum}:${distro_bootpart} ${tmp_addr_r} ${bootpath}/Image.lzma
+                       if test "$filesize" != "0"; then
+                               if lzmadec ${tmp_addr_r} ${kernel_addr_r}; then
+                                       echo "Successfully decompressed Image.lzma"
+                               else
+                                       echo "Failed decompressing Image.lzma"
+                                       filesize=0
+                               fi
+                       else
+                               echo "Failed to load ${subvol}/boot/Image.lzma"
+                       fi
+               fi
+               if test "$filesize" != "0"; then
+                       setenv bootargs "earlyprintk console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000 rootfstype=${bootfstype} root=${rootdev} rootflags=${rootflags} rootwait ${contract} rw cfg80211.freg=${regdomain} ${quirks}"
+                       booti ${kernel_addr_r} - ${fdt_addr_r}
+                       echo "Booting Image failed"
+               else
+                       echo "Cannot load kernel binary"
+               fi
+       fi
+
+       env delete bootuuid rootpart
+fi