1 /*********************************Copyright (c)*********************************************
5 **-------------------------------file info-------------------------------------------------
7 ** Filename: starfive_mailbox.c
8 ** Creator: shanlong.li
10 ** Description: starfive mailbox for e24
12 **-------------------------------history----------------------------------------------
18 ** ----------------------------------------------------------------------------------------
19 ******************************************************************************************/
21 #include <linux/bitops.h>
22 #include <linux/delay.h>
23 #include <linux/device.h>
24 #include <linux/err.h>
25 #include <linux/interrupt.h>
27 #include <linux/iopoll.h>
28 #include <linux/mailbox_controller.h>
29 #include <linux/module.h>
30 #include <linux/platform_device.h>
31 #include <linux/slab.h>
35 #define MBOX_CHAN_MAX 4
37 #define MBOX_BASE(mbox, ch) ((mbox)->base + ((ch) * 0x10))
38 #define MBOX_IRQ_REG 0x00
39 #define MBOX_SET_REG 0x04
40 #define MBOX_CLR_REG 0x08
41 #define MBOX_CMD_REG 0x0c
42 #define MBC_PEND_SMRY 0x100
44 static int mbox_init = 1;
45 module_param(mbox_init, int, 0644);
46 MODULE_PARM_DESC(mbox_init, "mbox_init on command.");
48 static void saif_clear_rst (void __iomem* addr,void __iomem* addr_status,uint32_t mask){
54 tmp = readl(addr_status);
55 }while((tmp&mask)!=mask);
58 static void saif_set_reg(void __iomem* addr,uint32_t data,uint32_t shift,uint32_t mask){
62 tmp |= (data<<shift) & mask;
66 #define _ENABLE_CLOCK_CLK_U0_MAILBOX_CLK_APB_(base) { \
67 void __iomem* clock_clk_mbox_addr = base + 0x1c4; \
68 uint32_t _clk_mbox_enable_data = 1; \
69 uint32_t _clk_mbox_enable_shift = 31; \
70 uint32_t _clk_mbox_enable_mask = 0x80000000U; \
71 saif_set_reg(clock_clk_mbox_addr,_clk_mbox_enable_data,_clk_mbox_enable_shift,_clk_mbox_enable_mask); \
74 #define _CLEAR_RESET_RSTGEN_RSTN_U0_MAILBOX_PRESETN_(base) { \
75 void __iomem* rstgen_mbox_addr = base + 0x300; \
76 void __iomem* rstgen_mbox_status0_addr = base + 0x310; \
77 uint32_t rstgen_mbox_mask = (0x1 << 4); \
78 saif_clear_rst(rstgen_mbox_addr,rstgen_mbox_status0_addr,rstgen_mbox_mask); \
89 struct mailbox_irq_name_c{
94 static const struct mailbox_irq_name_c irq_peer_name[MBOX_CHAN_MAX] = {
95 {MAILBOX_CORE_U7, "u74_core"},
96 {MAILBOX_CORE_HIFI4, "hifi4_core"},
97 {MAILBOX_CORE_E2, "e24_core"},
98 {MAILBOX_CORE_RSVD0, "" },
102 * starfive mailbox channel information
104 * A channel can be used for TX or RX, it can trigger remote
105 * processor interrupt to notify remote processor and can receive
106 * interrupt if has incoming message.
108 * @dst_irq: Interrupt vector for remote processor
109 * @core_id: id for remote processor
111 struct starfive_chan_info {
112 unsigned int dst_irq;
113 mailbox_core_t core_id;
117 * starfive mailbox controller data
119 * Mailbox controller includes 4 channels and can allocate
120 * channel for message transferring.
122 * @dev: Device to which it is attached
123 * @base: Base address of the register mapping region
124 * @chan: Representation of channels in mailbox controller
125 * @mchan: Representation of channel info
126 * @controller: Representation of a communication channel controller
128 struct starfive_mbox {
131 struct mbox_chan chan[MBOX_CHAN_MAX];
132 struct starfive_chan_info mchan[MBOX_CHAN_MAX];
133 struct mbox_controller controller;
136 static struct starfive_mbox *to_starfive_mbox(struct mbox_controller *mbox){
137 return container_of(mbox, struct starfive_mbox, controller);
140 static struct mbox_chan *
141 starfive_of_mbox_index_xlate(struct mbox_controller *mbox,
142 const struct of_phandle_args *sp){
143 int ind = sp->args[0];
144 int core_id = sp->args[1];
146 if (ind >= mbox->num_chans || core_id >= MAILBOX_CORE_NUM)
147 return ERR_PTR(-EINVAL);
149 struct starfive_mbox *sbox = to_starfive_mbox(mbox);
150 sbox->mchan[ind].core_id = core_id;
152 return &mbox->chans[ind];
155 static irqreturn_t starfive_rx_irq_handler(int irq, void *p){
156 struct mbox_chan *chan = p;
157 unsigned long ch = (unsigned long)chan->con_priv;
158 struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
159 void __iomem *base = MBOX_BASE(mbox, ch);
162 val = readl(base + MBOX_CMD_REG);
166 mbox_chan_received_data(chan, (void *)&val);
167 writel(val, base + MBOX_CLR_REG);
171 static int starfive_mbox_check_state(struct mbox_chan *chan){
172 unsigned long ch = (unsigned long)chan->con_priv;
173 struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
174 void __iomem *base = MBOX_BASE(mbox, ch);
177 /* Mailbox is idle so directly bail out */
178 if (readl(mbox->base + MBC_PEND_SMRY) & BIT(ch))
181 /* Ensure channel is released */
182 // writel(0x0, base + MBOX_IRQ_REG);
183 // writel(0x0, base + MBOX_CLR_REG);
185 if(mbox->mchan[ch].dst_irq > 0){
186 dev_dbg(mbox->dev, "%s: host IRQ = %d, ch:%d",__func__, mbox->mchan[ch].dst_irq,ch);
187 ret = devm_request_irq(mbox->dev, mbox->mchan[ch].dst_irq, starfive_rx_irq_handler,
188 IRQF_SHARED, irq_peer_name[ch].name, chan);
190 dev_err(mbox->dev, "request_irq %d failed\n", mbox->mchan[ch].dst_irq);
197 static int starfive_mbox_startup(struct mbox_chan *chan){
198 return starfive_mbox_check_state(chan);
201 static void starfive_mbox_shutdown(struct mbox_chan *chan){
202 struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
203 unsigned long ch = (unsigned long)chan->con_priv;
204 void __iomem *base = MBOX_BASE(mbox, ch);
206 writel(0x0, base + MBOX_IRQ_REG);
207 writel(0x0, base + MBOX_CLR_REG);
209 if(mbox->mchan[ch].dst_irq > 0){
210 devm_free_irq(mbox->dev,mbox->mchan[ch].dst_irq, chan);
214 static int starfive_mbox_send_data(struct mbox_chan *chan, void *msg){
215 unsigned long ch = (unsigned long)chan->con_priv;
216 struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
217 struct starfive_chan_info *mchan = &mbox->mchan[ch];
218 void __iomem *base = MBOX_BASE(mbox, ch);
221 /* Ensure channel is released */
222 if (readl(mbox->base + MBC_PEND_SMRY) & BIT(ch)){
223 pr_debug("%s:%d. busy\n",__func__,__LINE__);
227 /* Clear mask for destination interrupt */
228 writel(BIT(mchan->core_id), base + MBOX_IRQ_REG);
230 /* Fill message data */
231 writel(*buf, base + MBOX_SET_REG);
235 static struct mbox_chan_ops starfive_mbox_ops = {
236 .startup = starfive_mbox_startup,
237 .send_data = starfive_mbox_send_data,
238 .shutdown = starfive_mbox_shutdown,
241 static const struct of_device_id starfive_mbox_of_match[] = {
242 { .compatible = "starfive,mail_box", },
246 MODULE_DEVICE_TABLE(of, starfive_mbox_of_match);
247 void __iomem *clk_apb_ctrl_addr;
249 void starfive_mailbox_init(void){
250 clk_apb_ctrl_addr = ioremap(0x13020000, 0x1000);
252 pr_debug("%s:.\n",__func__);
253 _ENABLE_CLOCK_CLK_U0_MAILBOX_CLK_APB_(clk_apb_ctrl_addr);
254 _CLEAR_RESET_RSTGEN_RSTN_U0_MAILBOX_PRESETN_(clk_apb_ctrl_addr);
257 static int starfive_mbox_probe(struct platform_device *pdev){
258 struct device *dev = &pdev->dev;
259 struct starfive_mbox *mbox;
260 struct mbox_chan *chan;
261 struct resource *res;
265 mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
269 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
270 mbox->base = devm_ioremap_resource(dev, res);
272 if (IS_ERR(mbox->base))
273 return PTR_ERR(mbox->base);
276 starfive_mailbox_init();
279 mbox->controller.dev = dev;
280 mbox->controller.chans = mbox->chan;
281 mbox->controller.num_chans = MBOX_CHAN_MAX;
282 mbox->controller.ops = &starfive_mbox_ops;
283 mbox->controller.of_xlate = starfive_of_mbox_index_xlate;
284 mbox->controller.txdone_irq = true;
285 mbox->controller.txdone_poll = false;
287 /* Initialize mailbox channel data */
289 for(ch = 0;ch < MBOX_CHAN_MAX;ch++){
290 mbox->mchan[ch].dst_irq = 0;
291 mbox->mchan[ch].core_id = (mailbox_core_t)ch;
292 chan[ch].con_priv = (void *)ch;
294 mbox->mchan[MAILBOX_CORE_HIFI4].dst_irq = platform_get_irq(pdev, 0);
295 mbox->mchan[MAILBOX_CORE_E2].dst_irq = platform_get_irq(pdev, 1);
297 err = mbox_controller_register(&mbox->controller);
299 dev_err(dev, "Failed to register mailbox %d\n", err);
303 platform_set_drvdata(pdev, mbox);
304 dev_info(dev, "Mailbox enabled\n");
308 static int starfive_mbox_remove(struct platform_device *pdev){
309 struct starfive_mbox *mbox = platform_get_drvdata(pdev);
311 mbox_controller_unregister(&mbox->controller);
312 if(clk_apb_ctrl_addr)
313 iounmap(clk_apb_ctrl_addr);
317 static struct platform_driver starfive_mbox_driver = {
318 .probe = starfive_mbox_probe,
319 .remove = starfive_mbox_remove,
322 .of_match_table = starfive_mbox_of_match,
326 static int __init starfive_mbox_init(void){
327 return platform_driver_register(&starfive_mbox_driver);
329 core_initcall(starfive_mbox_init);
331 static void __exit starfive_mbox_exit(void){
332 platform_driver_unregister(&starfive_mbox_driver);
334 module_exit(starfive_mbox_exit);
336 MODULE_LICENSE("GPL");
337 MODULE_DESCRIPTION("StarFive Mailbox Controller");
338 MODULE_AUTHOR("StarFive Technology Co. Ltd.");