Index: device/pnp_device.c
===================================================================
--- device/pnp_device.c	(revision 999)
+++ device/pnp_device.c	(working copy)
@@ -85,6 +85,9 @@
 
 static void pnp_set_resource(struct device *dev, struct resource *resource)
 {
+	printk(BIOS_SPEW,
+	       "%s: %s %02lx %s\n",
+	       __func__, dev_path(dev), resource->index, resource_type(resource));
 	if (!(resource->flags & IORESOURCE_ASSIGNED)) {
 		printk(BIOS_ERR,
 		       "ERROR: %s %02lx %s size: 0x%010llx not assigned\n",
@@ -156,7 +159,6 @@
 	resource = new_resource(dev, index);
 
 	/* Initialize the resource. */
-	resource->limit = 0xffff;
 	resource->flags |= IORESOURCE_IO;
 
 	/* Get the resource size. */
@@ -189,6 +191,12 @@
 	resource->align = gran;
 	resource->limit = info->mask | (step - 1);
 	resource->size = 1 << gran;
+
+	if (info->fixed) {
+		resource->base = info->val;
+		resource->flags |= IORESOURCE_FIXED;
+		resource->flags |= IORESOURCE_ASSIGNED;
+	}
 }
 
 static void get_resources(struct device *dev, struct pnp_info *info)
@@ -211,21 +219,37 @@
 		resource = new_resource(dev, PNP_IDX_IRQ0);
 		resource->size = 1;
 		resource->flags |= IORESOURCE_IRQ;
+		if (info->irq0.fixed) {
+			resource->base = info->irq0.val;
+			resource->flags |= IORESOURCE_FIXED;
+		}
 	}
 	if (info->flags & PNP_IRQ1) {
 		resource = new_resource(dev, PNP_IDX_IRQ1);
 		resource->size = 1;
 		resource->flags |= IORESOURCE_IRQ;
+		if (info->irq1.fixed) {
+			resource->base = info->irq1.val;
+			resource->flags |= IORESOURCE_FIXED;
+		}
 	}
 	if (info->flags & PNP_DRQ0) {
 		resource = new_resource(dev, PNP_IDX_DRQ0);
 		resource->size = 1;
 		resource->flags |= IORESOURCE_DRQ;
+		if (info->drq0.fixed) {
+			resource->base = info->drq0.val;
+			resource->flags |= IORESOURCE_FIXED;
+		}
 	}
 	if (info->flags & PNP_DRQ1) {
 		resource = new_resource(dev, PNP_IDX_DRQ1);
 		resource->size = 1;
 		resource->flags |= IORESOURCE_DRQ;
+		if (info->drq1.fixed) {
+			resource->base = info->drq1.val;
+			resource->flags |= IORESOURCE_FIXED;
+		}
 	}
 }
 
@@ -233,7 +257,6 @@
 			unsigned int functions, struct pnp_info *info)
 {
 	struct device_path path;
-	struct device_id id = {.type = DEVICE_ID_PNP };
 	struct device *dev;
 	int i;
 
@@ -243,7 +266,13 @@
 	/* Setup the ops and resources on the newly allocated devices. */
 	for (i = 0; i < functions; i++) {
 		path.pnp.device = info[i].function;
-		dev = alloc_find_dev(base_dev->bus, &path, &id);
+		dev = find_dev_path(&base_dev->link[0], &path);
+		if (!dev) {
+			printk(BIOS_DEBUG,"No device at PNP port %02x function %x.\n",
+				base_dev->path.pnp.port, info[i].function);
+			continue;
+		}
+		
 
 		/* Don't initialize a device multiple times. */
 		if (dev->ops)
Index: include/device/pnp.h
===================================================================
--- include/device/pnp.h	(revision 999)
+++ include/device/pnp.h	(working copy)
@@ -53,7 +53,7 @@
 /* PNP helper operations */
 
 struct io_info {
-	unsigned mask, set;
+	unsigned mask, set, val, fixed;
 };
 
 struct pnp_info {
@@ -68,7 +68,7 @@
 #define PNP_IRQ1 0x20
 #define PNP_DRQ0 0x40
 #define PNP_DRQ1 0x80
-	struct io_info io0, io1, io2, io3;
+	struct io_info io0, io1, io2, io3, irq0, irq1, drq0, drq1;
 };
 struct resource *pnp_get_resource(struct device * dev, unsigned index);
 void pnp_enable_devices(struct device *dev, struct device_operations *ops,
Index: mainboard/amd/serengeti/dts
===================================================================
--- mainboard/amd/serengeti/dts	(revision 999)
+++ mainboard/amd/serengeti/dts	(working copy)
@@ -79,7 +79,26 @@
 		pci@18,3 {};
 		ioport@2e {
 			/config/("superio/winbond/w83627hf/dts");
-			com1enable = "1";
+			pnp@2 {
+				/config/("superio/common/pnp.dts");
+				enabled;
+				io = "0x3f8";
+				irq = "4";
+			};
+			pnp@5 {
+				/config/("superio/common/pnp.dts");
+				enabled;
+				io = "0x60";
+				io2 = "0x62";
+				irq = "1";
+				irq2 = "12";
+			};
+			pnp@a {
+				/config/("superio/common/pnp.dts");
+				enabled;
+				io = "0x290";
+				irq = "5";
+			};
 		};
 	};
 };
Index: superio/common/pnp.dts
===================================================================
--- superio/common/pnp.dts	(revision 0)
+++ superio/common/pnp.dts	(revision 0)
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Ronald G. Minnich <rminnich@gmail.com>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+{
+	/* To override any of these, put the over-ride in mainboard dts. */
+	io = "0";
+	io2 = "0";
+	io3 = "0";
+	io4 = "0";
+	irq = "0";
+	irq2 = "0";
+	drq = "0";
+	drq2 = "0";
+};
Index: superio/winbond/w83627hf/dts
===================================================================
--- superio/winbond/w83627hf/dts	(revision 999)
+++ superio/winbond/w83627hf/dts	(working copy)
@@ -22,65 +22,4 @@
 	device_operations = "w83627hf_ops";
 	/* To override any of these, put the over-ride in mainboard dts. */
 
-	/* Floppy */
-	floppydev = "0x0";
-	floppyenable = "0";
-	floppyio = "0x3f0";
-	floppyirq = "0x60";
-	floppydrq = "0x02";
-
-	/* Parallel port */
-	ppdev = "2";
-	ppenable = "0";
-	ppio = "0x378";
-	ppirq = "7";
-
-	/* COM1 */
-	com1dev = "2";
-	com1enable = "0";
-	com1io = "0x3f8";
-	com1irq = "4";
-
-	/* COM2 */
-	com2dev = "3";
-	com2enable = "0";
-	com2io = "0x2f8";
-	com2irq = "3";
-
-	/* Keyboard */
-	kbdev = "5";
-	kbenable = "0";
-	kbio = "0x60";
-	kbio2 = "0x62";
-	kbirq = "1";
-	kbirq2 = "12";
-
-	/* Consumer IR */
-	cirdev = "6";
-	cirenable = "0";
-
-	/* Game port */
-	gamedev = "7";
-	gameenable = "0";
-	gameio = "0x220";
-	gameio2 = "0x400";
-	gameirq = "9";
-
-	/* GPIO2 */
-	gpio2dev = "8";
-	gpio2enable = "0";
-
-	/* GPIO3 */
-	gpio3dev = "9";
-	gpio3enable = "0";
-
-	/* ACPI */
-	acpidev = "0xa";
-	acpienable = "0";
-
-	/* Hardware Monitor */
-	hwmdev = "0xb";
-	hwmenable = "0";
-	hwmio = "0x290";
-	hwmirq = "5";
 };
Index: superio/winbond/w83627hf/superio.c
===================================================================
--- superio/winbond/w83627hf/superio.c	(revision 999)
+++ superio/winbond/w83627hf/superio.c	(working copy)
@@ -117,32 +117,27 @@
 {
 	struct superio_winbond_w83627hf_dts_config *conf;
 	struct resource *res0, *res1;
-	struct pc_keyboard keyboard;
 
-#if 1
-	printk(BIOS_ERR, "dummy init XXXX\n");
-#endif
+	printk(BIOS_ERR, "%s: %s dummy init XXXX\n",__func__, dev->dtsname);
 
-	if (!dev->enabled) {
-		return;
-	}
-
 	conf = dev->device_configuration;
 	switch(dev->path.pnp.device) {
 	case W83627HF_SP1:
 		res0 = find_resource(dev, PNP_IDX_IO0);
 #warning init_uart8250
+		printk(BIOS_DEBUG, "%s: Not calling init_uart8250.\n",__func__);
 		//init_uart8250(res0->base, &conf->com1);
 		break;
 	case W83627HF_SP2:
 		res0 = find_resource(dev, PNP_IDX_IO0);
 #warning init_uart8250
+		printk(BIOS_DEBUG, "%s: Not calling init_uart8250.\n",__func__);
 		//init_uart8250(res0->base, &conf->com2);
 		break;
 	case W83627HF_KBC:
 		res0 = find_resource(dev, PNP_IDX_IO0);
 		res1 = find_resource(dev, PNP_IDX_IO1);
-		init_pc_keyboard(res0->base, res1->base, &keyboard);
+		init_pc_keyboard(res0->base, res1->base, NULL);
 		break;
 	case W83627HF_HWM:
 		res0 = find_resource(dev, PNP_IDX_IO0);
@@ -157,6 +152,7 @@
 
 void w83627hf_pnp_set_resources(struct device * dev)
 {
+	printk(BIOS_DEBUG, "%s\n",__func__);
 	pnp_enter_ext_func_mode(dev);
 	pnp_set_resources(dev);
 	pnp_exit_ext_func_mode(dev);
@@ -177,6 +173,14 @@
 
 }
 
+void w83627hf_enable_resources(struct device * dev)
+{
+	struct device * child;
+	for(child = dev->link[0].children; child; child = child->sibling)
+		if (child->path.type == DEVICE_PATH_PNP)
+			w83627hf_pnp_enable_resources(child);
+}
+
 void w83627hf_pnp_enable(struct device * dev)
 {
 
@@ -189,8 +193,19 @@
 		pnp_exit_ext_func_mode(dev);
 	}
 }
+
+void w83627hf_enable(struct device * dev)
+{
+	struct device * child;
+	for(child = dev->link[0].children; child; child = child->sibling)
+		if (child->path.type == DEVICE_PATH_PNP)
+			w83627hf_pnp_enable(child);
+}
+
 static void phase3_chip_setup_dev(struct device *dev);
-struct device_operations w83627hf_ops = {
+
+struct device_operations w83627hf_pnp_ops = {
+	.id = {.type = DEVICE_ID_PNP},
 	.phase3_chip_setup_dev   = phase3_chip_setup_dev,
 	.phase3_enable           = w83627hf_pnp_enable_resources,
 	.phase4_read_resources   = pnp_read_resources,
@@ -199,24 +214,81 @@
 	.phase6_init             = w83627hf_init,
 };
 
+struct device_operations w83627hf_ops = {
+	.id = {.type = DEVICE_ID_PNP},
+	.phase3_enable           = w83627hf_enable_resources,
+	.phase5_enable_resources = w83627hf_enable,
+};
+
 static struct pnp_info pnp_dev_info[] = {
-	{ &w83627hf_ops, W83627HF_FDC,  PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07f8, 0}, },
-	{ &w83627hf_ops, W83627HF_PP,   PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07f8, 0}, },
-	{ &w83627hf_ops, W83627HF_SP1,  PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
-	{ &w83627hf_ops, W83627HF_SP2,  PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
-	// No 4 { 0,},
-	{ &w83627hf_ops, W83627HF_KBC,  PNP_IO0 | PNP_IO1 | PNP_IRQ0 | PNP_IRQ1, { 0x7ff, 0 }, { 0x7ff, 0x4}, },
-	{ &w83627hf_ops, W83627HF_CIR, PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
-	{ &w83627hf_ops, W83627HF_GAME_MIDI_GPIO1, PNP_IO0 | PNP_IO1 | PNP_IRQ0, { 0x7ff, 0 }, {0x7fe, 0x4}, },
-	{ &w83627hf_ops, W83627HF_GPIO2, },
-	{ &w83627hf_ops, W83627HF_GPIO3, },
-	{ &w83627hf_ops, W83627HF_ACPI, },
-	{ &w83627hf_ops, W83627HF_HWM,  PNP_IO0 | PNP_IRQ0, { 0xff8, 0 }, },
+					/* All resources need by dev,  io_info_structs */
+	{ &w83627hf_pnp_ops, W83627HF_FDC,  PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07f8, 0}, },
+	{ &w83627hf_pnp_ops, W83627HF_PP,   PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07f8, 0}, },
+	{ &w83627hf_pnp_ops, W83627HF_SP1,  PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
+	{ &w83627hf_pnp_ops, W83627HF_SP2,  PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
+	{ 0,},
+	{ &w83627hf_pnp_ops, W83627HF_KBC,  PNP_IO0 | PNP_IO1 | PNP_IRQ0 | PNP_IRQ1, { 0x7ff, 0 }, { 0x7ff, 0x4}, },
+	{ &w83627hf_pnp_ops, W83627HF_CIR, PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
+	{ &w83627hf_pnp_ops, W83627HF_GAME_MIDI_GPIO1, PNP_IO0 | PNP_IO1 | PNP_IRQ0, { 0x7ff, 0 }, {0x7fe, 0x4}, },
+	{ &w83627hf_pnp_ops, W83627HF_GPIO2, },
+	{ &w83627hf_pnp_ops, W83627HF_GPIO3, },
+	{ &w83627hf_pnp_ops, W83627HF_ACPI, },
+	{ &w83627hf_pnp_ops, W83627HF_HWM,  PNP_IO0 | PNP_IRQ0, { 0xff8, 0 }, },
 };
 
 
 static void phase3_chip_setup_dev(struct device *dev)
 {
+	struct device *child = dev->link[0].children;
+	
+	/* For each PNP child of this device, get dts values */
+	for (child = dev->link[0].children; dev->links && child;
+			child= child->sibling) {
+		unsigned function;
+		const struct superio_common_pnp_config * const conf = child->device_configuration;
+		if (child->path.type !=  DEVICE_PATH_PNP)
+			continue;
+		child->path.pnp.port = dev->path.ioport.iobase;
+		function = child->path.pnp.device;
+		printk(BIOS_DEBUG, "%s fixup for child %s func %d\n",
+			__func__, dev->dtsname, function);
+		if (pnp_dev_info[function].function != function) {
+			printk(BIOS_ERR, "Error in PNP info struct! "
+				"function %02x labeled %02x\n",
+				function,pnp_dev_info[function].function);
+			continue;
+		}
+		if (conf->io) {
+			if (~pnp_dev_info[function].io0.mask & conf->io)
+				printk(BIOS_DEBUG,"Dts setting %02x outside mask %02x.\n",
+					conf->io, pnp_dev_info[function].io0.mask);
+			pnp_dev_info[function].io0.val = conf->io;
+			pnp_dev_info[function].io0.fixed = 1;
+		}
+		if (conf->io2) {
+			if (~pnp_dev_info[function].io1.mask & conf->io2)
+				printk(BIOS_DEBUG,"Dts setting %02x outside mask %02x.\n",
+					conf->io2, pnp_dev_info[function].io1.mask);
+			pnp_dev_info[function].io1.val = conf->io2;
+			pnp_dev_info[function].io1.fixed = 1;
+		}
+		if (conf->irq) {
+			pnp_dev_info[function].irq0.val = conf->irq;
+			pnp_dev_info[function].irq0.fixed = 1;
+		}
+		if (conf->irq2) {
+			pnp_dev_info[function].irq1.val = conf->irq2;
+			pnp_dev_info[function].irq1.fixed = 1;
+		}
+		if (conf->drq) {
+			pnp_dev_info[function].drq0.val = conf->drq;
+			pnp_dev_info[function].drq0.fixed = 1;
+		}
+		if (conf->drq2) {
+			pnp_dev_info[function].drq1.val = conf->drq2;
+			pnp_dev_info[function].drq1.fixed = 1;
+		}
+	}
 	pnp_enable_devices(dev, &w83627hf_ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
 }
 
