Skip to content

Commit

Permalink
firewire: fw-ohci: PPC PMac platform code
Browse files Browse the repository at this point in the history
Copied from ohci1394.c.  This code is necessary to prevent machine check
exceptions when reloading or resuming the driver.

Tested on a 1st generation PowerBook G4 Titanium, which also needs the
pci_probe() hunk.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>

I was able to reproduce the system exception on resume with a 3rd-gen
Titanium PowerBook G4 667, and this patch does let the system resume
successfully now.

Not quite clear if there was possibly an updated version coming using
pci_enable_device() instead of the pair of pmac_call_feature() calls,
but either way, this is a definite must-have, at least for older ppc
macs -- my Aluminum PowerBook G4/1.67 suspends and resumes without this
patch just fine.

Signed-off-by: Jarod Wilson <jwilson@redhat.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Stefan Richter committed Mar 13, 2008
1 parent efbf390 commit ea8d006
Showing 1 changed file with 49 additions and 0 deletions.
49 changes: 49 additions & 0 deletions drivers/firewire/fw-ohci.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#include <asm/page.h>
#include <asm/system.h>

#ifdef CONFIG_PPC_PMAC
#include <asm/pmac_feature.h>
#endif

#include "fw-ohci.h"
#include "fw-transaction.h"

Expand Down Expand Up @@ -2048,6 +2052,18 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
int err;
size_t size;

#ifdef CONFIG_PPC_PMAC
/* Necessary on some machines if fw-ohci was loaded/ unloaded before */
if (machine_is(powermac)) {
struct device_node *ofn = pci_device_to_OF_node(dev);

if (ofn) {
pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1);
pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
}
}
#endif /* CONFIG_PPC_PMAC */

ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
if (ohci == NULL) {
fw_error("Could not malloc fw_ohci data.\n");
Expand Down Expand Up @@ -2182,6 +2198,19 @@ static void pci_remove(struct pci_dev *dev)
pci_disable_device(dev);
fw_card_put(&ohci->card);

#ifdef CONFIG_PPC_PMAC
/* On UniNorth, power down the cable and turn off the chip clock
* to save power on laptops */
if (machine_is(powermac)) {
struct device_node *ofn = pci_device_to_OF_node(dev);

if (ofn) {
pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
}
}
#endif /* CONFIG_PPC_PMAC */

fw_notify("Removed fw-ohci device.\n");
}

Expand All @@ -2202,6 +2231,16 @@ static int pci_suspend(struct pci_dev *pdev, pm_message_t state)
if (err)
fw_error("pci_set_power_state failed with %d\n", err);

/* PowerMac suspend code comes last */
#ifdef CONFIG_PPC_PMAC
if (machine_is(powermac)) {
struct device_node *ofn = pci_device_to_OF_node(pdev);

if (ofn)
pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
}
#endif /* CONFIG_PPC_PMAC */

return 0;
}

Expand All @@ -2210,6 +2249,16 @@ static int pci_resume(struct pci_dev *pdev)
struct fw_ohci *ohci = pci_get_drvdata(pdev);
int err;

/* PowerMac resume code comes first */
#ifdef CONFIG_PPC_PMAC
if (machine_is(powermac)) {
struct device_node *ofn = pci_device_to_OF_node(pdev);

if (ofn)
pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
}
#endif /* CONFIG_PPC_PMAC */

pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
err = pci_enable_device(pdev);
Expand Down

0 comments on commit ea8d006

Please sign in to comment.