Skip to content

hisilicon: SD cards on generic-sdhci machines come up write-protected — vendor driver inverts the WP bit, wp-inverted is never set #209

Closed

Description

@openipc-ai

Symptom

On the HiSilicon machines that wire their SD slot as QEMU's generic-sdhci (hw/arm/hisilicon.c, the num_sdhci / sdhci_bases loop), every card attached with -drive if=sd is presented to the guest as write-protected. The OpenIPC kernel then registers it read-only, and every mount comes out ro:

mmcblk0: mmc0:3244 QEMU! 64.0 MiB (ro)
 mmcblk0: p1
/dev/mmcblk0p1 /mnt/mmcblk0p1 vfat ro,relatime,... 0 0

This applies to a writable raw image, the same way test-flash-rw.sh / test-firstboot.sh attach theirs. Those tests only read the card, so neither has noticed.

Cause

The vendor SDHCI driver reads the write-protect pin the opposite way from the SDHCI spec. drivers/mmc/host/sdhci-hisi.c in OpenIPC/linux's hisilicon-hi3516ev200 tarball (ev200 / ev300 / 18ev300 / dv200 all include it):

static const struct sdhci_pltfm_data sdhci_hisi_pdata = {
	.ops = &sdhci_hisi_ops,
	.quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
		  SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
	...

QEMU's sdhci_set_readonly() sets PRNSTS bit 19 (SDHC_WRITE_PROTECT) for a writable card. Linux's sdhci_check_ro() then inverts that because of the quirk, so the card comes out read-only. hisilicon.c never sets wp-inverted on its TYPE_SYSBUS_SDHCI instances. hw/arm/goke.c already handles the same thing for the GK710x SDIO (qdev_prop_set_bit(dev, "wp-inverted", true), citing gk_sd_get_ro).

Evidence (hi3516ev300, qemu-bench 07ec628, OpenIPC nightly-20261006-8a81fed)

Booted from a synthetic NOR as test-flash-rw.sh does, with a 64 MiB FAT32 card:

run kernel mount
as is mmcblk0: mmc0:3244 QEMU! 64.0 MiB (ro) vfat ro,...
-global generic-sdhci.wp-inverted=on mmcblk0: mmc0:80f7 QEMU! 64.0 MiB vfat rw,...

Suggested fix

In the SDHCI loop in hisilicon.c, qdev_prop_set_bit(sdhci, "wp-inverted", true) before realize, with a comment citing SDHCI_QUIRK_INVERTED_WRITE_PROTECT. A per-SoC flag would be needed if any of the other kernels behind this loop turn out not to carry the quirk.

Not verified: the kernels of the other machines that go through the same loop: hi3516cv608 / cv610 / cv613, hi3519dv500 / hi3516dv500 and gk7202v330. I have only checked the ev200-family sdhci-hisi.c. Their drivers should be checked for the same quirk before flipping it everywhere.

Why it matters

Any guest test that writes to the card, or depends on how a rw mount behaves, is testing something real cameras never do. I ran into it while reproducing OpenIPC/firmware#170 (kernel log noise from SD automount). A read-only device makes every rw mount attempt fail in the VFS before any filesystem's fill_super runs, so the noise that issue is about cannot appear.

Activity

  1. openipc-ai commented on Oct 26, 2026

    @openipc-ai
    ContributorAuthor

    Fixed by #210 (713e7f9).

    Cause: as described above, with one correction to the suggested fix. Not every machine behind the SDHCI loop inverts the pin. The kernels that do, each through SDHCI_QUIRK_INVERTED_WRITE_PROTECT:

    • hisilicon-hi3516ev200: sdhci-hisi.c
    • goke-gk7205v200: sdhci-goke.c
    • goke-gk7205v500: sdhci-xmedia-common.c
    • goke-gk7206v100: sdhci-lotus-common.c

    The nebula driver behind hi3516cv608/cv610/cv613 and hi3519dv500/hi3516dv500 uses the spec polarity. Flipping wp-inverted everywhere would have broken those machines.

    Fix: a per-SoC HisiSoCConfig.sdhci_wp_inverted. It's set on the four EV200-family entries and in HISI_V4_COMMON_PERIPH, which covers every Goke machine on this path.

    Evidence:

    • qemu/tests/test-hisi-sdhci-wp.sh (now in the CI build job): 8 failed / 2 passed on master, and 10/10 passed on the branch and in CI.
    • With the OpenIPC lite release kernel and a FAT32 card, hi3516ev300 and gk7205v200 now register mmcblk0: ... QEMU! 64.0 MiB without (ro), and automount mounts it vfat rw.

    Gaps:

    • The gk7205v500 release kernel probes no SD host at all, before and after this change, so on that machine only the register test covers it.
    • The nebula and gk7206 machines weren't boot-tested.
    • A read-only card can't be tested: QEMU refuses a read-only SD drive.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions