Commit e656cd0b authored by Loic Poulain's avatar Loic Poulain Committed by Bjorn Andersson
Browse files

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: default avatarLoic Poulain <loic.poulain@linaro.org>
[Konrad: reword, make conditional and flexible, add a define for NAV VMID]
Signed-off-by: default avatarKonrad Dybcio <konrad.dybcio@linaro.org>
Signed-off-by: default avatarBjorn Andersson <andersson@kernel.org>
Link: https://lore.kernel.org/r/20230109130523.298971-2-konrad.dybcio@linaro.org
parent da0d37e4
Loading
Loading
Loading
Loading
+22 −7
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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