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 'mailbox-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox

Pull mailbox updates from Jassi Brar:
"broadcom:
- remove unused pdc_dma_map

imx:
- fix TXDB_V2 channel race condition

mediatek:
- cleanup and refactor driver
- add bindings for gce-props

omap:
- fix mailbox interrupt sharing

qcom:
- add bindings for SA8775p
- add CPUCP driver

zynqmp:
- make polling period configurable"

* tag 'mailbox-v6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox:
mailbox: mtk-cmdq: Move devm_mbox_controller_register() after devm_pm_runtime_enable()
mailbox: zynqmp-ipi: Make polling period configurable
mailbox: qcom-cpucp: fix 64BIT dependency
mailbox: Add support for QTI CPUCP mailbox controller
dt-bindings: mailbox: qcom: Add CPUCP mailbox controller bindings
dt-bindings: remoteproc: qcom,sa8775p-pas: Document the SA8775p ADSP, CDSP and GPDSP
mailbox: mtk-cmdq: add missing MODULE_DESCRIPTION() macro
mailbox: bcm-pdc: remove unused struct 'pdc_dma_map'
mailbox: imx: fix TXDB_V2 channel race condition
mailbox: omap: Fix mailbox interrupt sharing
mailbox: mtk-cmdq: Dynamically allocate clk_bulk_data structure
mailbox: mtk-cmdq: Move and partially refactor clocks probe
mailbox: mtk-cmdq: Stop requiring name for GCE clock
dt-bindings: mailbox: Add mediatek,gce-props.yaml

+548 -43
+52
Documentation/devicetree/bindings/mailbox/mediatek,gce-props.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mailbox/mediatek,gce-props.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: MediaTek Global Command Engine Common Properties 8 + 9 + maintainers: 10 + - Houlong Wei <houlong.wei@mediatek.com> 11 + 12 + description: 13 + The Global Command Engine (GCE) is an instruction based, multi-threaded, 14 + single-core command dispatcher for MediaTek hardware. The Command Queue 15 + (CMDQ) mailbox driver is a driver for GCE, implemented using the Linux 16 + mailbox framework. It is used to receive messages from mailbox consumers 17 + and configure GCE to execute the specified instruction set in the message. 18 + We use mediatek,gce-mailbox.yaml to define the properties for CMDQ mailbox 19 + driver. A device driver that uses the CMDQ driver to configure its hardware 20 + registers is a mailbox consumer. The mailbox consumer can request a mailbox 21 + channel corresponding to a GCE hardware thread to send a message, specifying 22 + that the GCE thread to configure its hardware. The mailbox provider can also 23 + reserve a mailbox channel to configure GCE hardware register by the specific 24 + GCE thread. This binding defines the common GCE properties for both mailbox 25 + provider and consumers. 26 + 27 + properties: 28 + mediatek,gce-events: 29 + description: 30 + GCE has an event table in SRAM, consisting of 1024 event IDs (0~1023). 31 + Each event ID has a boolean event value with the default value 0. 32 + The property mediatek,gce-events is used to obtain the event IDs. 33 + Some gce-events are hardware-bound and cannot be changed by software. 34 + For instance, in MT8195, when VDO0_MUTEX is stream done, VDO_MUTEX will 35 + send an event signal to GCE, setting the value of event ID 597 to 1. 36 + Similarly, in MT8188, the value of event ID 574 will be set to 1 when 37 + VOD0_MUTEX is stream done. 38 + On the other hand, some gce-events are not hardware-bound and can be 39 + changed by software. For example, in MT8188, we can set the value of 40 + event ID 855, which is not bound to any hardware, to 1 when the driver 41 + in the secure world completes a task. However, in MT8195, event ID 855 42 + is already bound to VDEC_LAT1, so we need to select another event ID to 43 + achieve the same purpose. This event ID can be any ID that is not bound 44 + to any hardware and is not yet used in any software driver. 45 + To determine if the event ID is bound to the hardware or used by a 46 + software driver, refer to the GCE header 47 + include/dt-bindings/gce/<chip>-gce.h of each chip. 48 + $ref: /schemas/types.yaml#/definitions/uint32-array 49 + minItems: 1 50 + maxItems: 32 51 + 52 + additionalProperties: true
+49
Documentation/devicetree/bindings/mailbox/qcom,cpucp-mbox.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/mailbox/qcom,cpucp-mbox.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm Technologies, Inc. CPUCP Mailbox Controller 8 + 9 + maintainers: 10 + - Sibi Sankar <quic_sibis@quicinc.com> 11 + 12 + description: 13 + The CPUSS Control Processor (CPUCP) mailbox controller enables communication 14 + between AP and CPUCP by acting as a doorbell between them. 15 + 16 + properties: 17 + compatible: 18 + items: 19 + - const: qcom,x1e80100-cpucp-mbox 20 + 21 + reg: 22 + items: 23 + - description: CPUCP rx register region 24 + - description: CPUCP tx register region 25 + 26 + interrupts: 27 + maxItems: 1 28 + 29 + "#mbox-cells": 30 + const: 1 31 + 32 + required: 33 + - compatible 34 + - reg 35 + - interrupts 36 + - "#mbox-cells" 37 + 38 + additionalProperties: false 39 + 40 + examples: 41 + - | 42 + #include <dt-bindings/interrupt-controller/arm-gic.h> 43 + 44 + mailbox@17430000 { 45 + compatible = "qcom,x1e80100-cpucp-mbox"; 46 + reg = <0x17430000 0x10000>, <0x18830000 0x10000>; 47 + interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; 48 + #mbox-cells = <1>; 49 + };
+160
Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml
··· 1 + # SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/remoteproc/qcom,sa8775p-pas.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Qualcomm SA8775p Peripheral Authentication Service 8 + 9 + maintainers: 10 + - Bartosz Golaszewski <bartosz.golaszewski@linaro.org> 11 + 12 + description: 13 + Qualcomm SA8775p SoC Peripheral Authentication Service loads and boots firmware 14 + on the Qualcomm DSP Hexagon cores. 15 + 16 + properties: 17 + compatible: 18 + enum: 19 + - qcom,sa8775p-adsp-pas 20 + - qcom,sa8775p-cdsp0-pas 21 + - qcom,sa8775p-cdsp1-pas 22 + - qcom,sa8775p-gpdsp0-pas 23 + - qcom,sa8775p-gpdsp1-pas 24 + 25 + reg: 26 + maxItems: 1 27 + 28 + clocks: 29 + items: 30 + - description: XO clock 31 + 32 + clock-names: 33 + items: 34 + - const: xo 35 + 36 + qcom,qmp: 37 + $ref: /schemas/types.yaml#/definitions/phandle 38 + description: Reference to the AOSS side-channel message RAM. 39 + 40 + firmware-name: 41 + $ref: /schemas/types.yaml#/definitions/string-array 42 + items: 43 + - description: Firmware name of the Hexagon core 44 + 45 + memory-region: 46 + items: 47 + - description: Memory region for main Firmware authentication 48 + 49 + interrupts: 50 + maxItems: 5 51 + 52 + interrupt-names: 53 + maxItems: 5 54 + 55 + required: 56 + - compatible 57 + - reg 58 + - memory-region 59 + 60 + allOf: 61 + - $ref: /schemas/remoteproc/qcom,pas-common.yaml# 62 + 63 + - if: 64 + properties: 65 + compatible: 66 + enum: 67 + - qcom,sa8775p-adsp-pas 68 + then: 69 + properties: 70 + power-domains: 71 + items: 72 + - description: LCX power domain 73 + - description: LMX power domain 74 + power-domain-names: 75 + items: 76 + - const: lcx 77 + - const: lmx 78 + 79 + - if: 80 + properties: 81 + compatible: 82 + enum: 83 + - qcom,sa8775p-cdsp0-pas 84 + - qcom,sa8775p-cdsp1-pas 85 + then: 86 + properties: 87 + power-domains: 88 + items: 89 + - description: CX power domain 90 + - description: MXC power domain 91 + - description: NSP0 power domain 92 + power-domain-names: 93 + items: 94 + - const: cx 95 + - const: mxc 96 + - const: nsp 97 + 98 + - if: 99 + properties: 100 + compatible: 101 + enum: 102 + - qcom,sa8775p-gpdsp0-pas 103 + - qcom,sa8775p-gpdsp1-pas 104 + then: 105 + properties: 106 + power-domains: 107 + items: 108 + - description: CX power domain 109 + - description: MXC power domain 110 + power-domain-names: 111 + items: 112 + - const: cx 113 + - const: mxc 114 + 115 + unevaluatedProperties: false 116 + 117 + examples: 118 + - | 119 + #include <dt-bindings/clock/qcom,rpmh.h> 120 + #include <dt-bindings/interconnect/qcom,sa8775p-rpmh.h> 121 + #include <dt-bindings/interrupt-controller/irq.h> 122 + #include <dt-bindings/mailbox/qcom-ipcc.h> 123 + #include <dt-bindings/power/qcom,rpmhpd.h> 124 + 125 + remoteproc@30000000 { 126 + compatible = "qcom,sa8775p-adsp-pas"; 127 + reg = <0x30000000 0x100>; 128 + 129 + interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>, 130 + <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>, 131 + <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>, 132 + <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>, 133 + <&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>; 134 + interrupt-names = "wdog", "fatal", "ready", "handover", "stop-ack"; 135 + 136 + clocks = <&rpmhcc RPMH_CXO_CLK>; 137 + clock-names = "xo"; 138 + 139 + power-domains = <&rpmhpd RPMHPD_LCX>, <&rpmhpd RPMHPD_LMX>; 140 + power-domain-names = "lcx", "lmx"; 141 + 142 + interconnects = <&lpass_ag_noc MASTER_LPASS_PROC 0 &mc_virt SLAVE_EBI1 0>; 143 + 144 + memory-region = <&pil_adsp_mem>; 145 + 146 + qcom,qmp = <&aoss_qmp>; 147 + 148 + qcom,smem-states = <&smp2p_adsp_out 0>; 149 + qcom,smem-state-names = "stop"; 150 + 151 + glink-edge { 152 + interrupts-extended = <&ipcc IPCC_CLIENT_LPASS 153 + IPCC_MPROC_SIGNAL_GLINK_QMP 154 + IRQ_TYPE_EDGE_RISING>; 155 + mboxes = <&ipcc IPCC_CLIENT_LPASS IPCC_MPROC_SIGNAL_GLINK_QMP>; 156 + 157 + label = "lpass"; 158 + qcom,remote-pid = <2>; 159 + }; 160 + };
+7
MAINTAINERS
··· 18749 18749 F: Documentation/devicetree/bindings/power/avs/qcom,cpr.yaml 18750 18750 F: drivers/pmdomain/qcom/cpr.c 18751 18751 18752 + QUALCOMM CPUCP MAILBOX DRIVER 18753 + M: Sibi Sankar <quic_sibis@quicinc.com> 18754 + L: linux-arm-msm@vger.kernel.org 18755 + S: Supported 18756 + F: Documentation/devicetree/bindings/mailbox/qcom,cpucp-mbox.yaml 18757 + F: drivers/mailbox/qcom-cpucp-mbox.c 18758 + 18752 18759 QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096 18753 18760 M: Ilia Lin <ilia.lin@kernel.org> 18754 18761 L: linux-pm@vger.kernel.org
+8
drivers/mailbox/Kconfig
··· 276 276 to send message between application processors and MCU. Say Y here if 277 277 you want to build the Spreatrum mailbox controller driver. 278 278 279 + config QCOM_CPUCP_MBOX 280 + tristate "Qualcomm Technologies, Inc. CPUCP mailbox driver" 281 + depends on (ARCH_QCOM || COMPILE_TEST) && 64BIT 282 + help 283 + Qualcomm Technologies, Inc. CPUSS Control Processor (CPUCP) mailbox 284 + controller driver enables communication between AP and CPUCP. Say 285 + Y here if you want to build this driver. 286 + 279 287 config QCOM_IPCC 280 288 tristate "Qualcomm Technologies, Inc. IPCC driver" 281 289 depends on ARCH_QCOM || COMPILE_TEST
+2
drivers/mailbox/Makefile
··· 61 61 62 62 obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o 63 63 64 + obj-$(CONFIG_QCOM_CPUCP_MBOX) += qcom-cpucp-mbox.o 65 + 64 66 obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o
-4
drivers/mailbox/bcm-pdc-mailbox.c
··· 158 158 PDC_HW /* PDC/MDE hardware (i.e. Northstar 2, Pegasus) */ 159 159 }; 160 160 161 - struct pdc_dma_map { 162 - void *ctx; /* opaque context associated with frame */ 163 - }; 164 - 165 161 /* dma descriptor */ 166 162 struct dma64dd { 167 163 u32 ctrl1; /* misc control bits */
+9 -1
drivers/mailbox/imx-mailbox.c
··· 225 225 void *data) 226 226 { 227 227 u32 *arg = data; 228 + u32 val; 229 + int ret; 228 230 229 231 switch (cp->type) { 230 232 case IMX_MU_TYPE_TX: ··· 238 236 queue_work(system_bh_wq, &cp->txdb_work); 239 237 break; 240 238 case IMX_MU_TYPE_TXDB_V2: 241 - imx_mu_xcr_rmw(priv, IMX_MU_GCR, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx), 0); 239 + imx_mu_write(priv, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx), 240 + priv->dcfg->xCR[IMX_MU_GCR]); 241 + ret = readl_poll_timeout(priv->base + priv->dcfg->xCR[IMX_MU_GCR], val, 242 + !(val & IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx)), 243 + 0, 1000); 244 + if (ret) 245 + dev_warn_ratelimited(priv->dev, "channel type: %d failure\n", cp->type); 242 246 break; 243 247 default: 244 248 dev_warn_ratelimited(priv->dev, "Send data on wrong channel type: %d\n", cp->type);
+64 -36
drivers/mailbox/mtk-cmdq-mailbox.c
··· 22 22 23 23 #define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT) 24 24 #define CMDQ_NUM_CMD(t) (t->cmd_buf_size / CMDQ_INST_SIZE) 25 - #define CMDQ_GCE_NUM_MAX (2) 26 25 27 26 #define CMDQ_CURR_IRQ_STATUS 0x10 28 27 #define CMDQ_SYNC_TOKEN_UPDATE 0x68 ··· 80 81 u32 irq_mask; 81 82 const struct gce_plat *pdata; 82 83 struct cmdq_thread *thread; 83 - struct clk_bulk_data clocks[CMDQ_GCE_NUM_MAX]; 84 + struct clk_bulk_data *clocks; 84 85 bool suspended; 85 86 }; 86 87 ··· 577 578 return &mbox->chans[ind]; 578 579 } 579 580 581 + static int cmdq_get_clocks(struct device *dev, struct cmdq *cmdq) 582 + { 583 + static const char * const gce_name = "gce"; 584 + struct device_node *node, *parent = dev->of_node->parent; 585 + struct clk_bulk_data *clks; 586 + 587 + cmdq->clocks = devm_kcalloc(dev, cmdq->pdata->gce_num, 588 + sizeof(cmdq->clocks), GFP_KERNEL); 589 + if (!cmdq->clocks) 590 + return -ENOMEM; 591 + 592 + if (cmdq->pdata->gce_num == 1) { 593 + clks = &cmdq->clocks[0]; 594 + 595 + clks->id = gce_name; 596 + clks->clk = devm_clk_get(dev, NULL); 597 + if (IS_ERR(clks->clk)) 598 + return dev_err_probe(dev, PTR_ERR(clks->clk), 599 + "failed to get gce clock\n"); 600 + 601 + return 0; 602 + } 603 + 604 + /* 605 + * If there is more than one GCE, get the clocks for the others too, 606 + * as the clock of the main GCE must be enabled for additional IPs 607 + * to be reachable. 608 + */ 609 + for_each_child_of_node(parent, node) { 610 + int alias_id = of_alias_get_id(node, gce_name); 611 + 612 + if (alias_id < 0 || alias_id >= cmdq->pdata->gce_num) 613 + continue; 614 + 615 + clks = &cmdq->clocks[alias_id]; 616 + 617 + clks->id = devm_kasprintf(dev, GFP_KERNEL, "gce%d", alias_id); 618 + if (!clks->id) { 619 + of_node_put(node); 620 + return -ENOMEM; 621 + } 622 + 623 + clks->clk = of_clk_get(node, 0); 624 + if (IS_ERR(clks->clk)) { 625 + of_node_put(node); 626 + return dev_err_probe(dev, PTR_ERR(clks->clk), 627 + "failed to get gce%d clock\n", alias_id); 628 + } 629 + } 630 + 631 + return 0; 632 + } 633 + 580 634 static int cmdq_probe(struct platform_device *pdev) 581 635 { 582 636 struct device *dev = &pdev->dev; 583 637 struct cmdq *cmdq; 584 638 int err, i; 585 - struct device_node *phandle = dev->of_node; 586 - struct device_node *node; 587 - int alias_id = 0; 588 - static const char * const clk_name = "gce"; 589 - static const char * const clk_names[] = { "gce0", "gce1" }; 590 639 591 640 cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL); 592 641 if (!cmdq) ··· 659 612 dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n", 660 613 dev, cmdq->base, cmdq->irq); 661 614 662 - if (cmdq->pdata->gce_num > 1) { 663 - for_each_child_of_node(phandle->parent, node) { 664 - alias_id = of_alias_get_id(node, clk_name); 665 - if (alias_id >= 0 && alias_id < cmdq->pdata->gce_num) { 666 - cmdq->clocks[alias_id].id = clk_names[alias_id]; 667 - cmdq->clocks[alias_id].clk = of_clk_get(node, 0); 668 - if (IS_ERR(cmdq->clocks[alias_id].clk)) { 669 - of_node_put(node); 670 - return dev_err_probe(dev, 671 - PTR_ERR(cmdq->clocks[alias_id].clk), 672 - "failed to get gce clk: %d\n", 673 - alias_id); 674 - } 675 - } 676 - } 677 - } else { 678 - cmdq->clocks[alias_id].id = clk_name; 679 - cmdq->clocks[alias_id].clk = devm_clk_get(&pdev->dev, clk_name); 680 - if (IS_ERR(cmdq->clocks[alias_id].clk)) { 681 - return dev_err_probe(dev, PTR_ERR(cmdq->clocks[alias_id].clk), 682 - "failed to get gce clk\n"); 683 - } 684 - } 615 + err = cmdq_get_clocks(dev, cmdq); 616 + if (err) 617 + return err; 685 618 686 619 cmdq->mbox.dev = dev; 687 620 cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->thread_nr, ··· 687 660 CMDQ_THR_SIZE * i; 688 661 INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list); 689 662 cmdq->mbox.chans[i].con_priv = (void *)&cmdq->thread[i]; 690 - } 691 - 692 - err = devm_mbox_controller_register(dev, &cmdq->mbox); 693 - if (err < 0) { 694 - dev_err(dev, "failed to register mailbox: %d\n", err); 695 - return err; 696 663 } 697 664 698 665 platform_set_drvdata(pdev, cmdq); ··· 715 694 716 695 pm_runtime_set_autosuspend_delay(dev, CMDQ_MBOX_AUTOSUSPEND_DELAY_MS); 717 696 pm_runtime_use_autosuspend(dev); 697 + 698 + err = devm_mbox_controller_register(dev, &cmdq->mbox); 699 + if (err < 0) { 700 + dev_err(dev, "failed to register mailbox: %d\n", err); 701 + return err; 702 + } 718 703 719 704 return 0; 720 705 } ··· 817 790 subsys_initcall(cmdq_drv_init); 818 791 module_exit(cmdq_drv_exit); 819 792 793 + MODULE_DESCRIPTION("Mediatek Command Queue(CMDQ) Mailbox driver"); 820 794 MODULE_LICENSE("GPL v2");
+2 -1
drivers/mailbox/omap-mailbox.c
··· 230 230 int ret = 0; 231 231 232 232 ret = request_threaded_irq(mbox->irq, NULL, mbox_interrupt, 233 - IRQF_ONESHOT, mbox->name, mbox); 233 + IRQF_SHARED | IRQF_ONESHOT, mbox->name, 234 + mbox); 234 235 if (unlikely(ret)) { 235 236 pr_err("failed to register mailbox interrupt:%d\n", ret); 236 237 return ret;
+187
drivers/mailbox/qcom-cpucp-mbox.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. 4 + */ 5 + 6 + #include <linux/bitops.h> 7 + #include <linux/interrupt.h> 8 + #include <linux/io.h> 9 + #include <linux/irq.h> 10 + #include <linux/irqdomain.h> 11 + #include <linux/mailbox_controller.h> 12 + #include <linux/module.h> 13 + #include <linux/platform_device.h> 14 + 15 + #define APSS_CPUCP_IPC_CHAN_SUPPORTED 3 16 + #define APSS_CPUCP_MBOX_CMD_OFF 0x4 17 + 18 + /* Tx Registers */ 19 + #define APSS_CPUCP_TX_MBOX_CMD(i) (0x100 + ((i) * 8)) 20 + 21 + /* Rx Registers */ 22 + #define APSS_CPUCP_RX_MBOX_CMD(i) (0x100 + ((i) * 8)) 23 + #define APSS_CPUCP_RX_MBOX_MAP 0x4000 24 + #define APSS_CPUCP_RX_MBOX_STAT 0x4400 25 + #define APSS_CPUCP_RX_MBOX_CLEAR 0x4800 26 + #define APSS_CPUCP_RX_MBOX_EN 0x4c00 27 + #define APSS_CPUCP_RX_MBOX_CMD_MASK GENMASK_ULL(63, 0) 28 + 29 + /** 30 + * struct qcom_cpucp_mbox - Holder for the mailbox driver 31 + * @chans: The mailbox channel 32 + * @mbox: The mailbox controller 33 + * @tx_base: Base address of the CPUCP tx registers 34 + * @rx_base: Base address of the CPUCP rx registers 35 + */ 36 + struct qcom_cpucp_mbox { 37 + struct mbox_chan chans[APSS_CPUCP_IPC_CHAN_SUPPORTED]; 38 + struct mbox_controller mbox; 39 + void __iomem *tx_base; 40 + void __iomem *rx_base; 41 + }; 42 + 43 + static inline int channel_number(struct mbox_chan *chan) 44 + { 45 + return chan - chan->mbox->chans; 46 + } 47 + 48 + static irqreturn_t qcom_cpucp_mbox_irq_fn(int irq, void *data) 49 + { 50 + struct qcom_cpucp_mbox *cpucp = data; 51 + u64 status; 52 + int i; 53 + 54 + status = readq(cpucp->rx_base + APSS_CPUCP_RX_MBOX_STAT); 55 + 56 + for_each_set_bit(i, (unsigned long *)&status, APSS_CPUCP_IPC_CHAN_SUPPORTED) { 57 + u32 val = readl(cpucp->rx_base + APSS_CPUCP_RX_MBOX_CMD(i) + APSS_CPUCP_MBOX_CMD_OFF); 58 + struct mbox_chan *chan = &cpucp->chans[i]; 59 + unsigned long flags; 60 + 61 + /* Provide mutual exclusion with changes to chan->cl */ 62 + spin_lock_irqsave(&chan->lock, flags); 63 + if (chan->cl) 64 + mbox_chan_received_data(chan, &val); 65 + writeq(BIT(i), cpucp->rx_base + APSS_CPUCP_RX_MBOX_CLEAR); 66 + spin_unlock_irqrestore(&chan->lock, flags); 67 + } 68 + 69 + return IRQ_HANDLED; 70 + } 71 + 72 + static int qcom_cpucp_mbox_startup(struct mbox_chan *chan) 73 + { 74 + struct qcom_cpucp_mbox *cpucp = container_of(chan->mbox, struct qcom_cpucp_mbox, mbox); 75 + unsigned long chan_id = channel_number(chan); 76 + u64 val; 77 + 78 + val = readq(cpucp->rx_base + APSS_CPUCP_RX_MBOX_EN); 79 + val |= BIT(chan_id); 80 + writeq(val, cpucp->rx_base + APSS_CPUCP_RX_MBOX_EN); 81 + 82 + return 0; 83 + } 84 + 85 + static void qcom_cpucp_mbox_shutdown(struct mbox_chan *chan) 86 + { 87 + struct qcom_cpucp_mbox *cpucp = container_of(chan->mbox, struct qcom_cpucp_mbox, mbox); 88 + unsigned long chan_id = channel_number(chan); 89 + u64 val; 90 + 91 + val = readq(cpucp->rx_base + APSS_CPUCP_RX_MBOX_EN); 92 + val &= ~BIT(chan_id); 93 + writeq(val, cpucp->rx_base + APSS_CPUCP_RX_MBOX_EN); 94 + } 95 + 96 + static int qcom_cpucp_mbox_send_data(struct mbox_chan *chan, void *data) 97 + { 98 + struct qcom_cpucp_mbox *cpucp = container_of(chan->mbox, struct qcom_cpucp_mbox, mbox); 99 + unsigned long chan_id = channel_number(chan); 100 + u32 *val = data; 101 + 102 + writel(*val, cpucp->tx_base + APSS_CPUCP_TX_MBOX_CMD(chan_id) + APSS_CPUCP_MBOX_CMD_OFF); 103 + 104 + return 0; 105 + } 106 + 107 + static const struct mbox_chan_ops qcom_cpucp_mbox_chan_ops = { 108 + .startup = qcom_cpucp_mbox_startup, 109 + .send_data = qcom_cpucp_mbox_send_data, 110 + .shutdown = qcom_cpucp_mbox_shutdown 111 + }; 112 + 113 + static int qcom_cpucp_mbox_probe(struct platform_device *pdev) 114 + { 115 + struct device *dev = &pdev->dev; 116 + struct qcom_cpucp_mbox *cpucp; 117 + struct mbox_controller *mbox; 118 + int irq, ret; 119 + 120 + cpucp = devm_kzalloc(dev, sizeof(*cpucp), GFP_KERNEL); 121 + if (!cpucp) 122 + return -ENOMEM; 123 + 124 + cpucp->rx_base = devm_of_iomap(dev, dev->of_node, 0, NULL); 125 + if (IS_ERR(cpucp->rx_base)) 126 + return PTR_ERR(cpucp->rx_base); 127 + 128 + cpucp->tx_base = devm_of_iomap(dev, dev->of_node, 1, NULL); 129 + if (IS_ERR(cpucp->tx_base)) 130 + return PTR_ERR(cpucp->tx_base); 131 + 132 + writeq(0, cpucp->rx_base + APSS_CPUCP_RX_MBOX_EN); 133 + writeq(0, cpucp->rx_base + APSS_CPUCP_RX_MBOX_CLEAR); 134 + writeq(0, cpucp->rx_base + APSS_CPUCP_RX_MBOX_MAP); 135 + 136 + irq = platform_get_irq(pdev, 0); 137 + if (irq < 0) 138 + return irq; 139 + 140 + ret = devm_request_irq(dev, irq, qcom_cpucp_mbox_irq_fn, 141 + IRQF_TRIGGER_HIGH, "apss_cpucp_mbox", cpucp); 142 + if (ret < 0) 143 + return dev_err_probe(dev, ret, "Failed to register irq: %d\n", irq); 144 + 145 + writeq(APSS_CPUCP_RX_MBOX_CMD_MASK, cpucp->rx_base + APSS_CPUCP_RX_MBOX_MAP); 146 + 147 + mbox = &cpucp->mbox; 148 + mbox->dev = dev; 149 + mbox->num_chans = APSS_CPUCP_IPC_CHAN_SUPPORTED; 150 + mbox->chans = cpucp->chans; 151 + mbox->ops = &qcom_cpucp_mbox_chan_ops; 152 + 153 + ret = devm_mbox_controller_register(dev, mbox); 154 + if (ret) 155 + return dev_err_probe(dev, ret, "Failed to create mailbox\n"); 156 + 157 + return 0; 158 + } 159 + 160 + static const struct of_device_id qcom_cpucp_mbox_of_match[] = { 161 + { .compatible = "qcom,x1e80100-cpucp-mbox" }, 162 + {} 163 + }; 164 + MODULE_DEVICE_TABLE(of, qcom_cpucp_mbox_of_match); 165 + 166 + static struct platform_driver qcom_cpucp_mbox_driver = { 167 + .probe = qcom_cpucp_mbox_probe, 168 + .driver = { 169 + .name = "qcom_cpucp_mbox", 170 + .of_match_table = qcom_cpucp_mbox_of_match, 171 + }, 172 + }; 173 + 174 + static int __init qcom_cpucp_mbox_init(void) 175 + { 176 + return platform_driver_register(&qcom_cpucp_mbox_driver); 177 + } 178 + core_initcall(qcom_cpucp_mbox_init); 179 + 180 + static void __exit qcom_cpucp_mbox_exit(void) 181 + { 182 + platform_driver_unregister(&qcom_cpucp_mbox_driver); 183 + } 184 + module_exit(qcom_cpucp_mbox_exit); 185 + 186 + MODULE_DESCRIPTION("QTI CPUCP MBOX Driver"); 187 + MODULE_LICENSE("GPL");
+8 -1
drivers/mailbox/zynqmp-ipi-mailbox.c
··· 64 64 65 65 #define MAX_SGI 16 66 66 67 + /* 68 + * Module parameters 69 + */ 70 + static int tx_poll_period = 5; 71 + module_param_named(tx_poll_period, tx_poll_period, int, 0644); 72 + MODULE_PARM_DESC(tx_poll_period, "Poll period waiting for ack after send."); 73 + 67 74 /** 68 75 * struct zynqmp_ipi_mchan - Description of a Xilinx ZynqMP IPI mailbox channel 69 76 * @is_opened: indicate if the IPI channel is opened ··· 544 537 mbox->num_chans = 2; 545 538 mbox->txdone_irq = false; 546 539 mbox->txdone_poll = true; 547 - mbox->txpoll_period = 5; 540 + mbox->txpoll_period = tx_poll_period; 548 541 mbox->of_xlate = zynqmp_ipi_of_xlate; 549 542 chans = devm_kzalloc(mdev, 2 * sizeof(*chans), GFP_KERNEL); 550 543 if (!chans)