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 <mach/qmgr.h> 16 17static struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; 18static struct resource *mem_res; 19static spinlock_t qmgr_lock; 20static u32 used_sram_bitmap[4]; /* 128 16-dword pages */ 21static void (*irq_handlers[QUEUES])(void *pdev); 22static void *irq_pdevs[QUEUES]; 23 24#if DEBUG_QMGR 25char qmgr_queue_descs[QUEUES][32]; 26#endif 27 28void qmgr_set_irq(unsigned int queue, int src, 29 void (*handler)(void *pdev), void *pdev) 30{ 31 unsigned long flags; 32 33 spin_lock_irqsave(&qmgr_lock, flags); 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 46 irq_handlers[queue] = handler; 47 irq_pdevs[queue] = pdev; 48 spin_unlock_irqrestore(&qmgr_lock, flags); 49} 50 51 52static irqreturn_t qmgr_irq1_a0(int irq, void *pdev) 53{ 54 int i, ret = 0; 55 u32 en_bitmap, src, stat; 56 57 /* ACK - it may clear any bits so don't rely on it */ 58 __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[0]); 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)) { 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} 94 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; 112} 113 114 115void qmgr_enable_irq(unsigned int queue) 116{ 117 unsigned long flags; 118 int half = queue / 32; 119 u32 mask = 1 << (queue & (HALF_QUEUES - 1)); 120 121 spin_lock_irqsave(&qmgr_lock, flags); 122 __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) | mask, 123 &qmgr_regs->irqen[half]); 124 spin_unlock_irqrestore(&qmgr_lock, flags); 125} 126 127void qmgr_disable_irq(unsigned int queue) 128{ 129 unsigned long flags; 130 int half = queue / 32; 131 u32 mask = 1 << (queue & (HALF_QUEUES - 1)); 132 133 spin_lock_irqsave(&qmgr_lock, flags); 134 __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) & ~mask, 135 &qmgr_regs->irqen[half]); 136 __raw_writel(mask, &qmgr_regs->irqstat[half]); /* clear */ 137 spin_unlock_irqrestore(&qmgr_lock, flags); 138} 139 140static inline void shift_mask(u32 *mask) 141{ 142 mask[3] = mask[3] << 1 | mask[2] >> 31; 143 mask[2] = mask[2] << 1 | mask[1] >> 31; 144 mask[1] = mask[1] << 1 | mask[0] >> 31; 145 mask[0] <<= 1; 146} 147 148#if DEBUG_QMGR 149int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, 150 unsigned int nearly_empty_watermark, 151 unsigned int nearly_full_watermark, 152 const char *desc_format, const char* name) 153#else 154int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, 155 unsigned int nearly_empty_watermark, 156 unsigned int nearly_full_watermark) 157#endif 158{ 159 u32 cfg, addr = 0, mask[4]; /* in 16-dwords */ 160 int err; 161 162 BUG_ON(queue >= QUEUES); 163 164 if ((nearly_empty_watermark | nearly_full_watermark) & ~7) 165 return -EINVAL; 166 167 switch (len) { 168 case 16: 169 cfg = 0 << 24; 170 mask[0] = 0x1; 171 break; 172 case 32: 173 cfg = 1 << 24; 174 mask[0] = 0x3; 175 break; 176 case 64: 177 cfg = 2 << 24; 178 mask[0] = 0xF; 179 break; 180 case 128: 181 cfg = 3 << 24; 182 mask[0] = 0xFF; 183 break; 184 default: 185 return -EINVAL; 186 } 187 188 cfg |= nearly_empty_watermark << 26; 189 cfg |= nearly_full_watermark << 29; 190 len /= 16; /* in 16-dwords: 1, 2, 4 or 8 */ 191 mask[1] = mask[2] = mask[3] = 0; 192 193 if (!try_module_get(THIS_MODULE)) 194 return -ENODEV; 195 196 spin_lock_irq(&qmgr_lock); 197 if (__raw_readl(&qmgr_regs->sram[queue])) { 198 err = -EBUSY; 199 goto err; 200 } 201 202 while (1) { 203 if (!(used_sram_bitmap[0] & mask[0]) && 204 !(used_sram_bitmap[1] & mask[1]) && 205 !(used_sram_bitmap[2] & mask[2]) && 206 !(used_sram_bitmap[3] & mask[3])) 207 break; /* found free space */ 208 209 addr++; 210 shift_mask(mask); 211 if (addr + len > ARRAY_SIZE(qmgr_regs->sram)) { 212 printk(KERN_ERR "qmgr: no free SRAM space for" 213 " queue %i\n", queue); 214 err = -ENOMEM; 215 goto err; 216 } 217 } 218 219 used_sram_bitmap[0] |= mask[0]; 220 used_sram_bitmap[1] |= mask[1]; 221 used_sram_bitmap[2] |= mask[2]; 222 used_sram_bitmap[3] |= mask[3]; 223 __raw_writel(cfg | (addr << 14), &qmgr_regs->sram[queue]); 224#if DEBUG_QMGR 225 snprintf(qmgr_queue_descs[queue], sizeof(qmgr_queue_descs[0]), 226 desc_format, name); 227 printk(KERN_DEBUG "qmgr: requested queue %s(%i) addr = 0x%02X\n", 228 qmgr_queue_descs[queue], queue, addr); 229#endif 230 spin_unlock_irq(&qmgr_lock); 231 return 0; 232 233err: 234 spin_unlock_irq(&qmgr_lock); 235 module_put(THIS_MODULE); 236 return err; 237} 238 239void qmgr_release_queue(unsigned int queue) 240{ 241 u32 cfg, addr, mask[4]; 242 243 BUG_ON(queue >= QUEUES); /* not in valid range */ 244 245 spin_lock_irq(&qmgr_lock); 246 cfg = __raw_readl(&qmgr_regs->sram[queue]); 247 addr = (cfg >> 14) & 0xFF; 248 249 BUG_ON(!addr); /* not requested */ 250 251 switch ((cfg >> 24) & 3) { 252 case 0: mask[0] = 0x1; break; 253 case 1: mask[0] = 0x3; break; 254 case 2: mask[0] = 0xF; break; 255 case 3: mask[0] = 0xFF; break; 256 } 257 258 mask[1] = mask[2] = mask[3] = 0; 259 260 while (addr--) 261 shift_mask(mask); 262 263#if DEBUG_QMGR 264 printk(KERN_DEBUG "qmgr: releasing queue %s(%i)\n", 265 qmgr_queue_descs[queue], queue); 266 qmgr_queue_descs[queue][0] = '\x0'; 267#endif 268 269 while ((addr = qmgr_get_entry(queue))) 270 printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n", 271 queue, addr); 272 273 __raw_writel(0, &qmgr_regs->sram[queue]); 274 275 used_sram_bitmap[0] &= ~mask[0]; 276 used_sram_bitmap[1] &= ~mask[1]; 277 used_sram_bitmap[2] &= ~mask[2]; 278 used_sram_bitmap[3] &= ~mask[3]; 279 irq_handlers[queue] = NULL; /* catch IRQ bugs */ 280 spin_unlock_irq(&qmgr_lock); 281 282 module_put(THIS_MODULE); 283} 284 285static int qmgr_init(void) 286{ 287 int i, err; 288 irq_handler_t handler1, handler2; 289 290 mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS, 291 IXP4XX_QMGR_REGION_SIZE, 292 "IXP4xx Queue Manager"); 293 if (mem_res == NULL) 294 return -EBUSY; 295 296 /* reset qmgr registers */ 297 for (i = 0; i < 4; i++) { 298 __raw_writel(0x33333333, &qmgr_regs->stat1[i]); 299 __raw_writel(0, &qmgr_regs->irqsrc[i]); 300 } 301 for (i = 0; i < 2; i++) { 302 __raw_writel(0, &qmgr_regs->stat2[i]); 303 __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[i]); /* clear */ 304 __raw_writel(0, &qmgr_regs->irqen[i]); 305 } 306 307 __raw_writel(0xFFFFFFFF, &qmgr_regs->statne_h); 308 __raw_writel(0, &qmgr_regs->statf_h); 309 310 for (i = 0; i < QUEUES; i++) 311 __raw_writel(0, &qmgr_regs->sram[i]); 312 313 if (cpu_is_ixp42x_rev_a0()) { 314 handler1 = qmgr_irq1_a0; 315 handler2 = qmgr_irq2_a0; 316 } else 317 handler1 = handler2 = qmgr_irq; 318 319 err = request_irq(IRQ_IXP4XX_QM1, handler1, 0, "IXP4xx Queue Manager", 320 NULL); 321 if (err) { 322 printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n", 323 IRQ_IXP4XX_QM1, err); 324 goto error_irq; 325 } 326 327 err = request_irq(IRQ_IXP4XX_QM2, handler2, 0, "IXP4xx Queue Manager", 328 NULL); 329 if (err) { 330 printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n", 331 IRQ_IXP4XX_QM2, err); 332 goto error_irq2; 333 } 334 335 used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */ 336 spin_lock_init(&qmgr_lock); 337 338 printk(KERN_INFO "IXP4xx Queue Manager initialized.\n"); 339 return 0; 340 341error_irq2: 342 free_irq(IRQ_IXP4XX_QM1, NULL); 343error_irq: 344 release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE); 345 return err; 346} 347 348static void qmgr_remove(void) 349{ 350 free_irq(IRQ_IXP4XX_QM1, NULL); 351 free_irq(IRQ_IXP4XX_QM2, NULL); 352 synchronize_irq(IRQ_IXP4XX_QM1); 353 synchronize_irq(IRQ_IXP4XX_QM2); 354 release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE); 355} 356 357module_init(qmgr_init); 358module_exit(qmgr_remove); 359 360MODULE_LICENSE("GPL v2"); 361MODULE_AUTHOR("Krzysztof Halasa"); 362 363EXPORT_SYMBOL(qmgr_set_irq); 364EXPORT_SYMBOL(qmgr_enable_irq); 365EXPORT_SYMBOL(qmgr_disable_irq); 366#if DEBUG_QMGR 367EXPORT_SYMBOL(qmgr_queue_descs); 368EXPORT_SYMBOL(qmgr_request_queue); 369#else 370EXPORT_SYMBOL(__qmgr_request_queue); 371#endif 372EXPORT_SYMBOL(qmgr_release_queue); 373