diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000000..25277371affa --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: CI + +# The build lives in build-gk710x.yml on the openipc branch (the default +# branch, so it can be dispatched). GitHub runs a pull request's +# workflows from the PR's own tree, so this branch needs this caller for +# its pushes and pull requests to be built and smoke-tested at all. +# It never releases: that workflow only uploads on workflow_dispatch. +on: + push: + branches: [openipc-gk710x] + pull_request: + branches: [openipc-gk710x] + +jobs: + build: + uses: OpenIPC/u-boot/.github/workflows/build-gk710x.yml@openipc + # github.sha: on pull_request the merge of the PR into the current + # base, so the PR is built as it would land; on push, that commit. + with: + ref: ${{ github.sha }} + # A called workflow is validated against what its caller grants, + # skipped jobs included; release/publish ask for these. + permissions: + contents: write + id-token: write diff --git a/.gitignore b/.gitignore index eb769f144c3d..0183116964e3 100644 --- a/.gitignore +++ b/.gitignore @@ -104,3 +104,6 @@ __pycache__ # pylint files /pylint.cur /pylint.out/ + +# OpenIPC build outputs +/output/ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000000..caf7e14d390b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,239 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What this branch is + +`openipc-gk710x` is OpenIPC's U-Boot for Goke's own ARM1176 camera SoCs, the +GK7101 and GK7102. These are not the HiSilicon-derived GK7205/GK7605 that +`openipc-hisilicon` covers. The tree is **mainline U-Boot v2022.10**, the +same release as `openipc-hisilicon` and `openipc-xm`, plus: + +- the OpenIPC boot layer, carried over from `openipc-xm`, which took it from + `openipc-hisilicon`; +- the GK710x support, written from the vendor SDK (`GK710X_LinuxSDK_v2.0.0`, + U-Boot 2012.10 and Linux 3.4.43). + +No vendor driver comes along. The vendor's HAL blob is carried, for the +kernel only (see below). + +CI and user docs live on the `openipc` branch: + +- `.github/workflows/ci.yml` only calls `build-gk710x.yml@openipc`. +- `git show origin/openipc:CLAUDE.md` covers the workflow invariants. +- `git show origin/openipc-hisilicon:CLAUDE.md` covers the OpenIPC layer + (default environment, `common/openipc.c`, env compatibility). It applies + here unchanged. + +Adding or dropping a SoC needs both branches: + +- here: `build.sh` (`build_soc`, `ALL_SOCS`), `openipc/_config` and + `openipc/.rvs`; +- there: `build-gk710x.yml`'s matrices and the README. + +GK7101S/GK7102S (`gk7102s` in OpenIPC/firmware) are a different die with a +different HAL and register map. They are not supported here, and +qemu-hisilicon does not model them. + +## Relationship to mainline + +```sh +git diff --stat v2022.10 HEAD # the whole delta, small +git diff --diff-filter=M v2022.10 HEAD # the mainline files we patched +``` + +**Added** + +| Area | Location | +| --- | --- | +| SoC: clocks, timer, watchdog reset, DRAM size, pin functions | `arch/arm/mach-gk710x/` (`ARCH_GK710X`; `TARGET_GK7101`/`GK7102`; register map in `include/mach/gk710x.h`) | +| Kernel hand-off: HAL blob, U2K words | `arch/arm/mach-gk710x/kernel.c`, `hal_data.h` | +| Board: GPIO maps, internal Ethernet PHY, `misc_init_r` → `openipc_helper()` | `board/goke/gk710x/` | +| Memory map, console, timer | `include/configs/gk710x.h`, ending in `#include "openipc-common.h"` | +| SPI NOR controller, non-DM | `drivers/mtd/spi/gk_sflash.c` (`GK_SFLASH`). It provides `spi_flash_probe()` and fills `mtd->_read/_write/_erase`, as `xmsfc` does on `openipc-xm` | +| OpenIPC boot layer | `common/openipc.c`, `include/openipc.h` (as on `openipc-xm`), `include/configs/openipc-common.h` (GK rewrite, NOR only, same env commands) | +| Kconfig fragments, boot header, the build | `openipc/`, `build.sh` | + +**Patched mainline files**, each small: + +- `arch/arm/{Kconfig,Makefile}`: the `ARCH_GK710X` hook. +- `common/{Kconfig,Makefile}`: `OPENIPC`, `PRODUCT_SOC`, `PRODUCT_SOCMODEL`. +- `drivers/mtd/spi/{Kconfig,Makefile}`, `cmd/Kconfig` (`CMD_SF`) and + `env/Kconfig` (`ENV_IS_IN_SPI_FLASH`): accept `GK_SFLASH`. +- `drivers/net/Kconfig`: `NETDEVICES` selects `DM_ETH` only when `DM` is on, + as on `openipc-xm`. +- `drivers/net/designware.c`: the non-DM `designware_initialize()` uses an + MDIO bus the board has already registered under the device's name. The + GK710x PHY is not on the MAC's MDIO lines. + +The console (NS16550), the timer (`lib/time.c` over a raw counter) and +Ethernet (DesignWare) are mainline drivers. + +## The HAL, and why there is no vendor driver + +The vendor U-Boot and kernel never touch a register directly. Every access +goes through a HAL blob, written against a fictitious map (AHB `0x90000000`, +APB `0xA0000000`). The HAL: + +1. moves each block to its real place; +2. reorders registers inside some blocks; +3. permutes the bits of some registers (RCT PLLs, timer and watchdog + control, pad control). + +This tree programs the silicon directly. Every address and value in +`include/mach/gk710x.h`, `soc.c` and `board/goke/gk710x/gk710x.c` is the +store the HAL itself makes. It was found by executing the HAL's `hw_writel` +under Unicorn (qemu-hisilicon `qemu-boot/gk710x-halmap.py`). To port another +vendor register write, run it through the HAL the same way. Do not guess +from the vendor `*_reg.h`. + +The kernel still needs the blob (see "Hand-off to the kernel"). + +## Boot + +- The mask ROM reads the header at flash offset 0. It runs the register + writes and polls listed there (eFuse, DDR PHY, DDR controller), copies + U-Boot to `0xC0800000` (`SYS_TEXT_BASE`) and starts it. + - DDR is up before the first instruction, so there is no SPL, and + `lowlevel_init` is empty. +- `openipc/gk710x-image.py` builds that header: + - the words around the table are as in every SDK prebuilt and camera + flash seen; + - the table is `openipc/.rvs`, taken from the SDK's prebuilt + U-Boots, which matches what is on cameras in the field; + - GK7101 and GK7102 differ only in the DDR controller word at + `0x60004004` (128 vs 64 MiB). `dram_init()` reads the same word back. +- **Byte order.** The flash controller packs bytes MSB first. U-Boot, the + ROM and the vendor kernel all move whole little-endian words through it, so: + - the chip holds every 32-bit word byte-swapped; + - a camera dump reads as big-endian ("GK7101" in a hex editor); + - `output/u-boot--nor.bin` is in CPU order, which is what `sf write` + and the kernel's MTD driver expect; + - a raw image for a programmer, or for qemu's `flash-file=`, needs every + word swapped. + - `gk_sflash.c` keeps that mapping for unaligned offsets as well: whole + words only, writes padded with `0xff`. + +## Hand-off to the kernel + +The vendor kernel, OpenIPC's `gk7102` included, needs more than ATAGs. +`board_prep_linux()` in `mach-gk710x/kernel.c` provides: + +- **The HAL** at `0xC0012000`, with its address in U2K word `0xC0000008`. + The kernel calls `hal_init()` first thing and refuses a HAL older than + 20160324. The carried one is 20160913. +- **U2K words** at `0xC0000000`: + - total DDR in MiB; + - `mem=` in bytes, from `osmem`; + - the bitstream buffer, from `bsbsize`; + - `phytype`; + - the `0x7101` valid marker. + + The kernel places BSB, DSP and USR memory from these. `mem=` on the + command line still sets the kernel's own size. +- **The GPIO map** (vendor `gpio_cfg_t`) in the top 64 KiB of DDR. + - The kernel configures every pin from it ("gpio map get from uboot"): + sensor I2C and reset, IR cut, SD, Ethernet LED and PHY clock. + - Without it a camera boots with no sensor bus. + - `board_get_usable_ram_top()` keeps U-Boot below that 64 KiB. + +The SDK's 20-odd board GPIO headers come down to two layouts +(`board/goke/gk710x/gpio_map.c`): + +- `v2`, the default: rb-sc1035 v2.1, sc1045, imx225, ov9750, jxh42 v2.0, + gc1024, GK7101 rb-ov2710 v2.2; +- `v1`: rb-ov9712, ar0130, jxh42 v1.0, GK7101 imx222. + +`gpiomap=v1` in the environment selects the second. Other vendor boards +(EVBs, rb-ov2710 v1/v2.0/v2.1, ps1210, bg0703, ar0230) have other maps and +are not covered. + +U-Boot itself sets only GPIO 48, the internal PHY's reference clock, the +same in both layouts. It does not apply the whole map, as the vendor U-Boot +did. The two layouts put UART0 on different pins, so with the wrong default +a v1 board would lose its console before `gpiomap=v1` could be set. A v1 +board still needs `gpiomap=v1` for the kernel's pins, its console +included. + +## Peripherals + +- **Console:** UART0 at `0x70005000`, a 16550 with 32-bit registers, 24 MHz. + `arch_cpu_init()` sets the vendor's CPU PLL and UART divider. +- **Timer:** timer 1 at `0x7000B000`, counting down at the 69 MHz APB + clock. **Reset:** the watchdog. +- **Ethernet:** a DesignWare GMAC at `0x6000E000` with the SoC's own + 10/100 PHY. + - The PHY's MII registers are memory mapped at `0x60022000 + 4n`. The + board registers them as the MDIO bus, PHY address 0. + - `gk_ephy_init()` does the vendor's PHY clock (audio PLL, out on a pin), + analog trim and MAC/PHY mux. + - External-PHY boards (`phytype=1/2`) are not handled. +- **SD:** not enabled. The vendor U-Boot had none, the controller's base + clock is unknown, and the SD pins depend on the board map. SD recovery in + `common/openipc.c` is compiled out with `CONFIG_MMC`. +- **SPI NAND:** not supported. OpenIPC's GK7102 firmware is NOR only. + +## Build + +```sh +bash build.sh # gk7101 gk7102; continues past failures, exits non-zero if any failed +bash build.sh gk7102 # one or more SoCs (CROSS_COMPILE defaults to arm-linux-gnueabi-) +``` + +- The output is `output/u-boot--nor.bin`, built out of tree in + `output/build--nor/`. +- `.config` is `openipc/openipc_config`, then `openipc/_config`, then + `olddefconfig`. +- There are no `configs/*_defconfig` for these targets. +- There is no Thumb-2 on ARM1176, so the image is ~237 KiB. + `BOARD_SIZE_LIMIT` keeps header + image under the 256 KiB boot + partition. Check the size after enabling anything. + +## Verification + +The emulator is widgetii/qemu-hisilicon, machines `gk7101` and `gk7102` +(`docs/goke-gk710x.md` there). `-M gk7102,flash-file=` does the boot +ROM's job from the header, so it boots exactly the flashed bytes. The image +must be byte-swapped as described above. + +- **CI smoke:** two boots of an 8 MiB image holding only U-Boot. The second + must load the environment the first saved. +- **Checks to run by hand:** + - A full 8 MiB image reaches `login:`. It has U-Boot at 0, `uImage` at + 0x50000 and rootfs at 0x250000, from OpenIPC/firmware `latest` + `openipc.gk7102-nor-lite.tgz` (gk7101 boots the same). + - The kernel log shows `hal version = 20160913`, BSB/DSP/USR inside DDR, + and `[BOOT VERSION] GK7102 openipc-v2`. + - `sf erase/write/read` + `cmp.b` with an unaligned offset and length. + - `saveenv` + `reset`; `fw_printenv` from Linux. + - TFTP recovery from a flash holding only U-Boot + (`-nic user,net=192.168.1.0/24,host=192.168.1.107,tftp=`). + - The boot limit: two `reset`s, then `altbootcmd` boots with `failsafe`. +- **What qemu does not check:** + - DDR timing (the header is the vendor's, so this is low risk); + - PLL and clock values; + - pad control; + - the PHY's analog trim and real link. + + None of this has run on silicon yet. + +## Things to keep + +- `mem=` stays the first kernel argument, as on the other OpenIPC targets. + `osmem`/`bsbsize` must leave room for the DSP: + - GK7102: 36M + 2M of 64 MiB; + - GK7101: 50M + 4M of 128 MiB. +- The MTD name is `gk_flash`, the vendor kernel driver's (`SFC` in + `openipc-common.h`). The console is `ttySGK0`. +- The boot counter is the DRAM word at `0xC1F20000`, like the other + families' DDR + 0x1f20000. A healthy boot does not clear it, and the + GK7102 firmware ships no openipc-failsafe. After two reboots the boot + limit path therefore boots the same kernel with `failsafe`, which that + firmware ignores, as on `openipc-xm`. + +## Conventions + +- One topic per commit, `: ` (`gk710x:`, `gk_sflash:`, + `openipc:`, `net:`, `ci:`). +- Commit bodies say what was verified, and where: the qemu machine, or a + board. diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 82cd456f51f1..44cbc03dbd78 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1224,6 +1224,16 @@ config ARCH_U8500 imply SYS_THUMB_BUILD imply SYSRESET_SYSCON +config ARCH_GK710X + bool "Goke GK7101/GK7102 IP camera SoCs" + select CPU_ARM1176 + select CREATE_ARCH_SYMLINK + select SUPPORT_PASSING_ATAGS + help + Goke's own ARM1176 camera SoCs (not the HiSilicon-derived + GK7205/GK7605). The boot ROM runs the DDR set-up listed in the + flash header, copies U-Boot into DDR and starts it there. + config ARCH_VERSAL bool "Support Xilinx Versal Platform" select ARM64 @@ -2284,6 +2294,8 @@ source "arch/arm/mach-zynqmp/Kconfig" source "arch/arm/mach-versal/Kconfig" +source "arch/arm/mach-gk710x/Kconfig" + source "arch/arm/mach-zynqmp-r5/Kconfig" source "arch/arm/cpu/armv7/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 1f4a1d57883b..4c180efd263e 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -59,6 +59,7 @@ machine-$(CONFIG_ARCH_BCMBCA) += bcmbca machine-$(CONFIG_ARCH_BCMSTB) += bcmstb machine-$(CONFIG_ARCH_DAVINCI) += davinci machine-$(CONFIG_ARCH_EXYNOS) += exynos +machine-$(CONFIG_ARCH_GK710X) += gk710x machine-$(CONFIG_ARCH_GXP) += hpe machine-$(CONFIG_ARCH_HIGHBANK) += highbank machine-$(CONFIG_ARCH_IPQ40XX) += ipq40xx diff --git a/arch/arm/mach-gk710x/Kconfig b/arch/arm/mach-gk710x/Kconfig new file mode 100644 index 000000000000..db610d020543 --- /dev/null +++ b/arch/arm/mach-gk710x/Kconfig @@ -0,0 +1,31 @@ +if ARCH_GK710X + +choice + prompt "Goke SoC" + default TARGET_GK7102 + +config TARGET_GK7101 + bool "GK7101" + help + GK7101: ARM1176 with 128 MiB of external DDR2. + +config TARGET_GK7102 + bool "GK7102" + help + GK7102: the GK7101 die with 64 MiB of DDR2 in the package. + +endchoice + +config SYS_SOC + default "gk710x" + +config SYS_VENDOR + default "goke" + +config SYS_BOARD + default "gk710x" + +config SYS_CONFIG_NAME + default "gk710x" + +endif diff --git a/arch/arm/mach-gk710x/Makefile b/arch/arm/mach-gk710x/Makefile new file mode 100644 index 000000000000..46654b9be11c --- /dev/null +++ b/arch/arm/mach-gk710x/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += lowlevel_init.o soc.o gpio.o kernel.o diff --git a/arch/arm/mach-gk710x/gpio.c b/arch/arm/mach-gk710x/gpio.c new file mode 100644 index 000000000000..1d4cf6861815 --- /dev/null +++ b/arch/arm/mach-gk710x/gpio.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Goke GK710x pin functions, from the vendor U-Boot's drivers/gpio/ + * goke_gpio.c (gk7101_gpio_func_config()) with the HAL undone. + * + * A pin type is the vendor's GPIO_TYPE_* word: output function [7:0], input + * function + 2 [15:8], output-enable source [21:16], output and enable + * inversion [23:22], pad control [29:24] and direction [31:30]. The kernel + * decodes the same words from the map U-Boot leaves it (board/goke/gk710x). + */ + +#include +#include +#include + +#define TYPE_OUT_SEL(t) ((t) & 0xff) +#define TYPE_IN_SEL(t) (((t) >> 8) & 0xff) +#define TYPE_OEN_SEL(t) (((t) >> 16) & 0x3f) +#define TYPE_OUT_INV(t) (((t) >> 22) & 1) +#define TYPE_OEN_INV(t) (((t) >> 23) & 1) +#define TYPE_IOCTRL(t) (((t) >> 24) & 0x3f) +#define TYPE_FUNC(t) ((t) >> 30) + +#define FUNC_OUT 2 + +void gk_gpio_config(unsigned int pin, unsigned int type) +{ + unsigned int shift = 8 * (pin % 4); + u32 v; + + if (!type) + return; + + /* Input functions >= 2 are routed from a pin; 0 and 1 are constants */ + if (TYPE_FUNC(type) != FUNC_OUT && TYPE_IN_SEL(type) >= 2) + writel(pin, GK_GPIO_INPUT_CFG(TYPE_IN_SEL(type) - 2)); + + writel(TYPE_OUT_SEL(type) | TYPE_OEN_SEL(type) << 8 | + TYPE_OUT_INV(type) << 14 | TYPE_OEN_INV(type) << 15, + GK_GPIO_OUTPUT_CFG(pin)); + + if (TYPE_IOCTRL(type)) { + v = readl(GK_RCT_IOCTRL_GPIO(pin)); + v &= ~(0x3f << shift); + v |= TYPE_IOCTRL(type) << shift; + writel(v, GK_RCT_IOCTRL_GPIO(pin)); + } +} + +/* After a map is applied, as the vendor gk7101_gpio_initialize() ends */ +void gk_gpio_init(void) +{ + writel(1, GK_GPIO_IN_EN); + writel(0x11, GK_RCT_IOCTRL_MISC2); +} diff --git a/arch/arm/mach-gk710x/hal_data.h b/arch/arm/mach-gk710x/hal_data.h new file mode 100644 index 000000000000..ebe1ff8592c8 --- /dev/null +++ b/arch/arm/mach-gk710x/hal_data.h @@ -0,0 +1,680 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * The Goke GK7101/GK7102 HAL: a binary blob, as the vendor ships it in its + * U-Boot (SDK GK710X_LinuxSDK_v2.0.0, board/goke/gk7101/gk7101_hal_data.h, + * version 20160913), linked to run at GK_HAL_ADDR. + * + * U-Boot itself does not use it; its drivers program the silicon directly. + * The vendor kernel, OpenIPC's included, calls hal_init() at its start and + * makes every register access through the table that returns, so the blob + * is copied into place before the kernel starts (mach-gk710x/kernel.c). + * The OpenIPC kernel refuses a HAL older than 20160324. + */ + +static const u32 gk_hal_data[] = { + 0xe92d45f8, 0xe1a04000, 0xe1a05001, 0xe1a06002, 0xe1a0a003, 0xe59d7020, + 0xe3570000, 0x0a00000e, 0xe59f8148, 0xe58802f0, 0xe5881320, 0xe59832f8, + 0xe3530000, 0x0a000002, 0xe2880e2f, 0xe3a01001, 0xe12fff37, 0xe5983328, + 0xe3530000, 0x0a000002, 0xe59f011c, 0xe3a01001, 0xe12fff37, 0xe59f0114, + 0xe59f3114, 0xe5830000, 0xe3540000, 0x03a04206, 0xe59f3108, 0xe5834000, + 0xe3550000, 0x03a05207, 0xe59f30fc, 0xe5835000, 0xe244320f, 0xe2734000, + 0xe0a44003, 0xe59f30d4, 0xe5834330, 0xe59f30e4, 0xe5836000, 0xe59f30e0, + 0xe583a000, 0xe59f30dc, 0xe5803000, 0xe59f30d8, 0xe5803004, 0xe59f30d4, + 0xe5803008, 0xe59f30d0, 0xe580300c, 0xe59f30cc, 0xe5803010, 0xe59f30c8, + 0xe5803014, 0xe59f30c4, 0xe5803018, 0xe59f30c0, 0xe580301c, 0xe59f30bc, + 0xe5803020, 0xe59f30b8, 0xe5803024, 0xe59f30b4, 0xe5803028, 0xe59f30b0, + 0xe580302c, 0xe59f30ac, 0xe5803030, 0xe59f30a8, 0xe5803034, 0xe59f30a4, + 0xe5803038, 0xe59f30a0, 0xe580303c, 0xe59f309c, 0xe5803040, 0xe59f3098, + 0xe5803044, 0xe59f3094, 0xe5803048, 0xe59f3090, 0xe580304c, 0xe59f308c, + 0xe5803050, 0xe59f3088, 0xe5803054, 0xe59f3084, 0xe5803058, 0xe59f3080, + 0xe580305c, 0xe8bd85f8, 0xc0014ac0, 0xc0014de0, 0xc0015e58, 0xc0015eb8, + 0xc0015e4c, 0xc0015e48, 0xc0015e54, 0xc0015e50, 0xc00121f0, 0xc0012a3c, + 0xc0012cb8, 0xc0012c44, 0xc00128cc, 0xc0012bc8, 0xc0012b4c, 0xc0012a94, + 0xc0012298, 0xc00122b0, 0xc00122c8, 0xc00122e8, 0xc0012308, 0xc0012328, + 0xc0012348, 0xc0012368, 0xc0012388, 0xc00123a4, 0xc00123c0, 0xc00123d8, + 0xc00123f0, 0xc0012408, 0xc0012420, 0xc0012438, 0xe59f0000, 0xe12fff1e, + 0x20160913, 0xe92d4008, 0xe1a03001, 0xe3500000, 0x0a000006, 0xe590c008, + 0xe35c0000, 0x0a000003, 0xe1a00001, 0xe1a01002, 0xe12fff3c, 0xe1a03000, + 0xe1a00003, 0xe8bd8008, 0xe92d4008, 0xe1a03001, 0xe3500000, 0x0a000006, + 0xe590c008, 0xe35c0000, 0x0a000003, 0xe1a00001, 0xe1a01002, 0xe12fff3c, + 0xe6ff3070, 0xe1a00003, 0xe8bd8008, 0xe92d4008, 0xe1a03001, 0xe3500000, + 0x0a000006, 0xe590c008, 0xe35c0000, 0x0a000003, 0xe1a00001, 0xe1a01002, + 0xe12fff3c, 0xe6ef3070, 0xe1a00003, 0xe8bd8008, 0xe59f300c, 0xe5933000, + 0xe2833a16, 0xe5930000, 0xe12fff1e, 0xc0015e4c, 0xe59f300c, 0xe5933000, + 0xe2833a16, 0xe5830000, 0xe12fff1e, 0xc0015e4c, 0xe59f3014, 0xe5933000, + 0xe2833a06, 0xe1a00980, 0xe08339a0, 0xe7d30001, 0xe12fff1e, 0xc0015e4c, + 0xe59f3014, 0xe5933000, 0xe2833a06, 0xe1a00980, 0xe08339a0, 0xe19300b1, + 0xe12fff1e, 0xc0015e4c, 0xe59f3014, 0xe5933000, 0xe2833a06, 0xe1a00980, + 0xe08339a0, 0xe7930001, 0xe12fff1e, 0xc0015e4c, 0xe59f3014, 0xe5933000, + 0xe2833a06, 0xe1a00980, 0xe08339a0, 0xe7c32001, 0xe12fff1e, 0xc0015e4c, + 0xe59f3014, 0xe5933000, 0xe2833a06, 0xe1a00980, 0xe08339a0, 0xe18320b1, + 0xe12fff1e, 0xc0015e4c, 0xe59f3014, 0xe5933000, 0xe2833a06, 0xe1a00980, + 0xe08339a0, 0xe7832001, 0xe12fff1e, 0xc0015e4c, 0xe59f3010, 0xe5933000, + 0xe2833a05, 0xe1a00a00, 0xe7930a20, 0xe12fff1e, 0xc0015e4c, 0xe59f3010, + 0xe5933000, 0xe2833a05, 0xe1a00a00, 0xe7831a20, 0xe12fff1e, 0xc0015e4c, + 0xe1a00800, 0xe59f3008, 0xe5933000, 0xe7d30820, 0xe12fff1e, 0xc0015e48, + 0xe6ff0070, 0xe59f3008, 0xe5933000, 0xe19000b3, 0xe12fff1e, 0xc0015e48, + 0xe1a00800, 0xe59f3008, 0xe5933000, 0xe7930820, 0xe12fff1e, 0xc0015e48, + 0xe1a00800, 0xe59f3008, 0xe5933000, 0xe7c31820, 0xe12fff1e, 0xc0015e48, + 0xe6ff0070, 0xe59f3008, 0xe5933000, 0xe18010b3, 0xe12fff1e, 0xc0015e48, + 0xe1a00800, 0xe59f3008, 0xe5933000, 0xe7831820, 0xe12fff1e, 0xc0015e48, + 0xe20034ff, 0xe59f2420, 0xe5922000, 0xe1530002, 0x1a000066, 0xe2003aff, + 0xe3530a0a, 0x0a000041, 0xca00001f, 0xe3530901, 0x0a000038, 0xca00000d, + 0xe3530a01, 0x03a0001b, 0x012fff1e, 0xca000003, 0xe3530000, 0x03a0000c, + 0x012fff1e, 0xea0000ee, 0xe3530a02, 0x03a0000b, 0x012fff1e, 0xe3530a03, + 0x1a0000e9, 0xea000029, 0xe3530a07, 0x03a00016, 0x012fff1e, 0xca000004, + 0xe3530a05, 0x0a00002b, 0xe3530a06, 0x1a0000e0, 0xea000022, 0xe3530902, + 0x03a0001c, 0x012fff1e, 0xe3530a09, 0x1a0000da, 0xea00001e, 0xe3530a1e, + 0x0a000020, 0xca00000a, 0xe3530903, 0x0a00001b, 0xca000002, 0xe3530a0b, + 0x1a0000d1, 0xea000017, 0xe3530a0d, 0x0a000015, 0xe3530801, 0x1a0000cc, + 0xea000016, 0xe3530805, 0x0a000020, 0xca000004, 0xe3530a1f, 0x0a00000f, + 0xe3530802, 0x1a0000c4, 0xea000014, 0xe3530806, 0x0a00001e, 0xe3530807, + 0x1a0000bf, 0xea000021, 0xe3a00002, 0xe12fff1e, 0xe3a0000a, 0xe12fff1e, + 0xe3a00003, 0xe12fff1e, 0xe3a00008, 0xe12fff1e, 0xe3a0000d, 0xe12fff1e, + 0xe20008ff, 0xe59f32ec, 0xe3500811, 0x11a00003, 0x03a00021, 0xe12fff1e, + 0xe20008ff, 0xe59f32d4, 0xe3500812, 0x11a00003, 0x03a00022, 0xe12fff1e, + 0xe20008ff, 0xe59f32bc, 0xe3500815, 0x11a00003, 0x03a00020, 0xe12fff1e, + 0xe20008ff, 0xe59f32a4, 0xe3500816, 0x11a00003, 0x03a00023, 0xe12fff1e, + 0xe20008ff, 0xe59f328c, 0xe3500817, 0x11a00003, 0x03a00006, 0xe12fff1e, + 0xe59f227c, 0xe5922000, 0xe1530002, 0x1a000092, 0xe2003aff, 0xe3530a0b, + 0x0a00008f, 0xca000022, 0xe3530a05, 0x03a0000f, 0x012fff1e, 0xca00000f, + 0xe3530a02, 0x03a0001f, 0x012fff1e, 0xca000005, 0xe3530000, 0x01a00003, + 0x012fff1e, 0xe3530a01, 0x1a00006f, 0xea000034, 0xe3530a03, 0x03a00001, + 0x012fff1e, 0xe3530901, 0x1a000069, 0xea00007a, 0xe3530902, 0x03a0001d, + 0x012fff1e, 0xca000004, 0xe3530a06, 0x0a00002a, 0xe3530a07, 0x1a000060, + 0xea000027, 0xe3530a09, 0x03a0001e, 0x012fff1e, 0xe3530a0a, 0x1a00005a, + 0xea000023, 0xe3530a22, 0x0a000049, 0xca00000d, 0xe3530a16, 0x03a00014, + 0x012fff1e, 0xca000004, 0xe3530a0e, 0x0a00001c, 0xe3530a0f, 0x1a00004e, + 0xea000019, 0xe3530802, 0x0a000019, 0xe3530a21, 0x1a000049, 0xea000028, + 0xe3530703, 0x0a000044, 0xca000004, 0xe3530702, 0x0a000059, 0xe3530a8a, + 0x1a000041, 0xea000056, 0xe3530ac2, 0x0a00003c, 0xe3530ac3, 0x0a00003a, + 0xe3530ac1, 0x1a00003a, 0xea000037, 0xe3a0000e, 0xe12fff1e, 0xe3a00011, + 0xe12fff1e, 0xe3a00004, 0xe12fff1e, 0xe3a00009, 0xe12fff1e, 0xe59f3134, + 0xe0003003, 0xe2431b82, 0xe2411c02, 0xe59f2128, 0xe1510002, 0x93a00015, + 0x912fff1e, 0xe2431b83, 0xe1510002, 0x93a00017, 0x912fff1e, 0xe2822cfe, + 0xe59f0108, 0xe1530000, 0xd1a00002, 0xc3a00013, 0xe12fff1e, 0xe59f30ec, + 0xe0003003, 0xe2432a21, 0xe35200ff, 0x9a00002e, 0xe2422c01, 0xe3520c09, + 0x3a00002b, 0xe2432b87, 0xe35200ff, 0x93a00018, 0x912fff1e, 0xe59f20b4, + 0xe59f00c4, 0xe1530000, 0xd1a00002, 0xc3a00018, 0xe12fff1e, 0xe59f30a4, + 0xe0003003, 0xe2432a22, 0xe3520c06, 0x33a00010, 0x312fff1e, 0xe59f2084, + 0xe59f0098, 0xe1530000, 0xd1a00002, 0xc3a00019, 0xe12fff1e, 0xe3a0001a, + 0xe12fff1e, 0xe200080f, 0xe3500702, 0x0a000012, 0xe3500809, 0x0a000010, + 0xe350080a, 0x0a00000e, 0xe350080b, 0x0a00000c, 0xe350080d, 0x0a00000a, + 0xe350080e, 0x0a00000a, 0xe59f3030, 0xe350080f, 0x11a00003, 0x03a00005, + 0xe12fff1e, 0xe59f001c, 0xe12fff1e, 0xe3a00012, 0xe12fff1e, 0xe3a00005, + 0xe12fff1e, 0xe3a00005, 0xe12fff1e, 0xc0015e50, 0x0000ffff, 0xc0015e54, + 0x000fff00, 0x000001ff, 0x00020dff, 0x00021cff, 0x000225ff, 0xe92d4008, + 0xebfffeea, 0xe2503000, 0xb3a00000, 0xb8bd8008, 0xe3530023, 0xd3a00014, + 0xd59f2008, 0xd0202390, 0xc3a00000, 0xe8bd8008, 0xc0014ac0, 0xe92d4073, + 0xe1a06000, 0xe59f3134, 0xe1500003, 0x0a000046, 0x8a000007, 0xe59f3128, + 0xe1500003, 0x0a00001a, 0xe59f3120, 0xe1500003, 0x159f311c, 0x1a000005, + 0xea00000e, 0xe59f3114, 0xe1500003, 0x0a000012, 0x8a000003, 0xe59f3108, + 0xe1560003, 0x1a00001b, 0xea000008, 0xe59f30fc, 0xe1500003, 0x0a000003, + 0xe2833004, 0xe1500003, 0x1a000014, 0xea00002e, 0xe59f10e4, 0xea00002f, + 0xe59f30e0, 0xe5933000, 0xe2833a16, 0xe5931000, 0xea00002a, 0xe59f30d0, + 0xe5933000, 0xe2833a05, 0xe5933014, 0xe2031018, 0xe3c3203f, 0xe3822008, + 0xe2030006, 0xe18220a0, 0xe2033001, 0xe1823103, 0xe1831081, 0xea00001d, + 0xe3a05000, 0xe58d5004, 0xe1a00006, 0xebffffbe, 0xe2504000, 0x1a000005, + 0xe20634ff, 0xe3530206, 0x13530207, 0x15961000, 0x1a000012, 0xea000010, + 0xe5943004, 0xe1a00006, 0xe28d1004, 0xe12fff33, 0xe2501000, 0x0a00000b, + 0xe5911000, 0xe5943010, 0xe3530000, 0x0a000007, 0xe59d0004, 0xe1a02005, + 0xe12fff33, 0xe1a01000, 0xea000002, 0xe59f1034, 0xea000000, 0xe1a01004, + 0xe1a00001, 0xe8bd807c, 0xa016018c, 0xa0005014, 0xa0160188, 0x90016000, + 0xf3005014, 0xf2016000, 0xf3160188, 0x31303130, 0xc0015e4c, 0xc0015e48, + 0x00474b37, 0xe92d4010, 0xe1a04000, 0xebfffe81, 0xe3500000, 0xba00000b, + 0xe3500023, 0xca000009, 0xe3a02014, 0xe59f302c, 0xe0203092, 0xe5903004, + 0xe3530000, 0x0a000005, 0xe1a00004, 0xe3a01000, 0xe12fff33, 0xe8bd8010, + 0xe3a00000, 0xe8bd8010, 0xe1a00003, 0xe8bd8010, 0xc0014ac0, 0xe92d4073, + 0xe1a05000, 0xe1a04001, 0xe1a00001, 0xebffff7c, 0xe1a06000, 0xe3a03000, + 0xe58d3004, 0xe59f3084, 0xe1540003, 0x0a000004, 0xe59f307c, 0xe1540003, + 0x02433243, 0x1a000003, 0xea000000, 0xe59f306c, 0xe5835000, 0xea000016, + 0xe3500000, 0x1a000004, 0xe20434ff, 0xe3530206, 0x13530207, 0x0a000010, + 0xea00000e, 0xe5903004, 0xe1a00004, 0xe28d1004, 0xe12fff33, 0xe2504000, + 0x0a000009, 0xe5963010, 0xe3530000, 0x0a000005, 0xe59d0004, 0xe1a01005, + 0xe3a02001, 0xe12fff33, 0xe5840000, 0xea000000, 0xe5845000, 0xe8bd807c, + 0x90016000, 0xa0005004, 0x60016000, 0xe92d4073, 0xe1a05000, 0xe1a04001, + 0xe3a03000, 0xe58d3004, 0xe1a00001, 0xebffff4c, 0xe2506000, 0x1a000004, + 0xe20434ff, 0xe3530206, 0x13530207, 0x0a000010, 0xea00000e, 0xe5963004, + 0xe1a00004, 0xe28d1004, 0xe12fff33, 0xe2504000, 0x0a000009, 0xe596300c, + 0xe3530000, 0x0a000005, 0xe59d0004, 0xe1a01005, 0xe3a02001, 0xe12fff33, + 0xe1c400b0, 0xea000000, 0xe1c450b0, 0xe8bd807c, 0xe92d4073, 0xe1a05000, + 0xe1a04001, 0xe3a03000, 0xe58d3004, 0xe1a00001, 0xebffff2d, 0xe2506000, + 0x1a000004, 0xe20434ff, 0xe3530206, 0x13530207, 0x0a000010, 0xea00000e, + 0xe5963004, 0xe1a00004, 0xe28d1004, 0xe12fff33, 0xe2504000, 0x0a000009, + 0xe5963008, 0xe3530000, 0x0a000005, 0xe59d0004, 0xe1a01005, 0xe3a02001, + 0xe12fff33, 0xe5c40000, 0xea000000, 0xe5c45000, 0xe8bd807c, 0xe92d4073, + 0xe1a06000, 0xe3a05000, 0xe58d5004, 0xebffff10, 0xe2504000, 0x1a000005, + 0xe20634ff, 0xe3530206, 0x13530207, 0x11d610b0, 0x01a01004, 0xea00000d, + 0xe5943004, 0xe1a00006, 0xe28d1004, 0xe12fff33, 0xe2501000, 0x0a000007, + 0xe1d110b0, 0xe594300c, 0xe3530000, 0x0a000003, 0xe59d0004, 0xe1a02005, + 0xe12fff33, 0xe1a01000, 0xe1a00001, 0xe8bd807c, 0xe92d4073, 0xe1a06000, + 0xe3a05000, 0xe58d5004, 0xebfffef3, 0xe2504000, 0x1a000005, 0xe20634ff, + 0xe3530206, 0x13530207, 0x15d61000, 0x01a01004, 0xea00000d, 0xe5943004, + 0xe1a00006, 0xe28d1004, 0xe12fff33, 0xe2501000, 0x0a000007, 0xe5d11000, + 0xe5943008, 0xe3530000, 0x0a000003, 0xe59d0004, 0xe1a02005, 0xe12fff33, + 0xe1a01000, 0xe1a00001, 0xe8bd807c, 0xe3510000, 0x1a000007, 0xe6ff3070, + 0xe1a020a3, 0xe2000001, 0xe2022003, 0xe1820100, 0xe2033030, 0xe1830000, + 0xe12fff1e, 0xe2001001, 0xe6ff0070, 0xe1a03080, 0xe2033004, 0xe1a02e80, + 0xe1833081, 0xe1833fa2, 0xe2000030, 0xe1800003, 0xe12fff1e, 0xe3510000, + 0xe2003001, 0x1a00001a, 0xe1a010a0, 0xe2011002, 0xe1a0c080, 0xe1813003, + 0xe20cc004, 0xe1a010a0, 0xe18cc003, 0xe2011c01, 0xe1a030a0, 0xe181100c, + 0xe2033c02, 0xe1a02100, 0xe1833001, 0xe2022b01, 0xe1822003, 0xe2003b42, + 0xe1a010a0, 0xe1832002, 0xe2011802, 0xe1a03080, 0xe1811002, 0xe2033701, + 0xe1833001, 0xe59f2074, 0xe0002002, 0xe1820003, 0xe12fff1e, 0xe1a01080, + 0xe2011004, 0xe1a020a0, 0xe1813003, 0xe2022002, 0xe1a01080, 0xe1823003, + 0xe2011c02, 0xe1a02080, 0xe1811003, 0xe2022b01, 0xe1a03120, 0xe1822001, + 0xe2033c01, 0xe1833002, 0xe2002b42, 0xe1a01080, 0xe1823003, 0xe2011701, + 0xe1a020a0, 0xe1811003, 0xe2022802, 0xe1822001, 0xe59f3008, 0xe0003003, + 0xe1830002, 0xe12fff1e, 0x1ff80000, 0xe3510000, 0xe2003001, 0xe6ef0070, + 0xe2001002, 0x1a000007, 0xe1a02080, 0xe1813003, 0xe2022008, 0xe1a000a0, + 0xe1823003, 0xe2000004, 0xe1800003, 0xe12fff1e, 0xe1a020a0, 0xe1813003, + 0xe2022004, 0xe1a00080, 0xe1823003, 0xe2000008, 0xe1800003, 0xe12fff1e, + 0xe3510000, 0xe200103f, 0xe1a033a0, 0xe2033001, 0xe1811383, 0x1a00000b, + 0xe59f2058, 0xe0002002, 0xe1a0c0a0, 0xe1822001, 0xe20c1501, 0xe1a03080, + 0xe1812002, 0xe2033502, 0xe1832002, 0xe200040f, 0xe1800002, 0xe12fff1e, + 0xe59f3028, 0xe0003003, 0xe1a0c080, 0xe1833001, 0xe20c1502, 0xe1a020a0, + 0xe1813003, 0xe2022501, 0xe1823003, 0xe200040f, 0xe1800003, 0xe12fff1e, + 0x00273f00, 0xe3510000, 0xe1a030a0, 0x1a00000b, 0xe2033001, 0xe1a020a0, + 0xe2022002, 0xe1a010a0, 0xe1823003, 0xe2011004, 0xe2002001, 0xe1813003, + 0xe1833182, 0xe2000090, 0xe1800003, 0xe12fff1e, 0xe2002001, 0xe2031001, + 0xe1a01101, 0xe1a03080, 0xe1811082, 0xe2033008, 0xe1a02e00, 0xe1833001, + 0xe1833fa2, 0xe2000090, 0xe1800003, 0xe12fff1e, 0xe92d4010, 0xe2004001, + 0xe6ff3070, 0xe3510000, 0x1a00000f, 0xe1a010a3, 0xe2011002, 0xe1a020a3, + 0xe1811004, 0xe2022004, 0xe1a0c0a3, 0xe1822001, 0xe20cc008, 0xe1a00183, + 0xe18cc002, 0xe2000010, 0xe180000c, 0xe59f1048, 0xe0031001, 0xe1810000, + 0xe8bd8010, 0xe1a01083, 0xe2011004, 0xe1a02083, 0xe1811004, 0xe2022008, + 0xe1a0c083, 0xe1822001, 0xe20cc010, 0xe1a001a3, 0xe18cc002, 0xe2000002, + 0xe180000c, 0xe59f2008, 0xe0032002, 0xe1820000, 0xe8bd8010, 0x0000c1e0, + 0xe200c001, 0xe6ff3070, 0xe3510000, 0x1a000011, 0xe1a010a3, 0xe2011002, + 0xe1a02083, 0xe181100c, 0xe2022004, 0xe1822001, 0xe2030008, 0xe1a0c0a3, + 0xe1802002, 0xe20cc010, 0xe1a00083, 0xe18cc002, 0xe2000020, 0xe180000c, + 0xe59f1050, 0xe0031001, 0xe1810000, 0xe12fff1e, 0xe1a01083, 0xe2011004, + 0xe1a020a3, 0xe181100c, 0xe2022002, 0xe1822001, 0xe2030008, 0xe1a0c083, + 0xe1802002, 0xe20cc020, 0xe1a000a3, 0xe18cc002, 0xe2000010, 0xe180000c, + 0xe59f2008, 0xe0032002, 0xe1820000, 0xe12fff1e, 0x0000c1c0, 0xe200c001, + 0xe6ff3070, 0xe3510000, 0x1a000014, 0xe1a000a3, 0xe2000002, 0xe1a010a3, + 0xe180000c, 0xe2011004, 0xe1a02103, 0xe1811000, 0xe2022008, 0xe1822001, + 0xe2030010, 0xe1a0c0a3, 0xe1802002, 0xe20cc020, 0xe1a00083, 0xe18cc002, + 0xe2000040, 0xe180000c, 0xe59f105c, 0xe0031001, 0xe1810000, 0xe12fff1e, + 0xe1a00083, 0xe2000004, 0xe1a01083, 0xe180000c, 0xe2011008, 0xe1a02123, + 0xe1811000, 0xe2022002, 0xe1822001, 0xe2030010, 0xe1a0c083, 0xe1802002, + 0xe20cc040, 0xe1a000a3, 0xe18cc002, 0xe2000020, 0xe180000c, 0xe59f2008, + 0xe0032002, 0xe1820000, 0xe12fff1e, 0x00008380, 0xe3510000, 0x1a00000a, + 0xe6ff2070, 0xe1a010a2, 0xe200000b, 0xe2011010, 0xe1a03082, 0xe1810000, + 0xe2033020, 0xe1830000, 0xe2022dff, 0xe1820000, 0xe12fff1e, 0xe6ff3070, + 0xe1a01083, 0xe200000b, 0xe2011020, 0xe1a020a3, 0xe1810000, 0xe2022010, + 0xe1820000, 0xe2033dff, 0xe1830000, 0xe12fff1e, 0xe3510000, 0x1a000007, + 0xe6ef3070, 0xe1a020a3, 0xe2022001, 0xe2000001, 0xe1820080, 0xe2033004, + 0xe1830000, 0xe12fff1e, 0xe2001001, 0xe6ef3070, 0xe1a020a3, 0xe2022001, + 0xe1822081, 0xe2030004, 0xe1800002, 0xe12fff1e, 0xe3510000, 0xe2003001, + 0xe6ef0070, 0x1a00000f, 0xe1a010a0, 0xe2011002, 0xe1a02080, 0xe1813003, + 0xe2022004, 0xe1823003, 0xe2001008, 0xe1a023a0, 0xe1813003, 0xe1833202, + 0xe2002060, 0xe1a00180, 0xe1823003, 0xe2000080, 0xe1800003, 0xe12fff1e, + 0xe1a01080, 0xe2011004, 0xe1a020a0, 0xe1813003, 0xe2022002, 0xe1822003, + 0xe2001008, 0xe1a03180, 0xe1812002, 0xe2033080, 0xe1833002, 0xe2002060, + 0xe1a003a0, 0xe1823003, 0xe1830200, 0xe12fff1e, 0xe3510000, 0x1a000007, + 0xe6ef3070, 0xe1a020a3, 0xe2022001, 0xe2000001, 0xe1820080, 0xe2033004, + 0xe1830000, 0xe12fff1e, 0xe2001001, 0xe6ef3070, 0xe1a020a3, 0xe2022001, + 0xe1822081, 0xe2030004, 0xe1800002, 0xe12fff1e, 0xe92d4010, 0xe1a00a00, + 0xe1a0ca20, 0xe3a02000, 0xe1a03002, 0xe59f4060, 0xe7920004, 0xe15c0000, + 0xe59f0054, 0x1a00000b, 0xe3510000, 0x13a0200c, 0x10220392, 0x15812000, + 0xe3a0200c, 0xe0230392, 0xe59f2038, 0xe5920000, 0xe5933004, 0xe0800003, + 0xe2800a02, 0xe8bd8010, 0xe2833001, 0xe282200c, 0xe353001f, 0x1affffeb, + 0xe59f3010, 0xe5930000, 0xe2800a02, 0xe080000c, 0xe8bd8010, 0xc0014df4, + 0xc0015e4c, 0xe92d4010, 0xe1a00a00, 0xe1a0ca20, 0xe3a02000, 0xe1a03002, + 0xe59f4060, 0xe7920004, 0xe15c0000, 0xe59f0054, 0x1a00000b, 0xe3510000, + 0x13a0200c, 0x10220392, 0x15812000, 0xe3a0200c, 0xe0230392, 0xe59f2038, + 0xe5920000, 0xe5933004, 0xe0800003, 0xe2800a05, 0xe8bd8010, 0xe2833001, + 0xe282200c, 0xe3530015, 0x1affffeb, 0xe59f3010, 0xe5930000, 0xe2800a05, + 0xe080000c, 0xe8bd8010, 0xc0014f68, 0xc0015e4c, 0xe1a00001, 0xe12fff1e, + 0xe1a00001, 0xe12fff1e, 0xe92d4008, 0xe1a03001, 0xe3500000, 0x0a000006, + 0xe590c008, 0xe35c0000, 0x0a000003, 0xe1a00001, 0xe1a01002, 0xe12fff3c, + 0xe1a03000, 0xe1a00003, 0xe8bd8008, 0xe24dd008, 0xe59f3044, 0xe5933000, + 0xe3510000, 0x1a000007, 0xe2833a03, 0xe5932010, 0xe5933014, 0xe58d1000, + 0xe5cd2000, 0xe5cd3001, 0xe59d0000, 0xea000004, 0xe1a02420, 0xe6ef2072, + 0xe2833a03, 0xe5832014, 0xe6ef0070, 0xe28dd008, 0xe12fff1e, 0xc0015e48, + 0xe24dd008, 0xe59f302c, 0xe5933000, 0xe2510000, 0x0a000006, 0xe2833a03, + 0xe5932014, 0xe3a03000, 0xe58d3000, 0xe5cd3000, 0xe5cd2001, 0xe59d0000, + 0xe28dd008, 0xe12fff1e, 0xc0015e48, 0xe24dd010, 0xe3510000, 0x1a00000d, + 0xe58d1008, 0xe1a02180, 0xe2022010, 0xe1a030a0, 0xe20110ed, 0xe2033002, + 0xe1811002, 0xe1a00e00, 0xe1811003, 0xe3c11001, 0xe1810fa0, 0xe5cd0008, + 0xe59d0008, 0xea000007, 0xe6ef0070, 0xe1a021a0, 0xe1a03080, 0xe2022002, + 0xe2033004, 0xe2000001, 0xe1833002, 0xe1830180, 0xe28dd010, 0xe12fff1e, + 0xe3510000, 0xe1a03120, 0x1a000009, 0xe2001001, 0xe2033001, 0xe1a03083, + 0xe1a02e00, 0xe1833101, 0xe1a00100, 0xe1833fa2, 0xe2000008, 0xe1800003, + 0xe12fff1e, 0xe2033001, 0xe1a01080, 0xe2011004, 0xe2002001, 0xe1813003, + 0xe1a00120, 0xe1833182, 0xe2000002, 0xe1800003, 0xe12fff1e, 0xe6ef2070, + 0xe1a03122, 0xe3530007, 0xca00000f, 0xe3510000, 0x13a0c00c, 0x159f2050, + 0x1022239c, 0x15812000, 0xe3100901, 0xe59f1040, 0xe3a0000c, 0xe59f203c, + 0xe0231390, 0xe5920000, 0xe5933004, 0xe0800003, 0x12800a07, 0x02800a03, + 0xe12fff1e, 0xe3100901, 0xe59f3018, 0xe5930000, 0x12800a07, 0x10800002, + 0x02800a03, 0x00800002, 0xe12fff1e, 0xc0015064, 0xc0015e48, 0xe1a00001, + 0xe12fff1e, 0xe1a00001, 0xe12fff1e, 0xe92d4008, 0xe1a03001, 0xe3500000, + 0x0a000006, 0xe590c008, 0xe35c0000, 0x0a000003, 0xe1a00001, 0xe1a01002, + 0xe12fff3c, 0xe1a03000, 0xe1a00003, 0xe8bd8008, 0xe59f3010, 0xe5933000, + 0xe2833a09, 0xe1a00a00, 0xe0830a20, 0xe12fff1e, 0xc0015e48, 0xe3510000, + 0xe200301f, 0x1a00000f, 0xe1a02180, 0xe2022c02, 0xe1a01120, 0xe1823003, + 0xe2011080, 0xe1a021a0, 0xe1811003, 0xe2022020, 0xe1a03080, 0xe1822001, + 0xe2033040, 0xe1a00080, 0xe1833002, 0xe2000c01, 0xe1800003, 0xe12fff1e, + 0xe1a021a0, 0xe2022040, 0xe1a01100, 0xe1823003, 0xe2011c02, 0xe1a02180, + 0xe1811003, 0xe2022c01, 0xe1a030a0, 0xe1822001, 0xe2033020, 0xe1a000a0, + 0xe1833002, 0xe2000080, 0xe1800003, 0xe12fff1e, 0xe3510000, 0xe2003003, + 0x1a000012, 0xe1a01120, 0xe2011020, 0xe1a02120, 0xe1813003, 0xe2022004, + 0xe1a01280, 0xe1823003, 0xe2011080, 0xe1a021a0, 0xe1811003, 0xe2022008, + 0xe1a03080, 0xe1822001, 0xe2033010, 0xe1a00080, 0xe1833002, 0xe2000040, + 0xe1800003, 0xe12fff1e, 0xe1a01100, 0xe2011080, 0xe1a02100, 0xe1813003, + 0xe2022010, 0xe1a012a0, 0xe1823003, 0xe2011004, 0xe1a02180, 0xe1811003, + 0xe2022040, 0xe1a030a0, 0xe1822001, 0xe2033008, 0xe1a000a0, 0xe1833002, + 0xe2000020, 0xe1800003, 0xe12fff1e, 0xe3510000, 0xe1a030a0, 0x1a000008, + 0xe1a01120, 0xe2033001, 0xe2011004, 0xe1a02e00, 0xe1813083, 0xe2000001, + 0xe1833fa2, 0xe1830200, 0xe12fff1e, 0xe1a01100, 0xe2033001, 0xe2011010, + 0xe2002001, 0xe1813083, 0xe1a00d80, 0xe1833182, 0xe1830fa0, 0xe12fff1e, + 0xe3510000, 0x1a000009, 0xe1a01120, 0xe1a03100, 0xe2011004, 0xe2033008, + 0xe1a02e00, 0xe1833001, 0xe2000001, 0xe1833fa2, 0xe1830200, 0xe12fff1e, + 0xe1a01100, 0xe1a03120, 0xe2011010, 0xe2033002, 0xe2002001, 0xe1833001, + 0xe1a00d80, 0xe1833182, 0xe1830fa0, 0xe12fff1e, 0xe3510000, 0xe1a031a0, + 0x1a000009, 0xe2033001, 0xe2001001, 0xe1a01181, 0xe1a02f00, 0xe1813103, + 0xe1a000a0, 0xe1833fa2, 0xe2000002, 0xe1800003, 0xe12fff1e, 0xe1a01080, + 0xe2033001, 0xe2011008, 0xe2002001, 0xe1833001, 0xe1a00080, 0xe1833082, + 0xe2000004, 0xe1800003, 0xe12fff1e, 0xe3510000, 0xe1a031a0, 0x1a000008, + 0xe1a01100, 0xe2033001, 0xe2011008, 0xe2002001, 0xe1813103, 0xe1a00e80, + 0xe1833082, 0xe1830fa0, 0xe12fff1e, 0xe2033001, 0xe1a01080, 0xe2011008, + 0xe1a02f00, 0xe1813083, 0xe2000001, 0xe1833fa2, 0xe1830100, 0xe12fff1e, + 0xe3510000, 0xe1a03220, 0x1a00000b, 0xe1a02180, 0xe2033001, 0xe2022010, + 0xe2001001, 0xe1823183, 0xe1a02e80, 0xe1833081, 0xe1a000a0, 0xe1833fa2, + 0xe2000004, 0xe1800003, 0xe12fff1e, 0xe2033001, 0xe1a02080, 0xe2022010, + 0xe1a01f00, 0xe1823083, 0xe2002001, 0xe1833fa1, 0xe1a00080, 0xe1833102, + 0xe2000008, 0xe1800003, 0xe12fff1e, 0xe1a030a0, 0xe2000001, 0xe2033001, + 0xe1830080, 0xe12fff1e, 0xe3510000, 0xe1a030a0, 0x1a000008, 0xe1a02220, + 0xe2022001, 0xe2033001, 0xe1823083, 0xe200200c, 0xe2000001, 0xe1823003, + 0xe1830200, 0xe12fff1e, 0xe2002001, 0xe2033001, 0xe1a03083, 0xe1833202, + 0xe200200c, 0xe1a00d80, 0xe1823003, 0xe1830fa0, 0xe12fff1e, 0xe3510000, + 0xe1a03220, 0x1a00000b, 0xe1a02180, 0xe2033001, 0xe2022010, 0xe2001001, + 0xe1823183, 0xe1a02e80, 0xe1833081, 0xe1a000a0, 0xe1833fa2, 0xe2000004, + 0xe1800003, 0xe12fff1e, 0xe2033001, 0xe1a02080, 0xe2022010, 0xe1a01f00, + 0xe1823083, 0xe2002001, 0xe1833fa1, 0xe1a00080, 0xe1833102, 0xe2000008, + 0xe1800003, 0xe12fff1e, 0xe6ef0070, 0xe1a03120, 0xe3530016, 0xe59f2040, + 0xca00000b, 0xe3510000, 0xe59f0038, 0x13a0c00c, 0x102c039c, 0x1581c000, + 0xe3a0100c, 0xe0230391, 0xe5920000, 0xe5933004, 0xe0800003, 0xe2800a0a, + 0xe12fff1e, 0xe5923000, 0xe2833a0a, 0xe0830000, 0xe12fff1e, 0xc0015e4c, + 0xc00150c4, 0xe92d4008, 0xe1a03001, 0xe3500000, 0x0a000006, 0xe590c008, + 0xe35c0000, 0x0a000003, 0xe1a00001, 0xe1a01002, 0xe12fff3c, 0xe1a03000, + 0xe1a00003, 0xe8bd8008, 0xe59f3014, 0xe5933000, 0xe2833702, 0xe3c004ff, + 0xe3c0073e, 0xe0830000, 0xe12fff1e, 0xc0015e4c, 0xe3510000, 0x1a000005, + 0xe1a02420, 0xe200003f, 0xe59f3028, 0xe0023003, 0xe1830a00, 0xe12fff1e, + 0xe1a01400, 0xe59f3018, 0xe0013003, 0xe2012407, 0xe1a00300, 0xe1823003, + 0xe1830d20, 0xe12fff1e, 0x00077fff, 0x007fff00, 0xe3510000, 0x1a000005, + 0xe1a02420, 0xe200003f, 0xe59f3028, 0xe0023003, 0xe1830a00, 0xe12fff1e, + 0xe1a01400, 0xe59f3018, 0xe0013003, 0xe2012407, 0xe1a00300, 0xe1823003, + 0xe1830d20, 0xe12fff1e, 0x00077fff, 0x007fff00, 0xe3510000, 0x1a000005, + 0xe1a02420, 0xe200003f, 0xe59f3028, 0xe0023003, 0xe1830a00, 0xe12fff1e, + 0xe1a01400, 0xe59f3018, 0xe0013003, 0xe2012407, 0xe1a00300, 0xe1823003, + 0xe1830d20, 0xe12fff1e, 0x00077fff, 0x007fff00, 0xe3510000, 0x1a000005, + 0xe1a02420, 0xe200003f, 0xe59f3028, 0xe0023003, 0xe1830a00, 0xe12fff1e, + 0xe1a01400, 0xe59f3018, 0xe0013003, 0xe2012407, 0xe1a00300, 0xe1823003, + 0xe1830d20, 0xe12fff1e, 0x00077fff, 0x007fff00, 0xe3510000, 0xe1a030a0, + 0x1a000009, 0xe2033001, 0xe1a010a0, 0xe2011002, 0xe1a020a0, 0xe1813003, + 0xe2022004, 0xe2000001, 0xe1823003, 0xe1830180, 0xe12fff1e, 0xe2001001, + 0xe2032001, 0xe1a02102, 0xe1a03080, 0xe1822081, 0xe2033008, 0xe1a00e00, + 0xe1833002, 0xe1830fa0, 0xe12fff1e, 0xe3510000, 0x1a000005, 0xe1a02420, + 0xe200003f, 0xe59f3028, 0xe0023003, 0xe1830a00, 0xe12fff1e, 0xe1a01400, + 0xe59f3018, 0xe0013003, 0xe2012407, 0xe1a00300, 0xe1823003, 0xe1830d20, + 0xe12fff1e, 0x00077fff, 0x007fff00, 0xe3510000, 0xe1a030a0, 0x1a000014, + 0xe2033001, 0xe1a020a0, 0xe2022002, 0xe1a010a0, 0xe1823003, 0xe2011004, + 0xe1a020a0, 0xe1813003, 0xe2022008, 0xe1a010a0, 0xe1822003, 0xe2011010, + 0xe1a030a0, 0xe1811002, 0xe2033020, 0xe2002001, 0xe1833001, 0xe1833302, + 0xe2000601, 0xe1800003, 0xe12fff1e, 0xe2002001, 0xe203c001, 0xe1a0c10c, + 0xe1a03080, 0xe18cc082, 0xe2033008, 0xe1a02080, 0xe183300c, 0xe2022010, + 0xe1a01080, 0xe1822003, 0xe2011020, 0xe1a03080, 0xe1811002, 0xe2033040, + 0xe1a02c80, 0xe1833001, 0xe1833fa2, 0xe2000601, 0xe1800003, 0xe12fff1e, + 0xe3510000, 0xe1a03220, 0x02033001, 0x0200000f, 0x01830200, 0x12000001, + 0x1203300f, 0x11830200, 0xe12fff1e, 0xe3510000, 0xe200303f, 0x1a000008, + 0xe1a01420, 0xe201103f, 0xe1a02420, 0xe1813803, 0xe2022c3f, 0xe1823003, + 0xe200043f, 0xe1800003, 0xe12fff1e, 0xe1a01820, 0xe201103f, 0xe1a02400, + 0xe1813403, 0xe202283f, 0xe1823003, 0xe200043f, 0xe1800003, 0xe12fff1e, + 0xe92d4010, 0xe6ff0070, 0xe3a02000, 0xe1a03002, 0xe59f4060, 0xe792c004, + 0xe150000c, 0xe59fc054, 0x1a00000b, 0xe3510000, 0x13a0200c, 0x1022c392, + 0x15812000, 0xe3a0200c, 0xe023c392, 0xe59f2038, 0xe5920000, 0xe5933004, + 0xe0800003, 0xe2800817, 0xe8bd8010, 0xe2833001, 0xe282200c, 0xe353003e, + 0x1affffeb, 0xe59f3010, 0xe5933000, 0xe2833817, 0xe0830000, 0xe8bd8010, + 0xc00151d8, 0xc0015e48, 0xe92d4008, 0xe1a03001, 0xe3500000, 0x0a000006, + 0xe590c008, 0xe35c0000, 0x0a000003, 0xe1a00001, 0xe1a01002, 0xe12fff3c, + 0xe1a03000, 0xe1a00003, 0xe8bd8008, 0xe59f300c, 0xe5933000, 0xe2833a05, + 0xe6e30070, 0xe12fff1e, 0xc0015e4c, 0xe92d4010, 0xe6ef0070, 0xe3a02000, + 0xe1a03002, 0xe59f4060, 0xe792c004, 0xe150000c, 0xe59fc054, 0x1a00000b, + 0xe3510000, 0x13a0200c, 0x1022c392, 0x15812000, 0xe3a0200c, 0xe023c392, + 0xe59f2038, 0xe5920000, 0xe5933004, 0xe0800003, 0xe2800b83, 0xe8bd8010, + 0xe2833001, 0xe282200c, 0xe353001f, 0x1affffeb, 0xe59f3010, 0xe5933000, + 0xe2833b83, 0xe0830000, 0xe8bd8010, 0xc00154c0, 0xc0015e4c, 0xe59f300c, + 0xe5933000, 0xe2833b87, 0xe6e30070, 0xe12fff1e, 0xc0015e4c, 0xe3510000, + 0xe1a03820, 0xe1a00800, 0x01830000, 0x11a00820, 0x11800803, 0x11a00860, + 0xe12fff1e, 0xe3510000, 0x01a03a80, 0x02000001, 0x01a00500, 0x01800b23, + 0x11a03b00, 0x11a00520, 0x12000001, 0x11800aa3, 0xe12fff1e, 0xe92d4010, + 0xe6ff0070, 0xe3a02000, 0xe1a03002, 0xe59f4054, 0xe792c004, 0xe150000c, + 0xe59fc048, 0x1a00000b, 0xe3510000, 0x13a0200c, 0x1022c392, 0x15812000, + 0xe3a0200c, 0xe023c392, 0xe59f202c, 0xe5920000, 0xe5933004, 0xe0800003, + 0xe2800801, 0xe8bd8010, 0xe2833001, 0xe282200c, 0xe3530010, 0x1affffeb, + 0xe3a00000, 0xe8bd8010, 0xc0015634, 0xc0015e48, 0xe92d4010, 0xe6ff0070, + 0xe3a02000, 0xe1a03002, 0xe59f4058, 0xe792c004, 0xe150000c, 0xe59fc04c, + 0x1a00000a, 0xe3510000, 0x13a0200c, 0x1022c392, 0x15812000, 0xe3a0200c, + 0xe023c392, 0xe5930004, 0xe59f302c, 0xe5933000, 0xe0800003, 0xe8bd8010, + 0xe2833001, 0xe282200c, 0xe353001c, 0x1affffec, 0xe59f300c, 0xe5933000, + 0xe0800003, 0xe8bd8010, 0xc00156f4, 0xc0015e4c, 0xe3510000, 0xe2003001, + 0x1a000006, 0xe1a020a0, 0xe2022002, 0xe1a00080, 0xe1823003, 0xe2000004, + 0xe1800003, 0xe12fff1e, 0xe1a02080, 0xe2022004, 0xe1a000a0, 0xe1823003, + 0xe2000002, 0xe1800003, 0xe12fff1e, 0xe92d4010, 0xe3a02000, 0xe59f3064, + 0xe4832004, 0xe6ef0070, 0xe1a0c002, 0xe7924003, 0xe1500004, 0x1a00000d, + 0xe3510000, 0x13a0200c, 0x159f3044, 0x10233c92, 0x15813000, 0xe3a0200c, + 0xe59f3030, 0xe02c3c92, 0xe59f3030, 0xe5930000, 0xe59c3008, 0xe0800003, + 0xe2800903, 0xe8bd8010, 0xe28cc001, 0xe282200c, 0xe35c0007, 0x1affffea, + 0xe3a00000, 0xe8bd8010, 0xc0015844, 0xc0015848, 0xc0015e48, 0xe92d4010, + 0xe1a00a00, 0xe1a0ca20, 0xe3a02000, 0xe1a03002, 0xe59f4060, 0xe7920004, + 0xe15c0000, 0xe59f0054, 0x1a00000b, 0xe3510000, 0x13a0200c, 0x10220392, + 0x15812000, 0xe3a0200c, 0xe0230392, 0xe59f2038, 0xe5920000, 0xe5933004, + 0xe0800003, 0xe2800a02, 0xe8bd8010, 0xe2833001, 0xe282200c, 0xe3530019, + 0x1affffeb, 0xe59f3010, 0xe5930000, 0xe2800a02, 0xe080000c, 0xe8bd8010, + 0xc001589c, 0xc0015e48, 0xe92d4010, 0xe1a00a00, 0xe1a0ca20, 0xe3a02000, + 0xe1a03002, 0xe59f4060, 0xe7920004, 0xe15c0000, 0xe59f0054, 0x1a00000b, + 0xe3510000, 0x13a0200c, 0x10220392, 0x15812000, 0xe3a0200c, 0xe0230392, + 0xe59f2038, 0xe5920000, 0xe5933004, 0xe0800003, 0xe2800a0f, 0xe8bd8010, + 0xe2833001, 0xe282200c, 0xe3530019, 0x1affffeb, 0xe59f3010, 0xe5930000, + 0xe2800a0f, 0xe080000c, 0xe8bd8010, 0xc001589c, 0xc0015e48, 0xe92d4010, + 0xe1a00a00, 0xe1a0ca20, 0xe3a02000, 0xe1a03002, 0xe59f0064, 0xe7924000, + 0xe15c0004, 0x1a00000d, 0xe3510000, 0x13a0000c, 0x159f204c, 0x10222390, + 0x15812000, 0xe3a0100c, 0xe59f2040, 0xe0232391, 0xe59f203c, 0xe5920000, + 0xe5933130, 0xe0800003, 0xe2800a01, 0xe8bd8010, 0xe2833001, 0xe282200c, + 0xe3530004, 0x1affffea, 0xe59f3014, 0xe5930000, 0xe2800a01, 0xe080000c, + 0xe8bd8010, 0xc00159c8, 0xc001589c, 0xc0015e48, 0xe3510000, 0x1a000015, + 0xe1a01a80, 0xe1a032a0, 0xe2033002, 0xe1833fa1, 0xe2002004, 0xe1a012a0, + 0xe1823003, 0xe2011010, 0xe1811003, 0xe2003020, 0xe1a02280, 0xe1831001, + 0xe2022040, 0xe1822001, 0xe2001c01, 0xe1a03280, 0xe1812002, 0xe2033c02, + 0xe2000001, 0xe1833002, 0xe1830500, 0xe12fff1e, 0xe2001001, 0xe1a03280, + 0xe2033040, 0xe1833501, 0xe2002004, 0xe1a01280, 0xe1823003, 0xe2011c02, + 0xe1811003, 0xe2003020, 0xe1a022a0, 0xe1831001, 0xe2022002, 0xe1822001, + 0xe2001c01, 0xe1a032a0, 0xe1812002, 0xe2033010, 0xe1a00a80, 0xe1833002, + 0xe1830fa0, 0xe12fff1e, 0xe6ef0070, 0xe1a03120, 0xe353000e, 0xe59f2040, + 0xca00000b, 0xe3510000, 0xe59f0038, 0x13a0c00c, 0x102c039c, 0x1581c000, + 0xe3a0100c, 0xe0230391, 0xe5920000, 0xe5933004, 0xe0800003, 0xe2800a0b, + 0xe12fff1e, 0xe5923000, 0xe2833a0b, 0xe0830000, 0xe12fff1e, 0xc0015e48, + 0xc00159f8, 0xe3510000, 0x1a000002, 0xe1a00160, 0xe6bf0f30, 0xe12fff1e, + 0xe6bf0f30, 0xe1a00f60, 0xe12fff1e, 0xe3510000, 0x1a000002, 0xe1a00160, + 0xe6bf0f30, 0xe12fff1e, 0xe6bf0f30, 0xe1a00f60, 0xe12fff1e, 0xe1a03a00, + 0xe1a02a23, 0xe1a03b23, 0xe353000e, 0xca00000e, 0xe3510000, 0xe59f204c, + 0x13a0000c, 0x10202390, 0x15810000, 0xe3a0100c, 0xe0232391, 0xe5930004, + 0xe3800206, 0xe3800a03, 0xe59f302c, 0xe5933000, 0xe283320a, 0xe1800003, + 0xe12fff1e, 0xe59f3018, 0xe5930000, 0xe280020a, 0xe3800206, 0xe3800a03, + 0xe1800002, 0xe12fff1e, 0xc0015aac, 0xc0015e4c, 0xe1a03a00, 0xe1a02a23, + 0xe1a03b23, 0xe353000e, 0xca00000f, 0xe3510000, 0x13a0000c, 0x159f204c, + 0x10222390, 0x15812000, 0xe3a0100c, 0xe59f2040, 0xe0232391, 0xe59300b8, + 0xe3800206, 0xe3800801, 0xe59f3030, 0xe5933000, 0xe283320a, 0xe1800003, + 0xe12fff1e, 0xe59f301c, 0xe5930000, 0xe280020a, 0xe3800206, 0xe3800801, + 0xe1800002, 0xe12fff1e, 0xc0015b60, 0xc0015aac, 0xc0015e4c, 0xe92d4008, + 0xe1a03001, 0xe3500000, 0x0a000006, 0xe590c008, 0xe35c0000, 0x0a000003, + 0xe1a00001, 0xe1a01002, 0xe12fff3c, 0xe1a03000, 0xe1a00003, 0xe8bd8008, + 0xe3510000, 0x1a00000f, 0xe1a01120, 0xe2003001, 0xe2011003, 0xe1a02100, + 0xe1811103, 0xe2022008, 0xe1a03120, 0xe1822001, 0xe2033010, 0xe1833002, + 0xe2002020, 0xe1a00100, 0xe1823003, 0xe2000040, 0xe1800003, 0xe12fff1e, + 0xe1a01100, 0xe1a03e80, 0xe201100c, 0xe1a02120, 0xe1811fa3, 0xe2022002, + 0xe1a03100, 0xe1822001, 0xe2033040, 0xe1833002, 0xe2002020, 0xe1a00120, + 0xe1823003, 0xe2000010, 0xe1800003, 0xe12fff1e, 0xe3510000, 0x1a000014, + 0xe1a02c80, 0xe1a030a0, 0xe2033002, 0xe1a0c080, 0xe1833fa2, 0xe20cc004, + 0xe1a02120, 0xe18cc003, 0xe2022008, 0xe1a01080, 0xe182200c, 0xe2011010, + 0xe1a03080, 0xe1811002, 0xe2033020, 0xe2002001, 0xe1833001, 0xe1833302, + 0xe2000080, 0xe1800003, 0xe12fff1e, 0xe2002001, 0xe1a03080, 0xe2033004, + 0xe1a0c0a0, 0xe1833302, 0xe20cc002, 0xe1a02100, 0xe18cc003, 0xe2022020, + 0xe1a010a0, 0xe182200c, 0xe2011008, 0xe1a030a0, 0xe1811002, 0xe2033010, + 0xe1a02c80, 0xe1833001, 0xe1833fa2, 0xe2000080, 0xe1800003, 0xe12fff1e, + 0xe3510000, 0xe1a030a0, 0x1a000011, 0xe2033001, 0xe1a010a0, 0xe2011002, + 0xe2002001, 0xe1813003, 0xe1a01080, 0xe1833102, 0xe2011010, 0xe1a02080, + 0xe1811003, 0xe2022020, 0xe1a03120, 0xe1822001, 0xe2033008, 0xe1833002, + 0xe20000c0, 0xe1800003, 0xe12fff1e, 0xe2001001, 0xe2033001, 0xe1a03103, + 0xe1a02e80, 0xe1833081, 0xe1a010a0, 0xe1833fa2, 0xe2011008, 0xe1a020a0, + 0xe1811003, 0xe2022010, 0xe1a03100, 0xe1822001, 0xe2033020, 0xe1833002, + 0xe20000c0, 0xe1800003, 0xe12fff1e, 0xe3510000, 0xe2003003, 0x1a000011, + 0xe1a020a0, 0xe2022004, 0xe1a01080, 0xe1823003, 0xe2011008, 0xe1a021a0, + 0xe1813003, 0xe2022010, 0xe1822003, 0xe2001020, 0xe1a03100, 0xe1812002, + 0xe2033040, 0xe1a00080, 0xe1833002, 0xe2000080, 0xe1800003, 0xe12fff1e, + 0xe1a02080, 0xe2022008, 0xe1a010a0, 0xe1823003, 0xe2011004, 0xe1a02180, + 0xe1813003, 0xe2022080, 0xe1822003, 0xe2001020, 0xe1a03120, 0xe1812002, + 0xe2033010, 0xe1a000a0, 0xe1833002, 0xe2000040, 0xe1800003, 0xe12fff1e, + 0xe6ef3070, 0xe1a03123, 0xe3530006, 0xca00000e, 0xe3510000, 0xe59f2048, + 0x13a0c00c, 0x102c239c, 0x1581c000, 0xe3a0100c, 0xe0232391, 0xe5932004, + 0xe59f3030, 0xe5933000, 0xe0822003, 0xe59f3028, 0xe0003003, 0xe0820003, + 0xe12fff1e, 0xe3c004ff, 0xe3c0060f, 0xe59f300c, 0xe5932000, 0xe0800002, + 0xe12fff1e, 0xc0015c14, 0xc0015e48, 0x000fff00, 0xe59f300c, 0xe5933000, + 0xe2833a0b, 0xe6e30070, 0xe12fff1e, 0xc0015e4c, 0xe2003001, 0xe1a000a0, + 0xe2000001, 0xe1800083, 0xe12fff1e, 0xe1a03a00, 0xe1a0ca23, 0xe1a03b23, + 0xe3530026, 0xe59f2040, 0xca00000b, 0xe3510000, 0xe59f0038, 0x13a0c00c, + 0x102c039c, 0x1581c000, 0xe3a0100c, 0xe0230391, 0xe5920000, 0xe5933004, + 0xe0800003, 0xe2800905, 0xe12fff1e, 0xe5920000, 0xe2800905, 0xe080000c, + 0xe12fff1e, 0xc0015e4c, 0xc0015c68, 0xe59f3010, 0xe5933000, 0xe2833a22, + 0xe1a00a00, 0xe0830a20, 0xe12fff1e, 0xc0015e4c, 0xe59f3018, 0xe5933000, + 0xe283320a, 0xe3833206, 0xe3833a06, 0xe6ff0070, 0xe1830000, 0xe12fff1e, + 0xc0015e4c, 0xe59f300c, 0xe5933000, 0xe2833a21, 0xe6e30070, 0xe12fff1e, + 0xc0015e4c, 0xe3510000, 0xe1a03220, 0x1a000008, 0xe203300f, 0xe1a01180, + 0xe2011070, 0xe2002001, 0xe1813003, 0xe1833382, 0xe2000cff, 0xe1800003, + 0xe12fff1e, 0xe200100f, 0xe2033007, 0xe1a03083, 0xe1a02c00, 0xe1833201, + 0xe1833fa2, 0xe2000cff, 0xe1800003, 0xe12fff1e, 0xe59f3010, 0xe5933000, + 0xe2833b83, 0xe2833c02, 0xe6e30070, 0xe12fff1e, 0xc0015e4c, 0xe59f3010, + 0xe5933000, 0xe2833a16, 0xe1a00a00, 0xe0830a20, 0xe12fff1e, 0xc0015e4c, + 0xe6ef0070, 0xe59f2040, 0xe5923000, 0xe1500003, 0xe59f3038, 0x1a000007, + 0xe3510000, 0x15812000, 0xe5930000, 0xe5923004, 0xe0800003, 0xe2800b82, + 0xe2800c02, 0xe12fff1e, 0xe5933000, 0xe2833b82, 0xe2833c02, 0xe0830000, + 0xe12fff1e, 0xc0015e3c, 0xc0015e4c, 0xe59f3010, 0xe5933000, 0xe2833a0d, + 0xe1a00a00, 0xe0830a20, 0xe12fff1e, 0xc0015e48, 0xe59f3010, 0xe5933000, + 0xe2833b89, 0xe2833c02, 0xe6e30070, 0xe12fff1e, 0xc0015e4c, 0xe59f3010, + 0xe5933000, 0xe2833901, 0xe1a00a00, 0xe0830a20, 0xe12fff1e, 0xc0015e4c, + 0xe59f300c, 0xe5933000, 0xe2833815, 0xe6f30070, 0xe12fff1e, 0xc0015e48, + 0xe59f300c, 0xe5933000, 0xe2833811, 0xe6f30070, 0xe12fff1e, 0xc0015e48, + 0xe59f300c, 0xe5933000, 0xe2833812, 0xe6f30070, 0xe12fff1e, 0xc0015e48, + 0xe59f300c, 0xe5933000, 0xe2833816, 0xe6f30070, 0xe12fff1e, 0xc0015e48, + 0x00000000, 0xc0013318, 0xc0012264, 0xc0012230, 0xc00121fc, 0x00000001, + 0xc001339c, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0xc00135bc, + 0x00000000, 0x00000000, 0xc0013644, 0x00000003, 0xc0013678, 0x00000000, + 0x00000000, 0x00000000, 0x00000004, 0xc0013a60, 0x00000000, 0x00000000, + 0xc00121fc, 0x00000005, 0xc0013af0, 0x00000000, 0x00000000, 0x00000000, + 0x00000006, 0xc0013e00, 0x00000000, 0x00000000, 0xc00121fc, 0x00000007, + 0xc0013eb4, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0xc0013fac, + 0x00000000, 0x00000000, 0xc00121fc, 0x00000009, 0xc0014020, 0x00000000, + 0x00000000, 0x00000000, 0x0000000a, 0xc00140dc, 0x00000000, 0x00000000, + 0xc00121fc, 0x0000000b, 0xc001415c, 0x00000000, 0x00000000, 0x00000000, + 0x0000000c, 0xc00143a8, 0x00000000, 0x00000000, 0xc00121fc, 0x0000000d, + 0xc00147d8, 0x00000000, 0x00000000, 0xc00121fc, 0x0000000e, 0xc0014848, + 0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0xc0014874, 0x00000000, + 0x00000000, 0xc00121fc, 0x00000010, 0xc00148d4, 0x00000000, 0x00000000, + 0x00000000, 0x00000011, 0xc00148f0, 0x00000000, 0x00000000, 0x00000000, + 0x00000012, 0xc0014914, 0x00000000, 0x00000000, 0x00000000, 0x00000013, + 0xc0014980, 0x00000000, 0x00000000, 0x00000000, 0x00000014, 0xc001499c, + 0x00000000, 0x00000000, 0x00000000, 0x00000015, 0xc00149b8, 0xc0012264, + 0xc0012230, 0xc00121fc, 0x00000016, 0xc0014a0c, 0x00000000, 0x00000000, + 0x00000000, 0x00000017, 0xc0013ecc, 0x00000000, 0x00000000, 0x00000000, + 0x00000018, 0xc0013f4c, 0x00000000, 0x00000000, 0x00000000, 0x00000019, + 0xc0014a28, 0x00000000, 0x00000000, 0x00000000, 0x0000001a, 0xc0013af0, + 0x00000000, 0x00000000, 0x00000000, 0x0000001b, 0xc0014264, 0x00000000, + 0x00000000, 0x00000000, 0x0000001c, 0xc00141e0, 0x00000000, 0x00000000, + 0x00000000, 0x0000001d, 0xc0014444, 0x00000000, 0x00000000, 0xc00121fc, + 0x0000001e, 0xc00144b8, 0x00000000, 0x00000000, 0xc00121fc, 0x0000001f, + 0xc0014a44, 0x00000000, 0x00000000, 0x00000000, 0x00000020, 0xc0014a60, + 0x00000000, 0x00000000, 0x00000000, 0x00000021, 0xc0014a78, 0x00000000, + 0x00000000, 0x00000000, 0x00000022, 0xc0014a90, 0x00000000, 0x00000000, + 0x00000000, 0x00000023, 0xc0014aa8, 0x00000000, 0x00000000, 0x00000000, + 0x00424841, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00060000, 0x01000000, 0x00000000, + 0x00425041, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00070000, 0x01000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000c, 0x00000004, + 0x00000000, 0x0000000a, 0x00000006, 0x00000000, 0x00000034, 0x00000008, + 0x00000000, 0x00000004, 0x0000000c, 0xc0012d2c, 0x00000016, 0x0000000e, + 0xc0013198, 0x0000001c, 0x00000010, 0x00000000, 0x0000001e, 0x00000012, + 0x00000000, 0x00000020, 0x00000014, 0x00000000, 0x00000022, 0x00000016, + 0x00000000, 0x00000024, 0x00000018, 0x00000000, 0x00000026, 0x0000001a, + 0x00000000, 0x00000028, 0x0000001c, 0x00000000, 0x0000002a, 0x0000001e, + 0x00000000, 0x00000040, 0x00000020, 0x00000000, 0x00000030, 0x00000024, + 0xc0012d7c, 0x0000002c, 0x00000028, 0xc0012e64, 0x0000002d, 0x00000029, + 0x00000000, 0x0000002e, 0x0000002a, 0xc0013240, 0x0000002f, 0x0000002b, + 0xc00132d0, 0x0000001a, 0x0000002c, 0x00000000, 0x00000018, 0x0000002e, + 0x00000000, 0x00000019, 0x0000002f, 0xc00131f8, 0x00000012, 0x00000030, + 0xc00130dc, 0x00000014, 0x00000032, 0x00000000, 0x0000000e, 0x00000034, + 0x00000000, 0x00000010, 0x00000036, 0xc0013038, 0x00000006, 0x00000038, + 0x00000000, 0x00000008, 0x0000003a, 0xc0012fa0, 0x0000003c, 0x0000003c, + 0xc0012f34, 0x00000038, 0x00000040, 0xc0012eb8, 0x00000304, 0x000003f0, + 0x00000000, 0x00000308, 0x00000380, 0x00000000, 0x0000030c, 0x00000384, + 0x00000000, 0x00000310, 0x00000388, 0x00000000, 0x00000314, 0x0000038c, + 0x00000000, 0x0000031c, 0x00000300, 0x00000000, 0x00000320, 0x00000304, + 0x00000000, 0x00000324, 0x00000308, 0x00000000, 0x00000328, 0x0000030c, + 0x00000000, 0x0000032c, 0x00000310, 0x00000000, 0x00000330, 0x00000314, + 0x00000000, 0x00000334, 0x00000318, 0x00000000, 0x00000338, 0x0000031c, + 0x00000000, 0x0000033c, 0x00000320, 0x00000000, 0x00000340, 0x00000324, + 0x00000000, 0x00000344, 0x00000328, 0x00000000, 0x00000348, 0x0000032c, + 0x00000000, 0x0000034c, 0x00000330, 0x00000000, 0x00000350, 0x00000334, + 0x00000000, 0x00000354, 0x00000338, 0x00000000, 0x00000358, 0x0000033c, + 0x00000000, 0x00000000, 0x00000010, 0xc0013464, 0x00000004, 0x00000014, + 0xc00134b8, 0x00000008, 0x00000018, 0xc00134f4, 0x0000000c, 0x00000004, + 0xc0013560, 0x00000010, 0x0000000c, 0x00000000, 0x00000014, 0x00000000, + 0x00000000, 0x00000018, 0x00000008, 0x00000000, 0x0000001c, 0x0000001c, + 0x00000000, 0x00000000, 0x00000020, 0xc0013694, 0x00000004, 0x00000058, + 0x00000000, 0x00000008, 0x00000000, 0x00000000, 0x0000000c, 0x00000008, + 0xc0013720, 0x00000010, 0x00000018, 0x00000000, 0x00000014, 0x00000028, + 0xc00137c4, 0x00000018, 0x0000003c, 0x00000000, 0x0000001c, 0x0000002c, + 0x00000000, 0x00000020, 0x00000030, 0x00000000, 0x00000024, 0x00000044, + 0xc0013818, 0x00000028, 0x00000050, 0xc0013870, 0x0000002c, 0x00000004, + 0xc00138cc, 0x00000030, 0x00000038, 0x00000000, 0x00000034, 0x00000040, + 0x00000000, 0x00000038, 0x00000048, 0xc0013920, 0x0000003c, 0x0000001c, + 0x00000000, 0x00000040, 0x0000004c, 0x00000000, 0x00000044, 0x00000010, + 0x00000000, 0x00000048, 0x00000054, 0xc001398c, 0x0000004c, 0x00000024, + 0xc00139a0, 0x00000050, 0x00000014, 0x00000000, 0x00000054, 0x00000034, + 0xc00139f4, 0x00000058, 0x0000000c, 0x00000000, 0x00000014, 0x00000000, + 0xc0013b10, 0x0000001c, 0x00000004, 0x00000000, 0x00000018, 0x0000000c, + 0x00000000, 0x00000000, 0x00000014, 0xc0013b58, 0x0000000c, 0x00000018, + 0x00000000, 0x00000004, 0x0000001c, 0x00000000, 0x00000054, 0x00000024, + 0xc0013ba0, 0x0000004c, 0x00000028, 0x00000000, 0x0000003c, 0x0000002c, + 0x00000000, 0x00000038, 0x00000030, 0x00000000, 0x00000034, 0x00000034, + 0x00000000, 0x00000028, 0x00000038, 0x00000000, 0x00000030, 0x0000003c, + 0x00000000, 0x0000002c, 0x0000004c, 0x00000000, 0x00000024, 0x00000054, + 0xc0013be8, 0x00000078, 0x00000058, 0x00000000, 0x00000084, 0x0000005c, + 0x00000000, 0x00000080, 0x00000060, 0x00000000, 0x00000068, 0x00000068, + 0x00000000, 0x00000058, 0x00000078, 0x00000000, 0x0000005c, 0x00000080, + 0x00000000, 0x00000060, 0x00000084, 0x00000000, 0x000000e4, 0x0000008c, + 0xc0013c30, 0x000000e8, 0x0000009c, 0x00000000, 0x000000ec, 0x000000a0, + 0x00000000, 0x000000bc, 0x000000bc, 0x00000000, 0x0000008c, 0x000000e4, + 0xc0013c8c, 0x0000009c, 0x000000e8, 0x00000000, 0x000000a0, 0x000000ec, + 0x00000000, 0x00000108, 0x00000100, 0xc0013cd4, 0x00000100, 0x00000108, + 0xc0013cd4, 0x00000118, 0x00000118, 0x00000000, 0x00000124, 0x0000011c, + 0xc0013cd4, 0x00000130, 0x00000124, 0xc0013cd4, 0x0000011c, 0x00000130, + 0xc0013cd4, 0x000001fc, 0x00000148, 0x00000000, 0x00000200, 0x00000198, + 0x00000000, 0x00000214, 0x0000019c, 0x00000000, 0x00000228, 0x000001e0, + 0xc0013d88, 0x000001e4, 0x000001e4, 0x00000000, 0x000001f4, 0x000001f4, + 0x00000000, 0x00000148, 0x000001fc, 0x00000000, 0x00000198, 0x00000200, + 0x00000000, 0x0000019c, 0x00000214, 0x00000000, 0x0000021c, 0x0000021c, + 0x00000000, 0x000001e0, 0x00000228, 0x00000000, 0x0000022c, 0x0000022c, + 0x00000000, 0x00000264, 0x00000230, 0xc0013dac, 0x00000260, 0x00000234, + 0xc0013dac, 0x0000025c, 0x00000238, 0xc0013dac, 0x00000258, 0x0000023c, + 0xc0013dac, 0x00000254, 0x00000240, 0xc0013dac, 0x00000250, 0x00000244, + 0xc0013dac, 0x0000024c, 0x00000248, 0xc0013dac, 0x00000248, 0x0000024c, + 0xc0013dac, 0x00000244, 0x00000250, 0xc0013dac, 0x00000240, 0x00000254, + 0xc0013dac, 0x0000023c, 0x00000258, 0xc0013dac, 0x00000238, 0x0000025c, + 0xc0013dac, 0x00000234, 0x00000260, 0xc0013dac, 0x00000230, 0x00000264, + 0xc0013dac, 0x00000270, 0x00000270, 0x00000000, 0x00000008, 0x0000000c, + 0x00000000, 0x00000018, 0x00000008, 0x00000000, 0x0000001c, 0x00000014, + 0x00000000, 0x00000034, 0x00000018, 0x00000000, 0x00000038, 0x0000001c, + 0x00000000, 0x0000003c, 0x00000020, 0x00000000, 0x00000040, 0x00000024, + 0x00000000, 0x00000044, 0x00000028, 0x00000000, 0x00000048, 0x0000002c, + 0x00000000, 0x0000004c, 0x00000030, 0x00000000, 0x00000020, 0x00000034, + 0x00000000, 0x00000054, 0x00000038, 0x00000000, 0x00000058, 0x0000003c, + 0x00000000, 0x0000005c, 0x00000040, 0x00000000, 0x00000068, 0x00000044, + 0x00000000, 0x00000060, 0x00000048, 0x00000000, 0x00000064, 0x0000004c, + 0x00000000, 0x0000006c, 0x00000060, 0x00000000, 0x00000070, 0x00000064, + 0x00000000, 0x00000074, 0x00000068, 0x00000000, 0x0000007c, 0x0000006c, + 0x00000000, 0x00000078, 0x00000070, 0x00000000, 0x0000000c, 0x00000140, + 0x00000000, 0x00000014, 0x00000144, 0x00000000, 0x00000080, 0x00000148, + 0x00000000, 0x00000084, 0x0000014c, 0x00000000, 0x00000088, 0x00000150, + 0x00000000, 0x0000008c, 0x00000154, 0x00000000, 0x00000024, 0x00000164, + 0x00000000, 0x00000028, 0x00000168, 0x00000000, 0x00000030, 0x0000016c, + 0x00000000, 0x0000a004, 0x00000000, 0xc0013f64, 0x0000a000, 0x00000004, + 0x00000000, 0x0000a00c, 0x00000008, 0xc0013f84, 0x0000a008, 0x0000000c, + 0xc0013f64, 0x0000b004, 0x00001000, 0xc0013f64, 0x0000b000, 0x00001004, + 0x00000000, 0x0000b00c, 0x00001008, 0xc0013f84, 0x0000b008, 0x0000100c, + 0xc0013f64, 0x0000c004, 0x00002000, 0xc0013f64, 0x0000c000, 0x00002004, + 0x00000000, 0x0000c00c, 0x00002008, 0xc0013f84, 0x0000c008, 0x0000200c, + 0xc0013f64, 0x0000d004, 0x00003000, 0xc0013f64, 0x0000d000, 0x00003004, + 0x00000000, 0x0000d00c, 0x00003008, 0xc0013f84, 0x0000d008, 0x0000300c, + 0xc0013f64, 0x0000e000, 0x0000e000, 0x00000000, 0x0000e00c, 0x0000e004, + 0x00000000, 0x0000e010, 0x0000e008, 0x00000000, 0x0000e014, 0x0000e00c, + 0x00000000, 0x0000e004, 0x0000e010, 0x00000000, 0x0000e008, 0x0000e014, + 0x00000000, 0x0000e018, 0x0000e018, 0x00000000, 0x0000e01c, 0x0000e01c, + 0x00000000, 0x0000e058, 0x0000e020, 0x00000000, 0x0000e040, 0x0000e040, + 0x00000000, 0x0000e044, 0x0000e044, 0x00000000, 0x0000e048, 0x0000e048, + 0x00000000, 0x0000e04c, 0x0000e04c, 0x00000000, 0x0000e050, 0x0000e050, + 0x00000000, 0x0000e054, 0x0000e054, 0x00000000, 0x0000f008, 0x0000f000, + 0x00000000, 0x0000f000, 0x0000f004, 0x00000000, 0x0000f004, 0x0000f008, + 0x00000000, 0x0000f00c, 0x0000f00c, 0x00000000, 0x0000f010, 0x0000f010, + 0x00000000, 0x0000f014, 0x0000f014, 0x00000000, 0x0000f020, 0x0000f018, + 0x00000000, 0x0000f01c, 0x0000f01c, 0x00000000, 0x0000f018, 0x0000f020, + 0x00000000, 0x0000f048, 0x0000f048, 0x00000000, 0x0000f04c, 0x0000f04c, + 0x00000000, 0x0000f040, 0x0000f050, 0x00000000, 0x0000f044, 0x0000f054, + 0x00000000, 0x00000000, 0x00000000, 0x0000000c, 0xc0014098, 0x00000004, + 0x00000010, 0x00000000, 0x00000008, 0x00000014, 0x00000000, 0x0000000c, + 0x00000000, 0x00000000, 0x00000010, 0x00000004, 0x00000000, 0x00000014, + 0x00000008, 0x00000000, 0x00000018, 0x00000018, 0x00000000, 0x0000000c, + 0x00000000, 0x00000000, 0x00000010, 0x00000004, 0x00000000, 0x00000008, + 0x00000008, 0x00000000, 0x00000014, 0x0000000c, 0x00000000, 0x00000060, + 0x00000010, 0x00000000, 0x00000018, 0x00000014, 0x00000000, 0x0000003c, + 0x00000018, 0x00000000, 0x00000048, 0x0000001c, 0x00000000, 0x00000040, + 0x00000020, 0x00000000, 0x0000004c, 0x00000024, 0x00000000, 0x00000004, + 0x00000028, 0x00000000, 0x0000001c, 0x0000002c, 0x00000000, 0x00000030, + 0x00000030, 0x00000000, 0x0000002c, 0x00000034, 0x00000000, 0x00000044, + 0x00000038, 0x00000000, 0x00000050, 0x0000003c, 0x00000000, 0x00000054, + 0x00000040, 0x00000000, 0x00000024, 0x00000044, 0x00000000, 0x00000020, + 0x00000048, 0x00000000, 0x00000028, 0x0000004c, 0x00000000, 0x00000034, + 0x00000050, 0x00000000, 0x00000058, 0x00000054, 0x00000000, 0x00000000, + 0x00000058, 0x00000000, 0x0000005c, 0x0000005c, 0x00000000, 0x00000038, + 0x00000060, 0x00000000, 0x00000004, 0x00000000, 0x00000000, 0x00000000, + 0x00000004, 0x00000000, 0x0000000c, 0x00000008, 0x00000000, 0x00000008, + 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000004, + 0x00000008, 0x00000000, 0x00000008, 0x0000000c, 0x00000000, 0x0000000c, + 0x00000030, 0xc00142f0, 0x00000010, 0x000000ff, 0x00000000, 0x00000014, + 0x00000010, 0x00000000, 0x00000018, 0x00000018, 0x00000000, 0x0000001c, + 0x0000001c, 0x00000000, 0x00000020, 0x00000020, 0x00000000, 0x00000024, + 0x00000028, 0x00000000, 0x00000028, 0x0000002c, 0x00000000, 0x0000002c, + 0x000000ff, 0x00000000, 0x00000030, 0x00000004, 0x00000000, 0x00000034, + 0x00000014, 0x00000000, 0x00000038, 0x00000024, 0x00000000, 0x00000000, + 0x00000024, 0xc0014404, 0x00000004, 0x0000002c, 0xc0014404, 0x00000008, + 0x00000028, 0xc0014404, 0x0000000c, 0x0000000c, 0xc0014404, 0x00000010, + 0x00000010, 0xc0014404, 0x00000014, 0x00000014, 0xc0014404, 0x00000018, + 0x00000008, 0xc0014404, 0x0000001c, 0x00000018, 0xc0014404, 0x00000020, + 0x0000001c, 0xc0014404, 0x00000024, 0x00000020, 0x00000000, 0x00000028, + 0x00000030, 0x00000000, 0x0000002c, 0x00000034, 0x00000000, 0x00000030, + 0x00000000, 0xc0014404, 0x00000034, 0x00000004, 0xc0014404, 0x00000038, + 0x00000038, 0xc0014404, 0x00000000, 0x00000024, 0xc0014424, 0x00000004, + 0x0000002c, 0xc0014424, 0x00000008, 0x00000028, 0xc0014424, 0x0000000c, + 0x0000000c, 0xc0014424, 0x00000010, 0x00000010, 0xc0014424, 0x00000014, + 0x00000014, 0xc0014424, 0x00000018, 0x00000008, 0xc0014424, 0x0000001c, + 0x00000018, 0xc0014424, 0x00000020, 0x0000001c, 0xc0014424, 0x00000024, + 0x00000020, 0x00000000, 0x00000028, 0x00000030, 0x00000000, 0x0000002c, + 0x00000034, 0x00000000, 0x00000030, 0x00000000, 0xc0014424, 0x00000034, + 0x00000004, 0xc0014424, 0x00000038, 0x00000038, 0xc0014424, 0x00000000, + 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0x00000000, 0x00000008, + 0x00000008, 0x00000000, 0x0000000c, 0x00000010, 0xc0014568, 0x00000010, + 0x00000018, 0xc00145f0, 0x00000014, 0x00000014, 0xc00146a0, 0x00000018, + 0x0000000c, 0xc001473c, 0x00000000, 0x00000020, 0x00000000, 0x00000004, + 0x00000010, 0x00000000, 0x00000008, 0x00000004, 0x00000000, 0x0000000c, + 0x00000000, 0x00000000, 0x00000010, 0x0000000c, 0x00000000, 0x00000014, + 0x00000008, 0x00000000, 0x00000018, 0x00000014, 0x00000000, 0x0000001c, + 0x0000001c, 0x00000000, 0x00000020, 0x00000018, 0x00000000, 0x00000024, + 0x00000098, 0xc0014860, 0x00000028, 0x00000094, 0x00000000, 0x0000002c, + 0x0000007c, 0x00000000, 0x00000030, 0x00000068, 0x00000000, 0x00000034, + 0x00000064, 0x00000000, 0x00000038, 0x00000060, 0x00000000, 0x0000003c, + 0x0000005c, 0x00000000, 0x00000040, 0x00000058, 0x00000000, 0x00000044, + 0x00000054, 0x00000000, 0x00000048, 0x00000050, 0x00000000, 0x0000004c, + 0x0000004c, 0x00000000, 0x00000050, 0x00000048, 0x00000000, 0x00000054, + 0x00000044, 0x00000000, 0x00000058, 0x00000040, 0x00000000, 0x0000005c, + 0x0000003c, 0x00000000, 0x00000060, 0x00000038, 0x00000000, 0x00000064, + 0x00000034, 0x00000000, 0x00000068, 0x00000030, 0x00000000, 0x0000006c, + 0x0000002c, 0x00000000, 0x00000070, 0x00000028, 0x00000000, 0x00000074, + 0x00000024, 0x00000000, 0x00000078, 0x00000078, 0x00000000, 0x0000007c, + 0x00000074, 0x00000000, 0x00000080, 0x00000070, 0x00000000, 0x00000084, + 0x0000006c, 0x00000000, 0x00000088, 0x00000080, 0x00000000, 0x0000008c, + 0x00000090, 0x00000000, 0x00000090, 0x0000008c, 0x00000000, 0x00000094, + 0x00000088, 0x00000000, 0x00000098, 0x00000084, 0x00000000, 0x00000000, + 0x00000000, 0xc001492c, +}; diff --git a/arch/arm/mach-gk710x/include/mach/gk710x.h b/arch/arm/mach-gk710x/include/mach/gk710x.h new file mode 100644 index 000000000000..2b89f1180d8d --- /dev/null +++ b/arch/arm/mach-gk710x/include/mach/gk710x.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Goke GK7101 / GK7102: the silicon register map. + * + * The vendor U-Boot and kernel never touch these addresses. They go through + * a HAL blob (hal_data.h) that takes a fictitious map (AHB 0x90000000, APB + * 0xA0000000), moves each block to its real place, shuffles registers inside + * some blocks and permutes the bits of some registers. The addresses and + * values here are what the HAL itself writes, recovered by executing it + * (qemu-hisilicon's qemu-boot/gk710x-halmap.py). Underneath, the UART is a + * 16550, the MAC a Synopsys DWMAC and the timers and watchdog Ambarella's. + */ + +#ifndef __MACH_GK710X_H +#define __MACH_GK710X_H + +#define GK_DDR_BASE 0xC0000000 +#define GK_DDR_MAX 0x08000000 /* GK7101 */ + +/* AHB */ +#define GK_DDRC_BASE 0x60004000 +#define GK_DDRC_CFG (GK_DDRC_BASE + 0x04) /* from the boot header */ +#define GK_DDRC_CFG_128M 0x00100354 +#define GK_GMAC_BASE 0x6000E000 +#define GK_SFLASH_BASE 0x60016000 +#define GK_AHB_GENERAL0 0x60020E00 /* bit 1: external PHY */ +#define GK_EPHY_BASE 0x60022000 /* MII register n at +4n */ + +/* APB */ +#define GK_UART0_BASE 0x70005000 +#define GK_GPIO_BASE 0x70009000 +#define GK_TIMER_BASE 0x7000B000 +#define GK_WDT_BASE 0x7000C000 +#define GK_RCT_BASE 0x70170000 + +#define GK_UART_CLK 24000000 + +/* Timer 1 counts down at the APB clock; control is a nibble per timer */ +#define GK_APB_CLK 69000000 +#define GK_TIMER1_STATUS (GK_TIMER_BASE + 0x00) +#define GK_TIMER1_RELOAD (GK_TIMER_BASE + 0x04) +#define GK_TIMER_CTRL (GK_TIMER_BASE + 0x30) +#define GK_TIMER_CTRL_EN 0x1 + +#define GK_WDT_RELOAD (GK_WDT_BASE + 0x04) +#define GK_WDT_RESTART (GK_WDT_BASE + 0x08) +#define GK_WDT_CTRL (GK_WDT_BASE + 0x0C) +#define GK_WDT_MAGIC 0x4755 +#define GK_WDT_CTRL_EN 0x1 +#define GK_WDT_CTRL_RESET 0x2 + +/* GPIO: a function word per pin and a pin number per input function */ +#define GK_GPIO_IN_EN (GK_GPIO_BASE + 0x038) +#define GK_GPIO_PER_SEL (GK_GPIO_BASE + 0x03C) /* bit 0: external PHY */ +#define GK_GPIO_OUTPUT_CFG(n) (GK_GPIO_BASE + 0x100 + 4 * (n)) +#define GK_GPIO_INPUT_CFG(n) (GK_GPIO_BASE + 0x200 + 4 * (n)) + +/* RCT: clocks and pad control */ +#define GK_RCT_PLL_AUDIO_CTRL (GK_RCT_BASE + 0x054) +#define GK_RCT_PLL_AUDIO_FRAC (GK_RCT_BASE + 0x058) +#define GK_RCT_DIV_AUDIO_PST (GK_RCT_BASE + 0x05C) +#define GK_RCT_DIV_AUDIO_PRE (GK_RCT_BASE + 0x060) +#define GK_RCT_SCALER_UART (GK_RCT_BASE + 0x038) +#define GK_RCT_PLL_CORE (GK_RCT_BASE + 0x0E4) +#define GK_RCT_IOCTRL_MISC2 (GK_RCT_BASE + 0x200) +/* Pad drive and pull: one byte per pin, four pins per word */ +#define GK_RCT_IOCTRL_GPIO(n) (GK_RCT_BASE + 0x230 + 4 * ((n) / 4)) + +/* + * What the vendor U-Boot leaves for the kernel (include/configs/gk7101.h): + * the HAL, its address, and a few words of board parameters ("U2K") at the + * bottom of DDR; the board's GPIO map in its top 64 KiB. + */ +#define GK_HAL_ADDR (GK_DDR_BASE + 0x12000) +#define GK_U2K_PHY_TYPE (GK_DDR_BASE + 0x00) +#define GK_U2K_ARM_FREQ (GK_DDR_BASE + 0x04) +#define GK_U2K_HAL_ADDR (GK_DDR_BASE + 0x08) +#define GK_U2K_SOC (GK_DDR_BASE + 0x10) +#define GK_U2K_MEM (GK_DDR_BASE + 0x14) +#define GK_U2K_BSB (GK_DDR_BASE + 0x18) +#define GK_U2K_ENABLE (GK_DDR_BASE + 0x20) +#define GK_U2K_USR (GK_DDR_BASE + 0x24) +#define GK_U2K_TOTAL_MEM (GK_DDR_BASE + 0x28) +#define GK_U2K_MAGIC 0x7101 +#define GK_USR_SIZE 0x10000 + +/* The CPU PLL setting the vendor U-Boot programs, as the HAL takes it */ +#define GK_ARM_FREQ 0x00112032 + +#ifndef __ASSEMBLY__ +void gk_gpio_config(unsigned int pin, unsigned int type); +void gk_gpio_init(void); +/* board/goke/gk710x/gpio_map.c */ +void gk_gpio_map_apply(void); +void gk_gpio_map_save(void *dst); +#endif + +#endif diff --git a/arch/arm/mach-gk710x/kernel.c b/arch/arm/mach-gk710x/kernel.c new file mode 100644 index 000000000000..fc640664ffa4 --- /dev/null +++ b/arch/arm/mach-gk710x/kernel.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * What the GK710x kernel needs from its boot loader besides ATAGs, as the + * vendor U-Boot leaves it (common/cmd_bootm.c, CONFIG_UBOOT_TO_KERNEL): + * - the HAL blob at GK_HAL_ADDR and that address in a U2K word; + * - the other U2K words: total DDR, the BSB (bitstream buffer) carved out + * above the kernel's mem=, the PHY type; + * - the board's GPIO map in the top 64 KiB of DDR, which the kernel + * applies itself (board/goke/gk710x). + * The kernel places its DSP memory from mem=, bsbsize and the total. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hal_data.h" + +DECLARE_GLOBAL_DATA_PTR; + +/* A size as the kernel's mem= reads it: bytes, 0x for hex, K/M/G suffix */ +static ulong env_size(const char *name, const char *def) +{ + const char *s = env_get(name); + char *end; + + return ustrtoul(s ? s : def, &end, 0); +} + +void board_prep_linux(bootm_headers_t *images) +{ + const ulong top = GK_DDR_BASE + gd->ram_size; + + memcpy((void *)GK_HAL_ADDR, gk_hal_data, sizeof(gk_hal_data)); + + writel(env_get_ulong("phytype", 10, 0), GK_U2K_PHY_TYPE); + writel(GK_ARM_FREQ, GK_U2K_ARM_FREQ); + writel(GK_HAL_ADDR, GK_U2K_HAL_ADDR); + writel(0, GK_U2K_SOC); + writel(env_size("osmem", OPENIPC_OSMEM), GK_U2K_MEM); + writel(env_size("bsbsize", __stringify(GK_BSB_MIB) "M"), GK_U2K_BSB); + writel(GK_U2K_MAGIC, GK_U2K_ENABLE); + writel(0, GK_U2K_USR); + writel(gd->ram_size / SZ_1M, GK_U2K_TOTAL_MEM); + + gk_gpio_map_save((void *)(top - GK_USR_SIZE)); +} diff --git a/arch/arm/mach-gk710x/lowlevel_init.S b/arch/arm/mach-gk710x/lowlevel_init.S new file mode 100644 index 000000000000..e732209b526f --- /dev/null +++ b/arch/arm/mach-gk710x/lowlevel_init.S @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * The boot ROM has already run the PLL and DDR set-up from the flash + * header and copied U-Boot into DDR: nothing is left to do here. + */ + +#include + +ENTRY(lowlevel_init) + mov pc, lr +ENDPROC(lowlevel_init) diff --git a/arch/arm/mach-gk710x/soc.c b/arch/arm/mach-gk710x/soc.c new file mode 100644 index 000000000000..985eb2c2a6aa --- /dev/null +++ b/arch/arm/mach-gk710x/soc.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Goke GK7101 / GK7102: clocks, timer, reset and DRAM size. + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int arch_cpu_init(void) +{ + /* + * The CPU PLL and the UART divider as the vendor U-Boot sets them + * (arm_freq 0x00112032 and REG_PLL_SCALER_UART 1), in silicon bit + * order: the HAL permutes the PLL word on its way to the register. + */ + writel(0x01203201, GK_RCT_PLL_CORE); + writel(1, GK_RCT_SCALER_UART); + return 0; +} + +int timer_init(void) +{ + u32 ctrl = readl(GK_TIMER_CTRL) & ~0xf; + + /* Timer 1, free running over the whole 32 bits for lib/time.c */ + writel(ctrl, GK_TIMER_CTRL); + writel(0xffffffff, GK_TIMER1_STATUS); + writel(0xffffffff, GK_TIMER1_RELOAD); + writel(ctrl | GK_TIMER_CTRL_EN, GK_TIMER_CTRL); + gd->arch.tbl = 0; + gd->arch.tbu = 0; + return 0; +} + +void reset_cpu(void) +{ + writel(0xff, GK_WDT_RELOAD); + writel(GK_WDT_MAGIC, GK_WDT_RESTART); + writel(GK_WDT_CTRL_EN | GK_WDT_CTRL_RESET, GK_WDT_CTRL); + while (1) + ; +} + +/* The boot header's DDR controller set-up tells the 128 MiB GK7101 apart */ +int dram_init(void) +{ + ulong max = readl(GK_DDRC_CFG) == GK_DDRC_CFG_128M ? SZ_128M : SZ_64M; + + gd->ram_size = get_ram_size((long *)GK_DDR_BASE, max); + return 0; +} + +/* The top 64 KiB carry the GPIO map to the kernel: keep U-Boot below it */ +ulong board_get_usable_ram_top(ulong total_size) +{ + return gd->ram_top - GK_USR_SIZE; +} + +#ifdef CONFIG_DISPLAY_CPUINFO +int print_cpuinfo(void) +{ + printf("CPU: Goke %s\n", CONFIG_PRODUCT_SOC); + return 0; +} +#endif diff --git a/board/goke/gk710x/Makefile b/board/goke/gk710x/Makefile new file mode 100644 index 000000000000..195d83388844 --- /dev/null +++ b/board/goke/gk710x/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += gk710x.o gpio_map.o diff --git a/board/goke/gk710x/gk710x.c b/board/goke/gk710x/gk710x.c new file mode 100644 index 000000000000..ca70ab49112d --- /dev/null +++ b/board/goke/gk710x/gk710x.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Goke GK7101 / GK7102 camera board, after the vendor U-Boot 2012.10 + * (board/goke/gk7101/gk7101.c, drivers/net/goke_eth.c) with its HAL calls + * replaced by the silicon accesses they make. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int board_init(void) +{ + gd->bd->bi_boot_params = GK_DDR_BASE + 0x100; + return 0; +} + +int misc_init_r(void) +{ + gk_gpio_map_apply(); + return openipc_helper(); +} + +#ifdef CONFIG_ETH_DESIGNWARE +/* + * The internal 10/100 PHY is not on the GMAC's MDIO bus: its MII registers + * are memory mapped, register n in the low half of the word at +4n (the + * vendor kernel's gkhw_mdio_read() with phytype=0). It answers at address 0. + */ +static int gk_ephy_read(struct mii_dev *bus, int addr, int devad, int reg) +{ + return addr ? 0xffff : readl(GK_EPHY_BASE + 4 * reg) & 0xffff; +} + +static int gk_ephy_write(struct mii_dev *bus, int addr, int devad, int reg, + u16 val) +{ + if (!addr) + writel(val, GK_EPHY_BASE + 4 * reg); + return 0; +} + +/* The analog trim gk7101_ethphy_init() writes, byte by byte */ +static const struct { + u16 off; + u8 val; +} gk_ephy_trim[] = { + { 0x3bc, 0x59 }, { 0x3e8, 0x21 }, { 0x0e4, 0x80 }, { 0x3f8, 0x00 }, + { 0x3f9, 0x00 }, { 0x36d, 0x07 }, { 0x395, 0x11 }, { 0x398, 0x80 }, + { 0x399, 0xd1 }, { 0x3a8, 0x00 }, { 0x371, 0x40 }, { 0x375, 0x05 }, + { 0x3d4, 0x46 }, { 0x341, 0x00 }, { 0x474, 0x03 }, { 0x475, 0x00 }, + { 0x368, 0x56 }, /* gain shift */ + { 0x29d, 0x02 }, /* det max */ + { 0x2a1, 0x01 }, /* det min */ + { 0x2ed, 0x18 }, /* snr len (EMC noise) */ + { 0x285, 0x15 }, /* snr k */ + { 0x589, 0x00 }, /* 100 gat */ + { 0x460, 0x43 }, /* 200 gat */ + { 0x471, 0x41 }, /* en_100t_phase */ + { 0x055, 0x00 }, + { 0x3b0, 0xb0 }, { 0x3b1, 0x30 }, /* analog */ +}; + +static void gk_ephy_init(void) +{ + int i; + + /* Its reference clock: the audio PLL at 96 MHz / 4, out on a pin */ + writel(0x02402001, GK_RCT_PLL_AUDIO_CTRL); + writel(0, GK_RCT_PLL_AUDIO_FRAC); + writel(4, GK_RCT_DIV_AUDIO_PST); + writel(1, GK_RCT_DIV_AUDIO_PRE); + writel(readl(GK_GPIO_PER_SEL) & ~1, GK_GPIO_PER_SEL); + + writel(0, GK_EPHY_BASE + 0x540); /* MDIO error count */ + writel(0xc400, GK_EPHY_BASE + 0xc8); /* mux: test out */ + writel(0x810a, GK_EPHY_BASE + 0xe0); /* signal select */ + writel(7, GK_EPHY_BASE + 0x588); /* DAC 100M clock gate for 10M */ + for (i = 0; i < ARRAY_SIZE(gk_ephy_trim); i++) + writeb(gk_ephy_trim[i].val, GK_EPHY_BASE + gk_ephy_trim[i].off); + /* 10BASE-T waveform */ + writeb((readb(GK_EPHY_BASE + 0x5d0) & 0xf8) | 0x06, GK_EPHY_BASE + 0x5d0); + /* EEE off */ + writeb(readb(GK_EPHY_BASE + 0x059) | 0x40, GK_EPHY_BASE + 0x059); + writel(readl(GK_EPHY_BASE + 0x58) | BIT(12), GK_EPHY_BASE + 0x58); + + /* The MAC talks to the internal PHY, not the MII pins */ + writel(readl(GK_AHB_GENERAL0) & ~BIT(1), GK_AHB_GENERAL0); +} + +int board_eth_init(struct bd_info *bis) +{ + struct mii_dev *bus = mdio_alloc(); + int ret; + + if (!bus) + return -ENOMEM; + gk_ephy_init(); + + /* designware_initialize() takes a bus already named after its device */ + snprintf(bus->name, sizeof(bus->name), "dwmac.%x", GK_GMAC_BASE); + bus->read = gk_ephy_read; + bus->write = gk_ephy_write; + ret = mdio_register(bus); + if (ret) { + free(bus); + return ret; + } + + return designware_initialize(GK_GMAC_BASE, PHY_INTERFACE_MODE_MII); +} +#endif diff --git a/board/goke/gk710x/gpio_map.c b/board/goke/gk710x/gpio_map.c new file mode 100644 index 000000000000..b7ee9a0bf14d --- /dev/null +++ b/board/goke/gk710x/gpio_map.c @@ -0,0 +1,300 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * GPIO maps of the Goke GK7101/GK7102 reference boards, which camera makers + * copied, and the copy the kernel takes over. + * + * The vendor U-Boot builds one image per board (arch-gk7101/gpio_rb_*.h) + * and leaves that board's map in the top 64 KiB of DDR; the vendor kernel, + * OpenIPC's included, reads it from there ("gpio map get from uboot") and + * configures every pin from it -- sensor I2C and reset, IR cut, SD, the + * Ethernet PHY pins. Without a map the camera boots with no sensor bus. + * + * The SDK's 20-odd board headers come down to two layouts: + * - v2 (the default): GK7102 rb-sc1035 v2.1, rb-sc1045, rb-imx225, + * rb-ov9750, rb-jxh42 v2.0, ak-gc1024, GK7101 rb-ov2710 v2.2. + * UART0 on GPIO 25/26, SD on 39-47. + * - v1: GK7102 rb-ov9712, rb-ar0130, rb-jxh42 v1.0, GK7101 rb-imx222. + * UART0 on GPIO 30/31, the external-PHY pins on 41-47. + * gpiomap=v1 in the environment selects the second. + * + * Pin types are the vendor's GPIO_TYPE_* words (mach-gk710x/gpio.c), named + * in the comments; the tables were generated from the SDK headers. + */ + +#include +#include +#include + +struct gk_gpio_pin { + u32 pin; + u32 type; +}; + +static const struct gk_gpio_pin v2_xref[] = { + { 0, 0xa0000024 }, /* output_sf_cs0 */ + { 1, 0xa0000025 }, /* output_sf_cs1 */ + { 2, 0x40010000 }, /* input */ + { 4, 0x40010000 }, /* input */ + { 5, 0x40010000 }, /* input */ + { 6, 0x40010000 }, /* input */ + { 7, 0x40010000 }, /* input */ + { 8, 0x40010000 }, /* input */ + { 9, 0x40010000 }, /* input */ + { 10, 0x40010000 }, /* input */ + { 11, 0x40010000 }, /* input */ + { 12, 0xa0000000 }, /* output_0 (IR_LED_CTRL) */ + { 13, 0x40010000 }, /* input */ + { 14, 0x40010000 }, /* input */ + { 15, 0x40010000 }, /* input (IR_DET_ADC) */ + { 16, 0x40010000 }, /* input */ + { 17, 0x40010000 }, /* input */ + { 18, 0x40010000 }, /* input */ + { 19, 0x40010000 }, /* input */ + { 20, 0xa0000000 }, /* output_0 (IR_CUT+) */ + { 21, 0x40010000 }, /* input */ + { 22, 0x40010000 }, /* input */ + { 23, 0xa0000000 }, /* output_0 (IR_CUT-) */ + { 24, 0x40010000 }, /* input */ + { 25, 0x50010900 }, /* input_uart0_rx */ + { 26, 0x90000009 }, /* output_uart0_tx */ + { 27, 0xa0000001 }, /* output_1 (Sensor reset) */ + { 28, 0xd0030300 }, /* inout_i2c_data (S D) */ + { 29, 0xd0040400 }, /* inout_i2c_clk (S C) */ + { 34, 0x40010000 }, /* input */ + { 37, 0x40010000 }, /* input */ + { 38, 0x40010000 }, /* input */ + { 39, 0x50010f00 }, /* input_sd_cd_n */ + { 40, 0x40010000 }, /* input */ + { 41, 0xd08b1319 }, /* inout_sd_data_3 */ + { 42, 0xd08a1218 }, /* inout_sd_data_2 */ + { 43, 0xd090181e }, /* inout_sd_cmd */ + { 44, 0x9000001f }, /* output_sdio_clk */ + { 45, 0xd0891117 }, /* inout_sd_data_1 */ + { 46, 0xa0000001 }, /* output_1 (SDIO_CARD_POWER_EN) */ + { 47, 0xd0881016 }, /* inout_sd_data_0 */ + { 55, 0x40010000 }, /* input */ +}; + +static const struct gk_gpio_pin v2_intphy[] = { + { 3, 0x40010000 }, /* input */ + { 30, 0x40010000 }, /* input */ + { 31, 0x40010000 }, /* input */ + { 32, 0x40010000 }, /* input */ + { 33, 0x40010000 }, /* input */ + { 35, 0x40010000 }, /* input */ + { 36, 0x40010000 }, /* input */ + { 48, 0xa0000020 }, /* output_aomclk */ + { 49, 0x40010000 }, /* input */ + { 50, 0x40010000 }, /* input */ + { 51, 0x40010000 }, /* input */ + { 52, 0x40010000 }, /* input */ + { 53, 0x40010000 }, /* input */ + { 54, 0xa0000029 }, /* output_ephy_led_3 */ +}; + +static const struct gk_gpio_pin v2_extphy[] = { + { 3, 0x60012400 }, /* input_enet_phy_rxdv */ + { 30, 0xa0000030 }, /* output_enet_phy_txen */ + { 31, 0xa000002c }, /* output_enet_phy_txd_1 */ + { 32, 0xa000002b }, /* output_enet_phy_txd_0 */ + { 33, 0x60012300 }, /* input_enet_phy_rxer */ + { 35, 0xa0000032 }, /* output_enet_gmii_mdc_o */ + { 36, 0xe0932531 }, /* inout_eth_mdio */ + { 48, 0x40010000 }, /* input */ + { 49, 0xa0000001 }, /* output_1 (ETH reset) */ + { 50, 0xa0000020 }, /* output_aomclk */ + { 51, 0x60011e00 }, /* input_enet_phy_rxd_1 */ + { 52, 0x60011f00 }, /* input_enet_phy_rxd_2 (CLK) */ + { 53, 0x60011d00 }, /* input_enet_phy_rxd_0 */ + { 54, 0x40010000 }, /* input */ +}; + +static const struct gk_gpio_pin v1_xref[] = { + { 0, 0xa0000024 }, /* output_sf_cs0 */ + { 1, 0xa0000025 }, /* output_sf_cs1 */ + { 4, 0x40010000 }, /* input */ + { 5, 0x40010000 }, /* input */ + { 6, 0x40010000 }, /* input */ + { 7, 0x40010000 }, /* input */ + { 8, 0x40010000 }, /* input */ + { 9, 0x40010000 }, /* input */ + { 10, 0x40010000 }, /* input */ + { 11, 0x40010000 }, /* input */ + { 12, 0xa0000000 }, /* output_0 (IR_LED_CTRL) */ + { 13, 0x40010000 }, /* input */ + { 14, 0x40010000 }, /* input */ + { 15, 0x40010000 }, /* input (IR_DET_ADC) */ + { 16, 0x40010000 }, /* input */ + { 17, 0x40010000 }, /* input */ + { 18, 0x40010000 }, /* input */ + { 19, 0x40010000 }, /* input */ + { 20, 0xa0000000 }, /* output_0 (IR_CUT+) */ + { 21, 0x40010000 }, /* input */ + { 22, 0x40010000 }, /* input */ + { 23, 0xa0000000 }, /* output_0 (IR_CUT-) */ + { 24, 0x40010000 }, /* input */ + { 25, 0x40010000 }, /* input */ + { 26, 0x40010000 }, /* input */ + { 27, 0xa0000001 }, /* output_1 (Sensor reset) */ + { 28, 0xd0030300 }, /* inout_i2c_data (S D) */ + { 29, 0xd0040400 }, /* inout_i2c_clk (S C) */ + { 30, 0x90000009 }, /* output_uart0_tx */ + { 31, 0x50010900 }, /* input_uart0_rx */ + { 34, 0x40010000 }, /* input */ + { 35, 0xd0050500 }, /* inout_i2c_data2 */ + { 36, 0xd0060600 }, /* inout_i2c_clk2 */ + { 37, 0x40010000 }, /* input */ + { 38, 0x40010000 }, /* input */ + { 39, 0x40010000 }, /* input */ + { 40, 0x40010000 }, /* input */ + { 42, 0x40010000 }, /* input */ + { 45, 0x40010000 }, /* input */ + { 53, 0x40010000 }, /* input (ALARM_OUT) */ + { 54, 0x40010000 }, /* input (ALARM_IN) */ + { 55, 0x40010000 }, /* input */ +}; + +static const struct gk_gpio_pin v1_intphy[] = { + { 2, 0x40010000 }, /* input */ + { 3, 0x40010000 }, /* input */ + { 32, 0x40010000 }, /* input */ + { 33, 0x40010000 }, /* input */ + { 41, 0x40010000 }, /* input */ + { 43, 0x40010000 }, /* input */ + { 44, 0x40010000 }, /* input */ + { 46, 0x40010000 }, /* input */ + { 47, 0x40010000 }, /* input */ + { 48, 0xa0000020 }, /* output_aomclk */ + { 49, 0xa0000029 }, /* output_ephy_led_3 */ + { 50, 0x40010000 }, /* input */ + { 51, 0x40010000 }, /* input */ + { 52, 0x40010000 }, /* input */ +}; + +static const struct gk_gpio_pin v1_extphy[] = { + { 2, 0x60012300 }, /* input_enet_phy_rxer */ + { 3, 0xa0000032 }, /* output_enet_gmii_mdc_o */ + { 32, 0x60011e00 }, /* input_enet_phy_rxd_1 */ + { 33, 0xe0932531 }, /* inout_eth_mdio */ + { 41, 0xa0000001 }, /* output_1 (ETH reset) */ + { 43, 0xa0000020 }, /* output_aomclk */ + { 44, 0xa0000030 }, /* output_enet_phy_txen */ + { 46, 0xa000002c }, /* output_enet_phy_txd_1 */ + { 47, 0xa000002b }, /* output_enet_phy_txd_0 */ + { 48, 0x40010000 }, /* input */ + { 49, 0x40010000 }, /* input */ + { 50, 0x60011f00 }, /* input_enet_phy_rxd_2 (CLK) */ + { 51, 0x60012400 }, /* input_enet_phy_rxdv */ + { 52, 0x60011d00 }, /* input_enet_phy_rxd_0 */ +}; + +struct gk_gpio_map { + const char *name; + const struct gk_gpio_pin *pins, *intphy, *extphy; + u32 npins, nintphy, nextphy; + /* the pins the kernel drives itself, in gpio_cfg_t order */ + u32 ir_led_ctl, ir_cut1, ir_cut2, sensor_reset, phy_reset, phy_speed_led; + u32 spi0_en0, spi1_en0, pwm[4], usb_host, sd_detect, sd_power, pmu_ctl; +}; + +#define MAP(v) .pins = v##_xref, .npins = ARRAY_SIZE(v##_xref), \ + .intphy = v##_intphy, .nintphy = ARRAY_SIZE(v##_intphy), \ + .extphy = v##_extphy, .nextphy = ARRAY_SIZE(v##_extphy) + +static const struct gk_gpio_map gk_maps[] = { + { + .name = "v2", MAP(v2), + .ir_led_ctl = 4, .ir_cut1 = 20, .ir_cut2 = 23, + .sensor_reset = 27, .phy_reset = 49, .phy_speed_led = 54, + .spi0_en0 = 5, .spi1_en0 = 6, .pwm = { 7, 8, 9, 10 }, + .usb_host = 11, .sd_detect = 39, .sd_power = 46, .pmu_ctl = 55, + }, { + .name = "v1", MAP(v1), + .ir_led_ctl = 12, .ir_cut1 = 20, .ir_cut2 = 23, + .sensor_reset = 27, .phy_reset = 41, .phy_speed_led = 49, + .spi0_en0 = 37, .spi1_en0 = 38, .pwm = { 39, 40, 42, 45 }, + .usb_host = 55, .sd_detect = 4, .sd_power = 5, .pmu_ctl = 55, + }, +}; + +/* The vendor's gpio_cfg_t (drivers/gpio/goke_gpio.c), as the kernel reads it */ +struct gk_gpio_cfg { + u32 gpio_count; + struct gk_gpio_pin gpio_chip[64]; + u32 extphy_gpio_count; + struct gk_gpio_pin ext_phy_gpio[16]; + u32 intphy_gpio_count; + struct gk_gpio_pin int_phy_gpio[16]; + u32 ir_led_ctl, ir_cut1, ir_cut2, sensor_reset, phy_reset, phy_speed_led; + u32 spi0_en0, spi1_en0, pwm[4], usb_host, sd_detect, sd_power; + u32 soc_type; + char board_type[32]; + u32 board_version; + u32 reserve1; + u32 ext_phy_clk; /* MHz; 0: the internal PHY */ + u32 reserve2; + u32 pmu_ctl; +}; + +static const struct gk_gpio_map *gk_map(void) +{ + const char *name = env_get("gpiomap"); + int i; + + for (i = 0; name && i < ARRAY_SIZE(gk_maps); i++) + if (!strcmp(name, gk_maps[i].name)) + return &gk_maps[i]; + return &gk_maps[0]; +} + +/* + * U-Boot itself needs one pin: the internal PHY's reference clock, out on + * GPIO 48 in both layouts. The vendor U-Boot applied the whole map here, + * but the map is a guess until gpiomap is set, and the v2 map moves UART0 + * off GPIO 30/31 -- a v1 board would lose its console before anyone could + * set gpiomap=v1. The pins stay as the boot ROM left them; the kernel + * applies the full map it is handed. + */ +#define GK_EPHY_CLK_PIN 48 + +void gk_gpio_map_apply(void) +{ + const struct gk_gpio_map *m = gk_map(); + int i; + + for (i = 0; i < m->nintphy; i++) + if (m->intphy[i].pin == GK_EPHY_CLK_PIN) + gk_gpio_config(m->intphy[i].pin, m->intphy[i].type); + gk_gpio_init(); +} + +void gk_gpio_map_save(void *dst) +{ + const struct gk_gpio_map *m = gk_map(); + struct gk_gpio_cfg *c = dst; + + memset(c, 0, sizeof(*c)); + c->gpio_count = m->npins; + memcpy(c->gpio_chip, m->pins, m->npins * sizeof(*m->pins)); + c->extphy_gpio_count = m->nextphy; + memcpy(c->ext_phy_gpio, m->extphy, m->nextphy * sizeof(*m->extphy)); + c->intphy_gpio_count = m->nintphy; + memcpy(c->int_phy_gpio, m->intphy, m->nintphy * sizeof(*m->intphy)); + c->ir_led_ctl = m->ir_led_ctl; + c->ir_cut1 = m->ir_cut1; + c->ir_cut2 = m->ir_cut2; + c->sensor_reset = m->sensor_reset; + c->phy_reset = m->phy_reset; + c->phy_speed_led = m->phy_speed_led; + c->spi0_en0 = m->spi0_en0; + c->spi1_en0 = m->spi1_en0; + memcpy(c->pwm, m->pwm, sizeof(c->pwm)); + c->usb_host = m->usb_host; + c->sd_detect = m->sd_detect; + c->sd_power = m->sd_power; + c->pmu_ctl = m->pmu_ctl; + c->soc_type = IS_ENABLED(CONFIG_TARGET_GK7101) ? 0 : 1; + snprintf(c->board_type, sizeof(c->board_type), "openipc-%s", m->name); + c->board_version = 0; + c->ext_phy_clk = 0; +} diff --git a/build.sh b/build.sh new file mode 100755 index 000000000000..e8cf4b34b8b2 --- /dev/null +++ b/build.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# +# Build U-Boot for the SoCs named on the command line, or for every +# supported SoC when invoked without arguments. Failures are collected: +# every requested SoC is attempted and the script exits non-zero if any +# of them failed. + +cd "$(dirname "$0")" + +export ARCH=arm +export CROSS_COMPILE=${CROSS_COMPILE:-arm-linux-gnueabi-} + +BOOT_SRCDIR=$(pwd) + +mkdir -p output + +# Concatenate the config fragments into the build directory's .config; +# later fragments override earlier ones. +mkconfig() { + builddir=$1 + shift + mkdir -p "${builddir}" + cat "$@" > "${builddir}/.config" +} + +# Goke GK710x: the boot ROM runs the DDR set-up in the image's header, then +# copies U-Boot to its link address and starts it there. +build_gk710x() { + soc=$1 + builddir=${BOOT_SRCDIR}/output/build-${soc}-nor + make_opts="-C ${BOOT_SRCDIR} O=${builddir} -j$(nproc)" + + rm -rf "${builddir}" + mkconfig "${builddir}" openipc/openipc_config openipc/${soc}_config && \ + make ${make_opts} olddefconfig /dev/null && \ + make ${make_opts} &2 + return 1 ;; + esac +} + +ALL_SOCS="gk7101 gk7102" + +SOCS="$@" +[ -z "${SOCS}" ] && SOCS="${ALL_SOCS}" + +rc=0 +for soc in ${SOCS}; do + build_soc "${soc}" || { echo "build failed for ${soc}" >&2; rc=1; } +done + +exit ${rc} diff --git a/cmd/Kconfig b/cmd/Kconfig index 0e0be94f41f1..f21ddee00e60 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1412,7 +1412,7 @@ config CMD_SDRAM config CMD_SF bool "sf" - depends on DM_SPI_FLASH || SPI_FLASH + depends on DM_SPI_FLASH || SPI_FLASH || GK_SFLASH default y if DM_SPI_FLASH help SPI Flash support diff --git a/common/Kconfig b/common/Kconfig index ebee856e5676..b6f754d9fdf8 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1006,3 +1006,24 @@ config FDT_SIMPLEFB These functions can be used by board to indicate to the OS the presence of the simple frame buffer with associated reserved memory + +config OPENIPC + bool "OpenIPC boot layer" + help + The OpenIPC firmware scan, SD/USB recovery and boot-limit failsafe + (common/openipc.c), driven from the board's misc_init_r(), with the + default environment in include/configs/openipc-common.h. + +config PRODUCT_SOC + string "Product SoC name" + default SYS_CONFIG_NAME + help + Target SoC name exposed as 'soc=' (and 'board=') in the default + environment. Set per target by the build system. + +config PRODUCT_SOCMODEL + string "Product SoC model" + default "" + help + Optional board/binning model exposed as 'socmodel=' in the default + environment. diff --git a/common/Makefile b/common/Makefile index 2ed8672c3ac1..d725fc328029 100644 --- a/common/Makefile +++ b/common/Makefile @@ -112,3 +112,5 @@ obj-$(CONFIG_$(SPL_TPL_)STACKPROTECTOR) += stackprot.o obj-$(CONFIG_SCP03) += scp03.o obj-$(CONFIG_QFW) += qfw.o + +obj-$(CONFIG_OPENIPC) += openipc.o diff --git a/common/openipc.c b/common/openipc.c new file mode 100644 index 000000000000..00c363de3dbf --- /dev/null +++ b/common/openipc.c @@ -0,0 +1,715 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_USB +#include +#endif +#ifdef CONFIG_MMC +#include +#endif +#ifdef CONFIG_ENV_IS_IN_NAND +#include +#endif +#ifdef CONFIG_ENV_IS_IN_NAND +#include +#include +#include +#include +#include +#include +#endif + +#define SCAN_FROM CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE +#define SCAN_STEP 0x10000 +#define SCAN_LIMIT 0x400000 + +#define UBI_MAGIC_ASCII "UBI#" +#define FDT_MAGIC 0xd00dfeed + +#define SQSH_SIZE_OFF 0x58 +#define SQSH_MAGIC_BE 0x73717368 +#define SQSH_MAGIC_LE 0x68737173 + +static int check_squashfs(void *buf) { + uint32_t magic = get_unaligned_be32(buf); + if (magic == SQSH_MAGIC_BE || magic == SQSH_MAGIC_LE) + return 1; + return 0; +} + +#ifdef CONFIG_ENV_IS_IN_NAND +#define UBIFS_SB_MAGIC 0x06101831 + +static int check_ubifs(void *buf) { + return get_unaligned_le32(buf) == UBIFS_SB_MAGIC; +} + +/* Check for the UBI marker without attaching: attaching an empty MTD + * would create a fresh UBI on flash. */ +static int ubi_marker_present(void) { + struct mtd_info *mtd; + u8 buf[4]; + size_t retlen; + int ret; + + /* Register the mtdparts partitions before looking one up by name */ + mtd_probe_devices(); + mtd = get_mtd_device_nm("ubi"); + if (IS_ERR(mtd)) + return 0; + + ret = mtd_read(mtd, 0, sizeof(buf), &retlen, buf); + put_mtd_device(mtd); + + return !ret && retlen == sizeof(buf) && + get_unaligned_be32(buf) == UBI_EC_HDR_MAGIC; +} +#endif + +static int check_kernel(void *buf) { + struct image_header *hdr = (struct image_header *)buf; + if (image_check_magic(hdr)) { + return 1; + } + + if (fdt_magic(buf) == FDT_MAGIC) { + if (fdt_check_header(buf) == 0) { + return 1; + } + } + + return 0; +} + +#ifndef CONFIG_ENV_IS_IN_NAND + +static uint64_t get_squashfs_size(void *buf) { + uint32_t magic = get_unaligned_be32(buf); + uint64_t size; + + if (magic == SQSH_MAGIC_BE) { + size = get_unaligned_be64((u8 *)buf + SQSH_SIZE_OFF); + } else { + size = get_unaligned_le64((u8 *)buf + SQSH_SIZE_OFF); + } + + return size; +} + +static int check_rootfs(void *buf, uint64_t *rootfs_size) { + if (check_squashfs(buf)) { + *rootfs_size = get_squashfs_size(buf); + return 1; + } + if (memcmp(buf, UBI_MAGIC_ASCII, 4) == 0) { + *rootfs_size = 0; + return 1; + } + return 0; +} + +static int scan_spi_device(struct spi_flash *flash, ulong *kernel_off, ulong *rootfs_off, uint64_t *kernel_size, + uint64_t *rootfs_size) { + u8 *buf; + ulong offset; + ulong erase_size; + int ret; + + buf = malloc_cache_aligned(SCAN_STEP); + if (!buf) + return -1; + +#ifdef CONFIG_SPI_FLASH + erase_size = flash->sector_size; +#else + erase_size = 0x10000; +#endif + + printf("Scanning 0x%x-0x%x ...\n", SCAN_FROM, SCAN_LIMIT); + + for (offset = SCAN_FROM; offset < SCAN_LIMIT && offset < flash->size; offset += SCAN_STEP) { + ret = spi_flash_read(flash, offset, SCAN_STEP, buf); + if (ret != 0) + continue; + + /* Skip completely empty regions */ + if (buf[0] == 0x00 || buf[0] == 0xFF) { + int i, uniform = 1; + for (i = 1; i < 32; i++) { + if (buf[i] != buf[0]) { + uniform = 0; + break; + } + } + if (uniform) + continue; + } + + if (!*kernel_off && check_kernel(buf)) { + *kernel_off = offset; + printf("Found Kernel at 0x%08lx\n", offset); + } + + if (!*rootfs_off && check_rootfs(buf, rootfs_size)) { + *rootfs_off = offset; + printf("Found RootFS at 0x%08lx (%lldk)\n", offset, *rootfs_size / 1024); + } + + if (*kernel_off && *rootfs_off) + break; + } + + if (*kernel_off && *rootfs_off) { + *kernel_size = *rootfs_off - *kernel_off; + } + + /* Align rootfs size to erase block boundary */ + if (*rootfs_size > 0) { + ulong aligned_size = (*rootfs_size + erase_size - 1) & ~(erase_size - 1); + *rootfs_size = aligned_size; + } + + free(buf); + return 0; +} + +#endif /* !CONFIG_ENV_IS_IN_NAND */ + +#if (defined(CONFIG_MMC) || defined(CONFIG_USB_STORAGE)) && defined(CONFIG_FS_FAT) +#define RECOVERY_KERNEL 0 +#define RECOVERY_ROOTFS 1 + +static int recovery_mount(const char *ifname) { + if (!fs_set_blk_dev(ifname, "0:1", FS_TYPE_FAT)) + return 0; + if (!fs_set_blk_dev(ifname, "0", FS_TYPE_FAT)) + return 0; + return -1; +} + +#ifdef CONFIG_ENV_IS_IN_NAND +static int recovery_ensure_volume(const char *name, const char *size) { + struct ubi_volume_desc *desc; + char cmd[64]; + + desc = ubi_open_volume_nm(0, name, UBI_READONLY); + if (!IS_ERR(desc)) { + ubi_close_volume(desc); + return 0; + } + + printf("Recovery: creating volume %s\n", name); + snprintf(cmd, sizeof(cmd), "ubi create %s %s d", name, size); + + return run_command(cmd, 0); +} + +/* Recreate a system volume so it always has the expected size; the old + * one is removed first because UBI volumes cannot be resized. With + * `liberate' set, a create that runs out of space removes rootfs_data + * and retries: growing the rootfs is the only way to need its PEBs. */ +static int recovery_recreate_volume(const char *name, const char *size, + bool liberate) { + struct ubi_volume_desc *desc; + char cmd[64]; + int ret; + + desc = ubi_open_volume_nm(0, name, UBI_READONLY); + if (!IS_ERR(desc)) { + ubi_close_volume(desc); + printf("Recovery: recreating volume %s\n", name); + snprintf(cmd, sizeof(cmd), "ubi remove %s", name); + run_command(cmd, 0); + } else { + printf("Recovery: creating volume %s\n", name); + } + + snprintf(cmd, sizeof(cmd), "ubi create %s %s d", name, size); + ret = run_command(cmd, 0); + + if (ret && liberate) { + printf("Recovery: no room for %s, dropping rootfs_data\n", name); + run_command("ubi remove rootfs_data", 0); + ret = run_command(cmd, 0); + } + + return ret; +} + +static int recovery_write(const char *name, int type) { + struct image_header hdr; + loff_t actread; + ulong size; + int ret; + + if (!fs_exists(name)) + return 0; + + if (type == RECOVERY_ROOTFS) { + /* Raw ubifs image, written into the rootfs volume */ + loff_t fsize; + + ret = fs_size(name, &fsize); + if (ret || fsize == 0) { + printf("Recovery: failed to stat %s\n", name); + return -1; + } + size = fsize; + } else { + /* Kernel: uImage or FIT, written to the kernel volume */ + ret = fs_read(name, (ulong)&hdr, 0, sizeof(hdr), &actread); + if (ret || actread != sizeof(hdr)) { + printf("Recovery: failed to read %s\n", name); + return -1; + } + + if (image_check_magic(&hdr)) { + size = sizeof(hdr) + image_get_data_size(&hdr); + } else if (fdt_magic(&hdr) == FDT_MAGIC && fdt_check_header(&hdr) == 0) { + size = fdt_totalsize(&hdr); + } else { + printf("Recovery: no valid uImage/FIT header in %s\n", name); + return -1; + } + } + + ret = fs_read(name, CONFIG_SYS_LOAD_ADDR, 0, size, &actread); + if (ret || actread != size) { + printf("Recovery: failed to read %s\n", name); + return -1; + } + + /* Attach only now that there is something to write */ + if (ubi_part("ubi", NULL)) { + printf("Recovery: cannot attach UBI\n"); + return -1; + } + + if (type == RECOVERY_ROOTFS) { + char size_str[24]; + + /* The volume is sized to the image; if it does not fit, the data + * volume is dropped (UBI volumes cannot be resized) */ + snprintf(size_str, sizeof(size_str), "0x%lx", size); + ret = recovery_recreate_volume("rootfs", size_str, true); + if (ret) { + printf("Recovery: cannot recreate rootfs volume (%d)\n", ret); + return -1; + } + + ret = ubi_volume_write("rootfs", (void *)CONFIG_SYS_LOAD_ADDR, size); + if (ret) { + printf("Recovery: failed to write rootfs volume (%d)\n", ret); + return -1; + } + + /* The data volume takes the remaining space; keep it if present */ + recovery_ensure_volume("rootfs_data", "0"); + + printf("Recovery: wrote %s (%lu bytes) to rootfs volume\n", name, size); + } else { + ret = recovery_recreate_volume("kernel", "0x300000", false); + if (ret) { + printf("Recovery: cannot recreate kernel volume (%d)\n", ret); + return -1; + } + + ret = ubi_volume_write("kernel", (void *)CONFIG_SYS_LOAD_ADDR, size); + if (ret) { + printf("Recovery: failed to write kernel volume (%d)\n", ret); + return -1; + } + + printf("Recovery: wrote %s (%lu bytes) to kernel volume\n", name, size); + } + + return 1; +} +#else +static struct spi_flash *recovery_flash; + +static int recovery_write(const char *name, int type) { + struct image_header hdr; + loff_t actread; + ulong addr, size, erase_len; + int ret; + + if (!fs_exists(name)) + return 0; + + ret = fs_read(name, (ulong)&hdr, 0, sizeof(hdr), &actread); + if (ret || actread != sizeof(hdr)) { + printf("Recovery: failed to read %s\n", name); + return -1; + } + + if (image_check_magic(&hdr)) { + addr = image_get_load(&hdr); + size = sizeof(hdr) + image_get_data_size(&hdr); + } else if (type == RECOVERY_KERNEL && fdt_magic(&hdr) == FDT_MAGIC && + fdt_check_header(&hdr) == 0) { + const char *str = env_get("kernaddr"); + + addr = str ? hextoul(str, NULL) : OPENIPC_KERNADDR; + size = fdt_totalsize(&hdr); + } else { + printf("Recovery: no valid uImage/FIT header in %s\n", name); + return -1; + } + + ret = fs_read(name, CONFIG_SYS_LOAD_ADDR, 0, size, &actread); + if (ret || actread != size) { + printf("Recovery: failed to read %s\n", name); + return -1; + } + + erase_len = (size + recovery_flash->sector_size - 1) & + ~(recovery_flash->sector_size - 1); + spi_flash_erase(recovery_flash, addr, erase_len); + spi_flash_write(recovery_flash, addr, size, (void *)CONFIG_SYS_LOAD_ADDR); + + printf("Recovery: wrote %s (%lu bytes) to flash at 0x%lx\n", name, size, + addr); + + return 1; +} +#endif + +/* If a script.txt is present on the medium, execute it (uImage script or + * plain text) instead of searching for kernel/rootfs images. */ +static int recovery_run_script(const char *name) { + loff_t size, actread; + int ret; + char cmd[32]; + + if (!fs_exists(name)) + return 0; + + ret = fs_size(name, &size); + if (ret || size == 0) { + printf("Recovery: failed to stat %s\n", name); + return 1; + } + + ret = fs_read(name, CONFIG_SYS_LOAD_ADDR, 0, size, &actread); + if (ret || actread != size) { + printf("Recovery: failed to read %s\n", name); + return 1; + } + + if (image_check_magic((void *)CONFIG_SYS_LOAD_ADDR)) { + /* uImage-wrapped script (mkimage -A arm -T script -d ...) */ + sprintf(cmd, "source 0x%lx", (ulong)CONFIG_SYS_LOAD_ADDR); + ret = run_command(cmd, 0); + } else { + /* Plain text script */ + ret = run_command_list((char *)CONFIG_SYS_LOAD_ADDR, size, 0); + } + + printf("Recovery: executed %s (%lld bytes)\n", name, size); + + return 1; +} + +static int recovery_try(void) { + char name[64]; + int ret, found = 0; + + /* script.txt takes precedence over the kernel/rootfs search */ + if (recovery_run_script("script.txt")) + return 1; + +#ifndef CONFIG_ENV_IS_IN_NAND + /* Kernel: uImage preferred, FIT fallback */ + sprintf(name, "uImage.%s.img", CONFIG_PRODUCT_SOC); + ret = recovery_write(name, RECOVERY_KERNEL); + if (ret > 0) { + found = 1; + } else if (ret == 0) { + sprintf(name, "fitImage.%s.img", CONFIG_PRODUCT_SOC); + ret = recovery_write(name, RECOVERY_KERNEL); + if (ret > 0) + found = 1; + } +#endif + + /* Rootfs. On NAND it carries the kernel (/boot), its volume is sized + * to the image and rootfs_data takes the rest. */ +#ifdef CONFIG_ENV_IS_IN_NAND + sprintf(name, "rootfs.ubifs.%s.img", CONFIG_PRODUCT_SOC); +#else + sprintf(name, "rootfs.squashfs.%s.img", CONFIG_PRODUCT_SOC); +#endif + ret = recovery_write(name, RECOVERY_ROOTFS); + if (ret > 0) + found = 1; + + return found; +} + +int firmware_recovery(void) { + int found = 0; + +#ifndef CONFIG_ENV_IS_IN_NAND + recovery_flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS, + CONFIG_SF_DEFAULT_SPEED, + CONFIG_SF_DEFAULT_MODE); + if (!recovery_flash) + return -1; +#endif + +#ifdef CONFIG_MMC + { + struct mmc *mmc = find_mmc_device(0); + + if (mmc && !mmc_init(mmc) && !recovery_mount("mmc")) + found |= recovery_try(); + } +#endif + +#ifdef CONFIG_USB_STORAGE + if (!usb_init() && usb_stor_scan(1) == 0 && !recovery_mount("usb")) + found |= recovery_try(); +#endif + + fs_close(); +#ifndef CONFIG_ENV_IS_IN_NAND + spi_flash_free(recovery_flash); +#endif + + return found ? 0 : -1; +} +#else +int firmware_recovery(void) { + return -1; +} +#endif + +int firmware_scan(void) { +#ifdef CONFIG_ENV_IS_IN_NAND + u8 buf[64]; + int ret; + + printf("Checking UBI firmware...\n"); + + /* Only attach when the UBI actually exists, so we never create one */ + if (!ubi_marker_present()) { + printf("Firmware is absent/corrupt (no UBI)\n"); + env_set("bootfail", "1"); + return 0; + } + + if (ubi_part("ubi", NULL)) { + printf("Firmware is absent/corrupt (cannot attach UBI)\n"); + env_set("bootfail", "1"); + return 0; + } + + /* The kernel is a file in the UBIFS rootfs (/boot/fitImage or + * /boot/uImage): there is no kernel volume to check. */ + ret = ubi_volume_read("rootfs", (char *)buf, sizeof(buf)); + if (ret || !check_ubifs(buf)) { + printf("Firmware is absent/corrupt (rootfs volume)\n"); + env_set("bootfail", "1"); + return 0; + } + + /* A rootfs without a kernel in it boots nothing: hand it to recovery + * like a missing one. loadkernel mounts the volume again itself. */ + if (cmd_ubifs_mount("ubi0:rootfs")) { + printf("Firmware is absent/corrupt (cannot mount rootfs)\n"); + env_set("bootfail", "1"); + return 0; + } + ret = ubifs_exists("/boot/fitImage") || ubifs_exists("/boot/uImage"); + cmd_ubifs_umount(); + if (!ret) { + printf("Firmware is absent/corrupt (no /boot/fitImage or /boot/uImage)\n"); + env_set("bootfail", "1"); + return 0; + } + + env_set("bootfail", NULL); + + return 0; +#else + struct spi_flash *flash; + ulong kernel_off = 0; + ulong rootfs_off = 0; + uint64_t kernel_size = 0; + uint64_t rootfs_size = 0; + + printf("Automatic flash layout detection...\n"); + + flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS, CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE); + if (!flash) { + printf("Failed to probe SPI flash at %u:%u\n", CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS); + return -1; + } + + scan_spi_device(flash, &kernel_off, &rootfs_off, &kernel_size, &rootfs_size); + +#ifndef CONFIG_TARGET_HI3516CV610_FAMILY + if (kernel_size <= 0x200000) + kernel_size = 0x200000; + if (rootfs_size < 0x500000) + rootfs_size = 0x500000; + else if (rootfs_size > 0x500000 && flash->size > 0x800000) + rootfs_size = 0xa00000; +#endif + + spi_flash_free(flash); + + if (kernel_off) { + char str[32]; + sprintf(str, "0x%08lx", kernel_off); + env_set("kernaddr", str); + + sprintf(str, "0x%llx", kernel_size); + env_set("kernsize", str); + } + + if (rootfs_off) { + char str[32]; + sprintf(str, "0x%08lx", rootfs_off); + env_set("rootaddr", str); + + sprintf(str, "0x%llx", rootfs_size); + env_set("rootsize", str); + + char mtds[128], mtdparts[160]; + const char *mtdids = env_get("mtdids"); + /* + * An environment saved by an earlier OpenIPC U-Boot has no mtdids: its + * bootargs carried "mtdparts=${mtdparts}" with the controller name + * spelled out. Without one the kernel gets "mtdparts=:...", matches no + * flash, and cannot mount /dev/mtdblock3. Name the controller this + * build drives, as its own default environment does. + */ +#ifdef SFC + if (!mtdids || !*mtdids) + mtdids = SFC; +#endif + sprintf(mtds, "%dk(u-boot),%dk(env),%lldk(kernel),%lldk(rootfs),%lldk@0x%lx(firmware),-(rootfs_data)", + CONFIG_ENV_OFFSET / 1024, CONFIG_ENV_SIZE / 1024, kernel_size / 1024, rootfs_size / 1024, + (kernel_size + rootfs_size) / 1024, kernel_off); + env_set("mtds", mtds); + sprintf(mtdparts, "%s:%s", mtdids ? mtdids : "", mtds); + env_set("mtdparts", mtdparts); + } + + if (kernel_off && rootfs_off) { + env_set("bootfail", NULL); + } else { + printf("Firmware is absent/corrupt (kernel=0x%lx, rootfs=0x%lx)\n", kernel_off, rootfs_off); + env_set("bootfail", "1"); + } + + return 0; +#endif +} + +#ifndef OPENIPC_RAM_MAX_SIZE +#ifdef PHYS_SDRAM_1_SIZE +#define OPENIPC_RAM_MAX_SIZE PHYS_SDRAM_1_SIZE +#endif +#endif + +#if defined(OPENIPC_RAM_MAX_SIZE) && defined(CONFIG_SYS_SDRAM_BASE) +ulong openipc_ram_size(void) +{ + return get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, OPENIPC_RAM_MAX_SIZE); +} +#endif + +/* Check whether the device environment area is still blank (donor-style + * CRC check): only then it is safe to write the default environment. */ +static int env_crc_is_blank(void) { + u32 crc; + +#if defined(CONFIG_ENV_IS_IN_SPI_FLASH) + struct spi_flash *flash; + u8 *buf; + + flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS, + CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE); + if (!flash) + return 0; + + /* Cache-aligned: the DMA path invalidates cache lines around the + * buffer and a plain malloc buffer can share lines with heap metadata */ + buf = malloc_cache_aligned(CONFIG_ENV_SIZE); + if (!buf) { + spi_flash_free(flash); + return 0; + } + + if (spi_flash_read(flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf)) { + free(buf); + spi_flash_free(flash); + return 0; + } + + memcpy(&crc, buf, sizeof(crc)); + free(buf); + spi_flash_free(flash); +#elif defined(CONFIG_ENV_IS_IN_NAND) + struct mtd_info *mtd = get_nand_dev_by_index(0); + size_t len = sizeof(crc); + + if (!mtd) + return 0; + + if (nand_read_skip_bad(mtd, CONFIG_ENV_OFFSET, &len, NULL, mtd->size, + (u_char *)&crc)) + return 0; + + if (len != sizeof(crc)) + return 0; +#else + return 0; +#endif + + return crc == 0xffffffff; +} + +/* An environment saved by an earlier build of this tree carries the retired + * boot-limit command, which reflashes instead of entering failsafe (see + * OPENIPC_ALTBOOTCMD). Replace exactly that one, once; a command anyone + * edited is left alone. */ +static void altbootcmd_migrate(void) { + const char *s = env_get("altbootcmd"); + + if (!s || strcmp(s, OPENIPC_ALTBOOTCMD_RETIRED)) + return; + printf("altbootcmd: retired reflash command replaced with failsafe\n"); + env_set("altbootcmd", OPENIPC_ALTBOOTCMD); + env_save(); +} + +int openipc_helper(void) { + char msize[16]; + sprintf(msize, "%ldM", gd->ram_size / 1024 / 1024); + env_set("totalmem", msize); + firmware_recovery(); + firmware_scan(); + altbootcmd_migrate(); + + /* Persist the default environment on first start (or after a bad env); + * only if the device env area is still blank so we never overwrite + * foreign data (e.g. a RAM-booted U-Boot on another device). */ + if ((gd->flags & GD_FLG_ENV_DEFAULT) && env_crc_is_blank()) + env_save(); + + return 0; +} diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index 096338f27bf1..aa61779cb7a3 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -36,9 +36,17 @@ config SPI_FLASH If unsure, say N +config GK_SFLASH + bool "Goke GK710x sflash SPI NOR controller" + depends on ARCH_GK710X && !SPI_FLASH && !DM_SPI_FLASH + help + The GK7101/GK7102 serial flash controller. It runs SPI NOR + transactions itself and provides spi_flash_probe() directly, + without the SPI and spi-nor layers. + config SF_DEFAULT_BUS int "SPI Flash default bus identifier" - depends on SPI_FLASH || DM_SPI_FLASH + depends on SPI_FLASH || DM_SPI_FLASH || GK_SFLASH default 0 help The default bus may be provided by the platform @@ -47,7 +55,7 @@ config SF_DEFAULT_BUS config SF_DEFAULT_CS int "SPI Flash default Chip-select" - depends on SPI_FLASH || DM_SPI_FLASH + depends on SPI_FLASH || DM_SPI_FLASH || GK_SFLASH default 0 help The default chip select may be provided by the platform @@ -56,7 +64,7 @@ config SF_DEFAULT_CS config SF_DEFAULT_MODE hex "SPI Flash default mode (see include/spi.h)" - depends on SPI_FLASH || DM_SPI_FLASH + depends on SPI_FLASH || DM_SPI_FLASH || GK_SFLASH default 0x0 help The default mode may be provided by the platform @@ -68,7 +76,7 @@ config SF_DEFAULT_MODE config SF_DEFAULT_SPEED int "SPI Flash default speed in Hz" - depends on SPI_FLASH || DM_SPI_FLASH + depends on SPI_FLASH || DM_SPI_FLASH || GK_SFLASH default 1000000 help The default speed may be provided by the platform diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index 99cc41855223..6bc601eb2e98 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -21,3 +21,4 @@ obj-$(CONFIG_SPI_FLASH) += spi-nor.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o +obj-$(CONFIG_GK_SFLASH) += gk_sflash.o diff --git a/drivers/mtd/spi/gk_sflash.c b/drivers/mtd/spi/gk_sflash.c new file mode 100644 index 000000000000..7b4bc86ed048 --- /dev/null +++ b/drivers/mtd/spi/gk_sflash.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Goke GK7101/GK7102 serial flash controller ("sflash") with a SPI NOR + * behind it. + * + * A register-driven SPI master with no memory window. COMMAND describes one + * transaction -- opcode, address and dummy byte counts, direction, lane + * widths, 1-4 data bytes per DATA access -- and writing it starts the + * transaction. With address bytes, the first DATA write is the address; a + * command without data (an erase) runs then, reads and programs stream + * through DATA from there on. + * + * Bytes are packed MSB first: a four-byte read returns the first byte from + * flash in bits 31:24. Like the boot ROM and the vendor kernel, this driver + * moves whole little-endian words between memory and DATA, so the flash + * holds every 32-bit word of an image byte-swapped, and reads it back as it + * was written. A camera's flash dump reads as big-endian for that reason. + * + * After the vendor U-Boot's drivers/mtd/spi/gk7101_sflash.c and kernel + * gk_sflash_v1_00.c, single-lane only; like them it provides + * spi_flash_probe() itself, so mainline's non-DM spi_flash_*() wrappers, the + * sf command and the environment in SPI flash work without the SPI and + * spi-nor layers. Parts up to 16 MiB: the 4-byte/bank-register path of the + * vendor code is left out. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SF_DATA (GK_SFLASH_BASE + 0x00) +#define SF_COMMAND (GK_SFLASH_BASE + 0x04) +#define SF_CE (GK_SFLASH_BASE + 0x08) +#define SF_SPEED (GK_SFLASH_BASE + 0x0C) + +/* COMMAND */ +#define SF_SEND_CMD BIT(8) +#define SF_ADDR3 (3 << 9) +#define SF_RWN_READ (0 << 15) +#define SF_RWN_WRITE (1 << 15) +#define SF_RWN_NOTHING (3 << 15) +#define SF_BYTES(n) ((n) << 23) +#define SF_BYTES_4 SF_BYTES(0x1f) + +/* CE: chip select 0, WP and HOLD inactive (vendor value) */ +#define SF_CE_DEFAULT 0x0E +#define SF_SPEED_DIV2 0 + +#define SZ_PAGE 256 +#define SZ_SECTOR SZ_64K + +#define CMD_WRSR 0x01 +#define CMD_PP 0x02 +#define CMD_READ 0x03 +#define CMD_RDSR 0x05 +#define CMD_WREN 0x06 +#define CMD_RDSR2 0x35 +#define CMD_RDID 0x9F +#define CMD_SE_64K 0xD8 + +#define SR1_WIP BIT(0) +#define SR1_BP 0x7C /* GigaDevice/Winbond: BP0-4 */ +#define SR1_BP_OTHER 0x3C /* BP0-3 */ + +/* Longer than any erase or program of the parts on these boards */ +#define SF_TIMEOUT_MS 3000 + +#define MFR_GIGADEVICE 0xc8 +#define MFR_WINBOND 0xef +#define MFR_XMC 0x20 + +static u32 sf_reg_read(u8 op, unsigned int nbytes) +{ + writel(op | SF_SEND_CMD | SF_RWN_READ | SF_BYTES(nbytes), SF_COMMAND); + return readl(SF_DATA); +} + +/* A command without address or data starts with the DATA access */ +static void sf_cmd(u8 op) +{ + writel(op | SF_SEND_CMD | SF_RWN_NOTHING, SF_COMMAND); + readl(SF_DATA); +} + +static int sf_wait_ready(void) +{ + ulong start = get_timer(0); + + while (sf_reg_read(CMD_RDSR, 1) & SR1_WIP) { + if (get_timer(start) > SF_TIMEOUT_MS) { + printf("SF: timed out waiting for the flash\n"); + return -ETIMEDOUT; + } + WATCHDOG_RESET(); + } + return 0; +} + +static int sf_write_sr(u32 val, unsigned int nbytes) +{ + sf_cmd(CMD_WREN); + writel(CMD_WRSR | SF_SEND_CMD | SF_RWN_WRITE | SF_BYTES(nbytes), + SF_COMMAND); + writel(val, SF_DATA); + return sf_wait_ready(); +} + +/* Clear the block protection a vendor loader may have left set */ +static void sf_unprotect(u32 jedec) +{ + const u8 mfr = jedec >> 16; + u32 sr1 = sf_reg_read(CMD_RDSR, 1) & 0xff; + + if (sr1 == 0xff) + return; + if (mfr == MFR_GIGADEVICE || mfr == MFR_WINBOND || mfr == MFR_XMC) { + /* QE lives in SR2, written as WRSR's second byte: keep it */ + if (sr1 & SR1_BP) { + u32 sr2 = sf_reg_read(CMD_RDSR2, 1) & 0xff; + + printf("SF: block protection (SR1 %02x), clearing\n", sr1); + sf_write_sr((sr1 & ~SR1_BP) << 8 | sr2, 2); + } + } else if (sr1 & SR1_BP_OTHER) { + printf("SF: block protection (SR1 %02x), clearing\n", sr1); + sf_write_sr(sr1 & ~SR1_BP_OTHER, 1); + } +} + +static int sf_erase_sector(u32 addr) +{ + sf_cmd(CMD_WREN); + writel(CMD_SE_64K | SF_SEND_CMD | SF_ADDR3 | SF_RWN_NOTHING, + SF_COMMAND); + writel(addr, SF_DATA); + return sf_wait_ready(); +} + +/* Whole words, within one page */ +static int sf_program(u32 addr, const u8 *buf, unsigned int words) +{ + sf_cmd(CMD_WREN); + writel(CMD_PP | SF_SEND_CMD | SF_ADDR3 | SF_RWN_WRITE | SF_BYTES_4, + SF_COMMAND); + writel(addr, SF_DATA); + while (words--) { + writel(get_unaligned_le32(buf), SF_DATA); + buf += 4; + } + return sf_wait_ready(); +} + +static int gk_sf_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + u32 addr = from & ~3; + unsigned int skip = from & 3; + + if (from + len > mtd->size) + return -EINVAL; + *retlen = len; + if (!len) + return 0; + + writel(CMD_READ | SF_SEND_CMD | SF_ADDR3 | SF_RWN_READ | SF_BYTES_4, + SF_COMMAND); + writel(addr, SF_DATA); + while (len) { + u32 w = readl(SF_DATA); + unsigned int n = min_t(size_t, len, 4 - skip); + + if (!skip && n == 4) { + put_unaligned_le32(w, buf); + } else { + u8 b[4]; + + put_unaligned_le32(w, b); + memcpy(buf, b + skip, n); + skip = 0; + } + buf += n; + len -= n; + } + return 0; +} + +/* + * The controller programs whole words, so a write that starts or ends + * inside one pads it with 0xff, which leaves those flash bytes as they are. + */ +static int gk_sf_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + u8 page[SZ_PAGE]; + u32 addr = to & ~3; + unsigned int head = to & 3; + int ret; + + if (to + len > mtd->size) + return -EINVAL; + *retlen = 0; + while (len) { + unsigned int room = SZ_PAGE - (addr & (SZ_PAGE - 1)); + unsigned int n = min_t(size_t, len, room - head); + unsigned int span = ALIGN(head + n, 4); + + memset(page, 0xff, span); + memcpy(page + head, buf, n); + ret = sf_program(addr, page, span / 4); + if (ret) + return ret; + addr += span; + buf += n; + len -= n; + *retlen += n; + head = 0; + } + return 0; +} + +static int gk_sf_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + u32 addr = instr->addr; + u32 end = instr->addr + instr->len; + int ret; + + if (addr % SZ_SECTOR || instr->len % SZ_SECTOR || end > mtd->size) + return -EINVAL; + for (; addr < end; addr += SZ_SECTOR) { + ret = sf_erase_sector(addr); + if (ret) { + instr->fail_addr = addr; + return ret; + } + } + return 0; +} + +static struct spi_flash gk_flash; +static int gk_announced; + +struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int spi_mode) +{ + struct spi_flash *flash = &gk_flash; + struct mtd_info *mtd = &flash->mtd; + u32 jedec, size; + + writel(SF_CE_DEFAULT, SF_CE); + writel(SF_SPEED_DIV2, SF_SPEED); + jedec = sf_reg_read(CMD_RDID, 3) & 0xffffff; + if (!jedec || jedec == 0xffffff) { + printf("SF: no flash (JEDEC id %06x)\n", jedec); + return NULL; + } + /* The last ID byte is log2 of the size on the parts these boards carry */ + size = (jedec & 0xff) >= 0x14 && (jedec & 0xff) <= 0x18 ? + 1 << (jedec & 0xff) : SZ_8M; + + sf_unprotect(jedec); + + memset(flash, 0, sizeof(*flash)); + flash->name = "gk-sflash"; + flash->size = size; + flash->page_size = SZ_PAGE; + flash->sector_size = SZ_SECTOR; + flash->erase_size = SZ_SECTOR; + flash->erase_opcode = CMD_SE_64K; + flash->read_opcode = CMD_READ; + flash->program_opcode = CMD_PP; + + mtd->name = "gk-sflash"; + mtd->type = MTD_NORFLASH; + mtd->flags = MTD_CAP_NORFLASH; + mtd->size = size; + mtd->erasesize = SZ_SECTOR; + mtd->writesize = 1; + mtd->writebufsize = SZ_PAGE; + mtd->_read = gk_sf_read; + mtd->_write = gk_sf_write; + mtd->_erase = gk_sf_erase; + mtd->priv = flash; + + /* Once: the environment and common/openipc.c probe again and again */ + if (!gk_announced++) + printf("SF: Detected JEDEC %06x with page size %u Bytes, erase size %u KiB, total %u MiB\n", + jedec, SZ_PAGE, SZ_SECTOR >> 10, size >> 20); + return flash; +} + +void spi_flash_free(struct spi_flash *flash) +{ +} diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 6bbbadc5eef3..04ece297c8ac 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -94,7 +94,7 @@ config DSA_SANDBOX menuconfig NETDEVICES bool "Network device support" depends on NET - select DM_ETH + select DM_ETH if DM help You must select Y to enable any network device support Generally if you have any networking support this is a given diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 0e63f70934c0..ee23839033ab 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -694,7 +694,12 @@ int designware_initialize(ulong base_addr, u32 interface) priv->interface = interface; - dw_mdio_init(dev->name, priv->mac_regs_p); + /* + * A board whose PHY is not on the MAC's MDIO lines registers its own + * bus under the device's name first. + */ + if (!miiphy_get_dev_by_name(dev->name)) + dw_mdio_init(dev->name, priv->mac_regs_p); priv->bus = miiphy_get_dev_by_name(dev->name); return dw_phy_init(priv, dev); diff --git a/env/Kconfig b/env/Kconfig index 238e4c70cf05..69be54f8d74b 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -330,7 +330,7 @@ config ENV_IS_IN_REMOTE config ENV_IS_IN_SPI_FLASH bool "Environment is in SPI flash" - depends on !CHAIN_OF_TRUST && SPI + depends on !CHAIN_OF_TRUST && (SPI || GK_SFLASH) default y if ARMADA_XP default y if INTEL_BAYTRAIL default y if INTEL_BRASWELL diff --git a/include/configs/gk710x.h b/include/configs/gk710x.h new file mode 100644 index 000000000000..60b7a2188fe1 --- /dev/null +++ b/include/configs/gk710x.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Goke GK7101 / GK7102: memory map, console and timer. The environment and + * the rest of the OpenIPC configuration come from openipc-common.h. + */ + +#ifndef __GK710X_H +#define __GK710X_H + +#include + +#define CONFIG_SYS_SDRAM_BASE GK_DDR_BASE +#define PHYS_SDRAM_1_SIZE GK_DDR_MAX + +/* The boot ROM copies U-Boot to its link address and starts it there */ +#define CONFIG_SYS_UBOOT_BASE CONFIG_SYS_TEXT_BASE + +/* board_init_f() stack and global data, below U-Boot as the vendor's */ +#define CONFIG_SYS_INIT_RAM_ADDR (GK_DDR_BASE + 0x700000) +#define CONFIG_SYS_INIT_RAM_SIZE 0x100000 + +/* 16550 with 32-bit registers */ +#define CONFIG_SYS_NS16550_SERIAL +#define CONFIG_SYS_NS16550_REG_SIZE (-4) +#define CONFIG_SYS_NS16550_CLK GK_UART_CLK +#define CONFIG_SYS_NS16550_COM1 GK_UART0_BASE + +#define CONFIG_SYS_TIMER_RATE GK_APB_CLK +#define CONFIG_SYS_TIMER_COUNTER GK_TIMER1_STATUS +#define CONFIG_SYS_TIMER_COUNTS_DOWN + +/* Bitstream buffer above the kernel's mem=, as the vendor U-Boot sizes it */ +#ifdef CONFIG_TARGET_GK7101 +#define GK_BSB_MIB 4 +#else +#define GK_BSB_MIB 2 +#endif + +#include "openipc-common.h" + +#endif diff --git a/include/configs/openipc-common.h b/include/configs/openipc-common.h new file mode 100644 index 000000000000..5d2fa6ca203d --- /dev/null +++ b/include/configs/openipc-common.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Common OpenIPC configuration for the Goke GK7101/GK7102 targets. + * + * The single place for the default environment, kept in step with + * include/configs/openipc-common.h on the openipc-hisilicon branch: the + * update, recovery and boot-limit commands are the same, only the per-SoC + * parameters below differ. Per-SoC config headers include this last and must + * not define CONFIG_EXTRA_ENV_SETTINGS, CONFIG_BOOTARGS or + * CONFIG_BOOTCOMMAND themselves. + */ + +#ifndef __OPENIPC_COMMON_H +#define __OPENIPC_COMMON_H + +#include + +/* Default network configuration */ +#define CONFIG_IPADDR 192.168.1.10 +#define CONFIG_SERVERIP 192.168.1.107 +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_GATEWAYIP 192.168.1.1 + +#define VENDOR "goke" + +/* + * Kernel memory (mem=), from 0xC0200000. Above it the kernel carves the + * bitstream buffer (bsbsize) and gives the rest to the DSP, so both are + * passed to it as well (mach-gk710x/kernel.c). The vendor U-Boot defaults. + */ +#if defined(CONFIG_TARGET_GK7101) +#define OPENIPC_OSMEM "50M" +#else +#define OPENIPC_OSMEM "36M" +#endif + +#define OPENIPC_BASEADDR 0xC1000000 + +/* NOR layout, shared with every OpenIPC NOR camera */ +#define OPENIPC_KERNADDR 0x50000 +#define OPENIPC_KERNSIZE 0x200000 +#define OPENIPC_ROOTADDR 0x250000 +#define OPENIPC_ROOTSIZE 0x500000 + +#define OPENIPC_FW_FILE "firmware.${soc}" + +#define OPENIPC_BOOTARGSNFS "mem=\\${osmem} console=ttySGK0,115200 panic=20 root=/dev/nfs rootfstype=nfs ip=${ipaddr}:::255.255.255.0::eth0 nfsroot=${serverip}:${nfsroot},v3,nolock rw \\${extras}" + +/* NOR partition list; the reserved 'mtdparts' variable holds the full + * ":" string, the bootargs compose it from mtdids/mtds. */ +#define OPENIPC_MTDPARTS "256k(boot),64k(env),2048k(kernel),5120k(rootfs),7168k@0x50000(firmware),-(rootfs_data)" + +/* + * Past bootlimit -- a boot loop: the image is intact, but userspace never + * comes up healthy, so nothing clears the DRAM counter -- boot the same + * kernel with "failsafe". openipc-failsafe then brings up network and SSH + * only, so the camera stays reachable. Firmware without that package ignores + * the word and boots as usual. Firmware the scan found broken (bootfail) + * goes to recovery first, as bootflash does. A kernel that does not load + * leaves the camera at this prompt rather than in a reset loop. + * OPENIPC_ALTBOOTCMD_RETIRED is the reflash this replaced on the + * openipc-hisilicon branch; openipc_helper() migrates an environment that + * still carries it. + */ +#define OPENIPC_ALTBOOTCMD "run fwrecovery; echo \"*** Boot limit exceeded -- entering FAILSAFE (network + SSH only) ***\"; setenv setargs setenv bootargs ${bootargs} failsafe; run setargs; if " OPENIPC_LOADKERNEL "; then bootm ${baseaddr}; fi" +#define OPENIPC_ALTBOOTCMD_RETIRED "echo \"*** Boot limit exceeded -- forcing firmware recovery ***\"; run fwupd" + +/* Environment shared by all boot media: identity, network boot, update + * source selection and the medium-agnostic update commands. The selected + * medium provides ubfile/ubwrite/ukwrite/urwrite/loadkernel/mtdids/ + * mtdparts/bootargs. */ +#define OPENIPC_ENV_COMMON \ + "baseaddr=" __stringify(OPENIPC_BASEADDR) "\0" \ + "osmem=" OPENIPC_OSMEM "\0" \ + "bsbsize=" __stringify(GK_BSB_MIB) "M\0" \ + "board_name\0" \ + "board=" CONFIG_PRODUCT_SOC "\0" \ + "vendor=" VENDOR "\0" \ + "soc=" CONFIG_PRODUCT_SOC "\0" \ + "socmodel=" CONFIG_PRODUCT_SOCMODEL "\0" \ + "nfsroot=/srv/nfs/" CONFIG_PRODUCT_SOC "\0" \ + "bootargsnfs=" OPENIPC_BOOTARGSNFS "\0" \ + "bootnfs=setenv setargs setenv bootargs ${bootargsnfs}; run setargs; ${source} ${baseaddr} uImage.${soc}; bootm ${baseaddr}\0" \ + "source=tftpboot\0" \ + "srcnet=setenv source tftpboot\0" \ + "srcmmc=setenv source fatload mmc 0\0" \ + "srcusb=usb start; setenv source fatload usb 0\0" \ + "ub=${source} ${baseaddr} ${ubfile} && run ubwrite\0" \ + "uk=if ${source} ${baseaddr} uImage.${soc}; then run ukwrite; elif ${source} ${baseaddr} fitImage.${soc}; then run ukwrite; fi\0" \ + "ur=${source} ${baseaddr} ${urfile} && run urwrite\0" \ + OPENIPC_FWUPD \ + "bootlimit=2\0" \ + "altbootcmd=" OPENIPC_ALTBOOTCMD "\0" \ + "fwrecovery=if env exists bootfail; then run fwupd; sleep 5; reset; fi\0" \ + "bootflash=run fwrecovery; setenv setargs setenv bootargs ${bootargs}; run setargs; run loadkernel; bootm ${baseaddr}; reset\0" + +/* The flash's MTD name in the vendor kernel (drivers/mtd/devices/gk_sflash) */ +#define SFC "gk_flash" + +#define CONFIG_BOOTARGS "mem=\\${osmem} console=ttySGK0,115200 panic=20 root=/dev/mtdblock3 rootfstype=squashfs init=/init mtdparts=\\${mtdparts} \\${extras}" + +/* Recovery: the rootfs is fetched first so its size selects the NOR schema */ +#define OPENIPC_FWUPD "fwupd=run ur; run uk\0" + +#define OPENIPC_LOADKERNEL "sf probe 0; sf read ${baseaddr} ${kernaddr} ${kernsize}" +#define OPENIPC_ENV_MEDIUM \ + "ubfile=u-boot-" CONFIG_PRODUCT_SOC "-nor.bin\0" \ + "urfile=rootfs.squashfs." CONFIG_PRODUCT_SOC "\0" \ + "kernaddr=" __stringify(OPENIPC_KERNADDR) "\0" \ + "kernsize=" __stringify(OPENIPC_KERNSIZE) "\0" \ + "rootaddr=" __stringify(OPENIPC_ROOTADDR) "\0" \ + "rootsize=" __stringify(OPENIPC_ROOTSIZE) "\0" \ + "mtdslite=setenv kernsize 0x200000; setenv rootaddr 0x250000; setenv rootsize 0x500000\0" \ + "mtdsultimate=setenv kernsize 0x300000; setenv rootaddr 0x350000; setenv rootsize 0xa00000\0" \ + "ubwrite=sf probe 0; sf erase 0x0 ${kernaddr}; sf write ${baseaddr} 0x0 ${filesize}\0" \ + "ukwrite=sf probe 0; sf erase ${kernaddr} ${kernsize}; sf write ${baseaddr} ${kernaddr} ${filesize}\0" \ + "urwrite=sf probe 0; if itest ${filesize} -gt 500000; then run mtdsultimate; fi; sf erase ${rootaddr} ${rootsize}; sf write ${baseaddr} ${rootaddr} ${filesize}\0" \ + "fwwrite=sf probe 0; sf erase ${kernaddr} ${filesize}; sf write ${baseaddr} ${kernaddr} ${filesize}\0" \ + "loadkernel=" OPENIPC_LOADKERNEL "\0" \ + "mtdids=" SFC "\0" \ + "mtds=" OPENIPC_MTDPARTS "\0" \ + "mtdparts=" SFC ":" OPENIPC_MTDPARTS "\0" \ + "bootargs=" CONFIG_BOOTARGS + +#define CONFIG_BOOTCOMMAND "run bootflash" + +#define CONFIG_EXTRA_ENV_SETTINGS \ + OPENIPC_ENV_COMMON \ + OPENIPC_ENV_MEDIUM + +#endif /* __OPENIPC_COMMON_H */ diff --git a/include/openipc.h b/include/openipc.h new file mode 100644 index 000000000000..b8ccfe058431 --- /dev/null +++ b/include/openipc.h @@ -0,0 +1,7 @@ +#ifndef _OPENIPC_H +#define _OPENIPC_H + +unsigned long openipc_ram_size(void); +int openipc_helper(void); + +#endif \ No newline at end of file diff --git a/openipc/gk7101.rvs b/openipc/gk7101.rvs new file mode 100644 index 000000000000..9fa92df228f2 --- /dev/null +++ b/openipc/gk7101.rvs @@ -0,0 +1,71 @@ +# GK7101 boot ROM set-up: the register writes the mask ROM makes before it +# copies U-Boot into DDR -- eFuse, DDR PHY, the RCT and the DDR controller. +# Taken from the header of the SDK's prebuilt uboot-gk7101-rb-ov2710_v2.2.bin +# (GK710X_LinuxSDK_v2.0.0 boot/prebuild), the table on GK710x cameras in the +# field. build.sh writes it into the boot header. +# +# setup: = write +# rdcom: = wait until the register reads +# +setup: 0x6000B100 = 0xFF39C119 +setup: 0x60021A68 = 0x00000300 +setup: 0x60021A60 = 0x00002B52 +setup: 0x60021A64 = 0x00000035 +setup: 0x60021A48 = 0x00001000 +setup: 0x60021A48 = 0x00000000 +setup: 0x60021B00 = 0x00000031 +setup: 0x60021A00 = 0x00000012 +setup: 0x60021A08 = 0x0000F080 +setup: 0x60021A70 = 0x00000033 +setup: 0x60021A74 = 0x00000000 +setup: 0x60021A04 = 0x00000000 +setup: 0x60021A78 = 0x00000200 +setup: 0x60021A7C = 0x00000022 +setup: 0x60021A1C = 0x000000E7 +setup: 0x60021A1C = 0x000000A7 +setup: 0x60021A1C = 0x000000E7 +setup: 0x60021A1C = 0x000000A7 +setup: 0x60021ADC = 0x00009999 +setup: 0x60021AE4 = 0x00000006 +setup: 0x60021AD4 = 0x0000004F +setup: 0x60021AD0 = 0x0000004F +setup: 0x60021AA8 = 0x00000000 +setup: 0x60021A2C = 0x00000000 +setup: 0x60021A00 = 0x00000002 +setup: 0x60021A04 = 0x0000AAAA +setup: 0x60021A10 = 0x0000007F +setup: 0x70170228 = 0x00000001 +setup: 0x60004004 = 0x00100354 +setup: 0x60004008 = 0x48FA368B +setup: 0x6000400C = 0x00002872 +setup: 0x60004010 = 0x0020903F +setup: 0x60004020 = 0x000000A0 +setup: 0x60004000 = 0x00000004 +setup: 0x60004014 = 0x00000001 +rdcom: 0x60004014 = 0x00000000 +setup: 0x60004018 = 0x01020000 +rdcom: 0x60004018 = 0x01020000 +setup: 0x60004018 = 0x01030000 +rdcom: 0x60004018 = 0x01030000 +setup: 0x60004018 = 0x01010044 +rdcom: 0x60004018 = 0x01010044 +setup: 0x60004018 = 0x01000B63 +rdcom: 0x60004018 = 0x01000B63 +setup: 0x60004014 = 0x00000001 +rdcom: 0x60004014 = 0x00000000 +setup: 0x60004014 = 0x00000002 +rdcom: 0x60004014 = 0x00000000 +setup: 0x60004014 = 0x00000002 +rdcom: 0x60004014 = 0x00000000 +setup: 0x60004014 = 0x00000002 +rdcom: 0x60004014 = 0x00000000 +setup: 0x60004018 = 0x01000A63 +rdcom: 0x60004018 = 0x01000A63 +setup: 0x60004000 = 0x00000006 +setup: 0x60004018 = 0x01010380 +rdcom: 0x60004018 = 0x01010380 +setup: 0x60004018 = 0x01010000 +rdcom: 0x60004018 = 0x01010000 +setup: 0x6000401C = 0x00000210 +setup: 0x60004000 = 0x00000007 +setup: 0x6000B104 = 0x00000001 diff --git a/openipc/gk7101_config b/openipc/gk7101_config new file mode 100644 index 000000000000..8a48fd3c6fdb --- /dev/null +++ b/openipc/gk7101_config @@ -0,0 +1,2 @@ +CONFIG_TARGET_GK7101=y +CONFIG_PRODUCT_SOC="gk7101" diff --git a/openipc/gk7102.rvs b/openipc/gk7102.rvs new file mode 100644 index 000000000000..5cc534f13dcc --- /dev/null +++ b/openipc/gk7102.rvs @@ -0,0 +1,71 @@ +# GK7102 boot ROM set-up: the register writes the mask ROM makes before it +# copies U-Boot into DDR -- eFuse, DDR PHY, the RCT and the DDR controller. +# Taken from the header of the SDK's prebuilt uboot-gk7102-rb-jxh42_v2.0.bin +# (GK710X_LinuxSDK_v2.0.0 boot/prebuild), the table on GK710x cameras in the +# field. build.sh writes it into the boot header. +# +# setup: = write +# rdcom: = wait until the register reads +# +setup: 0x6000B100 = 0xFF39C119 +setup: 0x60021A68 = 0x00000300 +setup: 0x60021A60 = 0x00002B52 +setup: 0x60021A64 = 0x00000035 +setup: 0x60021A48 = 0x00001000 +setup: 0x60021A48 = 0x00000000 +setup: 0x60021B00 = 0x00000031 +setup: 0x60021A00 = 0x00000012 +setup: 0x60021A08 = 0x0000F080 +setup: 0x60021A70 = 0x00000033 +setup: 0x60021A74 = 0x00000000 +setup: 0x60021A04 = 0x00000000 +setup: 0x60021A78 = 0x00000200 +setup: 0x60021A7C = 0x00000022 +setup: 0x60021A1C = 0x000000E7 +setup: 0x60021A1C = 0x000000A7 +setup: 0x60021A1C = 0x000000E7 +setup: 0x60021A1C = 0x000000A7 +setup: 0x60021ADC = 0x00009999 +setup: 0x60021AE4 = 0x00000006 +setup: 0x60021AD4 = 0x0000004F +setup: 0x60021AD0 = 0x0000004F +setup: 0x60021AA8 = 0x00000000 +setup: 0x60021A2C = 0x00000000 +setup: 0x60021A00 = 0x00000002 +setup: 0x60021A04 = 0x0000AAAA +setup: 0x60021A10 = 0x0000007F +setup: 0x70170228 = 0x00000001 +setup: 0x60004004 = 0x00100344 +setup: 0x60004008 = 0x48FA368B +setup: 0x6000400C = 0x00002872 +setup: 0x60004010 = 0x0020903F +setup: 0x60004020 = 0x000000A0 +setup: 0x60004000 = 0x00000004 +setup: 0x60004014 = 0x00000001 +rdcom: 0x60004014 = 0x00000000 +setup: 0x60004018 = 0x01020000 +rdcom: 0x60004018 = 0x01020000 +setup: 0x60004018 = 0x01030000 +rdcom: 0x60004018 = 0x01030000 +setup: 0x60004018 = 0x01010044 +rdcom: 0x60004018 = 0x01010044 +setup: 0x60004018 = 0x01000B63 +rdcom: 0x60004018 = 0x01000B63 +setup: 0x60004014 = 0x00000001 +rdcom: 0x60004014 = 0x00000000 +setup: 0x60004014 = 0x00000002 +rdcom: 0x60004014 = 0x00000000 +setup: 0x60004014 = 0x00000002 +rdcom: 0x60004014 = 0x00000000 +setup: 0x60004014 = 0x00000002 +rdcom: 0x60004014 = 0x00000000 +setup: 0x60004018 = 0x01000A63 +rdcom: 0x60004018 = 0x01000A63 +setup: 0x60004000 = 0x00000006 +setup: 0x60004018 = 0x01010380 +rdcom: 0x60004018 = 0x01010380 +setup: 0x60004018 = 0x01010000 +rdcom: 0x60004018 = 0x01010000 +setup: 0x6000401C = 0x00000210 +setup: 0x60004000 = 0x00000007 +setup: 0x6000B104 = 0x00000001 diff --git a/openipc/gk7102_config b/openipc/gk7102_config new file mode 100644 index 000000000000..7e7363158a4c --- /dev/null +++ b/openipc/gk7102_config @@ -0,0 +1,2 @@ +CONFIG_TARGET_GK7102=y +CONFIG_PRODUCT_SOC="gk7102" diff --git a/openipc/gk710x-image.py b/openipc/gk710x-image.py new file mode 100755 index 000000000000..39d0740dc60e --- /dev/null +++ b/openipc/gk710x-image.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""Wrap u-boot.bin in the GK7101/GK7102 boot ROM header. + + gk710x-image.py .rvs u-boot.bin + +The mask ROM reads the header from flash offset 0, in CPU words: + + 0, 1 "GK71" magic, version (0x474B3731, 0x30310801) + 2 U-Boot length in words + 3 load address, where it also starts U-Boot + 4 the load address in words + 5, 6 DDR test address and pattern + 7.. the .rvs table: to write, or 0xFFFFFFFE, + to wait for; 0 ends it + +and U-Boot follows the 0. Words 0, 1 and 4-6 are as in every SDK prebuilt +U-Boot and camera flash seen. The output is in CPU byte order, what `sf +write` and the vendor kernel's driver store; the flash chip itself then +holds every word byte-swapped (drivers/mtd/spi/gk_sflash.c). +""" +import re +import struct +import sys + +MAGIC = 0x474B3731 +VERSION = 0x30310801 +DDR_TEST = (0xC4000000, 0x5A5A5A5A) +POLL = 0xFFFFFFFE + + +def table(path): + words = [] + for line in open(path): + m = re.match(r'\s*(setup|rdcom):\s*(0x[0-9a-fA-F]+)\s*=\s*' + r'(0x[0-9a-fA-F]+)', line) + if not m: + continue + if m.group(1) == 'rdcom': + words.append(POLL) + words += [int(m.group(2), 16), int(m.group(3), 16)] + if not words: + sys.exit('%s: no setup lines' % path) + return words + [0] + + +def main(): + rvs, src, load, dst = sys.argv[1], sys.argv[2], int(sys.argv[3], 0), \ + sys.argv[4] + code = open(src, 'rb').read() + code += b'\0' * (-len(code) % 4) + head = [MAGIC, VERSION, len(code) // 4, load, load // 4, *DDR_TEST] + head += table(rvs) + with open(dst, 'wb') as f: + f.write(struct.pack('<%dI' % len(head), *head) + code) + + +if __name__ == '__main__': + main() diff --git a/openipc/openipc_config b/openipc/openipc_config new file mode 100644 index 000000000000..cda648c42a15 --- /dev/null +++ b/openipc/openipc_config @@ -0,0 +1,91 @@ +# OpenIPC base configuration for the Goke GK7101/GK7102 targets. build.sh +# appends the per-SoC fragment and runs olddefconfig, so a later line +# overrides an earlier one. +CONFIG_ARM=y +CONFIG_ARCH_GK710X=y +CONFIG_SYS_TEXT_BASE=0xC0800000 +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_DM is not set +CONFIG_SYS_DCACHE_OFF=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SYS_MALLOC_LEN=0x400000 +CONFIG_SYS_LOAD_ADDR=0xC1000000 +CONFIG_NR_DRAM_BANKS=1 +CONFIG_STATIC_MACH_TYPE=y +# GOKE_IPC: what the vendor kernels register +CONFIG_MACH_TYPE=3988 +CONFIG_SETUP_MEMORY_TAGS=y +CONFIG_CMDLINE_TAG=y +CONFIG_INITRD_TAG=y +CONFIG_DISPLAY_CPUINFO=y +CONFIG_MISC_INIT_R=y + +# Console +CONFIG_SYS_NS16550=y +CONFIG_SPECIFY_CONSOLE_INDEX=y +CONFIG_CONS_INDEX=1 +CONFIG_BAUDRATE=115200 +CONFIG_SYS_PROMPT="OpenIPC # " +CONFIG_SILENT_CONSOLE=y +CONFIG_SILENT_CONSOLE_UPDATE_ON_RELOC=y +CONFIG_HUSH_PARSER=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y + +# Autoboot: Ctrl-C only +CONFIG_BOOTDELAY=1 +CONFIG_AUTOBOOT=y +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_PROMPT="Hit Ctrl-C to stop autoboot: %2d\n" +CONFIG_AUTOBOOT_STOP_STR="\x03" +CONFIG_AUTOBOOT_KEYED_CTRLC=y + +# OpenIPC boot layer: firmware scan, recovery, boot-limit failsafe +CONFIG_OPENIPC=y +CONFIG_BOOTCOUNT_LIMIT=y +CONFIG_BOOTCOUNT_GENERIC=y +CONFIG_SYS_BOOTCOUNT_SINGLEWORD=y +# DRAM + 0x1f20000, as on the HiSilicon and Xiongmai targets +CONFIG_SYS_BOOTCOUNT_ADDR=0xC1F20000 +CONFIG_LEGACY_IMAGE_FORMAT=y +CONFIG_OF_LIBFDT=y + +# SPI NOR, and the environment in it +CONFIG_GK_SFLASH=y +CONFIG_CMD_SF=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_ENV_OFFSET=0x40000 +CONFIG_ENV_SIZE=0x10000 +CONFIG_ENV_SECT_SIZE=0x10000 +# Boot header (576 bytes) + image must end before the environment: fail the +# build, not the board +CONFIG_HAS_BOARD_SIZE_LIMIT=y +CONFIG_BOARD_SIZE_LIMIT=261568 + +# Commands +CONFIG_CMD_BOOTM=y +CONFIG_CMD_GO=y +CONFIG_CMD_RUN=y +CONFIG_CMD_ECHO=y +CONFIG_CMD_ITEST=y +CONFIG_CMD_SOURCE=y +CONFIG_CMD_SETEXPR=y +CONFIG_CMD_EDITENV=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_ENV_EXISTS=y +CONFIG_CMD_MEMORY=y +CONFIG_CMD_CRC32=y +CONFIG_CMD_SLEEP=y + +# Network: the GMAC is a DesignWare MAC, the PHY the SoC's own +CONFIG_NET=y +CONFIG_NETDEVICES=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_PHYLIB=y +CONFIG_CMD_NET=y +CONFIG_CMD_TFTPBOOT=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_PING=y +CONFIG_CMD_MII=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_LIB_RAND=y