aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Armstrong <neil.armstrong@linaro.org>2022-11-29 20:10:31 +0100
committerNeil Armstrong <neil.armstrong@linaro.org>2023-01-02 10:33:29 +0100
commit1c07c8fa19572b31ab1aa98438aa5d27c18e5d82 (patch)
treea7c683b1a1b644e54bdde235a7fa8d2d913d16e3
parentcd9fa402058ec0715590fc204a56530551e8a568 (diff)
remoteproc: qcom_q6v5_pas: add support for assigning memory to firmware
Starting with SM8550, the DSM memory must now be shared to the firmware by the APPS process instead of beeing defined in the carveout memory reserved for MPSS. In order to handle that, add a region_assign_idx in adsp_data to specify with index of memory-region must be assigned to the MPSS via the qcom_scm_assign_mem() call at probe time. Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
-rw-r--r--drivers/remoteproc/qcom_q6v5_pas.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index 567120192afe..48b0e9b1af57 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -49,6 +49,8 @@ struct adsp_data {
const char *ssr_name;
const char *sysmon_name;
int ssctl_id;
+
+ int region_assign_idx;
};
struct qcom_adsp {
@@ -86,10 +88,15 @@ struct qcom_adsp {
phys_addr_t dtb_mem_phys;
phys_addr_t mem_reloc;
phys_addr_t dtb_mem_reloc;
+ phys_addr_t region_assign_phys;
void *mem_region;
void *dtb_mem_region;
size_t mem_size;
size_t dtb_mem_size;
+ size_t region_assign_size;
+
+ int region_assign_idx;
+ int region_assign_perms;
struct qcom_rproc_glink glink_subdev;
struct qcom_rproc_subdev smd_subdev;
@@ -561,6 +568,64 @@ static int adsp_alloc_memory_region(struct qcom_adsp *adsp)
return 0;
}
+static int adsp_assign_memory_region(struct qcom_adsp *adsp)
+{
+ struct qcom_scm_vmperm perm;
+ struct device_node *node;
+ struct resource r;
+ int ret;
+
+ if (!adsp->region_assign_idx)
+ return 0;
+
+ node = of_parse_phandle(adsp->dev->of_node, "memory-region", adsp->region_assign_idx);
+ if (!node) {
+ dev_err(adsp->dev, "missing shareable memory-region\n");
+ return -EINVAL;
+ }
+
+ ret = of_address_to_resource(node, 0, &r);
+ if (ret)
+ return ret;
+
+ perm.vmid = QCOM_SCM_VMID_MSS_MSA;
+ perm.perm = QCOM_SCM_PERM_RW;
+
+ adsp->region_assign_phys = r.start;
+ adsp->region_assign_size = resource_size(&r);
+ adsp->region_assign_perms = BIT(QCOM_SCM_VMID_HLOS);
+
+ ret = qcom_scm_assign_mem(adsp->region_assign_phys,
+ adsp->region_assign_size,
+ &adsp->region_assign_perms,
+ &perm, 1);
+ if (ret < 0) {
+ dev_err(adsp->dev, "assign memory failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void adsp_unassign_memory_region(struct qcom_adsp *adsp)
+{
+ struct qcom_scm_vmperm perm;
+ int ret;
+
+ if (!adsp->region_assign_idx)
+ return;
+
+ perm.vmid = QCOM_SCM_VMID_HLOS;
+ perm.perm = QCOM_SCM_PERM_RW;
+
+ ret = qcom_scm_assign_mem(adsp->region_assign_phys,
+ adsp->region_assign_size,
+ &adsp->region_assign_perms,
+ &perm, 1);
+ if (ret < 0)
+ dev_err(adsp->dev, "unassign memory failed\n");
+}
+
static int adsp_probe(struct platform_device *pdev)
{
const struct adsp_data *desc;
@@ -612,6 +677,7 @@ static int adsp_probe(struct platform_device *pdev)
adsp->has_aggre2_clk = desc->has_aggre2_clk;
adsp->info_name = desc->sysmon_name;
adsp->decrypt_shutdown = desc->decrypt_shutdown;
+ adsp->region_assign_idx = desc->region_assign_idx;
if (dtb_fw_name) {
adsp->dtb_firmware_name = dtb_fw_name;
adsp->dtb_pas_id = desc->dtb_pas_id;
@@ -626,6 +692,10 @@ static int adsp_probe(struct platform_device *pdev)
if (ret)
goto free_rproc;
+ ret = adsp_assign_memory_region(adsp);
+ if (ret)
+ goto free_rproc;
+
ret = adsp_init_clock(adsp);
if (ret)
goto free_rproc;
@@ -678,6 +748,7 @@ static int adsp_remove(struct platform_device *pdev)
rproc_del(adsp->rproc);
qcom_q6v5_deinit(&adsp->q6v5);
+ adsp_unassign_memory_region(adsp);
qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
qcom_remove_sysmon_subdev(adsp->sysmon);
qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);