diff options
Diffstat (limited to 'drivers/macintosh/macio_asic.c')
-rw-r--r-- | drivers/macintosh/macio_asic.c | 254 |
1 files changed, 148 insertions, 106 deletions
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 228e1852a836..2a545ceb523b 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c | |||
@@ -3,6 +3,13 @@ | |||
3 | * a MacIO ASIC. Interface to new driver model mostly | 3 | * a MacIO ASIC. Interface to new driver model mostly |
4 | * stolen from the PCI version. | 4 | * stolen from the PCI version. |
5 | * | 5 | * |
6 | * Copyright (C) 2005 Ben. Herrenschmidt (benh@kernel.crashing.org) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * | ||
6 | * TODO: | 13 | * TODO: |
7 | * | 14 | * |
8 | * - Don't probe below media bay by default, but instead provide | 15 | * - Don't probe below media bay by default, but instead provide |
@@ -218,12 +225,14 @@ postcore_initcall(macio_bus_driver_init); | |||
218 | 225 | ||
219 | 226 | ||
220 | /** | 227 | /** |
221 | * macio_release_dev - free a macio device structure when all users of it are finished. | 228 | * macio_release_dev - free a macio device structure when all users of it are |
229 | * finished. | ||
222 | * @dev: device that's been disconnected | 230 | * @dev: device that's been disconnected |
223 | * | 231 | * |
224 | * Will be called only by the device core when all users of this macio device are | 232 | * Will be called only by the device core when all users of this macio device |
225 | * done. This currently means never as we don't hot remove any macio device yet, | 233 | * are done. This currently means never as we don't hot remove any macio |
226 | * though that will happen with mediabay based devices in a later implementation. | 234 | * device yet, though that will happen with mediabay based devices in a later |
235 | * implementation. | ||
227 | */ | 236 | */ |
228 | static void macio_release_dev(struct device *dev) | 237 | static void macio_release_dev(struct device *dev) |
229 | { | 238 | { |
@@ -242,49 +251,114 @@ static void macio_release_dev(struct device *dev) | |||
242 | * If this routine returns non-null, then the resource is completely | 251 | * If this routine returns non-null, then the resource is completely |
243 | * skipped. | 252 | * skipped. |
244 | */ | 253 | */ |
245 | static int macio_resource_quirks(struct device_node *np, struct resource *res, int index) | 254 | static int macio_resource_quirks(struct device_node *np, struct resource *res, |
255 | int index) | ||
246 | { | 256 | { |
247 | if (res->flags & IORESOURCE_MEM) { | 257 | if (res->flags & IORESOURCE_MEM) { |
248 | /* Grand Central has too large resource 0 on some machines */ | 258 | /* Grand Central has too large resource 0 on some machines */ |
249 | if (index == 0 && !strcmp(np->name, "gc")) { | 259 | if (index == 0 && !strcmp(np->name, "gc")) |
250 | np->addrs[0].size = 0x20000; | ||
251 | res->end = res->start + 0x1ffff; | 260 | res->end = res->start + 0x1ffff; |
252 | } | 261 | |
253 | /* Airport has bogus resource 2 */ | 262 | /* Airport has bogus resource 2 */ |
254 | if (index >= 2 && !strcmp(np->name, "radio")) | 263 | if (index >= 2 && !strcmp(np->name, "radio")) |
255 | return 1; | 264 | return 1; |
265 | |||
266 | #ifndef CONFIG_PPC64 | ||
256 | /* DBDMAs may have bogus sizes */ | 267 | /* DBDMAs may have bogus sizes */ |
257 | if ((res->start & 0x0001f000) == 0x00008000) { | 268 | if ((res->start & 0x0001f000) == 0x00008000) |
258 | np->addrs[index].size = 0x100; | ||
259 | res->end = res->start + 0xff; | 269 | res->end = res->start + 0xff; |
260 | } | 270 | #endif /* CONFIG_PPC64 */ |
261 | /* ESCC parent eats child resources. We could have added a level of hierarchy, | 271 | |
262 | * but I don't really feel the need for it */ | 272 | /* ESCC parent eats child resources. We could have added a |
273 | * level of hierarchy, but I don't really feel the need | ||
274 | * for it | ||
275 | */ | ||
263 | if (!strcmp(np->name, "escc")) | 276 | if (!strcmp(np->name, "escc")) |
264 | return 1; | 277 | return 1; |
278 | |||
265 | /* ESCC has bogus resources >= 3 */ | 279 | /* ESCC has bogus resources >= 3 */ |
266 | if (index >= 3 && !(strcmp(np->name, "ch-a") && strcmp(np->name, "ch-b"))) | 280 | if (index >= 3 && !(strcmp(np->name, "ch-a") && |
281 | strcmp(np->name, "ch-b"))) | ||
267 | return 1; | 282 | return 1; |
283 | |||
268 | /* Media bay has too many resources, keep only first one */ | 284 | /* Media bay has too many resources, keep only first one */ |
269 | if (index > 0 && !strcmp(np->name, "media-bay")) | 285 | if (index > 0 && !strcmp(np->name, "media-bay")) |
270 | return 1; | 286 | return 1; |
287 | |||
271 | /* Some older IDE resources have bogus sizes */ | 288 | /* Some older IDE resources have bogus sizes */ |
272 | if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && | 289 | if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && |
273 | strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { | 290 | strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { |
274 | if (index == 0 && np->addrs[0].size > 0x1000) { | 291 | if (index == 0 && (res->end - res->start) > 0xfff) |
275 | np->addrs[0].size = 0x1000; | ||
276 | res->end = res->start + 0xfff; | 292 | res->end = res->start + 0xfff; |
277 | } | 293 | if (index == 1 && (res->end - res->start) > 0xff) |
278 | if (index == 1 && np->addrs[1].size > 0x100) { | ||
279 | np->addrs[1].size = 0x100; | ||
280 | res->end = res->start + 0xff; | 294 | res->end = res->start + 0xff; |
281 | } | ||
282 | } | 295 | } |
283 | } | 296 | } |
284 | return 0; | 297 | return 0; |
285 | } | 298 | } |
286 | 299 | ||
287 | 300 | ||
301 | static void macio_setup_interrupts(struct macio_dev *dev) | ||
302 | { | ||
303 | struct device_node *np = dev->ofdev.node; | ||
304 | int i,j; | ||
305 | |||
306 | /* For now, we use pre-parsed entries in the device-tree for | ||
307 | * interrupt routing and addresses, but we should change that | ||
308 | * to dynamically parsed entries and so get rid of most of the | ||
309 | * clutter in struct device_node | ||
310 | */ | ||
311 | for (i = j = 0; i < np->n_intrs; i++) { | ||
312 | struct resource *res = &dev->interrupt[j]; | ||
313 | |||
314 | if (j >= MACIO_DEV_COUNT_IRQS) | ||
315 | break; | ||
316 | res->start = np->intrs[i].line; | ||
317 | res->flags = IORESOURCE_IO; | ||
318 | if (np->intrs[j].sense) | ||
319 | res->flags |= IORESOURCE_IRQ_LOWLEVEL; | ||
320 | else | ||
321 | res->flags |= IORESOURCE_IRQ_HIGHEDGE; | ||
322 | res->name = dev->ofdev.dev.bus_id; | ||
323 | if (macio_resource_quirks(np, res, i)) | ||
324 | memset(res, 0, sizeof(struct resource)); | ||
325 | else | ||
326 | j++; | ||
327 | } | ||
328 | dev->n_interrupts = j; | ||
329 | } | ||
330 | |||
331 | static void macio_setup_resources(struct macio_dev *dev, | ||
332 | struct resource *parent_res) | ||
333 | { | ||
334 | struct device_node *np = dev->ofdev.node; | ||
335 | struct resource r; | ||
336 | int index; | ||
337 | |||
338 | for (index = 0; of_address_to_resource(np, index, &r) == 0; index++) { | ||
339 | struct resource *res = &dev->resource[index]; | ||
340 | if (index >= MACIO_DEV_COUNT_RESOURCES) | ||
341 | break; | ||
342 | *res = r; | ||
343 | res->name = dev->ofdev.dev.bus_id; | ||
344 | |||
345 | if (macio_resource_quirks(np, res, index)) { | ||
346 | memset(res, 0, sizeof(struct resource)); | ||
347 | continue; | ||
348 | } | ||
349 | /* Currently, we consider failure as harmless, this may | ||
350 | * change in the future, once I've found all the device | ||
351 | * tree bugs in older machines & worked around them | ||
352 | */ | ||
353 | if (insert_resource(parent_res, res)) { | ||
354 | printk(KERN_WARNING "Can't request resource " | ||
355 | "%d for MacIO device %s\n", | ||
356 | index, dev->ofdev.dev.bus_id); | ||
357 | } | ||
358 | } | ||
359 | dev->n_resources = index; | ||
360 | } | ||
361 | |||
288 | /** | 362 | /** |
289 | * macio_add_one_device - Add one device from OF node to the device tree | 363 | * macio_add_one_device - Add one device from OF node to the device tree |
290 | * @chip: pointer to the macio_chip holding the device | 364 | * @chip: pointer to the macio_chip holding the device |
@@ -294,12 +368,13 @@ static int macio_resource_quirks(struct device_node *np, struct resource *res, i | |||
294 | * When media-bay is changed to hotswap drivers, this function will | 368 | * When media-bay is changed to hotswap drivers, this function will |
295 | * be exposed to the bay driver some way... | 369 | * be exposed to the bay driver some way... |
296 | */ | 370 | */ |
297 | static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct device *parent, | 371 | static struct macio_dev * macio_add_one_device(struct macio_chip *chip, |
298 | struct device_node *np, struct macio_dev *in_bay, | 372 | struct device *parent, |
373 | struct device_node *np, | ||
374 | struct macio_dev *in_bay, | ||
299 | struct resource *parent_res) | 375 | struct resource *parent_res) |
300 | { | 376 | { |
301 | struct macio_dev *dev; | 377 | struct macio_dev *dev; |
302 | int i, j; | ||
303 | u32 *reg; | 378 | u32 *reg; |
304 | 379 | ||
305 | if (np == NULL) | 380 | if (np == NULL) |
@@ -326,7 +401,8 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct d | |||
326 | 401 | ||
327 | /* MacIO itself has a different reg, we use it's PCI base */ | 402 | /* MacIO itself has a different reg, we use it's PCI base */ |
328 | if (np == chip->of_node) { | 403 | if (np == chip->of_node) { |
329 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s", chip->lbus.index, | 404 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s", |
405 | chip->lbus.index, | ||
330 | #ifdef CONFIG_PCI | 406 | #ifdef CONFIG_PCI |
331 | pci_resource_start(chip->lbus.pdev, 0), | 407 | pci_resource_start(chip->lbus.pdev, 0), |
332 | #else | 408 | #else |
@@ -335,57 +411,16 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct d | |||
335 | MAX_NODE_NAME_SIZE, np->name); | 411 | MAX_NODE_NAME_SIZE, np->name); |
336 | } else { | 412 | } else { |
337 | reg = (u32 *)get_property(np, "reg", NULL); | 413 | reg = (u32 *)get_property(np, "reg", NULL); |
338 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", chip->lbus.index, | 414 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", |
415 | chip->lbus.index, | ||
339 | reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name); | 416 | reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name); |
340 | } | 417 | } |
341 | 418 | ||
342 | /* For now, we use pre-parsed entries in the device-tree for | 419 | /* Setup interrupts & resources */ |
343 | * interrupt routing and addresses, but we should change that | 420 | macio_setup_interrupts(dev); |
344 | * to dynamically parsed entries and so get rid of most of the | 421 | macio_setup_resources(dev, parent_res); |
345 | * clutter in struct device_node | ||
346 | */ | ||
347 | for (i = j = 0; i < np->n_intrs; i++) { | ||
348 | struct resource *res = &dev->interrupt[j]; | ||
349 | |||
350 | if (j >= MACIO_DEV_COUNT_IRQS) | ||
351 | break; | ||
352 | res->start = np->intrs[i].line; | ||
353 | res->flags = IORESOURCE_IO; | ||
354 | if (np->intrs[j].sense) | ||
355 | res->flags |= IORESOURCE_IRQ_LOWLEVEL; | ||
356 | else | ||
357 | res->flags |= IORESOURCE_IRQ_HIGHEDGE; | ||
358 | res->name = dev->ofdev.dev.bus_id; | ||
359 | if (macio_resource_quirks(np, res, i)) | ||
360 | memset(res, 0, sizeof(struct resource)); | ||
361 | else | ||
362 | j++; | ||
363 | } | ||
364 | dev->n_interrupts = j; | ||
365 | for (i = j = 0; i < np->n_addrs; i++) { | ||
366 | struct resource *res = &dev->resource[j]; | ||
367 | |||
368 | if (j >= MACIO_DEV_COUNT_RESOURCES) | ||
369 | break; | ||
370 | res->start = np->addrs[i].address; | ||
371 | res->end = np->addrs[i].address + np->addrs[i].size - 1; | ||
372 | res->flags = IORESOURCE_MEM; | ||
373 | res->name = dev->ofdev.dev.bus_id; | ||
374 | if (macio_resource_quirks(np, res, i)) | ||
375 | memset(res, 0, sizeof(struct resource)); | ||
376 | else { | ||
377 | j++; | ||
378 | /* Currently, we consider failure as harmless, this may | ||
379 | * change in the future, once I've found all the device | ||
380 | * tree bugs in older machines & worked around them | ||
381 | */ | ||
382 | if (insert_resource(parent_res, res)) | ||
383 | printk(KERN_WARNING "Can't request resource %d for MacIO" | ||
384 | " device %s\n", i, dev->ofdev.dev.bus_id); | ||
385 | } | ||
386 | } | ||
387 | dev->n_resources = j; | ||
388 | 422 | ||
423 | /* Register with core */ | ||
389 | if (of_device_register(&dev->ofdev) != 0) { | 424 | if (of_device_register(&dev->ofdev) != 0) { |
390 | printk(KERN_DEBUG"macio: device registration error for %s!\n", | 425 | printk(KERN_DEBUG"macio: device registration error for %s!\n", |
391 | dev->ofdev.dev.bus_id); | 426 | dev->ofdev.dev.bus_id); |
@@ -442,36 +477,42 @@ static void macio_pci_add_devices(struct macio_chip *chip) | |||
442 | 477 | ||
443 | /* First scan 1st level */ | 478 | /* First scan 1st level */ |
444 | for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) { | 479 | for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) { |
445 | if (!macio_skip_device(np)) { | 480 | if (macio_skip_device(np)) |
446 | of_node_get(np); | 481 | continue; |
447 | mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL, root_res); | 482 | of_node_get(np); |
448 | if (mdev == NULL) | 483 | mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL, |
449 | of_node_put(np); | 484 | root_res); |
450 | else if (strncmp(np->name, "media-bay", 9) == 0) | 485 | if (mdev == NULL) |
451 | mbdev = mdev; | 486 | of_node_put(np); |
452 | else if (strncmp(np->name, "escc", 4) == 0) | 487 | else if (strncmp(np->name, "media-bay", 9) == 0) |
453 | sdev = mdev; | 488 | mbdev = mdev; |
454 | } | 489 | else if (strncmp(np->name, "escc", 4) == 0) |
490 | sdev = mdev; | ||
455 | } | 491 | } |
456 | 492 | ||
457 | /* Add media bay devices if any */ | 493 | /* Add media bay devices if any */ |
458 | if (mbdev) | 494 | if (mbdev) |
459 | for (np = NULL; (np = of_get_next_child(mbdev->ofdev.node, np)) != NULL;) | 495 | for (np = NULL; (np = of_get_next_child(mbdev->ofdev.node, np)) |
460 | if (!macio_skip_device(np)) { | 496 | != NULL;) { |
461 | of_node_get(np); | 497 | if (macio_skip_device(np)) |
462 | if (macio_add_one_device(chip, &mbdev->ofdev.dev, np, mbdev, | 498 | continue; |
463 | root_res) == NULL) | 499 | of_node_get(np); |
464 | of_node_put(np); | 500 | if (macio_add_one_device(chip, &mbdev->ofdev.dev, np, |
465 | } | 501 | mbdev, root_res) == NULL) |
502 | of_node_put(np); | ||
503 | } | ||
504 | |||
466 | /* Add serial ports if any */ | 505 | /* Add serial ports if any */ |
467 | if (sdev) { | 506 | if (sdev) { |
468 | for (np = NULL; (np = of_get_next_child(sdev->ofdev.node, np)) != NULL;) | 507 | for (np = NULL; (np = of_get_next_child(sdev->ofdev.node, np)) |
469 | if (!macio_skip_device(np)) { | 508 | != NULL;) { |
470 | of_node_get(np); | 509 | if (macio_skip_device(np)) |
471 | if (macio_add_one_device(chip, &sdev->ofdev.dev, np, NULL, | 510 | continue; |
472 | root_res) == NULL) | 511 | of_node_get(np); |
473 | of_node_put(np); | 512 | if (macio_add_one_device(chip, &sdev->ofdev.dev, np, |
474 | } | 513 | NULL, root_res) == NULL) |
514 | of_node_put(np); | ||
515 | } | ||
475 | } | 516 | } |
476 | } | 517 | } |
477 | 518 | ||
@@ -519,7 +560,8 @@ void macio_unregister_driver(struct macio_driver *drv) | |||
519 | * Returns 0 on success, or %EBUSY on error. A warning | 560 | * Returns 0 on success, or %EBUSY on error. A warning |
520 | * message is also printed on failure. | 561 | * message is also printed on failure. |
521 | */ | 562 | */ |
522 | int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name) | 563 | int macio_request_resource(struct macio_dev *dev, int resource_no, |
564 | const char *name) | ||
523 | { | 565 | { |
524 | if (macio_resource_len(dev, resource_no) == 0) | 566 | if (macio_resource_len(dev, resource_no) == 0) |
525 | return 0; | 567 | return 0; |
@@ -606,20 +648,20 @@ static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
606 | if (ent->vendor != PCI_VENDOR_ID_APPLE) | 648 | if (ent->vendor != PCI_VENDOR_ID_APPLE) |
607 | return -ENODEV; | 649 | return -ENODEV; |
608 | 650 | ||
609 | /* Note regarding refcounting: We assume pci_device_to_OF_node() is ported | 651 | /* Note regarding refcounting: We assume pci_device_to_OF_node() is |
610 | * to new OF APIs and returns a node with refcount incremented. This isn't | 652 | * ported to new OF APIs and returns a node with refcount incremented. |
611 | * the case today, but on the other hand ppc32 doesn't do refcounting. This | ||
612 | * will have to be fixed when going to ppc64. --BenH. | ||
613 | */ | 653 | */ |
614 | np = pci_device_to_OF_node(pdev); | 654 | np = pci_device_to_OF_node(pdev); |
615 | if (np == NULL) | 655 | if (np == NULL) |
616 | return -ENODEV; | 656 | return -ENODEV; |
617 | 657 | ||
618 | /* This assumption is wrong, fix that here for now until I fix the arch */ | 658 | /* The above assumption is wrong !!! |
659 | * fix that here for now until I fix the arch code | ||
660 | */ | ||
619 | of_node_get(np); | 661 | of_node_get(np); |
620 | 662 | ||
621 | /* We also assume that pmac_feature will have done a get() on nodes stored | 663 | /* We also assume that pmac_feature will have done a get() on nodes |
622 | * in the macio chips array | 664 | * stored in the macio chips array |
623 | */ | 665 | */ |
624 | chip = macio_find(np, macio_unknown); | 666 | chip = macio_find(np, macio_unknown); |
625 | of_node_put(np); | 667 | of_node_put(np); |
@@ -639,9 +681,9 @@ static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
639 | 681 | ||
640 | /* | 682 | /* |
641 | * HACK ALERT: The WallStreet PowerBook and some OHare based machines | 683 | * HACK ALERT: The WallStreet PowerBook and some OHare based machines |
642 | * have 2 macio ASICs. I must probe the "main" one first or IDE ordering | 684 | * have 2 macio ASICs. I must probe the "main" one first or IDE |
643 | * will be incorrect. So I put on "hold" the second one since it seem to | 685 | * ordering will be incorrect. So I put on "hold" the second one since |
644 | * appear first on PCI | 686 | * it seem to appear first on PCI |
645 | */ | 687 | */ |
646 | if (chip->type == macio_gatwick || chip->type == macio_ohareII) | 688 | if (chip->type == macio_gatwick || chip->type == macio_ohareII) |
647 | if (macio_chips[0].lbus.pdev == NULL) { | 689 | if (macio_chips[0].lbus.pdev == NULL) { |