diff options
Diffstat (limited to 'drivers/macintosh')
-rw-r--r-- | drivers/macintosh/macio_asic.c | 234 |
1 files changed, 140 insertions, 94 deletions
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 228e1852a836..f14c744a94ef 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,7 +251,8 @@ 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 */ |
@@ -258,12 +268,15 @@ static int macio_resource_quirks(struct device_node *np, struct resource *res, i | |||
258 | np->addrs[index].size = 0x100; | 268 | np->addrs[index].size = 0x100; |
259 | res->end = res->start + 0xff; | 269 | res->end = res->start + 0xff; |
260 | } | 270 | } |
261 | /* ESCC parent eats child resources. We could have added a level of hierarchy, | 271 | /* ESCC parent eats child resources. We could have added a |
262 | * but I don't really feel the need for it */ | 272 | * level of hierarchy, but I don't really feel the need |
273 | * for it | ||
274 | */ | ||
263 | if (!strcmp(np->name, "escc")) | 275 | if (!strcmp(np->name, "escc")) |
264 | return 1; | 276 | return 1; |
265 | /* ESCC has bogus resources >= 3 */ | 277 | /* ESCC has bogus resources >= 3 */ |
266 | if (index >= 3 && !(strcmp(np->name, "ch-a") && strcmp(np->name, "ch-b"))) | 278 | if (index >= 3 && !(strcmp(np->name, "ch-a") && |
279 | strcmp(np->name, "ch-b"))) | ||
267 | return 1; | 280 | return 1; |
268 | /* Media bay has too many resources, keep only first one */ | 281 | /* Media bay has too many resources, keep only first one */ |
269 | if (index > 0 && !strcmp(np->name, "media-bay")) | 282 | if (index > 0 && !strcmp(np->name, "media-bay")) |
@@ -285,6 +298,71 @@ static int macio_resource_quirks(struct device_node *np, struct resource *res, i | |||
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 | u32 *addr; | ||
336 | u64 size; | ||
337 | int index; | ||
338 | |||
339 | for (index = 0; (addr = of_get_address(np, index, &size)) != NULL; | ||
340 | index++) { | ||
341 | struct resource *res = &dev->resource[index]; | ||
342 | if (index >= MACIO_DEV_COUNT_RESOURCES) | ||
343 | break; | ||
344 | res->start = of_translate_address(np, addr); | ||
345 | res->end = res->start + (unsigned long)size - 1; | ||
346 | res->flags = IORESOURCE_MEM; | ||
347 | res->name = dev->ofdev.dev.bus_id; | ||
348 | |||
349 | if (macio_resource_quirks(np, res, index)) { | ||
350 | memset(res, 0, sizeof(struct resource)); | ||
351 | continue; | ||
352 | } | ||
353 | /* Currently, we consider failure as harmless, this may | ||
354 | * change in the future, once I've found all the device | ||
355 | * tree bugs in older machines & worked around them | ||
356 | */ | ||
357 | if (insert_resource(parent_res, res)) { | ||
358 | printk(KERN_WARNING "Can't request resource " | ||
359 | "%d for MacIO device %s\n", | ||
360 | index, dev->ofdev.dev.bus_id); | ||
361 | } | ||
362 | } | ||
363 | dev->n_resources = index; | ||
364 | } | ||
365 | |||
288 | /** | 366 | /** |
289 | * macio_add_one_device - Add one device from OF node to the device tree | 367 | * macio_add_one_device - Add one device from OF node to the device tree |
290 | * @chip: pointer to the macio_chip holding the device | 368 | * @chip: pointer to the macio_chip holding the device |
@@ -294,12 +372,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 | 372 | * When media-bay is changed to hotswap drivers, this function will |
295 | * be exposed to the bay driver some way... | 373 | * be exposed to the bay driver some way... |
296 | */ | 374 | */ |
297 | static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct device *parent, | 375 | static struct macio_dev * macio_add_one_device(struct macio_chip *chip, |
298 | struct device_node *np, struct macio_dev *in_bay, | 376 | struct device *parent, |
377 | struct device_node *np, | ||
378 | struct macio_dev *in_bay, | ||
299 | struct resource *parent_res) | 379 | struct resource *parent_res) |
300 | { | 380 | { |
301 | struct macio_dev *dev; | 381 | struct macio_dev *dev; |
302 | int i, j; | ||
303 | u32 *reg; | 382 | u32 *reg; |
304 | 383 | ||
305 | if (np == NULL) | 384 | if (np == NULL) |
@@ -326,7 +405,8 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct d | |||
326 | 405 | ||
327 | /* MacIO itself has a different reg, we use it's PCI base */ | 406 | /* MacIO itself has a different reg, we use it's PCI base */ |
328 | if (np == chip->of_node) { | 407 | if (np == chip->of_node) { |
329 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s", chip->lbus.index, | 408 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s", |
409 | chip->lbus.index, | ||
330 | #ifdef CONFIG_PCI | 410 | #ifdef CONFIG_PCI |
331 | pci_resource_start(chip->lbus.pdev, 0), | 411 | pci_resource_start(chip->lbus.pdev, 0), |
332 | #else | 412 | #else |
@@ -335,57 +415,16 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct d | |||
335 | MAX_NODE_NAME_SIZE, np->name); | 415 | MAX_NODE_NAME_SIZE, np->name); |
336 | } else { | 416 | } else { |
337 | reg = (u32 *)get_property(np, "reg", NULL); | 417 | reg = (u32 *)get_property(np, "reg", NULL); |
338 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", chip->lbus.index, | 418 | sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", |
419 | chip->lbus.index, | ||
339 | reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name); | 420 | reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name); |
340 | } | 421 | } |
341 | 422 | ||
342 | /* For now, we use pre-parsed entries in the device-tree for | 423 | /* Setup interrupts & resources */ |
343 | * interrupt routing and addresses, but we should change that | 424 | macio_setup_interrupts(dev); |
344 | * to dynamically parsed entries and so get rid of most of the | 425 | 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 | 426 | ||
427 | /* Register with core */ | ||
389 | if (of_device_register(&dev->ofdev) != 0) { | 428 | if (of_device_register(&dev->ofdev) != 0) { |
390 | printk(KERN_DEBUG"macio: device registration error for %s!\n", | 429 | printk(KERN_DEBUG"macio: device registration error for %s!\n", |
391 | dev->ofdev.dev.bus_id); | 430 | dev->ofdev.dev.bus_id); |
@@ -442,36 +481,42 @@ static void macio_pci_add_devices(struct macio_chip *chip) | |||
442 | 481 | ||
443 | /* First scan 1st level */ | 482 | /* First scan 1st level */ |
444 | for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) { | 483 | for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) { |
445 | if (!macio_skip_device(np)) { | 484 | if (macio_skip_device(np)) |
446 | of_node_get(np); | 485 | continue; |
447 | mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL, root_res); | 486 | of_node_get(np); |
448 | if (mdev == NULL) | 487 | mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL, |
449 | of_node_put(np); | 488 | root_res); |
450 | else if (strncmp(np->name, "media-bay", 9) == 0) | 489 | if (mdev == NULL) |
451 | mbdev = mdev; | 490 | of_node_put(np); |
452 | else if (strncmp(np->name, "escc", 4) == 0) | 491 | else if (strncmp(np->name, "media-bay", 9) == 0) |
453 | sdev = mdev; | 492 | mbdev = mdev; |
454 | } | 493 | else if (strncmp(np->name, "escc", 4) == 0) |
494 | sdev = mdev; | ||
455 | } | 495 | } |
456 | 496 | ||
457 | /* Add media bay devices if any */ | 497 | /* Add media bay devices if any */ |
458 | if (mbdev) | 498 | if (mbdev) |
459 | for (np = NULL; (np = of_get_next_child(mbdev->ofdev.node, np)) != NULL;) | 499 | for (np = NULL; (np = of_get_next_child(mbdev->ofdev.node, np)) |
460 | if (!macio_skip_device(np)) { | 500 | != NULL;) { |
461 | of_node_get(np); | 501 | if (macio_skip_device(np)) |
462 | if (macio_add_one_device(chip, &mbdev->ofdev.dev, np, mbdev, | 502 | continue; |
463 | root_res) == NULL) | 503 | of_node_get(np); |
464 | of_node_put(np); | 504 | if (macio_add_one_device(chip, &mbdev->ofdev.dev, np, |
465 | } | 505 | mbdev, root_res) == NULL) |
506 | of_node_put(np); | ||
507 | } | ||
508 | |||
466 | /* Add serial ports if any */ | 509 | /* Add serial ports if any */ |
467 | if (sdev) { | 510 | if (sdev) { |
468 | for (np = NULL; (np = of_get_next_child(sdev->ofdev.node, np)) != NULL;) | 511 | for (np = NULL; (np = of_get_next_child(sdev->ofdev.node, np)) |
469 | if (!macio_skip_device(np)) { | 512 | != NULL;) { |
470 | of_node_get(np); | 513 | if (macio_skip_device(np)) |
471 | if (macio_add_one_device(chip, &sdev->ofdev.dev, np, NULL, | 514 | continue; |
472 | root_res) == NULL) | 515 | of_node_get(np); |
473 | of_node_put(np); | 516 | if (macio_add_one_device(chip, &sdev->ofdev.dev, np, |
474 | } | 517 | NULL, root_res) == NULL) |
518 | of_node_put(np); | ||
519 | } | ||
475 | } | 520 | } |
476 | } | 521 | } |
477 | 522 | ||
@@ -519,7 +564,8 @@ void macio_unregister_driver(struct macio_driver *drv) | |||
519 | * Returns 0 on success, or %EBUSY on error. A warning | 564 | * Returns 0 on success, or %EBUSY on error. A warning |
520 | * message is also printed on failure. | 565 | * message is also printed on failure. |
521 | */ | 566 | */ |
522 | int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name) | 567 | int macio_request_resource(struct macio_dev *dev, int resource_no, |
568 | const char *name) | ||
523 | { | 569 | { |
524 | if (macio_resource_len(dev, resource_no) == 0) | 570 | if (macio_resource_len(dev, resource_no) == 0) |
525 | return 0; | 571 | return 0; |
@@ -606,20 +652,20 @@ static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
606 | if (ent->vendor != PCI_VENDOR_ID_APPLE) | 652 | if (ent->vendor != PCI_VENDOR_ID_APPLE) |
607 | return -ENODEV; | 653 | return -ENODEV; |
608 | 654 | ||
609 | /* Note regarding refcounting: We assume pci_device_to_OF_node() is ported | 655 | /* 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 | 656 | * 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 | */ | 657 | */ |
614 | np = pci_device_to_OF_node(pdev); | 658 | np = pci_device_to_OF_node(pdev); |
615 | if (np == NULL) | 659 | if (np == NULL) |
616 | return -ENODEV; | 660 | return -ENODEV; |
617 | 661 | ||
618 | /* This assumption is wrong, fix that here for now until I fix the arch */ | 662 | /* The above assumption is wrong !!! |
663 | * fix that here for now until I fix the arch code | ||
664 | */ | ||
619 | of_node_get(np); | 665 | of_node_get(np); |
620 | 666 | ||
621 | /* We also assume that pmac_feature will have done a get() on nodes stored | 667 | /* We also assume that pmac_feature will have done a get() on nodes |
622 | * in the macio chips array | 668 | * stored in the macio chips array |
623 | */ | 669 | */ |
624 | chip = macio_find(np, macio_unknown); | 670 | chip = macio_find(np, macio_unknown); |
625 | of_node_put(np); | 671 | of_node_put(np); |
@@ -639,9 +685,9 @@ static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
639 | 685 | ||
640 | /* | 686 | /* |
641 | * HACK ALERT: The WallStreet PowerBook and some OHare based machines | 687 | * 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 | 688 | * 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 | 689 | * ordering will be incorrect. So I put on "hold" the second one since |
644 | * appear first on PCI | 690 | * it seem to appear first on PCI |
645 | */ | 691 | */ |
646 | if (chip->type == macio_gatwick || chip->type == macio_ohareII) | 692 | if (chip->type == macio_gatwick || chip->type == macio_ohareII) |
647 | if (macio_chips[0].lbus.pdev == NULL) { | 693 | if (macio_chips[0].lbus.pdev == NULL) { |