Skip to content
Merged
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
50 changes: 12 additions & 38 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,14 @@ git diff --diff-filter=M v2022.10 HEAD # the mainline files we patched
| SoC: PLL and DDR bring-up, timer, reset, DRAM size, SDHCI glue | `arch/arm/mach-xm/` (`ARCH_XM`; `TARGET_XM510`/`XM530`/`XM550`; register map in `include/mach/xm.h`) |
| Boards: `board_init`, `misc_init_r` → `openipc_helper()`, `board_eth_init` with the PHY reset / MAC glue | `board/xiongmai/{xm510,xm530}/`. XM550 uses the xm530 board with `XM_DDR3` |
| Memory map, console, timer | `include/configs/{xm510,xm530}.h`, each ending in `#include "openipc-common.h"` |
| SPI NAND on the v2 controller (XM530/550): raw NAND, full-ID table, on-die ECC status through `ecc.read_page` | `drivers/mtd/nand/raw/xmsfc_nand.c` (`NAND_XMSFC`) |
| SPI NOR controller, v1 (XM510) and v2 (XM530/550), non-DM | `drivers/mtd/spi/xmsfc.c`. It provides `spi_flash_probe()` and fills `mtd->_read/_write/_erase`, so mainline's non-DM `spi_flash_*()` wrappers, `sf` and env-in-SPI-flash work without the SPI and spi-nor layers |
| OpenIPC boot layer | `common/openipc.c` and `include/openipc.h` (copied from `openipc-hisilicon`, NAND gate rekeyed to `CONFIG_ENV_IS_IN_NAND`), `include/configs/openipc-common.h` (XM-only rewrite, same env commands) |
| OpenIPC boot layer | `common/openipc.c` and `include/openipc.h` (identical to `openipc-hisilicon`'s), `include/configs/openipc-common.h` (XM-only rewrite, same env commands) |
| Kconfig fragments and the build | `openipc/`, `build.sh` |

**Patched mainline files**, each small:

- `arch/arm/{Kconfig,Makefile}`: the `ARCH_XM` hook.
- `common/{Kconfig,Makefile}`: `OPENIPC`, `PRODUCT_SOC`, `PRODUCT_SOCMODEL`.
- `drivers/mtd/nand/raw/{Kconfig,Makefile}`: the `NAND_XMSFC` hook.
- `drivers/mtd/spi/{Kconfig,Makefile}`, `cmd/Kconfig` (`CMD_SF`) and
`env/Kconfig` (`ENV_IS_IN_SPI_FLASH`): accept `XMSFC_SPI_NOR`.
- `drivers/net/Kconfig`: `NETDEVICES` selects `DM_ETH` only when `DM` is on.
Expand Down Expand Up @@ -96,33 +94,11 @@ position-independent fixups. The only RAM before DDR is a 4 KiB SRAM at
driver restores it (`xmsfc_bus_mode()`) after every v2 operation, and only
ever runs after relocation, from DDR.

## SPI NAND (XM530/XM550): built on a guess
## No SPI NAND

Xiongmai never shipped a NAND U-Boot from this SDK. There is a
`CONFIG_SYS_USE_SPI_NAND` block in the vendor `xm530.h`, but no board target,
and nothing documents how the boot ROM starts from SPI NAND.

**What the NAND image assumes:**

- the controller's window serves the NAND page data linearly, as in NOR
bus-read mode;
- U-Boot is linked at 0x60001000 (the vendor's NAND `TEXT_BASE`), behind a
4 KiB header;
- the header's first word is `ldr pc, [pc, #-4]` followed by that address, so
it reaches U-Boot whether the ROM starts at the window or the 0x08000000
alias (`build.sh`).

**What it carries:**

- layout `768k(boot),256k(env),-(ubi)`;
- the environment at 0xc0000;
- the kernel at `/boot/uImage` inside the UBIFS `rootfs` volume;
- the same recovery as on `openipc-hisilicon` NAND.

Only qemu-hisilicon's NAND model, which implements the same guess, has run
it. The OpenIPC XM530 kernel has no SPI NAND driver either, so a NAND image
loads and starts the kernel, which then cannot mount its root. Treat NAND as
unverified on silicon, and say so wherever it is offered.
There are only NOR images. No XM530/XM550 board with SPI NAND has turned
up, and the OpenIPC XM530 kernel has no SPI NAND driver. `openipc.c`'s NAND
paths (`CONFIG_FMC_SPI_NAND`) are never built here.

## Build

Expand All @@ -131,10 +107,10 @@ bash build.sh # xm510 xm530 xm550; continues past failures, exits
bash build.sh xm530 # one or more SoCs (CROSS_COMPILE defaults to arm-linux-gnueabi-)
```

- Output: `output/u-boot-<soc>-nor.bin`, plus `-nand.bin` for xm530/xm550,
built out of tree in `output/build-<soc>-<nor|nand>/`.
- Output: `output/u-boot-<soc>-nor.bin`, built out of tree in
`output/build-<soc>-nor/`.
- `.config` is `openipc/openipc_config`, then `openipc/<soc>_config`, then
`openipc/nand_config` for NAND images, then `olddefconfig`. A later line
`olddefconfig`. A later line
wins. The "override" warnings are that layering.
- There are no `configs/*_defconfig` for these targets.
- The host toolchain must match CI (Ubuntu `gcc-arm-linux-gnueabi`). A Docker
Expand Down Expand Up @@ -162,12 +138,10 @@ with the reset vector at the window or alias, exactly as silicon does.
bootloaders leave it, with per-block locks on. `xmsfc_unprotect()` must clear
it before writes land.

- **NAND:** `-global xm-sfc.nand-file=<raw image>`, with no `flash-file`.
- The raw image is pages of 2048 + 64 bytes, U-Boot at page 0, and
`ubinize`'s output at 1 MiB.
- It must reach the prompt, save the env, mount the rootfs and start the
kernel.
- From an erased NAND, TFTP recovery must create the UBI volumes and boot.
- **SD recovery:** a FAT card (`-drive if=sd,file=<image>,format=raw`) with
`*.img` files: each valid uImage whose load address and size fit the flash
has its payload written there unless it is already on the flash; the
boot then goes on.

**What qemu does not check:** DDR training values, the v2 bus-read restore and
PHY/MDIO timing are acked instantly. A change to those needs a real board.
Expand Down
23 changes: 2 additions & 21 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,39 +31,20 @@ build_xm() {
builddir=${BOOT_SRCDIR}/output/build-${soc}-${kind}
make_opts="-C ${BOOT_SRCDIR} O=${builddir} -j$(nproc)"
fragments="openipc/openipc_config openipc/${soc}_config"
[ "${kind}" = nand ] && fragments="${fragments} openipc/nand_config"
Comment thread
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.

rm -rf "${builddir}"
mkconfig "${builddir}" ${fragments} && \
make ${make_opts} olddefconfig </dev/null >/dev/null && \
make ${make_opts} </dev/null || return 1

if [ "${kind}" = nor ]; then
cp "${builddir}/u-boot.bin" "output/u-boot-${soc}-nor.bin" || return 1
else
# SPI NAND: a 4 KiB header, then U-Boot linked at the window + 4 KiB
# (CONFIG_SYS_TEXT_BASE in nand_config). Nothing documents what the
# boot ROM expects here; the header's first word jumps to U-Boot
# wherever the ROM starts it (ldr pc, [pc, #-4] and the address).
text=$(sed -n 's/^CONFIG_SYS_TEXT_BASE=//p' "${builddir}/.config")
python3 - "${builddir}/u-boot.bin" "output/u-boot-${soc}-nand.bin" \
"${text}" <<'PY' || return 1
import struct, sys
src, dst, text = sys.argv[1], sys.argv[2], int(sys.argv[3], 0)
hdr = bytearray(b'\xff' * 0x1000)
hdr[0:8] = struct.pack('<II', 0xe51ff004, text)
open(dst, 'wb').write(bytes(hdr) + open(src, 'rb').read())
PY
fi
cp "${builddir}/u-boot.bin" "output/u-boot-${soc}-nor.bin"
}

build_soc() {
soc=$1
case "${soc}" in
xm510)
xm510|xm530|xm550)
build_xm "${soc}" nor ;;
xm530|xm550)
build_xm "${soc}" nor && build_xm "${soc}" nand ;;
*)
echo "unsupported SoC: ${soc}" >&2
return 1 ;;
Expand Down
Loading
Loading