summaryrefslogtreecommitdiffstats
path: root/drivers/remoteproc
diff options
context:
space:
mode:
authorAvaneesh Kumar Dwivedi <akdwived@codeaurora.org>2017-10-24 11:52:26 -0400
committerBjorn Andersson <bjorn.andersson@linaro.org>2017-10-30 21:37:22 -0400
commit6c5a9dc2481b4819c00bbcef8005b59c04d64963 (patch)
treec37f1f0c30d7c18ff0688dee90e35ddbf0e88588 /drivers/remoteproc
parent94c907859a4c678de8e74eeece5c0487b5629361 (diff)
remoteproc: qcom: Make secure world call for mem ownership switch
MSS proc on msm8996 can not access fw loaded region without stage second translation of memory pages where mpss image are loaded. This patch in order to enable mss boot on msm8996 invoke scm call to switch or share ownership between apps and modem. Signed-off-by: Avaneesh Kumar Dwivedi <akdwived@codeaurora.org> [bjorn: Corrected error path in q6v5_start()] Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Diffstat (limited to 'drivers/remoteproc')
-rw-r--r--drivers/remoteproc/qcom_q6v5_pil.c106
1 files changed, 101 insertions, 5 deletions
diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c
index 39b9ee4a63b7..728179ba7db2 100644
--- a/drivers/remoteproc/qcom_q6v5_pil.c
+++ b/drivers/remoteproc/qcom_q6v5_pil.c
@@ -110,6 +110,7 @@ struct rproc_hexagon_res {
110 struct qcom_mss_reg_res *active_supply; 110 struct qcom_mss_reg_res *active_supply;
111 char **proxy_clk_names; 111 char **proxy_clk_names;
112 char **active_clk_names; 112 char **active_clk_names;
113 bool need_mem_protection;
113}; 114};
114 115
115struct q6v5 { 116struct q6v5 {
@@ -154,6 +155,10 @@ struct q6v5 {
154 155
155 struct qcom_rproc_subdev smd_subdev; 156 struct qcom_rproc_subdev smd_subdev;
156 struct qcom_rproc_ssr ssr_subdev; 157 struct qcom_rproc_ssr ssr_subdev;
158 bool need_mem_protection;
159 int mpss_perm;
160 int mba_perm;
161
157}; 162};
158 163
159static int q6v5_regulator_init(struct device *dev, struct reg_info *regs, 164static int q6v5_regulator_init(struct device *dev, struct reg_info *regs,
@@ -289,6 +294,35 @@ static struct resource_table *q6v5_find_rsc_table(struct rproc *rproc,
289 return &table; 294 return &table;
290} 295}
291 296
297static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm,
298 bool remote_owner, phys_addr_t addr,
299 size_t size)
300{
301 struct qcom_scm_vmperm next;
302 int ret;
303
304 if (!qproc->need_mem_protection)
305 return 0;
306 if (remote_owner && *current_perm == BIT(QCOM_SCM_VMID_MSS_MSA))
307 return 0;
308 if (!remote_owner && *current_perm == BIT(QCOM_SCM_VMID_HLOS))
309 return 0;
310
311 next.vmid = remote_owner ? QCOM_SCM_VMID_MSS_MSA : QCOM_SCM_VMID_HLOS;
312 next.perm = remote_owner ? QCOM_SCM_PERM_RW : QCOM_SCM_PERM_RWX;
313
314 ret = qcom_scm_assign_mem(addr, ALIGN(size, SZ_4K),
315 current_perm, &next, 1);
316 if (ret < 0) {
317 pr_err("Failed to assign memory access in range %p to %p to %s ret = %d\n",
318 (void *)addr, (void *)(addr + size),
319 remote_owner ? "mss" : "hlos", ret);
320 return ret;
321 }
322
323 return 0;
324}
325
292static int q6v5_load(struct rproc *rproc, const struct firmware *fw) 326static int q6v5_load(struct rproc *rproc, const struct firmware *fw)
293{ 327{
294 struct q6v5 *qproc = rproc->priv; 328 struct q6v5 *qproc = rproc->priv;
@@ -451,6 +485,8 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
451{ 485{
452 unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS; 486 unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
453 dma_addr_t phys; 487 dma_addr_t phys;
488 int mdata_perm;
489 int xferop_ret;
454 void *ptr; 490 void *ptr;
455 int ret; 491 int ret;
456 492
@@ -462,6 +498,13 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
462 498
463 memcpy(ptr, fw->data, fw->size); 499 memcpy(ptr, fw->data, fw->size);
464 500
501 /* Hypervisor mapping to access metadata by modem */
502 mdata_perm = BIT(QCOM_SCM_VMID_HLOS);
503 ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm,
504 true, phys, fw->size);
505 if (ret)
506 return -EAGAIN;
507
465 writel(phys, qproc->rmb_base + RMB_PMI_META_DATA_REG); 508 writel(phys, qproc->rmb_base + RMB_PMI_META_DATA_REG);
466 writel(RMB_CMD_META_DATA_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG); 509 writel(RMB_CMD_META_DATA_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG);
467 510
@@ -471,6 +514,13 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
471 else if (ret < 0) 514 else if (ret < 0)
472 dev_err(qproc->dev, "MPSS header authentication failed: %d\n", ret); 515 dev_err(qproc->dev, "MPSS header authentication failed: %d\n", ret);
473 516
517 /* Metadata authentication done, remove modem access */
518 xferop_ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm,
519 false, phys, fw->size);
520 if (xferop_ret)
521 dev_warn(qproc->dev,
522 "mdt buffer not reclaimed system may become unstable\n");
523
474 dma_free_attrs(qproc->dev, fw->size, ptr, phys, dma_attrs); 524 dma_free_attrs(qproc->dev, fw->size, ptr, phys, dma_attrs);
475 525
476 return ret < 0 ? ret : 0; 526 return ret < 0 ? ret : 0;
@@ -578,7 +628,12 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
578 size += phdr->p_memsz; 628 size += phdr->p_memsz;
579 } 629 }
580 630
581 /* Transfer ownership of modem ddr region with q6*/ 631 /* Transfer ownership of modem ddr region to q6 */
632 ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, true,
633 qproc->mpss_phys, qproc->mpss_size);
634 if (ret)
635 return -EAGAIN;
636
582 boot_addr = relocate ? qproc->mpss_phys : min_addr; 637 boot_addr = relocate ? qproc->mpss_phys : min_addr;
583 writel(boot_addr, qproc->rmb_base + RMB_PMI_CODE_START_REG); 638 writel(boot_addr, qproc->rmb_base + RMB_PMI_CODE_START_REG);
584 writel(RMB_CMD_LOAD_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG); 639 writel(RMB_CMD_LOAD_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG);
@@ -599,6 +654,7 @@ release_firmware:
599static int q6v5_start(struct rproc *rproc) 654static int q6v5_start(struct rproc *rproc)
600{ 655{
601 struct q6v5 *qproc = (struct q6v5 *)rproc->priv; 656 struct q6v5 *qproc = (struct q6v5 *)rproc->priv;
657 int xfermemop_ret;
602 int ret; 658 int ret;
603 659
604 ret = q6v5_regulator_enable(qproc, qproc->proxy_regs, 660 ret = q6v5_regulator_enable(qproc, qproc->proxy_regs,
@@ -634,11 +690,18 @@ static int q6v5_start(struct rproc *rproc)
634 goto assert_reset; 690 goto assert_reset;
635 } 691 }
636 692
693 /* Assign MBA image access in DDR to q6 */
694 xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true,
695 qproc->mba_phys,
696 qproc->mba_size);
697 if (xfermemop_ret)
698 goto disable_active_clks;
699
637 writel(qproc->mba_phys, qproc->rmb_base + RMB_MBA_IMAGE_REG); 700 writel(qproc->mba_phys, qproc->rmb_base + RMB_MBA_IMAGE_REG);
638 701
639 ret = q6v5proc_reset(qproc); 702 ret = q6v5proc_reset(qproc);
640 if (ret) 703 if (ret)
641 goto halt_axi_ports; 704 goto reclaim_mba;
642 705
643 ret = q6v5_rmb_mba_wait(qproc, 0, 5000); 706 ret = q6v5_rmb_mba_wait(qproc, 0, 5000);
644 if (ret == -ETIMEDOUT) { 707 if (ret == -ETIMEDOUT) {
@@ -655,16 +718,22 @@ static int q6v5_start(struct rproc *rproc)
655 718
656 ret = q6v5_mpss_load(qproc); 719 ret = q6v5_mpss_load(qproc);
657 if (ret) 720 if (ret)
658 goto halt_axi_ports; 721 goto reclaim_mpss;
659 722
660 ret = wait_for_completion_timeout(&qproc->start_done, 723 ret = wait_for_completion_timeout(&qproc->start_done,
661 msecs_to_jiffies(5000)); 724 msecs_to_jiffies(5000));
662 if (ret == 0) { 725 if (ret == 0) {
663 dev_err(qproc->dev, "start timed out\n"); 726 dev_err(qproc->dev, "start timed out\n");
664 ret = -ETIMEDOUT; 727 ret = -ETIMEDOUT;
665 goto halt_axi_ports; 728 goto reclaim_mpss;
666 } 729 }
667 730
731 xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, false,
732 qproc->mba_phys,
733 qproc->mba_size);
734 if (xfermemop_ret)
735 dev_err(qproc->dev,
736 "Failed to reclaim mba buffer system may become unstable\n");
668 qproc->running = true; 737 qproc->running = true;
669 738
670 q6v5_clk_disable(qproc->dev, qproc->proxy_clks, 739 q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
@@ -674,12 +743,30 @@ static int q6v5_start(struct rproc *rproc)
674 743
675 return 0; 744 return 0;
676 745
746reclaim_mpss:
747 xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm,
748 false, qproc->mpss_phys,
749 qproc->mpss_size);
750 WARN_ON(xfermemop_ret);
751
677halt_axi_ports: 752halt_axi_ports:
678 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6); 753 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_q6);
679 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem); 754 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem);
680 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc); 755 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc);
756
757reclaim_mba:
758 xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, false,
759 qproc->mba_phys,
760 qproc->mba_size);
761 if (xfermemop_ret) {
762 dev_err(qproc->dev,
763 "Failed to reclaim mba buffer, system may become unstable\n");
764 }
765
766disable_active_clks:
681 q6v5_clk_disable(qproc->dev, qproc->active_clks, 767 q6v5_clk_disable(qproc->dev, qproc->active_clks,
682 qproc->active_clk_count); 768 qproc->active_clk_count);
769
683assert_reset: 770assert_reset:
684 reset_control_assert(qproc->mss_restart); 771 reset_control_assert(qproc->mss_restart);
685disable_vdd: 772disable_vdd:
@@ -699,6 +786,7 @@ static int q6v5_stop(struct rproc *rproc)
699{ 786{
700 struct q6v5 *qproc = (struct q6v5 *)rproc->priv; 787 struct q6v5 *qproc = (struct q6v5 *)rproc->priv;
701 int ret; 788 int ret;
789 u32 val;
702 790
703 qproc->running = false; 791 qproc->running = false;
704 792
@@ -716,6 +804,10 @@ static int q6v5_stop(struct rproc *rproc)
716 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem); 804 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_modem);
717 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc); 805 q6v5proc_halt_axi_port(qproc, qproc->halt_map, qproc->halt_nc);
718 806
807 ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, false,
808 qproc->mpss_phys, qproc->mpss_size);
809 WARN_ON(ret);
810
719 reset_control_assert(qproc->mss_restart); 811 reset_control_assert(qproc->mss_restart);
720 q6v5_clk_disable(qproc->dev, qproc->active_clks, 812 q6v5_clk_disable(qproc->dev, qproc->active_clks,
721 qproc->active_clk_count); 813 qproc->active_clk_count);
@@ -1014,6 +1106,7 @@ static int q6v5_probe(struct platform_device *pdev)
1014 if (ret) 1106 if (ret)
1015 goto free_rproc; 1107 goto free_rproc;
1016 1108
1109 qproc->need_mem_protection = desc->need_mem_protection;
1017 ret = q6v5_request_irq(qproc, pdev, "wdog", q6v5_wdog_interrupt); 1110 ret = q6v5_request_irq(qproc, pdev, "wdog", q6v5_wdog_interrupt);
1018 if (ret < 0) 1111 if (ret < 0)
1019 goto free_rproc; 1112 goto free_rproc;
@@ -1035,7 +1128,8 @@ static int q6v5_probe(struct platform_device *pdev)
1035 ret = PTR_ERR(qproc->state); 1128 ret = PTR_ERR(qproc->state);
1036 goto free_rproc; 1129 goto free_rproc;
1037 } 1130 }
1038 1131 qproc->mpss_perm = BIT(QCOM_SCM_VMID_HLOS);
1132 qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
1039 qcom_add_smd_subdev(rproc, &qproc->smd_subdev); 1133 qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
1040 qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss"); 1134 qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
1041 1135
@@ -1091,6 +1185,7 @@ static const struct rproc_hexagon_res msm8916_mss = {
1091 "mem", 1185 "mem",
1092 NULL 1186 NULL
1093 }, 1187 },
1188 .need_mem_protection = false,
1094}; 1189};
1095 1190
1096static const struct rproc_hexagon_res msm8974_mss = { 1191static const struct rproc_hexagon_res msm8974_mss = {
@@ -1128,6 +1223,7 @@ static const struct rproc_hexagon_res msm8974_mss = {
1128 "mem", 1223 "mem",
1129 NULL 1224 NULL
1130 }, 1225 },
1226 .need_mem_protection = false,
1131}; 1227};
1132 1228
1133static const struct of_device_id q6v5_of_match[] = { 1229static const struct of_device_id q6v5_of_match[] = {