2 * Intel IXP4xx Queue Manager driver for Linux
4 * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl>
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.
11 #include <linux/ioport.h>
12 #include <linux/interrupt.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <asm/arch/qmgr.h>
19 struct qmgr_regs __iomem
*qmgr_regs
;
20 static struct resource
*mem_res
;
21 static spinlock_t qmgr_lock
;
22 static u32 used_sram_bitmap
[4]; /* 128 16-dword pages */
23 static void (*irq_handlers
[HALF_QUEUES
])(void *pdev
);
24 static void *irq_pdevs
[HALF_QUEUES
];
26 void qmgr_set_irq(unsigned int queue
, int src
,
27 void (*handler
)(void *pdev
), void *pdev
)
29 u32 __iomem
*reg
= &qmgr_regs
->irqsrc
[queue
/ 8]; /* 8 queues / u32 */
30 int bit
= (queue
% 8) * 4; /* 3 bits + 1 reserved bit per queue */
34 spin_lock_irqsave(&qmgr_lock
, flags
);
35 __raw_writel((__raw_readl(reg
) & ~(7 << bit
)) | (src
<< bit
), reg
);
36 irq_handlers
[queue
] = handler
;
37 irq_pdevs
[queue
] = pdev
;
38 spin_unlock_irqrestore(&qmgr_lock
, flags
);
42 static irqreturn_t
qmgr_irq1(int irq
, void *pdev
)
45 u32 val
= __raw_readl(&qmgr_regs
->irqstat
[0]);
46 __raw_writel(val
, &qmgr_regs
->irqstat
[0]); /* ACK */
48 for (i
= 0; i
< HALF_QUEUES
; i
++)
50 irq_handlers
[i
](irq_pdevs
[i
]);
52 return val
? IRQ_HANDLED
: 0;
56 void qmgr_enable_irq(unsigned int queue
)
60 spin_lock_irqsave(&qmgr_lock
, flags
);
61 __raw_writel(__raw_readl(&qmgr_regs
->irqen
[0]) | (1 << queue
),
62 &qmgr_regs
->irqen
[0]);
63 spin_unlock_irqrestore(&qmgr_lock
, flags
);
66 void qmgr_disable_irq(unsigned int queue
)
70 spin_lock_irqsave(&qmgr_lock
, flags
);
71 __raw_writel(__raw_readl(&qmgr_regs
->irqen
[0]) & ~(1 << queue
),
72 &qmgr_regs
->irqen
[0]);
73 spin_unlock_irqrestore(&qmgr_lock
, flags
);
76 static inline void shift_mask(u32
*mask
)
78 mask
[3] = mask
[3] << 1 | mask
[2] >> 31;
79 mask
[2] = mask
[2] << 1 | mask
[1] >> 31;
80 mask
[1] = mask
[1] << 1 | mask
[0] >> 31;
84 int qmgr_request_queue(unsigned int queue
, unsigned int len
/* dwords */,
85 unsigned int nearly_empty_watermark
,
86 unsigned int nearly_full_watermark
)
88 u32 cfg
, addr
= 0, mask
[4]; /* in 16-dwords */
91 if (queue
>= HALF_QUEUES
)
94 if ((nearly_empty_watermark
| nearly_full_watermark
) & ~7)
118 cfg
|= nearly_empty_watermark
<< 26;
119 cfg
|= nearly_full_watermark
<< 29;
120 len
/= 16; /* in 16-dwords: 1, 2, 4 or 8 */
121 mask
[1] = mask
[2] = mask
[3] = 0;
123 if (!try_module_get(THIS_MODULE
))
126 spin_lock_irq(&qmgr_lock
);
127 if (__raw_readl(&qmgr_regs
->sram
[queue
])) {
133 if (!(used_sram_bitmap
[0] & mask
[0]) &&
134 !(used_sram_bitmap
[1] & mask
[1]) &&
135 !(used_sram_bitmap
[2] & mask
[2]) &&
136 !(used_sram_bitmap
[3] & mask
[3]))
137 break; /* found free space */
141 if (addr
+ len
> ARRAY_SIZE(qmgr_regs
->sram
)) {
142 printk(KERN_ERR
"qmgr: no free SRAM space for"
143 " queue %i\n", queue
);
149 used_sram_bitmap
[0] |= mask
[0];
150 used_sram_bitmap
[1] |= mask
[1];
151 used_sram_bitmap
[2] |= mask
[2];
152 used_sram_bitmap
[3] |= mask
[3];
153 __raw_writel(cfg
| (addr
<< 14), &qmgr_regs
->sram
[queue
]);
154 spin_unlock_irq(&qmgr_lock
);
157 printk(KERN_DEBUG
"qmgr: requested queue %i, addr = 0x%02X\n",
163 spin_unlock_irq(&qmgr_lock
);
164 module_put(THIS_MODULE
);
168 void qmgr_release_queue(unsigned int queue
)
170 u32 cfg
, addr
, mask
[4];
172 BUG_ON(queue
>= HALF_QUEUES
); /* not in valid range */
174 spin_lock_irq(&qmgr_lock
);
175 cfg
= __raw_readl(&qmgr_regs
->sram
[queue
]);
176 addr
= (cfg
>> 14) & 0xFF;
178 BUG_ON(!addr
); /* not requested */
180 switch ((cfg
>> 24) & 3) {
181 case 0: mask
[0] = 0x1; break;
182 case 1: mask
[0] = 0x3; break;
183 case 2: mask
[0] = 0xF; break;
184 case 3: mask
[0] = 0xFF; break;
190 __raw_writel(0, &qmgr_regs
->sram
[queue
]);
192 used_sram_bitmap
[0] &= ~mask
[0];
193 used_sram_bitmap
[1] &= ~mask
[1];
194 used_sram_bitmap
[2] &= ~mask
[2];
195 used_sram_bitmap
[3] &= ~mask
[3];
196 irq_handlers
[queue
] = NULL
; /* catch IRQ bugs */
197 spin_unlock_irq(&qmgr_lock
);
199 module_put(THIS_MODULE
);
201 printk(KERN_DEBUG
"qmgr: released queue %i\n", queue
);
205 static int qmgr_init(void)
208 mem_res
= request_mem_region(IXP4XX_QMGR_BASE_PHYS
,
209 IXP4XX_QMGR_REGION_SIZE
,
210 "IXP4xx Queue Manager");
214 qmgr_regs
= ioremap(IXP4XX_QMGR_BASE_PHYS
, IXP4XX_QMGR_REGION_SIZE
);
215 if (qmgr_regs
== NULL
) {
220 /* reset qmgr registers */
221 for (i
= 0; i
< 4; i
++) {
222 __raw_writel(0x33333333, &qmgr_regs
->stat1
[i
]);
223 __raw_writel(0, &qmgr_regs
->irqsrc
[i
]);
225 for (i
= 0; i
< 2; i
++) {
226 __raw_writel(0, &qmgr_regs
->stat2
[i
]);
227 __raw_writel(0xFFFFFFFF, &qmgr_regs
->irqstat
[i
]); /* clear */
228 __raw_writel(0, &qmgr_regs
->irqen
[i
]);
231 for (i
= 0; i
< QUEUES
; i
++)
232 __raw_writel(0, &qmgr_regs
->sram
[i
]);
234 err
= request_irq(IRQ_IXP4XX_QM1
, qmgr_irq1
, 0,
235 "IXP4xx Queue Manager", NULL
);
237 printk(KERN_ERR
"qmgr: failed to request IRQ%i\n",
242 used_sram_bitmap
[0] = 0xF; /* 4 first pages reserved for config */
243 spin_lock_init(&qmgr_lock
);
245 printk(KERN_INFO
"IXP4xx Queue Manager initialized.\n");
251 release_mem_region(IXP4XX_QMGR_BASE_PHYS
, IXP4XX_QMGR_REGION_SIZE
);
255 static void qmgr_remove(void)
257 free_irq(IRQ_IXP4XX_QM1
, NULL
);
258 synchronize_irq(IRQ_IXP4XX_QM1
);
260 release_mem_region(IXP4XX_QMGR_BASE_PHYS
, IXP4XX_QMGR_REGION_SIZE
);
263 module_init(qmgr_init
);
264 module_exit(qmgr_remove
);
266 MODULE_LICENSE("GPL v2");
267 MODULE_AUTHOR("Krzysztof Halasa");
269 EXPORT_SYMBOL(qmgr_regs
);
270 EXPORT_SYMBOL(qmgr_set_irq
);
271 EXPORT_SYMBOL(qmgr_enable_irq
);
272 EXPORT_SYMBOL(qmgr_disable_irq
);
273 EXPORT_SYMBOL(qmgr_request_queue
);
274 EXPORT_SYMBOL(qmgr_release_queue
);