History

Merge tag 'rproc-v5.3' of git://github.com/andersson/remoteproc

Pull remoteproc updates from Bjorn Andersson: "This adds support for the STM32 remoteproc, additional i.MX platforms with Cortex M4 remoteprocs and Qualcomm's QCS404 Compute DSP. Also initial support for vendor specific resource table entries and support for unprocessed Qualcomm firmware files" * tag 'rproc-v5.3' of git://github.com/andersson/remoteproc: remoteproc: stm32: fix building without ARM SMCC remoteproc: qcom: q6v5-mss: Fix build error without QCOM_MDT_LOADER remoteproc: copy parent dma_pfn_offset for vdev remoteproc: qcom: q6v5-mss: Support loading non-split images soc: qcom: mdt_loader: Support loading non-split images remoteproc: stm32: add an ST stm32_rproc driver dt-bindings: remoteproc: add bindings for stm32 remote processor driver dt-bindings: stm32: add bindings for ML-AHB interconnect remoteproc: Use struct_size() helper remoteproc: add vendor resources handling remoteproc: imx: Fix typo in "failed" remoteproc: imx: Broaden the Kconfig selection logic remoteproc,rpmsg: add missing MAINTAINERS file entries remoteproc: qcom: qdsp6-adsp: Add support for QCS404 CDSP dt-bindings: remoteproc: Rename and amend Hexagon v56 binding

Linus Torvalds committed 7 years ago

Commit fdcec002 parents 7636b75 93f1d3e17 files · +1009 −57Browse files

Unified · Split

17 files
  1. Documentation/devicetree/bindings/arm/stm32/mlahb.txt +37 −0
  2. Documentation/devicetree/bindings/remoteproc/qcom,hexagon-v56.txt +25 −10
  3. Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt +63 −0
  4. Documentation/remoteproc.txt +9 −5
  5. MAINTAINERS +5 −0
  6. drivers/remoteproc/Kconfig +17 −1
  7. drivers/remoteproc/Makefile +1 −0
  8. drivers/remoteproc/imx_rproc.c +4 −4
  9. drivers/remoteproc/qcom_q6v5_adsp.c +55 −18
  10. drivers/remoteproc/qcom_q6v5_mss.c +25 −8
  11. drivers/remoteproc/remoteproc_core.c +15 −0
  12. drivers/remoteproc/remoteproc_elf_loader.c +1 −2
  13. drivers/remoteproc/remoteproc_internal.h +11 −0
  14. drivers/remoteproc/stm32_rproc.c +628 −0
  15. drivers/soc/qcom/mdt_loader.c +85 −3
  16. include/linux/remoteproc.h +26 −6
  17. include/linux/soc/qcom/mdt_loader.h +2 −0
Documentation/devicetree/bindings/arm/stm32/mlahb.txt+37−0
@@ -0,0 +1,37 @@
1+ML-AHB interconnect bindings
2+
3+These bindings describe the STM32 SoCs ML-AHB interconnect bus which connects
4+a Cortex-M subsystem with dedicated memories.
5+The MCU SRAM and RETRAM memory parts can be accessed through different addresses
6+(see "RAM aliases" in [1]) using different buses (see [2]) : balancing the
7+Cortex-M firmware accesses among those ports allows to tune the system
8+performance.
9+
10+[1]: https://www.st.com/resource/en/reference_manual/dm00327659.pdf
11+[2]: https://wiki.st.com/stm32mpu/wiki/STM32MP15_RAM_mapping
12+
13+Required properties:
14+- compatible: should be "simple-bus"
15+- dma-ranges: describes memory addresses translation between the local CPU and
16+ the remote Cortex-M processor. Each memory region, is declared with
17+ 3 parameters:
18+ - param 1: device base address (Cortex-M processor address)
19+ - param 2: physical base address (local CPU address)
20+ - param 3: size of the memory region.
21+
22+The Cortex-M remote processor accessed via the mlahb interconnect is described
23+by a child node.
24+
25+Example:
26+mlahb {
27+ compatible = "simple-bus";
28+ #address-cells = <1>;
29+ #size-cells = <1>;
30+ dma-ranges = <0x00000000 0x38000000 0x10000>,
31+ <0x10000000 0x10000000 0x60000>,
32+ <0x30000000 0x30000000 0x60000>;
33+
34+ m4_rproc: m4@10000000 {
35+ ...
36+ };
37+};
Documentation/devicetree/bindings/remoteproc/qcom,hexagon-v56.txtrenamed from Documentation/devicetree/bindings/remoteproc/qcom,adsp-pil.txt+25−10
@@ -1,12 +1,13 @@
1−Qualcomm Technology Inc. ADSP Peripheral Image Loader
1+Qualcomm Technology Inc. Hexagon v56 Peripheral Image Loader
22
33 This document defines the binding for a component that loads and boots firmware
4−on the Qualcomm Technology Inc. ADSP Hexagon core.
4+on the Qualcomm Technology Inc. Hexagon v56 core.
55
66 - compatible:
77 Usage: required
88 Value type: <string>
99 Definition: must be one of:
10+ "qcom,qcs404-cdsp-pil",
1011 "qcom,sdm845-adsp-pil"
1112
1213 - reg:
@@ -28,10 +29,11 @@ on the Qualcomm Technology Inc. ADSP Hexagon core. · 15 unmodified lines
2829 - clocks:
2930 Usage: required
3031 Value type: <prop-encoded-array>
31− Definition: List of 8 phandle and clock specifier pairs for the adsp.
32+ Definition: List of phandles and clock specifier pairs for the Hexagon,
33+ per clock-names below.
3234
3335 - clock-names:
34− Usage: required
36+ Usage: required for SDM845 ADSP
3537 Value type: <stringlist>
3638 Definition: List of clock input name strings sorted in the same
3739 order as the clocks property. Definition must have
@@ -39,6 +41,14 @@ on the Qualcomm Technology Inc. ADSP Hexagon core. · 1 unmodified line
3941 "lpass_ahbm_aon_cbcr", "qdsp6ss_xo", "qdsp6ss_sleep"
4042 and "qdsp6ss_core".
4143
44+- clock-names:
45+ Usage: required for QCS404 CDSP
46+ Value type: <stringlist>
47+ Definition: List of clock input name strings sorted in the same
48+ order as the clocks property. Definition must have
49+ "xo", "sway", "tbu", "bimc", "ahb_aon", "q6ss_slave",
50+ "q6ss_master", "q6_axim".
51+
4252 - power-domains:
4353 Usage: required
4454 Value type: <phandle>
@@ -47,28 +57,33 @@ on the Qualcomm Technology Inc. ADSP Hexagon core. · 2 unmodified lines
4757 - resets:
4858 Usage: required
4959 Value type: <phandle>
50− Definition: reference to the list of 2 reset-controller for the adsp.
60+ Definition: reference to the list of resets for the Hexagon.
5161
5262 - reset-names:
53− Usage: required
63+ Usage: required for SDM845 ADSP
5464 Value type: <stringlist>
5565 Definition: must be "pdc_sync" and "cc_lpass"
5666
67+- reset-names:
68+ Usage: required for QCS404 CDSP
69+ Value type: <stringlist>
70+ Definition: must be "restart"
71+
5772 - qcom,halt-regs:
5873 Usage: required
5974 Value type: <prop-encoded-array>
6075 Definition: a phandle reference to a syscon representing TCSR followed
61− by the offset within syscon for lpass halt register.
76+ by the offset within syscon for Hexagon halt register.
6277
6378 - memory-region:
6479 Usage: required
6580 Value type: <phandle>
66− Definition: reference to the reserved-memory for the ADSP
81+ Definition: reference to the reserved-memory for the firmware
6782
6883 - qcom,smem-states:
6984 Usage: required
7085 Value type: <phandle>
71− Definition: reference to the smem state for requesting the ADSP to
86+ Definition: reference to the smem state for requesting the Hexagon to
7287 shut down
7388
7489 - qcom,smem-state-names:
@@ -79,7 +94,7 @@ on the Qualcomm Technology Inc. ADSP Hexagon core. · 4 unmodified lines
7994
8095 = SUBNODES
8196 The adsp node may have an subnode named "glink-edge" that describes the
82−communication edge, channels and devices related to the ADSP.
97+communication edge, channels and devices related to the Hexagon.
8398 See ../soc/qcom/qcom,glink.txt for details on how to describe these.
8499
85100 = EXAMPLE
Documentation/devicetree/bindings/remoteproc/stm32-rproc.txt+63−0
@@ -0,0 +1,63 @@
1+STMicroelectronics STM32 Remoteproc
2+-----------------------------------
3+This document defines the binding for the remoteproc component that loads and
4+boots firmwares on the ST32MP family chipset.
5+
6+Required properties:
7+- compatible: Must be "st,stm32mp1-m4"
8+- reg: Address ranges of the RETRAM and MCU SRAM memories used by the
9+ remote processor.
10+- resets: Reference to a reset controller asserting the remote processor.
11+- st,syscfg-holdboot: Reference to the system configuration which holds the
12+ remote processor reset hold boot
13+ 1st cell: phandle of syscon block
14+ 2nd cell: register offset containing the hold boot setting
15+ 3rd cell: register bitmask for the hold boot field
16+- st,syscfg-tz: Reference to the system configuration which holds the RCC trust
17+ zone mode
18+ 1st cell: phandle to syscon block
19+ 2nd cell: register offset containing the RCC trust zone mode setting
20+ 3rd cell: register bitmask for the RCC trust zone mode bit
21+
22+Optional properties:
23+- interrupts: Should contain the watchdog interrupt
24+- mboxes: This property is required only if the rpmsg/virtio functionality
25+ is used. List of phandle and mailbox channel specifiers:
26+ - a channel (a) used to communicate through virtqueues with the
27+ remote proc.
28+ Bi-directional channel:
29+ - from local to remote = send message
30+ - from remote to local = send message ack
31+ - a channel (b) working the opposite direction of channel (a)
32+ - a channel (c) used by the local proc to notify the remote proc
33+ that it is about to be shut down.
34+ Unidirectional channel:
35+ - from local to remote, where ACK from the remote means
36+ that it is ready for shutdown
37+- mbox-names: This property is required if the mboxes property is used.
38+ - must be "vq0" for channel (a)
39+ - must be "vq1" for channel (b)
40+ - must be "shutdown" for channel (c)
41+- memory-region: List of phandles to the reserved memory regions associated with
42+ the remoteproc device. This is variable and describes the
43+ memories shared with the remote processor (eg: remoteproc
44+ firmware and carveouts, rpmsg vrings, ...).
45+ (see ../reserved-memory/reserved-memory.txt)
46+- st,syscfg-pdds: Reference to the system configuration which holds the remote
47+ processor deep sleep setting
48+ 1st cell: phandle to syscon block
49+ 2nd cell: register offset containing the deep sleep setting
50+ 3rd cell: register bitmask for the deep sleep bit
51+- st,auto-boot: If defined, when remoteproc is probed, it loads the default
52+ firmware and starts the remote processor.
53+
54+Example:
55+ m4_rproc: m4@10000000 {
56+ compatible = "st,stm32mp1-m4";
57+ reg = <0x10000000 0x40000>,
58+ <0x30000000 0x40000>,
59+ <0x38000000 0x10000>;
60+ resets = <&rcc MCU_R>;
61+ st,syscfg-holdboot = <&rcc 0x10C 0x1>;
62+ st,syscfg-tz = <&rcc 0x000 0x1>;
63+ };
Documentation/remoteproc.txt+9−5
@@ -314,6 +314,8 @@ Here are the various resource types that are currently supported:: · 313 unmodified lines
314314 * @RSC_VDEV: declare support for a virtio device, and serve as its
315315 * virtio header.
316316 * @RSC_LAST: just keep this one at the end
317+ * @RSC_VENDOR_START: start of the vendor specific resource types range
318+ * @RSC_VENDOR_END: end of the vendor specific resource types range
317319 *
318320 * Please note that these values are used as indices to the rproc_handle_rsc
319321 * lookup table, so please keep them sane. Moreover, @RSC_LAST is used to
@@ -321,11 +323,13 @@ Here are the various resource types that are currently supported:: · 1 unmodified line
321323 * please update it as needed.
322324 */
323325 enum fw_resource_type {
324− RSC_CARVEOUT = 0,
325− RSC_DEVMEM = 1,
326− RSC_TRACE = 2,
327− RSC_VDEV = 3,
328− RSC_LAST = 4,
326+ RSC_CARVEOUT = 0,
327+ RSC_DEVMEM = 1,
328+ RSC_TRACE = 2,
329+ RSC_VDEV = 3,
330+ RSC_LAST = 4,
331+ RSC_VENDOR_START = 128,
332+ RSC_VENDOR_END = 512,
329333 };
330334
331335 For more details regarding a specific resource type, please see its
MAINTAINERS+5−0
@@ -13590,9 +13590,11 @@ L: linux-remoteproc@vger.kernel.org · 13589 unmodified lines
1359013590 T: git git://git.kernel.org/pub/scm/linux/kernel/git/ohad/remoteproc.git
1359113591 S: Maintained
1359213592 F: Documentation/devicetree/bindings/remoteproc/
13593+F: Documentation/ABI/testing/sysfs-class-remoteproc
1359313594 F: Documentation/remoteproc.txt
1359413595 F: drivers/remoteproc/
1359513596 F: include/linux/remoteproc.h
13597+F: include/linux/remoteproc/
1359613598
1359713599 REMOTE PROCESSOR MESSAGING (RPMSG) SUBSYSTEM
1359813600 M: Ohad Ben-Cohen <ohad@wizery.com>
@@ -13602,8 +13604,11 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/ohad/rpmsg.git · 3 unmodified lines
1360213604 S: Maintained
1360313605 F: drivers/rpmsg/
1360413606 F: Documentation/rpmsg.txt
13607+F: Documentation/ABI/testing/sysfs-bus-rpmsg
1360513608 F: include/linux/rpmsg.h
1360613609 F: include/linux/rpmsg/
13610+F: include/uapi/linux/rpmsg.h
13611+F: samples/rpmsg/
1360713612
1360813613 RENESAS CLOCK DRIVERS
1360913614 M: Geert Uytterhoeven <geert+renesas@glider.be>
drivers/remoteproc/Kconfig+17−1
@@ -16,7 +16,7 @@ if REMOTEPROC · 15 unmodified lines
1616
1717 config IMX_REMOTEPROC
1818 tristate "IMX6/7 remoteproc support"
19− depends on SOC_IMX6SX || SOC_IMX7D
19+ depends on ARCH_MXC
2020 help
2121 Say y here to support iMX's remote processors (Cortex M4
2222 on iMX7D) via the remote processor framework.
@@ -116,6 +116,7 @@ config QCOM_Q6V5_MSS · 93 unmodified lines
116116 depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
117117 depends on QCOM_SYSMON || QCOM_SYSMON=n
118118 select MFD_SYSCON
119+ select QCOM_MDT_LOADER
119120 select QCOM_Q6V5_COMMON
120121 select QCOM_RPROC_COMMON
121122 select QCOM_SCM
@@ -198,6 +199,21 @@ config ST_REMOTEPROC · 76 unmodified lines
198199 config ST_SLIM_REMOTEPROC
199200 tristate
200201
202+config STM32_RPROC
203+ tristate "STM32 remoteproc support"
204+ depends on ARCH_STM32
205+ depends on REMOTEPROC
206+ select MAILBOX
207+ help
208+ Say y here to support STM32 MCU processors via the
209+ remote processor framework.
210+
211+ You want to say y here in order to enable AMP
212+ use-cases to run on your platform (dedicated firmware could be
213+ offloaded to remote MCU processors using this framework).
214+
215+ This can be either built-in or a loadable module.
216+
201217 endif # REMOTEPROC
202218
203219 endmenu
drivers/remoteproc/Makefile+1−0
@@ -26,3 +26,4 @@ qcom_wcnss_pil-y += qcom_wcnss.o · 25 unmodified lines
2626 qcom_wcnss_pil-y += qcom_wcnss_iris.o
2727 obj-$(CONFIG_ST_REMOTEPROC) += st_remoteproc.o
2828 obj-$(CONFIG_ST_SLIM_REMOTEPROC) += st_slim_rproc.o
29+obj-$(CONFIG_STM32_RPROC) += stm32_rproc.o
drivers/remoteproc/imx_rproc.c+4−4
@@ -165,7 +165,7 @@ static int imx_rproc_start(struct rproc *rproc) · 164 unmodified lines
165165 ret = regmap_update_bits(priv->regmap, dcfg->src_reg,
166166 dcfg->src_mask, dcfg->src_start);
167167 if (ret)
168− dev_err(dev, "Filed to enable M4!\n");
168+ dev_err(dev, "Failed to enable M4!\n");
169169
170170 return ret;
171171 }
@@ -180,7 +180,7 @@ static int imx_rproc_stop(struct rproc *rproc) · 8 unmodified lines
180180 ret = regmap_update_bits(priv->regmap, dcfg->src_reg,
181181 dcfg->src_mask, dcfg->src_stop);
182182 if (ret)
183− dev_err(dev, "Filed to stop M4!\n");
183+ dev_err(dev, "Failed to stop M4!\n");
184184
185185 return ret;
186186 }
@@ -203,7 +203,7 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da, · 16 unmodified lines
203203 }
204204 }
205205
206− dev_warn(priv->dev, "Translation filed: da = 0x%llx len = 0x%x\n",
206+ dev_warn(priv->dev, "Translation failed: da = 0x%llx len = 0x%x\n",
207207 da, len);
208208 return -ENOENT;
209209 }
@@ -349,7 +349,7 @@ static int imx_rproc_probe(struct platform_device *pdev) · 139 unmodified lines
349349
350350 ret = imx_rproc_addr_init(priv, pdev);
351351 if (ret) {
352− dev_err(dev, "filed on imx_rproc_addr_init\n");
352+ dev_err(dev, "failed on imx_rproc_addr_init\n");
353353 goto err_put_rproc;
354354 }
355355
drivers/remoteproc/qcom_q6v5_adsp.c+55−18
@@ -46,11 +46,9 @@ · 45 unmodified lines
4646 #define LPASS_PWR_ON_REG 0x10
4747 #define LPASS_HALTREQ_REG 0x0
4848
49−/* list of clocks required by ADSP PIL */
50−static const char * const adsp_clk_id[] = {
51− "sway_cbcr", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr",
52− "qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core",
53−};
49+#define QDSP6SS_XO_CBCR 0x38
50+#define QDSP6SS_CORE_CBCR 0x20
51+#define QDSP6SS_SLEEP_CBCR 0x3c
5452
5553 struct adsp_pil_data {
5654 int crash_reason_smem;
@@ -59,6 +57,9 @@ struct adsp_pil_data { · 2 unmodified lines
5957 const char *ssr_name;
6058 const char *sysmon_name;
6159 int ssctl_id;
60+
61+ const char **clk_ids;
62+ int num_clks;
6263 };
6364
6465 struct qcom_adsp {
@@ -75,7 +76,7 @@ struct qcom_adsp { · 10 unmodified lines
7576 void __iomem *qdsp6ss_base;
7677
7778 struct reset_control *pdc_sync_reset;
78− struct reset_control *cc_lpass_restart;
79+ struct reset_control *restart;
7980
8081 struct regmap *halt_map;
8182 unsigned int halt_lpass;
@@ -143,7 +144,7 @@ reset: · 61 unmodified lines
143144 /* Assert the LPASS PDC Reset */
144145 reset_control_assert(adsp->pdc_sync_reset);
145146 /* Place the LPASS processor into reset */
146− reset_control_assert(adsp->cc_lpass_restart);
147+ reset_control_assert(adsp->restart);
147148 /* wait after asserting subsystem restart from AOSS */
148149 usleep_range(200, 300);
149150
@@ -153,7 +154,7 @@ reset: · 3 unmodified lines
153154 /* De-assert the LPASS PDC Reset */
154155 reset_control_deassert(adsp->pdc_sync_reset);
155156 /* Remove the LPASS reset */
156− reset_control_deassert(adsp->cc_lpass_restart);
157+ reset_control_deassert(adsp->restart);
157158 /* wait after de-asserting subsystem restart from AOSS */
158159 usleep_range(200, 300);
159160
@@ -192,6 +193,15 @@ static int adsp_start(struct rproc *rproc) · 32 unmodified lines
192193 goto disable_power_domain;
193194 }
194195
196+ /* Enable the XO clock */
197+ writel(1, adsp->qdsp6ss_base + QDSP6SS_XO_CBCR);
198+
199+ /* Enable the QDSP6SS sleep clock */
200+ writel(1, adsp->qdsp6ss_base + QDSP6SS_SLEEP_CBCR);
201+
202+ /* Enable the QDSP6 core clock */
203+ writel(1, adsp->qdsp6ss_base + QDSP6SS_CORE_CBCR);
204+
195205 /* Program boot address */
196206 writel(adsp->mem_phys >> 4, adsp->qdsp6ss_base + RST_EVB_REG);
197207
@@ -280,8 +290,9 @@ static const struct rproc_ops adsp_ops = { · 82 unmodified lines
280290 .load = adsp_load,
281291 };
282292
283−static int adsp_init_clock(struct qcom_adsp *adsp)
293+static int adsp_init_clock(struct qcom_adsp *adsp, const char **clk_ids)
284294 {
295+ int num_clks = 0;
285296 int i, ret;
286297
287298 adsp->xo = devm_clk_get(adsp->dev, "xo");
@@ -292,32 +303,39 @@ static int adsp_init_clock(struct qcom_adsp *adsp) · 4 unmodified lines
292303 return ret;
293304 }
294305
295− adsp->num_clks = ARRAY_SIZE(adsp_clk_id);
306+ for (i = 0; clk_ids[i]; i++)
307+ num_clks++;
308+
309+ adsp->num_clks = num_clks;
296310 adsp->clks = devm_kcalloc(adsp->dev, adsp->num_clks,
297311 sizeof(*adsp->clks), GFP_KERNEL);
298312 if (!adsp->clks)
299313 return -ENOMEM;
300314
301315 for (i = 0; i < adsp->num_clks; i++)
302− adsp->clks[i].id = adsp_clk_id[i];
316+ adsp->clks[i].id = clk_ids[i];
303317
304318 return devm_clk_bulk_get(adsp->dev, adsp->num_clks, adsp->clks);
305319 }
306320
307321 static int adsp_init_reset(struct qcom_adsp *adsp)
308322 {
309− adsp->pdc_sync_reset = devm_reset_control_get_exclusive(adsp->dev,
323+ adsp->pdc_sync_reset = devm_reset_control_get_optional_exclusive(adsp->dev,
310324 "pdc_sync");
311325 if (IS_ERR(adsp->pdc_sync_reset)) {
312326 dev_err(adsp->dev, "failed to acquire pdc_sync reset\n");
313327 return PTR_ERR(adsp->pdc_sync_reset);
314328 }
315329
316− adsp->cc_lpass_restart = devm_reset_control_get_exclusive(adsp->dev,
317− "cc_lpass");
318− if (IS_ERR(adsp->cc_lpass_restart)) {
319− dev_err(adsp->dev, "failed to acquire cc_lpass restart\n");
320− return PTR_ERR(adsp->cc_lpass_restart);
330+ adsp->restart = devm_reset_control_get_optional_exclusive(adsp->dev, "restart");
331+
332+ /* Fall back to the old "cc_lpass" if "restart" is absent */
333+ if (!adsp->restart)
334+ adsp->restart = devm_reset_control_get_exclusive(adsp->dev, "cc_lpass");
335+
336+ if (IS_ERR(adsp->restart)) {
337+ dev_err(adsp->dev, "failed to acquire restart\n");
338+ return PTR_ERR(adsp->restart);
321339 }
322340
323341 return 0;
@@ -415,7 +433,7 @@ static int adsp_probe(struct platform_device *pdev) · 91 unmodified lines
415433 if (ret)
416434 goto free_rproc;
417435
418− ret = adsp_init_clock(adsp);
436+ ret = adsp_init_clock(adsp, desc->clk_ids);
419437 if (ret)
420438 goto free_rproc;
421439
@@ -479,9 +497,28 @@ static const struct adsp_pil_data adsp_resource_init = { · 57 unmodified lines
479497 .ssr_name = "lpass",
480498 .sysmon_name = "adsp",
481499 .ssctl_id = 0x14,
500+ .clk_ids = (const char*[]) {
501+ "sway_cbcr", "lpass_ahbs_aon_cbcr", "lpass_ahbm_aon_cbcr",
502+ "qdsp6ss_xo", "qdsp6ss_sleep", "qdsp6ss_core", NULL
503+ },
504+ .num_clks = 7,
505+};
506+
507+static const struct adsp_pil_data cdsp_resource_init = {
508+ .crash_reason_smem = 601,
509+ .firmware_name = "cdsp.mdt",
510+ .ssr_name = "cdsp",
511+ .sysmon_name = "cdsp",
512+ .ssctl_id = 0x17,
513+ .clk_ids = (const char*[]) {
514+ "sway", "tbu", "bimc", "ahb_aon", "q6ss_slave", "q6ss_master",
515+ "q6_axim", NULL
516+ },
517+ .num_clks = 7,
482518 };
483519
484520 static const struct of_device_id adsp_of_match[] = {
521+ { .compatible = "qcom,qcs404-cdsp-pil", .data = &cdsp_resource_init },
485522 { .compatible = "qcom,sdm845-adsp-pil", .data = &adsp_resource_init },
486523 { },
487524 };
drivers/remoteproc/qcom_q6v5_mss.c+25−8
@@ -659,23 +659,29 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw) · 658 unmodified lines
659659 {
660660 unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
661661 dma_addr_t phys;
662+ void *metadata;
662663 int mdata_perm;
663664 int xferop_ret;
665+ size_t size;
664666 void *ptr;
665667 int ret;
666668
667− ptr = dma_alloc_attrs(qproc->dev, fw->size, &phys, GFP_KERNEL, dma_attrs);
669+ metadata = qcom_mdt_read_metadata(fw, &size);
670+ if (IS_ERR(metadata))
671+ return PTR_ERR(metadata);
672+
673+ ptr = dma_alloc_attrs(qproc->dev, size, &phys, GFP_KERNEL, dma_attrs);
668674 if (!ptr) {
675+ kfree(metadata);
669676 dev_err(qproc->dev, "failed to allocate mdt buffer\n");
670677 return -ENOMEM;
671678 }
672679
673− memcpy(ptr, fw->data, fw->size);
680+ memcpy(ptr, metadata, size);
674681
675682 /* Hypervisor mapping to access metadata by modem */
676683 mdata_perm = BIT(QCOM_SCM_VMID_HLOS);
677− ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm,
678− true, phys, fw->size);
684+ ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm, true, phys, size);
679685 if (ret) {
680686 dev_err(qproc->dev,
681687 "assigning Q6 access to metadata failed: %d\n", ret);
@@ -693,14 +699,14 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw) · 11 unmodified lines
693699 dev_err(qproc->dev, "MPSS header authentication failed: %d\n", ret);
694700
695701 /* Metadata authentication done, remove modem access */
696− xferop_ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm,
697− false, phys, fw->size);
702+ xferop_ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm, false, phys, size);
698703 if (xferop_ret)
699704 dev_warn(qproc->dev,
700705 "mdt buffer not reclaimed system may become unstable\n");
701706
702707 free_dma_attrs:
703− dma_free_attrs(qproc->dev, fw->size, ptr, phys, dma_attrs);
708+ dma_free_attrs(qproc->dev, size, ptr, phys, dma_attrs);
709+ kfree(metadata);
704710
705711 return ret < 0 ? ret : 0;
706712 }
@@ -981,7 +987,18 @@ static int q6v5_mpss_load(struct q6v5 *qproc) · 274 unmodified lines
981987
982988 ptr = qproc->mpss_region + offset;
983989
984− if (phdr->p_filesz) {
990+ if (phdr->p_filesz && phdr->p_offset < fw->size) {
991+ /* Firmware is large enough to be non-split */
992+ if (phdr->p_offset + phdr->p_filesz > fw->size) {
993+ dev_err(qproc->dev,
994+ "failed to load segment %d from truncated file %s\n",
995+ i, fw_name);
996+ ret = -EINVAL;
997+ goto release_firmware;
998+ }
999+
1000+ memcpy(ptr, fw->data + phdr->p_offset, phdr->p_filesz);
1001+ } else if (phdr->p_filesz) {
9851002 /* Replace "xxx.xxx" with "xxx.bxx" */
9861003 sprintf(fw_name + fw_name_len - 3, "b%02d", i);
9871004 ret = request_firmware(&seg_fw, fw_name, qproc->dev);
drivers/remoteproc/remoteproc_core.c+15−0
@@ -512,6 +512,7 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc, · 511 unmodified lines
512512 /* Initialise vdev subdevice */
513513 snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
514514 rvdev->dev.parent = rproc->dev.parent;
515+ rvdev->dev.dma_pfn_offset = rproc->dev.parent->dma_pfn_offset;
515516 rvdev->dev.release = rproc_rvdev_release;
516517 dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name);
517518 dev_set_drvdata(&rvdev->dev, rvdev);
@@ -1058,6 +1059,20 @@ static int rproc_handle_resources(struct rproc *rproc, · 540 unmodified lines
10581059
10591060 dev_dbg(dev, "rsc: type %d\n", hdr->type);
10601061
1062+ if (hdr->type >= RSC_VENDOR_START &&
1063+ hdr->type <= RSC_VENDOR_END) {
1064+ ret = rproc_handle_rsc(rproc, hdr->type, rsc,
1065+ offset + sizeof(*hdr), avail);
1066+ if (ret == RSC_HANDLED)
1067+ continue;
1068+ else if (ret < 0)
1069+ break;
1070+
1071+ dev_warn(dev, "unsupported vendor resource %d\n",
1072+ hdr->type);
1073+ continue;
1074+ }
1075+
10611076 if (hdr->type >= RSC_LAST) {
10621077 dev_warn(dev, "unsupported resource %d\n", hdr->type);
10631078 continue;
drivers/remoteproc/remoteproc_elf_loader.c+1−2
@@ -247,8 +247,7 @@ find_table(struct device *dev, struct elf32_hdr *ehdr, size_t fw_size) · 246 unmodified lines
247247 }
248248
249249 /* make sure the offsets array isn't truncated */
250− if (table->num * sizeof(table->offset[0]) +
251− sizeof(struct resource_table) > size) {
250+ if (struct_size(table, offset, table->num) > size) {
252251 dev_err(dev, "resource table incomplete\n");
253252 return NULL;
254253 }
drivers/remoteproc/remoteproc_internal.h+11−0
@@ -98,6 +98,17 @@ static inline int rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) · 97 unmodified lines
9898 return 0;
9999 }
100100
101+static inline
102+int rproc_handle_rsc(struct rproc *rproc, u32 rsc_type, void *rsc, int offset,
103+ int avail)
104+{
105+ if (rproc->ops->handle_rsc)
106+ return rproc->ops->handle_rsc(rproc, rsc_type, rsc, offset,
107+ avail);
108+
109+ return RSC_IGNORED;
110+}
111+
101112 static inline
102113 struct resource_table *rproc_find_loaded_rsc_table(struct rproc *rproc,
103114 const struct firmware *fw)
drivers/remoteproc/stm32_rproc.c+628−0
@@ -0,0 +1,628 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
4+ * Authors: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
5+ * Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
6+ */
7+
8+#include <linux/arm-smccc.h>
9+#include <linux/dma-mapping.h>
10+#include <linux/interrupt.h>
11+#include <linux/io.h>
12+#include <linux/mailbox_client.h>
13+#include <linux/mfd/syscon.h>
14+#include <linux/module.h>
15+#include <linux/of_address.h>
16+#include <linux/of_device.h>
17+#include <linux/of_reserved_mem.h>
18+#include <linux/regmap.h>
19+#include <linux/remoteproc.h>
20+#include <linux/reset.h>
21+
22+#include "remoteproc_internal.h"
23+
24+#define HOLD_BOOT 0
25+#define RELEASE_BOOT 1
26+
27+#define MBOX_NB_VQ 2
28+#define MBOX_NB_MBX 3
29+
30+#define STM32_SMC_RCC 0x82001000
31+#define STM32_SMC_REG_WRITE 0x1
32+
33+#define STM32_MBX_VQ0 "vq0"
34+#define STM32_MBX_VQ1 "vq1"
35+#define STM32_MBX_SHUTDOWN "shutdown"
36+
37+struct stm32_syscon {
38+ struct regmap *map;
39+ u32 reg;
40+ u32 mask;
41+};
42+
43+struct stm32_rproc_mem {
44+ char name[20];
45+ void __iomem *cpu_addr;
46+ phys_addr_t bus_addr;
47+ u32 dev_addr;
48+ size_t size;
49+};
50+
51+struct stm32_rproc_mem_ranges {
52+ u32 dev_addr;
53+ u32 bus_addr;
54+ u32 size;
55+};
56+
57+struct stm32_mbox {
58+ const unsigned char name[10];
59+ struct mbox_chan *chan;
60+ struct mbox_client client;
61+ int vq_id;
62+};
63+
64+struct stm32_rproc {
65+ struct reset_control *rst;
66+ struct stm32_syscon hold_boot;
67+ struct stm32_syscon pdds;
68+ u32 nb_rmems;
69+ struct stm32_rproc_mem *rmems;
70+ struct stm32_mbox mb[MBOX_NB_MBX];
71+ bool secured_soc;
72+};
73+
74+static int stm32_rproc_pa_to_da(struct rproc *rproc, phys_addr_t pa, u64 *da)
75+{
76+ unsigned int i;
77+ struct stm32_rproc *ddata = rproc->priv;
78+ struct stm32_rproc_mem *p_mem;
79+
80+ for (i = 0; i < ddata->nb_rmems; i++) {
81+ p_mem = &ddata->rmems[i];
82+
83+ if (pa < p_mem->bus_addr ||
84+ pa >= p_mem->bus_addr + p_mem->size)
85+ continue;
86+ *da = pa - p_mem->bus_addr + p_mem->dev_addr;
87+ dev_dbg(rproc->dev.parent, "pa %pa to da %llx\n", &pa, *da);
88+ return 0;
89+ }
90+
91+ return -EINVAL;
92+}
93+
94+static int stm32_rproc_mem_alloc(struct rproc *rproc,
95+ struct rproc_mem_entry *mem)
96+{
97+ struct device *dev = rproc->dev.parent;
98+ void *va;
99+
100+ dev_dbg(dev, "map memory: %pa+%x\n", &mem->dma, mem->len);
101+ va = ioremap_wc(mem->dma, mem->len);
102+ if (IS_ERR_OR_NULL(va)) {
103+ dev_err(dev, "Unable to map memory region: %pa+%x\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+
114+static int stm32_rproc_mem_release(struct rproc *rproc,
115+ struct rproc_mem_entry *mem)
116+{
117+ dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma);
118+ iounmap(mem->va);
119+
120+ return 0;
121+}
122+
123+static int stm32_rproc_of_memory_translations(struct rproc *rproc)
124+{
125+ struct device *parent, *dev = rproc->dev.parent;
126+ struct stm32_rproc *ddata = rproc->priv;
127+ struct device_node *np;
128+ struct stm32_rproc_mem *p_mems;
129+ struct stm32_rproc_mem_ranges *mem_range;
130+ int cnt, array_size, i, ret = 0;
131+
132+ parent = dev->parent;
133+ np = parent->of_node;
134+
135+ cnt = of_property_count_elems_of_size(np, "dma-ranges",
136+ sizeof(*mem_range));
137+ if (cnt <= 0) {
138+ dev_err(dev, "%s: dma-ranges property not defined\n", __func__);
139+ return -EINVAL;
140+ }
141+
142+ p_mems = devm_kcalloc(dev, cnt, sizeof(*p_mems), GFP_KERNEL);
143+ if (!p_mems)
144+ return -ENOMEM;
145+ mem_range = kcalloc(cnt, sizeof(*mem_range), GFP_KERNEL);
146+ if (!mem_range)
147+ return -ENOMEM;
148+
149+ array_size = cnt * sizeof(struct stm32_rproc_mem_ranges) / sizeof(u32);
150+
151+ ret = of_property_read_u32_array(np, "dma-ranges",
152+ (u32 *)mem_range, array_size);
153+ if (ret) {
154+ dev_err(dev, "error while get dma-ranges property: %x\n", ret);
155+ goto free_mem;
156+ }
157+
158+ for (i = 0; i < cnt; i++) {
159+ p_mems[i].bus_addr = mem_range[i].bus_addr;
160+ p_mems[i].dev_addr = mem_range[i].dev_addr;
161+ p_mems[i].size = mem_range[i].size;
162+
163+ dev_dbg(dev, "memory range[%i]: da %#x, pa %pa, size %#zx:\n",
164+ i, p_mems[i].dev_addr, &p_mems[i].bus_addr,
165+ p_mems[i].size);
166+ }
167+
168+ ddata->rmems = p_mems;
169+ ddata->nb_rmems = cnt;
170+
171+free_mem:
172+ kfree(mem_range);
173+ return ret;
174+}
175+
176+static int stm32_rproc_mbox_idx(struct rproc *rproc, const unsigned char *name)
177+{
178+ struct stm32_rproc *ddata = rproc->priv;
179+ int i;
180+
181+ for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) {
182+ if (!strncmp(ddata->mb[i].name, name, strlen(name)))
183+ return i;
184+ }
185+ dev_err(&rproc->dev, "mailbox %s not found\n", name);
186+
187+ return -EINVAL;
188+}
189+
190+static int stm32_rproc_elf_load_rsc_table(struct rproc *rproc,
191+ const struct firmware *fw)
192+{
193+ if (rproc_elf_load_rsc_table(rproc, fw))
194+ dev_warn(&rproc->dev, "no resource table found for this firmware\n");
195+
196+ return 0;
197+}
198+
199+static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
200+{
201+ struct device *dev = rproc->dev.parent;
202+ struct device_node *np = dev->of_node;
203+ struct of_phandle_iterator it;
204+ struct rproc_mem_entry *mem;
205+ struct reserved_mem *rmem;
206+ u64 da;
207+ int index = 0;
208+
209+ /* Register associated reserved memory regions */
210+ of_phandle_iterator_init(&it, np, "memory-region", NULL, 0);
211+ while (of_phandle_iterator_next(&it) == 0) {
212+ rmem = of_reserved_mem_lookup(it.node);
213+ if (!rmem) {
214+ dev_err(dev, "unable to acquire memory-region\n");
215+ return -EINVAL;
216+ }
217+
218+ if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) {
219+ dev_err(dev, "memory region not valid %pa\n",
220+ &rmem->base);
221+ return -EINVAL;
222+ }
223+
224+ /* No need to map vdev buffer */
225+ if (strcmp(it.node->name, "vdev0buffer")) {
226+ /* Register memory region */
227+ mem = rproc_mem_entry_init(dev, NULL,
228+ (dma_addr_t)rmem->base,
229+ rmem->size, da,
230+ stm32_rproc_mem_alloc,
231+ stm32_rproc_mem_release,
232+ it.node->name);
233+
234+ if (mem)
235+ rproc_coredump_add_segment(rproc, da,
236+ rmem->size);
237+ } else {
238+ /* Register reserved memory for vdev buffer alloc */
239+ mem = rproc_of_resm_mem_entry_init(dev, index,
240+ rmem->size,
241+ rmem->base,
242+ it.node->name);
243+ }
244+
245+ if (!mem)
246+ return -ENOMEM;
247+
248+ rproc_add_carveout(rproc, mem);
249+ index++;
250+ }
251+
252+ return stm32_rproc_elf_load_rsc_table(rproc, fw);
253+}
254+
255+static irqreturn_t stm32_rproc_wdg(int irq, void *data)
256+{
257+ struct rproc *rproc = data;
258+
259+ rproc_report_crash(rproc, RPROC_WATCHDOG);
260+
261+ return IRQ_HANDLED;
262+}
263+
264+static void stm32_rproc_mb_callback(struct mbox_client *cl, void *data)
265+{
266+ struct rproc *rproc = dev_get_drvdata(cl->dev);
267+ struct stm32_mbox *mb = container_of(cl, struct stm32_mbox, client);
268+
269+ if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE)
270+ dev_dbg(&rproc->dev, "no message found in vq%d\n", mb->vq_id);
271+}
272+
273+static void stm32_rproc_free_mbox(struct rproc *rproc)
274+{
275+ struct stm32_rproc *ddata = rproc->priv;
276+ unsigned int i;
277+
278+ for (i = 0; i < ARRAY_SIZE(ddata->mb); i++) {
279+ if (ddata->mb[i].chan)
280+ mbox_free_channel(ddata->mb[i].chan);
281+ ddata->mb[i].chan = NULL;
282+ }
283+}
284+
285+static const struct stm32_mbox stm32_rproc_mbox[MBOX_NB_MBX] = {
286+ {
287+ .name = STM32_MBX_VQ0,
288+ .vq_id = 0,
289+ .client = {
290+ .rx_callback = stm32_rproc_mb_callback,
291+ .tx_block = false,
292+ },
293+ },
294+ {
295+ .name = STM32_MBX_VQ1,
296+ .vq_id = 1,
297+ .client = {
298+ .rx_callback = stm32_rproc_mb_callback,
299+ .tx_block = false,
300+ },
301+ },
302+ {
303+ .name = STM32_MBX_SHUTDOWN,
304+ .vq_id = -1,
305+ .client = {
306+ .tx_block = true,
307+ .tx_done = NULL,
308+ .tx_tout = 500, /* 500 ms time out */
309+ },
310+ }
311+};
312+
313+static void stm32_rproc_request_mbox(struct rproc *rproc)
314+{
315+ struct stm32_rproc *ddata = rproc->priv;
316+ struct device *dev = &rproc->dev;
317+ unsigned int i;
318+ const unsigned char *name;
319+ struct mbox_client *cl;
320+
321+ /* Initialise mailbox structure table */
322+ memcpy(ddata->mb, stm32_rproc_mbox, sizeof(stm32_rproc_mbox));
323+
324+ for (i = 0; i < MBOX_NB_MBX; i++) {
325+ name = ddata->mb[i].name;
326+
327+ cl = &ddata->mb[i].client;
328+ cl->dev = dev->parent;
329+
330+ ddata->mb[i].chan = mbox_request_channel_byname(cl, name);
331+ if (IS_ERR(ddata->mb[i].chan)) {
332+ dev_warn(dev, "cannot get %s mbox\n", name);
333+ ddata->mb[i].chan = NULL;
334+ }
335+ }
336+}
337+
338+static int stm32_rproc_set_hold_boot(struct rproc *rproc, bool hold)
339+{
340+ struct stm32_rproc *ddata = rproc->priv;
341+ struct stm32_syscon hold_boot = ddata->hold_boot;
342+ struct arm_smccc_res smc_res;
343+ int val, err;
344+
345+ val = hold ? HOLD_BOOT : RELEASE_BOOT;
346+
347+ if (IS_ENABLED(CONFIG_HAVE_ARM_SMCCC) && ddata->secured_soc) {
348+ arm_smccc_smc(STM32_SMC_RCC, STM32_SMC_REG_WRITE,
349+ hold_boot.reg, val, 0, 0, 0, 0, &smc_res);
350+ err = smc_res.a0;
351+ } else {
352+ err = regmap_update_bits(hold_boot.map, hold_boot.reg,
353+ hold_boot.mask, val);
354+ }
355+
356+ if (err)
357+ dev_err(&rproc->dev, "failed to set hold boot\n");
358+
359+ return err;
360+}
361+
362+static void stm32_rproc_add_coredump_trace(struct rproc *rproc)
363+{
364+ struct rproc_debug_trace *trace;
365+ struct rproc_dump_segment *segment;
366+ bool already_added;
367+
368+ list_for_each_entry(trace, &rproc->traces, node) {
369+ already_added = false;
370+
371+ list_for_each_entry(segment, &rproc->dump_segments, node) {
372+ if (segment->da == trace->trace_mem.da) {
373+ already_added = true;
374+ break;
375+ }
376+ }
377+
378+ if (!already_added)
379+ rproc_coredump_add_segment(rproc, trace->trace_mem.da,
380+ trace->trace_mem.len);
381+ }
382+}
383+
384+static int stm32_rproc_start(struct rproc *rproc)
385+{
386+ int err;
387+
388+ stm32_rproc_add_coredump_trace(rproc);
389+
390+ err = stm32_rproc_set_hold_boot(rproc, false);
391+ if (err)
392+ return err;
393+
394+ return stm32_rproc_set_hold_boot(rproc, true);
395+}
396+
397+static int stm32_rproc_stop(struct rproc *rproc)
398+{
399+ struct stm32_rproc *ddata = rproc->priv;
400+ int err, dummy_data, idx;
401+
402+ /* request shutdown of the remote processor */
403+ if (rproc->state != RPROC_OFFLINE) {
404+ idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN);
405+ if (idx >= 0 && ddata->mb[idx].chan) {
406+ /* a dummy data is sent to allow to block on transmit */
407+ err = mbox_send_message(ddata->mb[idx].chan,
408+ &dummy_data);
409+ if (err < 0)
410+ dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n");
411+ }
412+ }
413+
414+ err = stm32_rproc_set_hold_boot(rproc, true);
415+ if (err)
416+ return err;
417+
418+ err = reset_control_assert(ddata->rst);
419+ if (err) {
420+ dev_err(&rproc->dev, "failed to assert the reset\n");
421+ return err;
422+ }
423+
424+ /* to allow platform Standby power mode, set remote proc Deep Sleep */
425+ if (ddata->pdds.map) {
426+ err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg,
427+ ddata->pdds.mask, 1);
428+ if (err) {
429+ dev_err(&rproc->dev, "failed to set pdds\n");
430+ return err;
431+ }
432+ }
433+
434+ return 0;
435+}
436+
437+static void stm32_rproc_kick(struct rproc *rproc, int vqid)
438+{
439+ struct stm32_rproc *ddata = rproc->priv;
440+ unsigned int i;
441+ int err;
442+
443+ if (WARN_ON(vqid >= MBOX_NB_VQ))
444+ return;
445+
446+ for (i = 0; i < MBOX_NB_MBX; i++) {
447+ if (vqid != ddata->mb[i].vq_id)
448+ continue;
449+ if (!ddata->mb[i].chan)
450+ return;
451+ err = mbox_send_message(ddata->mb[i].chan, (void *)(long)vqid);
452+ if (err < 0)
453+ dev_err(&rproc->dev, "%s: failed (%s, err:%d)\n",
454+ __func__, ddata->mb[i].name, err);
455+ return;
456+ }
457+}
458+
459+static struct rproc_ops st_rproc_ops = {
460+ .start = stm32_rproc_start,
461+ .stop = stm32_rproc_stop,
462+ .kick = stm32_rproc_kick,
463+ .load = rproc_elf_load_segments,
464+ .parse_fw = stm32_rproc_parse_fw,
465+ .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
466+ .sanity_check = rproc_elf_sanity_check,
467+ .get_boot_addr = rproc_elf_get_boot_addr,
468+};
469+
470+static const struct of_device_id stm32_rproc_match[] = {
471+ { .compatible = "st,stm32mp1-m4" },
472+ {},
473+};
474+MODULE_DEVICE_TABLE(of, stm32_rproc_match);
475+
476+static int stm32_rproc_get_syscon(struct device_node *np, const char *prop,
477+ struct stm32_syscon *syscon)
478+{
479+ int err = 0;
480+
481+ syscon->map = syscon_regmap_lookup_by_phandle(np, prop);
482+ if (IS_ERR(syscon->map)) {
483+ err = PTR_ERR(syscon->map);
484+ syscon->map = NULL;
485+ goto out;
486+ }
487+
488+ err = of_property_read_u32_index(np, prop, 1, &syscon->reg);
489+ if (err)
490+ goto out;
491+
492+ err = of_property_read_u32_index(np, prop, 2, &syscon->mask);
493+
494+out:
495+ return err;
496+}
497+
498+static int stm32_rproc_parse_dt(struct platform_device *pdev)
499+{
500+ struct device *dev = &pdev->dev;
501+ struct device_node *np = dev->of_node;
502+ struct rproc *rproc = platform_get_drvdata(pdev);
503+ struct stm32_rproc *ddata = rproc->priv;
504+ struct stm32_syscon tz;
505+ unsigned int tzen;
506+ int err, irq;
507+
508+ irq = platform_get_irq(pdev, 0);
509+ if (irq > 0) {
510+ err = devm_request_irq(dev, irq, stm32_rproc_wdg, 0,
511+ dev_name(dev), rproc);
512+ if (err) {
513+ dev_err(dev, "failed to request wdg irq\n");
514+ return err;
515+ }
516+
517+ dev_info(dev, "wdg irq registered\n");
518+ }
519+
520+ ddata->rst = devm_reset_control_get_by_index(dev, 0);
521+ if (IS_ERR(ddata->rst)) {
522+ dev_err(dev, "failed to get mcu reset\n");
523+ return PTR_ERR(ddata->rst);
524+ }
525+
526+ /*
527+ * if platform is secured the hold boot bit must be written by
528+ * smc call and read normally.
529+ * if not secure the hold boot bit could be read/write normally
530+ */
531+ err = stm32_rproc_get_syscon(np, "st,syscfg-tz", &tz);
532+ if (err) {
533+ dev_err(dev, "failed to get tz syscfg\n");
534+ return err;
535+ }
536+
537+ err = regmap_read(tz.map, tz.reg, &tzen);
538+ if (err) {
539+ dev_err(&rproc->dev, "failed to read tzen\n");
540+ return err;
541+ }
542+ ddata->secured_soc = tzen & tz.mask;
543+
544+ err = stm32_rproc_get_syscon(np, "st,syscfg-holdboot",
545+ &ddata->hold_boot);
546+ if (err) {
547+ dev_err(dev, "failed to get hold boot\n");
548+ return err;
549+ }
550+
551+ err = stm32_rproc_get_syscon(np, "st,syscfg-pdds", &ddata->pdds);
552+ if (err)
553+ dev_warn(dev, "failed to get pdds\n");
554+
555+ rproc->auto_boot = of_property_read_bool(np, "st,auto-boot");
556+
557+ return stm32_rproc_of_memory_translations(rproc);
558+}
559+
560+static int stm32_rproc_probe(struct platform_device *pdev)
561+{
562+ struct device *dev = &pdev->dev;
563+ struct stm32_rproc *ddata;
564+ struct device_node *np = dev->of_node;
565+ struct rproc *rproc;
566+ int ret;
567+
568+ ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
569+ if (ret)
570+ return ret;
571+
572+ rproc = rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata));
573+ if (!rproc)
574+ return -ENOMEM;
575+
576+ rproc->has_iommu = false;
577+ ddata = rproc->priv;
578+
579+ platform_set_drvdata(pdev, rproc);
580+
581+ ret = stm32_rproc_parse_dt(pdev);
582+ if (ret)
583+ goto free_rproc;
584+
585+ stm32_rproc_request_mbox(rproc);
586+
587+ ret = rproc_add(rproc);
588+ if (ret)
589+ goto free_mb;
590+
591+ return 0;
592+
593+free_mb:
594+ stm32_rproc_free_mbox(rproc);
595+free_rproc:
596+ rproc_free(rproc);
597+ return ret;
598+}
599+
600+static int stm32_rproc_remove(struct platform_device *pdev)
601+{
602+ struct rproc *rproc = platform_get_drvdata(pdev);
603+
604+ if (atomic_read(&rproc->power) > 0)
605+ rproc_shutdown(rproc);
606+
607+ rproc_del(rproc);
608+ stm32_rproc_free_mbox(rproc);
609+ rproc_free(rproc);
610+
611+ return 0;
612+}
613+
614+static struct platform_driver stm32_rproc_driver = {
615+ .probe = stm32_rproc_probe,
616+ .remove = stm32_rproc_remove,
617+ .driver = {
618+ .name = "stm32-rproc",
619+ .of_match_table = of_match_ptr(stm32_rproc_match),
620+ },
621+};
622+module_platform_driver(stm32_rproc_driver);
623+
624+MODULE_DESCRIPTION("STM32 Remote Processor Control Driver");
625+MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
626+MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>");
627+MODULE_LICENSE("GPL v2");
628+
drivers/soc/qcom/mdt_loader.c+85−3
@@ -66,6 +66,66 @@ ssize_t qcom_mdt_get_size(const struct firmware *fw) · 65 unmodified lines
6666 }
6767 EXPORT_SYMBOL_GPL(qcom_mdt_get_size);
6868
69+/**
70+ * qcom_mdt_read_metadata() - read header and metadata from mdt or mbn
71+ * @fw: firmware of mdt header or mbn
72+ * @data_len: length of the read metadata blob
73+ *
74+ * The mechanism that performs the authentication of the loading firmware
75+ * expects an ELF header directly followed by the segment of hashes, with no
76+ * padding inbetween. This function allocates a chunk of memory for this pair
77+ * and copy the two pieces into the buffer.
78+ *
79+ * In the case of split firmware the hash is found directly following the ELF
80+ * header, rather than at p_offset described by the second program header.
81+ *
82+ * The caller is responsible to free (kfree()) the returned pointer.
83+ *
84+ * Return: pointer to data, or ERR_PTR()
85+ */
86+void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len)
87+{
88+ const struct elf32_phdr *phdrs;
89+ const struct elf32_hdr *ehdr;
90+ size_t hash_offset;
91+ size_t hash_size;
92+ size_t ehdr_size;
93+ void *data;
94+
95+ ehdr = (struct elf32_hdr *)fw->data;
96+ phdrs = (struct elf32_phdr *)(ehdr + 1);
97+
98+ if (ehdr->e_phnum < 2)
99+ return ERR_PTR(-EINVAL);
100+
101+ if (phdrs[0].p_type == PT_LOAD || phdrs[1].p_type == PT_LOAD)
102+ return ERR_PTR(-EINVAL);
103+
104+ if ((phdrs[1].p_flags & QCOM_MDT_TYPE_MASK) != QCOM_MDT_TYPE_HASH)
105+ return ERR_PTR(-EINVAL);
106+
107+ ehdr_size = phdrs[0].p_filesz;
108+ hash_size = phdrs[1].p_filesz;
109+
110+ data = kmalloc(ehdr_size + hash_size, GFP_KERNEL);
111+ if (!data)
112+ return ERR_PTR(-ENOMEM);
113+
114+ /* Is the header and hash already packed */
115+ if (ehdr_size + hash_size == fw->size)
116+ hash_offset = phdrs[0].p_filesz;
117+ else
118+ hash_offset = phdrs[1].p_offset;
119+
120+ memcpy(data, fw->data, ehdr_size);
121+ memcpy(data + ehdr_size, fw->data + hash_offset, hash_size);
122+
123+ *data_len = ehdr_size + hash_size;
124+
125+ return data;
126+}
127+EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata);
128+
69129 static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
70130 const char *firmware, int pas_id, void *mem_region,
71131 phys_addr_t mem_phys, size_t mem_size,
@@ -78,12 +138,14 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, · 6 unmodified lines
78138 phys_addr_t mem_reloc;
79139 phys_addr_t min_addr = PHYS_ADDR_MAX;
80140 phys_addr_t max_addr = 0;
141+ size_t metadata_len;
81142 size_t fw_name_len;
82143 ssize_t offset;
144+ void *metadata;
83145 char *fw_name;
84146 bool relocate = false;
85147 void *ptr;
86− int ret;
148+ int ret = 0;
87149 int i;
88150
89151 if (!fw || !mem_region || !mem_phys || !mem_size)
@@ -101,7 +163,15 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, · 11 unmodified lines
101163 return -ENOMEM;
102164
103165 if (pas_init) {
104− ret = qcom_scm_pas_init_image(pas_id, fw->data, fw->size);
166+ metadata = qcom_mdt_read_metadata(fw, &metadata_len);
167+ if (IS_ERR(metadata)) {
168+ ret = PTR_ERR(metadata);
169+ goto out;
170+ }
171+
172+ ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len);
173+
174+ kfree(metadata);
105175 if (ret) {
106176 dev_err(dev, "invalid firmware metadata\n");
107177 goto out;
@@ -162,7 +232,19 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw, · 54 unmodified lines
162232
163233 ptr = mem_region + offset;
164234
165− if (phdr->p_filesz) {
235+ if (phdr->p_filesz && phdr->p_offset < fw->size) {
236+ /* Firmware is large enough to be non-split */
237+ if (phdr->p_offset + phdr->p_filesz > fw->size) {
238+ dev_err(dev,
239+ "failed to load segment %d from truncated file %s\n",
240+ i, firmware);
241+ ret = -EINVAL;
242+ break;
243+ }
244+
245+ memcpy(ptr, fw->data + phdr->p_offset, phdr->p_filesz);
246+ } else if (phdr->p_filesz) {
247+ /* Firmware not large enough, load split-out segments */
166248 sprintf(fw_name + fw_name_len - 3, "b%02d", i);
167249 ret = request_firmware_into_buf(&seg_fw, fw_name, dev,
168250 ptr, phdr->p_filesz);
include/linux/remoteproc.h+26−6
@@ -100,7 +100,9 @@ struct fw_rsc_hdr { · 99 unmodified lines
100100 * the remote processor will be writing logs.
101101 * @RSC_VDEV: declare support for a virtio device, and serve as its
102102 * virtio header.
103− * @RSC_LAST: just keep this one at the end
103+ * @RSC_LAST: just keep this one at the end of standard resources
104+ * @RSC_VENDOR_START: start of the vendor specific resource types range
105+ * @RSC_VENDOR_END: end of the vendor specific resource types range
104106 *
105107 * For more details regarding a specific resource type, please see its
106108 * dedicated structure below.
@@ -111,11 +113,13 @@ struct fw_rsc_hdr { · 4 unmodified lines
111113 * please update it as needed.
112114 */
113115 enum fw_resource_type {
114− RSC_CARVEOUT = 0,
115− RSC_DEVMEM = 1,
116− RSC_TRACE = 2,
117− RSC_VDEV = 3,
118− RSC_LAST = 4,
116+ RSC_CARVEOUT = 0,
117+ RSC_DEVMEM = 1,
118+ RSC_TRACE = 2,
119+ RSC_VDEV = 3,
120+ RSC_LAST = 4,
121+ RSC_VENDOR_START = 128,
122+ RSC_VENDOR_END = 512,
119123 };
120124
121125 #define FW_RSC_ADDR_ANY (-1)
@@ -339,6 +343,16 @@ struct rproc_mem_entry { · 217 unmodified lines
339343
340344 struct firmware;
341345
346+/**
347+ * enum rsc_handling_status - return status of rproc_ops handle_rsc hook
348+ * @RSC_HANDLED: resource was handled
349+ * @RSC_IGNORED: resource was ignored
350+ */
351+enum rsc_handling_status {
352+ RSC_HANDLED = 0,
353+ RSC_IGNORED = 1,
354+};
355+
342356 /**
343357 * struct rproc_ops - platform-specific device handlers
344358 * @start: power on the device and boot it
@@ -346,6 +360,10 @@ struct firmware; · 1 unmodified line
346360 * @kick: kick a virtqueue (virtqueue id given as a parameter)
347361 * @da_to_va: optional platform hook to perform address translations
348362 * @parse_fw: parse firmware to extract information (e.g. resource table)
363+ * @handle_rsc: optional platform hook to handle vendor resources. Should return
364+ * RSC_HANDLED if resource was handled, RSC_IGNORED if not handled and a
365+ * negative value on error
366+ * @load_rsc_table: load resource table from firmware image
349367 * @find_loaded_rsc_table: find the loaded resouce table
350368 * @load: load firmware to memory, where the remote processor
351369 * expects to find it
@@ -358,6 +376,8 @@ struct rproc_ops { · 6 unmodified lines
358376 void (*kick)(struct rproc *rproc, int vqid);
359377 void * (*da_to_va)(struct rproc *rproc, u64 da, int len);
360378 int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
379+ int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
380+ int offset, int avail);
361381 struct resource_table *(*find_loaded_rsc_table)(
362382 struct rproc *rproc, const struct firmware *fw);
363383 int (*load)(struct rproc *rproc, const struct firmware *fw);
include/linux/soc/qcom/mdt_loader.h+2−0
@@ -21,4 +21,6 @@ int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw, · 20 unmodified lines
2121 const char *fw_name, int pas_id, void *mem_region,
2222 phys_addr_t mem_phys, size_t mem_size,
2323 phys_addr_t *reloc_base);
24+void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len);
25+
2426 #endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t