Skip to content

WIP: core: Add support for Qualcomm MSM/QMI modems via rpmsg

Stephan Gerhold requested to merge (removed):rpmsg into master

Most older Qualcomm SoCs (e.g. MSM8916, MSM8974, ...) communicate with the integrated modem via shared memory (SMD channels). This is similar to QRTR on newer SoCs, but without the "network" layer. In fact, the older SoCs also have QRTR, but the modem QMI services are not exposed there.

The mainline Linux kernel exposes SMD channels via the "remote processor messaging bus" (rpmsg). Through special IOCTL calls it is possible to create a char device for a rpmsg/SMD channel. We can then use these to send QMI/AT messages to the modem, much like the ordinary serial char devices when using a Qualcomm modem through USB.

The QMI/AT messages needed to use the modem seem to be pretty much the same as when using QMI via USB. We have tested on a few smartphones with MSM8916 which are running a (close-to) mainline kernel, e.g.:

  • BQ Aquaris X5
  • Motorola Moto G4 Play
  • Samsung Galaxy A3/A5 (2015)
  • Wileyfox Swift
  • Xiaomi Redmi 2

Most of the modem functionality seems to be working fine, without any changes to the QMI/AT messages that are sent to the modem:

  • Voice calls
  • SMS
  • Mobile Internet
  • GPS

However, note that the implementation of voice call audio and network interface is very different from the USB modems. It is completely independent of the rpmsg channels that are used to control the modem. I have written special drivers for:

I have plans to upstream these, but there is still some more work needed (mostly fine tuning for some edge cases). This is independent of the changes in ModemManager, because the additional drivers are only necessary if you want to have audio/Internet actually working.

This commit adds support for probing rpmsg ports within ModemManager. I think most of the changes are quite straightforward, but there are some FIXME comments scattered over the code where I was not sure about the best way to implement it. Those still need to be discussed :)

Note: This commit does not add the udev rules necessary to use rpmsg modems with ModemManager. The reason for that is that you typically need additional system services/tools and udev rules anyway for the modem to work.

Currently I'm using:

SYMLINK=="modem", SUBSYSTEM=="rpmsg", ENV{ID_MM_CANDIDATE}="1", ENV{ID_MM_DEVICE_PROCESS}="1", ENV{ID_MM_PORT_TYPE_QCDM}="1", ENV{ID_MM_PHYSDEV_UID}="qcom-rpmsg"
SYMLINK=="modem-at", SUBSYSTEM=="rpmsg", ENV{ID_MM_CANDIDATE}="1", ENV{ID_MM_DEVICE_PROCESS}="1", ENV{ID_MM_PHYSDEV_UID}="qcom-rpmsg"
ENV{INTERFACE}=="rmnet0", SUBSYSTEM=="net", ENV{ID_MM_CANDIDATE}="1", ENV{ID_MM_DEVICE_PROCESS}="1", ENV{ID_MM_PHYSDEV_UID}="qcom-rpmsg"

The purpose of ENV{ID_MM_PHYSDEV_UID} is to link the network interface to the modem in ModemManager, since it isn't related to the rpmsg ports in any way. Of course this is rather naive because there could be also other network interfaces called rmnet0...

Also, the udev rules assume that we already have set up the rpmsg char devices at /dev/modem (SMD channel DATA5_CNTL) and /dev/modem-at (SMD channel DATA4). Those can be set up using rpmsgexport. In postmarketOS, this is handled using additional udev rules.

Edited by Stephan Gerhold

Merge request reports