Merge branch 'fix/hda' into for-linus
[pandora-kernel.git] / arch / arm / mach-ep93xx / dma-m2p.c
1 /*
2  * arch/arm/mach-ep93xx/dma-m2p.c
3  * M2P DMA handling for Cirrus EP93xx chips.
4  *
5  * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
6  * Copyright (C) 2006 Applied Data Systems
7  *
8  * Copyright (C) 2009 Ryan Mallon <ryan@bluewatersys.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or (at
13  * your option) any later version.
14  */
15
16 /*
17  * On the EP93xx chip the following peripherals my be allocated to the 10
18  * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
19  *
20  *      I2S     contains 3 Tx and 3 Rx DMA Channels
21  *      AAC     contains 3 Tx and 3 Rx DMA Channels
22  *      UART1   contains 1 Tx and 1 Rx DMA Channels
23  *      UART2   contains 1 Tx and 1 Rx DMA Channels
24  *      UART3   contains 1 Tx and 1 Rx DMA Channels
25  *      IrDA    contains 1 Tx and 1 Rx DMA Channels
26  *
27  * SSP and IDE use the Memory to Memory (M2M) channels and are not covered
28  * with this implementation.
29  */
30
31 #include <linux/kernel.h>
32 #include <linux/clk.h>
33 #include <linux/err.h>
34 #include <linux/interrupt.h>
35 #include <linux/module.h>
36 #include <linux/io.h>
37
38 #include <mach/dma.h>
39 #include <mach/hardware.h>
40
41 #define M2P_CONTROL                     0x00
42 #define  M2P_CONTROL_STALL_IRQ_EN       (1 << 0)
43 #define  M2P_CONTROL_NFB_IRQ_EN         (1 << 1)
44 #define  M2P_CONTROL_ERROR_IRQ_EN       (1 << 3)
45 #define  M2P_CONTROL_ENABLE             (1 << 4)
46 #define M2P_INTERRUPT                   0x04
47 #define  M2P_INTERRUPT_STALL            (1 << 0)
48 #define  M2P_INTERRUPT_NFB              (1 << 1)
49 #define  M2P_INTERRUPT_ERROR            (1 << 3)
50 #define M2P_PPALLOC                     0x08
51 #define M2P_STATUS                      0x0c
52 #define M2P_REMAIN                      0x14
53 #define M2P_MAXCNT0                     0x20
54 #define M2P_BASE0                       0x24
55 #define M2P_MAXCNT1                     0x30
56 #define M2P_BASE1                       0x34
57
58 #define STATE_IDLE      0       /* Channel is inactive.  */
59 #define STATE_STALL     1       /* Channel is active, no buffers pending.  */
60 #define STATE_ON        2       /* Channel is active, one buffer pending.  */
61 #define STATE_NEXT      3       /* Channel is active, two buffers pending.  */
62
63 struct m2p_channel {
64         char                            *name;
65         void __iomem                    *base;
66         int                             irq;
67
68         struct clk                      *clk;
69         spinlock_t                      lock;
70
71         void                            *client;
72         unsigned                        next_slot:1;
73         struct ep93xx_dma_buffer        *buffer_xfer;
74         struct ep93xx_dma_buffer        *buffer_next;
75         struct list_head                buffers_pending;
76 };
77
78 static struct m2p_channel m2p_rx[] = {
79         {"m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1},
80         {"m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3},
81         {"m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5},
82         {"m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7},
83         {"m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9},
84         {NULL},
85 };
86
87 static struct m2p_channel m2p_tx[] = {
88         {"m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0},
89         {"m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2},
90         {"m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4},
91         {"m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6},
92         {"m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8},
93         {NULL},
94 };
95
96 static void feed_buf(struct m2p_channel *ch, struct ep93xx_dma_buffer *buf)
97 {
98         if (ch->next_slot == 0) {
99                 writel(buf->size, ch->base + M2P_MAXCNT0);
100                 writel(buf->bus_addr, ch->base + M2P_BASE0);
101         } else {
102                 writel(buf->size, ch->base + M2P_MAXCNT1);
103                 writel(buf->bus_addr, ch->base + M2P_BASE1);
104         }
105         ch->next_slot ^= 1;
106 }
107
108 static void choose_buffer_xfer(struct m2p_channel *ch)
109 {
110         struct ep93xx_dma_buffer *buf;
111
112         ch->buffer_xfer = NULL;
113         if (!list_empty(&ch->buffers_pending)) {
114                 buf = list_entry(ch->buffers_pending.next,
115                                  struct ep93xx_dma_buffer, list);
116                 list_del(&buf->list);
117                 feed_buf(ch, buf);
118                 ch->buffer_xfer = buf;
119         }
120 }
121
122 static void choose_buffer_next(struct m2p_channel *ch)
123 {
124         struct ep93xx_dma_buffer *buf;
125
126         ch->buffer_next = NULL;
127         if (!list_empty(&ch->buffers_pending)) {
128                 buf = list_entry(ch->buffers_pending.next,
129                                  struct ep93xx_dma_buffer, list);
130                 list_del(&buf->list);
131                 feed_buf(ch, buf);
132                 ch->buffer_next = buf;
133         }
134 }
135
136 static inline void m2p_set_control(struct m2p_channel *ch, u32 v)
137 {
138         /*
139          * The control register must be read immediately after being written so
140          * that the internal state machine is correctly updated. See the ep93xx
141          * users' guide for details.
142          */
143         writel(v, ch->base + M2P_CONTROL);
144         readl(ch->base + M2P_CONTROL);
145 }
146
147 static inline int m2p_channel_state(struct m2p_channel *ch)
148 {
149         return (readl(ch->base + M2P_STATUS) >> 4) & 0x3;
150 }
151
152 static irqreturn_t m2p_irq(int irq, void *dev_id)
153 {
154         struct m2p_channel *ch = dev_id;
155         struct ep93xx_dma_m2p_client *cl;
156         u32 irq_status, v;
157         int error = 0;
158
159         cl = ch->client;
160
161         spin_lock(&ch->lock);
162         irq_status = readl(ch->base + M2P_INTERRUPT);
163
164         if (irq_status & M2P_INTERRUPT_ERROR) {
165                 writel(M2P_INTERRUPT_ERROR, ch->base + M2P_INTERRUPT);
166                 error = 1;
167         }
168
169         if ((irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)) == 0) {
170                 spin_unlock(&ch->lock);
171                 return IRQ_NONE;
172         }
173
174         switch (m2p_channel_state(ch)) {
175         case STATE_IDLE:
176                 pr_crit("m2p_irq: dma interrupt without a dma buffer\n");
177                 BUG();
178                 break;
179
180         case STATE_STALL:
181                 cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, error);
182                 if (ch->buffer_next != NULL) {
183                         cl->buffer_finished(cl->cookie, ch->buffer_next,
184                                             0, error);
185                 }
186                 choose_buffer_xfer(ch);
187                 choose_buffer_next(ch);
188                 if (ch->buffer_xfer != NULL)
189                         cl->buffer_started(cl->cookie, ch->buffer_xfer);
190                 break;
191
192         case STATE_ON:
193                 cl->buffer_finished(cl->cookie, ch->buffer_xfer, 0, error);
194                 ch->buffer_xfer = ch->buffer_next;
195                 choose_buffer_next(ch);
196                 cl->buffer_started(cl->cookie, ch->buffer_xfer);
197                 break;
198
199         case STATE_NEXT:
200                 pr_crit("m2p_irq: dma interrupt while next\n");
201                 BUG();
202                 break;
203         }
204
205         v = readl(ch->base + M2P_CONTROL) & ~(M2P_CONTROL_STALL_IRQ_EN |
206                                               M2P_CONTROL_NFB_IRQ_EN);
207         if (ch->buffer_xfer != NULL)
208                 v |= M2P_CONTROL_STALL_IRQ_EN;
209         if (ch->buffer_next != NULL)
210                 v |= M2P_CONTROL_NFB_IRQ_EN;
211         m2p_set_control(ch, v);
212
213         spin_unlock(&ch->lock);
214         return IRQ_HANDLED;
215 }
216
217 static struct m2p_channel *find_free_channel(struct ep93xx_dma_m2p_client *cl)
218 {
219         struct m2p_channel *ch;
220         int i;
221
222         if (cl->flags & EP93XX_DMA_M2P_RX)
223                 ch = m2p_rx;
224         else
225                 ch = m2p_tx;
226
227         for (i = 0; ch[i].base; i++) {
228                 struct ep93xx_dma_m2p_client *client;
229
230                 client = ch[i].client;
231                 if (client != NULL) {
232                         int port;
233
234                         port = cl->flags & EP93XX_DMA_M2P_PORT_MASK;
235                         if (port == (client->flags &
236                                      EP93XX_DMA_M2P_PORT_MASK)) {
237                                 pr_warning("DMA channel already used by %s\n",
238                                            cl->name ? : "unknown client");
239                                 return ERR_PTR(-EBUSY);
240                         }
241                 }
242         }
243
244         for (i = 0; ch[i].base; i++) {
245                 if (ch[i].client == NULL)
246                         return ch + i;
247         }
248
249         pr_warning("No free DMA channel for %s\n",
250                    cl->name ? : "unknown client");
251         return ERR_PTR(-ENODEV);
252 }
253
254 static void channel_enable(struct m2p_channel *ch)
255 {
256         struct ep93xx_dma_m2p_client *cl = ch->client;
257         u32 v;
258
259         clk_enable(ch->clk);
260
261         v = cl->flags & EP93XX_DMA_M2P_PORT_MASK;
262         writel(v, ch->base + M2P_PPALLOC);
263
264         v = cl->flags & EP93XX_DMA_M2P_ERROR_MASK;
265         v |= M2P_CONTROL_ENABLE | M2P_CONTROL_ERROR_IRQ_EN;
266         m2p_set_control(ch, v);
267 }
268
269 static void channel_disable(struct m2p_channel *ch)
270 {
271         u32 v;
272
273         v = readl(ch->base + M2P_CONTROL);
274         v &= ~(M2P_CONTROL_STALL_IRQ_EN | M2P_CONTROL_NFB_IRQ_EN);
275         m2p_set_control(ch, v);
276
277         while (m2p_channel_state(ch) == STATE_ON)
278                 cpu_relax();
279
280         m2p_set_control(ch, 0x0);
281
282         while (m2p_channel_state(ch) == STATE_STALL)
283                 cpu_relax();
284
285         clk_disable(ch->clk);
286 }
287
288 int ep93xx_dma_m2p_client_register(struct ep93xx_dma_m2p_client *cl)
289 {
290         struct m2p_channel *ch;
291         int err;
292
293         ch = find_free_channel(cl);
294         if (IS_ERR(ch))
295                 return PTR_ERR(ch);
296
297         err = request_irq(ch->irq, m2p_irq, 0, cl->name ? : "dma-m2p", ch);
298         if (err)
299                 return err;
300
301         ch->client = cl;
302         ch->next_slot = 0;
303         ch->buffer_xfer = NULL;
304         ch->buffer_next = NULL;
305         INIT_LIST_HEAD(&ch->buffers_pending);
306
307         cl->channel = ch;
308
309         channel_enable(ch);
310
311         return 0;
312 }
313 EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_client_register);
314
315 void ep93xx_dma_m2p_client_unregister(struct ep93xx_dma_m2p_client *cl)
316 {
317         struct m2p_channel *ch = cl->channel;
318
319         channel_disable(ch);
320         free_irq(ch->irq, ch);
321         ch->client = NULL;
322 }
323 EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_client_unregister);
324
325 void ep93xx_dma_m2p_submit(struct ep93xx_dma_m2p_client *cl,
326                            struct ep93xx_dma_buffer *buf)
327 {
328         struct m2p_channel *ch = cl->channel;
329         unsigned long flags;
330         u32 v;
331
332         spin_lock_irqsave(&ch->lock, flags);
333         v = readl(ch->base + M2P_CONTROL);
334         if (ch->buffer_xfer == NULL) {
335                 ch->buffer_xfer = buf;
336                 feed_buf(ch, buf);
337                 cl->buffer_started(cl->cookie, buf);
338
339                 v |= M2P_CONTROL_STALL_IRQ_EN;
340                 m2p_set_control(ch, v);
341
342         } else if (ch->buffer_next == NULL) {
343                 ch->buffer_next = buf;
344                 feed_buf(ch, buf);
345
346                 v |= M2P_CONTROL_NFB_IRQ_EN;
347                 m2p_set_control(ch, v);
348         } else {
349                 list_add_tail(&buf->list, &ch->buffers_pending);
350         }
351         spin_unlock_irqrestore(&ch->lock, flags);
352 }
353 EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_submit);
354
355 void ep93xx_dma_m2p_submit_recursive(struct ep93xx_dma_m2p_client *cl,
356                                      struct ep93xx_dma_buffer *buf)
357 {
358         struct m2p_channel *ch = cl->channel;
359
360         list_add_tail(&buf->list, &ch->buffers_pending);
361 }
362 EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_submit_recursive);
363
364 void ep93xx_dma_m2p_flush(struct ep93xx_dma_m2p_client *cl)
365 {
366         struct m2p_channel *ch = cl->channel;
367
368         channel_disable(ch);
369         ch->next_slot = 0;
370         ch->buffer_xfer = NULL;
371         ch->buffer_next = NULL;
372         INIT_LIST_HEAD(&ch->buffers_pending);
373         channel_enable(ch);
374 }
375 EXPORT_SYMBOL_GPL(ep93xx_dma_m2p_flush);
376
377 static int init_channel(struct m2p_channel *ch)
378 {
379         ch->clk = clk_get(NULL, ch->name);
380         if (IS_ERR(ch->clk))
381                 return PTR_ERR(ch->clk);
382
383         spin_lock_init(&ch->lock);
384         ch->client = NULL;
385
386         return 0;
387 }
388
389 static int __init ep93xx_dma_m2p_init(void)
390 {
391         int i;
392         int ret;
393
394         for (i = 0; m2p_rx[i].base; i++) {
395                 ret = init_channel(m2p_rx + i);
396                 if (ret)
397                         return ret;
398         }
399
400         for (i = 0; m2p_tx[i].base; i++) {
401                 ret = init_channel(m2p_tx + i);
402                 if (ret)
403                         return ret;
404         }
405
406         pr_info("M2P DMA subsystem initialized\n");
407         return 0;
408 }
409 arch_initcall(ep93xx_dma_m2p_init);