1 // SPDX-License-Identifier: GPL-2.0
2 /*********************************Copyright (c)*********************************************
4 **-------------------------------file info-------------------------------------------------
6 ** Filename: starfive_mailbox.c
7 ** Creator: shanlong.li
9 ** Description: starfive mailbox for e24
11 **-------------------------------history----------------------------------------------
17 ** ----------------------------------------------------------------------------------------
18 ******************************************************************************************/
20 #include <linux/bitops.h>
21 #include <linux/delay.h>
22 #include <linux/device.h>
23 #include <linux/err.h>
24 #include <linux/interrupt.h>
26 #include <linux/iopoll.h>
27 #include <linux/mailbox_controller.h>
28 #include <linux/module.h>
29 #include <linux/platform_device.h>
30 #include <linux/slab.h>
31 #include <linux/clk.h>
32 #include <linux/reset.h>
33 #include <linux/pm_runtime.h>
37 #define MBOX_CHAN_MAX 4
39 #define MBOX_BASE(mbox, ch) ((mbox)->base + ((ch) * 0x10))
40 #define MBOX_IRQ_REG 0x00
41 #define MBOX_SET_REG 0x04
42 #define MBOX_CLR_REG 0x08
43 #define MBOX_CMD_REG 0x0c
44 #define MBC_PEND_SMRY 0x100
54 struct mailbox_irq_name_c{
59 static const struct mailbox_irq_name_c irq_peer_name[MBOX_CHAN_MAX] = {
60 {MAILBOX_CORE_U7, "u74_core"},
61 {MAILBOX_CORE_HIFI4, "hifi4_core"},
62 {MAILBOX_CORE_E2, "e24_core"},
63 {MAILBOX_CORE_RSVD0, "" },
67 * starfive mailbox channel information
69 * A channel can be used for TX or RX, it can trigger remote
70 * processor interrupt to notify remote processor and can receive
71 * interrupt if has incoming message.
73 * @dst_irq: Interrupt vector for remote processor
74 * @core_id: id for remote processor
76 struct starfive_chan_info {
78 mailbox_core_t core_id;
82 * starfive mailbox controller data
84 * Mailbox controller includes 4 channels and can allocate
85 * channel for message transferring.
87 * @dev: Device to which it is attached
88 * @base: Base address of the register mapping region
89 * @chan: Representation of channels in mailbox controller
90 * @mchan: Representation of channel info
91 * @controller: Representation of a communication channel controller
93 struct starfive_mbox {
96 struct mbox_chan chan[MBOX_CHAN_MAX];
97 struct starfive_chan_info mchan[MBOX_CHAN_MAX];
98 struct mbox_controller controller;
100 struct reset_control *rst_rresetn;
103 static struct starfive_mbox *to_starfive_mbox(struct mbox_controller *mbox)
105 return container_of(mbox, struct starfive_mbox, controller);
108 static struct mbox_chan *
109 starfive_of_mbox_index_xlate(struct mbox_controller *mbox,
110 const struct of_phandle_args *sp)
112 struct starfive_mbox *sbox;
114 int ind = sp->args[0];
115 int core_id = sp->args[1];
117 if (ind >= mbox->num_chans || core_id >= MAILBOX_CORE_NUM)
118 return ERR_PTR(-EINVAL);
120 sbox = to_starfive_mbox(mbox);
122 sbox->mchan[ind].core_id = core_id;
124 return &mbox->chans[ind];
127 static irqreturn_t starfive_rx_irq_handler(int irq, void *p)
129 struct mbox_chan *chan = p;
130 unsigned long ch = (unsigned long)chan->con_priv;
131 struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
132 void __iomem *base = MBOX_BASE(mbox, ch);
135 val = readl(base + MBOX_CMD_REG);
139 mbox_chan_received_data(chan, (void *)&val);
140 writel(val, base + MBOX_CLR_REG);
144 static int starfive_mbox_check_state(struct mbox_chan *chan)
146 unsigned long ch = (unsigned long)chan->con_priv;
147 struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
148 unsigned long irq_flag = IRQF_SHARED;
151 pm_runtime_get_sync(mbox->dev);
152 /* MAILBOX should be with IRQF_NO_SUSPEND set */
153 if (!mbox->dev->pm_domain)
154 irq_flag |= IRQF_NO_SUSPEND;
156 /* Mailbox is idle so directly bail out */
157 if (readl(mbox->base + MBC_PEND_SMRY) & BIT(ch))
160 if (mbox->mchan[ch].dst_irq > 0) {
161 dev_dbg(mbox->dev, "%s: host IRQ = %d, ch:%ld", __func__, mbox->mchan[ch].dst_irq, ch);
162 ret = devm_request_irq(mbox->dev, mbox->mchan[ch].dst_irq, starfive_rx_irq_handler,
163 irq_flag, irq_peer_name[ch].name, chan);
165 dev_err(mbox->dev, "request_irq %d failed\n", mbox->mchan[ch].dst_irq);
171 static int starfive_mbox_startup(struct mbox_chan *chan)
173 return starfive_mbox_check_state(chan);
176 static void starfive_mbox_shutdown(struct mbox_chan *chan)
178 struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
179 unsigned long ch = (unsigned long)chan->con_priv;
180 void __iomem *base = MBOX_BASE(mbox, ch);
182 writel(0x0, base + MBOX_IRQ_REG);
183 writel(0x0, base + MBOX_CLR_REG);
185 if (mbox->mchan[ch].dst_irq > 0)
186 devm_free_irq(mbox->dev, mbox->mchan[ch].dst_irq, chan);
187 pm_runtime_put_sync(mbox->dev);
190 static int starfive_mbox_send_data(struct mbox_chan *chan, void *msg)
192 unsigned long ch = (unsigned long)chan->con_priv;
193 struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
194 struct starfive_chan_info *mchan = &mbox->mchan[ch];
195 void __iomem *base = MBOX_BASE(mbox, ch);
198 /* Ensure channel is released */
199 if (readl(mbox->base + MBC_PEND_SMRY) & BIT(ch)) {
200 pr_debug("%s:%d. busy\n", __func__, __LINE__);
204 /* Clear mask for destination interrupt */
205 writel(BIT(mchan->core_id), base + MBOX_IRQ_REG);
207 /* Fill message data */
208 writel(*buf, base + MBOX_SET_REG);
212 static struct mbox_chan_ops starfive_mbox_ops = {
213 .startup = starfive_mbox_startup,
214 .send_data = starfive_mbox_send_data,
215 .shutdown = starfive_mbox_shutdown,
218 static const struct of_device_id starfive_mbox_of_match[] = {
219 { .compatible = "starfive,mail_box",},
223 MODULE_DEVICE_TABLE(of, starfive_mbox_of_match);
225 void starfive_mailbox_init(struct starfive_mbox *mbox)
227 mbox->clk = devm_clk_get_optional(mbox->dev, "clk_apb");
228 if (IS_ERR(mbox->clk)) {
229 dev_err(mbox->dev, "failed to get mailbox\n");
233 mbox->rst_rresetn = devm_reset_control_get_exclusive(mbox->dev, "mbx_rre");
234 if (IS_ERR(mbox->rst_rresetn)) {
235 dev_err(mbox->dev, "failed to get mailbox reset\n");
239 clk_prepare_enable(mbox->clk);
240 reset_control_deassert(mbox->rst_rresetn);
243 static int starfive_mbox_probe(struct platform_device *pdev)
245 struct device *dev = &pdev->dev;
246 struct starfive_mbox *mbox;
247 struct mbox_chan *chan;
248 struct resource *res;
252 mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
256 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
257 mbox->base = devm_ioremap_resource(dev, res);
260 if (IS_ERR(mbox->base))
261 return PTR_ERR(mbox->base);
263 starfive_mailbox_init(mbox);
265 mbox->controller.dev = dev;
266 mbox->controller.chans = mbox->chan;
267 mbox->controller.num_chans = MBOX_CHAN_MAX;
268 mbox->controller.ops = &starfive_mbox_ops;
269 mbox->controller.of_xlate = starfive_of_mbox_index_xlate;
270 mbox->controller.txdone_irq = true;
271 mbox->controller.txdone_poll = false;
273 /* Initialize mailbox channel data */
275 for (ch = 0; ch < MBOX_CHAN_MAX; ch++) {
276 mbox->mchan[ch].dst_irq = 0;
277 mbox->mchan[ch].core_id = (mailbox_core_t)ch;
278 chan[ch].con_priv = (void *)ch;
280 mbox->mchan[MAILBOX_CORE_HIFI4].dst_irq = platform_get_irq(pdev, 0);
281 mbox->mchan[MAILBOX_CORE_E2].dst_irq = platform_get_irq(pdev, 1);
283 err = mbox_controller_register(&mbox->controller);
285 dev_err(dev, "Failed to register mailbox %d\n", err);
289 platform_set_drvdata(pdev, mbox);
290 dev_info(dev, "Mailbox enabled\n");
291 pm_runtime_set_active(dev);
292 pm_runtime_enable(dev);
297 static int starfive_mbox_remove(struct platform_device *pdev)
299 struct starfive_mbox *mbox = platform_get_drvdata(pdev);
301 mbox_controller_unregister(&mbox->controller);
302 devm_clk_put(mbox->dev, mbox->clk);
303 pm_runtime_disable(mbox->dev);
308 static int __maybe_unused starfive_mbox_suspend(struct device *dev)
310 struct starfive_mbox *mbox = dev_get_drvdata(dev);
312 clk_disable_unprepare(mbox->clk);
317 static int __maybe_unused starfive_mbox_resume(struct device *dev)
319 struct starfive_mbox *mbox = dev_get_drvdata(dev);
322 ret = clk_prepare_enable(mbox->clk);
324 dev_err(dev, "failed to enable clock\n");
329 static const struct dev_pm_ops starfive_mbox_pm_ops = {
330 .suspend = starfive_mbox_suspend,
331 .resume = starfive_mbox_resume,
332 SET_RUNTIME_PM_OPS(starfive_mbox_suspend, starfive_mbox_resume, NULL)
334 static struct platform_driver starfive_mbox_driver = {
335 .probe = starfive_mbox_probe,
336 .remove = starfive_mbox_remove,
339 .of_match_table = starfive_mbox_of_match,
340 .pm = &starfive_mbox_pm_ops,
344 static int __init starfive_mbox_init(void)
346 return platform_driver_register(&starfive_mbox_driver);
348 core_initcall(starfive_mbox_init);
350 static void __exit starfive_mbox_exit(void)
352 platform_driver_unregister(&starfive_mbox_driver);
354 module_exit(starfive_mbox_exit);
356 MODULE_LICENSE("GPL");
357 MODULE_DESCRIPTION("StarFive Mailbox Controller");
358 MODULE_AUTHOR("StarFive Technology Co. Ltd.");