aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,adsp-pil.txt5
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt23
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt79
-rw-r--r--drivers/remoteproc/qcom_q6v5_adsp.c6
-rw-r--r--drivers/remoteproc/qcom_q6v5_mss.c209
-rw-r--r--drivers/remoteproc/qcom_q6v5_pas.c13
-rw-r--r--drivers/remoteproc/qcom_sysmon.c82
-rw-r--r--drivers/remoteproc/qcom_wcnss.c6
-rw-r--r--drivers/remoteproc/remoteproc_core.c160
-rw-r--r--drivers/remoteproc/remoteproc_debugfs.c47
-rw-r--r--drivers/remoteproc/remoteproc_internal.h12
-rw-r--r--drivers/remoteproc/remoteproc_virtio.c61
-rw-r--r--drivers/remoteproc/st_remoteproc.c91
-rw-r--r--drivers/rpmsg/virtio_rpmsg_bus.c24
-rw-r--r--include/linux/remoteproc.h8
15 files changed, 706 insertions, 120 deletions
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp-pil.txt b/Documentation/devicetree/bindings/remoteproc/qcom,adsp-pil.txt
index a842a782b557..66af2c30944f 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp-pil.txt
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp-pil.txt
@@ -35,7 +35,7 @@ on the Qualcomm Technology Inc. ADSP Hexagon core.
35 Value type: <stringlist> 35 Value type: <stringlist>
36 Definition: List of clock input name strings sorted in the same 36 Definition: List of clock input name strings sorted in the same
37 order as the clocks property. Definition must have 37 order as the clocks property. Definition must have
38 "xo", "sway_cbcr", "lpass_aon", "lpass_ahbs_aon_cbcr", 38 "xo", "sway_cbcr", "lpass_ahbs_aon_cbcr",
39 "lpass_ahbm_aon_cbcr", "qdsp6ss_xo", "qdsp6ss_sleep" 39 "lpass_ahbm_aon_cbcr", "qdsp6ss_xo", "qdsp6ss_sleep"
40 and "qdsp6ss_core". 40 and "qdsp6ss_core".
41 41
@@ -100,13 +100,12 @@ ADSP, as it is found on SDM845 boards.
100 100
101 clocks = <&rpmhcc RPMH_CXO_CLK>, 101 clocks = <&rpmhcc RPMH_CXO_CLK>,
102 <&gcc GCC_LPASS_SWAY_CLK>, 102 <&gcc GCC_LPASS_SWAY_CLK>,
103 <&lpasscc LPASS_AUDIO_WRAPPER_AON_CLK>,
104 <&lpasscc LPASS_Q6SS_AHBS_AON_CLK>, 103 <&lpasscc LPASS_Q6SS_AHBS_AON_CLK>,
105 <&lpasscc LPASS_Q6SS_AHBM_AON_CLK>, 104 <&lpasscc LPASS_Q6SS_AHBM_AON_CLK>,
106 <&lpasscc LPASS_QDSP6SS_XO_CLK>, 105 <&lpasscc LPASS_QDSP6SS_XO_CLK>,
107 <&lpasscc LPASS_QDSP6SS_SLEEP_CLK>, 106 <&lpasscc LPASS_QDSP6SS_SLEEP_CLK>,
108 <&lpasscc LPASS_QDSP6SS_CORE_CLK>; 107 <&lpasscc LPASS_QDSP6SS_CORE_CLK>;
109 clock-names = "xo", "sway_cbcr", "lpass_aon", 108 clock-names = "xo", "sway_cbcr",
110 "lpass_ahbs_aon_cbcr", 109 "lpass_ahbs_aon_cbcr",
111 "lpass_ahbm_aon_cbcr", "qdsp6ss_xo", 110 "lpass_ahbm_aon_cbcr", "qdsp6ss_xo",
112 "qdsp6ss_sleep", "qdsp6ss_core"; 111 "qdsp6ss_sleep", "qdsp6ss_core";
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt
index 9c0cff3a5ed8..292dfda9770d 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt
@@ -19,13 +19,30 @@ on the Qualcomm ADSP Hexagon core.
19- interrupts-extended: 19- interrupts-extended:
20 Usage: required 20 Usage: required
21 Value type: <prop-encoded-array> 21 Value type: <prop-encoded-array>
22 Definition: must list the watchdog, fatal IRQs ready, handover and 22 Definition: reference to the interrupts that match interrupt-names
23 stop-ack IRQs
24 23
25- interrupt-names: 24- interrupt-names:
26 Usage: required 25 Usage: required
27 Value type: <stringlist> 26 Value type: <stringlist>
28 Definition: must be "wdog", "fatal", "ready", "handover", "stop-ack" 27 Definition: The interrupts needed depends on the compatible
28 string:
29 qcom,msm8974-adsp-pil:
30 qcom,msm8996-adsp-pil:
31 qcom,msm8996-slpi-pil:
32 qcom,qcs404-adsp-pas:
33 qcom,qcs404-cdsp-pas:
34 qcom,sdm845-adsp-pas:
35 qcom,sdm845-cdsp-pas:
36 must be "wdog", "fatal", "ready", "handover", "stop-ack"
37 qcom,qcs404-wcss-pas:
38 must be "wdog", "fatal", "ready", "handover", "stop-ack",
39 "shutdown-ack"
40
41- firmware-name:
42 Usage: optional
43 Value type: <string>
44 Definition: must list the relative firmware image path for the
45 Hexagon Core.
29 46
30- clocks: 47- clocks:
31 Usage: required 48 Usage: required
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
index 9ff5b0309417..41ca5df5be5a 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
@@ -28,24 +28,51 @@ on the Qualcomm Hexagon core.
28- interrupts-extended: 28- interrupts-extended:
29 Usage: required 29 Usage: required
30 Value type: <prop-encoded-array> 30 Value type: <prop-encoded-array>
31 Definition: must list the watchdog, fatal IRQs ready, handover and 31 Definition: reference to the interrupts that match interrupt-names
32 stop-ack IRQs
33 32
34- interrupt-names: 33- interrupt-names:
35 Usage: required 34 Usage: required
36 Value type: <stringlist> 35 Value type: <stringlist>
37 Definition: must be "wdog", "fatal", "ready", "handover", "stop-ack" 36 Definition: The interrupts needed depends on the the compatible
37 string:
38 qcom,q6v5-pil:
39 qcom,ipq8074-wcss-pil:
40 qcom,msm8916-mss-pil:
41 qcom,msm8974-mss-pil:
42 must be "wdog", "fatal", "ready", "handover", "stop-ack"
43 qcom,msm8996-mss-pil:
44 qcom,sdm845-mss-pil:
45 must be "wdog", "fatal", "ready", "handover", "stop-ack",
46 "shutdown-ack"
47
48- firmware-name:
49 Usage: optional
50 Value type: <stringlist>
51 Definition: must list the relative firmware image paths for mba and
52 modem. They are used for booting and authenticating the
53 Hexagon core.
38 54
39- clocks: 55- clocks:
40 Usage: required 56 Usage: required
41 Value type: <phandle> 57 Value type: <phandle>
42 Definition: reference to the iface, bus and mem clocks to be held on 58 Definition: reference to the clocks that match clock-names
43 behalf of the booting of the Hexagon core
44 59
45- clock-names: 60- clock-names:
46 Usage: required 61 Usage: required
47 Value type: <stringlist> 62 Value type: <stringlist>
48 Definition: must be "iface", "bus", "mem" 63 Definition: The clocks needed depend on the compatible string:
64 qcom,ipq8074-wcss-pil:
65 no clock names required
66 qcom,q6v5-pil:
67 qcom,msm8916-mss-pil:
68 qcom,msm8974-mss-pil:
69 must be "iface", "bus", "mem", "xo"
70 qcom,msm8996-mss-pil:
71 must be "iface", "bus", "mem", "xo", "gpll0_mss",
72 "snoc_axi", "mnoc_axi", "pnoc", "qdss"
73 qcom,sdm845-mss-pil:
74 must be "iface", "bus", "mem", "xo", "gpll0_mss",
75 "snoc_axi", "mnoc_axi", "prng"
49 76
50- resets: 77- resets:
51 Usage: required 78 Usage: required
@@ -65,6 +92,19 @@ on the Qualcomm Hexagon core.
65 must be "mss_restart", "pdc_reset" for the modem 92 must be "mss_restart", "pdc_reset" for the modem
66 sub-system on SDM845 SoCs 93 sub-system on SDM845 SoCs
67 94
95For the compatible strings below the following supplies are required:
96 "qcom,q6v5-pil"
97 "qcom,msm8916-mss-pil",
98- cx-supply:
99- mx-supply:
100- pll-supply:
101 Usage: required
102 Value type: <phandle>
103 Definition: reference to the regulators to be held on behalf of the
104 booting of the Hexagon core
105
106For the compatible string below the following supplies are required:
107 "qcom,msm8974-mss-pil"
68- cx-supply: 108- cx-supply:
69- mss-supply: 109- mss-supply:
70- mx-supply: 110- mx-supply:
@@ -74,6 +114,33 @@ on the Qualcomm Hexagon core.
74 Definition: reference to the regulators to be held on behalf of the 114 Definition: reference to the regulators to be held on behalf of the
75 booting of the Hexagon core 115 booting of the Hexagon core
76 116
117For the compatible string below the following supplies are required:
118 "qcom,msm8996-mss-pil"
119- pll-supply:
120 Usage: required
121 Value type: <phandle>
122 Definition: reference to the regulators to be held on behalf of the
123 booting of the Hexagon core
124
125- power-domains:
126 Usage: required
127 Value type: <phandle>
128 Definition: reference to power-domains that match power-domain-names
129
130- power-domain-names:
131 Usage: required
132 Value type: <stringlist>
133 Definition: The power-domains needed depend on the compatible string:
134 qcom,q6v5-pil:
135 qcom,ipq8074-wcss-pil:
136 qcom,msm8916-mss-pil:
137 qcom,msm8974-mss-pil:
138 no power-domain names required
139 qcom,msm8996-mss-pil:
140 must be "cx", "mx"
141 qcom,sdm845-mss-pil:
142 must be "cx", "mx", "mss", "load_state"
143
77- qcom,smem-states: 144- qcom,smem-states:
78 Usage: required 145 Usage: required
79 Value type: <phandle> 146 Value type: <phandle>
diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
index 79374d1de311..1f3ef9ee493c 100644
--- a/drivers/remoteproc/qcom_q6v5_adsp.c
+++ b/drivers/remoteproc/qcom_q6v5_adsp.c
@@ -48,7 +48,7 @@
48 48
49/* list of clocks required by ADSP PIL */ 49/* list of clocks required by ADSP PIL */
50static const char * const adsp_clk_id[] = { 50static const char * const adsp_clk_id[] = {
51 "sway_cbcr", "lpass_aon", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr", 51 "sway_cbcr", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr",
52 "qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core", 52 "qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core",
53}; 53};
54 54
@@ -439,6 +439,10 @@ static int adsp_probe(struct platform_device *pdev)
439 adsp->sysmon = qcom_add_sysmon_subdev(rproc, 439 adsp->sysmon = qcom_add_sysmon_subdev(rproc,
440 desc->sysmon_name, 440 desc->sysmon_name,
441 desc->ssctl_id); 441 desc->ssctl_id);
442 if (IS_ERR(adsp->sysmon)) {
443 ret = PTR_ERR(adsp->sysmon);
444 goto disable_pm;
445 }
442 446
443 ret = rproc_add(rproc); 447 ret = rproc_add(rproc);
444 if (ret) 448 if (ret)
diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index 01be7314e176..eacdf10fcfaf 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -25,6 +25,8 @@
25#include <linux/of_address.h> 25#include <linux/of_address.h>
26#include <linux/of_device.h> 26#include <linux/of_device.h>
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/pm_domain.h>
29#include <linux/pm_runtime.h>
28#include <linux/regmap.h> 30#include <linux/regmap.h>
29#include <linux/regulator/consumer.h> 31#include <linux/regulator/consumer.h>
30#include <linux/remoteproc.h> 32#include <linux/remoteproc.h>
@@ -131,6 +133,8 @@ struct rproc_hexagon_res {
131 char **proxy_clk_names; 133 char **proxy_clk_names;
132 char **reset_clk_names; 134 char **reset_clk_names;
133 char **active_clk_names; 135 char **active_clk_names;
136 char **active_pd_names;
137 char **proxy_pd_names;
134 int version; 138 int version;
135 bool need_mem_protection; 139 bool need_mem_protection;
136 bool has_alt_reset; 140 bool has_alt_reset;
@@ -156,9 +160,13 @@ struct q6v5 {
156 struct clk *active_clks[8]; 160 struct clk *active_clks[8];
157 struct clk *reset_clks[4]; 161 struct clk *reset_clks[4];
158 struct clk *proxy_clks[4]; 162 struct clk *proxy_clks[4];
163 struct device *active_pds[1];
164 struct device *proxy_pds[3];
159 int active_clk_count; 165 int active_clk_count;
160 int reset_clk_count; 166 int reset_clk_count;
161 int proxy_clk_count; 167 int proxy_clk_count;
168 int active_pd_count;
169 int proxy_pd_count;
162 170
163 struct reg_info active_regs[1]; 171 struct reg_info active_regs[1];
164 struct reg_info proxy_regs[3]; 172 struct reg_info proxy_regs[3];
@@ -188,6 +196,7 @@ struct q6v5 {
188 bool has_alt_reset; 196 bool has_alt_reset;
189 int mpss_perm; 197 int mpss_perm;
190 int mba_perm; 198 int mba_perm;
199 const char *hexagon_mdt_image;
191 int version; 200 int version;
192}; 201};
193 202
@@ -321,6 +330,41 @@ static void q6v5_clk_disable(struct device *dev,
321 clk_disable_unprepare(clks[i]); 330 clk_disable_unprepare(clks[i]);
322} 331}
323 332
333static int q6v5_pds_enable(struct q6v5 *qproc, struct device **pds,
334 size_t pd_count)
335{
336 int ret;
337 int i;
338
339 for (i = 0; i < pd_count; i++) {
340 dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
341 ret = pm_runtime_get_sync(pds[i]);
342 if (ret < 0)
343 goto unroll_pd_votes;
344 }
345
346 return 0;
347
348unroll_pd_votes:
349 for (i--; i >= 0; i--) {
350 dev_pm_genpd_set_performance_state(pds[i], 0);
351 pm_runtime_put(pds[i]);
352 }
353
354 return ret;
355};
356
357static void q6v5_pds_disable(struct q6v5 *qproc, struct device **pds,
358 size_t pd_count)
359{
360 int i;
361
362 for (i = 0; i < pd_count; i++) {
363 dev_pm_genpd_set_performance_state(pds[i], 0);
364 pm_runtime_put(pds[i]);
365 }
366}
367
324static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm, 368static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm,
325 bool remote_owner, phys_addr_t addr, 369 bool remote_owner, phys_addr_t addr,
326 size_t size) 370 size_t size)
@@ -690,11 +734,23 @@ static int q6v5_mba_load(struct q6v5 *qproc)
690 734
691 qcom_q6v5_prepare(&qproc->q6v5); 735 qcom_q6v5_prepare(&qproc->q6v5);
692 736
737 ret = q6v5_pds_enable(qproc, qproc->active_pds, qproc->active_pd_count);
738 if (ret < 0) {
739 dev_err(qproc->dev, "failed to enable active power domains\n");
740 goto disable_irqs;
741 }
742
743 ret = q6v5_pds_enable(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
744 if (ret < 0) {
745 dev_err(qproc->dev, "failed to enable proxy power domains\n");
746 goto disable_active_pds;
747 }
748
693 ret = q6v5_regulator_enable(qproc, qproc->proxy_regs, 749 ret = q6v5_regulator_enable(qproc, qproc->proxy_regs,
694 qproc->proxy_reg_count); 750 qproc->proxy_reg_count);
695 if (ret) { 751 if (ret) {
696 dev_err(qproc->dev, "failed to enable proxy supplies\n"); 752 dev_err(qproc->dev, "failed to enable proxy supplies\n");
697 goto disable_irqs; 753 goto disable_proxy_pds;
698 } 754 }
699 755
700 ret = q6v5_clk_enable(qproc->dev, qproc->proxy_clks, 756 ret = q6v5_clk_enable(qproc->dev, qproc->proxy_clks,
@@ -791,6 +847,10 @@ disable_proxy_clk:
791disable_proxy_reg: 847disable_proxy_reg:
792 q6v5_regulator_disable(qproc, qproc->proxy_regs, 848 q6v5_regulator_disable(qproc, qproc->proxy_regs,
793 qproc->proxy_reg_count); 849 qproc->proxy_reg_count);
850disable_proxy_pds:
851 q6v5_pds_disable(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
852disable_active_pds:
853 q6v5_pds_disable(qproc, qproc->active_pds, qproc->active_pd_count);
794disable_irqs: 854disable_irqs:
795 qcom_q6v5_unprepare(&qproc->q6v5); 855 qcom_q6v5_unprepare(&qproc->q6v5);
796 856
@@ -830,6 +890,7 @@ static void q6v5_mba_reclaim(struct q6v5 *qproc)
830 qproc->active_clk_count); 890 qproc->active_clk_count);
831 q6v5_regulator_disable(qproc, qproc->active_regs, 891 q6v5_regulator_disable(qproc, qproc->active_regs,
832 qproc->active_reg_count); 892 qproc->active_reg_count);
893 q6v5_pds_disable(qproc, qproc->active_pds, qproc->active_pd_count);
833 894
834 /* In case of failure or coredump scenario where reclaiming MBA memory 895 /* In case of failure or coredump scenario where reclaiming MBA memory
835 * could not happen reclaim it here. 896 * could not happen reclaim it here.
@@ -841,6 +902,8 @@ static void q6v5_mba_reclaim(struct q6v5 *qproc)
841 902
842 ret = qcom_q6v5_unprepare(&qproc->q6v5); 903 ret = qcom_q6v5_unprepare(&qproc->q6v5);
843 if (ret) { 904 if (ret) {
905 q6v5_pds_disable(qproc, qproc->proxy_pds,
906 qproc->proxy_pd_count);
844 q6v5_clk_disable(qproc->dev, qproc->proxy_clks, 907 q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
845 qproc->proxy_clk_count); 908 qproc->proxy_clk_count);
846 q6v5_regulator_disable(qproc, qproc->proxy_regs, 909 q6v5_regulator_disable(qproc, qproc->proxy_regs,
@@ -860,17 +923,26 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
860 phys_addr_t min_addr = PHYS_ADDR_MAX; 923 phys_addr_t min_addr = PHYS_ADDR_MAX;
861 phys_addr_t max_addr = 0; 924 phys_addr_t max_addr = 0;
862 bool relocate = false; 925 bool relocate = false;
863 char seg_name[10]; 926 char *fw_name;
927 size_t fw_name_len;
864 ssize_t offset; 928 ssize_t offset;
865 size_t size = 0; 929 size_t size = 0;
866 void *ptr; 930 void *ptr;
867 int ret; 931 int ret;
868 int i; 932 int i;
869 933
870 ret = request_firmware(&fw, "modem.mdt", qproc->dev); 934 fw_name_len = strlen(qproc->hexagon_mdt_image);
935 if (fw_name_len <= 4)
936 return -EINVAL;
937
938 fw_name = kstrdup(qproc->hexagon_mdt_image, GFP_KERNEL);
939 if (!fw_name)
940 return -ENOMEM;
941
942 ret = request_firmware(&fw, fw_name, qproc->dev);
871 if (ret < 0) { 943 if (ret < 0) {
872 dev_err(qproc->dev, "unable to load modem.mdt\n"); 944 dev_err(qproc->dev, "unable to load %s\n", fw_name);
873 return ret; 945 goto out;
874 } 946 }
875 947
876 /* Initialize the RMB validator */ 948 /* Initialize the RMB validator */
@@ -918,10 +990,11 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
918 ptr = qproc->mpss_region + offset; 990 ptr = qproc->mpss_region + offset;
919 991
920 if (phdr->p_filesz) { 992 if (phdr->p_filesz) {
921 snprintf(seg_name, sizeof(seg_name), "modem.b%02d", i); 993 /* Replace "xxx.xxx" with "xxx.bxx" */
922 ret = request_firmware(&seg_fw, seg_name, qproc->dev); 994 sprintf(fw_name + fw_name_len - 3, "b%02d", i);
995 ret = request_firmware(&seg_fw, fw_name, qproc->dev);
923 if (ret) { 996 if (ret) {
924 dev_err(qproc->dev, "failed to load %s\n", seg_name); 997 dev_err(qproc->dev, "failed to load %s\n", fw_name);
925 goto release_firmware; 998 goto release_firmware;
926 } 999 }
927 1000
@@ -960,6 +1033,8 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
960 1033
961release_firmware: 1034release_firmware:
962 release_firmware(fw); 1035 release_firmware(fw);
1036out:
1037 kfree(fw_name);
963 1038
964 return ret < 0 ? ret : 0; 1039 return ret < 0 ? ret : 0;
965} 1040}
@@ -1075,9 +1150,10 @@ static int qcom_q6v5_register_dump_segments(struct rproc *rproc,
1075 unsigned long i; 1150 unsigned long i;
1076 int ret; 1151 int ret;
1077 1152
1078 ret = request_firmware(&fw, "modem.mdt", qproc->dev); 1153 ret = request_firmware(&fw, qproc->hexagon_mdt_image, qproc->dev);
1079 if (ret < 0) { 1154 if (ret < 0) {
1080 dev_err(qproc->dev, "unable to load modem.mdt\n"); 1155 dev_err(qproc->dev, "unable to load %s\n",
1156 qproc->hexagon_mdt_image);
1081 return ret; 1157 return ret;
1082 } 1158 }
1083 1159
@@ -1121,6 +1197,7 @@ static void qcom_msa_handover(struct qcom_q6v5 *q6v5)
1121 qproc->proxy_clk_count); 1197 qproc->proxy_clk_count);
1122 q6v5_regulator_disable(qproc, qproc->proxy_regs, 1198 q6v5_regulator_disable(qproc, qproc->proxy_regs,
1123 qproc->proxy_reg_count); 1199 qproc->proxy_reg_count);
1200 q6v5_pds_disable(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
1124} 1201}
1125 1202
1126static int q6v5_init_mem(struct q6v5 *qproc, struct platform_device *pdev) 1203static int q6v5_init_mem(struct q6v5 *qproc, struct platform_device *pdev)
@@ -1181,6 +1258,45 @@ static int q6v5_init_clocks(struct device *dev, struct clk **clks,
1181 return i; 1258 return i;
1182} 1259}
1183 1260
1261static int q6v5_pds_attach(struct device *dev, struct device **devs,
1262 char **pd_names)
1263{
1264 size_t num_pds = 0;
1265 int ret;
1266 int i;
1267
1268 if (!pd_names)
1269 return 0;
1270
1271 while (pd_names[num_pds])
1272 num_pds++;
1273
1274 for (i = 0; i < num_pds; i++) {
1275 devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
1276 if (IS_ERR(devs[i])) {
1277 ret = PTR_ERR(devs[i]);
1278 goto unroll_attach;
1279 }
1280 }
1281
1282 return num_pds;
1283
1284unroll_attach:
1285 for (i--; i >= 0; i--)
1286 dev_pm_domain_detach(devs[i], false);
1287
1288 return ret;
1289};
1290
1291static void q6v5_pds_detach(struct q6v5 *qproc, struct device **pds,
1292 size_t pd_count)
1293{
1294 int i;
1295
1296 for (i = 0; i < pd_count; i++)
1297 dev_pm_domain_detach(pds[i], false);
1298}
1299
1184static int q6v5_init_reset(struct q6v5 *qproc) 1300static int q6v5_init_reset(struct q6v5 *qproc)
1185{ 1301{
1186 qproc->mss_restart = devm_reset_control_get_exclusive(qproc->dev, 1302 qproc->mss_restart = devm_reset_control_get_exclusive(qproc->dev,
@@ -1253,6 +1369,7 @@ static int q6v5_probe(struct platform_device *pdev)
1253 const struct rproc_hexagon_res *desc; 1369 const struct rproc_hexagon_res *desc;
1254 struct q6v5 *qproc; 1370 struct q6v5 *qproc;
1255 struct rproc *rproc; 1371 struct rproc *rproc;
1372 const char *mba_image;
1256 int ret; 1373 int ret;
1257 1374
1258 desc = of_device_get_match_data(&pdev->dev); 1375 desc = of_device_get_match_data(&pdev->dev);
@@ -1262,16 +1379,30 @@ static int q6v5_probe(struct platform_device *pdev)
1262 if (desc->need_mem_protection && !qcom_scm_is_available()) 1379 if (desc->need_mem_protection && !qcom_scm_is_available())
1263 return -EPROBE_DEFER; 1380 return -EPROBE_DEFER;
1264 1381
1382 mba_image = desc->hexagon_mba_image;
1383 ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name",
1384 0, &mba_image);
1385 if (ret < 0 && ret != -EINVAL)
1386 return ret;
1387
1265 rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_ops, 1388 rproc = rproc_alloc(&pdev->dev, pdev->name, &q6v5_ops,
1266 desc->hexagon_mba_image, sizeof(*qproc)); 1389 mba_image, sizeof(*qproc));
1267 if (!rproc) { 1390 if (!rproc) {
1268 dev_err(&pdev->dev, "failed to allocate rproc\n"); 1391 dev_err(&pdev->dev, "failed to allocate rproc\n");
1269 return -ENOMEM; 1392 return -ENOMEM;
1270 } 1393 }
1271 1394
1395 rproc->auto_boot = false;
1396
1272 qproc = (struct q6v5 *)rproc->priv; 1397 qproc = (struct q6v5 *)rproc->priv;
1273 qproc->dev = &pdev->dev; 1398 qproc->dev = &pdev->dev;
1274 qproc->rproc = rproc; 1399 qproc->rproc = rproc;
1400 qproc->hexagon_mdt_image = "modem.mdt";
1401 ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name",
1402 1, &qproc->hexagon_mdt_image);
1403 if (ret < 0 && ret != -EINVAL)
1404 return ret;
1405
1275 platform_set_drvdata(pdev, qproc); 1406 platform_set_drvdata(pdev, qproc);
1276 1407
1277 ret = q6v5_init_mem(qproc, pdev); 1408 ret = q6v5_init_mem(qproc, pdev);
@@ -1322,10 +1453,26 @@ static int q6v5_probe(struct platform_device *pdev)
1322 } 1453 }
1323 qproc->active_reg_count = ret; 1454 qproc->active_reg_count = ret;
1324 1455
1456 ret = q6v5_pds_attach(&pdev->dev, qproc->active_pds,
1457 desc->active_pd_names);
1458 if (ret < 0) {
1459 dev_err(&pdev->dev, "Failed to attach active power domains\n");
1460 goto free_rproc;
1461 }
1462 qproc->active_pd_count = ret;
1463
1464 ret = q6v5_pds_attach(&pdev->dev, qproc->proxy_pds,
1465 desc->proxy_pd_names);
1466 if (ret < 0) {
1467 dev_err(&pdev->dev, "Failed to init power domains\n");
1468 goto detach_active_pds;
1469 }
1470 qproc->proxy_pd_count = ret;
1471
1325 qproc->has_alt_reset = desc->has_alt_reset; 1472 qproc->has_alt_reset = desc->has_alt_reset;
1326 ret = q6v5_init_reset(qproc); 1473 ret = q6v5_init_reset(qproc);
1327 if (ret) 1474 if (ret)
1328 goto free_rproc; 1475 goto detach_proxy_pds;
1329 1476
1330 qproc->version = desc->version; 1477 qproc->version = desc->version;
1331 qproc->need_mem_protection = desc->need_mem_protection; 1478 qproc->need_mem_protection = desc->need_mem_protection;
@@ -1333,7 +1480,7 @@ static int q6v5_probe(struct platform_device *pdev)
1333 ret = qcom_q6v5_init(&qproc->q6v5, pdev, rproc, MPSS_CRASH_REASON_SMEM, 1480 ret = qcom_q6v5_init(&qproc->q6v5, pdev, rproc, MPSS_CRASH_REASON_SMEM,
1334 qcom_msa_handover); 1481 qcom_msa_handover);
1335 if (ret) 1482 if (ret)
1336 goto free_rproc; 1483 goto detach_proxy_pds;
1337 1484
1338 qproc->mpss_perm = BIT(QCOM_SCM_VMID_HLOS); 1485 qproc->mpss_perm = BIT(QCOM_SCM_VMID_HLOS);
1339 qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS); 1486 qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
@@ -1341,13 +1488,21 @@ static int q6v5_probe(struct platform_device *pdev)
1341 qcom_add_smd_subdev(rproc, &qproc->smd_subdev); 1488 qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
1342 qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss"); 1489 qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
1343 qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12); 1490 qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
1491 if (IS_ERR(qproc->sysmon)) {
1492 ret = PTR_ERR(qproc->sysmon);
1493 goto detach_proxy_pds;
1494 }
1344 1495
1345 ret = rproc_add(rproc); 1496 ret = rproc_add(rproc);
1346 if (ret) 1497 if (ret)
1347 goto free_rproc; 1498 goto detach_proxy_pds;
1348 1499
1349 return 0; 1500 return 0;
1350 1501
1502detach_proxy_pds:
1503 q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
1504detach_active_pds:
1505 q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count);
1351free_rproc: 1506free_rproc:
1352 rproc_free(rproc); 1507 rproc_free(rproc);
1353 1508
@@ -1364,6 +1519,10 @@ static int q6v5_remove(struct platform_device *pdev)
1364 qcom_remove_glink_subdev(qproc->rproc, &qproc->glink_subdev); 1519 qcom_remove_glink_subdev(qproc->rproc, &qproc->glink_subdev);
1365 qcom_remove_smd_subdev(qproc->rproc, &qproc->smd_subdev); 1520 qcom_remove_smd_subdev(qproc->rproc, &qproc->smd_subdev);
1366 qcom_remove_ssr_subdev(qproc->rproc, &qproc->ssr_subdev); 1521 qcom_remove_ssr_subdev(qproc->rproc, &qproc->ssr_subdev);
1522
1523 q6v5_pds_detach(qproc, qproc->active_pds, qproc->active_pd_count);
1524 q6v5_pds_detach(qproc, qproc->proxy_pds, qproc->proxy_pd_count);
1525
1367 rproc_free(qproc->rproc); 1526 rproc_free(qproc->rproc);
1368 1527
1369 return 0; 1528 return 0;
@@ -1388,6 +1547,16 @@ static const struct rproc_hexagon_res sdm845_mss = {
1388 "mnoc_axi", 1547 "mnoc_axi",
1389 NULL 1548 NULL
1390 }, 1549 },
1550 .active_pd_names = (char*[]){
1551 "load_state",
1552 NULL
1553 },
1554 .proxy_pd_names = (char*[]){
1555 "cx",
1556 "mx",
1557 "mss",
1558 NULL
1559 },
1391 .need_mem_protection = true, 1560 .need_mem_protection = true,
1392 .has_alt_reset = true, 1561 .has_alt_reset = true,
1393 .version = MSS_SDM845, 1562 .version = MSS_SDM845,
@@ -1395,16 +1564,26 @@ static const struct rproc_hexagon_res sdm845_mss = {
1395 1564
1396static const struct rproc_hexagon_res msm8996_mss = { 1565static const struct rproc_hexagon_res msm8996_mss = {
1397 .hexagon_mba_image = "mba.mbn", 1566 .hexagon_mba_image = "mba.mbn",
1567 .proxy_supply = (struct qcom_mss_reg_res[]) {
1568 {
1569 .supply = "pll",
1570 .uA = 100000,
1571 },
1572 {}
1573 },
1398 .proxy_clk_names = (char*[]){ 1574 .proxy_clk_names = (char*[]){
1399 "xo", 1575 "xo",
1400 "pnoc", 1576 "pnoc",
1577 "qdss",
1401 NULL 1578 NULL
1402 }, 1579 },
1403 .active_clk_names = (char*[]){ 1580 .active_clk_names = (char*[]){
1404 "iface", 1581 "iface",
1405 "bus", 1582 "bus",
1406 "mem", 1583 "mem",
1407 "gpll0_mss_clk", 1584 "gpll0_mss",
1585 "snoc_axi",
1586 "mnoc_axi",
1408 NULL 1587 NULL
1409 }, 1588 },
1410 .need_mem_protection = true, 1589 .need_mem_protection = true,
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index b1e63fcd5fdf..f280f196d007 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -258,6 +258,7 @@ static int adsp_probe(struct platform_device *pdev)
258 const struct adsp_data *desc; 258 const struct adsp_data *desc;
259 struct qcom_adsp *adsp; 259 struct qcom_adsp *adsp;
260 struct rproc *rproc; 260 struct rproc *rproc;
261 const char *fw_name;
261 int ret; 262 int ret;
262 263
263 desc = of_device_get_match_data(&pdev->dev); 264 desc = of_device_get_match_data(&pdev->dev);
@@ -267,8 +268,14 @@ static int adsp_probe(struct platform_device *pdev)
267 if (!qcom_scm_is_available()) 268 if (!qcom_scm_is_available())
268 return -EPROBE_DEFER; 269 return -EPROBE_DEFER;
269 270
271 fw_name = desc->firmware_name;
272 ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
273 &fw_name);
274 if (ret < 0 && ret != -EINVAL)
275 return ret;
276
270 rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops, 277 rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops,
271 desc->firmware_name, sizeof(*adsp)); 278 fw_name, sizeof(*adsp));
272 if (!rproc) { 279 if (!rproc) {
273 dev_err(&pdev->dev, "unable to allocate remoteproc\n"); 280 dev_err(&pdev->dev, "unable to allocate remoteproc\n");
274 return -ENOMEM; 281 return -ENOMEM;
@@ -304,6 +311,10 @@ static int adsp_probe(struct platform_device *pdev)
304 adsp->sysmon = qcom_add_sysmon_subdev(rproc, 311 adsp->sysmon = qcom_add_sysmon_subdev(rproc,
305 desc->sysmon_name, 312 desc->sysmon_name,
306 desc->ssctl_id); 313 desc->ssctl_id);
314 if (IS_ERR(adsp->sysmon)) {
315 ret = PTR_ERR(adsp->sysmon);
316 goto free_rproc;
317 }
307 318
308 ret = rproc_add(rproc); 319 ret = rproc_add(rproc);
309 if (ret) 320 if (ret)
diff --git a/drivers/remoteproc/qcom_sysmon.c b/drivers/remoteproc/qcom_sysmon.c
index e976a602b015..c231314eab66 100644
--- a/drivers/remoteproc/qcom_sysmon.c
+++ b/drivers/remoteproc/qcom_sysmon.c
@@ -6,8 +6,9 @@
6#include <linux/module.h> 6#include <linux/module.h>
7#include <linux/notifier.h> 7#include <linux/notifier.h>
8#include <linux/slab.h> 8#include <linux/slab.h>
9#include <linux/interrupt.h>
9#include <linux/io.h> 10#include <linux/io.h>
10#include <linux/notifier.h> 11#include <linux/of_irq.h>
11#include <linux/of_platform.h> 12#include <linux/of_platform.h>
12#include <linux/platform_device.h> 13#include <linux/platform_device.h>
13#include <linux/remoteproc/qcom_rproc.h> 14#include <linux/remoteproc/qcom_rproc.h>
@@ -25,6 +26,7 @@ struct qcom_sysmon {
25 26
26 const char *name; 27 const char *name;
27 28
29 int shutdown_irq;
28 int ssctl_version; 30 int ssctl_version;
29 int ssctl_instance; 31 int ssctl_instance;
30 32
@@ -34,6 +36,8 @@ struct qcom_sysmon {
34 36
35 struct rpmsg_endpoint *ept; 37 struct rpmsg_endpoint *ept;
36 struct completion comp; 38 struct completion comp;
39 struct completion ind_comp;
40 struct completion shutdown_comp;
37 struct mutex lock; 41 struct mutex lock;
38 42
39 bool ssr_ack; 43 bool ssr_ack;
@@ -137,6 +141,7 @@ static int sysmon_callback(struct rpmsg_device *rpdev, void *data, int count,
137} 141}
138 142
139#define SSCTL_SHUTDOWN_REQ 0x21 143#define SSCTL_SHUTDOWN_REQ 0x21
144#define SSCTL_SHUTDOWN_READY_IND 0x21
140#define SSCTL_SUBSYS_EVENT_REQ 0x23 145#define SSCTL_SUBSYS_EVENT_REQ 0x23
141 146
142#define SSCTL_MAX_MSG_LEN 7 147#define SSCTL_MAX_MSG_LEN 7
@@ -252,6 +257,29 @@ static struct qmi_elem_info ssctl_subsys_event_resp_ei[] = {
252 {} 257 {}
253}; 258};
254 259
260static struct qmi_elem_info ssctl_shutdown_ind_ei[] = {
261 {}
262};
263
264static void sysmon_ind_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
265 struct qmi_txn *txn, const void *data)
266{
267 struct qcom_sysmon *sysmon = container_of(qmi, struct qcom_sysmon, qmi);
268
269 complete(&sysmon->ind_comp);
270}
271
272static struct qmi_msg_handler qmi_indication_handler[] = {
273 {
274 .type = QMI_INDICATION,
275 .msg_id = SSCTL_SHUTDOWN_READY_IND,
276 .ei = ssctl_shutdown_ind_ei,
277 .decoded_size = 0,
278 .fn = sysmon_ind_cb
279 },
280 {}
281};
282
255/** 283/**
256 * ssctl_request_shutdown() - request shutdown via SSCTL QMI service 284 * ssctl_request_shutdown() - request shutdown via SSCTL QMI service
257 * @sysmon: sysmon context 285 * @sysmon: sysmon context
@@ -262,6 +290,8 @@ static void ssctl_request_shutdown(struct qcom_sysmon *sysmon)
262 struct qmi_txn txn; 290 struct qmi_txn txn;
263 int ret; 291 int ret;
264 292
293 reinit_completion(&sysmon->ind_comp);
294 reinit_completion(&sysmon->shutdown_comp);
265 ret = qmi_txn_init(&sysmon->qmi, &txn, ssctl_shutdown_resp_ei, &resp); 295 ret = qmi_txn_init(&sysmon->qmi, &txn, ssctl_shutdown_resp_ei, &resp);
266 if (ret < 0) { 296 if (ret < 0) {
267 dev_err(sysmon->dev, "failed to allocate QMI txn\n"); 297 dev_err(sysmon->dev, "failed to allocate QMI txn\n");
@@ -283,6 +313,17 @@ static void ssctl_request_shutdown(struct qcom_sysmon *sysmon)
283 dev_err(sysmon->dev, "shutdown request failed\n"); 313 dev_err(sysmon->dev, "shutdown request failed\n");
284 else 314 else
285 dev_dbg(sysmon->dev, "shutdown request completed\n"); 315 dev_dbg(sysmon->dev, "shutdown request completed\n");
316
317 if (sysmon->shutdown_irq > 0) {
318 ret = wait_for_completion_timeout(&sysmon->shutdown_comp,
319 10 * HZ);
320 if (!ret) {
321 ret = try_wait_for_completion(&sysmon->ind_comp);
322 if (!ret)
323 dev_err(sysmon->dev,
324 "timeout waiting for shutdown ack\n");
325 }
326 }
286} 327}
287 328
288/** 329/**
@@ -432,6 +473,15 @@ static int sysmon_notify(struct notifier_block *nb, unsigned long event,
432 return NOTIFY_DONE; 473 return NOTIFY_DONE;
433} 474}
434 475
476static irqreturn_t sysmon_shutdown_interrupt(int irq, void *data)
477{
478 struct qcom_sysmon *sysmon = data;
479
480 complete(&sysmon->shutdown_comp);
481
482 return IRQ_HANDLED;
483}
484
435/** 485/**
436 * qcom_add_sysmon_subdev() - create a sysmon subdev for the given remoteproc 486 * qcom_add_sysmon_subdev() - create a sysmon subdev for the given remoteproc
437 * @rproc: rproc context to associate the subdev with 487 * @rproc: rproc context to associate the subdev with
@@ -449,7 +499,7 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
449 499
450 sysmon = kzalloc(sizeof(*sysmon), GFP_KERNEL); 500 sysmon = kzalloc(sizeof(*sysmon), GFP_KERNEL);
451 if (!sysmon) 501 if (!sysmon)
452 return NULL; 502 return ERR_PTR(-ENOMEM);
453 503
454 sysmon->dev = rproc->dev.parent; 504 sysmon->dev = rproc->dev.parent;
455 sysmon->rproc = rproc; 505 sysmon->rproc = rproc;
@@ -458,13 +508,37 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
458 sysmon->ssctl_instance = ssctl_instance; 508 sysmon->ssctl_instance = ssctl_instance;
459 509
460 init_completion(&sysmon->comp); 510 init_completion(&sysmon->comp);
511 init_completion(&sysmon->ind_comp);
512 init_completion(&sysmon->shutdown_comp);
461 mutex_init(&sysmon->lock); 513 mutex_init(&sysmon->lock);
462 514
463 ret = qmi_handle_init(&sysmon->qmi, SSCTL_MAX_MSG_LEN, &ssctl_ops, NULL); 515 sysmon->shutdown_irq = of_irq_get_byname(sysmon->dev->of_node,
516 "shutdown-ack");
517 if (sysmon->shutdown_irq < 0) {
518 if (sysmon->shutdown_irq != -ENODATA) {
519 dev_err(sysmon->dev,
520 "failed to retrieve shutdown-ack IRQ\n");
521 return ERR_PTR(sysmon->shutdown_irq);
522 }
523 } else {
524 ret = devm_request_threaded_irq(sysmon->dev,
525 sysmon->shutdown_irq,
526 NULL, sysmon_shutdown_interrupt,
527 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
528 "q6v5 shutdown-ack", sysmon);
529 if (ret) {
530 dev_err(sysmon->dev,
531 "failed to acquire shutdown-ack IRQ\n");
532 return ERR_PTR(ret);
533 }
534 }
535
536 ret = qmi_handle_init(&sysmon->qmi, SSCTL_MAX_MSG_LEN, &ssctl_ops,
537 qmi_indication_handler);
464 if (ret < 0) { 538 if (ret < 0) {
465 dev_err(sysmon->dev, "failed to initialize qmi handle\n"); 539 dev_err(sysmon->dev, "failed to initialize qmi handle\n");
466 kfree(sysmon); 540 kfree(sysmon);
467 return NULL; 541 return ERR_PTR(ret);
468 } 542 }
469 543
470 qmi_add_lookup(&sysmon->qmi, 43, 0, 0); 544 qmi_add_lookup(&sysmon->qmi, 43, 0, 0);
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index b0e07e9f42d5..adcce523971e 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -553,6 +553,10 @@ static int wcnss_probe(struct platform_device *pdev)
553 553
554 qcom_add_smd_subdev(rproc, &wcnss->smd_subdev); 554 qcom_add_smd_subdev(rproc, &wcnss->smd_subdev);
555 wcnss->sysmon = qcom_add_sysmon_subdev(rproc, "wcnss", WCNSS_SSCTL_ID); 555 wcnss->sysmon = qcom_add_sysmon_subdev(rproc, "wcnss", WCNSS_SSCTL_ID);
556 if (IS_ERR(wcnss->sysmon)) {
557 ret = PTR_ERR(wcnss->sysmon);
558 goto free_rproc;
559 }
556 560
557 ret = rproc_add(rproc); 561 ret = rproc_add(rproc);
558 if (ret) 562 if (ret)
@@ -622,5 +626,5 @@ static void __exit wcnss_exit(void)
622} 626}
623module_exit(wcnss_exit); 627module_exit(wcnss_exit);
624 628
625MODULE_DESCRIPTION("Qualcomm Peripherial Image Loader for Wireless Subsystem"); 629MODULE_DESCRIPTION("Qualcomm Peripheral Image Loader for Wireless Subsystem");
626MODULE_LICENSE("GPL v2"); 630MODULE_LICENSE("GPL v2");
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 54ec38fc5dca..48feebd6d0a2 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -39,12 +39,16 @@
39#include <linux/idr.h> 39#include <linux/idr.h>
40#include <linux/elf.h> 40#include <linux/elf.h>
41#include <linux/crc32.h> 41#include <linux/crc32.h>
42#include <linux/of_reserved_mem.h>
42#include <linux/virtio_ids.h> 43#include <linux/virtio_ids.h>
43#include <linux/virtio_ring.h> 44#include <linux/virtio_ring.h>
44#include <asm/byteorder.h> 45#include <asm/byteorder.h>
46#include <linux/platform_device.h>
45 47
46#include "remoteproc_internal.h" 48#include "remoteproc_internal.h"
47 49
50#define HIGH_BITS_MASK 0xFFFFFFFF00000000ULL
51
48static DEFINE_MUTEX(rproc_list_mutex); 52static DEFINE_MUTEX(rproc_list_mutex);
49static LIST_HEAD(rproc_list); 53static LIST_HEAD(rproc_list);
50 54
@@ -145,7 +149,7 @@ static void rproc_disable_iommu(struct rproc *rproc)
145 iommu_domain_free(domain); 149 iommu_domain_free(domain);
146} 150}
147 151
148static phys_addr_t rproc_va_to_pa(void *cpu_addr) 152phys_addr_t rproc_va_to_pa(void *cpu_addr)
149{ 153{
150 /* 154 /*
151 * Return physical address according to virtual address location 155 * Return physical address according to virtual address location
@@ -160,6 +164,7 @@ static phys_addr_t rproc_va_to_pa(void *cpu_addr)
160 WARN_ON(!virt_addr_valid(cpu_addr)); 164 WARN_ON(!virt_addr_valid(cpu_addr));
161 return virt_to_phys(cpu_addr); 165 return virt_to_phys(cpu_addr);
162} 166}
167EXPORT_SYMBOL(rproc_va_to_pa);
163 168
164/** 169/**
165 * rproc_da_to_va() - lookup the kernel virtual address for a remoteproc address 170 * rproc_da_to_va() - lookup the kernel virtual address for a remoteproc address
@@ -204,6 +209,10 @@ void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
204 list_for_each_entry(carveout, &rproc->carveouts, node) { 209 list_for_each_entry(carveout, &rproc->carveouts, node) {
205 int offset = da - carveout->da; 210 int offset = da - carveout->da;
206 211
212 /* Verify that carveout is allocated */
213 if (!carveout->va)
214 continue;
215
207 /* try next carveout if da is too small */ 216 /* try next carveout if da is too small */
208 if (offset < 0) 217 if (offset < 0)
209 continue; 218 continue;
@@ -272,25 +281,27 @@ rproc_find_carveout_by_name(struct rproc *rproc, const char *name, ...)
272 * @len: associated area size 281 * @len: associated area size
273 * 282 *
274 * This function is a helper function to verify requested device area (couple 283 * This function is a helper function to verify requested device area (couple
275 * da, len) is part of specified carevout. 284 * da, len) is part of specified carveout.
285 * If da is not set (defined as FW_RSC_ADDR_ANY), only requested length is
286 * checked.
276 * 287 *
277 * Return: 0 if carveout match request else -ENOMEM 288 * Return: 0 if carveout matches request else error
278 */ 289 */
279int rproc_check_carveout_da(struct rproc *rproc, struct rproc_mem_entry *mem, 290static int rproc_check_carveout_da(struct rproc *rproc,
280 u32 da, u32 len) 291 struct rproc_mem_entry *mem, u32 da, u32 len)
281{ 292{
282 struct device *dev = &rproc->dev; 293 struct device *dev = &rproc->dev;
283 int delta = 0; 294 int delta;
284 295
285 /* Check requested resource length */ 296 /* Check requested resource length */
286 if (len > mem->len) { 297 if (len > mem->len) {
287 dev_err(dev, "Registered carveout doesn't fit len request\n"); 298 dev_err(dev, "Registered carveout doesn't fit len request\n");
288 return -ENOMEM; 299 return -EINVAL;
289 } 300 }
290 301
291 if (da != FW_RSC_ADDR_ANY && mem->da == FW_RSC_ADDR_ANY) { 302 if (da != FW_RSC_ADDR_ANY && mem->da == FW_RSC_ADDR_ANY) {
292 /* Update existing carveout da */ 303 /* Address doesn't match registered carveout configuration */
293 mem->da = da; 304 return -EINVAL;
294 } else if (da != FW_RSC_ADDR_ANY && mem->da != FW_RSC_ADDR_ANY) { 305 } else if (da != FW_RSC_ADDR_ANY && mem->da != FW_RSC_ADDR_ANY) {
295 delta = da - mem->da; 306 delta = da - mem->da;
296 307
@@ -298,13 +309,13 @@ int rproc_check_carveout_da(struct rproc *rproc, struct rproc_mem_entry *mem,
298 if (delta < 0) { 309 if (delta < 0) {
299 dev_err(dev, 310 dev_err(dev,
300 "Registered carveout doesn't fit da request\n"); 311 "Registered carveout doesn't fit da request\n");
301 return -ENOMEM; 312 return -EINVAL;
302 } 313 }
303 314
304 if (delta + len > mem->len) { 315 if (delta + len > mem->len) {
305 dev_err(dev, 316 dev_err(dev,
306 "Registered carveout doesn't fit len request\n"); 317 "Registered carveout doesn't fit len request\n");
307 return -ENOMEM; 318 return -EINVAL;
308 } 319 }
309 } 320 }
310 321
@@ -418,8 +429,25 @@ static int rproc_vdev_do_start(struct rproc_subdev *subdev)
418static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed) 429static void rproc_vdev_do_stop(struct rproc_subdev *subdev, bool crashed)
419{ 430{
420 struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev); 431 struct rproc_vdev *rvdev = container_of(subdev, struct rproc_vdev, subdev);
432 int ret;
421 433
422 rproc_remove_virtio_dev(rvdev); 434 ret = device_for_each_child(&rvdev->dev, NULL, rproc_remove_virtio_dev);
435 if (ret)
436 dev_warn(&rvdev->dev, "can't remove vdev child device: %d\n", ret);
437}
438
439/**
440 * rproc_rvdev_release() - release the existence of a rvdev
441 *
442 * @dev: the subdevice's dev
443 */
444static void rproc_rvdev_release(struct device *dev)
445{
446 struct rproc_vdev *rvdev = container_of(dev, struct rproc_vdev, dev);
447
448 of_reserved_mem_device_release(dev);
449
450 kfree(rvdev);
423} 451}
424 452
425/** 453/**
@@ -455,6 +483,7 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
455 struct device *dev = &rproc->dev; 483 struct device *dev = &rproc->dev;
456 struct rproc_vdev *rvdev; 484 struct rproc_vdev *rvdev;
457 int i, ret; 485 int i, ret;
486 char name[16];
458 487
459 /* make sure resource isn't truncated */ 488 /* make sure resource isn't truncated */
460 if (sizeof(*rsc) + rsc->num_of_vrings * sizeof(struct fw_rsc_vdev_vring) 489 if (sizeof(*rsc) + rsc->num_of_vrings * sizeof(struct fw_rsc_vdev_vring)
@@ -488,6 +517,29 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
488 rvdev->rproc = rproc; 517 rvdev->rproc = rproc;
489 rvdev->index = rproc->nb_vdev++; 518 rvdev->index = rproc->nb_vdev++;
490 519
520 /* Initialise vdev subdevice */
521 snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
522 rvdev->dev.parent = rproc->dev.parent;
523 rvdev->dev.release = rproc_rvdev_release;
524 dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name);
525 dev_set_drvdata(&rvdev->dev, rvdev);
526
527 ret = device_register(&rvdev->dev);
528 if (ret) {
529 put_device(&rvdev->dev);
530 return ret;
531 }
532 /* Make device dma capable by inheriting from parent's capabilities */
533 set_dma_ops(&rvdev->dev, get_dma_ops(rproc->dev.parent));
534
535 ret = dma_coerce_mask_and_coherent(&rvdev->dev,
536 dma_get_mask(rproc->dev.parent));
537 if (ret) {
538 dev_warn(dev,
539 "Failed to set DMA mask %llx. Trying to continue... %x\n",
540 dma_get_mask(rproc->dev.parent), ret);
541 }
542
491 /* parse the vrings */ 543 /* parse the vrings */
492 for (i = 0; i < rsc->num_of_vrings; i++) { 544 for (i = 0; i < rsc->num_of_vrings; i++) {
493 ret = rproc_parse_vring(rvdev, rsc, i); 545 ret = rproc_parse_vring(rvdev, rsc, i);
@@ -518,7 +570,7 @@ unwind_vring_allocations:
518 for (i--; i >= 0; i--) 570 for (i--; i >= 0; i--)
519 rproc_free_vring(&rvdev->vring[i]); 571 rproc_free_vring(&rvdev->vring[i]);
520free_rvdev: 572free_rvdev:
521 kfree(rvdev); 573 device_unregister(&rvdev->dev);
522 return ret; 574 return ret;
523} 575}
524 576
@@ -536,7 +588,7 @@ void rproc_vdev_release(struct kref *ref)
536 588
537 rproc_remove_subdev(rproc, &rvdev->subdev); 589 rproc_remove_subdev(rproc, &rvdev->subdev);
538 list_del(&rvdev->node); 590 list_del(&rvdev->node);
539 kfree(rvdev); 591 device_unregister(&rvdev->dev);
540} 592}
541 593
542/** 594/**
@@ -558,9 +610,8 @@ void rproc_vdev_release(struct kref *ref)
558static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc, 610static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc,
559 int offset, int avail) 611 int offset, int avail)
560{ 612{
561 struct rproc_mem_entry *trace; 613 struct rproc_debug_trace *trace;
562 struct device *dev = &rproc->dev; 614 struct device *dev = &rproc->dev;
563 void *ptr;
564 char name[15]; 615 char name[15];
565 616
566 if (sizeof(*rsc) > avail) { 617 if (sizeof(*rsc) > avail) {
@@ -574,28 +625,23 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc,
574 return -EINVAL; 625 return -EINVAL;
575 } 626 }
576 627
577 /* what's the kernel address of this resource ? */
578 ptr = rproc_da_to_va(rproc, rsc->da, rsc->len);
579 if (!ptr) {
580 dev_err(dev, "erroneous trace resource entry\n");
581 return -EINVAL;
582 }
583
584 trace = kzalloc(sizeof(*trace), GFP_KERNEL); 628 trace = kzalloc(sizeof(*trace), GFP_KERNEL);
585 if (!trace) 629 if (!trace)
586 return -ENOMEM; 630 return -ENOMEM;
587 631
588 /* set the trace buffer dma properties */ 632 /* set the trace buffer dma properties */
589 trace->len = rsc->len; 633 trace->trace_mem.len = rsc->len;
590 trace->va = ptr; 634 trace->trace_mem.da = rsc->da;
635
636 /* set pointer on rproc device */
637 trace->rproc = rproc;
591 638
592 /* make sure snprintf always null terminates, even if truncating */ 639 /* make sure snprintf always null terminates, even if truncating */
593 snprintf(name, sizeof(name), "trace%d", rproc->num_traces); 640 snprintf(name, sizeof(name), "trace%d", rproc->num_traces);
594 641
595 /* create the debugfs entry */ 642 /* create the debugfs entry */
596 trace->priv = rproc_create_trace_file(name, rproc, trace); 643 trace->tfile = rproc_create_trace_file(name, rproc, trace);
597 if (!trace->priv) { 644 if (!trace->tfile) {
598 trace->va = NULL;
599 kfree(trace); 645 kfree(trace);
600 return -EINVAL; 646 return -EINVAL;
601 } 647 }
@@ -604,8 +650,8 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc,
604 650
605 rproc->num_traces++; 651 rproc->num_traces++;
606 652
607 dev_dbg(dev, "%s added: va %pK, da 0x%x, len 0x%x\n", 653 dev_dbg(dev, "%s added: da 0x%x, len 0x%x\n",
608 name, ptr, rsc->da, rsc->len); 654 name, rsc->da, rsc->len);
609 655
610 return 0; 656 return 0;
611} 657}
@@ -715,6 +761,18 @@ static int rproc_alloc_carveout(struct rproc *rproc,
715 dev_dbg(dev, "carveout va %pK, dma %pad, len 0x%x\n", 761 dev_dbg(dev, "carveout va %pK, dma %pad, len 0x%x\n",
716 va, &dma, mem->len); 762 va, &dma, mem->len);
717 763
764 if (mem->da != FW_RSC_ADDR_ANY && !rproc->domain) {
765 /*
766 * Check requested da is equal to dma address
767 * and print a warn message in case of missalignment.
768 * Don't stop rproc_start sequence as coprocessor may
769 * build pa to da translation on its side.
770 */
771 if (mem->da != (u32)dma)
772 dev_warn(dev->parent,
773 "Allocated carveout doesn't fit device address request\n");
774 }
775
718 /* 776 /*
719 * Ok, this is non-standard. 777 * Ok, this is non-standard.
720 * 778 *
@@ -732,15 +790,7 @@ static int rproc_alloc_carveout(struct rproc *rproc,
732 * to use the iommu-based DMA API: we expect 'dma' to contain the 790 * to use the iommu-based DMA API: we expect 'dma' to contain the
733 * physical address in this case. 791 * physical address in this case.
734 */ 792 */
735 793 if (mem->da != FW_RSC_ADDR_ANY && rproc->domain) {
736 if (mem->da != FW_RSC_ADDR_ANY) {
737 if (!rproc->domain) {
738 dev_err(dev->parent,
739 "Bad carveout rsc configuration\n");
740 ret = -ENOMEM;
741 goto dma_free;
742 }
743
744 mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); 794 mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
745 if (!mapping) { 795 if (!mapping) {
746 ret = -ENOMEM; 796 ret = -ENOMEM;
@@ -767,11 +817,17 @@ static int rproc_alloc_carveout(struct rproc *rproc,
767 817
768 dev_dbg(dev, "carveout mapped 0x%x to %pad\n", 818 dev_dbg(dev, "carveout mapped 0x%x to %pad\n",
769 mem->da, &dma); 819 mem->da, &dma);
770 } else { 820 }
821
822 if (mem->da == FW_RSC_ADDR_ANY) {
823 /* Update device address as undefined by requester */
824 if ((u64)dma & HIGH_BITS_MASK)
825 dev_warn(dev, "DMA address cast in 32bit to fit resource table format\n");
826
771 mem->da = (u32)dma; 827 mem->da = (u32)dma;
772 } 828 }
773 829
774 mem->dma = (u32)dma; 830 mem->dma = dma;
775 mem->va = va; 831 mem->va = va;
776 832
777 return 0; 833 return 0;
@@ -900,7 +956,8 @@ EXPORT_SYMBOL(rproc_add_carveout);
900 * @dma: dma address 956 * @dma: dma address
901 * @len: memory carveout length 957 * @len: memory carveout length
902 * @da: device address 958 * @da: device address
903 * @release: memory carveout function 959 * @alloc: memory carveout allocation function
960 * @release: memory carveout release function
904 * @name: carveout name 961 * @name: carveout name
905 * 962 *
906 * This function allocates a rproc_mem_entry struct and fill it with parameters 963 * This function allocates a rproc_mem_entry struct and fill it with parameters
@@ -1110,6 +1167,7 @@ static int rproc_alloc_registered_carveouts(struct rproc *rproc)
1110 struct rproc_mem_entry *entry, *tmp; 1167 struct rproc_mem_entry *entry, *tmp;
1111 struct fw_rsc_carveout *rsc; 1168 struct fw_rsc_carveout *rsc;
1112 struct device *dev = &rproc->dev; 1169 struct device *dev = &rproc->dev;
1170 u64 pa;
1113 int ret; 1171 int ret;
1114 1172
1115 list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) { 1173 list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) {
@@ -1146,10 +1204,15 @@ static int rproc_alloc_registered_carveouts(struct rproc *rproc)
1146 1204
1147 /* Use va if defined else dma to generate pa */ 1205 /* Use va if defined else dma to generate pa */
1148 if (entry->va) 1206 if (entry->va)
1149 rsc->pa = (u32)rproc_va_to_pa(entry->va); 1207 pa = (u64)rproc_va_to_pa(entry->va);
1150 else 1208 else
1151 rsc->pa = (u32)entry->dma; 1209 pa = (u64)entry->dma;
1210
1211 if (((u64)pa) & HIGH_BITS_MASK)
1212 dev_warn(dev,
1213 "Physical address cast in 32bit to fit resource table format\n");
1152 1214
1215 rsc->pa = (u32)pa;
1153 rsc->da = entry->da; 1216 rsc->da = entry->da;
1154 rsc->len = entry->len; 1217 rsc->len = entry->len;
1155 } 1218 }
@@ -1182,15 +1245,16 @@ static void rproc_coredump_cleanup(struct rproc *rproc)
1182static void rproc_resource_cleanup(struct rproc *rproc) 1245static void rproc_resource_cleanup(struct rproc *rproc)
1183{ 1246{
1184 struct rproc_mem_entry *entry, *tmp; 1247 struct rproc_mem_entry *entry, *tmp;
1248 struct rproc_debug_trace *trace, *ttmp;
1185 struct rproc_vdev *rvdev, *rvtmp; 1249 struct rproc_vdev *rvdev, *rvtmp;
1186 struct device *dev = &rproc->dev; 1250 struct device *dev = &rproc->dev;
1187 1251
1188 /* clean up debugfs trace entries */ 1252 /* clean up debugfs trace entries */
1189 list_for_each_entry_safe(entry, tmp, &rproc->traces, node) { 1253 list_for_each_entry_safe(trace, ttmp, &rproc->traces, node) {
1190 rproc_remove_trace_file(entry->priv); 1254 rproc_remove_trace_file(trace->tfile);
1191 rproc->num_traces--; 1255 rproc->num_traces--;
1192 list_del(&entry->node); 1256 list_del(&trace->node);
1193 kfree(entry); 1257 kfree(trace);
1194 } 1258 }
1195 1259
1196 /* clean up iommu mapping entries */ 1260 /* clean up iommu mapping entries */
diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c
index e90135c64af0..6da934b8dc4b 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -47,10 +47,23 @@ static struct dentry *rproc_dbg;
47static ssize_t rproc_trace_read(struct file *filp, char __user *userbuf, 47static ssize_t rproc_trace_read(struct file *filp, char __user *userbuf,
48 size_t count, loff_t *ppos) 48 size_t count, loff_t *ppos)
49{ 49{
50 struct rproc_mem_entry *trace = filp->private_data; 50 struct rproc_debug_trace *data = filp->private_data;
51 int len = strnlen(trace->va, trace->len); 51 struct rproc_mem_entry *trace = &data->trace_mem;
52 void *va;
53 char buf[100];
54 int len;
55
56 va = rproc_da_to_va(data->rproc, trace->da, trace->len);
52 57
53 return simple_read_from_buffer(userbuf, count, ppos, trace->va, len); 58 if (!va) {
59 len = scnprintf(buf, sizeof(buf), "Trace %s not available\n",
60 trace->name);
61 va = buf;
62 } else {
63 len = strnlen(va, trace->len);
64 }
65
66 return simple_read_from_buffer(userbuf, count, ppos, va, len);
54} 67}
55 68
56static const struct file_operations trace_rproc_ops = { 69static const struct file_operations trace_rproc_ops = {
@@ -155,6 +168,30 @@ static const struct file_operations rproc_recovery_ops = {
155 .llseek = generic_file_llseek, 168 .llseek = generic_file_llseek,
156}; 169};
157 170
171/* expose the crash trigger via debugfs */
172static ssize_t
173rproc_crash_write(struct file *filp, const char __user *user_buf,
174 size_t count, loff_t *ppos)
175{
176 struct rproc *rproc = filp->private_data;
177 unsigned int type;
178 int ret;
179
180 ret = kstrtouint_from_user(user_buf, count, 0, &type);
181 if (ret < 0)
182 return ret;
183
184 rproc_report_crash(rproc, type);
185
186 return count;
187}
188
189static const struct file_operations rproc_crash_ops = {
190 .write = rproc_crash_write,
191 .open = simple_open,
192 .llseek = generic_file_llseek,
193};
194
158/* Expose resource table content via debugfs */ 195/* Expose resource table content via debugfs */
159static int rproc_rsc_table_show(struct seq_file *seq, void *p) 196static int rproc_rsc_table_show(struct seq_file *seq, void *p)
160{ 197{
@@ -288,7 +325,7 @@ void rproc_remove_trace_file(struct dentry *tfile)
288} 325}
289 326
290struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc, 327struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc,
291 struct rproc_mem_entry *trace) 328 struct rproc_debug_trace *trace)
292{ 329{
293 struct dentry *tfile; 330 struct dentry *tfile;
294 331
@@ -325,6 +362,8 @@ void rproc_create_debug_dir(struct rproc *rproc)
325 rproc, &rproc_name_ops); 362 rproc, &rproc_name_ops);
326 debugfs_create_file("recovery", 0400, rproc->dbg_dir, 363 debugfs_create_file("recovery", 0400, rproc->dbg_dir,
327 rproc, &rproc_recovery_ops); 364 rproc, &rproc_recovery_ops);
365 debugfs_create_file("crash", 0200, rproc->dbg_dir,
366 rproc, &rproc_crash_ops);
328 debugfs_create_file("resource_table", 0400, rproc->dbg_dir, 367 debugfs_create_file("resource_table", 0400, rproc->dbg_dir,
329 rproc, &rproc_rsc_table_ops); 368 rproc, &rproc_rsc_table_ops);
330 debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir, 369 debugfs_create_file("carveout_memories", 0400, rproc->dbg_dir,
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index f6cad243d7ca..45ff76a06c72 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -25,6 +25,13 @@
25 25
26struct rproc; 26struct rproc;
27 27
28struct rproc_debug_trace {
29 struct rproc *rproc;
30 struct dentry *tfile;
31 struct list_head node;
32 struct rproc_mem_entry trace_mem;
33};
34
28/* from remoteproc_core.c */ 35/* from remoteproc_core.c */
29void rproc_release(struct kref *kref); 36void rproc_release(struct kref *kref);
30irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id); 37irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
@@ -32,12 +39,12 @@ void rproc_vdev_release(struct kref *ref);
32 39
33/* from remoteproc_virtio.c */ 40/* from remoteproc_virtio.c */
34int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id); 41int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id);
35void rproc_remove_virtio_dev(struct rproc_vdev *rvdev); 42int rproc_remove_virtio_dev(struct device *dev, void *data);
36 43
37/* from remoteproc_debugfs.c */ 44/* from remoteproc_debugfs.c */
38void rproc_remove_trace_file(struct dentry *tfile); 45void rproc_remove_trace_file(struct dentry *tfile);
39struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc, 46struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc,
40 struct rproc_mem_entry *trace); 47 struct rproc_debug_trace *trace);
41void rproc_delete_debug_dir(struct rproc *rproc); 48void rproc_delete_debug_dir(struct rproc *rproc);
42void rproc_create_debug_dir(struct rproc *rproc); 49void rproc_create_debug_dir(struct rproc *rproc);
43void rproc_init_debugfs(void); 50void rproc_init_debugfs(void);
@@ -52,6 +59,7 @@ void rproc_free_vring(struct rproc_vring *rvring);
52int rproc_alloc_vring(struct rproc_vdev *rvdev, int i); 59int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
53 60
54void *rproc_da_to_va(struct rproc *rproc, u64 da, int len); 61void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
62phys_addr_t rproc_va_to_pa(void *cpu_addr);
55int rproc_trigger_recovery(struct rproc *rproc); 63int rproc_trigger_recovery(struct rproc *rproc);
56 64
57int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw); 65int rproc_elf_sanity_check(struct rproc *rproc, const struct firmware *fw);
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index 2d7cd344f3bf..44774de6f17b 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -17,7 +17,9 @@
17 * GNU General Public License for more details. 17 * GNU General Public License for more details.
18 */ 18 */
19 19
20#include <linux/dma-mapping.h>
20#include <linux/export.h> 21#include <linux/export.h>
22#include <linux/of_reserved_mem.h>
21#include <linux/remoteproc.h> 23#include <linux/remoteproc.h>
22#include <linux/virtio.h> 24#include <linux/virtio.h>
23#include <linux/virtio_config.h> 25#include <linux/virtio_config.h>
@@ -316,6 +318,8 @@ static void rproc_virtio_dev_release(struct device *dev)
316 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 318 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
317 struct rproc *rproc = vdev_to_rproc(vdev); 319 struct rproc *rproc = vdev_to_rproc(vdev);
318 320
321 kfree(vdev);
322
319 kref_put(&rvdev->refcount, rproc_vdev_release); 323 kref_put(&rvdev->refcount, rproc_vdev_release);
320 324
321 put_device(&rproc->dev); 325 put_device(&rproc->dev);
@@ -333,10 +337,53 @@ static void rproc_virtio_dev_release(struct device *dev)
333int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) 337int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
334{ 338{
335 struct rproc *rproc = rvdev->rproc; 339 struct rproc *rproc = rvdev->rproc;
336 struct device *dev = &rproc->dev; 340 struct device *dev = &rvdev->dev;
337 struct virtio_device *vdev = &rvdev->vdev; 341 struct virtio_device *vdev;
342 struct rproc_mem_entry *mem;
338 int ret; 343 int ret;
339 344
345 /* Try to find dedicated vdev buffer carveout */
346 mem = rproc_find_carveout_by_name(rproc, "vdev%dbuffer", rvdev->index);
347 if (mem) {
348 phys_addr_t pa;
349
350 if (mem->of_resm_idx != -1) {
351 struct device_node *np = rproc->dev.parent->of_node;
352
353 /* Associate reserved memory to vdev device */
354 ret = of_reserved_mem_device_init_by_idx(dev, np,
355 mem->of_resm_idx);
356 if (ret) {
357 dev_err(dev, "Can't associate reserved memory\n");
358 goto out;
359 }
360 } else {
361 if (mem->va) {
362 dev_warn(dev, "vdev %d buffer already mapped\n",
363 rvdev->index);
364 pa = rproc_va_to_pa(mem->va);
365 } else {
366 /* Use dma address as carveout no memmapped yet */
367 pa = (phys_addr_t)mem->dma;
368 }
369
370 /* Associate vdev buffer memory pool to vdev subdev */
371 ret = dma_declare_coherent_memory(dev, pa,
372 mem->da,
373 mem->len);
374 if (ret < 0) {
375 dev_err(dev, "Failed to associate buffer\n");
376 goto out;
377 }
378 }
379 }
380
381 /* Allocate virtio device */
382 vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
383 if (!vdev) {
384 ret = -ENOMEM;
385 goto out;
386 }
340 vdev->id.device = id, 387 vdev->id.device = id,
341 vdev->config = &rproc_virtio_config_ops, 388 vdev->config = &rproc_virtio_config_ops,
342 vdev->dev.parent = dev; 389 vdev->dev.parent = dev;
@@ -370,11 +417,15 @@ out:
370 417
371/** 418/**
372 * rproc_remove_virtio_dev() - remove an rproc-induced virtio device 419 * rproc_remove_virtio_dev() - remove an rproc-induced virtio device
373 * @rvdev: the remote vdev 420 * @dev: the virtio device
421 * @data: must be null
374 * 422 *
375 * This function unregisters an existing virtio device. 423 * This function unregisters an existing virtio device.
376 */ 424 */
377void rproc_remove_virtio_dev(struct rproc_vdev *rvdev) 425int rproc_remove_virtio_dev(struct device *dev, void *data)
378{ 426{
379 unregister_virtio_device(&rvdev->vdev); 427 struct virtio_device *vdev = dev_to_virtio(dev);
428
429 unregister_virtio_device(vdev);
430 return 0;
380} 431}
diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c
index aacef0ea3b90..51049d17b1e5 100644
--- a/drivers/remoteproc/st_remoteproc.c
+++ b/drivers/remoteproc/st_remoteproc.c
@@ -19,6 +19,7 @@
19#include <linux/mfd/syscon.h> 19#include <linux/mfd/syscon.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/of_address.h>
22#include <linux/of_device.h> 23#include <linux/of_device.h>
23#include <linux/of_reserved_mem.h> 24#include <linux/of_reserved_mem.h>
24#include <linux/platform_device.h> 25#include <linux/platform_device.h>
@@ -91,6 +92,77 @@ static void st_rproc_kick(struct rproc *rproc, int vqid)
91 dev_err(dev, "failed to send message via mbox: %d\n", ret); 92 dev_err(dev, "failed to send message via mbox: %d\n", ret);
92} 93}
93 94
95static int st_rproc_mem_alloc(struct rproc *rproc,
96 struct rproc_mem_entry *mem)
97{
98 struct device *dev = rproc->dev.parent;
99 void *va;
100
101 va = ioremap_wc(mem->dma, mem->len);
102 if (!va) {
103 dev_err(dev, "Unable to map memory region: %pa+%zx\n",
104 &mem->dma, mem->len);
105 return -ENOMEM;
106 }
107
108 /* Update memory entry va */
109 mem->va = va;
110
111 return 0;
112}
113
114static int st_rproc_mem_release(struct rproc *rproc,
115 struct rproc_mem_entry *mem)
116{
117 iounmap(mem->va);
118
119 return 0;
120}
121
122static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
123{
124 struct device *dev = rproc->dev.parent;
125 struct device_node *np = dev->of_node;
126 struct rproc_mem_entry *mem;
127 struct reserved_mem *rmem;
128 struct of_phandle_iterator it;
129 int index = 0;
130
131 of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
132 while (of_phandle_iterator_next(&it) == 0) {
133 rmem = of_reserved_mem_lookup(it.node);
134 if (!rmem) {
135 dev_err(dev, "unable to acquire memory-region\n");
136 return -EINVAL;
137 }
138
139 /* No need to map vdev buffer */
140 if (strcmp(it.node->name, "vdev0buffer")) {
141 /* Register memory region */
142 mem = rproc_mem_entry_init(dev, NULL,
143 (dma_addr_t)rmem->base,
144 rmem->size, rmem->base,
145 st_rproc_mem_alloc,
146 st_rproc_mem_release,
147 it.node->name);
148 } else {
149 /* Register reserved memory for vdev buffer allocation */
150 mem = rproc_of_resm_mem_entry_init(dev, index,
151 rmem->size,
152 rmem->base,
153 it.node->name);
154 }
155
156 if (!mem)
157 return -ENOMEM;
158
159 rproc_add_carveout(rproc, mem);
160 index++;
161 }
162
163 return rproc_elf_load_rsc_table(rproc, fw);
164}
165
94static int st_rproc_start(struct rproc *rproc) 166static int st_rproc_start(struct rproc *rproc)
95{ 167{
96 struct st_rproc *ddata = rproc->priv; 168 struct st_rproc *ddata = rproc->priv;
@@ -158,9 +230,14 @@ static int st_rproc_stop(struct rproc *rproc)
158} 230}
159 231
160static const struct rproc_ops st_rproc_ops = { 232static const struct rproc_ops st_rproc_ops = {
161 .kick = st_rproc_kick, 233 .kick = st_rproc_kick,
162 .start = st_rproc_start, 234 .start = st_rproc_start,
163 .stop = st_rproc_stop, 235 .stop = st_rproc_stop,
236 .parse_fw = st_rproc_parse_fw,
237 .load = rproc_elf_load_segments,
238 .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
239 .sanity_check = rproc_elf_sanity_check,
240 .get_boot_addr = rproc_elf_get_boot_addr,
164}; 241};
165 242
166/* 243/*
@@ -254,12 +331,6 @@ static int st_rproc_parse_dt(struct platform_device *pdev)
254 return -EINVAL; 331 return -EINVAL;
255 } 332 }
256 333
257 err = of_reserved_mem_device_init(dev);
258 if (err) {
259 dev_err(dev, "Failed to obtain shared memory\n");
260 return err;
261 }
262
263 err = clk_prepare(ddata->clk); 334 err = clk_prepare(ddata->clk);
264 if (err) 335 if (err)
265 dev_err(dev, "failed to get clock\n"); 336 dev_err(dev, "failed to get clock\n");
@@ -387,8 +458,6 @@ static int st_rproc_remove(struct platform_device *pdev)
387 458
388 clk_disable_unprepare(ddata->clk); 459 clk_disable_unprepare(ddata->clk);
389 460
390 of_reserved_mem_device_release(&pdev->dev);
391
392 for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++) 461 for (i = 0; i < ST_RPROC_MAX_VRING * MBOX_MAX; i++)
393 mbox_free_channel(ddata->mbox_chan[i]); 462 mbox_free_channel(ddata->mbox_chan[i]);
394 463
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 664f957012cd..5d3685bd76a2 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -11,21 +11,21 @@
11 11
12#define pr_fmt(fmt) "%s: " fmt, __func__ 12#define pr_fmt(fmt) "%s: " fmt, __func__
13 13
14#include <linux/dma-mapping.h>
15#include <linux/idr.h>
16#include <linux/jiffies.h>
14#include <linux/kernel.h> 17#include <linux/kernel.h>
15#include <linux/module.h> 18#include <linux/module.h>
16#include <linux/virtio.h> 19#include <linux/mutex.h>
17#include <linux/virtio_ids.h> 20#include <linux/of_device.h>
18#include <linux/virtio_config.h> 21#include <linux/rpmsg.h>
19#include <linux/scatterlist.h> 22#include <linux/scatterlist.h>
20#include <linux/dma-mapping.h>
21#include <linux/slab.h> 23#include <linux/slab.h>
22#include <linux/idr.h>
23#include <linux/jiffies.h>
24#include <linux/sched.h> 24#include <linux/sched.h>
25#include <linux/virtio.h>
26#include <linux/virtio_ids.h>
27#include <linux/virtio_config.h>
25#include <linux/wait.h> 28#include <linux/wait.h>
26#include <linux/rpmsg.h>
27#include <linux/mutex.h>
28#include <linux/of_device.h>
29 29
30#include "rpmsg_internal.h" 30#include "rpmsg_internal.h"
31 31
@@ -912,7 +912,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
912 total_buf_space = vrp->num_bufs * vrp->buf_size; 912 total_buf_space = vrp->num_bufs * vrp->buf_size;
913 913
914 /* allocate coherent memory for the buffers */ 914 /* allocate coherent memory for the buffers */
915 bufs_va = dma_alloc_coherent(vdev->dev.parent->parent, 915 bufs_va = dma_alloc_coherent(vdev->dev.parent,
916 total_buf_space, &vrp->bufs_dma, 916 total_buf_space, &vrp->bufs_dma,
917 GFP_KERNEL); 917 GFP_KERNEL);
918 if (!bufs_va) { 918 if (!bufs_va) {
@@ -980,7 +980,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
980 return 0; 980 return 0;
981 981
982free_coherent: 982free_coherent:
983 dma_free_coherent(vdev->dev.parent->parent, total_buf_space, 983 dma_free_coherent(vdev->dev.parent, total_buf_space,
984 bufs_va, vrp->bufs_dma); 984 bufs_va, vrp->bufs_dma);
985vqs_del: 985vqs_del:
986 vdev->config->del_vqs(vrp->vdev); 986 vdev->config->del_vqs(vrp->vdev);
@@ -1015,7 +1015,7 @@ static void rpmsg_remove(struct virtio_device *vdev)
1015 1015
1016 vdev->config->del_vqs(vrp->vdev); 1016 vdev->config->del_vqs(vrp->vdev);
1017 1017
1018 dma_free_coherent(vdev->dev.parent->parent, total_buf_space, 1018 dma_free_coherent(vdev->dev.parent, total_buf_space,
1019 vrp->rbufs, vrp->bufs_dma); 1019 vrp->rbufs, vrp->bufs_dma);
1020 1020
1021 kfree(vrp); 1021 kfree(vrp);
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 507a2b524208..04d04709f2bd 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -345,9 +345,9 @@ struct firmware;
345 * @stop: power off the device 345 * @stop: power off the device
346 * @kick: kick a virtqueue (virtqueue id given as a parameter) 346 * @kick: kick a virtqueue (virtqueue id given as a parameter)
347 * @da_to_va: optional platform hook to perform address translations 347 * @da_to_va: optional platform hook to perform address translations
348 * @load_rsc_table: load resource table from firmware image 348 * @parse_fw: parse firmware to extract information (e.g. resource table)
349 * @find_loaded_rsc_table: find the loaded resouce table 349 * @find_loaded_rsc_table: find the loaded resouce table
350 * @load: load firmeware to memory, where the remote processor 350 * @load: load firmware to memory, where the remote processor
351 * expects to find it 351 * expects to find it
352 * @sanity_check: sanity check the fw image 352 * @sanity_check: sanity check the fw image
353 * @get_boot_addr: get boot address to entry point specified in firmware 353 * @get_boot_addr: get boot address to entry point specified in firmware
@@ -554,11 +554,11 @@ struct rproc_vdev {
554 struct kref refcount; 554 struct kref refcount;
555 555
556 struct rproc_subdev subdev; 556 struct rproc_subdev subdev;
557 struct device dev;
557 558
558 unsigned int id; 559 unsigned int id;
559 struct list_head node; 560 struct list_head node;
560 struct rproc *rproc; 561 struct rproc *rproc;
561 struct virtio_device vdev;
562 struct rproc_vring vring[RVDEV_NUM_VRINGS]; 562 struct rproc_vring vring[RVDEV_NUM_VRINGS];
563 u32 rsc_offset; 563 u32 rsc_offset;
564 u32 index; 564 u32 index;
@@ -601,7 +601,7 @@ int rproc_coredump_add_custom_segment(struct rproc *rproc,
601 601
602static inline struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev) 602static inline struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev)
603{ 603{
604 return container_of(vdev, struct rproc_vdev, vdev); 604 return container_of(vdev->dev.parent, struct rproc_vdev, dev);
605} 605}
606 606
607static inline struct rproc *vdev_to_rproc(struct virtio_device *vdev) 607static inline struct rproc *vdev_to_rproc(struct virtio_device *vdev)