Add X96Q LPDDR3 v1.3 custom U-Boot build and eMMC flash tooling.
Armbian-compatible U-Boot v2025.01 with eMMC, DTB, and flash fixes for the X96Q TV box. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
# build artifacts
|
||||||
|
.build/
|
||||||
|
.venv/
|
||||||
|
output/u-boot-custom.bin
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
# X96Q LPDDR3 v1.3 — кастомный U-Boot
|
||||||
|
|
||||||
|
Кастомная сборка U-Boot для **X96Q TV Box LPDDR3 v1.3** (Allwinner H616/H313, 1 GiB LPDDR3, AXP313A, eMMC boot).
|
||||||
|
|
||||||
|
Проверено: UART 115200, загрузка Armbian с eMMC, `DRAM: 1 GiB`.
|
||||||
|
|
||||||
|
## Структура репозитория
|
||||||
|
|
||||||
|
```
|
||||||
|
x96q-uboot/
|
||||||
|
├── README.md
|
||||||
|
├── build.sh # сборка (macOS + Homebrew)
|
||||||
|
├── patches/
|
||||||
|
│ ├── jernejsk-emmc.patch # фикс eMMC на H616
|
||||||
|
│ ├── easter-egg.patch # баннер в SPL + Kconfig
|
||||||
|
│ └── fdtfile-armbian.patch # совместимость DTB с Armbian
|
||||||
|
├── overlays/
|
||||||
|
│ ├── configs/x96_q_lpddr3_v1.3_defconfig
|
||||||
|
│ └── dts/sun50i-h313-x96q-lpddr3-v1.3.dts
|
||||||
|
├── output/
|
||||||
|
│ └── u-boot-custom.bin # артефакт сборки (gitignore)
|
||||||
|
└── scripts/
|
||||||
|
├── flash-emmc.sh # образ + U-Boot на eMMC
|
||||||
|
└── flash-uboot-only.sh # только U-Boot поверх существующего образа
|
||||||
|
```
|
||||||
|
|
||||||
|
## Что было сломано и как чинили
|
||||||
|
|
||||||
|
### 1. Неправильный defconfig (DDR3 вместо LPDDR3)
|
||||||
|
|
||||||
|
**Симптом:** `DRAM: not supported` в UART.
|
||||||
|
|
||||||
|
**Причина:** generic `x96q_defconfig` настроен на DDR3, а плата — **LPDDR3 v1.3** с другими таймингами и AXP313.
|
||||||
|
|
||||||
|
**Фикс:** defconfig `x96_q_lpddr3_v1.3_defconfig` из Armbian/NickAlilovic + DTS `sun50i-h313-x96q-lpddr3-v1.3.dts`.
|
||||||
|
|
||||||
|
### 2. eMMC read error в SPL
|
||||||
|
|
||||||
|
**Симптом:** SPL не читает eMMC, BootROM зацикливается или грузит битый bootloader.
|
||||||
|
|
||||||
|
**Причина:** на H616 контроллеру MMC нужен hardware reset карты и FIFO threshold (патч Jernej Skrabec, upstream U-Boot).
|
||||||
|
|
||||||
|
**Фикс:** `patches/jernejsk-emmc.patch` — backport на **v2025.01**.
|
||||||
|
|
||||||
|
### 3. Несовпадение имени DTB (главный баг загрузки)
|
||||||
|
|
||||||
|
**Симптом:**
|
||||||
|
```
|
||||||
|
The file allwinner/sun50i-h313-x96q-lpddr3-v1.3.dtb was not found
|
||||||
|
ERROR: Did not find a cmdline Flattened Device Tree
|
||||||
|
```
|
||||||
|
|
||||||
|
**Причина:** U-Boot из SPL выставляет `fdtfile` по имени **своего** device tree (`…-lpddr3-v1.3.dtb`). Armbian в `/boot/dtb/allwinner/` кладёт только `sun50i-h313-x96q-lpddr3.dtb` (без суффикса v1.3). Ядро и initrd грузятся, DTB — нет.
|
||||||
|
|
||||||
|
**Фикс (три уровня):**
|
||||||
|
1. **Патч U-Boot** `fdtfile-armbian.patch` — в `misc_init_r()` подменяет `fdtfile` на Armbian-имя.
|
||||||
|
2. **`flash-emmc.sh`** — после прошивки пишет `fdtfile=sun50i-h313-x96q-lpddr3.dtb` в `armbianEnv.txt` и создаёт symlink `…-v1.3.dtb`.
|
||||||
|
3. Вручную на работающей системе — то же в `/boot/armbianEnv.txt`.
|
||||||
|
|
||||||
|
> U-Boot DT (`v1.3`) и kernel DT (`lpddr3`) — **разные файлы с разным назначением**. SPL использует свой DTS для DRAM/PMIC; ядро — DTB из образа Armbian.
|
||||||
|
|
||||||
|
### 4. `dd: Operation not permitted` на boot0/boot1
|
||||||
|
|
||||||
|
**Симптом:** запись в user area проходит, в `mmcblk2boot0` — отказ.
|
||||||
|
|
||||||
|
**Причина:** boot-разделы eMMC по умолчанию read-only (`force_ro=1`).
|
||||||
|
|
||||||
|
**Фикс:** перед `dd`:
|
||||||
|
```bash
|
||||||
|
echo 0 > /sys/block/mmcblk2boot0/force_ro
|
||||||
|
echo 0 > /sys/block/mmcblk2boot1/force_ro
|
||||||
|
```
|
||||||
|
Скрипт `flash-emmc.sh` делает это автоматически.
|
||||||
|
|
||||||
|
### 5. `Card did not respond to voltage select! : -110` на mmc0
|
||||||
|
|
||||||
|
**Симптом:** при фолбэке boot.scr пытается mmc0 и падает.
|
||||||
|
|
||||||
|
**Причина:** в U-Boot mmc0 — SD-слот, при определённых условиях voltage select не проходит; это **не блокер**, если DTB найден на правильном mmc (SD = mmc1 в нашем случае).
|
||||||
|
|
||||||
|
## Карта MMC
|
||||||
|
|
||||||
|
| Где | Устройство | Назначение |
|
||||||
|
|-----|------------|------------|
|
||||||
|
| Linux | `mmcblk0` | SD-карта |
|
||||||
|
| Linux | `mmcblk2` | eMMC (user area) |
|
||||||
|
| Linux | `mmcblk2boot0/1` | eMMC boot partitions (по 2 MiB) |
|
||||||
|
| U-Boot shell | `mmc dev 1` | eMMC |
|
||||||
|
| U-Boot shell | `mmc dev 2` | то же eMMC (другой индекс) |
|
||||||
|
| U-Boot autoboot | `mmc1` | откуда грузится boot.scr (SD при вставленной карте) |
|
||||||
|
|
||||||
|
SPL/U-Boot пишется в **три места**:
|
||||||
|
- user area @ **8 KiB** (`dd seek=8`) — legacy sunxi offset
|
||||||
|
- **boot0** — основная boot-область eMMC
|
||||||
|
- **boot1** — зеркало (резерв)
|
||||||
|
|
||||||
|
## Сборка
|
||||||
|
|
||||||
|
### Требования (macOS)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install aarch64-elf-gcc gnu-sed openssl@3 swig python3
|
||||||
|
```
|
||||||
|
|
||||||
|
### Команда
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Скрипт:
|
||||||
|
1. Клонирует U-Boot `v2025.01` и ARM TF-A в `.build/`
|
||||||
|
2. Накатывает патчи из `patches/`
|
||||||
|
3. Копирует defconfig и DTS из `overlays/`
|
||||||
|
4. Собирает BL31 + U-Boot
|
||||||
|
5. Кладёт бинарник в `output/u-boot-custom.bin` (~822 KiB)
|
||||||
|
|
||||||
|
### Проверка артефакта
|
||||||
|
|
||||||
|
```bash
|
||||||
|
strings output/u-boot-custom.bin | grep -E 'binary build|2025.01|lpddr3'
|
||||||
|
```
|
||||||
|
|
||||||
|
Ожидаемо:
|
||||||
|
- `*** binary build ***`
|
||||||
|
- `U-Boot SPL 2025.01-dirty`
|
||||||
|
- `sun50i-h313-x96q-lpddr3.dtb` (fdtfile для Armbian)
|
||||||
|
|
||||||
|
## Прошивка eMMC
|
||||||
|
|
||||||
|
### Полная (образ Armbian + U-Boot)
|
||||||
|
|
||||||
|
На приставке (под root, лучше загрузившись с SD):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# скопировать на приставку:
|
||||||
|
# output/u-boot-custom.bin
|
||||||
|
# scripts/flash-emmc.sh
|
||||||
|
# Armbian_*.img.xz
|
||||||
|
|
||||||
|
cd /home/binary # или куда положили файлы
|
||||||
|
sudo ./flash-emmc.sh
|
||||||
|
# или явно:
|
||||||
|
sudo ./flash-emmc.sh Armbian_community_26.2.0-trunk.904_X96q_trixie_current_6.18.29_minimal.img.xz
|
||||||
|
```
|
||||||
|
|
||||||
|
Скрипт:
|
||||||
|
1. `xz -dc образ | dd of=/dev/mmcblk2` — запись образа локально (не через SSH pipe)
|
||||||
|
2. U-Boot → user @ 8 KiB
|
||||||
|
3. Разблокировка boot0/boot1
|
||||||
|
4. U-Boot → boot0 + boot1
|
||||||
|
5. Правка `armbianEnv.txt` + symlink DTB
|
||||||
|
|
||||||
|
После прошивки: **вынуть SD**, перезагрузка.
|
||||||
|
|
||||||
|
### Только U-Boot (образ уже на eMMC)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./flash-uboot-only.sh /path/to/u-boot-custom.bin
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ожидаемый UART при успешной загрузке
|
||||||
|
|
||||||
|
```
|
||||||
|
*** binary build ***
|
||||||
|
U-Boot 2025.01-dirty (...) binary build
|
||||||
|
CPU: Allwinner H616 (SUN50I)
|
||||||
|
Model: hechuang,x96-q LPDDR3 v1.3
|
||||||
|
DRAM: 1 GiB
|
||||||
|
...
|
||||||
|
U-boot loaded from eMMC
|
||||||
|
Load fdt: /boot/dtb/allwinner/sun50i-h313-x96q-lpddr3.dtb
|
||||||
|
```
|
||||||
|
|
||||||
|
## Патчи
|
||||||
|
|
||||||
|
| Патч | Зачем |
|
||||||
|
|------|-------|
|
||||||
|
| `jernejsk-emmc.patch` | reset eMMC + FIFO threshold на H616 |
|
||||||
|
| `easter-egg.patch` | `CONFIG_X96Q_BINARY_BUILD` — маркер в SPL, идентификация сборки |
|
||||||
|
| `fdtfile-armbian.patch` | `fdtfile` → имя DTB из Armbian, иначе boot.scr не находит дерево |
|
||||||
|
|
||||||
|
## Восстановление (FEL)
|
||||||
|
|
||||||
|
Если eMMC bootloader битый и SD не помогает:
|
||||||
|
|
||||||
|
1. Зажать кнопку **FEL**, подключить USB (`1f3a:efe8`)
|
||||||
|
2. FEL + sunxi-tools: wipe boot0/boot1/SPL или прошить свежий `u-boot-custom.bin`
|
||||||
|
|
||||||
|
Подробности — в родительском репозитории FEL (`fel-recover.sh`, `fel-wipe-emmc.sh`).
|
||||||
|
|
||||||
|
## Версии
|
||||||
|
|
||||||
|
| Компонент | Версия |
|
||||||
|
|-----------|--------|
|
||||||
|
| U-Boot base | `v2025.01` |
|
||||||
|
| ARM TF-A BL31 | sun50i_h616 |
|
||||||
|
| Defconfig | Armbian `x96_q_lpddr3_v1.3` |
|
||||||
|
| Плата | X96Q LPDDR3 **v1.3** (не путать с DDR3 и не-LPDDR3 ревизиями) |
|
||||||
|
|
||||||
|
## Лицензия
|
||||||
|
|
||||||
|
Патчи и overlay — поверх GPL-2.0+ U-Boot. DTS: GPL-2.0+ OR MIT (см. заголовок файла).
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Сборка U-Boot для X96Q LPDDR3 v1.3 (Allwinner H616)
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
UBOOT_DIR="$ROOT/.build/u-boot"
|
||||||
|
ATF_DIR="$ROOT/.build/arm-trusted-firmware"
|
||||||
|
PATCH_DIR="$ROOT/patches"
|
||||||
|
OVERLAY_DIR="$ROOT/overlays"
|
||||||
|
CROSS_BIN="$ROOT/.build/cross-bin"
|
||||||
|
OUT_DIR="$ROOT/output"
|
||||||
|
CROSS_COMPILE=aarch64-elf-
|
||||||
|
UBOOT_TAG=v2025.01
|
||||||
|
DEFCONFIG=x96_q_lpddr3_v1.3_defconfig
|
||||||
|
BL31="$ATF_DIR/build/sun50i_h616/debug/bl31.bin"
|
||||||
|
OUTPUT="$UBOOT_DIR/u-boot-sunxi-with-spl.bin"
|
||||||
|
NCPU="$(sysctl -n hw.ncpu 2>/dev/null || nproc 2>/dev/null || echo 4)"
|
||||||
|
|
||||||
|
export PATH="$CROSS_BIN:/opt/homebrew/opt/gnu-sed/libexec/gnubin:/opt/homebrew/bin:$PATH"
|
||||||
|
|
||||||
|
need_cmd() {
|
||||||
|
command -v "$1" >/dev/null 2>&1 || { echo "Missing: $1" >&2; exit 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_venv() {
|
||||||
|
if [[ ! -x "$ROOT/.venv/bin/python3" ]]; then
|
||||||
|
python3 -m venv "$ROOT/.venv"
|
||||||
|
"$ROOT/.venv/bin/pip" install -q 'setuptools==69.5.1'
|
||||||
|
fi
|
||||||
|
export PATH="$ROOT/.venv/bin:$PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_cross_shims() {
|
||||||
|
mkdir -p "$CROSS_BIN"
|
||||||
|
for t in objcopy ar ranlib ld nm strip; do
|
||||||
|
ln -sf "/opt/homebrew/bin/${CROSS_COMPILE}${t}" "$CROSS_BIN/$t"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
clone_repos() {
|
||||||
|
mkdir -p "$ROOT/.build"
|
||||||
|
if [[ ! -d "$UBOOT_DIR/.git" ]]; then
|
||||||
|
git clone --filter=blob:none --tags https://github.com/u-boot/u-boot.git "$UBOOT_DIR"
|
||||||
|
fi
|
||||||
|
if [[ ! -d "$ATF_DIR/.git" ]]; then
|
||||||
|
git clone --depth=1 https://github.com/ARM-software/arm-trusted-firmware.git "$ATF_DIR"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_uboot_tree() {
|
||||||
|
local patch applied=0
|
||||||
|
(
|
||||||
|
cd "$UBOOT_DIR"
|
||||||
|
git fetch --depth 1 origin tag "$UBOOT_TAG" 2>/dev/null || true
|
||||||
|
git checkout -f "$UBOOT_TAG"
|
||||||
|
git clean -fdx
|
||||||
|
)
|
||||||
|
for patch in \
|
||||||
|
"$PATCH_DIR"/jernejsk-emmc.patch \
|
||||||
|
"$PATCH_DIR"/easter-egg.patch \
|
||||||
|
"$PATCH_DIR"/fdtfile-armbian.patch; do
|
||||||
|
[[ -f "$patch" ]] || continue
|
||||||
|
if (cd "$UBOOT_DIR" && git apply --check "$patch" 2>/dev/null); then
|
||||||
|
(cd "$UBOOT_DIR" && git apply "$patch")
|
||||||
|
applied=$((applied + 1))
|
||||||
|
elif (cd "$UBOOT_DIR" && git apply --reverse --check "$patch" 2>/dev/null); then
|
||||||
|
echo "Already applied: $(basename "$patch")"
|
||||||
|
else
|
||||||
|
echo "Failed to apply: $patch" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
mkdir -p "$UBOOT_DIR/configs" \
|
||||||
|
"$UBOOT_DIR/dts/upstream/src/arm64/allwinner"
|
||||||
|
cp -f "$OVERLAY_DIR/configs/$DEFCONFIG" \
|
||||||
|
"$UBOOT_DIR/configs/$DEFCONFIG"
|
||||||
|
cp -f "$OVERLAY_DIR/dts/sun50i-h313-x96q-lpddr3-v1.3.dts" \
|
||||||
|
"$UBOOT_DIR/dts/upstream/src/arm64/allwinner/sun50i-h313-x96q-lpddr3-v1.3.dts"
|
||||||
|
echo "U-Boot $UBOOT_TAG + $applied patches + overlay"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_bl31() {
|
||||||
|
(
|
||||||
|
cd "$ATF_DIR"
|
||||||
|
gmake CROSS_COMPILE="$CROSS_COMPILE" AR="${CROSS_COMPILE}ar" RANLIB="${CROSS_COMPILE}ranlib" \
|
||||||
|
PLAT=sun50i_h616 DEBUG=1 bl31
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
build_uboot() {
|
||||||
|
local openssl_prefix py_ldflags py_cflags
|
||||||
|
openssl_prefix="$(brew --prefix openssl@3)"
|
||||||
|
py_ldflags="$(python3-config --ldflags --embed 2>/dev/null || python3-config --ldflags)"
|
||||||
|
py_cflags="$(python3-config --includes)"
|
||||||
|
(
|
||||||
|
cd "$UBOOT_DIR"
|
||||||
|
export PATH="$ROOT/.venv/bin:$PATH"
|
||||||
|
gmake CROSS_COMPILE="$CROSS_COMPILE" BL31="$BL31" "$DEFCONFIG"
|
||||||
|
gmake CROSS_COMPILE="$CROSS_COMPILE" BL31="$BL31" \
|
||||||
|
BINMAN_ALLOW_MISSING=1 \
|
||||||
|
HOSTCFLAGS="$py_cflags -I$openssl_prefix/include" \
|
||||||
|
HOSTLDFLAGS="$py_ldflags -L$openssl_prefix/lib -lcrypto" \
|
||||||
|
-j"$NCPU"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
need_cmd git
|
||||||
|
need_cmd gmake
|
||||||
|
need_cmd "${CROSS_COMPILE}gcc"
|
||||||
|
need_cmd python3
|
||||||
|
need_cmd swig
|
||||||
|
need_cmd brew
|
||||||
|
|
||||||
|
setup_cross_shims
|
||||||
|
setup_venv
|
||||||
|
clone_repos
|
||||||
|
prepare_uboot_tree
|
||||||
|
build_bl31
|
||||||
|
build_uboot
|
||||||
|
|
||||||
|
mkdir -p "$OUT_DIR"
|
||||||
|
cp -f "$OUTPUT" "$OUT_DIR/u-boot-custom.bin"
|
||||||
|
echo "U-Boot: $(git -C "$UBOOT_DIR" describe --tags --always)"
|
||||||
|
echo "Output: $OUT_DIR/u-boot-custom.bin"
|
||||||
|
ls -la "$OUT_DIR/u-boot-custom.bin"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# Armbian/NickAlilovic x96_q_lpddr3_v1.3 — проверенный LPDDR3 конфиг
|
||||||
|
CONFIG_ARM=y
|
||||||
|
CONFIG_ARCH_SUNXI=y
|
||||||
|
CONFIG_DEFAULT_DEVICE_TREE="allwinner/sun50i-h313-x96q-lpddr3-v1.3"
|
||||||
|
CONFIG_SPL=y
|
||||||
|
CONFIG_SUNXI_DRAM_H616_LPDDR3=y
|
||||||
|
CONFIG_DRAM_CLK=600
|
||||||
|
CONFIG_DRAM_SUN50I_H616_DX_ODT=0x06060606
|
||||||
|
CONFIG_DRAM_SUN50I_H616_DX_DRI=0x0d0d0d0d
|
||||||
|
CONFIG_DRAM_SUN50I_H616_CA_DRI=0x00000d0d
|
||||||
|
CONFIG_DRAM_SUN50I_H616_ODT_EN=0x00000001
|
||||||
|
CONFIG_DRAM_SUN50I_H616_TPR0=0x0
|
||||||
|
CONFIG_DRAM_SUN50I_H616_TPR2=0x00000000
|
||||||
|
CONFIG_DRAM_SUN50I_H616_TPR10=0x002f3359
|
||||||
|
CONFIG_DRAM_SUN50I_H616_TPR11=0xaa889967
|
||||||
|
CONFIG_DRAM_SUN50I_H616_TPR12=0xeeee8979
|
||||||
|
CONFIG_MACH_SUN50I_H616=y
|
||||||
|
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
|
||||||
|
CONFIG_R_I2C_ENABLE=y
|
||||||
|
CONFIG_SPL_I2C=y
|
||||||
|
CONFIG_SPL_I2C_SUPPORT=y
|
||||||
|
CONFIG_SPL_SYS_I2C_LEGACY=y
|
||||||
|
CONFIG_SYS_I2C_MVTWSI=y
|
||||||
|
CONFIG_SYS_I2C_SLAVE=0x7f
|
||||||
|
CONFIG_SYS_I2C_SPEED=100000
|
||||||
|
CONFIG_SYS_MONITOR_LEN=786432
|
||||||
|
CONFIG_PHY_REALTEK=y
|
||||||
|
CONFIG_SUN8I_EMAC=y
|
||||||
|
CONFIG_I2C3_ENABLE=y
|
||||||
|
CONFIG_AXP313_POWER=y
|
||||||
|
CONFIG_AXP_DCDC3_VOLT=1200
|
||||||
|
CONFIG_USB_EHCI_HCD=y
|
||||||
|
CONFIG_USB_OHCI_HCD=y
|
||||||
|
CONFIG_USB_MUSB_GADGET=y
|
||||||
|
CONFIG_SUPPORT_EMMC_BOOT=y
|
||||||
|
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x40
|
||||||
|
# custom additions
|
||||||
|
CONFIG_X96Q_BINARY_BUILD=y
|
||||||
|
CONFIG_IDENT_STRING=" binary build"
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||||
|
/*
|
||||||
|
* Author: piotr.oniszczuk@gmail.com
|
||||||
|
* X96Q LPDDR3 v1.3 board
|
||||||
|
*/
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
#include "sun50i-h616.dtsi"
|
||||||
|
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
#include <dt-bindings/leds/common.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
model = "hechuang,x96-q LPDDR3 v1.3";
|
||||||
|
compatible = "hechuang,x96-q", "allwinner,sun50i-h616";
|
||||||
|
|
||||||
|
aliases {
|
||||||
|
mmc0 = &mmc0;
|
||||||
|
mmc1 = &mmc1;
|
||||||
|
mmc2 = &mmc2;
|
||||||
|
ethernet1 = &wlan;
|
||||||
|
serial0 = &uart0;
|
||||||
|
};
|
||||||
|
|
||||||
|
chosen {
|
||||||
|
stdout-path = "serial0:115200n8";
|
||||||
|
};
|
||||||
|
|
||||||
|
leds {
|
||||||
|
compatible = "gpio-leds";
|
||||||
|
|
||||||
|
led-red {
|
||||||
|
function = LED_FUNCTION_DISK_ACTIVITY;
|
||||||
|
color = <LED_COLOR_ID_RED>;
|
||||||
|
gpios = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */
|
||||||
|
linux,default-trigger = "mmc0";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
reg_vcc5v: vcc5v {
|
||||||
|
compatible = "regulator-fixed";
|
||||||
|
regulator-name = "vcc-5v";
|
||||||
|
regulator-min-microvolt = <5000000>;
|
||||||
|
regulator-max-microvolt = <5000000>;
|
||||||
|
regulator-always-on;
|
||||||
|
};
|
||||||
|
|
||||||
|
reg_vcc_wifi: reg_vcc_wifi {
|
||||||
|
compatible = "regulator-fixed";
|
||||||
|
regulator-name = "vcc-wifi";
|
||||||
|
regulator-min-microvolt = <3300000>;
|
||||||
|
regulator-max-microvolt = <3300000>;
|
||||||
|
gpio = <&pio 6 18 GPIO_ACTIVE_HIGH>; /* PG18 WL_REG_ON */
|
||||||
|
regulator-always-on;
|
||||||
|
enable-active-high;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
wifi_pwrseq: wifi_pwrseq {
|
||||||
|
compatible = "mmc-pwrseq-simple";
|
||||||
|
clocks = <&rtc CLK_OSC32K_FANOUT>;
|
||||||
|
clock-names = "ext_clock";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cpu0 {
|
||||||
|
cpu-supply = <®_dcdc2>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cpu1 {
|
||||||
|
cpu-supply = <®_dcdc2>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cpu2 {
|
||||||
|
cpu-supply = <®_dcdc2>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cpu3 {
|
||||||
|
cpu-supply = <®_dcdc2>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&mmc0 {
|
||||||
|
vmmc-supply = <®_dldo2>;
|
||||||
|
broken-cd;
|
||||||
|
bus-width = <4>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&mmc1 {
|
||||||
|
vmmc-supply = <®_dldo2>;
|
||||||
|
vqmmc-supply = <®_vcc_wifi>;
|
||||||
|
mmc-pwrseq = <&wifi_pwrseq>;
|
||||||
|
bus-width = <4>;
|
||||||
|
non-removable;
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
wlan: wifi@1 {
|
||||||
|
reg = <1>;
|
||||||
|
interrupt-parent = <&pio>;
|
||||||
|
interrupts = <6 15 IRQ_TYPE_EDGE_RISING>; /* PG15 WL_HOSTWAKE */
|
||||||
|
interrupt-names = "host-wake";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&mmc2 {
|
||||||
|
vmmc-supply = <®_dldo2>;
|
||||||
|
bus-width = <8>;
|
||||||
|
non-removable;
|
||||||
|
cap-mmc-hw-reset;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&r_i2c {
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
axp313a: pmic@36 {
|
||||||
|
compatible = "x-powers,axp313a";
|
||||||
|
reg = <0x36>;
|
||||||
|
wakeup-source;
|
||||||
|
|
||||||
|
regulators {
|
||||||
|
reg_dcdc1: dcdc1 {
|
||||||
|
regulator-always-on;
|
||||||
|
regulator-min-microvolt = <1160000>;
|
||||||
|
regulator-max-microvolt = <1160000>;
|
||||||
|
regulator-name = "vdd-cpu";
|
||||||
|
};
|
||||||
|
|
||||||
|
reg_dcdc2: dcdc2 {
|
||||||
|
regulator-always-on;
|
||||||
|
regulator-min-microvolt = <1160000>;
|
||||||
|
regulator-max-microvolt = <1160000>;
|
||||||
|
regulator-name = "vdd-gpu-sys";
|
||||||
|
};
|
||||||
|
|
||||||
|
reg_dcdc3: dcdc3 {
|
||||||
|
regulator-always-on;
|
||||||
|
regulator-min-microvolt = <1200000>;
|
||||||
|
regulator-max-microvolt = <1200000>;
|
||||||
|
regulator-name = "vdd-dram";
|
||||||
|
};
|
||||||
|
|
||||||
|
reg_aldo1: ldo1 {
|
||||||
|
regulator-always-on;
|
||||||
|
regulator-min-microvolt = <1800000>;
|
||||||
|
regulator-max-microvolt = <1800000>;
|
||||||
|
regulator-name = "vcc-sys";
|
||||||
|
};
|
||||||
|
|
||||||
|
reg_dldo2: ldo2 {
|
||||||
|
regulator-always-on;
|
||||||
|
regulator-min-microvolt = <3300000>;
|
||||||
|
regulator-max-microvolt = <3300000>;
|
||||||
|
regulator-name = "vcc3v3-ext";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&uart0 {
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&uart0_ph_pins>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
|
||||||
|
index 8065161e6..b92c0402c 100644
|
||||||
|
--- a/arch/arm/mach-sunxi/Kconfig
|
||||||
|
+++ b/arch/arm/mach-sunxi/Kconfig
|
||||||
|
@@ -1130,6 +1130,12 @@ config BLUETOOTH_DT_DEVICE_FIXUP
|
||||||
|
The used address is "bdaddr" if set, and "ethaddr" with the LSB
|
||||||
|
flipped elsewise.
|
||||||
|
|
||||||
|
+config X96Q_BINARY_BUILD
|
||||||
|
+ bool "Print 'binary build' easter egg on UART in SPL"
|
||||||
|
+ default n
|
||||||
|
+ help
|
||||||
|
+ Print a short banner on the serial console early in SPL boot.
|
||||||
|
+
|
||||||
|
source "board/sunxi/Kconfig"
|
||||||
|
|
||||||
|
endif
|
||||||
|
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
|
||||||
|
index 701899ee4..7b6e9ee9c 100644
|
||||||
|
--- a/arch/arm/mach-sunxi/board.c
|
||||||
|
+++ b/arch/arm/mach-sunxi/board.c
|
||||||
|
@@ -470,6 +470,9 @@ void board_init_f(ulong dummy)
|
||||||
|
|
||||||
|
spl_init();
|
||||||
|
preloader_console_init();
|
||||||
|
+#ifdef CONFIG_X96Q_BINARY_BUILD
|
||||||
|
+ puts("*** binary build ***\n");
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(I2C) && CONFIG_IS_ENABLED(SYS_I2C_LEGACY)
|
||||||
|
/* Needed early by sunxi_board_init if PMU is enabled */
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
|
||||||
|
--- a/board/sunxi/board.c
|
||||||
|
+++ b/board/sunxi/board.c
|
||||||
|
@@ -826,6 +826,10 @@ int misc_init_r(void)
|
||||||
|
char *prefix = IS_ENABLED(CONFIG_ARM64) ? "allwinner/" : "";
|
||||||
|
char str[64];
|
||||||
|
|
||||||
|
snprintf(str, sizeof(str), "%s%s.dtb", prefix, spl_dt_name);
|
||||||
|
+#ifdef CONFIG_X96Q_BINARY_BUILD
|
||||||
|
+ /* Armbian ships sun50i-h313-x96q-lpddr3.dtb, not the v1.3 suffix */
|
||||||
|
+ snprintf(str, sizeof(str), "%ssun50i-h313-x96q-lpddr3.dtb", prefix);
|
||||||
|
+#endif
|
||||||
|
env_set("fdtfile", str);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
commit 3e78f8f407a0a0e7b50aa7eaa6f2f579f35e9837
|
||||||
|
Author: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
Date: Sun Mar 9 07:12:41 2025 +0100
|
||||||
|
|
||||||
|
sunxi: mmc: Improve reset procedure
|
||||||
|
|
||||||
|
Cards should always be reset and threshold set. This fixes eMMC on H616.
|
||||||
|
|
||||||
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||||
|
[Andre: use macro-defined offsets to fix build on older SoCs]
|
||||||
|
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
|
||||||
|
|
||||||
|
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
|
||||||
|
index 8f72d758e..951e6acd3 100644
|
||||||
|
--- a/drivers/mmc/sunxi_mmc.c
|
||||||
|
+++ b/drivers/mmc/sunxi_mmc.c
|
||||||
|
@@ -449,6 +449,26 @@ out:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void sunxi_mmc_reset(void *regs)
|
||||||
|
+{
|
||||||
|
+ /* Reset controller */
|
||||||
|
+ writel(SUNXI_MMC_GCTRL_RESET, regs + SUNXI_MMC_GCTRL);
|
||||||
|
+ udelay(1000);
|
||||||
|
+
|
||||||
|
+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
|
||||||
|
+ /* Reset card */
|
||||||
|
+ writel(SUNXI_MMC_HWRST_ASSERT, regs + SUNXI_MMC_HWRST);
|
||||||
|
+ udelay(10);
|
||||||
|
+ writel(SUNXI_MMC_HWRST_DEASSERT, regs + SUNXI_MMC_HWRST);
|
||||||
|
+ udelay(300);
|
||||||
|
+
|
||||||
|
+ /* Setup FIFO R/W threshold. Needed on H616. */
|
||||||
|
+ writel(SUNXI_MMC_THLDC_READ_THLD(512) |
|
||||||
|
+ SUNXI_MMC_THLDC_WRITE_EN |
|
||||||
|
+ SUNXI_MMC_THLDC_READ_EN, regs + SUNXI_MMC_THLDC);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* non-DM code here is used by the (ARM) SPL only */
|
||||||
|
|
||||||
|
#if !CONFIG_IS_ENABLED(DM_MMC)
|
||||||
|
@@ -496,9 +516,7 @@ static int sunxi_mmc_core_init(struct mmc *mmc)
|
||||||
|
{
|
||||||
|
struct sunxi_mmc_priv *priv = mmc->priv;
|
||||||
|
|
||||||
|
- /* Reset controller */
|
||||||
|
- writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
|
||||||
|
- udelay(1000);
|
||||||
|
+ sunxi_mmc_reset(priv->reg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -691,9 +709,7 @@ static int sunxi_mmc_probe(struct udevice *dev)
|
||||||
|
|
||||||
|
upriv->mmc = &plat->mmc;
|
||||||
|
|
||||||
|
- /* Reset controller */
|
||||||
|
- writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
|
||||||
|
- udelay(1000);
|
||||||
|
+ sunxi_mmc_reset(priv->reg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff --git a/drivers/mmc/sunxi_mmc.h b/drivers/mmc/sunxi_mmc.h
|
||||||
|
index f4ae5a790..718651603 100644
|
||||||
|
--- a/drivers/mmc/sunxi_mmc.h
|
||||||
|
+++ b/drivers/mmc/sunxi_mmc.h
|
||||||
|
@@ -37,7 +37,9 @@ struct sunxi_mmc {
|
||||||
|
u32 res0; /* 0x54 reserved */
|
||||||
|
u32 a12a; /* 0x58 Auto command 12 argument */
|
||||||
|
u32 ntsr; /* 0x5c New timing set register */
|
||||||
|
- u32 res1[8];
|
||||||
|
+ u32 res1[6];
|
||||||
|
+ u32 hwrst; /* 0x78 Hardware Reset */
|
||||||
|
+ u32 res5;
|
||||||
|
u32 dmac; /* 0x80 internal DMA control */
|
||||||
|
u32 dlba; /* 0x84 internal DMA descr list base address */
|
||||||
|
u32 idst; /* 0x88 internal DMA status */
|
||||||
|
@@ -46,7 +48,8 @@ struct sunxi_mmc {
|
||||||
|
u32 cbda; /* 0x94 */
|
||||||
|
u32 res2[26];
|
||||||
|
#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
|
||||||
|
- u32 res3[17];
|
||||||
|
+ u32 thldc; /* 0x100 Threshold control */
|
||||||
|
+ u32 res3[16];
|
||||||
|
u32 samp_dl;
|
||||||
|
u32 res4[46];
|
||||||
|
#endif
|
||||||
|
@@ -57,6 +60,7 @@ struct sunxi_mmc {
|
||||||
|
#define SUNXI_MMC_CLK_ENABLE (0x1 << 16)
|
||||||
|
#define SUNXI_MMC_CLK_DIVIDER_MASK (0xff)
|
||||||
|
|
||||||
|
+#define SUNXI_MMC_GCTRL 0x000
|
||||||
|
#define SUNXI_MMC_GCTRL_SOFT_RESET (0x1 << 0)
|
||||||
|
#define SUNXI_MMC_GCTRL_FIFO_RESET (0x1 << 1)
|
||||||
|
#define SUNXI_MMC_GCTRL_DMA_RESET (0x1 << 2)
|
||||||
|
@@ -123,6 +127,10 @@ struct sunxi_mmc {
|
||||||
|
|
||||||
|
#define SUNXI_MMC_NTSR_MODE_SEL_NEW (0x1 << 31)
|
||||||
|
|
||||||
|
+#define SUNXI_MMC_HWRST 0x078
|
||||||
|
+#define SUNXI_MMC_HWRST_ASSERT (0x0 << 0)
|
||||||
|
+#define SUNXI_MMC_HWRST_DEASSERT (0x1 << 0)
|
||||||
|
+
|
||||||
|
#define SUNXI_MMC_IDMAC_RESET (0x1 << 0)
|
||||||
|
#define SUNXI_MMC_IDMAC_FIXBURST (0x1 << 1)
|
||||||
|
#define SUNXI_MMC_IDMAC_ENABLE (0x1 << 7)
|
||||||
|
@@ -133,6 +141,12 @@ struct sunxi_mmc {
|
||||||
|
#define SUNXI_MMC_COMMON_CLK_GATE (1 << 16)
|
||||||
|
#define SUNXI_MMC_COMMON_RESET (1 << 18)
|
||||||
|
|
||||||
|
+#define SUNXI_MMC_THLDC 0x100
|
||||||
|
+#define SUNXI_MMC_THLDC_READ_EN (0x1 << 0)
|
||||||
|
+#define SUNXI_MMC_THLDC_BSY_CLR_INT_EN (0x1 << 1)
|
||||||
|
+#define SUNXI_MMC_THLDC_WRITE_EN (0x1 << 2)
|
||||||
|
+#define SUNXI_MMC_THLDC_READ_THLD(x) (((x) & 0xfff) << 16)
|
||||||
|
+
|
||||||
|
#define SUNXI_MMC_CAL_DL_SW_EN (0x1 << 7)
|
||||||
|
|
||||||
|
#endif /* _SUNXI_MMC_H */
|
||||||
Executable
+93
@@ -0,0 +1,93 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Прошивка eMMC на X96Q — запускать на приставке под root
|
||||||
|
# Usage: sudo ./flash-emmc.sh [образ.img.xz]
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
UBOOT="${UBOOT:-${DIR}/../output/u-boot-custom.bin}"
|
||||||
|
IMG_XZ="${1:-}"
|
||||||
|
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "Запустите: sudo $0 [образ.img.xz]"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$IMG_XZ" ]]; then
|
||||||
|
shopt -s nullglob
|
||||||
|
imgs=( "$DIR"/*.img.xz )
|
||||||
|
if [[ ${#imgs[@]} -eq 0 ]]; then
|
||||||
|
echo "Нет .img.xz в $DIR"
|
||||||
|
exit 1
|
||||||
|
elif [[ ${#imgs[@]} -eq 1 ]]; then
|
||||||
|
IMG_XZ="${imgs[0]}"
|
||||||
|
else
|
||||||
|
echo "Несколько образов — укажите явно:"
|
||||||
|
ls -lh "${imgs[@]}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ -f "$IMG_XZ" ]] || { echo "Нет файла: $IMG_XZ"; exit 1; }
|
||||||
|
[[ -f "$UBOOT" ]] || { echo "Нет $UBOOT"; exit 1; }
|
||||||
|
|
||||||
|
EMMC=/dev/mmcblk2
|
||||||
|
BOOT0=/dev/mmcblk2boot0
|
||||||
|
BOOT1=/dev/mmcblk2boot1
|
||||||
|
|
||||||
|
[[ -b "$EMMC" ]] || { echo "eMMC не найден: $EMMC"; exit 1; }
|
||||||
|
|
||||||
|
unlock_boot() {
|
||||||
|
local ro
|
||||||
|
for part in boot0 boot1; do
|
||||||
|
ro="/sys/block/mmcblk2${part}/force_ro"
|
||||||
|
[[ -w "$ro" ]] || continue
|
||||||
|
echo 0 >"$ro"
|
||||||
|
echo "mmcblk2${part}: force_ro=$(cat "$ro")"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "=== eMMC flash (X96Q) ==="
|
||||||
|
echo "Образ: $IMG_XZ ($(du -h "$IMG_XZ" | cut -f1))"
|
||||||
|
echo "U-Boot: $UBOOT"
|
||||||
|
echo "Цель: $EMMC + $BOOT0 + $BOOT1"
|
||||||
|
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT 2>/dev/null | grep -E 'mmcblk|NAME' || lsblk
|
||||||
|
|
||||||
|
echo "[1/4] Запись образа на $EMMC ..."
|
||||||
|
xz -dc "$IMG_XZ" | dd of="$EMMC" bs=4M status=progress conv=fsync
|
||||||
|
sync
|
||||||
|
|
||||||
|
echo "[2/4] U-Boot → user area @ 8 KiB ..."
|
||||||
|
dd if="$UBOOT" of="$EMMC" bs=1024 seek=8 conv=fsync
|
||||||
|
|
||||||
|
echo "Разблокировка boot0/boot1 (force_ro) ..."
|
||||||
|
unlock_boot
|
||||||
|
|
||||||
|
echo "[3/4] U-Boot → boot0 ..."
|
||||||
|
dd if="$UBOOT" of="$BOOT0" bs=1024 conv=fsync
|
||||||
|
|
||||||
|
echo "[4/4] U-Boot → boot1 ..."
|
||||||
|
dd if="$UBOOT" of="$BOOT1" bs=1024 conv=fsync
|
||||||
|
sync
|
||||||
|
|
||||||
|
# Armbian DTB: в образе sun50i-h313-x96q-lpddr3.dtb, не v1.3
|
||||||
|
MNT="/tmp/emmc-fix"
|
||||||
|
mkdir -p "$MNT"
|
||||||
|
if mount "${EMMC}p1" "$MNT"; then
|
||||||
|
ENV="${MNT}/boot/armbianEnv.txt"
|
||||||
|
DTB="${MNT}/boot/dtb/allwinner"
|
||||||
|
if [[ -f "$ENV" ]]; then
|
||||||
|
if grep -q '^fdtfile=' "$ENV"; then
|
||||||
|
sed -i 's/^fdtfile=.*/fdtfile=sun50i-h313-x96q-lpddr3.dtb/' "$ENV"
|
||||||
|
else
|
||||||
|
echo 'fdtfile=sun50i-h313-x96q-lpddr3.dtb' >>"$ENV"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ -d "$DTB" && -f "${DTB}/sun50i-h313-x96q-lpddr3.dtb" ]]; then
|
||||||
|
ln -sf sun50i-h313-x96q-lpddr3.dtb "${DTB}/sun50i-h313-x96q-lpddr3-v1.3.dtb"
|
||||||
|
fi
|
||||||
|
sync
|
||||||
|
umount "$MNT"
|
||||||
|
fi
|
||||||
|
rmdir "$MNT" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "Готово. Выключите, выньте SD, включите — загрузка с eMMC."
|
||||||
Executable
+30
@@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Только U-Boot на eMMC (без перезаписи образа) — запускать на приставке под root
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
UBOOT="${1:-${DIR}/../output/u-boot-custom.bin}"
|
||||||
|
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "Запустите: sudo $0 [u-boot-custom.bin]"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ -f "$UBOOT" ]] || { echo "Нет файла: $UBOOT"; exit 1; }
|
||||||
|
|
||||||
|
EMMC=/dev/mmcblk2
|
||||||
|
BOOT0=/dev/mmcblk2boot0
|
||||||
|
BOOT1=/dev/mmcblk2boot1
|
||||||
|
|
||||||
|
echo "=== U-Boot only → $EMMC ==="
|
||||||
|
echo "Бинарник: $UBOOT"
|
||||||
|
|
||||||
|
echo 0 >/sys/block/mmcblk2boot0/force_ro
|
||||||
|
echo 0 >/sys/block/mmcblk2boot1/force_ro
|
||||||
|
|
||||||
|
dd if="$UBOOT" of="$EMMC" bs=1024 seek=8 conv=fsync
|
||||||
|
dd if="$UBOOT" of="$BOOT0" bs=1024 conv=fsync
|
||||||
|
dd if="$UBOOT" of="$BOOT1" bs=1024 conv=fsync
|
||||||
|
sync
|
||||||
|
|
||||||
|
echo "Готово."
|
||||||
Reference in New Issue
Block a user