mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-19 12:24:34 +08:00
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 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE6EwehDt/SOnwFyTyf9lkf8eYP5UFAmadSsUACgkQf9lkf8eY P5XSXg/9GDhIXf3nfqfRbuIA29tWwEPDBZJ4KTtiuW0lNrk2x+VyEo90xvLly4vZ h/AbZLDjnWE+Tfbht7dDrbXMcmpDAsRKhoQ6dDbz9leOMGDBMGwAqXOKim7SCY38 SqgPwR1LHXoJRBoD7Qa91PNcScCF6his5T+bTSLsJCJ9CL8wzh8OrADIJSCS7Qpi ubBuV4sOey9SCnfdxn/TR4sfaJw1cu8DPSWUXEoAkvFkOt4SxZZZSVdb0JgnCm6y rEhp4E3j5YlVbSR382WoXmXijo3hl9NY3vI3180rE9Bu1F/c8au3cP0gHKnsFYBd trLamCYMAsBzRYQCmTKqIhS87b//5MiCQIMmid4UrtItRZlrK2dJV6fRT1fHhfq9 ZrErep6x0Sr0qSIUgqcRHIaBdSxRRg63vfHcWRjvpsjwaKXW/vJQhWMFXceIuxi7 YrfuoogoCkydYjUoU9lJN0rLBmZF5ak88rf/KCRbYxRLOxFsJrNd81Dy1mkqCSAl oG3p+D7znKbgVsdLktGihk3UpkTRS09hD//FSncktFPIa8nuesY9hKe2RfFbqk3b HhPvhPz04Sig/DPnQNzNcxS9TCCbMLdS+9x+YVMTYamFGjbSAo4Jkczd1ttERqXI BPhTHvNpqqwgEmQWCVOzEiJMCtlomP+D0gezZM8iOlTrej3zOak= =JTUn -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
d51f8f63f7
@ -0,0 +1,52 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mailbox/mediatek,gce-props.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek Global Command Engine Common Properties
|
||||
|
||||
maintainers:
|
||||
- Houlong Wei <houlong.wei@mediatek.com>
|
||||
|
||||
description:
|
||||
The Global Command Engine (GCE) is an instruction based, multi-threaded,
|
||||
single-core command dispatcher for MediaTek hardware. The Command Queue
|
||||
(CMDQ) mailbox driver is a driver for GCE, implemented using the Linux
|
||||
mailbox framework. It is used to receive messages from mailbox consumers
|
||||
and configure GCE to execute the specified instruction set in the message.
|
||||
We use mediatek,gce-mailbox.yaml to define the properties for CMDQ mailbox
|
||||
driver. A device driver that uses the CMDQ driver to configure its hardware
|
||||
registers is a mailbox consumer. The mailbox consumer can request a mailbox
|
||||
channel corresponding to a GCE hardware thread to send a message, specifying
|
||||
that the GCE thread to configure its hardware. The mailbox provider can also
|
||||
reserve a mailbox channel to configure GCE hardware register by the specific
|
||||
GCE thread. This binding defines the common GCE properties for both mailbox
|
||||
provider and consumers.
|
||||
|
||||
properties:
|
||||
mediatek,gce-events:
|
||||
description:
|
||||
GCE has an event table in SRAM, consisting of 1024 event IDs (0~1023).
|
||||
Each event ID has a boolean event value with the default value 0.
|
||||
The property mediatek,gce-events is used to obtain the event IDs.
|
||||
Some gce-events are hardware-bound and cannot be changed by software.
|
||||
For instance, in MT8195, when VDO0_MUTEX is stream done, VDO_MUTEX will
|
||||
send an event signal to GCE, setting the value of event ID 597 to 1.
|
||||
Similarly, in MT8188, the value of event ID 574 will be set to 1 when
|
||||
VOD0_MUTEX is stream done.
|
||||
On the other hand, some gce-events are not hardware-bound and can be
|
||||
changed by software. For example, in MT8188, we can set the value of
|
||||
event ID 855, which is not bound to any hardware, to 1 when the driver
|
||||
in the secure world completes a task. However, in MT8195, event ID 855
|
||||
is already bound to VDEC_LAT1, so we need to select another event ID to
|
||||
achieve the same purpose. This event ID can be any ID that is not bound
|
||||
to any hardware and is not yet used in any software driver.
|
||||
To determine if the event ID is bound to the hardware or used by a
|
||||
software driver, refer to the GCE header
|
||||
include/dt-bindings/gce/<chip>-gce.h of each chip.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 1
|
||||
maxItems: 32
|
||||
|
||||
additionalProperties: true
|
@ -0,0 +1,49 @@
|
||||
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mailbox/qcom,cpucp-mbox.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies, Inc. CPUCP Mailbox Controller
|
||||
|
||||
maintainers:
|
||||
- Sibi Sankar <quic_sibis@quicinc.com>
|
||||
|
||||
description:
|
||||
The CPUSS Control Processor (CPUCP) mailbox controller enables communication
|
||||
between AP and CPUCP by acting as a doorbell between them.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: qcom,x1e80100-cpucp-mbox
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: CPUCP rx register region
|
||||
- description: CPUCP tx register region
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
"#mbox-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- "#mbox-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
mailbox@17430000 {
|
||||
compatible = "qcom,x1e80100-cpucp-mbox";
|
||||
reg = <0x17430000 0x10000>, <0x18830000 0x10000>;
|
||||
interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#mbox-cells = <1>;
|
||||
};
|
@ -0,0 +1,160 @@
|
||||
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/remoteproc/qcom,sa8775p-pas.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm SA8775p Peripheral Authentication Service
|
||||
|
||||
maintainers:
|
||||
- Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
|
||||
|
||||
description:
|
||||
Qualcomm SA8775p SoC Peripheral Authentication Service loads and boots firmware
|
||||
on the Qualcomm DSP Hexagon cores.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sa8775p-adsp-pas
|
||||
- qcom,sa8775p-cdsp0-pas
|
||||
- qcom,sa8775p-cdsp1-pas
|
||||
- qcom,sa8775p-gpdsp0-pas
|
||||
- qcom,sa8775p-gpdsp1-pas
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: XO clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: xo
|
||||
|
||||
qcom,qmp:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: Reference to the AOSS side-channel message RAM.
|
||||
|
||||
firmware-name:
|
||||
$ref: /schemas/types.yaml#/definitions/string-array
|
||||
items:
|
||||
- description: Firmware name of the Hexagon core
|
||||
|
||||
memory-region:
|
||||
items:
|
||||
- description: Memory region for main Firmware authentication
|
||||
|
||||
interrupts:
|
||||
maxItems: 5
|
||||
|
||||
interrupt-names:
|
||||
maxItems: 5
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- memory-region
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/remoteproc/qcom,pas-common.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sa8775p-adsp-pas
|
||||
then:
|
||||
properties:
|
||||
power-domains:
|
||||
items:
|
||||
- description: LCX power domain
|
||||
- description: LMX power domain
|
||||
power-domain-names:
|
||||
items:
|
||||
- const: lcx
|
||||
- const: lmx
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sa8775p-cdsp0-pas
|
||||
- qcom,sa8775p-cdsp1-pas
|
||||
then:
|
||||
properties:
|
||||
power-domains:
|
||||
items:
|
||||
- description: CX power domain
|
||||
- description: MXC power domain
|
||||
- description: NSP0 power domain
|
||||
power-domain-names:
|
||||
items:
|
||||
- const: cx
|
||||
- const: mxc
|
||||
- const: nsp
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sa8775p-gpdsp0-pas
|
||||
- qcom,sa8775p-gpdsp1-pas
|
||||
then:
|
||||
properties:
|
||||
power-domains:
|
||||
items:
|
||||
- description: CX power domain
|
||||
- description: MXC power domain
|
||||
power-domain-names:
|
||||
items:
|
||||
- const: cx
|
||||
- const: mxc
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
#include <dt-bindings/interconnect/qcom,sa8775p-rpmh.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/mailbox/qcom-ipcc.h>
|
||||
#include <dt-bindings/power/qcom,rpmhpd.h>
|
||||
|
||||
remoteproc@30000000 {
|
||||
compatible = "qcom,sa8775p-adsp-pas";
|
||||
reg = <0x30000000 0x100>;
|
||||
|
||||
interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
|
||||
<&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
|
||||
<&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
|
||||
<&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
|
||||
<&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "wdog", "fatal", "ready", "handover", "stop-ack";
|
||||
|
||||
clocks = <&rpmhcc RPMH_CXO_CLK>;
|
||||
clock-names = "xo";
|
||||
|
||||
power-domains = <&rpmhpd RPMHPD_LCX>, <&rpmhpd RPMHPD_LMX>;
|
||||
power-domain-names = "lcx", "lmx";
|
||||
|
||||
interconnects = <&lpass_ag_noc MASTER_LPASS_PROC 0 &mc_virt SLAVE_EBI1 0>;
|
||||
|
||||
memory-region = <&pil_adsp_mem>;
|
||||
|
||||
qcom,qmp = <&aoss_qmp>;
|
||||
|
||||
qcom,smem-states = <&smp2p_adsp_out 0>;
|
||||
qcom,smem-state-names = "stop";
|
||||
|
||||
glink-edge {
|
||||
interrupts-extended = <&ipcc IPCC_CLIENT_LPASS
|
||||
IPCC_MPROC_SIGNAL_GLINK_QMP
|
||||
IRQ_TYPE_EDGE_RISING>;
|
||||
mboxes = <&ipcc IPCC_CLIENT_LPASS IPCC_MPROC_SIGNAL_GLINK_QMP>;
|
||||
|
||||
label = "lpass";
|
||||
qcom,remote-pid = <2>;
|
||||
};
|
||||
};
|
@ -18749,6 +18749,13 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/power/avs/qcom,cpr.yaml
|
||||
F: drivers/pmdomain/qcom/cpr.c
|
||||
|
||||
QUALCOMM CPUCP MAILBOX DRIVER
|
||||
M: Sibi Sankar <quic_sibis@quicinc.com>
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/mailbox/qcom,cpucp-mbox.yaml
|
||||
F: drivers/mailbox/qcom-cpucp-mbox.c
|
||||
|
||||
QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
|
||||
M: Ilia Lin <ilia.lin@kernel.org>
|
||||
L: linux-pm@vger.kernel.org
|
||||
|
@ -276,6 +276,14 @@ config SPRD_MBOX
|
||||
to send message between application processors and MCU. Say Y here if
|
||||
you want to build the Spreatrum mailbox controller driver.
|
||||
|
||||
config QCOM_CPUCP_MBOX
|
||||
tristate "Qualcomm Technologies, Inc. CPUCP mailbox driver"
|
||||
depends on (ARCH_QCOM || COMPILE_TEST) && 64BIT
|
||||
help
|
||||
Qualcomm Technologies, Inc. CPUSS Control Processor (CPUCP) mailbox
|
||||
controller driver enables communication between AP and CPUCP. Say
|
||||
Y here if you want to build this driver.
|
||||
|
||||
config QCOM_IPCC
|
||||
tristate "Qualcomm Technologies, Inc. IPCC driver"
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
|
@ -61,4 +61,6 @@ obj-$(CONFIG_SUN6I_MSGBOX) += sun6i-msgbox.o
|
||||
|
||||
obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox.o
|
||||
|
||||
obj-$(CONFIG_QCOM_CPUCP_MBOX) += qcom-cpucp-mbox.o
|
||||
|
||||
obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o
|
||||
|
@ -158,10 +158,6 @@ enum pdc_hw {
|
||||
PDC_HW /* PDC/MDE hardware (i.e. Northstar 2, Pegasus) */
|
||||
};
|
||||
|
||||
struct pdc_dma_map {
|
||||
void *ctx; /* opaque context associated with frame */
|
||||
};
|
||||
|
||||
/* dma descriptor */
|
||||
struct dma64dd {
|
||||
u32 ctrl1; /* misc control bits */
|
||||
|
@ -225,6 +225,8 @@ static int imx_mu_generic_tx(struct imx_mu_priv *priv,
|
||||
void *data)
|
||||
{
|
||||
u32 *arg = data;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
switch (cp->type) {
|
||||
case IMX_MU_TYPE_TX:
|
||||
@ -236,7 +238,13 @@ static int imx_mu_generic_tx(struct imx_mu_priv *priv,
|
||||
queue_work(system_bh_wq, &cp->txdb_work);
|
||||
break;
|
||||
case IMX_MU_TYPE_TXDB_V2:
|
||||
imx_mu_xcr_rmw(priv, IMX_MU_GCR, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx), 0);
|
||||
imx_mu_write(priv, IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx),
|
||||
priv->dcfg->xCR[IMX_MU_GCR]);
|
||||
ret = readl_poll_timeout(priv->base + priv->dcfg->xCR[IMX_MU_GCR], val,
|
||||
!(val & IMX_MU_xCR_GIRn(priv->dcfg->type, cp->idx)),
|
||||
0, 1000);
|
||||
if (ret)
|
||||
dev_warn_ratelimited(priv->dev, "channel type: %d failure\n", cp->type);
|
||||
break;
|
||||
default:
|
||||
dev_warn_ratelimited(priv->dev, "Send data on wrong channel type: %d\n", cp->type);
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT)
|
||||
#define CMDQ_NUM_CMD(t) (t->cmd_buf_size / CMDQ_INST_SIZE)
|
||||
#define CMDQ_GCE_NUM_MAX (2)
|
||||
|
||||
#define CMDQ_CURR_IRQ_STATUS 0x10
|
||||
#define CMDQ_SYNC_TOKEN_UPDATE 0x68
|
||||
@ -81,7 +80,7 @@ struct cmdq {
|
||||
u32 irq_mask;
|
||||
const struct gce_plat *pdata;
|
||||
struct cmdq_thread *thread;
|
||||
struct clk_bulk_data clocks[CMDQ_GCE_NUM_MAX];
|
||||
struct clk_bulk_data *clocks;
|
||||
bool suspended;
|
||||
};
|
||||
|
||||
@ -578,16 +577,64 @@ static struct mbox_chan *cmdq_xlate(struct mbox_controller *mbox,
|
||||
return &mbox->chans[ind];
|
||||
}
|
||||
|
||||
static int cmdq_get_clocks(struct device *dev, struct cmdq *cmdq)
|
||||
{
|
||||
static const char * const gce_name = "gce";
|
||||
struct device_node *node, *parent = dev->of_node->parent;
|
||||
struct clk_bulk_data *clks;
|
||||
|
||||
cmdq->clocks = devm_kcalloc(dev, cmdq->pdata->gce_num,
|
||||
sizeof(cmdq->clocks), GFP_KERNEL);
|
||||
if (!cmdq->clocks)
|
||||
return -ENOMEM;
|
||||
|
||||
if (cmdq->pdata->gce_num == 1) {
|
||||
clks = &cmdq->clocks[0];
|
||||
|
||||
clks->id = gce_name;
|
||||
clks->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(clks->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(clks->clk),
|
||||
"failed to get gce clock\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is more than one GCE, get the clocks for the others too,
|
||||
* as the clock of the main GCE must be enabled for additional IPs
|
||||
* to be reachable.
|
||||
*/
|
||||
for_each_child_of_node(parent, node) {
|
||||
int alias_id = of_alias_get_id(node, gce_name);
|
||||
|
||||
if (alias_id < 0 || alias_id >= cmdq->pdata->gce_num)
|
||||
continue;
|
||||
|
||||
clks = &cmdq->clocks[alias_id];
|
||||
|
||||
clks->id = devm_kasprintf(dev, GFP_KERNEL, "gce%d", alias_id);
|
||||
if (!clks->id) {
|
||||
of_node_put(node);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
clks->clk = of_clk_get(node, 0);
|
||||
if (IS_ERR(clks->clk)) {
|
||||
of_node_put(node);
|
||||
return dev_err_probe(dev, PTR_ERR(clks->clk),
|
||||
"failed to get gce%d clock\n", alias_id);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmdq_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct cmdq *cmdq;
|
||||
int err, i;
|
||||
struct device_node *phandle = dev->of_node;
|
||||
struct device_node *node;
|
||||
int alias_id = 0;
|
||||
static const char * const clk_name = "gce";
|
||||
static const char * const clk_names[] = { "gce0", "gce1" };
|
||||
|
||||
cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
|
||||
if (!cmdq)
|
||||
@ -612,29 +659,9 @@ static int cmdq_probe(struct platform_device *pdev)
|
||||
dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
|
||||
dev, cmdq->base, cmdq->irq);
|
||||
|
||||
if (cmdq->pdata->gce_num > 1) {
|
||||
for_each_child_of_node(phandle->parent, node) {
|
||||
alias_id = of_alias_get_id(node, clk_name);
|
||||
if (alias_id >= 0 && alias_id < cmdq->pdata->gce_num) {
|
||||
cmdq->clocks[alias_id].id = clk_names[alias_id];
|
||||
cmdq->clocks[alias_id].clk = of_clk_get(node, 0);
|
||||
if (IS_ERR(cmdq->clocks[alias_id].clk)) {
|
||||
of_node_put(node);
|
||||
return dev_err_probe(dev,
|
||||
PTR_ERR(cmdq->clocks[alias_id].clk),
|
||||
"failed to get gce clk: %d\n",
|
||||
alias_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cmdq->clocks[alias_id].id = clk_name;
|
||||
cmdq->clocks[alias_id].clk = devm_clk_get(&pdev->dev, clk_name);
|
||||
if (IS_ERR(cmdq->clocks[alias_id].clk)) {
|
||||
return dev_err_probe(dev, PTR_ERR(cmdq->clocks[alias_id].clk),
|
||||
"failed to get gce clk\n");
|
||||
}
|
||||
}
|
||||
err = cmdq_get_clocks(dev, cmdq);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
cmdq->mbox.dev = dev;
|
||||
cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->thread_nr,
|
||||
@ -662,12 +689,6 @@ static int cmdq_probe(struct platform_device *pdev)
|
||||
cmdq->mbox.chans[i].con_priv = (void *)&cmdq->thread[i];
|
||||
}
|
||||
|
||||
err = devm_mbox_controller_register(dev, &cmdq->mbox);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to register mailbox: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, cmdq);
|
||||
|
||||
WARN_ON(clk_bulk_prepare(cmdq->pdata->gce_num, cmdq->clocks));
|
||||
@ -695,6 +716,12 @@ static int cmdq_probe(struct platform_device *pdev)
|
||||
pm_runtime_set_autosuspend_delay(dev, CMDQ_MBOX_AUTOSUSPEND_DELAY_MS);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
|
||||
err = devm_mbox_controller_register(dev, &cmdq->mbox);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "failed to register mailbox: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -790,4 +817,5 @@ static void __exit cmdq_drv_exit(void)
|
||||
subsys_initcall(cmdq_drv_init);
|
||||
module_exit(cmdq_drv_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Mediatek Command Queue(CMDQ) Mailbox driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -230,7 +230,8 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
|
||||
int ret = 0;
|
||||
|
||||
ret = request_threaded_irq(mbox->irq, NULL, mbox_interrupt,
|
||||
IRQF_ONESHOT, mbox->name, mbox);
|
||||
IRQF_SHARED | IRQF_ONESHOT, mbox->name,
|
||||
mbox);
|
||||
if (unlikely(ret)) {
|
||||
pr_err("failed to register mailbox interrupt:%d\n", ret);
|
||||
return ret;
|
||||
|
187
drivers/mailbox/qcom-cpucp-mbox.c
Normal file
187
drivers/mailbox/qcom-cpucp-mbox.c
Normal file
@ -0,0 +1,187 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/mailbox_controller.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define APSS_CPUCP_IPC_CHAN_SUPPORTED 3
|
||||
#define APSS_CPUCP_MBOX_CMD_OFF 0x4
|
||||
|
||||
/* Tx Registers */
|
||||
#define APSS_CPUCP_TX_MBOX_CMD(i) (0x100 + ((i) * 8))
|
||||
|
||||
/* Rx Registers */
|
||||
#define APSS_CPUCP_RX_MBOX_CMD(i) (0x100 + ((i) * 8))
|
||||
#define APSS_CPUCP_RX_MBOX_MAP 0x4000
|
||||
#define APSS_CPUCP_RX_MBOX_STAT 0x4400
|
||||
#define APSS_CPUCP_RX_MBOX_CLEAR 0x4800
|
||||
#define APSS_CPUCP_RX_MBOX_EN 0x4c00
|
||||
#define APSS_CPUCP_RX_MBOX_CMD_MASK GENMASK_ULL(63, 0)
|
||||
|
||||
/**
|
||||
* struct qcom_cpucp_mbox - Holder for the mailbox driver
|
||||
* @chans: The mailbox channel
|
||||
* @mbox: The mailbox controller
|
||||
* @tx_base: Base address of the CPUCP tx registers
|
||||
* @rx_base: Base address of the CPUCP rx registers
|
||||
*/
|
||||
struct qcom_cpucp_mbox {
|
||||
struct mbox_chan chans[APSS_CPUCP_IPC_CHAN_SUPPORTED];
|
||||
struct mbox_controller mbox;
|
||||
void __iomem *tx_base;
|
||||
void __iomem *rx_base;
|
||||
};
|
||||
|
||||
static inline int channel_number(struct mbox_chan *chan)
|
||||
{
|
||||
return chan - chan->mbox->chans;
|
||||
}
|
||||
|
||||
static irqreturn_t qcom_cpucp_mbox_irq_fn(int irq, void *data)
|
||||
{
|
||||
struct qcom_cpucp_mbox *cpucp = data;
|
||||
u64 status;
|
||||
int i;
|
||||
|
||||
status = readq(cpucp->rx_base + APSS_CPUCP_RX_MBOX_STAT);
|
||||
|
||||
for_each_set_bit(i, (unsigned long *)&status, APSS_CPUCP_IPC_CHAN_SUPPORTED) {
|
||||
u32 val = readl(cpucp->rx_base + APSS_CPUCP_RX_MBOX_CMD(i) + APSS_CPUCP_MBOX_CMD_OFF);
|
||||
struct mbox_chan *chan = &cpucp->chans[i];
|
||||
unsigned long flags;
|
||||
|
||||
/* Provide mutual exclusion with changes to chan->cl */
|
||||
spin_lock_irqsave(&chan->lock, flags);
|
||||
if (chan->cl)
|
||||
mbox_chan_received_data(chan, &val);
|
||||
writeq(BIT(i), cpucp->rx_base + APSS_CPUCP_RX_MBOX_CLEAR);
|
||||
spin_unlock_irqrestore(&chan->lock, flags);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int qcom_cpucp_mbox_startup(struct mbox_chan *chan)
|
||||
{
|
||||
struct qcom_cpucp_mbox *cpucp = container_of(chan->mbox, struct qcom_cpucp_mbox, mbox);
|
||||
unsigned long chan_id = channel_number(chan);
|
||||
u64 val;
|
||||
|
||||
val = readq(cpucp->rx_base + APSS_CPUCP_RX_MBOX_EN);
|
||||
val |= BIT(chan_id);
|
||||
writeq(val, cpucp->rx_base + APSS_CPUCP_RX_MBOX_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qcom_cpucp_mbox_shutdown(struct mbox_chan *chan)
|
||||
{
|
||||
struct qcom_cpucp_mbox *cpucp = container_of(chan->mbox, struct qcom_cpucp_mbox, mbox);
|
||||
unsigned long chan_id = channel_number(chan);
|
||||
u64 val;
|
||||
|
||||
val = readq(cpucp->rx_base + APSS_CPUCP_RX_MBOX_EN);
|
||||
val &= ~BIT(chan_id);
|
||||
writeq(val, cpucp->rx_base + APSS_CPUCP_RX_MBOX_EN);
|
||||
}
|
||||
|
||||
static int qcom_cpucp_mbox_send_data(struct mbox_chan *chan, void *data)
|
||||
{
|
||||
struct qcom_cpucp_mbox *cpucp = container_of(chan->mbox, struct qcom_cpucp_mbox, mbox);
|
||||
unsigned long chan_id = channel_number(chan);
|
||||
u32 *val = data;
|
||||
|
||||
writel(*val, cpucp->tx_base + APSS_CPUCP_TX_MBOX_CMD(chan_id) + APSS_CPUCP_MBOX_CMD_OFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mbox_chan_ops qcom_cpucp_mbox_chan_ops = {
|
||||
.startup = qcom_cpucp_mbox_startup,
|
||||
.send_data = qcom_cpucp_mbox_send_data,
|
||||
.shutdown = qcom_cpucp_mbox_shutdown
|
||||
};
|
||||
|
||||
static int qcom_cpucp_mbox_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct qcom_cpucp_mbox *cpucp;
|
||||
struct mbox_controller *mbox;
|
||||
int irq, ret;
|
||||
|
||||
cpucp = devm_kzalloc(dev, sizeof(*cpucp), GFP_KERNEL);
|
||||
if (!cpucp)
|
||||
return -ENOMEM;
|
||||
|
||||
cpucp->rx_base = devm_of_iomap(dev, dev->of_node, 0, NULL);
|
||||
if (IS_ERR(cpucp->rx_base))
|
||||
return PTR_ERR(cpucp->rx_base);
|
||||
|
||||
cpucp->tx_base = devm_of_iomap(dev, dev->of_node, 1, NULL);
|
||||
if (IS_ERR(cpucp->tx_base))
|
||||
return PTR_ERR(cpucp->tx_base);
|
||||
|
||||
writeq(0, cpucp->rx_base + APSS_CPUCP_RX_MBOX_EN);
|
||||
writeq(0, cpucp->rx_base + APSS_CPUCP_RX_MBOX_CLEAR);
|
||||
writeq(0, cpucp->rx_base + APSS_CPUCP_RX_MBOX_MAP);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_irq(dev, irq, qcom_cpucp_mbox_irq_fn,
|
||||
IRQF_TRIGGER_HIGH, "apss_cpucp_mbox", cpucp);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Failed to register irq: %d\n", irq);
|
||||
|
||||
writeq(APSS_CPUCP_RX_MBOX_CMD_MASK, cpucp->rx_base + APSS_CPUCP_RX_MBOX_MAP);
|
||||
|
||||
mbox = &cpucp->mbox;
|
||||
mbox->dev = dev;
|
||||
mbox->num_chans = APSS_CPUCP_IPC_CHAN_SUPPORTED;
|
||||
mbox->chans = cpucp->chans;
|
||||
mbox->ops = &qcom_cpucp_mbox_chan_ops;
|
||||
|
||||
ret = devm_mbox_controller_register(dev, mbox);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to create mailbox\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_cpucp_mbox_of_match[] = {
|
||||
{ .compatible = "qcom,x1e80100-cpucp-mbox" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, qcom_cpucp_mbox_of_match);
|
||||
|
||||
static struct platform_driver qcom_cpucp_mbox_driver = {
|
||||
.probe = qcom_cpucp_mbox_probe,
|
||||
.driver = {
|
||||
.name = "qcom_cpucp_mbox",
|
||||
.of_match_table = qcom_cpucp_mbox_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init qcom_cpucp_mbox_init(void)
|
||||
{
|
||||
return platform_driver_register(&qcom_cpucp_mbox_driver);
|
||||
}
|
||||
core_initcall(qcom_cpucp_mbox_init);
|
||||
|
||||
static void __exit qcom_cpucp_mbox_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&qcom_cpucp_mbox_driver);
|
||||
}
|
||||
module_exit(qcom_cpucp_mbox_exit);
|
||||
|
||||
MODULE_DESCRIPTION("QTI CPUCP MBOX Driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -64,6 +64,13 @@
|
||||
|
||||
#define MAX_SGI 16
|
||||
|
||||
/*
|
||||
* Module parameters
|
||||
*/
|
||||
static int tx_poll_period = 5;
|
||||
module_param_named(tx_poll_period, tx_poll_period, int, 0644);
|
||||
MODULE_PARM_DESC(tx_poll_period, "Poll period waiting for ack after send.");
|
||||
|
||||
/**
|
||||
* struct zynqmp_ipi_mchan - Description of a Xilinx ZynqMP IPI mailbox channel
|
||||
* @is_opened: indicate if the IPI channel is opened
|
||||
@ -537,7 +544,7 @@ static int zynqmp_ipi_mbox_probe(struct zynqmp_ipi_mbox *ipi_mbox,
|
||||
mbox->num_chans = 2;
|
||||
mbox->txdone_irq = false;
|
||||
mbox->txdone_poll = true;
|
||||
mbox->txpoll_period = 5;
|
||||
mbox->txpoll_period = tx_poll_period;
|
||||
mbox->of_xlate = zynqmp_ipi_of_xlate;
|
||||
chans = devm_kzalloc(mdev, 2 * sizeof(*chans), GFP_KERNEL);
|
||||
if (!chans)
|
||||
|
Loading…
Reference in New Issue
Block a user