diff options
Diffstat (limited to 'arch/arm/mach-ixp4xx/ixp4xx_qmgr.c')
-rw-r--r-- | arch/arm/mach-ixp4xx/ixp4xx_qmgr.c | 71 |
1 files changed, 49 insertions, 22 deletions
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c index bfddc73d0a20..7531bfdb7b4e 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; | |||
18 | static struct resource *mem_res; | 18 | static struct resource *mem_res; |
19 | static spinlock_t qmgr_lock; | 19 | static spinlock_t qmgr_lock; |
20 | static u32 used_sram_bitmap[4]; /* 128 16-dword pages */ | 20 | static u32 used_sram_bitmap[4]; /* 128 16-dword pages */ |
21 | static void (*irq_handlers[HALF_QUEUES])(void *pdev); | 21 | static void (*irq_handlers[QUEUES])(void *pdev); |
22 | static void *irq_pdevs[HALF_QUEUES]; | 22 | static void *irq_pdevs[QUEUES]; |
23 | 23 | ||
24 | #if DEBUG_QMGR | 24 | #if DEBUG_QMGR |
25 | char qmgr_queue_descs[QUEUES][32]; | 25 | char qmgr_queue_descs[QUEUES][32]; |
@@ -28,29 +28,38 @@ char qmgr_queue_descs[QUEUES][32]; | |||
28 | void qmgr_set_irq(unsigned int queue, int src, | 28 | void 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 | ||
44 | static irqreturn_t qmgr_irq1(int irq, void *pdev) | 52 | static irqreturn_t qmgr_irq(int irq, void *pdev) |
45 | { | 53 | { |
46 | int i; | 54 | int i, half = (irq == IRQ_IXP4XX_QM1 ? 0 : 1); |
47 | u32 val = __raw_readl(&qmgr_regs->irqstat[0]); | 55 | u32 val = __raw_readl(&qmgr_regs->irqstat[half]); |
48 | __raw_writel(val, &qmgr_regs->irqstat[0]); /* ACK */ | 56 | __raw_writel(val, &qmgr_regs->irqstat[half]); /* ACK */ |
49 | 57 | ||
50 | for (i = 0; i < HALF_QUEUES; i++) | 58 | for (i = 0; i < HALF_QUEUES; i++) |
51 | if (val & (1 << i)) | 59 | if (val & (1 << i)) { |
52 | irq_handlers[i](irq_pdevs[i]); | 60 | int irq = half * HALF_QUEUES + i; |
53 | 61 | irq_handlers[irq](irq_pdevs[irq]); | |
62 | } | ||
54 | return val ? IRQ_HANDLED : 0; | 63 | return val ? IRQ_HANDLED : 0; |
55 | } | 64 | } |
56 | 65 | ||
@@ -58,21 +67,25 @@ static irqreturn_t qmgr_irq1(int irq, void *pdev) | |||
58 | void qmgr_enable_irq(unsigned int queue) | 67 | void qmgr_enable_irq(unsigned int queue) |
59 | { | 68 | { |
60 | unsigned long flags; | 69 | unsigned long flags; |
70 | int half = queue / 32; | ||
71 | u32 mask = 1 << (queue & (HALF_QUEUES - 1)); | ||
61 | 72 | ||
62 | spin_lock_irqsave(&qmgr_lock, flags); | 73 | spin_lock_irqsave(&qmgr_lock, flags); |
63 | __raw_writel(__raw_readl(&qmgr_regs->irqen[0]) | (1 << queue), | 74 | __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) | mask, |
64 | &qmgr_regs->irqen[0]); | 75 | &qmgr_regs->irqen[half]); |
65 | spin_unlock_irqrestore(&qmgr_lock, flags); | 76 | spin_unlock_irqrestore(&qmgr_lock, flags); |
66 | } | 77 | } |
67 | 78 | ||
68 | void qmgr_disable_irq(unsigned int queue) | 79 | void qmgr_disable_irq(unsigned int queue) |
69 | { | 80 | { |
70 | unsigned long flags; | 81 | unsigned long flags; |
82 | int half = queue / 32; | ||
83 | u32 mask = 1 << (queue & (HALF_QUEUES - 1)); | ||
71 | 84 | ||
72 | spin_lock_irqsave(&qmgr_lock, flags); | 85 | spin_lock_irqsave(&qmgr_lock, flags); |
73 | __raw_writel(__raw_readl(&qmgr_regs->irqen[0]) & ~(1 << queue), | 86 | __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) & ~mask, |
74 | &qmgr_regs->irqen[0]); | 87 | &qmgr_regs->irqen[half]); |
75 | __raw_writel(1 << queue, &qmgr_regs->irqstat[0]); /* clear */ | 88 | __raw_writel(mask, &qmgr_regs->irqstat[half]); /* clear */ |
76 | spin_unlock_irqrestore(&qmgr_lock, flags); | 89 | spin_unlock_irqrestore(&qmgr_lock, flags); |
77 | } | 90 | } |
78 | 91 | ||
@@ -98,8 +111,7 @@ int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, | |||
98 | u32 cfg, addr = 0, mask[4]; /* in 16-dwords */ | 111 | u32 cfg, addr = 0, mask[4]; /* in 16-dwords */ |
99 | int err; | 112 | int err; |
100 | 113 | ||
101 | if (queue >= HALF_QUEUES) | 114 | BUG_ON(queue >= QUEUES); |
102 | return -ERANGE; | ||
103 | 115 | ||
104 | if ((nearly_empty_watermark | nearly_full_watermark) & ~7) | 116 | if ((nearly_empty_watermark | nearly_full_watermark) & ~7) |
105 | return -EINVAL; | 117 | return -EINVAL; |
@@ -180,7 +192,7 @@ void qmgr_release_queue(unsigned int queue) | |||
180 | { | 192 | { |
181 | u32 cfg, addr, mask[4]; | 193 | u32 cfg, addr, mask[4]; |
182 | 194 | ||
183 | BUG_ON(queue >= HALF_QUEUES); /* not in valid range */ | 195 | BUG_ON(queue >= QUEUES); /* not in valid range */ |
184 | 196 | ||
185 | spin_lock_irq(&qmgr_lock); | 197 | spin_lock_irq(&qmgr_lock); |
186 | cfg = __raw_readl(&qmgr_regs->sram[queue]); | 198 | cfg = __raw_readl(&qmgr_regs->sram[queue]); |
@@ -247,10 +259,13 @@ static int qmgr_init(void) | |||
247 | __raw_writel(0, &qmgr_regs->irqen[i]); | 259 | __raw_writel(0, &qmgr_regs->irqen[i]); |
248 | } | 260 | } |
249 | 261 | ||
262 | __raw_writel(0xFFFFFFFF, &qmgr_regs->statne_h); | ||
263 | __raw_writel(0, &qmgr_regs->statf_h); | ||
264 | |||
250 | for (i = 0; i < QUEUES; i++) | 265 | for (i = 0; i < QUEUES; i++) |
251 | __raw_writel(0, &qmgr_regs->sram[i]); | 266 | __raw_writel(0, &qmgr_regs->sram[i]); |
252 | 267 | ||
253 | err = request_irq(IRQ_IXP4XX_QM1, qmgr_irq1, 0, | 268 | err = request_irq(IRQ_IXP4XX_QM1, qmgr_irq, 0, |
254 | "IXP4xx Queue Manager", NULL); | 269 | "IXP4xx Queue Manager", NULL); |
255 | if (err) { | 270 | if (err) { |
256 | printk(KERN_ERR "qmgr: failed to request IRQ%i\n", | 271 | printk(KERN_ERR "qmgr: failed to request IRQ%i\n", |
@@ -258,12 +273,22 @@ static int qmgr_init(void) | |||
258 | goto error_irq; | 273 | goto error_irq; |
259 | } | 274 | } |
260 | 275 | ||
276 | err = request_irq(IRQ_IXP4XX_QM2, qmgr_irq, 0, | ||
277 | "IXP4xx Queue Manager", NULL); | ||
278 | if (err) { | ||
279 | printk(KERN_ERR "qmgr: failed to request IRQ%i\n", | ||
280 | IRQ_IXP4XX_QM2); | ||
281 | goto error_irq2; | ||
282 | } | ||
283 | |||
261 | used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */ | 284 | used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */ |
262 | spin_lock_init(&qmgr_lock); | 285 | spin_lock_init(&qmgr_lock); |
263 | 286 | ||
264 | printk(KERN_INFO "IXP4xx Queue Manager initialized.\n"); | 287 | printk(KERN_INFO "IXP4xx Queue Manager initialized.\n"); |
265 | return 0; | 288 | return 0; |
266 | 289 | ||
290 | error_irq2: | ||
291 | free_irq(IRQ_IXP4XX_QM1, NULL); | ||
267 | error_irq: | 292 | error_irq: |
268 | iounmap(qmgr_regs); | 293 | iounmap(qmgr_regs); |
269 | error_map: | 294 | error_map: |
@@ -274,7 +299,9 @@ error_map: | |||
274 | static void qmgr_remove(void) | 299 | static void qmgr_remove(void) |
275 | { | 300 | { |
276 | free_irq(IRQ_IXP4XX_QM1, NULL); | 301 | free_irq(IRQ_IXP4XX_QM1, NULL); |
302 | free_irq(IRQ_IXP4XX_QM2, NULL); | ||
277 | synchronize_irq(IRQ_IXP4XX_QM1); | 303 | synchronize_irq(IRQ_IXP4XX_QM1); |
304 | synchronize_irq(IRQ_IXP4XX_QM2); | ||
278 | iounmap(qmgr_regs); | 305 | iounmap(qmgr_regs); |
279 | release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE); | 306 | release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE); |
280 | } | 307 | } |