df6c4ecd913ca8fe00867a0c1a0fd68501bc544d
[linux-2.6-microblaze.git] / drivers / mailbox / imx-mailbox.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
4  */
5
6 #include <linux/clk.h>
7 #include <linux/interrupt.h>
8 #include <linux/io.h>
9 #include <linux/kernel.h>
10 #include <linux/mailbox_controller.h>
11 #include <linux/module.h>
12 #include <linux/of_device.h>
13 #include <linux/slab.h>
14
15 #define IMX_MU_xSR_GIPn(x)      BIT(28 + (3 - (x)))
16 #define IMX_MU_xSR_RFn(x)       BIT(24 + (3 - (x)))
17 #define IMX_MU_xSR_TEn(x)       BIT(20 + (3 - (x)))
18 #define IMX_MU_xSR_BRDIP        BIT(9)
19
20 /* General Purpose Interrupt Enable */
21 #define IMX_MU_xCR_GIEn(x)      BIT(28 + (3 - (x)))
22 /* Receive Interrupt Enable */
23 #define IMX_MU_xCR_RIEn(x)      BIT(24 + (3 - (x)))
24 /* Transmit Interrupt Enable */
25 #define IMX_MU_xCR_TIEn(x)      BIT(20 + (3 - (x)))
26 /* General Purpose Interrupt Request */
27 #define IMX_MU_xCR_GIRn(x)      BIT(16 + (3 - (x)))
28
29 #define IMX_MU_CHANS            16
30 #define IMX_MU_CHAN_NAME_SIZE   20
31
32 enum imx_mu_chan_type {
33         IMX_MU_TYPE_TX,         /* Tx */
34         IMX_MU_TYPE_RX,         /* Rx */
35         IMX_MU_TYPE_TXDB,       /* Tx doorbell */
36         IMX_MU_TYPE_RXDB,       /* Rx doorbell */
37 };
38
39 struct imx_mu_con_priv {
40         unsigned int            idx;
41         char                    irq_desc[IMX_MU_CHAN_NAME_SIZE];
42         enum imx_mu_chan_type   type;
43         struct mbox_chan        *chan;
44         struct tasklet_struct   txdb_tasklet;
45 };
46
47 struct imx_mu_priv {
48         struct device           *dev;
49         void __iomem            *base;
50         spinlock_t              xcr_lock; /* control register lock */
51
52         struct mbox_controller  mbox;
53         struct mbox_chan        mbox_chans[IMX_MU_CHANS];
54
55         struct imx_mu_con_priv  con_priv[IMX_MU_CHANS];
56         const struct imx_mu_dcfg        *dcfg;
57         struct clk              *clk;
58         int                     irq;
59
60         bool                    side_b;
61 };
62
63 struct imx_mu_dcfg {
64         int (*tx)(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp, void *data);
65         int (*rx)(struct imx_mu_priv *priv, struct imx_mu_con_priv *cp);
66         void (*init)(struct imx_mu_priv *priv);
67         u32     xTR[4];         /* Transmit Registers */
68         u32     xRR[4];         /* Receive Registers */
69         u32     xSR;            /* Status Register */
70         u32     xCR;            /* Control Register */
71 };
72
73 static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
74 {
75         return container_of(mbox, struct imx_mu_priv, mbox);
76 }
77
78 static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
79 {
80         iowrite32(val, priv->base + offs);
81 }
82
83 static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
84 {
85         return ioread32(priv->base + offs);
86 }
87
88 static u32 imx_mu_xcr_rmw(struct imx_mu_priv *priv, u32 set, u32 clr)
89 {
90         unsigned long flags;
91         u32 val;
92
93         spin_lock_irqsave(&priv->xcr_lock, flags);
94         val = imx_mu_read(priv, priv->dcfg->xCR);
95         val &= ~clr;
96         val |= set;
97         imx_mu_write(priv, val, priv->dcfg->xCR);
98         spin_unlock_irqrestore(&priv->xcr_lock, flags);
99
100         return val;
101 }
102
103 static int imx_mu_generic_tx(struct imx_mu_priv *priv,
104                              struct imx_mu_con_priv *cp,
105                              void *data)
106 {
107         u32 *arg = data;
108
109         switch (cp->type) {
110         case IMX_MU_TYPE_TX:
111                 imx_mu_write(priv, *arg, priv->dcfg->xTR[cp->idx]);
112                 imx_mu_xcr_rmw(priv, IMX_MU_xCR_TIEn(cp->idx), 0);
113                 break;
114         case IMX_MU_TYPE_TXDB:
115                 imx_mu_xcr_rmw(priv, IMX_MU_xCR_GIRn(cp->idx), 0);
116                 tasklet_schedule(&cp->txdb_tasklet);
117                 break;
118         default:
119                 dev_warn_ratelimited(priv->dev, "Send data on wrong channel type: %d\n", cp->type);
120                 return -EINVAL;
121         }
122
123         return 0;
124 }
125
126 static int imx_mu_generic_rx(struct imx_mu_priv *priv,
127                              struct imx_mu_con_priv *cp)
128 {
129         u32 dat;
130
131         dat = imx_mu_read(priv, priv->dcfg->xRR[cp->idx]);
132         mbox_chan_received_data(cp->chan, (void *)&dat);
133
134         return 0;
135 }
136
137 static void imx_mu_txdb_tasklet(unsigned long data)
138 {
139         struct imx_mu_con_priv *cp = (struct imx_mu_con_priv *)data;
140
141         mbox_chan_txdone(cp->chan, 0);
142 }
143
144 static irqreturn_t imx_mu_isr(int irq, void *p)
145 {
146         struct mbox_chan *chan = p;
147         struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
148         struct imx_mu_con_priv *cp = chan->con_priv;
149         u32 val, ctrl;
150
151         ctrl = imx_mu_read(priv, priv->dcfg->xCR);
152         val = imx_mu_read(priv, priv->dcfg->xSR);
153
154         switch (cp->type) {
155         case IMX_MU_TYPE_TX:
156                 val &= IMX_MU_xSR_TEn(cp->idx) &
157                         (ctrl & IMX_MU_xCR_TIEn(cp->idx));
158                 break;
159         case IMX_MU_TYPE_RX:
160                 val &= IMX_MU_xSR_RFn(cp->idx) &
161                         (ctrl & IMX_MU_xCR_RIEn(cp->idx));
162                 break;
163         case IMX_MU_TYPE_RXDB:
164                 val &= IMX_MU_xSR_GIPn(cp->idx) &
165                         (ctrl & IMX_MU_xCR_GIEn(cp->idx));
166                 break;
167         default:
168                 break;
169         }
170
171         if (!val)
172                 return IRQ_NONE;
173
174         if (val == IMX_MU_xSR_TEn(cp->idx)) {
175                 imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_TIEn(cp->idx));
176                 mbox_chan_txdone(chan, 0);
177         } else if (val == IMX_MU_xSR_RFn(cp->idx)) {
178                 priv->dcfg->rx(priv, cp);
179         } else if (val == IMX_MU_xSR_GIPn(cp->idx)) {
180                 imx_mu_write(priv, IMX_MU_xSR_GIPn(cp->idx), priv->dcfg->xSR);
181                 mbox_chan_received_data(chan, NULL);
182         } else {
183                 dev_warn_ratelimited(priv->dev, "Not handled interrupt\n");
184                 return IRQ_NONE;
185         }
186
187         return IRQ_HANDLED;
188 }
189
190 static int imx_mu_send_data(struct mbox_chan *chan, void *data)
191 {
192         struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
193         struct imx_mu_con_priv *cp = chan->con_priv;
194
195         return priv->dcfg->tx(priv, cp, data);
196 }
197
198 static int imx_mu_startup(struct mbox_chan *chan)
199 {
200         struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
201         struct imx_mu_con_priv *cp = chan->con_priv;
202         int ret;
203
204         if (cp->type == IMX_MU_TYPE_TXDB) {
205                 /* Tx doorbell don't have ACK support */
206                 tasklet_init(&cp->txdb_tasklet, imx_mu_txdb_tasklet,
207                              (unsigned long)cp);
208                 return 0;
209         }
210
211         ret = request_irq(priv->irq, imx_mu_isr, IRQF_SHARED |
212                           IRQF_NO_SUSPEND, cp->irq_desc, chan);
213         if (ret) {
214                 dev_err(priv->dev,
215                         "Unable to acquire IRQ %d\n", priv->irq);
216                 return ret;
217         }
218
219         switch (cp->type) {
220         case IMX_MU_TYPE_RX:
221                 imx_mu_xcr_rmw(priv, IMX_MU_xCR_RIEn(cp->idx), 0);
222                 break;
223         case IMX_MU_TYPE_RXDB:
224                 imx_mu_xcr_rmw(priv, IMX_MU_xCR_GIEn(cp->idx), 0);
225                 break;
226         default:
227                 break;
228         }
229
230         return 0;
231 }
232
233 static void imx_mu_shutdown(struct mbox_chan *chan)
234 {
235         struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
236         struct imx_mu_con_priv *cp = chan->con_priv;
237
238         if (cp->type == IMX_MU_TYPE_TXDB) {
239                 tasklet_kill(&cp->txdb_tasklet);
240                 return;
241         }
242
243         switch (cp->type) {
244         case IMX_MU_TYPE_TX:
245                 imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_TIEn(cp->idx));
246                 break;
247         case IMX_MU_TYPE_RX:
248                 imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_RIEn(cp->idx));
249                 break;
250         case IMX_MU_TYPE_RXDB:
251                 imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_GIEn(cp->idx));
252                 break;
253         default:
254                 break;
255         }
256
257         free_irq(priv->irq, chan);
258 }
259
260 static const struct mbox_chan_ops imx_mu_ops = {
261         .send_data = imx_mu_send_data,
262         .startup = imx_mu_startup,
263         .shutdown = imx_mu_shutdown,
264 };
265
266 static struct mbox_chan * imx_mu_xlate(struct mbox_controller *mbox,
267                                        const struct of_phandle_args *sp)
268 {
269         u32 type, idx, chan;
270
271         if (sp->args_count != 2) {
272                 dev_err(mbox->dev, "Invalid argument count %d\n", sp->args_count);
273                 return ERR_PTR(-EINVAL);
274         }
275
276         type = sp->args[0]; /* channel type */
277         idx = sp->args[1]; /* index */
278         chan = type * 4 + idx;
279
280         if (chan >= mbox->num_chans) {
281                 dev_err(mbox->dev, "Not supported channel number: %d. (type: %d, idx: %d)\n", chan, type, idx);
282                 return ERR_PTR(-EINVAL);
283         }
284
285         return &mbox->chans[chan];
286 }
287
288 static void imx_mu_init_generic(struct imx_mu_priv *priv)
289 {
290         unsigned int i;
291
292         for (i = 0; i < IMX_MU_CHANS; i++) {
293                 struct imx_mu_con_priv *cp = &priv->con_priv[i];
294
295                 cp->idx = i % 4;
296                 cp->type = i >> 2;
297                 cp->chan = &priv->mbox_chans[i];
298                 priv->mbox_chans[i].con_priv = cp;
299                 snprintf(cp->irq_desc, sizeof(cp->irq_desc),
300                          "imx_mu_chan[%i-%i]", cp->type, cp->idx);
301         }
302
303         priv->mbox.num_chans = IMX_MU_CHANS;
304         priv->mbox.of_xlate = imx_mu_xlate;
305
306         if (priv->side_b)
307                 return;
308
309         /* Set default MU configuration */
310         imx_mu_write(priv, 0, priv->dcfg->xCR);
311 }
312
313 static int imx_mu_probe(struct platform_device *pdev)
314 {
315         struct device *dev = &pdev->dev;
316         struct device_node *np = dev->of_node;
317         struct imx_mu_priv *priv;
318         const struct imx_mu_dcfg *dcfg;
319         int ret;
320
321         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
322         if (!priv)
323                 return -ENOMEM;
324
325         priv->dev = dev;
326
327         priv->base = devm_platform_ioremap_resource(pdev, 0);
328         if (IS_ERR(priv->base))
329                 return PTR_ERR(priv->base);
330
331         priv->irq = platform_get_irq(pdev, 0);
332         if (priv->irq < 0)
333                 return priv->irq;
334
335         dcfg = of_device_get_match_data(dev);
336         if (!dcfg)
337                 return -EINVAL;
338         priv->dcfg = dcfg;
339
340         priv->clk = devm_clk_get(dev, NULL);
341         if (IS_ERR(priv->clk)) {
342                 if (PTR_ERR(priv->clk) != -ENOENT)
343                         return PTR_ERR(priv->clk);
344
345                 priv->clk = NULL;
346         }
347
348         ret = clk_prepare_enable(priv->clk);
349         if (ret) {
350                 dev_err(dev, "Failed to enable clock\n");
351                 return ret;
352         }
353
354         priv->side_b = of_property_read_bool(np, "fsl,mu-side-b");
355
356         priv->dcfg->init(priv);
357
358         spin_lock_init(&priv->xcr_lock);
359
360         priv->mbox.dev = dev;
361         priv->mbox.ops = &imx_mu_ops;
362         priv->mbox.chans = priv->mbox_chans;
363         priv->mbox.txdone_irq = true;
364
365         platform_set_drvdata(pdev, priv);
366
367         return devm_mbox_controller_register(dev, &priv->mbox);
368 }
369
370 static int imx_mu_remove(struct platform_device *pdev)
371 {
372         struct imx_mu_priv *priv = platform_get_drvdata(pdev);
373
374         clk_disable_unprepare(priv->clk);
375
376         return 0;
377 }
378
379 static const struct imx_mu_dcfg imx_mu_cfg_imx6sx = {
380         .tx     = imx_mu_generic_tx,
381         .rx     = imx_mu_generic_rx,
382         .init   = imx_mu_init_generic,
383         .xTR    = {0x0, 0x4, 0x8, 0xc},
384         .xRR    = {0x10, 0x14, 0x18, 0x1c},
385         .xSR    = 0x20,
386         .xCR    = 0x24,
387 };
388
389 static const struct imx_mu_dcfg imx_mu_cfg_imx7ulp = {
390         .tx     = imx_mu_generic_tx,
391         .rx     = imx_mu_generic_rx,
392         .init   = imx_mu_init_generic,
393         .xTR    = {0x20, 0x24, 0x28, 0x2c},
394         .xRR    = {0x40, 0x44, 0x48, 0x4c},
395         .xSR    = 0x60,
396         .xCR    = 0x64,
397 };
398
399 static const struct of_device_id imx_mu_dt_ids[] = {
400         { .compatible = "fsl,imx7ulp-mu", .data = &imx_mu_cfg_imx7ulp },
401         { .compatible = "fsl,imx6sx-mu", .data = &imx_mu_cfg_imx6sx },
402         { },
403 };
404 MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
405
406 static struct platform_driver imx_mu_driver = {
407         .probe          = imx_mu_probe,
408         .remove         = imx_mu_remove,
409         .driver = {
410                 .name   = "imx_mu",
411                 .of_match_table = imx_mu_dt_ids,
412         },
413 };
414 module_platform_driver(imx_mu_driver);
415
416 MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
417 MODULE_DESCRIPTION("Message Unit driver for i.MX");
418 MODULE_LICENSE("GPL v2");