Disable the modem on a MSM8916 device and reclaim reserved memory

2026/06/21

Another article about the MSM8916 dongles. I have many of them, and they use an incredibly small amount of power, so they are somewhat useful if I basically just need a Linux computer and the specs don’t matter. Some of them even have nominally working Bluetooth, so I am experimenting with making these into, essentially, a smart speaker node.

On MSM8916 devices and I imagine many other Qualcomm platforms, some of the overall memory is reserved for exclusive use by the modem. I don’t need cellular communications, and a couple of the devices that I have don’t even have US cellular bands anyway, so the modem is just sitting there, parking its ass on ~80MB out of ~512mb, which is a significant chunk. That’s basically as much memory as an OpenRC console install of PostmarketOS uses on its own. Ideally, I’d like that chunk of memory back. PostmarketOS used to support disabling the modem in a user accessible way - or more accurately, the bootloader used for many older Qualcomm devices, lk2nd, used to. At one point, though, lk2nd underwent a significant or complete rewrite, and in the process of that, this remote processor selection was dropped. You can see the source code that handled this in the old version of lk2nd here, and this is ultimately derived from that. They do the device tree changes at runtime before passing it off to Linux, I am doing it at device tree compile-time.

Here is the output of git diff after applying this change on the device tree for one of my devices. These basic changes should work on any device based on the msm8916-ufi device tree, which includes all of the devices referred to as ‘zhihe-generic’ If you are curious, this ’thwc-hmuf02’ device tree is not upstream, it’s one I made myself from modifying the UFI001C one. The only differences are the LED and SIM select GPIOs, everything else is identical. Apply these changes to the .dts file of your choice.

diff --git a/arch/arm64/boot/dts/qcom/msm8916-thwc-hmuf02.dts b/arch/arm64/boot/dts/qcom/msm8916-thwc-hmuf02.dts
index b771cebe057e..cd15327ed222 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-thwc-hmuf02.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-thwc-hmuf02.dts
@@ -25,9 +25,13 @@ &led_r {
        gpios = <&tlmm 72 GPIO_ACTIVE_HIGH>;
 };
 
-&mpss {
-       pinctrl-0 = <&sim_ctrl_default>;
-       pinctrl-names = "default";
+&mpss { 
+       status = "disabled";
+};
+
+&mpss_mem {
+        reg = <0x0 0x86800000 0x0 0x0>;
+        status = "disabled";
 };
 
 &button_default {

Disabling the modem will also disable cellular GPS services. (Side note: Cellular GPS still works on Qualcomm’s APQ- variants of their Snapdragon chips. It still uses this ‘mpss’ subsystem for that, so those platforms still reserve memory for this purpose, just a smaller amount. I just think that’s interesting.)

The method I present here is somewhat hacky - I didn’t even properly compile with this change, I just pulled the kernel version that I was using for these devices and ran make dtbs (with CROSS_COMPILE=aarch64-unknown-linux-gnu- the prefix of my arm64 GCC cross-compiler binary on NixOS, and ARCH=arm64 set) and this may be better handled by a device tree overlay. lk2nd does apparently support the “fdtoverlay”/ “devicetree-overlay” extlinux configuration, so it’s possible. A properly written device tree overlay could be distributed in compiled form and used for any of these devices for convenience, since they all share these labels. Or possibly even all MSM8916 devices. If anyone knows how to write one that does the changes I present here, write in and I’ll credit you and change this page to present it. I tried, and it blew up in my face, and even though these changes are quite manual, they’re good enough for my purposes, since I can just copy a re-compiled device tree onto any device I want to disable the modem on and edit extlinux.conf to point at it.

Bonus - HMUF02-V05 device tree.

I am definitely overdue to send this into the MSM8916 ‘close to mainline’ PMOS kernel or the Linux kernel - it’s going here, in patch form, as compensation. That date is accurate, and I’m embarassed by it. In a pinch, the device tree for the UFI001C should boot these devices, the LEDs just won’t be easily accessible and you may have problems with the cellular modem.

add-HMUF02-V5-device-tree.patch

From: Rudi Knauss <hello@ryjelsum.me>
Date: Sat, 14 Mar 2026 16:49:02 -0700
Subject: [PATCH] add HMUF02-V5 device tree

---
 arch/arm64/boot/dts/qcom/Makefile             |  1 +
 .../boot/dts/qcom/msm8916-thwc-hmuf02.dts     | 68 +++++++++++++++++++
 2 files changed, 69 insertions(+)
 create mode 100644 arch/arm64/boot/dts/qcom/msm8916-thwc-hmuf02.dts

diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 6d951fbdd44f..ba932d5b2849 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -63,6 +63,7 @@ dtb-$(CONFIG_ARCH_QCOM)	+= msm8916-samsung-j5x.dtb
 dtb-$(CONFIG_ARCH_QCOM)	+= msm8916-samsung-rossa.dtb
 dtb-$(CONFIG_ARCH_QCOM)	+= msm8916-samsung-on7.dtb
 dtb-$(CONFIG_ARCH_QCOM)	+= msm8916-samsung-serranove.dtb
+dtb-$(CONFIG_ARCH_QCOM)	+= msm8916-thwc-hmuf02.dtb
 dtb-$(CONFIG_ARCH_QCOM)	+= msm8916-thwc-uf896.dtb
 dtb-$(CONFIG_ARCH_QCOM)	+= msm8916-thwc-ufi001c.dtb
 dtb-$(CONFIG_ARCH_QCOM)	+= msm8916-vivo-y21l.dtb
diff --git a/arch/arm64/boot/dts/qcom/msm8916-thwc-hmuf02.dts b/arch/arm64/boot/dts/qcom/msm8916-thwc-hmuf02.dts
new file mode 100644
index 000000000000..b771cebe057e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-thwc-hmuf02.dts
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/dts-v1/;
+
+#include "msm8916-ufi.dtsi"
+
+/ {
+	model = "HMUF02-V5 4G Modem Stick";
+	compatible = "thwc,hmuf02-v5", "qcom,msm8916";
+};
+
+&button_restart {
+	gpios = <&tlmm 37 GPIO_ACTIVE_HIGH>;
+};
+
+&led_b {
+	gpios = <&tlmm 73 GPIO_ACTIVE_HIGH>;
+};
+
+&led_g {
+	gpios = <&tlmm 71 GPIO_ACTIVE_HIGH>;
+};
+
+&led_r {
+	gpios = <&tlmm 72 GPIO_ACTIVE_HIGH>;
+};
+
+&mpss {
+	pinctrl-0 = <&sim_ctrl_default>;
+	pinctrl-names = "default";
+};
+
+&button_default {
+	pins = "gpio37";
+	bias-pull-down;
+};
+
+&gpio_leds_default {
+	pins = "gpio73", "gpio71", "gpio72";
+};
+
+/* This selects the external SIM card slot by default
+ * Not known to be fully working - see comments for labels from Android dts
+ */
+&tlmm {
+	sim_ctrl_default: sim-ctrl-default-state {
+		esim-sel-pins {
+			pins = "gpio14", "gpio12"; // "esim2_en, esim3_en"
+			function = "gpio";
+			bias-disable;
+			output-low;
+		};
+
+		sim-en-pins {
+			pins = "gpio114"; // "sim_hotplug"
+			function = "gpio";
+			bias-disable;
+			output-low;
+		};
+
+		sim-sel-pins {
+			pins = "gpio119"; // "esim1_en"
+			function = "gpio";
+			bias-disable;
+			output-high;
+		};
+	};
+};
-- 
2.51.2

>> Home