summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-02-14 11:13:32 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2026-02-14 11:13:32 -0800
commitf0a475aedd190db95cf92914ca7760c06fbdb704 (patch)
tree9d78f3d5366d401f5e1cbf885818557377c80942
parentdd530598bc02f9db0ebef644d8e2002aecf0ab15 (diff)
parent75df94d05fc03fd9d861eaf79ce10fbb7a548bd8 (diff)
Merge tag 'mailbox-v6.20' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox
Pull mailbox updates from Jassi Brar: "Platform and core updates PCC: - Updates to transmission and interrupt handling, including dynamic txdone configuration, ->last_tx_done() wiring, and SHMEM initialization fixes. Reverted previous shared buffer patch MediaTek - Introduce mtk-vcp-mailbox driver and bindings for MT8196 VCP - Expand mtk-cmdq for MT8196 with GCE virtualization, mminfra_offset, and instruction generation data Spreadtrum (SPRD) - Add Mailbox Revision 2 support and UMS9230 bindings - Fix unhandled interrupt masking and TX done delivery flags Microchip - Add pic64gx compatibility to MPFS - Fix out-of-bounds access and smatch warnings in mchp-ipc-sbi Core & Misc Platform Updates - Prevent out-of-bounds access in fw_mbox_index_xlate() - Add bindings for Qualcomm CPUCP (Kaanapali) - Simplify mtk-cmdq and zynqmp-ipi with scoped OF child iterators - Consolidate various minor fixes, dead code removal, and typo corrections across Broadcom, NXP, Samsung, Xilinx, ARM, and core headers" * tag 'mailbox-v6.20' of git://git.kernel.org/pub/scm/linux/kernel/git/jassibrar/mailbox: (34 commits) mailbox: sprd: mask interrupts that are not handled mailbox: sprd: add support for mailbox revision 2 mailbox: sprd: clear delivery flag before handling TX done dt-bindings: mailbox: sprd: add compatible for UMS9230 mailbox: bcm-ferxrm-mailbox: Use default primary handler mailbox: Remove mailbox_client.h from controller drivers mailbox: zynqmp-ipi: Simplify with scoped for each OF child loop mailbox: mtk-cmdq: Simplify with scoped for each OF child loop dt-bindings: mailbox: xlnx,zynqmp-ipi-mailbox: Document msg region requirement mailbox: Improve RISCV_SBI_MPXY_MBOX guidance mailbox: mchp-ipc-sbi: fix uninitialized symbol and other smatch warnings mailbox: arm_mhuv3: fix typo in comment mailbox: cix: fix typo in error message mailbox: imx: Skip the suspend flag for i.MX7ULP mailbox: exynos: drop unneeded runtime pointer (pclk) mailbox: pcc: Remove spurious IRQF_ONESHOT usage mailbox: mtk-cmdq: Add driver data to support for MT8196 mailbox: mtk-cmdq: Add mminfra_offset configuration for DRAM transaction mailbox: mtk-cmdq: Add GCE hardware virtualization configuration mailbox: mtk-cmdq: Add cmdq private data to cmdq_pkt for generating instruction ...
-rw-r--r--Documentation/devicetree/bindings/mailbox/mediatek,mt8196-vcp-mbox.yaml49
-rw-r--r--Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml6
-rw-r--r--Documentation/devicetree/bindings/mailbox/sprd-mailbox.yaml1
-rw-r--r--Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml11
-rw-r--r--drivers/mailbox/Kconfig17
-rw-r--r--drivers/mailbox/Makefile2
-rw-r--r--drivers/mailbox/arm_mhuv3.c2
-rw-r--r--drivers/mailbox/bcm-flexrm-mailbox.c1
-rw-r--r--drivers/mailbox/cix-mailbox.c2
-rw-r--r--drivers/mailbox/cv1800-mailbox.c1
-rw-r--r--drivers/mailbox/exynos-mailbox.c9
-rw-r--r--drivers/mailbox/imx-mailbox.c8
-rw-r--r--drivers/mailbox/mailbox-mchp-ipc-sbi.c41
-rw-r--r--drivers/mailbox/mailbox.c6
-rw-r--r--drivers/mailbox/mtk-cmdq-mailbox.c12
-rw-r--r--drivers/mailbox/mtk-vcp-mailbox.c170
-rw-r--r--drivers/mailbox/omap-mailbox.c1
-rw-r--r--drivers/mailbox/pcc.c120
-rw-r--r--drivers/mailbox/sprd-mailbox.c117
-rw-r--r--drivers/mailbox/zynqmp-ipi-mailbox.c5
-rw-r--r--include/acpi/pcc.h29
-rw-r--r--include/linux/mailbox/mtk-vcp-mailbox.h32
22 files changed, 434 insertions, 208 deletions
diff --git a/Documentation/devicetree/bindings/mailbox/mediatek,mt8196-vcp-mbox.yaml b/Documentation/devicetree/bindings/mailbox/mediatek,mt8196-vcp-mbox.yaml
new file mode 100644
index 000000000000..7b1c5165e64e
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/mediatek,mt8196-vcp-mbox.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mailbox/mediatek,mt8196-vcp-mbox.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek Video Companion Processor (VCP) mailbox
+
+maintainers:
+ - Jjian Zhou <Jjian.Zhou@mediatek.com>
+
+description:
+ The MTK VCP mailbox enables the SoC to communicate with the VCP by passing
+ messages through 64 32-bit wide registers. It has 32 interrupt vectors in
+ either direction for signalling purposes.
+
+properties:
+ compatible:
+ enum:
+ - mediatek,mt8196-vcp-mbox
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ "#mbox-cells":
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - "#mbox-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ mailbox@31b80000 {
+ compatible = "mediatek,mt8196-vcp-mbox";
+ reg = <0x31b80000 0x1000>;
+ interrupts = <GIC_SPI 789 IRQ_TYPE_LEVEL_HIGH 0>;
+ #mbox-cells = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml b/Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml
index 1332aab9a888..5f2ec74c1b29 100644
--- a/Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml
+++ b/Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml
@@ -11,7 +11,11 @@ maintainers:
properties:
compatible:
- const: microchip,mpfs-mailbox
+ oneOf:
+ - items:
+ - const: microchip,pic64gx-mailbox
+ - const: microchip,mpfs-mailbox
+ - const: microchip,mpfs-mailbox
reg:
oneOf:
diff --git a/Documentation/devicetree/bindings/mailbox/sprd-mailbox.yaml b/Documentation/devicetree/bindings/mailbox/sprd-mailbox.yaml
index b526f9c0c272..bf6ab4e7050c 100644
--- a/Documentation/devicetree/bindings/mailbox/sprd-mailbox.yaml
+++ b/Documentation/devicetree/bindings/mailbox/sprd-mailbox.yaml
@@ -16,6 +16,7 @@ properties:
enum:
- sprd,sc9860-mailbox
- sprd,sc9863a-mailbox
+ - sprd,ums9230-mailbox
reg:
items:
diff --git a/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml b/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml
index 04d6473d666f..a5205ee5ad0f 100644
--- a/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml
+++ b/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.yaml
@@ -11,6 +11,17 @@ description: |
messaging between two Xilinx Zynq UltraScale+ MPSoC IPI agents. Each IPI
agent owns registers used for notification and buffers for message.
+ For Versal devices, there are two types of IPI channels:
+ - Buffered channels: Support message passing and require the "msg"
+ register region to be present on both the host and remote IPI agents.
+ - Buffer-less channels: Support notification only and do not require the
+ "msg" register region. For these channels, the "msg" region should be
+ omitted.
+
+ For message passing, both the host and remote IPI agents must define the "msg"
+ register region. If either agent omits the "msg" region, only notification
+ based communication is possible.
+
+-------------------------------------+
| Xilinx ZynqMP IPI Controller |
+-------------------------------------+
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 29f16f220384..5bf4155b090a 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -199,7 +199,7 @@ config POLARFIRE_SOC_MAILBOX
tristate "PolarFire SoC (MPFS) Mailbox"
depends on HAS_IOMEM
depends on MFD_SYSCON
- depends on ARCH_MICROCHIP_POLARFIRE || COMPILE_TEST
+ depends on ARCH_MICROCHIP || COMPILE_TEST
help
This driver adds support for the PolarFire SoC (MPFS) mailbox controller.
@@ -279,7 +279,7 @@ config MTK_ADSP_MBOX
tristate "MediaTek ADSP Mailbox Controller"
depends on ARCH_MEDIATEK || COMPILE_TEST
help
- Say yes here to add support for "MediaTek ADSP Mailbox Controller.
+ Say yes here to add support for MediaTek ADSP Mailbox Controller.
This mailbox driver is used to send notification or short message
between processors with ADSP. It will place the message to share
buffer and will access the ipc control.
@@ -304,6 +304,15 @@ config MTK_GPUEB_MBOX
Say Y or m here if you want to support the MT8196 SoC in your kernel
build.
+config MTK_VCP_MBOX
+ tristate "MediaTek VCP Mailbox Support"
+ depends on ARCH_MEDIATEK || COMPILE_TEST
+ help
+ Say yes here to add support for the MediaTek VCP mailbox driver.
+ The mailbox implementation provides access from the application
+ processor to Video Companion Processor Unit.
+ If unsure say N.
+
config ZYNQMP_IPI_MBOX
tristate "Xilinx ZynqMP IPI Mailbox"
depends on ARCH_ZYNQMP && OF
@@ -387,7 +396,7 @@ config RISCV_SBI_MPXY_MBOX
Mailbox driver implementation for RISC-V SBI Message Proxy (MPXY)
extension. This mailbox driver is used to send messages to the
remote processor through the SBI implementation (M-mode firmware
- or HS-mode hypervisor). Say Y here if you want to have this support.
- If unsure say N.
+ or HS-mode hypervisor). Say Y here, unless you are sure you do not
+ need this.
endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 81820a4f5528..944d8ea39f34 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -65,6 +65,8 @@ obj-$(CONFIG_MTK_CMDQ_MBOX) += mtk-cmdq-mailbox.o
obj-$(CONFIG_MTK_GPUEB_MBOX) += mtk-gpueb-mailbox.o
+obj-$(CONFIG_MTK_VCP_MBOX) += mtk-vcp-mailbox.o
+
obj-$(CONFIG_ZYNQMP_IPI_MBOX) += zynqmp-ipi-mailbox.o
obj-$(CONFIG_SUN6I_MSGBOX) += sun6i-msgbox.o
diff --git a/drivers/mailbox/arm_mhuv3.c b/drivers/mailbox/arm_mhuv3.c
index 0910da67f8a1..a1c528be47f3 100644
--- a/drivers/mailbox/arm_mhuv3.c
+++ b/drivers/mailbox/arm_mhuv3.c
@@ -333,7 +333,7 @@ struct mhuv3_extension {
* @rev: MHUv3 controller IIDR revision.
* @var: MHUv3 controller IIDR variant.
* @prod_id: MHUv3 controller IIDR product_id.
- * @num_chans: The total number of channnels discovered across all extensions.
+ * @num_chans: The total number of channels discovered across all extensions.
* @cmb_irq: Combined IRQ number if any found defined.
* @ctrl: A reference to the MHUv3 control page for this block.
* @pbx: Base address of the PBX register mapping region.
diff --git a/drivers/mailbox/bcm-flexrm-mailbox.c b/drivers/mailbox/bcm-flexrm-mailbox.c
index 4255fefc3a5a..04c47eadf950 100644
--- a/drivers/mailbox/bcm-flexrm-mailbox.c
+++ b/drivers/mailbox/bcm-flexrm-mailbox.c
@@ -26,7 +26,6 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mailbox_controller.h>
-#include <linux/mailbox_client.h>
#include <linux/mailbox/brcm-message.h>
#include <linux/module.h>
#include <linux/msi.h>
diff --git a/drivers/mailbox/cix-mailbox.c b/drivers/mailbox/cix-mailbox.c
index 5bb1416c26a5..443620e8ae37 100644
--- a/drivers/mailbox/cix-mailbox.c
+++ b/drivers/mailbox/cix-mailbox.c
@@ -346,7 +346,7 @@ static void cix_mbox_isr_fifo(struct mbox_chan *chan)
/* FIFO overflow is generated */
if (int_status & CIX_FIFO_OFLOW_INT) {
status = cix_mbox_read(priv, CIX_FIFO_STAS);
- dev_err(priv->dev, "fifo overlow: int_stats %d\n", status);
+ dev_err(priv->dev, "fifo overflow: int_stats %d\n", status);
cix_mbox_write(priv, CIX_FIFO_OFLOW_INT, CIX_INT_CLEAR);
}
}
diff --git a/drivers/mailbox/cv1800-mailbox.c b/drivers/mailbox/cv1800-mailbox.c
index 4761191acf78..4bca9d8be4ba 100644
--- a/drivers/mailbox/cv1800-mailbox.c
+++ b/drivers/mailbox/cv1800-mailbox.c
@@ -11,7 +11,6 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kfifo.h>
-#include <linux/mailbox_client.h>
#include <linux/mailbox_controller.h>
#include <linux/module.h>
#include <linux/platform_device.h>
diff --git a/drivers/mailbox/exynos-mailbox.c b/drivers/mailbox/exynos-mailbox.c
index 2320649bf60c..5f2d3b81c1db 100644
--- a/drivers/mailbox/exynos-mailbox.c
+++ b/drivers/mailbox/exynos-mailbox.c
@@ -35,12 +35,10 @@
* struct exynos_mbox - driver's private data.
* @regs: mailbox registers base address.
* @mbox: pointer to the mailbox controller.
- * @pclk: pointer to the mailbox peripheral clock.
*/
struct exynos_mbox {
void __iomem *regs;
struct mbox_controller *mbox;
- struct clk *pclk;
};
static int exynos_mbox_send_data(struct mbox_chan *chan, void *data)
@@ -100,6 +98,7 @@ static int exynos_mbox_probe(struct platform_device *pdev)
struct exynos_mbox *exynos_mbox;
struct mbox_controller *mbox;
struct mbox_chan *chans;
+ struct clk *pclk;
int i;
exynos_mbox = devm_kzalloc(dev, sizeof(*exynos_mbox), GFP_KERNEL);
@@ -119,9 +118,9 @@ static int exynos_mbox_probe(struct platform_device *pdev)
if (IS_ERR(exynos_mbox->regs))
return PTR_ERR(exynos_mbox->regs);
- exynos_mbox->pclk = devm_clk_get_enabled(dev, "pclk");
- if (IS_ERR(exynos_mbox->pclk))
- return dev_err_probe(dev, PTR_ERR(exynos_mbox->pclk),
+ pclk = devm_clk_get_enabled(dev, "pclk");
+ if (IS_ERR(pclk))
+ return dev_err_probe(dev, PTR_ERR(pclk),
"Failed to enable clock.\n");
mbox->num_chans = EXYNOS_MBOX_CHAN_COUNT;
diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
index 6778afc64a04..003f9236c35e 100644
--- a/drivers/mailbox/imx-mailbox.c
+++ b/drivers/mailbox/imx-mailbox.c
@@ -122,6 +122,7 @@ struct imx_mu_dcfg {
u32 xRR; /* Receive Register0 */
u32 xSR[IMX_MU_xSR_MAX]; /* Status Registers */
u32 xCR[IMX_MU_xCR_MAX]; /* Control Registers */
+ bool skip_suspend_flag;
};
#define IMX_MU_xSR_GIPn(type, x) (type & IMX_MU_V2 ? BIT(x) : BIT(28 + (3 - (x))))
@@ -988,6 +989,7 @@ static const struct imx_mu_dcfg imx_mu_cfg_imx7ulp = {
.xRR = 0x40,
.xSR = {0x60, 0x60, 0x60, 0x60},
.xCR = {0x64, 0x64, 0x64, 0x64, 0x64},
+ .skip_suspend_flag = true,
};
static const struct imx_mu_dcfg imx_mu_cfg_imx8ulp = {
@@ -1071,7 +1073,8 @@ static int __maybe_unused imx_mu_suspend_noirq(struct device *dev)
priv->xcr[i] = imx_mu_read(priv, priv->dcfg->xCR[i]);
}
- priv->suspend = true;
+ if (!priv->dcfg->skip_suspend_flag)
+ priv->suspend = true;
return 0;
}
@@ -1094,7 +1097,8 @@ static int __maybe_unused imx_mu_resume_noirq(struct device *dev)
imx_mu_write(priv, priv->xcr[i], priv->dcfg->xCR[i]);
}
- priv->suspend = false;
+ if (!priv->dcfg->skip_suspend_flag)
+ priv->suspend = false;
return 0;
}
diff --git a/drivers/mailbox/mailbox-mchp-ipc-sbi.c b/drivers/mailbox/mailbox-mchp-ipc-sbi.c
index a6e52009a424..b87bf2fb4b9b 100644
--- a/drivers/mailbox/mailbox-mchp-ipc-sbi.c
+++ b/drivers/mailbox/mailbox-mchp-ipc-sbi.c
@@ -174,26 +174,30 @@ static irqreturn_t mchp_ipc_cluster_aggr_isr(int irq, void *data)
struct mchp_ipc_msg ipc_msg;
struct mchp_ipc_status status_msg;
int ret;
- unsigned long hartid;
u32 i, chan_index, chan_id;
+ bool found = false;
/* Find out the hart that originated the irq */
for_each_online_cpu(i) {
- hartid = cpuid_to_hartid_map(i);
- if (irq == ipc->cluster_cfg[hartid].irq)
+ if (irq == ipc->cluster_cfg[i].irq) {
+ found = true;
break;
+ }
}
- status_msg.cluster = hartid;
- memcpy(ipc->cluster_cfg[hartid].buf_base, &status_msg, sizeof(struct mchp_ipc_status));
+ if (unlikely(!found))
+ return IRQ_NONE;
- ret = mchp_ipc_sbi_send(SBI_EXT_IPC_STATUS, ipc->cluster_cfg[hartid].buf_base_addr);
+ status_msg.cluster = cpuid_to_hartid_map(i);
+ memcpy(ipc->cluster_cfg[i].buf_base, &status_msg, sizeof(struct mchp_ipc_status));
+
+ ret = mchp_ipc_sbi_send(SBI_EXT_IPC_STATUS, ipc->cluster_cfg[i].buf_base_addr);
if (ret < 0) {
dev_err_ratelimited(ipc->dev, "could not get IHC irq status ret=%d\n", ret);
return IRQ_HANDLED;
}
- memcpy(&status_msg, ipc->cluster_cfg[hartid].buf_base, sizeof(struct mchp_ipc_status));
+ memcpy(&status_msg, ipc->cluster_cfg[i].buf_base, sizeof(struct mchp_ipc_status));
/*
* Iterate over each bit set in the IHC interrupt status register (IRQ_STATUS) to identify
@@ -321,13 +325,6 @@ static int mchp_ipc_startup(struct mbox_chan *chan)
goto fail_free_buf_msg_rx;
}
- if (ret) {
- dev_err(ipc->dev, "failed to register interrupt(s)\n");
- goto fail_free_buf_msg_rx;
- }
-
- return ret;
-
fail_free_buf_msg_rx:
kfree(chan_info->msg_buf_rx);
fail_free_buf_msg_tx:
@@ -385,21 +382,21 @@ static int mchp_ipc_get_cluster_aggr_irq(struct mchp_ipc_sbi_mbox *ipc)
if (ret <= 0)
continue;
- ipc->cluster_cfg[hartid].irq = ret;
- ret = devm_request_irq(ipc->dev, ipc->cluster_cfg[hartid].irq,
+ ipc->cluster_cfg[cpuid].irq = ret;
+ ret = devm_request_irq(ipc->dev, ipc->cluster_cfg[cpuid].irq,
mchp_ipc_cluster_aggr_isr, IRQF_SHARED,
"miv-ihc-irq", ipc);
if (ret)
return ret;
- ipc->cluster_cfg[hartid].buf_base = devm_kmalloc(ipc->dev,
- sizeof(struct mchp_ipc_status),
- GFP_KERNEL);
+ ipc->cluster_cfg[cpuid].buf_base = devm_kmalloc(ipc->dev,
+ sizeof(struct mchp_ipc_status),
+ GFP_KERNEL);
- if (!ipc->cluster_cfg[hartid].buf_base)
+ if (!ipc->cluster_cfg[cpuid].buf_base)
return -ENOMEM;
- ipc->cluster_cfg[hartid].buf_base_addr = __pa(ipc->cluster_cfg[hartid].buf_base);
+ ipc->cluster_cfg[cpuid].buf_base_addr = __pa(ipc->cluster_cfg[cpuid].buf_base);
irq_found = true;
}
@@ -419,7 +416,7 @@ static int mchp_ipc_probe(struct platform_device *pdev)
ret = sbi_probe_extension(SBI_EXT_MICROCHIP_TECHNOLOGY);
if (ret <= 0)
- return dev_err_probe(dev, ret, "Microchip SBI extension not detected\n");
+ return dev_err_probe(dev, -ENODEV, "Microchip SBI extension not detected\n");
ipc = devm_kzalloc(dev, sizeof(*ipc), GFP_KERNEL);
if (!ipc)
diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
index 2acc6ec229a4..617ba505691d 100644
--- a/drivers/mailbox/mailbox.c
+++ b/drivers/mailbox/mailbox.c
@@ -489,12 +489,10 @@ EXPORT_SYMBOL_GPL(mbox_free_channel);
static struct mbox_chan *fw_mbox_index_xlate(struct mbox_controller *mbox,
const struct fwnode_reference_args *sp)
{
- int ind = sp->args[0];
-
- if (ind >= mbox->num_chans)
+ if (sp->nargs < 1 || sp->args[0] >= mbox->num_chans)
return ERR_PTR(-EINVAL);
- return &mbox->chans[ind];
+ return &mbox->chans[sp->args[0]];
}
/**
diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
index 1bf6984948ef..9da16b30eb41 100644
--- a/drivers/mailbox/mtk-cmdq-mailbox.c
+++ b/drivers/mailbox/mtk-cmdq-mailbox.c
@@ -636,7 +636,7 @@ static struct mbox_chan *cmdq_xlate(struct mbox_controller *mbox,
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 device_node *parent = dev->of_node->parent;
struct clk_bulk_data *clks;
cmdq->clocks = devm_kcalloc(dev, cmdq->pdata->gce_num,
@@ -661,7 +661,7 @@ static int cmdq_get_clocks(struct device *dev, struct cmdq *cmdq)
* as the clock of the main GCE must be enabled for additional IPs
* to be reachable.
*/
- for_each_child_of_node(parent, node) {
+ for_each_child_of_node_scoped(parent, node) {
int alias_id = of_alias_get_id(node, gce_name);
if (alias_id < 0 || alias_id >= cmdq->pdata->gce_num)
@@ -670,17 +670,13 @@ static int cmdq_get_clocks(struct device *dev, struct cmdq *cmdq)
clks = &cmdq->clocks[alias_id];
clks->id = devm_kasprintf(dev, GFP_KERNEL, "gce%d", alias_id);
- if (!clks->id) {
- of_node_put(node);
+ if (!clks->id)
return -ENOMEM;
- }
clks->clk = of_clk_get(node, 0);
- if (IS_ERR(clks->clk)) {
- of_node_put(node);
+ if (IS_ERR(clks->clk))
return dev_err_probe(dev, PTR_ERR(clks->clk),
"failed to get gce%d clock\n", alias_id);
- }
}
return 0;
diff --git a/drivers/mailbox/mtk-vcp-mailbox.c b/drivers/mailbox/mtk-vcp-mailbox.c
new file mode 100644
index 000000000000..cedad575528f
--- /dev/null
+++ b/drivers/mailbox/mtk-vcp-mailbox.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 MediaTek Corporation. All rights reserved.
+ * Author: Jjian Zhou <jjian.zhou.@mediatek.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/mailbox/mtk-vcp-mailbox.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+struct mtk_vcp_mbox {
+ struct mbox_controller mbox;
+ void __iomem *base;
+ struct device *dev;
+ const struct mtk_vcp_mbox_cfg *cfg;
+ struct mtk_ipi_info ipi_recv;
+ struct mbox_chan chans;
+};
+
+struct mtk_vcp_mbox_cfg {
+ u16 set_in;
+ u16 clr_out;
+};
+
+static irqreturn_t mtk_vcp_mbox_irq_thread(int irq, void *data)
+{
+ struct mtk_vcp_mbox *priv = data;
+
+ /* get irq status */
+ priv->ipi_recv.irq_status = readl(priv->base + priv->cfg->clr_out);
+
+ __ioread32_copy(priv->ipi_recv.msg, priv->base,
+ MTK_VCP_MBOX_SLOT_MAX_SIZE / 4);
+
+ mbox_chan_received_data(&priv->chans, &priv->ipi_recv);
+
+ /* clear irq status */
+ writel(priv->ipi_recv.irq_status, priv->base + priv->cfg->clr_out);
+
+ return IRQ_HANDLED;
+}
+
+static struct mbox_chan *mtk_vcp_mbox_xlate(struct mbox_controller *mbox,
+ const struct of_phandle_args *sp)
+{
+ if (sp->args_count)
+ return NULL;
+
+ return &mbox->chans[0];
+}
+
+static int mtk_vcp_mbox_send_data(struct mbox_chan *chan, void *data)
+{
+ struct mtk_vcp_mbox *priv = chan->con_priv;
+ struct mtk_ipi_info *ipi_info = data;
+ u32 status;
+
+ if (!ipi_info->msg) {
+ dev_err(priv->dev, "msg buffer is NULL.\n");
+ return -EINVAL;
+ }
+
+ status = readl(priv->base + priv->cfg->set_in);
+ if (status & BIT(ipi_info->index)) {
+ dev_warn(priv->dev, "mailbox IPI %d is busy.\n", ipi_info->id);
+ return -EBUSY;
+ }
+
+ if (ipi_info->slot_ofs + ipi_info->len > MTK_VCP_MBOX_SLOT_MAX_SIZE)
+ return -EINVAL;
+ __iowrite32_copy(priv->base + ipi_info->slot_ofs, ipi_info->msg,
+ ipi_info->len);
+
+ writel(BIT(ipi_info->index), priv->base + priv->cfg->set_in);
+
+ return 0;
+}
+
+static bool mtk_vcp_mbox_last_tx_done(struct mbox_chan *chan)
+{
+ struct mtk_ipi_info *ipi_info = chan->active_req;
+ struct mtk_vcp_mbox *priv = chan->con_priv;
+
+ return !(readl(priv->base + priv->cfg->set_in) & BIT(ipi_info->index));
+}
+
+static const struct mbox_chan_ops mtk_vcp_mbox_chan_ops = {
+ .send_data = mtk_vcp_mbox_send_data,
+ .last_tx_done = mtk_vcp_mbox_last_tx_done,
+};
+
+static int mtk_vcp_mbox_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mtk_vcp_mbox *priv;
+ struct mbox_controller *mbox;
+ int ret, irq;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+ priv->chans.con_priv = priv;
+ mbox = &priv->mbox;
+ mbox->dev = dev;
+ mbox->ops = &mtk_vcp_mbox_chan_ops;
+ mbox->txdone_irq = false;
+ mbox->txdone_poll = true;
+ mbox->of_xlate = mtk_vcp_mbox_xlate;
+ mbox->num_chans = 1;
+ mbox->chans = &priv->chans;
+
+ priv->ipi_recv.msg = devm_kzalloc(dev, MTK_VCP_MBOX_SLOT_MAX_SIZE,
+ GFP_KERNEL);
+ if (!priv->ipi_recv.msg)
+ return -ENOMEM;
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ priv->cfg = of_device_get_match_data(dev);
+ if (!priv->cfg)
+ return -EINVAL;
+
+ platform_set_drvdata(pdev, priv);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ mtk_vcp_mbox_irq_thread, IRQF_ONESHOT,
+ dev_name(dev), priv);
+ if (ret < 0)
+ return ret;
+
+ return devm_mbox_controller_register(dev, &priv->mbox);
+}
+
+static const struct mtk_vcp_mbox_cfg mt8196_cfg = {
+ .set_in = 0x100,
+ .clr_out = 0x10c,
+};
+
+static const struct of_device_id mtk_vcp_mbox_of_match[] = {
+ { .compatible = "mediatek,mt8196-vcp-mbox", .data = &mt8196_cfg },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mtk_vcp_mbox_of_match);
+
+static struct platform_driver mtk_vcp_mbox_driver = {
+ .probe = mtk_vcp_mbox_probe,
+ .driver = {
+ .name = "mtk_vcp_mbox",
+ .of_match_table = mtk_vcp_mbox_of_match,
+ },
+};
+module_platform_driver(mtk_vcp_mbox_driver);
+
+MODULE_AUTHOR("Jjian Zhou <jjian.zhou@mediatek.com>");
+MODULE_DESCRIPTION("MTK VCP Mailbox Controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index 17fe6545875d..d9f100c18895 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -21,7 +21,6 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/mailbox_controller.h>
-#include <linux/mailbox_client.h>
#include "mailbox.h"
diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index ff292b9e0be9..22e70af1ae5d 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -305,22 +305,6 @@ static void pcc_chan_acknowledge(struct pcc_chan_info *pchan)
pcc_chan_reg_read_modify_write(&pchan->db);
}
-static void *write_response(struct pcc_chan_info *pchan)
-{
- struct pcc_header pcc_header;
- void *buffer;
- int data_len;
-
- memcpy_fromio(&pcc_header, pchan->chan.shmem,
- sizeof(pcc_header));
- data_len = pcc_header.length - sizeof(u32) + sizeof(struct pcc_header);
-
- buffer = pchan->chan.rx_alloc(pchan->chan.mchan->cl, data_len);
- if (buffer != NULL)
- memcpy_fromio(buffer, pchan->chan.shmem, data_len);
- return buffer;
-}
-
/**
* pcc_mbox_irq - PCC mailbox interrupt handler
* @irq: interrupt number
@@ -332,8 +316,6 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
{
struct pcc_chan_info *pchan;
struct mbox_chan *chan = p;
- struct pcc_header *pcc_header = chan->active_req;
- void *handle = NULL;
pchan = chan->con_priv;
@@ -357,17 +339,8 @@ static irqreturn_t pcc_mbox_irq(int irq, void *p)
* required to avoid any possible race in updatation of this flag.
*/
pchan->chan_in_use = false;
-
- if (pchan->chan.rx_alloc)
- handle = write_response(pchan);
-
- if (chan->active_req) {
- pcc_header = chan->active_req;
- if (pcc_header->flags & PCC_CMD_COMPLETION_NOTIFY)
- mbox_chan_txdone(chan, 0);
- }
-
- mbox_chan_received_data(chan, handle);
+ mbox_chan_received_data(chan, NULL);
+ mbox_chan_txdone(chan, 0);
pcc_chan_acknowledge(pchan);
@@ -404,33 +377,20 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
return ERR_PTR(-EBUSY);
}
- rc = mbox_bind_client(chan, cl);
- if (rc)
- return ERR_PTR(rc);
-
pcc_mchan = &pchan->chan;
pcc_mchan->shmem = acpi_os_ioremap(pcc_mchan->shmem_base_addr,
pcc_mchan->shmem_size);
if (!pcc_mchan->shmem)
- goto err;
-
- pcc_mchan->manage_writes = false;
+ return ERR_PTR(-ENXIO);
- /* This indicates that the channel is ready to accept messages.
- * This needs to happen after the channel has registered
- * its callback. There is no access point to do that in
- * the mailbox API. That implies that the mailbox client must
- * have set the allocate callback function prior to
- * sending any messages.
- */
- if (pchan->type == ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE)
- pcc_chan_reg_read_modify_write(&pchan->cmd_update);
+ rc = mbox_bind_client(chan, cl);
+ if (rc) {
+ iounmap(pcc_mchan->shmem);
+ pcc_mchan->shmem = NULL;
+ return ERR_PTR(rc);
+ }
return pcc_mchan;
-
-err:
- mbox_free_channel(chan);
- return ERR_PTR(-ENXIO);
}
EXPORT_SYMBOL_GPL(pcc_mbox_request_channel);
@@ -459,38 +419,8 @@ void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan)
}
EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);
-static int pcc_write_to_buffer(struct mbox_chan *chan, void *data)
-{
- struct pcc_chan_info *pchan = chan->con_priv;
- struct pcc_mbox_chan *pcc_mbox_chan = &pchan->chan;
- struct pcc_header *pcc_header = data;
-
- if (!pchan->chan.manage_writes)
- return 0;
-
- /* The PCC header length includes the command field
- * but not the other values from the header.
- */
- int len = pcc_header->length - sizeof(u32) + sizeof(struct pcc_header);
- u64 val;
-
- pcc_chan_reg_read(&pchan->cmd_complete, &val);
- if (!val) {
- pr_info("%s pchan->cmd_complete not set", __func__);
- return -1;
- }
- memcpy_toio(pcc_mbox_chan->shmem, data, len);
- return 0;
-}
-
-
/**
- * pcc_send_data - Called from Mailbox Controller code. If
- * pchan->chan.rx_alloc is set, then the command complete
- * flag is checked and the data is written to the shared
- * buffer io memory.
- *
- * If pchan->chan.rx_alloc is not set, then it is used
+ * pcc_send_data - Called from Mailbox Controller code. Used
* here only to ring the channel doorbell. The PCC client
* specific read/write is done in the client driver in
* order to maintain atomicity over PCC channel once
@@ -506,37 +436,24 @@ static int pcc_send_data(struct mbox_chan *chan, void *data)
int ret;
struct pcc_chan_info *pchan = chan->con_priv;
- ret = pcc_write_to_buffer(chan, data);
- if (ret)
- return ret;
-
ret = pcc_chan_reg_read_modify_write(&pchan->cmd_update);
if (ret)
return ret;
ret = pcc_chan_reg_read_modify_write(&pchan->db);
-
if (!ret && pchan->plat_irq > 0)
pchan->chan_in_use = true;
return ret;
}
-
static bool pcc_last_tx_done(struct mbox_chan *chan)
{
struct pcc_chan_info *pchan = chan->con_priv;
- u64 val;
- pcc_chan_reg_read(&pchan->cmd_complete, &val);
- if (!val)
- return false;
- else
- return true;
+ return pcc_mbox_cmd_complete_check(pchan);
}
-
-
/**
* pcc_startup - Called from Mailbox Controller code. Used here
* to request the interrupt.
@@ -550,9 +467,15 @@ static int pcc_startup(struct mbox_chan *chan)
unsigned long irqflags;
int rc;
+ /*
+ * Clear and acknowledge any pending interrupts on responder channel
+ * before enabling the interrupt
+ */
+ pcc_chan_acknowledge(pchan);
+
if (pchan->plat_irq > 0) {
irqflags = pcc_chan_plat_irq_can_be_shared(pchan) ?
- IRQF_SHARED | IRQF_ONESHOT : 0;
+ IRQF_SHARED : 0;
rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq,
irqflags, MBOX_IRQ_NAME, chan);
if (unlikely(rc)) {
@@ -877,8 +800,13 @@ static int pcc_mbox_probe(struct platform_device *pdev)
(unsigned long) pcct_tbl + sizeof(struct acpi_table_pcct));
acpi_pcct_tbl = (struct acpi_table_pcct *) pcct_tbl;
- if (acpi_pcct_tbl->flags & ACPI_PCCT_DOORBELL)
+ if (acpi_pcct_tbl->flags & ACPI_PCCT_DOORBELL) {
pcc_mbox_ctrl->txdone_irq = true;
+ pcc_mbox_ctrl->txdone_poll = false;
+ } else {
+ pcc_mbox_ctrl->txdone_irq = false;
+ pcc_mbox_ctrl->txdone_poll = true;
+ }
for (i = 0; i < count; i++) {
struct pcc_chan_info *pchan = chan_info + i;
diff --git a/drivers/mailbox/sprd-mailbox.c b/drivers/mailbox/sprd-mailbox.c
index ee8539dfcef5..565502904e1f 100644
--- a/drivers/mailbox/sprd-mailbox.c
+++ b/drivers/mailbox/sprd-mailbox.c
@@ -24,7 +24,8 @@
#define SPRD_MBOX_IRQ_STS 0x18
#define SPRD_MBOX_IRQ_MSK 0x1c
#define SPRD_MBOX_LOCK 0x20
-#define SPRD_MBOX_FIFO_DEPTH 0x24
+#define SPRD_MBOX_FIFO_DEPTH 0x24 /* outbox only */
+#define SPRD_MBOX_IN_FIFO_STS2 0x24 /* inbox only, revision 2 */
/* Bit and mask definition for inbox's SPRD_MBOX_FIFO_STS register */
#define SPRD_INBOX_FIFO_DELIVER_MASK GENMASK(23, 16)
@@ -32,8 +33,18 @@
#define SPRD_INBOX_FIFO_DELIVER_SHIFT 16
#define SPRD_INBOX_FIFO_BUSY_MASK GENMASK(7, 0)
+/* Bit and mask definition for R2 inbox's SPRD_MBOX_FIFO_RST register */
+#define SPRD_INBOX_R2_FIFO_OVERFLOW_DELIVER_RST GENMASK(31, 0)
+
+/* Bit and mask definition for R2 inbox's SPRD_MBOX_FIFO_STS register */
+#define SPRD_INBOX_R2_FIFO_DELIVER_MASK GENMASK(15, 0)
+
+/* Bit and mask definition for SPRD_MBOX_IN_FIFO_STS2 register */
+#define SPRD_INBOX_R2_FIFO_OVERFLOW_MASK GENMASK(31, 16)
+#define SPRD_INBOX_R2_FIFO_BUSY_MASK GENMASK(15, 0)
+
/* Bit and mask definition for SPRD_MBOX_IRQ_STS register */
-#define SPRD_MBOX_IRQ_CLR BIT(0)
+#define SPRD_MBOX_IRQ_CLR GENMASK(31, 0)
/* Bit and mask definition for outbox's SPRD_MBOX_FIFO_STS register */
#define SPRD_OUTBOX_FIFO_FULL BIT(2)
@@ -52,8 +63,18 @@
#define SPRD_OUTBOX_FIFO_IRQ_MASK GENMASK(4, 0)
#define SPRD_OUTBOX_BASE_SPAN 0x1000
-#define SPRD_MBOX_CHAN_MAX 8
-#define SPRD_SUPP_INBOX_ID_SC9863A 7
+#define SPRD_MBOX_R1_CHAN_MAX 8
+#define SPRD_MBOX_R2_CHAN_MAX 16
+
+enum sprd_mbox_version {
+ SPRD_MBOX_R1,
+ SPRD_MBOX_R2,
+};
+
+struct sprd_mbox_info {
+ enum sprd_mbox_version version;
+ unsigned long supp_id;
+};
struct sprd_mbox_priv {
struct mbox_controller mbox;
@@ -64,9 +85,11 @@ struct sprd_mbox_priv {
void __iomem *supp_base;
u32 outbox_fifo_depth;
+ const struct sprd_mbox_info *info;
+
struct mutex lock;
u32 refcnt;
- struct mbox_chan chan[SPRD_MBOX_CHAN_MAX];
+ struct mbox_chan chan[SPRD_MBOX_R2_CHAN_MAX];
};
static struct sprd_mbox_priv *to_sprd_mbox_priv(struct mbox_controller *mbox)
@@ -154,18 +177,35 @@ static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data)
{
struct sprd_mbox_priv *priv = data;
struct mbox_chan *chan;
- u32 fifo_sts, send_sts, busy, id;
+ u32 fifo_sts, fifo_sts2, send_sts, busy, id;
fifo_sts = readl(priv->inbox_base + SPRD_MBOX_FIFO_STS);
+ if (priv->info->version == SPRD_MBOX_R2)
+ fifo_sts2 = readl(priv->inbox_base + SPRD_MBOX_IN_FIFO_STS2);
+
/* Get the inbox data delivery status */
- send_sts = (fifo_sts & SPRD_INBOX_FIFO_DELIVER_MASK) >>
- SPRD_INBOX_FIFO_DELIVER_SHIFT;
+ if (priv->info->version == SPRD_MBOX_R2) {
+ send_sts = fifo_sts & SPRD_INBOX_R2_FIFO_DELIVER_MASK;
+ } else {
+ send_sts = (fifo_sts & SPRD_INBOX_FIFO_DELIVER_MASK) >>
+ SPRD_INBOX_FIFO_DELIVER_SHIFT;
+ }
+
if (!send_sts) {
dev_warn_ratelimited(priv->dev, "spurious inbox interrupt\n");
return IRQ_NONE;
}
+ /* Clear FIFO delivery and overflow status first */
+ if (priv->info->version == SPRD_MBOX_R2) {
+ writel(SPRD_INBOX_R2_FIFO_OVERFLOW_DELIVER_RST,
+ priv->inbox_base + SPRD_MBOX_FIFO_RST);
+ } else {
+ writel(fifo_sts & (SPRD_INBOX_FIFO_DELIVER_MASK | SPRD_INBOX_FIFO_OVERLOW_MASK),
+ priv->inbox_base + SPRD_MBOX_FIFO_RST);
+ }
+
while (send_sts) {
id = __ffs(send_sts);
send_sts &= (send_sts - 1);
@@ -176,16 +216,15 @@ static irqreturn_t sprd_mbox_inbox_isr(int irq, void *data)
* Check if the message was fetched by remote target, if yes,
* that means the transmission has been completed.
*/
- busy = fifo_sts & SPRD_INBOX_FIFO_BUSY_MASK;
+ if (priv->info->version == SPRD_MBOX_R2)
+ busy = fifo_sts2 & SPRD_INBOX_R2_FIFO_BUSY_MASK;
+ else
+ busy = fifo_sts & SPRD_INBOX_FIFO_BUSY_MASK;
+
if (!(busy & BIT(id)))
mbox_chan_txdone(chan, 0);
}
- /* Clear FIFO delivery and overflow status */
- writel(fifo_sts &
- (SPRD_INBOX_FIFO_DELIVER_MASK | SPRD_INBOX_FIFO_OVERLOW_MASK),
- priv->inbox_base + SPRD_MBOX_FIFO_RST);
-
/* Clear irq status */
writel(SPRD_MBOX_IRQ_CLR, priv->inbox_base + SPRD_MBOX_IRQ_STS);
@@ -243,21 +282,19 @@ static int sprd_mbox_startup(struct mbox_chan *chan)
/* Select outbox FIFO mode and reset the outbox FIFO status */
writel(0x0, priv->outbox_base + SPRD_MBOX_FIFO_RST);
- /* Enable inbox FIFO overflow and delivery interrupt */
- val = readl(priv->inbox_base + SPRD_MBOX_IRQ_MSK);
- val &= ~(SPRD_INBOX_FIFO_OVERFLOW_IRQ | SPRD_INBOX_FIFO_DELIVER_IRQ);
+ /* Enable inbox FIFO delivery interrupt */
+ val = SPRD_INBOX_FIFO_IRQ_MASK;
+ val &= ~SPRD_INBOX_FIFO_DELIVER_IRQ;
writel(val, priv->inbox_base + SPRD_MBOX_IRQ_MSK);
/* Enable outbox FIFO not empty interrupt */
- val = readl(priv->outbox_base + SPRD_MBOX_IRQ_MSK);
+ val = SPRD_OUTBOX_FIFO_IRQ_MASK;
val &= ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ;
writel(val, priv->outbox_base + SPRD_MBOX_IRQ_MSK);
/* Enable supplementary outbox as the fundamental one */
if (priv->supp_base) {
writel(0x0, priv->supp_base + SPRD_MBOX_FIFO_RST);
- val = readl(priv->supp_base + SPRD_MBOX_IRQ_MSK);
- val &= ~SPRD_OUTBOX_FIFO_NOT_EMPTY_IRQ;
writel(val, priv->supp_base + SPRD_MBOX_IRQ_MSK);
}
}
@@ -295,7 +332,7 @@ static int sprd_mbox_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct sprd_mbox_priv *priv;
int ret, inbox_irq, outbox_irq, supp_irq;
- unsigned long id, supp;
+ unsigned long id;
struct clk *clk;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -305,6 +342,10 @@ static int sprd_mbox_probe(struct platform_device *pdev)
priv->dev = dev;
mutex_init(&priv->lock);
+ priv->info = of_device_get_match_data(dev);
+ if (!priv->info)
+ return -EINVAL;
+
/*
* Unisoc mailbox uses an inbox to send messages to the target
* core, and uses (an) outbox(es) to receive messages from other
@@ -362,12 +403,12 @@ static int sprd_mbox_probe(struct platform_device *pdev)
return ret;
}
- supp = (unsigned long) of_device_get_match_data(dev);
- if (!supp) {
+ if (!priv->info->supp_id) {
dev_err(dev, "no supplementary outbox specified\n");
return -ENODEV;
}
- priv->supp_base = priv->outbox_base + (SPRD_OUTBOX_BASE_SPAN * supp);
+ priv->supp_base = priv->outbox_base +
+ (SPRD_OUTBOX_BASE_SPAN * priv->info->supp_id);
}
/* Get the default outbox FIFO depth */
@@ -375,11 +416,15 @@ static int sprd_mbox_probe(struct platform_device *pdev)
readl(priv->outbox_base + SPRD_MBOX_FIFO_DEPTH) + 1;
priv->mbox.dev = dev;
priv->mbox.chans = &priv->chan[0];
- priv->mbox.num_chans = SPRD_MBOX_CHAN_MAX;
priv->mbox.ops = &sprd_mbox_ops;
priv->mbox.txdone_irq = true;
- for (id = 0; id < SPRD_MBOX_CHAN_MAX; id++)
+ if (priv->info->version == SPRD_MBOX_R2)
+ priv->mbox.num_chans = SPRD_MBOX_R2_CHAN_MAX;
+ else
+ priv->mbox.num_chans = SPRD_MBOX_R1_CHAN_MAX;
+
+ for (id = 0; id < priv->mbox.num_chans; id++)
priv->chan[id].con_priv = (void *)id;
ret = devm_mbox_controller_register(dev, &priv->mbox);
@@ -391,10 +436,24 @@ static int sprd_mbox_probe(struct platform_device *pdev)
return 0;
}
+static const struct sprd_mbox_info sc9860_mbox_info = {
+ .version = SPRD_MBOX_R1,
+};
+
+static const struct sprd_mbox_info sc9863a_mbox_info = {
+ .version = SPRD_MBOX_R1,
+ .supp_id = 7,
+};
+
+static const struct sprd_mbox_info ums9230_mbox_info = {
+ .version = SPRD_MBOX_R2,
+ .supp_id = 6,
+};
+
static const struct of_device_id sprd_mbox_of_match[] = {
- { .compatible = "sprd,sc9860-mailbox" },
- { .compatible = "sprd,sc9863a-mailbox",
- .data = (void *)SPRD_SUPP_INBOX_ID_SC9863A },
+ { .compatible = "sprd,sc9860-mailbox", .data = &sc9860_mbox_info },
+ { .compatible = "sprd,sc9863a-mailbox", .data = &sc9863a_mbox_info },
+ { .compatible = "sprd,ums9230-mailbox", .data = &ums9230_mbox_info },
{ },
};
MODULE_DEVICE_TABLE(of, sprd_mbox_of_match);
diff --git a/drivers/mailbox/zynqmp-ipi-mailbox.c b/drivers/mailbox/zynqmp-ipi-mailbox.c
index 967967b2b8a9..42d2583e44ca 100644
--- a/drivers/mailbox/zynqmp-ipi-mailbox.c
+++ b/drivers/mailbox/zynqmp-ipi-mailbox.c
@@ -904,7 +904,7 @@ static void zynqmp_ipi_free_mboxes(struct zynqmp_ipi_pdata *pdata)
static int zynqmp_ipi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct device_node *nc, *np = pdev->dev.of_node;
+ struct device_node *np = pdev->dev.of_node;
struct zynqmp_ipi_pdata *pdata;
struct of_phandle_args out_irq;
struct zynqmp_ipi_mbox *mbox;
@@ -940,13 +940,12 @@ static int zynqmp_ipi_probe(struct platform_device *pdev)
pdata->num_mboxes = num_mboxes;
mbox = pdata->ipi_mboxes;
- for_each_available_child_of_node(np, nc) {
+ for_each_available_child_of_node_scoped(np, nc) {
mbox->pdata = pdata;
mbox->setup_ipi_fn = ipi_fn;
ret = zynqmp_ipi_mbox_probe(mbox, nc);
if (ret) {
- of_node_put(nc);
dev_err(dev, "failed to probe subdev.\n");
ret = -EINVAL;
goto free_mbox_dev;
diff --git a/include/acpi/pcc.h b/include/acpi/pcc.h
index 9af3b502f839..840bfc95bae3 100644
--- a/include/acpi/pcc.h
+++ b/include/acpi/pcc.h
@@ -17,35 +17,6 @@ struct pcc_mbox_chan {
u32 latency;
u32 max_access_rate;
u16 min_turnaround_time;
-
- /* Set to true to indicate that the mailbox should manage
- * writing the dat to the shared buffer. This differs from
- * the case where the drivesr are writing to the buffer and
- * using send_data only to ring the doorbell. If this flag
- * is set, then the void * data parameter of send_data must
- * point to a kernel-memory buffer formatted in accordance with
- * the PCC specification.
- *
- * The active buffer management will include reading the
- * notify_on_completion flag, and will then
- * call mbox_chan_txdone when the acknowledgment interrupt is
- * received.
- */
- bool manage_writes;
-
- /* Optional callback that allows the driver
- * to allocate the memory used for receiving
- * messages. The return value is the location
- * inside the buffer where the mailbox should write the data.
- */
- void *(*rx_alloc)(struct mbox_client *cl, int size);
-};
-
-struct pcc_header {
- u32 signature;
- u32 flags;
- u32 length;
- u32 command;
};
/* Generic Communications Channel Shared Memory Region */
diff --git a/include/linux/mailbox/mtk-vcp-mailbox.h b/include/linux/mailbox/mtk-vcp-mailbox.h
new file mode 100644
index 000000000000..16e59d6780a7
--- /dev/null
+++ b/include/linux/mailbox/mtk-vcp-mailbox.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (c) 2025 MediaTek Inc.
+ */
+
+#ifndef __MTK_VCP_MAILBOX_H__
+#define __MTK_VCP_MAILBOX_H__
+
+#define MTK_VCP_MBOX_SLOT_MAX_SIZE 0x100 /* mbox max slot size */
+
+/**
+ * struct mtk_ipi_info - mailbox message info for mtk-vcp-mailbox
+ * @msg: The share buffer between IPC and mailbox driver
+ * @len: Message length
+ * @id: This is for identification purposes and not actually used
+ * by the mailbox hardware.
+ * @index: The signal number of the mailbox message.
+ * @slot_ofs: Data slot offset.
+ * @irq_status: Captures incoming signals for the RX path.
+ *
+ * It is used between IPC with mailbox driver.
+ */
+struct mtk_ipi_info {
+ void *msg;
+ u32 len;
+ u32 id;
+ u32 index;
+ u32 slot_ofs;
+ u32 irq_status;
+};
+
+#endif