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

mailbox: mediatek: add support for adsp mailbox controller

This patch is to for MediaTek ADSP IPC mailbox controller driver
It is used to send short messages between processors with adsp

Signed-off-by: Allen-KH Cheng <allen-kh.cheng@mediatek.com>
Reviewed-by: Tzung-Bi Shih <tzungbi@google.com>
Reviewed-by: YC Hung <yc.hung@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>

authored by

Allen-KH Cheng and committed by
Jassi Brar
af2dfa96 afa092e1

+187
+9
drivers/mailbox/Kconfig
··· 238 238 with hardware for Inter-Processor Communication Controller (IPCC) 239 239 between processors. Say Y here if you want to have this support. 240 240 241 + config MTK_ADSP_MBOX 242 + tristate "MediaTek ADSP Mailbox Controller" 243 + depends on ARCH_MEDIATEK || COMPILE_TEST 244 + help 245 + Say yes here to add support for "MediaTek ADSP Mailbox Controller. 246 + This mailbox driver is used to send notification or short message 247 + between processors with ADSP. It will place the message to share 248 + buffer and will access the ipc control. 249 + 241 250 config MTK_CMDQ_MBOX 242 251 tristate "MediaTek CMDQ Mailbox Support" 243 252 depends on ARCH_MEDIATEK || COMPILE_TEST
+2
drivers/mailbox/Makefile
··· 49 49 50 50 obj-$(CONFIG_STM32_IPCC) += stm32-ipcc.o 51 51 52 + obj-$(CONFIG_MTK_ADSP_MBOX) += mtk-adsp-mailbox.o 53 + 52 54 obj-$(CONFIG_MTK_CMDQ_MBOX) += mtk-cmdq-mailbox.o 53 55 54 56 obj-$(CONFIG_ZYNQMP_IPI_MBOX) += zynqmp-ipi-mailbox.o
+176
drivers/mailbox/mtk-adsp-mailbox.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2022 MediaTek Corporation. All rights reserved. 4 + * Author: Allen-KH Cheng <allen-kh.cheng@mediatek.com> 5 + */ 6 + 7 + #include <linux/interrupt.h> 8 + #include <linux/io.h> 9 + #include <linux/iopoll.h> 10 + #include <linux/kernel.h> 11 + #include <linux/mailbox_controller.h> 12 + #include <linux/module.h> 13 + #include <linux/of_device.h> 14 + #include <linux/slab.h> 15 + 16 + struct mtk_adsp_mbox_priv { 17 + struct device *dev; 18 + struct mbox_controller mbox; 19 + void __iomem *va_mboxreg; 20 + const struct mtk_adsp_mbox_cfg *cfg; 21 + }; 22 + 23 + struct mtk_adsp_mbox_cfg { 24 + u32 set_in; 25 + u32 set_out; 26 + u32 clr_in; 27 + u32 clr_out; 28 + }; 29 + 30 + static inline struct mtk_adsp_mbox_priv *get_mtk_adsp_mbox_priv(struct mbox_controller *mbox) 31 + { 32 + return container_of(mbox, struct mtk_adsp_mbox_priv, mbox); 33 + } 34 + 35 + static irqreturn_t mtk_adsp_mbox_irq(int irq, void *data) 36 + { 37 + struct mbox_chan *chan = data; 38 + struct mtk_adsp_mbox_priv *priv = get_mtk_adsp_mbox_priv(chan->mbox); 39 + u32 op = readl(priv->va_mboxreg + priv->cfg->set_out); 40 + 41 + writel(op, priv->va_mboxreg + priv->cfg->clr_out); 42 + 43 + return IRQ_WAKE_THREAD; 44 + } 45 + 46 + static irqreturn_t mtk_adsp_mbox_isr(int irq, void *data) 47 + { 48 + struct mbox_chan *chan = data; 49 + 50 + mbox_chan_received_data(chan, NULL); 51 + 52 + return IRQ_HANDLED; 53 + } 54 + 55 + static struct mbox_chan *mtk_adsp_mbox_xlate(struct mbox_controller *mbox, 56 + const struct of_phandle_args *sp) 57 + { 58 + return mbox->chans; 59 + } 60 + 61 + static int mtk_adsp_mbox_startup(struct mbox_chan *chan) 62 + { 63 + struct mtk_adsp_mbox_priv *priv = get_mtk_adsp_mbox_priv(chan->mbox); 64 + 65 + /* Clear ADSP mbox command */ 66 + writel(0xFFFFFFFF, priv->va_mboxreg + priv->cfg->clr_in); 67 + writel(0xFFFFFFFF, priv->va_mboxreg + priv->cfg->clr_out); 68 + 69 + return 0; 70 + } 71 + 72 + static void mtk_adsp_mbox_shutdown(struct mbox_chan *chan) 73 + { 74 + struct mtk_adsp_mbox_priv *priv = get_mtk_adsp_mbox_priv(chan->mbox); 75 + 76 + /* Clear ADSP mbox command */ 77 + writel(0xFFFFFFFF, priv->va_mboxreg + priv->cfg->clr_in); 78 + writel(0xFFFFFFFF, priv->va_mboxreg + priv->cfg->clr_out); 79 + } 80 + 81 + static int mtk_adsp_mbox_send_data(struct mbox_chan *chan, void *data) 82 + { 83 + struct mtk_adsp_mbox_priv *priv = get_mtk_adsp_mbox_priv(chan->mbox); 84 + u32 *msg = data; 85 + 86 + writel(*msg, priv->va_mboxreg + priv->cfg->set_in); 87 + 88 + return 0; 89 + } 90 + 91 + static bool mtk_adsp_mbox_last_tx_done(struct mbox_chan *chan) 92 + { 93 + struct mtk_adsp_mbox_priv *priv = get_mtk_adsp_mbox_priv(chan->mbox); 94 + 95 + return readl(priv->va_mboxreg + priv->cfg->set_in) == 0; 96 + } 97 + 98 + static const struct mbox_chan_ops mtk_adsp_mbox_chan_ops = { 99 + .send_data = mtk_adsp_mbox_send_data, 100 + .startup = mtk_adsp_mbox_startup, 101 + .shutdown = mtk_adsp_mbox_shutdown, 102 + .last_tx_done = mtk_adsp_mbox_last_tx_done, 103 + }; 104 + 105 + static int mtk_adsp_mbox_probe(struct platform_device *pdev) 106 + { 107 + struct device *dev = &pdev->dev; 108 + struct mtk_adsp_mbox_priv *priv; 109 + const struct mtk_adsp_mbox_cfg *cfg; 110 + struct mbox_controller *mbox; 111 + int ret, irq; 112 + 113 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 114 + if (!priv) 115 + return -ENOMEM; 116 + 117 + mbox = &priv->mbox; 118 + mbox->dev = dev; 119 + mbox->ops = &mtk_adsp_mbox_chan_ops; 120 + mbox->txdone_irq = false; 121 + mbox->txdone_poll = true; 122 + mbox->of_xlate = mtk_adsp_mbox_xlate; 123 + mbox->num_chans = 1; 124 + mbox->chans = devm_kzalloc(dev, sizeof(*mbox->chans), GFP_KERNEL); 125 + if (!mbox->chans) 126 + return -ENOMEM; 127 + 128 + priv->va_mboxreg = devm_platform_ioremap_resource(pdev, 0); 129 + if (IS_ERR(priv->va_mboxreg)) 130 + return PTR_ERR(priv->va_mboxreg); 131 + 132 + cfg = of_device_get_match_data(dev); 133 + if (!cfg) 134 + return -EINVAL; 135 + priv->cfg = cfg; 136 + 137 + irq = platform_get_irq(pdev, 0); 138 + if (irq < 0) 139 + return irq; 140 + 141 + ret = devm_request_threaded_irq(dev, irq, mtk_adsp_mbox_irq, 142 + mtk_adsp_mbox_isr, IRQF_TRIGGER_NONE, 143 + dev_name(dev), mbox->chans); 144 + if (ret < 0) 145 + return ret; 146 + 147 + platform_set_drvdata(pdev, priv); 148 + 149 + return devm_mbox_controller_register(dev, &priv->mbox); 150 + } 151 + 152 + static const struct mtk_adsp_mbox_cfg mt8195_adsp_mbox_cfg = { 153 + .set_in = 0x00, 154 + .set_out = 0x1c, 155 + .clr_in = 0x04, 156 + .clr_out = 0x20, 157 + }; 158 + 159 + static const struct of_device_id mtk_adsp_mbox_of_match[] = { 160 + { .compatible = "mediatek,mt8195-adsp-mbox", .data = &mt8195_adsp_mbox_cfg }, 161 + {}, 162 + }; 163 + MODULE_DEVICE_TABLE(of, mtk_adsp_mbox_of_match); 164 + 165 + static struct platform_driver mtk_adsp_mbox_driver = { 166 + .probe = mtk_adsp_mbox_probe, 167 + .driver = { 168 + .name = "mtk_adsp_mbox", 169 + .of_match_table = mtk_adsp_mbox_of_match, 170 + }, 171 + }; 172 + module_platform_driver(mtk_adsp_mbox_driver); 173 + 174 + MODULE_AUTHOR("Allen-KH Cheng <Allen-KH.Cheng@mediatek.com>"); 175 + MODULE_DESCRIPTION("MTK ADSP Mailbox Controller"); 176 + MODULE_LICENSE("GPL v2");