diff options
Diffstat (limited to 'drivers/ieee1394/ohci1394.c')
-rw-r--r-- | drivers/ieee1394/ohci1394.c | 140 |
1 files changed, 95 insertions, 45 deletions
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index eae97d8dcf03..628130a58af3 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c | |||
@@ -468,7 +468,6 @@ static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg) | |||
468 | /* Global initialization */ | 468 | /* Global initialization */ |
469 | static void ohci_initialize(struct ti_ohci *ohci) | 469 | static void ohci_initialize(struct ti_ohci *ohci) |
470 | { | 470 | { |
471 | char irq_buf[16]; | ||
472 | quadlet_t buf; | 471 | quadlet_t buf; |
473 | int num_ports, i; | 472 | int num_ports, i; |
474 | 473 | ||
@@ -586,11 +585,10 @@ static void ohci_initialize(struct ti_ohci *ohci) | |||
586 | reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable); | 585 | reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable); |
587 | 586 | ||
588 | buf = reg_read(ohci, OHCI1394_Version); | 587 | buf = reg_read(ohci, OHCI1394_Version); |
589 | sprintf (irq_buf, "%d", ohci->dev->irq); | 588 | PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%d] " |
590 | PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s] " | ||
591 | "MMIO=[%llx-%llx] Max Packet=[%d] IR/IT contexts=[%d/%d]", | 589 | "MMIO=[%llx-%llx] Max Packet=[%d] IR/IT contexts=[%d/%d]", |
592 | ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10), | 590 | ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10), |
593 | ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf, | 591 | ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), ohci->dev->irq, |
594 | (unsigned long long)pci_resource_start(ohci->dev, 0), | 592 | (unsigned long long)pci_resource_start(ohci->dev, 0), |
595 | (unsigned long long)pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1, | 593 | (unsigned long long)pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1, |
596 | ohci->max_packet_size, | 594 | ohci->max_packet_size, |
@@ -3217,6 +3215,18 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, | |||
3217 | struct ti_ohci *ohci; /* shortcut to currently handled device */ | 3215 | struct ti_ohci *ohci; /* shortcut to currently handled device */ |
3218 | resource_size_t ohci_base; | 3216 | resource_size_t ohci_base; |
3219 | 3217 | ||
3218 | #ifdef CONFIG_PPC_PMAC | ||
3219 | /* Necessary on some machines if ohci1394 was loaded/ unloaded before */ | ||
3220 | if (machine_is(powermac)) { | ||
3221 | struct device_node *ofn = pci_device_to_OF_node(dev); | ||
3222 | |||
3223 | if (ofn) { | ||
3224 | pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1); | ||
3225 | pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1); | ||
3226 | } | ||
3227 | } | ||
3228 | #endif /* CONFIG_PPC_PMAC */ | ||
3229 | |||
3220 | if (pci_enable_device(dev)) | 3230 | if (pci_enable_device(dev)) |
3221 | FAIL(-ENXIO, "Failed to enable OHCI hardware"); | 3231 | FAIL(-ENXIO, "Failed to enable OHCI hardware"); |
3222 | pci_set_master(dev); | 3232 | pci_set_master(dev); |
@@ -3505,17 +3515,14 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) | |||
3505 | #endif | 3515 | #endif |
3506 | 3516 | ||
3507 | #ifdef CONFIG_PPC_PMAC | 3517 | #ifdef CONFIG_PPC_PMAC |
3508 | /* On UniNorth, power down the cable and turn off the chip | 3518 | /* On UniNorth, power down the cable and turn off the chip clock |
3509 | * clock when the module is removed to save power on | 3519 | * to save power on laptops */ |
3510 | * laptops. Turning it back ON is done by the arch code when | 3520 | if (machine_is(powermac)) { |
3511 | * pci_enable_device() is called */ | 3521 | struct device_node* ofn = pci_device_to_OF_node(ohci->dev); |
3512 | { | ||
3513 | struct device_node* of_node; | ||
3514 | 3522 | ||
3515 | of_node = pci_device_to_OF_node(ohci->dev); | 3523 | if (ofn) { |
3516 | if (of_node) { | 3524 | pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0); |
3517 | pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0); | 3525 | pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0); |
3518 | pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, of_node, 0, 0); | ||
3519 | } | 3526 | } |
3520 | } | 3527 | } |
3521 | #endif /* CONFIG_PPC_PMAC */ | 3528 | #endif /* CONFIG_PPC_PMAC */ |
@@ -3529,59 +3536,102 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) | |||
3529 | } | 3536 | } |
3530 | 3537 | ||
3531 | #ifdef CONFIG_PM | 3538 | #ifdef CONFIG_PM |
3532 | static int ohci1394_pci_resume (struct pci_dev *pdev) | 3539 | static int ohci1394_pci_suspend(struct pci_dev *pdev, pm_message_t state) |
3533 | { | ||
3534 | /* PowerMac resume code comes first */ | ||
3535 | #ifdef CONFIG_PPC_PMAC | ||
3536 | if (machine_is(powermac)) { | ||
3537 | struct device_node *of_node; | ||
3538 | |||
3539 | /* Re-enable 1394 */ | ||
3540 | of_node = pci_device_to_OF_node (pdev); | ||
3541 | if (of_node) | ||
3542 | pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1); | ||
3543 | } | ||
3544 | #endif /* CONFIG_PPC_PMAC */ | ||
3545 | |||
3546 | pci_set_power_state(pdev, PCI_D0); | ||
3547 | pci_restore_state(pdev); | ||
3548 | return pci_enable_device(pdev); | ||
3549 | } | ||
3550 | |||
3551 | static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) | ||
3552 | { | 3540 | { |
3553 | int err; | 3541 | int err; |
3542 | struct ti_ohci *ohci = pci_get_drvdata(pdev); | ||
3554 | 3543 | ||
3555 | printk(KERN_INFO "%s does not fully support suspend and resume yet\n", | 3544 | printk(KERN_INFO "%s does not fully support suspend and resume yet\n", |
3556 | OHCI1394_DRIVER_NAME); | 3545 | OHCI1394_DRIVER_NAME); |
3557 | 3546 | ||
3547 | if (!ohci) { | ||
3548 | printk(KERN_ERR "%s: tried to suspend nonexisting host\n", | ||
3549 | OHCI1394_DRIVER_NAME); | ||
3550 | return -ENXIO; | ||
3551 | } | ||
3552 | DBGMSG("suspend called"); | ||
3553 | |||
3554 | /* Clear the async DMA contexts and stop using the controller */ | ||
3555 | hpsb_bus_reset(ohci->host); | ||
3556 | |||
3557 | /* See ohci1394_pci_remove() for comments on this sequence */ | ||
3558 | reg_write(ohci, OHCI1394_ConfigROMhdr, 0); | ||
3559 | reg_write(ohci, OHCI1394_BusOptions, | ||
3560 | (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) | | ||
3561 | 0x00ff0000); | ||
3562 | reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); | ||
3563 | reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); | ||
3564 | reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); | ||
3565 | reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff); | ||
3566 | reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); | ||
3567 | reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); | ||
3568 | set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4)); | ||
3569 | reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); | ||
3570 | ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT); | ||
3571 | ohci_soft_reset(ohci); | ||
3572 | |||
3558 | err = pci_save_state(pdev); | 3573 | err = pci_save_state(pdev); |
3559 | if (err) { | 3574 | if (err) { |
3560 | printk(KERN_ERR "%s: pci_save_state failed with %d\n", | 3575 | PRINT(KERN_ERR, "pci_save_state failed with %d", err); |
3561 | OHCI1394_DRIVER_NAME, err); | ||
3562 | return err; | 3576 | return err; |
3563 | } | 3577 | } |
3564 | err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 3578 | err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); |
3565 | #ifdef OHCI1394_DEBUG | ||
3566 | if (err) | 3579 | if (err) |
3567 | printk(KERN_DEBUG "%s: pci_set_power_state failed with %d\n", | 3580 | DBGMSG("pci_set_power_state failed with %d", err); |
3568 | OHCI1394_DRIVER_NAME, err); | ||
3569 | #endif /* OHCI1394_DEBUG */ | ||
3570 | 3581 | ||
3571 | /* PowerMac suspend code comes last */ | 3582 | /* PowerMac suspend code comes last */ |
3572 | #ifdef CONFIG_PPC_PMAC | 3583 | #ifdef CONFIG_PPC_PMAC |
3573 | if (machine_is(powermac)) { | 3584 | if (machine_is(powermac)) { |
3574 | struct device_node *of_node; | 3585 | struct device_node *ofn = pci_device_to_OF_node(pdev); |
3575 | 3586 | ||
3576 | /* Disable 1394 */ | 3587 | if (ofn) |
3577 | of_node = pci_device_to_OF_node (pdev); | 3588 | pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0); |
3578 | if (of_node) | ||
3579 | pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0); | ||
3580 | } | 3589 | } |
3581 | #endif /* CONFIG_PPC_PMAC */ | 3590 | #endif /* CONFIG_PPC_PMAC */ |
3582 | 3591 | ||
3583 | return 0; | 3592 | return 0; |
3584 | } | 3593 | } |
3594 | |||
3595 | static int ohci1394_pci_resume(struct pci_dev *pdev) | ||
3596 | { | ||
3597 | int err; | ||
3598 | struct ti_ohci *ohci = pci_get_drvdata(pdev); | ||
3599 | |||
3600 | if (!ohci) { | ||
3601 | printk(KERN_ERR "%s: tried to resume nonexisting host\n", | ||
3602 | OHCI1394_DRIVER_NAME); | ||
3603 | return -ENXIO; | ||
3604 | } | ||
3605 | DBGMSG("resume called"); | ||
3606 | |||
3607 | /* PowerMac resume code comes first */ | ||
3608 | #ifdef CONFIG_PPC_PMAC | ||
3609 | if (machine_is(powermac)) { | ||
3610 | struct device_node *ofn = pci_device_to_OF_node(pdev); | ||
3611 | |||
3612 | if (ofn) | ||
3613 | pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1); | ||
3614 | } | ||
3615 | #endif /* CONFIG_PPC_PMAC */ | ||
3616 | |||
3617 | pci_set_power_state(pdev, PCI_D0); | ||
3618 | pci_restore_state(pdev); | ||
3619 | err = pci_enable_device(pdev); | ||
3620 | if (err) { | ||
3621 | PRINT(KERN_ERR, "pci_enable_device failed with %d", err); | ||
3622 | return err; | ||
3623 | } | ||
3624 | |||
3625 | /* See ohci1394_pci_probe() for comments on this sequence */ | ||
3626 | ohci_soft_reset(ohci); | ||
3627 | reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); | ||
3628 | reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); | ||
3629 | reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); | ||
3630 | mdelay(50); | ||
3631 | ohci_initialize(ohci); | ||
3632 | |||
3633 | return 0; | ||
3634 | } | ||
3585 | #endif /* CONFIG_PM */ | 3635 | #endif /* CONFIG_PM */ |
3586 | 3636 | ||
3587 | #define PCI_CLASS_FIREWIRE_OHCI ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10) | 3637 | #define PCI_CLASS_FIREWIRE_OHCI ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10) |