Skip to content

Goke GK7101/GK7102 on v2022.10, with the OpenIPC boot layer (NOR) - #22

Merged
dimerr merged 10 commits into
openipc-gk710xfrom
gk710x/nor-port
Oct 18, 2026
Merged

dimerr merged 10 commits into
openipc-gk710xfrom
gk710x/nor-port

Conversation

@dimerr

@dimerr dimerr commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

U-Boot for Goke's own ARM1176 camera SoCs, GK7101 and GK7102. These are not the HiSilicon-derived GK7205/GK7605. It's built on mainline v2022.10 with the OpenIPC boot layer, the same way as openipc-hisilicon and openipc-xm. I wrote it from the vendor SDK GK710X_LinuxSDK_v2.0.0 (U-Boot 2012.10, Linux 3.4.43). None of the vendor drivers are used.

Commits

  • net: NETDEVICES selects DM_ETH only with DM, as on openipc-xm.
  • net: designware: the non-DM path uses an MDIO bus the board has already registered. The GK710x internal PHY is memory mapped, not on MDIO.
  • openipc: common/openipc.c / include/openipc.h, unchanged from openipc-xm.
  • arm: gk710x: the SoC, board and config headers. Details below.
  • gk_sflash: a non-DM driver for the SPI-NOR controller. It provides spi_flash_probe(), as xmsfc does.
  • openipc: build.sh, Kconfig fragments, and the boot ROM header (openipc/gk710x-image.py + <soc>.rvs, the DDR table from the SDK's prebuilt U-Boots).
  • ci, docs: a thin ci.yml caller and CLAUDE.md.

What's specific to these chips

  • No SPL: the boot ROM runs the DDR set-up in the flash header and copies U-Boot to 0xC0800000.
  • Register values: the vendor code goes through a HAL blob that remaps registers and bits. Here the silicon is programmed directly, with the writes the HAL itself makes, recovered by running it under emulation.
  • Kernel hand-off: the vendor kernel, OpenIPC's gk7102 included, needs the HAL blob at 0xC0012000, the U2K memory-layout words, and the board's GPIO map in the top 64 KiB of DDR. U-Boot leaves all three, as the vendor U-Boot did.
  • GPIO maps: two layouts, generated from the SDK board headers. The default covers rb-sc1035 v2.1, sc1045, imx225, ov9750, jxh42 v2.0, gc1024 and GK7101 rb-ov2710 v2.2. gpiomap=v1 covers rb-ov9712, ar0130, jxh42 v1.0 and GK7101 imx222.
  • Flash byte order: the chip holds every 32-bit word byte-swapped. The released .bin is in CPU order, which is what sf write expects.

Tested on qemu-hisilicon gk7101/gk7102 only, not yet on a camera

  • Boots the OpenIPC gk7102 lite firmware to login. The kernel takes the HAL (20160913), the BSB/DSP/USR layout and the GPIO map; DHCP works from Linux.
  • An unaligned sf write/read compares equal.
  • saveenv survives a reset, and fw_printenv reads it from Linux.
  • TFTP recovery from an empty flash works.
  • The boot-limit failsafe works.

Not covered

  • SD recovery is not enabled.
  • No SPI NAND, no GK710xS.
  • A healthy boot doesn't clear the DRAM boot counter (the gk7102 firmware has no openipc-failsafe), the same as on openipc-xm.

Merge this before #21. This branch's ci.yml calls build-gk710x.yml@openipc, which only exists once #21 lands, so this PR has no CI run of its own. The build and smoke test run on #21 once this is merged.

Since opening, I've pushed fixes for three Qodo findings: U-Boot sets only the PHY clock pin, so a v1-layout board keeps its console; the flash status wait times out; osmem/bsbsize are parsed like mem=.

NETDEVICES selected DM_ETH, so with CONFIG_DM off a board with a network
driver failed to link on uclass and dev_get_priv references. Select it
only when DM is on, as openipc-hisilicon and openipc-xm do, so the legacy
designware_initialize() path still builds.
The non-DM designware_initialize() always registered an MDIO bus on the
MAC's own MDIO lines, named after the device, and connected the PHY there.
A PHY that is not on those lines could not be reached. Register the MAC's
bus only if no bus of that name exists yet, so a board can supply its own
first. Boards that do not are unchanged.

The Goke GK710x needs it: its internal PHY's MII registers are memory
mapped, not on MDIO.
The firmware scan, recovery and boot-limit failsafe of the
openipc-hisilicon branch, for the Goke GK7101/GK7102: common/openipc.c and
include/openipc.h as on openipc-xm (7208b96, itself from
openipc-hisilicon 655d32f), unchanged. CONFIG_OPENIPC builds it;
PRODUCT_SOC and PRODUCT_SOCMODEL name the target in the environment.
Goke's own ARM1176 camera SoCs, not the HiSilicon-derived GK7205/GK7605:
GK7102 is the GK7101 die with 64 MiB of DDR2 in the package, GK7101 has
128 MiB outside. Written from the vendor SDK GK710X_LinuxSDK_v2.0.0
(U-Boot 2012.10, Linux 3.4.43); none of its drivers come along.

- The boot ROM runs the DDR set-up listed in the flash header and copies
  U-Boot to its link address, 0xC0800000, so there is no SPL and
  lowlevel_init is empty. dram_init() tells 64 from 128 MiB by the DDR
  controller word the header programmed.
- The vendor code reaches every register through a HAL blob that remaps
  blocks, registers and bits. Here the silicon is programmed directly,
  with the stores the HAL itself makes, recovered by executing it
  (qemu-hisilicon's gk710x-halmap.py): CPU PLL and UART divider, timer 1
  (Ambarella, 69 MHz, through lib/time.c), watchdog reset, pin functions
  and pad control.
- Console: mainline NS16550 at 0x70005000, 32-bit registers, 24 MHz.
- Ethernet: mainline DesignWare at 0x6000E000 with the SoC's 10/100 PHY,
  whose MII registers are memory mapped and are registered as its MDIO
  bus. The vendor's PHY clock (audio PLL out on a pin), analog trim and
  MAC/PHY mux are done first.
- The vendor kernel, OpenIPC's included, needs more than ATAGs, and
  board_prep_linux() leaves it what the vendor U-Boot did: the HAL blob at
  0xC0012000 (hal_data.h, version 20160913; the kernel calls it first and
  refuses one older than 20160324), the U2K words at 0xC0000000 (total
  DDR, mem=, bitstream buffer, PHY type) from which it places its BSB, DSP
  and USR memory, and the board's GPIO map in the top 64 KiB, from which
  it configures every pin. U-Boot stays below that 64 KiB.
- The SDK's board GPIO headers come down to two layouts, v2 (rb-sc1035
  v2.1, sc1045, imx225, ov9750, jxh42 v2.0, gc1024, GK7101 rb-ov2710 v2.2)
  and v1 (rb-ov9712, ar0130, jxh42 v1.0, GK7101 imx222). Both are built
  in, generated from the headers; gpiomap=v1 selects the second. U-Boot
  applies the selected map at misc_init_r() as the vendor U-Boot did.
- include/configs/openipc-common.h: the openipc-xm environment, NOR only,
  with the GK parameters: mem= 36M/50M and bsbsize 2M/4M (GK7102/GK7101,
  the vendor defaults), baseaddr 0xC1000000, console ttySGK0 and the
  vendor kernel's MTD name gk_flash.

SD is left out: the vendor U-Boot had none and the controller's base
clock is not known. Under qemu-hisilicon's gk7102 and gk7101 machines
(with the flash driver that follows): 64/128 MiB, console, timer, reset,
ping and TFTP; the OpenIPC gk7102 kernel takes the HAL, the U2K layout
and the GPIO map and boots to login.
A register-driven SPI master with no memory window: COMMAND describes one
transaction (opcode, address and dummy bytes, direction, 1-4 data bytes
per DATA access) and DATA carries the address and the data. Like the
vendor U-Boot this driver provides spi_flash_probe() itself and fills
mtd->_read/_write/_erase, 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. CMD_SF, ENV_IS_IN_SPI_FLASH and the SF_DEFAULT_* options
accept GK_SFLASH for that.

The controller packs bytes MSB first, and the boot ROM and the vendor
kernel move whole little-endian words through it. The driver does the
same, for unaligned offsets and lengths too (reads through the covering
words, programs padded with 0xff), so what it writes the ROM and the
kernel read back unchanged. Single lane, parts up to 16 MiB; block
protection left by a vendor loader is cleared.

Under qemu-hisilicon's gk7102 machine: a 0x12345-byte write at 0x700003
reads back identical, with 0xff around it; saveenv survives a reset and
fw_printenv reads it from Linux; the kernel and rootfs written by TFTP
recovery boot.
build.sh as on openipc-xm: each SoC's .config is openipc/openipc_config
followed by openipc/<soc>_config, then olddefconfig; `bash build.sh
[soc...]` writes output/u-boot-<soc>-nor.bin.

The image is u-boot.bin behind the boot ROM's header
(openipc/gk710x-image.py): magic and version, the U-Boot length, load and
entry address, the DDR test words, then openipc/<soc>.rvs -- the eFuse,
DDR PHY and DDR controller set-up, taken from the SDK's prebuilt U-Boots
and the same on cameras in the field; GK7101 and GK7102 differ only in the
DDR size word. The image is in CPU byte order, as `sf write` stores it.

The base fragment carries the OpenIPC options: prompt "OpenIPC # ",
autoboot stopped by Ctrl-C only, silent=1, hush, the environment at
0x40000 in SPI NOR, TFTP for recovery, a random MAC when none is set, and
the DRAM boot counter at DDR + 0x1f20000. BOARD_SIZE_LIMIT keeps header
and image within the 256 KiB boot partition; with no Thumb-2 on ARM1176
the image is about 237 KiB.

Under qemu-hisilicon, from an 8 MiB flash image: gk7102 and gk7101 boot
the OpenIPC gk7102 lite kernel and rootfs to login; an empty flash
recovers by TFTP (ur, uk) and boots; two resets without a healthy boot
take altbootcmd into failsafe.
.github/workflows/ci.yml is the thin caller openipc-xm has: pushes and
pull requests on this branch run build-gk710x.yml from the openipc branch
with this revision.

CLAUDE.md is guidance for Claude Code sessions on this branch: how it
differs from mainline v2022.10, the HAL and how register values were
recovered, the boot header and flash byte order, what the kernel is
handed, the GPIO maps, and what qemu-hisilicon does and does not verify.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add OpenIPC NOR boot support for Goke GK7101 and GK7102

✨ Enhancement 🐞 Bug fix ⚙️ Configuration changes 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Add GK7101/GK7102 U-Boot support with ROM-initialized DDR and vendor-kernel handoff.
• Bring OpenIPC firmware detection, recovery, and boot-limit behavior to SPI NOR cameras.
• Add native flash and internal-PHY access, image builds, and a CI workflow caller.
Diagram

graph TD
  Flash[("SPI NOR flash")] --> ROM["Boot ROM"] --> UBoot["GK710x U-Boot"] --> OpenIPC["OpenIPC boot"] --> Handoff["Kernel handoff"] --> Linux["Vendor Linux"]
  OpenIPC --> Driver["GK flash driver"] --> Flash
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use driver-model SPI and SPI NOR
  • ➕ Reuses standard flash discovery and operations.
  • ➕ Could simplify future flash-part support.
  • ➖ Requires more controller integration for this non-DM port.
  • ➖ Does not remove the chip-specific word-order or ROM-header requirements.
2. Duplicate vendor boot drivers
  • ➕ Could reduce initial work translating hardware behavior.
  • ➖ Retains dependency on the vendor HAL for U-Boot hardware access.
  • ➖ Diverges further from mainline drivers and the existing OpenIPC boot layer.

Recommendation: Keep the direct-register SoC port and shared OpenIPC boot behavior: they avoid vendor-driver dependence while meeting the kernel's required HAL handoff. The custom non-DM flash driver is a pragmatic initial integration, though driver-model SPI is worth revisiting after physical-camera validation.

Files changed (35) +3267 / -8

Enhancement (12) +2389 / -1
gpio.cProgram GK710x pin functions directly +55/-0

Program GK710x pin functions directly

• Decodes vendor GPIO function words into silicon register writes and completes GPIO initialization.

arch/arm/mach-gk710x/gpio.c

hal_data.hCarry kernel-required GK710x HAL +680/-0

Carry kernel-required GK710x HAL

• Adds the SDK's 20160913 HAL blob for copying into DDR before the vendor kernel starts. U-Boot hardware drivers do not call it.

arch/arm/mach-gk710x/hal_data.h

gk710x.hDefine silicon and handoff addresses +98/-0

Define silicon and handoff addresses

• Defines direct hardware register addresses, clock constants, and the DDR locations used for the HAL and U2K parameters.

arch/arm/mach-gk710x/include/mach/gk710x.h

kernel.cPrepare vendor-kernel DDR handoff +51/-0

Prepare vendor-kernel DDR handoff

• Copies the HAL, writes memory and PHY parameters into U2K words, and saves the selected GPIO map at the top of DDR.

arch/arm/mach-gk710x/kernel.c

lowlevel_init.SLeave DDR initialization to the ROM +11/-0

Leave DDR initialization to the ROM

• Provides an empty low-level hook because the boot ROM executes DDR setup before starting U-Boot.

arch/arm/mach-gk710x/lowlevel_init.S

soc.cInitialize clocks, timer, reset, and RAM +72/-0

Initialize clocks, timer, reset, and RAM

• Programs the CPU and UART clocks, starts the free-running timer, resets through the watchdog, detects RAM size, and reserves the top 64 KiB for kernel handoff.

arch/arm/mach-gk710x/soc.c

gk710x.cInitialize board and internal Ethernet PHY +122/-0

Initialize board and internal Ethernet PHY

• Sets ATAG parameters, applies the selected GPIO map, and starts OpenIPC initialization. Registers the memory-mapped internal PHY as the DesignWare MAC's MDIO bus.

board/goke/gk710x/gk710x.c

gpio_map.cProvide selectable camera GPIO maps +292/-0

Provide selectable camera GPIO maps

• Adds v2 and v1 board pin layouts, with v2 as default and v1 selected through gpiomap. Applies the active map and serializes the vendor-compatible GPIO configuration for Linux.

board/goke/gk710x/gpio_map.c

openipc.cAdd shared OpenIPC boot behavior +715/-0

Add shared OpenIPC boot behavior

• Brings in firmware scanning, recovery paths, boot-failure state, environment persistence, and boot-limit command migration from the existing OpenIPC layer. GK710x uses its NOR path.

common/openipc.c

gk_sflash.cImplement non-DM GK710x NOR access +280/-0

Implement non-DM GK710x NOR access

• Implements controller transactions, JEDEC detection, protection clearing, and MTD read, write, and erase operations. Preserves the controller's word-swapped flash behavior across unaligned accesses.

drivers/mtd/spi/gk_sflash.c

designware.cReuse a board-registered MDIO bus +6/-1

Reuse a board-registered MDIO bus

• Changes legacy DesignWare initialization to register its own MDIO bus only when the board has not already supplied one under the MAC's name.

drivers/net/designware.c

openipc.hDeclare OpenIPC board hooks +7/-0

Declare OpenIPC board hooks

• Exposes the OpenIPC initialization helper and RAM-size helper.

include/openipc.h

Bug fix (1) +1 / -1
KconfigPermit legacy networking without DM_ETH +1/-1

Permit legacy networking without DM_ETH

• Selects DM_ETH for NETDEVICES only when driver model is enabled, allowing the non-DM DesignWare build.

drivers/net/Kconfig

Documentation (1) +233 / -0
CLAUDE.mdDocument GK710x port and verification +233/-0

Document GK710x port and verification

• Explains the hardware map, ROM boot format, kernel handoff, build process, supported board maps, and emulator-only verification limits.

CLAUDE.md

Other (21) +644 / -6
ci.ymlCall the GK710x build workflow +25/-0

Call the GK710x build workflow

• Adds push and pull-request triggers that call the reusable GK710x workflow on the openipc branch with the current SHA. This depends on that workflow being available there.

.github/workflows/ci.yml

KconfigExpose the GK710x ARM architecture +12/-0

Expose the GK710x ARM architecture

• Adds the ARM1176 architecture option, ATAG support, and GK710x machine Kconfig source.

arch/arm/Kconfig

MakefileConnect GK710x machine build +1/-0

Connect GK710x machine build

• Maps ARCH_GK710X to the new ARM machine directory.

arch/arm/Makefile

KconfigDefine GK7101 and GK7102 targets +31/-0

Define GK7101 and GK7102 targets

• Provides mutually exclusive SoC choices and their common board, vendor, and config names.

arch/arm/mach-gk710x/Kconfig

MakefileBuild GK710x machine support +3/-0

Build GK710x machine support

• Includes low-level initialization, SoC setup, GPIO functions, and kernel handoff objects.

arch/arm/mach-gk710x/Makefile

MakefileBuild GK710x board support +3/-0

Build GK710x board support

• Includes board initialization and GPIO-map objects.

board/goke/gk710x/Makefile

build.shBuild both NOR SoC images +64/-0

Build both NOR SoC images

• Combines common and per-SoC config fragments, builds each requested target out of tree, and wraps U-Boot in its ROM header. Attempts all requested SoCs while reporting any build failure.

build.sh

KconfigAllow sf commands with GK_SFLASH +1/-1

Allow sf commands with GK_SFLASH

• Makes the sf command available when the GK710x flash driver supplies flash operations without the standard SPI flash stack.

cmd/Kconfig

KconfigConfigure the OpenIPC boot layer +21/-0

Configure the OpenIPC boot layer

• Adds the OpenIPC option and product SoC identity strings used by the default environment.

common/Kconfig

MakefileConditionally build OpenIPC support +2/-0

Conditionally build OpenIPC support

• Builds openipc.o when CONFIG_OPENIPC is enabled.

common/Makefile

KconfigConfigure native GK710x SPI NOR +12/-4

Configure native GK710x SPI NOR

• Adds GK_SFLASH and allows it to supply default flash bus, chip-select, mode, and speed settings.

drivers/mtd/spi/Kconfig

MakefileBuild the GK710x flash driver +1/-0

Build the GK710x flash driver

• Includes gk_sflash.o when GK_SFLASH is selected.

drivers/mtd/spi/Makefile

KconfigAllow SPI-flash environment with GK_SFLASH +1/-1

Allow SPI-flash environment with GK_SFLASH

• Permits the existing SPI-flash environment backend when the native GK710x flash driver is selected.

env/Kconfig

gk710x.hSet GK710x memory and console configuration +41/-0

Set GK710x memory and console configuration

• Defines DDR placement, early stack, UART, timer, and per-SoC bitstream-buffer size before including the OpenIPC defaults.

include/configs/gk710x.h

openipc-common.hDefine GK710x OpenIPC NOR environment +131/-0

Define GK710x OpenIPC NOR environment

• Sets kernel memory, NOR partitions, update commands, network defaults, and normal and failsafe boot commands for these SoCs.

include/configs/openipc-common.h

gk7101.rvsSupply GK7101 ROM DDR setup table +71/-0

Supply GK7101 ROM DDR setup table

• Records the SDK-derived register writes and polls used by the ROM before loading the 128 MiB GK7101 image.

openipc/gk7101.rvs

gk7101_configSelect the GK7101 build target +2/-0

Select the GK7101 build target

• Selects GK7101 and sets its OpenIPC SoC identity.

openipc/gk7101_config

gk7102.rvsSupply GK7102 ROM DDR setup table +71/-0

Supply GK7102 ROM DDR setup table

• Records the SDK-derived register writes and polls for GK7102's 64 MiB DDR configuration.

openipc/gk7102.rvs

gk7102_configSelect the GK7102 build target +2/-0

Select the GK7102 build target

• Selects GK7102 and sets its OpenIPC SoC identity.

openipc/gk7102_config

gk710x-image.pyGenerate the GK710x ROM boot header +58/-0

Generate the GK710x ROM boot header

• Wraps the padded U-Boot binary with ROM metadata and the SoC's DDR setup table, producing the CPU-order image expected by sf write.

openipc/gk710x-image.py

openipc_configDefine common GK710x build options +91/-0

Define common GK710x build options

• Configures non-DM ARM boot, ATAGs, console, OpenIPC behavior, NOR environment, size limit, commands, and DesignWare networking.

openipc/openipc_config

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (1) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Linux cannot find the flash device 📘 Rule violation ≡ Correctness
Description
spi_flash_probe() names the registered MTD device gk-sflash instead of the required gk_flash.
The generated mtdparts string and vendor kernel expect gk_flash, so partition lookup can fail
when Linux matches the controller name.
Code

drivers/mtd/spi/gk_sflash.c[259]

+	mtd->name = "gk-sflash";
Evidence
The compliance rule requires the MTD device to remain named gk_flash. The driver instead assigns
gk-sflash to mtd->name, while the OpenIPC configuration uses SFC "gk_flash" for partition
identifiers.

CLAUDE.md: Preserve Vendor-Compatible Flash and Console Names: CLAUDE.md: Preserve Vendor-Compatible Flash and Console Names: CLAUDE.md: Preserve Vendor-Compatible Flash and Console Names: CLAUDE.md: Preserve Vendor-Compatible Flash and Console Names
drivers/mtd/spi/gk_sflash.c[259-263]
include/configs/openipc-common.h[97-100]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The SPI NOR driver registers its MTD device as `gk-sflash`, while the boot environment and vendor kernel expect the controller name `gk_flash`.
## Fix Focus Areas
- drivers/mtd/spi/gk_sflash.c[249-263]
## Recommended Fix
Set the registered MTD device name to `gk_flash` so it matches the `SFC` identifier used in `mtdids`, `mtdparts`, and the vendor kernel.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Linux reads the wrong rootfs after a gap 🐞 Bug ≡ Correctness
Description
firmware_scan() records the discovered kernel offset but generates sequential kernel and
rootfs partitions without placing the kernel partition at that offset. When a valid kernel starts
later than 0x50000, Linux receives partition boundaries that disagree with the scanned kernaddr
and rootaddr, so its rootfs partition starts before the actual rootfs.
Code

common/openipc.c[R603-605]

+    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);
Evidence
The scan records actual offsets, but only the synthetic firmware partition receives an explicit
offset in the MTD string; the boot variables retain the discovered offsets.

common/openipc.c[140-174]
common/openipc.c[573-608]
include/configs/openipc-common.h[39-51]
include/configs/openipc-common.h[100-100]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The generated MTD partitions assume the kernel starts immediately after the environment, even though firmware scanning accepts a later kernel offset. This shifts Linux's rootfs partition away from the discovered rootfs.
## Fix Focus Areas
- common/openipc.c[573-608]
## Recommended Fix
Generate partitions using the scanned physical offsets, including an explicit kernel offset or a correctly sized preceding gap. Ensure the resulting rootfs partition begins at `rootfs_off` and remains consistent with the boot variables.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Cameras on the v1 pin layout lose their serial console ✓ Resolved
Description
misc_init_r() calls gk_gpio_map_apply() with gk_map(). That falls back to the v2 map whenever
gpiomap is unset, and it is unset in the default environment. The v2 map makes GPIO 30/31 plain
inputs and moves the UART0 RX input function to pin 25. On an rb-ov9712, ar0130, jxh42 v1.0 or
GK7101 imx222 board, UART0 is on GPIO 30/31, so the console dies before the autoboot prompt and
nobody can stop autoboot to setenv gpiomap v1. The kernel then gets the same wrong map from
gk_gpio_map_save(), so its console is dead too.
Code

board/goke/gk710x/gk710x.c[R28-32]

+int misc_init_r(void)
+{
+	gk_gpio_map_apply();
+	return openipc_helper();
+}
Evidence
gk_map() returns gk_maps[0] (v2) when gpiomap is unset, and the default environment never sets
it. v2_intphy sets pins 30/31 to input type 0x40010000. In v2, pin 25 has type 0x50010900, so
gk_gpio_config() writes 25 into GK_GPIO_INPUT_CFG(9-2), the same input-function slot v1 gives
pin 31. misc_init_r runs during board init, before main_loop's autoboot, so the console is
rerouted before any key can be pressed.

board/goke/gk710x/gpio_map.c[239-261]
board/goke/gk710x/gpio_map.c[78-93]
board/goke/gk710x/gpio_map.c[141-142]
arch/arm/mach-gk710x/gpio.c[26-40]
include/configs/openipc-common.h[72-95]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
With no `gpiomap` set, U-Boot's `misc_init_r()` applies the v2 GPIO map. On v1-layout boards (UART0 on GPIO 30/31) this reroutes UART0 away from the console pins before autoboot, so there is no way to set `gpiomap=v1` from the console.
## Fix Focus Areas
- board/goke/gk710x/gpio_map.c[250-261]
- board/goke/gk710x/gk710x.c[28-32]
## Recommended Fix
In `gk_gpio_map_apply()`, apply only the pins U-Boot itself needs (for example, the internal-PHY clock/LED pins). At minimum, skip the UART0 pins (25, 26, 30, 31) and the UART0 RX input-function slot, so the boot ROM's console routing stays as it is. Another option is to apply the map only when `gpiomap` is explicitly set. Document that the kernel still receives the selected map.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

4. A missing or stuck flash hangs boot forever ✓ Resolved
Description
sf_wait_ready() polls RDSR until WIP clears, with no timeout or error return. If the flash stays
busy or a status read returns 0xff because the chip is absent or the bus fails, U-Boot remains in
that loop after a status write, page program, or sector erase, blocking saveenv, the first-boot
environment write in openipc_helper(), and sf commands before the surrounding loops can reset
the watchdog.
Code

drivers/mtd/spi/gk_sflash.c[R87-91]

+static void sf_wait_ready(void)
+{
+	while (sf_reg_read(CMD_RDSR, 1) & SR1_WIP)
+		;
+}
Evidence
The polling loop exits only when the WIP bit clears, so an RDSR value of 0xff keeps it running
indefinitely. sf_write_sr, sf_erase_sector, and sf_program call this loop; program and erase
cannot return to their callers or reach the watchdog resets in the surrounding loops while it
remains busy.

drivers/mtd/spi/gk_sflash.c[87-145]
drivers/mtd/spi/gk_sflash.c[87-100]
drivers/mtd/spi/gk_sflash.c[124-145]
drivers/mtd/spi/gk_sflash.c[195-223]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`sf_wait_ready()` never terminates if flash status continues to report WIP, trapping U-Boot during status writes, programs, or erases.
## Fix Focus Areas
- drivers/mtd/spi/gk_sflash.c[87-145]
- drivers/mtd/spi/gk_sflash.c[185-224]
## Recommended Fix
Bound status polling with `get_timer()` using a timeout suitable for the operation, such as a few seconds for a sector erase, and return `-ETIMEDOUT` on expiry. Propagate the error through `sf_program` and `sf_erase_sector` to `gk_sf_write`, `gk_sf_erase`, and their MTD or SPI-flash callers, and print a message. Service the watchdog while waiting if needed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Kernel memory words go wrong for sizes not given in MiB ✓ Resolved
Description
env_mib() reads osmem and bsbsize with simple_strtoul(..., 10) and treats the result as MiB,
ignoring any suffix and base prefix. The same osmem string goes to the kernel as mem=, which
accepts K/M/G and hex. A value such as 0x2400000 becomes 0, and 36864K becomes 36864 MiB, so the
U2K MEM/BSB words the vendor kernel uses to place BSB/DSP memory disagree with the kernel's own
size.
Code

arch/arm/mach-gk710x/kernel.c[R26-32]

+/* "36M" -> 36: the environment spells these sizes in MiB */
+static ulong env_mib(const char *name, const char *def)
+{
+	const char *s = env_get(name);
+
+	return simple_strtoul(s ? s : def, NULL, 10);
+}
Evidence
bootargs passes mem=${osmem} verbatim, while board_prep_linux writes `env_mib("osmem") *
SZ_1M into GK_U2K_MEM`. The two parse the same variable differently.

arch/arm/mach-gk710x/kernel.c[26-48]
include/configs/openipc-common.h[100-100]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`env_mib()` parses `osmem`/`bsbsize` as base-10 MiB only. `mem=` in bootargs accepts suffixes and hex, so the U2K words can disagree with the kernel's memory size.
## Fix Focus Areas
- arch/arm/mach-gk710x/kernel.c[26-48]
## Recommended Fix
Parse the value as bytes with `ustrtoul(s, &end, 0)`, which handles 0x, K, M and G like memparse. Write those bytes directly into `GK_U2K_MEM`/`GK_U2K_BSB`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can move or hide resolved findings to focus on what still needs action

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

flash->read_opcode = CMD_READ;
flash->program_opcode = CMD_PP;

mtd->name = "gk-sflash";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Linux cannot find the flash device 📘 Rule violation ≡ Correctness

spi_flash_probe() names the registered MTD device gk-sflash instead of the required gk_flash.
The generated mtdparts string and vendor kernel expect gk_flash, so partition lookup can fail
when Linux matches the controller name.
Agent Prompt
## Issue description
The SPI NOR driver registers its MTD device as `gk-sflash`, while the boot environment and vendor kernel expect the controller name `gk_flash`.

## Fix Focus Areas
- drivers/mtd/spi/gk_sflash.c[249-263]

## Recommended Fix
Set the registered MTD device name to `gk_flash` so it matches the `SFC` identifier used in `mtdids`, `mtdparts`, and the vendor kernel.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread common/openipc.c
Comment on lines +603 to +605
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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Linux reads the wrong rootfs after a gap 🐞 Bug ≡ Correctness

firmware_scan() records the discovered kernel offset but generates sequential kernel and
rootfs partitions without placing the kernel partition at that offset. When a valid kernel starts
later than 0x50000, Linux receives partition boundaries that disagree with the scanned kernaddr
and rootaddr, so its rootfs partition starts before the actual rootfs.
Agent Prompt
## Issue description
The generated MTD partitions assume the kernel starts immediately after the environment, even though firmware scanning accepts a later kernel offset. This shifts Linux's rootfs partition away from the discovered rootfs.
## Fix Focus Areas
- common/openipc.c[573-608]
## Recommended Fix
Generate partitions using the scanned physical offsets, including an explicit kernel offset or a correctly sized preceding gap. Ensure the resulting rootfs partition begins at `rootfs_off` and remains consistent with the boot variables.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread board/goke/gk710x/gk710x.c
Comment thread drivers/mtd/spi/gk_sflash.c Outdated
Comment thread arch/arm/mach-gk710x/kernel.c Outdated
misc_init_r() applied the selected GPIO map, as the vendor U-Boot did.
Until gpiomap is set that map is the v2 default, and v2 makes GPIO 30/31
plain inputs and routes UART0 RX from pin 25. On a v1-layout board
(rb-ov9712, ar0130, jxh42 v1.0, GK7101 imx222), where UART0 is on GPIO
30/31, the console then died before autoboot, so nobody could set
gpiomap=v1.

U-Boot only needs GPIO 48, the internal PHY's reference clock, which is
the same in both layouts. Set that and leave the other pins as the boot
ROM left them. The kernel still gets the full selected map.

Under qemu-hisilicon gk7102: ping and TFTP still work, and the kernel
still takes the v2 map, or the v1 one with gpiomap=v1 (PHY reset on pin
41). The machine does not model pin muxing, so the console fix itself is
unverified.

Reported by Qodo on #22.
sf_wait_ready() polled the status register until WIP cleared, with no
limit. A flash that stayed busy, or a missing part reading 0xff, hung
saveenv, the first-boot environment save and sf erase/write for good.

Give up after 3 s, which is longer than any erase or program of the parts
on these boards, and service the watchdog while waiting. Return
-ETIMEDOUT through sf_program() and sf_erase_sector() to the MTD
write/erase callbacks. Those now report how much was written, and the
failing erase address.

Under qemu-hisilicon gk7102: unaligned sf write/read and cmp, saveenv and
reset, and TFTP recovery behave as before.

Reported by Qodo on #22.
The U2K memory words were parsed as decimal MiB, ignoring any suffix.
The same osmem string goes to the kernel as mem=, which takes bytes, hex
and K/M/G. So mem=0x2400000 left a 0 in the word, and 36864K became
36864 MiB, and the kernel placed its BSB and DSP memory from a size that
disagreed with its own.

Parse both with ustrtoul(), as bytes. The defaults ("36M", "2M") give the
same words as before: under qemu-hisilicon the gk7102 and gk7101 kernels
still place BSB/DSP at 0xc2600000/0xc2800000 and 0xc3400000/0xc3800000.

Reported by Qodo on #22.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant