mlxsw: spectrum: Set KVH XLT cache mode for Spectrum2/3
[linux-2.6-microblaze.git] / drivers / mailbox / mailbox-altera.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright Altera Corporation (C) 2013-2014. All rights reserved
4  */
5
6 #include <linux/device.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.h>
13 #include <linux/platform_device.h>
14
15 #define DRIVER_NAME     "altera-mailbox"
16
17 #define MAILBOX_CMD_REG                 0x00
18 #define MAILBOX_PTR_REG                 0x04
19 #define MAILBOX_STS_REG                 0x08
20 #define MAILBOX_INTMASK_REG             0x0C
21
22 #define INT_PENDING_MSK                 0x1
23 #define INT_SPACE_MSK                   0x2
24
25 #define STS_PENDING_MSK                 0x1
26 #define STS_FULL_MSK                    0x2
27 #define STS_FULL_OFT                    0x1
28
29 #define MBOX_PENDING(status)    (((status) & STS_PENDING_MSK))
30 #define MBOX_FULL(status)       (((status) & STS_FULL_MSK) >> STS_FULL_OFT)
31
32 enum altera_mbox_msg {
33         MBOX_CMD = 0,
34         MBOX_PTR,
35 };
36
37 #define MBOX_POLLING_MS         5       /* polling interval 5ms */
38
39 struct altera_mbox {
40         bool is_sender;         /* 1-sender, 0-receiver */
41         bool intr_mode;
42         int irq;
43         void __iomem *mbox_base;
44         struct device *dev;
45         struct mbox_controller controller;
46
47         /* If the controller supports only RX polling mode */
48         struct timer_list rxpoll_timer;
49         struct mbox_chan *chan;
50 };
51
52 static struct altera_mbox *mbox_chan_to_altera_mbox(struct mbox_chan *chan)
53 {
54         if (!chan || !chan->con_priv)
55                 return NULL;
56
57         return (struct altera_mbox *)chan->con_priv;
58 }
59
60 static inline int altera_mbox_full(struct altera_mbox *mbox)
61 {
62         u32 status;
63
64         status = readl_relaxed(mbox->mbox_base + MAILBOX_STS_REG);
65         return MBOX_FULL(status);
66 }
67
68 static inline int altera_mbox_pending(struct altera_mbox *mbox)
69 {
70         u32 status;
71
72         status = readl_relaxed(mbox->mbox_base + MAILBOX_STS_REG);
73         return MBOX_PENDING(status);
74 }
75
76 static void altera_mbox_rx_intmask(struct altera_mbox *mbox, bool enable)
77 {
78         u32 mask;
79
80         mask = readl_relaxed(mbox->mbox_base + MAILBOX_INTMASK_REG);
81         if (enable)
82                 mask |= INT_PENDING_MSK;
83         else
84                 mask &= ~INT_PENDING_MSK;
85         writel_relaxed(mask, mbox->mbox_base + MAILBOX_INTMASK_REG);
86 }
87
88 static void altera_mbox_tx_intmask(struct altera_mbox *mbox, bool enable)
89 {
90         u32 mask;
91
92         mask = readl_relaxed(mbox->mbox_base + MAILBOX_INTMASK_REG);
93         if (enable)
94                 mask |= INT_SPACE_MSK;
95         else
96                 mask &= ~INT_SPACE_MSK;
97         writel_relaxed(mask, mbox->mbox_base + MAILBOX_INTMASK_REG);
98 }
99
100 static bool altera_mbox_is_sender(struct altera_mbox *mbox)
101 {
102         u32 reg;
103         /* Write a magic number to PTR register and read back this register.
104          * This register is read-write if it is a sender.
105          */
106         #define MBOX_MAGIC      0xA5A5AA55
107         writel_relaxed(MBOX_MAGIC, mbox->mbox_base + MAILBOX_PTR_REG);
108         reg = readl_relaxed(mbox->mbox_base + MAILBOX_PTR_REG);
109         if (reg == MBOX_MAGIC) {
110                 /* Clear to 0 */
111                 writel_relaxed(0, mbox->mbox_base + MAILBOX_PTR_REG);
112                 return true;
113         }
114         return false;
115 }
116
117 static void altera_mbox_rx_data(struct mbox_chan *chan)
118 {
119         struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
120         u32 data[2];
121
122         if (altera_mbox_pending(mbox)) {
123                 data[MBOX_PTR] =
124                         readl_relaxed(mbox->mbox_base + MAILBOX_PTR_REG);
125                 data[MBOX_CMD] =
126                         readl_relaxed(mbox->mbox_base + MAILBOX_CMD_REG);
127                 mbox_chan_received_data(chan, (void *)data);
128         }
129 }
130
131 static void altera_mbox_poll_rx(struct timer_list *t)
132 {
133         struct altera_mbox *mbox = from_timer(mbox, t, rxpoll_timer);
134
135         altera_mbox_rx_data(mbox->chan);
136
137         mod_timer(&mbox->rxpoll_timer,
138                   jiffies + msecs_to_jiffies(MBOX_POLLING_MS));
139 }
140
141 static irqreturn_t altera_mbox_tx_interrupt(int irq, void *p)
142 {
143         struct mbox_chan *chan = (struct mbox_chan *)p;
144         struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
145
146         altera_mbox_tx_intmask(mbox, false);
147         mbox_chan_txdone(chan, 0);
148
149         return IRQ_HANDLED;
150 }
151
152 static irqreturn_t altera_mbox_rx_interrupt(int irq, void *p)
153 {
154         struct mbox_chan *chan = (struct mbox_chan *)p;
155
156         altera_mbox_rx_data(chan);
157         return IRQ_HANDLED;
158 }
159
160 static int altera_mbox_startup_sender(struct mbox_chan *chan)
161 {
162         int ret;
163         struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
164
165         if (mbox->intr_mode) {
166                 ret = request_irq(mbox->irq, altera_mbox_tx_interrupt, 0,
167                                   DRIVER_NAME, chan);
168                 if (unlikely(ret)) {
169                         dev_err(mbox->dev,
170                                 "failed to register mailbox interrupt:%d\n",
171                                 ret);
172                         return ret;
173                 }
174         }
175
176         return 0;
177 }
178
179 static int altera_mbox_startup_receiver(struct mbox_chan *chan)
180 {
181         int ret;
182         struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
183
184         if (mbox->intr_mode) {
185                 ret = request_irq(mbox->irq, altera_mbox_rx_interrupt, 0,
186                                   DRIVER_NAME, chan);
187                 if (unlikely(ret)) {
188                         mbox->intr_mode = false;
189                         goto polling; /* use polling if failed */
190                 }
191
192                 altera_mbox_rx_intmask(mbox, true);
193                 return 0;
194         }
195
196 polling:
197         /* Setup polling timer */
198         mbox->chan = chan;
199         timer_setup(&mbox->rxpoll_timer, altera_mbox_poll_rx, 0);
200         mod_timer(&mbox->rxpoll_timer,
201                   jiffies + msecs_to_jiffies(MBOX_POLLING_MS));
202
203         return 0;
204 }
205
206 static int altera_mbox_send_data(struct mbox_chan *chan, void *data)
207 {
208         struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
209         u32 *udata = (u32 *)data;
210
211         if (!mbox || !data)
212                 return -EINVAL;
213         if (!mbox->is_sender) {
214                 dev_warn(mbox->dev,
215                          "failed to send. This is receiver mailbox.\n");
216                 return -EINVAL;
217         }
218
219         if (altera_mbox_full(mbox))
220                 return -EBUSY;
221
222         /* Enable interrupt before send */
223         if (mbox->intr_mode)
224                 altera_mbox_tx_intmask(mbox, true);
225
226         /* Pointer register must write before command register */
227         writel_relaxed(udata[MBOX_PTR], mbox->mbox_base + MAILBOX_PTR_REG);
228         writel_relaxed(udata[MBOX_CMD], mbox->mbox_base + MAILBOX_CMD_REG);
229
230         return 0;
231 }
232
233 static bool altera_mbox_last_tx_done(struct mbox_chan *chan)
234 {
235         struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
236
237         /* Return false if mailbox is full */
238         return altera_mbox_full(mbox) ? false : true;
239 }
240
241 static bool altera_mbox_peek_data(struct mbox_chan *chan)
242 {
243         struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
244
245         return altera_mbox_pending(mbox) ? true : false;
246 }
247
248 static int altera_mbox_startup(struct mbox_chan *chan)
249 {
250         struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
251         int ret = 0;
252
253         if (!mbox)
254                 return -EINVAL;
255
256         if (mbox->is_sender)
257                 ret = altera_mbox_startup_sender(chan);
258         else
259                 ret = altera_mbox_startup_receiver(chan);
260
261         return ret;
262 }
263
264 static void altera_mbox_shutdown(struct mbox_chan *chan)
265 {
266         struct altera_mbox *mbox = mbox_chan_to_altera_mbox(chan);
267
268         if (mbox->intr_mode) {
269                 /* Unmask all interrupt masks */
270                 writel_relaxed(~0, mbox->mbox_base + MAILBOX_INTMASK_REG);
271                 free_irq(mbox->irq, chan);
272         } else if (!mbox->is_sender) {
273                 del_timer_sync(&mbox->rxpoll_timer);
274         }
275 }
276
277 static const struct mbox_chan_ops altera_mbox_ops = {
278         .send_data = altera_mbox_send_data,
279         .startup = altera_mbox_startup,
280         .shutdown = altera_mbox_shutdown,
281         .last_tx_done = altera_mbox_last_tx_done,
282         .peek_data = altera_mbox_peek_data,
283 };
284
285 static int altera_mbox_probe(struct platform_device *pdev)
286 {
287         struct altera_mbox *mbox;
288         struct resource *regs;
289         struct mbox_chan *chans;
290         int ret;
291
292         mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox),
293                             GFP_KERNEL);
294         if (!mbox)
295                 return -ENOMEM;
296
297         /* Allocated one channel */
298         chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL);
299         if (!chans)
300                 return -ENOMEM;
301
302         regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
303
304         mbox->mbox_base = devm_ioremap_resource(&pdev->dev, regs);
305         if (IS_ERR(mbox->mbox_base))
306                 return PTR_ERR(mbox->mbox_base);
307
308         /* Check is it a sender or receiver? */
309         mbox->is_sender = altera_mbox_is_sender(mbox);
310
311         mbox->irq = platform_get_irq(pdev, 0);
312         if (mbox->irq >= 0)
313                 mbox->intr_mode = true;
314
315         mbox->dev = &pdev->dev;
316
317         /* Hardware supports only one channel. */
318         chans[0].con_priv = mbox;
319         mbox->controller.dev = mbox->dev;
320         mbox->controller.num_chans = 1;
321         mbox->controller.chans = chans;
322         mbox->controller.ops = &altera_mbox_ops;
323
324         if (mbox->is_sender) {
325                 if (mbox->intr_mode) {
326                         mbox->controller.txdone_irq = true;
327                 } else {
328                         mbox->controller.txdone_poll = true;
329                         mbox->controller.txpoll_period = MBOX_POLLING_MS;
330                 }
331         }
332
333         ret = devm_mbox_controller_register(&pdev->dev, &mbox->controller);
334         if (ret) {
335                 dev_err(&pdev->dev, "Register mailbox failed\n");
336                 goto err;
337         }
338
339         platform_set_drvdata(pdev, mbox);
340 err:
341         return ret;
342 }
343
344 static const struct of_device_id altera_mbox_match[] = {
345         { .compatible = "altr,mailbox-1.0" },
346         { /* Sentinel */ }
347 };
348
349 MODULE_DEVICE_TABLE(of, altera_mbox_match);
350
351 static struct platform_driver altera_mbox_driver = {
352         .probe  = altera_mbox_probe,
353         .driver = {
354                 .name   = DRIVER_NAME,
355                 .of_match_table = altera_mbox_match,
356         },
357 };
358
359 module_platform_driver(altera_mbox_driver);
360
361 MODULE_LICENSE("GPL v2");
362 MODULE_DESCRIPTION("Altera mailbox specific functions");
363 MODULE_AUTHOR("Ley Foon Tan <lftan@altera.com>");
364 MODULE_ALIAS("platform:altera-mailbox");