Skip to content

arm64: dts: amlogic: enable eMMC HS200 by default#13

Open
allolive wants to merge 1 commit into
CoreELEC:5.15.196_20260225from
allolive:am6b-plus-emmc-hs400
Open

arm64: dts: amlogic: enable eMMC HS200 by default#13
allolive wants to merge 1 commit into
CoreELEC:5.15.196_20260225from
allolive:am6b-plus-emmc-hs400

Conversation

@allolive
Copy link
Copy Markdown

@allolive allolive commented May 24, 2026

coreelec_common.dtsi does not enables HS200 on boards whose eMMC (at least G12B and SM1).
The eMMC therefore tops out at plain high-speed (~50 MB/s) instead of HS200 (~150 MB/s).

Enable HS200 next to the existing HS400 removal so capable eMMCs negotiate HS200 by default.

@Pro-me3us
Copy link
Copy Markdown
Contributor

Pro-me3us commented May 25, 2026

Did you try only adding the mmc-hs400-1_8v; property to the emmc node, without changing anything else? This is normally all that's required (was enough on the 2nd gen Cube with meson-gx-mmc driver).

CE intentionally doesn't place the mmc-hs400-1_8v; property by default in the dts for greater compatibility. Toggling HS400 within CE Settings adds the mmc-hs400-1_8v; property so that the user has the flexibility of disabling the higher speed if they experience any problems.

@Portisch
Copy link
Copy Markdown
Contributor

This is what I would prefer. Bring back the option in the CE settings so users can adjust it themselves, but don't force HS400 mode as it may lead to devices not booting.

Since internal installation is no longer possible as of Android 14, this option also receives less attention.
When we have time, we can look into this item again.

For the other items, please change or split the PR as this one will not be merged.

@allolive
Copy link
Copy Markdown
Author

@Pro-me3us @Portisch — thanks both, got it.

To Pro-me3us's question: I did try a simpler approach first — just adding mmc-hs200-1_8v to the AM6B+ DTS while keeping the mainline meson-gx-mmc driver bound. It stayed at legacy HS mode rather than negotiating HS200, which led me down the driver-swap path. I'll look into the FTC 2nd gen implementation to understand what makes the simpler path work there.

To Portisch's points: understood, this PR won't be merged as is.

Would you be OK with me opening two follow-ups:

  1. Standalone HDMI vendor info fix for the AM6B+ board file (patch 7 from this series). vendor_name = "UGOOS", product_desc = "AM6B+" so AVRs/TVs show the actual product instead of the generic "G12B" SoC name. Independent of any eMMC work.

  2. AM6B+ HS400 enablement IF I can get the 2nd gen Cube DTS pattern to work on AM6B+.

@Portisch
Copy link
Copy Markdown
Contributor

  1. Yes, for the second I will need more time to check the sources. Just leave this PR open and force push it without the HDMI info.

@allolive allolive force-pushed the am6b-plus-emmc-hs400 branch from 1371264 to 3757596 Compare May 25, 2026 21:34
@allolive
Copy link
Copy Markdown
Author

Sure, I force-pushed this branch to drop the HDMI commit. That change is now in PR #14 as a standalone.

For the HS400 side, I tried the simpler path first on the mainline meson-gx-mmc driver — just adding mmc-hs400-1_8v in DT, with the meson-gx-mmc.caps2_quirks=mmc-hs400 in /flash/config.ini negotiates, but sustained writes to AM6B+'s eMMC hit CRC errors right away.

Adding tx_delay = <16> in the DTS on the parent &sd_emmc_c node (one line of DTS, no driver changes) fixes it — looks stable so far. Obviously needs more testing than the 20 mins I spent.

Happy to open that as a separate PR as it would allow it as an option in the CE settings.

@Pro-me3us Pro-me3us force-pushed the 5.15.196_20260225 branch from 4e69fc2 to 3b1456a Compare May 26, 2026 14:40
Copy link
Copy Markdown
Contributor

@Portisch Portisch left a comment

Choose a reason for hiding this comment

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

This is not true, it uses this driver:

{ .compatible = "amlogic,meson-axg-mmc", .data = &meson_axg_data },

In Linux config the AML driver is used:
CONFIG_AMLOGIC_MMC_MESON_GX=y

@allolive
Copy link
Copy Markdown
Author

Sorry @Portisch, you're right, I had the driver wrong.

The experiment still stands though: mmc-hs400-1_8v; in DTS as suggested by @Pro-me3us + tx_delay = <16> also in DTS + the caps2_quirks=mmc-hs400 cmdline gets HS400 stable on my AM6B+ without any driver changes.

Something like that in the DTS:

&sd_emmc_c {
     mmc-hs400-1_8v;
     tx_delay = <16>;
};

Should I close this PR and open a new one with just the few lines of DTS change?

@Pro-me3us
Copy link
Copy Markdown
Contributor

Pro-me3us commented May 27, 2026

The 4.9 sdio driver has AML SOC specific configurations that aren't present in the meson-gx-mmc version. In the 4.9 sdio driver, the g12b revb table does use tx_delay = <16> for HS400
https://github.com/CoreELEC/linux-amlogic/blob/50c8e8154c5aba3c7cd8438d04dd5fdd51733e41/drivers/amlogic/mmc/aml_sd_emmc.c#L3701-L3703

But in meson-gx-mmc tx_delay = <16> is the default value. If no tx_delay property is present under the eMMC node, I don't think it should make a difference having it in the dts?

if (device_property_read_u32(dev, "tx_delay",
&mmc->sd_mmc.hs4.tx_delay) < 0)
mmc->sd_mmc.hs4.tx_delay = 16;

@allolive
Copy link
Copy Markdown
Author

Thanks for the pointer @Pro-me3us . I re-tested today on myAM6B+ to be sure.

The default-to-16 at meson-gx-mmc.c:163-164 doesn't actually fire on this binding:

# SD_EMMC_CLOCK @ 0xffe07000, tx_delay = bits 21-16
v=$(busybox devmem 0xffe07000 32)
printf "tx_delay = %d  (raw: %s)\n" $(( (v >> 16) & 0x3f )) "$v"

With tx_delay = <16>; in DTS: tx_delay = 16 (raw: 0x10100002)
Without: tx_delay = 0 (raw: 0x10000002)

So the delay line makes a difference. Not a no-op.

When I ran without the delay setting earlier this week-end the boot CRCs progressed into the write failure and corrupted the eMMC. I had to re-flash the amlogic image to recover.

So, two runs, same outcome.

@allolive
Copy link
Copy Markdown
Author

@Pro-me3us @Portisch , I think I tracked it down.

meson-gx-mmc does default tx_delay to 16. The reason that default never takes effect is that mesong12b.dtsi hard-codes tx_delay = <0>. So the property is present (= 0) and amlogic_of_parse() never reaches the < 0 fallback at meson-gx-mmc.c#L162-L164.

So to replace all my driver code, it should come down to a simple 2-file change:

  1. add the HS400 enable to the Ugoos DTS
  2. remove (or replace) the default tx_delay value in mesong12b.dtsi

Should I recreate this PR as a single commit with that?

@Pro-me3us
Copy link
Copy Markdown
Contributor

Pro-me3us commented May 29, 2026

Yeah you're right, I hadn't noticed the final .dtb included with the CE-NO image has the tx_delay = <0> property. Maybe that's present because it's best for cap-mmc-highspeed (default mode) on the g12b. If that is the case, removing tx_delay = <0> from the dtsi might cause problems with other g12b boards that don't have HS400 set.

It would be safer to follow your previous suggestion and only apply the tx_delay = <16> + mmc-hs400-1_8v properties to the AM6. Or use the same strategy as CE-NG and add an option under CoreELEC Settings / Hardware to enable HS400 through the dtb.xml, which then adds mmc-hs400-1_8v; + tx_delay = <16>;

@Portisch

This comment was marked as off-topic.

1 similar comment
@Portisch
Copy link
Copy Markdown
Contributor

I tested the changes on G12B, Minix U22-XJ, installed CE on eMMC.

Default DTB:

emmc@ffe07000 {
    status = "okay";
    compatible = "amlogic,meson-axg-mmc";
    reg = <0x00000000 0xffe07000 0x00000000 0x00000800 0x00000000 0xffe07000 0x00000000 0x00000800 0x00000000 0xffe07000 0x00000000 0x00000800>;
    interrupts = <0x00000000 0x000000bf 0x00000004>;
    clocks = <0x00000007 0x00000023 0x00000007 0x00000043 0x00000007 0x0000003e 0x00000017 0x00000007 0x00000002 0x00000007 0x00000063>;
    clock-names = "core", "mux0", "mux1", "clkin0", "clkin1", "clkin2";
    tx_delay = <0x00000000>;
    card_type = <0x00000001>;
    mmc_debug_flag;
    disable-wp;
    no-sdio;
    no-sd;
    pinctrl-0 = <0x00000042 0x00000043>;
    pinctrl-1 = <0x00000044>;
    pinctrl-names = "default", "clk-gate";
    bus-width = <0x00000008>;
    cap-mmc-highspeed;
    max-frequency = <0x0bebc200>;
    non-removable;
    mmc-pwrseq = <0x00000045>;
};

Speed test:

U22X-NO:~ # dd if=/dev/zero of=/storage/test.tmp bs=1M conv=fsync count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.0GB) copied, 29.359403 seconds, 34.9MB/s

U22X-NO:~ # rm /storage/test.tmp

U22X-NO:~ # dd if=/dev/zero of=/storage/test.tmp bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.0GB) copied, 11.052423 seconds, 92.6MB/s

U22X-NO:~ # dd if=/storage/test.tmp of=/dev/null bs=1M
1024+0 records in
1024+0 records out
1073741824 bytes (1.0GB) copied, 0.350659 seconds, 2.9GB/s

With changes:

&sd_emmc_c {
	mmc-hs400-1_8v;
	tx_delay = <16>;
};
emmc@ffe07000 {
    status = "okay";
    compatible = "amlogic,meson-axg-mmc";
    reg = <0x00000000 0xffe07000 0x00000000 0x00000800 0x00000000 0xffe07000 0x00000000 0x00000800 0x00000000 0xffe07000 0x00000000 0x00000800>;
    interrupts = <0x00000000 0x000000bf 0x00000004>;
    clocks = <0x00000007 0x00000023 0x00000007 0x00000043 0x00000007 0x0000003e 0x00000017 0x00000007 0x00000002 0x00000007 0x00000063>;
    clock-names = "core", "mux0", "mux1", "clkin0", "clkin1", "clkin2";
    tx_delay = <0x00000010>;
    card_type = <0x00000001>;
    mmc_debug_flag;
    disable-wp;
    no-sdio;
    no-sd;
    pinctrl-0 = <0x00000042 0x00000043>;
    pinctrl-1 = <0x00000044>;
    pinctrl-names = "default", "clk-gate";
    bus-width = <0x00000008>;
    cap-mmc-highspeed;
    max-frequency = <0x0bebc200>;
    non-removable;
    mmc-pwrseq = <0x00000045>;
    mmc-hs400-1_8v;
};

Speed test:

U22X-NO:~ # dd if=/dev/zero of=/storage/test.tmp bs=1M conv=fsync count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.0GB) copied, 9.708706 seconds, 105.5MB/s

U22X-NO:~ # rm /storage/test.tmp

U22X-NO:~ # dd if=/dev/zero of=/storage/test.tmp bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.0GB) copied, 3.354739 seconds, 305.2MB/s

U22X-NO:~ # dd if=/storage/test.tmp of=/dev/null bs=1M
1024+0 records in
1024+0 records out
1073741824 bytes (1.0GB) copied, 0.341832 seconds, 2.9GB/s

@allolive
Copy link
Copy Markdown
Author

Thanks @Pro-me3us @Portisch , I finally understood the settings comment.
It's got nothing to do with /flash/config.ini entries; it's the dtb.xml framework you pointed me at.

I didn't have to touch the settings add-on. There's already an "eMMC Speed Mode" entry in there.
The whole feature ends up being one file: an emmc node in the device's dtb.xml.

diff --git a/projects/Amlogic-ce/devices/Amlogic-no/bootloader/dtb.xml b/projects/Amlogic-ce/devices/Amlogic-no/bootloader/dtb.xml
index c99292869a..ded8cc12fe 100644
--- a/projects/Amlogic-ce/devices/Amlogic-no/bootloader/dtb.xml
+++ b/projects/Amlogic-ce/devices/Amlogic-no/bootloader/dtb.xml
@@ -182,6 +182,27 @@
     </wol_off>
   </wol>
 
+  <!-- eMMC HS400 opt-in (Settings > Hardware > eMMC Speed Mode). G12B, /emmc@ffe07000.
+       Validated HS400-stable: Ugoos AM6B+ (allolive), Minix U22-XJ (Portisch). -->
+  <emmc status="default" version="1" dt_id="am6b u22xj">
+    <emmc_default name="default">
+      <cmd path="/emmc@ffe07000 mmc-hs400-1_8v" option="d" type="i">
+        <value/>
+      </cmd>
+      <cmd path="/emmc@ffe07000 tx_delay" option="d" type="i">
+        <value/>
+      </cmd>
+    </emmc_default>
+    <emmc_hs400 name="hs400">
+      <cmd path="/emmc@ffe07000 mmc-hs400-1_8v" type="i">
+        <value>1</value>
+      </cmd>
+      <cmd path="/emmc@ffe07000 tx_delay" type="i">
+        <value>16</value>
+      </cmd>
+    </emmc_hs400>
+  </emmc>
+
   <custom_edid status="custom" version="0">
     <edid name="custom">
       <cmd path="/amhdmitx custom_edid" type="s">

With that node in place, the eMMC Speed Mode option shows up under Settings → Hardware, and flipping it to hs400 brings the eMMC up in HS400 after a reboot. Default stays at plain HS.

Stability looks solid here on my box with zero CRC errors

Happy to send a PR for this to CoreELEC. I'll wait for your feedbacks first.

@Portisch
Copy link
Copy Markdown
Contributor

Please test with this update.
Set to HS200:
mmc0: new HS200 MMC card at address 0001
Set to HS200,HS400:
mmc0: new HS400 MMC card at address 0001

https://test.coreelec.org/Portisch/temp/CoreELEC-Amlogic-no.aarch64-22.0-Piers_nightly_20260529.tar

@allolive
Copy link
Copy Markdown
Author

allolive commented May 29, 2026

Tested nightly 20260529.tar on the AM6B+

  • HS200,HS400 works great. Comes up as mmc0: new HS400 MMC card, ~224 MB/s read, zero CRC over a soak.
  • HS200 option only negotiates base high-speed (~44 MB/s), not HS200.

To enable HS200 properly, I add to update the xml file to this:

  <normal_speed name="HS200">
    <cmd path="*mmc@f* mmc-hs400-1_8v" option="d"/>
    <cmd path="*mmc@f* tx_delay" type="i"><value>0</value></cmd>
    <cmd path="*mmc@f* mmc-hs200-1_8v" option="c"/>   <!-- ADDED THIS LINE -->
  </normal_speed>

@Portisch
Copy link
Copy Markdown
Contributor

Portisch commented May 29, 2026

The HS200 may should be added as default, not by dtb.xml.

So you can fixup your PR to add default the hs200 property in common coreelec dtsi.

The hs400 is covered than by a dtb-xml change.

@allolive
Copy link
Copy Markdown
Author

allolive commented May 29, 2026

@Portisch to confirm, you mean to update this PR with 1 single commit and 1 file changed: arch/arm64/boot/dts/amlogic/g12b_s922x_ugoos_am6b_2g.dts

with this single edit:

&sd_emmc_c {
	mmc-hs200-1_8v;
};

or do you mean the global mesong12b.dtsi / coreelec_g12b_common.dtsi shared by all similar boards? or the global amlogic/coreelec_common.dtsi?

@Portisch
Copy link
Copy Markdown
Contributor

I think this is the best place:

It's at least G12B and SM1 what miss this setting.

coreelec_common.dtsi strips mmc-hs400-1_8v from the eMMC node for
compatibility, but nothing enables HS200 either. On boards whose eMMC
does not advertise HS200 on its own (at least G12B and SM1) the eMMC
therefore tops out at plain high-speed (~50 MB/s) instead of HS200
(~150 MB/s).

mmc-hs200-1_8v is a capability flag, not a forced mode: the kernel still
gates it on the card's EXT_CSD, so an eMMC that cannot do HS200 simply
stays at high-speed. Enable it next to the existing HS400 removal so
capable eMMCs negotiate HS200 by default.

Signed-off-by: allolive <160342668+allolive@users.noreply.github.com>
@allolive allolive force-pushed the am6b-plus-emmc-hs400 branch from 3757596 to 46cc2a7 Compare May 29, 2026 21:00
@allolive allolive changed the title AM6B+: enable eMMC HS400 (experimental) arm64: dts: amlogic: enable eMMC HS200 by default May 29, 2026
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.

3 participants