From 2afd157f2b0504898ee4987ffd93797e9bd84c09 Mon Sep 17 00:00:00 2001 From: Daniel Rossier Date: Fri, 17 Jul 2026 12:45:59 +0200 Subject: [PATCH] arch/arm32: restore the 32-bit Raspberry Pi 4 platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 32-bit rpi4 platform was dropped when the tree moved to rpi4_64: arm32 now only carries VIRT32. What was left behind is a set of "depends on RPI4" in devices/ pointing at a symbol that no longer exists — kernel/Kconfig and devices/serial/Kconfig still spell "RPI4 || RPI4_64", and i2c/rpisense were lined up the same way in e09572557. So the tree is already written for this platform; only the arch symbol and its wiring were missing. Restore them: - config RPI4 in arch/arm32/Kconfig (select GIC_V2, as VIRT32 and RPI4_64 do) - TARGET = rpi4 in the top Makefile, dtb-$(CONFIG_RPI4) in dts/Makefile - arch/arm32/rpi4/: Makefile, platsmp.c and mach/io.h. Unlike arm64, which releases the secondaries through the spin table, the 32-bit path wakes them by writing the entry point into mailbox 3 of the ARM local interrupt controller — hence LOCAL_INTC_PHYS, which the arm64 mach/io.h does not need. - dts/rpi4.dts and configs/rpi4_defconfig, mirroring their rpi4_64 counterparts with the 32-bit values: one address/size cell instead of two, KERNEL_VADDR 0xc0000000, IO_MAPPING_BASE 0xe0000000, and a memory base of 0x01000000 (= the 0x01008000 FIT load minus the arm32 0x8000 text offset, where the 64-bit chain uses 0x01080000 / 0x80000). The mini UART node carries its AUX interrupt (SPI 93, the value Broadcom's bcm2711-rpi-4-b.dtb gives for /soc/serial@7e215040). The driver does not read "interrupts" today, so it is inert; it is simply what the hardware has. Booted on a real RPi 4 Model B: U-Boot (armv7) loads the FIT image and SO3 reaches user space. --- so3/so3/Makefile | 3 + so3/so3/arch/arm32/Kconfig | 4 + so3/so3/arch/arm32/rpi4/Makefile | 5 + so3/so3/arch/arm32/rpi4/include/mach/io.h | 82 +++++++++++++++ so3/so3/arch/arm32/rpi4/platsmp.c | 46 ++++++++ so3/so3/configs/rpi4_defconfig | 88 ++++++++++++++++ so3/so3/dts/Makefile | 1 + so3/so3/dts/rpi4.dts | 123 ++++++++++++++++++++++ 8 files changed, 352 insertions(+) create mode 100644 so3/so3/arch/arm32/rpi4/Makefile create mode 100644 so3/so3/arch/arm32/rpi4/include/mach/io.h create mode 100644 so3/so3/arch/arm32/rpi4/platsmp.c create mode 100644 so3/so3/configs/rpi4_defconfig create mode 100644 so3/so3/dts/rpi4.dts diff --git a/so3/so3/Makefile b/so3/so3/Makefile index dc600c3cb9..e7c4a75fcf 100644 --- a/so3/so3/Makefile +++ b/so3/so3/Makefile @@ -371,6 +371,9 @@ export KBUILD_ARFLAGS ifeq ($(CONFIG_VIRT32),y) TARGET = virt32 endif +ifeq ($(CONFIG_RPI4),y) +TARGET = rpi4 +endif ifeq ($(CONFIG_RPI4_64),y) TARGET = rpi4_64 endif diff --git a/so3/so3/arch/arm32/Kconfig b/so3/so3/arch/arm32/Kconfig index 16b4f7f786..522b3f5236 100644 --- a/so3/so3/arch/arm32/Kconfig +++ b/so3/so3/arch/arm32/Kconfig @@ -14,6 +14,10 @@ choice bool "QEMU virt 32-bit machine" select GIC_V2 + config RPI4 + bool "Raspberry Pi 4 Model B 32-bit" + select GIC_V2 + endchoice endmenu diff --git a/so3/so3/arch/arm32/rpi4/Makefile b/so3/so3/arch/arm32/rpi4/Makefile new file mode 100644 index 0000000000..33477109fe --- /dev/null +++ b/so3/so3/arch/arm32/rpi4/Makefile @@ -0,0 +1,5 @@ +# +# Makefile +# + +obj-$(CONFIG_SMP) += platsmp.o diff --git a/so3/so3/arch/arm32/rpi4/include/mach/io.h b/so3/so3/arch/arm32/rpi4/include/mach/io.h new file mode 100644 index 0000000000..a184fd2d63 --- /dev/null +++ b/so3/so3/arch/arm32/rpi4/include/mach/io.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2020-2026 Daniel Rossier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef MACH_IO_H +#define MACH_IO_H + +/* + * ARM local interrupt controller, which carries the per-CPU mailboxes. + * Unlike arm64, which releases the secondaries through the spin table, + * the 32-bit boot path wakes them by writing the entry point into + * mailbox 3 (see platsmp.c) — hence the mapping below. + */ +#define LOCAL_INTC_PHYS 0xff800000 +#define LOCAL_INTC_SIZE 0x100 + +/* + * From BCM2835 ARM peripherals documentation. + * + * Mini UART register offsets. + */ + +#define MU_IO_REG 0x00 +#define MU_IER_REG 0x04 +#define MU_IIR_REG 0x08 +#define MU_LCR_REG 0x0C +#define MU_MCR_REG 0x10 +#define MU_LSR_REG 0x14 +#define MU_MSR_REG 0x18 +#define MU_SCRATCH 0x1C +#define MU_CNTL_REG 0x20 +#define MU_STAT_REG 0x24 +#define MU_BAUD_REG 0x28 + +#define MU_IO_DATA (0xFF << 0) +#define MU_STAT_SP_AVAIL (1 << 0) +#define MU_STAT_RX_FIFO_FILL (0xF << 16) +#define MU_LSR_TX_EMPTY (1 << 5) +#define MU_LSR_DATA_READY (1 << 0) +/* TODO : all other bit offsets */ + +/* + * The low 4 bits of this are the CPU's per-mailbox IRQ enables, and + * the next 4 bits are the CPU's per-mailbox FIQ enables (which + * override the IRQ bits). + */ +#define LOCAL_MAILBOX_INT_CONTROL0 0x050 + +/* + * Mailbox write-to-set bits. There are 16 mailboxes, 4 per CPU, and + * these bits are organized by mailbox number and then CPU number. We + * use mailbox 0 for IPIs. The mailbox's interrupt is raised while + * any bit is set. + */ +#define LOCAL_MAILBOX0_SET0 0x080 +#define LOCAL_MAILBOX3_SET0 0x08c + +/* Mailbox write-to-clear bits. */ +#define LOCAL_MAILBOX0_CLR0 0x0c0 +#define LOCAL_MAILBOX3_CLR0 0x0cc + +/* CPU Release address to be woken up following spin table method. */ +#define CPU0_RELEASE_ADDR 0xd8 +#define CPU1_RELEASE_ADDR 0xe0 +#define CPU2_RELEASE_ADDR 0xe8 +#define CPU3_RELEASE_ADDR 0xf0 + +#endif /* MACH_IO_H */ diff --git a/so3/so3/arch/arm32/rpi4/platsmp.c b/so3/so3/arch/arm32/rpi4/platsmp.c new file mode 100644 index 0000000000..dd63e891ee --- /dev/null +++ b/so3/so3/arch/arm32/rpi4/platsmp.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016,2017 Daniel Rossier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include + +#include +#include +#include + +#include + +#include + +extern void secondary_startup(void); + +void smp_boot_secondary(unsigned int cpu) +{ + unsigned long secondary_startup_phys = (unsigned long) __pa((void *) secondary_startup); + void *intc_vaddr; /* We will add bytes to this pointer */ + + printk("%s: booting CPU: %d...\n", __func__, cpu); + + intc_vaddr = (void *) io_map(LOCAL_INTC_PHYS, LOCAL_INTC_SIZE); + + iowrite32(intc_vaddr + LOCAL_MAILBOX3_SET0 + 16 * cpu, secondary_startup_phys); + + dsb(sy); + sev(); +} diff --git a/so3/so3/configs/rpi4_defconfig b/so3/so3/configs/rpi4_defconfig new file mode 100644 index 0000000000..c3dfee5056 --- /dev/null +++ b/so3/so3/configs/rpi4_defconfig @@ -0,0 +1,88 @@ +# +# Automatically generated make config: don't edit +# SO3 Polymorphic OS Configuration +# +CONFIG_ARCH_ARM32=y +# CONFIG_ARCH_ARM64 is not set +CONFIG_ARCH="arm32" +CONFIG_CROSS_COMPILE="arm-none-eabi-" +# CONFIG_ARM_TRUSTZONE is not set + +# +# Platform +# +CONFIG_KERNEL_VADDR=0xc0000000 +# CONFIG_VIRT32 is not set +CONFIG_RPI4=y +# CONFIG_THREAD_ENV is not set +CONFIG_PROC_ENV=y + +# +# Kernel & CPU features +# +CONFIG_MAX_THREADS=32 +# CONFIG_SMP is not set +CONFIG_NR_CPUS=1 +CONFIG_HZ=100 +CONFIG_SCHED_FLIP_SCHEDFREQ=30 + +# +# SO3 Scheduling configuration +# +CONFIG_SCHED_RR=y +# CONFIG_SCHED_PRIO is not set +CONFIG_SCHED_FREQ_PREEMPTION=y + +# +# Drivers +# +CONFIG_UART=y +CONFIG_IO_MAPPING_BASE=0xe0000000 +# CONFIG_I2C is not set +# CONFIG_NET is not set +# CONFIG_FB is not set +# CONFIG_INPUT is not set +# CONFIG_NS16550 is not set +CONFIG_BCM283x_MU_UART=y +CONFIG_UART_LL_PADDR=0xfe215040 +# CONFIG_MMC is not set +CONFIG_RAMDEV=y +CONFIG_ARM_TIMER=y +CONFIG_GIC=y +CONFIG_GIC_V2=y + +# +# SO3 Applications +# +# CONFIG_APP_SAMPLE is not set +# CONFIG_APP_REFSO3 is not set + +# +# Filesystems +# +CONFIG_FS_FAT=y +# CONFIG_ROOTFS_NONE is not set +# CONFIG_ROOTFS_MMC is not set +CONFIG_ROOTFS_RAMDEV=y + +# +# IPC +# +CONFIG_IPC_SIGNAL=y +CONFIG_IPC_PIPE=y +CONFIG_HEAP_SIZE_MB=8 +CONFIG_SYS_STACK_SIZE_KB=64 +CONFIG_THREAD_STACK_SIZE_KB=64 +# CONFIG_RTOS is not set +# CONFIG_AVZ is not set +CONFIG_USER_INIT_PROGRAM="init.elf" +# CONFIG_LOG_LEVEL_CRITICAL is not set +# CONFIG_LOG_LEVEL_ERROR is not set +# CONFIG_LOG_LEVEL_WARNING is not set +CONFIG_LOG_LEVEL_INFO=y +# CONFIG_LOG_LEVEL_DEBUG is not set +# CONFIG_LOG_LEVEL_TRACE is not set +# CONFIG_LOG_LEVEL_NONE is not set +CONFIG_LOG_LEVEL=4 +# CONFIG_SOO is not set +CONFIG_MMU=y diff --git a/so3/so3/dts/Makefile b/so3/so3/dts/Makefile index 0173af01cf..28697617a9 100644 --- a/so3/so3/dts/Makefile +++ b/so3/so3/dts/Makefile @@ -1,4 +1,5 @@ +dtb-$(CONFIG_RPI4) += rpi4.dtb dtb-$(CONFIG_RPI4_64) += rpi4_64.dtb rpi4_64_avz.dtb rpi4_64_capsule.dtb dtb-$(CONFIG_VIRT64) += virt64.dtb virt64_avz.dtb virt64_capsule.dtb virt64_lvperf.dtb dtb-$(CONFIG_VIRT32) += virt32.dtb virt32_lvperf.dtb diff --git a/so3/so3/dts/rpi4.dts b/so3/so3/dts/rpi4.dts new file mode 100644 index 0000000000..6010aad84d --- /dev/null +++ b/so3/so3/dts/rpi4.dts @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2014-2026 REDS Institute, HEIG-VD, Yverdon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/dts-v1/; + +/ { + model = "SO3 RPi4 32-bit"; + compatible = "arm,rpi4"; + + /* + * Single address/size cell, unlike rpi4_64.dts: this is the 32-bit + * platform, so every reg below carries one address cell instead of two. + */ + #address-cells = <1>; + #size-cells = <1>; + + cpus { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + }; + + memory { + device_type = "memory"; + reg = <0x01000000 0x20000000>; /* 512 MB; base = ITS load 0x01008000 - 0x8000 text offset */ + }; + + mem { + compatible = "mem"; + status = "ok"; + }; + + /* GIC interrupt controller */ + gic:interrupt-controller@ff841000 { + compatible = "intc,gic"; + interrupt-controller; + #interrupt-cells = <3>; + + reg = <0xff841000 0x1000 + 0xff842000 0x1000>; + status = "ok"; + }; + + /* RPi4 miniuart NS16550 console */ + serial@fe215040 { + compatible = "serial,bcm283x-mu"; + reg = <0xfe215040 0x1000>; + interrupt-parent = <&gic>; + + /* + * AUX (mini UART) — SPI 93, the value Broadcom's + * bcm2711-rpi-4-b.dtb gives for /soc/serial@7e215040. + */ + interrupts = <0 93 4>; + status = "ok"; + }; + + /* I2C1 controller (Broadcom Serial Controller BSC1) */ + i2c1:i2c1@fe804000 { + compatible = "bcm,i2c_bsc"; + reg = <0xfe804000 0x400>; + status = "disabled"; + interrupt-parent = <&gic>; + + /* IRQ 53 of VC which start at SPI96 -> 96 + 53 = 149 */ + interrupts = <0 117 4>; + }; + + /* Periodic timer based on ARM CP15 timer */ + periodic-timer { + compatible = "arm,periodic-timer"; + interrupt-parent = <&gic>; + + /* IRQ 10 with VT support or 11 without */ + interrupts = <1 11 4>; + status = "ok"; + }; + + /* Clocksource free-running timer based on ARM CP15 timer */ + clocksource-timer { + compatible = "arm,clocksource-timer"; + status = "ok"; + }; + + rpisense { + compatible = "bcm,rpisense"; + interrupt-parent = <&gic>; + interrupts = <0 113 4>; + status = "disabled"; + }; + + /* + * Present only so U-Boot's RPi 4 bootm fixup can copy the + * firmware-corrected dma-ranges into this static DT (see u-boot + * boot/bootm.c, CONFIG_BCM2711). Silences the "Can't find emmc2bus in + * the DT stored in the ITB" warning. SO3 boots from ramfs and does not + * drive emmc2 itself, so the child controller node is intentionally + * omitted. The parent address in ranges/dma-ranges is a single cell + * here, matching this tree's #address-cells. + */ + emmc2bus { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + ranges = <0x0 0x7e000000 0xfe000000 0x01800000>; + dma-ranges = <0x0 0xc0000000 0x00000000 0x40000000>; + }; + +};