]> asedeno.scripts.mit.edu Git - linux.git/blob - arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
ARM: dts: Add some initial IXP4xx device trees
[linux.git] / arch / arm / mach-ixp4xx / ixp4xx_qmgr.c
1 /*
2  * Intel IXP4xx Queue Manager driver for Linux
3  *
4  * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of version 2 of the GNU General Public License
8  * as published by the Free Software Foundation.
9  */
10
11 #include <linux/ioport.h>
12 #include <linux/interrupt.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/of.h>
16 #include <mach/qmgr.h>
17
18 #include "irqs.h"
19
20 static struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
21 static struct resource *mem_res;
22 static spinlock_t qmgr_lock;
23 static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
24 static void (*irq_handlers[QUEUES])(void *pdev);
25 static void *irq_pdevs[QUEUES];
26
27 #if DEBUG_QMGR
28 char qmgr_queue_descs[QUEUES][32];
29 #endif
30
31 void qmgr_set_irq(unsigned int queue, int src,
32                   void (*handler)(void *pdev), void *pdev)
33 {
34         unsigned long flags;
35
36         spin_lock_irqsave(&qmgr_lock, flags);
37         if (queue < HALF_QUEUES) {
38                 u32 __iomem *reg;
39                 int bit;
40                 BUG_ON(src > QUEUE_IRQ_SRC_NOT_FULL);
41                 reg = &qmgr_regs->irqsrc[queue >> 3]; /* 8 queues per u32 */
42                 bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
43                 __raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit),
44                              reg);
45         } else
46                 /* IRQ source for queues 32-63 is fixed */
47                 BUG_ON(src != QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY);
48
49         irq_handlers[queue] = handler;
50         irq_pdevs[queue] = pdev;
51         spin_unlock_irqrestore(&qmgr_lock, flags);
52 }
53
54
55 static irqreturn_t qmgr_irq1_a0(int irq, void *pdev)
56 {
57         int i, ret = 0;
58         u32 en_bitmap, src, stat;
59
60         /* ACK - it may clear any bits so don't rely on it */
61         __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[0]);
62
63         en_bitmap = qmgr_regs->irqen[0];
64         while (en_bitmap) {
65                 i = __fls(en_bitmap); /* number of the last "low" queue */
66                 en_bitmap &= ~BIT(i);
67                 src = qmgr_regs->irqsrc[i >> 3];
68                 stat = qmgr_regs->stat1[i >> 3];
69                 if (src & 4) /* the IRQ condition is inverted */
70                         stat = ~stat;
71                 if (stat & BIT(src & 3)) {
72                         irq_handlers[i](irq_pdevs[i]);
73                         ret = IRQ_HANDLED;
74                 }
75         }
76         return ret;
77 }
78
79
80 static irqreturn_t qmgr_irq2_a0(int irq, void *pdev)
81 {
82         int i, ret = 0;
83         u32 req_bitmap;
84
85         /* ACK - it may clear any bits so don't rely on it */
86         __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[1]);
87
88         req_bitmap = qmgr_regs->irqen[1] & qmgr_regs->statne_h;
89         while (req_bitmap) {
90                 i = __fls(req_bitmap); /* number of the last "high" queue */
91                 req_bitmap &= ~BIT(i);
92                 irq_handlers[HALF_QUEUES + i](irq_pdevs[HALF_QUEUES + i]);
93                 ret = IRQ_HANDLED;
94         }
95         return ret;
96 }
97
98
99 static irqreturn_t qmgr_irq(int irq, void *pdev)
100 {
101         int i, half = (irq == IRQ_IXP4XX_QM1 ? 0 : 1);
102         u32 req_bitmap = __raw_readl(&qmgr_regs->irqstat[half]);
103
104         if (!req_bitmap)
105                 return 0;
106         __raw_writel(req_bitmap, &qmgr_regs->irqstat[half]); /* ACK */
107
108         while (req_bitmap) {
109                 i = __fls(req_bitmap); /* number of the last queue */
110                 req_bitmap &= ~BIT(i);
111                 i += half * HALF_QUEUES;
112                 irq_handlers[i](irq_pdevs[i]);
113         }
114         return IRQ_HANDLED;
115 }
116
117
118 void qmgr_enable_irq(unsigned int queue)
119 {
120         unsigned long flags;
121         int half = queue / 32;
122         u32 mask = 1 << (queue & (HALF_QUEUES - 1));
123
124         spin_lock_irqsave(&qmgr_lock, flags);
125         __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) | mask,
126                      &qmgr_regs->irqen[half]);
127         spin_unlock_irqrestore(&qmgr_lock, flags);
128 }
129
130 void qmgr_disable_irq(unsigned int queue)
131 {
132         unsigned long flags;
133         int half = queue / 32;
134         u32 mask = 1 << (queue & (HALF_QUEUES - 1));
135
136         spin_lock_irqsave(&qmgr_lock, flags);
137         __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) & ~mask,
138                      &qmgr_regs->irqen[half]);
139         __raw_writel(mask, &qmgr_regs->irqstat[half]); /* clear */
140         spin_unlock_irqrestore(&qmgr_lock, flags);
141 }
142
143 static inline void shift_mask(u32 *mask)
144 {
145         mask[3] = mask[3] << 1 | mask[2] >> 31;
146         mask[2] = mask[2] << 1 | mask[1] >> 31;
147         mask[1] = mask[1] << 1 | mask[0] >> 31;
148         mask[0] <<= 1;
149 }
150
151 #if DEBUG_QMGR
152 int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
153                        unsigned int nearly_empty_watermark,
154                        unsigned int nearly_full_watermark,
155                        const char *desc_format, const char* name)
156 #else
157 int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
158                          unsigned int nearly_empty_watermark,
159                          unsigned int nearly_full_watermark)
160 #endif
161 {
162         u32 cfg, addr = 0, mask[4]; /* in 16-dwords */
163         int err;
164
165         BUG_ON(queue >= QUEUES);
166
167         if ((nearly_empty_watermark | nearly_full_watermark) & ~7)
168                 return -EINVAL;
169
170         switch (len) {
171         case  16:
172                 cfg = 0 << 24;
173                 mask[0] = 0x1;
174                 break;
175         case  32:
176                 cfg = 1 << 24;
177                 mask[0] = 0x3;
178                 break;
179         case  64:
180                 cfg = 2 << 24;
181                 mask[0] = 0xF;
182                 break;
183         case 128:
184                 cfg = 3 << 24;
185                 mask[0] = 0xFF;
186                 break;
187         default:
188                 return -EINVAL;
189         }
190
191         cfg |= nearly_empty_watermark << 26;
192         cfg |= nearly_full_watermark << 29;
193         len /= 16;              /* in 16-dwords: 1, 2, 4 or 8 */
194         mask[1] = mask[2] = mask[3] = 0;
195
196         if (!try_module_get(THIS_MODULE))
197                 return -ENODEV;
198
199         spin_lock_irq(&qmgr_lock);
200         if (__raw_readl(&qmgr_regs->sram[queue])) {
201                 err = -EBUSY;
202                 goto err;
203         }
204
205         while (1) {
206                 if (!(used_sram_bitmap[0] & mask[0]) &&
207                     !(used_sram_bitmap[1] & mask[1]) &&
208                     !(used_sram_bitmap[2] & mask[2]) &&
209                     !(used_sram_bitmap[3] & mask[3]))
210                         break; /* found free space */
211
212                 addr++;
213                 shift_mask(mask);
214                 if (addr + len > ARRAY_SIZE(qmgr_regs->sram)) {
215                         printk(KERN_ERR "qmgr: no free SRAM space for"
216                                " queue %i\n", queue);
217                         err = -ENOMEM;
218                         goto err;
219                 }
220         }
221
222         used_sram_bitmap[0] |= mask[0];
223         used_sram_bitmap[1] |= mask[1];
224         used_sram_bitmap[2] |= mask[2];
225         used_sram_bitmap[3] |= mask[3];
226         __raw_writel(cfg | (addr << 14), &qmgr_regs->sram[queue]);
227 #if DEBUG_QMGR
228         snprintf(qmgr_queue_descs[queue], sizeof(qmgr_queue_descs[0]),
229                  desc_format, name);
230         printk(KERN_DEBUG "qmgr: requested queue %s(%i) addr = 0x%02X\n",
231                qmgr_queue_descs[queue], queue, addr);
232 #endif
233         spin_unlock_irq(&qmgr_lock);
234         return 0;
235
236 err:
237         spin_unlock_irq(&qmgr_lock);
238         module_put(THIS_MODULE);
239         return err;
240 }
241
242 void qmgr_release_queue(unsigned int queue)
243 {
244         u32 cfg, addr, mask[4];
245
246         BUG_ON(queue >= QUEUES); /* not in valid range */
247
248         spin_lock_irq(&qmgr_lock);
249         cfg = __raw_readl(&qmgr_regs->sram[queue]);
250         addr = (cfg >> 14) & 0xFF;
251
252         BUG_ON(!addr);          /* not requested */
253
254         switch ((cfg >> 24) & 3) {
255         case 0: mask[0] = 0x1; break;
256         case 1: mask[0] = 0x3; break;
257         case 2: mask[0] = 0xF; break;
258         case 3: mask[0] = 0xFF; break;
259         }
260
261         mask[1] = mask[2] = mask[3] = 0;
262
263         while (addr--)
264                 shift_mask(mask);
265
266 #if DEBUG_QMGR
267         printk(KERN_DEBUG "qmgr: releasing queue %s(%i)\n",
268                qmgr_queue_descs[queue], queue);
269         qmgr_queue_descs[queue][0] = '\x0';
270 #endif
271
272         while ((addr = qmgr_get_entry(queue)))
273                 printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n",
274                        queue, addr);
275
276         __raw_writel(0, &qmgr_regs->sram[queue]);
277
278         used_sram_bitmap[0] &= ~mask[0];
279         used_sram_bitmap[1] &= ~mask[1];
280         used_sram_bitmap[2] &= ~mask[2];
281         used_sram_bitmap[3] &= ~mask[3];
282         irq_handlers[queue] = NULL; /* catch IRQ bugs */
283         spin_unlock_irq(&qmgr_lock);
284
285         module_put(THIS_MODULE);
286 }
287
288 static int qmgr_init(void)
289 {
290         int i, err;
291         irq_handler_t handler1, handler2;
292
293         /* This driver does not work with device tree */
294         if (of_have_populated_dt())
295                 return -ENODEV;
296
297         mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS,
298                                      IXP4XX_QMGR_REGION_SIZE,
299                                      "IXP4xx Queue Manager");
300         if (mem_res == NULL)
301                 return -EBUSY;
302
303         /* reset qmgr registers */
304         for (i = 0; i < 4; i++) {
305                 __raw_writel(0x33333333, &qmgr_regs->stat1[i]);
306                 __raw_writel(0, &qmgr_regs->irqsrc[i]);
307         }
308         for (i = 0; i < 2; i++) {
309                 __raw_writel(0, &qmgr_regs->stat2[i]);
310                 __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[i]); /* clear */
311                 __raw_writel(0, &qmgr_regs->irqen[i]);
312         }
313
314         __raw_writel(0xFFFFFFFF, &qmgr_regs->statne_h);
315         __raw_writel(0, &qmgr_regs->statf_h);
316
317         for (i = 0; i < QUEUES; i++)
318                 __raw_writel(0, &qmgr_regs->sram[i]);
319
320         if (cpu_is_ixp42x_rev_a0()) {
321                 handler1 = qmgr_irq1_a0;
322                 handler2 = qmgr_irq2_a0;
323         } else
324                 handler1 = handler2 = qmgr_irq;
325
326         err = request_irq(IRQ_IXP4XX_QM1, handler1, 0, "IXP4xx Queue Manager",
327                           NULL);
328         if (err) {
329                 printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n",
330                        IRQ_IXP4XX_QM1, err);
331                 goto error_irq;
332         }
333
334         err = request_irq(IRQ_IXP4XX_QM2, handler2, 0, "IXP4xx Queue Manager",
335                           NULL);
336         if (err) {
337                 printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n",
338                        IRQ_IXP4XX_QM2, err);
339                 goto error_irq2;
340         }
341
342         used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
343         spin_lock_init(&qmgr_lock);
344
345         printk(KERN_INFO "IXP4xx Queue Manager initialized.\n");
346         return 0;
347
348 error_irq2:
349         free_irq(IRQ_IXP4XX_QM1, NULL);
350 error_irq:
351         release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
352         return err;
353 }
354
355 static void qmgr_remove(void)
356 {
357         free_irq(IRQ_IXP4XX_QM1, NULL);
358         free_irq(IRQ_IXP4XX_QM2, NULL);
359         synchronize_irq(IRQ_IXP4XX_QM1);
360         synchronize_irq(IRQ_IXP4XX_QM2);
361         release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
362 }
363
364 module_init(qmgr_init);
365 module_exit(qmgr_remove);
366
367 MODULE_LICENSE("GPL v2");
368 MODULE_AUTHOR("Krzysztof Halasa");
369
370 EXPORT_SYMBOL(qmgr_set_irq);
371 EXPORT_SYMBOL(qmgr_enable_irq);
372 EXPORT_SYMBOL(qmgr_disable_irq);
373 #if DEBUG_QMGR
374 EXPORT_SYMBOL(qmgr_queue_descs);
375 EXPORT_SYMBOL(qmgr_request_queue);
376 #else
377 EXPORT_SYMBOL(__qmgr_request_queue);
378 #endif
379 EXPORT_SYMBOL(qmgr_release_queue);