User:PReDiToR/ModemOnPinePhone
!Modem on PinePhone
This page is taken from Megi's site.
Quectel EG25-G modem in PinePhone handles WWAN, GPS and cellular services. It is based on Qualcomm MDM 9607 chipset, has 256 MiB DRAM, 256 MiB NAND, and a single Cortex-A7 CPU clocked up to 1.3GHz.
The modem's firmware is split into two parts:
Linux kernel + userspace runs on an ARM CPU Modem's firmware runs on Hexagon ADSP
Most AT commands are run on a separate DSP processor cores (Hexagon QDSP6 V5), with some being forwarded to a Linux userspace program called atfwd_daemon running on the ARM CPU.
Reverse engineering the existing software for ARM CPU inside the modem is quite easy using ghidra. ADB unlocker was made this way. Modem power driver
My kernel is a bit special, since it contains a special modem power manager driver (released 2020–08–03 along with Linux 5.8).
My driver implements several features:
it ensures modem is configured properly for audio and sleep it implements airplane mode via rfkill interface it implements modem suspend/resume it hides PinePhone variant differences it implements URC caching on all pinephone variants regardless of AP_READY availability it makes the modem sleep most of the time it handles powerup/powerdown errors properly it checks for killswitch and reports it to userspace/dmesg it doesn't waste time during powerdown and waits for actual modem powerdown (it doesn't just sleep for a fixed time) it handles SoC wakeup on RI it shuts down the modem properly during kernel powerdown/reboot to avoid data loss inside the modem's NAND flash it reports all errors to dmesg for easy troubleshooting/failure detection
Enabling and disabling the power to the modem is as simple as:
- request powerup
echo 1 > /sys/class/modem-power/modem-power/device/powered
- request powerdown
echo 0 > /sys/class/modem-power/modem-power/device/powered
- read power status (changes only after power state transition is complete)
cat /sys/class/modem-power/modem-power/device/powered
So there's no need to mess with gpios via sysfs. Connecting to the modem
You can connect to the modem once it's powered up via:
screen /dev/ttyUSB2 115200
Disconnect by CTRL+a k. Setting up the modem for voice calling
Once per a lifetime you have to run AT+QDAI=1,0,0,2,0,1,1,1 and reboot the modem. That will configure audio on the modem side correctly and store the configuration persistently inside the modem. This is not necessary if you use my modem driver.
To setup audio for call use my call audio setup program.
You need to run the program after the call starts twice. Once with your desired audio setup without -2 option and once with -2 option.
To answer a call type ATA, to make a call ATDsomenumber;, to hangup ATH.
That's it. ;)
!!Modem reverse engineering
See this page for details.
!!Unlock ADB access
It's possible to access the Linux side of the modem via adb, or reboot the modem to fastboot mode and boot your own kernel, The modem is rooted by default, and you can install and run your own software inside the modem. It's possible to communicate between A64 and the modem's ARM CPU via USB serial port (ttyGS0 on modem side and ttyUSB1 on A64).
It's also possible to create your own URCs up to 128B in size by sending them as a datagram message to UNIX socket /tmp/.urc_sock. See urc.c.
To install your own program on the modem persistently you need to remount modem's root filesystem read write and install your program somewhere in /usr/bin. Add your startup script to /etc/init.d.
To get adb access to the modem:
Get adb key via AT+QADBKEY? Enter the adb key to the unlocker utility Follow the instructions from the qadbkey-unlock Install or get adb for your distribution adb shell should get you a root shell on the modem adb pull and adb push can be used to copy files to/from the modem
On Arch Linux ARM, adb is in the AUR.
!!Modem power management
Various PinePhone variants have SoC GPIOs routed to the modem differently. So you need to be aware of what PinePhone variant you have, when experimenting with the modem.
Power management comes down to:
letting the modem sleep when it's not in use, and waking it up when it's needed for something, and letting the host sleep, and configure the modem to wake the host up, when some important event happens (incoming call, sms, …).
Summary of modem's behavior related to powerup/powerdown and power management:
powerup takes about 14s, unless the modem is too hot (>50–60°C), then it may take as long as 22s due to CPU inside the modem being downclocked from 1.3Ghz to 400MHz configuration of the physical UART and ttyUSB2 is shared for some reason, so ATE0 issued on UART will turn echo off also on ttyUSB2 modem sleeps when an election process based on the status of USB port, DTR pin, etc. results in a positive decision modem disables RF based on #W_DISABLE only when configured to do so via AT+QCFG="airplanecontrol" modem wakes up the host via USB or RI pin based on AT+QCFG="risignaltype" modem will cache URCs based on AP_READY pin's status only when AT+QCFG="apready" is configured powerdown takes about the same time as powerup