Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'rproc-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux

Pull remoteproc updates from Bjorn Andersson:

- The maximum amount of DDR memory used by the Mediatek MT8188/MT8195
SCP is increased to handle new use cases. Handling of optional L1TCM
memory is made actually optional.

- An optimization is introduced to only clear the unused portion of IPI
shared buffers, rather than the entire buffer before writing the
message.

- Detection for IPC-only mode in the TI K3 DSP remoteproc driver is
corrected. The loglevel of a debug print in the same is lowered from
error.

- Support for attaching to an running remote processor is added to the
Xilinx R5F.

- An in-kernel implementation of the Qualcomm "protected domain mapper"
(aka service registry) service is introduced, to remove the
dependency on a userspace implementation to detect when the battery
monitor and USB Type-C port manager becomes available. This is then
integrated with the Qualcomm remoteproc driver.

- The Qualcomm PAS remoteproc driver gains support for attempting to
bust hwspinlocks held by the remote processor when it
crashed/stopped.

- The TI OMAP remoteproc driver is transitioned to use devres helpers
for various forms of allocations.

- Parsing of memory-regions in the i.MX remoteproc driver is improved
to avoid a NULL pointer dereference if the phandle reference is
empty. of_node reference counting is corrected in the same.

* tag 'rproc-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux:
remoteproc: mediatek: Increase MT8188/MT8195 SCP core0 DRAM size
remoteproc: k3-dsp: Fix log levels where appropriate
remoteproc: xlnx: Add attach detach support
remoteproc: qcom: select AUXILIARY_BUS
remoteproc: k3-r5: Fix IPC-only mode detection
remoteproc: mediatek: Don't attempt to remap l1tcm memory if missing
remoteproc: qcom: enable in-kernel PD mapper
dt-bindings: remoteproc: imx_rproc: Add minItems for power-domain
remoteproc: imx_rproc: Fix refcount mistake in imx_rproc_addr_init
remoteproc: omap: Use devm_rproc_add() helper
remoteproc: omap: Use devm action to release reserved memory
remoteproc: omap: Use devm_rproc_alloc() helper
remoteproc: imx_rproc: Skip over memory region when node value is NULL
dt-bindings: remoteproc: k3-dsp: Correct optional sram properties for AM62A SoCs
remoteproc: qcom_q6v5_pas: Add hwspinlock bust on stop
soc: qcom: smem: Add qcom_smem_bust_hwspin_lock_by_host()
remoteproc: mediatek: Zero out only remaining bytes of IPI buffer

+414 -84
+15
Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml
··· 59 59 maxItems: 32 60 60 61 61 power-domains: 62 + minItems: 2 62 63 maxItems: 8 63 64 64 65 fsl,auto-boot: ··· 99 98 then: 100 99 properties: 101 100 fsl,iomuxc-gpr: false 101 + 102 + - if: 103 + properties: 104 + compatible: 105 + contains: 106 + enum: 107 + - fsl,imx8qxp-cm4 108 + - fsl,imx8qm-cm4 109 + then: 110 + required: 111 + - power-domains 112 + else: 113 + properties: 114 + power-domains: false 102 115 103 116 additionalProperties: false 104 117
+51 -38
Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml
··· 25 25 host processor (Arm CorePac) to perform the device management of the remote 26 26 processor and to communicate with the remote processor. 27 27 28 - allOf: 29 - - $ref: /schemas/arm/keystone/ti,k3-sci-common.yaml# 30 - 31 28 properties: 32 29 compatible: 33 30 enum: ··· 86 89 should be defined as per the generic bindings in, 87 90 Documentation/devicetree/bindings/sram/sram.yaml 88 91 89 - if: 90 - properties: 91 - compatible: 92 - enum: 93 - - ti,j721e-c66-dsp 94 - then: 95 - properties: 96 - reg: 97 - items: 98 - - description: Address and Size of the L2 SRAM internal memory region 99 - - description: Address and Size of the L1 PRAM internal memory region 100 - - description: Address and Size of the L1 DRAM internal memory region 101 - reg-names: 102 - items: 103 - - const: l2sram 104 - - const: l1pram 105 - - const: l1dram 106 - else: 107 - if: 108 - properties: 109 - compatible: 110 - enum: 111 - - ti,am62a-c7xv-dsp 112 - - ti,j721e-c71-dsp 113 - - ti,j721s2-c71-dsp 114 - then: 115 - properties: 116 - reg: 117 - items: 118 - - description: Address and Size of the L2 SRAM internal memory region 119 - - description: Address and Size of the L1 DRAM internal memory region 120 - reg-names: 121 - items: 122 - - const: l2sram 123 - - const: l1dram 92 + allOf: 93 + - if: 94 + properties: 95 + compatible: 96 + enum: 97 + - ti,j721e-c66-dsp 98 + then: 99 + properties: 100 + reg: 101 + items: 102 + - description: Address and Size of the L2 SRAM internal memory region 103 + - description: Address and Size of the L1 PRAM internal memory region 104 + - description: Address and Size of the L1 DRAM internal memory region 105 + reg-names: 106 + items: 107 + - const: l2sram 108 + - const: l1pram 109 + - const: l1dram 110 + 111 + - if: 112 + properties: 113 + compatible: 114 + enum: 115 + - ti,j721e-c71-dsp 116 + - ti,j721s2-c71-dsp 117 + then: 118 + properties: 119 + reg: 120 + items: 121 + - description: Address and Size of the L2 SRAM internal memory region 122 + - description: Address and Size of the L1 DRAM internal memory region 123 + reg-names: 124 + items: 125 + - const: l2sram 126 + - const: l1dram 127 + 128 + - if: 129 + properties: 130 + compatible: 131 + enum: 132 + - ti,am62a-c7xv-dsp 133 + then: 134 + properties: 135 + reg: 136 + items: 137 + - description: Address and Size of the L2 SRAM internal memory region 138 + reg-names: 139 + items: 140 + - const: l2sram 141 + 142 + - $ref: /schemas/arm/keystone/ti,k3-sci-common.yaml# 124 143 125 144 required: 126 145 - compatible
+1
drivers/remoteproc/Kconfig
··· 166 166 167 167 config QCOM_RPROC_COMMON 168 168 tristate 169 + select AUXILIARY_BUS 169 170 170 171 config QCOM_Q6V5_COMMON 171 172 tristate
+8 -2
drivers/remoteproc/imx_rproc.c
··· 726 726 struct resource res; 727 727 728 728 node = of_parse_phandle(np, "memory-region", a); 729 + if (!node) 730 + continue; 729 731 /* Not map vdevbuffer, vdevring region */ 730 732 if (!strncmp(node->name, "vdev", strlen("vdev"))) { 731 733 of_node_put(node); 732 734 continue; 733 735 } 734 736 err = of_address_to_resource(node, 0, &res); 735 - of_node_put(node); 736 737 if (err) { 737 738 dev_err(dev, "unable to resolve memory region\n"); 739 + of_node_put(node); 738 740 return err; 739 741 } 740 742 741 - if (b >= IMX_RPROC_MEM_MAX) 743 + if (b >= IMX_RPROC_MEM_MAX) { 744 + of_node_put(node); 742 745 break; 746 + } 743 747 744 748 /* Not use resource version, because we might share region */ 745 749 priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, res.start, resource_size(&res)); 746 750 if (!priv->mem[b].cpu_addr) { 747 751 dev_err(dev, "failed to remap %pr\n", &res); 752 + of_node_put(node); 748 753 return -ENOMEM; 749 754 } 750 755 priv->mem[b].sys_addr = res.start; 751 756 priv->mem[b].size = resource_size(&res); 752 757 if (!strcmp(node->name, "rsc-table")) 753 758 priv->rsc_table = priv->mem[b].cpu_addr; 759 + of_node_put(node); 754 760 b++; 755 761 } 756 762
+13 -10
drivers/remoteproc/mtk_scp.c
··· 117 117 return; 118 118 } 119 119 120 - memset(scp->share_buf, 0, scp_sizes->ipi_share_buffer_size); 121 120 memcpy_fromio(scp->share_buf, &rcv_obj->share_buf, len); 121 + memset(&scp->share_buf[len], 0, scp_sizes->ipi_share_buffer_size - len); 122 122 handler(scp->share_buf, len, ipi_desc[id].priv); 123 123 scp_ipi_unlock(scp, id); 124 124 ··· 1344 1344 1345 1345 /* l1tcm is an optional memory region */ 1346 1346 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "l1tcm"); 1347 - scp_cluster->l1tcm_base = devm_ioremap_resource(dev, res); 1348 - if (IS_ERR(scp_cluster->l1tcm_base)) { 1349 - ret = PTR_ERR(scp_cluster->l1tcm_base); 1350 - if (ret != -EINVAL) 1351 - return dev_err_probe(dev, ret, "Failed to map l1tcm memory\n"); 1347 + if (res) { 1348 + scp_cluster->l1tcm_base = devm_ioremap_resource(dev, res); 1349 + if (IS_ERR(scp_cluster->l1tcm_base)) 1350 + return dev_err_probe(dev, PTR_ERR(scp_cluster->l1tcm_base), 1351 + "Failed to map l1tcm memory\n"); 1352 1352 1353 - scp_cluster->l1tcm_base = NULL; 1354 - } else { 1355 1353 scp_cluster->l1tcm_size = resource_size(res); 1356 1354 scp_cluster->l1tcm_phys = res->start; 1357 1355 } ··· 1388 1390 }; 1389 1391 1390 1392 static const struct mtk_scp_sizes_data mt8188_scp_sizes = { 1391 - .max_dram_size = 0x500000, 1393 + .max_dram_size = 0x800000, 1392 1394 .ipi_share_buffer_size = 600, 1393 1395 }; 1394 1396 1395 1397 static const struct mtk_scp_sizes_data mt8188_scp_c1_sizes = { 1396 1398 .max_dram_size = 0xA00000, 1397 1399 .ipi_share_buffer_size = 600, 1400 + }; 1401 + 1402 + static const struct mtk_scp_sizes_data mt8195_scp_sizes = { 1403 + .max_dram_size = 0x800000, 1404 + .ipi_share_buffer_size = 288, 1398 1405 }; 1399 1406 1400 1407 static const struct mtk_scp_of_data mt8183_of_data = { ··· 1479 1476 .scp_da_to_va = mt8192_scp_da_to_va, 1480 1477 .host_to_scp_reg = MT8192_GIPC_IN_SET, 1481 1478 .host_to_scp_int_bit = MT8192_HOST_IPC_INT_BIT, 1482 - .scp_sizes = &default_scp_sizes, 1479 + .scp_sizes = &mt8195_scp_sizes, 1483 1480 }; 1484 1481 1485 1482 static const struct mtk_scp_of_data mt8195_of_data_c1 = {
+19 -27
drivers/remoteproc/omap_remoteproc.c
··· 1277 1277 return 0; 1278 1278 } 1279 1279 1280 + static void omap_rproc_mem_release(void *data) 1281 + { 1282 + struct device *dev = data; 1283 + 1284 + of_reserved_mem_device_release(dev); 1285 + } 1286 + 1280 1287 static int omap_rproc_probe(struct platform_device *pdev) 1281 1288 { 1282 1289 struct device_node *np = pdev->dev.of_node; ··· 1312 1305 return ret; 1313 1306 } 1314 1307 1315 - rproc = rproc_alloc(&pdev->dev, dev_name(&pdev->dev), &omap_rproc_ops, 1316 - firmware, sizeof(*oproc)); 1308 + rproc = devm_rproc_alloc(&pdev->dev, dev_name(&pdev->dev), &omap_rproc_ops, 1309 + firmware, sizeof(*oproc)); 1317 1310 if (!rproc) 1318 1311 return -ENOMEM; 1319 1312 ··· 1325 1318 1326 1319 ret = omap_rproc_of_get_internal_memories(pdev, rproc); 1327 1320 if (ret) 1328 - goto free_rproc; 1321 + return ret; 1329 1322 1330 1323 ret = omap_rproc_get_boot_data(pdev, rproc); 1331 1324 if (ret) 1332 - goto free_rproc; 1325 + return ret; 1333 1326 1334 1327 ret = omap_rproc_of_get_timers(pdev, rproc); 1335 1328 if (ret) 1336 - goto free_rproc; 1329 + return ret; 1337 1330 1338 1331 init_completion(&oproc->pm_comp); 1339 1332 oproc->autosuspend_delay = DEFAULT_AUTOSUSPEND_DELAY; ··· 1344 1337 pm_runtime_set_autosuspend_delay(&pdev->dev, oproc->autosuspend_delay); 1345 1338 1346 1339 oproc->fck = devm_clk_get(&pdev->dev, 0); 1347 - if (IS_ERR(oproc->fck)) { 1348 - ret = PTR_ERR(oproc->fck); 1349 - goto free_rproc; 1350 - } 1340 + if (IS_ERR(oproc->fck)) 1341 + return PTR_ERR(oproc->fck); 1351 1342 1352 1343 ret = of_reserved_mem_device_init(&pdev->dev); 1353 1344 if (ret) { ··· 1353 1348 dev_warn(&pdev->dev, "Typically this should be provided,\n"); 1354 1349 dev_warn(&pdev->dev, "only omit if you know what you are doing.\n"); 1355 1350 } 1351 + ret = devm_add_action_or_reset(&pdev->dev, omap_rproc_mem_release, &pdev->dev); 1352 + if (ret) 1353 + return ret; 1356 1354 1357 1355 platform_set_drvdata(pdev, rproc); 1358 1356 1359 - ret = rproc_add(rproc); 1357 + ret = devm_rproc_add(&pdev->dev, rproc); 1360 1358 if (ret) 1361 - goto release_mem; 1359 + return ret; 1362 1360 1363 1361 return 0; 1364 - 1365 - release_mem: 1366 - of_reserved_mem_device_release(&pdev->dev); 1367 - free_rproc: 1368 - rproc_free(rproc); 1369 - return ret; 1370 - } 1371 - 1372 - static void omap_rproc_remove(struct platform_device *pdev) 1373 - { 1374 - struct rproc *rproc = platform_get_drvdata(pdev); 1375 - 1376 - rproc_del(rproc); 1377 - rproc_free(rproc); 1378 - of_reserved_mem_device_release(&pdev->dev); 1379 1362 } 1380 1363 1381 1364 static const struct dev_pm_ops omap_rproc_pm_ops = { ··· 1374 1381 1375 1382 static struct platform_driver omap_rproc_driver = { 1376 1383 .probe = omap_rproc_probe, 1377 - .remove_new = omap_rproc_remove, 1378 1384 .driver = { 1379 1385 .name = "omap-rproc", 1380 1386 .pm = &omap_rproc_pm_ops,
+87
drivers/remoteproc/qcom_common.c
··· 13 13 #include <linux/notifier.h> 14 14 #include <linux/remoteproc.h> 15 15 #include <linux/remoteproc/qcom_rproc.h> 16 + #include <linux/auxiliary_bus.h> 16 17 #include <linux/rpmsg/qcom_glink.h> 17 18 #include <linux/rpmsg/qcom_smd.h> 18 19 #include <linux/slab.h> ··· 26 25 #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev) 27 26 #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev) 28 27 #define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev) 28 + #define to_pdm_subdev(d) container_of(d, struct qcom_rproc_pdm, subdev) 29 29 30 30 #define MAX_NUM_OF_SS 10 31 31 #define MAX_REGION_NAME_LENGTH 16 ··· 520 518 ssr->info = NULL; 521 519 } 522 520 EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev); 521 + 522 + static void pdm_dev_release(struct device *dev) 523 + { 524 + struct auxiliary_device *adev = to_auxiliary_dev(dev); 525 + 526 + kfree(adev); 527 + } 528 + 529 + static int pdm_notify_prepare(struct rproc_subdev *subdev) 530 + { 531 + struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev); 532 + struct auxiliary_device *adev; 533 + int ret; 534 + 535 + adev = kzalloc(sizeof(*adev), GFP_KERNEL); 536 + if (!adev) 537 + return -ENOMEM; 538 + 539 + adev->dev.parent = pdm->dev; 540 + adev->dev.release = pdm_dev_release; 541 + adev->name = "pd-mapper"; 542 + adev->id = pdm->index; 543 + 544 + ret = auxiliary_device_init(adev); 545 + if (ret) { 546 + kfree(adev); 547 + return ret; 548 + } 549 + 550 + ret = auxiliary_device_add(adev); 551 + if (ret) { 552 + auxiliary_device_uninit(adev); 553 + return ret; 554 + } 555 + 556 + pdm->adev = adev; 557 + 558 + return 0; 559 + } 560 + 561 + 562 + static void pdm_notify_unprepare(struct rproc_subdev *subdev) 563 + { 564 + struct qcom_rproc_pdm *pdm = to_pdm_subdev(subdev); 565 + 566 + if (!pdm->adev) 567 + return; 568 + 569 + auxiliary_device_delete(pdm->adev); 570 + auxiliary_device_uninit(pdm->adev); 571 + pdm->adev = NULL; 572 + } 573 + 574 + /** 575 + * qcom_add_pdm_subdev() - register PD Mapper subdevice 576 + * @rproc: rproc handle 577 + * @pdm: PDM subdevice handle 578 + * 579 + * Register @pdm so that Protection Device mapper service is started when the 580 + * DSP is started too. 581 + */ 582 + void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm) 583 + { 584 + pdm->dev = &rproc->dev; 585 + pdm->index = rproc->index; 586 + 587 + pdm->subdev.prepare = pdm_notify_prepare; 588 + pdm->subdev.unprepare = pdm_notify_unprepare; 589 + 590 + rproc_add_subdev(rproc, &pdm->subdev); 591 + } 592 + EXPORT_SYMBOL_GPL(qcom_add_pdm_subdev); 593 + 594 + /** 595 + * qcom_remove_pdm_subdev() - remove PD Mapper subdevice 596 + * @rproc: rproc handle 597 + * @pdm: PDM subdevice handle 598 + * 599 + * Remove the PD Mapper subdevice. 600 + */ 601 + void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm) 602 + { 603 + rproc_remove_subdev(rproc, &pdm->subdev); 604 + } 605 + EXPORT_SYMBOL_GPL(qcom_remove_pdm_subdev); 523 606 524 607 MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver"); 525 608 MODULE_LICENSE("GPL v2");
+10
drivers/remoteproc/qcom_common.h
··· 34 34 struct qcom_ssr_subsystem *info; 35 35 }; 36 36 37 + struct qcom_rproc_pdm { 38 + struct rproc_subdev subdev; 39 + struct device *dev; 40 + int index; 41 + struct auxiliary_device *adev; 42 + }; 43 + 37 44 void qcom_minidump(struct rproc *rproc, unsigned int minidump_id, 38 45 void (*rproc_dumpfn_t)(struct rproc *rproc, 39 46 struct rproc_dump_segment *segment, void *dest, size_t offset, ··· 58 51 void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr, 59 52 const char *ssr_name); 60 53 void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr); 54 + 55 + void qcom_add_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm); 56 + void qcom_remove_pdm_subdev(struct rproc *rproc, struct qcom_rproc_pdm *pdm); 61 57 62 58 #if IS_ENABLED(CONFIG_QCOM_SYSMON) 63 59 struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc,
+3
drivers/remoteproc/qcom_q6v5_adsp.c
··· 112 112 struct dev_pm_domain_list *pd_list; 113 113 114 114 struct qcom_rproc_glink glink_subdev; 115 + struct qcom_rproc_pdm pdm_subdev; 115 116 struct qcom_rproc_ssr ssr_subdev; 116 117 struct qcom_sysmon *sysmon; 117 118 ··· 727 726 goto disable_pm; 728 727 729 728 qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name); 729 + qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev); 730 730 qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name); 731 731 adsp->sysmon = qcom_add_sysmon_subdev(rproc, 732 732 desc->sysmon_name, ··· 757 755 758 756 qcom_q6v5_deinit(&adsp->q6v5); 759 757 qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev); 758 + qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev); 760 759 qcom_remove_sysmon_subdev(adsp->sysmon); 761 760 qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); 762 761 qcom_rproc_pds_detach(adsp);
+3
drivers/remoteproc/qcom_q6v5_mss.c
··· 228 228 229 229 struct qcom_rproc_glink glink_subdev; 230 230 struct qcom_rproc_subdev smd_subdev; 231 + struct qcom_rproc_pdm pdm_subdev; 231 232 struct qcom_rproc_ssr ssr_subdev; 232 233 struct qcom_sysmon *sysmon; 233 234 struct platform_device *bam_dmux; ··· 2103 2102 qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS); 2104 2103 qcom_add_glink_subdev(rproc, &qproc->glink_subdev, "mpss"); 2105 2104 qcom_add_smd_subdev(rproc, &qproc->smd_subdev); 2105 + qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev); 2106 2106 qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss"); 2107 2107 qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12); 2108 2108 if (IS_ERR(qproc->sysmon)) { ··· 2145 2143 qcom_q6v5_deinit(&qproc->q6v5); 2146 2144 qcom_remove_sysmon_subdev(qproc->sysmon); 2147 2145 qcom_remove_ssr_subdev(rproc, &qproc->ssr_subdev); 2146 + qcom_remove_pdm_subdev(rproc, &qproc->pdm_subdev); 2148 2147 qcom_remove_smd_subdev(rproc, &qproc->smd_subdev); 2149 2148 qcom_remove_glink_subdev(rproc, &qproc->glink_subdev); 2150 2149
+14
drivers/remoteproc/qcom_q6v5_pas.c
··· 52 52 const char *ssr_name; 53 53 const char *sysmon_name; 54 54 int ssctl_id; 55 + unsigned int smem_host_id; 55 56 56 57 int region_assign_idx; 57 58 int region_assign_count; ··· 82 81 int lite_pas_id; 83 82 unsigned int minidump_id; 84 83 int crash_reason_smem; 84 + unsigned int smem_host_id; 85 85 bool decrypt_shutdown; 86 86 const char *info_name; 87 87 ··· 111 109 112 110 struct qcom_rproc_glink glink_subdev; 113 111 struct qcom_rproc_subdev smd_subdev; 112 + struct qcom_rproc_pdm pdm_subdev; 114 113 struct qcom_rproc_ssr ssr_subdev; 115 114 struct qcom_sysmon *sysmon; 116 115 ··· 401 398 handover = qcom_q6v5_unprepare(&adsp->q6v5); 402 399 if (handover) 403 400 qcom_pas_handover(&adsp->q6v5); 401 + 402 + if (adsp->smem_host_id) 403 + ret = qcom_smem_bust_hwspin_lock_by_host(adsp->smem_host_id); 404 404 405 405 return ret; 406 406 } ··· 733 727 adsp->pas_id = desc->pas_id; 734 728 adsp->lite_pas_id = desc->lite_pas_id; 735 729 adsp->info_name = desc->sysmon_name; 730 + adsp->smem_host_id = desc->smem_host_id; 736 731 adsp->decrypt_shutdown = desc->decrypt_shutdown; 737 732 adsp->region_assign_idx = desc->region_assign_idx; 738 733 adsp->region_assign_count = min_t(int, MAX_ASSIGN_COUNT, desc->region_assign_count); ··· 778 771 779 772 qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name); 780 773 qcom_add_smd_subdev(rproc, &adsp->smd_subdev); 774 + qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev); 781 775 adsp->sysmon = qcom_add_sysmon_subdev(rproc, 782 776 desc->sysmon_name, 783 777 desc->ssctl_id); ··· 813 805 qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev); 814 806 qcom_remove_sysmon_subdev(adsp->sysmon); 815 807 qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev); 808 + qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev); 816 809 qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); 817 810 adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count); 818 811 device_init_wakeup(adsp->dev, false); ··· 1205 1196 .ssr_name = "lpass", 1206 1197 .sysmon_name = "adsp", 1207 1198 .ssctl_id = 0x14, 1199 + .smem_host_id = 2, 1208 1200 }; 1209 1201 1210 1202 static const struct adsp_data sm8550_cdsp_resource = { ··· 1226 1216 .ssr_name = "cdsp", 1227 1217 .sysmon_name = "cdsp", 1228 1218 .ssctl_id = 0x17, 1219 + .smem_host_id = 5, 1229 1220 }; 1230 1221 1231 1222 static const struct adsp_data sm8550_mpss_resource = { ··· 1247 1236 .ssr_name = "mpss", 1248 1237 .sysmon_name = "modem", 1249 1238 .ssctl_id = 0x12, 1239 + .smem_host_id = 1, 1250 1240 .region_assign_idx = 2, 1251 1241 .region_assign_count = 1, 1252 1242 .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA, ··· 1287 1275 .ssr_name = "cdsp", 1288 1276 .sysmon_name = "cdsp", 1289 1277 .ssctl_id = 0x17, 1278 + .smem_host_id = 5, 1290 1279 .region_assign_idx = 2, 1291 1280 .region_assign_count = 1, 1292 1281 .region_assign_shared = true, ··· 1312 1299 .ssr_name = "mpss", 1313 1300 .sysmon_name = "modem", 1314 1301 .ssctl_id = 0x12, 1302 + .smem_host_id = 1, 1315 1303 .region_assign_idx = 2, 1316 1304 .region_assign_count = 3, 1317 1305 .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA,
+3
drivers/remoteproc/qcom_q6v5_wcss.c
··· 148 148 bool requires_force_stop; 149 149 150 150 struct qcom_rproc_glink glink_subdev; 151 + struct qcom_rproc_pdm pdm_subdev; 151 152 struct qcom_rproc_ssr ssr_subdev; 152 153 }; 153 154 ··· 1053 1052 return ret; 1054 1053 1055 1054 qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss"); 1055 + qcom_add_pdm_subdev(rproc, &wcss->pdm_subdev); 1056 1056 qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss"); 1057 1057 1058 1058 if (desc->ssctl_id) ··· 1076 1074 struct q6v5_wcss *wcss = rproc->priv; 1077 1075 1078 1076 qcom_q6v5_deinit(&wcss->q6v5); 1077 + qcom_remove_pdm_subdev(rproc, &wcss->pdm_subdev); 1079 1078 rproc_del(rproc); 1080 1079 } 1081 1080
+1 -1
drivers/remoteproc/ti_k3_dsp_remoteproc.c
··· 327 327 goto put_mbox; 328 328 } 329 329 330 - dev_err(dev, "booting DSP core using boot addr = 0x%x\n", boot_addr); 330 + dev_dbg(dev, "booting DSP core using boot addr = 0x%x\n", boot_addr); 331 331 ret = ti_sci_proc_set_config(kproc->tsp, boot_addr, 0, 0); 332 332 if (ret) 333 333 goto put_mbox;
+7 -6
drivers/remoteproc/ti_k3_r5_remoteproc.c
··· 1144 1144 u32 atcm_enable, btcm_enable, loczrama; 1145 1145 struct k3_r5_core *core0; 1146 1146 enum cluster_mode mode = cluster->mode; 1147 + int reset_ctrl_status; 1147 1148 int ret; 1148 1149 1149 1150 core0 = list_first_entry(&cluster->cores, struct k3_r5_core, elem); ··· 1161 1160 r_state, c_state); 1162 1161 } 1163 1162 1164 - ret = reset_control_status(core->reset); 1165 - if (ret < 0) { 1163 + reset_ctrl_status = reset_control_status(core->reset); 1164 + if (reset_ctrl_status < 0) { 1166 1165 dev_err(cdev, "failed to get initial local reset status, ret = %d\n", 1167 - ret); 1168 - return ret; 1166 + reset_ctrl_status); 1167 + return reset_ctrl_status; 1169 1168 } 1170 1169 1171 1170 /* ··· 1200 1199 * irrelevant if module reset is asserted (POR value has local reset 1201 1200 * deasserted), and is deemed as remoteproc mode 1202 1201 */ 1203 - if (c_state && !ret && !halted) { 1202 + if (c_state && !reset_ctrl_status && !halted) { 1204 1203 dev_info(cdev, "configured R5F for IPC-only mode\n"); 1205 1204 kproc->rproc->state = RPROC_DETACHED; 1206 1205 ret = 1; ··· 1218 1217 ret = 0; 1219 1218 } else { 1220 1219 dev_err(cdev, "mismatched mode: local_reset = %s, module_reset = %s, core_state = %s\n", 1221 - !ret ? "deasserted" : "asserted", 1220 + !reset_ctrl_status ? "deasserted" : "asserted", 1222 1221 c_state ? "deasserted" : "asserted", 1223 1222 halted ? "halted" : "unhalted"); 1224 1223 ret = -EINVAL;
+151
drivers/remoteproc/xlnx_r5_remoteproc.c
··· 25 25 /* RX mailbox client buffer max length */ 26 26 #define MBOX_CLIENT_BUF_MAX (IPI_BUF_LEN_MAX + \ 27 27 sizeof(struct zynqmp_ipi_message)) 28 + 29 + #define RSC_TBL_XLNX_MAGIC ((uint32_t)'x' << 24 | (uint32_t)'a' << 16 | \ 30 + (uint32_t)'m' << 8 | (uint32_t)'p') 31 + 28 32 /* 29 33 * settings for RPU cluster mode which 30 34 * reflects possible values of xlnx,cluster-mode dt-property ··· 77 73 struct mbox_chan *rx_chan; 78 74 }; 79 75 76 + /** 77 + * struct rsc_tbl_data 78 + * 79 + * Platform specific data structure used to sync resource table address. 80 + * It's important to maintain order and size of each field on remote side. 81 + * 82 + * @version: version of data structure 83 + * @magic_num: 32-bit magic number. 84 + * @comp_magic_num: complement of above magic number 85 + * @rsc_tbl_size: resource table size 86 + * @rsc_tbl: resource table address 87 + */ 88 + struct rsc_tbl_data { 89 + const int version; 90 + const u32 magic_num; 91 + const u32 comp_magic_num; 92 + const u32 rsc_tbl_size; 93 + const uintptr_t rsc_tbl; 94 + } __packed; 95 + 80 96 /* 81 97 * Hardcoded TCM bank values. This will stay in driver to maintain backward 82 98 * compatibility with device-tree that does not have TCM information. ··· 119 95 /** 120 96 * struct zynqmp_r5_core 121 97 * 98 + * @rsc_tbl_va: resource table virtual address 122 99 * @dev: device of RPU instance 123 100 * @np: device node of RPU instance 124 101 * @tcm_bank_count: number TCM banks accessible to this RPU 125 102 * @tcm_banks: array of each TCM bank data 126 103 * @rproc: rproc handle 104 + * @rsc_tbl_size: resource table size retrieved from remote 127 105 * @pm_domain_id: RPU CPU power domain id 128 106 * @ipi: pointer to mailbox information 129 107 */ 130 108 struct zynqmp_r5_core { 109 + void __iomem *rsc_tbl_va; 131 110 struct device *dev; 132 111 struct device_node *np; 133 112 int tcm_bank_count; 134 113 struct mem_bank_data **tcm_banks; 135 114 struct rproc *rproc; 115 + u32 rsc_tbl_size; 136 116 u32 pm_domain_id; 137 117 struct mbox_info *ipi; 138 118 }; ··· 585 557 dev_dbg(dev, "TCM carveout %s addr=%llx, da=0x%x, size=0x%lx", 586 558 bank_name, bank_addr, da, bank_size); 587 559 560 + /* 561 + * In DETACHED state firmware is already running so no need to 562 + * request add TCM registers. However, request TCM PD node to let 563 + * platform management firmware know that TCM is in use. 564 + */ 565 + if (rproc->state == RPROC_DETACHED) 566 + continue; 567 + 588 568 rproc_mem = rproc_mem_entry_init(dev, NULL, bank_addr, 589 569 bank_size, da, 590 570 tcm_mem_map, tcm_mem_unmap, ··· 698 662 return 0; 699 663 } 700 664 665 + static struct resource_table *zynqmp_r5_get_loaded_rsc_table(struct rproc *rproc, 666 + size_t *size) 667 + { 668 + struct zynqmp_r5_core *r5_core; 669 + 670 + r5_core = rproc->priv; 671 + 672 + *size = r5_core->rsc_tbl_size; 673 + 674 + return (struct resource_table *)r5_core->rsc_tbl_va; 675 + } 676 + 677 + static int zynqmp_r5_get_rsc_table_va(struct zynqmp_r5_core *r5_core) 678 + { 679 + struct resource_table *rsc_tbl_addr; 680 + struct device *dev = r5_core->dev; 681 + struct rsc_tbl_data *rsc_data_va; 682 + struct resource res_mem; 683 + struct device_node *np; 684 + int ret; 685 + 686 + /* 687 + * It is expected from remote processor firmware to provide resource 688 + * table address via struct rsc_tbl_data data structure. 689 + * Start address of first entry under "memory-region" property list 690 + * contains that data structure which holds resource table address, size 691 + * and some magic number to validate correct resource table entry. 692 + */ 693 + np = of_parse_phandle(r5_core->np, "memory-region", 0); 694 + if (!np) { 695 + dev_err(dev, "failed to get memory region dev node\n"); 696 + return -EINVAL; 697 + } 698 + 699 + ret = of_address_to_resource(np, 0, &res_mem); 700 + of_node_put(np); 701 + if (ret) { 702 + dev_err(dev, "failed to get memory-region resource addr\n"); 703 + return -EINVAL; 704 + } 705 + 706 + rsc_data_va = (struct rsc_tbl_data *)ioremap_wc(res_mem.start, 707 + sizeof(struct rsc_tbl_data)); 708 + if (!rsc_data_va) { 709 + dev_err(dev, "failed to map resource table data address\n"); 710 + return -EIO; 711 + } 712 + 713 + /* 714 + * If RSC_TBL_XLNX_MAGIC number and its complement isn't found then 715 + * do not consider resource table address valid and don't attach 716 + */ 717 + if (rsc_data_va->magic_num != RSC_TBL_XLNX_MAGIC || 718 + rsc_data_va->comp_magic_num != ~RSC_TBL_XLNX_MAGIC) { 719 + dev_dbg(dev, "invalid magic number, won't attach\n"); 720 + return -EINVAL; 721 + } 722 + 723 + r5_core->rsc_tbl_va = ioremap_wc(rsc_data_va->rsc_tbl, 724 + rsc_data_va->rsc_tbl_size); 725 + if (!r5_core->rsc_tbl_va) { 726 + dev_err(dev, "failed to get resource table va\n"); 727 + return -EINVAL; 728 + } 729 + 730 + rsc_tbl_addr = (struct resource_table *)r5_core->rsc_tbl_va; 731 + 732 + /* 733 + * As of now resource table version 1 is expected. Don't fail to attach 734 + * but warn users about it. 735 + */ 736 + if (rsc_tbl_addr->ver != 1) 737 + dev_warn(dev, "unexpected resource table version %d\n", 738 + rsc_tbl_addr->ver); 739 + 740 + r5_core->rsc_tbl_size = rsc_data_va->rsc_tbl_size; 741 + 742 + iounmap((void __iomem *)rsc_data_va); 743 + 744 + return 0; 745 + } 746 + 747 + static int zynqmp_r5_attach(struct rproc *rproc) 748 + { 749 + dev_dbg(&rproc->dev, "rproc %d attached\n", rproc->index); 750 + 751 + return 0; 752 + } 753 + 754 + static int zynqmp_r5_detach(struct rproc *rproc) 755 + { 756 + /* 757 + * Generate last notification to remote after clearing virtio flag. 758 + * Remote can avoid polling on virtio reset flag if kick is generated 759 + * during detach by host and check virtio reset flag on kick interrupt. 760 + */ 761 + zynqmp_r5_rproc_kick(rproc, 0); 762 + 763 + return 0; 764 + } 765 + 701 766 static const struct rproc_ops zynqmp_r5_rproc_ops = { 702 767 .prepare = zynqmp_r5_rproc_prepare, 703 768 .unprepare = zynqmp_r5_rproc_unprepare, ··· 810 673 .sanity_check = rproc_elf_sanity_check, 811 674 .get_boot_addr = rproc_elf_get_boot_addr, 812 675 .kick = zynqmp_r5_rproc_kick, 676 + .get_loaded_rsc_table = zynqmp_r5_get_loaded_rsc_table, 677 + .attach = zynqmp_r5_attach, 678 + .detach = zynqmp_r5_detach, 813 679 }; 814 680 815 681 /** ··· 862 722 dev_err(cdev, "failed to add r5 remoteproc\n"); 863 723 goto free_rproc; 864 724 } 725 + 726 + /* 727 + * If firmware is already available in the memory then move rproc state 728 + * to DETACHED. Firmware can be preloaded via debugger or by any other 729 + * agent (processors) in the system. 730 + * If firmware isn't available in the memory and resource table isn't 731 + * found, then rproc state remains OFFLINE. 732 + */ 733 + if (!zynqmp_r5_get_rsc_table_va(r5_core)) 734 + r5_rproc->state = RPROC_DETACHED; 865 735 866 736 r5_core->rproc = r5_rproc; 867 737 return r5_core; ··· 1284 1134 for (i = 0; i < cluster->core_count; i++) { 1285 1135 r5_core = cluster->r5_cores[i]; 1286 1136 zynqmp_r5_free_mbox(r5_core->ipi); 1137 + iounmap(r5_core->rsc_tbl_va); 1287 1138 of_reserved_mem_device_release(r5_core->dev); 1288 1139 put_device(r5_core->dev); 1289 1140 rproc_del(r5_core->rproc);
+26
drivers/soc/qcom/smem.c
··· 359 359 /* Timeout (ms) for the trylock of remote spinlocks */ 360 360 #define HWSPINLOCK_TIMEOUT 1000 361 361 362 + /* The qcom hwspinlock id is always plus one from the smem host id */ 363 + #define SMEM_HOST_ID_TO_HWSPINLOCK_ID(__x) ((__x) + 1) 364 + 365 + /** 366 + * qcom_smem_bust_hwspin_lock_by_host() - bust the smem hwspinlock for a host 367 + * @host: remote processor id 368 + * 369 + * Busts the hwspin_lock for the given smem host id. This helper is intended 370 + * for remoteproc drivers that manage remoteprocs with an equivalent smem 371 + * driver instance in the remote firmware. Drivers can force a release of the 372 + * smem hwspin_lock if the rproc unexpectedly goes into a bad state. 373 + * 374 + * Context: Process context. 375 + * 376 + * Returns: 0 on success, otherwise negative errno. 377 + */ 378 + int qcom_smem_bust_hwspin_lock_by_host(unsigned int host) 379 + { 380 + /* This function is for remote procs, so ignore SMEM_HOST_APPS */ 381 + if (host == SMEM_HOST_APPS || host >= SMEM_HOST_COUNT) 382 + return -EINVAL; 383 + 384 + return hwspin_lock_bust(__smem->hwlock, SMEM_HOST_ID_TO_HWSPINLOCK_ID(host)); 385 + } 386 + EXPORT_SYMBOL_GPL(qcom_smem_bust_hwspin_lock_by_host); 387 + 362 388 /** 363 389 * qcom_smem_is_available() - Check if SMEM is available 364 390 *
+2
include/linux/soc/qcom/smem.h
··· 15 15 int qcom_smem_get_soc_id(u32 *id); 16 16 int qcom_smem_get_feature_code(u32 *code); 17 17 18 + int qcom_smem_bust_hwspin_lock_by_host(unsigned int host); 19 + 18 20 #endif