Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.26 420 lines 9.9 kB view raw
1/* 2 * Copyright 2007, Michael Ellerman, IBM Corporation. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 */ 9 10 11#include <linux/interrupt.h> 12#include <linux/irq.h> 13#include <linux/kernel.h> 14#include <linux/pci.h> 15#include <linux/msi.h> 16#include <linux/of_platform.h> 17 18#include <asm/dcr.h> 19#include <asm/machdep.h> 20#include <asm/prom.h> 21 22 23/* 24 * MSIC registers, specified as offsets from dcr_base 25 */ 26#define MSIC_CTRL_REG 0x0 27 28/* Base Address registers specify FIFO location in BE memory */ 29#define MSIC_BASE_ADDR_HI_REG 0x3 30#define MSIC_BASE_ADDR_LO_REG 0x4 31 32/* Hold the read/write offsets into the FIFO */ 33#define MSIC_READ_OFFSET_REG 0x5 34#define MSIC_WRITE_OFFSET_REG 0x6 35 36 37/* MSIC control register flags */ 38#define MSIC_CTRL_ENABLE 0x0001 39#define MSIC_CTRL_FIFO_FULL_ENABLE 0x0002 40#define MSIC_CTRL_IRQ_ENABLE 0x0008 41#define MSIC_CTRL_FULL_STOP_ENABLE 0x0010 42 43/* 44 * The MSIC can be configured to use a FIFO of 32KB, 64KB, 128KB or 256KB. 45 * Currently we're using a 64KB FIFO size. 46 */ 47#define MSIC_FIFO_SIZE_SHIFT 16 48#define MSIC_FIFO_SIZE_BYTES (1 << MSIC_FIFO_SIZE_SHIFT) 49 50/* 51 * To configure the FIFO size as (1 << n) bytes, we write (n - 15) into bits 52 * 8-9 of the MSIC control reg. 53 */ 54#define MSIC_CTRL_FIFO_SIZE (((MSIC_FIFO_SIZE_SHIFT - 15) << 8) & 0x300) 55 56/* 57 * We need to mask the read/write offsets to make sure they stay within 58 * the bounds of the FIFO. Also they should always be 16-byte aligned. 59 */ 60#define MSIC_FIFO_SIZE_MASK ((MSIC_FIFO_SIZE_BYTES - 1) & ~0xFu) 61 62/* Each entry in the FIFO is 16 bytes, the first 4 bytes hold the irq # */ 63#define MSIC_FIFO_ENTRY_SIZE 0x10 64 65 66struct axon_msic { 67 struct irq_host *irq_host; 68 __le32 *fifo_virt; 69 dma_addr_t fifo_phys; 70 dcr_host_t dcr_host; 71 u32 read_offset; 72}; 73 74static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val) 75{ 76 pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n); 77 78 dcr_write(msic->dcr_host, dcr_n, val); 79} 80 81static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc) 82{ 83 struct axon_msic *msic = get_irq_data(irq); 84 u32 write_offset, msi; 85 int idx; 86 87 write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG); 88 pr_debug("axon_msi: original write_offset 0x%x\n", write_offset); 89 90 /* write_offset doesn't wrap properly, so we have to mask it */ 91 write_offset &= MSIC_FIFO_SIZE_MASK; 92 93 while (msic->read_offset != write_offset) { 94 idx = msic->read_offset / sizeof(__le32); 95 msi = le32_to_cpu(msic->fifo_virt[idx]); 96 msi &= 0xFFFF; 97 98 pr_debug("axon_msi: woff %x roff %x msi %x\n", 99 write_offset, msic->read_offset, msi); 100 101 msic->read_offset += MSIC_FIFO_ENTRY_SIZE; 102 msic->read_offset &= MSIC_FIFO_SIZE_MASK; 103 104 if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host) 105 generic_handle_irq(msi); 106 else 107 pr_debug("axon_msi: invalid irq 0x%x!\n", msi); 108 } 109 110 desc->chip->eoi(irq); 111} 112 113static struct axon_msic *find_msi_translator(struct pci_dev *dev) 114{ 115 struct irq_host *irq_host; 116 struct device_node *dn, *tmp; 117 const phandle *ph; 118 struct axon_msic *msic = NULL; 119 120 dn = of_node_get(pci_device_to_OF_node(dev)); 121 if (!dn) { 122 dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n"); 123 return NULL; 124 } 125 126 for (; dn; dn = of_get_next_parent(dn)) { 127 ph = of_get_property(dn, "msi-translator", NULL); 128 if (ph) 129 break; 130 } 131 132 if (!ph) { 133 dev_dbg(&dev->dev, 134 "axon_msi: no msi-translator property found\n"); 135 goto out_error; 136 } 137 138 tmp = dn; 139 dn = of_find_node_by_phandle(*ph); 140 of_node_put(tmp); 141 if (!dn) { 142 dev_dbg(&dev->dev, 143 "axon_msi: msi-translator doesn't point to a node\n"); 144 goto out_error; 145 } 146 147 irq_host = irq_find_host(dn); 148 if (!irq_host) { 149 dev_dbg(&dev->dev, "axon_msi: no irq_host found for node %s\n", 150 dn->full_name); 151 goto out_error; 152 } 153 154 msic = irq_host->host_data; 155 156out_error: 157 of_node_put(dn); 158 159 return msic; 160} 161 162static int axon_msi_check_device(struct pci_dev *dev, int nvec, int type) 163{ 164 if (!find_msi_translator(dev)) 165 return -ENODEV; 166 167 return 0; 168} 169 170static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg) 171{ 172 struct device_node *dn; 173 struct msi_desc *entry; 174 int len; 175 const u32 *prop; 176 177 dn = of_node_get(pci_device_to_OF_node(dev)); 178 if (!dn) { 179 dev_dbg(&dev->dev, "axon_msi: no pci_dn found\n"); 180 return -ENODEV; 181 } 182 183 entry = list_first_entry(&dev->msi_list, struct msi_desc, list); 184 185 for (; dn; dn = of_get_next_parent(dn)) { 186 if (entry->msi_attrib.is_64) { 187 prop = of_get_property(dn, "msi-address-64", &len); 188 if (prop) 189 break; 190 } 191 192 prop = of_get_property(dn, "msi-address-32", &len); 193 if (prop) 194 break; 195 } 196 197 if (!prop) { 198 dev_dbg(&dev->dev, 199 "axon_msi: no msi-address-(32|64) properties found\n"); 200 return -ENOENT; 201 } 202 203 switch (len) { 204 case 8: 205 msg->address_hi = prop[0]; 206 msg->address_lo = prop[1]; 207 break; 208 case 4: 209 msg->address_hi = 0; 210 msg->address_lo = prop[0]; 211 break; 212 default: 213 dev_dbg(&dev->dev, 214 "axon_msi: malformed msi-address-(32|64) property\n"); 215 of_node_put(dn); 216 return -EINVAL; 217 } 218 219 of_node_put(dn); 220 221 return 0; 222} 223 224static int axon_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 225{ 226 unsigned int virq, rc; 227 struct msi_desc *entry; 228 struct msi_msg msg; 229 struct axon_msic *msic; 230 231 msic = find_msi_translator(dev); 232 if (!msic) 233 return -ENODEV; 234 235 rc = setup_msi_msg_address(dev, &msg); 236 if (rc) 237 return rc; 238 239 /* We rely on being able to stash a virq in a u16 */ 240 BUILD_BUG_ON(NR_IRQS > 65536); 241 242 list_for_each_entry(entry, &dev->msi_list, list) { 243 virq = irq_create_direct_mapping(msic->irq_host); 244 if (virq == NO_IRQ) { 245 dev_warn(&dev->dev, 246 "axon_msi: virq allocation failed!\n"); 247 return -1; 248 } 249 dev_dbg(&dev->dev, "axon_msi: allocated virq 0x%x\n", virq); 250 251 set_irq_msi(virq, entry); 252 msg.data = virq; 253 write_msi_msg(virq, &msg); 254 } 255 256 return 0; 257} 258 259static void axon_msi_teardown_msi_irqs(struct pci_dev *dev) 260{ 261 struct msi_desc *entry; 262 263 dev_dbg(&dev->dev, "axon_msi: tearing down msi irqs\n"); 264 265 list_for_each_entry(entry, &dev->msi_list, list) { 266 if (entry->irq == NO_IRQ) 267 continue; 268 269 set_irq_msi(entry->irq, NULL); 270 irq_dispose_mapping(entry->irq); 271 } 272} 273 274static struct irq_chip msic_irq_chip = { 275 .mask = mask_msi_irq, 276 .unmask = unmask_msi_irq, 277 .shutdown = unmask_msi_irq, 278 .typename = "AXON-MSI", 279}; 280 281static int msic_host_map(struct irq_host *h, unsigned int virq, 282 irq_hw_number_t hw) 283{ 284 set_irq_chip_and_handler(virq, &msic_irq_chip, handle_simple_irq); 285 286 return 0; 287} 288 289static struct irq_host_ops msic_host_ops = { 290 .map = msic_host_map, 291}; 292 293static int axon_msi_shutdown(struct of_device *device) 294{ 295 struct axon_msic *msic = device->dev.platform_data; 296 u32 tmp; 297 298 pr_debug("axon_msi: disabling %s\n", 299 msic->irq_host->of_node->full_name); 300 tmp = dcr_read(msic->dcr_host, MSIC_CTRL_REG); 301 tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE; 302 msic_dcr_write(msic, MSIC_CTRL_REG, tmp); 303 304 return 0; 305} 306 307static int axon_msi_probe(struct of_device *device, 308 const struct of_device_id *device_id) 309{ 310 struct device_node *dn = device->node; 311 struct axon_msic *msic; 312 unsigned int virq; 313 int dcr_base, dcr_len; 314 315 pr_debug("axon_msi: setting up dn %s\n", dn->full_name); 316 317 msic = kzalloc(sizeof(struct axon_msic), GFP_KERNEL); 318 if (!msic) { 319 printk(KERN_ERR "axon_msi: couldn't allocate msic for %s\n", 320 dn->full_name); 321 goto out; 322 } 323 324 dcr_base = dcr_resource_start(dn, 0); 325 dcr_len = dcr_resource_len(dn, 0); 326 327 if (dcr_base == 0 || dcr_len == 0) { 328 printk(KERN_ERR 329 "axon_msi: couldn't parse dcr properties on %s\n", 330 dn->full_name); 331 goto out; 332 } 333 334 msic->dcr_host = dcr_map(dn, dcr_base, dcr_len); 335 if (!DCR_MAP_OK(msic->dcr_host)) { 336 printk(KERN_ERR "axon_msi: dcr_map failed for %s\n", 337 dn->full_name); 338 goto out_free_msic; 339 } 340 341 msic->fifo_virt = dma_alloc_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, 342 &msic->fifo_phys, GFP_KERNEL); 343 if (!msic->fifo_virt) { 344 printk(KERN_ERR "axon_msi: couldn't allocate fifo for %s\n", 345 dn->full_name); 346 goto out_free_msic; 347 } 348 349 msic->irq_host = irq_alloc_host(of_node_get(dn), IRQ_HOST_MAP_NOMAP, 350 NR_IRQS, &msic_host_ops, 0); 351 if (!msic->irq_host) { 352 printk(KERN_ERR "axon_msi: couldn't allocate irq_host for %s\n", 353 dn->full_name); 354 goto out_free_fifo; 355 } 356 357 msic->irq_host->host_data = msic; 358 359 virq = irq_of_parse_and_map(dn, 0); 360 if (virq == NO_IRQ) { 361 printk(KERN_ERR "axon_msi: irq parse and map failed for %s\n", 362 dn->full_name); 363 goto out_free_host; 364 } 365 366 set_irq_data(virq, msic); 367 set_irq_chained_handler(virq, axon_msi_cascade); 368 pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq); 369 370 /* Enable the MSIC hardware */ 371 msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32); 372 msic_dcr_write(msic, MSIC_BASE_ADDR_LO_REG, 373 msic->fifo_phys & 0xFFFFFFFF); 374 msic_dcr_write(msic, MSIC_CTRL_REG, 375 MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE | 376 MSIC_CTRL_FIFO_SIZE); 377 378 device->dev.platform_data = msic; 379 380 ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs; 381 ppc_md.teardown_msi_irqs = axon_msi_teardown_msi_irqs; 382 ppc_md.msi_check_device = axon_msi_check_device; 383 384 printk(KERN_DEBUG "axon_msi: setup MSIC on %s\n", dn->full_name); 385 386 return 0; 387 388out_free_host: 389 kfree(msic->irq_host); 390out_free_fifo: 391 dma_free_coherent(&device->dev, MSIC_FIFO_SIZE_BYTES, msic->fifo_virt, 392 msic->fifo_phys); 393out_free_msic: 394 kfree(msic); 395out: 396 397 return -1; 398} 399 400static const struct of_device_id axon_msi_device_id[] = { 401 { 402 .compatible = "ibm,axon-msic" 403 }, 404 {} 405}; 406 407static struct of_platform_driver axon_msi_driver = { 408 .match_table = axon_msi_device_id, 409 .probe = axon_msi_probe, 410 .shutdown = axon_msi_shutdown, 411 .driver = { 412 .name = "axon-msi" 413 }, 414}; 415 416static int __init axon_msi_init(void) 417{ 418 return of_register_platform_driver(&axon_msi_driver); 419} 420subsys_initcall(axon_msi_init);