firewire: fw-ohci: PPC PMac platform code

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>

+49
+49
drivers/firewire/fw-ohci.c
··· 33 33 #include <asm/page.h> 34 34 #include <asm/system.h> 35 35 36 + #ifdef CONFIG_PPC_PMAC 37 + #include <asm/pmac_feature.h> 38 + #endif 39 + 36 40 #include "fw-ohci.h" 37 41 #include "fw-transaction.h" 38 42 ··· 2052 2048 int err; 2053 2049 size_t size; 2054 2050 2051 + #ifdef CONFIG_PPC_PMAC 2052 + /* Necessary on some machines if fw-ohci was loaded/ unloaded before */ 2053 + if (machine_is(powermac)) { 2054 + struct device_node *ofn = pci_device_to_OF_node(dev); 2055 + 2056 + if (ofn) { 2057 + pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1); 2058 + pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1); 2059 + } 2060 + } 2061 + #endif /* CONFIG_PPC_PMAC */ 2062 + 2055 2063 ohci = kzalloc(sizeof(*ohci), GFP_KERNEL); 2056 2064 if (ohci == NULL) { 2057 2065 fw_error("Could not malloc fw_ohci data.\n"); ··· 2198 2182 pci_disable_device(dev); 2199 2183 fw_card_put(&ohci->card); 2200 2184 2185 + #ifdef CONFIG_PPC_PMAC 2186 + /* On UniNorth, power down the cable and turn off the chip clock 2187 + * to save power on laptops */ 2188 + if (machine_is(powermac)) { 2189 + struct device_node *ofn = pci_device_to_OF_node(dev); 2190 + 2191 + if (ofn) { 2192 + pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0); 2193 + pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0); 2194 + } 2195 + } 2196 + #endif /* CONFIG_PPC_PMAC */ 2197 + 2201 2198 fw_notify("Removed fw-ohci device.\n"); 2202 2199 } 2203 2200 ··· 2231 2202 if (err) 2232 2203 fw_error("pci_set_power_state failed with %d\n", err); 2233 2204 2205 + /* PowerMac suspend code comes last */ 2206 + #ifdef CONFIG_PPC_PMAC 2207 + if (machine_is(powermac)) { 2208 + struct device_node *ofn = pci_device_to_OF_node(pdev); 2209 + 2210 + if (ofn) 2211 + pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0); 2212 + } 2213 + #endif /* CONFIG_PPC_PMAC */ 2214 + 2234 2215 return 0; 2235 2216 } 2236 2217 ··· 2248 2209 { 2249 2210 struct fw_ohci *ohci = pci_get_drvdata(pdev); 2250 2211 int err; 2212 + 2213 + /* PowerMac resume code comes first */ 2214 + #ifdef CONFIG_PPC_PMAC 2215 + if (machine_is(powermac)) { 2216 + struct device_node *ofn = pci_device_to_OF_node(pdev); 2217 + 2218 + if (ofn) 2219 + pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1); 2220 + } 2221 + #endif /* CONFIG_PPC_PMAC */ 2251 2222 2252 2223 pci_set_power_state(pdev, PCI_D0); 2253 2224 pci_restore_state(pdev);