aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLoic Poulain <loic.poulain@linaro.org>2023-01-09 14:05:22 +0100
committerBjorn Andersson <andersson@kernel.org>2023-01-10 22:55:28 -0600
commite656cd0bcf3d2ba2eceac82b44714bf355428ec4 (patch)
tree68660c2e2138f659cd93ecc510fb30e04797d8e5
parentdt-bindings: reserved-memory: rmtfs: Make qcom,vmid an array (diff)
downloadwireguard-linux-e656cd0bcf3d2ba2eceac82b44714bf355428ec4.tar.xz
wireguard-linux-e656cd0bcf3d2ba2eceac82b44714bf355428ec4.zip
soc: qcom: rmtfs: Optionally map RMTFS to more VMs
Some SoCs require that RMTFS is also mapped to the NAV VM. Trying to power on the modem without that results in the whole platform crashing and forces a hard reboot within about 2 seconds. Add support for mapping the region to additional VMs, such as NAV to open a path towards enabling modem on such platforms. Signed-off-by: Loic Poulain <loic.poulain@linaro.org> [Konrad: reword, make conditional and flexible, add a define for NAV VMID] Signed-off-by: Konrad Dybcio <konrad.dybcio@linaro.org> Signed-off-by: Bjorn Andersson <andersson@kernel.org> Link: https://lore.kernel.org/r/20230109130523.298971-2-konrad.dybcio@linaro.org
-rw-r--r--drivers/soc/qcom/rmtfs_mem.c29
-rw-r--r--include/linux/qcom_scm.h1
2 files changed, 23 insertions, 7 deletions
diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c
index 0feaae357821..9d59ad509a5c 100644
--- a/drivers/soc/qcom/rmtfs_mem.c
+++ b/drivers/soc/qcom/rmtfs_mem.c
@@ -17,6 +17,7 @@
#include <linux/qcom_scm.h>
#define QCOM_RMTFS_MEM_DEV_MAX (MINORMASK + 1)
+#define NUM_MAX_VMIDS 2
static dev_t qcom_rmtfs_mem_major;
@@ -171,12 +172,12 @@ static void qcom_rmtfs_mem_release_device(struct device *dev)
static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
- struct qcom_scm_vmperm perms[2];
+ struct qcom_scm_vmperm perms[NUM_MAX_VMIDS + 1];
struct reserved_mem *rmem;
struct qcom_rmtfs_mem *rmtfs_mem;
u32 client_id;
- u32 vmid;
- int ret;
+ u32 num_vmids, vmid[NUM_MAX_VMIDS];
+ int ret, i;
rmem = of_reserved_mem_lookup(node);
if (!rmem) {
@@ -226,7 +227,18 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
goto put_device;
}
- ret = of_property_read_u32(node, "qcom,vmid", &vmid);
+ num_vmids = of_property_count_u32_elems(node, "qcom,vmid");
+ if (num_vmids < 0) {
+ dev_err(&pdev->dev, "failed to count qcom,vmid elements: %d\n", ret);
+ goto remove_cdev;
+ } else if (num_vmids > NUM_MAX_VMIDS) {
+ dev_warn(&pdev->dev,
+ "too many VMIDs (%d) specified! Only mapping first %d entries\n",
+ num_vmids, NUM_MAX_VMIDS);
+ num_vmids = NUM_MAX_VMIDS;
+ }
+
+ ret = of_property_read_u32_array(node, "qcom,vmid", vmid, num_vmids);
if (ret < 0 && ret != -EINVAL) {
dev_err(&pdev->dev, "failed to parse qcom,vmid\n");
goto remove_cdev;
@@ -238,12 +250,15 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
perms[0].vmid = QCOM_SCM_VMID_HLOS;
perms[0].perm = QCOM_SCM_PERM_RW;
- perms[1].vmid = vmid;
- perms[1].perm = QCOM_SCM_PERM_RW;
+
+ for (i = 0; i < num_vmids; i++) {
+ perms[i + 1].vmid = vmid[i];
+ perms[i + 1].perm = QCOM_SCM_PERM_RW;
+ }
rmtfs_mem->perms = BIT(QCOM_SCM_VMID_HLOS);
ret = qcom_scm_assign_mem(rmtfs_mem->addr, rmtfs_mem->size,
- &rmtfs_mem->perms, perms, 2);
+ &rmtfs_mem->perms, perms, num_vmids + 1);
if (ret < 0) {
dev_err(&pdev->dev, "assign memory failed\n");
goto remove_cdev;
diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h
index f8335644a01a..150b72edb879 100644
--- a/include/linux/qcom_scm.h
+++ b/include/linux/qcom_scm.h
@@ -55,6 +55,7 @@ enum qcom_scm_ice_cipher {
#define QCOM_SCM_VMID_MSS_MSA 0xF
#define QCOM_SCM_VMID_WLAN 0x18
#define QCOM_SCM_VMID_WLAN_CE 0x19
+#define QCOM_SCM_VMID_NAV 0x2B
#define QCOM_SCM_PERM_READ 0x4
#define QCOM_SCM_PERM_WRITE 0x2
#define QCOM_SCM_PERM_EXEC 0x1