44Booting Linux on ZTE zx297520v3 SoCs
55====================================
66
7- ...............................................................................
8-
97Author: Stefan Dösinger
108
119Date : 27 Jan 2026
1210
13111. Hardware description
1412---------------------------
15- Zx297520v3 SoCs use a 64 bit capable Cortex-A53 CPU and GICv3, although they
13+ Zx297520v3 SoCs use a 64- bit capable Cortex-A53 CPU and GICv3, although they
1614run in arm32 mode only. The CPU has support EL3, but no hypervisor (EL2) and
1715it seems to lack VFP and NEON.
1816
@@ -27,7 +25,7 @@ Some devices, especially the stationary ones, have 100 mbit Ethernet and an
2725Ethernet switch.
2826
2927Usually the devices have LEDs for status indication, although some have SPI or
30- I2C connected displays
28+ I2C connected displays.
3129
3230Some have an SD card slot. If it exists, it is a better choice for the root
3331file system because it easily outperforms the built-in NAND.
@@ -39,7 +37,7 @@ IRQs on either ends.
3937
4038There is also a Cortex M0 CPU, which is responsible for early HW initialization
4139and starting the Cortex A53 CPU. It does not have any essential purpose once
42- U-Boot is started. A SRAM-Based handover protocol exists to run custom code on
40+ U-Boot is started. An SRAM-based handover protocol exists to run custom code on
4341this CPU.
4442
45432. Booting via USB
@@ -63,13 +61,13 @@ Contains an U-Boot version that can be used with the USB loader and sets up the
6361CPU and interrupt controller to comply with Linux's booting requirements.
6462
65633. Building for built-in U-Boot
66- ---------------------------
64+ -------------------------------
6765The devices come with an ancient U-Boot that loads legacy uImages from NAND and
6866boots them without a chance for the user to interrupt. The images are stored in
6967files ap_cpuap.bin and ap_recovery.bin on a jffs2 partition named imagefs,
7068usually mtd4. A file named "fotaflag" switches between the two modes.
7169
72- In addition to the uImage header, those files have a 384 byte signature header,
70+ In addition to the uImage header, those files have a 384- byte signature header,
7371which is used for authenticating the images on some devices. Most devices have
7472this authentication disabled and it is enough to pad the uImage files with 384
7573zero bytes.
@@ -88,7 +86,7 @@ So to build an image that boots from NAND the following steps are necessary:
88866) dd if=/dev/zero bs=1 count=384 of=ap_recovery.bin
89877) cat uimg >> ap_recovery.bin
90888) Place this file onto imagefs on the device. Delete ap_cpuap.bin if the
91- free space is not enough.
89+ free space is not enough.
92909) Create the file fotaflag: echo -n FOTA-RECOVERY > fotaflag
9391
9492For development, booting ap_recovery.bin is recommended because the normal boot
@@ -113,55 +111,56 @@ the binary blobs.
113111
114112The assembly code below is given as an example of how to achieve this:
115113
116- ```
117- #include <linux/irqchip/arm-gic-v3.h>
118- #include <asm/assembler.h>
119- #include <asm/cp15.h>
120-
121- @ Detect sane bootloaders and skip the hack
122- ldr r3, =0xf2000000
123- ldr r3, [r3]
124- ldr r4, =(GICD_CTLR_ARE_NS | GICD_CTLR_DS)
125- cmp r3, r4
126- beq skip_zx_hack
127- @ This allows EL1 to handle ints hat are normally handled by EL2/3.
128- ldr r3, =0xf2000000
129- str r4, [r3]
130-
131- cps #MON_MODE
132-
133- @ Work in non-secure physical address space: SCR_EL3.NS = 1. At least the UART
134- @ seems to respond only to non-secure addresses. I have taken insipiration from
135- @ Raspberry pi's armstub7.S here.
136- mov r3, #0x131 @ non-secure, Make F, A bits in CPSR writeable
137- @ Allow hypervisor call.
138- mcr p15, 0, r3, c1, c1, 0
139-
140- @ AP_PPI_MODE_REG: Configure timer PPIs (10, 11, 13, 14) to active-low.
141- ldr r3, =0xF22020a8
142- ldr r4, =0x50
143- str r4, [r3]
144- ldr r3, =0xF22020ac
145- ldr r4, =0x14
146- str r4, [r3]
147-
148- @ Enable EL2 access to ICC_SRE (bit 3, ICC_SRE_EL3.Enable). Enable system reg
149- @ access to GICv3 registers (bit 0, ICC_SRE_EL3.SRE) for EL1 and EL3.
150- mrc p15, 6, r3, c12, c12, 5 @ ICC_SRE_EL3
151- orr r3, #0x9 @ FIXME: No defines for SRE_EL3 values?
152- mcr p15, 6, r3, c12, c12, 5
153- mrc p15, 0, r3, c12, c12, 5 @ ICC_SRE_EL1
154- orr r3, #(ICC_SRE_EL1_SRE)
155- mcr p15, 0, r3, c12, c12, 5
156-
157- @ Like ICC_SRE_EL3, enable EL1 access to ICC_SRE and system register access
158- @ for EL2.
159- mrc p15, 4, r3, c12, c9, 5 @ ICC_SRE_EL2 aka ICC_HSRE
160- orr r3, r3, #(ICC_SRE_EL2_ENABLE | ICC_SRE_EL2_SRE)
161- mcr p15, 4, r3, c12, c9, 5
162- isb
163-
164- @ Back to SVC mode
165- cps #SVC_MODE
166- skip_zx_hack:
167- ```
114+ ::
115+
116+ #include <linux/irqchip/arm-gic-v3.h>
117+ #include <asm/assembler.h>
118+ #include <asm/cp15.h>
119+
120+ @ Detect sane bootloaders and skip the hack
121+ ldr r3, =0xf2000000
122+ ldr r3, [r3]
123+ ldr r4, =(GICD_CTLR_ARE_NS | GICD_CTLR_DS)
124+ cmp r3, r4
125+ beq skip_zx_hack
126+ @ This allows EL1 to handle ints hat are normally handled by EL2/3.
127+ ldr r3, =0xf2000000
128+ str r4, [r3]
129+
130+ cps #MON_MODE
131+
132+ @ Work in non-secure physical address space: SCR_EL3.NS = 1. At least the UART
133+ @ seems to respond only to non-secure addresses. I have taken insipiration from
134+ @ Raspberry pi's armstub7.S here.
135+ mov r3, #0x131 @ non-secure, Make F, A bits in CPSR writeable
136+ @ Allow hypervisor call.
137+ mcr p15, 0, r3, c1, c1, 0
138+
139+ @ AP_PPI_MODE_REG: Configure timer PPIs (10, 11, 13, 14) to active-low.
140+ ldr r3, =0xF22020a8
141+ ldr r4, =0x50
142+ str r4, [r3]
143+ ldr r3, =0xF22020ac
144+ ldr r4, =0x14
145+ str r4, [r3]
146+
147+ @ Enable EL2 access to ICC_SRE (bit 3, ICC_SRE_EL3.Enable). Enable system reg
148+ @ access to GICv3 registers (bit 0, ICC_SRE_EL3.SRE) for EL1 and EL3.
149+ mrc p15, 6, r3, c12, c12, 5 @ ICC_SRE_EL3
150+ orr r3, #0x9 @ FIXME: No defines for SRE_EL3 values?
151+ mcr p15, 6, r3, c12, c12, 5
152+ mrc p15, 0, r3, c12, c12, 5 @ ICC_SRE_EL1
153+ orr r3, #(ICC_SRE_EL1_SRE)
154+ mcr p15, 0, r3, c12, c12, 5
155+
156+ @ Like ICC_SRE_EL3, enable EL1 access to ICC_SRE and system register access
157+ @ for EL2.
158+ mrc p15, 4, r3, c12, c9, 5 @ ICC_SRE_EL2 aka ICC_HSRE
159+ orr r3, r3, #(ICC_SRE_EL2_ENABLE | ICC_SRE_EL2_SRE)
160+ mcr p15, 4, r3, c12, c9, 5
161+ isb
162+
163+ @ Back to SVC mode
164+ cps #SVC_MODE
165+ skip_zx_hack:
166+
0 commit comments