Qualcomm Snapdragon 845/850 (SDM845/SDM850)

SDM845 (or Snapdragon 845) is a Qualcomm SoC released in 2018, with mainline support originally added for the Dragonboard 845c. It is currently one of the fastest mobile SoCs booting Mainline with full support for hardware accelerated graphics, CPU frequency scaling and wifi/bluetooth, with more features on the way.
== Devices ==
=== SDM845 (Snapdragon 845) ===
=== SDM850 (Snapdragon 850) ===
== UFS internal storage ==
== Join Us! ==
If you own an SDM845 device and want to get postmarketOS & mainline booting, head over to the #mainline:postmarketos.org postmarketOS mainline channel.
We also discuss packaging, other distros and various other non-porting stuff on matrix: #sdm845:postmarketos.org.
Feel free to ping @caleb:postmarketos.org.
== Adding yours ==
If you have an SDM845 based device that isn't in this list you should definitely do something about that, checkout the SDM845 Mainlining Guide for instructions on porting new devices. It is fairly straightforward to get core functionality working on most devices.
== Audio ==
The kernel side audio stuff is mostly functional on SDM845.
* Support for OnePlus 6 added here
* Hack needed to fix the OnePlus 6 speaker (WHY???)
== Modem ==
The modem is booted by the Q6V5 MSS Peripheral Image Loader, it is required to boot the WiFi adapter. It is exposed via the QRTR_NET layer, a custom shared memory transport layer developed by Qualcomm. Over this the standard QMI interface is exposed. ModemManager has great support for QRTR and thus it is possible to send/receive SMS, use mobile data and make calls.
=== References ===
* Relevant discussion on renaming the msm-modem package as rpmsgexport is not needed on SDM845.
== Wakeups ==
Wakeups are a concept in the Linux kernel referring to a specific device or subdevice that can cause the system to exit suspend, usually via an interrupt. A good example of this is the power button, when pressed it fires an interrupt, and because that interrupt is denoted as a "wakeirq" (an interrupt that when fired _should_ wake the system from suspend) that's exactly what happens.
=== Context ===
Qualcomm platforms currently (at least as far back as SDM845) don't have a real suspend mode. The closest we get is suspend to idle (s2idle), this has the kernel freeze all of userspace and almost all kernel threads. In s2idle, peripherals (e.g. the touchscreen) can be powered down, the CPU timers (which usually fire periodic interrupts) are disabled, and the CPUs are able to spend the majority of their time in their lowest idle states. This isn't enough to enable a device to go for days at a time without charging, but it is more than enough to get through a single day at least.
When in s2idle, all interrupts are disabled with two exceptions: (enabled) wakeirqs, and irqs with the IRQF_NO_SUSPEND flag. Wakeirqs may not always be enabled, for example if your touchscreen has a double tap to wake feature then the driver would denote its IRQ as "wakeup capable", this associated a "wakeup" with the interrupt. The wakeup can then be enabled via sysfs or in the driver somewhere. If a wakeup capable interrupt doesn't have its wakeup feature enabled then the irq will be disabled during s2idle.
The IRQF_NO_SUSPEND flag enables a driver to run its interrupt handler and process interrupts while the kernel is in s2idle. This is useful for some essential housekeeping duties that have to happen even when the user isn't interacting with the device.
==== Glink ====
Glink is a communication mechanism used by Qualcomm SoCs to enable communication between the different processors (e.g. the Modem, Audio/Compute DSPs and Sensor DSP). It is a peer to peer system based on shared memory, every pair of processors (e.g. the AP (Linux) and Modem) have their own glink edge made up of a shared memory region and a pair of interrupts, one on the modem side and one for us. To provide a very simplified explanation: data is sent and received by finding a free "bucket" in the shared memory region, putting your data in the bucket, and then triggering an interrupt on the other side.
Glink is a kind of mesh network where (for the most part) every processor is connected to every other. It represents the "Link Layer".
The Glink driver makes use of the IRQF_NO_SUSPEND flag, meaning that even when in s2idle the kernel will still process interrupts from Glink. This allows for pending messages to be handled and queued up for userspace where they might otherwise be missed.
==== QRTR ====
On top of glink is the protocol layer, QRTR (Pronounced Q-Router). QRTR is a socket-based network protocol that allows for a much higher level of communication. Each processor can expose services over the QRTR network, programs on other processors can connect to and utilise these services. For example, the modem provides a Wireless Data Service for configuring a mobile data connection, the Sensor DSP also provides its own service for retreiving sensor data (See Qualcomm_Snapdragon_Sensor_Core).
QRTR represents the "Internet Layer", performing routing and session management.
==== QMI ====
QMI is a TLV (Type-Length-Value) binary format. It predates QRTR and is quite common in modems. It serves as the transport layer, however it also defines what messages can be sent/received and how the messages are formatted. QMI is the only mechanism used by ModemManager to communicate with the modem to initiate calls, send SMS, retrieve SIM and signal status information, cell tower information, etc. An incoming call or SMS is signalled by the modem sending a QMI message.
==== In summary ====
Walking back down the stack, when you receive a phone call, the modem will check that you have an active QRTR session with it (this will be the case if ModemManager hasn't explicitly closed the connection) which is subscribed to incoming calls. It will send a QMI message to notify ModemManager. It goes roughly as follows:
1. The message is transported over QRTR and sent via Glink.
2. The Glink interrupt will fire and run the interrupt handler in the kernel.
3. The interrupt handler reads the message and passes it on the QRTR protocol implementation in the kernel.
4. The QRTR net code queues it up to be received by userspace on the next poll()
This is all well and good, however when we're in s2idle, userspace is frozen, there's no way to handle the message, figure out that it's a call, and make the phone ring.
=== Waking up for calls and SMS ===
Without a way to properly differentiate between a signal strength change and an incoming call, it isn't possible for the kernel to know which messages from the modem should cause a wakeup, and which should not. All we have is a global switch.
The ideal solution here is that ModemManager becomes capable of disabling all non-essential notifications from the modem before the device suspends. While currently ModemManager is not able to do this, there is a patch for 1.22.0 available here: disable_3gpp_unsolicited_1.22.0.patch. When issue MM!927 is resolved an MR will be made to make this standard, hopefully in time for 1.23.
However, this only works when wlan is not connected, as the ath10k driver is heavily hitting the QIPCRTR irq as well.
For now, you can make sure that you never miss a call by waking up for every incoming message from the modem. This would be acceptable if it were possible to do this without immediately turning on the display, and if the message isn't a call or SMS, automatically suspending again. For Phosh, I believe this requires support to be added to GNOME session daemon to wake up without turning on the display. Figuring out why the device woke up (maybe it was a power button press or USB cable insertion) requires keeping track of all the counts in /sys/class/wakeup/wakeup*/wakeup_count and then having a look up table for each wakeup (to know that e.g. wakeup /sys/devices/platform/soc@0/c440000.spmi/spmi-0/0-00/c440000.spmi:pmic@0:pon@800/c440000.spmi:pmic@0:pon@800:pwrkey/wakeup is associated with the power button)
You can enable this wakeup for yourself by running the following command as root:
echo enabled > /sys/bus/rpmsg/devices/4080000.remoteproc:glink-edge.IPCRTR.-1.-1/power/wakeup
This will cause the device to wake up for all incoming data from the modem.
=== Waking up for notifications ===
When on a mobile data connection, the IPA (Qualcomm dedicated network packet routing hardware) will wake up the device by default for any incoming data, this usually has no effect as most TCP connections have a relatively short TCP keepalive time. However the plan is to disable it by default for now (see ) to avoid any confusion.
The IPA has the ability to maintain a TCP connection and perform some arbitrary filtering to avoid waking up the device for things that aren't notifications, e.g. matching on source IP or specific magic bytes in the packet. Unfortunately the mainline kernel driver doesn't yet implement any of these features.
The Wifi on SDM845 is ath10k and includes full Wake-On-WLAN (WoWLAN) support! Using the iw utility it's possible to enable waking up on actions like wifi disconnect, specific SSIDs becoming available, or via packet matching based on source/destination IP, magic bytes, etc.
Ath10k hardware supports offloading station keepalive, where it will send null packets to whatever AP your device is connected to in order to ensure that it doesn't get dropped. However this feature is explicitly disabled (via This patch) in favour of software polling, perhaps worth reinvestigating!
A notification push client service could be taught how to utilise WoWLAN and the IPA to maintain a persistent TCP connection with the server and cause the device to wake up for incoming notifications. It should be possible to also implement automatic switching between mobile data and wifi, between wifi networks, and between mobile cell towers. WoWLAN can wake up on wifi disconnect, and the modem can wake up when switching cell tower, allowing the connection to be re-established. A very long keepalive time will ensure that it doesn't drop for some other reason.
== WiFi ==
Wifi is functional! Firmware for the modem and ath10k module must be loaded in order to have functional wifi.
3 packages are required for functional wifi:
rmtfs, pd-mapper and tqftpserv can be installed with
apk add rmtfs pd-mapper tqftpserv
().
This readme can then be followed to fixup the firmware.
Some devices need this quirk enabled for ath10k probe to succeed.
More details may also be found on the Snapdragon 835 SoC page.
== Display ==
The Adreno 630 is relatively easy to work with, after adding a driver for your panel, obtain the firmware from
your device and either compile into the kernel (in addition to enabling CONFIG_DRM_FBDEV_EMULATION for early dmesg)) or add to the right subdirectory under /lib/firmware.
== I2C ==
I2C and the Geni hardware is functional and supported, however it is missing a driver for special GPI DMA mode used by a few devices (e.g. touchscreen on Enchilada). As of 5.11-rc1 geni is capable of DMA, however not through the GPI hardware. The issues previously discussed here no longer apply.
* WIP GPI DMA driver in mainline: https://patchwork.kernel.org/patch/11732405/
== Sensors ==
Typically you would interact with sensors via iio-sensor-proxy,
However on sdm845 sensors you need to use hexagonrpcd and libssc.
=== Hexagonrpcd ===
Sensor registry:
in version 0.1 /var/lib/qcom/sensors (Postmarket OS)
in version 0.3 /usr/share/qcom/sensors (Latest)
Note:
release build is non functional at the moment, use debug build instead.
git clone https://gitlab.com/flamingradian/sensh/
cd sensh
meson build
ninja -C build
cd fastrpc
meson build
ninja -C build
Then run (As root)
build/hexagonrpcd/hexagonrpcd -f /dev/fastrpc-sdsp -s
=== Libssc ===
git clone https://codeberg.org/DylanVanAssche/libssc.git
cd libssc
meson build
ninja -C build
Then you can run build/src/ssccli --sensor=light
If all goes well you should see the light sensor's value.
== Bluetooth ==
There are 2 firmwares installed on the system:
/lib/firmware/qca/crbtfw21.tlv and /lib/firmware/postmarketos/qca/crbtfw21.tlv
The firmware needs to be overwritten in order for the driver to load properly
echo -n /lib/firmware/postmarketos > /sys/module/firmware_class/parameters/path
Otherwise it will fail to load and show up in dmesg with:
Bluetooth: hci0: QCA TLV with error stat 0x0 rtype 0x4 (0x5)
Bluetooth: hci0: Opcode 0x0c03 failed: -110
In addition you must set a proper mac address otherwise the BT adapter will be in a broken state.</br>
In postmarketOS this is handled by /usr/bin/bootmac which can be simplified down to this:
#!/bin/sh
SERIAL=$(grep -o "serialno.*" /proc/cmdline | cut -d" " -f1)
BT_MAC=$(echo "$SERIAL-BT" | sha256sum | awk -v prefix=0200 '{printf("%s%010s\n", prefix, $1)}')
BT_MAC=$(echo "$BT_MAC" | cut -c1-12 | sed 's/\(..\)/\1:/g' | sed '$s/:$//')
btmgmt -i hci0 power off
btmgmt -i hci0 public-addr "$BT_MAC"
== Haptics ==
Haptics is supported! See Haptics for more details.
== Bootloaders ==
===Renegade Project===
Renegade Project support some sdm845 device
===uboot===
In progress u-boot port exists
== See also == 
* OnePlus_6_(oneplus-enchilada)
* SDM845 Linux mainline kernel fork a common near-mainline kernel tree for SDM845 device development, this is the kernel shipped in postmarketOS and Mobian.
* SDM845 kernel package
* Caleb's 2022 FOSDEM talk on mainlining the Snapdragon 845
== Who's working on it ==
* User:Caleb (@caleb:postmarketos.org on Matrix)
* User:venji10 (@venji10 on Matrix)
* User:Joel (@jo:jsfamily.in on Matrix)
* User:Dsankouski (@dsankouski on Matrix) - u-boot porting for Samsung_Galaxy_S9_(samsung-starqltechn)
* 'And more...'
__FORCETOC__