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
This commit is contained in:
Loic Poulain 2023-01-09 14:05:22 +01:00 committed by Bjorn Andersson
parent da0d37e42f
commit e656cd0bcf
2 changed files with 23 additions and 7 deletions

View File

@ -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;

View File

@ -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