LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: Dynamic libraries do not work
From: Theo Gjaltema @ 2005-05-27  5:36 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <528646bc05052615304d896b94@mail.gmail.com>

Grant Likely schreef:

>On 5/26/05, Theo Gjaltema <gjalt007@chello.nl> wrote:
>  
>
>>Hello,
>>
>>I have a linux 2.4.20 kernel running, but the files in the ramdisk fail
>>to execute if they are dynamically build.
>>The whole system stops (debuggers shows that it crashed while in an erea
>>where no flash/ram is present.
>>Anyone an idea?
>>There is nog difference between the use of a ramdisk or an nfs mounted
>>root filesystem.
>>
>>    
>>
>More data please;  Make sure you attach actual output when asking for help.
>
>  
>
You are right, this gives too little info. Since the system stops 
without giving any data, I don't know what to attach
maybe:
RAM: 64 Mbyte

(using a static linked busybox: activating a sh (=busybox) b 
::sysinit:/bin/sh)
sh: /lib/ld.so.1
< help page of ld.so.1>
sh: /lib/ld.so.1 --verify /bin/xxx (or just any dynamic linked library)
<here the system has crahed>

or
sh: /bin/xxx
<here the system has crashed>

I have tried to step through the dynamic linking, but did not succeed 
til after the creation of a thread.
With a dynamic linked busybox the system stops after a message such as
"freeing xxx kbytes" (I don't know the actual number by head)
When init is then called, which is a part of the busybox which is dyn. 
liked, it crashes.


Greetings,
   Theo

^ permalink raw reply

* [PATCH] EXPERIMENTAL: global suspend cleanup
From: Benjamin Herrenschmidt @ 2005-05-27  6:57 UTC (permalink / raw)
  To: linuxppc-dev list; +Cc: Linux-pm mailing list, Linux Kernel list

Hi !

(This is not to be merged upstream or anywhere else yet)

This patch applies on top of my previous ones. It moves all of the
PowerMac PM code away from drivers/macintosh/via-pmu.c to a new
arch/ppc/platforms/pmac_pm.c file, and "merges" the code for supporting
suspend to RAM and suspend to disk in a more consistent way. It also
fixes issues with suspend to disk. Currently, the refrigerator is still
used for suspend to RAM _and_ suspend to disk, I may consider keeping it
if it gets fast & reliable enough in 2.6.13 as it does work around
issues with misbehaved userland processes vs. kernel driver races,
though i'd rather have the kernel fixed :)

Note to linux-pm citizens: This merges the pmac PM code into the "core"
PM infrastructure. In order to do that properly, I had to add a
significant amount of callbacks to pm_ops, in fact, I need basically a
hook between every step for various reasons. There is also some
significant discrepancy between the hooks used by "generic" stuffs and
the ones used by swsusp. The later doesn't call all the normal hooks in
all cases but then has it's own support functions
(arch_prepare_suspend(), save/restore_cpu_state()) that are not in
pm_ops... this is rather a mess, though I got it all together for pmac.

Please comment on those changes.

I also fixed what I think is a possible bug in device_suspend() if it
fails, it can leave some stuffs in the dpm_irq_off list forever.

I've also had to remove the sysdev I used for the interrupt controllers.
I have an ordering problems here. I absolutely need the interrupt
controller suspend code to be run after cpufreq and the resume one
before cpufreq, which is simply not possible right now with a sysdev
(unless I hook on the cpu class itself suspend/resume routines but
that's ugly). cpufreq is a driver of class cpu, which is first
registered, and thus is always the first in the list.

For now, the PIC suspend/resume code is back into arch specific realm.

I'm still having some problems with the refrigerator. It tends to
regulary fail to freeze pmud for some reason I haven't yet explained. I
need to add more debugging to it. But I may not bother if Nigel's new
implementation gets in 2.6.13.

I did some tests of both suspend to ram and to disk on an old tipb model
and it appears to work fine, but I haven't stressed it nor tested on any
other machine yet.

Note that with this patch, you can use echo "mem" /sys/power/state to
trigger suspend-to-RAM. The old ioctl on /dev/pmu still works, and will
trigger suspend-to-RAM on machiens where it's supported and will
fallback to suspend-to-disk when not.

Index: linux-work/arch/ppc/platforms/Makefile
===================================================================
--- linux-work.orig/arch/ppc/platforms/Makefile	2005-05-27 16:06:59.000000000 +1000
+++ linux-work/arch/ppc/platforms/Makefile	2005-05-27 16:07:24.000000000 +1000
@@ -10,8 +10,9 @@
 obj-$(CONFIG_PCI)		+= apus_pci.o
 endif
 obj-$(CONFIG_PPC_PMAC)		+= pmac_pic.o pmac_setup.o pmac_time.o \
-					pmac_feature.o pmac_pci.o pmac_sleep.o \
-					pmac_low_i2c.o pmac_cache.o
+				   pmac_feature.o pmac_pci.o pmac_sleep.o \
+				   pmac_low_i2c.o pmac_cache.o pmac_pm.o
+
 obj-$(CONFIG_PPC_CHRP)		+= chrp_setup.o chrp_time.o chrp_pci.o \
 					chrp_pegasos_eth.o
 obj-$(CONFIG_PPC_PREP)		+= prep_pci.o prep_setup.o
Index: linux-work/arch/ppc/platforms/pmac_pm.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-work/arch/ppc/platforms/pmac_pm.c	2005-05-27 16:07:24.000000000 +1000
@@ -0,0 +1,782 @@
+/*
+ * PowerMac Power Management core
+ *
+ * Copyright (C) 2005 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * Bits from drivers/macintosh/via-pmu.c
+ *
+ * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
+ * Copyright (C) 2001-2002 Benjamin Herrenschmidt
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/suspend.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/cpu.h>
+#include <linux/syscalls.h>
+#include <linux/reboot.h>
+
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/pmac_feature.h>
+#include <asm/mmu_context.h>
+#include <asm/cputable.h>
+#include <asm/time.h>
+#include <asm/sections.h>
+#include <asm/system.h>
+#include <asm/open_pic.h>
+
+#ifdef CONFIG_PM_DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+/* debugging */
+int __fake_sleep;
+
+/* lid wakeup control (fixme) */
+int pmac_option_lid_wakeup __pmacdata;
+EXPORT_SYMBOL_GPL(pmac_option_lid_wakeup);
+
+/* main callback for suspend to RAM */
+static int (*pmac_pm_low_suspend)(void) __pmacdata;
+
+/* assembly stuff */
+extern void low_sleep_handler(void);
+/* pmac_pic stuff */
+extern void pmacpic_suspend(void);
+extern void pmacpic_resume(void);
+
+
+/*************************************************************************
+ *
+ * Here is the "old style" PowerMac PM notifiers. They are still used by a
+ * couple of drivers that haven't yet been fitted in the device model.
+ * They will ultimately be deprecated.
+ *
+ *************************************************************************/
+
+static LIST_HEAD(sleep_notifiers);
+
+int __pmac pmu_register_sleep_notifier(struct pmu_sleep_notifier *n)
+{
+	struct list_head *list;
+	struct pmu_sleep_notifier *notifier;
+
+	for (list = sleep_notifiers.next; list != &sleep_notifiers;
+	     list = list->next) {
+		notifier = list_entry(list, struct pmu_sleep_notifier, list);
+		if (n->priority > notifier->priority)
+			break;
+	}
+	__list_add(&n->list, list->prev, list);
+	return 0;
+}
+EXPORT_SYMBOL(pmu_register_sleep_notifier);
+
+int __pmac pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n)
+{
+	if (n->list.next == 0)
+		return -ENOENT;
+	list_del(&n->list);
+	n->list.next = NULL;
+	return 0;
+}
+EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
+
+/* Sleep is broadcast last-to-first */
+static int __pmac broadcast_sleep(int when, int fallback)
+{
+	int ret = PBOOK_SLEEP_OK;
+	struct list_head *list;
+	struct pmu_sleep_notifier *notifier;
+
+	for (list = sleep_notifiers.prev; list != &sleep_notifiers;
+	     list = list->prev) {
+		notifier = list_entry(list, struct pmu_sleep_notifier, list);
+		ret = notifier->notifier_call(notifier, when);
+		if (ret != PBOOK_SLEEP_OK) {
+			DBG("sleep %d rejected by %p (%p)\n",
+			    when, notifier, notifier->notifier_call);
+			for (; list != &sleep_notifiers; list = list->next) {
+				notifier = list_entry(list,
+					      struct pmu_sleep_notifier, list);
+				notifier->notifier_call(notifier, fallback);
+			}
+			return ret;
+		}
+	}
+	return ret;
+}
+
+/* Wake is broadcast first-to-last */
+static int __pmac broadcast_wake(void)
+{
+	int ret = PBOOK_SLEEP_OK;
+	struct list_head *list;
+	struct pmu_sleep_notifier *notifier;
+
+	for (list = sleep_notifiers.next; list != &sleep_notifiers;
+	     list = list->next) {
+		notifier = list_entry(list, struct pmu_sleep_notifier, list);
+		notifier->notifier_call(notifier, PBOOK_WAKE);
+	}
+	return ret;
+}
+
+/**************************************************************************
+ *
+ * Here, we have code to save/restore PCI config space. Most of that code
+ * should be removed once we are confident with the generic code, including
+ * with P2P bridges
+ *
+ **************************************************************************/
+
+static struct pci_save {
+	u16	command;
+	u16	cache_lat;
+	u16	intr;
+	u32	bars[6];
+	u32	rom_address;
+} *pbook_pci_saves __pmacdata;
+static int pbook_npci_saves __pmacdata;
+
+static void __pmac pbook_alloc_pci_save(void)
+{
+	int npci;
+	struct pci_dev *pd = NULL;
+
+	npci = 0;
+	while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+		++npci;
+	}
+	if (npci == 0)
+		return;
+	pbook_pci_saves = (struct pci_save *)
+		kmalloc(npci * sizeof(struct pci_save), GFP_KERNEL);
+	pbook_npci_saves = npci;
+}
+
+static void __pmac pbook_free_pci_save(void)
+{
+	if (pbook_pci_saves == NULL)
+		return;
+	kfree(pbook_pci_saves);
+	pbook_pci_saves = NULL;
+	pbook_npci_saves = 0;
+}
+
+static void __pmac pbook_pci_save(void)
+{
+	struct pci_save *ps = pbook_pci_saves;
+	struct pci_dev *pd = NULL;
+	int npci = pbook_npci_saves;
+	int i;
+
+	if (ps == NULL)
+		return;
+
+	while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+		if (npci-- == 0)
+			return;
+		switch (pd->hdr_type) {
+		case PCI_HEADER_TYPE_NORMAL:
+			pci_read_config_word(pd, PCI_COMMAND, &ps->command);
+			pci_read_config_word(pd, PCI_CACHE_LINE_SIZE,
+					     &ps->cache_lat);
+			pci_read_config_word(pd, PCI_INTERRUPT_LINE,
+					     &ps->intr);
+			pci_read_config_dword(pd, PCI_ROM_ADDRESS,
+					      &ps->rom_address);
+			for (i=0; i<6; i++)
+				pci_read_config_dword(pd,
+						      PCI_BASE_ADDRESS_0+i*4,
+						      &ps->bars[i]);
+			break;
+		case PCI_HEADER_TYPE_BRIDGE:
+			pci_read_config_word(pd, PCI_COMMAND, &ps->command);
+			pci_read_config_word(pd, PCI_CACHE_LINE_SIZE,
+					     &ps->cache_lat);
+			pci_read_config_dword(pd, PCI_ROM_ADDRESS1,
+					      &ps->rom_address);
+			pci_read_config_dword(pd, PCI_BASE_ADDRESS_0,
+					      &ps->bars[0]);
+			pci_read_config_dword(pd, PCI_BASE_ADDRESS_1,
+					      &ps->bars[1]);
+			break;
+		case PCI_HEADER_TYPE_CARDBUS:
+			pci_read_config_word(pd, PCI_COMMAND, &ps->command);
+			pci_read_config_word(pd, PCI_CACHE_LINE_SIZE,
+					     &ps->cache_lat);
+			pci_read_config_word(pd, PCI_INTERRUPT_LINE,
+					     &ps->intr);
+			pci_read_config_dword(pd, PCI_BASE_ADDRESS_0,
+					      &ps->bars[0]);
+			break;
+		}			
+		++ps;
+	}
+}
+
+/* For this to work, we must take care of a few things: If gmac was enabled
+ * during boot, it will be in the pci dev list. If it's disabled at this point
+ * (and it will probably be), then you can't access it's config space.
+ */
+static void __pmac pbook_pci_restore(void)
+{
+	u16 cmd;
+	struct pci_save *ps = pbook_pci_saves - 1;
+	struct pci_dev *pd = NULL;
+	int npci = pbook_npci_saves;
+	int i;
+
+	while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+		if (npci-- == 0)
+			return;
+		ps++;
+		if (ps->command == 0)
+			continue;
+		pci_read_config_word(pd, PCI_COMMAND, &cmd);
+		if ((ps->command & ~cmd) == 0)
+			continue;
+		switch (pd->hdr_type) {
+		case PCI_HEADER_TYPE_NORMAL:
+			for (i = 0; i < 6; ++i)
+				pci_write_config_dword(pd,
+						       PCI_BASE_ADDRESS_0+i*4,
+						       ps->bars[i]);
+			pci_write_config_dword(pd, PCI_ROM_ADDRESS,
+					       ps->rom_address);
+			pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
+					      ps->cache_lat);
+			pci_write_config_word(pd, PCI_INTERRUPT_LINE,
+					      ps->intr);
+			pci_write_config_word(pd, PCI_COMMAND, ps->command);
+			break;
+		case PCI_HEADER_TYPE_BRIDGE:
+			pci_write_config_dword(pd, PCI_BASE_ADDRESS_0,
+					       ps->bars[0]);
+			pci_write_config_dword(pd, PCI_BASE_ADDRESS_1,
+					       ps->bars[1]);
+			pci_write_config_dword(pd, PCI_ROM_ADDRESS,
+					       ps->rom_address);
+			pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
+					      ps->cache_lat);
+			pci_write_config_word(pd, PCI_COMMAND, ps->command);
+			break;
+		case PCI_HEADER_TYPE_CARDBUS:
+			pci_write_config_dword(pd, PCI_BASE_ADDRESS_0, 
+					       ps->bars[0]);
+			pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
+					      ps->cache_lat);
+			pci_write_config_word(pd, PCI_INTERRUPT_LINE,
+					      ps->intr);
+			pci_write_config_word(pd, PCI_COMMAND, ps->command);
+			break;
+		}
+	}
+}
+
+/*************************************************************************
+ *
+ * Here are the per-machine family low level sleep routines and the
+ * par-machine family initialization routines.
+ *
+ *************************************************************************/
+
+
+#define PB3400_MEM_CTRL		0xf8000000
+#define PB3400_MEM_CTRL_SLEEP	0x70
+
+static void __iomem *mem_ctrl_3400 __pmacdata;
+
+static int __pmac pmac_pm_sleep_3400(void)
+{
+	int i, x;
+	unsigned int hid0;
+	unsigned long p;
+	struct adb_request sleep_req;
+	unsigned int __iomem *mem_ctrl_sleep;
+
+	mem_ctrl_sleep = mem_ctrl_3400 + PB3400_MEM_CTRL_SLEEP;
+
+	/* Set the memory controller to keep the memory refreshed
+	   while we're asleep */
+	for (i = 0x403f; i >= 0x4000; --i) {
+		out_be32(mem_ctrl_sleep, i);
+		do {
+			x = (in_be32(mem_ctrl_sleep) >> 16) & 0x3ff;
+		} while (x == 0);
+		if (x >= 0x100)
+			break;
+	}
+
+	/* Ask the PMU to put us to sleep */
+	pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
+	while (!sleep_req.complete)
+		mb();
+
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);
+
+	/* displacement-flush the L2 cache - necessary? */
+	for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000)
+		i = *(volatile int *)p;
+
+	/* Put the CPU into sleep mode */
+	asm volatile("mfspr %0,1008" : "=r" (hid0) :);
+	hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;
+	asm volatile("mtspr 1008,%0" : : "r" (hid0));
+	_nmask_and_or_msr(0, MSR_POW | MSR_EE);
+	udelay(10);
+
+	/* OK, we're awake again, start restoring things */
+	out_be32(mem_ctrl_sleep, 0x3f);
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
+	pbook_pci_restore();
+	pmu_unlock();
+
+	mdelay(10);
+
+	return 0;
+}
+
+static void __pmac pmac_pm_init_3400(void)
+{
+	/* first map in the memory controller registers */
+	mem_ctrl_3400 = ioremap(PB3400_MEM_CTRL, 0x100);
+	if (mem_ctrl_3400 == NULL) {
+		printk(KERN_ERR "pmac_pm_init_3400: ioremap failed\n");
+		return;
+	}
+
+	pmac_pm_low_suspend = pmac_pm_sleep_3400;
+}
+
+#define	GRACKLE_PM	(1<<7)
+#define GRACKLE_DOZE	(1<<5)
+#define	GRACKLE_NAP	(1<<4)
+#define	GRACKLE_SLEEP	(1<<3)
+
+static struct pci_dev *grackle __pmacdata;
+
+static int __pmac pmac_pm_sleep_grackle(void)
+{
+	unsigned long save_l2cr;
+	unsigned short pmcr1;
+	struct adb_request req;
+
+	/* Turn off various things. Darwin does some retry tests here... */
+	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0,
+		    PMU_POW0_OFF | PMU_POW0_HARD_DRIVE);
+	pmu_wait_complete(&req);
+	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+		    PMU_POW_OFF | PMU_POW_BACKLIGHT |
+		    PMU_POW_IRLED | PMU_POW_MEDIABAY);
+	pmu_wait_complete(&req);
+
+	/* For 750, save backside cache setting and disable it */
+	save_l2cr = _get_L2CR();	/* (returns -1 if not available) */
+
+	if (!__fake_sleep) {
+		/* Ask the PMU to put us to sleep */
+		pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
+		pmu_wait_complete(&req);
+	}
+
+	/* The VIA is supposed not to be restored correctly*/
+	pmu_save_via_state();
+
+	/* We shut down some HW */
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);
+
+	pci_read_config_word(grackle, 0x70, &pmcr1);
+	/* Apparently, MacOS uses NAP mode for Grackle ??? */
+	pmcr1 &= ~(GRACKLE_DOZE|GRACKLE_SLEEP); 
+	pmcr1 |= GRACKLE_PM|GRACKLE_NAP;
+	pci_write_config_word(grackle, 0x70, pmcr1);
+
+	/* Call low-level ASM sleep handler */
+	if (__fake_sleep)
+		mdelay(5000);
+	else
+		low_sleep_handler();
+
+	/* We're awake again, stop grackle PM */
+	pci_read_config_word(grackle, 0x70, &pmcr1);
+	pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); 
+	pci_write_config_word(grackle, 0x70, pmcr1);
+
+	/* Make sure the PMU is idle */
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
+	pmu_restore_via_state();
+	
+	/* Restore L2 cache */
+	if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
+ 		_set_L2CR(save_l2cr);
+	
+	/* Power things up */
+	pmu_unlock();
+	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0,
+			PMU_POW0_ON | PMU_POW0_HARD_DRIVE);
+	pmu_wait_complete(&req);
+	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+		    PMU_POW_ON | PMU_POW_BACKLIGHT | PMU_POW_CHARGER |
+		    PMU_POW_IRLED | PMU_POW_MEDIABAY);
+	pmu_wait_complete(&req);
+
+	return 0;
+}
+
+static void __pmac pmac_pm_init_grackle(void)
+{
+	grackle = pci_find_slot(0, 0);
+	if (!grackle)
+		return;
+
+	pmac_pm_low_suspend = pmac_pm_sleep_grackle;
+}
+
+
+static int __pmac pmac_pm_sleep_core99(void)
+{
+	unsigned long save_l2cr;
+	unsigned long save_l3cr;
+	struct adb_request req;
+	
+	/* Tell PMU what events will wake us up */
+	pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS,
+		0xff, 0xff);
+	pmu_wait_complete(&req);
+	pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_SET_WAKEUP_EVENTS,
+		0, PMU_PWR_WAKEUP_KEY |
+		(pmac_option_lid_wakeup ? PMU_PWR_WAKEUP_LID_OPEN : 0));
+	pmu_wait_complete(&req);
+
+	/* Save the state of the L2 and L3 caches */
+	save_l3cr = _get_L3CR();	/* (returns -1 if not available) */
+	save_l2cr = _get_L2CR();	/* (returns -1 if not available) */
+
+	if (!__fake_sleep) {
+		/* Ask the PMU to put us to sleep */
+		pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
+		pmu_wait_complete(&req);
+	}
+
+	/* The VIA is supposed not to be restored correctly*/
+	pmu_save_via_state();
+
+	/* Shut down various ASICs. There's a chance that we can no longer
+	 * talk to the PMU after this, so I moved it to _after_ sending the
+	 * sleep command to it. Still need to be checked.
+	 */
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1);
+
+	/* Call low-level ASM sleep handler */
+	if (__fake_sleep)
+		mdelay(5000);
+	else
+		low_sleep_handler();
+
+	/* Restore Apple core ASICs state */
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0);
+
+	/* Restore VIA */
+	pmu_restore_via_state();
+
+	/* Restore video */
+	pmac_call_early_video_resume();
+
+	/* Restore L2 cache */
+	if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
+ 		_set_L2CR(save_l2cr);
+	/* Restore L3 cache */
+	if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
+ 		_set_L3CR(save_l3cr);
+	
+	/* Tell PMU we are ready */
+	pmu_unlock();
+	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
+	pmu_wait_complete(&req);
+
+	return 0;
+}
+
+static void __pmac pmac_pm_init_core99(void)
+{
+	pmac_pm_low_suspend = pmac_pm_sleep_core99;
+}
+
+
+
+/*************************************************************************
+ *
+ * Here are the callbacks interfacing with the common code.
+ *
+ *************************************************************************/
+
+static inline void wakeup_decrementer(void)
+{
+	set_dec(tb_ticks_per_jiffy);
+	/* No currently-supported powerbook has a 601,
+	 * so use get_tbl, not native
+	 */
+	last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
+}
+
+static int __pmac pmac_pm_pre_freeze(suspend_state_t state)
+{
+	int ret;
+
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	/* Check if suspend to RAM is possible */
+	if (state == PM_SUSPEND_MEM) {
+		if (pmac_pm_low_suspend == NULL)
+			return -EINVAL;
+		if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)
+			return -EINVAL;
+		if (num_online_cpus() > 1 || cpu_is_offline(0))
+			return -EAGAIN;
+	}
+
+	DBG("Notify (1) old style drivers...\n");
+
+	/* Notify old-style device drivers & userland */
+	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
+	if (ret != PBOOK_SLEEP_OK) {
+		printk(KERN_ERR "Sleep rejected by drivers\n");
+		return -EBUSY;
+	}
+
+	/* Sync the disks. */
+
+	/* XXX It would be nice to have some way to ensure that
+	 * nobody is dirtying any new buffers while we wait. That
+	 * could be achieved using the refrigerator for processes
+	 * that swsusp uses
+	 */
+	DBG("Sync disks...\n");
+	sys_sync();
+
+	//	return (state == PM_SUSPEND_DISK);
+	return 1;
+}
+
+static int __pmac pmac_pm_prepare(suspend_state_t state)
+{
+	int ret;
+
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+
+	/* Sleep can fail now. May not be very robust but useful for
+	 * debugging
+	 */
+	DBG("Notify (2) old style drivers...\n");
+	ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE);
+	if (ret != PBOOK_SLEEP_OK) {
+		printk(KERN_ERR "Driver sleep failed\n");
+		return -EBUSY;
+	}
+
+	/* Allocate room for PCI save */
+	DBG("Alloc PCI stuffs...\n");
+	pbook_alloc_pci_save();
+
+	return 0;
+}
+
+static int __pmac pmac_pm_prepare_irqs(suspend_state_t state)
+{
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	/* That state only applies to suspend to RAM */
+	if (state != PM_SUSPEND_MEM)
+		return 0;
+
+	/* Stop interrupts on openpic */
+	if (pmu_get_model() == PMU_KEYLARGO_BASED)
+		openpic_set_priority(0xf);
+
+	/* Stop preemption */
+	preempt_disable();
+
+	/* Disable clock spreading on some machines */
+	pmac_tweak_clock_spreading(0);
+
+	/* Make sure the decrementer won't interrupt us */
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+	/* Make sure any pending DEC interrupt occurring while we did
+	 * the above didn't re-enable the DEC */
+	mb();
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+
+	/* We disable interrupts now and not in the generic code so
+	 * that we entre pmac_pm_finish_irqs() with interrupts still
+	 * off and can properly wakeup decrementer before enabling them.
+	 */
+	local_irq_disable();
+
+	return 0;
+}
+
+static void __pmac pmac_pm_pre_suspend(void)
+{
+	DBG("%s\n", __FUNCTION__);
+
+	/* Save the state of PCI config space for some slots */
+	pbook_pci_save();
+
+	/* Suspend openpic */
+	if (pmu_get_model() == PMU_KEYLARGO_BASED)
+		openpic_suspend();
+	else
+		pmacpic_suspend();
+
+	/* Giveup the lazy FPU & vec so we don't have to back them
+	 * up from the low level code
+	 */
+	enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+		enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+}
+
+static void __pmac pmac_pm_post_suspend(void)
+{
+	DBG("%s\n", __FUNCTION__);
+
+	/* Restore the state of PCI config space for some slots */
+	pbook_pci_restore();
+
+	/* Resume openpic */
+	if (pmu_get_model() == PMU_KEYLARGO_BASED)
+		openpic_resume();
+	else
+		pmacpic_resume();
+
+	/* Restore userland MMU context */
+	set_context(current->active_mm->context, current->active_mm->pgd);
+}
+
+static int __pmac pmac_pm_enter(suspend_state_t state)
+{
+	int rc = 0;
+
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	if (state == PM_SUSPEND_MEM) {
+		pmac_pm_pre_suspend();
+		rc = pmac_pm_low_suspend();
+		pmac_pm_post_suspend();
+		
+	} else if (state == PM_SUSPEND_DISK) {
+		device_shutdown();
+		machine_restart(NULL);
+	} else
+		rc = -EINVAL;
+	return rc;
+}
+
+static void __pmac pmac_pm_finish_irqs(suspend_state_t state)
+{
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	/* That state only applies to suspend to RAM */
+	if (state != PM_SUSPEND_MEM)
+		return;
+
+	/* Restart jiffies & scheduling */
+	wakeup_decrementer();
+
+	/* Start interrupts on openpic */
+	if (pmu_get_model() == PMU_KEYLARGO_BASED)
+		openpic_set_priority(0);
+
+	/* Re-enable local CPU interrupts */
+	local_irq_enable();
+	mdelay(10);
+	preempt_enable();
+
+	/* Re-enable clock spreading on some machines */
+	pmac_tweak_clock_spreading(1);
+}
+
+static void __pmac pmac_pm_finish(suspend_state_t state)
+{
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	/* Free PCI save block */
+	pbook_free_pci_save();
+
+}
+
+static void __pmac pmac_pm_post_freeze(suspend_state_t state)
+{
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	/* Broadcase old style wakeup */
+	broadcast_wake();
+}
+
+static struct pm_ops pmac_pm_ops  __pmacdata = {
+	.pm_disk_mode	= PM_DISK_PLATFORM,
+	.pre_freeze	= pmac_pm_pre_freeze,
+	.prepare	= pmac_pm_prepare,
+	.prepare_irqs	= pmac_pm_prepare_irqs,
+	.enter		= pmac_pm_enter,
+	.finish_irqs	= pmac_pm_finish_irqs,
+	.finish		= pmac_pm_finish,
+	.post_freeze	= pmac_pm_post_freeze,
+};
+
+static int pmac_pm_init(void)
+{
+	if (_machine != _MACH_Pmac)
+		return 0;
+
+	switch (pmu_get_model()) {
+	case PMU_OHARE_BASED:
+		pmac_pm_init_3400();
+		break;
+	case PMU_HEATHROW_BASED:
+	case PMU_PADDINGTON_BASED:
+		pmac_pm_init_grackle();
+		break;
+	case PMU_KEYLARGO_BASED:
+		pmac_pm_init_core99();
+		break;
+	}
+
+#ifdef CONFIG_SOFTWARE_SUSPEND
+	ppc_md.save_processor_state = pmac_pm_pre_suspend;
+	ppc_md.restore_processor_state = pmac_pm_post_suspend;
+#endif
+
+	pm_set_ops(&pmac_pm_ops);
+
+	return 0;
+}
+
+late_initcall(pmac_pm_init);
Index: linux-work/arch/ppc/platforms/pmac_setup.c
===================================================================
--- linux-work.orig/arch/ppc/platforms/pmac_setup.c	2005-05-27 16:06:59.000000000 +1000
+++ linux-work/arch/ppc/platforms/pmac_setup.c	2005-05-27 16:07:24.000000000 +1000
@@ -423,68 +423,6 @@
 #endif
 }
 
-static int initializing = 1;
-/* TODO: Merge the suspend-to-ram with the common code !!!
- * currently, this is a stub implementation for suspend-to-disk
- * only
- */
-
-#ifdef CONFIG_SOFTWARE_SUSPEND
-
-static int pmac_pm_prepare(suspend_state_t state)
-{
-	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-	return 0;
-}
-
-static int pmac_pm_enter(suspend_state_t state)
-{
-	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-	/* Giveup the lazy FPU & vec so we don't have to back them
-	 * up from the low level code
-	 */
-	enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
-	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
-		enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
-	return 0;
-}
-
-static int pmac_pm_finish(suspend_state_t state)
-{
-	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-	/* Restore userland MMU context */
-	set_context(current->active_mm->context, current->active_mm->pgd);
-
-	return 0;
-}
-
-static struct pm_ops pmac_pm_ops = {
-	.pm_disk_mode	= PM_DISK_SHUTDOWN,
-	.prepare	= pmac_pm_prepare,
-	.enter		= pmac_pm_enter,
-	.finish		= pmac_pm_finish,
-};
-
-#endif /* CONFIG_SOFTWARE_SUSPEND */
-
-static int pmac_late_init(void)
-{
-	initializing = 0;
-#ifdef CONFIG_SOFTWARE_SUSPEND
-	pm_set_ops(&pmac_pm_ops);
-#endif /* CONFIG_SOFTWARE_SUSPEND */
-	return 0;
-}
-
-late_initcall(pmac_late_init);
-
 /* can't be __init - can be called whenever a disk is first accessed */
 void __pmac
 note_bootable_part(dev_t dev, int part, int goodness)
@@ -492,7 +430,7 @@
 	static int found_boot = 0;
 	char *p;
 
-	if (!initializing)
+	if (system_state != SYSTEM_BOOTING)
 		return;
 	if ((goodness <= current_root_goodness) &&
 	    ROOT_DEV != DEFAULT_ROOT_DEVICE)
Index: linux-work/drivers/base/power/suspend.c
===================================================================
--- linux-work.orig/drivers/base/power/suspend.c	2005-05-27 16:06:59.000000000 +1000
+++ linux-work/drivers/base/power/suspend.c	2005-05-27 16:07:24.000000000 +1000
@@ -100,8 +100,19 @@
 		put_device(dev);
 	}
 	up(&dpm_list_sem);
-	if (error)
+	if (error) {
+		/* we failed... before resuming, bring back devices from
+		 * dpm_off_irq list back to main dpm_off list, we do want
+		 * to call resume() on them, in case they partially suspended
+		 * despite returning -EAGAIN
+		 */
+		while (!list_empty(&dpm_off_irq)) {
+			struct list_head * entry = dpm_off_irq.next;
+			list_del(entry);
+			list_add(entry, &dpm_off);
+		}
 		dpm_resume();
+	}
 	up(&dpm_sem);
 	return error;
 }
Index: linux-work/drivers/macintosh/via-pmu.c
===================================================================
--- linux-work.orig/drivers/macintosh/via-pmu.c	2005-05-27 16:06:59.000000000 +1000
+++ linux-work/drivers/macintosh/via-pmu.c	2005-05-27 16:42:57.000000000 +1000
@@ -14,10 +14,7 @@
  * THIS DRIVER IS BECOMING A TOTAL MESS !
  *  - Cleanup atomically disabling reply to PMU events after
  *    a sleep or a freq. switch
- *  - Move sleep code out of here to pmac_pm, merge into new
- *    common PM infrastructure
  *  - Move backlight code out as well
- *  - Save/Restore PCI space properly
  *
  */
 #include <stdarg.h>
@@ -45,8 +42,6 @@
 #include <linux/device.h>
 #include <linux/sysdev.h>
 #include <linux/suspend.h>
-#include <linux/syscalls.h>
-#include <linux/cpu.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
@@ -54,11 +49,11 @@
 #include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
-#include <asm/pmac_feature.h>
 #include <asm/uaccess.h>
-#include <asm/mmu_context.h>
 #include <asm/cputable.h>
 #include <asm/time.h>
+#include <asm/pmac_feature.h>
+
 #ifdef CONFIG_PMAC_BACKLIGHT
 #include <asm/backlight.h>
 #endif
@@ -70,7 +65,6 @@
 /* Some compile options */
 #undef SUSPEND_USES_PMU
 #define DEBUG_SLEEP
-#undef HACKED_PCI_SAVE
 
 /* Misc minor number allocated for /dev/pmu */
 #define PMU_MINOR		154
@@ -155,12 +149,12 @@
 static u8 pmu_intr_mask;
 static int pmu_version;
 static int drop_interrupts;
-#ifdef CONFIG_PMAC_PBOOK
-static int option_lid_wakeup = 1;
-static int sleep_in_progress;
-#endif /* CONFIG_PMAC_PBOOK */
 static unsigned long async_req_locks;
 static unsigned int pmu_irq_stats[11];
+static int pmu_sys_suspended = 0;
+
+/* from pmac_pm ... */
+extern int pmac_option_lid_wakeup;
 
 static struct proc_dir_entry *proc_pmu_root;
 static struct proc_dir_entry *proc_pmu_info;
@@ -168,7 +162,6 @@
 static struct proc_dir_entry *proc_pmu_options;
 static int option_server_mode;
 
-#ifdef CONFIG_PMAC_PBOOK
 int pmu_battery_count;
 int pmu_cur_battery;
 unsigned int pmu_power_flags;
@@ -176,14 +169,11 @@
 static int query_batt_timer = BATTERY_POLLING_COUNT;
 static struct adb_request batt_req;
 static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES];
-#endif /* CONFIG_PMAC_PBOOK */
 
 #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
 extern int disable_kernel_backlight;
 #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
 
-int __fake_sleep;
-int asleep;
 struct notifier_block *sleep_notifier_list;
 
 #ifdef CONFIG_ADB
@@ -210,11 +200,9 @@
 static int pmu_set_backlight_level(int level, void* data);
 static int pmu_set_backlight_enable(int on, int level, void* data);
 #endif /* CONFIG_PMAC_BACKLIGHT */
-#ifdef CONFIG_PMAC_PBOOK
 static void pmu_pass_intr(unsigned char *data, int len);
 static int proc_get_batt(char *page, char **start, off_t off,
 			int count, int *eof, void *data);
-#endif /* CONFIG_PMAC_PBOOK */
 static int proc_read_options(char *page, char **start, off_t off,
 			int count, int *eof, void *data);
 static int proc_write_options(struct file *file, const char __user *buffer,
@@ -232,10 +220,6 @@
 };
 #endif /* CONFIG_ADB */
 
-extern void low_sleep_handler(void);
-extern void enable_kernel_altivec(void);
-extern void enable_kernel_fp(void);
-
 #ifdef DEBUG_SLEEP
 int pmu_polled_request(struct adb_request *req);
 int pmu_wink(struct adb_request *req);
@@ -407,9 +391,7 @@
 
 	bright_req_1.complete = 1;
 	bright_req_2.complete = 1;
-#ifdef CONFIG_PMAC_PBOOK
 	batt_req.complete = 1;
-#endif
 
 #ifdef CONFIG_PPC32
 	if (pmu_kind == PMU_KEYLARGO_BASED)
@@ -468,7 +450,6 @@
 	register_backlight_controller(&pmu_backlight_controller, NULL, "pmu");
 #endif /* CONFIG_PMAC_BACKLIGHT */
 
-#ifdef CONFIG_PMAC_PBOOK
   	if (machine_is_compatible("AAPL,3400/2400") ||
   		machine_is_compatible("AAPL,3500")) {
 		int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
@@ -496,11 +477,9 @@
 				pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART;
 		}
 	}
-#endif /* CONFIG_PMAC_PBOOK */
 	/* Create /proc/pmu */
 	proc_pmu_root = proc_mkdir("pmu", NULL);
 	if (proc_pmu_root) {
-#ifdef CONFIG_PMAC_PBOOK
 		int i;
 
 		for (i=0; i<pmu_battery_count; i++) {
@@ -509,7 +488,6 @@
 			proc_pmu_batt[i] = create_proc_read_entry(title, 0, proc_pmu_root,
 						proc_get_batt, (void *)i);
 		}
-#endif /* CONFIG_PMAC_PBOOK */
 
 		proc_pmu_info = create_proc_read_entry("info", 0, proc_pmu_root,
 					proc_get_info, NULL);
@@ -595,17 +573,6 @@
 	return pmu_kind;
 }
 
-#ifndef CONFIG_PPC64
-static inline void wakeup_decrementer(void)
-{
-	set_dec(tb_ticks_per_jiffy);
-	/* No currently-supported powerbook has a 601,
-	 * so use get_tbl, not native
-	 */
-	last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
-}
-#endif
-
 static void pmu_set_server_mode(int server_mode)
 {
 	struct adb_request req;
@@ -629,7 +596,6 @@
 	pmu_wait_complete(&req);
 }
 
-#ifdef CONFIG_PMAC_PBOOK
 
 /* This new version of the code for 2400/3400/3500 powerbooks
  * is inspired from the implementation in gkrellm-pmu
@@ -803,6 +769,8 @@
 static void __pmac
 query_battery_state(void)
 {
+	if (pmu_sys_suspended)
+		return;
 	if (test_and_set_bit(0, &async_req_locks))
 		return;
 	if (pmu_kind == PMU_OHARE_BASED)
@@ -813,8 +781,6 @@
 			2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1);
 }
 
-#endif /* CONFIG_PMAC_PBOOK */
-
 static int __pmac
 proc_get_info(char *page, char **start, off_t off,
 		int count, int *eof, void *data)
@@ -823,11 +789,9 @@
 
 	p += sprintf(p, "PMU driver version     : %d\n", PMU_DRIVER_VERSION);
 	p += sprintf(p, "PMU firmware version   : %02x\n", pmu_version);
-#ifdef CONFIG_PMAC_PBOOK
 	p += sprintf(p, "AC Power               : %d\n",
 		((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0));
 	p += sprintf(p, "Battery count          : %d\n", pmu_battery_count);
-#endif /* CONFIG_PMAC_PBOOK */
 
 	return p - page;
 }
@@ -859,7 +823,6 @@
 	return p - page;
 }
 
-#ifdef CONFIG_PMAC_PBOOK
 static int __pmac
 proc_get_batt(char *page, char **start, off_t off,
 		int count, int *eof, void *data)
@@ -883,7 +846,6 @@
 
 	return p - page;
 }
-#endif /* CONFIG_PMAC_PBOOK */
 
 static int __pmac
 proc_read_options(char *page, char **start, off_t off,
@@ -891,11 +853,9 @@
 {
 	char *p = page;
 
-#ifdef CONFIG_PMAC_PBOOK
 	if (pmu_kind == PMU_KEYLARGO_BASED &&
 	    pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
-		p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup);
-#endif /* CONFIG_PMAC_PBOOK */
+		p += sprintf(p, "lid_wakeup=%d\n", pmac_option_lid_wakeup);
 	if (pmu_kind == PMU_KEYLARGO_BASED)
 		p += sprintf(p, "server_mode=%d\n", option_server_mode);
 
@@ -932,12 +892,10 @@
 	*(val++) = 0;
 	while(*val == ' ')
 		val++;
-#ifdef CONFIG_PMAC_PBOOK
 	if (pmu_kind == PMU_KEYLARGO_BASED &&
 	    pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
 		if (!strcmp(label, "lid_wakeup"))
-			option_lid_wakeup = ((*val) == '1');
-#endif /* CONFIG_PMAC_PBOOK */
+			pmac_option_lid_wakeup = ((*val) == '1');
 	if (pmu_kind == PMU_KEYLARGO_BASED && !strcmp(label, "server_mode")) {
 		int new_value;
 		new_value = ((*val) == '1');
@@ -1344,7 +1302,6 @@
 	unsigned char ints, pirq;
 	int i = 0;
 
-	asleep = 0;
 	if (drop_interrupts || len < 1) {
 		adb_int_pending = 0;
 		pmu_irq_stats[8]++;
@@ -1432,7 +1389,6 @@
 	}
 	/* Tick interrupt */
 	else if ((1 << pirq) & PMU_INT_TICK) {
-#ifdef CONFIG_PMAC_PBOOK
 		/* Environement or tick interrupt, query batteries */
 		if (pmu_battery_count) {
 			if ((--query_batt_timer) == 0) {
@@ -1447,7 +1403,6 @@
 		pmu_pass_intr(data, len);
 	} else {
 	       pmu_pass_intr(data, len);
-#endif /* CONFIG_PMAC_PBOOK */
 	}
 	goto next;
 }
@@ -1692,6 +1647,8 @@
 	
 	if (vias == NULL)
 		return -ENODEV;
+	if (pmu_sys_suspended)
+		return -EIO;
 
 	if (on) {
 		pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT,
@@ -1719,6 +1676,8 @@
 {
 	if (vias == NULL)
 		return -ENODEV;
+	if (pmu_sys_suspended)
+		return -EIO;
 
 	if (test_and_set_bit(1, &async_req_locks))
 		return -EAGAIN;
@@ -2062,201 +2021,9 @@
 	return -1;
 }
 
-#ifdef CONFIG_PMAC_PBOOK
-
-static LIST_HEAD(sleep_notifiers);
-
-int
-pmu_register_sleep_notifier(struct pmu_sleep_notifier *n)
-{
-	struct list_head *list;
-	struct pmu_sleep_notifier *notifier;
-
-	for (list = sleep_notifiers.next; list != &sleep_notifiers;
-	     list = list->next) {
-		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		if (n->priority > notifier->priority)
-			break;
-	}
-	__list_add(&n->list, list->prev, list);
-	return 0;
-}
-
-int
-pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n)
-{
-	if (n->list.next == 0)
-		return -ENOENT;
-	list_del(&n->list);
-	n->list.next = NULL;
-	return 0;
-}
-
-/* Sleep is broadcast last-to-first */
-static int __pmac
-broadcast_sleep(int when, int fallback)
-{
-	int ret = PBOOK_SLEEP_OK;
-	struct list_head *list;
-	struct pmu_sleep_notifier *notifier;
-
-	for (list = sleep_notifiers.prev; list != &sleep_notifiers;
-	     list = list->prev) {
-		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		ret = notifier->notifier_call(notifier, when);
-		if (ret != PBOOK_SLEEP_OK) {
-			printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n",
-			       when, notifier, notifier->notifier_call);
-			for (; list != &sleep_notifiers; list = list->next) {
-				notifier = list_entry(list, struct pmu_sleep_notifier, list);
-				notifier->notifier_call(notifier, fallback);
-			}
-			return ret;
-		}
-	}
-	return ret;
-}
-
-/* Wake is broadcast first-to-last */
-static int __pmac
-broadcast_wake(void)
-{
-	int ret = PBOOK_SLEEP_OK;
-	struct list_head *list;
-	struct pmu_sleep_notifier *notifier;
-
-	for (list = sleep_notifiers.next; list != &sleep_notifiers;
-	     list = list->next) {
-		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		notifier->notifier_call(notifier, PBOOK_WAKE);
-	}
-	return ret;
-}
-
-/*
- * This struct is used to store config register values for
- * PCI devices which may get powered off when we sleep.
- */
-static struct pci_save {
-#ifndef HACKED_PCI_SAVE
-	u16	command;
-	u16	cache_lat;
-	u16	intr;
-	u32	rom_address;
-#else
-	u32	config[16];
-#endif	
-} *pbook_pci_saves;
-static int pbook_npci_saves;
-
-static void __pmac
-pbook_alloc_pci_save(void)
-{
-	int npci;
-	struct pci_dev *pd = NULL;
-
-	npci = 0;
-	while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-		++npci;
-	}
-	if (npci == 0)
-		return;
-	pbook_pci_saves = (struct pci_save *)
-		kmalloc(npci * sizeof(struct pci_save), GFP_KERNEL);
-	pbook_npci_saves = npci;
-}
-
-static void __pmac
-pbook_free_pci_save(void)
-{
-	if (pbook_pci_saves == NULL)
-		return;
-	kfree(pbook_pci_saves);
-	pbook_pci_saves = NULL;
-	pbook_npci_saves = 0;
-}
 
-static void __pmac
-pbook_pci_save(void)
-{
-	struct pci_save *ps = pbook_pci_saves;
-	struct pci_dev *pd = NULL;
-	int npci = pbook_npci_saves;
-	
-	if (ps == NULL)
-		return;
-
-	while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-		if (npci-- == 0)
-			return;
-#ifndef HACKED_PCI_SAVE
-		pci_read_config_word(pd, PCI_COMMAND, &ps->command);
-		pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat);
-		pci_read_config_word(pd, PCI_INTERRUPT_LINE, &ps->intr);
-		pci_read_config_dword(pd, PCI_ROM_ADDRESS, &ps->rom_address);
-#else
-		int i;
-		for (i=1;i<16;i++)
-			pci_read_config_dword(pd, i<<4, &ps->config[i]);
-#endif
-		++ps;
-	}
-}
-
-/* For this to work, we must take care of a few things: If gmac was enabled
- * during boot, it will be in the pci dev list. If it's disabled at this point
- * (and it will probably be), then you can't access it's config space.
- */
-static void __pmac
-pbook_pci_restore(void)
-{
-	u16 cmd;
-	struct pci_save *ps = pbook_pci_saves - 1;
-	struct pci_dev *pd = NULL;
-	int npci = pbook_npci_saves;
-	int j;
-
-	while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-#ifdef HACKED_PCI_SAVE
-		int i;
-		if (npci-- == 0)
-			return;
-		ps++;
-		for (i=2;i<16;i++)
-			pci_write_config_dword(pd, i<<4, ps->config[i]);
-		pci_write_config_dword(pd, 4, ps->config[1]);
-#else
-		if (npci-- == 0)
-			return;
-		ps++;
-		if (ps->command == 0)
-			continue;
-		pci_read_config_word(pd, PCI_COMMAND, &cmd);
-		if ((ps->command & ~cmd) == 0)
-			continue;
-		switch (pd->hdr_type) {
-		case PCI_HEADER_TYPE_NORMAL:
-			for (j = 0; j < 6; ++j)
-				pci_write_config_dword(pd,
-					PCI_BASE_ADDRESS_0 + j*4,
-					pd->resource[j].start);
-			pci_write_config_dword(pd, PCI_ROM_ADDRESS,
-				ps->rom_address);
-			pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
-				ps->cache_lat);
-			pci_write_config_word(pd, PCI_INTERRUPT_LINE,
-				ps->intr);
-			pci_write_config_word(pd, PCI_COMMAND, ps->command);
-			break;
-		}
-#endif	
-	}
-}
-
-#ifdef DEBUG_SLEEP
 /* N.B. This doesn't work on the 3400 */
-void  __pmac
-pmu_blink(int n)
+void  __pmac pmu_blink(int n)
 {
 	struct adb_request req;
 
@@ -2288,7 +2055,6 @@
 	}
 	mdelay(50);
 }
-#endif
 
 /*
  * Put the powerbook to sleep.
@@ -2296,8 +2062,7 @@
  
 static u32 save_via[8] __pmacdata;
 
-static void __pmac
-save_via_state(void)
+void __pmac pmu_save_via_state(void)
 {
 	save_via[0] = in_8(&via[ANH]);
 	save_via[1] = in_8(&via[DIRA]);
@@ -2308,8 +2073,7 @@
 	save_via[6] = in_8(&via[T1CL]);
 	save_via[7] = in_8(&via[T1CH]);
 }
-static void __pmac
-restore_via_state(void)
+void __pmac pmu_restore_via_state(void)
 {
 	out_8(&via[ANH], save_via[0]);
 	out_8(&via[DIRA], save_via[1]);
@@ -2324,390 +2088,6 @@
 	out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
 }
 
-static int __pmac
-pmac_suspend_devices(void)
-{
-	int ret;
-
-	pm_prepare_console();
-	
-	/* Notify old-style device drivers & userland */
-	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
-	if (ret != PBOOK_SLEEP_OK) {
-		printk(KERN_ERR "Sleep rejected by drivers\n");
-		return -EBUSY;
-	}
-
-	/* Sync the disks. */
-	/* XXX It would be nice to have some way to ensure that
-	 * nobody is dirtying any new buffers while we wait. That
-	 * could be achieved using the refrigerator for processes
-	 * that swsusp uses
-	 */
-	sys_sync();
-
-	/* Sleep can fail now. May not be very robust but useful for debugging */
-	ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE);
-	if (ret != PBOOK_SLEEP_OK) {
-		printk(KERN_ERR "Driver sleep failed\n");
-		return -EBUSY;
-	}
-
-	/* Send suspend call to devices, hold the device core's dpm_sem */
-	ret = device_suspend(PMSG_SUSPEND);
-	if (ret) {
-		broadcast_wake();
-		printk(KERN_ERR "Driver sleep failed\n");
-		return -EBUSY;
-	}
-
-	/* Disable clock spreading on some machines */
-	pmac_tweak_clock_spreading(0);
-
-	/* Stop preemption */
-	preempt_disable();
-
-	/* Make sure the decrementer won't interrupt us */
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-	/* Make sure any pending DEC interrupt occurring while we did
-	 * the above didn't re-enable the DEC */
-	mb();
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-
-	/* We can now disable MSR_EE. This code of course works properly only
-	 * on UP machines... For SMP, if we ever implement sleep, we'll have to
-	 * stop the "other" CPUs way before we do all that stuff.
-	 */
-	local_irq_disable();
-
-	/* Broadcast power down irq
-	 * This isn't that useful in most cases (only directly wired devices can
-	 * use this but still... This will take care of sysdev's as well, so
-	 * we exit from here with local irqs disabled and PIC off.
-	 */
-	ret = device_power_down(PMSG_SUSPEND);
-	if (ret) {
-		wakeup_decrementer();
-		local_irq_enable();
-		preempt_enable();
-		device_resume();
-		broadcast_wake();
-		printk(KERN_ERR "Driver powerdown failed\n");
-		return -EBUSY;
-	}
-
-	/* Wait for completion of async backlight requests */
-	while (!bright_req_1.complete || !bright_req_2.complete ||
-			!batt_req.complete)
-		pmu_poll();
-
-	/* Giveup the lazy FPU & vec so we don't have to back them
-	 * up from the low level code
-	 */
-	enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
-	if (cpu_has_feature(CPU_FTR_ALTIVEC))
-		enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
-	return 0;
-}
-
-static int __pmac
-pmac_wakeup_devices(void)
-{
-	mdelay(100);
-
-	/* Power back up system devices (including the PIC) */
-	device_power_up();
-
-	/* Force a poll of ADB interrupts */
-	adb_int_pending = 1;
-	via_pmu_interrupt(0, NULL, NULL);
-
-	/* Restart jiffies & scheduling */
-	wakeup_decrementer();
-
-	/* Re-enable local CPU interrupts */
-	local_irq_enable();
-	mdelay(10);
-	preempt_enable();
-
-	/* Re-enable clock spreading on some machines */
-	pmac_tweak_clock_spreading(1);
-
-	/* Resume devices */
-	device_resume();
-
-	/* Notify old style drivers */
-	broadcast_wake();
-
-	pm_restore_console();
-
-	return 0;
-}
-
-#define	GRACKLE_PM	(1<<7)
-#define GRACKLE_DOZE	(1<<5)
-#define	GRACKLE_NAP	(1<<4)
-#define	GRACKLE_SLEEP	(1<<3)
-
-int __pmac
-powerbook_sleep_grackle(void)
-{
-	unsigned long save_l2cr;
-	unsigned short pmcr1;
-	struct adb_request req;
-	int ret;
-	struct pci_dev *grackle;
-
-	grackle = pci_find_slot(0, 0);
-	if (!grackle)
-		return -ENODEV;
-
-	ret = pmac_suspend_devices();
-	if (ret) {
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-	
-	/* Turn off various things. Darwin does some retry tests here... */
-	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE);
-	pmu_wait_complete(&req);
-	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
-		PMU_POW_OFF|PMU_POW_BACKLIGHT|PMU_POW_IRLED|PMU_POW_MEDIABAY);
-	pmu_wait_complete(&req);
-
-	/* For 750, save backside cache setting and disable it */
-	save_l2cr = _get_L2CR();	/* (returns -1 if not available) */
-
-	if (!__fake_sleep) {
-		/* Ask the PMU to put us to sleep */
-		pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
-		pmu_wait_complete(&req);
-	}
-
-	/* The VIA is supposed not to be restored correctly*/
-	save_via_state();
-	/* We shut down some HW */
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);
-
-	pci_read_config_word(grackle, 0x70, &pmcr1);
-	/* Apparently, MacOS uses NAP mode for Grackle ??? */
-	pmcr1 &= ~(GRACKLE_DOZE|GRACKLE_SLEEP); 
-	pmcr1 |= GRACKLE_PM|GRACKLE_NAP;
-	pci_write_config_word(grackle, 0x70, pmcr1);
-
-	/* Call low-level ASM sleep handler */
-	if (__fake_sleep)
-		mdelay(5000);
-	else
-		low_sleep_handler();
-
-	/* We're awake again, stop grackle PM */
-	pci_read_config_word(grackle, 0x70, &pmcr1);
-	pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); 
-	pci_write_config_word(grackle, 0x70, pmcr1);
-
-	/* Make sure the PMU is idle */
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
-	restore_via_state();
-	
-	/* Restore L2 cache */
-	if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
- 		_set_L2CR(save_l2cr);
-	
-	/* Restore userland MMU context */
-	set_context(current->active_mm->context, current->active_mm->pgd);
-
-	/* Power things up */
-	pmu_unlock();
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
-	pmu_wait_complete(&req);
-	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0,
-			PMU_POW0_ON|PMU_POW0_HARD_DRIVE);
-	pmu_wait_complete(&req);
-	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
-			PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY);
-	pmu_wait_complete(&req);
-
-	pmac_wakeup_devices();
-
-	return 0;
-}
-
-static int __pmac
-powerbook_sleep_Core99(void)
-{
-	unsigned long save_l2cr;
-	unsigned long save_l3cr;
-	struct adb_request req;
-	int ret;
-	
-	if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) {
-		printk(KERN_ERR "Sleep mode not supported on this machine\n");
-		return -ENOSYS;
-	}
-
-	if (num_online_cpus() > 1 || cpu_is_offline(0))
-		return -EAGAIN;
-
-	ret = pmac_suspend_devices();
-	if (ret) {
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-
-	/* Stop environment and ADB interrupts */
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
-	pmu_wait_complete(&req);
-
-	/* Tell PMU what events will wake us up */
-	pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS,
-		0xff, 0xff);
-	pmu_wait_complete(&req);
-	pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_SET_WAKEUP_EVENTS,
-		0, PMU_PWR_WAKEUP_KEY |
-		(option_lid_wakeup ? PMU_PWR_WAKEUP_LID_OPEN : 0));
-	pmu_wait_complete(&req);
-
-	/* Save the state of the L2 and L3 caches */
-	save_l3cr = _get_L3CR();	/* (returns -1 if not available) */
-	save_l2cr = _get_L2CR();	/* (returns -1 if not available) */
-
-	if (!__fake_sleep) {
-		/* Ask the PMU to put us to sleep */
-		pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
-		pmu_wait_complete(&req);
-	}
-
-	/* The VIA is supposed not to be restored correctly*/
-	save_via_state();
-
-	/* Shut down various ASICs. There's a chance that we can no longer
-	 * talk to the PMU after this, so I moved it to _after_ sending the
-	 * sleep command to it. Still need to be checked.
-	 */
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1);
-
-	/* Call low-level ASM sleep handler */
-	if (__fake_sleep)
-		mdelay(5000);
-	else
-		low_sleep_handler();
-
-	/* Restore Apple core ASICs state */
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0);
-
-	/* Restore VIA */
-	restore_via_state();
-
-	/* Restore video */
-	pmac_call_early_video_resume();
-
-	/* Restore L2 cache */
-	if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
- 		_set_L2CR(save_l2cr);
-	/* Restore L3 cache */
-	if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
- 		_set_L3CR(save_l3cr);
-	
-	/* Restore userland MMU context */
-	set_context(current->active_mm->context, current->active_mm->pgd);
-
-	/* Tell PMU we are ready */
-	pmu_unlock();
-	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
-	pmu_wait_complete(&req);
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
-	pmu_wait_complete(&req);
-
-	pmac_wakeup_devices();
-
-	return 0;
-}
-
-#define PB3400_MEM_CTRL		0xf8000000
-#define PB3400_MEM_CTRL_SLEEP	0x70
-
-static int __pmac
-powerbook_sleep_3400(void)
-{
-	int ret, i, x;
-	unsigned int hid0;
-	unsigned long p;
-	struct adb_request sleep_req;
-	void __iomem *mem_ctrl;
-	unsigned int __iomem *mem_ctrl_sleep;
-
-	/* first map in the memory controller registers */
-	mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
-	if (mem_ctrl == NULL) {
-		printk("powerbook_sleep_3400: ioremap failed\n");
-		return -ENOMEM;
-	}
-	mem_ctrl_sleep = mem_ctrl + PB3400_MEM_CTRL_SLEEP;
-
-	/* Allocate room for PCI save */
-	pbook_alloc_pci_save();
-
-	ret = pmac_suspend_devices();
-	if (ret) {
-		pbook_free_pci_save();
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-
-	/* Save the state of PCI config space for some slots */
-	pbook_pci_save();
-
-	/* Set the memory controller to keep the memory refreshed
-	   while we're asleep */
-	for (i = 0x403f; i >= 0x4000; --i) {
-		out_be32(mem_ctrl_sleep, i);
-		do {
-			x = (in_be32(mem_ctrl_sleep) >> 16) & 0x3ff;
-		} while (x == 0);
-		if (x >= 0x100)
-			break;
-	}
-
-	/* Ask the PMU to put us to sleep */
-	pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
-	while (!sleep_req.complete)
-		mb();
-
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);
-
-	/* displacement-flush the L2 cache - necessary? */
-	for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000)
-		i = *(volatile int *)p;
-	asleep = 1;
-
-	/* Put the CPU into sleep mode */
-	asm volatile("mfspr %0,1008" : "=r" (hid0) :);
-	hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;
-	asm volatile("mtspr 1008,%0" : : "r" (hid0));
-	_nmask_and_or_msr(0, MSR_POW | MSR_EE);
-	udelay(10);
-
-	/* OK, we're awake again, start restoring things */
-	out_be32(mem_ctrl_sleep, 0x3f);
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
-	pbook_pci_restore();
-	pmu_unlock();
-
-	/* wait for the PMU interrupt sequence to complete */
-	while (asleep)
-		mb();
-
-	pmac_wakeup_devices();
-	pbook_free_pci_save();
-	iounmap(mem_ctrl);
-
-	return 0;
-}
 
 /*
  * Support for /dev/pmu device
@@ -2896,24 +2276,10 @@
 	case PMU_IOC_SLEEP:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
-		if (sleep_in_progress)
-			return -EBUSY;
-		sleep_in_progress = 1;
-		switch (pmu_kind) {
-		case PMU_OHARE_BASED:
-			error = powerbook_sleep_3400();
-			break;
-		case PMU_HEATHROW_BASED:
-		case PMU_PADDINGTON_BASED:
-			error = powerbook_sleep_grackle();
-			break;
-		case PMU_KEYLARGO_BASED:
-			error = powerbook_sleep_Core99();
-			break;
-		default:
-			error = -ENOSYS;
-		}
-		sleep_in_progress = 0;
+		if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)
+			error = pm_suspend(PM_SUSPEND_MEM);		
+		else
+			error = pm_suspend(PM_SUSPEND_DISK);		
 		return error;
 	case PMU_IOC_CAN_SLEEP:
 		if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)
@@ -2926,8 +2292,6 @@
 	 * the fbdev
 	 */
 	case PMU_IOC_GET_BACKLIGHT:
-		if (sleep_in_progress)
-			return -EBUSY;
 		error = get_backlight_level();
 		if (error < 0)
 			return error;
@@ -2935,8 +2299,6 @@
 	case PMU_IOC_SET_BACKLIGHT:
 	{
 		__u32 value;
-		if (sleep_in_progress)
-			return -EBUSY;
 		error = get_user(value, argp);
 		if (!error)
 			error = set_backlight_level(value);
@@ -2983,7 +2345,6 @@
 	if (misc_register(&pmu_device) < 0)
 		printk(KERN_ERR "via-pmu: cannot register misc device.\n");
 }
-#endif /* CONFIG_PMAC_PBOOK */
 
 #ifdef DEBUG_SLEEP
 static inline void  __pmac
@@ -3065,17 +2426,29 @@
 
 #ifdef CONFIG_PM
 
-static int pmu_sys_suspended = 0;
-
 static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state)
 {
-	if (state != PM_SUSPEND_DISK || pmu_sys_suspended)
+	struct adb_request req;
+
+	if (pmu_sys_suspended)
 		return 0;
 
+	/* Stop environment interrupts */
+	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
+	pmu_wait_complete(&req);
+
 	/* Suspend PMU event interrupts */
 	pmu_suspend();
 
+	/* Mark driver suspended */
 	pmu_sys_suspended = 1;
+
+	/* Wait for completion of async backlight requests */
+	while (!bright_req_1.complete || !bright_req_2.complete ||
+			!batt_req.complete)
+		pmu_poll();
+	
+
 	return 0;
 }
 
@@ -3086,6 +2459,10 @@
 	if (!pmu_sys_suspended)
 		return 0;
 
+	/* Restart environment interrupts */ 
+	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
+	pmu_wait_complete(&req);
+
 	/* Tell PMU we are ready */
 	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
 	pmu_wait_complete(&req);
@@ -3093,6 +2470,7 @@
 	/* Resume PMU event interrupts */
 	pmu_resume();
 
+	/* Mark driver ready for async requests */
 	pmu_sys_suspended = 0;
 
 	return 0;
@@ -3151,12 +2529,8 @@
 EXPORT_SYMBOL(pmu_i2c_stdsub_write);
 EXPORT_SYMBOL(pmu_i2c_simple_read);
 EXPORT_SYMBOL(pmu_i2c_simple_write);
-#ifdef CONFIG_PMAC_PBOOK
-EXPORT_SYMBOL(pmu_register_sleep_notifier);
-EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
 EXPORT_SYMBOL(pmu_enable_irled);
 EXPORT_SYMBOL(pmu_battery_count);
 EXPORT_SYMBOL(pmu_batteries);
 EXPORT_SYMBOL(pmu_power_flags);
-#endif /* CONFIG_PMAC_PBOOK */
 
Index: linux-work/include/asm-ppc/machdep.h
===================================================================
--- linux-work.orig/include/asm-ppc/machdep.h	2005-05-27 16:06:59.000000000 +1000
+++ linux-work/include/asm-ppc/machdep.h	2005-05-27 16:07:24.000000000 +1000
@@ -110,6 +110,12 @@
 	 */
 	long (*feature_call)(unsigned int feature, ...);
 
+#ifdef CONFIG_SOFTWARE_SUSPEND
+	int (*arch_prepare_suspend)(void);
+	void (*save_processor_state)(void);
+	void (*restore_processor_state)(void);
+#endif /* CONFIG_SOFTWARE_SUSPEND */
+
 #ifdef CONFIG_SMP
 	/* functions for dealing with other cpus */
 	struct smp_ops_t *smp_ops;
Index: linux-work/include/asm-ppc/suspend.h
===================================================================
--- linux-work.orig/include/asm-ppc/suspend.h	2005-05-27 16:06:59.000000000 +1000
+++ linux-work/include/asm-ppc/suspend.h	2005-05-27 16:07:24.000000000 +1000
@@ -1,12 +1,44 @@
+#ifndef __PPC_SUSPEND_H
+#define __PPC_SUSPEND_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/machdep.h>
+
+
+#ifdef CONFIG_SOFTWARE_SUSPEND
 static inline int arch_prepare_suspend(void)
 {
+	if (ppc_md.arch_prepare_suspend)
+		return ppc_md.arch_prepare_suspend();
 	return 0;
 }
 
 static inline void save_processor_state(void)
 {
+	if (ppc_md.save_processor_state)
+		return ppc_md.save_processor_state();
 }
 
 static inline void restore_processor_state(void)
 {
+	if (ppc_md.restore_processor_state)
+		return ppc_md.restore_processor_state();
 }
+#else
+static inline int arch_prepare_suspend(void)
+{
+	return 0;
+}
+
+static inline void save_processor_state(void)
+{
+}
+
+static inline void restore_processor_state(void)
+{
+}
+#endif
+
+
+#endif /* __PPC_SUSPEND_H */
Index: linux-work/include/linux/pm.h
===================================================================
--- linux-work.orig/include/linux/pm.h	2005-05-27 16:06:59.000000000 +1000
+++ linux-work/include/linux/pm.h	2005-05-27 16:07:24.000000000 +1000
@@ -169,9 +169,38 @@
 
 struct pm_ops {
 	suspend_disk_method_t pm_disk_mode;
+	
+	/* Call before process freezing. If returns 0, then no freeze
+	 * should be done, if 1, freeze, negative -> error
+	 */
+	int (*pre_freeze)(suspend_state_t state);
+
+	/* called before devices are suspended */
 	int (*prepare)(suspend_state_t state);
+
+	/* called just before irqs are off and device second pass
+	 * and sysdevs are suspended. This function can on some archs
+	 * shut irqs off, in which case, they'll still be off when
+	 * finish_irqs() is called.
+	 */
+	int (*prepare_irqs)(suspend_state_t state);
+
+	/* called for entering the actual suspend state. Exits with
+	 * machine worken up and interrupts off
+	 */
 	int (*enter)(suspend_state_t state);
-	int (*finish)(suspend_state_t state);
+
+	/* called after sysdevs and "irq off" devices have been
+	 * worken up, irqs have just been restored to whatever state
+	 * prepare_irqs() left them in.
+	 */
+	void (*finish_irqs)(suspend_state_t state);
+
+	/* called after all devices are woken up, processes still frozen */
+	void (*finish)(suspend_state_t state);
+
+	/* called after unfreezing userland */
+	void (*post_freeze)(suspend_state_t state);
 };
 
 extern void pm_set_ops(struct pm_ops *);
Index: linux-work/include/linux/pmu.h
===================================================================
--- linux-work.orig/include/linux/pmu.h	2005-05-27 16:06:59.000000000 +1000
+++ linux-work/include/linux/pmu.h	2005-05-27 16:07:24.000000000 +1000
@@ -151,6 +151,9 @@
 extern void pmu_suspend(void);
 extern void pmu_resume(void);
 
+extern void pmu_save_via_state(void);
+extern void pmu_restore_via_state(void);
+
 extern void pmu_enable_irled(int on);
 
 extern void pmu_restart(void);
Index: linux-work/kernel/power/main.c
===================================================================
--- linux-work.orig/kernel/power/main.c	2005-05-27 16:06:59.000000000 +1000
+++ linux-work/kernel/power/main.c	2005-05-27 16:09:28.000000000 +1000
@@ -23,6 +23,7 @@
 
 struct pm_ops * pm_ops = NULL;
 suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN;
+static int pm_process_frozen;
 
 /**
  *	pm_set_ops - Set the global power method table. 
@@ -49,32 +50,53 @@
 static int suspend_prepare(suspend_state_t state)
 {
 	int error = 0;
+	int freeze = 1;
 
 	if (!pm_ops || !pm_ops->enter)
 		return -EPERM;
 
 	pm_prepare_console();
 
-	if (freeze_processes()) {
+	if (pm_ops->pre_freeze)
+		freeze = pm_ops->pre_freeze(state);
+	if (freeze < 0)
+		goto Console;
+
+	if (freeze && freeze_processes()) {
 		error = -EAGAIN;
 		goto Thaw;
 	}
+	pm_process_frozen = freeze;
 
 	if (pm_ops->prepare) {
+		pr_debug("preparing arch...\n");
 		if ((error = pm_ops->prepare(state)))
 			goto Thaw;
 	}
 
+	pr_debug("suspending devices...\n");
 	if ((error = device_suspend(PMSG_SUSPEND))) {
 		printk(KERN_ERR "Some devices failed to suspend\n");
 		goto Finish;
 	}
+
+	if (pm_ops->prepare_irqs) {
+		pr_debug("preparing arch irqs...\n");
+		if ((error = pm_ops->prepare_irqs(state)))
+			goto Finish;
+	}
+
 	return 0;
  Finish:
 	if (pm_ops->finish)
 		pm_ops->finish(state);
  Thaw:
-	thaw_processes();
+	if (freeze)
+		thaw_processes();
+
+	if (pm_ops->post_freeze)
+		pm_ops->post_freeze(state);
+ Console:
 	pm_restore_console();
 	return error;
 }
@@ -109,10 +131,18 @@
 
 static void suspend_finish(suspend_state_t state)
 {
+	if (!pm_ops)
+		return;
+
+	if (pm_ops->finish_irqs)
+		pm_ops->finish_irqs(state);
 	device_resume();
-	if (pm_ops && pm_ops->finish)
+	if (pm_ops->finish)
 		pm_ops->finish(state);
-	thaw_processes();
+	if (pm_process_frozen)
+		thaw_processes();
+	if (pm_ops->post_freeze)
+		pm_ops->post_freeze(state);
 	pm_restore_console();
 }
 
Index: linux-work/arch/ppc/platforms/pmac_pic.c
===================================================================
--- linux-work.orig/arch/ppc/platforms/pmac_pic.c	2005-05-27 16:06:59.000000000 +1000
+++ linux-work/arch/ppc/platforms/pmac_pic.c	2005-05-27 16:07:24.000000000 +1000
@@ -619,7 +619,7 @@
 	return viaint;
 }
 
-static int pmacpic_suspend(struct sys_device *sysdev, u32 state)
+void __pmac pmacpic_suspend(void)
 {
 	int viaint = pmacpic_find_viaint();
 
@@ -636,11 +636,9 @@
 	/* make sure mask gets to controller before we return to caller */
 	mb();
         (void)in_le32(&pmac_irq_hw[0]->enable);
-
-        return 0;
 }
 
-static int pmacpic_resume(struct sys_device *sysdev)
+void __pmac pmacpic_resume(void)
 {
 	int i;
 
@@ -651,12 +649,11 @@
 	for (i = 0; i < max_real_irqs; ++i)
 		if (test_bit(i, sleep_save_mask))
 			pmac_unmask_irq(i);
-
-	return 0;
 }
 
 #endif /* CONFIG_PM */
 
+#if 0
 static struct sysdev_class pmacpic_sysclass = {
 	set_kset_name("pmac_pic"),
 };
@@ -686,4 +683,4 @@
 }
 
 subsys_initcall(init_pmacpic_sysfs);
-
+#endif
Index: linux-work/arch/ppc/syslib/open_pic.c
===================================================================
--- linux-work.orig/arch/ppc/syslib/open_pic.c	2005-05-27 16:06:59.000000000 +1000
+++ linux-work/arch/ppc/syslib/open_pic.c	2005-05-27 16:07:24.000000000 +1000
@@ -948,11 +948,7 @@
 	save_irq_src_vp[irq - open_pic_irq_offset] |= OPENPIC_MASK;
 }
 
-/* WARNING: Can be called directly by the cpufreq code with NULL parameter,
- * we need something better to deal with that... Maybe switch to S1 for
- * cpufreq changes
- */
-int openpic_suspend(struct sys_device *sysdev, u32 state)
+void openpic_suspend(void)
 {
 	int	i;
 	unsigned long flags;
@@ -961,11 +957,9 @@
 
 	if (openpic_suspend_count++ > 0) {
 		spin_unlock_irqrestore(&openpic_setup_lock, flags);
-		return 0;
+		return;
 	}
 
- 	openpic_set_priority(0xf);
-
 	open_pic.enable = openpic_cached_enable_irq;
 	open_pic.disable = openpic_cached_disable_irq;
 
@@ -975,6 +969,8 @@
 				   OPENPIC_CURRENT_TASK_PRIORITY_MASK, 0xf);
 	}
 
+ 	openpic_set_priority(0xf);
+
 	for (i=0; i<OPENPIC_NUM_IPI; i++)
 		save_ipi_vp[i] = openpic_read(&OpenPIC->Global.IPI_Vector_Priority(i));
 	for (i=0; i<NumSources; i++) {
@@ -985,15 +981,13 @@
 	}
 
 	spin_unlock_irqrestore(&openpic_setup_lock, flags);
-
-	return 0;
 }
 
 /* WARNING: Can be called directly by the cpufreq code with NULL parameter,
  * we need something better to deal with that... Maybe switch to S1 for
  * cpufreq changes
  */
-int openpic_resume(struct sys_device *sysdev)
+void openpic_resume(void)
 {
 	int		i;
 	unsigned long	flags;
@@ -1005,9 +999,11 @@
 
 	if ((--openpic_suspend_count) > 0) {
 		spin_unlock_irqrestore(&openpic_setup_lock, flags);
-		return 0;
+		return;
 	}
 
+ 	openpic_set_priority(0xf);
+
 	/* OpenPIC sometimes seem to need some time to be fully back up... */
 	do {
 		openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
@@ -1030,22 +1026,19 @@
 		} while (openpic_readfield(&ISR[i]->Vector_Priority, vppmask)
 			 != (save_irq_src_vp[i] & vppmask));
 	}
-	for (i=0; i<NumProcessors; i++)
-		openpic_write(&OpenPIC->Processor[i].Current_Task_Priority,
-			      save_cpu_task_pri[i]);
-
 	open_pic.enable = openpic_enable_irq;
 	open_pic.disable = openpic_disable_irq;
 
- 	openpic_set_priority(0);
+	for (i=0; i<NumProcessors; i++)
+		openpic_write(&OpenPIC->Processor[i].Current_Task_Priority,
+			      save_cpu_task_pri[i]);
 
 	spin_unlock_irqrestore(&openpic_setup_lock, flags);
-
-	return 0;
 }
 
 #endif /* CONFIG_PM */
 
+#if 0
 static struct sysdev_class openpic_sysclass = {
 	set_kset_name("openpic"),
 };
@@ -1089,3 +1082,4 @@
 
 subsys_initcall(init_openpic_sysfs);
 
+#endif
Index: linux-work/include/asm-ppc/open_pic.h
===================================================================
--- linux-work.orig/include/asm-ppc/open_pic.h	2005-05-27 16:06:59.000000000 +1000
+++ linux-work/include/asm-ppc/open_pic.h	2005-05-27 16:08:12.000000000 +1000
@@ -64,6 +64,9 @@
 extern void openpic_set_priority(u_int pri);
 extern u_int openpic_get_priority(void);
 
+extern void openpic_suspend(void);
+extern void openpic_resume(void);
+
 extern inline int openpic_to_irq(int irq)
 {
 	/* IRQ 0 usually means 'disabled'.. don't mess with it

^ permalink raw reply

* Re: Dynamic libraries do not work
From: Jaap-Jan Boor @ 2005-05-27  6:53 UTC (permalink / raw)
  To: Theo Gjaltema; +Cc: linuxppc-embedded
In-Reply-To: <429639D5.20609@chello.nl>

Theo,

What type of processor are you using? 8xx?
Did you build a tool-chain yourself and are
you perhaps using floating point?

Jaap-Jan

On 26-mei-2005, at 23:04, Theo Gjaltema wrote:

> Hello,
>
> I have a linux 2.4.20 kernel running, but the files in the ramdisk  
> fail to execute if they are dynamically build.
> The whole system stops (debuggers shows that it crashed while in an  
> erea where no flash/ram is present.
> Anyone an idea?
> There is nog difference between the use of a ramdisk or an nfs  
> mounted root filesystem.
>
> Greetings,
>    Theo.
>
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>

____
J.G.J. Boor                       Anton Philipsweg 1
Software Engineer                 1223 KZ Hilversum
AimSys bv                         tel. +31 35 689 1941
Postbus 2194, 1200 CD Hilversum   jjboor at aimsys dot nl

^ permalink raw reply

* Re: memec virtex 2 Pro
From: S. van Beek @ 2005-05-27  6:46 UTC (permalink / raw)
  To: linuxppc-embedded, mcnernbm
In-Reply-To: <OF51B36924.7EF29E2C-ON8525700E.000EEB35-8525700E.000F1DC6@notes.udayton.edu>

[-- Attachment #1: Type: text/plain, Size: 1107 bytes --]

Hi there

We have montavista linux running on a memec virtex II-pro ff672 board with communications 2 module here. 
What error do you get? What steps do you need help with? I can send you a working .config file if you want.

Regards
Sander van Beek
  ----- Original Message ----- 
  From: mcnernbm@notes.udayton.edu 
  To: linuxppc-embedded@ozlabs.org 
  Sent: Friday 27 May 2005 4:45
  Subject: memec virtex 2 Pro



  Has anyone had any success getting linux to boot on a memc viretx 2 board?  I am trying to replicate the steps to get the kernel built for the ml300 but run error after error in doing so.  The make zImage is borken and fails all the time. Anybody that has success with the memec virtex 2 pro or the xilinx ml300 board it would be greatly appreciated if you could explain how you did so.   
  Thanks 
  Brett 


------------------------------------------------------------------------------


  _______________________________________________
  Linuxppc-embedded mailing list
  Linuxppc-embedded@ozlabs.org
  https://ozlabs.org/mailman/listinfo/linuxppc-embedded

[-- Attachment #2: Type: text/html, Size: 2389 bytes --]

^ permalink raw reply

* Re: MPC860 CP / CPM Misbehaving
From: Harald Küthe @ 2005-05-27  6:54 UTC (permalink / raw)
  To: linuxppc-embedded

>> but I chose to stick with Fix #2

Fix #2 as well gives you a 100% performance boost

regards
Harald

^ permalink raw reply

* Re: memec virtex 2 Pro
From: Andrei Konovalov @ 2005-05-27  9:20 UTC (permalink / raw)
  To: mcnernbm; +Cc: linuxppc-embedded
In-Reply-To: <OF51B36924.7EF29E2C-ON8525700E.000EEB35-8525700E.000F1DC6@notes.udayton.edu>

mcnernbm@notes.udayton.edu wrote:
> Has anyone had any success getting linux to boot on a memc viretx 2 board? 
>  I am trying to replicate the steps to get the kernel built for the ml300 
> but run error after error in doing so.  The make zImage is borken and 
> fails all the time. Anybody that has success with the memec virtex 2 pro 
> or the xilinx ml300 board it would be greatly appreciated if you could 
> explain how you did so. 
> Thanks
> Brett 
> 

What kernel tree are you using?

Thanks,
Andrei

> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply

* Re: Dynamic libraries do not work
From: Theo Gjaltema @ 2005-05-27 11:58 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <E6CEFEB5-1F03-45DA-8BA3-C1F1511950EA@aimsys.nl>



Toolchain used:   ELDK 2.0
target processor: mpc862
RAM:                64 Mbyte
Kernel:               2.4.20, extended with ATM/UTOPIA
init:                  /sbin/init -> /bin/busybox


(using a static linked busybox: activating a sh (=busybox)  
::sysinit:/bin/sh)
sh: /lib/ld.so.1          (note: /lib/ld.so.1 is a link to 
/lib/ld.so.2.5.5, part of the ELDK 2.0 )
< help page of ld.so.1>
sh: /lib/ld.so.1 --verify /bin/xxx (or just any dynamic linked executable)
<here the system has crahed>

or
sh: /bin/xxx
<here the system has crashed>

I have tried to step through the dynamic linking, but did not succeed 
til after the creation of a thread.
With a dynamic linked busybox the system stops after a message such as
"freeing xxx kbytes" (I don't know the actual number by head)
When init is then called, which is a part of the busybox which is dyn. 
liked, it crashes.


Greetings,
  Theo
Jaap-Jan Boor schreef:

> Theo,
>
> What type of processor are you using? 8xx?
> Did you build a tool-chain yourself and are
> you perhaps using floating point?
>
> Jaap-Jan
>
> On 26-mei-2005, at 23:04, Theo Gjaltema wrote:
>
>> Hello,
>>
>> I have a linux 2.4.20 kernel running, but the files in the ramdisk  
>> fail to execute if they are dynamically build.
>> The whole system stops (debuggers shows that it crashed while in an  
>> erea where no flash/ram is present.
>> Anyone an idea?
>> There is nog difference between the use of a ramdisk or an nfs  
>> mounted root filesystem.
>>
>> Greetings,
>>    Theo.
>>
>>
>> _______________________________________________
>> Linuxppc-embedded mailing list
>> Linuxppc-embedded@ozlabs.org
>> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>>
>
> ____
> J.G.J. Boor                       Anton Philipsweg 1
> Software Engineer                 1223 KZ Hilversum
> AimSys bv                         tel. +31 35 689 1941
> Postbus 2194, 1200 CD Hilversum   jjboor at aimsys dot nl
>
>
>

^ permalink raw reply

* [PATCH] PSC with devfs on 5200
From: Mark Chambers @ 2005-05-27 15:48 UTC (permalink / raw)
  To: linux-ppc-embedded
In-Reply-To: <20050521222713.GA28813@logos.cnet>

[-- Attachment #1: Type: text/plain, Size: 199 bytes --]

The attached patch allows the PSC ports on the MPC5200 to work with the
devfs file system.

I've never posted a patch before, somebody let me know if I should do
anything differently.

Mark Chambers

[-- Attachment #2: psc.patch --]
[-- Type: application/octet-stream, Size: 818 bytes --]

--- arch/ppc/5xxx_io/psc.c	2005-05-27 11:09:36.000000000 -0400
+++ /opt/eldk/ppc_82xx/usr/src/linux-2.4.24/arch/ppc/5xxx_io/psc.c	2003-12-03 14:08:19.000000000 -0500
@@ -806,11 +806,7 @@
 	memset(&rs_driver, 0, sizeof(rs_driver));
 	rs_driver.magic = TTY_DRIVER_MAGIC;
 	rs_driver.driver_name = "serial";
-#ifdef CONFIG_DEVFS_FS
-	rs_driver.name = "tts/%d";
-#else
 	rs_driver.name = "ttyS";
-#endif
 	rs_driver.major = TTY_MAJOR;
 	rs_driver.minor_start = 64;
 	rs_driver.num = MPC5xxx_PSC_NPORTS;
@@ -841,11 +837,7 @@
 	rs_driver.hangup = gs_hangup;
 
 	rs_callout_driver = rs_driver;
-#ifdef CONFIG_DEVFS_FS
-	rs_callout_driver.name = "cua/%d";
-#else
 	rs_callout_driver.name = "cua";
-#endif
 	rs_callout_driver.major = TTYAUX_MAJOR;
 	rs_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
 

^ permalink raw reply

* bd_t Cleaning: Interface Part
From: Jon Loeliger @ 2005-05-27 19:14 UTC (permalink / raw)
  To: linuxppc-embedded@ozlabs.org
In-Reply-To: <f003613a0526b7b6a00a0bd477cd5ac3@freescale.com>

On Thu, 2005-05-26 at 18:08, Kumar Gala wrote:
> Jon,
> 
> Can you break the patch up into a few pieces, it will be easier to 
> review that way.  Here are the following pieces that make sense to me:
> 
> 0. New firmware interface (fw_bdt*, Kconfig, ...)
> 1. board code changes (everything in arch/ppc/platforms/*)
> 2. driver changes (things in *_io, ide, net, serial dirs -- try to give 
> a better list below)
> 3. System changes (files in arch/ppc/syslib and include/asm-ppc)


OK.

Here's the first of the same patch in four part harmony.

 ppc/Kconfig                             |   29 +
 ppc/syslib/fw_bdt.c                     |  598 ++++++++++++++++++++++++++++++++
 ppc/syslib/fw_bdt.h                     |  453 ++++++++++++++++++++++++
 ppc/syslib/Makefile                     |    4 
 asm-ppc/firmware.h                      |   62 +++
 ppc/kernel/ppc_ksyms.c                  |    4 

Index: arch/ppc/Kconfig
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/Kconfig  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/Kconfig  (mode:100644)
@@ -955,6 +955,35 @@
 	  some command-line options at build time by entering them here.  In
 	  most cases you will need to specify the root device here.
 
+choice
+	prompt "Firmware setup interface"
+	default FW_BDT
+	help
+	  The bd_t structure setup by U-Boot is a flat structure with a
+	  fixed structure that must be consistent between U-Boot and Linux.
+	  Often that structure definition is out of date and inconsistent.
+	  The Open Firmware Flattened Device Tree provides a less fragile
+	  mechanism for communicating setup data from the firmware to Linux.
+
+	  The Implementation of the Open Firwmare flattened Device Tree
+	  hasn't been added to U-Boot yet, so select the bd_t option.
+
+config FW_BDT
+	bool "bd_t structure"
+	help
+	  Select this option to use the traditional bd_t style interface
+	  to pass residual data from U-Boot to the Linux startup code.
+
+	  Select this choice if unsure.
+
+config FW_OF
+	bool "OF Flattened Device Tree"
+	help
+	  Select this option to use a flattened Open Firmware device tree
+	  to pass data from U-Boot to the Linux startup code.
+
+endchoice
+
 config AMIGA
 	bool
 	depends on APUS
Index: arch/ppc/syslib/fw_bdt.c
===================================================================
--- /dev/null  (tree:c7d7a187a2125518e655dfeadffd38156239ffc3)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/fw_bdt.c  (mode:100644)
@@ -0,0 +1,598 @@
+/*
+ * arch/ppc/syslib/fw_bdt.c
+ *
+ * Implements the interface to Firmware information based
+ * on U-Boot's bd_t structure definition.
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * 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/module.h>
+#include <linux/init.h>
+
+#include <asm/firmware.h>
+
+#include "fw_bdt.h"
+
+
+/*
+ * The "residual" data area holds data supplied by the firmware in order
+ * to communicate initialization and setup data to the Linux startup.
+ */
+bd_t __res;
+static bd_t *binfo = &__res;
+
+EXPORT_SYMBOL(__res);
+
+
+/*
+ * Perform any initialization needed in order to setup the interface
+ * between the Firmware-supplied setup data and the Linux use of it.
+ *
+ * That is, copy the data pointed to by r3 to the __res "residual" structure.
+ */
+
+void __init
+fw_initialize(unsigned long r3)
+{
+	if (r3) {
+		memcpy((void *) &__res,
+		       (void *) (r3 + KERNELBASE),
+		       sizeof(bd_t));
+	}
+}
+
+
+/*
+ * Return the address of an in-memory structure that can be used
+ * to initialize the bd_t firware setup. Woo.
+ */
+
+void *
+fw_get_init_data(void)
+{
+	return &__res;
+}
+
+
+/*
+ * Return the start of DRAM memory.
+ */
+unsigned long
+fw_get_memory_start(void)
+{
+#if defined(FW_BDT_HAS_MEMSTART)
+        return binfo->bi_memstart;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Return the amount of memory in bytes.
+ */
+unsigned long
+fw_get_memory_size(void)
+{
+#if defined(FW_BDT_HAS_MEMSIZE)
+        return binfo->bi_memsize;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Return the start of FLASH memory.
+ */
+unsigned long
+fw_get_flash_start(void)
+{
+#if defined(FW_BDT_HAS_FLASHSTART)
+        return binfo->bi_flashstart;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Return the amount of FLASH memory in bytes.
+ */
+unsigned long
+fw_get_flash_size(void)
+{
+#if defined(FW_BDT_HAS_FLASHSIZE)
+        return binfo->bi_flashsize;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_flash_offset(void)
+{
+#if defined(FW_BDT_HAS_FLASHOFFSET)
+        return binfo->bi_flashoffset;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Return the start of SRAM memory.
+ */
+unsigned long
+fw_get_sram_start(void)
+{
+#if defined(FW_BDT_HAS_SRAMSTART)
+        return binfo->bi_sramstart;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Return the amount of SRAM memory in bytes.
+ */
+unsigned long
+fw_get_sram_size(void)
+{
+#if defined(FW_BDT_HAS_SRAMSIZE)
+        return binfo->bi_sramsize;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Return the amount of NVRAM in bytes.
+ */
+unsigned long
+fw_get_nvram_size(void)
+{
+#if defined(FW_BDT_HAS_NVRAM_SIZE)
+        return binfo->bi_nvramsize;
+#else
+	return 0;
+#endif
+}
+
+
+
+/*
+ * Return the internal core frequency in MHz.
+ */
+unsigned long
+fw_get_intfreq(void)
+{
+#if defined(FW_BDT_HAS_INTFREQ)
+        return binfo->bi_intfreq;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Return the bus frequency in MHz.
+ */
+unsigned long
+fw_get_busfreq(void)
+{
+#if defined(FW_BDT_HAS_BUSFREQ)
+        return binfo->bi_busfreq;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Return the CPM frequency.
+ */
+unsigned long
+fw_get_cpmfreq(void)
+{
+#if defined(FW_BDT_HAS_CPMFREQ)
+        return binfo->bi_cpmfreq;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Return the BRG frequency.
+ */
+unsigned long
+fw_get_brgfreq(void)
+{
+#if defined(FW_BDT_HAS_BRGFREQ)
+        return binfo->bi_brgfreq;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_sccfreq(void)
+{
+#if defined(FW_BDT_HAS_SCCFREQ)
+        return binfo->bi_sccfreq;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_ipbfreq(void)
+{
+#if defined(FW_BDT_HAS_IPBFREQ)
+        return binfo->bi_ipbfreq;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_procfreq(void)
+{
+#if defined(FW_BDT_HAS_PROCFREQ)
+        return binfo->bi_procfreq;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_tbfreq(void)
+{
+#if defined(FW_BDT_HAS_TBFREQ)
+        return binfo->bi_tbfreq;
+#elif defined(FW_BDT_HAS_INTFREQ)
+	/* This should be the case for:
+	 *     ep405, Ash, Oak, Sycamore, Walnut, xilinx_ml300,
+	 *     bubinga, cpci405
+	 */
+        return binfo->bi_intfreq;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_opbfreq(void)
+{
+#if defined(FW_BDT_HAS_OPBFREQ)
+        return binfo->bi_opbfreq;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_opb_busfreq(void)
+{
+#if defined(FW_BDT_HAS_OPB_BUSFREQ)
+        return binfo->bi_opb_busfreq;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_pllouta_freq(void)
+{
+#if defined(FW_BDT_HAS_PLLOUTA_FREQ)
+        return binfo->bi_pllouta_freq;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_pcifreq(void)
+{
+#if defined(FW_BDT_HAS_PCIFREQ)
+        return binfo->bi_pcifreq;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_pci_busfreq(void)
+{
+#if defined(FW_BDT_HAS_PCI_BUSFREQ)
+        return binfo->bi_pci_busfreq;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_plb_busfreq(void)
+{
+#if defined(FW_BDT_HAS_PLB_BUSFREQ)
+        return binfo->bi_plb_busfreq;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Return the baudrate.
+ */
+unsigned long
+fw_get_baudrate(void)
+{
+#if defined(FW_BDT_HAS_BAUDRATE)
+	return binfo->bi_baudrate;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Return IMMR base address.
+ */
+unsigned long
+fw_get_immr_base(void)
+{
+#if defined(FW_BDT_HAS_IMMR_BASE)
+        return binfo->bi_immr_base;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Return the base address of a 6-element array of unsigned bytes
+ * that contains the MAC address of the given Ethernet device.
+ *
+ * which_one should be [0 .. num_of_ethaddrs), for some num_of_ethaddrs
+ *
+ *     0 == enetaddr  == enetaddr[0]
+ *     1 == enet1addr == enetaddr[1]
+ *     2 == enet2addr == enetaddr[2]
+ *     3 == enet3addr == enetaddr[3]
+ */
+
+unsigned char *
+fw_get_enetaddr(unsigned int which_one)
+{
+
+#if defined(FW_BDT_HAS_ENETADDR_A2) || defined(FW_BDT_HAS_ENETADDR_A4)
+	/* FIXME: Could check range 0 .. 1 or  0 .. 3 respectively */
+	return &binfo->bi_enetaddr[which_one][0];
+#else
+
+	if (which_one == 0) {
+
+#if defined(FW_BDT_HAS_ENETADDR)
+		return &binfo->bi_enetaddr[0];
+#endif
+
+#if defined(FW_BDT_HAS_ENET1ADDR)
+	} else if (which_one == 1) {
+		return &binfo->bi_enet1addr[0];
+#endif
+
+#if defined(FW_BDT_HAS_ENET2ADDR)
+	} else if (which_one == 2) {
+		return &binfo->bi_enet2addr[0];
+#endif
+
+#if defined(FW_BDT_HAS_ENET3ADDR)
+	} else if (which_one == 3) {
+		return &binfo->bi_enet3addr[0];
+#endif
+
+	}
+
+#endif
+
+	return 0;
+}
+
+
+unsigned char *
+fw_get_pci_enetaddr(void)
+{
+#if defined(FW_BDT_HAS_PCI_ENETADDR)
+        return binfo->bi_pci_enetaddr;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_ethspped(void)
+{
+#if defined(FW_BDT_HAS_ETHSPEED)
+	return binfo->bi_ethspeed;
+#else
+	return 0;
+#endif
+}
+
+
+char *
+fw_get_s_version(void)
+{
+#if defined(FW_BDT_HAS_S_VERSION)
+	return &binfo->bi_s_version[0];
+#else
+	return 0;
+#endif
+}
+
+
+char *
+fw_get_r_version(void)
+{
+#if defined(FW_BDT_HAS_R_VERSION)
+	return &binfo->bi_r_version[0];
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_bootflags(void)
+{
+#if defined(FW_BDT_HAS_BOOTFLAGS)
+	return binfo->bi_bootflags;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_ip_addr(void)
+{
+#if defined(FW_BDT_HAS_IP_ADDR)
+	return binfo->bi_ip_addr;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_vco(void)
+{
+#if defined(FW_BDT_HAS_VCO)
+	return binfo->bi_vco;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_tag(void)
+{
+#if defined(FW_BDT_HAS_TAG)
+	return binfo->bi_tag;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_size(void)
+{
+#if defined(FW_BDT_HAS_SIZE)
+	return binfo->bi_size;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_revision(void)
+{
+#if defined(FW_BDT_HAS_REVISION)
+	return binfo->bi_revision;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_bdate(void)
+{
+#if defined(FW_BDT_HAS_BDATE)
+	return binfo->bi_bdate;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_clun(void)
+{
+#if defined(FW_BDT_HAS_CLUN)
+	return binfo->bi_clun;
+#else
+	return 0;
+#endif
+}
+
+
+unsigned long
+fw_get_dlun(void)
+{
+#if defined(FW_BDT_HAS_DLUN)
+	return binfo->bi_dlun;
+#else
+	return 0;
+#endif
+}
+
+
+
+
+void
+fw_set_busfreq(unsigned long freq)
+{
+	binfo->bi_busfreq = freq;
+}
+
+void
+fw_set_intfreq(unsigned long freq)
+{
+	binfo->bi_intfreq = freq;
+}
+
+void
+fw_set_ipbfreq(unsigned long freq)
+{
+#if defined(FW_BDT_HAS_IPBFREQ)
+	binfo->bi_ipbfreq = freq;
+#endif
+}
+
+void
+fw_set_pcifreq(unsigned long freq)
+{
+#if defined(FW_BDT_HAS_PCIFREQ)
+	binfo->bi_pcifreq = freq;
+#endif
+}
Index: arch/ppc/syslib/fw_bdt.h
===================================================================
--- /dev/null  (tree:c7d7a187a2125518e655dfeadffd38156239ffc3)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/fw_bdt.h  (mode:100644)
@@ -0,0 +1,453 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __PPC_SYSLIB_FW_BDT_H__
+#define __PPC_SYSLIB_FW_BDT_H__
+
+/*
+ * Board information passed to kernel from U-Boot
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/*
+ * The following set of boards have special bd_info structures below.
+ * All other boards use the generic bd_info.
+ */
+#if    !defined(CONFIG_MBX) \
+    && !defined(CONFIG_RPXCLASSIC) \
+    && !defined(CONFIG_RPXLITE) \
+    && !defined(CONFIG_BSEIP) \
+    && !defined(CONFIG_SBS8260) \
+    && !defined(CONFIG_EST8260) \
+    && !defined(CONFIG_RPX8260) \
+    && !defined(CONFIG_EP405) \
+    && !defined(CONFIG_XILINX_ML300) \
+    && !defined(CONFIG_REDWOOD_5) \
+    && !defined(CONFIG_REDWOOD_6) \
+    && !defined(CONFIG_BUBINGA) \
+    && !defined(CONFIG_ASH) \
+    && !defined(CONFIG_OAK) \
+    && !defined(CONFIG_SYCAMORE) \
+    && !defined(CONFIG_WALNUT)
+
+
+/*
+ * The "generic" bd_info as originally defined in ppcboot.h
+ * and used by the majority of ppc32 boards.
+ */
+typedef struct bd_info {
+
+#define FW_BDT_HAS_MEMSTART
+#define FW_BDT_HAS_MEMSIZE
+#define FW_BDT_HAS_FLASHSTART
+#define FW_BDT_HAS_FLASHSIZE
+#define FW_BDT_HAS_FLASHOFFSET
+#define FW_BDT_HAS_SRAMSTART
+#define FW_BDT_HAS_SRAMSIZE
+	unsigned long	bi_memstart;	/* start of DRAM memory */
+	unsigned long	bi_memsize;	/* size	 of DRAM memory in bytes */
+	unsigned long	bi_flashstart;	/* start of FLASH memory */
+	unsigned long	bi_flashsize;	/* size	 of FLASH memory */
+	unsigned long	bi_flashoffset; /* reserved area for startup monitor */
+	unsigned long	bi_sramstart;	/* start of SRAM memory */
+	unsigned long	bi_sramsize;	/* size	 of SRAM memory */
+
+#if    defined(CONFIG_8xx) \
+    || defined(CONFIG_CPM2) \
+    || defined(CONFIG_85xx) \
+    || defined(CONFIG_83xx)
+#define FW_BDT_HAS_IMMR_BASE
+	unsigned long	bi_immr_base;	/* base of IMMR register */
+#endif
+
+#if defined(CONFIG_PPC_MPC52xx)
+#define FW_BDT_HAS_MBAR_BASE
+	unsigned long   bi_mbar_base;   /* base of internal registers */
+#endif
+
+#define FW_BDT_HAS_BOOTFLAGS
+#define FW_BDT_HAS_IP_ADDR
+#define FW_BDT_HAS_ENETADDR
+#define FW_BDT_HAS_ETHSPEED
+#define FW_BDT_HAS_INTFREQ
+#define FW_BDT_HAS_BUSFREQ
+	unsigned long	bi_bootflags;	/* boot / reboot flag (for LynxOS) */
+	unsigned long	bi_ip_addr;	/* IP Address */
+	unsigned char	bi_enetaddr[6];	/* Ethernet address */
+	unsigned short	bi_ethspeed;	/* Ethernet speed in Mbps */
+	unsigned long	bi_intfreq;	/* Internal Freq, in MHz */
+	unsigned long	bi_busfreq;	/* Bus Freq, in MHz */
+
+#if defined(CONFIG_CPM2)
+#define FW_BDT_HAS_CPMFREQ
+#define FW_BDT_HAS_BRGFREQ
+#define FW_BDT_HAS_SCCFREQ
+#define FW_BDT_HAS_VCO
+	unsigned long	bi_cpmfreq;	/* CPM_CLK Freq, in MHz */
+	unsigned long	bi_brgfreq;	/* BRG_CLK Freq, in MHz */
+	unsigned long	bi_sccfreq;	/* SCC_CLK Freq, in MHz */
+	unsigned long	bi_vco;		/* VCO Out from PLL, in MHz */
+#endif
+
+#if defined(CONFIG_PPC_MPC52xx)
+#define FW_BDT_HAS_IPBFREQ
+#define FW_BDT_HAS_PCIFREQ
+	unsigned long   bi_ipbfreq;     /* IPB Bus Freq, in MHz */
+	unsigned long   bi_pcifreq;     /* PCI Bus Freq, in MHz */
+#endif
+
+#define FW_BDT_HAS_BAUDRATE
+	unsigned long	bi_baudrate;	/* Console Baudrate */
+
+#if defined(CONFIG_4xx)
+#define FW_BDT_HAS_S_VERSION
+#define FW_BDT_HAS_R_VERSION
+#define FW_BDT_HAS_PROCFREQ
+#define FW_BDT_HAS_PLB_BUSFREQ
+#define FW_BDT_HAS_PCI_BUSFREQ
+#define FW_BDT_HAS_PCI_ENETADDR
+	unsigned char	bi_s_version[4];	/* Version of this structure */
+	unsigned char	bi_r_version[32];	/* Version of the ROM (IBM) */
+	unsigned int	bi_procfreq;	/* CPU (Internal) Freq, in Hz */
+	unsigned int	bi_plb_busfreq;	/* PLB Bus speed, in Hz */
+	unsigned int	bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+	unsigned char	bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
+#endif
+
+#if defined(CONFIG_HYMOD)
+#define FW_BDT_HAS_HYMOD_CONF
+	hymod_conf_t	bi_hymod_conf;	/* hymod configuration information */
+#endif
+
+#if    defined(CONFIG_EVB64260) \
+    || defined(CONFIG_44x) \
+    || defined(CONFIG_85xx) \
+    || defined(CONFIG_83xx)
+#define FW_BDT_HAS_ENET1ADDR
+	/* second onboard ethernet port */
+	unsigned char	bi_enet1addr[6];
+#endif
+
+#if    defined(CONFIG_EVB64260) \
+    || defined(CONFIG_440GX) \
+    || defined(CONFIG_85xx)
+#define FW_BDT_HAS_ENET2ADDR
+	/* third onboard ethernet ports */
+	unsigned char	bi_enet2addr[6];
+#endif
+
+#if defined(CONFIG_440GX)
+#define FW_BDT_HAS_ENET3ADDR
+	/* fourth onboard ethernet ports */
+	unsigned char	bi_enet3addr[6];
+#endif
+
+#if defined(CONFIG_4xx)
+#define FW_BDT_HAS_OBPFREQ
+#define FW_BDT_HAS_IIC_FAST
+	unsigned int	bi_opbfreq;		/* OB clock in Hz */
+	int		bi_iic_fast[2];		/* Use fast i2c mode */
+#endif
+
+#if defined(CONFIG_440GX)
+#define FW_BDT_HAS_PHYNUM
+#define FW_BDT_HAS_PHYMODE
+	int		bi_phynum[4];		/* phy mapping */
+	int		bi_phymode[4];		/* phy mode */
+#endif
+
+} bd_t;
+
+
+#else	/* non-generic bd_info declarations */
+
+
+#if defined(CONFIG_MBX)
+
+typedef struct bd_info {
+
+#define FW_BDT_HAS_TAG
+#define FW_BDT_HAS_SIZE
+#define FW_BDT_HAS_REVISION
+#define FW_BDT_HAS_BDATE
+#define FW_BDT_HAS_MEMSTART
+#define FW_BDT_HAS_MEMSIZE
+#define FW_BDT_HAS_INTFREQ
+#define FW_BDT_HAS_BUSFREQ
+#define FW_BDT_HAS_CLUN
+#define FW_BDT_HAS_DLUN
+	unsigned int	bi_tag;		/* Should be 0x42444944 "BDID" */
+	unsigned int	bi_size;	/* Size of this structure */
+	unsigned int	bi_revision;	/* revision of this structure */
+	unsigned int	bi_bdate;	/* EPPCbug date, i.e. 0x11061997 */
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+	unsigned int	bi_clun;	/* Boot device controller */
+	unsigned int	bi_dlun;	/* Boot device logical dev */
+
+	/* These fields are not part of the board information structure
+	 * provided by the boot rom.  They are filled in by embed_config.c
+	 * so we have the information consistent with other platforms.
+	 */
+#define FW_BDT_HAS_ENETADDR
+#define FW_BDT_HAS_BAUDRATE
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
+} bd_t;
+#endif
+
+
+#if    defined(CONFIG_RPXCLASSIC) \
+    || defined(CONFIG_RPXLITE) \
+    || defined(CONFIG_BSEIP)
+
+typedef struct bd_info {
+
+#define FW_BDT_HAS_MEMSTART
+#define FW_BDT_HAS_MEMSIZE
+#define FW_BDT_HAS_INTFREQ
+#define FW_BDT_HAS_BUSFREQ
+#define FW_BDT_HAS_ENETADDR
+#define FW_BDT_HAS_BAUDRATE
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
+} bd_t;
+#endif
+
+
+#if    defined(CONFIG_SBS8260) \
+    || defined(CONFIG_EST8260) \
+    || defined(CONFIG_RPX8260)
+
+typedef struct bd_info {
+
+#define FW_BDT_HAS_MEMSTART
+#define FW_BDT_HAS_MEMSIZE
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+
+#if defined(CONFIG_RPX8260)
+#define FW_BDT_HAS_NVRAMSIZE
+	unsigned int	bi_nvramsize;	/* NVRAM size in bytes (can be 0) */
+#endif
+
+#define FW_BDT_HAS_INTFREQ
+#define FW_BDT_HAS_BUSFREQ
+#define FW_BDT_HAS_CPMFREQ
+#define FW_BDT_HAS_BRGFREQ
+#define FW_BDT_HAS_VCO
+#define FW_BDT_HAS_BAUDRATE
+#define FW_BDT_HAS_IMMR_BASE
+#define FW_BDT_HAS_ENETADDR
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in MHz */
+	unsigned int	bi_cpmfreq;	/* CPM Freq, in MHz */
+	unsigned int	bi_brgfreq;	/* BRG Freq, in MHz */
+	unsigned int	bi_vco;		/* VCO Out from PLL */
+	unsigned int	bi_baudrate;	/* Default console baud rate */
+	unsigned int	bi_immr_base;	/* IMMR when called from boot rom */
+	unsigned char	bi_enetaddr[6];
+} bd_t;
+#endif
+
+
+#if    defined(CONFIG_EP405) \
+    || defined(CONFIG_XILINX_ML300)
+
+typedef struct bd_info {
+
+#define FW_BDT_HAS_MEMSIZE
+#define FW_BDT_HAS_ENETADDR
+#define FW_BDT_HAS_INTFREQ
+#define FW_BDT_HAS_BUSFREQ
+#define FW_BDT_HAS_PCI_BUSFREQ
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address*/
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+
+#if defined(CONFIG_EP405)
+#define FW_BDT_HAS_NVRAMSIZE
+	unsigned int	 bi_nvramsize;		/* Size of the NVRAM/RTC */
+#endif
+
+} bd_t;
+#endif
+
+
+#if    defined(CONFIG_REDWOOD_5) \
+    || defined(CONFIG_REDWOOD_6)
+
+typedef struct bd_info {
+
+#define FW_BDT_HAS_S_VERSION
+#define FW_BDT_HAS_R_VERSION
+#define FW_BDT_HAS_MEMSIZE
+#define FW_BDT_HAS_ENETADDR
+#define FW_BDT_HAS_INTFREQ
+#define FW_BDT_HAS_BUSFREQ
+#define FW_BDT_HAS_TBFREQ
+	unsigned char	bi_s_version[4];	/* Version of this structure */
+	unsigned char	bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	bi_memsize;		/* DRAM installed, in bytes */
+	unsigned int	bi_dummy;		/* field shouldn't exist */
+	unsigned char	bi_enetaddr[6];		/* Ethernet MAC address */
+	unsigned int	bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	bi_busfreq;		/* Bus speed, in Hz */
+	unsigned int	bi_tbfreq;		/* Software timebase freq */
+} bd_t;
+#endif
+
+
+#if defined(CONFIG_BUBINGA)
+
+typedef struct bd_info {
+
+#define FW_BDT_HAS_S_VERSION
+#define FW_BDT_HAS_R_VERSION
+#define FW_BDT_HAS_MEMSIZE
+#define FW_BDT_HAS_ENETADDR_A2
+#define FW_BDT_HAS_PCI_ENETADDR
+#define FW_BDT_HAS_INTFREQ
+#define FW_BDT_HAS_BUSFREQ
+#define FW_BDT_HAS_PCI_BUSFREQ
+#define FW_BDT_HAS_OPB_BUSFREQ
+#define FW_BDT_HAS_PLLOUTA_FREQ
+        unsigned char    bi_s_version[4];       /* Version of this structure */
+        unsigned char    bi_r_version[30];      /* Version of the IBM ROM */
+        unsigned int     bi_memsize;            /* DRAM installed, in bytes */
+        unsigned char    bi_enetaddr[2][6];     /* Local Ethernet MAC address*/
+        unsigned char    bi_pci_enetaddr[6];    /* PCI Ethernet MAC address */
+        unsigned int     bi_intfreq;            /* Processor speed, in Hz */
+        unsigned int     bi_busfreq;            /* PLB Bus speed, in Hz */
+        unsigned int     bi_pci_busfreq;        /* PCI Bus speed, in Hz */
+        unsigned int     bi_opb_busfreq;        /* OPB Bus speed, in Hz */
+        unsigned int     bi_pllouta_freq;       /* PLL OUTA speed, in Hz */
+} bd_t;
+#endif
+
+
+#if defined(CONFIG_ASH)
+
+typedef struct bd_info {
+
+#define FW_BDT_HAS_S_VERSION
+#define FW_BDT_HAS_R_VERSION
+#define FW_BDT_HAS_MEMSIZE
+#define FW_BDT_HAS_ENETADDR_A4
+#define FW_BDT_HAS_PCI_ENETADDR
+#define FW_BDT_HAS_INTFREQ
+#define FW_BDT_HAS_BUSFREQ
+#define FW_BDT_HAS_PCI_BUSFREQ
+	unsigned char	 bi_s_version[4];	/* Version of this structure */
+	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[4][6];	/* Local Ethernet MAC address*/
+	unsigned char	 bi_pci_enetaddr[6];
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI speed in Hz */
+} bd_t;
+#endif
+
+
+#if defined(CONFIG_OAK)
+
+typedef struct bd_info {
+
+#define FW_BDT_HAS_S_VERSION
+#define FW_BDT_HAS_R_VERSION
+#define FW_BDT_HAS_MEMSIZE
+#define FW_BDT_HAS_ENETADDR
+#define FW_BDT_HAS_INTFREQ
+#define FW_BDT_HAS_BUSFREQ
+	unsigned char	 bi_s_version[4];	/* Version of this structure */
+	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Ethernet MAC address */
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* Bus speed, in Hz */
+} bd_t;
+#endif
+
+
+#if defined(CONFIG_SYCAMORE)
+
+typedef struct bd_info {
+
+#define FW_BDT_HAS_S_VERSION
+#define FW_BDT_HAS_R_VERSION
+#define FW_BDT_HAS_MEMSIZE
+#define FW_BDT_HAS_ENETADDR
+#define FW_BDT_HAS_PCI_ENETADDR
+#define FW_BDT_HAS_INTFREQ
+#define FW_BDT_HAS_BUSFREQ
+#define FW_BDT_HAS_PCI_BUSFREQ
+	unsigned char	 bi_s_version[4];	/* Version of this structure */
+	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address*/
+	unsigned char	 bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+} bd_t;
+#endif
+
+
+#if defined(CONFIG_WALNUT)
+
+typedef struct bd_info {
+
+#define FW_BDT_HAS_S_VERSION
+#define FW_BDT_HAS_R_VERSION
+#define FW_BDT_HAS_MEMSIZE
+#define FW_BDT_HAS_ENETADDR
+#define FW_BDT_HAS_PCI_ENETADDR
+#define FW_BDT_HAS_INTFREQ
+#define FW_BDT_HAS_BUSFREQ
+#define FW_BDT_HAS_PCI_BUSFREQ
+	unsigned char	 bi_s_version[4];	/* Version of this structure */
+	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address*/
+	unsigned char	 bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+} bd_t;
+#endif
+
+#endif	/* non-generic bd_info structures */
+
+
+#endif /* __ASSEMBLY__ */
+#endif	/* __PPC_SYSLIB_FW_BDT_H__ */
+
Index: arch/ppc/syslib/Makefile
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/Makefile  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/Makefile  (mode:100644)
@@ -113,3 +113,7 @@
 ifeq ($(CONFIG_PPC_MPC52xx),y)
 obj-$(CONFIG_PCI)		+= mpc52xx_pci.o
 endif
+
+obj-$(CONFIG_FW_BDT)		+= fw_bdt.o
+obj-$(CONFIG_FW_OF)		+= fw_of.o
+
Index: include/asm-ppc/firmware.h
===================================================================
--- /dev/null  (tree:c7d7a187a2125518e655dfeadffd38156239ffc3)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/include/asm-ppc/firmware.h  (mode:100644)
@@ -0,0 +1,62 @@
+/*
+ * include/asm-ppc/firmware.h
+ *
+ * Provide an abstract interface to firmware information
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+
+void __init fw_initialize(unsigned long r3);
+unsigned long fw_get_memory_size(void);
+unsigned long fw_get_memory_start(void);
+unsigned long fw_get_flash_size(void);
+unsigned long fw_get_flash_start(void);
+unsigned long fw_get_flash_offset(void);
+unsigned long fw_get_sram_start(void);
+unsigned long fw_get_sram_size(void);
+unsigned long fw_get_nvram_size(void);
+
+unsigned long fw_get_intfreq(void);
+unsigned long fw_get_busfreq(void);
+unsigned long fw_get_cpmfreq(void);
+unsigned long fw_get_brgfreq(void);
+unsigned long fw_get_sccfreq(void);
+unsigned long fw_get_ipbfreq(void);
+unsigned long fw_get_procfreq(void);
+unsigned long fw_get_tbfreq(void);
+unsigned long fw_get_opbfreq(void);
+unsigned long fw_get_opb_busfreq(void);
+unsigned long fw_get_pllouta_freq(void);
+unsigned long fw_get_pcifreq(void);
+unsigned long fw_get_pci_busfreq(void);
+unsigned long fw_get_plb_busfreq(void);
+unsigned long fw_get_baudrate(void);
+unsigned long fw_get_immr_base(void);
+unsigned char *fw_get_enetaddr(unsigned int which_one);
+unsigned char *fw_get_pci_enetaddr(void);
+unsigned long fw_get_ethspped(void);
+char *fw_get_s_version(void);
+char *fw_get_r_version(void);
+unsigned long fw_get_bootflags(void);
+unsigned long fw_get_ip_addr(void);
+unsigned long fw_get_vco(void);
+
+void *fw_get_init_data(void);
+
+void fw_set_busfreq(unsigned long freq);
+void fw_set_intfreq(unsigned long freq);
+void fw_set_ipbfreq(unsigned long freq);
+void fw_set_pcifreq(unsigned long freq);
+
+#endif /* __KERNEL__ */
Index: arch/ppc/kernel/ppc_ksyms.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/kernel/ppc_ksyms.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/kernel/ppc_ksyms.c  (mode:100644)
@@ -319,10 +319,6 @@
 EXPORT_SYMBOL(cpm_install_handler);
 EXPORT_SYMBOL(cpm_free_handler);
 #endif /* CONFIG_8xx */
-#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) ||\
-	defined(CONFIG_83xx)
-EXPORT_SYMBOL(__res);
-#endif
 
 EXPORT_SYMBOL(next_mmu_context);
 EXPORT_SYMBOL(set_context);

^ permalink raw reply

* bd_t Cleaning: Board Changes
From: Jon Loeliger @ 2005-05-27 19:16 UTC (permalink / raw)
  To: linuxppc-embedded@ozlabs.org
In-Reply-To: <f003613a0526b7b6a00a0bd477cd5ac3@freescale.com>

On Thu, 2005-05-26 at 18:08, Kumar Gala wrote:
> Jon,
> 
> Can you break the patch up into a few pieces, it will be easier to 
> review that way.  Here are the following pieces that make sense to me:
> 
> 0. New firmware interface (fw_bdt*, Kconfig, ...)
> 1. board code changes (everything in arch/ppc/platforms/*)
> 2. driver changes (things in *_io, ide, net, serial dirs -- try to give 
> a better list below)
> 3. System changes (files in arch/ppc/syslib and include/asm-ppc)

Part Two of Four, the Board Changes.

 ppc/platforms/4xx/ash.h                 |   21 -
 ppc/platforms/4xx/bubinga.c             |    4 
 ppc/platforms/4xx/bubinga.h             |   23 -
 ppc/platforms/4xx/cpci405.h             |    2 
 ppc/platforms/4xx/ebony.c               |    9 
 ppc/platforms/4xx/ep405.c               |   12 
 ppc/platforms/4xx/ep405.h               |   13 
 ppc/platforms/4xx/luan.c                |    7 
 ppc/platforms/4xx/oak.c                 |   15 
 ppc/platforms/4xx/oak.h                 |   19 -
 ppc/platforms/4xx/oak_setup.h           |    2 
 ppc/platforms/4xx/ocotea.c              |   13 
 ppc/platforms/4xx/redwood5.h            |   13 
 ppc/platforms/4xx/redwood6.c            |   27 -
 ppc/platforms/4xx/redwood6.h            |   13 
 ppc/platforms/4xx/sycamore.h            |   22 -
 ppc/platforms/4xx/walnut.h              |   22 -
 ppc/platforms/4xx/xilinx_ml300.h        |   12 
 ppc/platforms/83xx/mpc834x_sys.c        |   49 +-
 ppc/platforms/83xx/mpc834x_sys.h        |    1 
 ppc/platforms/85xx/mpc8540_ads.c        |   57 ++-
 ppc/platforms/85xx/mpc8560_ads.c        |   21 -
 ppc/platforms/85xx/mpc85xx_ads_common.c |   10 
 ppc/platforms/85xx/mpc85xx_ads_common.h |    1 
 ppc/platforms/85xx/mpc85xx_cds_common.c |   48 +-
 ppc/platforms/85xx/mpc85xx_cds_common.h |    1 
 ppc/platforms/85xx/sbc8560.c            |   19 -
 ppc/platforms/85xx/sbc85xx.c            |   14 
 ppc/platforms/85xx/sbc85xx.h            |    1 
 ppc/platforms/85xx/stx_gp3.c            |   34 -
 ppc/platforms/85xx/stx_gp3.h            |    1 
 ppc/platforms/bseip.h                   |   13 
 ppc/platforms/ccm.h                     |    2 
 ppc/platforms/cpci690.h                 |   10 
 ppc/platforms/est8260.h                 |   18 
 ppc/platforms/fads.h                    |    2 
 ppc/platforms/hdpu.c                    |   13 
 ppc/platforms/hermes.h                  |    2 
 ppc/platforms/ip860.h                   |    2 
 ppc/platforms/ivms8.h                   |    2 
 ppc/platforms/katana.c                  |    6 
 ppc/platforms/lantec.h                  |    2 
 ppc/platforms/lite5200.c                |    9 
 ppc/platforms/lwmon.h                   |    2 
 ppc/platforms/mbx.h                     |   22 -
 ppc/platforms/pcu_e.h                   |    2 
 ppc/platforms/pq2ads.c                  |    1 
 ppc/platforms/pq2ads.h                  |    2 
 ppc/platforms/radstone_ppc7d.c          |   32 -
 ppc/platforms/radstone_ppc7d.h          |    2 
 ppc/platforms/rpx8260.h                 |   19 -
 ppc/platforms/rpxclassic.h              |   13 
 ppc/platforms/rpxlite.h                 |   13 
 ppc/platforms/sandpoint.c               |   11 
 ppc/platforms/sandpoint.h               |    2 
 ppc/platforms/sbc82xx.c                 |    6 
 ppc/platforms/sbc82xx.h                 |    2 
 ppc/platforms/sbs8260.h                 |   18 
 ppc/platforms/spd8xx.h                  |    2 
 ppc/platforms/tqm8260.h                 |    2 
 ppc/platforms/tqm8260_setup.c           |    1 
 ppc/platforms/tqm8xx.h                  |    2 

Index: arch/ppc/platforms/4xx/ash.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/ash.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/ash.h  (mode:100644)
@@ -18,27 +18,6 @@
 #include <platforms/4xx/ibmnp405h.h>
 
 #ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's "Ash" evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
-	unsigned char	 bi_s_version[4];	/* Version of this structure */
-	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
-	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
-	unsigned char	 bi_enetaddr[4][6];	/* Local Ethernet MAC address */
-	unsigned char	 bi_pci_enetaddr[6];
-	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
-	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
-	unsigned int	 bi_pci_busfreq;	/* PCI speed in Hz */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
 
 /* Memory map for the IBM "Ash" NP405H evaluation board.
  */
Index: arch/ppc/platforms/4xx/bubinga.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/bubinga.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/bubinga.c  (mode:100644)
@@ -34,6 +34,7 @@
 #include <asm/kgdb.h>
 #include <asm/ocp.h>
 #include <asm/ibm_ocp_pci.h>
+#include <asm/firmware.h>
 
 #include <platforms/4xx/ibm405ep.h>
 
@@ -45,7 +46,6 @@
 #define DBG(x...)
 #endif
 
-extern bd_t __res;
 
 void *bubinga_rtc_base;
 
@@ -89,7 +89,7 @@
           * by 16.
           */
 	uart_div = (mfdcr(DCRN_CPC0_UCR_BASE) & DCRN_CPC0_UCR_U0DIV);
-	uart_clock = __res.bi_pllouta_freq / uart_div;
+	uart_clock = fw_get_pllouta_freq() / uart_div;
 
 	/* Setup serial port access */
 	memset(&port, 0, sizeof(port));
Index: arch/ppc/platforms/4xx/bubinga.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/bubinga.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/bubinga.h  (mode:100644)
@@ -18,29 +18,6 @@
 #include <platforms/4xx/ibm405ep.h>
 
 #ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
-        unsigned char    bi_s_version[4];       /* Version of this structure */
-        unsigned char    bi_r_version[30];      /* Version of the IBM ROM */
-        unsigned int     bi_memsize;            /* DRAM installed, in bytes */
-        unsigned char    bi_enetaddr[2][6];     /* Local Ethernet MAC address */        unsigned char    bi_pci_enetaddr[6];    /* PCI Ethernet MAC address */
-        unsigned int     bi_intfreq;            /* Processor speed, in Hz */
-        unsigned int     bi_busfreq;            /* PLB Bus speed, in Hz */
-        unsigned int     bi_pci_busfreq;        /* PCI Bus speed, in Hz */
-        unsigned int     bi_opb_busfreq;        /* OPB Bus speed, in Hz */
-        unsigned int     bi_pllouta_freq;       /* PLL OUTA speed, in Hz */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
 
 /* Memory map for the Bubinga board.
  * Generic 4xx plus RTC.
Index: arch/ppc/platforms/4xx/cpci405.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/cpci405.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/cpci405.h  (mode:100644)
@@ -13,8 +13,6 @@
 /* We have a 405GP core */
 #include <platforms/4xx/ibm405gp.h>
 
-#include <asm/ppcboot.h>
-
 #ifndef __ASSEMBLY__
 /* Some 4xx parts use a different timebase frequency from the internal clock.
 */
Index: arch/ppc/platforms/4xx/ebony.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/ebony.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/ebony.c  (mode:100644)
@@ -49,7 +49,7 @@
 #include <asm/todc.h>
 #include <asm/bootinfo.h>
 #include <asm/ppc4xx_pic.h>
-#include <asm/ppcboot.h>
+#include <asm/firmware.h>
 
 #include <syslib/gen550.h>
 #include <syslib/ibm440gp_common.h>
@@ -61,7 +61,6 @@
  */
 #include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
 
-bd_t __res;
 
 static struct ibm44x_clocks clocks __initdata;
 
@@ -276,13 +275,13 @@
 	emacdata = def->additions;
 	emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
 	emacdata->phy_mode = PHY_MODE_RMII;
-	memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+	memcpy(emacdata->mac_addr, fw_get_enetaddr(0), 6);
 
 	def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 1);
 	emacdata = def->additions;
 	emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
 	emacdata->phy_mode = PHY_MODE_RMII;
-	memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
+	memcpy(emacdata->mac_addr, fw_get_enetaddr(1), 6);
 
 	/*
 	 * Determine various clocks.
@@ -333,7 +332,7 @@
 	 * residual data area.
 	 */
 	if (r3)
-		__res = *(bd_t *)(r3 + KERNELBASE);
+		fw_initialize(r3);
 
 	ibm44x_platform_init();
 
Index: arch/ppc/platforms/4xx/ep405.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/ep405.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/ep405.c  (mode:100644)
@@ -20,6 +20,7 @@
 #include <asm/todc.h>
 #include <asm/ocp.h>
 #include <asm/ibm_ocp_pci.h>
+#include <asm/firmware.h>
 
 #undef DEBUG
 #ifdef DEBUG
@@ -62,7 +63,7 @@
 
 	ibm_ocp_set_emac(0, 0);
 
-	if (__res.bi_nvramsize == 512*1024) {
+	if (fw_get_nvram_size() == 512*1024) {
 		/* FIXME: we should properly handle NVRTCs of different sizes */
 		TODC_INIT(TODC_TYPE_DS1557, ep405_nvram, ep405_nvram, ep405_nvram, 8);
 	}
@@ -138,14 +139,15 @@
 void __init
 ep405_map_io(void)
 {
-	bd_t *bip = &__res;
+	unsigned long nvram_size;
 
 	ppc4xx_map_io();
 
 	ep405_bcsr = ioremap(EP405_BCSR_PADDR, EP405_BCSR_SIZE);
 
-	if (bip->bi_nvramsize > 0) {
-		ep405_nvram = ioremap(EP405_NVRAM_PADDR, bip->bi_nvramsize);
+	nvram_size = fw_get_nvram_size();
+	if (nvram_size > 0) {
+		ep405_nvram = ioremap(EP405_NVRAM_PADDR, nvram_size);
 	}
 }
 
@@ -187,7 +189,7 @@
 	ppc_md.nvram_read_val = todc_direct_read_val;
 	ppc_md.nvram_write_val = todc_direct_write_val;
 
-	if (__res.bi_nvramsize == 512*1024) {
+	if (fw_get_nvram_size() == 512*1024) {
 		ppc_md.time_init = todc_time_init;
 		ppc_md.set_rtc_time = todc_set_rtc_time;
 		ppc_md.get_rtc_time = todc_get_rtc_time;
Index: arch/ppc/platforms/4xx/ep405.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/ep405.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/ep405.h  (mode:100644)
@@ -23,19 +23,6 @@
 
 #include <linux/types.h>
 
-typedef struct board_info {
-	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
-	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
-	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
-	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
-	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
-	unsigned int	 bi_nvramsize;		/* Size of the NVRAM/RTC */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
 extern u8 *ep405_bcsr;
 extern u8 *ep405_nvram;
 
Index: arch/ppc/platforms/4xx/luan.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/luan.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/luan.c  (mode:100644)
@@ -47,7 +47,7 @@
 #include <asm/todc.h>
 #include <asm/bootinfo.h>
 #include <asm/ppc4xx_pic.h>
-#include <asm/ppcboot.h>
+#include <asm/firmware.h>
 
 #include <syslib/ibm44x_common.h>
 #include <syslib/ibm440gx_common.h>
@@ -60,7 +60,6 @@
  */
 #include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
 
-bd_t __res;
 
 static struct ibm44x_clocks clocks __initdata;
 
@@ -137,7 +136,7 @@
 	emacdata = def->additions;
 	emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
 	emacdata->phy_mode = PHY_MODE_GMII;
-	memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+	memcpy(emacdata->mac_addr, fw_get_enetaddr(0), 6);
 }
 
 #define PCIX_READW(offset) \
@@ -370,7 +369,7 @@
 	 * residual data area.
 	 */
 	if (r3)
-		__res = *(bd_t *)(r3 + KERNELBASE);
+		fw_initialize(f3);
 
 	ibm44x_platform_init();
 
Index: arch/ppc/platforms/4xx/oak.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/oak.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/oak.c  (mode:100644)
@@ -28,6 +28,7 @@
 #include <asm/bootinfo.h>
 #include <asm/ppc4xx_pic.h>
 #include <asm/time.h>
+#include <asm/firmware.h>
 
 #include "oak.h"
 
@@ -35,9 +36,6 @@
 
 extern void abort(void);
 
-/* Global Variables */
-
-unsigned char __res[sizeof(bd_t)];
 
 
 /*
@@ -75,7 +73,7 @@
 	 * residual data area.
 	 */
 	if (r3) {
-		memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+		fw_initialize(r3);
 	}
 
 #if defined(CONFIG_BLK_DEV_INITRD)
@@ -145,12 +143,10 @@
 int
 oak_show_percpuinfo(struct seq_file *m, int i)
 {
-	bd_t *bp = (bd_t *)__res;
-
 	seq_printf(m, "clock\t\t: %dMHz\n"
 		   "bus clock\t\t: %dMHz\n",
-		   bp->bi_intfreq / 1000000,
-		   bp->bi_busfreq / 1000000);
+		   fw_get_intfreq() / 1000000,
+		   fw_get_busfreq() / 1000000);
 
 	return 0;
 }
@@ -237,9 +233,8 @@
 oak_calibrate_decr(void)
 {
 	unsigned int freq;
-	bd_t *bip = (bd_t *)__res;
 
-	freq = bip->bi_intfreq;
+	freq = fw_get_intfreq();
 
 	decrementer_count = freq / HZ;
 	count_period_num = 1;
Index: arch/ppc/platforms/4xx/oak.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/oak.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/oak.h  (mode:100644)
@@ -44,21 +44,6 @@
 #define	OAKSERIAL_INT		28	/* AIC_INT28 */
 
 #ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's "Oak" evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
-	unsigned char	 bi_s_version[4];	/* Version of this structure */
-	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
-	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
-	unsigned char	 bi_enetaddr[6];	/* Ethernet MAC address */
-	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
-	unsigned int	 bi_busfreq;		/* Bus speed, in Hz */
-} bd_t;
 
 #ifdef __cplusplus
 extern "C" {
@@ -85,10 +70,6 @@
 }
 #endif
 
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
 #define PPC4xx_MACHINE_NAME	"IBM Oak"
 
 #endif /* !__ASSEMBLY__ */
Index: arch/ppc/platforms/4xx/oak_setup.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/oak_setup.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/oak_setup.h  (mode:100644)
@@ -23,8 +23,6 @@
 extern "C" {
 #endif
 
-extern unsigned char	 __res[sizeof(bd_t)];
-
 extern void		 oak_init(unsigned long r3,
 				  unsigned long ird_start,
 				  unsigned long ird_end,
Index: arch/ppc/platforms/4xx/ocotea.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/ocotea.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/ocotea.c  (mode:100644)
@@ -47,7 +47,7 @@
 #include <asm/todc.h>
 #include <asm/bootinfo.h>
 #include <asm/ppc4xx_pic.h>
-#include <asm/ppcboot.h>
+#include <asm/firmware.h>
 
 #include <syslib/gen550.h>
 #include <syslib/ibm440gx_common.h>
@@ -59,7 +59,6 @@
  */
 #include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
 
-bd_t __res;
 
 static struct ibm44x_clocks clocks __initdata;
 
@@ -134,13 +133,13 @@
 			emacdata->phy_mode = PHY_MODE_RGMII;
 		}
 		if (i == 0)
-			memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+			memcpy(emacdata->mac_addr, fw_get_enetaddr(0), 6);
 		else if (i == 1)
-			memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
+			memcpy(emacdata->mac_addr, fw_get_enetaddr(1), 6);
 		else if (i == 2)
-			memcpy(emacdata->mac_addr, __res.bi_enet2addr, 6);
+			memcpy(emacdata->mac_addr, fw_get_enetaddr(2), 6);
 		else if (i == 3)
-			memcpy(emacdata->mac_addr, __res.bi_enet3addr, 6);
+			memcpy(emacdata->mac_addr, fw_get_enetaddr(3), 6);
 	}
 }
 
@@ -335,7 +334,7 @@
 	 * residual data area.
 	 */
 	if (r3)
-		__res = *(bd_t *)(r3 + KERNELBASE);
+		fw_initialize(r3);
 
 	/*
 	 * Determine various clocks.
Index: arch/ppc/platforms/4xx/redwood5.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/redwood5.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/redwood5.h  (mode:100644)
@@ -19,19 +19,6 @@
 /* Redwood5 has an STB04xxx core */
 #include <platforms/4xx/ibmstb4.h>
 
-#ifndef __ASSEMBLY__
-typedef struct board_info {
-	unsigned char	bi_s_version[4];	/* Version of this structure */
-	unsigned char	bi_r_version[30];	/* Version of the IBM ROM */
-	unsigned int	bi_memsize;		/* DRAM installed, in bytes */
-	unsigned int	bi_dummy;		/* field shouldn't exist */
-	unsigned char	bi_enetaddr[6];		/* Ethernet MAC address */
-	unsigned int	bi_intfreq;		/* Processor speed, in Hz */
-	unsigned int	bi_busfreq;		/* Bus speed, in Hz */
-	unsigned int	bi_tbfreq;		/* Software timebase freq */
-} bd_t;
-#endif /* !__ASSEMBLY__ */
-
 
 #define SMC91111_BASE_ADDR	0xf2000300
 #define SMC91111_REG_SIZE	16
Index: arch/ppc/platforms/4xx/redwood6.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/redwood6.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/redwood6.c  (mode:100644)
@@ -98,27 +98,34 @@
 #endif
 
 #ifdef DEBUG_BRINGUP
-	bd_t *bip = (bd_t *) __res;
+	{
+	unsigned long memsize = fw_get_memory_size();
+	unsigned char *p_addr = fw_get_enetaddr(0);
+	unsigned long int_freq = fw_get_intfreq();
+	unsigned long bus_freq = fw_get_busfreq();
+	unsigned long tb_freq = fw_get_tbfreq();
+
 	printk("\n");
 	printk("machine\t: %s\n", PPC4xx_MACHINE_NAME);
 	printk("\n");
-	printk("bi_s_version\t %s\n", bip->bi_s_version);
-	printk("bi_r_version\t %s\n", bip->bi_r_version);
-	printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize,
-	       bip->bi_memsize / (1024 * 1000));
+	printk("bi_s_version\t %s\n", fw_get_s_version());
+	printk("bi_r_version\t %s\n", fw_get_r_version());
+	printk("bi_memsize\t 0x%8.8x\t %dMBytes\n",
+	       memsize, memsize / (1024 * 1000));
 	printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0,
-	       bip->bi_enetaddr[0], bip->bi_enetaddr[1], bip->bi_enetaddr[2],
-	       bip->bi_enetaddr[3], bip->bi_enetaddr[4], bip->bi_enetaddr[5]);
+	       p_addr[0], p_addr[1], p_addr[2],
+	       p_addr[3], p_addr[4], p_addr[5]);
 
 	printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n",
-	       bip->bi_intfreq, bip->bi_intfreq / 1000000);
+	       int_freq, int_freq / 1000000);
 
 	printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n",
-	       bip->bi_busfreq, bip->bi_busfreq / 1000000);
+	       bus_freq, bus_freq / 1000000);
 	printk("bi_tbfreq\t 0x%8.8x\t TB freq:\t %dMHz\n",
-	       bip->bi_tbfreq, bip->bi_tbfreq / 1000000);
+	       tb_freq, tb_freq / 1000000);
 
 	printk("\n");
+	}
 #endif
 
 	/* Identify the system */
Index: arch/ppc/platforms/4xx/redwood6.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/redwood6.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/redwood6.h  (mode:100644)
@@ -19,19 +19,6 @@
 /* Redwood6 has an STBx25xx core */
 #include <platforms/4xx/ibmstbx25.h>
 
-#ifndef __ASSEMBLY__
-typedef struct board_info {
-	unsigned char bi_s_version[4];	/* Version of this structure */
-	unsigned char bi_r_version[30];	/* Version of the IBM ROM */
-	unsigned int bi_memsize;	/* DRAM installed, in bytes */
-	unsigned int bi_dummy;	/* field shouldn't exist */
-	unsigned char bi_enetaddr[6];	/* Ethernet MAC address */
-	unsigned int bi_intfreq;	/* Processor speed, in Hz */
-	unsigned int bi_busfreq;	/* Bus speed, in Hz */
-	unsigned int bi_tbfreq;	/* Software timebase freq */
-} bd_t;
-#endif				/* !__ASSEMBLY__ */
-
 #define SMC91111_BASE_ADDR	0xf2030300
 #define SMC91111_REG_SIZE	16
 #define SMC91111_IRQ		27
Index: arch/ppc/platforms/4xx/sycamore.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/sycamore.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/sycamore.h  (mode:100644)
@@ -19,28 +19,6 @@
 #include <platforms/4xx/ibm405gpr.h>
 
 #ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's "Sycamore" evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
-	unsigned char	 bi_s_version[4];	/* Version of this structure */
-	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
-	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
-	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
-	unsigned char	 bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
-	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
-	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
-	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
 
 /* Memory map for the IBM "Sycamore" 405GP evaluation board.
  * Generic 4xx plus RTC.
Index: arch/ppc/platforms/4xx/walnut.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/walnut.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/walnut.h  (mode:100644)
@@ -24,28 +24,6 @@
 #include <platforms/4xx/ibm405gp.h>
 
 #ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's "Walnut" evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
-	unsigned char	 bi_s_version[4];	/* Version of this structure */
-	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
-	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
-	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
-	unsigned char	 bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
-	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
-	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
-	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
 
 /* Memory map for the IBM "Walnut" 405GP evaluation board.
  * Generic 4xx plus RTC.
Index: arch/ppc/platforms/4xx/xilinx_ml300.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/4xx/xilinx_ml300.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/4xx/xilinx_ml300.h  (mode:100644)
@@ -22,18 +22,6 @@
 
 #include <linux/types.h>
 
-typedef struct board_info {
-	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
-	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
-	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
-	unsigned int	 bi_busfreq;		/* PLB Bus speed, in Hz */
-	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
 #endif /* !__ASSEMBLY__ */
 
 /* We don't need anything mapped.  Size of zero will accomplish that. */
Index: arch/ppc/platforms/83xx/mpc834x_sys.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/83xx/mpc834x_sys.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/83xx/mpc834x_sys.c  (mode:100644)
@@ -60,8 +60,6 @@
 
 extern unsigned long total_memory;	/* in mm/init */
 
-unsigned char __res[sizeof (bd_t)];
-
 #ifdef CONFIG_PCI
 #error "PCI is not supported"
 /* NEED mpc83xx_map_irq & mpc83xx_exclude_device
@@ -76,12 +74,12 @@
 static void __init
 mpc834x_sys_setup_arch(void)
 {
-	bd_t *binfo = (bd_t *) __res;
 	unsigned int freq;
+	unsigned int immr_base;
 	struct gianfar_platform_data *pdata;
 
 	/* get the core frequency */
-	freq = binfo->bi_intfreq;
+	freq = fw_get_intfreq();
 
 	/* Set loops_per_jiffy to a half-way reasonable value,
 	   for use until calibrate_delay gets called. */
@@ -93,22 +91,24 @@
 #endif
 	mpc83xx_early_serial_map();
 
+	immr_base = fw_get_immr_base();
+
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1);
 	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
 	pdata->interruptPHY = MPC83xx_IRQ_EXT1;
 	pdata->phyid = 0;
 	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(0), 6);
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2);
 	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
 	pdata->interruptPHY = MPC83xx_IRQ_EXT2;
 	pdata->phyid = 1;
 	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(1), 6);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
@@ -134,11 +134,11 @@
 mpc834x_sys_show_cpuinfo(struct seq_file *m)
 {
 	uint pvid, svid, phid1;
-	bd_t *binfo = (bd_t *) __res;
-	unsigned int freq;
+	unsigned int core_freq, bus_freq;
 
 	/* get the core frequency */
-	freq = binfo->bi_intfreq;
+	core_freq = fw_get_intfreq();
+	bus_freq = fw_get_busfreq();
 
 	pvid = mfspr(SPRN_PVR);
 	svid = mfspr(SPRN_SVR);
@@ -147,8 +147,8 @@
 	seq_printf(m, "Machine\t\t: mpc%s sys\n", cur_ppc_sys_spec->ppc_sys_name);
 	seq_printf(m, "core clock\t: %d MHz\n"
 			"bus  clock\t: %d MHz\n",
-			(int)(binfo->bi_intfreq / 1000000),
-			(int)(binfo->bi_busfreq / 1000000));
+			(int)(core_freq / 1000000),
+			(int)(bus_freq / 1000000));
 	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
 	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
 
@@ -157,7 +157,8 @@
 	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
 
 	/* Display the amount of memory */
-	seq_printf(m, "Memory\t\t: %d MB\n", (int)(binfo->bi_memsize / (1024 * 1024)));
+	seq_printf(m, "Memory\t\t: %d MB\n",
+		   (int)(fw_get_memory_size() / (1024 * 1024)));
 
 	return 0;
 }
@@ -166,8 +167,7 @@
 void __init
 mpc834x_sys_init_IRQ(void)
 {
-	bd_t *binfo = (bd_t *) __res;
-
+	unsigned long immr_base;
 	u8 senses[8] = {
 		0,			/* EXT 0 */
 		IRQ_SENSE_LEVEL,	/* EXT 1 */
@@ -179,7 +179,8 @@
 		0,			/* EXT 7 */
 	};
 
-	ipic_init(binfo->bi_immr_base + 0x00700, 0, MPC83xx_IPIC_IRQ_OFFSET, senses, 8);
+	immr_base = fw_get_immr_base();
+	ipic_init(immr_base + 0x00700, 0, MPC83xx_IPIC_IRQ_OFFSET, senses, 8);
 
 	/* Initialize the default interrupt mapping priorities,
 	 * in case the boot rom changed something on us.
@@ -201,8 +202,6 @@
 platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	      unsigned long r6, unsigned long r7)
 {
-	bd_t *binfo = (bd_t *) __res;
-
 	/* parse_bootinfo must always be called first */
 	parse_bootinfo(find_bootinfo());
 
@@ -211,8 +210,7 @@
 	 * residual data area.
 	 */
 	if (r3) {
-		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
-		       sizeof (bd_t));
+		fw_initialize(r3);
 	}
 
 #if defined(CONFIG_BLK_DEV_INITRD)
@@ -232,25 +230,28 @@
 		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
 	}
 
-	immrbar = binfo->bi_immr_base;
+	immrbar = fw_get_immr_base();
 
 	mpc834x_sys_set_bat();
 
 #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
 	{
 		struct uart_port p;
+		unsigned int busfreq;
+
+		busfreq = fw_get_busfreq();
 
 		memset(&p, 0, sizeof (p));
 		p.iotype = SERIAL_IO_MEM;
 		p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4500);
-		p.uartclk = binfo->bi_busfreq;
+		p.uartclk = busfreq;
 
 		gen550_init(0, &p);
 
 		memset(&p, 0, sizeof (p));
 		p.iotype = SERIAL_IO_MEM;
 		p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4600);
-		p.uartclk = binfo->bi_busfreq;
+		p.uartclk = busfreq;
 
 		gen550_init(1, &p);
 	}
Index: arch/ppc/platforms/83xx/mpc834x_sys.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/83xx/mpc834x_sys.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/83xx/mpc834x_sys.h  (mode:100644)
@@ -21,7 +21,6 @@
 #include <linux/init.h>
 #include <linux/seq_file.h>
 #include <syslib/ppc83xx_setup.h>
-#include <asm/ppcboot.h>
 
 #define VIRT_IMMRBAR		((uint)0xfe000000)
 
Index: arch/ppc/platforms/85xx/mpc8540_ads.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/85xx/mpc8540_ads.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/85xx/mpc8540_ads.c  (mode:100644)
@@ -51,6 +51,7 @@
 #include <asm/kgdb.h>
 #include <asm/ppc_sys.h>
 #include <mm/mmu_decl.h>
+#include <asm/firmware.h>
 
 #include <syslib/ppc85xx_setup.h>
 
@@ -62,12 +63,12 @@
 static void __init
 mpc8540ads_setup_arch(void)
 {
-	bd_t *binfo = (bd_t *) __res;
 	unsigned int freq;
+	unsigned int immr_base;
 	struct gianfar_platform_data *pdata;
 
 	/* get the core frequency */
-	freq = binfo->bi_intfreq;
+	freq = fw_get_intfreq();
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc8540ads_setup_arch()", 0);
@@ -85,36 +86,54 @@
 	mpc85xx_early_serial_map();
 #endif
 
+	if (ppc_md.progress)
+		ppc_md.progress("after mpc85xx_early_serial_map()", 0);
+
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	/* Invalidate the entry we stole earlier the serial ports
 	 * should be properly mapped */
 	invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
 #endif
 
+	immr_base = fw_get_immr_base();
+
+	if (ppc_md.progress)
+		ppc_md.progress("after getting immr base", 0);
+
+
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
 	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
 	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
 	pdata->phyid = 0;
 	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(0), 6);
+
+	if (ppc_md.progress)
+		ppc_md.progress("after enetaddr(0)", 0);
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
 	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
 	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
 	pdata->phyid = 1;
 	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(1), 6);
+
+	if (ppc_md.progress)
+		ppc_md.progress("after enetaddr(1)", 0);
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
 	pdata->board_flags = 0;
 	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
 	pdata->phyid = 3;
 	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(2), 6);
+
+	if (ppc_md.progress)
+		ppc_md.progress("after enetaddr(2)", 0);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
@@ -126,6 +145,9 @@
 #else
 		ROOT_DEV = Root_HDA1;
 #endif
+
+	if (ppc_md.progress)
+		ppc_md.progress("leaving mpc8540ads_setup_arch()", 0);
 }
 
 /* ************************************************************************ */
@@ -141,29 +163,30 @@
 	 * residual data area.
 	 */
 	if (r3) {
-		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
-		       sizeof (bd_t));
+		fw_initialize(r3);
 	}
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	{
-		bd_t *binfo = (bd_t *) __res;
+		unsigned int immr_base;
 		struct uart_port p;
 
+		immr_base = fw_get_immr_base();
+
 		/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
-		settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
-			  binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
+		settlbcam(NUM_TLBCAMS - 1, immr_base,
+			  immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
 
 		memset(&p, 0, sizeof (p));
 		p.iotype = SERIAL_IO_MEM;
-		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET;
-		p.uartclk = binfo->bi_busfreq;
+		p.membase = (void *) immr_base + MPC85xx_UART0_OFFSET;
+		p.uartclk = fw_get_busfreq();
 
 		gen550_init(0, &p);
 
 		memset(&p, 0, sizeof (p));
 		p.iotype = SERIAL_IO_MEM;
-		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET;
-		p.uartclk = binfo->bi_busfreq;
+		p.membase = (void *) immr_base + MPC85xx_UART1_OFFSET;
+		p.uartclk = fw_get_busfreq();
 
 		gen550_init(1, &p);
 	}
Index: arch/ppc/platforms/85xx/mpc8560_ads.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/85xx/mpc8560_ads.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/85xx/mpc8560_ads.c  (mode:100644)
@@ -51,6 +51,8 @@
 #include <asm/kgdb.h>
 #include <asm/ppc_sys.h>
 #include <asm/cpm2.h>
+#include <asm/firmware.h>
+
 #include <mm/mmu_decl.h>
 
 #include <syslib/cpm2_pic.h>
@@ -68,14 +70,13 @@
 static void __init
 mpc8560ads_setup_arch(void)
 {
-	bd_t *binfo = (bd_t *) __res;
-	unsigned int freq;
+	unsigned int freq, immr_base;
 	struct gianfar_platform_data *pdata;
 
 	cpm2_reset();
 
 	/* get the core frequency */
-	freq = binfo->bi_intfreq;
+	freq = fw_get_intfreq();
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc8560ads_setup_arch()", 0);
@@ -89,22 +90,24 @@
 	mpc85xx_setup_hose();
 #endif
 
+	immr_base = fw_get_immr_base();
+
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
 	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
 	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
 	pdata->phyid = 0;
 	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(0), 6);
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
 	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
 	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
 	pdata->phyid = 1;
 	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(1), 6);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
@@ -161,9 +164,7 @@
 	 * residual data area.
 	 */
 	if (r3) {
-		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
-		       sizeof (bd_t));
-
+		fw_initialize(r3);
 	}
 #if defined(CONFIG_BLK_DEV_INITRD)
 	/*
Index: arch/ppc/platforms/85xx/mpc85xx_ads_common.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/85xx/mpc85xx_ads_common.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/85xx/mpc85xx_ads_common.c  (mode:100644)
@@ -44,6 +44,7 @@
 #include <asm/irq.h>
 #include <asm/immap_85xx.h>
 #include <asm/ppc_sys.h>
+#include <asm/firmware.h>
 
 #include <mm/mmu_decl.h>
 
@@ -56,7 +57,6 @@
 
 extern unsigned long total_memory;	/* in mm/init */
 
-unsigned char __res[sizeof (bd_t)];
 
 /* Internal interrupts are all Level Sensitive, and Positive Polarity */
 
@@ -120,11 +120,10 @@
 {
 	uint pvid, svid, phid1;
 	uint memsize = total_memory;
-	bd_t *binfo = (bd_t *) __res;
 	unsigned int freq;
 
 	/* get the core frequency */
-	freq = binfo->bi_intfreq;
+	freq = fw_get_intfreq();
 
 	pvid = mfspr(SPRN_PVR);
 	svid = mfspr(SPRN_SVR);
@@ -148,10 +147,9 @@
 void __init
 mpc85xx_ads_init_IRQ(void)
 {
-	bd_t *binfo = (bd_t *) __res;
 	/* Determine the Physical Address of the OpenPIC regs */
-	phys_addr_t OpenPIC_PAddr =
-	    binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+	unsigned int immr_base = fw_get_immr_base();
+	phys_addr_t OpenPIC_PAddr = immr_base + MPC85xx_OPENPIC_OFFSET;
 	OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
 	OpenPIC_InitSenses = mpc85xx_ads_openpic_initsenses;
 	OpenPIC_NumInitSenses = sizeof (mpc85xx_ads_openpic_initsenses);
Index: arch/ppc/platforms/85xx/mpc85xx_ads_common.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/85xx/mpc85xx_ads_common.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/85xx/mpc85xx_ads_common.h  (mode:100644)
@@ -20,7 +20,6 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/seq_file.h>
-#include <asm/ppcboot.h>
 
 #define BOARD_CCSRBAR		((uint)0xe0000000)
 #define BCSR_ADDR		((uint)0xf8000000)
Index: arch/ppc/platforms/85xx/mpc85xx_cds_common.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/85xx/mpc85xx_cds_common.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/85xx/mpc85xx_cds_common.c  (mode:100644)
@@ -66,7 +66,6 @@
 
 extern unsigned long total_memory;      /* in mm/init */
 
-unsigned char __res[sizeof (bd_t)];
 
 static int cds_pci_slot = 2;
 static volatile u8 * cadmus;
@@ -137,11 +136,10 @@
 {
 	uint pvid, svid, phid1;
 	uint memsize = total_memory;
-	bd_t *binfo = (bd_t *) __res;
 	unsigned int freq;
 
 	/* get the core frequency */
-	freq = binfo->bi_intfreq;
+	freq = fw_get_intfreq();
 
 	pvid = mfspr(SPRN_PVR);
 	svid = mfspr(SPRN_SVR);
@@ -180,10 +178,13 @@
 void __init
 mpc85xx_cds_init_IRQ(void)
 {
-	bd_t *binfo = (bd_t *) __res;
+	phys_addr_t OpenPIC_PAddr;
+	unsigned int immr_base;
+
+	immr_base = fw_get_immr_base();
 
 	/* Determine the Physical Address of the OpenPIC regs */
-	phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+	OpenPIC_PAddr = immr_base + MPC85xx_OPENPIC_OFFSET;
 	OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
 	OpenPIC_InitSenses = mpc85xx_cds_openpic_initsenses;
 	OpenPIC_NumInitSenses = sizeof (mpc85xx_cds_openpic_initsenses);
@@ -299,12 +300,12 @@
 static void __init
 mpc85xx_cds_setup_arch(void)
 {
-	bd_t *binfo = (bd_t *) __res;
+	unsigned int immr_base;
 	unsigned int freq;
 	struct gianfar_platform_data *pdata;
 
 	/* get the core frequency */
-	freq = binfo->bi_intfreq;
+	freq = fw_get_intfreq();
 
 	printk("mpc85xx_cds_setup_arch\n");
 
@@ -342,22 +343,24 @@
 	invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
 #endif
 
+	immr_base = fw_get_immr_base();
+
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
 	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
 	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
 	pdata->phyid = 0;
 	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(0), 6);
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
 	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
 	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
 	pdata->phyid = 1;
 	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(1), 6);
 
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -385,30 +388,33 @@
 	 * residual data area.
 	 */
 	if (r3) {
-		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
-				sizeof (bd_t));
-
+		fw_initialize(r3);
 	}
+
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	{
-		bd_t *binfo = (bd_t *) __res;
+		unsigned int immr_base;
+		unsigned int busfreq;
 		struct uart_port p;
 
+		immr_base = fw_get_immr_base();
+		busfreq = fw_get_busfreq();
+
 		/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
-		settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
-				binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
+		settlbcam(NUM_TLBCAMS - 1, immr_base,
+				immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
 
 		memset(&p, 0, sizeof (p));
 		p.iotype = SERIAL_IO_MEM;
-		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET;
-		p.uartclk = binfo->bi_busfreq;
+		p.membase = (void *) immr_base + MPC85xx_UART0_OFFSET;
+		p.uartclk = busfreq;
 
 		gen550_init(0, &p);
 
 		memset(&p, 0, sizeof (p));
 		p.iotype = SERIAL_IO_MEM;
-		p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET;
-		p.uartclk = binfo->bi_busfreq;
+		p.membase = (void *) immr_base + MPC85xx_UART1_OFFSET;
+		p.uartclk = busfreq;
 
 		gen550_init(1, &p);
 	}
Index: arch/ppc/platforms/85xx/mpc85xx_cds_common.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/85xx/mpc85xx_cds_common.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/85xx/mpc85xx_cds_common.h  (mode:100644)
@@ -19,7 +19,6 @@
 
 #include <linux/config.h>
 #include <linux/serial.h>
-#include <asm/ppcboot.h>
 #include <linux/initrd.h>
 #include <syslib/ppc85xx_setup.h>
 
Index: arch/ppc/platforms/85xx/sbc8560.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/85xx/sbc8560.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/85xx/sbc8560.c  (mode:100644)
@@ -50,6 +50,8 @@
 #include <asm/immap_85xx.h>
 #include <asm/kgdb.h>
 #include <asm/ppc_sys.h>
+#include <asm/firmware.h>
+
 #include <mm/mmu_decl.h>
 
 #include <syslib/ppc85xx_common.h>
@@ -101,12 +103,12 @@
 static void __init
 sbc8560_setup_arch(void)
 {
-	bd_t *binfo = (bd_t *) __res;
 	unsigned int freq;
+	unsigned int immr_base;
 	struct gianfar_platform_data *pdata;
 
 	/* get the core frequency */
-	freq = binfo->bi_intfreq;
+	freq = fw_get_intfreq();
 
 	if (ppc_md.progress)
 		ppc_md.progress("sbc8560_setup_arch()", 0);
@@ -128,22 +130,24 @@
 	invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
 #endif
 
+	immr_base = fw_get_immr_base();
+
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
 	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
 	pdata->interruptPHY = MPC85xx_IRQ_EXT6;
 	pdata->phyid = 25;
 	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(0), 6);
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
 	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
 	pdata->interruptPHY = MPC85xx_IRQ_EXT7;
 	pdata->phyid = 26;
 	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(1), 6);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
@@ -170,8 +174,7 @@
 	 * residual data area.
 	 */
 	if (r3) {
-		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
-		       sizeof (bd_t));
+		fw_initialize(r3);
 	}
 
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
Index: arch/ppc/platforms/85xx/sbc85xx.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/85xx/sbc85xx.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/85xx/sbc85xx.c  (mode:100644)
@@ -48,8 +48,6 @@
 
 #include <platforms/85xx/sbc85xx.h>
 
-unsigned char __res[sizeof (bd_t)];
-
 #ifndef CONFIG_PCI
 unsigned long isa_io_base = 0;
 unsigned long isa_mem_base = 0;
@@ -120,11 +118,10 @@
 {
 	uint pvid, svid, phid1;
 	uint memsize = total_memory;
-	bd_t *binfo = (bd_t *) __res;
 	unsigned int freq;
 
 	/* get the core frequency */
-	freq = binfo->bi_intfreq;
+	freq = fw_get_intfreq();
 
 	pvid = mfspr(SPRN_PVR);
 	svid = mfspr(SPRN_SVR);
@@ -148,10 +145,13 @@
 void __init
 sbc8560_init_IRQ(void)
 {
-	bd_t *binfo = (bd_t *) __res;
+	phys_addr_t OpenPIC_PAddr;
+	unsigned long immr_base;
+
+	immr_base = fw_get_immr_base();
+
 	/* Determine the Physical Address of the OpenPIC regs */
-	phys_addr_t OpenPIC_PAddr =
-	    binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+	OpenPIC_PAddr = immr_base + MPC85xx_OPENPIC_OFFSET;
 	OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
 	OpenPIC_InitSenses = sbc8560_openpic_initsenses;
 	OpenPIC_NumInitSenses = sizeof (sbc8560_openpic_initsenses);
Index: arch/ppc/platforms/85xx/sbc85xx.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/85xx/sbc85xx.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/85xx/sbc85xx.h  (mode:100644)
@@ -19,7 +19,6 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/seq_file.h>
-#include <asm/ppcboot.h>
 
 #define BOARD_CCSRBAR		((uint)0xff700000)
 #define CCSRBAR_SIZE		((uint)1024*1024)
Index: arch/ppc/platforms/85xx/stx_gp3.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/85xx/stx_gp3.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/85xx/stx_gp3.c  (mode:100644)
@@ -56,14 +56,13 @@
 #include <asm/immap_cpm2.h>
 #include <asm/mpc85xx.h>
 #include <asm/ppc_sys.h>
+#include <asm/firmware.h>
 
 #include <syslib/cpm2_pic.h>
 #include <syslib/ppc85xx_common.h>
 
 extern void cpm2_reset(void);
 
-unsigned char __res[sizeof(bd_t)];
-
 #ifndef CONFIG_PCI
 unsigned long isa_io_base = 0;
 unsigned long isa_mem_base = 0;
@@ -131,14 +130,14 @@
 static void __init
 gp3_setup_arch(void)
 {
-	bd_t *binfo = (bd_t *) __res;
 	unsigned int freq;
+	unsigned long immr_base;
 	struct gianfar_platform_data *pdata;
 
 	cpm2_reset();
 
 	/* get the core frequency */
-	freq = binfo->bi_intfreq;
+	freq = fw_get_intfreq();
 
 	if (ppc_md.progress)
 		ppc_md.progress("gp3_setup_arch()", 0);
@@ -152,21 +151,23 @@
 	mpc85xx_setup_hose();
 #endif
 
+	immr_base = fw_get_immr_base();
+
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
 /*	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
 	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
 	pdata->phyid = 2;
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(0), 6);
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
 /*	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
 	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
 	pdata->phyid = 4;
 	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	pdata->phy_reg_addr += immr_base;
+	memcpy(pdata->mac_addr, fw_get_enetaddr(1), 6);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
@@ -179,7 +180,7 @@
 		ROOT_DEV = Root_HDA1;
 #endif
 
-	printk ("bi_immr_base = %8.8lx\n", binfo->bi_immr_base);
+	printk ("bi_immr_base = %8.8lx\n", immr_base);
 }
 
 static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
@@ -200,16 +201,18 @@
 static void __init
 gp3_init_IRQ(void)
 {
+	unsigned long immr_base;
+	phys_addr_t OpenPIC_PAddr;
 	int i;
-	bd_t *binfo = (bd_t *) __res;
+
+	immr_base = fw_get_immr_base();
 
 	/*
 	 * Setup OpenPIC
 	 */
 
 	/* Determine the Physical Address of the OpenPIC regs */
-	phys_addr_t OpenPIC_PAddr =
-	    binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+	OpenPIC_PAddr = immr_base + MPC85xx_OPENPIC_OFFSET;
 	OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
 	OpenPIC_InitSenses = gp3_openpic_initsenses;
 	OpenPIC_NumInitSenses = sizeof (gp3_openpic_initsenses);
@@ -238,13 +241,12 @@
 gp3_show_cpuinfo(struct seq_file *m)
 {
 	uint pvid, svid, phid1;
-	bd_t *binfo = (bd_t *) __res;
 	uint	memsize;
 	unsigned int freq;
 	extern unsigned long total_memory;	/* in mm/init */
 
 	/* get the core frequency */
-	freq = binfo->bi_intfreq;
+	freq = fw_get_intfreq();
 
 	pvid = mfspr(SPRN_PVR);
 	svid = mfspr(SPRN_SVR);
@@ -309,9 +311,7 @@
 	 * residual data area.
 	 */
 	if (r3) {
-		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
-		       sizeof (bd_t));
-
+		fw_initialize(r3);
 	}
 #if defined(CONFIG_BLK_DEV_INITRD)
 	/*
Index: arch/ppc/platforms/85xx/stx_gp3.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/85xx/stx_gp3.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/85xx/stx_gp3.h  (mode:100644)
@@ -22,7 +22,6 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/seq_file.h>
-#include <asm/ppcboot.h>
 
 #define BOARD_CCSRBAR		((uint)0xe0000000)
 #define CCSRBAR_SIZE		((uint)1024*1024)
Index: arch/ppc/platforms/bseip.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/bseip.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/bseip.h  (mode:100644)
@@ -8,19 +8,6 @@
 #define __MACH_BSEIP_DEFS
 
 #ifndef __ASSEMBLY__
-/* A Board Information structure that is given to a program when
- * prom starts it up.
- */
-typedef struct bd_info {
-	unsigned int	bi_memstart;	/* Memory start address */
-	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
-	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
-	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
-	unsigned char	bi_enetaddr[6];
-	unsigned int	bi_baudrate;
-} bd_t;
-
-extern bd_t m8xx_board_info;
 
 /* Memory map is configured by the PROM startup.
  * All we need to get started is the IMMR.
Index: arch/ppc/platforms/ccm.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/ccm.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/ccm.h  (mode:100644)
@@ -9,8 +9,6 @@
 
 #include <linux/config.h>
 
-#include <asm/ppcboot.h>
-
 #define	CCM_IMMR_BASE    0xF0000000	/* phys. addr of IMMR			*/
 #define	CCM_IMAP_SIZE   (64 * 1024)	/* size of mapped area			*/
 
Index: arch/ppc/platforms/cpci690.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/cpci690.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/cpci690.h  (mode:100644)
@@ -19,16 +19,6 @@
 #ifndef __PPC_PLATFORMS_CPCI690_H
 #define __PPC_PLATFORMS_CPCI690_H
 
-/*
- * Define bd_t to pass in the MAC addresses used by the GT64260's enet ctlrs.
- */
-#define	CPCI690_BI_MAGIC		0xFE8765DC
-
-typedef struct board_info {
-	u32	bi_magic;
-	u8	bi_enetaddr[3][6];
-} bd_t;
-
 /* PCI bus Resource setup */
 #define CPCI690_PCI0_MEM_START_PROC_ADDR	0x80000000
 #define CPCI690_PCI0_MEM_START_PCI_HI_ADDR	0x00000000
Index: arch/ppc/platforms/est8260.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/est8260.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/est8260.h  (mode:100644)
@@ -14,22 +14,4 @@
 #define CPUINFO_VENDOR		"EST Corporation"
 #define CPUINFO_MACHINE		"SBC8260 PowerPC"
 
-/* A Board Information structure that is given to a program when
- * prom starts it up.
- */
-typedef struct bd_info {
-	unsigned int	bi_memstart;	/* Memory start address */
-	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
-	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
-	unsigned int	bi_busfreq;	/* Bus Freq, in MHz */
-	unsigned int	bi_cpmfreq;	/* CPM Freq, in MHz */
-	unsigned int	bi_brgfreq;	/* BRG Freq, in MHz */
-	unsigned int	bi_vco;		/* VCO Out from PLL */
-	unsigned int	bi_baudrate;	/* Default console baud rate */
-	unsigned int	bi_immr;	/* IMMR when called from boot rom */
-	unsigned char	bi_enetaddr[6];
-} bd_t;
-
-extern bd_t m8xx_board_info;
-
 #endif 	/* __EST8260_PLATFORM */
Index: arch/ppc/platforms/fads.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/fads.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/fads.h  (mode:100644)
@@ -10,8 +10,6 @@
 
 #include <linux/config.h>
 
-#include <asm/ppcboot.h>
-
 /* Memory map is configured by the PROM startup.
  * I tried to follow the FADS manual, although the startup PROM
  * dictates this and we simply have to move some of the physical
Index: arch/ppc/platforms/hdpu.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/hdpu.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/hdpu.c  (mode:100644)
@@ -31,7 +31,8 @@
 #include <asm/machdep.h>
 #include <asm/todc.h>
 #include <asm/mv64x60.h>
-#include <asm/ppcboot.h>
+#include <asm/firmware.h>
+
 #include <platforms/hdpu.h>
 #include <linux/mv643xx.h>
 #include <linux/hdpu_features.h>
@@ -41,7 +42,6 @@
 #define BOARD_VENDOR	"Sky Computers"
 #define BOARD_MACHINE	"HDPU-CB-A"
 
-bd_t ppcboot_bd;
 int ppcboot_bd_valid = 0;
 
 static mv64x60_handle_t bh;
@@ -337,7 +337,7 @@
 
 	pdata->max_idle = 40;
 	if (ppcboot_bd_valid)
-		pdata->default_baud = ppcboot_bd.bi_baudrate;
+		pdata->default_baud = fw_get_baudrate();
 	else
 		pdata->default_baud = HDPU_DEFAULT_BAUD;
 	pdata->brg_clk_src = HDPU_MPSC_CLK_SRC;
@@ -550,7 +550,7 @@
 	ulong freq;
 
 	if (ppcboot_bd_valid)
-		freq = ppcboot_bd.bi_busfreq / 4;
+		freq = fw_get_busfreq() / 4;
 	else
 		freq = 133000000;
 
@@ -567,7 +567,6 @@
 			   unsigned long r4, unsigned long r5,
 			   unsigned long r6, unsigned long r7)
 {
-	bd_t *bd = NULL;
 	char *cmdline_start = NULL;
 	int cmdline_len = 0;
 
@@ -575,9 +574,7 @@
 		if ((r3 & 0xf0000000) == 0)
 			r3 += KERNELBASE;
 		if ((r3 & 0xf0000000) == KERNELBASE) {
-			bd = (void *)r3;
-
-			memcpy(&ppcboot_bd, bd, sizeof(ppcboot_bd));
+			fw_initialize(r3);
 			ppcboot_bd_valid = 1;
 		}
 	}
Index: arch/ppc/platforms/hermes.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/hermes.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/hermes.h  (mode:100644)
@@ -9,8 +9,6 @@
 
 #include <linux/config.h>
 
-#include <asm/ppcboot.h>
-
 #define	HERMES_IMMR_BASE    0xFF000000	/* phys. addr of IMMR			*/
 #define	HERMES_IMAP_SIZE   (64 * 1024)	/* size of mapped area			*/
 
Index: arch/ppc/platforms/ip860.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/ip860.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/ip860.h  (mode:100644)
@@ -9,8 +9,6 @@
 
 #include <linux/config.h>
 
-#include <asm/ppcboot.h>
-
 #define	IP860_IMMR_BASE	0xF1000000	/* phys. addr of IMMR			*/
 #define	IP860_IMAP_SIZE	(64 * 1024)	/* size of mapped area			*/
 
Index: arch/ppc/platforms/ivms8.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/ivms8.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/ivms8.h  (mode:100644)
@@ -15,8 +15,6 @@
 
 #include <linux/config.h>
 
-#include <asm/ppcboot.h>
-
 #define IVMS_IMMR_BASE	0xFFF00000	/* phys. addr of IMMR */
 #define IVMS_IMAP_SIZE	(64 * 1024)	/* size of mapped area */
 
Index: arch/ppc/platforms/katana.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/katana.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/katana.c  (mode:100644)
@@ -38,8 +38,9 @@
 #include <asm/smp.h>
 #include <asm/todc.h>
 #include <asm/bootinfo.h>
-#include <asm/ppcboot.h>
 #include <asm/mv64x60.h>
+#include <asm/firmware.h>
+
 #include <platforms/katana.h>
 
 static struct		mv64x60_handle bh;
@@ -52,7 +53,6 @@
 
 static u32		katana_bus_frequency;
 
-unsigned char	__res[sizeof(bd_t)];
 
 /* PCI Interrupt routing */
 static int __init
@@ -763,7 +763,7 @@
 	 */
 	if (r3 && r6) {
 		/* copy board info structure */
-		memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+		fw_initialize(r3);
 		/* copy command line */
 		*(char *)(r7+KERNELBASE) = 0;
 		strcpy(cmd_line, (char *)(r6+KERNELBASE));
Index: arch/ppc/platforms/lantec.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/lantec.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/lantec.h  (mode:100644)
@@ -9,8 +9,6 @@
 
 #include <linux/config.h>
 
-#include <asm/ppcboot.h>
-
 #define	IMAP_ADDR	0xFFF00000	/* physical base address of IMMR area	*/
 #define IMAP_SIZE	(64 * 1024)	/* mapped size of IMMR area		*/
 
Index: arch/ppc/platforms/lite5200.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/lite5200.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/lite5200.c  (mode:100644)
@@ -35,16 +35,13 @@
 #include <asm/io.h>
 #include <asm/mpc52xx.h>
 #include <asm/ppc_sys.h>
+#include <asm/firmware.h>
 
 #include <syslib/mpc52xx_pci.h>
 
 
 extern int powersave_nap;
 
-/* Board data given by U-Boot */
-bd_t __res;
-EXPORT_SYMBOL(__res);	/* For modules */
-
 
 /* ======================================================================== */
 /* Platform specific code                                                   */
@@ -168,10 +165,8 @@
 	if (bootinfo)
 		parse_bootinfo(bootinfo);
 	else {
-		/* Load the bd_t board info structure */
 		if (r3)
-			memcpy((void*)&__res,(void*)(r3+KERNELBASE),
-					sizeof(bd_t));
+			fw_initialize(r3);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 		/* Load the initrd */
Index: arch/ppc/platforms/lwmon.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/lwmon.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/lwmon.h  (mode:100644)
@@ -9,8 +9,6 @@
 
 #include <linux/config.h>
 
-#include <asm/ppcboot.h>
-
 #define	IMAP_ADDR	0xFFF00000	/* physical base address of IMMR area	*/
 #define IMAP_SIZE	(64 * 1024)	/* mapped size of IMMR area		*/
 
Index: arch/ppc/platforms/mbx.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/mbx.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/mbx.h  (mode:100644)
@@ -12,28 +12,6 @@
 #define __MACH_MBX_DEFS
 
 #ifndef __ASSEMBLY__
-/* A Board Information structure that is given to a program when
- * EPPC-Bug starts it up.
- */
-typedef struct bd_info {
-	unsigned int	bi_tag;		/* Should be 0x42444944 "BDID" */
-	unsigned int	bi_size;	/* Size of this structure */
-	unsigned int	bi_revision;	/* revision of this structure */
-	unsigned int	bi_bdate;	/* EPPCbug date, i.e. 0x11061997 */
-	unsigned int	bi_memstart;	/* Memory start address */
-	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
-	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
-	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
-	unsigned int	bi_clun;	/* Boot device controller */
-	unsigned int	bi_dlun;	/* Boot device logical dev */
-
-	/* These fields are not part of the board information structure
-	 * provided by the boot rom.  They are filled in by embed_config.c
-	 * so we have the information consistent with other platforms.
-	 */
-	unsigned char	bi_enetaddr[6];
-	unsigned int	bi_baudrate;
-} bd_t;
 
 /* Memory map for the MBX as configured by EPPC-Bug.  We could reprogram
  * The SIU and PCI bridge, and try to use larger MMU pages, but the
Index: arch/ppc/platforms/pcu_e.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/pcu_e.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/pcu_e.h  (mode:100644)
@@ -9,8 +9,6 @@
 
 #include <linux/config.h>
 
-#include <asm/ppcboot.h>
-
 #define	PCU_E_IMMR_BASE    0xFE000000	/* phys. addr of IMMR			*/
 #define	PCU_E_IMAP_SIZE   (64 * 1024)	/* size of mapped area			*/
 
Index: arch/ppc/platforms/pq2ads.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/pq2ads.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/pq2ads.c  (mode:100644)
@@ -14,6 +14,7 @@
  * option) any later version.
  */
 
+#include <linux/types.h>
 #include <linux/init.h>
 
 #include <asm/mpc8260.h>
Index: arch/ppc/platforms/pq2ads.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/pq2ads.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/pq2ads.h  (mode:100644)
@@ -11,8 +11,6 @@
 
 #include <linux/config.h>
 
-#include <asm/ppcboot.h>
-
 /* Memory map is configured by the PROM startup.
  * We just map a few things we need.  The CSR is actually 4 byte-wide
  * registers that can be accessed as 8-, 16-, or 32-bit values.
Index: arch/ppc/platforms/radstone_ppc7d.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/radstone_ppc7d.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/radstone_ppc7d.c  (mode:100644)
@@ -60,6 +60,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/mv64x60.h>
 #include <asm/i8259.h>
+#include <asm/firmware.h>
 
 #include "radstone_ppc7d.h"
 
@@ -81,8 +82,6 @@
 #define DS1337_GET_DATE         0
 #define DS1337_SET_DATE         1
 
-/* residual data */
-unsigned char __res[sizeof(bd_t)];
 
 /*****************************************************************************
  * Serial port code
@@ -128,10 +127,10 @@
 
 static unsigned long __init ppc7d_find_end_of_memory(void)
 {
-	bd_t *bp = (bd_t *) __res;
+	unsigned long memsize = fw_get_memory_size();
 
-	if (bp->bi_memsize)
-		return bp->bi_memsize;
+	if (memsize)
+		return memsize;
 
 	return (256 * 1024 * 1024);
 }
@@ -1386,25 +1385,30 @@
 	 * which uses birecs.
 	 */
 	if (r3 && r6) {
-		bd_t *bp = (bd_t *) __res;
+		char *p_addr;
 
 		/* copy board info structure */
-		memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+		fw_initialize(r3);
+
 		/* copy command line */
 		*(char *)(r7 + KERNELBASE) = 0;
 		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
 
 		printk(KERN_INFO "Board info data:-\n");
 		printk(KERN_INFO "  Internal freq: %lu MHz, bus freq: %lu MHz\n",
-		       bp->bi_intfreq, bp->bi_busfreq);
-		printk(KERN_INFO "  Memory: %lx, size %lx\n", bp->bi_memstart,
-		       bp->bi_memsize);
-		printk(KERN_INFO "  Console baudrate: %lu\n", bp->bi_baudrate);
+		       fw_get_intfreq(),
+		       fw_get_busfreq());
+		printk(KERN_INFO "  Memory: %lx, size %lx\n",
+		       fw_get_memory_start(),
+		       fw_get_memory_size());
+		printk(KERN_INFO "  Console baudrate: %lu\n",
+		       fw_get_baudrate());
+		p_addr = fw_get_enetaddr(0);
 		printk(KERN_INFO "  Ethernet address: "
 		       "%02x:%02x:%02x:%02x:%02x:%02x\n",
-		       bp->bi_enetaddr[0], bp->bi_enetaddr[1],
-		       bp->bi_enetaddr[2], bp->bi_enetaddr[3],
-		       bp->bi_enetaddr[4], bp->bi_enetaddr[5]);
+		       p_addr[0], p_addr[1],
+		       p_addr[2], p_addr[3],
+		       p_addr[4], p_addr[5]);
 	}
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* take care of initrd if we have one */
Index: arch/ppc/platforms/radstone_ppc7d.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/radstone_ppc7d.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/radstone_ppc7d.h  (mode:100644)
@@ -35,8 +35,6 @@
 #ifndef __PPC_PLATFORMS_PPC7D_H
 #define __PPC_PLATFORMS_PPC7D_H
 
-#include <asm/ppcboot.h>
-
 /*****************************************************************************
  * CPU Physical Memory Map setup.
  *****************************************************************************/
Index: arch/ppc/platforms/rpx8260.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/rpx8260.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/rpx8260.h  (mode:100644)
@@ -9,25 +9,6 @@
 #ifndef __ASM_PLATFORMS_RPX8260_H__
 #define __ASM_PLATFORMS_RPX8260_H__
 
-/* A Board Information structure that is given to a program when
- * prom starts it up.
- */
-typedef struct bd_info {
-	unsigned int	bi_memstart;	/* Memory start address */
-	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
-	unsigned int	bi_nvsize;	/* NVRAM size in bytes (can be 0) */
-	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
-	unsigned int	bi_busfreq;	/* Bus Freq, in MHz */
-	unsigned int	bi_cpmfreq;	/* CPM Freq, in MHz */
-	unsigned int	bi_brgfreq;	/* BRG Freq, in MHz */
-	unsigned int	bi_vco;		/* VCO Out from PLL */
-	unsigned int	bi_baudrate;	/* Default console baud rate */
-	unsigned int	bi_immr;	/* IMMR when called from boot rom */
-	unsigned char	bi_enetaddr[6];
-} bd_t;
-
-extern bd_t m8xx_board_info;
-
 /* Memory map is configured by the PROM startup.
  * We just map a few things we need.  The CSR is actually 4 byte-wide
  * registers that can be accessed as 8-, 16-, or 32-bit values.
Index: arch/ppc/platforms/rpxclassic.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/rpxclassic.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/rpxclassic.h  (mode:100644)
@@ -11,19 +11,6 @@
 #include <linux/config.h>
 
 #ifndef __ASSEMBLY__
-/* A Board Information structure that is given to a program when
- * prom starts it up.
- */
-typedef struct bd_info {
-	unsigned int	bi_memstart;	/* Memory start address */
-	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
-	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
-	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
-	unsigned char	bi_enetaddr[6];
-	unsigned int	bi_baudrate;
-} bd_t;
-
-extern bd_t m8xx_board_info;
 
 /* Memory map is configured by the PROM startup.
  * We just map a few things we need.  The CSR is actually 4 byte-wide
Index: arch/ppc/platforms/rpxlite.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/rpxlite.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/rpxlite.h  (mode:100644)
@@ -11,19 +11,6 @@
 #include <linux/config.h>
 
 #ifndef __ASSEMBLY__
-/* A Board Information structure that is given to a program when
- * prom starts it up.
- */
-typedef struct bd_info {
-	unsigned int	bi_memstart;	/* Memory start address */
-	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
-	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
-	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
-	unsigned char	bi_enetaddr[6];
-	unsigned int	bi_baudrate;
-} bd_t;
-
-extern bd_t m8xx_board_info;
 
 /* Memory map is configured by the PROM startup.
  * We just map a few things we need.  The CSR is actually 4 byte-wide
Index: arch/ppc/platforms/sandpoint.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/sandpoint.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/sandpoint.c  (mode:100644)
@@ -99,14 +99,13 @@
 #include <asm/mpc10x.h>
 #include <asm/pci-bridge.h>
 #include <asm/kgdb.h>
+#include <asm/firmware.h>
 
 #include "sandpoint.h"
 
 /* Set non-zero if an X2 Sandpoint detected. */
 static int sandpoint_is_x2;
 
-unsigned char __res[sizeof(bd_t)];
-
 static void sandpoint_halt(void);
 static void sandpoint_probe_type(void);
 
@@ -497,10 +496,10 @@
 static unsigned long __init
 sandpoint_find_end_of_memory(void)
 {
-	bd_t *bp = (bd_t *)__res;
+	unsigned long memsize = fw_get_memory_size();
 
-	if (bp->bi_memsize)
-		return bp->bi_memsize;
+	if (memsize)
+		return memsize;
 
 	/* DINK32 13.0 correctly initalizes things, so iff you use
 	 * this you _should_ be able to change this instead of a
@@ -681,7 +680,7 @@
 	 */
 	if (r3 && r6) {
 		/* copy board info structure */
-		memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+		fw_initialize(r3);
 		/* copy command line */
 		*(char *)(r7+KERNELBASE) = 0;
 		strcpy(cmd_line, (char *)(r6+KERNELBASE));
Index: arch/ppc/platforms/sandpoint.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/sandpoint.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/sandpoint.h  (mode:100644)
@@ -19,8 +19,6 @@
 #ifndef __PPC_PLATFORMS_SANDPOINT_H
 #define __PPC_PLATFORMS_SANDPOINT_H
 
-#include <asm/ppcboot.h>
-
 #if 0
 /* The Sandpoint X3 allows the IDE interrupt to be directly connected
  * from the Windbond (PCI INTC or INTD) to the serial EPIC.  Someday
Index: arch/ppc/platforms/sbc82xx.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/sbc82xx.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/sbc82xx.c  (mode:100644)
@@ -28,11 +28,10 @@
 #include <asm/todc.h>
 #include <asm/immap_cpm2.h>
 #include <asm/pci.h>
+#include <asm/firmware.h>
 
 static void (*callback_init_IRQ)(void);
 
-extern unsigned char __res[sizeof(bd_t)];
-
 extern void (*late_time_init)(void);
 
 #ifdef CONFIG_GEN_RTC
@@ -241,7 +240,8 @@
 {
 	/* u-boot may be using one of the FCC Ethernet devices.
 	   Use the MAC address to the SCC. */
-	__res[offsetof(bd_t, bi_enetaddr[5])] &= ~3;
+	unsigned char *p_addr = fw_get_enetaddr(0);
+	p_addr[5] &= ~3;
 
 	/* Anything special for this platform */
 	callback_init_IRQ	= ppc_md.init_IRQ;
Index: arch/ppc/platforms/sbc82xx.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/sbc82xx.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/sbc82xx.h  (mode:100644)
@@ -7,8 +7,6 @@
 #ifndef __PPC_SBC82xx_H__
 #define __PPC_SBC82xx_H__
 
-#include <asm/ppcboot.h>
-
 #define CPM_MAP_ADDR			0xf0000000
 
 #define SBC82xx_TODC_NVRAM_ADDR		0xd0000000
Index: arch/ppc/platforms/sbs8260.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/sbs8260.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/sbs8260.h  (mode:100644)
@@ -7,22 +7,4 @@
 
 #define CPM_MAP_ADDR	((uint)0xfe000000)
 
-
-/* A Board Information structure that is given to a program when
- * prom starts it up.
- */
-typedef struct bd_info {
-	unsigned int	bi_memstart;	/* Memory start address */
-	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
-	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
-	unsigned int	bi_busfreq;	/* Bus Freq, in MHz */
-	unsigned int	bi_cpmfreq;	/* CPM Freq, in MHz */
-	unsigned int	bi_brgfreq;	/* BRG Freq, in MHz */
-	unsigned int	bi_vco;		/* VCO Out from PLL */
-	unsigned int	bi_baudrate;	/* Default console baud rate */
-	unsigned int	bi_immr;	/* IMMR when called from boot rom */
-	unsigned char	bi_enetaddr[6];
-} bd_t;
-
-extern bd_t m8xx_board_info;
 #endif /* !__ASSEMBLY__ */
Index: arch/ppc/platforms/spd8xx.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/spd8xx.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/spd8xx.h  (mode:100644)
@@ -10,8 +10,6 @@
 
 #include <linux/config.h>
 
-#include <asm/ppcboot.h>
-
 #ifndef __ASSEMBLY__
 #define SPD_IMMR_BASE	0xFFF00000	/* phys. addr of IMMR */
 #define SPD_IMAP_SIZE	(64 * 1024)	/* size of mapped area */
Index: arch/ppc/platforms/tqm8260.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/tqm8260.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/tqm8260.h  (mode:100644)
@@ -9,8 +9,6 @@
 
 #include <linux/config.h>
 
-#include <asm/ppcboot.h>
-
 #define CPM_MAP_ADDR		((uint)0xFFF00000)
 #define PHY_INTERRUPT		25
 
Index: arch/ppc/platforms/tqm8260_setup.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/tqm8260_setup.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/tqm8260_setup.c  (mode:100644)
@@ -14,6 +14,7 @@
  * option) any later version.
  */
 
+#include <linux/types.h>
 #include <linux/init.h>
 
 #include <asm/immap_cpm2.h>
Index: arch/ppc/platforms/tqm8xx.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/platforms/tqm8xx.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/platforms/tqm8xx.h  (mode:100644)
@@ -10,8 +10,6 @@
 
 #include <linux/config.h>
 
-#include <asm/ppcboot.h>
-
 #ifndef __ASSEMBLY__
 #define	TQM_IMMR_BASE	0xFFF00000	/* phys. addr of IMMR */
 #define	TQM_IMAP_SIZE	(64 * 1024)	/* size of mapped area */

^ permalink raw reply

* bd_t Cleaning: Driver Bits
From: Jon Loeliger @ 2005-05-27 19:18 UTC (permalink / raw)
  To: linuxppc-embedded@ozlabs.org
In-Reply-To: <f003613a0526b7b6a00a0bd477cd5ac3@freescale.com>

On Thu, 2005-05-26 at 18:08, Kumar Gala wrote:
> Jon,
> 
> Can you break the patch up into a few pieces, it will be easier to 
> review that way.  Here are the following pieces that make sense to me:
> 
> 0. New firmware interface (fw_bdt*, Kconfig, ...)
> 1. board code changes (everything in arch/ppc/platforms/*)
> 2. driver changes (things in *_io, ide, net, serial dirs -- try to give 
> a better list below)
> 3. System changes (files in arch/ppc/syslib and include/asm-ppc)

And Part 3 of 4 is the Driver Bits:


 ppc/8260_io/enet.c                      |    9 
 ppc/8260_io/fcc_enet.c                  |   15 
 ppc/8xx_io/commproc.c                   |    3 
 ppc/8xx_io/enet.c                       |   10 
 ppc/8xx_io/fec.c                        |    8 
 ide/ppc/mpc8xx.c                        |   14 
 mtd/maps/tqm8xxl.c                      |    7 
 net/fec.c                               |    6 
 net/fec_8xx/fec_8xx-netta.c             |    5 
 net/oaknet.c                            |    6 
 serial/68360serial.c                    |    3 
 serial/cpm_uart/cpm_uart_core.c         |    8 
 serial/cpm_uart/cpm_uart_cpm1.c         |   13 
 serial/cpm_uart/cpm_uart_cpm2.c         |   13 
 serial/mpc52xx_uart.c                   |   11 

Index: arch/ppc/8260_io/enet.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/8260_io/enet.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/8260_io/enet.c  (mode:100644)
@@ -47,6 +47,7 @@
 #include <asm/uaccess.h>
 #include <asm/cpm2.h>
 #include <asm/irq.h>
+#include <asm/firmware.h>
 
 /*
  *				Theory of Operation
@@ -614,9 +615,8 @@
 	struct scc_enet_private *cep;
 	int i, j, err;
 	uint dp_offset;
-	unsigned char	*eap;
+	unsigned char	*eap, *p_addr;
 	unsigned long	mem_addr;
-	bd_t		*bd;
 	volatile	cbd_t		*bdp;
 	volatile	cpm_cpm2_t	*cp;
 	volatile	scc_t		*sccp;
@@ -629,8 +629,6 @@
 	immap = (cpm2_map_t *)CPM_MAP_ADDR;	/* and to internal registers */
 	io = &immap->im_ioport;
 
-	bd = (bd_t *)__res;
-
 	/* Create an Ethernet device instance.
 	*/
 	dev = alloc_etherdev(sizeof(*cep));
@@ -735,9 +733,10 @@
 	 * This is supplied in the board information structure, so we
 	 * copy that into the controller.
 	 */
+	p_addr = fw_get_enetaddr(0);
 	eap = (unsigned char *)&(ep->sen_paddrh);
 	for (i=5; i>=0; i--)
-		*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+		*eap++ = dev->dev_addr[i] = p_addr[i];
 
 	ep->sen_pper = 0;	/* 'cause the book says so */
 	ep->sen_taddrl = 0;	/* temp address (LSB) */
Index: arch/ppc/8260_io/fcc_enet.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/8260_io/fcc_enet.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/8260_io/fcc_enet.c  (mode:100644)
@@ -47,6 +47,7 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/signal.h>
+#include <asm/firmware.h>
 
 /* We can't use the PHY interrupt if we aren't using MDIO. */
 #if !defined(CONFIG_USE_MDIO)
@@ -1866,9 +1867,8 @@
 init_fcc_param(fcc_info_t *fip, struct net_device *dev,
 						volatile cpm2_map_t *immap)
 {
-	unsigned char	*eap;
+	unsigned char	*eap, *p_addr;
 	unsigned long	mem_addr;
-	bd_t		*bd;
 	int		i, j;
 	struct		fcc_enet_private *cep;
 	volatile	fcc_enet_t	*ep;
@@ -1879,8 +1879,6 @@
 	ep = cep->ep;
 	cp = cpmp;
 
-	bd = (bd_t *)__res;
-
 	/* Zero the whole thing.....I must have missed some individually.
 	 * It works when I do this.
 	 */
@@ -1962,6 +1960,7 @@
 	 * it unique by setting a few bits in the upper byte of the
 	 * non-static part of the address.
 	 */
+	p_addr = fw_get_enetaddr(0);
 	eap = (unsigned char *)&(ep->fen_paddrh);
 	for (i=5; i>=0; i--) {
 
@@ -1971,22 +1970,22 @@
  */
 #ifdef CONFIG_SBC82xx
 		if (i == 5) {
-			/* bd->bi_enetaddr holds the SCC0 address; the FCC
+			/* p_addr holds the SCC0 address; the FCC
 			   devices count up from there */
-			dev->dev_addr[i] = bd->bi_enetaddr[i] & ~3;
+			dev->dev_addr[i] = p_addr[i] & ~3;
 			dev->dev_addr[i] += 1 + fip->fc_fccnum;
 			*eap++ = dev->dev_addr[i];
 		}
 #else
 #ifndef CONFIG_RPX8260
 		if (i == 3) {
-			dev->dev_addr[i] = bd->bi_enetaddr[i];
+			dev->dev_addr[i] = p_addr[i];
 			dev->dev_addr[i] |= (1 << (7 - fip->fc_fccnum));
 			*eap++ = dev->dev_addr[i];
 		} else
 #endif
 		{
-			*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+			*eap++ = dev->dev_addr[i] = p_addr[i];
 		}
 #endif
 	}
Index: arch/ppc/8xx_io/commproc.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/8xx_io/commproc.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/8xx_io/commproc.c  (mode:100644)
@@ -38,6 +38,7 @@
 #include <asm/io.h>
 #include <asm/tlbflush.h>
 #include <asm/rheap.h>
+#include <asm/firmware.h>
 
 extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
 
@@ -346,7 +347,7 @@
  * The internal baud rate clock is the system clock divided by 16.
  * This assumes the baudrate is 16x oversampled by the uart.
  */
-#define BRG_INT_CLK		(((bd_t *)__res)->bi_intfreq)
+#define BRG_INT_CLK		(fw_get_intfreq())
 #define BRG_UART_CLK		(BRG_INT_CLK/16)
 #define BRG_UART_CLK_DIV16	(BRG_UART_CLK/16)
 
Index: arch/ppc/8xx_io/enet.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/8xx_io/enet.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/8xx_io/enet.c  (mode:100644)
@@ -46,6 +46,8 @@
 #include <asm/mpc8xx.h>
 #include <asm/uaccess.h>
 #include <asm/commproc.h>
+#include <asm/firmware.h>
+
 
 /*
  *				Theory of Operation
@@ -646,9 +648,8 @@
 	struct scc_enet_private *cep;
 	int i, j, k, err;
 	uint dp_offset;
-	unsigned char	*eap, *ba;
+	unsigned char	*eap, *ba, *p_addr;
 	dma_addr_t	mem_addr;
-	bd_t		*bd;
 	volatile	cbd_t		*bdp;
 	volatile	cpm8xx_t	*cp;
 	volatile	scc_t		*sccp;
@@ -659,8 +660,6 @@
 
 	immap = (immap_t *)(mfspr(SPRN_IMMR) & 0xFFFF0000);	/* and to internal registers */
 
-	bd = (bd_t *)__res;
-
 	dev = alloc_etherdev(sizeof(*cep));
 	if (!dev)
 		return -ENOMEM;
@@ -803,9 +802,10 @@
 
 	/* Set Ethernet station address.
 	 */
+	p_addr = fw_get_enetaddr(0);
 	eap = (unsigned char *)&(ep->sen_paddrh);
 	for (i=5; i>=0; i--)
-		*eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+		*eap++ = dev->dev_addr[i] = p_addr[i];
 
 	ep->sen_pper = 0;	/* 'cause the book says so */
 	ep->sen_taddrl = 0;	/* temp address (LSB) */
Index: arch/ppc/8xx_io/fec.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/8xx_io/fec.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/8xx_io/fec.c  (mode:100644)
@@ -55,6 +55,7 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/commproc.h>
+#include <asm/firmware.h>
 
 #ifdef	CONFIG_USE_MDIO
 /* Forward declarations of some structures to support different PHYs
@@ -1580,15 +1581,12 @@
 	cbd_t		*cbd_base;
 	volatile	immap_t	*immap;
 	volatile	fec_t	*fecp;
-	bd_t		*bd;
 #ifdef CONFIG_SCC_ENET
 	unsigned char	tmpaddr[6];
 #endif
 
 	immap = (immap_t *)IMAP_ADDR;	/* pointer to internal registers */
 
-	bd = (bd_t *)__res;
-
 	dev = alloc_etherdev(sizeof(*fep));
 	if (!dev)
 		return -ENOMEM;
@@ -1613,7 +1611,7 @@
 	 * this needs some work to get unique addresses.
 	 */
 	eap = (unsigned char *)my_enet_addr;
-	iap = bd->bi_enetaddr;
+	iap = fw_get_enetaddr(0);
 
 #ifdef CONFIG_SCC_ENET
 	/*
@@ -1744,7 +1742,7 @@
 	/* Set MII speed to 2.5 MHz
 	*/
 	fecp->fec_mii_speed = fep->phy_speed =
-		(( (bd->bi_intfreq + 500000) / 2500000 / 2 ) & 0x3F ) << 1;
+		(( (fw_get_intfreq() + 500000) / 2500000 / 2 ) & 0x3F ) << 1;
 #else
 	fecp->fec_mii_speed = 0;	/* turn off MDIO */
 #endif	/* CONFIG_USE_MDIO */
Index: drivers/ide/ppc/mpc8xx.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/drivers/ide/ppc/mpc8xx.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/drivers/ide/ppc/mpc8xx.c  (mode:100644)
@@ -41,6 +41,7 @@
 #include <asm/8xx_immap.h>
 #include <asm/machdep.h>
 #include <asm/irq.h>
+#include <asm/firmware.h>
 
 static int identify  (volatile u8 *p);
 static void print_fixed (volatile u8 *p);
@@ -177,6 +178,7 @@
 	u32 pcmcia_phy_end;
 	static unsigned long pcmcia_base = 0;
 	unsigned long base;
+	unsigned int busfreq;
 
 	*p = 0;
 	if (irq)
@@ -224,21 +226,19 @@
 		printk ("PCMCIA virt base: %08lx\n", pcmcia_base);
 #endif
 		/* Compute clock cycles for PIO timings */
+		busfreq = fw_get_busfreq();
 		for (i=0; i<6; ++i) {
-			bd_t	*binfo = (bd_t *)__res;
-
 			hold_time[i]   =
-				PCMCIA_MK_CLKS (hold_time[i],
-						binfo->bi_busfreq);
+				PCMCIA_MK_CLKS (hold_time[i], busfreq);
 			ide_pio_clocks[i].setup_time  =
 				PCMCIA_MK_CLKS (ide_pio_timings[i].setup_time,
-						binfo->bi_busfreq);
+						busfreq);
 			ide_pio_clocks[i].active_time =
 				PCMCIA_MK_CLKS (ide_pio_timings[i].active_time,
-						binfo->bi_busfreq);
+						busfreq);
 			ide_pio_clocks[i].cycle_time  =
 				PCMCIA_MK_CLKS (ide_pio_timings[i].cycle_time,
-						binfo->bi_busfreq);
+						busfreq);
 #if 0
 			printk ("PIO mode %d timings: %d/%d/%d => %d/%d/%d\n",
 				i,
Index: drivers/mtd/maps/tqm8xxl.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/drivers/mtd/maps/tqm8xxl.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/drivers/mtd/maps/tqm8xxl.c  (mode:100644)
@@ -33,6 +33,8 @@
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 
+#include <asm/firmware.h>
+
 #define FLASH_ADDR 0x40000000
 #define FLASH_SIZE 0x00800000
 #define FLASH_BANK_MAX 4
@@ -115,10 +117,9 @@
 	int idx = 0, ret = 0;
 	unsigned long flash_addr, flash_size, mtd_size = 0;
 	/* pointer to TQM8xxL board info data */
-	bd_t *bd = (bd_t *)__res;
 
-	flash_addr = bd->bi_flashstart;
-	flash_size = bd->bi_flashsize;
+	flash_addr = fw_get_flashstart();
+	flash_size = fw_get_flashsize();
 
 	//request maximum flash size address space
 	start_scan_addr = ioremap(flash_addr, flash_size);
Index: drivers/net/fec.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/drivers/net/fec.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/drivers/net/fec.c  (mode:100644)
@@ -1426,11 +1426,9 @@
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 	unsigned char *iap, tmpaddr[6];
-	bd_t *bd;
 	int i;
 
-	iap = bd->bi_enetaddr;
-	bd = (bd_t *)__res;
+	iap = fw_get_enetaddr(0);
 
 #ifdef CONFIG_RPXCLASSIC
 	/* The Embedded Planet boards have only one MAC address in
@@ -1472,7 +1470,7 @@
 	/* Set MII speed to 2.5 MHz
 	*/
 	fecp->fec_mii_speed = fep->phy_speed = 
-		((bd->bi_busfreq * 1000000) / 2500000) & 0x7e;
+		((fw_get_busfreq() * 1000000) / 2500000) & 0x7e;
 }
 
 static void __inline__ fec_enable_phy_intr(void)
Index: drivers/net/fec_8xx/fec_8xx-netta.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/drivers/net/fec_8xx/fec_8xx-netta.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/drivers/net/fec_8xx/fec_8xx-netta.c  (mode:100644)
@@ -29,6 +29,7 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/commproc.h>
+#include <asm/firmware.h>
 
 #include "fec_8xx.h"
 
@@ -76,7 +77,6 @@
 int fec_8xx_platform_init(void)
 {
 	immap_t *immap = (immap_t *)IMAP_ADDR;
-	bd_t *bd = (bd_t *) __res;
 	const char *s;
 	char *e;
 	int i;
@@ -116,8 +116,7 @@
 	setbits16(immap->im_ioport.iop_pcint, 0x0200);
 
 	/* fill up */
-	fec1_info.sys_clk = bd->bi_intfreq;
-	fec2_info.sys_clk = bd->bi_intfreq;
+	fec1_info.sys_clk = fec2_info.sys_clk = fw_get_intfreq();
 
 	s = __fw_getenv("ethaddr");
 	if (s != NULL) {
Index: drivers/net/oaknet.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/drivers/net/oaknet.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/drivers/net/oaknet.c  (mode:100644)
@@ -23,6 +23,7 @@
 
 #include <asm/board.h>
 #include <asm/io.h>
+#include <asm/firmware.h>
 
 #include "8390.h"
 
@@ -101,7 +102,7 @@
 #else
 	unsigned long ioaddr = ioremap(OAKNET_IO_BASE, OAKNET_IO_SIZE);
 #endif
-	bd_t *bip = (bd_t *)__res;
+	unsigned char *p_addr;
 
 	if (!ioaddr)
 		return -ENOMEM;
@@ -170,9 +171,10 @@
 
 	/* Tell the world about what and where we've found. */
 
+	p_addr = fw_get_enetaddr(0);
 	printk("%s: %s at", dev->name, name);
 	for (i = 0; i < ETHER_ADDR_LEN; ++i) {
-		dev->dev_addr[i] = bip->bi_enetaddr[i];
+		dev->dev_addr[i] = p_addr[i];
 		printk("%c%.2x", (i ? ':' : ' '), dev->dev_addr[i]);
 	}
 	printk(", found at %#lx, using IRQ %d.\n", dev->base_addr, dev->irq);
Index: drivers/serial/68360serial.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/drivers/serial/68360serial.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/drivers/serial/68360serial.c  (mode:100644)
@@ -2852,9 +2852,6 @@
 /* mleslie TODO:
  * add something to the 68k bootloader to store a desired initial console baud rate */
 
-/* 	bd_t						*bd; */ /* a board info struct used by EPPC-bug */
-/* 	bd = (bd_t *)__res; */
-
  	for (bidx = 0; bidx < (sizeof(baud_table) / sizeof(int)); bidx++)
 	 /* if (bd->bi_baudrate == baud_table[bidx]) */
  		if (CONSOLE_BAUDRATE == baud_table[bidx])
Index: drivers/serial/cpm_uart/cpm_uart_core.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/drivers/serial/cpm_uart/cpm_uart_core.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/drivers/serial/cpm_uart/cpm_uart_core.c  (mode:100644)
@@ -44,6 +44,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/delay.h>
+#include <asm/firmware.h>
 
 #if defined(CONFIG_SERIAL_CPM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
@@ -1051,10 +1052,9 @@
 	if (options) {
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
 	} else {
-		bd_t *bd = (bd_t *) __res;
-
-		if (bd->bi_baudrate)
-			baud = bd->bi_baudrate;
+		int rate = fw_get_baudrate();
+		if (rate)
+			baud = rate;
 		else
 			baud = 9600;
 	}
Index: drivers/serial/cpm_uart/cpm_uart_cpm1.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/drivers/serial/cpm_uart/cpm_uart_cpm1.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/drivers/serial/cpm_uart/cpm_uart_cpm1.c  (mode:100644)
@@ -39,6 +39,7 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/firmware.h>
 
 #include <linux/serial_core.h>
 #include <linux/kernel.h>
@@ -215,7 +216,7 @@
 	    (unsigned long)&cpmp->cp_smc[0];
 	cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
 	cpm_uart_ports[UART_SMC1].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-	cpm_uart_ports[UART_SMC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SMC1].port.uartclk = fw_get_intfreq();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
 #endif
 
@@ -227,7 +228,7 @@
 	    (unsigned long)&cpmp->cp_smc[1];
 	cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
 	cpm_uart_ports[UART_SMC2].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-	cpm_uart_ports[UART_SMC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SMC2].port.uartclk = fw_get_intfreq();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
 #endif
 
@@ -241,7 +242,7 @@
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC1].sccp->scc_gsmrl &=
 	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	cpm_uart_ports[UART_SCC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SCC1].port.uartclk = fw_get_intfreq();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
 #endif
 
@@ -255,7 +256,7 @@
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC2].sccp->scc_gsmrl &=
 	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	cpm_uart_ports[UART_SCC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SCC2].port.uartclk = fw_get_intfreq();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
 #endif
 
@@ -269,7 +270,7 @@
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC3].sccp->scc_gsmrl &=
 	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	cpm_uart_ports[UART_SCC3].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SCC3].port.uartclk = fw_get_intfreq();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
 #endif
 
@@ -283,7 +284,7 @@
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC4].sccp->scc_gsmrl &=
 	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	cpm_uart_ports[UART_SCC4].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SCC4].port.uartclk = fw_get_intfreq();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
 #endif
 	return 0;
Index: drivers/serial/cpm_uart/cpm_uart_cpm2.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/drivers/serial/cpm_uart/cpm_uart_cpm2.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/drivers/serial/cpm_uart/cpm_uart_cpm2.c  (mode:100644)
@@ -39,6 +39,7 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/firmware.h>
 
 #include <linux/serial_core.h>
 #include <linux/kernel.h>
@@ -252,7 +253,7 @@
 	    (unsigned long)&cpm2_immr->im_smc[0];
 	cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
 	cpm_uart_ports[UART_SMC1].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-	cpm_uart_ports[UART_SMC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SMC1].port.uartclk = fw_get_intfreq();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
 #endif
 
@@ -264,7 +265,7 @@
 	    (unsigned long)&cpm2_immr->im_smc[1];
 	cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
 	cpm_uart_ports[UART_SMC2].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
-	cpm_uart_ports[UART_SMC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SMC2].port.uartclk = fw_get_intfreq();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
 #endif
 
@@ -278,7 +279,7 @@
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC1].sccp->scc_gsmrl &=
 	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	cpm_uart_ports[UART_SCC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SCC1].port.uartclk = fw_get_intfreq();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
 #endif
 
@@ -292,7 +293,7 @@
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC2].sccp->scc_gsmrl &=
 	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	cpm_uart_ports[UART_SCC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SCC2].port.uartclk = fw_get_intfreq();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
 #endif
 
@@ -306,7 +307,7 @@
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC3].sccp->scc_gsmrl &=
 	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	cpm_uart_ports[UART_SCC3].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SCC3].port.uartclk = fw_get_intfreq();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
 #endif
 
@@ -320,7 +321,7 @@
 	    ~(UART_SCCM_TX | UART_SCCM_RX);
 	cpm_uart_ports[UART_SCC4].sccp->scc_gsmrl &=
 	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
-	cpm_uart_ports[UART_SCC4].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_ports[UART_SCC4].port.uartclk = fw_get_intfreq();
 	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
 #endif
 
Index: drivers/serial/mpc52xx_uart.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/drivers/serial/mpc52xx_uart.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/drivers/serial/mpc52xx_uart.c  (mode:100644)
@@ -54,6 +54,7 @@
 
 #include <asm/delay.h>
 #include <asm/io.h>
+#include <asm/firmware.h>
 
 #include <asm/mpc52xx.h>
 #include <asm/mpc52xx_psc.h>
@@ -572,14 +573,16 @@
 {
 	struct mpc52xx_psc __iomem *psc = PSC(port);
 	unsigned char mr1;
+	unsigned int fw_baud;
 
 	/* Read the mode registers */
 	out_8(&psc->command,MPC52xx_PSC_SEL_MODE_REG_1);
 	mr1 = in_8(&psc->mode);
 	
 	/* CT{U,L}R are write-only ! */
-	*baud = __res.bi_baudrate ?
-		__res.bi_baudrate : CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
+	fw_baud = fw_get_baudrate();
+	*baud = fw_baud ?
+		fw_baud : CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
 
 	/* Parse them */
 	switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) {
@@ -649,7 +652,7 @@
 	/* Basic port init. Needed since we use some uart_??? func before
 	 * real init for early access */
 	spin_lock_init(&port->lock);
-	port->uartclk	= __res.bi_ipbfreq / 2; /* Look at CTLR doc */
+	port->uartclk	= fw_get_ipbfreq() / 2; /* Look at CTLR doc */
 	port->ops	= &mpc52xx_uart_ops;
 	port->mapbase	= MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1));
 
@@ -739,7 +742,7 @@
 	memset(port, 0x00, sizeof(struct uart_port));
 
 	spin_lock_init(&port->lock);
-	port->uartclk	= __res.bi_ipbfreq / 2; /* Look at CTLR doc */
+	port->uartclk	= fw_get_ipbfreq() / 2; /* Look at CTLR doc */
 	port->fifosize	= 255; /* Should be 512 ! But it can't be */
 	                       /* stored in a unsigned char       */
 	port->iotype	= UPIO_MEM;

^ permalink raw reply

* bd_t Cleaning: System Parts
From: Jon Loeliger @ 2005-05-27 19:20 UTC (permalink / raw)
  To: linuxppc-embedded@ozlabs.org
In-Reply-To: <f003613a0526b7b6a00a0bd477cd5ac3@freescale.com>

On Thu, 2005-05-26 at 18:08, Kumar Gala wrote:
> Jon,
> 
> Can you break the patch up into a few pieces, it will be easier to 
> review that way.  Here are the following pieces that make sense to me:
> 
> 0. New firmware interface (fw_bdt*, Kconfig, ...)
> 1. board code changes (everything in arch/ppc/platforms/*)
> 2. driver changes (things in *_io, ide, net, serial dirs -- try to give 
> a better list below)
> 3. System changes (files in arch/ppc/syslib and include/asm-ppc)

And the final quarter, the System Bits:

 ppc/syslib/cpm2_common.c                |    3 
 ppc/syslib/m8260_pci.h                  |    6 
 ppc/syslib/m8260_setup.c                |   31 -
 ppc/syslib/m8xx_setup.c                 |   27 -
 ppc/syslib/m8xx_wdt.c                   |    8 
 ppc/syslib/m8xx_wdt.h                   |    2 
 ppc/syslib/mpc52xx_setup.c              |   15 
 ppc/syslib/ppc4xx_setup.c               |   18 
 ppc/syslib/ppc83xx_setup.c              |   28 -
 ppc/syslib/ppc83xx_setup.h              |    1 
 ppc/syslib/ppc85xx_setup.c              |   56 +-
 ppc/syslib/ppc85xx_setup.h              |    1 
 asm-ppc/bseip.h                         |   13 
 asm-ppc/ibm4xx.h                        |   17 
 asm-ppc/ibm_ocp.h                       |    3 
 asm-ppc/mpc52xx.h                       |    4 
 asm-ppc/mpc8260.h                       |    7 
 asm-ppc/mpc83xx.h                       |    5 
 asm-ppc/mpc85xx.h                       |    5 
 asm-ppc/mpc8xx.h                        |    7 

Index: arch/ppc/syslib/cpm2_common.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/cpm2_common.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/cpm2_common.c  (mode:100644)
@@ -30,6 +30,7 @@
 #include <asm/immap_cpm2.h>
 #include <asm/cpm2.h>
 #include <asm/rheap.h>
+#include <asm/firmware.h>
 
 static void cpm2_dpinit(void);
 cpm_cpm2_t	*cpmp;		/* Pointer to comm processor space */
@@ -67,7 +68,7 @@
  * Baud rate clocks are zero-based in the driver code (as that maps
  * to port numbers).  Documentation uses 1-based numbering.
  */
-#define BRG_INT_CLK	(((bd_t *)__res)->bi_brgfreq)
+#define BRG_INT_CLK	(fw_get_brgfreq())
 #define BRG_UART_CLK	(BRG_INT_CLK/16)
 
 /* This function is used by UARTS, or anything else that uses a 16x
Index: arch/ppc/syslib/m8260_pci.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/m8260_pci.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/m8260_pci.h  (mode:100644)
@@ -26,9 +26,9 @@
  */
 
 #ifndef MPC826x_PCI_SLAVE_MEM_LOCAL
-#define MPC826x_PCI_SLAVE_MEM_LOCAL	(((struct bd_info *)__res)->bi_memstart)
-#define MPC826x_PCI_SLAVE_MEM_BUS	(((struct bd_info *)__res)->bi_memstart)
-#define MPC826x_PCI_SLAVE_MEM_SIZE	(((struct bd_info *)__res)->bi_memsize)
+#define MPC826x_PCI_SLAVE_MEM_LOCAL	(fw_get_memory_start())
+#define MPC826x_PCI_SLAVE_MEM_BUS	(fw_get_memory_start())
+#define MPC826x_PCI_SLAVE_MEM_SIZE	(fw_get_memory_size())
 #endif
 
 /* 
Index: arch/ppc/syslib/m8260_setup.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/m8260_setup.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/m8260_setup.c  (mode:100644)
@@ -28,11 +28,10 @@
 #include <asm/machdep.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
+#include <asm/firmware.h>
 
 #include "cpm2_pic.h"
 
-unsigned char __res[sizeof(bd_t)];
-
 extern void cpm2_reset(void);
 extern void m8260_find_bridges(void);
 extern void idma_pci9_init(void);
@@ -71,10 +70,9 @@
 static void __init
 m8260_calibrate_decr(void)
 {
-	bd_t *binfo = (bd_t *)__res;
 	int freq, divisor;
 
-	freq = binfo->bi_busfreq;
+	freq = fw_get_busfreq();
         divisor = 4;
         tb_ticks_per_jiffy = freq / HZ / divisor;
 	tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
@@ -109,7 +107,7 @@
 static void
 m8260_restart(char *cmd)
 {
-	extern void m8260_gorom(bd_t *bi, uint addr);
+	extern void m8260_gorom(void *bi, uint addr);
 	uint	startaddr;
 
 	/* Most boot roms have a warmstart as the second instruction
@@ -122,7 +120,7 @@
 			startaddr = simple_strtoul(&cmd[10], NULL, 0);
 	}
 
-	m8260_gorom((void*)__pa(__res), startaddr);
+	m8260_gorom((void*)__pa(fw_get_init_data()), startaddr);
 }
 
 static void
@@ -141,9 +139,8 @@
 static int
 m8260_show_cpuinfo(struct seq_file *m)
 {
-	bd_t *bp = (bd_t *)__res;
-
-	seq_printf(m, "vendor\t\t: %s\n"
+	seq_printf(m,
+		   "vendor\t\t: %s\n"
 		   "machine\t\t: %s\n"
 		   "\n"
 		   "mem size\t\t: 0x%08x\n"
@@ -152,9 +149,13 @@
 		   "core clock\t: %u MHz\n"
 		   "CPM  clock\t: %u MHz\n"
 		   "bus  clock\t: %u MHz\n",
-		   CPUINFO_VENDOR, CPUINFO_MACHINE, bp->bi_memsize,
-		   bp->bi_baudrate, bp->bi_intfreq / 1000000,
-		   bp->bi_cpmfreq / 1000000, bp->bi_busfreq / 1000000);
+		   CPUINFO_VENDOR,
+		   CPUINFO_MACHINE,
+		   fw_get_memory_size(),
+		   fw_get_baudrate(),
+		   fw_get_intfreq() / 1000000,
+		   fw_get_cpmfreq() / 1000000,
+		   fw_get_busfreq() / 1000000);
 	return 0;
 }
 
@@ -181,9 +182,7 @@
 static unsigned long __init
 m8260_find_end_of_memory(void)
 {
-	bd_t *binfo = (bd_t *)__res;
-
-	return binfo->bi_memsize;
+	return fw_get_memory_size();
 }
 
 /* Map the IMMR, plus anything else we can cover
@@ -228,7 +227,7 @@
 	parse_bootinfo(find_bootinfo());
 
 	if ( r3 )
-		memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+		fw_initialize(r3);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* take care of initrd if we have one */
Index: arch/ppc/syslib/m8xx_setup.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/m8xx_setup.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/m8xx_setup.c  (mode:100644)
@@ -45,6 +45,7 @@
 #include <asm/bootinfo.h>
 #include <asm/time.h>
 #include <asm/xmon.h>
+#include <asm/firmware.h>
 
 #include "ppc8xx_pic.h"
 
@@ -52,13 +53,11 @@
 static unsigned long m8xx_get_rtc_time(void);
 void m8xx_calibrate_decr(void);
 
-unsigned char __res[sizeof(bd_t)];
-
 extern void m8xx_ide_init(void);
 
 extern unsigned long find_available_memory(void);
 extern void m8xx_cpm_reset(uint cpm_page);
-extern void m8xx_wdt_handler_install(bd_t *bp);
+extern void m8xx_wdt_handler_install(void);
 extern void rpxfb_alloc_pages(void);
 extern void cpm_interrupt_init(void);
 
@@ -144,7 +143,6 @@
  */
 void __init m8xx_calibrate_decr(void)
 {
-	bd_t	*binfo = (bd_t *)__res;
 	int freq, fp, divisor;
 
 	/* Unlock the SCCR. */
@@ -157,7 +155,7 @@
 	/* Processor frequency is MHz.
 	 * The value 'fp' is the number of decrementer ticks per second.
 	 */
-	fp = binfo->bi_intfreq / 16;
+	fp = fw_get_intfreq() / 16;
 	freq = fp*60;	/* try to make freq/1e6 an integer */
         divisor = 60;
         printk("Decrementer Frequency = %d/%d\n", freq, divisor);
@@ -209,7 +207,7 @@
 	/* Install watchdog timer handler early because it might be
 	 * already enabled by the bootloader
 	 */
-	m8xx_wdt_handler_install(binfo);
+	m8xx_wdt_handler_install();
 #endif
 }
 
@@ -266,14 +264,10 @@
 static int
 m8xx_show_percpuinfo(struct seq_file *m, int i)
 {
-	bd_t	*bp;
-
-	bp = (bd_t *)__res;
-
 	seq_printf(m, "clock\t\t: %ldMHz\n"
 		   "bus clock\t: %ldMHz\n",
-		   bp->bi_intfreq / 1000000,
-		   bp->bi_busfreq / 1000000);
+		   fw_get_intfreq() / 1000000,
+		   fw_get_busfreq() / 1000000);
 
 	return 0;
 }
@@ -332,12 +326,7 @@
 static unsigned long __init
 m8xx_find_end_of_memory(void)
 {
-	bd_t	*binfo;
-	extern unsigned char __res[];
-
-	binfo = (bd_t *)__res;
-
-	return binfo->bi_memsize;
+	return fw_get_memory_size();
 }
 
 /*
@@ -387,7 +376,7 @@
 	parse_bootinfo(find_bootinfo());
 
 	if ( r3 )
-		memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+		fw_initialize(r3);
 
 #ifdef CONFIG_PCI
 	m8xx_setup_pci_ptrs();
Index: arch/ppc/syslib/m8xx_wdt.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/m8xx_wdt.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/m8xx_wdt.c  (mode:100644)
@@ -44,7 +44,7 @@
 	return IRQ_HANDLED;
 }
 
-void __init m8xx_wdt_handler_install(bd_t * binfo)
+void __init m8xx_wdt_handler_install(void)
 {
 	volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
 	u32 pitc;
@@ -83,9 +83,9 @@
 		pitrtclk = 8192;
 
 	if ((wdt_timeout) > (UINT_MAX / pitrtclk))
-		pitc = wdt_timeout / binfo->bi_intfreq * pitrtclk / 2;
+		pitc = wdt_timeout / fw_get_intfreq() * pitrtclk / 2;
 	else
-		pitc = pitrtclk * wdt_timeout / binfo->bi_intfreq / 2;
+		pitc = pitrtclk * wdt_timeout / fw_get_intfreq() / 2;
 
 	imap->im_sit.sit_pitc = pitc << 16;
 	imap->im_sit.sit_piscr =
@@ -97,7 +97,7 @@
 	printk(KERN_NOTICE
 	       "m8xx_wdt: keep-alive trigger installed (PITC: 0x%04X)\n", pitc);
 
-	wdt_timeout /= binfo->bi_intfreq;
+	wdt_timeout /= fw_get_intfreq();
 }
 
 int m8xx_wdt_get_timeout(void)
Index: arch/ppc/syslib/m8xx_wdt.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/m8xx_wdt.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/m8xx_wdt.h  (mode:100644)
@@ -9,7 +9,7 @@
 #ifndef _PPC_SYSLIB_M8XX_WDT_H
 #define _PPC_SYSLIB_M8XX_WDT_H
 
-extern void m8xx_wdt_handler_install(bd_t * binfo);
+extern void m8xx_wdt_handler_install(void);
 extern int m8xx_wdt_get_timeout(void);
 extern void m8xx_wdt_reset(void);
 
Index: arch/ppc/syslib/mpc52xx_setup.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/mpc52xx_setup.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/mpc52xx_setup.c  (mode:100644)
@@ -24,9 +24,8 @@
 #include <asm/mpc52xx.h>
 #include <asm/mpc52xx_psc.h>
 #include <asm/pgtable.h>
-#include <asm/ppcboot.h>
+#include <asm/firmware.h>
 
-extern bd_t __res;
 
 static int core_mult[] = {		/* CPU Frequency multiplier, taken    */
 	0,  0,  0,  10, 20, 20, 25, 45,	/* from the datasheet used to compute */
@@ -127,7 +126,7 @@
 unsigned long __init
 mpc52xx_find_end_of_memory(void)
 {
-	u32 ramsize = __res.bi_memsize;
+	u32 ramsize = fw_get_memory_size();
 
 	/*
 	 * if bootloader passed a memsize, just use it
@@ -161,7 +160,7 @@
 	int tbl_start, tbl_end;
 	unsigned int xlbfreq, cpufreq, ipbfreq, pcifreq, divisor;
 
-	xlbfreq = __res.bi_busfreq;
+	xlbfreq = fw_get_busfreq();
 	/* if bootloader didn't pass bus frequencies, calculate them */
 	if (xlbfreq == 0) {
 		/* Get RTC & Clock manager modules */
@@ -200,10 +199,10 @@
 			pcifreq = xlbfreq / 4;
 			break;
 		}
-		__res.bi_busfreq = xlbfreq;
-		__res.bi_intfreq = cpufreq;
-		__res.bi_ipbfreq = ipbfreq;
-		__res.bi_pcifreq = pcifreq;
+		fw_set_busfreq(xlbfreq);
+		fw_set_intfreq(cpufreq);
+		fw_set_ipbfreq(ipbfreq);
+		fw_set_pcifreq(pcifreq);
 
 		/* Release mapping */
 		iounmap(rtc);
Index: arch/ppc/syslib/ppc4xx_setup.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/ppc4xx_setup.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/ppc4xx_setup.c  (mode:100644)
@@ -41,6 +41,7 @@
 #include <asm/ppc4xx_pic.h>
 #include <asm/pci-bridge.h>
 #include <asm/bootinfo.h>
+#include <asm/firmware.h>
 
 #include <syslib/gen550.h>
 
@@ -52,8 +53,6 @@
 extern int wdt_enable;
 extern unsigned long wdt_period;
 
-/* Global Variables */
-bd_t __res;
 
 void __init
 ppc4xx_setup_arch(void)
@@ -81,7 +80,7 @@
 static int
 ppc4xx_show_percpuinfo(struct seq_file *m, int i)
 {
-	seq_printf(m, "clock\t\t: %ldMHz\n", (long)__res.bi_intfreq / 1000000);
+	seq_printf(m, "clock\t\t: %ldMHz\n", fw_get_intfreq() / 1000000);
 
 	return 0;
 }
@@ -93,14 +92,12 @@
 static int
 ppc4xx_show_cpuinfo(struct seq_file *m)
 {
-	bd_t *bip = &__res;
-
 	seq_printf(m, "machine\t\t: %s\n", PPC4xx_MACHINE_NAME);
 	seq_printf(m, "plb bus clock\t: %ldMHz\n",
-		   (long) bip->bi_busfreq / 1000000);
+		   (long) fw_get_busfreq() / 1000000);
 #ifdef CONFIG_PCI
 	seq_printf(m, "pci bus clock\t: %dMHz\n",
-		   bip->bi_pci_busfreq / 1000000);
+		   fw_get_pci_busfreq() / 1000000);
 #endif
 
 	return 0;
@@ -112,7 +109,7 @@
 static unsigned long __init
 ppc4xx_find_end_of_memory(void)
 {
-	return ((unsigned long) __res.bi_memsize);
+	return fw_get_memory_size();
 }
 
 void __init
@@ -169,13 +166,12 @@
 ppc4xx_calibrate_decr(void)
 {
 	unsigned int freq;
-	bd_t *bip = &__res;
 
 #if defined(CONFIG_WALNUT) || defined(CONFIG_ASH) || defined(CONFIG_SYCAMORE)
 	/* Walnut boot rom sets DCR CHCR1 (aka CPC0_CR1) bit CETE to 1 */
 	mtdcr(DCRN_CHCR1, mfdcr(DCRN_CHCR1) & ~CHR1_CETE);
 #endif
-	freq = bip->bi_tbfreq;
+	freq = fw_get_tbfreq();
 	tb_ticks_per_jiffy = freq / HZ;
 	tb_to_us = mulhwu_scale_factor(freq, 1000000);
 
@@ -238,7 +234,7 @@
 	 * residual data area.
 	 */
 	if (r3)
-		__res = *(bd_t *)(r3 + KERNELBASE);
+		fw_initialize(r3);
 
 #if defined(CONFIG_BLK_DEV_INITRD)
 	/*
Index: arch/ppc/syslib/ppc83xx_setup.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/ppc83xx_setup.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/ppc83xx_setup.c  (mode:100644)
@@ -29,20 +29,18 @@
 #include <asm/mmu.h>
 #include <asm/ppc_sys.h>
 #include <asm/kgdb.h>
+#include <asm/firmware.h>
 
 #include <syslib/ppc83xx_setup.h>
 
 phys_addr_t immrbar;
 
 /* Return the amount of memory */
+/* FIXME: ppc_md.find_of_memory() could use fw_get_memory_size() directly */
 unsigned long __init
 mpc83xx_find_end_of_memory(void)
 {
-        bd_t *binfo;
-
-        binfo = (bd_t *) __res;
-
-        return binfo->bi_memsize;
+        return fw_get_memory_size();
 }
 
 long __init
@@ -51,8 +49,7 @@
 #define SPCR_OFFS   0x00000110
 #define SPCR_TBEN   0x00400000
 
-	bd_t *binfo = (bd_t *)__res;
-	u32 *spcr = ioremap(binfo->bi_immr_base + SPCR_OFFS, 4);
+	u32 *spcr = ioremap(fw_get_immr_base() + SPCR_OFFS, 4);
 
 	*spcr |= SPCR_TBEN;
 
@@ -65,10 +62,10 @@
 void __init
 mpc83xx_calibrate_decr(void)
 {
-        bd_t *binfo = (bd_t *) __res;
         unsigned int freq, divisor;
 
-	freq = binfo->bi_busfreq;
+	freq = fw_get_busfreq();
+
 	divisor = 4;
 	tb_ticks_per_jiffy = freq / HZ / divisor;
 	tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
@@ -82,12 +79,15 @@
 	struct uart_port serial_req;
 #endif
 	struct plat_serial8250_port *pdata;
-	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq, immr_base;
+
 	pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(MPC83xx_DUART);
+	freq = fw_get_busfreq();
+	immr_base = fw_get_immr_base();
 
 	/* Setup serial port access */
-	pdata[0].uartclk = binfo->bi_busfreq;
-	pdata[0].mapbase += binfo->bi_immr_base;
+	pdata[0].uartclk = freq;
+	pdata[0].mapbase += immr_base;
 	pdata[0].membase = ioremap(pdata[0].mapbase, 0x100);
 
 #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
@@ -100,8 +100,8 @@
 	gen550_init(0, &serial_req);
 #endif
 
-	pdata[1].uartclk = binfo->bi_busfreq;
-	pdata[1].mapbase += binfo->bi_immr_base;
+	pdata[1].uartclk = freq;
+	pdata[1].mapbase += immr_base;
 	pdata[1].membase = ioremap(pdata[1].mapbase, 0x100);
 
 #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
Index: arch/ppc/syslib/ppc83xx_setup.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/ppc83xx_setup.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/ppc83xx_setup.h  (mode:100644)
@@ -19,7 +19,6 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
-#include <asm/ppcboot.h>
 
 extern unsigned long mpc83xx_find_end_of_memory(void) __init;
 extern long mpc83xx_time_init(void) __init;
Index: arch/ppc/syslib/ppc85xx_setup.c
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/ppc85xx_setup.c  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/ppc85xx_setup.c  (mode:100644)
@@ -30,29 +30,26 @@
 #include <asm/mmu.h>
 #include <asm/ppc_sys.h>
 #include <asm/kgdb.h>
+#include <asm/firmware.h>
 
 #include <syslib/ppc85xx_setup.h>
 
 /* Return the amount of memory */
+/* FIXME: ppc_md.find_of_memory() could use fw_get_memory_size() directly */
 unsigned long __init
 mpc85xx_find_end_of_memory(void)
 {
-        bd_t *binfo;
-
-        binfo = (bd_t *) __res;
-
-        return binfo->bi_memsize;
+        return fw_get_memory_size();
 }
 
 /* The decrementer counts at the system (internal) clock freq divided by 8 */
 void __init
 mpc85xx_calibrate_decr(void)
 {
-        bd_t *binfo = (bd_t *) __res;
         unsigned int freq, divisor;
 
-        /* get the core frequency */
-        freq = binfo->bi_busfreq;
+        /* get the bus frequency */
+        freq = fw_get_busfreq();
 
         /* The timebase is updated every 8 bus clocks, HID0[SEL_TBCLK] = 0 */
         divisor = 8;
@@ -78,12 +75,15 @@
 	struct uart_port serial_req;
 #endif
 	struct plat_serial8250_port *pdata;
-	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq, immr_base;
+
 	pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(MPC85xx_DUART);
+	freq = fw_get_busfreq();
+	immr_base = fw_get_immr_base();
 
 	/* Setup serial port access */
-	pdata[0].uartclk = binfo->bi_busfreq;
-	pdata[0].mapbase += binfo->bi_immr_base;
+	pdata[0].uartclk = freq;
+	pdata[0].mapbase += immr_base;
 	pdata[0].membase = ioremap(pdata[0].mapbase, MPC85xx_UART0_SIZE);
 
 #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
@@ -96,8 +96,8 @@
 	gen550_init(0, &serial_req);
 #endif
 
-	pdata[1].uartclk = binfo->bi_busfreq;
-	pdata[1].mapbase += binfo->bi_immr_base;
+	pdata[1].uartclk = freq;
+	pdata[1].mapbase += immr_base;
 	pdata[1].membase = ioremap(pdata[1].mapbase, MPC85xx_UART0_SIZE);
 
 #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
@@ -138,13 +138,12 @@
 	volatile struct ccsr_pci *pci;
 	volatile struct ccsr_guts *guts;
 	unsigned short temps;
-	bd_t *binfo = (bd_t *) __res;
+	unsigned int immr_base;
 
-	pci = ioremap(binfo->bi_immr_base + MPC85xx_PCI1_OFFSET,
-		    MPC85xx_PCI1_SIZE);
+	immr_base = fw_get_immr_base();
 
-	guts = ioremap(binfo->bi_immr_base + MPC85xx_GUTS_OFFSET,
-		    MPC85xx_GUTS_SIZE);
+	pci = ioremap(immr_base + MPC85xx_PCI1_OFFSET, MPC85xx_PCI1_SIZE);
+	guts = ioremap(immr_base + MPC85xx_GUTS_OFFSET, MPC85xx_GUTS_SIZE);
 
 	early_read_config_word(hose, 0, 0, PCI_COMMAND, &temps);
 	temps |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
@@ -201,10 +200,11 @@
 {
 	volatile struct ccsr_pci *pci;
 	unsigned short temps;
-	bd_t *binfo = (bd_t *) __res;
+	unsigned int immr_base;
 
-	pci = ioremap(binfo->bi_immr_base + MPC85xx_PCI2_OFFSET,
-		    MPC85xx_PCI2_SIZE);
+	immr_base = fw_get_immr_base();
+
+	pci = ioremap(immr_base + MPC85xx_PCI2_OFFSET, MPC85xx_PCI2_SIZE);
 
 	early_read_config_word(hose, hose->bus_offset, 0, PCI_COMMAND, &temps);
 	temps |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
@@ -248,11 +248,13 @@
 void __init
 mpc85xx_setup_hose(void)
 {
+	unsigned int immr_base;
 	struct pci_controller *hose_a;
 #ifdef CONFIG_85xx_PCI2
 	struct pci_controller *hose_b;
 #endif
-	bd_t *binfo = (bd_t *) __res;
+
+	immr_base = fw_get_immr_base();
 
 	hose_a = pcibios_alloc_controller();
 
@@ -266,8 +268,9 @@
 	hose_a->bus_offset = 0;
 	hose_a->last_busno = 0xff;
 
-	setup_indirect_pci(hose_a, binfo->bi_immr_base + PCI1_CFG_ADDR_OFFSET,
-			   binfo->bi_immr_base + PCI1_CFG_DATA_OFFSET);
+	setup_indirect_pci(hose_a,
+			   immr_base + PCI1_CFG_ADDR_OFFSET,
+			   immr_base + PCI1_CFG_DATA_OFFSET);
 	hose_a->set_cfg_type = 1;
 
 	mpc85xx_setup_pci1(hose_a);
@@ -314,8 +317,9 @@
 	hose_b->first_busno = hose_a->last_busno + 1;
 	hose_b->last_busno = 0xff;
 
-	setup_indirect_pci(hose_b, binfo->bi_immr_base + PCI2_CFG_ADDR_OFFSET,
-			   binfo->bi_immr_base + PCI2_CFG_DATA_OFFSET);
+	setup_indirect_pci(hose_b,
+			   immr_base + PCI2_CFG_ADDR_OFFSET,
+			   immr_base + PCI2_CFG_DATA_OFFSET);
 	hose_b->set_cfg_type = 1;
 
 	mpc85xx_setup_pci2(hose_b);
Index: arch/ppc/syslib/ppc85xx_setup.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/arch/ppc/syslib/ppc85xx_setup.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/arch/ppc/syslib/ppc85xx_setup.h  (mode:100644)
@@ -19,7 +19,6 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
-#include <asm/ppcboot.h>
 
 extern unsigned long mpc85xx_find_end_of_memory(void) __init;
 extern void mpc85xx_calibrate_decr(void) __init;
Index: include/asm-ppc/bseip.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/include/asm-ppc/bseip.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/include/asm-ppc/bseip.h  (mode:100644)
@@ -8,19 +8,6 @@
 #define __MACH_BSEIP_DEFS
 
 #ifndef __ASSEMBLY__
-/* A Board Information structure that is given to a program when
- * prom starts it up.
- */
-typedef struct bd_info {
-	unsigned int	bi_memstart;	/* Memory start address */
-	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
-	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
-	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
-	unsigned char	bi_enetaddr[6];
-	unsigned int	bi_baudrate;
-} bd_t;
-
-extern bd_t m8xx_board_info;
 
 /* Memory map is configured by the PROM startup.
  * All we need to get started is the IMMR.
Index: include/asm-ppc/ibm4xx.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/include/asm-ppc/ibm4xx.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/include/asm-ppc/ibm4xx.h  (mode:100644)
@@ -65,14 +65,6 @@
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_40x
-/*
- * The "residual" board information structure the boot loader passes
- * into the kernel.
- */
-extern bd_t __res;
-#endif
-
 void ppc4xx_setup_arch(void);
 void ppc4xx_map_io(void);
 void ppc4xx_init_IRQ(void);
@@ -109,15 +101,6 @@
 #include <platforms/4xx/ocotea.h>
 #endif
 
-#ifndef __ASSEMBLY__
-#ifdef CONFIG_40x
-/*
- * The "residual" board information structure the boot loader passes
- * into the kernel.
- */
-extern bd_t __res;
-#endif
-#endif
 #endif /* CONFIG_40x */
 
 #endif /* __ASM_IBM4XX_H__ */
Index: include/asm-ppc/ibm_ocp.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/include/asm-ppc/ibm_ocp.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/include/asm-ppc/ibm_ocp.h  (mode:100644)
@@ -91,6 +91,7 @@
 }
 
 #ifdef CONFIG_40x
+#include "asm/firmware.h"
 /*
  * Helper function to copy MAC addresses from the bd_t to OCP EMAC
  * additions.
@@ -106,7 +107,7 @@
 	for (i=start; i<=end; i++) {
 		def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i);
 		memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr,
-				&__res.bi_enetaddr[i],
+				fw_get_enetaddr(i),
 				6);
 	}
 }
Index: include/asm-ppc/mpc52xx.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/include/asm-ppc/mpc52xx.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/include/asm-ppc/mpc52xx.h  (mode:100644)
@@ -22,7 +22,6 @@
 #define __ASM_MPC52xx_H__
 
 #ifndef __ASSEMBLY__
-#include <asm/ppcboot.h>
 #include <asm/types.h>
 
 struct pt_regs;
@@ -433,9 +432,6 @@
 /* Platform configuration                                                    */
 /* ========================================================================= */
 
-/* The U-Boot platform information struct */
-extern bd_t __res;
-
 /* Platform options */
 #if defined(CONFIG_LITE5200)
 #include <platforms/lite5200.h>
Index: include/asm-ppc/mpc8260.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/include/asm-ppc/mpc8260.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/include/asm-ppc/mpc8260.h  (mode:100644)
@@ -67,13 +67,6 @@
 #define IO_VIRT_ADDR	IO_PHYS_ADDR
 #endif
 
-#ifndef __ASSEMBLY__
-/* The "residual" data board information structure the boot loader
- * hands to us.
- */
-extern unsigned char __res[];
-#endif
-
 #endif /* CONFIG_8260 */
 #endif /* !__ASM_PPC_MPC8260_H__ */
 #endif /* __KERNEL__ */
Index: include/asm-ppc/mpc83xx.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/include/asm-ppc/mpc83xx.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/include/asm-ppc/mpc83xx.h  (mode:100644)
@@ -34,11 +34,6 @@
 #define PCI_DRAM_OFFSET 0
 #endif
 
-/*
- * The "residual" board information structure the boot loader passes
- * into the kernel.
- */
-extern unsigned char __res[];
 
 /* Internal IRQs on MPC83xx OpenPIC */
 /* Not all of these exist on all MPC83xx implementations */
Index: include/asm-ppc/mpc85xx.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/include/asm-ppc/mpc85xx.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/include/asm-ppc/mpc85xx.h  (mode:100644)
@@ -46,11 +46,6 @@
 #define PCI_DRAM_OFFSET 0
 #endif
 
-/*
- * The "residual" board information structure the boot loader passes
- * into the kernel.
- */
-extern unsigned char __res[];
 
 /* Offset from CCSRBAR */
 #define MPC85xx_CPM_OFFSET	(0x80000)
Index: include/asm-ppc/mpc8xx.h
===================================================================
--- c7d7a187a2125518e655dfeadffd38156239ffc3/include/asm-ppc/mpc8xx.h  (mode:100644)
+++ eb4292a8874abcc926f536de90af0bdb001cf12e/include/asm-ppc/mpc8xx.h  (mode:100644)
@@ -90,14 +90,9 @@
 #endif
 
 #ifndef __ASSEMBLY__
-/* The "residual" data board information structure the boot loader
- * hands to us.
- */
-extern unsigned char __res[];
-
 struct pt_regs;
-
 #endif /* !__ASSEMBLY__ */
+
 #endif /* CONFIG_8xx */
 #endif /* __CONFIG_8xx_DEFS */
 #endif /* __KERNEL__ */

^ permalink raw reply

* [PATCH] ppc32: MPC834x BCSR_SIZE too small for use in a BAT.
From: Kumar Gala @ 2005-05-27 22:08 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel, linuxppc-embedded

The call to io_block_mapping was creating an invalid BAT entry because
the value of BCSR_SIZE (32K) is too small to be used in a BAT (128K min).
This change removes the io_block_mapping call since these registers can
easily be mapped using ioremap at the point of use.

Signed-off-by: Randy Vinson <rvinson@mvista.com>
Signed-off-by: Kumar Gala <kumar.gala@freescale.com>

---
commit 2c6dd281d28694239de9e453541ed3b937d11e25
tree 0d93680a000f9dafe78831ee00573c1bb544bcf6
parent 4ec5240ec367a592834385893200dd4fb369354c
author Kumar K. Gala <kumar.gala@freescale.com> Thu, 26 May 2005 19:14:39 -0500
committer Kumar K. Gala <kumar.gala@freescale.com> Thu, 26 May 2005 19:14:39 -0500

 ppc/platforms/83xx/mpc834x_sys.c |    1 -
 ppc/platforms/83xx/mpc834x_sys.h |    1 -
 2 files changed, 2 deletions(-)

Index: arch/ppc/platforms/83xx/mpc834x_sys.c
===================================================================
--- 3ac9a34948049bff79a2b2ce49c0a3c84e35a748/arch/ppc/platforms/83xx/mpc834x_sys.c  (mode:100644)
+++ 0d93680a000f9dafe78831ee00573c1bb544bcf6/arch/ppc/platforms/83xx/mpc834x_sys.c  (mode:100644)
@@ -127,7 +127,6 @@
 {
 	/* we steal the lowest ioremap addr for virt space */
 	io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO);
-	io_block_mapping(BCSR_VIRT_ADDR, BCSR_PHYS_ADDR, BCSR_SIZE, _PAGE_IO);
 }
 
 int
Index: arch/ppc/platforms/83xx/mpc834x_sys.h
===================================================================
--- 3ac9a34948049bff79a2b2ce49c0a3c84e35a748/arch/ppc/platforms/83xx/mpc834x_sys.h  (mode:100644)
+++ 0d93680a000f9dafe78831ee00573c1bb544bcf6/arch/ppc/platforms/83xx/mpc834x_sys.h  (mode:100644)
@@ -26,7 +26,6 @@
 #define VIRT_IMMRBAR		((uint)0xfe000000)
 
 #define BCSR_PHYS_ADDR		((uint)0xf8000000)
-#define BCSR_VIRT_ADDR		((uint)0xfe100000)
 #define BCSR_SIZE		((uint)(32 * 1024))
 
 #ifdef CONFIG_PCI

^ permalink raw reply

* [PATCH] ppc32: Add soft reset to MPC834x
From: Kumar Gala @ 2005-05-27 22:09 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel, linuxppc-embedded

This change allows mpc83xx_restart to issue a software reset.

Signed-off-by: Randy Vinson <rvinson@mvista.com>
Signed-off-by: Kumar Gala <kumar.gala@freescale.com>

---
commit 1a0a26adb3ef9323ac3e17e14af6c2b138f1656a
tree ec5c9971711cdd5ce074c2798a16cc12d35318ee
parent 2c6dd281d28694239de9e453541ed3b937d11e25
author Kumar K. Gala <kumar.gala@freescale.com> Fri, 27 May 2005 09:35:28 -0500
committer Kumar K. Gala <kumar.gala@freescale.com> Fri, 27 May 2005 09:35:28 -0500

 ppc/platforms/83xx/mpc834x_sys.h |    6 ++++++
 ppc/syslib/ppc83xx_setup.c       |   28 ++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

Index: arch/ppc/platforms/83xx/mpc834x_sys.h
===================================================================
--- 0d93680a000f9dafe78831ee00573c1bb544bcf6/arch/ppc/platforms/83xx/mpc834x_sys.h  (mode:100644)
+++ ec5c9971711cdd5ce074c2798a16cc12d35318ee/arch/ppc/platforms/83xx/mpc834x_sys.h  (mode:100644)
@@ -28,6 +28,12 @@
 #define BCSR_PHYS_ADDR		((uint)0xf8000000)
 #define BCSR_SIZE		((uint)(32 * 1024))
 
+#define BCSR_MISC_REG2_OFF	0x07
+#define BCSR_MISC_REG2_PORESET	0x01
+
+#define BCSR_MISC_REG3_OFF	0x08
+#define BCSR_MISC_REG3_CNFLOCK	0x80
+
 #ifdef CONFIG_PCI
 /* PCI interrupt controller */
 #define PIRQA        MPC83xx_IRQ_IRQ4
Index: arch/ppc/syslib/ppc83xx_setup.c
===================================================================
--- 0d93680a000f9dafe78831ee00573c1bb544bcf6/arch/ppc/syslib/ppc83xx_setup.c  (mode:100644)
+++ ec5c9971711cdd5ce074c2798a16cc12d35318ee/arch/ppc/syslib/ppc83xx_setup.c  (mode:100644)
@@ -29,6 +29,7 @@
 #include <asm/mmu.h>
 #include <asm/ppc_sys.h>
 #include <asm/kgdb.h>
+#include <asm/delay.h>
 
 #include <syslib/ppc83xx_setup.h>
 
@@ -117,7 +118,34 @@
 void
 mpc83xx_restart(char *cmd)
 {
+	volatile unsigned char __iomem *reg;
+	unsigned char tmp;
+
+	reg = ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
+
 	local_irq_disable();
+
+	/*
+	 * Unlock the BCSR bits so a PRST will update the contents.
+	 * Otherwise the reset asserts but doesn't clear.
+	 */
+	tmp = in_8(reg + BCSR_MISC_REG3_OFF);
+	tmp |= BCSR_MISC_REG3_CNFLOCK; /* low true, high false */
+	out_8(reg + BCSR_MISC_REG3_OFF, tmp);
+
+	/*
+	 * Trigger a reset via a low->high transition of the
+	 * PORESET bit.
+	 */
+	tmp = in_8(reg + BCSR_MISC_REG2_OFF);
+	tmp &= ~BCSR_MISC_REG2_PORESET;
+	out_8(reg + BCSR_MISC_REG2_OFF, tmp);
+
+	udelay(1);
+
+	tmp |= BCSR_MISC_REG2_PORESET;
+	out_8(reg + BCSR_MISC_REG2_OFF, tmp);
+
 	for(;;);
 }
 

^ permalink raw reply

* [PATCH] ppc32: i8259 PIC should not be initialized if PCI is not configured
From: Kumar Gala @ 2005-05-27 22:10 UTC (permalink / raw)
  To: Andrew Morton; +Cc: shall, linux-kernel, linuxppc-embedded

Trying to initialize the i8259 PIC will not work if CONFIG_PCI is
not enabled.  The kernel hangs if the initialization is tried.

Signed-off-by: Kumar Gala <kumar.gala@freescale.com>

---
commit 947c0e2c89c4e5cda2093bcfca7c13e097641e3b
tree 12a3e07d44c69f110708c359da5132439c2527c5
parent 219d058f65dbd666964b1e951b8d491e4b19dc0c
author Kumar K. Gala <kumar.gala@freescale.com> Fri, 27 May 2005 16:57:41 -0500
committer Kumar K. Gala <kumar.gala@freescale.com> Fri, 27 May 2005 16:57:41 -0500

 ppc/platforms/85xx/mpc85xx_cds_common.c |    2 ++
 1 files changed, 2 insertions(+)

Index: arch/ppc/platforms/85xx/mpc85xx_cds_common.c
===================================================================
--- 109a4648d2cc627d17c129bc1ca102a736c817aa/arch/ppc/platforms/85xx/mpc85xx_cds_common.c  (mode:100644)
+++ 12a3e07d44c69f110708c359da5132439c2527c5/arch/ppc/platforms/85xx/mpc85xx_cds_common.c  (mode:100644)
@@ -200,12 +200,14 @@
 	 */
 	openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
 
+#ifdef CONFIG_PCI
 	openpic_hookup_cascade(PIRQ0A, "82c59 cascade", i8259_irq);
 
 	for (i = 0; i < NUM_8259_INTERRUPTS; i++)
 		irq_desc[i].handler = &i8259_pic;
 
 	i8259_init(0);
+#endif
 
 #ifdef CONFIG_CPM2
 	/* Setup CPM2 PIC */

^ permalink raw reply

* Re: Dynamic libraries do not work
From: Grant Likely @ 2005-05-28  0:50 UTC (permalink / raw)
  To: Theo Gjaltema; +Cc: linuxppc-embedded
In-Reply-To: <42970B74.1060602@chello.nl>

On 5/27/05, Theo Gjaltema <gjalt007@chello.nl> wrote:
>=20
>=20
> Toolchain used:   ELDK 2.0
> target processor: mpc862
> RAM:                64 Mbyte
> Kernel:               2.4.20, extended with ATM/UTOPIA
> init:                  /sbin/init -> /bin/busybox
>=20
>=20
> (using a static linked busybox: activating a sh (=3Dbusybox)
> ::sysinit:/bin/sh)
> sh: /lib/ld.so.1          (note: /lib/ld.so.1 is a link to
> /lib/ld.so.2.5.5, part of the ELDK 2.0 )
> < help page of ld.so.1>
> sh: /lib/ld.so.1 --verify /bin/xxx (or just any dynamic linked executable=
)
> <here the system has crahed>
>=20
> or
> sh: /bin/xxx
> <here the system has crashed>
>=20
> I have tried to step through the dynamic linking, but did not succeed
> til after the creation of a thread.
> With a dynamic linked busybox the system stops after a message such as
> "freeing xxx kbytes" (I don't know the actual number by head)
> When init is then called, which is a part of the busybox which is dyn.
> liked, it crashes.
>=20
It's really hard to give any advice with the limited data.
Do you get a kernel panic?  Has the kernel crashed or has it become
unresponsive.  Making a large number of assumptions, it sounds like
you've got a kernel problem, not a dynamic linking problem.  Dynamic
linking is handled 100% in user space.  If init crashes (or is killed)
you should get a kernel panic message.  The fact that you get nothing
says to me that dynamic linking is simply exposing a kernel bug.

A good place to start is to make sure all of memory is working.  Try a
simple test; allocate memory in an infinite loop and see where it
breaks.

Cheers,
g.

^ permalink raw reply

* [PATCH] ppc32: PowerMac PM rework
From: Benjamin Herrenschmidt @ 2005-05-28  2:15 UTC (permalink / raw)
  To: linuxppc-dev list

Hi !

This new version of my PM rework fixes bits & pieces, most
significantly, improves suspend to disk by properly saving/restoring
MacIO ASIC state, and fixes issues with suspend to disk vs. AGP/DRI.

Also, the previous patch had the backward compatible ioctl backward, it
would suspend to disk instead of to RAM :)

Applies on top of current git plus:

http://gate.crashing.org/~benh/ppc32-pmac-cpufreq-upd.diff
http://gate.crashing.org/~benh/ppc32-pmac-pmu-irq-pri.diff
http://gate.crashing.org/~benh/ppc32-pmu-wakeup.diff

Please test and report any issue.

Index: linux-work/arch/ppc/platforms/Makefile
===================================================================
--- linux-work.orig/arch/ppc/platforms/Makefile	2005-05-02 10:48:08.000000000 +1000
+++ linux-work/arch/ppc/platforms/Makefile	2005-05-28 10:30:21.000000000 +1000
@@ -10,8 +10,9 @@
 obj-$(CONFIG_PCI)		+= apus_pci.o
 endif
 obj-$(CONFIG_PPC_PMAC)		+= pmac_pic.o pmac_setup.o pmac_time.o \
-					pmac_feature.o pmac_pci.o pmac_sleep.o \
-					pmac_low_i2c.o pmac_cache.o
+				   pmac_feature.o pmac_pci.o pmac_sleep.o \
+				   pmac_low_i2c.o pmac_cache.o pmac_pm.o
+
 obj-$(CONFIG_PPC_CHRP)		+= chrp_setup.o chrp_time.o chrp_pci.o \
 					chrp_pegasos_eth.o
 obj-$(CONFIG_PPC_PREP)		+= prep_pci.o prep_setup.o
Index: linux-work/arch/ppc/platforms/pmac_pm.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-work/arch/ppc/platforms/pmac_pm.c	2005-05-28 11:58:16.000000000 +1000
@@ -0,0 +1,802 @@
+/*
+ * PowerMac Power Management core
+ *
+ * Copyright (C) 2005 Benjamin Herrenschmidt, IBM Corp.
+ *
+ * Bits from drivers/macintosh/via-pmu.c
+ *
+ * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
+ * Copyright (C) 2001-2002 Benjamin Herrenschmidt
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/suspend.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/cpu.h>
+#include <linux/syscalls.h>
+#include <linux/reboot.h>
+#include <linux/timer.h>
+
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/pmac_feature.h>
+#include <asm/mmu_context.h>
+#include <asm/cputable.h>
+#include <asm/time.h>
+#include <asm/sections.h>
+#include <asm/system.h>
+#include <asm/open_pic.h>
+
+#ifdef CONFIG_PM_DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+/* debugging */
+int __fake_sleep;
+
+/* lid wakeup control (fixme) */
+int pmac_option_lid_wakeup __pmacdata;
+EXPORT_SYMBOL_GPL(pmac_option_lid_wakeup);
+
+/* main callback for suspend to RAM */
+static int (*pmac_pm_low_suspend)(void) __pmacdata;
+
+/* assembly stuff */
+extern void low_sleep_handler(void);
+/* pmac_pic stuff */
+extern void pmacpic_suspend(void);
+extern void pmacpic_resume(void);
+
+
+/*************************************************************************
+ *
+ * Here is the "old style" PowerMac PM notifiers. They are still used by a
+ * couple of drivers that haven't yet been fitted in the device model.
+ * They will ultimately be deprecated.
+ *
+ *************************************************************************/
+
+static LIST_HEAD(sleep_notifiers);
+
+int __pmac pmu_register_sleep_notifier(struct pmu_sleep_notifier *n)
+{
+	struct list_head *list;
+	struct pmu_sleep_notifier *notifier;
+
+	for (list = sleep_notifiers.next; list != &sleep_notifiers;
+	     list = list->next) {
+		notifier = list_entry(list, struct pmu_sleep_notifier, list);
+		if (n->priority > notifier->priority)
+			break;
+	}
+	__list_add(&n->list, list->prev, list);
+	return 0;
+}
+EXPORT_SYMBOL(pmu_register_sleep_notifier);
+
+int __pmac pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n)
+{
+	if (n->list.next == 0)
+		return -ENOENT;
+	list_del(&n->list);
+	n->list.next = NULL;
+	return 0;
+}
+EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
+
+/* Sleep is broadcast last-to-first */
+static int __pmac broadcast_sleep(int when, int fallback)
+{
+	int ret = PBOOK_SLEEP_OK;
+	struct list_head *list;
+	struct pmu_sleep_notifier *notifier;
+
+	for (list = sleep_notifiers.prev; list != &sleep_notifiers;
+	     list = list->prev) {
+		notifier = list_entry(list, struct pmu_sleep_notifier, list);
+		ret = notifier->notifier_call(notifier, when);
+		if (ret != PBOOK_SLEEP_OK) {
+			DBG("sleep %d rejected by %p (%p)\n",
+			    when, notifier, notifier->notifier_call);
+			for (; list != &sleep_notifiers; list = list->next) {
+				notifier = list_entry(list,
+					      struct pmu_sleep_notifier, list);
+				notifier->notifier_call(notifier, fallback);
+			}
+			return ret;
+		}
+	}
+	return ret;
+}
+
+/* Wake is broadcast first-to-last */
+static int __pmac broadcast_wake(void)
+{
+	int ret = PBOOK_SLEEP_OK;
+	struct list_head *list;
+	struct pmu_sleep_notifier *notifier;
+
+	for (list = sleep_notifiers.next; list != &sleep_notifiers;
+	     list = list->next) {
+		notifier = list_entry(list, struct pmu_sleep_notifier, list);
+		notifier->notifier_call(notifier, PBOOK_WAKE);
+	}
+	return ret;
+}
+
+/**************************************************************************
+ *
+ * Here, we have code to save/restore PCI config space. Most of that code
+ * should be removed once we are confident with the generic code, including
+ * with P2P bridges
+ *
+ **************************************************************************/
+
+static struct pci_save {
+	u16	command;
+	u16	cache_lat;
+	u16	intr;
+	u32	bars[6];
+	u32	rom_address;
+} *pbook_pci_saves __pmacdata;
+static int pbook_npci_saves __pmacdata;
+
+static void __pmac pbook_alloc_pci_save(void)
+{
+	int npci;
+	struct pci_dev *pd = NULL;
+
+	npci = 0;
+	while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+		++npci;
+	}
+	if (npci == 0)
+		return;
+	pbook_pci_saves = (struct pci_save *)
+		kmalloc(npci * sizeof(struct pci_save), GFP_KERNEL);
+	pbook_npci_saves = npci;
+}
+
+static void __pmac pbook_free_pci_save(void)
+{
+	if (pbook_pci_saves == NULL)
+		return;
+	kfree(pbook_pci_saves);
+	pbook_pci_saves = NULL;
+	pbook_npci_saves = 0;
+}
+
+static void __pmac pbook_pci_save(void)
+{
+	struct pci_save *ps = pbook_pci_saves;
+	struct pci_dev *pd = NULL;
+	int npci = pbook_npci_saves;
+	int i;
+
+	if (ps == NULL)
+		return;
+
+	while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+		if (npci-- == 0)
+			return;
+		switch (pd->hdr_type) {
+		case PCI_HEADER_TYPE_NORMAL:
+			pci_read_config_word(pd, PCI_COMMAND, &ps->command);
+			pci_read_config_word(pd, PCI_CACHE_LINE_SIZE,
+					     &ps->cache_lat);
+			pci_read_config_word(pd, PCI_INTERRUPT_LINE,
+					     &ps->intr);
+			pci_read_config_dword(pd, PCI_ROM_ADDRESS,
+					      &ps->rom_address);
+			for (i=0; i<6; i++)
+				pci_read_config_dword(pd,
+						      PCI_BASE_ADDRESS_0+i*4,
+						      &ps->bars[i]);
+			break;
+		case PCI_HEADER_TYPE_BRIDGE:
+			pci_read_config_word(pd, PCI_COMMAND, &ps->command);
+			pci_read_config_word(pd, PCI_CACHE_LINE_SIZE,
+					     &ps->cache_lat);
+			pci_read_config_dword(pd, PCI_ROM_ADDRESS1,
+					      &ps->rom_address);
+			pci_read_config_dword(pd, PCI_BASE_ADDRESS_0,
+					      &ps->bars[0]);
+			pci_read_config_dword(pd, PCI_BASE_ADDRESS_1,
+					      &ps->bars[1]);
+			break;
+		case PCI_HEADER_TYPE_CARDBUS:
+			pci_read_config_word(pd, PCI_COMMAND, &ps->command);
+			pci_read_config_word(pd, PCI_CACHE_LINE_SIZE,
+					     &ps->cache_lat);
+			pci_read_config_word(pd, PCI_INTERRUPT_LINE,
+					     &ps->intr);
+			pci_read_config_dword(pd, PCI_BASE_ADDRESS_0,
+					      &ps->bars[0]);
+			break;
+		}			
+		++ps;
+	}
+}
+
+/* For this to work, we must take care of a few things: If gmac was enabled
+ * during boot, it will be in the pci dev list. If it's disabled at this point
+ * (and it will probably be), then you can't access it's config space.
+ */
+static void __pmac pbook_pci_restore(void)
+{
+	u16 cmd;
+	struct pci_save *ps = pbook_pci_saves - 1;
+	struct pci_dev *pd = NULL;
+	int npci = pbook_npci_saves;
+	int i;
+
+	while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
+		if (npci-- == 0)
+			return;
+		ps++;
+		if (ps->command == 0)
+			continue;
+		pci_read_config_word(pd, PCI_COMMAND, &cmd);
+		if ((ps->command & ~cmd) == 0)
+			continue;
+		switch (pd->hdr_type) {
+		case PCI_HEADER_TYPE_NORMAL:
+			for (i = 0; i < 6; ++i)
+				pci_write_config_dword(pd,
+						       PCI_BASE_ADDRESS_0+i*4,
+						       ps->bars[i]);
+			pci_write_config_dword(pd, PCI_ROM_ADDRESS,
+					       ps->rom_address);
+			pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
+					      ps->cache_lat);
+			pci_write_config_word(pd, PCI_INTERRUPT_LINE,
+					      ps->intr);
+			pci_write_config_word(pd, PCI_COMMAND, ps->command);
+			break;
+		case PCI_HEADER_TYPE_BRIDGE:
+			pci_write_config_dword(pd, PCI_BASE_ADDRESS_0,
+					       ps->bars[0]);
+			pci_write_config_dword(pd, PCI_BASE_ADDRESS_1,
+					       ps->bars[1]);
+			pci_write_config_dword(pd, PCI_ROM_ADDRESS,
+					       ps->rom_address);
+			pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
+					      ps->cache_lat);
+			pci_write_config_word(pd, PCI_COMMAND, ps->command);
+			break;
+		case PCI_HEADER_TYPE_CARDBUS:
+			pci_write_config_dword(pd, PCI_BASE_ADDRESS_0, 
+					       ps->bars[0]);
+			pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
+					      ps->cache_lat);
+			pci_write_config_word(pd, PCI_INTERRUPT_LINE,
+					      ps->intr);
+			pci_write_config_word(pd, PCI_COMMAND, ps->command);
+			break;
+		}
+	}
+}
+
+/*************************************************************************
+ *
+ * Here are the per-machine family low level sleep routines and the
+ * par-machine family initialization routines.
+ *
+ *************************************************************************/
+
+
+#define PB3400_MEM_CTRL		0xf8000000
+#define PB3400_MEM_CTRL_SLEEP	0x70
+
+static void __iomem *mem_ctrl_3400 __pmacdata;
+
+static int __pmac pmac_pm_sleep_3400(void)
+{
+	int i, x;
+	unsigned int hid0;
+	unsigned long p;
+	struct adb_request sleep_req;
+	unsigned int __iomem *mem_ctrl_sleep;
+
+	mem_ctrl_sleep = mem_ctrl_3400 + PB3400_MEM_CTRL_SLEEP;
+
+	/* Set the memory controller to keep the memory refreshed
+	   while we're asleep */
+	for (i = 0x403f; i >= 0x4000; --i) {
+		out_be32(mem_ctrl_sleep, i);
+		do {
+			x = (in_be32(mem_ctrl_sleep) >> 16) & 0x3ff;
+		} while (x == 0);
+		if (x >= 0x100)
+			break;
+	}
+
+	/* Ask the PMU to put us to sleep */
+	pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
+	while (!sleep_req.complete)
+		mb();
+
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);
+
+	/* displacement-flush the L2 cache - necessary? */
+	for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000)
+		i = *(volatile int *)p;
+
+	/* Put the CPU into sleep mode */
+	asm volatile("mfspr %0,1008" : "=r" (hid0) :);
+	hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;
+	asm volatile("mtspr 1008,%0" : : "r" (hid0));
+	_nmask_and_or_msr(0, MSR_POW | MSR_EE);
+	udelay(10);
+
+	/* OK, we're awake again, start restoring things */
+	out_be32(mem_ctrl_sleep, 0x3f);
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
+	pbook_pci_restore();
+	pmu_unlock();
+
+	mdelay(10);
+
+	return 0;
+}
+
+static void __pmac pmac_pm_init_3400(void)
+{
+	/* first map in the memory controller registers */
+	mem_ctrl_3400 = ioremap(PB3400_MEM_CTRL, 0x100);
+	if (mem_ctrl_3400 == NULL) {
+		printk(KERN_ERR "pmac_pm_init_3400: ioremap failed\n");
+		return;
+	}
+
+	pmac_pm_low_suspend = pmac_pm_sleep_3400;
+}
+
+#define	GRACKLE_PM	(1<<7)
+#define GRACKLE_DOZE	(1<<5)
+#define	GRACKLE_NAP	(1<<4)
+#define	GRACKLE_SLEEP	(1<<3)
+
+static struct pci_dev *grackle __pmacdata;
+
+static int __pmac pmac_pm_sleep_grackle(void)
+{
+	unsigned long save_l2cr;
+	unsigned short pmcr1;
+	struct adb_request req;
+
+	/* Turn off various things. Darwin does some retry tests here... */
+	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0,
+		    PMU_POW0_OFF | PMU_POW0_HARD_DRIVE);
+	pmu_wait_complete(&req);
+	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+		    PMU_POW_OFF | PMU_POW_BACKLIGHT |
+		    PMU_POW_IRLED | PMU_POW_MEDIABAY);
+	pmu_wait_complete(&req);
+
+	/* For 750, save backside cache setting and disable it */
+	save_l2cr = _get_L2CR();	/* (returns -1 if not available) */
+
+	if (!__fake_sleep) {
+		/* Ask the PMU to put us to sleep */
+		pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
+		pmu_wait_complete(&req);
+	}
+
+	/* The VIA is supposed not to be restored correctly*/
+	pmu_save_via_state();
+
+	/* We shut down some HW */
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);
+
+	pci_read_config_word(grackle, 0x70, &pmcr1);
+	/* Apparently, MacOS uses NAP mode for Grackle ??? */
+	pmcr1 &= ~(GRACKLE_DOZE|GRACKLE_SLEEP); 
+	pmcr1 |= GRACKLE_PM|GRACKLE_NAP;
+	pci_write_config_word(grackle, 0x70, pmcr1);
+
+	/* Call low-level ASM sleep handler */
+	if (__fake_sleep)
+		mdelay(5000);
+	else
+		low_sleep_handler();
+
+	/* We're awake again, stop grackle PM */
+	pci_read_config_word(grackle, 0x70, &pmcr1);
+	pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); 
+	pci_write_config_word(grackle, 0x70, pmcr1);
+
+	/* Make sure the PMU is idle */
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
+	pmu_restore_via_state();
+	
+	/* Restore L2 cache */
+	if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
+ 		_set_L2CR(save_l2cr);
+	
+	/* Power things up */
+	pmu_unlock();
+	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0,
+			PMU_POW0_ON | PMU_POW0_HARD_DRIVE);
+	pmu_wait_complete(&req);
+	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+		    PMU_POW_ON | PMU_POW_BACKLIGHT | PMU_POW_CHARGER |
+		    PMU_POW_IRLED | PMU_POW_MEDIABAY);
+	pmu_wait_complete(&req);
+
+	return 0;
+}
+
+static void __pmac pmac_pm_init_grackle(void)
+{
+	grackle = pci_find_slot(0, 0);
+	if (!grackle)
+		return;
+
+	pmac_pm_low_suspend = pmac_pm_sleep_grackle;
+}
+
+
+static int __pmac pmac_pm_sleep_core99(void)
+{
+	unsigned long save_l2cr;
+	unsigned long save_l3cr;
+	struct adb_request req;
+	
+	/* Tell PMU what events will wake us up */
+	pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS,
+		0xff, 0xff);
+	pmu_wait_complete(&req);
+	pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_SET_WAKEUP_EVENTS,
+		0, PMU_PWR_WAKEUP_KEY |
+		(pmac_option_lid_wakeup ? PMU_PWR_WAKEUP_LID_OPEN : 0));
+	pmu_wait_complete(&req);
+
+	/* Save the state of the L2 and L3 caches */
+	save_l3cr = _get_L3CR();	/* (returns -1 if not available) */
+	save_l2cr = _get_L2CR();	/* (returns -1 if not available) */
+
+	if (!__fake_sleep) {
+		/* Ask the PMU to put us to sleep */
+		pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
+		pmu_wait_complete(&req);
+	}
+
+	/* The VIA is supposed not to be restored correctly*/
+	pmu_save_via_state();
+
+	/* Shut down various ASICs. There's a chance that we can no longer
+	 * talk to the PMU after this, so I moved it to _after_ sending the
+	 * sleep command to it. Still need to be checked.
+	 */
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1);
+
+	/* Call low-level ASM sleep handler */
+	if (__fake_sleep)
+		mdelay(5000);
+	else
+		low_sleep_handler();
+
+	/* Restore Apple core ASICs state */
+	pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0);
+
+	/* Restore VIA */
+	pmu_restore_via_state();
+
+	/* Restore video */
+	pmac_call_early_video_resume();
+
+	/* Restore L2 cache */
+	if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
+ 		_set_L2CR(save_l2cr);
+	/* Restore L3 cache */
+	if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
+ 		_set_L3CR(save_l3cr);
+	
+	/* Tell PMU we are ready */
+	pmu_unlock();
+	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
+	pmu_wait_complete(&req);
+
+	return 0;
+}
+
+static void __pmac pmac_pm_init_core99(void)
+{
+	pmac_pm_low_suspend = pmac_pm_sleep_core99;
+}
+
+
+/*************************************************************************
+ *
+ * Here are the callbacks interfacing with the common code.
+ *
+ *************************************************************************/
+
+static inline void wakeup_decrementer(void)
+{
+	/* No currently-supported powerbook has a 601,
+	 * so use get_tbl, not native
+	 */
+	last_jiffy_stamp(0) = tb_last_stamp = get_native_tbl();
+	set_dec(1);
+}
+
+static int __pmac pmac_pm_pre_freeze(suspend_state_t state)
+{
+	int ret;
+
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	/* Check if suspend to RAM is possible */
+	if (state == PM_SUSPEND_MEM) {
+		if (pmac_pm_low_suspend == NULL)
+			return -EINVAL;
+		if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)
+			return -EINVAL;
+		if (num_online_cpus() > 1 || cpu_is_offline(0))
+			return -EAGAIN;
+	}
+
+	DBG("Notify (1) old style drivers...\n");
+
+	/* Notify old-style device drivers & userland */
+	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
+	if (ret != PBOOK_SLEEP_OK) {
+		printk(KERN_ERR "Sleep rejected by drivers\n");
+		return -EBUSY;
+	}
+
+	/* Sync the disks. */
+
+	/* XXX It would be nice to have some way to ensure that
+	 * nobody is dirtying any new buffers while we wait. That
+	 * could be achieved using the refrigerator for processes
+	 * that swsusp uses
+	 */
+	DBG("Sync disks...\n");
+	sys_sync();
+
+	//	return (state == PM_SUSPEND_DISK);
+	return 1;
+}
+
+static int __pmac pmac_pm_prepare(suspend_state_t state)
+{
+	int ret;
+
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	/* Sleep can fail now. May not be very robust but useful for
+	 * debugging
+	 */
+	DBG("Notify (2) old style drivers...\n");
+	ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE);
+	if (ret != PBOOK_SLEEP_OK) {
+		printk(KERN_ERR "Driver sleep failed\n");
+		return -EBUSY;
+	}
+
+	/* Allocate room for PCI save */
+	DBG("Alloc PCI stuffs...\n");
+	pbook_alloc_pci_save();
+
+	return 0;
+}
+
+static int __pmac pmac_pm_prepare_irqs(suspend_state_t state)
+{
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	/* That state only applies to suspend to RAM */
+	if (state != PM_SUSPEND_MEM)
+		return 0;
+
+	/* Stop interrupts on openpic */
+	if (pmu_get_model() == PMU_KEYLARGO_BASED)
+		openpic_set_priority(0xf);
+
+	/* Stop preemption */
+	preempt_disable();
+
+	/* Disable clock spreading on some machines */
+	pmac_tweak_clock_spreading(0);
+
+	/* Make sure the decrementer won't interrupt us */
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+	/* Make sure any pending DEC interrupt occurring while we did
+	 * the above didn't re-enable the DEC */
+	mb();
+	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+
+	/* We disable interrupts now and not in the generic code so
+	 * that we entre pmac_pm_finish_irqs() with interrupts still
+	 * off and can properly wakeup decrementer before enabling them.
+	 */
+	local_irq_disable();
+
+	return 0;
+}
+
+static void __pmac pmac_pm_pre_suspend(suspend_state_t state)
+{
+	DBG("%s\n", __FUNCTION__);
+
+	/* Save the state of PCI config space for some slots */
+	pbook_pci_save();
+
+	/* Suspend openpic */
+	if (pmu_get_model() == PMU_KEYLARGO_BASED)
+		openpic_suspend();
+	else
+		pmacpic_suspend();
+
+	/* Giveup the lazy FPU & vec so we don't have to back them
+	 * up from the low level code
+	 */
+	enable_kernel_fp();
+
+#ifdef CONFIG_ALTIVEC
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+		enable_kernel_altivec();
+#endif /* CONFIG_ALTIVEC */
+
+	/* save ASIC state on suspend to disk */
+	if (state == PM_SUSPEND_DISK)
+		pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,2);
+}
+
+static void __pmac pmac_pmdisk_save_state(void)
+{
+	pmac_pm_pre_suspend(PM_SUSPEND_DISK);
+}
+
+static void __pmac pmac_pm_post_suspend(suspend_state_t state)
+{
+	DBG("%s\n", __FUNCTION__);
+
+	/* Restore ASIC state on suspend to disk */
+	if (state == PM_SUSPEND_DISK)
+		pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
+
+	/* Restore the state of PCI config space for some slots */
+	pbook_pci_restore();
+
+	/* Resume openpic */
+	if (pmu_get_model() == PMU_KEYLARGO_BASED)
+		openpic_resume();
+	else
+		pmacpic_resume();
+
+	/* Restore userland MMU context */
+	set_context(current->active_mm->context, current->active_mm->pgd);
+}
+
+static void __pmac pmac_pmdisk_restore_state(void)
+{
+	pmac_pm_post_suspend(PM_SUSPEND_DISK);
+}
+
+static int __pmac pmac_pm_enter(suspend_state_t state)
+{
+	int rc = 0;
+
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	if (state == PM_SUSPEND_MEM) {
+		pmac_pm_pre_suspend(state);
+		rc = pmac_pm_low_suspend();
+		pmac_pm_post_suspend(state);
+		
+	} else if (state == PM_SUSPEND_DISK) {
+		device_shutdown();
+		machine_restart(NULL);
+	} else
+		rc = -EINVAL;
+	return rc;
+}
+
+static void __pmac pmac_pm_finish_irqs(suspend_state_t state)
+{
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	/* That state only applies to suspend to RAM */
+	if (state != PM_SUSPEND_MEM)
+		return;
+
+	/* Force a fetch from the PIC on the first DEC interrupt. */
+	ppc_force_interrupt = 1;
+
+	/* Restart jiffies & scheduling */
+	wakeup_decrementer();
+
+	/* Start interrupts on openpic */
+	if (pmu_get_model() == PMU_KEYLARGO_BASED)
+		openpic_set_priority(0);
+
+	/* Re-enable local CPU interrupts */
+	local_irq_enable();
+	mdelay(10);
+	preempt_enable();
+
+	/* Re-enable clock spreading on some machines */
+	pmac_tweak_clock_spreading(1);
+}
+
+static void __pmac pmac_pm_finish(suspend_state_t state)
+{
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	/* Free PCI save block */
+	pbook_free_pci_save();
+
+}
+
+static void __pmac pmac_pm_post_freeze(suspend_state_t state)
+{
+	DBG("%s(%d)\n", __FUNCTION__, state);
+
+	/* Broadcase old style wakeup */
+	broadcast_wake();
+}
+
+static struct pm_ops pmac_pm_ops  __pmacdata = {
+	.pm_disk_mode	= PM_DISK_PLATFORM,
+	.pre_freeze	= pmac_pm_pre_freeze,
+	.prepare	= pmac_pm_prepare,
+	.prepare_irqs	= pmac_pm_prepare_irqs,
+	.enter		= pmac_pm_enter,
+	.finish_irqs	= pmac_pm_finish_irqs,
+	.finish		= pmac_pm_finish,
+	.post_freeze	= pmac_pm_post_freeze,
+};
+
+static int pmac_pm_init(void)
+{
+	if (_machine != _MACH_Pmac)
+		return 0;
+
+	switch (pmu_get_model()) {
+	case PMU_OHARE_BASED:
+		pmac_pm_init_3400();
+		break;
+	case PMU_HEATHROW_BASED:
+	case PMU_PADDINGTON_BASED:
+		pmac_pm_init_grackle();
+		break;
+	case PMU_KEYLARGO_BASED:
+		pmac_pm_init_core99();
+		break;
+	}
+
+#ifdef CONFIG_SOFTWARE_SUSPEND
+	ppc_md.save_processor_state = pmac_pmdisk_save_state;
+	ppc_md.restore_processor_state = pmac_pmdisk_restore_state;
+#endif
+
+	pm_set_ops(&pmac_pm_ops);
+
+	return 0;
+}
+
+late_initcall(pmac_pm_init);
Index: linux-work/arch/ppc/platforms/pmac_setup.c
===================================================================
--- linux-work.orig/arch/ppc/platforms/pmac_setup.c	2005-05-02 10:48:08.000000000 +1000
+++ linux-work/arch/ppc/platforms/pmac_setup.c	2005-05-28 10:30:21.000000000 +1000
@@ -423,68 +423,6 @@
 #endif
 }
 
-static int initializing = 1;
-/* TODO: Merge the suspend-to-ram with the common code !!!
- * currently, this is a stub implementation for suspend-to-disk
- * only
- */
-
-#ifdef CONFIG_SOFTWARE_SUSPEND
-
-static int pmac_pm_prepare(suspend_state_t state)
-{
-	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-	return 0;
-}
-
-static int pmac_pm_enter(suspend_state_t state)
-{
-	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-	/* Giveup the lazy FPU & vec so we don't have to back them
-	 * up from the low level code
-	 */
-	enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
-	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
-		enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
-	return 0;
-}
-
-static int pmac_pm_finish(suspend_state_t state)
-{
-	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
-	/* Restore userland MMU context */
-	set_context(current->active_mm->context, current->active_mm->pgd);
-
-	return 0;
-}
-
-static struct pm_ops pmac_pm_ops = {
-	.pm_disk_mode	= PM_DISK_SHUTDOWN,
-	.prepare	= pmac_pm_prepare,
-	.enter		= pmac_pm_enter,
-	.finish		= pmac_pm_finish,
-};
-
-#endif /* CONFIG_SOFTWARE_SUSPEND */
-
-static int pmac_late_init(void)
-{
-	initializing = 0;
-#ifdef CONFIG_SOFTWARE_SUSPEND
-	pm_set_ops(&pmac_pm_ops);
-#endif /* CONFIG_SOFTWARE_SUSPEND */
-	return 0;
-}
-
-late_initcall(pmac_late_init);
-
 /* can't be __init - can be called whenever a disk is first accessed */
 void __pmac
 note_bootable_part(dev_t dev, int part, int goodness)
@@ -492,7 +430,7 @@
 	static int found_boot = 0;
 	char *p;
 
-	if (!initializing)
+	if (system_state != SYSTEM_BOOTING)
 		return;
 	if ((goodness <= current_root_goodness) &&
 	    ROOT_DEV != DEFAULT_ROOT_DEVICE)
Index: linux-work/drivers/base/power/suspend.c
===================================================================
--- linux-work.orig/drivers/base/power/suspend.c	2005-05-26 13:27:08.000000000 +1000
+++ linux-work/drivers/base/power/suspend.c	2005-05-28 10:30:21.000000000 +1000
@@ -113,8 +113,19 @@
 		put_device(dev);
 	}
 	up(&dpm_list_sem);
-	if (error)
+	if (error) {
+		/* we failed... before resuming, bring back devices from
+		 * dpm_off_irq list back to main dpm_off list, we do want
+		 * to call resume() on them, in case they partially suspended
+		 * despite returning -EAGAIN
+		 */
+		while (!list_empty(&dpm_off_irq)) {
+			struct list_head * entry = dpm_off_irq.next;
+			list_del(entry);
+			list_add(entry, &dpm_off);
+		}
 		dpm_resume();
+	}
 	up(&dpm_sem);
 	return error;
 }
Index: linux-work/drivers/macintosh/via-pmu.c
===================================================================
--- linux-work.orig/drivers/macintosh/via-pmu.c	2005-05-28 10:30:17.000000000 +1000
+++ linux-work/drivers/macintosh/via-pmu.c	2005-05-28 10:30:21.000000000 +1000
@@ -14,10 +14,7 @@
  * THIS DRIVER IS BECOMING A TOTAL MESS !
  *  - Cleanup atomically disabling reply to PMU events after
  *    a sleep or a freq. switch
- *  - Move sleep code out of here to pmac_pm, merge into new
- *    common PM infrastructure
  *  - Move backlight code out as well
- *  - Save/Restore PCI space properly
  *
  */
 #include <stdarg.h>
@@ -45,8 +42,6 @@
 #include <linux/device.h>
 #include <linux/sysdev.h>
 #include <linux/suspend.h>
-#include <linux/syscalls.h>
-#include <linux/cpu.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
@@ -54,11 +49,11 @@
 #include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
-#include <asm/pmac_feature.h>
 #include <asm/uaccess.h>
-#include <asm/mmu_context.h>
 #include <asm/cputable.h>
 #include <asm/time.h>
+#include <asm/pmac_feature.h>
+
 #ifdef CONFIG_PMAC_BACKLIGHT
 #include <asm/backlight.h>
 #endif
@@ -70,7 +65,6 @@
 /* Some compile options */
 #undef SUSPEND_USES_PMU
 #define DEBUG_SLEEP
-#undef HACKED_PCI_SAVE
 
 /* Misc minor number allocated for /dev/pmu */
 #define PMU_MINOR		154
@@ -155,12 +149,12 @@
 static u8 pmu_intr_mask;
 static int pmu_version;
 static int drop_interrupts;
-#ifdef CONFIG_PMAC_PBOOK
-static int option_lid_wakeup = 1;
-static int sleep_in_progress;
-#endif /* CONFIG_PMAC_PBOOK */
 static unsigned long async_req_locks;
 static unsigned int pmu_irq_stats[11];
+static int pmu_sys_suspended = 0;
+
+/* from pmac_pm ... */
+extern int pmac_option_lid_wakeup;
 
 static struct proc_dir_entry *proc_pmu_root;
 static struct proc_dir_entry *proc_pmu_info;
@@ -168,7 +162,6 @@
 static struct proc_dir_entry *proc_pmu_options;
 static int option_server_mode;
 
-#ifdef CONFIG_PMAC_PBOOK
 int pmu_battery_count;
 int pmu_cur_battery;
 unsigned int pmu_power_flags;
@@ -176,14 +169,11 @@
 static int query_batt_timer = BATTERY_POLLING_COUNT;
 static struct adb_request batt_req;
 static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES];
-#endif /* CONFIG_PMAC_PBOOK */
 
 #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
 extern int disable_kernel_backlight;
 #endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
 
-int __fake_sleep;
-int asleep;
 struct notifier_block *sleep_notifier_list;
 
 #ifdef CONFIG_ADB
@@ -210,11 +200,9 @@
 static int pmu_set_backlight_level(int level, void* data);
 static int pmu_set_backlight_enable(int on, int level, void* data);
 #endif /* CONFIG_PMAC_BACKLIGHT */
-#ifdef CONFIG_PMAC_PBOOK
 static void pmu_pass_intr(unsigned char *data, int len);
 static int proc_get_batt(char *page, char **start, off_t off,
 			int count, int *eof, void *data);
-#endif /* CONFIG_PMAC_PBOOK */
 static int proc_read_options(char *page, char **start, off_t off,
 			int count, int *eof, void *data);
 static int proc_write_options(struct file *file, const char __user *buffer,
@@ -232,10 +220,6 @@
 };
 #endif /* CONFIG_ADB */
 
-extern void low_sleep_handler(void);
-extern void enable_kernel_altivec(void);
-extern void enable_kernel_fp(void);
-
 #ifdef DEBUG_SLEEP
 int pmu_polled_request(struct adb_request *req);
 int pmu_wink(struct adb_request *req);
@@ -407,9 +391,7 @@
 
 	bright_req_1.complete = 1;
 	bright_req_2.complete = 1;
-#ifdef CONFIG_PMAC_PBOOK
 	batt_req.complete = 1;
-#endif
 
 #ifdef CONFIG_PPC32
 	if (pmu_kind == PMU_KEYLARGO_BASED)
@@ -468,7 +450,6 @@
 	register_backlight_controller(&pmu_backlight_controller, NULL, "pmu");
 #endif /* CONFIG_PMAC_BACKLIGHT */
 
-#ifdef CONFIG_PMAC_PBOOK
   	if (machine_is_compatible("AAPL,3400/2400") ||
   		machine_is_compatible("AAPL,3500")) {
 		int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
@@ -496,11 +477,9 @@
 				pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART;
 		}
 	}
-#endif /* CONFIG_PMAC_PBOOK */
 	/* Create /proc/pmu */
 	proc_pmu_root = proc_mkdir("pmu", NULL);
 	if (proc_pmu_root) {
-#ifdef CONFIG_PMAC_PBOOK
 		int i;
 
 		for (i=0; i<pmu_battery_count; i++) {
@@ -509,7 +488,6 @@
 			proc_pmu_batt[i] = create_proc_read_entry(title, 0, proc_pmu_root,
 						proc_get_batt, (void *)i);
 		}
-#endif /* CONFIG_PMAC_PBOOK */
 
 		proc_pmu_info = create_proc_read_entry("info", 0, proc_pmu_root,
 					proc_get_info, NULL);
@@ -595,17 +573,6 @@
 	return pmu_kind;
 }
 
-#ifndef CONFIG_PPC64
-static inline void wakeup_decrementer(void)
-{
-	set_dec(tb_ticks_per_jiffy);
-	/* No currently-supported powerbook has a 601,
-	 * so use get_tbl, not native
-	 */
-	last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
-}
-#endif
-
 static void pmu_set_server_mode(int server_mode)
 {
 	struct adb_request req;
@@ -629,7 +596,6 @@
 	pmu_wait_complete(&req);
 }
 
-#ifdef CONFIG_PMAC_PBOOK
 
 /* This new version of the code for 2400/3400/3500 powerbooks
  * is inspired from the implementation in gkrellm-pmu
@@ -803,6 +769,8 @@
 static void __pmac
 query_battery_state(void)
 {
+	if (pmu_sys_suspended)
+		return;
 	if (test_and_set_bit(0, &async_req_locks))
 		return;
 	if (pmu_kind == PMU_OHARE_BASED)
@@ -813,8 +781,6 @@
 			2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1);
 }
 
-#endif /* CONFIG_PMAC_PBOOK */
-
 static int __pmac
 proc_get_info(char *page, char **start, off_t off,
 		int count, int *eof, void *data)
@@ -823,11 +789,9 @@
 
 	p += sprintf(p, "PMU driver version     : %d\n", PMU_DRIVER_VERSION);
 	p += sprintf(p, "PMU firmware version   : %02x\n", pmu_version);
-#ifdef CONFIG_PMAC_PBOOK
 	p += sprintf(p, "AC Power               : %d\n",
 		((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0));
 	p += sprintf(p, "Battery count          : %d\n", pmu_battery_count);
-#endif /* CONFIG_PMAC_PBOOK */
 
 	return p - page;
 }
@@ -859,7 +823,6 @@
 	return p - page;
 }
 
-#ifdef CONFIG_PMAC_PBOOK
 static int __pmac
 proc_get_batt(char *page, char **start, off_t off,
 		int count, int *eof, void *data)
@@ -883,7 +846,6 @@
 
 	return p - page;
 }
-#endif /* CONFIG_PMAC_PBOOK */
 
 static int __pmac
 proc_read_options(char *page, char **start, off_t off,
@@ -891,11 +853,9 @@
 {
 	char *p = page;
 
-#ifdef CONFIG_PMAC_PBOOK
 	if (pmu_kind == PMU_KEYLARGO_BASED &&
 	    pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
-		p += sprintf(p, "lid_wakeup=%d\n", option_lid_wakeup);
-#endif /* CONFIG_PMAC_PBOOK */
+		p += sprintf(p, "lid_wakeup=%d\n", pmac_option_lid_wakeup);
 	if (pmu_kind == PMU_KEYLARGO_BASED)
 		p += sprintf(p, "server_mode=%d\n", option_server_mode);
 
@@ -932,12 +892,10 @@
 	*(val++) = 0;
 	while(*val == ' ')
 		val++;
-#ifdef CONFIG_PMAC_PBOOK
 	if (pmu_kind == PMU_KEYLARGO_BASED &&
 	    pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0)
 		if (!strcmp(label, "lid_wakeup"))
-			option_lid_wakeup = ((*val) == '1');
-#endif /* CONFIG_PMAC_PBOOK */
+			pmac_option_lid_wakeup = ((*val) == '1');
 	if (pmu_kind == PMU_KEYLARGO_BASED && !strcmp(label, "server_mode")) {
 		int new_value;
 		new_value = ((*val) == '1');
@@ -1344,7 +1302,6 @@
 	unsigned char ints, pirq;
 	int i = 0;
 
-	asleep = 0;
 	if (drop_interrupts || len < 1) {
 		adb_int_pending = 0;
 		pmu_irq_stats[8]++;
@@ -1432,7 +1389,6 @@
 	}
 	/* Tick interrupt */
 	else if ((1 << pirq) & PMU_INT_TICK) {
-#ifdef CONFIG_PMAC_PBOOK
 		/* Environement or tick interrupt, query batteries */
 		if (pmu_battery_count) {
 			if ((--query_batt_timer) == 0) {
@@ -1447,7 +1403,6 @@
 		pmu_pass_intr(data, len);
 	} else {
 	       pmu_pass_intr(data, len);
-#endif /* CONFIG_PMAC_PBOOK */
 	}
 	goto next;
 }
@@ -1692,6 +1647,8 @@
 	
 	if (vias == NULL)
 		return -ENODEV;
+	if (pmu_sys_suspended)
+		return -EIO;
 
 	if (on) {
 		pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT,
@@ -1719,6 +1676,8 @@
 {
 	if (vias == NULL)
 		return -ENODEV;
+	if (pmu_sys_suspended)
+		return -EIO;
 
 	if (test_and_set_bit(1, &async_req_locks))
 		return -EAGAIN;
@@ -2062,201 +2021,9 @@
 	return -1;
 }
 
-#ifdef CONFIG_PMAC_PBOOK
-
-static LIST_HEAD(sleep_notifiers);
-
-int
-pmu_register_sleep_notifier(struct pmu_sleep_notifier *n)
-{
-	struct list_head *list;
-	struct pmu_sleep_notifier *notifier;
-
-	for (list = sleep_notifiers.next; list != &sleep_notifiers;
-	     list = list->next) {
-		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		if (n->priority > notifier->priority)
-			break;
-	}
-	__list_add(&n->list, list->prev, list);
-	return 0;
-}
-
-int
-pmu_unregister_sleep_notifier(struct pmu_sleep_notifier* n)
-{
-	if (n->list.next == 0)
-		return -ENOENT;
-	list_del(&n->list);
-	n->list.next = NULL;
-	return 0;
-}
-
-/* Sleep is broadcast last-to-first */
-static int __pmac
-broadcast_sleep(int when, int fallback)
-{
-	int ret = PBOOK_SLEEP_OK;
-	struct list_head *list;
-	struct pmu_sleep_notifier *notifier;
-
-	for (list = sleep_notifiers.prev; list != &sleep_notifiers;
-	     list = list->prev) {
-		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		ret = notifier->notifier_call(notifier, when);
-		if (ret != PBOOK_SLEEP_OK) {
-			printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n",
-			       when, notifier, notifier->notifier_call);
-			for (; list != &sleep_notifiers; list = list->next) {
-				notifier = list_entry(list, struct pmu_sleep_notifier, list);
-				notifier->notifier_call(notifier, fallback);
-			}
-			return ret;
-		}
-	}
-	return ret;
-}
-
-/* Wake is broadcast first-to-last */
-static int __pmac
-broadcast_wake(void)
-{
-	int ret = PBOOK_SLEEP_OK;
-	struct list_head *list;
-	struct pmu_sleep_notifier *notifier;
-
-	for (list = sleep_notifiers.next; list != &sleep_notifiers;
-	     list = list->next) {
-		notifier = list_entry(list, struct pmu_sleep_notifier, list);
-		notifier->notifier_call(notifier, PBOOK_WAKE);
-	}
-	return ret;
-}
-
-/*
- * This struct is used to store config register values for
- * PCI devices which may get powered off when we sleep.
- */
-static struct pci_save {
-#ifndef HACKED_PCI_SAVE
-	u16	command;
-	u16	cache_lat;
-	u16	intr;
-	u32	rom_address;
-#else
-	u32	config[16];
-#endif	
-} *pbook_pci_saves;
-static int pbook_npci_saves;
-
-static void __pmac
-pbook_alloc_pci_save(void)
-{
-	int npci;
-	struct pci_dev *pd = NULL;
-
-	npci = 0;
-	while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-		++npci;
-	}
-	if (npci == 0)
-		return;
-	pbook_pci_saves = (struct pci_save *)
-		kmalloc(npci * sizeof(struct pci_save), GFP_KERNEL);
-	pbook_npci_saves = npci;
-}
-
-static void __pmac
-pbook_free_pci_save(void)
-{
-	if (pbook_pci_saves == NULL)
-		return;
-	kfree(pbook_pci_saves);
-	pbook_pci_saves = NULL;
-	pbook_npci_saves = 0;
-}
 
-static void __pmac
-pbook_pci_save(void)
-{
-	struct pci_save *ps = pbook_pci_saves;
-	struct pci_dev *pd = NULL;
-	int npci = pbook_npci_saves;
-	
-	if (ps == NULL)
-		return;
-
-	while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-		if (npci-- == 0)
-			return;
-#ifndef HACKED_PCI_SAVE
-		pci_read_config_word(pd, PCI_COMMAND, &ps->command);
-		pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat);
-		pci_read_config_word(pd, PCI_INTERRUPT_LINE, &ps->intr);
-		pci_read_config_dword(pd, PCI_ROM_ADDRESS, &ps->rom_address);
-#else
-		int i;
-		for (i=1;i<16;i++)
-			pci_read_config_dword(pd, i<<4, &ps->config[i]);
-#endif
-		++ps;
-	}
-}
-
-/* For this to work, we must take care of a few things: If gmac was enabled
- * during boot, it will be in the pci dev list. If it's disabled at this point
- * (and it will probably be), then you can't access it's config space.
- */
-static void __pmac
-pbook_pci_restore(void)
-{
-	u16 cmd;
-	struct pci_save *ps = pbook_pci_saves - 1;
-	struct pci_dev *pd = NULL;
-	int npci = pbook_npci_saves;
-	int j;
-
-	while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
-#ifdef HACKED_PCI_SAVE
-		int i;
-		if (npci-- == 0)
-			return;
-		ps++;
-		for (i=2;i<16;i++)
-			pci_write_config_dword(pd, i<<4, ps->config[i]);
-		pci_write_config_dword(pd, 4, ps->config[1]);
-#else
-		if (npci-- == 0)
-			return;
-		ps++;
-		if (ps->command == 0)
-			continue;
-		pci_read_config_word(pd, PCI_COMMAND, &cmd);
-		if ((ps->command & ~cmd) == 0)
-			continue;
-		switch (pd->hdr_type) {
-		case PCI_HEADER_TYPE_NORMAL:
-			for (j = 0; j < 6; ++j)
-				pci_write_config_dword(pd,
-					PCI_BASE_ADDRESS_0 + j*4,
-					pd->resource[j].start);
-			pci_write_config_dword(pd, PCI_ROM_ADDRESS,
-				ps->rom_address);
-			pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
-				ps->cache_lat);
-			pci_write_config_word(pd, PCI_INTERRUPT_LINE,
-				ps->intr);
-			pci_write_config_word(pd, PCI_COMMAND, ps->command);
-			break;
-		}
-#endif	
-	}
-}
-
-#ifdef DEBUG_SLEEP
 /* N.B. This doesn't work on the 3400 */
-void  __pmac
-pmu_blink(int n)
+void  __pmac pmu_blink(int n)
 {
 	struct adb_request req;
 
@@ -2288,7 +2055,6 @@
 	}
 	mdelay(50);
 }
-#endif
 
 /*
  * Put the powerbook to sleep.
@@ -2296,8 +2062,7 @@
  
 static u32 save_via[8] __pmacdata;
 
-static void __pmac
-save_via_state(void)
+void __pmac pmu_save_via_state(void)
 {
 	save_via[0] = in_8(&via[ANH]);
 	save_via[1] = in_8(&via[DIRA]);
@@ -2308,8 +2073,7 @@
 	save_via[6] = in_8(&via[T1CL]);
 	save_via[7] = in_8(&via[T1CH]);
 }
-static void __pmac
-restore_via_state(void)
+void __pmac pmu_restore_via_state(void)
 {
 	out_8(&via[ANH], save_via[0]);
 	out_8(&via[DIRA], save_via[1]);
@@ -2324,390 +2088,6 @@
 	out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
 }
 
-static int __pmac
-pmac_suspend_devices(void)
-{
-	int ret;
-
-	pm_prepare_console();
-	
-	/* Notify old-style device drivers & userland */
-	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
-	if (ret != PBOOK_SLEEP_OK) {
-		printk(KERN_ERR "Sleep rejected by drivers\n");
-		return -EBUSY;
-	}
-
-	/* Sync the disks. */
-	/* XXX It would be nice to have some way to ensure that
-	 * nobody is dirtying any new buffers while we wait. That
-	 * could be achieved using the refrigerator for processes
-	 * that swsusp uses
-	 */
-	sys_sync();
-
-	/* Sleep can fail now. May not be very robust but useful for debugging */
-	ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE);
-	if (ret != PBOOK_SLEEP_OK) {
-		printk(KERN_ERR "Driver sleep failed\n");
-		return -EBUSY;
-	}
-
-	/* Send suspend call to devices, hold the device core's dpm_sem */
-	ret = device_suspend(PMSG_SUSPEND);
-	if (ret) {
-		broadcast_wake();
-		printk(KERN_ERR "Driver sleep failed\n");
-		return -EBUSY;
-	}
-
-	/* Disable clock spreading on some machines */
-	pmac_tweak_clock_spreading(0);
-
-	/* Stop preemption */
-	preempt_disable();
-
-	/* Make sure the decrementer won't interrupt us */
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-	/* Make sure any pending DEC interrupt occurring while we did
-	 * the above didn't re-enable the DEC */
-	mb();
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-
-	/* We can now disable MSR_EE. This code of course works properly only
-	 * on UP machines... For SMP, if we ever implement sleep, we'll have to
-	 * stop the "other" CPUs way before we do all that stuff.
-	 */
-	local_irq_disable();
-
-	/* Broadcast power down irq
-	 * This isn't that useful in most cases (only directly wired devices can
-	 * use this but still... This will take care of sysdev's as well, so
-	 * we exit from here with local irqs disabled and PIC off.
-	 */
-	ret = device_power_down(PMSG_SUSPEND);
-	if (ret) {
-		wakeup_decrementer();
-		local_irq_enable();
-		preempt_enable();
-		device_resume();
-		broadcast_wake();
-		printk(KERN_ERR "Driver powerdown failed\n");
-		return -EBUSY;
-	}
-
-	/* Wait for completion of async backlight requests */
-	while (!bright_req_1.complete || !bright_req_2.complete ||
-			!batt_req.complete)
-		pmu_poll();
-
-	/* Giveup the lazy FPU & vec so we don't have to back them
-	 * up from the low level code
-	 */
-	enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
-	if (cpu_has_feature(CPU_FTR_ALTIVEC))
-		enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
-	return 0;
-}
-
-static int __pmac
-pmac_wakeup_devices(void)
-{
-	mdelay(100);
-
-	/* Power back up system devices (including the PIC) */
-	device_power_up();
-
-	/* Force a poll of ADB interrupts */
-	adb_int_pending = 1;
-	via_pmu_interrupt(0, NULL, NULL);
-
-	/* Restart jiffies & scheduling */
-	wakeup_decrementer();
-
-	/* Re-enable local CPU interrupts */
-	local_irq_enable();
-	mdelay(10);
-	preempt_enable();
-
-	/* Re-enable clock spreading on some machines */
-	pmac_tweak_clock_spreading(1);
-
-	/* Resume devices */
-	device_resume();
-
-	/* Notify old style drivers */
-	broadcast_wake();
-
-	pm_restore_console();
-
-	return 0;
-}
-
-#define	GRACKLE_PM	(1<<7)
-#define GRACKLE_DOZE	(1<<5)
-#define	GRACKLE_NAP	(1<<4)
-#define	GRACKLE_SLEEP	(1<<3)
-
-int __pmac
-powerbook_sleep_grackle(void)
-{
-	unsigned long save_l2cr;
-	unsigned short pmcr1;
-	struct adb_request req;
-	int ret;
-	struct pci_dev *grackle;
-
-	grackle = pci_find_slot(0, 0);
-	if (!grackle)
-		return -ENODEV;
-
-	ret = pmac_suspend_devices();
-	if (ret) {
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-	
-	/* Turn off various things. Darwin does some retry tests here... */
-	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE);
-	pmu_wait_complete(&req);
-	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
-		PMU_POW_OFF|PMU_POW_BACKLIGHT|PMU_POW_IRLED|PMU_POW_MEDIABAY);
-	pmu_wait_complete(&req);
-
-	/* For 750, save backside cache setting and disable it */
-	save_l2cr = _get_L2CR();	/* (returns -1 if not available) */
-
-	if (!__fake_sleep) {
-		/* Ask the PMU to put us to sleep */
-		pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
-		pmu_wait_complete(&req);
-	}
-
-	/* The VIA is supposed not to be restored correctly*/
-	save_via_state();
-	/* We shut down some HW */
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);
-
-	pci_read_config_word(grackle, 0x70, &pmcr1);
-	/* Apparently, MacOS uses NAP mode for Grackle ??? */
-	pmcr1 &= ~(GRACKLE_DOZE|GRACKLE_SLEEP); 
-	pmcr1 |= GRACKLE_PM|GRACKLE_NAP;
-	pci_write_config_word(grackle, 0x70, pmcr1);
-
-	/* Call low-level ASM sleep handler */
-	if (__fake_sleep)
-		mdelay(5000);
-	else
-		low_sleep_handler();
-
-	/* We're awake again, stop grackle PM */
-	pci_read_config_word(grackle, 0x70, &pmcr1);
-	pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); 
-	pci_write_config_word(grackle, 0x70, pmcr1);
-
-	/* Make sure the PMU is idle */
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
-	restore_via_state();
-	
-	/* Restore L2 cache */
-	if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
- 		_set_L2CR(save_l2cr);
-	
-	/* Restore userland MMU context */
-	set_context(current->active_mm->context, current->active_mm->pgd);
-
-	/* Power things up */
-	pmu_unlock();
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
-	pmu_wait_complete(&req);
-	pmu_request(&req, NULL, 2, PMU_POWER_CTRL0,
-			PMU_POW0_ON|PMU_POW0_HARD_DRIVE);
-	pmu_wait_complete(&req);
-	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
-			PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY);
-	pmu_wait_complete(&req);
-
-	pmac_wakeup_devices();
-
-	return 0;
-}
-
-static int __pmac
-powerbook_sleep_Core99(void)
-{
-	unsigned long save_l2cr;
-	unsigned long save_l3cr;
-	struct adb_request req;
-	int ret;
-	
-	if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0) {
-		printk(KERN_ERR "Sleep mode not supported on this machine\n");
-		return -ENOSYS;
-	}
-
-	if (num_online_cpus() > 1 || cpu_is_offline(0))
-		return -EAGAIN;
-
-	ret = pmac_suspend_devices();
-	if (ret) {
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-
-	/* Stop environment and ADB interrupts */
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
-	pmu_wait_complete(&req);
-
-	/* Tell PMU what events will wake us up */
-	pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS,
-		0xff, 0xff);
-	pmu_wait_complete(&req);
-	pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_SET_WAKEUP_EVENTS,
-		0, PMU_PWR_WAKEUP_KEY |
-		(option_lid_wakeup ? PMU_PWR_WAKEUP_LID_OPEN : 0));
-	pmu_wait_complete(&req);
-
-	/* Save the state of the L2 and L3 caches */
-	save_l3cr = _get_L3CR();	/* (returns -1 if not available) */
-	save_l2cr = _get_L2CR();	/* (returns -1 if not available) */
-
-	if (!__fake_sleep) {
-		/* Ask the PMU to put us to sleep */
-		pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
-		pmu_wait_complete(&req);
-	}
-
-	/* The VIA is supposed not to be restored correctly*/
-	save_via_state();
-
-	/* Shut down various ASICs. There's a chance that we can no longer
-	 * talk to the PMU after this, so I moved it to _after_ sending the
-	 * sleep command to it. Still need to be checked.
-	 */
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 1);
-
-	/* Call low-level ASM sleep handler */
-	if (__fake_sleep)
-		mdelay(5000);
-	else
-		low_sleep_handler();
-
-	/* Restore Apple core ASICs state */
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, 0);
-
-	/* Restore VIA */
-	restore_via_state();
-
-	/* Restore video */
-	pmac_call_early_video_resume();
-
-	/* Restore L2 cache */
-	if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
- 		_set_L2CR(save_l2cr);
-	/* Restore L3 cache */
-	if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
- 		_set_L3CR(save_l3cr);
-	
-	/* Restore userland MMU context */
-	set_context(current->active_mm->context, current->active_mm->pgd);
-
-	/* Tell PMU we are ready */
-	pmu_unlock();
-	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
-	pmu_wait_complete(&req);
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
-	pmu_wait_complete(&req);
-
-	pmac_wakeup_devices();
-
-	return 0;
-}
-
-#define PB3400_MEM_CTRL		0xf8000000
-#define PB3400_MEM_CTRL_SLEEP	0x70
-
-static int __pmac
-powerbook_sleep_3400(void)
-{
-	int ret, i, x;
-	unsigned int hid0;
-	unsigned long p;
-	struct adb_request sleep_req;
-	void __iomem *mem_ctrl;
-	unsigned int __iomem *mem_ctrl_sleep;
-
-	/* first map in the memory controller registers */
-	mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
-	if (mem_ctrl == NULL) {
-		printk("powerbook_sleep_3400: ioremap failed\n");
-		return -ENOMEM;
-	}
-	mem_ctrl_sleep = mem_ctrl + PB3400_MEM_CTRL_SLEEP;
-
-	/* Allocate room for PCI save */
-	pbook_alloc_pci_save();
-
-	ret = pmac_suspend_devices();
-	if (ret) {
-		pbook_free_pci_save();
-		printk(KERN_ERR "Sleep rejected by devices\n");
-		return ret;
-	}
-
-	/* Save the state of PCI config space for some slots */
-	pbook_pci_save();
-
-	/* Set the memory controller to keep the memory refreshed
-	   while we're asleep */
-	for (i = 0x403f; i >= 0x4000; --i) {
-		out_be32(mem_ctrl_sleep, i);
-		do {
-			x = (in_be32(mem_ctrl_sleep) >> 16) & 0x3ff;
-		} while (x == 0);
-		if (x >= 0x100)
-			break;
-	}
-
-	/* Ask the PMU to put us to sleep */
-	pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
-	while (!sleep_req.complete)
-		mb();
-
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,1);
-
-	/* displacement-flush the L2 cache - necessary? */
-	for (p = KERNELBASE; p < KERNELBASE + 0x100000; p += 0x1000)
-		i = *(volatile int *)p;
-	asleep = 1;
-
-	/* Put the CPU into sleep mode */
-	asm volatile("mfspr %0,1008" : "=r" (hid0) :);
-	hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;
-	asm volatile("mtspr 1008,%0" : : "r" (hid0));
-	_nmask_and_or_msr(0, MSR_POW | MSR_EE);
-	udelay(10);
-
-	/* OK, we're awake again, start restoring things */
-	out_be32(mem_ctrl_sleep, 0x3f);
-	pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,0);
-	pbook_pci_restore();
-	pmu_unlock();
-
-	/* wait for the PMU interrupt sequence to complete */
-	while (asleep)
-		mb();
-
-	pmac_wakeup_devices();
-	pbook_free_pci_save();
-	iounmap(mem_ctrl);
-
-	return 0;
-}
 
 /*
  * Support for /dev/pmu device
@@ -2896,24 +2276,10 @@
 	case PMU_IOC_SLEEP:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
-		if (sleep_in_progress)
-			return -EBUSY;
-		sleep_in_progress = 1;
-		switch (pmu_kind) {
-		case PMU_OHARE_BASED:
-			error = powerbook_sleep_3400();
-			break;
-		case PMU_HEATHROW_BASED:
-		case PMU_PADDINGTON_BASED:
-			error = powerbook_sleep_grackle();
-			break;
-		case PMU_KEYLARGO_BASED:
-			error = powerbook_sleep_Core99();
-			break;
-		default:
-			error = -ENOSYS;
-		}
-		sleep_in_progress = 0;
+		if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)
+			error = pm_suspend(PM_SUSPEND_DISK);		
+		else
+			error = pm_suspend(PM_SUSPEND_MEM);		
 		return error;
 	case PMU_IOC_CAN_SLEEP:
 		if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) < 0)
@@ -2926,8 +2292,6 @@
 	 * the fbdev
 	 */
 	case PMU_IOC_GET_BACKLIGHT:
-		if (sleep_in_progress)
-			return -EBUSY;
 		error = get_backlight_level();
 		if (error < 0)
 			return error;
@@ -2935,8 +2299,6 @@
 	case PMU_IOC_SET_BACKLIGHT:
 	{
 		__u32 value;
-		if (sleep_in_progress)
-			return -EBUSY;
 		error = get_user(value, argp);
 		if (!error)
 			error = set_backlight_level(value);
@@ -2983,7 +2345,6 @@
 	if (misc_register(&pmu_device) < 0)
 		printk(KERN_ERR "via-pmu: cannot register misc device.\n");
 }
-#endif /* CONFIG_PMAC_PBOOK */
 
 #ifdef DEBUG_SLEEP
 static inline void  __pmac
@@ -3065,17 +2426,29 @@
 
 #ifdef CONFIG_PM
 
-static int pmu_sys_suspended = 0;
-
 static int pmu_sys_suspend(struct sys_device *sysdev, pm_message_t state)
 {
-	if (state != PM_SUSPEND_DISK || pmu_sys_suspended)
+	struct adb_request req;
+
+	if (pmu_sys_suspended)
 		return 0;
 
+	/* Stop environment interrupts */
+	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
+	pmu_wait_complete(&req);
+
 	/* Suspend PMU event interrupts */
 	pmu_suspend();
 
+	/* Mark driver suspended */
 	pmu_sys_suspended = 1;
+
+	/* Wait for completion of async backlight requests */
+	while (!bright_req_1.complete || !bright_req_2.complete ||
+			!batt_req.complete)
+		pmu_poll();
+	
+
 	return 0;
 }
 
@@ -3086,6 +2459,10 @@
 	if (!pmu_sys_suspended)
 		return 0;
 
+	/* Restart environment interrupts */ 
+	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
+	pmu_wait_complete(&req);
+
 	/* Tell PMU we are ready */
 	pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
 	pmu_wait_complete(&req);
@@ -3093,6 +2470,7 @@
 	/* Resume PMU event interrupts */
 	pmu_resume();
 
+	/* Mark driver ready for async requests */
 	pmu_sys_suspended = 0;
 
 	return 0;
@@ -3151,12 +2529,8 @@
 EXPORT_SYMBOL(pmu_i2c_stdsub_write);
 EXPORT_SYMBOL(pmu_i2c_simple_read);
 EXPORT_SYMBOL(pmu_i2c_simple_write);
-#ifdef CONFIG_PMAC_PBOOK
-EXPORT_SYMBOL(pmu_register_sleep_notifier);
-EXPORT_SYMBOL(pmu_unregister_sleep_notifier);
 EXPORT_SYMBOL(pmu_enable_irled);
 EXPORT_SYMBOL(pmu_battery_count);
 EXPORT_SYMBOL(pmu_batteries);
 EXPORT_SYMBOL(pmu_power_flags);
-#endif /* CONFIG_PMAC_PBOOK */
 
Index: linux-work/include/asm-ppc/machdep.h
===================================================================
--- linux-work.orig/include/asm-ppc/machdep.h	2005-05-02 10:49:57.000000000 +1000
+++ linux-work/include/asm-ppc/machdep.h	2005-05-28 10:30:21.000000000 +1000
@@ -110,6 +110,12 @@
 	 */
 	long (*feature_call)(unsigned int feature, ...);
 
+#ifdef CONFIG_SOFTWARE_SUSPEND
+	int (*arch_prepare_suspend)(void);
+	void (*save_processor_state)(void);
+	void (*restore_processor_state)(void);
+#endif /* CONFIG_SOFTWARE_SUSPEND */
+
 #ifdef CONFIG_SMP
 	/* functions for dealing with other cpus */
 	struct smp_ops_t *smp_ops;
Index: linux-work/include/asm-ppc/suspend.h
===================================================================
--- linux-work.orig/include/asm-ppc/suspend.h	2005-05-02 10:49:59.000000000 +1000
+++ linux-work/include/asm-ppc/suspend.h	2005-05-28 10:30:21.000000000 +1000
@@ -1,12 +1,44 @@
+#ifndef __PPC_SUSPEND_H
+#define __PPC_SUSPEND_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/machdep.h>
+
+
+#ifdef CONFIG_SOFTWARE_SUSPEND
 static inline int arch_prepare_suspend(void)
 {
+	if (ppc_md.arch_prepare_suspend)
+		return ppc_md.arch_prepare_suspend();
 	return 0;
 }
 
 static inline void save_processor_state(void)
 {
+	if (ppc_md.save_processor_state)
+		return ppc_md.save_processor_state();
 }
 
 static inline void restore_processor_state(void)
 {
+	if (ppc_md.restore_processor_state)
+		return ppc_md.restore_processor_state();
 }
+#else
+static inline int arch_prepare_suspend(void)
+{
+	return 0;
+}
+
+static inline void save_processor_state(void)
+{
+}
+
+static inline void restore_processor_state(void)
+{
+}
+#endif
+
+
+#endif /* __PPC_SUSPEND_H */
Index: linux-work/include/linux/pm.h
===================================================================
--- linux-work.orig/include/linux/pm.h	2005-05-02 10:50:24.000000000 +1000
+++ linux-work/include/linux/pm.h	2005-05-28 10:30:21.000000000 +1000
@@ -169,9 +169,38 @@
 
 struct pm_ops {
 	suspend_disk_method_t pm_disk_mode;
+	
+	/* Call before process freezing. If returns 0, then no freeze
+	 * should be done, if 1, freeze, negative -> error
+	 */
+	int (*pre_freeze)(suspend_state_t state);
+
+	/* called before devices are suspended */
 	int (*prepare)(suspend_state_t state);
+
+	/* called just before irqs are off and device second pass
+	 * and sysdevs are suspended. This function can on some archs
+	 * shut irqs off, in which case, they'll still be off when
+	 * finish_irqs() is called.
+	 */
+	int (*prepare_irqs)(suspend_state_t state);
+
+	/* called for entering the actual suspend state. Exits with
+	 * machine worken up and interrupts off
+	 */
 	int (*enter)(suspend_state_t state);
-	int (*finish)(suspend_state_t state);
+
+	/* called after sysdevs and "irq off" devices have been
+	 * worken up, irqs have just been restored to whatever state
+	 * prepare_irqs() left them in.
+	 */
+	void (*finish_irqs)(suspend_state_t state);
+
+	/* called after all devices are woken up, processes still frozen */
+	void (*finish)(suspend_state_t state);
+
+	/* called after unfreezing userland */
+	void (*post_freeze)(suspend_state_t state);
 };
 
 extern void pm_set_ops(struct pm_ops *);
Index: linux-work/include/linux/pmu.h
===================================================================
--- linux-work.orig/include/linux/pmu.h	2005-05-02 10:50:24.000000000 +1000
+++ linux-work/include/linux/pmu.h	2005-05-28 10:30:21.000000000 +1000
@@ -151,6 +151,9 @@
 extern void pmu_suspend(void);
 extern void pmu_resume(void);
 
+extern void pmu_save_via_state(void);
+extern void pmu_restore_via_state(void);
+
 extern void pmu_enable_irled(int on);
 
 extern void pmu_restart(void);
Index: linux-work/kernel/power/main.c
===================================================================
--- linux-work.orig/kernel/power/main.c	2005-05-26 13:27:08.000000000 +1000
+++ linux-work/kernel/power/main.c	2005-05-28 10:30:21.000000000 +1000
@@ -23,6 +23,7 @@
 
 struct pm_ops * pm_ops = NULL;
 suspend_disk_method_t pm_disk_mode = PM_DISK_SHUTDOWN;
+static int pm_process_frozen;
 
 /**
  *	pm_set_ops - Set the global power method table. 
@@ -49,32 +50,53 @@
 static int suspend_prepare(suspend_state_t state)
 {
 	int error = 0;
+	int freeze = 1;
 
 	if (!pm_ops || !pm_ops->enter)
 		return -EPERM;
 
 	pm_prepare_console();
 
-	if (freeze_processes()) {
+	if (pm_ops->pre_freeze)
+		freeze = pm_ops->pre_freeze(state);
+	if (freeze < 0)
+		goto Console;
+
+	if (freeze && freeze_processes()) {
 		error = -EAGAIN;
 		goto Thaw;
 	}
+	pm_process_frozen = freeze;
 
 	if (pm_ops->prepare) {
+		pr_debug("preparing arch...\n");
 		if ((error = pm_ops->prepare(state)))
 			goto Thaw;
 	}
 
+	pr_debug("suspending devices...\n");
 	if ((error = device_suspend(PMSG_SUSPEND))) {
 		printk(KERN_ERR "Some devices failed to suspend\n");
 		goto Finish;
 	}
+
+	if (pm_ops->prepare_irqs) {
+		pr_debug("preparing arch irqs...\n");
+		if ((error = pm_ops->prepare_irqs(state)))
+			goto Finish;
+	}
+
 	return 0;
  Finish:
 	if (pm_ops->finish)
 		pm_ops->finish(state);
  Thaw:
-	thaw_processes();
+	if (freeze)
+		thaw_processes();
+
+	if (pm_ops->post_freeze)
+		pm_ops->post_freeze(state);
+ Console:
 	pm_restore_console();
 	return error;
 }
@@ -109,10 +131,18 @@
 
 static void suspend_finish(suspend_state_t state)
 {
+	if (!pm_ops)
+		return;
+
+	if (pm_ops->finish_irqs)
+		pm_ops->finish_irqs(state);
 	device_resume();
-	if (pm_ops && pm_ops->finish)
+	if (pm_ops->finish)
 		pm_ops->finish(state);
-	thaw_processes();
+	if (pm_process_frozen)
+		thaw_processes();
+	if (pm_ops->post_freeze)
+		pm_ops->post_freeze(state);
 	pm_restore_console();
 }
 
Index: linux-work/arch/ppc/platforms/pmac_pic.c
===================================================================
--- linux-work.orig/arch/ppc/platforms/pmac_pic.c	2005-05-02 10:48:08.000000000 +1000
+++ linux-work/arch/ppc/platforms/pmac_pic.c	2005-05-28 10:30:21.000000000 +1000
@@ -619,7 +619,7 @@
 	return viaint;
 }
 
-static int pmacpic_suspend(struct sys_device *sysdev, u32 state)
+void __pmac pmacpic_suspend(void)
 {
 	int viaint = pmacpic_find_viaint();
 
@@ -636,11 +636,9 @@
 	/* make sure mask gets to controller before we return to caller */
 	mb();
         (void)in_le32(&pmac_irq_hw[0]->enable);
-
-        return 0;
 }
 
-static int pmacpic_resume(struct sys_device *sysdev)
+void __pmac pmacpic_resume(void)
 {
 	int i;
 
@@ -651,12 +649,11 @@
 	for (i = 0; i < max_real_irqs; ++i)
 		if (test_bit(i, sleep_save_mask))
 			pmac_unmask_irq(i);
-
-	return 0;
 }
 
 #endif /* CONFIG_PM */
 
+#if 0
 static struct sysdev_class pmacpic_sysclass = {
 	set_kset_name("pmac_pic"),
 };
@@ -686,4 +683,4 @@
 }
 
 subsys_initcall(init_pmacpic_sysfs);
-
+#endif
Index: linux-work/arch/ppc/syslib/open_pic.c
===================================================================
--- linux-work.orig/arch/ppc/syslib/open_pic.c	2005-05-28 10:30:17.000000000 +1000
+++ linux-work/arch/ppc/syslib/open_pic.c	2005-05-28 10:30:21.000000000 +1000
@@ -946,11 +946,7 @@
 	save_irq_src_vp[irq - open_pic_irq_offset] |= OPENPIC_MASK;
 }
 
-/* WARNING: Can be called directly by the cpufreq code with NULL parameter,
- * we need something better to deal with that... Maybe switch to S1 for
- * cpufreq changes
- */
-int openpic_suspend(struct sys_device *sysdev, u32 state)
+void openpic_suspend(void)
 {
 	int	i;
 	unsigned long flags;
@@ -959,11 +955,9 @@
 
 	if (openpic_suspend_count++ > 0) {
 		spin_unlock_irqrestore(&openpic_setup_lock, flags);
-		return 0;
+		return;
 	}
 
- 	openpic_set_priority(0xf);
-
 	open_pic.enable = openpic_cached_enable_irq;
 	open_pic.disable = openpic_cached_disable_irq;
 
@@ -973,6 +967,8 @@
 				   OPENPIC_CURRENT_TASK_PRIORITY_MASK, 0xf);
 	}
 
+ 	openpic_set_priority(0xf);
+
 	for (i=0; i<OPENPIC_NUM_IPI; i++)
 		save_ipi_vp[i] = openpic_read(&OpenPIC->Global.IPI_Vector_Priority(i));
 	for (i=0; i<NumSources; i++) {
@@ -983,15 +979,13 @@
 	}
 
 	spin_unlock_irqrestore(&openpic_setup_lock, flags);
-
-	return 0;
 }
 
 /* WARNING: Can be called directly by the cpufreq code with NULL parameter,
  * we need something better to deal with that... Maybe switch to S1 for
  * cpufreq changes
  */
-int openpic_resume(struct sys_device *sysdev)
+void openpic_resume(void)
 {
 	int		i;
 	unsigned long	flags;
@@ -1003,9 +997,11 @@
 
 	if ((--openpic_suspend_count) > 0) {
 		spin_unlock_irqrestore(&openpic_setup_lock, flags);
-		return 0;
+		return;
 	}
 
+ 	openpic_set_priority(0xf);
+
 	/* OpenPIC sometimes seem to need some time to be fully back up... */
 	do {
 		openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
@@ -1028,22 +1024,19 @@
 		} while (openpic_readfield(&ISR[i]->Vector_Priority, vppmask)
 			 != (save_irq_src_vp[i] & vppmask));
 	}
-	for (i=0; i<NumProcessors; i++)
-		openpic_write(&OpenPIC->Processor[i].Current_Task_Priority,
-			      save_cpu_task_pri[i]);
-
 	open_pic.enable = openpic_enable_irq;
 	open_pic.disable = openpic_disable_irq;
 
- 	openpic_set_priority(0);
+	for (i=0; i<NumProcessors; i++)
+		openpic_write(&OpenPIC->Processor[i].Current_Task_Priority,
+			      save_cpu_task_pri[i]);
 
 	spin_unlock_irqrestore(&openpic_setup_lock, flags);
-
-	return 0;
 }
 
 #endif /* CONFIG_PM */
 
+#if 0
 static struct sysdev_class openpic_sysclass = {
 	set_kset_name("openpic"),
 };
@@ -1087,3 +1080,4 @@
 
 subsys_initcall(init_openpic_sysfs);
 
+#endif
Index: linux-work/include/asm-ppc/open_pic.h
===================================================================
--- linux-work.orig/include/asm-ppc/open_pic.h	2005-05-28 10:29:53.000000000 +1000
+++ linux-work/include/asm-ppc/open_pic.h	2005-05-28 10:30:21.000000000 +1000
@@ -64,6 +64,9 @@
 extern void openpic_set_priority(u_int pri);
 extern u_int openpic_get_priority(void);
 
+extern void openpic_suspend(void);
+extern void openpic_resume(void);
+
 extern inline int openpic_to_irq(int irq)
 {
 	/* IRQ 0 usually means 'disabled'.. don't mess with it
Index: linux-work/arch/ppc/kernel/time.c
===================================================================
--- linux-work.orig/arch/ppc/kernel/time.c	2005-05-02 10:48:08.000000000 +1000
+++ linux-work/arch/ppc/kernel/time.c	2005-05-28 10:30:21.000000000 +1000
@@ -86,6 +86,7 @@
 unsigned tb_to_us;
 unsigned tb_last_stamp;
 unsigned long tb_to_ns_scale;
+int ppc_force_interrupt;
 
 extern unsigned long wall_jiffies;
 
@@ -131,8 +132,11 @@
 	unsigned jiffy_stamp = last_jiffy_stamp(cpu);
 	extern void do_IRQ(struct pt_regs *);
 
-	if (atomic_read(&ppc_n_lost_interrupts) != 0)
+	if ((atomic_read(&ppc_n_lost_interrupts) != 0) ||
+	    ppc_force_interrupt) {
+		ppc_force_interrupt = 0;
 		do_IRQ(regs);
+	}
 
 	irq_enter();
 
Index: linux-work/arch/ppc/platforms/pmac_cpufreq.c
===================================================================
--- linux-work.orig/arch/ppc/platforms/pmac_cpufreq.c	2005-05-28 10:30:17.000000000 +1000
+++ linux-work/arch/ppc/platforms/pmac_cpufreq.c	2005-05-28 10:30:21.000000000 +1000
@@ -112,11 +112,11 @@
 
 static inline void wakeup_decrementer(void)
 {
-	set_dec(tb_ticks_per_jiffy);
 	/* No currently-supported powerbook has a 601,
 	 * so use get_tbl, not native
 	 */
 	last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
+	set_dec(1);
 }
 
 #ifdef DEBUG_FREQ
@@ -340,6 +340,9 @@
 	/* Restore interrupts */
  	openpic_set_priority(pic_prio);
 
+	/* Force a fetch from the PIC on the first DEC interrupt. */
+	ppc_force_interrupt = 1;
+
 	/* Let interrupts flow again ... */
 	local_irq_restore(flags);
 
Index: linux-work/arch/ppc/platforms/pmac_feature.c
===================================================================
--- linux-work.orig/arch/ppc/platforms/pmac_feature.c	2005-05-03 13:51:57.000000000 +1000
+++ linux-work/arch/ppc/platforms/pmac_feature.c	2005-05-28 10:30:21.000000000 +1000
@@ -548,7 +548,7 @@
 }
 
 static void __pmac
-heathrow_sleep(struct macio_chip* macio, int secondary)
+heathrow_sleep(struct macio_chip* macio, int secondary, int turnoff)
 {
 	if (secondary) {
 		dbdma_save(macio, save_alt_dbdma);
@@ -559,17 +559,22 @@
 		save_fcr[0] = MACIO_IN32(0x38);
 		save_fcr[1] = MACIO_IN32(0x3c);
 		save_mbcr = MACIO_IN32(0x34);
-		/* Make sure sound is shut down */
-		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
-		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
-		/* This seems to be necessary as well or the fan
-		 * keeps coming up and battery drains fast */
-		MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);
-		MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N);
-		/* Make sure eth is down even if module or sleep
-		 * won't work properly */
-		MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);
+		if (turnoff) {
+			/* Make sure sound is shut down */
+			MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
+			MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+			/* This seems to be necessary as well or the fan
+			 * keeps coming up and battery drains fast */
+			MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);
+			MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N);
+			/* Make sure eth is down even if module or sleep
+			 * won't work properly */
+			MACIO_BIC(HEATHROW_FCR,
+				  HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);
+		}
 	}
+	if (!turnoff)
+		return;
 	/* Make sure modem is shut down */
 	MACIO_OUT8(HRW_GPIO_MODEM_RESET,
 		MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1);
@@ -612,12 +617,16 @@
 		return -EPERM;
 	if (value == 1) {
 		if (macio_chips[1].type == macio_gatwick)
-			heathrow_sleep(&macio_chips[0], 1);
-		heathrow_sleep(&macio_chips[0], 0);
+			heathrow_sleep(&macio_chips[1], 1, 1);
+		heathrow_sleep(&macio_chips[0], 0, 1);
+	} else if (value == 2) {
+		if (macio_chips[1].type == macio_gatwick)
+			heathrow_sleep(&macio_chips[1], 1, 0);
+		heathrow_sleep(&macio_chips[0], 0, 0);
 	} else if (value == 0) {
 		heathrow_wakeup(&macio_chips[0], 0);
 		if (macio_chips[1].type == macio_gatwick)
-			heathrow_wakeup(&macio_chips[0], 1);
+			heathrow_wakeup(&macio_chips[1], 1);
 	}
 	return 0;
 }
@@ -1699,7 +1708,7 @@
 
 
 static int __pmac
-core99_sleep(void)
+core99_sleep(int turnoff)
 {
 	struct macio_chip* macio;
 	int i;
@@ -1709,26 +1718,28 @@
 	    macio->type != macio_intrepid)
 		return -ENODEV;
 
-	/* We power off the wireless slot in case it was not done
-	 * by the driver. We don't power it on automatically however
-	 */
-	if (macio->flags & MACIO_FLAG_AIRPORT_ON)
-		core99_airport_enable(macio->of_node, 0, 0);
+	if (turnoff) {
+		/* We power off the wireless slot in case it was not done
+		 * by the driver. We don't power it on automatically however
+		 */
+		if (macio->flags & MACIO_FLAG_AIRPORT_ON)
+			core99_airport_enable(macio->of_node, 0, 0);
 
-	/* We power off the FW cable. Should be done by the driver... */
-	if (macio->flags & MACIO_FLAG_FW_SUPPORTED) {
-		core99_firewire_enable(NULL, 0, 0);
-		core99_firewire_cable_power(NULL, 0, 0);
-	}
+		/* We power off the FW cable.Should be done by the driver... */
+		if (macio->flags & MACIO_FLAG_FW_SUPPORTED) {
+			core99_firewire_enable(NULL, 0, 0);
+			core99_firewire_cable_power(NULL, 0, 0);
+		}
 
-	/* We make sure int. modem is off (in case driver lost it) */
-	if (macio->type == macio_keylargo)
-		core99_modem_enable(macio->of_node, 0, 0);
-	else
-		pangea_modem_enable(macio->of_node, 0, 0);
+		/* We make sure int. modem is off (in case driver lost it) */
+		if (macio->type == macio_keylargo)
+			core99_modem_enable(macio->of_node, 0, 0);
+		else
+			pangea_modem_enable(macio->of_node, 0, 0);
 
-	/* We make sure the sound is off as well */
-	core99_sound_chip_enable(macio->of_node, 0, 0);
+		/* We make sure the sound is off as well */
+		core99_sound_chip_enable(macio->of_node, 0, 0);
+	}
 
 	/*
 	 * Save various bits of KeyLargo
@@ -1756,26 +1767,32 @@
 	/* Save state & config of DBDMA channels */
 	dbdma_save(macio, save_dbdma);
 
-	/*
-	 * Turn off as much as we can
-	 */
-	if (macio->type == macio_pangea)
-		pangea_shutdown(macio, 1);
-	else if (macio->type == macio_intrepid)
-		intrepid_shutdown(macio, 1);
-	else if (macio->type == macio_keylargo)
-		keylargo_shutdown(macio, 1);
+	if (turnoff) {
+		/*
+		 * Turn off as much as we can
+		 */
+		if (macio->type == macio_pangea)
+			pangea_shutdown(macio, 1);
+		else if (macio->type == macio_intrepid)
+			intrepid_shutdown(macio, 1);
+		else if (macio->type == macio_keylargo)
+			keylargo_shutdown(macio, 1);
+	}
 
 	/*
-	 * Put the host bridge to sleep
+	 * Save host bridge state and put to sleep
 	 */
 
 	save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);
-	/* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it
-	 * enabled !
+
+	if (!turnoff)
+		return 0;
+
+	/* Note: do not switch GMAC off, driver does it when necessary,
+	 * WOL must keep it  enabled !
 	 */
 	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*/));
+	       ~(UNI_N_CLOCK_CNTL_FW));
 	udelay(100);
 	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
 	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);
@@ -1876,7 +1893,9 @@
 		return -EPERM;
 
 	if (value == 1)
-		return core99_sleep();
+		return core99_sleep(1);
+	else if (value == 2)
+		return core99_sleep(0);
 	else if (value == 0)
 		return core99_wake_up();
 	return 0;
Index: linux-work/include/asm-ppc/pmac_feature.h
===================================================================
--- linux-work.orig/include/asm-ppc/pmac_feature.h	2005-05-03 13:51:57.000000000 +1000
+++ linux-work/include/asm-ppc/pmac_feature.h	2005-05-28 10:30:21.000000000 +1000
@@ -245,6 +245,7 @@
  * set the sleep state of the motherboard.
  *
  * Pass -1 as value to query for sleep capability
+ * Pass 2 to save state & not sleep
  * Pass 1 to set IOs to sleep
  * Pass 0 to set IOs to wake
  */
Index: linux-work/include/asm-ppc/irq.h
===================================================================
--- linux-work.orig/include/asm-ppc/irq.h	2005-05-02 10:49:57.000000000 +1000
+++ linux-work/include/asm-ppc/irq.h	2005-05-28 10:30:21.000000000 +1000
@@ -391,6 +391,7 @@
 extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
 extern unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
 extern atomic_t ppc_n_lost_interrupts;
+extern int ppc_force_interrupt;
 
 struct irqaction;
 struct pt_regs;
Index: linux-work/drivers/ide/ide-io.c
===================================================================
--- linux-work.orig/drivers/ide/ide-io.c	2005-05-02 10:48:09.000000000 +1000
+++ linux-work/drivers/ide/ide-io.c	2005-05-28 10:30:21.000000000 +1000
@@ -150,7 +150,7 @@
 
 	switch (rq->pm->pm_step) {
 	case ide_pm_flush_cache:	/* Suspend step 1 (flush cache) complete */
-		if (rq->pm->pm_state == 4)
+		if (rq->pm->pm_state == PM_SUSPEND_DISK)
 			rq->pm->pm_step = ide_pm_state_completed;
 		else
 			rq->pm->pm_step = idedisk_pm_standby;
Index: linux-work/drivers/video/aty/aty128fb.c
===================================================================
--- linux-work.orig/drivers/video/aty/aty128fb.c	2005-05-02 10:48:53.000000000 +1000
+++ linux-work/drivers/video/aty/aty128fb.c	2005-05-28 10:30:21.000000000 +1000
@@ -2337,21 +2337,15 @@
 	 * can properly take care of D3 ? Also, with swsusp, we
 	 * know we'll be rebooted, ...
 	 */
-#ifdef CONFIG_PPC_PMAC
-	/* HACK ALERT ! Once I find a proper way to say to each driver
-	 * individually what will happen with it's PCI slot, I'll change
-	 * that. On laptops, the AGP slot is just unclocked, so D2 is
-	 * expected, while on desktops, the card is powered off
-	 */
-	if (state >= 3)
-		state = 2;
-#endif /* CONFIG_PPC_PMAC */
 	 
-	if (state != 2 || state == pdev->dev.power.power_state)
+	if (pdev->dev.power.power_state)
 		return 0;
 
 	printk(KERN_DEBUG "aty128fb: suspending...\n");
 	
+	if (state == PM_SUSPEND_DISK)
+		goto skip;
+
 	acquire_console_sem();
 
 	fb_set_suspend(info, 1);
@@ -2381,12 +2375,11 @@
 	 * used dummy fb ops, 2.5 need proper support for this at the
 	 * fbdev level
 	 */
-	if (state == 2)
-		aty128_set_suspend(par, 1);
+	aty128_set_suspend(par, 1);
 
 	release_console_sem();
-
-	pdev->dev.power.power_state = state;
+ skip:
+	pdev->dev.power.power_state = 1;
 
 	return 0;
 }
@@ -2400,8 +2393,7 @@
 		return 0;
 
 	/* Wakeup chip */
-	if (pdev->dev.power.power_state == 2)
-		aty128_set_suspend(par, 0);
+	aty128_set_suspend(par, 0);
 	par->asleep = 0;
 
 	/* Restore display & engine */
Index: linux-work/drivers/char/agp/uninorth-agp.c
===================================================================
--- linux-work.orig/drivers/char/agp/uninorth-agp.c	2005-05-02 10:48:09.000000000 +1000
+++ linux-work/drivers/char/agp/uninorth-agp.c	2005-05-28 11:37:38.000000000 +1000
@@ -347,6 +347,8 @@
 	struct agp_bridge_data *bridge;
 	u32 command;
 
+	uninorth_configure();
+
 	bridge = agp_find_bridge(pdev);
 	if (bridge == NULL)
 		return -ENODEV;
Index: linux-work/drivers/video/aty/radeon_base.c
===================================================================
--- linux-work.orig/drivers/video/aty/radeon_base.c	2005-05-28 11:25:03.000000000 +1000
+++ linux-work/drivers/video/aty/radeon_base.c	2005-05-28 11:31:14.000000000 +1000
@@ -2036,7 +2036,7 @@
  */
 #ifdef CONFIG_PPC_OF
 #undef SET_MC_FB_FROM_APERTURE
-static void fixup_memory_mappings(struct radeonfb_info *rinfo)
+void radeon_fixup_memory_mappings(struct radeonfb_info *rinfo)
 {
 	u32 save_crtc_gen_cntl, save_crtc2_gen_cntl = 0;
 	u32 save_crtc_ext_cntl;
@@ -2360,7 +2360,7 @@
 	 * to cause lockups when enabling the engine. We reconfigure
 	 * the card internal memory mappings properly
 	 */
-	fixup_memory_mappings(rinfo);
+	radeon_fixup_memory_mappings(rinfo);
 #endif /* CONFIG_PPC_OF */
 
 	/* Get VRAM size and type */
Index: linux-work/drivers/video/aty/radeon_pm.c
===================================================================
--- linux-work.orig/drivers/video/aty/radeon_pm.c	2005-05-28 11:25:03.000000000 +1000
+++ linux-work/drivers/video/aty/radeon_pm.c	2005-05-28 11:26:41.000000000 +1000
@@ -2659,8 +2659,10 @@
 			radeon_set_suspend(rinfo, 0);
 
 		rinfo->asleep = 0;
-	} else
+	} else {
+		radeon_fixup_memory_mappings(rinfo);
 		radeon_engine_idle();
+	}
 
 	/* Restore display & engine */
 	radeon_write_mode (rinfo, &rinfo->state, 1);
Index: linux-work/drivers/video/aty/radeonfb.h
===================================================================
--- linux-work.orig/drivers/video/aty/radeonfb.h	2005-05-02 10:48:53.000000000 +1000
+++ linux-work/drivers/video/aty/radeonfb.h	2005-05-28 11:25:54.000000000 +1000
@@ -618,6 +618,7 @@
 extern void radeonfb_engine_reset(struct radeonfb_info *rinfo);
 
 /* Other functions */
+extern void radeon_fixup_memory_mappings(struct radeonfb_info *rinfo);
 extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch);
 extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
 			       int reg_only);

^ permalink raw reply

* Re: [PATCH] ppc32: PowerMac PM rework
From: Andreas Schwab @ 2005-05-28 19:17 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list
In-Reply-To: <1117246520.5228.5.camel@gaston>

Benjamin Herrenschmidt <benh@kernel.crashing.org> writes:

> Please test and report any issue.

With this patch my iBook G3 no longer wakes up by opening the lid.  I have
to touch the keyboard to wake it up.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply

* Re: [PATCH] ppc32: PowerMac PM rework
From: Benjamin Herrenschmidt @ 2005-05-28 22:29 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: linuxppc-dev list
In-Reply-To: <jewtpjjh2m.fsf@sykes.suse.de>

On Sat, 2005-05-28 at 21:17 +0200, Andreas Schwab wrote:
> Benjamin Herrenschmidt <benh@kernel.crashing.org> writes:
> 
> > Please test and report any issue.
> 
> With this patch my iBook G3 no longer wakes up by opening the lid.  I have
> to touch the keyboard to wake it up.

Yup, that's a minor issue, the lid wakeup option lost it's default
value :) Will be fixed in the next version of the patch.

Ben.

^ permalink raw reply

* load u-boot.bin failure with BDI2000
From: tuotuo wang @ 2005-05-29 15:51 UTC (permalink / raw)
  To: linuxppc-embedded

hi,my friends:

My target board is SBC8260,my debugger BDI2000,i have complied my u-boot 
file .But here is a mistake when i load it.Now i cann't enter the command 
line of u-boot.here is the display of BDI2000:
- TARGET: processing user reset request
- TARGET: Target PVR is 0x00810101
- TARGET: reseting target passed
- TARGET: processing target init list ....
*** TARGET: processing target init list failed
# PPC: Writing to workspace failed
- TARGET: target will be restarted in 10 sec


help me please!!
think you.

_________________________________________________________________
与联机的朋友进行交流,请使用 MSN Messenger:  http://messenger.msn.com/cn  

^ permalink raw reply

* Re: load u-boot.bin failure with BDI2000
From: Shawn Jin @ 2005-05-29 18:28 UTC (permalink / raw)
  To: tuotuo wang; +Cc: linuxppc-embedded
In-Reply-To: <BAY24-F3232D1E642991A24EBA041AD020@phx.gbl>

> My target board is SBC8260,my debugger BDI2000,i have complied my u-boot
> file .But here is a mistake when i load it.Now i cann't enter the command
> line of u-boot.here is the display of BDI2000:
> - TARGET: processing user reset request
> - TARGET: Target PVR is 0x00810101
> - TARGET: reseting target passed
> - TARGET: processing target init list ....
> *** TARGET: processing target init list failed
> # PPC: Writing to workspace failed

There is somehting wrong with BDI2000 configuration file. Double check
what [INIT] section does for your target board.

-Shawn.

^ permalink raw reply

* FW: Re: load u-boot.bin failure with BDI2000
From: tuotuo wang @ 2005-05-30  1:07 UTC (permalink / raw)
  To: linuxppc-embedded



>From: Shawn Jin <shawnxjin@gmail.com>
>Reply-To: Shawn Jin <shawnxjin@gmail.com>
>To: tuotuo wang <dvdstar@hotmail.com>
>CC: linuxppc-embedded@ozlabs.org
>Subject: Re: load u-boot.bin failure with BDI2000
>Date: Sun, 29 May 2005 11:28:28 -0700
>
> > My target board is SBC8260,my debugger BDI2000,i have complied my 
u-boot
> > file .But here is a mistake when i load it.Now i cann't enter the 
command
> > line of u-boot.here is the display of BDI2000:
> > - TARGET: processing user reset request
> > - TARGET: Target PVR is 0x00810101
> > - TARGET: reseting target passed
> > - TARGET: processing target init list ....
> > *** TARGET: processing target init list failed
> > # PPC: Writing to workspace failed
>
>There is somehting wrong with BDI2000 configuration file. Double check
>what [INIT] section does for your target board.
>
>-Shawn.


You know,my config file of BDI2000 is download from www.denx.de,because 
there have the sbc8260's.My board run the ppcboot at first,and i can use my 
BDI2000 properly with this config file.

_________________________________________________________________
享用世界上最大的电子邮件系统― MSN Hotmail。  http://www.hotmail.com  

^ permalink raw reply

* [PATCH] ppc32: Rework power management take #3
From: Benjamin Herrenschmidt @ 2005-05-30  3:35 UTC (permalink / raw)
  To: linuxppc-dev list; +Cc: debian-powerpc@lists.debian.org

Ok, the patch is now getting "good enough" for wider testing. It applies
on current "git" tree (or 2.6.12-rc6 when/if that is ever released). It
requires one other patch to be applied first:

http://gate.crashing.org/~benh/ppc32-remove-macserial.diff

The PM patch itself can be found at:

http://gate.crashing.org/~benh/ppc32-rework-pm.diff

This patch completely reworks both suspend-to-ram and suspend-to-disk
support on PowerMac:

 - suspend-to-ram code is moved away from the via-pmu.c driver
 - both suspend-to-disk & to-ram consolidated to use the same
infrastructure and code base in a new pmac_pm.c file
 - significants fixes & improvements to suspend-to-disk
 - for now (may change), use the "refrigerator" with suspend-to-ram as
well as suspend-to-disk. This may help make it a bit more robust vs.
userland activity during the sleep process
 - CONFIG_PMAC_PBOOK is gone. CONFIG_PMAC_MEDIABAY is new and controls
wether the powerbook hostwap bay driver is included. The rest of bits
formerly under CONFIG_PMAC_PBOOK control are now either always on
(like /dev/pmu interface on PMU based machines) or dependent on other
config options (like CONFIG_PM, CONFIG_PPC_PMAC, ...)

The patch will not be in 2.6.12 (though will probably apply on top of
it). I aim for a 2.6.13 release, knowing that the patch changes a bunch
of non-ppc-specific power management bits, and thus may need some time
to be fully merged upstream.

^ permalink raw reply

* symlinks in /proc/device-tree
From: Benjamin Herrenschmidt @ 2005-05-30  5:07 UTC (permalink / raw)
  To: linuxppc64-dev, linuxppc-dev list

Hi !

Is anybody actually using one of these things in /proc/device-tree ?

 - for a node name@address, symlinks from name->node and @address->node
 - the fact that we remove the @address part if address is 0

I'm considering killing both of these things for 2.6.13. That will
reduce the memory footprint of the device-tree significantly (bloat in
inode cache) and it will be a more exact representation of the actual
tree. Besides, the symlinks are not really useful in practice.

Ben.
  

^ permalink raw reply

* Re: symlinks in /proc/device-tree
From: Olaf Hering @ 2005-05-30  6:17 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc64-dev, linuxppc-dev list
In-Reply-To: <1117429620.5228.38.camel@gaston>

 On Mon, May 30, Benjamin Herrenschmidt wrote:

> Hi !
> 
> Is anybody actually using one of these things in /proc/device-tree ?

Just make sure the devspec file in sysfs doesnt contain symlinks.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox