Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions config/boards/bananapim4.csc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Realtek RTD1395 quad core 1GB/2GB RAM 8GB eMMC FE USB HDMI
BOARD_NAME="BananaPi M4"
BOARD_VENDOR="sinovoip"
BOARDFAMILY="realtek-rtd129x"
BOARD_MAINTAINER="igorpecovnik"
INTRODUCED="2019"
BOOTCONFIG="bananapi-m4_defconfig"
KERNEL_TARGET="current,edge"
KERNEL_TEST_TARGET="current"
BOOT_FDT_FILE="realtek/rtd1395-bpi-m4.dtb"
# The vendor loader in SPI flash reads U-Boot from SD or eMMC sector 80.
RTD129X_EMMC_BOOTAREA="no"
# The RTD1395 build of the audio firmware, which runs the HDMI output
RTD129X_AUDIO_FW_FILE="bluecore-rtd1395.audio"

# eth0: the RJ45, the SoC's MAC with its embedded 10/100 PHY.
# wlan0: the RTL8821CU module on USB port 2 (bus 1, port 2).
function post_family_tweaks__bananapim4_udev_network_interfaces() {
display_alert "$BOARD" "Renaming interfaces eth0 wlan0" "info"
mkdir -p "${SDCARD}"/etc/udev/rules.d/
cat <<- EOF2 > "${SDCARD}/etc/udev/rules.d/70-persistent-net.rules"
SUBSYSTEM=="net", ACTION=="add", KERNELS=="98016000.ethernet", NAME:="eth0"
SUBSYSTEM=="net", ACTION=="add", KERNELS=="1-2:1.2", DRIVERS=="rtw88_8821cu", NAME:="wlan0"
EOF2
}
6 changes: 6 additions & 0 deletions config/kernel/linux-realtek-rtd129x-current.config
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_XFRM_USER=m
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
Expand Down Expand Up @@ -328,6 +330,7 @@ CONFIG_PCI_XGENE=y
CONFIG_PCI_MESON=m
CONFIG_PCI_HISI=y
CONFIG_PCIE_KIRIN=y
CONFIG_PCIE_RTD139X=y
CONFIG_PCI_ENDPOINT=y
CONFIG_PCI_ENDPOINT_CONFIGFS=y
CONFIG_PCI_EPF_TEST=m
Expand Down Expand Up @@ -757,6 +760,7 @@ CONFIG_REGULATOR_BD9571MWV=y
CONFIG_REGULATOR_CROS_EC=y
CONFIG_REGULATOR_DA9211=m
CONFIG_REGULATOR_G2227=y
CONFIG_REGULATOR_G2237=y
CONFIG_REGULATOR_FAN53555=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_HI6421V530=y
Expand Down Expand Up @@ -868,6 +872,7 @@ CONFIG_DRM_PANTHOR=m
CONFIG_DRM_TIDSS=m
CONFIG_DRM_POWERVR=m
CONFIG_FB=y
CONFIG_FB_SIMPLE=y
CONFIG_FB_EFI=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_BACKLIGHT_PWM=m
Expand All @@ -883,6 +888,7 @@ CONFIG_SND_ALOOP=m
CONFIG_RTD129X_ACPU=m
CONFIG_SND_RTD129X_HDMIRX=m
CONFIG_RTD129X_VO=m
CONFIG_SND_RTD129X_HDMI_OUT=m
CONFIG_SND_SOC=m
CONFIG_SND_SOC_FSL_ASRC=m
CONFIG_SND_SOC_FSL_SAI=m
Expand Down
6 changes: 6 additions & 0 deletions config/kernel/linux-realtek-rtd129x-edge.config
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_XFRM_USER=m
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
Expand Down Expand Up @@ -328,6 +330,7 @@ CONFIG_PCI_XGENE=y
CONFIG_PCI_MESON=m
CONFIG_PCI_HISI=y
CONFIG_PCIE_KIRIN=y
CONFIG_PCIE_RTD139X=y
CONFIG_PCI_ENDPOINT=y
CONFIG_PCI_ENDPOINT_CONFIGFS=y
CONFIG_PCI_EPF_TEST=m
Expand Down Expand Up @@ -754,6 +757,7 @@ CONFIG_REGULATOR_BD9571MWV=y
CONFIG_REGULATOR_CROS_EC=y
CONFIG_REGULATOR_DA9211=m
CONFIG_REGULATOR_G2227=y
CONFIG_REGULATOR_G2237=y
CONFIG_REGULATOR_FAN53555=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_HI6421V530=y
Expand Down Expand Up @@ -865,6 +869,7 @@ CONFIG_DRM_PL111=m
CONFIG_DRM_TIDSS=m
CONFIG_DRM_V3D=m
CONFIG_FB=y
CONFIG_FB_SIMPLE=y
CONFIG_FB_EFI=y
CONFIG_BACKLIGHT_PWM=m
CONFIG_BACKLIGHT_LP855X=m
Expand All @@ -878,6 +883,7 @@ CONFIG_SND_ALOOP=m
CONFIG_RTD129X_ACPU=m
CONFIG_SND_RTD129X_HDMIRX=m
CONFIG_RTD129X_VO=m
CONFIG_SND_RTD129X_HDMI_OUT=m
CONFIG_SND_SOC=m
CONFIG_SND_SOC_FSL_ASRC=m
CONFIG_SND_SOC_FSL_SAI=m
Expand Down
76 changes: 57 additions & 19 deletions config/sources/families/realtek-rtd129x.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# This file is a part of the Armbian Build Framework
# https://github.com/armbian/build/
#
# Realtek RTD1295/RTD1296: mainline kernel and mainline u-boot.
# Realtek RTD1295/RTD1296/RTD1395: mainline kernel and mainline u-boot.
# Kernel patches: https://github.com/JalenLin/BPI-W2-linux
#
declare -g ARCH="arm64"
Expand All @@ -15,17 +15,24 @@ declare -g LINUXCONFIG="linux-${LINUXFAMILY}-${BRANCH}"
declare -g SERIALCON="ttyS0:115200"

# Mainline u-boot. The Realtek loader starts it from SD sector 80 (40 KiB).
declare -g BOOTBRANCH="tag:v2026.10-rc5"
declare -g BOOTBRANCH="tag:v2026.10"
declare -g BOOTPATCHDIR="v2026.10-rtd129x"
declare -g UBOOT_TARGET_MAP=";;u-boot.bin rtd129x-emmc-boot.bin"
# RTD1295/RTD1296 boards boot from the eMMC boot area. RTD1395 boards do not.
declare -g RTD129X_EMMC_BOOTAREA="${RTD129X_EMMC_BOOTAREA:-yes}"
if [[ ${RTD129X_EMMC_BOOTAREA} == yes ]]; then
declare -g UBOOT_TARGET_MAP=";;u-boot.bin rtd129x-emmc-boot.bin"
else
declare -g UBOOT_TARGET_MAP=";;u-boot.bin"
fi
declare -g BOOTSCRIPT="boot-realtek-rtd129x.cmd:boot.cmd"
declare -g BOOTENV_FILE="realtek-rtd129x.txt"
# No ATF: U-Boot and Linux start at EL3/EL2 from the Realtek loader.
declare -g ATF_COMPILE="no"

# Audio firmware, pinned to a BPI-W2-bsp commit. U-Boot starts it before Linux.
declare -g RTD129X_AUDIO_FW_URL="https://raw.githubusercontent.com/BPI-SINOVOIP/BPI-W2-bsp/6e6aefc35dc50b1b8231cdb03a995d088f29eb21/rtk-pack/rtk/bpi-w2/configs/default/linux/bluecore.audio"
declare -g RTD129X_AUDIO_FW_SHA256="59252270f05cc55cba0ddeb246bc7c6b20dab9554fa18be4e9595ea549fd9b1c"
# Audio firmware from packages/blobs/rtd129x. U-Boot starts it before Linux.
# It runs the audio and the HDMI output. RTD1395 boards set their own build.
declare -g RTD129X_AUDIO_FW="${RTD129X_AUDIO_FW:-yes}"
declare -g RTD129X_AUDIO_FW_FILE="${RTD129X_AUDIO_FW_FILE:-bluecore-rtd1296.audio}"

case "${BRANCH}" in

Expand All @@ -44,28 +51,59 @@ declare -g KERNELPATCHDIR="archive/${LINUXFAMILY}-${KERNEL_MAJOR_MINOR}"
# The eMMC boot area: the factory boot parts (packages/blobs/rtd129x) with
# this U-Boot. The Realtek SPI loader reads it from eMMC byte 0x20000.
function uboot_custom_postprocess() {
[[ ${RTD129X_EMMC_BOOTAREA} == yes ]] || return 0
run_host_command_logged python3 "${SRC}/packages/blobs/rtd129x/mkbootarea.py" \
"${SRC}/packages/blobs/rtd129x" u-boot.bin rtd129x-emmc-boot.bin
}

# SD card: U-Boot at 40 KiB. eMMC: the whole boot area at 0x20000.
# SD card: U-Boot at 40 KiB. eMMC: the whole boot area at 0x20000, or
# U-Boot at 40 KiB without a boot area (RTD1395).
# The RTD1395 SPI loader cannot read U-Boot raw from the eMMC. It loads
# u-boot-bpi-m4.bin from FAT partition 1. Keep that partition in the 16 MiB
# gap before the root and make it entry 1. The root keeps its UUID.
function write_uboot_platform() {
if [[ $2 == /dev/mmcblk* && -b ${2}boot0 ]]; then
if [[ $2 == /dev/mmcblk* && -b ${2}boot0 && -f $1/rtd129x-emmc-boot.bin ]]; then
dd if="$1/rtd129x-emmc-boot.bin" of="$2" bs=512 seek=256 conv=notrunc,fsync status=none
return
fi
dd if="$1/u-boot.bin" of="$2" bs=1024 seek=40 conv=notrunc,fsync status=none
[[ $2 == /dev/mmcblk* && -b ${2}boot0 && -f /proc/device-tree/compatible ]] || return 0
grep -q "realtek,rtd1395" /proc/device-tree/compatible || return 0

local fat_start=8192 fat_size=24576 table loop mnt rc=0
table=$(sfdisk -d "$2") || return 1
if ! grep -qE "^${2}p1 *: start= *${fat_start}, size= *${fat_size}, type=c" <<< "${table}"; then
# only an MBR with the gap free and a free entry
grep -q "^label: dos" <<< "${table}" || return 1
[[ $(grep -c "^${2}p" <<< "${table}") -lt 4 ]] || return 1
awk -v end=$((fat_start + fat_size)) '/^\/dev\// {
split($0, f, "start="); if (f[2] + 0 < end) exit 1 }' <<< "${table}" || return 1
{
grep -E "^(label|label-id|unit):" <<< "${table}"
echo "start=${fat_start}, size=${fat_size}, type=c"
grep "^${2}p" <<< "${table}" | sed 's/^[^:]*: *//'
} | sfdisk --quiet --no-reread --no-tell-kernel "$2" || return 1
Comment thread
coderabbitai[bot] marked this conversation as resolved.
fi

loop=$(losetup -f --show -o $((fat_start * 512)) --sizelimit $((fat_size * 512)) "$2") || return 1
blkid -p -s TYPE -o value "${loop}" | grep -q vfat || mkfs.vfat -n BPI-BOOT "${loop}" > /dev/null || rc=1
mnt=$(mktemp -d)
if [[ $rc == 0 ]] && mount "${loop}" "${mnt}"; then
cp "$1/u-boot.bin" "${mnt}/u-boot-bpi-m4.bin" || rc=1
umount "${mnt}"
else
dd if="$1/u-boot.bin" of="$2" bs=1024 seek=40 conv=notrunc,fsync status=none
rc=1
fi
rmdir "${mnt}"
losetup -d "${loop}"
sync
return $rc
}

function post_family_tweaks_bsp__rtd129x_audio_firmware() {
display_alert "${BOARD}" "Add audio firmware" "info"
declare cache="${SRC}/cache/rtd129x-blobs" file
file="${cache}/bluecore.audio"
run_host_command_logged mkdir -p "${cache}" "${destination}/boot"
if ! echo "${RTD129X_AUDIO_FW_SHA256} ${file}" | sha256sum --check --status 2> /dev/null; then
run_host_command_logged curl -fsSL -o "${file}" "${RTD129X_AUDIO_FW_URL}"
echo "${RTD129X_AUDIO_FW_SHA256} ${file}" | sha256sum --check --status ||
exit_with_error "Checksum mismatch" "bluecore.audio"
fi
run_host_command_logged cp -v "${file}" "${destination}/boot/bluecore.audio"
[[ ${RTD129X_AUDIO_FW} == yes ]] || return 0
display_alert "${BOARD}" "Add audio firmware" "${RTD129X_AUDIO_FW_FILE}"
run_host_command_logged mkdir -p "${destination}/boot"
run_host_command_logged cp -v "${SRC}/packages/blobs/rtd129x/${RTD129X_AUDIO_FW_FILE}" \
"${destination}/boot/bluecore.audio"
}
10 changes: 10 additions & 0 deletions packages/blobs/rtd129x/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,13 @@ encrypted by Realtek.

`mkbootarea.py` puts them together with a U-Boot into the boot area that
the BPI-W2 SPI loader reads from eMMC byte 0x20000.

# Audio firmware

U-Boot starts it on the audio CPU before Linux. It runs the audio and the
HDMI output. The family installs it as `/boot/bluecore.audio`.

| File | SoC | Source | SHA-256 |
|---|---|---|---|
| `bluecore-rtd1296.audio` | RTD1295/RTD1296 | [BPI-W2-bsp@6e6aefc3](https://github.com/BPI-SINOVOIP/BPI-W2-bsp/blob/6e6aefc35dc50b1b8231cdb03a995d088f29eb21/rtk-pack/rtk/bpi-w2/configs/default/linux/bluecore.audio) | `59252270f05cc55cba0ddeb246bc7c6b20dab9554fa18be4e9595ea549fd9b1c` |
| `bluecore-rtd1395.audio` | RTD1395 | [BPI-M4-bsp@25f5b88e](https://github.com/BPI-SINOVOIP/BPI-M4-bsp/blob/25f5b88ec4ba34029f964693dc34028b26e6c67c/rtk-pack/rtk/bpi-m4/configs/default/linux/bluecore.audio) | `774832da0a18c1ba837ff41926502fb8444e83397562c7170c71435416aff4df` |
Binary file added packages/blobs/rtd129x/bluecore-rtd1296.audio
Binary file not shown.
Binary file added packages/blobs/rtd129x/bluecore-rtd1395.audio
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
From f6467e42e330eeb25a6fc183791054d552a3e2b5 Mon Sep 17 00:00:00 2001
From: Igor Pecovnik <igor@armbian.com>
Date: Wed, 21 Oct 2026 10:37:07 +0000
Subject: [PATCH 30/37] irqchip: rtd129x: add the RTD1395 interrupt muxes

The RTD1395 has the same ISO and MISC muxes as the RTD1295.
Some status bits map to other sources. Add tables for them.

Assisted-by: Claude Opus 5.5
Signed-off-by: Igor Pecovnik <igor@armbian.com>
---
drivers/irqchip/irq-rtd129x.c | 63 +++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)

diff --git a/drivers/irqchip/irq-rtd129x.c b/drivers/irqchip/irq-rtd129x.c
index 40403cca2..a7398e15b 100644
--- a/drivers/irqchip/irq-rtd129x.c
+++ b/drivers/irqchip/irq-rtd129x.c
@@ -295,6 +295,53 @@ static int __init rtd129x_irq_mux_init(struct device_node *np,
return ret;
}

+/* RTD1395: no MISC GPIO, RTC or I2C2-4; LSADC and GPHY HV moved to ISO */
+static const struct rtd129x_irq_mux_info rtd1395_misc_irq_mux = {
+ .name = "misc",
+ .enable_bit = {
+ [0 ... 31] = RTD129X_IRQ_NONE,
+ [2] = RTD129X_IRQ_UNGATED,
+ [3] = 3, /* UART1 */
+ [5] = 5, /* UART1 timeout */
+ [6] = RTD129X_IRQ_UNGATED,
+ [7] = RTD129X_IRQ_UNGATED,
+ [8] = 7, /* UART2 */
+ [13] = 6, /* UART2 timeout */
+ [14] = 14, /* I2C5 */
+ [24] = 24, /* smartcard 0 */
+ [27] = 27, /* GSPI */
+ [29] = 29, /* fan */
+ },
+};
+
+static const struct rtd129x_irq_mux_info rtd1395_iso_irq_mux = {
+ .name = "iso",
+ .enable_bit = {
+ [0 ... 31] = RTD129X_IRQ_NONE,
+ [1] = RTD129X_IRQ_UNGATED,
+ [2] = 2, /* UART0 */
+ [5] = 5, /* IrDA */
+ [7] = RTD129X_IRQ_UNGATED,
+ [8] = 8, /* I2C0 */
+ [9] = RTD129X_IRQ_UNGATED,
+ [11] = 11, /* I2C1 */
+ [12] = 12, /* RTC half-second */
+ [13] = 13, /* RTC alarm */
+ [16] = 16, /* LSADC0 */
+ [17] = 17, /* LSADC1 */
+ [19] = 19, /* GPIO assert */
+ [20] = 20, /* GPIO deassert */
+ [21] = RTD129X_IRQ_UNGATED,
+ [22] = RTD129X_IRQ_UNGATED,
+ [23] = RTD129X_IRQ_UNGATED,
+ [24] = RTD129X_IRQ_UNGATED,
+ [28] = 28, /* GPHY HV */
+ [29] = 29, /* GPHY digital */
+ [30] = 30, /* GPHY analog */
+ [31] = 31, /* I2C1 request */
+ },
+};
+
static int __init rtd1295_misc_irq_mux_init(struct device_node *np,
struct device_node *parent)
{
@@ -307,6 +354,22 @@ static int __init rtd1295_iso_irq_mux_init(struct device_node *np,
return rtd129x_irq_mux_init(np, parent, &rtd1295_iso_irq_mux);
}

+static int __init rtd1395_misc_irq_mux_init(struct device_node *np,
+ struct device_node *parent)
+{
+ return rtd129x_irq_mux_init(np, parent, &rtd1395_misc_irq_mux);
+}
+
+static int __init rtd1395_iso_irq_mux_init(struct device_node *np,
+ struct device_node *parent)
+{
+ return rtd129x_irq_mux_init(np, parent, &rtd1395_iso_irq_mux);
+}
+
+IRQCHIP_DECLARE(rtd1395_misc_irq_mux, "realtek,rtd1395-misc-irq-mux",
+ rtd1395_misc_irq_mux_init);
+IRQCHIP_DECLARE(rtd1395_iso_irq_mux, "realtek,rtd1395-iso-irq-mux",
+ rtd1395_iso_irq_mux_init);
IRQCHIP_DECLARE(rtd1295_misc_irq_mux, "realtek,rtd1295-misc-irq-mux",
rtd1295_misc_irq_mux_init);
IRQCHIP_DECLARE(rtd1295_iso_irq_mux, "realtek,rtd1295-iso-irq-mux",
--
2.53.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
From b828f4eba3f330f002c0ade04165ab16e80ca282 Mon Sep 17 00:00:00 2001
From: Igor Pecovnik <igor@armbian.com>
Date: Wed, 21 Oct 2026 10:37:07 +0000
Subject: [PATCH 31/37] arm64: drain the SB2 bridge on the RTD1395 too

The RTD1395 has the same SB2 bridge and sync register.

Assisted-by: Claude Opus 5.5
Signed-off-by: Igor Pecovnik <igor@armbian.com>
---
arch/arm64/kernel/rtd129x-sb2-sync.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/rtd129x-sb2-sync.c b/arch/arm64/kernel/rtd129x-sb2-sync.c
index 0c425787c..4a5ecbc7b 100644
--- a/arch/arm64/kernel/rtd129x-sb2-sync.c
+++ b/arch/arm64/kernel/rtd129x-sb2-sync.c
@@ -58,7 +58,8 @@ static int __init rtd_sb2_sync_init(void)
{
if (!of_machine_is_compatible("realtek,rtd1293") &&
!of_machine_is_compatible("realtek,rtd1295") &&
- !of_machine_is_compatible("realtek,rtd1296"))
+ !of_machine_is_compatible("realtek,rtd1296") &&
+ !of_machine_is_compatible("realtek,rtd1395"))
return 0;

sb2_sync_map = ioremap(RTD129X_SB2_SYNC, 4);
--
2.53.0

Loading
Loading