aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ixp4xx/ixp4xx_qmgr.c')
-rw-r--r--arch/arm/mach-ixp4xx/ixp4xx_qmgr.c135
1 files changed, 109 insertions, 26 deletions
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
index bfddc73d0a20..bfdbe4b5a3cc 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
@@ -18,8 +18,8 @@ struct qmgr_regs __iomem *qmgr_regs;
18static struct resource *mem_res; 18static struct resource *mem_res;
19static spinlock_t qmgr_lock; 19static spinlock_t qmgr_lock;
20static u32 used_sram_bitmap[4]; /* 128 16-dword pages */ 20static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
21static void (*irq_handlers[HALF_QUEUES])(void *pdev); 21static void (*irq_handlers[QUEUES])(void *pdev);
22static void *irq_pdevs[HALF_QUEUES]; 22static void *irq_pdevs[QUEUES];
23 23
24#if DEBUG_QMGR 24#if DEBUG_QMGR
25char qmgr_queue_descs[QUEUES][32]; 25char qmgr_queue_descs[QUEUES][32];
@@ -28,51 +28,112 @@ char qmgr_queue_descs[QUEUES][32];
28void qmgr_set_irq(unsigned int queue, int src, 28void qmgr_set_irq(unsigned int queue, int src,
29 void (*handler)(void *pdev), void *pdev) 29 void (*handler)(void *pdev), void *pdev)
30{ 30{
31 u32 __iomem *reg = &qmgr_regs->irqsrc[queue / 8]; /* 8 queues / u32 */
32 int bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
33 unsigned long flags; 31 unsigned long flags;
34 32
35 src &= 7;
36 spin_lock_irqsave(&qmgr_lock, flags); 33 spin_lock_irqsave(&qmgr_lock, flags);
37 __raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit), reg); 34 if (queue < HALF_QUEUES) {
35 u32 __iomem *reg;
36 int bit;
37 BUG_ON(src > QUEUE_IRQ_SRC_NOT_FULL);
38 reg = &qmgr_regs->irqsrc[queue >> 3]; /* 8 queues per u32 */
39 bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
40 __raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit),
41 reg);
42 } else
43 /* IRQ source for queues 32-63 is fixed */
44 BUG_ON(src != QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY);
45
38 irq_handlers[queue] = handler; 46 irq_handlers[queue] = handler;
39 irq_pdevs[queue] = pdev; 47 irq_pdevs[queue] = pdev;
40 spin_unlock_irqrestore(&qmgr_lock, flags); 48 spin_unlock_irqrestore(&qmgr_lock, flags);
41} 49}
42 50
43 51
44static irqreturn_t qmgr_irq1(int irq, void *pdev) 52static irqreturn_t qmgr_irq1_a0(int irq, void *pdev)
45{ 53{
46 int i; 54 int i, ret = 0;
47 u32 val = __raw_readl(&qmgr_regs->irqstat[0]); 55 u32 en_bitmap, src, stat;
48 __raw_writel(val, &qmgr_regs->irqstat[0]); /* ACK */ 56
49 57 /* ACK - it may clear any bits so don't rely on it */
50 for (i = 0; i < HALF_QUEUES; i++) 58 __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[0]);
51 if (val & (1 << i)) 59
60 en_bitmap = qmgr_regs->irqen[0];
61 while (en_bitmap) {
62 i = __fls(en_bitmap); /* number of the last "low" queue */
63 en_bitmap &= ~BIT(i);
64 src = qmgr_regs->irqsrc[i >> 3];
65 stat = qmgr_regs->stat1[i >> 3];
66 if (src & 4) /* the IRQ condition is inverted */
67 stat = ~stat;
68 if (stat & BIT(src & 3)) {
52 irq_handlers[i](irq_pdevs[i]); 69 irq_handlers[i](irq_pdevs[i]);
70 ret = IRQ_HANDLED;
71 }
72 }
73 return ret;
74}
75
76
77static irqreturn_t qmgr_irq2_a0(int irq, void *pdev)
78{
79 int i, ret = 0;
80 u32 req_bitmap;
81
82 /* ACK - it may clear any bits so don't rely on it */
83 __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[1]);
84
85 req_bitmap = qmgr_regs->irqen[1] & qmgr_regs->statne_h;
86 while (req_bitmap) {
87 i = __fls(req_bitmap); /* number of the last "high" queue */
88 req_bitmap &= ~BIT(i);
89 irq_handlers[HALF_QUEUES + i](irq_pdevs[HALF_QUEUES + i]);
90 ret = IRQ_HANDLED;
91 }
92 return ret;
93}
53 94
54 return val ? IRQ_HANDLED : 0; 95
96static irqreturn_t qmgr_irq(int irq, void *pdev)
97{
98 int i, half = (irq == IRQ_IXP4XX_QM1 ? 0 : 1);
99 u32 req_bitmap = __raw_readl(&qmgr_regs->irqstat[half]);
100
101 if (!req_bitmap)
102 return 0;
103 __raw_writel(req_bitmap, &qmgr_regs->irqstat[half]); /* ACK */
104
105 while (req_bitmap) {
106 i = __fls(req_bitmap); /* number of the last queue */
107 req_bitmap &= ~BIT(i);
108 i += half * HALF_QUEUES;
109 irq_handlers[i](irq_pdevs[i]);
110 }
111 return IRQ_HANDLED;
55} 112}
56 113
57 114
58void qmgr_enable_irq(unsigned int queue) 115void qmgr_enable_irq(unsigned int queue)
59{ 116{
60 unsigned long flags; 117 unsigned long flags;
118 int half = queue / 32;
119 u32 mask = 1 << (queue & (HALF_QUEUES - 1));
61 120
62 spin_lock_irqsave(&qmgr_lock, flags); 121 spin_lock_irqsave(&qmgr_lock, flags);
63 __raw_writel(__raw_readl(&qmgr_regs->irqen[0]) | (1 << queue), 122 __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) | mask,
64 &qmgr_regs->irqen[0]); 123 &qmgr_regs->irqen[half]);
65 spin_unlock_irqrestore(&qmgr_lock, flags); 124 spin_unlock_irqrestore(&qmgr_lock, flags);
66} 125}
67 126
68void qmgr_disable_irq(unsigned int queue) 127void qmgr_disable_irq(unsigned int queue)
69{ 128{
70 unsigned long flags; 129 unsigned long flags;
130 int half = queue / 32;
131 u32 mask = 1 << (queue & (HALF_QUEUES - 1));
71 132
72 spin_lock_irqsave(&qmgr_lock, flags); 133 spin_lock_irqsave(&qmgr_lock, flags);
73 __raw_writel(__raw_readl(&qmgr_regs->irqen[0]) & ~(1 << queue), 134 __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) & ~mask,
74 &qmgr_regs->irqen[0]); 135 &qmgr_regs->irqen[half]);
75 __raw_writel(1 << queue, &qmgr_regs->irqstat[0]); /* clear */ 136 __raw_writel(mask, &qmgr_regs->irqstat[half]); /* clear */
76 spin_unlock_irqrestore(&qmgr_lock, flags); 137 spin_unlock_irqrestore(&qmgr_lock, flags);
77} 138}
78 139
@@ -98,8 +159,7 @@ int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
98 u32 cfg, addr = 0, mask[4]; /* in 16-dwords */ 159 u32 cfg, addr = 0, mask[4]; /* in 16-dwords */
99 int err; 160 int err;
100 161
101 if (queue >= HALF_QUEUES) 162 BUG_ON(queue >= QUEUES);
102 return -ERANGE;
103 163
104 if ((nearly_empty_watermark | nearly_full_watermark) & ~7) 164 if ((nearly_empty_watermark | nearly_full_watermark) & ~7)
105 return -EINVAL; 165 return -EINVAL;
@@ -180,7 +240,7 @@ void qmgr_release_queue(unsigned int queue)
180{ 240{
181 u32 cfg, addr, mask[4]; 241 u32 cfg, addr, mask[4];
182 242
183 BUG_ON(queue >= HALF_QUEUES); /* not in valid range */ 243 BUG_ON(queue >= QUEUES); /* not in valid range */
184 244
185 spin_lock_irq(&qmgr_lock); 245 spin_lock_irq(&qmgr_lock);
186 cfg = __raw_readl(&qmgr_regs->sram[queue]); 246 cfg = __raw_readl(&qmgr_regs->sram[queue]);
@@ -224,6 +284,8 @@ void qmgr_release_queue(unsigned int queue)
224static int qmgr_init(void) 284static int qmgr_init(void)
225{ 285{
226 int i, err; 286 int i, err;
287 irq_handler_t handler1, handler2;
288
227 mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS, 289 mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS,
228 IXP4XX_QMGR_REGION_SIZE, 290 IXP4XX_QMGR_REGION_SIZE,
229 "IXP4xx Queue Manager"); 291 "IXP4xx Queue Manager");
@@ -247,23 +309,42 @@ static int qmgr_init(void)
247 __raw_writel(0, &qmgr_regs->irqen[i]); 309 __raw_writel(0, &qmgr_regs->irqen[i]);
248 } 310 }
249 311
312 __raw_writel(0xFFFFFFFF, &qmgr_regs->statne_h);
313 __raw_writel(0, &qmgr_regs->statf_h);
314
250 for (i = 0; i < QUEUES; i++) 315 for (i = 0; i < QUEUES; i++)
251 __raw_writel(0, &qmgr_regs->sram[i]); 316 __raw_writel(0, &qmgr_regs->sram[i]);
252 317
253 err = request_irq(IRQ_IXP4XX_QM1, qmgr_irq1, 0, 318 if (cpu_is_ixp42x_rev_a0()) {
254 "IXP4xx Queue Manager", NULL); 319 handler1 = qmgr_irq1_a0;
320 handler2 = qmgr_irq2_a0;
321 } else
322 handler1 = handler2 = qmgr_irq;
323
324 err = request_irq(IRQ_IXP4XX_QM1, handler1, 0, "IXP4xx Queue Manager",
325 NULL);
255 if (err) { 326 if (err) {
256 printk(KERN_ERR "qmgr: failed to request IRQ%i\n", 327 printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n",
257 IRQ_IXP4XX_QM1); 328 IRQ_IXP4XX_QM1, err);
258 goto error_irq; 329 goto error_irq;
259 } 330 }
260 331
332 err = request_irq(IRQ_IXP4XX_QM2, handler2, 0, "IXP4xx Queue Manager",
333 NULL);
334 if (err) {
335 printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n",
336 IRQ_IXP4XX_QM2, err);
337 goto error_irq2;
338 }
339
261 used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */ 340 used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
262 spin_lock_init(&qmgr_lock); 341 spin_lock_init(&qmgr_lock);
263 342
264 printk(KERN_INFO "IXP4xx Queue Manager initialized.\n"); 343 printk(KERN_INFO "IXP4xx Queue Manager initialized.\n");
265 return 0; 344 return 0;
266 345
346error_irq2:
347 free_irq(IRQ_IXP4XX_QM1, NULL);
267error_irq: 348error_irq:
268 iounmap(qmgr_regs); 349 iounmap(qmgr_regs);
269error_map: 350error_map:
@@ -274,7 +355,9 @@ error_map:
274static void qmgr_remove(void) 355static void qmgr_remove(void)
275{ 356{
276 free_irq(IRQ_IXP4XX_QM1, NULL); 357 free_irq(IRQ_IXP4XX_QM1, NULL);
358 free_irq(IRQ_IXP4XX_QM2, NULL);
277 synchronize_irq(IRQ_IXP4XX_QM1); 359 synchronize_irq(IRQ_IXP4XX_QM1);
360 synchronize_irq(IRQ_IXP4XX_QM2);
278 iounmap(qmgr_regs); 361 iounmap(qmgr_regs);
279 release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE); 362 release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
280} 363}