patch-2.4.18 linux/arch/ppc/kernel/feature.c

Next file: linux/arch/ppc/kernel/head.S
Previous file: linux/arch/ppc/kernel/entry.S
Back to the patch index
Back to the overall index

diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/feature.c linux/arch/ppc/kernel/feature.c
@@ -1,1300 +0,0 @@
-/*
- * BK Id: SCCS/s.feature.c 1.21 09/08/01 15:47:42 paulus
- */
-/*
- *  arch/ppc/kernel/feature.c
- *
- *  Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
- *                     Ben. Herrenschmidt (benh@kernel.crashing.org)
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- *
- */
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <asm/sections.h>
-#include <asm/errno.h>
-#include <asm/ohare.h>
-#include <asm/heathrow.h>
-#include <asm/keylargo.h>
-#include <asm/uninorth.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/feature.h>
-#include <asm/dbdma.h>
-#include <asm/machdep.h>
-
-#undef DEBUG_FEATURE
-
-#define MAX_FEATURE_CONTROLLERS		2
-#define FREG(c,r)			(&(((c)->reg)[(r)>>2]))
-
-/* Keylargo reg. access. */
-#define KL_FCR(r)		(keylargo_base + ((r) >> 2))
-#define KL_IN(r)		(in_le32(KL_FCR(r)))
-#define KL_OUT(r,v)		(out_le32(KL_FCR(r), (v)))
-#define KL_BIS(r,v)		(KL_OUT((r), KL_IN(r) | (v)))
-#define KL_BIC(r,v)		(KL_OUT((r), KL_IN(r) & ~(v)))
-#define KL_GPIO_IN(r)		(in_8(((volatile u8 *)keylargo_base)+(r)))
-#define KL_GPIO_OUT(r,v)	(out_8(((volatile u8 *)keylargo_base)+(r), (v)))
-#define KL_LOCK()		spin_lock_irqsave(&keylargo->lock, flags)
-#define KL_UNLOCK()		spin_unlock_irqrestore(&keylargo->lock, flags)
-
-/* Uni-N reg. access. Note that Uni-N regs are big endian */
-#define UN_REG(r)	(uninorth_base + ((r) >> 2))
-#define UN_IN(r)	(in_be32(UN_REG(r)))
-#define UN_OUT(r,v)	(out_be32(UN_REG(r), (v)))
-#define UN_BIS(r,v)	(UN_OUT((r), UN_IN(r) | (v)))
-#define UN_BIC(r,v)	(UN_OUT((r), UN_IN(r) & ~(v)))
-
-typedef struct feature_bit {
-	int		reg;		/* reg. offset from mac-io base */
-	unsigned int	polarity;	/* 0 = normal, 1 = inverse */
-	unsigned int	mask;		/* bit mask */
-} fbit;
-
-/* Those features concern for OHare-based PowerBooks (2400, 3400, 3500)
- */
-static fbit feature_bits_ohare_pbook[] __pmacdata = {
-	{0x38,0,0},			/* FEATURE_null */
-	{0x38,0,OH_SCC_RESET},		/* FEATURE_Serial_reset */
-	{0x38,0,OH_SCC_ENABLE},		/* FEATURE_Serial_enable */
-	{0x38,0,OH_SCCA_IO},		/* FEATURE_Serial_IO_A */
-	{0x38,0,OH_SCCB_IO},		/* FEATURE_Serial_IO_B */
-	{0x38,0,OH_FLOPPY_ENABLE},	/* FEATURE_SWIM3_enable */
-	{0x38,0,OH_MESH_ENABLE},	/* FEATURE_MESH_enable */
-	{0x38,0,OH_IDE0_ENABLE},	/* FEATURE_IDE0_enable */
-	{0x38,1,OH_IDE0_RESET_N},	/* FEATURE_IDE0_reset */
-	{0x38,0,OH_IOBUS_ENABLE},	/* FEATURE_IOBUS_enable */
-	{0x38,1,OH_BAY_RESET_N},	/* FEATURE_Mediabay_reset */
-	{0x38,1,OH_BAY_POWER_N},	/* FEATURE_Mediabay_power */
-	{0x38,0,OH_BAY_PCI_ENABLE},	/* FEATURE_Mediabay_PCI_enable */
-	{0x38,0,OH_BAY_IDE_ENABLE},	/* FEATURE_IDE1_enable */
-	{0x38,1,OH_IDE1_RESET_N},	/* FEATURE_IDE1_reset */
-	{0x38,0,OH_BAY_FLOPPY_ENABLE},	/* FEATURE_Mediabay_floppy_enable */
-	{0x38,0,0},			/* FEATURE_BMac_reset */
-	{0x38,0,0},			/* FEATURE_BMac_IO_enable */
-	{0x38,0,0},			/* FEATURE_Modem_power */
-	{0x38,0,0},			/* FEATURE_Slow_SCC_PCLK */
-	{0x38,0,0},			/* FEATURE_Sound_Power */
-	{0x38,0,0},			/* FEATURE_Sound_CLK_Enable */
-	{0x38,0,0},			/* FEATURE_IDE2_enable */
-	{0x38,0,0},			/* FEATURE_IDE2_reset */
-	{0x38,0,0},			/* FEATURE_Mediabay_IDE_switch */
-	{0x38,0,0},			/* FEATURE_Mediabay_content */
-	{0x38,0,0},			/* FEATURE_Airport_reset */
-};
-
-/* Those bits concern heathrow-based desktop machines (Beige G3s). We have removed
- * the SCC related bits and init them once. They have proven to occasionally cause
- * problems with the desktop units.
- */
-static fbit feature_bits_heathrow[] __pmacdata = {
-	{0x38,0,0},			/* FEATURE_null */
-	{0x38,0,0},			/* FEATURE_Serial_reset */
-	{0x38,0,0},			/* FEATURE_Serial_enable */
-	{0x38,0,0},			/* FEATURE_Serial_IO_A */
-	{0x38,0,0},			/* FEATURE_Serial_IO_B */
-	{0x38,0,HRW_SWIM_ENABLE},	/* FEATURE_SWIM3_enable */
-	{0x38,0,HRW_MESH_ENABLE},	/* FEATURE_MESH_enable */
-	{0x38,0,HRW_IDE0_ENABLE},	/* FEATURE_IDE0_enable */
-	{0x38,1,HRW_IDE0_RESET_N},	/* FEATURE_IDE0_reset */
-	{0x38,0,HRW_IOBUS_ENABLE},	/* FEATURE_IOBUS_enable */
-	{0x38,1,0},			/* FEATURE_Mediabay_reset */
-	{0x38,1,0},			/* FEATURE_Mediabay_power */
-	{0x38,0,0},			/* FEATURE_Mediabay_PCI_enable */
-	{0x38,0,HRW_BAY_IDE_ENABLE},	/* FEATURE_IDE1_enable */
-	{0x38,1,HRW_IDE1_RESET_N},	/* FEATURE_IDE1_reset */
-	{0x38,0,0},			/* FEATURE_Mediabay_floppy_enable */
-	{0x38,0,HRW_BMAC_RESET},	/* FEATURE_BMac_reset */
-	{0x38,0,HRW_BMAC_IO_ENABLE},	/* FEATURE_BMac_IO_enable */
-	{0x38,1,0},			/* FEATURE_Modem_power */
-	{0x38,0,HRW_SLOW_SCC_PCLK},	/* FEATURE_Slow_SCC_PCLK */
-	{0x38,1,0},			/* FEATURE_Sound_Power */
-	{0x38,0,0},			/* FEATURE_Sound_CLK_Enable */
-	{0x38,0,0},			/* FEATURE_IDE2_enable */
-	{0x38,0,0},			/* FEATURE_IDE2_reset */
-	{0x38,0,0},			/* FEATURE_Mediabay_IDE_switch */
-	{0x38,0,0},			/* FEATURE_Mediabay_content */
-	{0x38,0,0},			/* FEATURE_Airport_reset */
-};
-
-/* Those bits concern heathrow-based PowerBooks (wallstreet/mainstreet).
- * Heathrow-based desktop macs (Beige G3s) are _not_ handled here
- */
-static fbit feature_bits_wallstreet[] __pmacdata = {
-	{0x38,0,0},			/* FEATURE_null */
-	{0x38,0,HRW_RESET_SCC},		/* FEATURE_Serial_reset */
-	{0x38,0,HRW_SCC_ENABLE},	/* FEATURE_Serial_enable */
-	{0x38,0,HRW_SCCA_IO},		/* FEATURE_Serial_IO_A */
-	{0x38,0,HRW_SCCB_IO},		/* FEATURE_Serial_IO_B */
-	{0x38,0,HRW_SWIM_ENABLE},	/* FEATURE_SWIM3_enable */
-	{0x38,0,HRW_MESH_ENABLE},	/* FEATURE_MESH_enable */
-	{0x38,0,HRW_IDE0_ENABLE},	/* FEATURE_IDE0_enable */
-	{0x38,1,HRW_IDE0_RESET_N},	/* FEATURE_IDE0_reset */
-	{0x38,0,HRW_IOBUS_ENABLE},	/* FEATURE_IOBUS_enable */
-	{0x38,1,HRW_BAY_RESET_N},	/* FEATURE_Mediabay_reset */
-	{0x38,1,HRW_BAY_POWER_N},	/* FEATURE_Mediabay_power */
-	{0x38,0,HRW_BAY_PCI_ENABLE},	/* FEATURE_Mediabay_PCI_enable */
-	{0x38,0,HRW_BAY_IDE_ENABLE},	/* FEATURE_IDE1_enable */
-	{0x38,1,HRW_IDE1_RESET_N},	/* FEATURE_IDE1_reset */
-	{0x38,0,HRW_BAY_FLOPPY_ENABLE},	/* FEATURE_Mediabay_floppy_enable */
-	{0x38,0,HRW_BMAC_RESET},	/* FEATURE_BMac_reset */
-	{0x38,0,HRW_BMAC_IO_ENABLE},	/* FEATURE_BMac_IO_enable */
-	{0x38,1,HRW_MODEM_POWER_N},	/* FEATURE_Modem_power */
-	{0x38,0,HRW_SLOW_SCC_PCLK},	/* FEATURE_Slow_SCC_PCLK */
-	{0x38,1,HRW_SOUND_POWER_N},	/* FEATURE_Sound_Power */
-	{0x38,0,HRW_SOUND_CLK_ENABLE},	/* FEATURE_Sound_CLK_Enable */
-	{0x38,0,0},			/* FEATURE_IDE2_enable */
-	{0x38,0,0},			/* FEATURE_IDE2_reset */
-	{0x38,0,0},			/* FEATURE_Mediabay_IDE_switch */
-	{0x38,0,0},			/* FEATURE_Mediabay_content */
-	{0x38,0,0},			/* FEATURE_Airport_reset */
-};
-
-/*
- * Those bits are from a 1999 G3 PowerBook, with a paddington chip.
- * Mostly the same as the heathrow. They are used on both PowerBooks
- * and desktop machines using the paddington chip
- */
-static fbit feature_bits_paddington[] __pmacdata = {
-	{0x38,0,0},			/* FEATURE_null */
-	{0x38,0,PADD_RESET_SCC},	/* FEATURE_Serial_reset */
-	{0x38,0,HRW_SCC_ENABLE},	/* FEATURE_Serial_enable */
-	{0x38,0,HRW_SCCA_IO},		/* FEATURE_Serial_IO_A */
-	{0x38,0,HRW_SCCB_IO},		/* FEATURE_Serial_IO_B */
-	{0x38,0,HRW_SWIM_ENABLE},	/* FEATURE_SWIM3_enable */
-	{0x38,0,HRW_MESH_ENABLE},	/* FEATURE_MESH_enable */
-	{0x38,0,HRW_IDE0_ENABLE},	/* FEATURE_IDE0_enable */
-	{0x38,1,HRW_IDE0_RESET_N},	/* FEATURE_IDE0_reset */
-	{0x38,0,HRW_IOBUS_ENABLE},	/* FEATURE_IOBUS_enable */
-	{0x38,1,HRW_BAY_RESET_N},	/* FEATURE_Mediabay_reset */
-	{0x38,1,HRW_BAY_POWER_N},	/* FEATURE_Mediabay_power */
-	{0x38,0,HRW_BAY_PCI_ENABLE},	/* FEATURE_Mediabay_PCI_enable */
-	{0x38,0,HRW_BAY_IDE_ENABLE},	/* FEATURE_IDE1_enable */
-	{0x38,1,HRW_IDE1_RESET_N},	/* FEATURE_IDE1_reset */
-	{0x38,0,HRW_BAY_FLOPPY_ENABLE},	/* FEATURE_Mediabay_floppy_enable */
-	{0x38,0,HRW_BMAC_RESET},	/* FEATURE_BMac_reset */
-	{0x38,0,HRW_BMAC_IO_ENABLE},	/* FEATURE_BMac_IO_enable */
-	{0x38,1,PADD_MODEM_POWER_N},	/* FEATURE_Modem_power */
-	{0x38,0,HRW_SLOW_SCC_PCLK},	/* FEATURE_Slow_SCC_PCLK */
-	{0x38,1,HRW_SOUND_POWER_N},	/* FEATURE_Sound_Power */
-	{0x38,0,HRW_SOUND_CLK_ENABLE},	/* FEATURE_Sound_CLK_Enable */
-	{0x38,0,0},			/* FEATURE_IDE2_enable */
-	{0x38,0,0},			/* FEATURE_IDE2_reset */
-	{0x38,0,0},			/* FEATURE_Mediabay_IDE_switch */
-	{0x38,0,0},			/* FEATURE_Mediabay_content */
-	{0x38,0,0},			/* FEATURE_Airport_reset */
-};
-
-/* Those bits are for Core99 machines (iBook,G4,iMacSL/DV,Pismo,...).
- * Note: Different sets may be needed for iBook, especially for sound
- */
-static fbit feature_bits_keylargo[] __pmacdata = {
-	{0x38,0,0},			/* FEATURE_null */
-	{0x38,0,KL0_SCC_RESET},		/* FEATURE_Serial_reset */
-	{0x38,0,KL0_SERIAL_ENABLE},	/* FEATURE_Serial_enable */
-	{0x38,0,KL0_SCC_A_INTF_ENABLE},	/* FEATURE_Serial_IO_A */
-	{0x38,0,KL0_SCC_B_INTF_ENABLE},	/* FEATURE_Serial_IO_B */
-	{0x38,0,0},			/* FEATURE_SWIM3_enable */
-	{0x38,0,0},			/* FEATURE_MESH_enable */
-	{0x3c,0,KL1_EIDE0_ENABLE},	/* FEATURE_IDE0_enable */
- 	{0x3c,1,KL1_EIDE0_RESET_N},	/* FEATURE_IDE0_reset */
-	{0x38,0,0},			/* FEATURE_IOBUS_enable */
-	{0x34,1,KL_MBCR_MB0_DEV_RESET},	/* FEATURE_Mediabay_reset */
-	{0x34,1,KL_MBCR_MB0_DEV_POWER},	/* FEATURE_Mediabay_power */
-	{0x38,0,0},			/* FEATURE_Mediabay_PCI_enable */
-	{0x3c,0,KL1_EIDE1_ENABLE},	/* FEATURE_IDE1_enable */
-	{0x3c,1,KL1_EIDE1_RESET_N},	/* FEATURE_IDE1_reset */
-	{0x38,0,0},			/* FEATURE_Mediabay_floppy_enable */
-	{0x38,0,0},			/* FEATURE_BMac_reset */
-	{0x38,0,0},			/* FEATURE_BMac_IO_enable */
-	{0x40,1,KL2_MODEM_POWER_N},	/* FEATURE_Modem_power */
-	{0x38,0,0},			/* FEATURE_Slow_SCC_PCLK */
-	{0x38,0,0},			/* FEATURE_Sound_Power */
-	{0x38,0,0},			/* FEATURE_Sound_CLK_Enable */
-	{0x3c,0,KL1_UIDE_ENABLE},	/* FEATURE_IDE2_enable */
-	{0x3c,1,KL1_UIDE_RESET_N},	/* FEATURE_IDE2_reset */
-	{0x34,0,KL_MBCR_MB0_DEV_ENABLE},/* FEATURE_Mediabay_IDE_switch */
-	{0x34,0,KL_MBCR_MB0_ENABLE},	/* FEATURE_Mediabay_content */
-	{0x40,1,KL2_AIRPORT_RESET_N},	/* FEATURE_Airport_reset */
-};
-
-/* definition of a feature controller object */
-struct feature_controller {
-	fbit*			bits;
-	volatile u32*		reg;
-	struct device_node*	device;
-	spinlock_t		lock;
-};
-
-/* static functions */
-static struct feature_controller*
-feature_add_controller(struct device_node *controller_device, fbit* bits);
-
-static struct feature_controller*
-feature_lookup_controller(struct device_node *device);
-
-static void uninorth_init(void);
-static void keylargo_init(void);
-#ifdef CONFIG_PMAC_PBOOK
-static void heathrow_prepare_for_sleep(struct feature_controller* ctrler);
-static void heathrow_wakeup(struct feature_controller* ctrler);
-static void core99_prepare_for_sleep(struct feature_controller* ctrler);
-static void core99_wake_up(struct feature_controller* ctrler);
-#endif /* CONFIG_PMAC_PBOOK */
-
-/* static variables */
-static struct feature_controller	controllers[MAX_FEATURE_CONTROLLERS];
-static int				controller_count = 0;
-
-/* Core99 stuffs */
-/*static*/ volatile u32*		uninorth_base;
-static volatile u32*			keylargo_base;
-static struct feature_controller*	keylargo;
-static int				uninorth_rev;
-static int				keylargo_rev;
-static u32				board_features;
-static int				airport_pwr_state;
-static struct device_node*		airport_dev;
-static struct device_node*		uninorth_fw;
-
-/* Feature bits for Apple motherboards */
-#define FTR_NEED_OPENPIC_TWEAK		0x00000001
-#define FTR_CAN_NAP			0x00000002
-#define FTR_HAS_FW_POWER		0x00000004
-#define FTR_CAN_SLEEP			0x00000008
-
-/* This table currently lacks most oldworld machines, but
- * they currently don't need it so...
- * 
- * Todo: The whole feature_xxx mecanism need to be redone
- * some way to be able to handle the new kind of features
- * exposed by core99. At this point, the main "tables" will
- * probably be in this table, which will have to be filled with
- * all known machines
- */
-/* Warning: Don't change ordering of entries as some machines
- * adverstise beeing compatible with several models. In those
- * case, the "highest" has to be first
- */
-static struct board_features_t {
-	char*	compatible;
-	u32	features;
-} board_features_datas[] __initdata = 
-{
-  {	"AAPL,PowerMac G3",	0				}, /* Beige G3 */
-  {	"iMac,1",		0				}, /* First iMac (gossamer) */
-  {	"PowerMac1,1",		0				}, /* B&W G3 / Yikes */
-  {	"PowerMac1,2",		0				}, /* B&W G3 / Yikes */
-  {	"PowerMac2,1",		FTR_CAN_SLEEP			}, /* r128 based iMac */
-  {	"PowerMac2,2",		FTR_HAS_FW_POWER|FTR_CAN_SLEEP	}, /* Summer 2000 iMac */
-  {	"PowerMac4,1",		FTR_CAN_SLEEP			}, /* iMac "Flower Power" */
-  {	"PowerMac3,1",		FTR_NEED_OPENPIC_TWEAK		}, /* Sawtooth (G4) */
-  {	"PowerMac3,2",		0				}, /* G4/Dual G4 */
-  {	"PowerMac3,3",		FTR_NEED_OPENPIC_TWEAK		}, /* G4/Dual G4 */
-  {	"PowerMac3,4",		0				}, /* QuickSilver G4 */
-  {	"PowerMac3,5",		0				}, /* QuickSilver G4 */
-  {	"PowerMac5,1",		FTR_CAN_NAP			}, /* Cube */
-  {	"AAPL,3400/2400",	FTR_CAN_SLEEP			}, /* 2400/3400 PowerBook */
-  {	"AAPL,3500",		FTR_CAN_SLEEP			}, /* 3500 PowerBook (G3) */
-  {	"AAPL,PowerBook1998",	FTR_CAN_SLEEP			}, /* Wallstreet PowerBook */
-  {	"PowerBook1,1",		FTR_CAN_SLEEP			}, /* 101 (Lombard) PowerBook */
-  {	"PowerBook4,1",		FTR_CAN_NAP|FTR_CAN_SLEEP|	   /* New polycarbonate iBook */
-  				0/*FTR_HAS_FW_POWER*/		}, 
-  {	"PowerBook2,1",		FTR_CAN_SLEEP 			}, /* iBook */
-  {	"PowerBook2,2",		FTR_CAN_SLEEP /*| FTR_CAN_NAP*/	}, /* iBook FireWire */
-  {	"PowerBook3,1",		FTR_CAN_SLEEP|FTR_CAN_NAP|	   /* PowerBook 2000 (Pismo) */
-  				FTR_HAS_FW_POWER		}, 
-  {	"PowerBook3,2",		FTR_CAN_NAP|FTR_CAN_SLEEP|	   /* PowerBook Titanium */
-  				0/*FTR_HAS_FW_POWER*/		},
-  {	NULL, 0 }
-};
-
-extern unsigned long powersave_nap;
-
-void __init
-feature_init(void)
-{
-	struct device_node *np;
-	u32 *rev;
-	int i;
-	char* model;
-	
-	if (_machine != _MACH_Pmac)
-		return;
-
-	np = find_path_device("/");
-	if (!np) {
-		printk(KERN_ERR "feature.c: Can't find device-tree root !\n");
-		return;
-	}
-	model = (char*)get_property(np, "model", NULL);
-	if (model) {
-		printk("PowerMac model: %s\n", model);
-		/* Figure out motherboard type & options */
-		for(i=0;board_features_datas[i].compatible;i++) {
-			if (!strcmp(board_features_datas[i].compatible, model)) {
-				board_features = board_features_datas[i].features;
-				break;
-			}
-		}
-	}
-
-	/* Set default value of powersave_nap on machines that support it */
-	if (board_features & FTR_CAN_NAP)
-		powersave_nap = 1;
-		
-	/* Track those poor mac-io's */
-	np = find_devices("mac-io");
-	while (np != NULL) {
-		/* KeyLargo contains several (5 ?) FCR registers in mac-io,
-		 * plus some gpio's which could eventually be handled here.
-		 */
-		if (device_is_compatible(np, "Keylargo")) {
-			struct feature_controller* ctrler =
-				feature_add_controller(np, feature_bits_keylargo);
-			if (ctrler) {
-				keylargo = ctrler;
-				keylargo_base = ctrler->reg;
-				rev = (u32 *)get_property(ctrler->device, "revision-id", NULL);
-				if (rev)
-					keylargo_rev = *rev;
-				
-				rev = (u32 *)get_property(ctrler->device, "device-id", NULL);
-				if (rev && (*rev) == 0x0025)
-					keylargo_rev |= KL_PANGEA_REV;
-			}
-		} else if (device_is_compatible(np, "paddington")) {
-			feature_add_controller(np, feature_bits_paddington);
-			/* We disable the modem power bit on Yikes as it can
-			 * do bad things (it's the nvram power)
-			 */
-			if (machine_is_compatible("PowerMac1,1") ||
-				machine_is_compatible("PowerMac1,2")) {
-				feature_bits_paddington[FEATURE_Modem_power].mask = 0;
-			}
-		} else if (machine_is_compatible("AAPL,PowerBook1998")) {
-			feature_add_controller(np, feature_bits_wallstreet);
-		} else {
-			struct feature_controller* ctrler =
-				feature_add_controller(np, feature_bits_heathrow);
-			if (ctrler)
-				out_le32(FREG(ctrler,HEATHROW_FEATURE_REG),
-					in_le32(FREG(ctrler,HEATHROW_FEATURE_REG)) | HRW_DEFAULTS);
-			
-		}
-		np = np->next;
-	}
-	if (controller_count == 0)
-	{
-		np = find_devices("ohare");
-		if (np) {
-			if (find_devices("via-pmu") != NULL)
-				feature_add_controller(np, feature_bits_ohare_pbook);
-			else
-				/* else not sure; maybe this is a Starmax? */
-				feature_add_controller(np, NULL);
-		}
-	}
-
-	/* Locate core99 Uni-N */
-	np = find_devices("uni-n");
-	if (np && np->n_addrs > 0) {
-		uninorth_base = ioremap(np->addrs[0].address, 0x1000);
-		uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
-		printk("Uninorth at 0x%08x\n", np->addrs[0].address);
-	}
-	if (uninorth_base && keylargo_base)
-		printk("Uni-N revision: %d, KeyLargo revision: %d %s\n",
-			uninorth_rev, keylargo_rev,
-			(keylargo_rev & KL_PANGEA_REV) ? "(Pangea chipset)" : "");
-
-	if (uninorth_base)
-		uninorth_init();
-	if (keylargo_base)
-		keylargo_init();
-
-	if (controller_count)
-		printk(KERN_INFO "Registered %d feature controller(s)\n", controller_count);
-
-#if defined(CONFIG_PMAC_PBOOK) && !defined(CONFIG_DMASOUND_AWACS)
-	/* On PowerBooks, we disable the sound chip when dmasound is a module
-	 * or not used at all
-	 */
-	if (controller_count && find_devices("via-pmu") != NULL) {
-		feature_clear(controllers[0].device, FEATURE_Sound_power);
-		feature_clear(controllers[0].device, FEATURE_Sound_CLK_enable);
-	}
-#endif
-
-#ifdef CONFIG_PMAC_PBOOK
-	/* On PowerBooks, we disable the serial ports by default, they
-	 * will be re-enabled by the driver
-	 */
-#ifndef CONFIG_XMON
-	if (controller_count && find_devices("via-pmu") != NULL) {
-		feature_set_modem_power(NULL, 0);
-		feature_clear(controllers[0].device, FEATURE_Serial_IO_A);
-		feature_clear(controllers[0].device, FEATURE_Serial_IO_B);
-		feature_clear(controllers[0].device, FEATURE_Serial_enable);
-		if (controller_count > 1) {
-			feature_clear(controllers[1].device, FEATURE_Serial_IO_A);
-			feature_clear(controllers[1].device, FEATURE_Serial_IO_B);
-			feature_clear(controllers[1].device, FEATURE_Serial_enable);
-		}
-	}
-#endif
-#endif
-}
-
-static struct feature_controller __init *
-feature_add_controller(struct device_node *controller_device, fbit* bits)
-{
-	struct feature_controller*	controller;
-	
-	if (controller_count >= MAX_FEATURE_CONTROLLERS) {
-		printk(KERN_INFO "Feature controller %s skipped(MAX:%d)\n",
-			controller_device->full_name, MAX_FEATURE_CONTROLLERS);
-		return NULL;
-	}
-	controller = &controllers[controller_count];
-
-	controller->bits	= bits;
-	controller->device	= controller_device;
-	if (controller_device->n_addrs == 0) {
-		printk(KERN_ERR "No addresses for %s\n",
-			controller_device->full_name);
-		return NULL;
-	}
-
-	/* We remap the entire mac-io here. Normally, this will just
-	 * give us back our already existing BAT mapping
-	 */
-	controller->reg		= (volatile u32 *)ioremap(
-		controller_device->addrs[0].address,
-		controller_device->addrs[0].size);
-
-	if (bits == NULL) {
-		printk(KERN_INFO "Twiddling the magic ohare bits\n");
-		out_le32(FREG(controller,OHARE_FEATURE_REG), STARMAX_FEATURES);
-		return NULL;
-	}
-
-	spin_lock_init(&controller->lock);
-
-	controller_count++;
-
-	return controller;
-}
-
-static struct feature_controller __pmac *
-feature_lookup_controller(struct device_node *device)
-{
-	int	i;
-	
-	if (device == NULL)
-		return NULL;
-		
-	while(device)
-	{
-		for (i=0; i<controller_count; i++)
-			if (device == controllers[i].device)
-				return &controllers[i];
-		device = device->parent;
-	}
-
-#ifdef DEBUG_FEATURE
-	printk("feature: <%s> not found on any controller\n",
-		device->name);
-#endif
-	
-	return NULL;
-}
-
-int __pmac
-feature_set(struct device_node* device, enum system_feature f)
-{
-	struct feature_controller*	controller;
-	unsigned long			flags;
-	unsigned long			value;
-	fbit*				bit;
-
-	if (f >= FEATURE_last)
-		return -EINVAL;	
-
-	controller = feature_lookup_controller(device);
-	if (!controller)
-		return -ENODEV;
-	bit = &controller->bits[f];
-	if (!bit->mask)
-		return -EINVAL;
-	
-#ifdef DEBUG_FEATURE
-	printk("feature: <%s> setting feature %d in controller @0x%x\n",
-		device->name, (int)f, (unsigned int)controller->reg);
-#endif
-
-	spin_lock_irqsave(&controller->lock, flags);
-	value = in_le32(FREG(controller, bit->reg));
-	value = bit->polarity ? (value & ~bit->mask) : (value | bit->mask);
-	out_le32(FREG(controller, bit->reg), value);
-	(void)in_le32(FREG(controller, bit->reg));
-	spin_unlock_irqrestore(&controller->lock, flags);
-	
-	return 0;
-}
-
-int __pmac
-feature_clear(struct device_node* device, enum system_feature f)
-{
-	struct feature_controller*	controller;
-	unsigned long			flags;
-	unsigned long			value;
-	fbit*				bit;
-
-	if (f >= FEATURE_last)
-		return -EINVAL;	
-
-	controller = feature_lookup_controller(device);
-	if (!controller)
-		return -ENODEV;
-	bit = &controller->bits[f];
-	if (!bit->mask)
-		return -EINVAL;
-	
-#ifdef DEBUG_FEATURE
-	printk("feature: <%s> clearing feature %d in controller @0x%x\n",
-		device->name, (int)f, (unsigned int)controller->reg);
-#endif
-
-	spin_lock_irqsave(&controller->lock, flags);
-	value = in_le32(FREG(controller, bit->reg));
-	value = bit->polarity ? (value | bit->mask) : (value & ~bit->mask);
-	out_le32(FREG(controller, bit->reg), value);
-	(void)in_le32(FREG(controller, bit->reg));
-	spin_unlock_irqrestore(&controller->lock, flags);
-	
-	return 0;
-}
-
-int __pmac
-feature_test(struct device_node* device, enum system_feature f)
-{
-	struct feature_controller*	controller;
-	unsigned long			value;
-	fbit*				bit;
-
-	if (f >= FEATURE_last)
-		return -EINVAL;	
-
-	controller = feature_lookup_controller(device);
-	if (!controller)
-		return -ENODEV;
-	bit = &controller->bits[f];
-	if (!bit->mask)
-		return -EINVAL;
-	
-#ifdef DEBUG_FEATURE
-	printk("feature: <%s> clearing feature %d in controller @0x%x\n",
-		device->name, (int)f, (unsigned int)controller->reg);
-#endif
-	/* If one feature contains several bits, all of them must be set
-	 * for value to be true, or all of them must be 0 if polarity is
-	 * inverse
-	 */
-	value = (in_le32(FREG(controller, bit->reg)) & bit->mask);
-	return bit->polarity ? (value == 0) : (value == bit->mask);
-}
-
-int __pmac
-feature_can_sleep(void)
-{
-	return ((board_features & FTR_CAN_SLEEP) != 0);	
-}
-
-/*
- * Core99 functions
- * 
- * Note: We currently assume there is _one_ UniN chip and _one_ KeyLargo
- *       chip, which is the case on all Core99 machines so far
- */
-
-/* Only one GMAC is assumed */
-void __pmac
-feature_set_gmac_power(struct device_node* device, int power)
-{
-	unsigned long flags;
-	
-	if (!uninorth_base || !keylargo)
-		return;
-		
-	/* TODO: Handle save/restore of PCI config space here
-	 */
-
-	/* XXX We use the keylargo spinlock, but we never
-	 * have uninorth without keylargo, so...
-	 */
-	KL_LOCK();
-	if (power)
-		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
-	else
-		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
-	(void)UN_IN(UNI_N_CLOCK_CNTL);
-	KL_UNLOCK();
-	udelay(20);
-}
-
-void __pmac
-feature_gmac_phy_reset(struct device_node* device)
-{
-	unsigned long flags;
-	
-	if (!keylargo_base || !keylargo)
-		return;
-		
-	KL_LOCK();
-	KL_GPIO_OUT(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);
-	(void)KL_GPIO_IN(KL_GPIO_ETH_PHY_RESET);
-	KL_UNLOCK();
-	mdelay(10);
-	KL_LOCK();
-	KL_GPIO_OUT(KL_GPIO_ETH_PHY_RESET,
-		KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
-	(void)KL_GPIO_IN(KL_GPIO_ETH_PHY_RESET);
-	KL_UNLOCK();
-	mdelay(10);
-}
-
-/* Pass the node of the correct controller, please */
-void __pmac
-feature_set_usb_power(struct device_node* device, int power)
-{
-	char* prop;
-	int number;
-	u32 reg;
-	
-	unsigned long flags;
-	
-	if (!keylargo_base || !keylargo)
-		return;
-		
-	prop = (char *)get_property(device, "AAPL,clock-id", NULL);
-	if (!prop)
-		return;
-	if (strncmp(prop, "usb0u048", strlen("usb0u048")) == 0)
-		number = 0;
-	else if (strncmp(prop, "usb1u148", strlen("usb1u148")) == 0)
-		number = 2;
-	else
-		return;
-
-	KL_LOCK();
-	if (power) {
-		/* Turn ON */
-			
-		if (number == 0) {
-			KL_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
-			(void)KL_IN(KEYLARGO_FCR0);
-			KL_UNLOCK();
-			mdelay(1);
-			KL_LOCK();
-			KL_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
-		} else {
-			KL_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
-			KL_UNLOCK();
-			(void)KL_IN(KEYLARGO_FCR0);
-			mdelay(1);
-			KL_LOCK();
-			KL_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
-		}
-		reg = KL_IN(KEYLARGO_FCR4);
-		reg &=	~(KL4_SET_PORT_ENABLE(number) | KL4_SET_PORT_RESUME(number) |
-			KL4_SET_PORT_CONNECT(number) | KL4_SET_PORT_DISCONNECT(number));
-		reg &=	~(KL4_SET_PORT_ENABLE(number+1) | KL4_SET_PORT_RESUME(number+1) |
-			KL4_SET_PORT_CONNECT(number+1) | KL4_SET_PORT_DISCONNECT(number+1));
-		KL_OUT(KEYLARGO_FCR4, reg);
-		(void)KL_IN(KEYLARGO_FCR4);
-		udelay(10);
-	} else {
-		/* Turn OFF */
-		
-		reg = KL_IN(KEYLARGO_FCR4);
-		reg |=	KL4_SET_PORT_ENABLE(number) | KL4_SET_PORT_RESUME(number) |
-			KL4_SET_PORT_CONNECT(number) | KL4_SET_PORT_DISCONNECT(number);
-		reg |=	KL4_SET_PORT_ENABLE(number+1) | KL4_SET_PORT_RESUME(number+1) |
-			KL4_SET_PORT_CONNECT(number+1) | KL4_SET_PORT_DISCONNECT(number+1);
-		KL_OUT(KEYLARGO_FCR4, reg);
-		(void)KL_IN(KEYLARGO_FCR4);
-		udelay(1);
-		if (number == 0) {
-			KL_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
-			(void)KL_IN(KEYLARGO_FCR0);
-			udelay(1);
-			KL_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
-			(void)KL_IN(KEYLARGO_FCR0);
-		} else {
-			KL_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
-			(void)KL_IN(KEYLARGO_FCR0);
-			udelay(1);
-			KL_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
-			(void)KL_IN(KEYLARGO_FCR0);
-		}
-		udelay(1);
-	}
-	KL_UNLOCK();
-}
-
-void  __pmac
-feature_set_firewire_power(struct device_node* device, int power)
-{
-	unsigned long flags;
-
-	/* TODO: should probably handle save/restore of PCI config space here
-	 */
-		
-	if (!uninorth_fw || (device && uninorth_fw != device))
-		return;
-	if (!uninorth_base)
-		return;
-
-	/* XXX We use the keylargo spinlock, but we never
-	 * have uninorth without keylargo, so...
-	 */
-	KL_LOCK();
-	if (power)
-		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
-	else
-		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
-	(void)UN_IN(UNI_N_CLOCK_CNTL);
-	KL_UNLOCK();
-	udelay(20);
-}
-
-/* Warning: will kill the PHY.. */
-void  __pmac
-feature_set_firewire_cable_power(struct device_node* device, int power)
-{
-	unsigned long flags;
-	u8 gpioValue = power ? 0 : 4;
-
-	if (!uninorth_fw || (device && uninorth_fw != device))
-		return;
-	if (!keylargo_base || !(board_features & FTR_HAS_FW_POWER))
-		return;
-	KL_LOCK();
-	KL_GPIO_OUT(KL_GPIO_FW_CABLE_POWER, gpioValue);
-	(void)KL_GPIO_IN(KL_GPIO_FW_CABLE_POWER);
-	KL_UNLOCK();		
-}
-
-void
-feature_set_modem_power(struct device_node* device, int power)
-{
-	unsigned long flags;
-
-	if (!device) {
-		device = find_devices("ch-a");
-		while(device && !device_is_compatible(device, "cobalt"))
-			device = device->next;
-		if (!device)
-			return;
-	}
-	if (keylargo && (keylargo_rev & KL_PANGEA_REV)) {
-		KL_LOCK();
-		if (power) {
-			/* Assert modem reset */
-			KL_GPIO_OUT(KL_GPIO_MODEM_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);
-			(void)KL_GPIO_IN(KL_GPIO_MODEM_RESET);
-			udelay(10);
-			/* Power up modem */
-			KL_GPIO_OUT(KL_GPIO_MODEM_POWER, KEYLARGO_GPIO_OUTPUT_ENABLE);
-			(void)KL_GPIO_IN(KL_GPIO_MODEM_POWER);
-			udelay(10);
-			/* Release modem reset */
-			KL_GPIO_OUT(KL_GPIO_MODEM_RESET,
-				KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
-			(void)KL_GPIO_IN(KL_GPIO_MODEM_RESET);
-		} else {
-			/* Power down modem */
-			KL_GPIO_OUT(KL_GPIO_MODEM_POWER,
-				KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
-			(void)KL_GPIO_IN(KL_GPIO_MODEM_POWER);
-		}
-		KL_UNLOCK();
-	} else {
-		if (power) {
-			mdelay(300);
-			feature_set(device, FEATURE_Modem_power);
-	   		mdelay(5);
-			feature_clear(device, FEATURE_Modem_power);
-	   		mdelay(10);
-			feature_set(device, FEATURE_Modem_power);
-		} else {
-			feature_clear(device, FEATURE_Modem_power);
-			mdelay(10);
-		}
-	}
-}
-
-#ifdef CONFIG_SMP
-void __pmac
-feature_core99_kick_cpu(int cpu_nr)
-{
-	const int reset_lines[] = {	KL_GPIO_RESET_CPU0,
-					KL_GPIO_RESET_CPU1,
-					KL_GPIO_RESET_CPU2,
-					KL_GPIO_RESET_CPU3 };
-	int reset_io;
-	unsigned long flags;
-	
-	if (!keylargo_base || cpu_nr > 3)
-		return;
-	reset_io = reset_lines[cpu_nr];
-	
-	KL_LOCK();
-	KL_GPIO_OUT(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
-	(void)KL_GPIO_IN(reset_io);
-	udelay(1);
-	KL_GPIO_OUT(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
-	(void)KL_GPIO_IN(reset_io);
-	KL_UNLOCK();
-}
-#endif /* CONFIG_SMP */
-
-void __pmac
-feature_set_airport_power(struct device_node* device, int power)
-{
-	unsigned long flags;
-	
-	if (!keylargo_base || !airport_dev || airport_dev != device)
-		return;
-	if (airport_pwr_state == power)
-		return;	
-	if (power) {
-		/* This code is a reproduction of OF enable-cardslot
-		 * and init-wireless methods, slightly hacked until
-		 * I got it working.
-		 */
-		KL_LOCK();
-		KL_GPIO_OUT(KEYLARGO_GPIO_0+0xf, 5);
-		(void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xf);
-		KL_UNLOCK();
-		mdelay(10);
-		KL_LOCK();
-		KL_GPIO_OUT(KEYLARGO_GPIO_0+0xf, 4);
-		(void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xf);
-		KL_UNLOCK();
-
-		mdelay(10);
-
-		KL_LOCK();
-		KL_BIC(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N);
-		(void)KL_IN(KEYLARGO_FCR2);
-		udelay(10);
-		KL_GPIO_OUT(KEYLARGO_GPIO_EXTINT_0+0xb, 0);
-		(void)KL_GPIO_IN(KEYLARGO_GPIO_EXTINT_0+0xb);
-		udelay(10);
-		KL_GPIO_OUT(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28);
-		(void)KL_GPIO_IN(KEYLARGO_GPIO_EXTINT_0+0xa);
-		udelay(10);
-		KL_GPIO_OUT(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28);
-		(void)KL_GPIO_IN(KEYLARGO_GPIO_EXTINT_0+0xd);
-		udelay(10);
-		KL_GPIO_OUT(KEYLARGO_GPIO_0+0xd, 0x28);
-		(void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xd);
-		udelay(10);
-		KL_GPIO_OUT(KEYLARGO_GPIO_0+0xe, 0x28);
-		(void)KL_GPIO_IN(KEYLARGO_GPIO_0+0xe);
-		KL_UNLOCK();
-		udelay(10);
-		KL_OUT(0x1c000, 0);
-		
-		mdelay(1);
-		out_8((volatile u8*)KL_FCR(0x1a3e0), 0x41);
-		(void)in_8((volatile u8*)KL_FCR(0x1a3e0));
-		udelay(10);
-		KL_LOCK();
-		KL_BIS(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N);
-		(void)KL_IN(KEYLARGO_FCR2);
-		KL_UNLOCK();
-		mdelay(100);
-	} else {
-		KL_LOCK();
-		KL_BIC(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N);
-		(void)KL_IN(KEYLARGO_FCR2);
-		KL_GPIO_OUT(KL_GPIO_AIRPORT_0, 0);
-		KL_GPIO_OUT(KL_GPIO_AIRPORT_1, 0);
-		KL_GPIO_OUT(KL_GPIO_AIRPORT_2, 0);
-		KL_GPIO_OUT(KL_GPIO_AIRPORT_3, 0);
-		KL_GPIO_OUT(KL_GPIO_AIRPORT_4, 0);
-		(void)KL_GPIO_IN(KL_GPIO_AIRPORT_4);
-		KL_UNLOCK();
-	}
-	airport_pwr_state = power;	
-}
-
-/* Initialize the Core99 UniNorth host bridge and memory controller
- */
-static void __init
-uninorth_init(void)
-{
-	struct device_node* gmac, *fw;
-	unsigned long actrl;
-	
-	/* Set the arbitrer QAck delay according to what Apple does
-	 */
-	if (uninorth_rev < 0x10) {
-		actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
-		actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
-			UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
-		UN_OUT(UNI_N_ARB_CTRL, actrl);
-	}
-	
-	/* Enable GMAC for now for PCI probing. It will be disabled
-	 * later on after PCI probe
-	 */
-	gmac = find_devices("ethernet");
-	while(gmac) {
-		if (device_is_compatible(gmac, "gmac"))
-			break;
-		gmac = gmac->next;
-	}
-	if (gmac)
-		feature_set_gmac_power(gmac, 1);
-
-	/* Enable FW before PCI probe. Will be disabled later on
-	 */
-	fw = find_devices("firewire");
-	if (fw && (device_is_compatible(fw, "pci106b,18") || 
-			device_is_compatible(fw, "pci106b,30"))) {
-		uninorth_fw = fw;
-		feature_set_firewire_power(fw, 1);
-	}
-}
-
-/* Initialize the Core99 KeyLargo ASIC. 
- */
-static void __init
-keylargo_init(void)
-{
-	struct device_node* np;
-	
-	KL_BIS(KEYLARGO_FCR2, KL2_MPIC_ENABLE);
-
-	/* Lookup for an airport card, and disable it if found
-	 * to save power (will be re-enabled by driver if used)
-	 */
-	np = find_devices("radio");
-	if (np && np->parent == keylargo->device)
-		airport_dev = np;
-
-	if (airport_dev) {
-		airport_pwr_state = 1;
-		feature_set_airport_power(airport_dev, 0);
-	}
-	
-}
-
-#ifdef CONFIG_PMAC_PBOOK
-void __pmac
-feature_prepare_for_sleep(void)
-{
-	/* We assume gatwick is second */
-	struct feature_controller* ctrler = &controllers[0];
-
-	if (controller_count > 1 &&
-		device_is_compatible(ctrler->device, "gatwick"))
-		ctrler = &controllers[1];
-
-	if (ctrler->bits == feature_bits_wallstreet ||
-		ctrler->bits == feature_bits_paddington) {
-		heathrow_prepare_for_sleep(ctrler);
-		return;
-	}
-	if (ctrler->bits == feature_bits_keylargo) {
-		core99_prepare_for_sleep(ctrler);
-		return;
-	}
-}
-
-void __pmac
-feature_wake_up(void)
-{
-	struct feature_controller* ctrler = &controllers[0];
-
-	if (controller_count > 1 &&
-		device_is_compatible(ctrler->device, "gatwick"))
-		ctrler = &controllers[1];
-	
-	if (ctrler->bits == feature_bits_wallstreet ||
-		ctrler->bits == feature_bits_paddington) {
-		heathrow_wakeup(ctrler);
-		return;
-	}
-	if (ctrler->bits == feature_bits_keylargo) {
-		core99_wake_up(ctrler);
-		return;
-	}
-}
-
-static u32 save_fcr[5];
-static u32 save_mbcr;
-static u32 save_gpio_levels[2];
-static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
-static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
-static u32 save_unin_clock_ctl;
-static struct dbdma_regs save_dbdma[13];
-
-static void __pmac
-heathrow_prepare_for_sleep(struct feature_controller* ctrler)
-{
-	save_mbcr = in_le32(FREG(ctrler, 0x34));
-	save_fcr[0] = in_le32(FREG(ctrler, 0x38));
-	save_fcr[1] = in_le32(FREG(ctrler, 0x3c));
-
-	out_le32(FREG(ctrler, 0x38), save_fcr[0] & ~HRW_IOBUS_ENABLE);
-}
-
-static void __pmac
-heathrow_wakeup(struct feature_controller* ctrler)
-{
-	out_le32(FREG(ctrler, 0x38), save_fcr[0]);
-	out_le32(FREG(ctrler, 0x3c), save_fcr[1]);
-	out_le32(FREG(ctrler, 0x34), save_mbcr);
-	mdelay(1);
-	out_le32(FREG(ctrler, 0x38), save_fcr[0] | HRW_IOBUS_ENABLE);
-	mdelay(1);
-}
-
-static void __pmac
-turn_off_keylargo(void)
-{
-	u32 temp;
-
-	mdelay(1);
-	KL_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
-	(void)KL_IN(KEYLARGO_FCR0);
-	mdelay(100);
-
-	KL_BIC(KEYLARGO_FCR0,	KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
-				KL0_SCC_CELL_ENABLE |
-		      		KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
-		      		KL0_IRDA_CLK19_ENABLE);
-
-	(void)KL_IN(KEYLARGO_FCR0); udelay(10);
-	KL_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_ENABLE);
-	(void)KL_IN(KEYLARGO_MBCR); udelay(10);
-
-	KL_BIC(KEYLARGO_FCR1,
-		KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
-		KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
-		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
-		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
-		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
-		KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
-		KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
-		KL1_UIDE_ENABLE);
-	(void)KL_IN(KEYLARGO_FCR1); udelay(10);
-
-	KL_BIS(KEYLARGO_FCR2, KL2_MODEM_POWER_N);
- 	udelay(10);
- 	KL_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
- 	udelay(10);
-	temp = KL_IN(KEYLARGO_FCR3);
-	if (keylargo_rev >= 2)
-		temp |= (KL3_SHUTDOWN_PLL2X | KL3_SHUTDOWN_PLL_TOTAL);
-		
-	temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
-		KL3_SHUTDOWN_PLLKW35 | KL3_SHUTDOWN_PLLKW12;
-	temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
-		| KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
-		| KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
-	KL_OUT(KEYLARGO_FCR3, temp);
-	(void)KL_IN(KEYLARGO_FCR3); udelay(10);
-}
-
-static void __pmac
-turn_off_pangea(void)
-{
-	u32 temp;
-
-	KL_BIC(KEYLARGO_FCR0,	KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
-				KL0_SCC_CELL_ENABLE |
-				KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
-
-	(void)KL_IN(KEYLARGO_FCR0); udelay(10);
-	KL_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_ENABLE);
-	(void)KL_IN(KEYLARGO_MBCR); udelay(10);
-
-	KL_BIC(KEYLARGO_FCR1,
-		KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
-		KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
-		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
-		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
-		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
-		KL1_UIDE_ENABLE);
-	(void)KL_IN(KEYLARGO_FCR1); udelay(10);
-
-	KL_BIS(KEYLARGO_FCR2, KL2_MODEM_POWER_N);
- 	udelay(10);
-	temp = KL_IN(KEYLARGO_FCR3);
-	temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
-		KL3_SHUTDOWN_PLLKW35;
-	temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
-		| KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
-		| KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
-	KL_OUT(KEYLARGO_FCR3, temp);
-	(void)KL_IN(KEYLARGO_FCR3); udelay(10);
-}
-
-static void __pmac
-core99_prepare_for_sleep(struct feature_controller* ctrler)
-{
-	int i;
-	volatile u8* base8;
-	
-	/*
-	 * Save various bits of KeyLargo
-	 */
-
-	/* We power off the wireless slot in case it was not done
-	 * by the driver. We don't power it on automatically however
-	 */
-	feature_set_airport_power(airport_dev, 0);
-
-	/* We power off the FW cable. Should be done by the driver... */
-	feature_set_firewire_power(NULL, 0);
-	feature_set_firewire_cable_power(NULL, 0);
-
-	/* We make sure int. modem is off (in case driver lost it) */
-	feature_set_modem_power(NULL, 0);
-	 
-	/* Save the state of the various GPIOs */
-	save_gpio_levels[0] = KL_IN(KEYLARGO_GPIO_LEVELS0);
-	save_gpio_levels[1] = KL_IN(KEYLARGO_GPIO_LEVELS1);
-	base8 = ((volatile u8 *)keylargo_base) + KEYLARGO_GPIO_EXTINT_0;
-	for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
-		save_gpio_extint[i] = in_8(base8+i);
-	base8 = ((volatile u8 *)keylargo_base) + KEYLARGO_GPIO_0;
-	for (i=0; i<KEYLARGO_GPIO_CNT; i++)
-		save_gpio_normal[i] = in_8(base8+i);
-
-	/* Save the FCRs */
-	save_mbcr = KL_IN(KEYLARGO_MBCR);
-	save_fcr[0] = KL_IN(KEYLARGO_FCR0);
-	save_fcr[1] = KL_IN(KEYLARGO_FCR1);
-	save_fcr[2] = KL_IN(KEYLARGO_FCR2);
-	save_fcr[3] = KL_IN(KEYLARGO_FCR3);
-	save_fcr[4] = KL_IN(KEYLARGO_FCR4);
-
-	/* Save state & config of DBDMA channels */
-	for (i=0; i<13; i++) {
-		volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*)
-			(keylargo_base + ((0x8000+i*0x100)>>2));
-		save_dbdma[i].cmdptr_hi = in_le32(&chan->cmdptr_hi);
-		save_dbdma[i].cmdptr = in_le32(&chan->cmdptr);
-		save_dbdma[i].intr_sel = in_le32(&chan->intr_sel);
-		save_dbdma[i].br_sel = in_le32(&chan->br_sel);
-		save_dbdma[i].wait_sel = in_le32(&chan->wait_sel);
-	}
-
-	/*
-	 * Turn off as much as we can
-	 */
-	if (keylargo_rev & KL_PANGEA_REV)
-		turn_off_pangea();
-	else
-		turn_off_keylargo();
-	
-	/* 
-	 * Put the host bridge to sleep
-	 */
-
-	save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);
-	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl &
-		~(UNI_N_CLOCK_CNTL_GMAC|UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/));
-	udelay(100);
-	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
-	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);
-
-	/*
-	 * FIXME: A bit of black magic with OpenPIC (don't ask me why)
-	 */
-	if (board_features & FTR_NEED_OPENPIC_TWEAK) {
-		KL_BIS(0x506e0, 0x00400000);
-		KL_BIS(0x506e0, 0x80000000);
-	}
-}
-
-static void __pmac
-core99_wake_up(struct feature_controller* ctrler)
-{
-	int i;
-	volatile u8* base8;
-
-	/*
-	 * Wakeup the host bridge
-	 */
-	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
-	udelay(10);
-	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
-	udelay(10);
-	
-	/*
-	 * Restore KeyLargo
-	 */
-	 
-	KL_OUT(KEYLARGO_MBCR, save_mbcr);
-	(void)KL_IN(KEYLARGO_MBCR); udelay(10);
-	KL_OUT(KEYLARGO_FCR0, save_fcr[0]);
-	(void)KL_IN(KEYLARGO_FCR0); udelay(10);
-	KL_OUT(KEYLARGO_FCR1, save_fcr[1]);
-	(void)KL_IN(KEYLARGO_FCR1); udelay(10);
-	KL_OUT(KEYLARGO_FCR2, save_fcr[2]);
-	(void)KL_IN(KEYLARGO_FCR2); udelay(10);
-	KL_OUT(KEYLARGO_FCR3, save_fcr[3]);
-	(void)KL_IN(KEYLARGO_FCR3); udelay(10);
-	KL_OUT(KEYLARGO_FCR4, save_fcr[4]);
-	(void)KL_IN(KEYLARGO_FCR4); udelay(10);
-
-	for (i=0; i<13; i++) {
-		volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*)
-			(keylargo_base + ((0x8000+i*0x100)>>2));
-		out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);
-		while (in_le32(&chan->status) & ACTIVE)
-			mb();
-		out_le32(&chan->cmdptr_hi, save_dbdma[i].cmdptr_hi);
-		out_le32(&chan->cmdptr, save_dbdma[i].cmdptr);
-		out_le32(&chan->intr_sel, save_dbdma[i].intr_sel);
-		out_le32(&chan->br_sel, save_dbdma[i].br_sel);
-		out_le32(&chan->wait_sel, save_dbdma[i].wait_sel);
-	}
-
-	KL_OUT(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]);
-	KL_OUT(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]);
-	base8 = ((volatile u8 *)keylargo_base) + KEYLARGO_GPIO_EXTINT_0;
-	for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
-		out_8(base8+i, save_gpio_extint[i]);
-	base8 = ((volatile u8 *)keylargo_base) + KEYLARGO_GPIO_0;
-	for (i=0; i<KEYLARGO_GPIO_CNT; i++)
-		out_8(base8+i, save_gpio_normal[i]);
-
-	/* FIXME more black magic with OpenPIC ... */
-	if (board_features & FTR_NEED_OPENPIC_TWEAK) {
-		KL_BIC(0x506e0, 0x00400000);
-		KL_BIC(0x506e0, 0x80000000);
-	}
-
-	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
-	udelay(100);
-}
-#endif /* CONFIG_PMAC_PBOOK */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)