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