* Re: [PR PATCH] [Updated] X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
@ 2024-03-31 4:00 ` classabbyamp
2024-03-31 4:21 ` classabbyamp
` (33 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-03-31 4:00 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 996 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] how to document/set the necessary cmdline arguments? (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- [ ] xfix bluetooth mac address: (`btmgmt public-addr 00:A0:C6:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [ ] mkinitcpio drop-in config
- [ ] create and test live images
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 11514 bytes --]
From 38edb19d5aae236603f06701c2fc82c24144ed6b Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/2] New package: x13s-base-0.1
---
srcpkgs/x13s-base/INSTALL | 12 ++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/template | 18 ++++++++++++++++++
5 files changed, 38 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6b7a4d1eaa0df7
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,12 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+ ln -sf /etc/sv/pd-mapper etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..79911ffb908b29
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..c6ee58563f3b3d
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+add_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+add_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+add_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux "
+add_drivers+=" phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm "
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..5f76aa521ca36b
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,18 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.1
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm alsa-ucm-conf qrtr-ns pd-mapper"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# TODO: bluetooth: https://github.com/jhovold/linux/wiki/X13s#bluetooth
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 90-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut.conf.d x13s.conf
+}
From e33609411a83c6bb8b5c41a23e686c2d5c711924 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/2] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 75 ++++++++++++++++++--------
srcpkgs/linux6.8/template | 2 +-
2 files changed, 55 insertions(+), 22 deletions(-)
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index 77f5b8afd5ed5d..7c7faeaed05c74 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.1 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2368,7 +2368,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2436,7 +2436,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2492,7 +2492,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4903,7 +4904,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5132,7 +5133,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5321,7 +5322,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5910,12 +5911,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5973,7 +5975,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6011,7 +6013,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6024,7 +6026,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9324,7 +9326,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10343,7 +10345,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10355,9 +10357,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10415,7 +10417,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10493,7 +10495,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10534,9 +10536,9 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# end of Generic IOMMU Pagetable Support
# CONFIG_IOMMU_DEBUGFS is not set
-# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
+CONFIG_IOMMU_DEFAULT_DMA_STRICT=y
# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -11926,7 +11928,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index a0365a618bd173..1ee9678dbafb16 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.2
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
2024-03-31 4:00 ` [PR PATCH] [Updated] " classabbyamp
@ 2024-03-31 4:21 ` classabbyamp
2024-03-31 5:06 ` [PR REVIEW] " classabbyamp
` (32 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-03-31 4:21 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1087 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [ ] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] create and test live images
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 12183 bytes --]
From efde39f4e878e8b37349731bc7d77bc8762a3406 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/2] New package: x13s-base-0.1
---
srcpkgs/x13s-base/INSTALL | 12 ++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 19 +++++++++++++++++++
6 files changed, 45 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6b7a4d1eaa0df7
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,12 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+ ln -sf /etc/sv/pd-mapper etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..79911ffb908b29
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..c6ee58563f3b3d
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+add_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+add_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+add_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux "
+add_drivers+=" phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..d1904fae9d099f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux
+ phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..c697e8f376c198
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,19 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.1
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm alsa-ucm-conf qrtr-ns pd-mapper"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# TODO: bluetooth: https://github.com/jhovold/linux/wiki/X13s#bluetooth
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 90-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 2e8bbe9ba33b1873a07193456832614336abb57b Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/2] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 75 ++++++++++++++++++--------
srcpkgs/linux6.8/template | 2 +-
2 files changed, 55 insertions(+), 22 deletions(-)
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index 77f5b8afd5ed5d..7c7faeaed05c74 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.1 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2368,7 +2368,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2436,7 +2436,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2492,7 +2492,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4903,7 +4904,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5132,7 +5133,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5321,7 +5322,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5910,12 +5911,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5973,7 +5975,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6011,7 +6013,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6024,7 +6026,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9324,7 +9326,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10343,7 +10345,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10355,9 +10357,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10415,7 +10417,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10493,7 +10495,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10534,9 +10536,9 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# end of Generic IOMMU Pagetable Support
# CONFIG_IOMMU_DEBUGFS is not set
-# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
+CONFIG_IOMMU_DEFAULT_DMA_STRICT=y
# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -11926,7 +11928,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index a0365a618bd173..1ee9678dbafb16 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.2
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR REVIEW] X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
2024-03-31 4:00 ` [PR PATCH] [Updated] " classabbyamp
2024-03-31 4:21 ` classabbyamp
@ 2024-03-31 5:06 ` classabbyamp
2024-03-31 5:42 ` [PR PATCH] [Updated] Lenovo " classabbyamp
` (31 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-03-31 5:06 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 466 bytes --]
New review comment by classabbyamp on void-packages repository
https://github.com/void-linux/void-packages/pull/49615#discussion_r1545545592
Comment:
should we use [`IOMMU_DEFAULT_DMA_STRICT`](https://www.kernelconfig.io/CONFIG_IOMMU_DEFAULT_DMA_STRICT) or [`_LAZY`](https://www.kernelconfig.io/CONFIG_IOMMU_DEFAULT_DMA_LAZY)?
`_PASSTHROUGH` was only ever set on aarch64 (since 26e0eb9f8989be62dade9968b97ffc273bf59fb7) and breaks the keyboard/touchpad on x13s
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (2 preceding siblings ...)
2024-03-31 5:06 ` [PR REVIEW] " classabbyamp
@ 2024-03-31 5:42 ` classabbyamp
2024-03-31 12:52 ` classabbyamp
` (30 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-03-31 5:42 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1140 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [ ] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] create and test live images
- [ ] kernel install hook to update the dtb?
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 12209 bytes --]
From 44de1ce89032930edb4ef7310075add195bbb9f0 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/2] New package: x13s-base-0.1
---
srcpkgs/x13s-base/INSTALL | 12 ++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 20 ++++++++++++++++++++
6 files changed, 46 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6b7a4d1eaa0df7
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,12 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+ ln -sf /etc/sv/pd-mapper etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..79911ffb908b29
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..c6ee58563f3b3d
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+add_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+add_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+add_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux "
+add_drivers+=" phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..d1904fae9d099f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux
+ phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..2d170196ca6ba8
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,20 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.1
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns pd-mapper"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# TODO: bluetooth: https://github.com/jhovold/linux/wiki/X13s#bluetooth
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 90-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 8af8e3c9eb9924c401d820ef2740c3631d265f0d Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/2] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 75 ++++++++++++++++++--------
srcpkgs/linux6.8/template | 2 +-
2 files changed, 55 insertions(+), 22 deletions(-)
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index 77f5b8afd5ed5d..7c7faeaed05c74 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.1 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2368,7 +2368,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2436,7 +2436,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2492,7 +2492,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4903,7 +4904,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5132,7 +5133,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5321,7 +5322,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5910,12 +5911,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5973,7 +5975,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6011,7 +6013,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6024,7 +6026,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9324,7 +9326,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10343,7 +10345,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10355,9 +10357,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10415,7 +10417,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10493,7 +10495,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10534,9 +10536,9 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# end of Generic IOMMU Pagetable Support
# CONFIG_IOMMU_DEBUGFS is not set
-# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
+CONFIG_IOMMU_DEFAULT_DMA_STRICT=y
# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -11926,7 +11928,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index a0365a618bd173..1ee9678dbafb16 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.2
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (3 preceding siblings ...)
2024-03-31 5:42 ` [PR PATCH] [Updated] Lenovo " classabbyamp
@ 2024-03-31 12:52 ` classabbyamp
2024-03-31 15:00 ` zdykstra
` (29 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-03-31 12:52 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [ ] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [ ] kernel install hook to update the dtb?
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 12165 bytes --]
From 44de1ce89032930edb4ef7310075add195bbb9f0 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/2] New package: x13s-base-0.1
---
srcpkgs/x13s-base/INSTALL | 12 ++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 20 ++++++++++++++++++++
6 files changed, 46 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6b7a4d1eaa0df7
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,12 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+ ln -sf /etc/sv/pd-mapper etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..79911ffb908b29
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..c6ee58563f3b3d
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+add_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+add_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+add_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux "
+add_drivers+=" phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..d1904fae9d099f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux
+ phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..2d170196ca6ba8
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,20 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.1
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns pd-mapper"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# TODO: bluetooth: https://github.com/jhovold/linux/wiki/X13s#bluetooth
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 90-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 43917c7ac6d84925f0c473426d439a5f94cb0674 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/2] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 75 ++++++++++++++++++--------
srcpkgs/linux6.8/template | 2 +-
2 files changed, 55 insertions(+), 22 deletions(-)
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index 77f5b8afd5ed5d..16e44b2911e714 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.1 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2368,7 +2368,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2436,7 +2436,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2492,7 +2492,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4903,7 +4904,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5132,7 +5133,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5321,7 +5322,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5910,12 +5911,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5973,7 +5975,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6011,7 +6013,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6024,7 +6026,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9324,7 +9326,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10343,7 +10345,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10355,9 +10357,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10415,7 +10417,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10493,7 +10495,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10535,8 +10537,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -11926,7 +11928,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index a0365a618bd173..1ee9678dbafb16 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.2
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (4 preceding siblings ...)
2024-03-31 12:52 ` classabbyamp
@ 2024-03-31 15:00 ` zdykstra
2024-03-31 15:07 ` zdykstra
` (28 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: zdykstra @ 2024-03-31 15:00 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 269 bytes --]
New comment by zdykstra on void-packages repository
https://github.com/void-linux/void-packages/pull/49615#issuecomment-2028788232
Comment:
Should the x13s package depend on the network firmware package? That provides the ath11k firmware needed for the WiFi chipset.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (5 preceding siblings ...)
2024-03-31 15:00 ` zdykstra
@ 2024-03-31 15:07 ` zdykstra
2024-04-02 21:08 ` [PR PATCH] [Updated] " classabbyamp
` (27 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: zdykstra @ 2024-03-31 15:07 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 269 bytes --]
New comment by zdykstra on void-packages repository
https://github.com/void-linux/void-packages/pull/49615#issuecomment-2028788232
Comment:
Should the x13s package depend on the network firmware package? That provides the ath11k firmware needed for the WiFi chipset.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (6 preceding siblings ...)
2024-03-31 15:07 ` zdykstra
@ 2024-04-02 21:08 ` classabbyamp
2024-04-02 21:10 ` [PR REVIEW] " classabbyamp
` (26 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-04-02 21:08 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [ ] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [ ] kernel install hook to update the dtb?
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 13776 bytes --]
From 44de1ce89032930edb4ef7310075add195bbb9f0 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/3] New package: x13s-base-0.1
---
srcpkgs/x13s-base/INSTALL | 12 ++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 20 ++++++++++++++++++++
6 files changed, 46 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6b7a4d1eaa0df7
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,12 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+ ln -sf /etc/sv/pd-mapper etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..79911ffb908b29
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..c6ee58563f3b3d
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+add_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+add_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+add_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux "
+add_drivers+=" phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..d1904fae9d099f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux
+ phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..2d170196ca6ba8
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,20 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.1
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns pd-mapper"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# TODO: bluetooth: https://github.com/jhovold/linux/wiki/X13s#bluetooth
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 90-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 43917c7ac6d84925f0c473426d439a5f94cb0674 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/3] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 75 ++++++++++++++++++--------
srcpkgs/linux6.8/template | 2 +-
2 files changed, 55 insertions(+), 22 deletions(-)
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index 77f5b8afd5ed5d..16e44b2911e714 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.1 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2368,7 +2368,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2436,7 +2436,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2492,7 +2492,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4903,7 +4904,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5132,7 +5133,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5321,7 +5322,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5910,12 +5911,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5973,7 +5975,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6011,7 +6013,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6024,7 +6026,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9324,7 +9326,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10343,7 +10345,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10355,9 +10357,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10415,7 +10417,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10493,7 +10495,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10535,8 +10537,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -11926,7 +11928,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index a0365a618bd173..1ee9678dbafb16 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.2
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From 2a39aaf07cc78bc842baa03bbf3141701ab8842b Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 2 Apr 2024 17:07:53 -0400
Subject: [PATCH 3/3] New package: x13s-firmware-20240312
---
srcpkgs/x13s-firmware/template | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 srcpkgs/x13s-firmware/template
diff --git a/srcpkgs/x13s-firmware/template b/srcpkgs/x13s-firmware/template
new file mode 100644
index 00000000000000..7615a5098d6ce1
--- /dev/null
+++ b/srcpkgs/x13s-firmware/template
@@ -0,0 +1,24 @@
+# Template file for 'x13s-firmware'
+pkgname=x13s-firmware
+version=20240312
+revision=1
+_commit=d1e35f1c10398994f4a675c9c42f089b88bc806d
+archs="aarch64*"
+build_style=fetch
+short_desc="Firmware for ThinkPad X13s"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="custom:idk"
+homepage="https://github.com/ironrobin/x13s-alarm/blob/trunk/x13s-firmware"
+distfiles="https://github.com/ironrobin/x13s-alarm/raw/${_commit}/x13s-firmware/a690_gmu.bin
+ https://github.com/ironrobin/x13s-alarm/raw/${_commit}/x13s-firmware/hpnv21.b8c
+ https://github.com/ironrobin/x13s-alarm/raw/${_commit}/x13s-firmware/qcvss8280.mbn"
+checksum="163c1e3126d70d36c1ad9db5dd3721969b164f9623f6a7db773677882e40936d
+ 8b6a1e2d4233e0a17d5c2dce568386fe9c7974b872da47900242c3485f57d0f7
+ c81f3f060f69c5940121fe6e36da20d9c864d78b3bbffe361ec8878a7f9bd7b3"
+nostrip=yes
+
+do_install() {
+ vinstall a690_gmu.bin 644 usr/lib/firmware/qcom
+ vinstall hpnv21.b8c 644 usr/lib/firmware/qca
+ vinstall qcvss8280.mbn 644 usr/lib/firmware/qcom/sc8280xp/LENOVO/21BX
+}
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR REVIEW] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (7 preceding siblings ...)
2024-04-02 21:08 ` [PR PATCH] [Updated] " classabbyamp
@ 2024-04-02 21:10 ` classabbyamp
2024-04-02 21:21 ` zdykstra
` (25 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-04-02 21:10 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 313 bytes --]
New review comment by classabbyamp on void-packages repository
https://github.com/void-linux/void-packages/pull/49615#discussion_r1548612098
Comment:
this may need to be a restricted package, as this comes from arch linux arm, who I think have extracted it from windows/lenovo. licencing seems dubious at best.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR REVIEW] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (8 preceding siblings ...)
2024-04-02 21:10 ` [PR REVIEW] " classabbyamp
@ 2024-04-02 21:21 ` zdykstra
2024-04-02 21:26 ` classabbyamp
` (24 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: zdykstra @ 2024-04-02 21:21 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 375 bytes --]
New review comment by zdykstra on void-packages repository
https://github.com/void-linux/void-packages/pull/49615#discussion_r1548621372
Comment:
My brief searches on a690_gmu.bin show that up until recently a660_gmu.bin was the recommended firmware for the x13s. Are there any details on where the x13s-alarm project pulled in a690_gmu.bin from / why they switched to it?
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR REVIEW] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (9 preceding siblings ...)
2024-04-02 21:21 ` zdykstra
@ 2024-04-02 21:26 ` classabbyamp
2024-04-02 21:54 ` [PR PATCH] [Updated] " classabbyamp
` (23 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-04-02 21:26 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 223 bytes --]
New review comment by classabbyamp on void-packages repository
https://github.com/void-linux/void-packages/pull/49615#discussion_r1548627305
Comment:
my search showed that a660 works but a690 is the exact firmware for it
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (10 preceding siblings ...)
2024-04-02 21:26 ` classabbyamp
@ 2024-04-02 21:54 ` classabbyamp
2024-04-02 22:14 ` classabbyamp
` (22 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-04-02 21:54 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [ ] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [ ] kernel install hook to update the dtb?
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 15747 bytes --]
From 44de1ce89032930edb4ef7310075add195bbb9f0 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/4] New package: x13s-base-0.1
---
srcpkgs/x13s-base/INSTALL | 12 ++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 20 ++++++++++++++++++++
6 files changed, 46 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6b7a4d1eaa0df7
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,12 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+ ln -sf /etc/sv/pd-mapper etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..79911ffb908b29
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..c6ee58563f3b3d
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+add_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+add_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+add_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux "
+add_drivers+=" phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..d1904fae9d099f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux
+ phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..2d170196ca6ba8
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,20 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.1
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns pd-mapper"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# TODO: bluetooth: https://github.com/jhovold/linux/wiki/X13s#bluetooth
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 90-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 43917c7ac6d84925f0c473426d439a5f94cb0674 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/4] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 75 ++++++++++++++++++--------
srcpkgs/linux6.8/template | 2 +-
2 files changed, 55 insertions(+), 22 deletions(-)
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index 77f5b8afd5ed5d..16e44b2911e714 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.1 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2368,7 +2368,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2436,7 +2436,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2492,7 +2492,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4903,7 +4904,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5132,7 +5133,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5321,7 +5322,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5910,12 +5911,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5973,7 +5975,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6011,7 +6013,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6024,7 +6026,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9324,7 +9326,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10343,7 +10345,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10355,9 +10357,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10415,7 +10417,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10493,7 +10495,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10535,8 +10537,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -11926,7 +11928,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index a0365a618bd173..1ee9678dbafb16 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.2
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From 2a39aaf07cc78bc842baa03bbf3141701ab8842b Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 2 Apr 2024 17:07:53 -0400
Subject: [PATCH 3/4] New package: x13s-firmware-20240312
---
srcpkgs/x13s-firmware/template | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 srcpkgs/x13s-firmware/template
diff --git a/srcpkgs/x13s-firmware/template b/srcpkgs/x13s-firmware/template
new file mode 100644
index 00000000000000..7615a5098d6ce1
--- /dev/null
+++ b/srcpkgs/x13s-firmware/template
@@ -0,0 +1,24 @@
+# Template file for 'x13s-firmware'
+pkgname=x13s-firmware
+version=20240312
+revision=1
+_commit=d1e35f1c10398994f4a675c9c42f089b88bc806d
+archs="aarch64*"
+build_style=fetch
+short_desc="Firmware for ThinkPad X13s"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="custom:idk"
+homepage="https://github.com/ironrobin/x13s-alarm/blob/trunk/x13s-firmware"
+distfiles="https://github.com/ironrobin/x13s-alarm/raw/${_commit}/x13s-firmware/a690_gmu.bin
+ https://github.com/ironrobin/x13s-alarm/raw/${_commit}/x13s-firmware/hpnv21.b8c
+ https://github.com/ironrobin/x13s-alarm/raw/${_commit}/x13s-firmware/qcvss8280.mbn"
+checksum="163c1e3126d70d36c1ad9db5dd3721969b164f9623f6a7db773677882e40936d
+ 8b6a1e2d4233e0a17d5c2dce568386fe9c7974b872da47900242c3485f57d0f7
+ c81f3f060f69c5940121fe6e36da20d9c864d78b3bbffe361ec8878a7f9bd7b3"
+nostrip=yes
+
+do_install() {
+ vinstall a690_gmu.bin 644 usr/lib/firmware/qcom
+ vinstall hpnv21.b8c 644 usr/lib/firmware/qca
+ vinstall qcvss8280.mbn 644 usr/lib/firmware/qcom/sc8280xp/LENOVO/21BX
+}
From 551148835135a3aa97f986598f3b97902a740daf Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 2 Apr 2024 17:54:38 -0400
Subject: [PATCH 4/4] fixup! New package: x13s-firmware-20240312
---
srcpkgs/x13s-firmware/template | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/srcpkgs/x13s-firmware/template b/srcpkgs/x13s-firmware/template
index 7615a5098d6ce1..2a62e36a949711 100644
--- a/srcpkgs/x13s-firmware/template
+++ b/srcpkgs/x13s-firmware/template
@@ -3,22 +3,29 @@ pkgname=x13s-firmware
version=20240312
revision=1
_commit=d1e35f1c10398994f4a675c9c42f089b88bc806d
+_gfx_ver=20
archs="aarch64*"
build_style=fetch
+hostmakedepends="innoextract"
short_desc="Firmware for ThinkPad X13s"
maintainer="classabbyamp <void@placeviolette.net>"
license="custom:idk"
homepage="https://github.com/ironrobin/x13s-alarm/blob/trunk/x13s-firmware"
distfiles="https://github.com/ironrobin/x13s-alarm/raw/${_commit}/x13s-firmware/a690_gmu.bin
https://github.com/ironrobin/x13s-alarm/raw/${_commit}/x13s-firmware/hpnv21.b8c
- https://github.com/ironrobin/x13s-alarm/raw/${_commit}/x13s-firmware/qcvss8280.mbn"
+ https://download.lenovo.com/pccbbs/mobiles/n3hdr${_gfx_ver}w.exe"
checksum="163c1e3126d70d36c1ad9db5dd3721969b164f9623f6a7db773677882e40936d
8b6a1e2d4233e0a17d5c2dce568386fe9c7974b872da47900242c3485f57d0f7
- c81f3f060f69c5940121fe6e36da20d9c864d78b3bbffe361ec8878a7f9bd7b3"
+ 270ca5f6e28e9e3a707c777e55a1878d8b3dc7c714b9174508446e5ea689c046"
nostrip=yes
+do_build() {
+ innoextract --extract "n3hdr${_gfx_ver}w.exe" --include "N3HDR${_gfx_ver}W/drivers/qcvss8280.mbn"
+}
+
do_install() {
vinstall a690_gmu.bin 644 usr/lib/firmware/qcom
vinstall hpnv21.b8c 644 usr/lib/firmware/qca
- vinstall qcvss8280.mbn 644 usr/lib/firmware/qcom/sc8280xp/LENOVO/21BX
+ vinstall "code\$GetExtractPath\$/N3HDR${_gfx_ver}W/drivers/qcvss8280.mbn" 644 \
+ usr/lib/firmware/qcom/sc8280xp/LENOVO/21BX
}
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (11 preceding siblings ...)
2024-04-02 21:54 ` [PR PATCH] [Updated] " classabbyamp
@ 2024-04-02 22:14 ` classabbyamp
2024-04-02 22:15 ` classabbyamp
` (21 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-04-02 22:14 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [ ] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [ ] kernel install hook to update the dtb?
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 13861 bytes --]
From cf5de23f5efdee660551aa5594f1838e36e97c69 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/3] New package: x13s-base-0.1
---
srcpkgs/x13s-base/INSTALL | 12 ++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 20 ++++++++++++++++++++
6 files changed, 46 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6b7a4d1eaa0df7
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,12 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+ ln -sf /etc/sv/pd-mapper etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..79911ffb908b29
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..c6ee58563f3b3d
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+add_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+add_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+add_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux "
+add_drivers+=" phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..d1904fae9d099f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux
+ phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..2d170196ca6ba8
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,20 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.1
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns pd-mapper"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# TODO: bluetooth: https://github.com/jhovold/linux/wiki/X13s#bluetooth
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 90-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From df5a05fe293cae5deecca31a909b6be704a8dce7 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/3] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 75 ++++++++++++++++++--------
srcpkgs/linux6.8/template | 2 +-
2 files changed, 55 insertions(+), 22 deletions(-)
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index 77f5b8afd5ed5d..16e44b2911e714 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.1 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2368,7 +2368,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2436,7 +2436,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2492,7 +2492,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4903,7 +4904,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5132,7 +5133,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5321,7 +5322,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5910,12 +5911,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5973,7 +5975,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6011,7 +6013,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6024,7 +6026,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9324,7 +9326,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10343,7 +10345,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10355,9 +10357,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10415,7 +10417,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10493,7 +10495,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10535,8 +10537,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -11926,7 +11928,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index a0365a618bd173..1ee9678dbafb16 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.2
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From 136fce3af56c05d2524156c6308a99725c3c1129 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 2 Apr 2024 17:07:53 -0400
Subject: [PATCH 3/3] New package: x13s-firmware-20240312
---
srcpkgs/x13s-firmware/template | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
create mode 100644 srcpkgs/x13s-firmware/template
diff --git a/srcpkgs/x13s-firmware/template b/srcpkgs/x13s-firmware/template
new file mode 100644
index 00000000000000..5e90d17b21c8a6
--- /dev/null
+++ b/srcpkgs/x13s-firmware/template
@@ -0,0 +1,29 @@
+# Template file for 'x13s-firmware'
+pkgname=x13s-firmware
+version=20240402
+revision=1
+_bt_ver=14
+_gfx_ver=20
+archs="aarch64*"
+build_style=fetch
+hostmakedepends="innoextract"
+short_desc="Bluetooth and GPU Firmware for ThinkPad X13s"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="custom:Lenovo"
+homepage="https://github.com/ironrobin/x13s-alarm/blob/trunk/x13s-firmware"
+distfiles="https://download.lenovo.com/pccbbs/mobiles/n3hww${_bt_ver}w.exe
+ https://download.lenovo.com/pccbbs/mobiles/n3hdr${_gfx_ver}w.exe"
+checksum="8b6a1e2d4233e0a17d5c2dce568386fe9c7974b872da47900242c3485f57d0f7
+ 270ca5f6e28e9e3a707c777e55a1878d8b3dc7c714b9174508446e5ea689c046"
+nostrip=yes
+
+post_extract() {
+ innoextract --extract "n3hdr${_gfx_ver}w.exe" --include "N3HDR${_gfx_ver}W/drivers/qcvss8280.mbn"
+ innoextract --extract "n3hww${_bt_ver}w.exe" --include "hpnv21.b8c"
+}
+
+do_install() {
+ vinstall "code\$GetExtractPath\$/bluetooth_hsp/hpnv21.b8c" 644 usr/lib/firmware/qca
+ vinstall "code\$GetExtractPath\$/N3HDR${_gfx_ver}W/drivers/qcvss8280.mbn" 644 \
+ usr/lib/firmware/qcom/sc8280xp/LENOVO/21BX
+}
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (12 preceding siblings ...)
2024-04-02 22:14 ` classabbyamp
@ 2024-04-02 22:15 ` classabbyamp
2024-04-02 22:19 ` [PR REVIEW] " classabbyamp
` (20 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-04-02 22:15 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [ ] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [ ] kernel install hook to update the dtb?
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 13861 bytes --]
From cf5de23f5efdee660551aa5594f1838e36e97c69 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/3] New package: x13s-base-0.1
---
srcpkgs/x13s-base/INSTALL | 12 ++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 20 ++++++++++++++++++++
6 files changed, 46 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6b7a4d1eaa0df7
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,12 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+ ln -sf /etc/sv/pd-mapper etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..79911ffb908b29
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..c6ee58563f3b3d
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+add_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+add_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+add_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux "
+add_drivers+=" phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..d1904fae9d099f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux
+ phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..2d170196ca6ba8
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,20 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.1
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns pd-mapper"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# TODO: bluetooth: https://github.com/jhovold/linux/wiki/X13s#bluetooth
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 90-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From df5a05fe293cae5deecca31a909b6be704a8dce7 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/3] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 75 ++++++++++++++++++--------
srcpkgs/linux6.8/template | 2 +-
2 files changed, 55 insertions(+), 22 deletions(-)
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index 77f5b8afd5ed5d..16e44b2911e714 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.1 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2368,7 +2368,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2436,7 +2436,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2492,7 +2492,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4903,7 +4904,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5132,7 +5133,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5321,7 +5322,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5910,12 +5911,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5973,7 +5975,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6011,7 +6013,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6024,7 +6026,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9324,7 +9326,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10343,7 +10345,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10355,9 +10357,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10415,7 +10417,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10493,7 +10495,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10535,8 +10537,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -11926,7 +11928,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index a0365a618bd173..1ee9678dbafb16 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.2
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From e61b1a464164557cb2f8dc494b713724a12c44ad Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 2 Apr 2024 17:07:53 -0400
Subject: [PATCH 3/3] New package: x13s-firmware-20240312
---
srcpkgs/x13s-firmware/template | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
create mode 100644 srcpkgs/x13s-firmware/template
diff --git a/srcpkgs/x13s-firmware/template b/srcpkgs/x13s-firmware/template
new file mode 100644
index 00000000000000..b5985ca90ed1a7
--- /dev/null
+++ b/srcpkgs/x13s-firmware/template
@@ -0,0 +1,29 @@
+# Template file for 'x13s-firmware'
+pkgname=x13s-firmware
+version=20240402
+revision=1
+_bt_ver=14
+_gfx_ver=20
+archs="aarch64*"
+build_style=fetch
+hostmakedepends="innoextract"
+short_desc="Bluetooth and GPU Firmware for ThinkPad X13s"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="custom:Lenovo"
+homepage="https://github.com/ironrobin/x13s-alarm/blob/trunk/x13s-firmware"
+distfiles="https://download.lenovo.com/pccbbs/mobiles/n3hww${_bt_ver}w.exe
+ https://download.lenovo.com/pccbbs/mobiles/n3hdr${_gfx_ver}w.exe"
+checksum="491fbf0dd1ab17aa9bdc196ffff82feefa106308b65f5f3a2dd0cc894ae4def3
+ 270ca5f6e28e9e3a707c777e55a1878d8b3dc7c714b9174508446e5ea689c046"
+nostrip=yes
+
+post_extract() {
+ innoextract --extract "n3hdr${_gfx_ver}w.exe" --include "N3HDR${_gfx_ver}W/drivers/qcvss8280.mbn"
+ innoextract --extract "n3hww${_bt_ver}w.exe" --include "hpnv21.b8c"
+}
+
+do_install() {
+ vinstall "code\$GetExtractPath\$/bluetooth_hsp/hpnv21.b8c" 644 usr/lib/firmware/qca
+ vinstall "code\$GetExtractPath\$/N3HDR${_gfx_ver}W/drivers/qcvss8280.mbn" 644 \
+ usr/lib/firmware/qcom/sc8280xp/LENOVO/21BX
+}
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR REVIEW] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (13 preceding siblings ...)
2024-04-02 22:15 ` classabbyamp
@ 2024-04-02 22:19 ` classabbyamp
2024-04-03 10:00 ` [PR PATCH] [Updated] " classabbyamp
` (19 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-04-02 22:19 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 439 bytes --]
New review comment by classabbyamp on void-packages repository
https://github.com/void-linux/void-packages/pull/49615#discussion_r1548685601
Comment:
decided to drop it and extract the firmware from lenovo directly, but still unsure on the licence, as there's no indication on [lenovo's site](https://pcsupport.lenovo.com/us/en/products/laptops-and-netbooks/thinkpad-x-series-laptops/thinkpad-x13s-type-21bx-21by/downloads/driver-list/)
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (14 preceding siblings ...)
2024-04-02 22:19 ` [PR REVIEW] " classabbyamp
@ 2024-04-03 10:00 ` classabbyamp
2024-04-05 18:41 ` classabbyamp
` (18 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-04-03 10:00 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [ ] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [ ] kernel install hook to update the dtb?
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 12781 bytes --]
From 022714331c30596fdf2daca8695ce99ae0037812 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/2] New package: x13s-base-0.1
---
srcpkgs/x13s-base/INSTALL | 12 ++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 20 ++++++++++++++++++++
6 files changed, 46 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6b7a4d1eaa0df7
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,12 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+ ln -sf /etc/sv/pd-mapper etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..79911ffb908b29
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..c6ee58563f3b3d
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+add_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+add_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+add_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux "
+add_drivers+=" phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..d1904fae9d099f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux
+ phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..2d170196ca6ba8
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,20 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.1
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns pd-mapper"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# TODO: bluetooth: https://github.com/jhovold/linux/wiki/X13s#bluetooth
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 90-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From cf731861486b3601a4287c83f2759ef4d1314b90 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/2] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 79 ++++++++++++++++++--------
srcpkgs/linux6.8/template | 2 +-
2 files changed, 57 insertions(+), 24 deletions(-)
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index 77f5b8afd5ed5d..67b2f8152c3de0 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.1 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2368,7 +2368,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2436,7 +2436,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2492,7 +2492,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4903,7 +4904,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5132,7 +5133,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5303,7 +5304,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5321,7 +5322,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5329,7 +5330,7 @@ CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SM8250_LPASS_LPI is not set
# CONFIG_PINCTRL_SM8350_LPASS_LPI is not set
CONFIG_PINCTRL_SM8450_LPASS_LPI=m
-CONFIG_PINCTRL_SC8280XP_LPASS_LPI=m
+CONFIG_PINCTRL_SC8280XP_LPASS_LPI=y
CONFIG_PINCTRL_SM8550_LPASS_LPI=m
# CONFIG_PINCTRL_SM8650_LPASS_LPI is not set
CONFIG_PINCTRL_RTD=y
@@ -5910,12 +5911,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5973,7 +5975,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6011,7 +6013,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6024,7 +6026,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9324,7 +9326,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10343,7 +10345,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10355,9 +10357,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10415,7 +10417,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10493,7 +10495,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10535,8 +10537,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -11926,7 +11928,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index a0365a618bd173..d59187d064bdf4 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.2
-revision=1
+revision=3
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (15 preceding siblings ...)
2024-04-03 10:00 ` [PR PATCH] [Updated] " classabbyamp
@ 2024-04-05 18:41 ` classabbyamp
2024-04-20 21:54 ` classabbyamp
` (17 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-04-05 18:41 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [ ] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [ ] kernel install hook to update the dtb?
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 12796 bytes --]
From bc8994c5ceefb1c60cfc0360faa0df8f19b8b2d8 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/2] New package: x13s-base-0.1
---
srcpkgs/x13s-base/INSTALL | 12 ++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 20 ++++++++++++++++++++
6 files changed, 46 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6b7a4d1eaa0df7
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,12 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+ ln -sf /etc/sv/pd-mapper etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..79911ffb908b29
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..76e58843f9bc93
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux "
+force_drivers+=" phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..d1904fae9d099f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux
+ phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..89b0263a6fde44
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,20 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.1
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns pd-mapper"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# TODO: bluetooth: https://github.com/jhovold/linux/wiki/X13s#bluetooth
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 90-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 494a435dd3ace990de4977293c7882fb95cb86b2 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/2] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 79 ++++++++++++++++++--------
srcpkgs/linux6.8/template | 2 +-
2 files changed, 57 insertions(+), 24 deletions(-)
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index 0eea6c711dad1b..1a068fb98b73cb 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.3 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2368,7 +2368,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2436,7 +2436,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2492,7 +2492,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4903,7 +4904,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5132,7 +5133,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5303,7 +5304,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5321,7 +5322,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5329,7 +5330,7 @@ CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SM8250_LPASS_LPI is not set
# CONFIG_PINCTRL_SM8350_LPASS_LPI is not set
CONFIG_PINCTRL_SM8450_LPASS_LPI=m
-CONFIG_PINCTRL_SC8280XP_LPASS_LPI=m
+CONFIG_PINCTRL_SC8280XP_LPASS_LPI=y
CONFIG_PINCTRL_SM8550_LPASS_LPI=m
# CONFIG_PINCTRL_SM8650_LPASS_LPI is not set
CONFIG_PINCTRL_RTD=y
@@ -5910,12 +5911,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5973,7 +5975,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6011,7 +6013,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6024,7 +6026,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9324,7 +9326,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10343,7 +10345,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10355,9 +10357,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10415,7 +10417,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10493,7 +10495,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10535,8 +10537,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -11926,7 +11928,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 653e6fc1393f02..0b7e3a89db136a 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.4
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (16 preceding siblings ...)
2024-04-05 18:41 ` classabbyamp
@ 2024-04-20 21:54 ` classabbyamp
2024-05-05 15:26 ` classabbyamp
` (16 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-04-20 21:54 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [ ] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [ ] kernel install hook to update the dtb?
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 12796 bytes --]
From 38544a449e4811bb4f637162367373660e90648d Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/2] New package: x13s-base-0.1
---
srcpkgs/x13s-base/INSTALL | 12 ++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 20 ++++++++++++++++++++
6 files changed, 46 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6b7a4d1eaa0df7
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,12 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+ ln -sf /etc/sv/pd-mapper etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..79911ffb908b29
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..76e58843f9bc93
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux "
+force_drivers+=" phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..d1904fae9d099f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux
+ phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..89b0263a6fde44
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,20 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.1
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns pd-mapper"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# TODO: bluetooth: https://github.com/jhovold/linux/wiki/X13s#bluetooth
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 90-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From a712e8012b3ccc4d575fa348b47c9f5c9bcb27e8 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/2] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 79 ++++++++++++++++++--------
srcpkgs/linux6.8/template | 2 +-
2 files changed, 57 insertions(+), 24 deletions(-)
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index 0eea6c711dad1b..1a068fb98b73cb 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.3 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2368,7 +2368,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2436,7 +2436,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2492,7 +2492,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4903,7 +4904,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5132,7 +5133,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5303,7 +5304,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5321,7 +5322,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5329,7 +5330,7 @@ CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SM8250_LPASS_LPI is not set
# CONFIG_PINCTRL_SM8350_LPASS_LPI is not set
CONFIG_PINCTRL_SM8450_LPASS_LPI=m
-CONFIG_PINCTRL_SC8280XP_LPASS_LPI=m
+CONFIG_PINCTRL_SC8280XP_LPASS_LPI=y
CONFIG_PINCTRL_SM8550_LPASS_LPI=m
# CONFIG_PINCTRL_SM8650_LPASS_LPI is not set
CONFIG_PINCTRL_RTD=y
@@ -5910,12 +5911,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5973,7 +5975,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6011,7 +6013,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6024,7 +6026,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9324,7 +9326,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10343,7 +10345,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10355,9 +10357,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10415,7 +10417,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10493,7 +10495,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10535,8 +10537,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -11926,7 +11928,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 7dd87784363c41..46ef1c2a2d13bd 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.7
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (17 preceding siblings ...)
2024-04-20 21:54 ` classabbyamp
@ 2024-05-05 15:26 ` classabbyamp
2024-05-05 17:02 ` classabbyamp
` (15 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-05-05 15:26 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [ ] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [ ] kernel install hook to update the dtb?
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 74755 bytes --]
From e0f2f17347057b0922e816930cd572965e819bdf Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/3] New package: x13s-base-0.2
---
srcpkgs/x13s-base/INSTALL | 11 +++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 20 ++++++++++++++++++++
6 files changed, 45 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..3e6aa4b76b7e93
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,11 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..79911ffb908b29
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..76e58843f9bc93
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux "
+force_drivers+=" phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..d1904fae9d099f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux
+ phy_qcom_qmp_combo gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp panel_edp msm)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..f3f8fd976ce049
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,20 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.2
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# TODO: bluetooth: https://github.com/jhovold/linux/wiki/X13s#bluetooth
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 90-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 57d306fb47fcdae60bb21cbee864b41df0067a01 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/3] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 81 +-
...d-in-kernel-pd-mapper-implementation.patch | 2011 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2070 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index ada0e5a9e51201..97e9d729c3aa38 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.9 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..a0288d36034b11
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,2011 @@
+source: https://patchwork.kernel.org/project/linux-remoteproc/cover/20240424-qcom-pd-mapper-v7-0-05f7fc646e0f@linaro.org/
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Wed, 24 Apr 2024 12:27:57 +0300
+Subject: [PATCH v7 1/6] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..19cfe4b41235 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Wed, 24 Apr 2024 12:27:58 +0300
+Subject: [PATCH v7 2/6] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 19cfe4b41235..3c6f2d21e5e4 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -415,7 +415,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Wed, 24 Apr 2024 12:27:59 +0300
+Subject: [PATCH v7 3/6] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Wed, 24 Apr 2024 12:28:00 +0300
+Subject: [PATCH v7 4/6] soc: qcom: qmi: add a way to remove running service
+
+Add qmi_del_server(), a pair to qmi_add_server(), a way to remove
+running server from the QMI socket. This is e.g. necessary for
+pd-mapper, which needs to readd a server each time the DSP is started or
+stopped.
+
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/qmi_interface.c | 67 ++++++++++++++++++++++++++++++++++++++++
+ include/linux/soc/qcom/qmi.h | 2 ++
+ 2 files changed, 69 insertions(+)
+
+diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c
+index bb98b06e87f8..18ff2015c682 100644
+--- a/drivers/soc/qcom/qmi_interface.c
++++ b/drivers/soc/qcom/qmi_interface.c
+@@ -289,6 +289,73 @@ int qmi_add_server(struct qmi_handle *qmi, unsigned int service,
+ }
+ EXPORT_SYMBOL_GPL(qmi_add_server);
+
++static void qmi_send_del_server(struct qmi_handle *qmi, struct qmi_service *svc)
++{
++ struct qrtr_ctrl_pkt pkt;
++ struct sockaddr_qrtr sq;
++ struct msghdr msg = { };
++ struct kvec iv = { &pkt, sizeof(pkt) };
++ int ret;
++
++ memset(&pkt, 0, sizeof(pkt));
++ pkt.cmd = cpu_to_le32(QRTR_TYPE_DEL_SERVER);
++ pkt.server.service = cpu_to_le32(svc->service);
++ pkt.server.instance = cpu_to_le32(svc->version | svc->instance << 8);
++ pkt.server.node = cpu_to_le32(qmi->sq.sq_node);
++ pkt.server.port = cpu_to_le32(qmi->sq.sq_port);
++
++ sq.sq_family = qmi->sq.sq_family;
++ sq.sq_node = qmi->sq.sq_node;
++ sq.sq_port = QRTR_PORT_CTRL;
++
++ msg.msg_name = &sq;
++ msg.msg_namelen = sizeof(sq);
++
++ mutex_lock(&qmi->sock_lock);
++ if (qmi->sock) {
++ ret = kernel_sendmsg(qmi->sock, &msg, &iv, 1, sizeof(pkt));
++ if (ret < 0)
++ pr_err("send service deregistration failed: %d\n", ret);
++ }
++ mutex_unlock(&qmi->sock_lock);
++}
++
++/**
++ * qmi_del_server() - register a service with the name service
++ * @qmi: qmi handle
++ * @service: type of the service
++ * @instance: instance of the service
++ * @version: version of the service
++ *
++ * Remove registration of the service with the name service. This notifies
++ * clients that they should no longer send messages to the client associated
++ * with @qmi.
++ *
++ * Return: 0 on success, negative errno on failure.
++ */
++int qmi_del_server(struct qmi_handle *qmi, unsigned int service,
++ unsigned int version, unsigned int instance)
++{
++ struct qmi_service *svc;
++ struct qmi_service *tmp;
++
++ list_for_each_entry_safe(svc, tmp, &qmi->services, list_node) {
++ if (svc->service != service ||
++ svc->version != version ||
++ svc->instance != instance)
++ continue;
++
++ qmi_send_del_server(qmi, svc);
++ list_del(&svc->list_node);
++ kfree(svc);
++
++ return 0;
++ }
++
++ return -EINVAL;
++}
++EXPORT_SYMBOL_GPL(qmi_del_server);
++
+ /**
+ * qmi_txn_init() - allocate transaction id within the given QMI handle
+ * @qmi: QMI handle
+diff --git a/include/linux/soc/qcom/qmi.h b/include/linux/soc/qcom/qmi.h
+index 469e02d2aa0d..5039c30e4bdc 100644
+--- a/include/linux/soc/qcom/qmi.h
++++ b/include/linux/soc/qcom/qmi.h
+@@ -241,6 +241,8 @@ int qmi_add_lookup(struct qmi_handle *qmi, unsigned int service,
+ unsigned int version, unsigned int instance);
+ int qmi_add_server(struct qmi_handle *qmi, unsigned int service,
+ unsigned int version, unsigned int instance);
++int qmi_del_server(struct qmi_handle *qmi, unsigned int service,
++ unsigned int version, unsigned int instance);
+
+ int qmi_handle_init(struct qmi_handle *qmi, size_t max_msg_len,
+ const struct qmi_ops *ops,
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Wed, 24 Apr 2024 12:28:01 +0300
+Subject: [PATCH v7 5/6] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 10 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 656 +++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ include/linux/soc/qcom/pd_mapper.h | 28 ++
+ 6 files changed, 743 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..f666366841b8 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,16 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ba5440506c95
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,656 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/soc/qcom/pd_mapper.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++static DEFINE_MUTEX(qcom_pdm_count_mutex); /* guards count */
++/*
++ * It is not possible to use refcount_t here. The service needs to go to 0 and
++ * back without warnings.
++ */
++static unsigned int qcom_pdm_count;
++
++static DEFINE_MUTEX(qcom_pdm_mutex);
++static struct qmi_handle qcom_pdm_handle;
++static LIST_HEAD(qcom_pdm_services);
++
++static struct qcom_pdm_service *qcom_pdm_find(const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &qcom_pdm_services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &qcom_pdm_services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(const struct qcom_pdm_domain_data *data)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(TMS_SERVREG_SERVICE,
++ data->domain,
++ data->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; data->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data->services[i],
++ data->domain,
++ data->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(void)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &qcom_pdm_services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static int qcom_pdm_start(void)
++{
++ const struct of_device_id *match;
++ const struct qcom_pdm_domain_data * const *domains;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return -ENODEV;
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return -ENODEV;
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return -ENODEV;
++ }
++
++ mutex_lock(&qcom_pdm_mutex);
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(domains[i]);
++ if (ret)
++ goto free_domains;
++ }
++
++ ret = qmi_handle_init(&qcom_pdm_handle, 1024,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret)
++ goto free_domains;
++
++ ret = qmi_add_server(&qcom_pdm_handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto release_handle;
++ }
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return 0;
++
++release_handle:
++ qmi_handle_release(&qcom_pdm_handle);
++
++free_domains:
++ qcom_pdm_free_domains();
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_stop(void)
++{
++ qmi_del_server(&qcom_pdm_handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++
++ qmi_handle_release(&qcom_pdm_handle);
++
++ qcom_pdm_free_domains();
++}
++
++/**
++ * qcom_pdm_get() - ensure that PD mapper is up and running
++ *
++ * Start the in-kernel Qualcomm DSP protection domain mapper service if it was
++ * not running.
++ *
++ * Return: 0 on success, negative error code on failure.
++ */
++int qcom_pdm_get(void)
++{
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_count_mutex);
++
++ if (!qcom_pdm_count)
++ ret = qcom_pdm_start();
++ if (!ret)
++ ++qcom_pdm_count;
++
++ mutex_unlock(&qcom_pdm_count_mutex);
++
++ /*
++ * If it is -ENODEV, the plaform is not supported by the in-kernel
++ * mapper. Still return 0 to rproc driver, userspace daemon will be
++ * used instead of the kernel server.
++ */
++ if (ret == -ENODEV)
++ return 0;
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(qcom_pdm_get);
++
++/**
++ * qcom_pdm_release() - possibly stop PD mapper service
++ *
++ * Decreases refcount, stopping the server when the last user was removed.
++ */
++void qcom_pdm_release(void)
++{
++ mutex_lock(&qcom_pdm_count_mutex);
++
++ if (qcom_pdm_count == 1)
++ qcom_pdm_stop();
++
++ if (qcom_pdm_count >= 1)
++ --qcom_pdm_count;
++
++ mutex_unlock(&qcom_pdm_count_mutex);
++}
++EXPORT_SYMBOL_GPL(qcom_pdm_release);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+diff --git a/include/linux/soc/qcom/pd_mapper.h b/include/linux/soc/qcom/pd_mapper.h
+new file mode 100644
+index 000000000000..d0dd3dfc8fea
+--- /dev/null
++++ b/include/linux/soc/qcom/pd_mapper.h
+@@ -0,0 +1,28 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++#ifndef __QCOM_PD_MAPPER__
++#define __QCOM_PD_MAPPER__
++
++#if IS_ENABLED(CONFIG_QCOM_PD_MAPPER)
++
++int qcom_pdm_get(void);
++void qcom_pdm_release(void);
++
++#else
++
++static inline int qcom_pdm_get(void)
++{
++ return 0;
++}
++
++static inline void qcom_pdm_release(void)
++{
++}
++
++#endif
++
++#endif
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Wed, 24 Apr 2024 12:28:02 +0300
+Subject: [PATCH v7 6/6] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/Kconfig | 4 ++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 11 ++++++++++-
+ drivers/remoteproc/qcom_q6v5_mss.c | 10 +++++++++-
+ drivers/remoteproc/qcom_q6v5_pas.c | 12 +++++++++++-
+ drivers/remoteproc/qcom_q6v5_wcss.c | 12 +++++++++++-
+ 5 files changed, 45 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
+index 48845dc8fa85..a0ce552f89a1 100644
+--- a/drivers/remoteproc/Kconfig
++++ b/drivers/remoteproc/Kconfig
+@@ -181,6 +181,7 @@ config QCOM_Q6V5_ADSP
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
+ depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n
++ depends on QCOM_PD_MAPPER || QCOM_PD_MAPPER=n
+ select MFD_SYSCON
+ select QCOM_PIL_INFO
+ select QCOM_MDT_LOADER
+@@ -201,6 +202,7 @@ config QCOM_Q6V5_MSS
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
+ depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n
++ depends on QCOM_PD_MAPPER || QCOM_PD_MAPPER=n
+ select MFD_SYSCON
+ select QCOM_MDT_LOADER
+ select QCOM_PIL_INFO
+@@ -221,6 +223,7 @@ config QCOM_Q6V5_PAS
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
+ depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n
++ depends on QCOM_PD_MAPPER || QCOM_PD_MAPPER=n
+ select MFD_SYSCON
+ select QCOM_PIL_INFO
+ select QCOM_MDT_LOADER
+@@ -243,6 +246,7 @@ config QCOM_Q6V5_WCSS
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
+ depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n
++ depends on QCOM_PD_MAPPER || QCOM_PD_MAPPER=n
+ select MFD_SYSCON
+ select QCOM_MDT_LOADER
+ select QCOM_PIL_INFO
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..02d0c626b03b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -23,6 +23,7 @@
+ #include <linux/remoteproc.h>
+ #include <linux/reset.h>
+ #include <linux/soc/qcom/mdt_loader.h>
++#include <linux/soc/qcom/pd_mapper.h>
+ #include <linux/soc/qcom/smem.h>
+ #include <linux/soc/qcom/smem_state.h>
+
+@@ -375,10 +376,14 @@ static int adsp_start(struct rproc *rproc)
+ int ret;
+ unsigned int val;
+
+- ret = qcom_q6v5_prepare(&adsp->q6v5);
++ ret = qcom_pdm_get();
+ if (ret)
+ return ret;
+
++ ret = qcom_q6v5_prepare(&adsp->q6v5);
++ if (ret)
++ goto put_pdm;
++
+ ret = adsp_map_carveout(rproc);
+ if (ret) {
+ dev_err(adsp->dev, "ADSP smmu mapping failed\n");
+@@ -446,6 +451,8 @@ static int adsp_start(struct rproc *rproc)
+ adsp_unmap_carveout(rproc);
+ disable_irqs:
+ qcom_q6v5_unprepare(&adsp->q6v5);
++put_pdm:
++ qcom_pdm_release();
+
+ return ret;
+ }
+@@ -478,6 +485,8 @@ static int adsp_stop(struct rproc *rproc)
+ if (handover)
+ qcom_adsp_pil_handover(&adsp->q6v5);
+
++ qcom_pdm_release();
++
+ return ret;
+ }
+
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..791f11e7adbf 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -26,6 +26,7 @@
+ #include <linux/remoteproc.h>
+ #include <linux/reset.h>
+ #include <linux/soc/qcom/mdt_loader.h>
++#include <linux/soc/qcom/pd_mapper.h>
+ #include <linux/iopoll.h>
+ #include <linux/slab.h>
+
+@@ -1581,10 +1582,14 @@ static int q6v5_start(struct rproc *rproc)
+ int xfermemop_ret;
+ int ret;
+
+- ret = q6v5_mba_load(qproc);
++ ret = qcom_pdm_get();
+ if (ret)
+ return ret;
+
++ ret = q6v5_mba_load(qproc);
++ if (ret)
++ goto put_pdm;
++
+ dev_info(qproc->dev, "MBA booted with%s debug policy, loading mpss\n",
+ qproc->dp_size ? "" : "out");
+
+@@ -1613,6 +1618,8 @@ static int q6v5_start(struct rproc *rproc)
+ reclaim_mpss:
+ q6v5_mba_reclaim(qproc);
+ q6v5_dump_mba_logs(qproc);
++put_pdm:
++ qcom_pdm_release();
+
+ return ret;
+ }
+@@ -1627,6 +1634,7 @@ static int q6v5_stop(struct rproc *rproc)
+ dev_err(qproc->dev, "timed out on wait\n");
+
+ q6v5_mba_reclaim(qproc);
++ qcom_pdm_release();
+
+ return 0;
+ }
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 54d8005d40a3..653e54f975fc 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -23,6 +23,7 @@
+ #include <linux/regulator/consumer.h>
+ #include <linux/remoteproc.h>
+ #include <linux/soc/qcom/mdt_loader.h>
++#include <linux/soc/qcom/pd_mapper.h>
+ #include <linux/soc/qcom/smem.h>
+ #include <linux/soc/qcom/smem_state.h>
+
+@@ -261,10 +262,14 @@ static int adsp_start(struct rproc *rproc)
+ struct qcom_adsp *adsp = rproc->priv;
+ int ret;
+
+- ret = qcom_q6v5_prepare(&adsp->q6v5);
++ ret = qcom_pdm_get();
+ if (ret)
+ return ret;
+
++ ret = qcom_q6v5_prepare(&adsp->q6v5);
++ if (ret)
++ goto put_pdm;
++
+ ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ if (ret < 0)
+ goto disable_irqs;
+@@ -356,6 +361,9 @@ static int adsp_start(struct rproc *rproc)
+ /* Remove pointer to the loaded firmware, only valid in adsp_load() & adsp_start() */
+ adsp->firmware = NULL;
+
++put_pdm:
++ qcom_pdm_release();
++
+ return ret;
+ }
+
+@@ -399,6 +407,8 @@ static int adsp_stop(struct rproc *rproc)
+ if (handover)
+ qcom_pas_handover(&adsp->q6v5);
+
++ qcom_pdm_release();
++
+ return ret;
+ }
+
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..6ed60f3f3eee 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -18,6 +18,7 @@
+ #include <linux/regulator/consumer.h>
+ #include <linux/reset.h>
+ #include <linux/soc/qcom/mdt_loader.h>
++#include <linux/soc/qcom/pd_mapper.h>
+ #include "qcom_common.h"
+ #include "qcom_pil_info.h"
+ #include "qcom_q6v5.h"
+@@ -240,13 +241,17 @@ static int q6v5_wcss_start(struct rproc *rproc)
+ struct q6v5_wcss *wcss = rproc->priv;
+ int ret;
+
++ ret = qcom_pdm_get();
++ if (ret)
++ return ret;
++
+ qcom_q6v5_prepare(&wcss->q6v5);
+
+ /* Release Q6 and WCSS reset */
+ ret = reset_control_deassert(wcss->wcss_reset);
+ if (ret) {
+ dev_err(wcss->dev, "wcss_reset failed\n");
+- return ret;
++ goto put_pdm;
+ }
+
+ ret = reset_control_deassert(wcss->wcss_q6_reset);
+@@ -288,6 +293,9 @@ static int q6v5_wcss_start(struct rproc *rproc)
+ wcss_reset:
+ reset_control_assert(wcss->wcss_reset);
+
++put_pdm:
++ qcom_pdm_release();
++
+ return ret;
+ }
+
+@@ -735,6 +743,8 @@ static int q6v5_wcss_stop(struct rproc *rproc)
+
+ qcom_q6v5_unprepare(&wcss->q6v5);
+
++ qcom_pdm_release();
++
+ return 0;
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 6c1328da295d7c..7ee5d17b608095 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.9
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From 87b1521f884c6d3389466e5138b1109410072f64 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Sun, 5 May 2024 10:06:58 -0400
Subject: [PATCH 3/3] grub: support loading devicetrees
---
srcpkgs/grub/patches/devicetree-loading.patch | 50 +++++++++++++++++++
srcpkgs/grub/template | 2 +-
2 files changed, 51 insertions(+), 1 deletion(-)
create mode 100644 srcpkgs/grub/patches/devicetree-loading.patch
diff --git a/srcpkgs/grub/patches/devicetree-loading.patch b/srcpkgs/grub/patches/devicetree-loading.patch
new file mode 100644
index 00000000000000..b2284bf0f35937
--- /dev/null
+++ b/srcpkgs/grub/patches/devicetree-loading.patch
@@ -0,0 +1,50 @@
+support loading a devicetree based on GRUB_DEFAULT_DTB in /etc/default/grub
+
+looks in /boot/dtbs/dtbs-${version}/${GRUB_DEFAULT_DTB}
+
+based on https://src.fedoraproject.org/rpms/grub2/blob/rawhide/f/0022-Add-devicetree-loading.patch
+
+--- a/util/grub-mkconfig.in
++++ b/util/grub-mkconfig.in
+@@ -255,7 +255,8 @@
+ GRUB_ENABLE_CRYPTODISK \
+ GRUB_BADRAM \
+ GRUB_OS_PROBER_SKIP_LIST \
+- GRUB_DISABLE_SUBMENU
++ GRUB_DISABLE_SUBMENU \
++ GRUB_DEFAULT_DTB
+
+ if test "x${grub_cfg}" != "x"; then
+ rm -f "${grub_cfg}.new"
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -129,6 +129,14 @@
+
+ echo " insmod gzio" | sed "s/^/$submenu_indentation/"
+
++ if test -n "${dtb}" ; then
++ message="$(gettext_printf "Loading devicetree ...")"
++ sed "s/^/$submenu_indentation/" << EOF
++ echo '$(echo "$message" | grub_quote)'
++ devicetree ${rel_dirname}/${dtb}
++EOF
++ fi
++
+ if [ x$dirname = x/ ]; then
+ if [ -z "${prepare_root_cache}" ]; then
+ prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | grub_add_tab)"
+@@ -250,6 +258,14 @@
+ gettext_printf "Found initrd image: %s\n" "$(echo $initrd_display)" >&2
+ fi
+
++ dtb=
++ for i in "dtbs-${version}" "dtbs-${alt_version}"; do
++ if test -f "${dirname}/dtbs/${i}/${GRUB_DEFAULT_DTB}" ; then
++ dtb="dtbs/${i}/${GRUB_DEFAULT_DTB}"
++ break
++ fi
++ done
++
+ config=
+ for i in "${dirname}/config-${version}" "${dirname}/config-${alt_version}" "/etc/kernels/kernel-config-${version}" ; do
+ if test -e "${i}" ; then
diff --git a/srcpkgs/grub/template b/srcpkgs/grub/template
index 6f2dcb03684fdc..5bf8c1d7909f80 100644
--- a/srcpkgs/grub/template
+++ b/srcpkgs/grub/template
@@ -1,7 +1,7 @@
# Template file for 'grub'
pkgname=grub
version=2.12
-revision=1
+revision=2
hostmakedepends="python3 pkg-config flex freetype-devel font-unifont-bdf help2man
automake gettext-devel-tools"
makedepends="libusb-compat-devel ncurses-devel freetype-devel liblzma-devel
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (18 preceding siblings ...)
2024-05-05 15:26 ` classabbyamp
@ 2024-05-05 17:02 ` classabbyamp
2024-05-22 6:57 ` classabbyamp
` (14 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-05-05 17:02 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1289 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [ ] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 72277 bytes --]
From 326031a95d2a8a34863fa6b07feef3327b314116 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/2] New package: x13s-base-0.2
---
srcpkgs/x13s-base/INSTALL | 16 ++++++++++++++++
srcpkgs/x13s-base/files/90-bt-address.sh | 4 ++++
srcpkgs/x13s-base/files/90-net-address.rules | 2 ++
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 18 ++++++++++++++++++
6 files changed, 52 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..c30648a8f3d2e0
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,16 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:AA:BB:CC/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm -f usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+
+ # assign a random bluetooth MAC address with the correct OUI
+ sed -i.bak -e "s/:AA:BB:CC/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ etc/runit/core-services/90-x13s-bt-address.sh
+ rm -f usr/lib/udev/rules.d/90-x13s-bt-address.sh.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh
new file mode 100644
index 00000000000000..9c0be47992efb5
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-bt-address.sh
@@ -0,0 +1,4 @@
+if type btmgmt >/dev/null 2>&1; then
+ msg "Setting bluetooth MAC address..."
+ btmgmt --index 0 public-addr F4:A0:0D:AA:BB:CC
+fi
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..c16e39b9df089e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1,2 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", \
+ RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:AA:BB:CC"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..a24acfa3d0a06e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm "
+force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..a428eefb2016f9
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm
+ phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..347e58d4c38dd8
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,18 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.3
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+do_install() {
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From cb1d870b7206a444e058c9cf3c9e55a5c47f130b Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/2] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 81 +-
...d-in-kernel-pd-mapper-implementation.patch | 2011 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2070 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index ada0e5a9e51201..97e9d729c3aa38 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.9 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..a0288d36034b11
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,2011 @@
+source: https://patchwork.kernel.org/project/linux-remoteproc/cover/20240424-qcom-pd-mapper-v7-0-05f7fc646e0f@linaro.org/
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Wed, 24 Apr 2024 12:27:57 +0300
+Subject: [PATCH v7 1/6] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..19cfe4b41235 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Wed, 24 Apr 2024 12:27:58 +0300
+Subject: [PATCH v7 2/6] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 19cfe4b41235..3c6f2d21e5e4 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -415,7 +415,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Wed, 24 Apr 2024 12:27:59 +0300
+Subject: [PATCH v7 3/6] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Wed, 24 Apr 2024 12:28:00 +0300
+Subject: [PATCH v7 4/6] soc: qcom: qmi: add a way to remove running service
+
+Add qmi_del_server(), a pair to qmi_add_server(), a way to remove
+running server from the QMI socket. This is e.g. necessary for
+pd-mapper, which needs to readd a server each time the DSP is started or
+stopped.
+
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/qmi_interface.c | 67 ++++++++++++++++++++++++++++++++++++++++
+ include/linux/soc/qcom/qmi.h | 2 ++
+ 2 files changed, 69 insertions(+)
+
+diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c
+index bb98b06e87f8..18ff2015c682 100644
+--- a/drivers/soc/qcom/qmi_interface.c
++++ b/drivers/soc/qcom/qmi_interface.c
+@@ -289,6 +289,73 @@ int qmi_add_server(struct qmi_handle *qmi, unsigned int service,
+ }
+ EXPORT_SYMBOL_GPL(qmi_add_server);
+
++static void qmi_send_del_server(struct qmi_handle *qmi, struct qmi_service *svc)
++{
++ struct qrtr_ctrl_pkt pkt;
++ struct sockaddr_qrtr sq;
++ struct msghdr msg = { };
++ struct kvec iv = { &pkt, sizeof(pkt) };
++ int ret;
++
++ memset(&pkt, 0, sizeof(pkt));
++ pkt.cmd = cpu_to_le32(QRTR_TYPE_DEL_SERVER);
++ pkt.server.service = cpu_to_le32(svc->service);
++ pkt.server.instance = cpu_to_le32(svc->version | svc->instance << 8);
++ pkt.server.node = cpu_to_le32(qmi->sq.sq_node);
++ pkt.server.port = cpu_to_le32(qmi->sq.sq_port);
++
++ sq.sq_family = qmi->sq.sq_family;
++ sq.sq_node = qmi->sq.sq_node;
++ sq.sq_port = QRTR_PORT_CTRL;
++
++ msg.msg_name = &sq;
++ msg.msg_namelen = sizeof(sq);
++
++ mutex_lock(&qmi->sock_lock);
++ if (qmi->sock) {
++ ret = kernel_sendmsg(qmi->sock, &msg, &iv, 1, sizeof(pkt));
++ if (ret < 0)
++ pr_err("send service deregistration failed: %d\n", ret);
++ }
++ mutex_unlock(&qmi->sock_lock);
++}
++
++/**
++ * qmi_del_server() - register a service with the name service
++ * @qmi: qmi handle
++ * @service: type of the service
++ * @instance: instance of the service
++ * @version: version of the service
++ *
++ * Remove registration of the service with the name service. This notifies
++ * clients that they should no longer send messages to the client associated
++ * with @qmi.
++ *
++ * Return: 0 on success, negative errno on failure.
++ */
++int qmi_del_server(struct qmi_handle *qmi, unsigned int service,
++ unsigned int version, unsigned int instance)
++{
++ struct qmi_service *svc;
++ struct qmi_service *tmp;
++
++ list_for_each_entry_safe(svc, tmp, &qmi->services, list_node) {
++ if (svc->service != service ||
++ svc->version != version ||
++ svc->instance != instance)
++ continue;
++
++ qmi_send_del_server(qmi, svc);
++ list_del(&svc->list_node);
++ kfree(svc);
++
++ return 0;
++ }
++
++ return -EINVAL;
++}
++EXPORT_SYMBOL_GPL(qmi_del_server);
++
+ /**
+ * qmi_txn_init() - allocate transaction id within the given QMI handle
+ * @qmi: QMI handle
+diff --git a/include/linux/soc/qcom/qmi.h b/include/linux/soc/qcom/qmi.h
+index 469e02d2aa0d..5039c30e4bdc 100644
+--- a/include/linux/soc/qcom/qmi.h
++++ b/include/linux/soc/qcom/qmi.h
+@@ -241,6 +241,8 @@ int qmi_add_lookup(struct qmi_handle *qmi, unsigned int service,
+ unsigned int version, unsigned int instance);
+ int qmi_add_server(struct qmi_handle *qmi, unsigned int service,
+ unsigned int version, unsigned int instance);
++int qmi_del_server(struct qmi_handle *qmi, unsigned int service,
++ unsigned int version, unsigned int instance);
+
+ int qmi_handle_init(struct qmi_handle *qmi, size_t max_msg_len,
+ const struct qmi_ops *ops,
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Wed, 24 Apr 2024 12:28:01 +0300
+Subject: [PATCH v7 5/6] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 10 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 656 +++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ include/linux/soc/qcom/pd_mapper.h | 28 ++
+ 6 files changed, 743 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..f666366841b8 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,16 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ba5440506c95
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,656 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/soc/qcom/pd_mapper.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++static DEFINE_MUTEX(qcom_pdm_count_mutex); /* guards count */
++/*
++ * It is not possible to use refcount_t here. The service needs to go to 0 and
++ * back without warnings.
++ */
++static unsigned int qcom_pdm_count;
++
++static DEFINE_MUTEX(qcom_pdm_mutex);
++static struct qmi_handle qcom_pdm_handle;
++static LIST_HEAD(qcom_pdm_services);
++
++static struct qcom_pdm_service *qcom_pdm_find(const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &qcom_pdm_services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &qcom_pdm_services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(const struct qcom_pdm_domain_data *data)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(TMS_SERVREG_SERVICE,
++ data->domain,
++ data->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; data->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data->services[i],
++ data->domain,
++ data->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(void)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &qcom_pdm_services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static int qcom_pdm_start(void)
++{
++ const struct of_device_id *match;
++ const struct qcom_pdm_domain_data * const *domains;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return -ENODEV;
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return -ENODEV;
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return -ENODEV;
++ }
++
++ mutex_lock(&qcom_pdm_mutex);
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(domains[i]);
++ if (ret)
++ goto free_domains;
++ }
++
++ ret = qmi_handle_init(&qcom_pdm_handle, 1024,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret)
++ goto free_domains;
++
++ ret = qmi_add_server(&qcom_pdm_handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto release_handle;
++ }
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return 0;
++
++release_handle:
++ qmi_handle_release(&qcom_pdm_handle);
++
++free_domains:
++ qcom_pdm_free_domains();
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_stop(void)
++{
++ qmi_del_server(&qcom_pdm_handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++
++ qmi_handle_release(&qcom_pdm_handle);
++
++ qcom_pdm_free_domains();
++}
++
++/**
++ * qcom_pdm_get() - ensure that PD mapper is up and running
++ *
++ * Start the in-kernel Qualcomm DSP protection domain mapper service if it was
++ * not running.
++ *
++ * Return: 0 on success, negative error code on failure.
++ */
++int qcom_pdm_get(void)
++{
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_count_mutex);
++
++ if (!qcom_pdm_count)
++ ret = qcom_pdm_start();
++ if (!ret)
++ ++qcom_pdm_count;
++
++ mutex_unlock(&qcom_pdm_count_mutex);
++
++ /*
++ * If it is -ENODEV, the plaform is not supported by the in-kernel
++ * mapper. Still return 0 to rproc driver, userspace daemon will be
++ * used instead of the kernel server.
++ */
++ if (ret == -ENODEV)
++ return 0;
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(qcom_pdm_get);
++
++/**
++ * qcom_pdm_release() - possibly stop PD mapper service
++ *
++ * Decreases refcount, stopping the server when the last user was removed.
++ */
++void qcom_pdm_release(void)
++{
++ mutex_lock(&qcom_pdm_count_mutex);
++
++ if (qcom_pdm_count == 1)
++ qcom_pdm_stop();
++
++ if (qcom_pdm_count >= 1)
++ --qcom_pdm_count;
++
++ mutex_unlock(&qcom_pdm_count_mutex);
++}
++EXPORT_SYMBOL_GPL(qcom_pdm_release);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+diff --git a/include/linux/soc/qcom/pd_mapper.h b/include/linux/soc/qcom/pd_mapper.h
+new file mode 100644
+index 000000000000..d0dd3dfc8fea
+--- /dev/null
++++ b/include/linux/soc/qcom/pd_mapper.h
+@@ -0,0 +1,28 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++#ifndef __QCOM_PD_MAPPER__
++#define __QCOM_PD_MAPPER__
++
++#if IS_ENABLED(CONFIG_QCOM_PD_MAPPER)
++
++int qcom_pdm_get(void);
++void qcom_pdm_release(void);
++
++#else
++
++static inline int qcom_pdm_get(void)
++{
++ return 0;
++}
++
++static inline void qcom_pdm_release(void)
++{
++}
++
++#endif
++
++#endif
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Wed, 24 Apr 2024 12:28:02 +0300
+Subject: [PATCH v7 6/6] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/Kconfig | 4 ++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 11 ++++++++++-
+ drivers/remoteproc/qcom_q6v5_mss.c | 10 +++++++++-
+ drivers/remoteproc/qcom_q6v5_pas.c | 12 +++++++++++-
+ drivers/remoteproc/qcom_q6v5_wcss.c | 12 +++++++++++-
+ 5 files changed, 45 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
+index 48845dc8fa85..a0ce552f89a1 100644
+--- a/drivers/remoteproc/Kconfig
++++ b/drivers/remoteproc/Kconfig
+@@ -181,6 +181,7 @@ config QCOM_Q6V5_ADSP
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
+ depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n
++ depends on QCOM_PD_MAPPER || QCOM_PD_MAPPER=n
+ select MFD_SYSCON
+ select QCOM_PIL_INFO
+ select QCOM_MDT_LOADER
+@@ -201,6 +202,7 @@ config QCOM_Q6V5_MSS
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
+ depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n
++ depends on QCOM_PD_MAPPER || QCOM_PD_MAPPER=n
+ select MFD_SYSCON
+ select QCOM_MDT_LOADER
+ select QCOM_PIL_INFO
+@@ -221,6 +223,7 @@ config QCOM_Q6V5_PAS
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
+ depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n
++ depends on QCOM_PD_MAPPER || QCOM_PD_MAPPER=n
+ select MFD_SYSCON
+ select QCOM_PIL_INFO
+ select QCOM_MDT_LOADER
+@@ -243,6 +246,7 @@ config QCOM_Q6V5_WCSS
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
+ depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n
++ depends on QCOM_PD_MAPPER || QCOM_PD_MAPPER=n
+ select MFD_SYSCON
+ select QCOM_MDT_LOADER
+ select QCOM_PIL_INFO
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..02d0c626b03b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -23,6 +23,7 @@
+ #include <linux/remoteproc.h>
+ #include <linux/reset.h>
+ #include <linux/soc/qcom/mdt_loader.h>
++#include <linux/soc/qcom/pd_mapper.h>
+ #include <linux/soc/qcom/smem.h>
+ #include <linux/soc/qcom/smem_state.h>
+
+@@ -375,10 +376,14 @@ static int adsp_start(struct rproc *rproc)
+ int ret;
+ unsigned int val;
+
+- ret = qcom_q6v5_prepare(&adsp->q6v5);
++ ret = qcom_pdm_get();
+ if (ret)
+ return ret;
+
++ ret = qcom_q6v5_prepare(&adsp->q6v5);
++ if (ret)
++ goto put_pdm;
++
+ ret = adsp_map_carveout(rproc);
+ if (ret) {
+ dev_err(adsp->dev, "ADSP smmu mapping failed\n");
+@@ -446,6 +451,8 @@ static int adsp_start(struct rproc *rproc)
+ adsp_unmap_carveout(rproc);
+ disable_irqs:
+ qcom_q6v5_unprepare(&adsp->q6v5);
++put_pdm:
++ qcom_pdm_release();
+
+ return ret;
+ }
+@@ -478,6 +485,8 @@ static int adsp_stop(struct rproc *rproc)
+ if (handover)
+ qcom_adsp_pil_handover(&adsp->q6v5);
+
++ qcom_pdm_release();
++
+ return ret;
+ }
+
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..791f11e7adbf 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -26,6 +26,7 @@
+ #include <linux/remoteproc.h>
+ #include <linux/reset.h>
+ #include <linux/soc/qcom/mdt_loader.h>
++#include <linux/soc/qcom/pd_mapper.h>
+ #include <linux/iopoll.h>
+ #include <linux/slab.h>
+
+@@ -1581,10 +1582,14 @@ static int q6v5_start(struct rproc *rproc)
+ int xfermemop_ret;
+ int ret;
+
+- ret = q6v5_mba_load(qproc);
++ ret = qcom_pdm_get();
+ if (ret)
+ return ret;
+
++ ret = q6v5_mba_load(qproc);
++ if (ret)
++ goto put_pdm;
++
+ dev_info(qproc->dev, "MBA booted with%s debug policy, loading mpss\n",
+ qproc->dp_size ? "" : "out");
+
+@@ -1613,6 +1618,8 @@ static int q6v5_start(struct rproc *rproc)
+ reclaim_mpss:
+ q6v5_mba_reclaim(qproc);
+ q6v5_dump_mba_logs(qproc);
++put_pdm:
++ qcom_pdm_release();
+
+ return ret;
+ }
+@@ -1627,6 +1634,7 @@ static int q6v5_stop(struct rproc *rproc)
+ dev_err(qproc->dev, "timed out on wait\n");
+
+ q6v5_mba_reclaim(qproc);
++ qcom_pdm_release();
+
+ return 0;
+ }
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 54d8005d40a3..653e54f975fc 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -23,6 +23,7 @@
+ #include <linux/regulator/consumer.h>
+ #include <linux/remoteproc.h>
+ #include <linux/soc/qcom/mdt_loader.h>
++#include <linux/soc/qcom/pd_mapper.h>
+ #include <linux/soc/qcom/smem.h>
+ #include <linux/soc/qcom/smem_state.h>
+
+@@ -261,10 +262,14 @@ static int adsp_start(struct rproc *rproc)
+ struct qcom_adsp *adsp = rproc->priv;
+ int ret;
+
+- ret = qcom_q6v5_prepare(&adsp->q6v5);
++ ret = qcom_pdm_get();
+ if (ret)
+ return ret;
+
++ ret = qcom_q6v5_prepare(&adsp->q6v5);
++ if (ret)
++ goto put_pdm;
++
+ ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ if (ret < 0)
+ goto disable_irqs;
+@@ -356,6 +361,9 @@ static int adsp_start(struct rproc *rproc)
+ /* Remove pointer to the loaded firmware, only valid in adsp_load() & adsp_start() */
+ adsp->firmware = NULL;
+
++put_pdm:
++ qcom_pdm_release();
++
+ return ret;
+ }
+
+@@ -399,6 +407,8 @@ static int adsp_stop(struct rproc *rproc)
+ if (handover)
+ qcom_pas_handover(&adsp->q6v5);
+
++ qcom_pdm_release();
++
+ return ret;
+ }
+
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..6ed60f3f3eee 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -18,6 +18,7 @@
+ #include <linux/regulator/consumer.h>
+ #include <linux/reset.h>
+ #include <linux/soc/qcom/mdt_loader.h>
++#include <linux/soc/qcom/pd_mapper.h>
+ #include "qcom_common.h"
+ #include "qcom_pil_info.h"
+ #include "qcom_q6v5.h"
+@@ -240,13 +241,17 @@ static int q6v5_wcss_start(struct rproc *rproc)
+ struct q6v5_wcss *wcss = rproc->priv;
+ int ret;
+
++ ret = qcom_pdm_get();
++ if (ret)
++ return ret;
++
+ qcom_q6v5_prepare(&wcss->q6v5);
+
+ /* Release Q6 and WCSS reset */
+ ret = reset_control_deassert(wcss->wcss_reset);
+ if (ret) {
+ dev_err(wcss->dev, "wcss_reset failed\n");
+- return ret;
++ goto put_pdm;
+ }
+
+ ret = reset_control_deassert(wcss->wcss_q6_reset);
+@@ -288,6 +293,9 @@ static int q6v5_wcss_start(struct rproc *rproc)
+ wcss_reset:
+ reset_control_assert(wcss->wcss_reset);
+
++put_pdm:
++ qcom_pdm_release();
++
+ return ret;
+ }
+
+@@ -735,6 +743,8 @@ static int q6v5_wcss_stop(struct rproc *rproc)
+
+ qcom_q6v5_unprepare(&wcss->q6v5);
+
++ qcom_pdm_release();
++
+ return 0;
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 6c1328da295d7c..7ee5d17b608095 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.9
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (19 preceding siblings ...)
2024-05-05 17:02 ` classabbyamp
@ 2024-05-22 6:57 ` classabbyamp
2024-05-31 1:14 ` classabbyamp
` (13 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-05-22 6:57 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [x] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] mkinitcpio working
- https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/377
- does not load modules and/or firmware correctly
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 72935 bytes --]
From 520fd26bdd218cebfccf04ffdb08c10545d90a5a Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/2] New package: x13s-base-0.4
---
srcpkgs/x13s-base/INSTALL | 16 ++++++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-bt-address.sh | 4 ++++
srcpkgs/x13s-base/files/90-net-address.rules | 2 ++
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 19 +++++++++++++++++++
7 files changed, 54 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..c30648a8f3d2e0
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,16 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:AA:BB:CC/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm -f usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+
+ # assign a random bluetooth MAC address with the correct OUI
+ sed -i.bak -e "s/:AA:BB:CC/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ etc/runit/core-services/90-x13s-bt-address.sh
+ rm -f usr/lib/udev/rules.d/90-x13s-bt-address.sh.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh
new file mode 100644
index 00000000000000..9c0be47992efb5
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-bt-address.sh
@@ -0,0 +1,4 @@
+if type btmgmt >/dev/null 2>&1; then
+ msg "Setting bluetooth MAC address..."
+ btmgmt --index 0 public-addr F4:A0:0D:AA:BB:CC
+fi
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..c16e39b9df089e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1,2 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", \
+ RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:AA:BB:CC"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..a24acfa3d0a06e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm "
+force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..a428eefb2016f9
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm
+ phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..5956eaa6bac558
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,19 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.4
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 72-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From bb9e327807475e7cab3625e4514f16cd4342fe0b Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/2] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 81 +-
...d-in-kernel-pd-mapper-implementation.patch | 1964 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2023 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index c83b61e5fcbe2f..ee27ce08cf34f3 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.9 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..839f0933e411d1
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1964 @@
+source: https://patchwork.kernel.org/project/linux-remoteproc/cover/20240512-qcom-pd-mapper-v8-0-5ecbb276fcc0@linaro.org/
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:03 +0300
+Subject: [PATCH v8 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..e014dd2d8ab3 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,6 +365,7 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+@@ -373,15 +374,16 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ req);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+- return ret;
++ goto err_unlock;
+ }
+
+ ret = qmi_txn_wait(&txn, 5 * HZ);
+ if (ret < 0) {
+ pr_err("PDR: %s get domain list txn wait failed: %d\n",
+ req->service_name, ret);
+- return ret;
++ goto err_unlock;
+ }
++ mutex_unlock(&pdr->lock);
+
+ if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
+ pr_err("PDR: %s get domain list failed: 0x%x\n",
+@@ -390,6 +392,11 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ }
+
+ return 0;
++
++err_unlock:
++ mutex_unlock(&pdr->lock);
++
++ return ret;
+ }
+
+ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:04 +0300
+Subject: [PATCH v8 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index e014dd2d8ab3..d495ee736519 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -422,7 +422,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:05 +0300
+Subject: [PATCH v8 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:06 +0300
+Subject: [PATCH v8 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:07 +0300
+Subject: [PATCH v8 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 54d8005d40a3..399c3bc104bd 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -109,6 +109,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -771,6 +772,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -805,6 +807,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 79e6a131a75640..f1c842f040396d 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.10
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (20 preceding siblings ...)
2024-05-22 6:57 ` classabbyamp
@ 2024-05-31 1:14 ` classabbyamp
2024-06-08 1:52 ` [PR REVIEW] " classabbyamp
` (12 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-05-31 1:14 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [x] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] mkinitcpio working
- https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/377
- does not load modules and/or firmware correctly
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 72935 bytes --]
From 32076a9a1fecef44dc1d6cdb72148ad64e6a24b6 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/2] New package: x13s-base-0.4
---
srcpkgs/x13s-base/INSTALL | 16 ++++++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-bt-address.sh | 4 ++++
srcpkgs/x13s-base/files/90-net-address.rules | 2 ++
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 19 +++++++++++++++++++
7 files changed, 54 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..c30648a8f3d2e0
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,16 @@
+case "$ACTION" in
+post)
+ mkdir -p etc/runit/runsvdir/default/
+ ln -sf /etc/sv/qrtr-ns etc/runit/runsvdir/default/
+
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:AA:BB:CC/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm -f usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+
+ # assign a random bluetooth MAC address with the correct OUI
+ sed -i.bak -e "s/:AA:BB:CC/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ etc/runit/core-services/90-x13s-bt-address.sh
+ rm -f usr/lib/udev/rules.d/90-x13s-bt-address.sh.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh
new file mode 100644
index 00000000000000..9c0be47992efb5
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-bt-address.sh
@@ -0,0 +1,4 @@
+if type btmgmt >/dev/null 2>&1; then
+ msg "Setting bluetooth MAC address..."
+ btmgmt --index 0 public-addr F4:A0:0D:AA:BB:CC
+fi
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..c16e39b9df089e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1,2 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", \
+ RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:AA:BB:CC"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..a24acfa3d0a06e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm "
+force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..a428eefb2016f9
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm
+ phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..5956eaa6bac558
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,19 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.4
+revision=1
+archs="aarch64*"
+depends="linux6.8 dracut linux-firmware-qualcomm linux-firmware-network
+ alsa-ucm-conf qrtr-ns"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 72-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 3829d3f52e4968f42b247acebb1501e0c3ef58cd Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/2] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 81 +-
...d-in-kernel-pd-mapper-implementation.patch | 1964 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2023 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index c83b61e5fcbe2f..ee27ce08cf34f3 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.9 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..839f0933e411d1
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1964 @@
+source: https://patchwork.kernel.org/project/linux-remoteproc/cover/20240512-qcom-pd-mapper-v8-0-5ecbb276fcc0@linaro.org/
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:03 +0300
+Subject: [PATCH v8 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..e014dd2d8ab3 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,6 +365,7 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+@@ -373,15 +374,16 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ req);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+- return ret;
++ goto err_unlock;
+ }
+
+ ret = qmi_txn_wait(&txn, 5 * HZ);
+ if (ret < 0) {
+ pr_err("PDR: %s get domain list txn wait failed: %d\n",
+ req->service_name, ret);
+- return ret;
++ goto err_unlock;
+ }
++ mutex_unlock(&pdr->lock);
+
+ if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
+ pr_err("PDR: %s get domain list failed: 0x%x\n",
+@@ -390,6 +392,11 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ }
+
+ return 0;
++
++err_unlock:
++ mutex_unlock(&pdr->lock);
++
++ return ret;
+ }
+
+ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:04 +0300
+Subject: [PATCH v8 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index e014dd2d8ab3..d495ee736519 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -422,7 +422,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:05 +0300
+Subject: [PATCH v8 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:06 +0300
+Subject: [PATCH v8 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:07 +0300
+Subject: [PATCH v8 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 54d8005d40a3..399c3bc104bd 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -109,6 +109,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -771,6 +772,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -805,6 +807,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 0db68f04bb6e23..f9ff81b3d68d62 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.12
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR REVIEW] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (21 preceding siblings ...)
2024-05-31 1:14 ` classabbyamp
@ 2024-06-08 1:52 ` classabbyamp
2024-06-08 7:37 ` classabbyamp
` (11 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-06-08 1:52 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 279 bytes --]
New review comment by classabbyamp on void-packages repository
https://github.com/void-linux/void-packages/pull/49615#discussion_r1631815240
Comment:
```bash
ln -sf /usr/share/ModemManager/fcc-unlock.available.d/105b "${DESTDIR}/etc/ModemManager/fcc-unlock.d/105b:e0c3"
```
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR REVIEW] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (22 preceding siblings ...)
2024-06-08 1:52 ` [PR REVIEW] " classabbyamp
@ 2024-06-08 7:37 ` classabbyamp
2024-06-08 7:37 ` classabbyamp
` (10 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-06-08 7:37 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 171 bytes --]
New review comment by classabbyamp on void-packages repository
https://github.com/void-linux/void-packages/pull/49615#discussion_r1631939507
Comment:
```suggestion
```
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR REVIEW] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (23 preceding siblings ...)
2024-06-08 7:37 ` classabbyamp
@ 2024-06-08 7:37 ` classabbyamp
2024-06-08 8:26 ` [PR PATCH] [Updated] " classabbyamp
` (9 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-06-08 7:37 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 188 bytes --]
New review comment by classabbyamp on void-packages repository
https://github.com/void-linux/void-packages/pull/49615#discussion_r1631938933
Comment:
```suggestion
alsa-ucm-conf"
```
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (24 preceding siblings ...)
2024-06-08 7:37 ` classabbyamp
@ 2024-06-08 8:26 ` classabbyamp
2024-06-26 4:41 ` classabbyamp
` (8 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-06-08 8:26 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [ ] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [x] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] mkinitcpio working
- https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/377
- does not load modules and/or firmware correctly
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 72808 bytes --]
From 31f85e60684be97def68a0c0c0c10621aeacd9bd Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/2] New package: x13s-base-0.5
---
srcpkgs/x13s-base/INSTALL | 13 +++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-bt-address.sh | 4 ++++
srcpkgs/x13s-base/files/90-net-address.rules | 2 ++
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 18 ++++++++++++++++++
7 files changed, 50 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6a5fd0b712f42b
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,13 @@
+case "$ACTION" in
+post)
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:AA:BB:CC/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm -f usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+
+ # assign a random bluetooth MAC address with the correct OUI
+ sed -i.bak -e "s/:AA:BB:CC/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ etc/runit/core-services/90-x13s-bt-address.sh
+ rm -f usr/lib/udev/rules.d/90-x13s-bt-address.sh.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh
new file mode 100644
index 00000000000000..9c0be47992efb5
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-bt-address.sh
@@ -0,0 +1,4 @@
+if type btmgmt >/dev/null 2>&1; then
+ msg "Setting bluetooth MAC address..."
+ btmgmt --index 0 public-addr F4:A0:0D:AA:BB:CC
+fi
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..c16e39b9df089e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1,2 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", \
+ RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:AA:BB:CC"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..a24acfa3d0a06e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm "
+force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..a428eefb2016f9
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm
+ phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..6580d8cef79782
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,18 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=0.5
+revision=1
+archs="aarch64*"
+depends="linux6.8 linux-base linux-firmware-qualcomm alsa-ucm-conf"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 72-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 030b962163fd7bb0fcbb886a6bf910a1008c67b0 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/2] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 81 +-
...d-in-kernel-pd-mapper-implementation.patch | 1964 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2023 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index c83b61e5fcbe2f..ee27ce08cf34f3 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.8.9 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..839f0933e411d1
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1964 @@
+source: https://patchwork.kernel.org/project/linux-remoteproc/cover/20240512-qcom-pd-mapper-v8-0-5ecbb276fcc0@linaro.org/
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:03 +0300
+Subject: [PATCH v8 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..e014dd2d8ab3 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,6 +365,7 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+@@ -373,15 +374,16 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ req);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+- return ret;
++ goto err_unlock;
+ }
+
+ ret = qmi_txn_wait(&txn, 5 * HZ);
+ if (ret < 0) {
+ pr_err("PDR: %s get domain list txn wait failed: %d\n",
+ req->service_name, ret);
+- return ret;
++ goto err_unlock;
+ }
++ mutex_unlock(&pdr->lock);
+
+ if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
+ pr_err("PDR: %s get domain list failed: 0x%x\n",
+@@ -390,6 +392,11 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ }
+
+ return 0;
++
++err_unlock:
++ mutex_unlock(&pdr->lock);
++
++ return ret;
+ }
+
+ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:04 +0300
+Subject: [PATCH v8 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index e014dd2d8ab3..d495ee736519 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -422,7 +422,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:05 +0300
+Subject: [PATCH v8 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:06 +0300
+Subject: [PATCH v8 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 12 May 2024 00:56:07 +0300
+Subject: [PATCH v8 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 54d8005d40a3..399c3bc104bd 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -109,6 +109,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -771,6 +772,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -805,6 +807,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 0db68f04bb6e23..f9ff81b3d68d62 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.12
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (25 preceding siblings ...)
2024-06-08 8:26 ` [PR PATCH] [Updated] " classabbyamp
@ 2024-06-26 4:41 ` classabbyamp
2024-06-26 5:12 ` classabbyamp
` (7 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-06-26 4:41 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [x] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [x] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] mkinitcpio working
- https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/377
- does not load modules and/or firmware correctly
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 141238 bytes --]
From d6bc1a99a34f1b023f6ee32f803916095ae75120 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/3] New package: x13s-base-1
---
srcpkgs/x13s-base/INSTALL | 13 +++++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-bt-address.sh | 4 ++++
srcpkgs/x13s-base/files/90-net-address.rules | 2 ++
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/template | 19 +++++++++++++++++++
7 files changed, 51 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6a5fd0b712f42b
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,13 @@
+case "$ACTION" in
+post)
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:AA:BB:CC/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm -f usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+
+ # assign a random bluetooth MAC address with the correct OUI
+ sed -i.bak -e "s/:AA:BB:CC/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ etc/runit/core-services/90-x13s-bt-address.sh
+ rm -f usr/lib/udev/rules.d/90-x13s-bt-address.sh.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh
new file mode 100644
index 00000000000000..9c0be47992efb5
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-bt-address.sh
@@ -0,0 +1,4 @@
+if type btmgmt >/dev/null 2>&1; then
+ msg "Setting bluetooth MAC address..."
+ btmgmt --index 0 public-addr F4:A0:0D:AA:BB:CC
+fi
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..c16e39b9df089e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1,2 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", \
+ RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:AA:BB:CC"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..a24acfa3d0a06e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm "
+force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..a428eefb2016f9
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm
+ phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..80a7c553b02ef8
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,19 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=1
+revision=1
+archs="aarch64*"
+depends="linux-mainline>=6.8 linux-firmware-qualcomm alsa-ucm-conf"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 72-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ # not currently working
+ # vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 04468b55ad4916cea4c9c11b055889604e44917e Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/3] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 84 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2012 insertions(+), 25 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index c83b61e5fcbe2f..883783fc5653fe 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm64 6.8.9 Kernel Configuration
+# Linux/arm64 6.8.12 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
@@ -18,7 +18,7 @@ CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
-CONFIG_PAHOLE_VERSION=126
+CONFIG_PAHOLE_VERSION=127
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
@@ -12429,6 +12464,7 @@ CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_SIG=y
CONFIG_CRYPTO_SIG2=y
CONFIG_CRYPTO_SKCIPHER=y
CONFIG_CRYPTO_SKCIPHER2=y
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 0db68f04bb6e23..f9ff81b3d68d62 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.12
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From 222c3dcdf70c88cdae534dc5503fd60b7d3d8529 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 25 Jun 2024 19:36:18 -0400
Subject: [PATCH 3/3] linux6.9: add support for lenovo x13s
---
srcpkgs/linux6.9/files/arm64-dotconfig | 83 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.9/template | 2 +-
3 files changed, 2012 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.9/files/arm64-dotconfig b/srcpkgs/linux6.9/files/arm64-dotconfig
index cfa614ac8a6946..34050f4fe256cc 100644
--- a/srcpkgs/linux6.9/files/arm64-dotconfig
+++ b/srcpkgs/linux6.9/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.9.6 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -602,7 +602,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2379,7 +2379,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2447,7 +2447,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2503,7 +2503,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4921,7 +4922,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5150,7 +5151,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5323,7 +5324,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5341,7 +5342,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5938,12 +5939,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -6001,7 +6003,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6040,7 +6042,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6053,7 +6055,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9368,7 +9370,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10392,7 +10394,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10404,9 +10406,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_VIDEOCC_7180=m
@@ -10463,7 +10465,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10541,7 +10543,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10583,8 +10585,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10744,7 +10746,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11990,7 +11994,40 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8909 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM7150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.9/template b/srcpkgs/linux6.9/template
index c912190004f66f..0f084a538fc902 100644
--- a/srcpkgs/linux6.9/template
+++ b/srcpkgs/linux6.9/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.9'
pkgname=linux6.9
version=6.9.6
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (26 preceding siblings ...)
2024-06-26 4:41 ` classabbyamp
@ 2024-06-26 5:12 ` classabbyamp
2024-06-28 3:27 ` classabbyamp
` (6 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-06-26 5:12 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [x] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [x] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] mkinitcpio working
- https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/377
- does not load modules and/or firmware correctly
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 141377 bytes --]
From 55c5bb7d5849d61e47350be201ece82fed74aa6a Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/3] New package: x13s-base-1
---
srcpkgs/x13s-base/INSTALL | 13 +++++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-bt-address.sh | 4 ++++
srcpkgs/x13s-base/files/90-net-address.rules | 2 ++
srcpkgs/x13s-base/files/dracut.conf | 6 +++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 +++++
srcpkgs/x13s-base/template | 24 ++++++++++++++++++++
7 files changed, 56 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..d88f9677608441
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,13 @@
+case "$ACTION" in
+post)
+ # assign a random wlan MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ usr/lib/udev/rules.d/90-x13s-net-address.rules
+ rm -f usr/lib/udev/rules.d/90-x13s-net-address.rules.bak
+
+ # assign a random bluetooth MAC address with the correct OUI
+ sed -i.bak -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ etc/runit/core-services/90-x13s-bt-address.sh
+ rm -f usr/lib/udev/rules.d/90-x13s-bt-address.sh.bak
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh
new file mode 100644
index 00000000000000..7b44e0044ebc6c
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-bt-address.sh
@@ -0,0 +1,4 @@
+if type btmgmt >/dev/null 2>&1; then
+ msg "Setting bluetooth MAC address..."
+ btmgmt --index 0 public-addr F4:A0:0D:XX:YY:ZZ
+fi
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..014123105683c5
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1,2 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", \
+ RUN+="/usr/bin/ip link set dev $name address F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..a24acfa3d0a06e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm "
+force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..a428eefb2016f9
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm
+ phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp)
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..520b7c951e9900
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,24 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=1
+revision=1
+archs="aarch64*"
+depends="linux-mainline>=6.8 linux-firmware-qualcomm alsa-ucm-conf"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+
+# modified by INSTALL
+mutable_files="
+ /usr/lib/udev/rules.d/90-x13s-net-address.rules
+ /etc/runit/core-services/90-x13s-bt-address.sh"
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 72-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ # not currently working
+ # vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 1840163cb2e0d2f99a7cff091e49833d52a82dd3 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/3] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 84 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2012 insertions(+), 25 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index c83b61e5fcbe2f..883783fc5653fe 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm64 6.8.9 Kernel Configuration
+# Linux/arm64 6.8.12 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
@@ -18,7 +18,7 @@ CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
-CONFIG_PAHOLE_VERSION=126
+CONFIG_PAHOLE_VERSION=127
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
@@ -12429,6 +12464,7 @@ CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_SIG=y
CONFIG_CRYPTO_SIG2=y
CONFIG_CRYPTO_SKCIPHER=y
CONFIG_CRYPTO_SKCIPHER2=y
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 0db68f04bb6e23..f9ff81b3d68d62 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.12
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From d00c719948e763552e1237e486e5a8be3d70d452 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 25 Jun 2024 19:36:18 -0400
Subject: [PATCH 3/3] linux6.9: add support for lenovo x13s
---
srcpkgs/linux6.9/files/arm64-dotconfig | 83 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.9/template | 2 +-
3 files changed, 2012 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.9/files/arm64-dotconfig b/srcpkgs/linux6.9/files/arm64-dotconfig
index cfa614ac8a6946..34050f4fe256cc 100644
--- a/srcpkgs/linux6.9/files/arm64-dotconfig
+++ b/srcpkgs/linux6.9/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.9.6 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -602,7 +602,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2379,7 +2379,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2447,7 +2447,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2503,7 +2503,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4921,7 +4922,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5150,7 +5151,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5323,7 +5324,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5341,7 +5342,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5938,12 +5939,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -6001,7 +6003,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6040,7 +6042,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6053,7 +6055,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9368,7 +9370,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10392,7 +10394,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10404,9 +10406,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_VIDEOCC_7180=m
@@ -10463,7 +10465,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10541,7 +10543,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10583,8 +10585,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10744,7 +10746,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11990,7 +11994,40 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8909 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM7150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.9/template b/srcpkgs/linux6.9/template
index c912190004f66f..0f084a538fc902 100644
--- a/srcpkgs/linux6.9/template
+++ b/srcpkgs/linux6.9/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.9'
pkgname=linux6.9
version=6.9.6
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (27 preceding siblings ...)
2024-06-26 5:12 ` classabbyamp
@ 2024-06-28 3:27 ` classabbyamp
2024-07-04 8:51 ` classabbyamp
` (5 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-06-28 3:27 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [x] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [x] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] mkinitcpio working
- https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/377
- does not load modules and/or firmware correctly
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 142229 bytes --]
From 060fcfb96efdb4c7970906ff112ea6c584c20ca3 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/3] New package: x13s-base-1
---
srcpkgs/x13s-base/INSTALL | 9 ++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-bt-address.sh | 2 ++
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/files/x13s-setup | 18 ++++++++++++++++
srcpkgs/x13s-base/files/x13s.default | 2 ++
srcpkgs/x13s-base/template | 22 ++++++++++++++++++++
9 files changed, 67 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/files/x13s-setup
create mode 100644 srcpkgs/x13s-base/files/x13s.default
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6c586f7969f06f
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,9 @@
+case "$ACTION" in
+post)
+ # assign a random wlan and bluetooh MAC addresses with the correct OUI
+ # as the firmware doesn't support saving this
+ sed -i -e "s/:UU:VV:WW/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ etc/default/x13s
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh
new file mode 100644
index 00000000000000..a0273efbb063c3
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-bt-address.sh
@@ -0,0 +1,2 @@
+msg "Setting bluetooth MAC address..."
+/usr/libexec/x13s-setup bluetooth
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..1c50a4a2e45ea4
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/libexec/x13s-setup wlan $name"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..a24acfa3d0a06e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm "
+force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..a428eefb2016f9
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm
+ phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp)
diff --git a/srcpkgs/x13s-base/files/x13s-setup b/srcpkgs/x13s-base/files/x13s-setup
new file mode 100644
index 00000000000000..ce0872e83d8e04
--- /dev/null
+++ b/srcpkgs/x13s-base/files/x13s-setup
@@ -0,0 +1,18 @@
+#!/bin/sh
+# x13s-setup wlan <interface>
+# x13s-setup bluetooth
+
+[ -r /etc/default/x13s ] && . /etc/default/x13s
+
+case "$1" in
+wlan)
+ if [ -n "$WLAN_MAC" ] && command -v ip >/dev/null 2>&1; then
+ exec ip link set dev "$2" address "$WLAN_MAC"
+ fi
+ ;;
+bluetooth)
+ if [ -n "$BLUETOOTH_MAC" ] && command -v btmgmt >/dev/null 2>&1; then
+ exec btmgmt --index 0 public-addr "$BLUETOOTH_MAC"
+ fi
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/x13s.default b/srcpkgs/x13s-base/files/x13s.default
new file mode 100644
index 00000000000000..e54adc7013f26f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/x13s.default
@@ -0,0 +1,2 @@
+WLAN_MAC="F4:A0:0D:UU:VV:WW"
+BLUETOOTH_MAC="F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..17da5ee388cc3d
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,22 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=1
+revision=1
+archs="aarch64*"
+depends="linux-mainline>=6.8 linux-firmware-qualcomm alsa-ucm-conf"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+conf_files="/etc/default/x13s"
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 72-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/x13s-setup 755 usr/libexec
+ vinstall "${FILESDIR}"/x13s.default 644 etc/default x13s
+ # not currently working
+ # vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From d5662c2a36329167578370618fde547147fa123a Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/3] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 84 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2012 insertions(+), 25 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index c83b61e5fcbe2f..883783fc5653fe 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm64 6.8.9 Kernel Configuration
+# Linux/arm64 6.8.12 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
@@ -18,7 +18,7 @@ CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
-CONFIG_PAHOLE_VERSION=126
+CONFIG_PAHOLE_VERSION=127
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
@@ -12429,6 +12464,7 @@ CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_SIG=y
CONFIG_CRYPTO_SIG2=y
CONFIG_CRYPTO_SKCIPHER=y
CONFIG_CRYPTO_SKCIPHER2=y
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 0db68f04bb6e23..f9ff81b3d68d62 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.12
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From 385ee9011c717dad58d7524938adbd3ec98531f1 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 25 Jun 2024 19:36:18 -0400
Subject: [PATCH 3/3] linux6.9: add support for lenovo x13s
---
srcpkgs/linux6.9/files/arm64-dotconfig | 83 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.9/template | 2 +-
3 files changed, 2012 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.9/files/arm64-dotconfig b/srcpkgs/linux6.9/files/arm64-dotconfig
index cfa614ac8a6946..34050f4fe256cc 100644
--- a/srcpkgs/linux6.9/files/arm64-dotconfig
+++ b/srcpkgs/linux6.9/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.9.6 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -602,7 +602,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2379,7 +2379,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2447,7 +2447,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2503,7 +2503,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4921,7 +4922,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5150,7 +5151,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5323,7 +5324,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5341,7 +5342,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5938,12 +5939,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -6001,7 +6003,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6040,7 +6042,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6053,7 +6055,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9368,7 +9370,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10392,7 +10394,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10404,9 +10406,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_VIDEOCC_7180=m
@@ -10463,7 +10465,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10541,7 +10543,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10583,8 +10585,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10744,7 +10746,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11990,7 +11994,40 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8909 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM7150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.9/template b/srcpkgs/linux6.9/template
index c912190004f66f..0f084a538fc902 100644
--- a/srcpkgs/linux6.9/template
+++ b/srcpkgs/linux6.9/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.9'
pkgname=linux6.9
version=6.9.6
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (28 preceding siblings ...)
2024-06-28 3:27 ` classabbyamp
@ 2024-07-04 8:51 ` classabbyamp
2024-07-04 8:51 ` classabbyamp
` (4 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-07-04 8:51 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [x] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [x] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] mkinitcpio working
- https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/377
- does not load modules and/or firmware correctly
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 142229 bytes --]
From e1bbbf6686ce537c36203df399f82378fdb188b3 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/3] New package: x13s-base-1
---
srcpkgs/x13s-base/INSTALL | 9 ++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-bt-address.sh | 2 ++
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/files/x13s-setup | 18 ++++++++++++++++
srcpkgs/x13s-base/files/x13s.default | 2 ++
srcpkgs/x13s-base/template | 22 ++++++++++++++++++++
9 files changed, 67 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/files/x13s-setup
create mode 100644 srcpkgs/x13s-base/files/x13s.default
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6c586f7969f06f
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,9 @@
+case "$ACTION" in
+post)
+ # assign a random wlan and bluetooh MAC addresses with the correct OUI
+ # as the firmware doesn't support saving this
+ sed -i -e "s/:UU:VV:WW/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ etc/default/x13s
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh
new file mode 100644
index 00000000000000..a0273efbb063c3
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-bt-address.sh
@@ -0,0 +1,2 @@
+msg "Setting bluetooth MAC address..."
+/usr/libexec/x13s-setup bluetooth
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..1c50a4a2e45ea4
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/libexec/x13s-setup wlan $name"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..a24acfa3d0a06e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm "
+force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..a428eefb2016f9
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm
+ phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp)
diff --git a/srcpkgs/x13s-base/files/x13s-setup b/srcpkgs/x13s-base/files/x13s-setup
new file mode 100644
index 00000000000000..ce0872e83d8e04
--- /dev/null
+++ b/srcpkgs/x13s-base/files/x13s-setup
@@ -0,0 +1,18 @@
+#!/bin/sh
+# x13s-setup wlan <interface>
+# x13s-setup bluetooth
+
+[ -r /etc/default/x13s ] && . /etc/default/x13s
+
+case "$1" in
+wlan)
+ if [ -n "$WLAN_MAC" ] && command -v ip >/dev/null 2>&1; then
+ exec ip link set dev "$2" address "$WLAN_MAC"
+ fi
+ ;;
+bluetooth)
+ if [ -n "$BLUETOOTH_MAC" ] && command -v btmgmt >/dev/null 2>&1; then
+ exec btmgmt --index 0 public-addr "$BLUETOOTH_MAC"
+ fi
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/x13s.default b/srcpkgs/x13s-base/files/x13s.default
new file mode 100644
index 00000000000000..e54adc7013f26f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/x13s.default
@@ -0,0 +1,2 @@
+WLAN_MAC="F4:A0:0D:UU:VV:WW"
+BLUETOOTH_MAC="F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..17da5ee388cc3d
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,22 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=1
+revision=1
+archs="aarch64*"
+depends="linux-mainline>=6.8 linux-firmware-qualcomm alsa-ucm-conf"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+conf_files="/etc/default/x13s"
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 72-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/x13s-setup 755 usr/libexec
+ vinstall "${FILESDIR}"/x13s.default 644 etc/default x13s
+ # not currently working
+ # vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 385dc93f928df4a630de661780801bf5f76f95d4 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/3] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 84 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2012 insertions(+), 25 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index c83b61e5fcbe2f..883783fc5653fe 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm64 6.8.9 Kernel Configuration
+# Linux/arm64 6.8.12 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
@@ -18,7 +18,7 @@ CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
-CONFIG_PAHOLE_VERSION=126
+CONFIG_PAHOLE_VERSION=127
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
@@ -12429,6 +12464,7 @@ CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_SIG=y
CONFIG_CRYPTO_SIG2=y
CONFIG_CRYPTO_SKCIPHER=y
CONFIG_CRYPTO_SKCIPHER2=y
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 0db68f04bb6e23..f9ff81b3d68d62 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.12
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From df5e788a5a3e13789ee2173bb5c966252451babc Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 25 Jun 2024 19:36:18 -0400
Subject: [PATCH 3/3] linux6.9: add support for lenovo x13s
---
srcpkgs/linux6.9/files/arm64-dotconfig | 83 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.9/template | 2 +-
3 files changed, 2012 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.9/files/arm64-dotconfig b/srcpkgs/linux6.9/files/arm64-dotconfig
index f17c05f71ce103..70428d6dc8e2e9 100644
--- a/srcpkgs/linux6.9/files/arm64-dotconfig
+++ b/srcpkgs/linux6.9/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.9.7 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -602,7 +602,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2379,7 +2379,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2447,7 +2447,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2503,7 +2503,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4921,7 +4922,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5150,7 +5151,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5323,7 +5324,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5341,7 +5342,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5938,12 +5939,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -6001,7 +6003,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6040,7 +6042,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6053,7 +6055,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9368,7 +9370,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10392,7 +10394,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10404,9 +10406,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_VIDEOCC_7180=m
@@ -10463,7 +10465,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10541,7 +10543,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10583,8 +10585,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10744,7 +10746,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11990,7 +11994,40 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8909 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM7150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.9/template b/srcpkgs/linux6.9/template
index 23cfb055a453ba..662076d6f86470 100644
--- a/srcpkgs/linux6.9/template
+++ b/srcpkgs/linux6.9/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.9'
pkgname=linux6.9
version=6.9.7
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (29 preceding siblings ...)
2024-07-04 8:51 ` classabbyamp
@ 2024-07-04 8:51 ` classabbyamp
2024-07-05 17:50 ` classabbyamp
` (3 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-07-04 8:51 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [x] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [x] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] mkinitcpio working
- https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/377
- does not load modules and/or firmware correctly
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 142229 bytes --]
From 3a15f7add8e2d6b3e0f693a58893b9bee14bb607 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/3] New package: x13s-base-1
---
srcpkgs/x13s-base/INSTALL | 9 ++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-bt-address.sh | 2 ++
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/files/x13s-setup | 18 ++++++++++++++++
srcpkgs/x13s-base/files/x13s.default | 2 ++
srcpkgs/x13s-base/template | 22 ++++++++++++++++++++
9 files changed, 67 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/files/x13s-setup
create mode 100644 srcpkgs/x13s-base/files/x13s.default
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6c586f7969f06f
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,9 @@
+case "$ACTION" in
+post)
+ # assign a random wlan and bluetooh MAC addresses with the correct OUI
+ # as the firmware doesn't support saving this
+ sed -i -e "s/:UU:VV:WW/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ etc/default/x13s
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh
new file mode 100644
index 00000000000000..a0273efbb063c3
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-bt-address.sh
@@ -0,0 +1,2 @@
+msg "Setting bluetooth MAC address..."
+/usr/libexec/x13s-setup bluetooth
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..1c50a4a2e45ea4
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/libexec/x13s-setup wlan $name"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..a24acfa3d0a06e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm "
+force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..a428eefb2016f9
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm
+ phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp)
diff --git a/srcpkgs/x13s-base/files/x13s-setup b/srcpkgs/x13s-base/files/x13s-setup
new file mode 100644
index 00000000000000..ce0872e83d8e04
--- /dev/null
+++ b/srcpkgs/x13s-base/files/x13s-setup
@@ -0,0 +1,18 @@
+#!/bin/sh
+# x13s-setup wlan <interface>
+# x13s-setup bluetooth
+
+[ -r /etc/default/x13s ] && . /etc/default/x13s
+
+case "$1" in
+wlan)
+ if [ -n "$WLAN_MAC" ] && command -v ip >/dev/null 2>&1; then
+ exec ip link set dev "$2" address "$WLAN_MAC"
+ fi
+ ;;
+bluetooth)
+ if [ -n "$BLUETOOTH_MAC" ] && command -v btmgmt >/dev/null 2>&1; then
+ exec btmgmt --index 0 public-addr "$BLUETOOTH_MAC"
+ fi
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/x13s.default b/srcpkgs/x13s-base/files/x13s.default
new file mode 100644
index 00000000000000..e54adc7013f26f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/x13s.default
@@ -0,0 +1,2 @@
+WLAN_MAC="F4:A0:0D:UU:VV:WW"
+BLUETOOTH_MAC="F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..17da5ee388cc3d
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,22 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=1
+revision=1
+archs="aarch64*"
+depends="linux-mainline>=6.8 linux-firmware-qualcomm alsa-ucm-conf"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+conf_files="/etc/default/x13s"
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 72-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/x13s-setup 755 usr/libexec
+ vinstall "${FILESDIR}"/x13s.default 644 etc/default x13s
+ # not currently working
+ # vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 3ec5ec9d9ce3eabd609e2843b10aca29823261d3 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/3] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 84 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2012 insertions(+), 25 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index c83b61e5fcbe2f..883783fc5653fe 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm64 6.8.9 Kernel Configuration
+# Linux/arm64 6.8.12 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
@@ -18,7 +18,7 @@ CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
-CONFIG_PAHOLE_VERSION=126
+CONFIG_PAHOLE_VERSION=127
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
@@ -12429,6 +12464,7 @@ CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_SIG=y
CONFIG_CRYPTO_SIG2=y
CONFIG_CRYPTO_SKCIPHER=y
CONFIG_CRYPTO_SKCIPHER2=y
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 0db68f04bb6e23..f9ff81b3d68d62 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.12
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From 93fb65892b83d98f0f5b5f8c17c20419291926e1 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 25 Jun 2024 19:36:18 -0400
Subject: [PATCH 3/3] linux6.9: add support for lenovo x13s
---
srcpkgs/linux6.9/files/arm64-dotconfig | 83 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.9/template | 2 +-
3 files changed, 2012 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.9/files/arm64-dotconfig b/srcpkgs/linux6.9/files/arm64-dotconfig
index f17c05f71ce103..70428d6dc8e2e9 100644
--- a/srcpkgs/linux6.9/files/arm64-dotconfig
+++ b/srcpkgs/linux6.9/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.9.7 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -602,7 +602,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2379,7 +2379,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2447,7 +2447,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2503,7 +2503,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4921,7 +4922,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5150,7 +5151,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5323,7 +5324,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5341,7 +5342,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5938,12 +5939,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -6001,7 +6003,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6040,7 +6042,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6053,7 +6055,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9368,7 +9370,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10392,7 +10394,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10404,9 +10406,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_VIDEOCC_7180=m
@@ -10463,7 +10465,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10541,7 +10543,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10583,8 +10585,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10744,7 +10746,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11990,7 +11994,40 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8909 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM7150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.9/template b/srcpkgs/linux6.9/template
index 23cfb055a453ba..662076d6f86470 100644
--- a/srcpkgs/linux6.9/template
+++ b/srcpkgs/linux6.9/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.9'
pkgname=linux6.9
version=6.9.7
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (30 preceding siblings ...)
2024-07-04 8:51 ` classabbyamp
@ 2024-07-05 17:50 ` classabbyamp
2024-07-07 5:30 ` classabbyamp
` (2 subsequent siblings)
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-07-05 17:50 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [x] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [x] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] mkinitcpio working
- https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/377
- does not load modules and/or firmware correctly
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 142229 bytes --]
From cacfc30c73890a78d591602db65ae46f2a5d31e9 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 1/3] New package: x13s-base-1
---
srcpkgs/x13s-base/INSTALL | 9 ++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-bt-address.sh | 2 ++
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/files/x13s-setup | 18 ++++++++++++++++
srcpkgs/x13s-base/files/x13s.default | 2 ++
srcpkgs/x13s-base/template | 22 ++++++++++++++++++++
9 files changed, 67 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/files/x13s-setup
create mode 100644 srcpkgs/x13s-base/files/x13s.default
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6c586f7969f06f
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,9 @@
+case "$ACTION" in
+post)
+ # assign a random wlan and bluetooh MAC addresses with the correct OUI
+ # as the firmware doesn't support saving this
+ sed -i -e "s/:UU:VV:WW/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ etc/default/x13s
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh
new file mode 100644
index 00000000000000..a0273efbb063c3
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-bt-address.sh
@@ -0,0 +1,2 @@
+msg "Setting bluetooth MAC address..."
+/usr/libexec/x13s-setup bluetooth
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..1c50a4a2e45ea4
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/libexec/x13s-setup wlan $name"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..a24acfa3d0a06e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm "
+force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..a428eefb2016f9
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm
+ phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp)
diff --git a/srcpkgs/x13s-base/files/x13s-setup b/srcpkgs/x13s-base/files/x13s-setup
new file mode 100644
index 00000000000000..ce0872e83d8e04
--- /dev/null
+++ b/srcpkgs/x13s-base/files/x13s-setup
@@ -0,0 +1,18 @@
+#!/bin/sh
+# x13s-setup wlan <interface>
+# x13s-setup bluetooth
+
+[ -r /etc/default/x13s ] && . /etc/default/x13s
+
+case "$1" in
+wlan)
+ if [ -n "$WLAN_MAC" ] && command -v ip >/dev/null 2>&1; then
+ exec ip link set dev "$2" address "$WLAN_MAC"
+ fi
+ ;;
+bluetooth)
+ if [ -n "$BLUETOOTH_MAC" ] && command -v btmgmt >/dev/null 2>&1; then
+ exec btmgmt --index 0 public-addr "$BLUETOOTH_MAC"
+ fi
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/x13s.default b/srcpkgs/x13s-base/files/x13s.default
new file mode 100644
index 00000000000000..e54adc7013f26f
--- /dev/null
+++ b/srcpkgs/x13s-base/files/x13s.default
@@ -0,0 +1,2 @@
+WLAN_MAC="F4:A0:0D:UU:VV:WW"
+BLUETOOTH_MAC="F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..17da5ee388cc3d
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,22 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=1
+revision=1
+archs="aarch64*"
+depends="linux-mainline>=6.8 linux-firmware-qualcomm alsa-ucm-conf"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+conf_files="/etc/default/x13s"
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 72-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/x13s-setup 755 usr/libexec
+ vinstall "${FILESDIR}"/x13s.default 644 etc/default x13s
+ # not currently working
+ # vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
From 21fdefac377cd18d37ad01dd64ff3f5aed41d15d Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 2/3] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 84 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2012 insertions(+), 25 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index c83b61e5fcbe2f..883783fc5653fe 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm64 6.8.9 Kernel Configuration
+# Linux/arm64 6.8.12 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
@@ -18,7 +18,7 @@ CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
-CONFIG_PAHOLE_VERSION=126
+CONFIG_PAHOLE_VERSION=127
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
@@ -12429,6 +12464,7 @@ CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_SIG=y
CONFIG_CRYPTO_SIG2=y
CONFIG_CRYPTO_SKCIPHER=y
CONFIG_CRYPTO_SKCIPHER2=y
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 0db68f04bb6e23..f9ff81b3d68d62 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.12
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From f227d03c028f8911183fb0a1efcb08b817e487e5 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 25 Jun 2024 19:36:18 -0400
Subject: [PATCH 3/3] linux6.9: add support for lenovo x13s
---
srcpkgs/linux6.9/files/arm64-dotconfig | 83 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.9/template | 2 +-
3 files changed, 2012 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.9/files/arm64-dotconfig b/srcpkgs/linux6.9/files/arm64-dotconfig
index f17c05f71ce103..70428d6dc8e2e9 100644
--- a/srcpkgs/linux6.9/files/arm64-dotconfig
+++ b/srcpkgs/linux6.9/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.9.7 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -602,7 +602,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2379,7 +2379,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2447,7 +2447,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2503,7 +2503,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4921,7 +4922,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5150,7 +5151,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5323,7 +5324,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5341,7 +5342,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5938,12 +5939,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -6001,7 +6003,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6040,7 +6042,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6053,7 +6055,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9368,7 +9370,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10392,7 +10394,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10404,9 +10406,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_VIDEOCC_7180=m
@@ -10463,7 +10465,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10541,7 +10543,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10583,8 +10585,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10744,7 +10746,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11990,7 +11994,40 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8909 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM7150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.9/template b/srcpkgs/linux6.9/template
index 48d279faa64c53..a107ed8f6b53b1 100644
--- a/srcpkgs/linux6.9/template
+++ b/srcpkgs/linux6.9/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.9'
pkgname=linux6.9
version=6.9.8
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (31 preceding siblings ...)
2024-07-05 17:50 ` classabbyamp
@ 2024-07-07 5:30 ` classabbyamp
2024-07-07 5:31 ` classabbyamp
2024-07-07 5:32 ` [PR PATCH] [Merged]: " classabbyamp
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-07-07 5:30 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [x] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [x] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] mkinitcpio working
- https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/377
- does not load modules and/or firmware correctly
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 142544 bytes --]
From 12f620238a430e8ae2eb5645d10f8d4f76ce385a Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 1/3] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 84 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2012 insertions(+), 25 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index c83b61e5fcbe2f..883783fc5653fe 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm64 6.8.9 Kernel Configuration
+# Linux/arm64 6.8.12 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
@@ -18,7 +18,7 @@ CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
-CONFIG_PAHOLE_VERSION=126
+CONFIG_PAHOLE_VERSION=127
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
@@ -12429,6 +12464,7 @@ CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_SIG=y
CONFIG_CRYPTO_SIG2=y
CONFIG_CRYPTO_SKCIPHER=y
CONFIG_CRYPTO_SKCIPHER2=y
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 0db68f04bb6e23..f9ff81b3d68d62 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.12
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From 268d4144379d51a34b924f01e687ed4f72c87f39 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 25 Jun 2024 19:36:18 -0400
Subject: [PATCH 2/3] linux6.9: add support for lenovo x13s
---
srcpkgs/linux6.9/files/arm64-dotconfig | 83 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.9/template | 2 +-
3 files changed, 2012 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.9/files/arm64-dotconfig b/srcpkgs/linux6.9/files/arm64-dotconfig
index f17c05f71ce103..70428d6dc8e2e9 100644
--- a/srcpkgs/linux6.9/files/arm64-dotconfig
+++ b/srcpkgs/linux6.9/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.9.7 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -602,7 +602,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2379,7 +2379,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2447,7 +2447,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2503,7 +2503,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4921,7 +4922,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5150,7 +5151,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5323,7 +5324,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5341,7 +5342,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5938,12 +5939,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -6001,7 +6003,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6040,7 +6042,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6053,7 +6055,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9368,7 +9370,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10392,7 +10394,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10404,9 +10406,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_VIDEOCC_7180=m
@@ -10463,7 +10465,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10541,7 +10543,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10583,8 +10585,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10744,7 +10746,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11990,7 +11994,40 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8909 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM7150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.9/template b/srcpkgs/linux6.9/template
index 48d279faa64c53..a107ed8f6b53b1 100644
--- a/srcpkgs/linux6.9/template
+++ b/srcpkgs/linux6.9/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.9'
pkgname=linux6.9
version=6.9.8
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From de2210b842a1befd296be107bfdcb1d39902f49d Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 3/3] New package: x13s-base-1
---
srcpkgs/x13s-base/INSTALL | 9 ++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-bt-address.sh | 2 ++
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/files/x13s-setup | 18 ++++++++++++++++
srcpkgs/x13s-base/files/x13s.default | 7 +++++++
srcpkgs/x13s-base/template | 22 ++++++++++++++++++++
9 files changed, 72 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/files/x13s-setup
create mode 100644 srcpkgs/x13s-base/files/x13s.default
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..6c586f7969f06f
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,9 @@
+case "$ACTION" in
+post)
+ # assign a random wlan and bluetooh MAC addresses with the correct OUI
+ # as the firmware doesn't support saving this
+ sed -i -e "s/:UU:VV:WW/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ etc/default/x13s
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh
new file mode 100644
index 00000000000000..a0273efbb063c3
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-bt-address.sh
@@ -0,0 +1,2 @@
+msg "Setting bluetooth MAC address..."
+/usr/libexec/x13s-setup bluetooth
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..1c50a4a2e45ea4
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/libexec/x13s-setup wlan $name"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..a24acfa3d0a06e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm "
+force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..a428eefb2016f9
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm
+ phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp)
diff --git a/srcpkgs/x13s-base/files/x13s-setup b/srcpkgs/x13s-base/files/x13s-setup
new file mode 100644
index 00000000000000..ce0872e83d8e04
--- /dev/null
+++ b/srcpkgs/x13s-base/files/x13s-setup
@@ -0,0 +1,18 @@
+#!/bin/sh
+# x13s-setup wlan <interface>
+# x13s-setup bluetooth
+
+[ -r /etc/default/x13s ] && . /etc/default/x13s
+
+case "$1" in
+wlan)
+ if [ -n "$WLAN_MAC" ] && command -v ip >/dev/null 2>&1; then
+ exec ip link set dev "$2" address "$WLAN_MAC"
+ fi
+ ;;
+bluetooth)
+ if [ -n "$BLUETOOTH_MAC" ] && command -v btmgmt >/dev/null 2>&1; then
+ exec btmgmt --index 0 public-addr "$BLUETOOTH_MAC"
+ fi
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/x13s.default b/srcpkgs/x13s-base/files/x13s.default
new file mode 100644
index 00000000000000..1350a65c7b696d
--- /dev/null
+++ b/srcpkgs/x13s-base/files/x13s.default
@@ -0,0 +1,7 @@
+# the X13s' wlan and bluetooth firmware/hardware do not support
+# storing their default MAC address, so it must be set on boot
+# by default, these are set to a random MAC address with the
+# correct vendor prefix (OUI) of F4:A0:0D. These MAC addresses
+# can also be assigned manually by editing this file.
+WLAN_MAC="F4:A0:0D:UU:VV:WW"
+BLUETOOTH_MAC="F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..17da5ee388cc3d
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,22 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=1
+revision=1
+archs="aarch64*"
+depends="linux-mainline>=6.8 linux-firmware-qualcomm alsa-ucm-conf"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+conf_files="/etc/default/x13s"
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 72-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/x13s-setup 755 usr/libexec
+ vinstall "${FILESDIR}"/x13s.default 644 etc/default x13s
+ # not currently working
+ # vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Updated] Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (32 preceding siblings ...)
2024-07-07 5:30 ` classabbyamp
@ 2024-07-07 5:31 ` classabbyamp
2024-07-07 5:32 ` [PR PATCH] [Merged]: " classabbyamp
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-07-07 5:31 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1459 bytes --]
There is an updated pull request by classabbyamp against master on the void-packages repository
https://github.com/classabbyamp/void-packages x13s-support
https://github.com/void-linux/void-packages/pull/49615
Lenovo X13s support
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [x] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [x] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] mkinitcpio working
- https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/377
- does not load modules and/or firmware correctly
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
A patch file from https://github.com/void-linux/void-packages/pull/49615.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-x13s-support-49615.patch --]
[-- Type: text/x-diff, Size: 142545 bytes --]
From 12f620238a430e8ae2eb5645d10f8d4f76ce385a Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:01:30 -0400
Subject: [PATCH 1/3] linux6.8: add support for lenovo x13s
---
srcpkgs/linux6.8/files/arm64-dotconfig | 84 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.8/template | 2 +-
3 files changed, 2012 insertions(+), 25 deletions(-)
create mode 100644 srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.8/files/arm64-dotconfig b/srcpkgs/linux6.8/files/arm64-dotconfig
index c83b61e5fcbe2f..883783fc5653fe 100644
--- a/srcpkgs/linux6.8/files/arm64-dotconfig
+++ b/srcpkgs/linux6.8/files/arm64-dotconfig
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/arm64 6.8.9 Kernel Configuration
+# Linux/arm64 6.8.12 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
@@ -18,7 +18,7 @@ CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
-CONFIG_PAHOLE_VERSION=126
+CONFIG_PAHOLE_VERSION=127
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -596,7 +596,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2369,7 +2369,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2437,7 +2437,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2493,7 +2493,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4904,7 +4905,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5133,7 +5134,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5304,7 +5305,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5322,7 +5323,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5911,12 +5912,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -5974,7 +5976,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6012,7 +6014,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6025,7 +6027,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9325,7 +9327,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10344,7 +10346,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10356,9 +10358,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_MSS_7180=m
@@ -10416,7 +10418,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10494,7 +10496,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10536,8 +10538,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10695,7 +10697,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11927,7 +11931,38 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
@@ -12429,6 +12464,7 @@ CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_SIG=y
CONFIG_CRYPTO_SIG2=y
CONFIG_CRYPTO_SKCIPHER=y
CONFIG_CRYPTO_SKCIPHER2=y
diff --git a/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.8/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.8/template b/srcpkgs/linux6.8/template
index 0db68f04bb6e23..f9ff81b3d68d62 100644
--- a/srcpkgs/linux6.8/template
+++ b/srcpkgs/linux6.8/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.8'
pkgname=linux6.8
version=6.8.12
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From 268d4144379d51a34b924f01e687ed4f72c87f39 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Tue, 25 Jun 2024 19:36:18 -0400
Subject: [PATCH 2/3] linux6.9: add support for lenovo x13s
---
srcpkgs/linux6.9/files/arm64-dotconfig | 83 +-
...d-in-kernel-pd-mapper-implementation.patch | 1951 +++++++++++++++++
srcpkgs/linux6.9/template | 2 +-
3 files changed, 2012 insertions(+), 24 deletions(-)
create mode 100644 srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
diff --git a/srcpkgs/linux6.9/files/arm64-dotconfig b/srcpkgs/linux6.9/files/arm64-dotconfig
index f17c05f71ce103..70428d6dc8e2e9 100644
--- a/srcpkgs/linux6.9/files/arm64-dotconfig
+++ b/srcpkgs/linux6.9/files/arm64-dotconfig
@@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.9.7 Kernel Configuration
#
-CONFIG_CC_VERSION_TEXT="aarch64-linux-musl-gcc (GCC) 13.2.0"
+CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (GCC) 13.2.0"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130200
CONFIG_CLANG_VERSION=0
@@ -29,7 +29,7 @@ CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
-CONFIG_LOCALVERSION="_1"
+CONFIG_LOCALVERSION="_2"
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_BUILD_SALT=""
CONFIG_DEFAULT_INIT=""
@@ -602,7 +602,7 @@ CONFIG_DPM_WATCHDOG=y
CONFIG_DPM_WATCHDOG_TIMEOUT=60
CONFIG_PM_CLK=y
CONFIG_PM_GENERIC_DOMAINS=y
-# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
CONFIG_PM_GENERIC_DOMAINS_SLEEP=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_CPU_PM=y
@@ -2379,7 +2379,7 @@ CONFIG_SOC_BUS=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_SPI=y
-CONFIG_REGMAP_SPMI=m
+CONFIG_REGMAP_SPMI=y
CONFIG_REGMAP_W1=m
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
@@ -2447,7 +2447,7 @@ CONFIG_ARM_SCMI_TRANSPORT_VIRTIO_VERSION1_COMPLIANCE=y
CONFIG_ARM_SCMI_POWER_CONTROL=m
# end of ARM System Control and Management Interface Protocol
-CONFIG_ARM_SCPI_PROTOCOL=m
+CONFIG_ARM_SCPI_PROTOCOL=y
CONFIG_ARM_SDE_INTERFACE=y
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_DMIID=y
@@ -2503,7 +2503,8 @@ CONFIG_ARM_PSCI_FW=y
#
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
-# CONFIG_QCOM_QSEECOM is not set
+CONFIG_QCOM_QSEECOM=y
+CONFIG_QCOM_QSEECOM_UEFISECAPP=y
# end of Qualcomm firmware drivers
CONFIG_HAVE_ARM_SMCCC=y
@@ -4921,7 +4922,7 @@ CONFIG_XILLYUSB=m
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
-# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=m
@@ -5150,7 +5151,7 @@ CONFIG_SPI_SLAVE=y
CONFIG_SPI_SLAVE_TIME=m
CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
CONFIG_SPI_DYNAMIC=y
-CONFIG_SPMI=m
+CONFIG_SPMI=y
CONFIG_SPMI_HISI3670=m
CONFIG_SPMI_MSM_PMIC_ARB=m
CONFIG_SPMI_MTK_PMIF=m
@@ -5323,7 +5324,7 @@ CONFIG_PINCTRL_SA8775P=m
CONFIG_PINCTRL_SC7180=m
CONFIG_PINCTRL_SC7280=m
CONFIG_PINCTRL_SC8180X=m
-CONFIG_PINCTRL_SC8280XP=m
+CONFIG_PINCTRL_SC8280XP=y
# CONFIG_PINCTRL_SDM660 is not set
CONFIG_PINCTRL_SDM670=m
CONFIG_PINCTRL_SDM845=m
@@ -5341,7 +5342,7 @@ CONFIG_PINCTRL_SM8450=m
CONFIG_PINCTRL_SM8550=m
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 is not set
-CONFIG_PINCTRL_QCOM_SPMI_PMIC=m
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=m
CONFIG_PINCTRL_LPASS_LPI=m
# CONFIG_PINCTRL_SC7280_LPASS_LPI is not set
@@ -5938,12 +5939,13 @@ CONFIG_THERMAL_OF=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_DEFAULT_GOV_BANG_BANG is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
CONFIG_THERMAL_GOV_USER_SPACE=y
-# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_FREQ_THERMAL=y
# CONFIG_CPU_IDLE_THERMAL is not set
@@ -6001,7 +6003,7 @@ CONFIG_GENERIC_ADC_THERMAL=m
#
CONFIG_QCOM_TSENS=m
CONFIG_QCOM_SPMI_ADC_TM5=m
-# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
+CONFIG_QCOM_SPMI_TEMP_ALARM=m
CONFIG_QCOM_LMH=m
# end of Qualcomm thermal drivers
@@ -6040,7 +6042,7 @@ CONFIG_XILINX_WATCHDOG=m
CONFIG_ZIIRAVE_WATCHDOG=m
CONFIG_MLX_WDT=m
CONFIG_SL28CPLD_WATCHDOG=m
-# CONFIG_ARM_SP805_WATCHDOG is not set
+CONFIG_ARM_SP805_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=m
CONFIG_ARMADA_37XX_WATCHDOG=m
CONFIG_CADENCE_WATCHDOG=m
@@ -6053,7 +6055,7 @@ CONFIG_IMX2_WDT=m
CONFIG_IMX_SC_WDT=m
CONFIG_IMX7ULP_WDT=m
CONFIG_TEGRA_WATCHDOG=m
-# CONFIG_QCOM_WDT is not set
+CONFIG_QCOM_WDT=m
CONFIG_MESON_GXBB_WATCHDOG=m
CONFIG_MESON_WATCHDOG=m
CONFIG_MEDIATEK_WATCHDOG=m
@@ -9368,7 +9370,7 @@ CONFIG_SCSI_UFSHCD_PCI=m
CONFIG_SCSI_UFSHCD_PLATFORM=m
CONFIG_SCSI_UFS_CDNS_PLATFORM=m
# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set
-# CONFIG_SCSI_UFS_QCOM is not set
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_SCSI_UFS_MEDIATEK=m
CONFIG_SCSI_UFS_HISI=m
CONFIG_SCSI_UFS_EXYNOS=m
@@ -10392,7 +10394,7 @@ CONFIG_QCM_GCC_2290=m
CONFIG_QCS_GCC_404=m
CONFIG_SC_CAMCC_7180=m
CONFIG_SC_CAMCC_7280=m
-# CONFIG_SC_CAMCC_8280XP is not set
+CONFIG_SC_CAMCC_8280XP=m
CONFIG_SC_DISPCC_7180=m
CONFIG_SC_DISPCC_7280=m
CONFIG_SC_DISPCC_8280XP=m
@@ -10404,9 +10406,9 @@ CONFIG_SC_GCC_8180X=m
CONFIG_SC_GCC_8280XP=m
CONFIG_SC_GPUCC_7180=m
CONFIG_SC_GPUCC_7280=m
-# CONFIG_SC_GPUCC_8280XP is not set
+CONFIG_SC_GPUCC_8280XP=m
CONFIG_SC_LPASSCC_7280=m
-# CONFIG_SC_LPASSCC_8280XP is not set
+CONFIG_SC_LPASSCC_8280XP=m
CONFIG_SC_LPASS_CORECC_7180=m
CONFIG_SC_LPASS_CORECC_7280=m
CONFIG_SC_VIDEOCC_7180=m
@@ -10463,7 +10465,7 @@ CONFIG_SM_TCSRCC_8550=m
# CONFIG_SM_TCSRCC_8650 is not set
CONFIG_SM_VIDEOCC_8150=m
CONFIG_SM_VIDEOCC_8250=m
-# CONFIG_SM_VIDEOCC_8350 is not set
+CONFIG_SM_VIDEOCC_8350=m
# CONFIG_SM_VIDEOCC_8550 is not set
CONFIG_SPMI_PMIC_CLKDIV=m
CONFIG_QCOM_HFPLL=m
@@ -10541,7 +10543,7 @@ CONFIG_TIMER_IMX_SYS_CTR=y
# end of Clock Source drivers
CONFIG_MAILBOX=y
-# CONFIG_ARM_MHU is not set
+CONFIG_ARM_MHU=y
CONFIG_ARM_MHU_V2=m
CONFIG_IMX_MBOX=m
CONFIG_PLATFORM_MHU=m
@@ -10583,8 +10585,8 @@ CONFIG_IOMMU_IO_PGTABLE_DART=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_STRICT is not set
-# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
-CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y
+CONFIG_IOMMU_DEFAULT_DMA_LAZY=y
+# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_OF_IOMMU=y
CONFIG_IOMMU_DMA=y
CONFIG_IOMMU_SVA=y
@@ -10744,7 +10746,9 @@ CONFIG_QCOM_LLCC=m
CONFIG_QCOM_KRYO_L2_ACCESSORS=y
CONFIG_QCOM_MDT_LOADER=m
CONFIG_QCOM_OCMEM=m
+CONFIG_QCOM_PD_MAPPER=m
CONFIG_QCOM_PDR_HELPERS=m
+CONFIG_QCOM_PDR_MSG=m
# CONFIG_QCOM_PMIC_PDCHARGER_ULOG is not set
CONFIG_QCOM_PMIC_GLINK=m
CONFIG_QCOM_QMI_HELPERS=m
@@ -11990,7 +11994,40 @@ CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
CONFIG_INTERCONNECT_IMX8MP=m
-# CONFIG_INTERCONNECT_QCOM is not set
+CONFIG_INTERCONNECT_QCOM=y
+CONFIG_INTERCONNECT_QCOM_BCM_VOTER=y
+# CONFIG_INTERCONNECT_QCOM_MSM8909 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8916 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8939 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8974 is not set
+# CONFIG_INTERCONNECT_QCOM_MSM8996 is not set
+CONFIG_INTERCONNECT_QCOM_OSM_L3=m
+# CONFIG_INTERCONNECT_QCOM_QCM2290 is not set
+# CONFIG_INTERCONNECT_QCOM_QCS404 is not set
+# CONFIG_INTERCONNECT_QCOM_QDU1000 is not set
+CONFIG_INTERCONNECT_QCOM_RPMH_POSSIBLE=y
+CONFIG_INTERCONNECT_QCOM_RPMH=y
+# CONFIG_INTERCONNECT_QCOM_SA8775P is not set
+# CONFIG_INTERCONNECT_QCOM_SC7180 is not set
+# CONFIG_INTERCONNECT_QCOM_SC7280 is not set
+# CONFIG_INTERCONNECT_QCOM_SC8180X is not set
+CONFIG_INTERCONNECT_QCOM_SC8280XP=y
+# CONFIG_INTERCONNECT_QCOM_SDM660 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM670 is not set
+# CONFIG_INTERCONNECT_QCOM_SDM845 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX55 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX65 is not set
+# CONFIG_INTERCONNECT_QCOM_SDX75 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6115 is not set
+# CONFIG_INTERCONNECT_QCOM_SM6350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM7150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8150 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8250 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8350 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8450 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8550 is not set
+# CONFIG_INTERCONNECT_QCOM_SM8650 is not set
+# CONFIG_INTERCONNECT_QCOM_X1E80100 is not set
CONFIG_INTERCONNECT_SAMSUNG=y
CONFIG_INTERCONNECT_EXYNOS=m
CONFIG_INTERCONNECT_CLK=m
diff --git a/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
new file mode 100644
index 00000000000000..794ac2f2d77f92
--- /dev/null
+++ b/srcpkgs/linux6.9/patches/soc-qcom-add-in-kernel-pd-mapper-implementation.patch
@@ -0,0 +1,1951 @@
+https://patchwork.kernel.org/project/linux-arm-msm/cover/20240622-qcom-pd-mapper-v9-0-a84ee3591c8e@linaro.org/
+
+accepted upstream, expected mainline in 6.11
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:40 +0300
+Subject: [PATCH v9 1/5] soc: qcom: pdr: protect locator_addr with the main
+ mutex
+
+If the service locator server is restarted fast enough, the PDR can
+rewrite locator_addr fields concurrently. Protect them by placing
+modification of those fields under the main pdr->lock.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+---
+ drivers/soc/qcom/pdr_interface.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index a1b6a4081dea..76a62c2ecc58 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -76,12 +76,12 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
+ locator_hdl);
+ struct pdr_service *pds;
+
++ mutex_lock(&pdr->lock);
+ /* Create a local client port for QMI communication */
+ pdr->locator_addr.sq_family = AF_QIPCRTR;
+ pdr->locator_addr.sq_node = svc->node;
+ pdr->locator_addr.sq_port = svc->port;
+
+- mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = true;
+ mutex_unlock(&pdr->lock);
+
+@@ -104,10 +104,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
+
+ mutex_lock(&pdr->lock);
+ pdr->locator_init_complete = false;
+- mutex_unlock(&pdr->lock);
+
+ pdr->locator_addr.sq_node = 0;
+ pdr->locator_addr.sq_port = 0;
++ mutex_unlock(&pdr->lock);
+ }
+
+ static const struct qmi_ops pdr_locator_ops = {
+@@ -365,12 +365,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
+ if (ret < 0)
+ return ret;
+
++ mutex_lock(&pdr->lock);
+ ret = qmi_send_request(&pdr->locator_hdl,
+ &pdr->locator_addr,
+ &txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ servreg_get_domain_list_req_ei,
+ req);
++ mutex_unlock(&pdr->lock);
+ if (ret < 0) {
+ qmi_txn_cancel(&txn);
+ return ret;
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:41 +0300
+Subject: [PATCH v9 2/5] soc: qcom: pdr: fix parsing of domains lists
+
+While parsing the domains list, start offsets from 0 rather than from
+domains_read. The domains_read is equal to the total count of the
+domains we have seen, while the domains list in the message starts from
+offset 0.
+
+Fixes: fbe639b44a82 ("soc: qcom: Introduce Protection Domain Restart helpers")
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/pdr_interface.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
+index 76a62c2ecc58..216166e98fae 100644
+--- a/drivers/soc/qcom/pdr_interface.c
++++ b/drivers/soc/qcom/pdr_interface.c
+@@ -417,7 +417,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
+ if (ret < 0)
+ goto out;
+
+- for (i = domains_read; i < resp->domain_list_len; i++) {
++ for (i = 0; i < resp->domain_list_len; i++) {
+ entry = &resp->domain_list[i];
+
+ if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:42 +0300
+Subject: [PATCH v9 3/5] soc: qcom: pdr: extract PDR message marshalling
+ data
+
+The in-kernel PD mapper is going to use same message structures as the
+QCOM_PDR_HELPERS module. Extract message marshalling data to separate
+module that can be used by both PDR helpers and by PD mapper.
+
+Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 4 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 306 ++------------------------------------
+ drivers/soc/qcom/qcom_pdr_msg.c | 319 ++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 334 insertions(+), 296 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 5af33b0e3470..95973c6b828f 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -75,8 +75,12 @@ config QCOM_OCMEM
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
++ select QCOM_PDR_MSG
+ depends on NET
+
++config QCOM_PDR_MSG
++ tristate
++
+ config QCOM_PMIC_PDCHARGER_ULOG
+ tristate "Qualcomm PMIC PDCharger ULOG driver"
+ depends on RPMSG
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index ca0bece0dfff..3110ac3288bc 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
++obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
+ obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 03c282b7f17e..7e5bb5a95275 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -28,83 +28,12 @@ struct servreg_location_entry {
+ u32 instance;
+ };
+
+-static const struct qmi_elem_info servreg_location_entry_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- name),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- instance),
+- },
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0,
+- .offset = offsetof(struct servreg_location_entry,
+- service_data),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_req {
+ char service_name[SERVREG_NAME_LENGTH + 1];
+ u8 domain_offset_valid;
+ u32 domain_offset;
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- service_name),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_4_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_req,
+- domain_offset),
+- },
+- {}
+-};
+-
+ struct servreg_get_domain_list_resp {
+ struct qmi_response_type_v01 resp;
+ u8 total_domains_valid;
+@@ -116,264 +45,49 @@ struct servreg_get_domain_list_resp {
+ struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
+ };
+
+-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- total_domains),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count_valid),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x11,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- db_rev_count),
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_valid),
+- },
+- {
+- .data_type = QMI_DATA_LEN,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list_len),
+- },
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+- .elem_size = sizeof(struct servreg_location_entry),
+- .array_type = VAR_LEN_ARRAY,
+- .tlv_type = 0x12,
+- .offset = offsetof(struct servreg_get_domain_list_resp,
+- domain_list),
+- .ei_array = servreg_location_entry_ei,
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_req {
+ u8 enable;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+- {
+- .data_type = QMI_UNSIGNED_1_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_register_listener_req,
+- enable),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_register_listener_resp {
+ struct qmi_response_type_v01 resp;
+ u8 curr_state_valid;
+ enum servreg_service_state curr_state;
+ };
+
+-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {
+- .data_type = QMI_OPT_FLAG,
+- .elem_len = 1,
+- .elem_size = sizeof(u8),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state_valid),
+- },
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(enum servreg_service_state),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x10,
+- .offset = offsetof(struct servreg_register_listener_resp,
+- curr_state),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_restart_pd_req,
+- service_path),
+- },
+- {}
+-};
+-
+ struct servreg_restart_pd_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_restart_pd_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
+-
+ struct servreg_state_updated_ind {
+ enum servreg_service_state curr_state;
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+- {
+- .data_type = QMI_SIGNED_4_BYTE_ENUM,
+- .elem_len = 1,
+- .elem_size = sizeof(u32),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- curr_state),
+- },
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x03,
+- .offset = offsetof(struct servreg_state_updated_ind,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_req {
+ char service_path[SERVREG_NAME_LENGTH + 1];
+ u16 transaction_id;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+- {
+- .data_type = QMI_STRING,
+- .elem_len = SERVREG_NAME_LENGTH + 1,
+- .elem_size = sizeof(char),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x01,
+- .offset = offsetof(struct servreg_set_ack_req,
+- service_path),
+- },
+- {
+- .data_type = QMI_UNSIGNED_2_BYTE,
+- .elem_len = 1,
+- .elem_size = sizeof(u16),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_req,
+- transaction_id),
+- },
+- {}
+-};
+-
+ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
+-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+- {
+- .data_type = QMI_STRUCT,
+- .elem_len = 1,
+- .elem_size = sizeof(struct qmi_response_type_v01),
+- .array_type = NO_ARRAY,
+- .tlv_type = 0x02,
+- .offset = offsetof(struct servreg_set_ack_resp,
+- resp),
+- .ei_array = qmi_response_type_v01_ei,
+- },
+- {}
+-};
++extern const struct qmi_elem_info servreg_location_entry_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
++extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
++extern const struct qmi_elem_info servreg_register_listener_req_ei[];
++extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
++extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
++extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
++extern const struct qmi_elem_info servreg_set_ack_req_ei[];
++extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+new file mode 100644
+index 000000000000..9b46f42aa146
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -0,0 +1,319 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/module.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++const struct qmi_elem_info servreg_location_entry_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ name),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ instance),
++ },
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0,
++ .offset = offsetof(struct servreg_location_entry,
++ service_data),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_location_entry_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ service_name),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_4_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_req,
++ domain_offset),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
++
++const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ total_domains),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count_valid),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x11,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ db_rev_count),
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_valid),
++ },
++ {
++ .data_type = QMI_DATA_LEN,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list_len),
++ },
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
++ .elem_size = sizeof(struct servreg_location_entry),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x12,
++ .offset = offsetof(struct servreg_get_domain_list_resp,
++ domain_list),
++ .ei_array = servreg_location_entry_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
++
++const struct qmi_elem_info servreg_register_listener_req_ei[] = {
++ {
++ .data_type = QMI_UNSIGNED_1_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_register_listener_req,
++ enable),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
++
++const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {
++ .data_type = QMI_OPT_FLAG,
++ .elem_len = 1,
++ .elem_size = sizeof(u8),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state_valid),
++ },
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(enum servreg_service_state),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x10,
++ .offset = offsetof(struct servreg_register_listener_resp,
++ curr_state),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
++
++const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_restart_pd_req,
++ service_path),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
++
++const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_restart_pd_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
++
++const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
++ {
++ .data_type = QMI_SIGNED_4_BYTE_ENUM,
++ .elem_len = 1,
++ .elem_size = sizeof(u32),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ curr_state),
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x03,
++ .offset = offsetof(struct servreg_state_updated_ind,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
++
++const struct qmi_elem_info servreg_set_ack_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_set_ack_req,
++ service_path),
++ },
++ {
++ .data_type = QMI_UNSIGNED_2_BYTE,
++ .elem_len = 1,
++ .elem_size = sizeof(u16),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_req,
++ transaction_id),
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
++
++const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof(struct qmi_response_type_v01),
++ .array_type = NO_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_set_ack_resp,
++ resp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:43 +0300
+Subject: [PATCH v9 4/5] soc: qcom: add pd-mapper implementation
+
+Existing userspace protection domain mapper implementation has several
+issue. It doesn't play well with CONFIG_EXTRA_FIRMWARE, it doesn't
+reread JSON files if firmware location is changed (or if firmware was
+not available at the time pd-mapper was started but the corresponding
+directory is mounted later), etc.
+
+Provide in-kernel service implementing protection domain mapping
+required to work with several services, which are provided by the DSP
+firmware.
+
+This module is loaded automatically by the remoteproc drivers when
+necessary via the symbol dependency. It uses a root node to match a
+protection domains map for a particular board. It is not possible to
+implement it as a 'driver' as there is no corresponding device.
+
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Alexey Minnekhanov <alexeymin@postmarketos.org>
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/soc/qcom/Kconfig | 11 +
+ drivers/soc/qcom/Makefile | 1 +
+ drivers/soc/qcom/pdr_internal.h | 14 +
+ drivers/soc/qcom/qcom_pd_mapper.c | 676 ++++++++++++++++++++++++++++++++++++++
+ drivers/soc/qcom/qcom_pdr_msg.c | 34 ++
+ 5 files changed, 736 insertions(+)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index 95973c6b828f..0a2f2bfd7863 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -72,6 +72,17 @@ config QCOM_OCMEM
+ requirements. This is typically used by the GPU, camera/video, and
+ audio components on some Snapdragon SoCs.
+
++config QCOM_PD_MAPPER
++ tristate "Qualcomm Protection Domain Mapper"
++ select QCOM_QMI_HELPERS
++ depends on NET && QRTR
++ default QCOM_RPROC_COMMON
++ help
++ The Protection Domain Mapper maps registered services to the domains
++ and instances handled by the remote DSPs. This is a kernel-space
++ implementation of the service. It is a simpler alternative to the
++ userspace daemon.
++
+ config QCOM_PDR_HELPERS
+ tristate
+ select QCOM_QMI_HELPERS
+diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
+index 3110ac3288bc..d3560f861085 100644
+--- a/drivers/soc/qcom/Makefile
++++ b/drivers/soc/qcom/Makefile
+@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+ obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
+ obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
++obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
+ obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+ obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
+ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
+diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
+index 7e5bb5a95275..8d17f7fb79e7 100644
+--- a/drivers/soc/qcom/pdr_internal.h
++++ b/drivers/soc/qcom/pdr_internal.h
+@@ -13,6 +13,8 @@
+ #define SERVREG_SET_ACK_REQ 0x23
+ #define SERVREG_RESTART_PD_REQ 0x24
+
++#define SERVREG_LOC_PFR_REQ 0x24
++
+ #define SERVREG_DOMAIN_LIST_LENGTH 32
+ #define SERVREG_RESTART_PD_REQ_MAX_LEN 67
+ #define SERVREG_REGISTER_LISTENER_REQ_LEN 71
+@@ -20,6 +22,7 @@
+ #define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
+ #define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
+ #define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
++#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
+
+ struct servreg_location_entry {
+ char name[SERVREG_NAME_LENGTH + 1];
+@@ -79,6 +82,15 @@ struct servreg_set_ack_resp {
+ struct qmi_response_type_v01 resp;
+ };
+
++struct servreg_loc_pfr_req {
++ char service[SERVREG_NAME_LENGTH + 1];
++ char reason[257];
++};
++
++struct servreg_loc_pfr_resp {
++ struct qmi_response_type_v01 rsp;
++};
++
+ extern const struct qmi_elem_info servreg_location_entry_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+ extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+@@ -89,5 +101,7 @@ extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+ extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+ extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
++extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
+ #endif
+diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
+new file mode 100644
+index 000000000000..ecb64f06527f
+--- /dev/null
++++ b/drivers/soc/qcom/qcom_pd_mapper.c
+@@ -0,0 +1,676 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm Protection Domain mapper
++ *
++ * Copyright (c) 2023 Linaro Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/kernel.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/refcount.h>
++#include <linux/soc/qcom/qmi.h>
++
++#include "pdr_internal.h"
++
++#define SERVREG_QMI_VERSION 0x101
++#define SERVREG_QMI_INSTANCE 0
++
++#define TMS_SERVREG_SERVICE "tms/servreg"
++
++struct qcom_pdm_domain_data {
++ const char *domain;
++ u32 instance_id;
++ /* NULL-terminated array */
++ const char * services[];
++};
++
++struct qcom_pdm_domain {
++ struct list_head list;
++ const char *name;
++ u32 instance_id;
++};
++
++struct qcom_pdm_service {
++ struct list_head list;
++ struct list_head domains;
++ const char *name;
++};
++
++struct qcom_pdm_data {
++ refcount_t refcnt;
++ struct qmi_handle handle;
++ struct list_head services;
++};
++
++static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
++static struct qcom_pdm_data *__qcom_pdm_data;
++
++static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
++ const char *name)
++{
++ struct qcom_pdm_service *service;
++
++ list_for_each_entry(service, &data->services, list) {
++ if (!strcmp(service->name, name))
++ return service;
++ }
++
++ return NULL;
++}
++
++static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
++ const char *service_name,
++ const char *domain_name,
++ u32 instance_id)
++{
++ struct qcom_pdm_service *service;
++ struct qcom_pdm_domain *domain;
++
++ service = qcom_pdm_find(data, service_name);
++ if (service) {
++ list_for_each_entry(domain, &service->domains, list) {
++ if (!strcmp(domain->name, domain_name))
++ return -EBUSY;
++ }
++ } else {
++ service = kzalloc(sizeof(*service), GFP_KERNEL);
++ if (!service)
++ return -ENOMEM;
++
++ INIT_LIST_HEAD(&service->domains);
++ service->name = service_name;
++
++ list_add_tail(&service->list, &data->services);
++ }
++
++ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
++ if (!domain) {
++ if (list_empty(&service->domains)) {
++ list_del(&service->list);
++ kfree(service);
++ }
++
++ return -ENOMEM;
++ }
++
++ domain->name = domain_name;
++ domain->instance_id = instance_id;
++ list_add_tail(&domain->list, &service->domains);
++
++ return 0;
++}
++
++static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
++ const struct qcom_pdm_domain_data *domain)
++{
++ int ret;
++ int i;
++
++ ret = qcom_pdm_add_service_domain(data,
++ TMS_SERVREG_SERVICE,
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++
++ for (i = 0; domain->services[i]; i++) {
++ ret = qcom_pdm_add_service_domain(data,
++ domain->services[i],
++ domain->domain,
++ domain->instance_id);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++
++}
++
++static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
++{
++ struct qcom_pdm_service *service, *tservice;
++ struct qcom_pdm_domain *domain, *tdomain;
++
++ list_for_each_entry_safe(service, tservice, &data->services, list) {
++ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
++ list_del(&domain->list);
++ kfree(domain);
++ }
++
++ list_del(&service->list);
++ kfree(service);
++ }
++}
++
++static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
++ const struct servreg_get_domain_list_req *req = decoded;
++ struct servreg_get_domain_list_resp *rsp;
++ struct qcom_pdm_service *service;
++ u32 offset;
++ int ret;
++
++ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
++ if (!rsp)
++ return;
++
++ offset = req->domain_offset_valid ? req->domain_offset : 0;
++
++ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
++ rsp->resp.error = QMI_ERR_NONE_V01;
++
++ rsp->db_rev_count_valid = true;
++ rsp->db_rev_count = 1;
++
++ rsp->total_domains_valid = true;
++ rsp->total_domains = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ service = qcom_pdm_find(data, req->service_name);
++ if (service) {
++ struct qcom_pdm_domain *domain;
++
++ rsp->domain_list_valid = true;
++ rsp->domain_list_len = 0;
++
++ list_for_each_entry(domain, &service->domains, list) {
++ u32 i = rsp->total_domains++;
++
++ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
++ u32 j = rsp->domain_list_len++;
++
++ strscpy(rsp->domain_list[j].name, domain->name,
++ sizeof(rsp->domain_list[i].name));
++ rsp->domain_list[j].instance = domain->instance_id;
++
++ pr_debug("PDM: found %s / %d\n", domain->name,
++ domain->instance_id);
++ }
++ }
++ }
++
++ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
++ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
++ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
++ servreg_get_domain_list_resp_ei, rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ kfree(rsp);
++}
++
++static void qcom_pdm_pfr(struct qmi_handle *qmi,
++ struct sockaddr_qrtr *sq,
++ struct qmi_txn *txn,
++ const void *decoded)
++{
++ const struct servreg_loc_pfr_req *req = decoded;
++ struct servreg_loc_pfr_resp rsp = {};
++ int ret;
++
++ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
++
++ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
++ rsp.rsp.error = QMI_ERR_NONE_V01;
++
++ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
++ SERVREG_LOC_PFR_RESP_MAX_LEN,
++ servreg_loc_pfr_resp_ei, &rsp);
++ if (ret)
++ pr_err("Error sending servreg response: %d\n", ret);
++}
++
++static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
++ .ei = servreg_get_domain_list_req_ei,
++ .decoded_size = sizeof(struct servreg_get_domain_list_req),
++ .fn = qcom_pdm_get_domain_list,
++ },
++ {
++ .type = QMI_REQUEST,
++ .msg_id = SERVREG_LOC_PFR_REQ,
++ .ei = servreg_loc_pfr_req_ei,
++ .decoded_size = sizeof(struct servreg_loc_pfr_req),
++ .fn = qcom_pdm_pfr,
++ },
++ { },
++};
++
++static const struct qcom_pdm_domain_data adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 74,
++ .services = {
++ "avs/audio",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_charger_pd = {
++ .domain = "msm/adsp/charger_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 74,
++ .services = {
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data adsp_sensor_pd = {
++ .domain = "msm/adsp/sensor_pd",
++ .instance_id = 74,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
++ .domain = "msm/adsp/audio_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
++ .domain = "msm/adsp/root_pd",
++ .instance_id = 4,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data cdsp_root_pd = {
++ .domain = "msm/cdsp/root_pd",
++ .instance_id = 76,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_root_pd = {
++ .domain = "msm/slpi/root_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data slpi_sensor_pd = {
++ .domain = "msm/slpi/sensor_pd",
++ .instance_id = 90,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 180,
++ .services = {
++ "gps/gps_service",
++ "tms/pdr_enabled",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
++ .domain = "msm/modem/root_pd",
++ .instance_id = 100,
++ .services = { NULL },
++};
++
++static const struct qcom_pdm_domain_data mpss_wlan_pd = {
++ .domain = "msm/modem/wlan_pd",
++ .instance_id = 180,
++ .services = {
++ "kernel/elf_loader",
++ "wlan/fw",
++ NULL,
++ },
++};
++
++static const struct qcom_pdm_domain_data *msm8996_domains[] = {
++ &msm8996_adsp_audio_pd,
++ &msm8996_adsp_root_pd,
++ &msm8996_mpss_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *msm8998_domains[] = {
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *qcs404_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7180_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_sensor_pd,
++ &mpss_root_pd_gps_pdr,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc7280_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps_pdr,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm660_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm670_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sdm845_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd,
++ &mpss_wlan_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6115_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm6350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8150_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &mpss_wlan_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8250_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &cdsp_root_pd,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8350_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd_pdr,
++ &adsp_charger_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ &slpi_root_pd,
++ &slpi_sensor_pd,
++ NULL,
++};
++
++static const struct qcom_pdm_domain_data *sm8550_domains[] = {
++ &adsp_audio_pd,
++ &adsp_root_pd,
++ &adsp_charger_pd,
++ &adsp_sensor_pd,
++ &cdsp_root_pd,
++ &mpss_root_pd_gps,
++ NULL,
++};
++
++static const struct of_device_id qcom_pdm_domains[] = {
++ { .compatible = "qcom,apq8064", .data = NULL, },
++ { .compatible = "qcom,apq8074", .data = NULL, },
++ { .compatible = "qcom,apq8084", .data = NULL, },
++ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8226", .data = NULL, },
++ { .compatible = "qcom,msm8974", .data = NULL, },
++ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
++ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
++ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
++ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
++ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
++ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
++ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
++ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
++ { .compatible = "qcom,sda660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
++ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
++ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
++ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
++ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
++ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
++ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
++ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
++ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
++ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
++ {},
++};
++
++static void qcom_pdm_stop(struct qcom_pdm_data *data)
++{
++ qcom_pdm_free_domains(data);
++
++ /* The server is removed automatically */
++ qmi_handle_release(&data->handle);
++
++ kfree(data);
++}
++
++static struct qcom_pdm_data *qcom_pdm_start(void)
++{
++ const struct qcom_pdm_domain_data * const *domains;
++ const struct of_device_id *match;
++ struct qcom_pdm_data *data;
++ struct device_node *root;
++ int ret, i;
++
++ root = of_find_node_by_path("/");
++ if (!root)
++ return ERR_PTR(-ENODEV);
++
++ match = of_match_node(qcom_pdm_domains, root);
++ of_node_put(root);
++ if (!match) {
++ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ domains = match->data;
++ if (!domains) {
++ pr_debug("PDM: no domains\n");
++ return ERR_PTR(-ENODEV);
++ }
++
++ data = kzalloc(sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return ERR_PTR(-ENOMEM);
++
++ INIT_LIST_HEAD(&data->services);
++
++ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
++ NULL, qcom_pdm_msg_handlers);
++ if (ret) {
++ kfree(data);
++ return ERR_PTR(ret);
++ }
++
++ refcount_set(&data->refcnt, 1);
++
++ for (i = 0; domains[i]; i++) {
++ ret = qcom_pdm_add_domain(data, domains[i]);
++ if (ret)
++ goto err_stop;
++ }
++
++ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
++ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
++ if (ret) {
++ pr_err("PDM: error adding server %d\n", ret);
++ goto err_stop;
++ }
++
++ return data;
++
++err_stop:
++ qcom_pdm_stop(data);
++
++ return ERR_PTR(ret);
++}
++
++static int qcom_pdm_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++
++{
++ struct qcom_pdm_data *data;
++ int ret = 0;
++
++ mutex_lock(&qcom_pdm_mutex);
++
++ if (!__qcom_pdm_data) {
++ data = qcom_pdm_start();
++
++ if (IS_ERR(data))
++ ret = PTR_ERR(data);
++ else
++ __qcom_pdm_data = data;
++ }
++
++ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
++
++ mutex_unlock(&qcom_pdm_mutex);
++
++ return ret;
++}
++
++static void qcom_pdm_remove(struct auxiliary_device *auxdev)
++{
++ struct qcom_pdm_data *data;
++
++ data = auxiliary_get_drvdata(auxdev);
++ if (!data)
++ return;
++
++ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
++ __qcom_pdm_data = NULL;
++ qcom_pdm_stop(data);
++ mutex_unlock(&qcom_pdm_mutex);
++ }
++}
++
++static const struct auxiliary_device_id qcom_pdm_table[] = {
++ { .name = "qcom_common.pd-mapper" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
++
++static struct auxiliary_driver qcom_pdm_drv = {
++ .name = "qcom-pdm-mapper",
++ .id_table = qcom_pdm_table,
++ .probe = qcom_pdm_probe,
++ .remove = qcom_pdm_remove,
++};
++module_auxiliary_driver(qcom_pdm_drv);
++
++MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
+index 9b46f42aa146..bf3e4a47165e 100644
+--- a/drivers/soc/qcom/qcom_pdr_msg.c
++++ b/drivers/soc/qcom/qcom_pdr_msg.c
+@@ -315,5 +315,39 @@ const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ };
+ EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
++const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x01,
++ .offset = offsetof(struct servreg_loc_pfr_req, service)
++ },
++ {
++ .data_type = QMI_STRING,
++ .elem_len = SERVREG_NAME_LENGTH + 1,
++ .elem_size = sizeof(char),
++ .array_type = VAR_LEN_ARRAY,
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_req, reason)
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
++
++const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
++ {
++ .data_type = QMI_STRUCT,
++ .elem_len = 1,
++ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
++ .tlv_type = 0x02,
++ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
++ .ei_array = qmi_response_type_v01_ei,
++ },
++ {}
++};
++EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sat, 22 Jun 2024 01:03:44 +0300
+Subject: [PATCH v9 5/5] remoteproc: qcom: enable in-kernel PD mapper
+
+Request in-kernel protection domain mapper to be started before starting
+Qualcomm DSP and release it once DSP is stopped. Once all DSPs are
+stopped, the PD mapper will be stopped too.
+
+Reviewed-by: Chris Lew <quic_clew@quicinc.com>
+Tested-by: Steev Klimaszewski <steev@kali.org>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+---
+ drivers/remoteproc/qcom_common.c | 87 +++++++++++++++++++++++++++++++++++++
+ drivers/remoteproc/qcom_common.h | 10 +++++
+ drivers/remoteproc/qcom_q6v5_adsp.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_mss.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_pas.c | 3 ++
+ drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++
+ 6 files changed, 109 insertions(+)
+
+diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c
+index 03e5f5d533eb..8c8688f99f0a 100644
+--- a/drivers/remoteproc/qcom_common.c
++++ b/drivers/remoteproc/qcom_common.c
+@@ -13,6 +13,7 @@
+ #include <linux/notifier.h>
+ #include <linux/remoteproc.h>
+ #include <linux/remoteproc/qcom_rproc.h>
++#include <linux/auxiliary_bus.h>
+ #include <linux/rpmsg/qcom_glink.h>
+ #include <linux/rpmsg/qcom_smd.h>
+ #include <linux/slab.h>
+@@ -25,6 +26,7 @@
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
+ #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
+ #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
++#define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev)
+
+ #define MAX_NUM_OF_SS 10
+ #define MAX_REGION_NAME_LENGTH 16
+@@ -519,5 +521,90 @@ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
+
++static void pdm_dev_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ kfree(adev);
++}
++
++static int pdm_notify_prepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ adev->dev.parent = pdm->dev;
++ adev->dev.release = pdm_dev_release;
++ adev->name = "pd-mapper";
++ adev->id = pdm->index;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ pdm->adev = adev;
++
++ return 0;
++}
++
++
++static void pdm_notify_unprepare(struct rproc_subdev *subdev)
++{
++ struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev);
++
++ if (!pdm->adev)
++ return;
++
++ auxiliary_device_delete(pdm->adev);
++ auxiliary_device_uninit(pdm->adev);
++ pdm->adev = NULL;
++}
++
++/**
++ * qcom_add_pdm_subdev() - register PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Register @pdm so that Protection Device mapper service is started when the
++ * DSP is started too.
++ */
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ pdm->dev = &rproc->dev;
++ pdm->index = rproc->index;
++
++ pdm->subdev.prepare = pdm_notify_prepare;
++ pdm->subdev.unprepare = pdm_notify_unprepare;
++
++ rproc_add_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev);
++
++/**
++ * qcom_remove_pdm_subdev() - remove PD Mapper subdevice
++ * @rproc: rproc handle
++ * @pdm: PDM subdevice handle
++ *
++ * Remove the PD Mapper subdevice.
++ */
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm)
++{
++ rproc_remove_subdev(rproc, &pdm->subdev);
++}
++EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev);
++
+ MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h
+index 9ef4449052a9..b07fbaa091a0 100644
+--- a/drivers/remoteproc/qcom_common.h
++++ b/drivers/remoteproc/qcom_common.h
+@@ -34,6 +34,13 @@ struct qcom_rproc_ssr {
+ struct qcom_ssr_subsystem *info;
+ };
+
++struct qcom_rproc_pdm {
++ struct rproc_subdev subdev;
++ struct device *dev;
++ int index;
++ struct auxiliary_device *adev;
++};
++
+ void qcom_minidump(struct rproc *rproc, unsigned int minidump_id,
+ void (*rproc_dumpfn_t)(struct rproc *rproc,
+ struct rproc_dump_segment *segment, void *dest, size_t offset,
+@@ -52,6 +59,9 @@ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
+ const char *ssr_name);
+ void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
+
++void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm);
++
+ #if IS_ENABLED(CONFIG_QCOM_SYSMON)
+ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+ const char *name,
+diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
+index 1d24c9b656a8..572dcb0f055b 100644
+--- a/drivers/remoteproc/qcom_q6v5_adsp.c
++++ b/drivers/remoteproc/qcom_q6v5_adsp.c
+@@ -112,6 +112,7 @@ struct qcom_adsp {
+ struct dev_pm_domain_list *pd_list;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -726,6 +727,7 @@ static int adsp_probe(struct platform_device *pdev)
+ goto disable_pm;
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+@@ -755,6 +757,7 @@ static void adsp_remove(struct platform_device *pdev)
+
+ qcom_q6v5_deinit(&adsp->q6v5);
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ qcom_rproc_pds_detach(adsp);
+diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
+index 1779fc890e10..2a42215ce8e0 100644
+--- a/drivers/remoteproc/qcom_q6v5_mss.c
++++ b/drivers/remoteproc/qcom_q6v5_mss.c
+@@ -228,6 +228,7 @@ struct q6v5 {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+ struct platform_device *bam_dmux;
+@@ -2102,6 +2103,7 @@ static int q6v5_probe(struct platform_device *pdev)
+ qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss");
+ qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
+ qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
+ if (IS_ERR(qproc->sysmon)) {
+@@ -2143,6 +2145,7 @@ static void q6v5_remove(struct platform_device *pdev)
+ qcom_q6v5_deinit(&qproc->q6v5);
+ qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev);
++ qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev);
+ qcom_remove_smd_subdev(rproc, &qproc->smd_subdev);
+ qcom_remove_glink_subdev(rproc, &qproc->glink_subdev);
+
+diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
+index 8458bcfe9e19..88e7b84f223c 100644
+--- a/drivers/remoteproc/qcom_q6v5_pas.c
++++ b/drivers/remoteproc/qcom_q6v5_pas.c
+@@ -111,6 +111,7 @@ struct qcom_adsp {
+
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_subdev smd_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_sysmon *sysmon;
+
+@@ -777,6 +778,7 @@ static int adsp_probe(struct platform_device *pdev)
+
+ qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name);
+ qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
++ qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev);
+ adsp->sysmon = qcom_add_sysmon_subdev(rproc,
+ desc->sysmon_name,
+ desc->ssctl_id);
+@@ -811,6 +813,7 @@ static void adsp_remove(struct platform_device *pdev)
+ qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
+ qcom_remove_sysmon_subdev(adsp->sysmon);
+ qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
++ qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev);
+ qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
+ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count);
+ device_init_wakeup(adsp->dev, false);
+diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
+index 94f68c919ee6..e913dabae992 100644
+--- a/drivers/remoteproc/qcom_q6v5_wcss.c
++++ b/drivers/remoteproc/qcom_q6v5_wcss.c
+@@ -148,6 +148,7 @@ struct q6v5_wcss {
+ bool requires_force_stop;
+
+ struct qcom_rproc_glink glink_subdev;
++ struct qcom_rproc_pdm pdm_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ };
+
+@@ -1052,6 +1053,7 @@ static int q6v5_wcss_probe(struct platform_device *pdev)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
++ qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ if (desc->ssctl_id)
+@@ -1074,6 +1076,7 @@ static void q6v5_wcss_remove(struct platform_device *pdev)
+ struct q6v5_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6v5);
++ qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev);
+ rproc_del(rproc);
+ }
+
diff --git a/srcpkgs/linux6.9/template b/srcpkgs/linux6.9/template
index 48d279faa64c53..a107ed8f6b53b1 100644
--- a/srcpkgs/linux6.9/template
+++ b/srcpkgs/linux6.9/template
@@ -1,7 +1,7 @@
# Template file for 'linux6.9'
pkgname=linux6.9
version=6.9.8
-revision=1
+revision=2
short_desc="Linux kernel and modules (${version%.*} series)"
maintainer="Duncaen <duncaen@voidlinux.org>"
license="GPL-2.0-only"
From c9da2d33d114c00eb8cb3c7560c332257042eb12 Mon Sep 17 00:00:00 2001
From: classabbyamp <void@placeviolette.net>
Date: Thu, 21 Mar 2024 18:00:45 -0400
Subject: [PATCH 3/3] New package: x13s-base-1
---
srcpkgs/x13s-base/INSTALL | 9 ++++++++
srcpkgs/x13s-base/files/72-touchscreen.rules | 1 +
srcpkgs/x13s-base/files/90-bt-address.sh | 2 ++
srcpkgs/x13s-base/files/90-net-address.rules | 1 +
srcpkgs/x13s-base/files/dracut.conf | 6 ++++++
srcpkgs/x13s-base/files/mkinitcpio.conf | 6 ++++++
srcpkgs/x13s-base/files/x13s-setup | 18 ++++++++++++++++
srcpkgs/x13s-base/files/x13s.default | 7 +++++++
srcpkgs/x13s-base/template | 22 ++++++++++++++++++++
9 files changed, 72 insertions(+)
create mode 100644 srcpkgs/x13s-base/INSTALL
create mode 100644 srcpkgs/x13s-base/files/72-touchscreen.rules
create mode 100644 srcpkgs/x13s-base/files/90-bt-address.sh
create mode 100644 srcpkgs/x13s-base/files/90-net-address.rules
create mode 100644 srcpkgs/x13s-base/files/dracut.conf
create mode 100644 srcpkgs/x13s-base/files/mkinitcpio.conf
create mode 100644 srcpkgs/x13s-base/files/x13s-setup
create mode 100644 srcpkgs/x13s-base/files/x13s.default
create mode 100644 srcpkgs/x13s-base/template
diff --git a/srcpkgs/x13s-base/INSTALL b/srcpkgs/x13s-base/INSTALL
new file mode 100644
index 00000000000000..50459153a32160
--- /dev/null
+++ b/srcpkgs/x13s-base/INSTALL
@@ -0,0 +1,9 @@
+case "$ACTION" in
+post)
+ # assign a random wlan and bluetooth MAC addresses with the correct OUI
+ # as the firmware doesn't support saving this
+ sed -i -e "s/:UU:VV:WW/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ -e "s/:XX:YY:ZZ/$(od -An -N3 -t x1 /dev/urandom | tr ' ' ':')/g" \
+ etc/default/x13s
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/72-touchscreen.rules b/srcpkgs/x13s-base/files/72-touchscreen.rules
new file mode 100644
index 00000000000000..c0a1cb63749643
--- /dev/null
+++ b/srcpkgs/x13s-base/files/72-touchscreen.rules
@@ -0,0 +1 @@
+ACTION=="add" , RUN+="/bin/sh -c 'echo 4-0010 > /sys/bus/i2c/drivers/i2c_hid_of/bind'"
diff --git a/srcpkgs/x13s-base/files/90-bt-address.sh b/srcpkgs/x13s-base/files/90-bt-address.sh
new file mode 100644
index 00000000000000..a0273efbb063c3
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-bt-address.sh
@@ -0,0 +1,2 @@
+msg "Setting bluetooth MAC address..."
+/usr/libexec/x13s-setup bluetooth
diff --git a/srcpkgs/x13s-base/files/90-net-address.rules b/srcpkgs/x13s-base/files/90-net-address.rules
new file mode 100644
index 00000000000000..1c50a4a2e45ea4
--- /dev/null
+++ b/srcpkgs/x13s-base/files/90-net-address.rules
@@ -0,0 +1 @@
+ACTION=="add", SUBSYSTEM=="net", KERNELS=="0006:01:00.0", RUN+="/usr/libexec/x13s-setup wlan $name"
diff --git a/srcpkgs/x13s-base/files/dracut.conf b/srcpkgs/x13s-base/files/dracut.conf
new file mode 100644
index 00000000000000..a24acfa3d0a06e
--- /dev/null
+++ b/srcpkgs/x13s-base/files/dracut.conf
@@ -0,0 +1,6 @@
+force_drivers+=" nvme phy_qcom_qmp_pcie "
+# keyboard
+force_drivers+=" i2c_hid_of i2c_qcom_geni "
+# display
+force_drivers+=" leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm "
+force_drivers+=" phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp "
diff --git a/srcpkgs/x13s-base/files/mkinitcpio.conf b/srcpkgs/x13s-base/files/mkinitcpio.conf
new file mode 100644
index 00000000000000..a428eefb2016f9
--- /dev/null
+++ b/srcpkgs/x13s-base/files/mkinitcpio.conf
@@ -0,0 +1,6 @@
+MODULES+=(nvme phy_qcom_qmp_pcie)
+# keyboard
+MODULES+=(i2c_hid_of i2c_qcom_geni)
+# display
+MODULES+=(leds_qcom_lpg pwm_bl qrtr pmic_glink_altmode gpio_sbu_mux panel_edp msm
+ phy_qcom_qmp_combo pinctrl_sc8280xp gpucc_sc8280xp dispcc_sc8280xp phy_qcom_edp)
diff --git a/srcpkgs/x13s-base/files/x13s-setup b/srcpkgs/x13s-base/files/x13s-setup
new file mode 100644
index 00000000000000..ce0872e83d8e04
--- /dev/null
+++ b/srcpkgs/x13s-base/files/x13s-setup
@@ -0,0 +1,18 @@
+#!/bin/sh
+# x13s-setup wlan <interface>
+# x13s-setup bluetooth
+
+[ -r /etc/default/x13s ] && . /etc/default/x13s
+
+case "$1" in
+wlan)
+ if [ -n "$WLAN_MAC" ] && command -v ip >/dev/null 2>&1; then
+ exec ip link set dev "$2" address "$WLAN_MAC"
+ fi
+ ;;
+bluetooth)
+ if [ -n "$BLUETOOTH_MAC" ] && command -v btmgmt >/dev/null 2>&1; then
+ exec btmgmt --index 0 public-addr "$BLUETOOTH_MAC"
+ fi
+ ;;
+esac
diff --git a/srcpkgs/x13s-base/files/x13s.default b/srcpkgs/x13s-base/files/x13s.default
new file mode 100644
index 00000000000000..1350a65c7b696d
--- /dev/null
+++ b/srcpkgs/x13s-base/files/x13s.default
@@ -0,0 +1,7 @@
+# the X13s' wlan and bluetooth firmware/hardware do not support
+# storing their default MAC address, so it must be set on boot
+# by default, these are set to a random MAC address with the
+# correct vendor prefix (OUI) of F4:A0:0D. These MAC addresses
+# can also be assigned manually by editing this file.
+WLAN_MAC="F4:A0:0D:UU:VV:WW"
+BLUETOOTH_MAC="F4:A0:0D:XX:YY:ZZ"
diff --git a/srcpkgs/x13s-base/template b/srcpkgs/x13s-base/template
new file mode 100644
index 00000000000000..17da5ee388cc3d
--- /dev/null
+++ b/srcpkgs/x13s-base/template
@@ -0,0 +1,22 @@
+# Template file for 'x13s-base'
+pkgname=x13s-base
+version=1
+revision=1
+archs="aarch64*"
+depends="linux-mainline>=6.8 linux-firmware-qualcomm alsa-ucm-conf"
+short_desc="Void Linux Thinkpad X13s platform package"
+maintainer="classabbyamp <void@placeviolette.net>"
+license="Public Domain"
+homepage="https://www.voidlinux.org"
+conf_files="/etc/default/x13s"
+
+do_install() {
+ vinstall "${FILESDIR}"/72-touchscreen.rules 644 usr/lib/udev/rules.d 72-x13s-touchscreen.rules
+ vinstall "${FILESDIR}"/90-net-address.rules 644 usr/lib/udev/rules.d 90-x13s-net-address.rules
+ vinstall "${FILESDIR}"/90-bt-address.sh 644 etc/runit/core-services 90-x13s-bt-address.sh
+ vinstall "${FILESDIR}"/dracut.conf 644 usr/lib/dracut/dracut.conf.d x13s.conf
+ vinstall "${FILESDIR}"/x13s-setup 755 usr/libexec
+ vinstall "${FILESDIR}"/x13s.default 644 etc/default x13s
+ # not currently working
+ # vinstall "${FILESDIR}"/mkinitcpio.conf 644 etc/mkinitcpio.conf.d x13s.conf
+}
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PR PATCH] [Merged]: Lenovo X13s support
2024-03-31 2:52 [PR PATCH] X13s support classabbyamp
` (33 preceding siblings ...)
2024-07-07 5:31 ` classabbyamp
@ 2024-07-07 5:32 ` classabbyamp
34 siblings, 0 replies; 36+ messages in thread
From: classabbyamp @ 2024-07-07 5:32 UTC (permalink / raw)
To: ml
[-- Attachment #1: Type: text/plain, Size: 1288 bytes --]
There's a merged pull request on the void-packages repository
Lenovo X13s support
https://github.com/void-linux/void-packages/pull/49615
Description:
## repo for testing: https://devspace.voidlinux.org/abby/x13s/
#### TODOs
- [x] document install process, including required cmdline (`arm64.nopauth clk_ignore_unused pd_ignore_unused`)
- https://github.com/void-linux/void-docs/compare/master...classabbyamp:void-docs:x13s
- [x] fix bluetooth mac address: (`btmgmt public-addr F4:A0:0D:XX:YY:ZZ`)
- [x] set a random mac with the correct OUI (`F4:A0:0D:xx:yy:zz`) at install?
- [x] mkinitcpio drop-in config
- [ ] mkinitcpio working
- https://gitlab.archlinux.org/archlinux/mkinitcpio/mkinitcpio/-/merge_requests/377
- does not load modules and/or firmware correctly
- [ ] create and test live images
- **HEAVILY WIP** https://github.com/void-linux/void-mklive/compare/master...classabbyamp:void-mklive:aarch64-live
- [x] ~~kernel install hook to update the dtb?~~ grub dtb loading support
#### Testing the changes
- I tested the changes in this PR: **YES**
#### New package
- This new package conforms to the [package requirements](https://github.com/void-linux/void-packages/blob/master/CONTRIBUTING.md#package-requirements): **YES**
[ci skip]
^ permalink raw reply [flat|nested] 36+ messages in thread