diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 |
| commit | 5e66dd6d66ffe758b39b6dcadf2330753ee1159b (patch) | |
| tree | a72cdcff4448e4af9425cc213ddf56ab23e697fe /drivers/macintosh/macio_asic.c | |
| parent | 026477c1141b67e98e3bd8bdedb7d4b88a3ecd09 (diff) | |
| parent | ca78f6baca863afe2e6a244a0fe94b3a70211d46 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'drivers/macintosh/macio_asic.c')
| -rw-r--r-- | drivers/macintosh/macio_asic.c | 152 |
1 files changed, 103 insertions, 49 deletions
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 40ae7b6a939d..80c0c665b5f6 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c | |||
| @@ -280,75 +280,128 @@ static void macio_release_dev(struct device *dev) | |||
| 280 | static int macio_resource_quirks(struct device_node *np, struct resource *res, | 280 | static int macio_resource_quirks(struct device_node *np, struct resource *res, |
| 281 | int index) | 281 | int index) |
| 282 | { | 282 | { |
| 283 | if (res->flags & IORESOURCE_MEM) { | 283 | /* Only quirks for memory resources for now */ |
| 284 | /* Grand Central has too large resource 0 on some machines */ | 284 | if ((res->flags & IORESOURCE_MEM) == 0) |
| 285 | if (index == 0 && !strcmp(np->name, "gc")) | 285 | return 0; |
| 286 | res->end = res->start + 0x1ffff; | 286 | |
| 287 | /* Grand Central has too large resource 0 on some machines */ | ||
| 288 | if (index == 0 && !strcmp(np->name, "gc")) | ||
| 289 | res->end = res->start + 0x1ffff; | ||
| 287 | 290 | ||
| 288 | /* Airport has bogus resource 2 */ | 291 | /* Airport has bogus resource 2 */ |
| 289 | if (index >= 2 && !strcmp(np->name, "radio")) | 292 | if (index >= 2 && !strcmp(np->name, "radio")) |
| 290 | return 1; | 293 | return 1; |
| 291 | 294 | ||
| 292 | #ifndef CONFIG_PPC64 | 295 | #ifndef CONFIG_PPC64 |
| 293 | /* DBDMAs may have bogus sizes */ | 296 | /* DBDMAs may have bogus sizes */ |
| 294 | if ((res->start & 0x0001f000) == 0x00008000) | 297 | if ((res->start & 0x0001f000) == 0x00008000) |
| 295 | res->end = res->start + 0xff; | 298 | res->end = res->start + 0xff; |
| 296 | #endif /* CONFIG_PPC64 */ | 299 | #endif /* CONFIG_PPC64 */ |
| 297 | 300 | ||
| 298 | /* ESCC parent eats child resources. We could have added a | 301 | /* ESCC parent eats child resources. We could have added a |
| 299 | * level of hierarchy, but I don't really feel the need | 302 | * level of hierarchy, but I don't really feel the need |
| 300 | * for it | 303 | * for it |
| 301 | */ | 304 | */ |
| 302 | if (!strcmp(np->name, "escc")) | 305 | if (!strcmp(np->name, "escc")) |
| 303 | return 1; | 306 | return 1; |
| 304 | 307 | ||
| 305 | /* ESCC has bogus resources >= 3 */ | 308 | /* ESCC has bogus resources >= 3 */ |
| 306 | if (index >= 3 && !(strcmp(np->name, "ch-a") && | 309 | if (index >= 3 && !(strcmp(np->name, "ch-a") && |
| 307 | strcmp(np->name, "ch-b"))) | 310 | strcmp(np->name, "ch-b"))) |
| 308 | return 1; | 311 | return 1; |
| 309 | 312 | ||
| 310 | /* Media bay has too many resources, keep only first one */ | 313 | /* Media bay has too many resources, keep only first one */ |
| 311 | if (index > 0 && !strcmp(np->name, "media-bay")) | 314 | if (index > 0 && !strcmp(np->name, "media-bay")) |
| 312 | return 1; | 315 | return 1; |
| 313 | 316 | ||
| 314 | /* Some older IDE resources have bogus sizes */ | 317 | /* Some older IDE resources have bogus sizes */ |
| 315 | if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && | 318 | if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && |
| 316 | strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { | 319 | strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { |
| 317 | if (index == 0 && (res->end - res->start) > 0xfff) | 320 | if (index == 0 && (res->end - res->start) > 0xfff) |
| 318 | res->end = res->start + 0xfff; | 321 | res->end = res->start + 0xfff; |
| 319 | if (index == 1 && (res->end - res->start) > 0xff) | 322 | if (index == 1 && (res->end - res->start) > 0xff) |
| 320 | res->end = res->start + 0xff; | 323 | res->end = res->start + 0xff; |
| 321 | } | ||
| 322 | } | 324 | } |
| 323 | return 0; | 325 | return 0; |
| 324 | } | 326 | } |
| 325 | 327 | ||
| 328 | static void macio_create_fixup_irq(struct macio_dev *dev, int index, | ||
| 329 | unsigned int line) | ||
| 330 | { | ||
| 331 | unsigned int irq; | ||
| 326 | 332 | ||
| 327 | static void macio_setup_interrupts(struct macio_dev *dev) | 333 | irq = irq_create_mapping(NULL, line, 0); |
| 334 | if (irq != NO_IRQ) { | ||
| 335 | dev->interrupt[index].start = irq; | ||
| 336 | dev->interrupt[index].flags = IORESOURCE_IRQ; | ||
| 337 | dev->interrupt[index].name = dev->ofdev.dev.bus_id; | ||
| 338 | } | ||
| 339 | if (dev->n_interrupts <= index) | ||
| 340 | dev->n_interrupts = index + 1; | ||
| 341 | } | ||
| 342 | |||
| 343 | static void macio_add_missing_resources(struct macio_dev *dev) | ||
| 328 | { | 344 | { |
| 329 | struct device_node *np = dev->ofdev.node; | 345 | struct device_node *np = dev->ofdev.node; |
| 330 | int i,j; | 346 | unsigned int irq_base; |
| 347 | |||
| 348 | /* Gatwick has some missing interrupts on child nodes */ | ||
| 349 | if (dev->bus->chip->type != macio_gatwick) | ||
| 350 | return; | ||
| 331 | 351 | ||
| 332 | /* For now, we use pre-parsed entries in the device-tree for | 352 | /* irq_base is always 64 on gatwick. I have no cleaner way to get |
| 333 | * interrupt routing and addresses, but we should change that | 353 | * that value from here at this point |
| 334 | * to dynamically parsed entries and so get rid of most of the | ||
| 335 | * clutter in struct device_node | ||
| 336 | */ | 354 | */ |
| 337 | for (i = j = 0; i < np->n_intrs; i++) { | 355 | irq_base = 64; |
| 356 | |||
| 357 | /* Fix SCC */ | ||
| 358 | if (strcmp(np->name, "ch-a") == 0) { | ||
| 359 | macio_create_fixup_irq(dev, 0, 15 + irq_base); | ||
| 360 | macio_create_fixup_irq(dev, 1, 4 + irq_base); | ||
| 361 | macio_create_fixup_irq(dev, 2, 5 + irq_base); | ||
| 362 | printk(KERN_INFO "macio: fixed SCC irqs on gatwick\n"); | ||
| 363 | } | ||
| 364 | |||
| 365 | /* Fix media-bay */ | ||
| 366 | if (strcmp(np->name, "media-bay") == 0) { | ||
| 367 | macio_create_fixup_irq(dev, 0, 29 + irq_base); | ||
| 368 | printk(KERN_INFO "macio: fixed media-bay irq on gatwick\n"); | ||
| 369 | } | ||
| 370 | |||
| 371 | /* Fix left media bay childs */ | ||
| 372 | if (dev->media_bay != NULL && strcmp(np->name, "floppy") == 0) { | ||
| 373 | macio_create_fixup_irq(dev, 0, 19 + irq_base); | ||
| 374 | macio_create_fixup_irq(dev, 1, 1 + irq_base); | ||
| 375 | printk(KERN_INFO "macio: fixed left floppy irqs\n"); | ||
| 376 | } | ||
| 377 | if (dev->media_bay != NULL && strcasecmp(np->name, "ata4") == 0) { | ||
| 378 | macio_create_fixup_irq(dev, 0, 14 + irq_base); | ||
| 379 | macio_create_fixup_irq(dev, 0, 3 + irq_base); | ||
| 380 | printk(KERN_INFO "macio: fixed left ide irqs\n"); | ||
| 381 | } | ||
| 382 | } | ||
| 383 | |||
| 384 | static void macio_setup_interrupts(struct macio_dev *dev) | ||
| 385 | { | ||
| 386 | struct device_node *np = dev->ofdev.node; | ||
| 387 | unsigned int irq; | ||
| 388 | int i = 0, j = 0; | ||
| 389 | |||
| 390 | for (;;) { | ||
| 338 | struct resource *res = &dev->interrupt[j]; | 391 | struct resource *res = &dev->interrupt[j]; |
| 339 | 392 | ||
| 340 | if (j >= MACIO_DEV_COUNT_IRQS) | 393 | if (j >= MACIO_DEV_COUNT_IRQS) |
| 341 | break; | 394 | break; |
| 342 | res->start = np->intrs[i].line; | 395 | irq = irq_of_parse_and_map(np, i++); |
| 343 | res->flags = IORESOURCE_IO; | 396 | if (irq == NO_IRQ) |
| 344 | if (np->intrs[j].sense) | 397 | break; |
| 345 | res->flags |= IORESOURCE_IRQ_LOWLEVEL; | 398 | res->start = irq; |
| 346 | else | 399 | res->flags = IORESOURCE_IRQ; |
| 347 | res->flags |= IORESOURCE_IRQ_HIGHEDGE; | ||
| 348 | res->name = dev->ofdev.dev.bus_id; | 400 | res->name = dev->ofdev.dev.bus_id; |
| 349 | if (macio_resource_quirks(np, res, i)) | 401 | if (macio_resource_quirks(np, res, i - 1)) { |
| 350 | memset(res, 0, sizeof(struct resource)); | 402 | memset(res, 0, sizeof(struct resource)); |
| 351 | else | 403 | continue; |
| 404 | } else | ||
| 352 | j++; | 405 | j++; |
| 353 | } | 406 | } |
| 354 | dev->n_interrupts = j; | 407 | dev->n_interrupts = j; |
| @@ -445,6 +498,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, | |||
| 445 | /* Setup interrupts & resources */ | 498 | /* Setup interrupts & resources */ |
| 446 | macio_setup_interrupts(dev); | 499 | macio_setup_interrupts(dev); |
| 447 | macio_setup_resources(dev, parent_res); | 500 | macio_setup_resources(dev, parent_res); |
| 501 | macio_add_missing_resources(dev); | ||
| 448 | 502 | ||
| 449 | /* Register with core */ | 503 | /* Register with core */ |
| 450 | if (of_device_register(&dev->ofdev) != 0) { | 504 | if (of_device_register(&dev->ofdev) != 0) { |
