Skip to content

allwinner: add the V3s and V851s - #72

Merged
dimerr merged 4 commits into
openipc-allwinnerfrom
allwinner/v3s-v851s
Oct 25, 2026
Merged

dimerr merged 4 commits into
openipc-allwinnerfrom
allwinner/v3s-v851s

Conversation

@dimerr

@dimerr dimerr commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator

Adds the V3s and V851s to openipc-allwinner, built the same way as the V831/V833. Each SoC gets an SPL plus an LZMA U-Boot inside the 256 KiB boot partition, with the OpenIPC environment in the SPI NOR, as u-boot-<soc>-nor.bin and u-boot-<soc>-mmc.bin (SD unbricking). bash build.sh now builds v3s v831 v833 v851s.

SoC Generation DDR DRAM driver Kernel hand-off
V3s H3 64 MiB DDR2 mainline dram_sunxi_dw.c ATAGs
V851s D1/T113 (SUNXI_GEN_NCAT2) 64 MiB DDR2 dram_sun20i_d1.c ATAGs, HYP + PSCI

V3s: mainline's MACH_SUN8I_V3S and its DRAM driver as they are. This PR adds:

  • the SPI NOR SPL;
  • the EMAC with the internal PHY: the V3s compatible in sun8i_emac, and the EMAC/EPHY gates in clk_v3s.c;
  • sun8i-v3s-openipc.dts.

V851s: the D1 generation, backported from mainline 2023-2024 only as far as U-Boot uses it, next to the SUN50I_GEN_H6 conditions as mainline has them:

  • the NCAT2 memory map, clocks and MMC;
  • the new pinctrl layout;
  • the SPL's SPI0 at 0x04025000 on PC0-PC5, plus spi-sunxi's R329 variant (no divider inside the controller);
  • the watchdog key.

The DRAM driver is the copy carried by OpenIPC/u-boot-allwinner's hardware-tested V851s U-Boot, made non-DM, with its parameters as the Kconfig defaults.

Shared changes:

  • v83x.h becomes openipc-sunxi.h.
  • The SoC, device tree, PSCI and SPL stack move into the per-SoC fragments.
  • ATAGs are built in (SUPPORT_PASSING_ATAGS); without it bootm panics.
  • With OPENIPC, the SPI-flash env fallback and source=fatload mmc 0 after an SD boot now apply to every SoC. The V3s/V851s -mmc images hung before the console without them.

Verified under qemu-bench (machines from OpenIPC/qemu-bench#205):

  • Every SoC's -nor and -mmc image: the environment is saved and read back, and reset works.
  • V3s and V851s: run ub from the card onto an erased NOR, then a boot from the NOR alone.
  • V851s: after this SPL and after the published u-boot-v851s-nor.bin, the DRAM COM/PHY, CCU and PRCM registers are equal. The only difference is SMHC0's clock, because this U-Boot probes the card.
  • V851s: OpenIPC's published uImage.v851s + rootfs.squashfs.v851s boot from the NOR to a shell (HYP, ATAGs, root on mtdblock3), and reboot -f comes back through the SPL.
  • V831: the OpenIPC kernel still boots to a shell and reboots.

Not run on a camera yet. For that reason the CI PR does not publish the V851s images over OpenIPC/firmware's camera-tested u-boot-v851s-nor.bin. No OpenIPC V3s firmware exists to boot.

The -mmc images of the V3s and V851s hung before the console after an
SD boot: the SPI flash fallback in env_get_location() was the V831's
only, so env_init() found no location. It now applies with OPENIPC,
whose images all keep the environment in the SPI NOR; other sunxi
boards are unaffected, as before.

v83x_boot_source() (source=fatload mmc 0 after an SD boot, not saved)
moves to board.c as openipc_boot_source(), for every SoC.
Two more Allwinner camera SoCs, built as the V831/V833 are: an SPL and
an LZMA U-Boot in the 256 KiB boot partition, the OpenIPC environment
in the SPI NOR, -nor and -mmc images (build.sh v3s v851s).

V3s: mainline's MACH_SUN8I_V3S and its DRAM driver as they are. Added:
the SPI NOR SPL (the H3's SPI0), the EMAC and its internal PHY
(sun8i_emac's V3s compatible, the EMAC/EPHY gates and resets in
clk_v3s.c), sun8i-v3s-openipc.dts.

V851s: the D1/T113 generation backported from mainline (2023-2024) as
far as U-Boot uses it, alongside the SUN50I_GEN_H6 conditions as mainline
has them:
- SUNXI_GEN_NCAT2 and its memory map (cpu_sunxi_ncat2.h); clocks
  (PLL_CPU LDO, PLL_PERI0 P0, no AHB3, no resistor calibration); MMC
  calibration and new mode; the watchdog's 0x16AA key;
- SUNXI_NEW_PINCTRL: PIO banks 0x30 apart, 4-bit drive fields;
- the SPL's SPI0 at 0x04025000 on PC0-PC5, without the controller
  divider; spi-sunxi's R329 variant (no divider, normal sampling);
- DRAM: dram_sun20i_d1.c as OpenIPC's hardware-tested V851s U-Boot
  (mainline 2024.10) carries it, non-DM, with its parameters as the
  Kconfig defaults;
- sun8i-v851s.dtsi with what U-Boot uses (the CCU's gates are the H6's);
  the kernel is entered in HYP with PSCI from psci_v831.c.

Shared: include/configs/v83x.h becomes openipc-sunxi.h (the DDR size per
SoC); the SoC, device tree, PSCI and SPL stack move to the per-SoC
fragments; ATAGs are built in for the kernels with an appended device
tree; BINMAN is off with OPENIPC.

Under qemu-bench every SoC's -nor and -mmc image passes the two-boot
smoke test and reset; the SD unbricking path (run ub, then the NOR
alone) works on the V3s and V851s. The V851s's DRAM, CCU and PRCM
registers equal those left by the published OpenIPC u-boot-v851s-nor.bin
(SMHC0's clock aside: this U-Boot probes the card), and the published
OpenIPC V851s kernel and rootfs boot to a shell from the NOR and reboot.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add OpenIPC boot images for Allwinner V3s and V851s

✨ Enhancement 🐞 Bug fix 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Add NOR and SD recovery images for V3s and V851s using the existing OpenIPC boot layout.
• Backport V851s platform support and enable V3s SPI NOR boot and internal-PHY Ethernet.
• Share SPI-flash environment and SD boot-source handling across all four SoCs.
Diagram

graph TD
  ROM["Boot ROM"] --> SPL["Sunxi SPL"] --> DRAM["DRAM init"] --> BOOT["U-Boot"] --> KERNEL["OpenIPC kernel"]
  NOR["SPI NOR"] --> SPL
  MMC["SD card"] --> SPL
  BOOT --> NOR
  BOOT --> MMC
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use the published V851s boot binary
  • ➕ Uses an image already tested on camera hardware.
  • ➕ Avoids maintaining a DRAM initialization backport.
  • ➖ Does not provide the shared, source-built SPL and recovery-image workflow.
  • ➖ Makes boot behavior and future fixes dependent on a separate binary.
2. Port V851s DRAM through driver model
  • ➕ Would align more closely with the newer upstream RAM-driver integration.
  • ➖ Requires broader changes to this v2022.10 SPL and increases early-boot integration risk.
  • ➖ Provides little immediate benefit for the fixed V851s target.

Recommendation: Keep the source-built, non-DM V851s DRAM path and shared image layout: they fit this tree's SPL architecture while preserving the existing OpenIPC recovery workflow. The QEMU and register-comparison results support the approach, but camera testing should precede replacing the published V851s image.

Files changed (45) +2476 / -107

Enhancement (29) +2270 / -30
MakefileReuse the V831 PSCI monitor on V851s +1/-1

Reuse the V831 PSCI monitor on V851s

• Selects the existing V831-specific PSCI implementation for V851s as well as V831.

arch/arm/cpu/armv7/sunxi/Makefile

sun8i-v3s-openipc.dtsDescribe the OpenIPC V3s board +53/-0

Describe the OpenIPC V3s board

• Enables UART0, SD, SPI NOR, and the EMAC with its internal PHY for the V3s image.

arch/arm/dts/sun8i-v3s-openipc.dts

sun8i-v851s-openipc.dtsDescribe the OpenIPC V851s board +47/-0

Describe the OpenIPC V851s board

• Enables the V851s UART console, SD controller, and SPI NOR on top of the new SoC description.

arch/arm/dts/sun8i-v851s-openipc.dts

sun8i-v851s.dtsiDefine V851s peripherals used by U-Boot +150/-0

Define V851s peripherals used by U-Boot

• Introduces the V851s CPU, clocks, pinctrl, interrupt controller, UART, MMC, and SPI nodes with NCAT2 addresses and bindings.

arch/arm/dts/sun8i-v851s.dtsi

clock.hSelect H6-style clock definitions for NCAT2 +1/-1

Select H6-style clock definitions for NCAT2

• Routes NCAT2 builds to the clock register definitions reused by V851s.

arch/arm/include/asm/arch-sunxi/clock.h

clock_sun50i_h6.hAdd V851s PLL fields and clock defaults +8/-0

Add V851s PLL fields and clock defaults

• Defines NCAT2 PLL control fields and the V851s clock values used during early initialization.

arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h

cpu.hSelect the NCAT2 memory map +2/-0

Select the NCAT2 memory map

• Includes the new NCAT2 CPU address definitions when building for that generation.

arch/arm/include/asm/arch-sunxi/cpu.h

cpu_sunxi_ncat2.hDefine D1-generation peripheral addresses +56/-0

Define D1-generation peripheral addresses

• Adds the SRAM, clock, DRAM, storage, watchdog, and other register bases needed by V851s early boot.

arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h

dram.hAccommodate the V851s DRAM driver header +2/-0

Accommodate the V851s DRAM driver header

• Leaves V851s DRAM structures to the new driver's local header instead of including an unrelated controller definition.

arch/arm/include/asm/arch-sunxi/dram.h

gpio.hModel the NCAT2 GPIO register layout +21/-0

Model the NCAT2 GPIO register layout

• Adds the wider drive-strength fields and bank spacing used by the new pinctrl layout, plus V851s UART pin settings.

arch/arm/include/asm/arch-sunxi/gpio.h

mmc.hExpose extended MMC registers on NCAT2 +2/-1

Expose extended MMC registers on NCAT2

• Applies the newer MMC register layout to the V851s generation.

arch/arm/include/asm/arch-sunxi/mmc.h

prcm.hReuse H6-style PRCM definitions on NCAT2 +1/-1

Reuse H6-style PRCM definitions on NCAT2

• Selects the PRCM register definitions used by the V851s platform.

arch/arm/include/asm/arch-sunxi/prcm.h

timer.hInclude NCAT2 watchdogs in the timer layout +2/-1

Include NCAT2 watchdogs in the timer layout

• Makes the existing five-watchdog register layout available to NCAT2 builds.

arch/arm/include/asm/arch-sunxi/timer.h

watchdog.hAdd the NCAT2 watchdog write key +8/-2

Add the NCAT2 watchdog write key

• Includes the required 0x16AA key in V851s watchdog configuration and enable values so reset writes take effect.

arch/arm/include/asm/arch-sunxi/watchdog.h

KconfigConfigure V851s and shared OpenIPC sunxi defaults +78/-5

Configure V851s and shared OpenIPC sunxi defaults

• Adds the NCAT2 SoC, pinctrl, and DRAM options with V851s parameters. Enables V3s/V851s SPI SPL support and sets generation-specific SRAM, clocks, and SPL stack defaults.

arch/arm/mach-sunxi/Kconfig

MakefileBuild NCAT2 clocks and V851s DRAM initialization +2/-0

Build NCAT2 clocks and V851s DRAM initialization

• Includes the reused H6-style clock code and the new D1-generation DRAM driver for V851s builds.

arch/arm/mach-sunxi/Makefile

board.cInitialize V851s UART pins and watchdog reset +6/-1

Initialize V851s UART pins and watchdog reset

• Configures the V851s UART0 pins during early boot and includes NCAT2 in the watchdog reset path.

arch/arm/mach-sunxi/board.c

clock_sun50i_h6.cAdapt early clock setup to NCAT2 +16/-2

Adapt early clock setup to NCAT2

• Skips unsupported resistor calibration and AHB3 setup, enables the NCAT2 CPU PLL fields, and accounts for its PLL_PERI0 divider.

arch/arm/mach-sunxi/clock_sun50i_h6.c

cpu_info.cIdentify V851s on the console +2/-0

Identify V851s on the console

• Adds a V851s CPU identification string to the boot banner.

arch/arm/mach-sunxi/cpu_info.c

dram_sun20i_d1.cInitialize and size V851s DDR2 in SPL +1496/-0

Initialize and size V851s DDR2 in SPL

• Adds the D1-generation DRAM initialization sequence adapted for non-DM SPL use, including voltage calibration, training, topology detection, timing, and size reporting. Its parameters come from Kconfig.

arch/arm/mach-sunxi/dram_sun20i_d1.c

dram_sun20i_d1.hDefine D1 DRAM registers and parameters +209/-0

Define D1 DRAM registers and parameters

• Introduces the controller, PHY, SID, and SRAM register layouts and parameter structure used by the V851s DRAM initialization code.

arch/arm/mach-sunxi/dram_sun20i_d1.h

spl_spi_sunxi.cLoad V851s U-Boot through NCAT2 SPI0 +36/-8

Load V851s U-Boot through NCAT2 SPI0

• Adds NCAT2 SPI and CCU addresses, V851s pin setup, and normal sampling. Avoids writing a controller clock divider that NCAT2 SPI lacks.

arch/arm/mach-sunxi/spl_spi_sunxi.c

build.shBuild NOR and SD images for four Allwinner SoCs +2/-2

Build NOR and SD images for four Allwinner SoCs

• Adds V3s and V851s to the accepted targets and default build list while retaining the existing image assembly and partition-size checks.

build.sh

clk_sunxi.cBind the V851s CCU +2/-0

Bind the V851s CCU

• Maps the V851s clock-controller compatible to the reused H6 CCU description.

drivers/clk/sunxi/clk_sunxi.c

clk_v3s.cEnable V3s EMAC and internal PHY clocks +4/-0

Enable V3s EMAC and internal PHY clocks

• Adds the EMAC and EPHY bus gates and resets required for the V3s network interface.

drivers/clk/sunxi/clk_v3s.c

sunxi_mmc.cSupport NCAT2 MMC calibration and clocks +8/-4

Support NCAT2 MMC calibration and clocks

• Enables the newer MMC calibration, register handling, bus-width selection, and module-clock offsets for NCAT2.

drivers/mmc/sunxi_mmc.c

sun8i_emac.cBind the V3s EMAC as an H3 variant +1/-0

Bind the V3s EMAC as an H3 variant

• Recognizes the V3s EMAC compatible and uses the existing H3 controller behavior.

drivers/net/sun8i_emac.c

pinctrl-sunxi.cDefine V851s MMC, SPI, and UART pin functions +22/-0

Define V851s MMC, SPI, and UART pin functions

• Adds the V851s pin-function mapping and device-tree compatible for the common sunxi pinctrl driver.

drivers/pinctrl/sunxi/pinctrl-sunxi.c

spi-sunxi.cAdd the dividerless R329-style SPI variant +32/-1

Add the dividerless R329-style SPI variant

• Introduces the SPI variant used by V851s and selects normal sampling instead of programming a nonexistent controller clock divider.

drivers/spi/spi-sunxi.c

Bug fix (1) +21 / -7
board.cShare OpenIPC NOR environment and SD source handling +21/-7

Share OpenIPC NOR environment and SD source handling

• Falls back to the SPI-flash environment for every OpenIPC SoC after SD boot. Moves the per-boot SD recovery source selection here so V3s and V851s receive it too.

board/sunxi/board.c

Refactor (3) +16 / -22
v83x.cRemove V83x-only SD boot-source handling +0/-17

Remove V83x-only SD boot-source handling

• Drops the boot-source function and its no-longer-needed SPL includes after the behavior moves to the shared sunxi board code.

board/sunxi/v83x.c

openipc-common.hDerive OpenIPC memory setting from SDRAM size +3/-4

Derive OpenIPC memory setting from SDRAM size

• Uses the configured physical DDR size rather than V831-specific DRAM type to choose the shared 64 MiB or 128 MiB kernel memory setting.

include/configs/openipc-common.h

openipc-sunxi.hShare the OpenIPC sunxi configuration header +13/-1

Share the OpenIPC sunxi configuration header

• Generalizes the former V83x header, retaining V831/V833 sizing while adding V3s/V851s 64 MiB sizing and the V851s GIC base.

include/configs/openipc-sunxi.h

Documentation (2) +104 / -31
CLAUDE.mdDocument four-SoC boot architecture and verification +103/-30

Document four-SoC boot architecture and verification

• Expands the platform, DRAM, peripheral, build, and kernel hand-off guidance to cover V3s and V851s. Records QEMU verification and the absence of camera testing.

CLAUDE.md

dram_sun8i_v831.cClarify V831 DRAM sizing behavior under QEMU +1/-1

Clarify V831 DRAM sizing behavior under QEMU

• Qualifies a comment about QEMU's reported DRAM size to distinguish machines that model address mapping.

arch/arm/mach-sunxi/dram_sun8i_v831.c

Other (10) +65 / -17
KconfigExclude OpenIPC sunxi builds from binman +1/-1

Exclude OpenIPC sunxi builds from binman

• Makes the binman exception apply to all OpenIPC builds rather than only V831, since the build script assembles their images.

arch/arm/Kconfig

MakefileRegister the OpenIPC V3s and V851s device trees +4/-1

Register the OpenIPC V3s and V851s device trees

• Adds both new board DTBs to their respective SoC build lists.

arch/arm/dts/Makefile

KconfigPlace V851s SPL data and entry point +2/-2

Place V851s SPL data and entry point

• Adds V851s to the relevant SPL BSS and SRAM text-address defaults.

common/spl/Kconfig

KconfigEnable the reused CCU driver on V851s +1/-1

Enable the reused CCU driver on V851s

• Selects H6-style common clock support by default for the V851s target.

drivers/clk/sunxi/Kconfig

KconfigEnable V851s pinctrl support +5/-0

Enable V851s pinctrl support

• Adds a V851s pinctrl option selected by default for its SoC.

drivers/pinctrl/sunxi/Kconfig

openipc_configKeep only common OpenIPC boot configuration +6/-12

Keep only common OpenIPC boot configuration

• Moves SoC selection, device trees, SPL stacks, and PSCI settings to per-SoC fragments. Enables ATAG hand-off options needed by the V3s and V851s kernels.

openipc/openipc_config

v3s_configConfigure the OpenIPC V3s image +9/-0

Configure the OpenIPC V3s image

• Selects the V3s SoC and board tree, 360 MHz DRAM, image identity, and SRAM SPL stack.

openipc/v3s_config

v831_configLocalize V831 platform and PSCI settings +11/-0

Localize V831 platform and PSCI settings

• Adds the V831 SoC, device tree, identity, SPL stack, and non-secure PSCI settings formerly supplied by the common fragment.

openipc/v831_config

v833_configLocalize V833 platform and PSCI settings +11/-0

Localize V833 platform and PSCI settings

• Adds the shared V83x SoC and device-tree selection, SPL stack, identity, and non-secure PSCI settings alongside V833 DRAM parameters.

openipc/v833_config

v851s_configConfigure the OpenIPC V851s image +15/-0

Configure the OpenIPC V851s image

• Selects V851s, its device tree and identity, the SRAM A1 SPL stack, and non-secure PSCI kernel hand-off.

openipc/v851s_config

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

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

Copy link
Copy Markdown

Code Review by Qodo

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

Grey Divider


Action required

1. V851s can boot without a DDR clock ✓ Resolved
Description
ccu_set_pll_ddr_clk() sets the output-enable bit on pll1_cfg even though it configures PLL5 as
the DRAM clock source. If PLL5's output bit is clear when the SPL starts, PLL5 can lock but DRAM
initialization proceeds without its selected clock and can stall in controller polling.
Code

arch/arm/mach-sunxi/dram_sun20i_d1.c[539]

+	setbits_le32(&ccm->pll1_cfg, BIT(27));
Evidence
The routine configures and waits for PLL5, then writes the output-enable bit to a different PLL
register. The clock definitions identify bit 27 as PLL5's output enable, and the same routine
selects the PLL5 DRAM clock.

arch/arm/mach-sunxi/dram_sun20i_d1.c[524-545]
arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h[230-245]

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 V851s DRAM setup enables PLL1's output instead of the PLL5 output selected for DRAM.
## Fix Focus Areas
- arch/arm/mach-sunxi/dram_sun20i_d1.c[524-545]
## Recommended Fix
Set the PLL5 output-enable bit on `ccm->pll5_cfg` after PLL5 locks, rather than setting it on `ccm->pll1_cfg`.

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



Remediation recommended

2. SD card on the V851s runs at half the requested clock 🐞 Bug ≡ Correctness
Description
clock_get_pll6() forces m = 1 for NCAT2, so with the programmed 0xe8216310 (N=100, P0=2) it
returns 24 MHz·100/2 = 1200 MHz, which is PLL_PERI0(2X), whereas mmc_set_mod_clk() treats the
value as plain PLL6 (1X) and the D1 SMHC mux value 1 selects PLL_PERI(1X) at 600 MHz with no
post-divider. Every MMC divider is therefore computed for twice the real source rate, so SD
transfers (including the -mmc unbricking path and ub/fwupd from the card) run at half the
intended frequency.
Code

arch/arm/mach-sunxi/clock_sun50i_h6.c[R138-143]

+	/* NCAT2: P0 divides PLL_PERI0 (1X), as mainline's R528 code does */
+	if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
+		div1 = ((rval & CCM_PLL6_CTRL_P0_MASK) >>
+			CCM_PLL6_CTRL_P0_SHIFT) + 1;
+		m = 1;
+	}
Evidence
The default m is 2 for non-H6 SoCs so the function returns the 1X rate; the NCAT2 branch overrides
it to 1, doubling the result. mmc_set_mod_clk explicitly assumes PLL6 1X ('pretend it's always
PLL6 without a post divider') and computes div = pll_hz / hz. The PR notes that SMHC0's clock is
the one register that differs from the published V851s U-Boot.

arch/arm/mach-sunxi/clock_sun50i_h6.c[128-146]
drivers/mmc/sunxi_mmc.c[130-152]
arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h[292-296]

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

## Issue description
On NCAT2 `clock_get_pll6()` sets `m = 1`, returning PLL_PERI0(2X) (1200 MHz) instead of the 1X rate (600 MHz) that `mmc_set_mod_clk()` assumes, so SD clocks come out at half the requested rate.
## Fix Focus Areas
- arch/arm/mach-sunxi/clock_sun50i_h6.c[138-145]
## Recommended Fix
In the NCAT2 branch only replace `div1` with the P0 divider; do not override `m` (leave it at 2), so the function returns 24 MHz * N / M / P0 / 2 = PLL_PERI(1X), as mainline does. Fix the comment accordingly.

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


3. SPI mode from the device tree is ignored on the V851s ✓ Resolved
Description
sun4i_spi_claim_bus() skips sun4i_spi_set_speed_mode() when has_clk_ctl is false, although
that helper programs CPOL/CPHA in TCR as well as the CCR divider. On the R329/V851s variant, a
requested non-default mode from spi-cpol/spi-cpha or sf probe is stored but never applied to
hardware, leaving the controller in its reset or SPL mode.
Code

drivers/spi/spi-sunxi.c[R308-319]

+	if (priv->variant->has_clk_ctl) {
+		sun4i_spi_set_speed_mode(dev->parent);
+	} else {
+		/*
+		 * No divider inside (R329, D1, V851s): the module clock, the
+		 * 24 MHz HOSC, is the bus clock; sample in the normal mode
+		 */
+		clrsetbits_le32(SPI_REG(priv, SPI_TCR),
+				SPI_BIT(priv, SPI_TCR_SDC) |
+				SPI_BIT(priv, SPI_TCR_SDM),
+				SPI_BIT(priv, SPI_TCR_SDM));
+	}
Evidence
sun4i_spi_set_speed_mode() writes the CCR divider and then updates TCR CPOL/CPHA from
priv->mode. The new no-divider branch bypasses that helper and changes only the SDC/SDM sampling
bits, while sun4i_spi_set_mode() merely stores the requested mode; consequently, this path never
writes the requested CPOL/CPHA bits.

drivers/spi/spi-sunxi.c[235-288]
drivers/spi/spi-sunxi.c[290-322]
drivers/spi/spi-sunxi.c[237-286]
drivers/spi/spi-sunxi.c[299-319]
drivers/spi/spi-sunxi.c[416-427]

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 R329/V851s no-divider path skips `sun4i_spi_set_speed_mode()`, so it also skips programming the requested CPOL/CPHA mode.
## Fix Focus Areas
- drivers/spi/spi-sunxi.c[235-288]
- drivers/spi/spi-sunxi.c[305-319]
## Recommended Fix
Call `sun4i_spi_set_speed_mode()` when claiming the bus for both controller variants. Inside the helper, guard only the CCR divider computation and write with `if (priv->variant->has_clk_ctl)`; for the no-divider case, set SDM and clear SDC there. Keep the TCR CPOL/CPHA update unconditional so both variants apply the stored mode.

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


4. V851s PSCI monitor sits in RAM the kernel may overwrite ✓ Resolved
Description
The V851s fragment enables ARMV7_NONSEC/ARMV7_PSCI, but HAS_ARMV7_SECURE_BASE only defaults on
for MACH_SUN6I/7I/8I, so the monitor (__secure_start..__secure_end, MVBAR) stays inside
relocated U-Boot at the top of DDR, and it is protected only by fdt_add_mem_rsv() in the
device-tree fixup. The V851s kernel is booted with ATAGs and an appended DTB, so no reservation
reaches it and the memory ATAG covers all 64 MiB; once Linux reuses those pages, any later SMC (PSCI
SYSTEM_RESET/SYSTEM_OFF/CPU_OFF) jumps into overwritten memory.
Code

openipc/v851s_config[R12-15]

+CONFIG_ARMV7_NONSEC=y
+CONFIG_ARMV7_PSCI=y
+CONFIG_ARMV7_PSCI_1_0=y
+CONFIG_ARMV7_PSCI_NR_CPUS=1
Evidence
Without ARMV7_SECURE_BASE, the secure section is only protected via the FDT memreserve in virt-dt.c;
MACH_SUN8I (which gives SECURE_BASE 0x44000) does not include V851S. The new base config switches
the V3s/V851s hand-off to ATAGs, so no FDT is modified for the kernel.

arch/arm/cpu/armv7/Kconfig[30-44]
arch/arm/cpu/armv7/virt-dt.c[60-70]
arch/arm/mach-sunxi/Kconfig[417-426]
openipc/openipc_config[33-37]

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

## Issue description
On the V851s the PSCI monitor stays in DRAM and is only reserved through an FDT memreserve, which ATAG-booted kernels never see, so the kernel can overwrite it.
## Fix Focus Areas
- arch/arm/cpu/armv7/Kconfig[30-58]
- openipc/v851s_config[10-15]
## Recommended Fix
Enable `HAS_ARMV7_SECURE_BASE` for MACH_SUN8I_V851S and give `ARMV7_SECURE_BASE`/`ARMV7_SECURE_MAX_SIZE` an SRAM region not used after boot (e.g. part of SRAM A1 above the SPL), so `relocate_secure_section()` copies the monitor out of DRAM; alternatively reduce the memory ATAG/`mem=` to exclude the U-Boot area.

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



Informational

5. SPI flash pins get the wrong mux instead of being disabled on V851s ✓ Resolved
Description
spi0_deinit() sets PC0-PC5 to SUNXI_GPIO_DISABLE (7) for sun6i-gen SPI, but this PR's new
pinctrl layout (SUNXI_NEW_PINCTRL) uses 0xF as the disabled value and 7 is a peripheral function
slot. After the SPL hands over, the V851s SPI flash pins sit in function 7, not disabled, until
U-Boot's pinctrl re-muxes them, and pinctrl-sunxi also misreports disabled pins on this SoC.
Code

arch/arm/include/asm/arch-sunxi/gpio.h[R55-58]

+#ifdef CONFIG_SUNXI_NEW_PINCTRL
+/* D1/T113 (NCAT2): four drive registers, 4 bits a pin; banks 0x30 apart */
+struct sunxi_gpio {
+	u32 cfg[4];
Evidence
SUNXI_GPIO_DISABLE stays 7 regardless of CONFIG_SUNXI_NEW_PINCTRL, and spl_spi_sunxi.c uses it for
sun6i-gen controllers, which now include NCAT2 via is_h6_spi().

arch/arm/include/asm/arch-sunxi/gpio.h[150-160]
arch/arm/mach-sunxi/spl_spi_sunxi.c[263-273]

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 CONFIG_SUNXI_NEW_PINCTRL the pin 'disabled' function is 0xF, but SUNXI_GPIO_DISABLE is still 7, so spi0_deinit() muxes the V851s SPI pins to function 7.
## Fix Focus Areas
- arch/arm/include/asm/arch-sunxi/gpio.h[150-160]
## Recommended Fix
Wrap the define: `#ifdef CONFIG_SUNXI_NEW_PINCTRL #define SUNXI_GPIO_DISABLE 0xf #else #define SUNXI_GPIO_DISABLE 7 #endif`, as mainline does.

ⓘ 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 enable the Remediation agent and Qodo fixes findings in a dedicated fix PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread arch/arm/mach-sunxi/dram_sun20i_d1.c Resolved
Comment thread arch/arm/mach-sunxi/clock_sun50i_h6.c Resolved
Comment thread drivers/spi/spi-sunxi.c Resolved
Comment thread openipc/v851s_config Resolved
Comment thread arch/arm/include/asm/arch-sunxi/gpio.h Resolved
…PLL_DDR

- The PSCI monitor stayed in relocated U-Boot at the top of the DDR,
  reserved only in a device tree; the V851s kernels boot with ATAGs.
  Their own tree keeps that region no-map (the RISC-V core's), but that
  is the RISC-V firmware's place. HAS_ARMV7_SECURE_BASE now copies it to
  SRAM A1 at 0x38000 (32 KiB, free once the SPL is done; U-Boot's early
  stack is below 0x28000).
- spi-sunxi's R329 variant skipped sun4i_spi_set_speed_mode() whole, and
  with it CPOL/CPHA: only the divider is skipped now.
- SUNXI_GPIO_DISABLE is 0xf with the new pinctrl layout (7 is a function
  there): the SPL's spi0_deinit() and pinctrl's status use it.
- dram_sun20i_d1.c set bit 27, the output enable, on PLL_CPU's register
  after locking PLL_DDR (as mainline and awboot do; PLL_DDR's is set at
  reset, so it worked): PLL_DDR's now.

clock_get_pll6() keeps mainline's NCAT2 m = 1 (see the PR).

Every image passes the smoke test and reset again; the V851s kernel boots
to a shell with the monitor in SRAM, and reboots.
@dimerr
dimerr merged commit 5b87822 into openipc-allwinner Oct 25, 2026
10 checks passed
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