e2884a114e98daa05c2bd99aa08db0cc2864d031
[platform/kernel/linux-starfive.git] / drivers / mailbox / starfive_mailbox.c
1 /*********************************Copyright (c)*********************************************
2  **
3  **
4  **
5  **-------------------------------file info-------------------------------------------------
6  ** Vrsions:      V1.0
7  ** Filename:     starfive_mailbox.c
8  ** Creator:      shanlong.li
9  ** Date:         2021/06/07
10  ** Description:  starfive mailbox for e24
11  **
12  **-------------------------------history----------------------------------------------
13  ** Name:         shanlong.li
14  ** Versions:     V1.0
15  ** Date:         2021/06/07
16  ** Description:     
17  **
18  ** ----------------------------------------------------------------------------------------
19  ******************************************************************************************/
20
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>
26 #include <linux/io.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>
32
33 #include "mailbox.h"
34
35 #define MBOX_CHAN_MAX           4
36
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
43
44 static int mbox_init = 1;
45 module_param(mbox_init, int, 0644);
46 MODULE_PARM_DESC(mbox_init, "mbox_init on command.");
47
48 static void saif_clear_rst (void __iomem* addr,void __iomem* addr_status,uint32_t mask){
49     uint32_t tmp;
50     tmp = readl(addr);
51     tmp &= ~mask;
52     writel(tmp,addr);
53     do{
54         tmp = readl(addr_status);
55     }while((tmp&mask)!=mask);
56 }
57
58 static void saif_set_reg(void __iomem* addr,uint32_t data,uint32_t shift,uint32_t mask){
59     uint32_t tmp;
60     tmp = readl(addr);
61     tmp &= ~mask;
62     tmp |= (data<<shift) & mask;
63     writel(tmp,addr);
64 }
65
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); \
72 }
73
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); \
79 }
80
81 typedef enum{
82     MAILBOX_CORE_U7 = 0,
83     MAILBOX_CORE_HIFI4,
84     MAILBOX_CORE_E2,
85     MAILBOX_CORE_RSVD0,
86     MAILBOX_CORE_NUM,
87 } mailbox_core_t;
88
89 struct mailbox_irq_name_c{
90     int id;
91     char name[16];
92 };
93
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, "" },
99 };
100
101 /**
102  * starfive mailbox channel information
103  *
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.
107  *
108  * @dst_irq:    Interrupt vector for remote processor
109  * @core_id:    id for remote processor
110  */
111 struct starfive_chan_info {
112     unsigned int dst_irq;
113     mailbox_core_t core_id;
114 };
115
116 /**
117  * starfive mailbox controller data
118  *
119  * Mailbox controller includes 4 channels and can allocate
120  * channel for message transferring.
121  *
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
127  */
128 struct starfive_mbox {
129     struct device *dev;
130     void __iomem *base;
131     struct mbox_chan chan[MBOX_CHAN_MAX];
132     struct starfive_chan_info mchan[MBOX_CHAN_MAX];
133     struct mbox_controller controller;
134 };
135
136 static struct starfive_mbox *to_starfive_mbox(struct mbox_controller *mbox){
137     return container_of(mbox, struct starfive_mbox, controller);
138 }
139
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];
145
146     if (ind >= mbox->num_chans || core_id >= MAILBOX_CORE_NUM)
147         return ERR_PTR(-EINVAL);
148
149     struct starfive_mbox *sbox = to_starfive_mbox(mbox);
150     sbox->mchan[ind].core_id = core_id;
151
152     return &mbox->chans[ind];
153 }
154
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);
160     u32 val;
161
162     val = readl(base + MBOX_CMD_REG);
163     if (!val)
164         return IRQ_NONE;
165
166     mbox_chan_received_data(chan, (void *)&val);
167     writel(val, base + MBOX_CLR_REG);
168     return IRQ_HANDLED;
169 }
170
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);
175     long ret = 0;
176
177     /* Mailbox is idle so directly bail out */
178     if (readl(mbox->base + MBC_PEND_SMRY) & BIT(ch))
179         return -EBUSY;
180
181     /* Ensure channel is released */
182 //    writel(0x0, base + MBOX_IRQ_REG);
183 //    writel(0x0, base + MBOX_CLR_REG);
184
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);
189         if (ret < 0) {
190             dev_err(mbox->dev, "request_irq %d failed\n", mbox->mchan[ch].dst_irq);
191         }
192     }
193
194     return ret;
195 }
196
197 static int starfive_mbox_startup(struct mbox_chan *chan){
198     return starfive_mbox_check_state(chan);
199 }
200
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);
205
206     writel(0x0, base + MBOX_IRQ_REG);
207     writel(0x0, base + MBOX_CLR_REG);
208     
209     if(mbox->mchan[ch].dst_irq > 0){
210     devm_free_irq(mbox->dev,mbox->mchan[ch].dst_irq, chan);
211     }
212 }
213
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);
219     u32 *buf = msg;
220
221     /* Ensure channel is released */
222     if (readl(mbox->base + MBC_PEND_SMRY) & BIT(ch)){
223         pr_debug("%s:%d. busy\n",__func__,__LINE__);
224         return -EBUSY;
225     }
226
227     /* Clear mask for destination interrupt */
228     writel(BIT(mchan->core_id), base + MBOX_IRQ_REG);
229
230     /* Fill message data */
231     writel(*buf, base + MBOX_SET_REG);
232     return 0;
233 }
234
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,
239 };
240
241 static const struct of_device_id starfive_mbox_of_match[] = {
242     { .compatible = "starfive,mail_box", },
243     {},
244 };
245
246 MODULE_DEVICE_TABLE(of, starfive_mbox_of_match);
247 void __iomem *clk_apb_ctrl_addr;
248
249 void starfive_mailbox_init(void){
250     clk_apb_ctrl_addr = ioremap(0x13020000, 0x1000);
251
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);
255 }
256
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;
262     unsigned long ch;
263     int err;
264
265     mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
266     if (!mbox)
267         return -ENOMEM;
268
269     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
270     mbox->base = devm_ioremap_resource(dev, res);
271
272     if (IS_ERR(mbox->base))
273         return PTR_ERR(mbox->base);
274
275     if(mbox_init)
276         starfive_mailbox_init();
277     
278     mbox->dev = dev;
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;
286
287     /* Initialize mailbox channel data */
288     chan = mbox->chan;
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;
293     }
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);
296
297     err = mbox_controller_register(&mbox->controller);
298     if (err) {
299         dev_err(dev, "Failed to register mailbox %d\n", err);
300         return err;
301     }
302
303     platform_set_drvdata(pdev, mbox);
304     dev_info(dev, "Mailbox enabled\n");
305     return 0;
306 }
307
308 static int starfive_mbox_remove(struct platform_device *pdev){
309     struct starfive_mbox *mbox = platform_get_drvdata(pdev);
310
311     mbox_controller_unregister(&mbox->controller);
312     if(clk_apb_ctrl_addr)
313         iounmap(clk_apb_ctrl_addr);
314     return 0;
315 }
316
317 static struct platform_driver starfive_mbox_driver = {
318     .probe  = starfive_mbox_probe,
319     .remove = starfive_mbox_remove,
320     .driver = {
321         .name = "mailbox",
322         .of_match_table = starfive_mbox_of_match,
323     },
324 };
325
326 static int __init starfive_mbox_init(void){
327     return platform_driver_register(&starfive_mbox_driver);
328 }
329 core_initcall(starfive_mbox_init);
330
331 static void __exit starfive_mbox_exit(void){
332     platform_driver_unregister(&starfive_mbox_driver);
333 }
334 module_exit(starfive_mbox_exit);
335
336 MODULE_LICENSE("GPL");
337 MODULE_DESCRIPTION("StarFive Mailbox Controller");
338 MODULE_AUTHOR("StarFive Technology Co. Ltd.");