Allocating resource for Expansion ROM

More correct resource allocation for legacy VGA on K8


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1829 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c
index b16e922..6062fa6 100644
--- a/src/devices/pci_device.c
+++ b/src/devices/pci_device.c
@@ -37,6 +37,7 @@
 
 	return ones ^ zeroes;
 }
+
 static uint16_t pci_moving_config16(struct device *dev, unsigned reg)
 {
 	uint16_t value, ones, zeroes;
@@ -81,7 +82,7 @@
 	if (pos > PCI_CAP_LIST_NEXT) {
 		pos = pci_read_config8(dev, pos);
 	}
-	while(pos != 0) {   /* loop through the linked list */
+	while (pos != 0) {   /* loop through the linked list */
 		int this_cap;
 		this_cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID);
 		if (this_cap == cap) {
@@ -111,7 +112,7 @@
 
 	/* See which bits move */
 	moving = pci_moving_config32(dev, index);
-	
+
 	/* Initialize attr to the bits that do not move */
 	attr = value & ~moving;
 
@@ -153,9 +154,8 @@
 	 */
 	if (moving == 0) {
 		if (value != 0) {
-			printk_debug(
-				"%s register %02x(%08x), read-only ignoring it\n",
-				dev_path(dev), index, value);
+			printk_debug("%s register %02x(%08x), read-only ignoring it\n",
+				     dev_path(dev), index, value);
 		}
 		resource->flags = 0;
 	}
@@ -199,9 +199,9 @@
 #if 0
 	if (resource->flags) {
 		printk_debug("%s %02x ->",
-			dev_path(dev), resource->index);
+			     dev_path(dev), resource->index);
 		printk_debug(" value: 0x%08Lx zeroes: 0x%08Lx ones: 0x%08Lx attr: %08lx\n",
-			value, zeroes, ones, attr);
+			     value, zeroes, ones, attr);
 		printk_debug(
 			"%s %02x -> size: 0x%08Lx max: 0x%08Lx %s%s\n ",
 			dev_path(dev),
@@ -225,7 +225,7 @@
 {
 	unsigned long index;
 
-	for(index = PCI_BASE_ADDRESS_0; (index < PCI_BASE_ADDRESS_0 + (howmany << 2)); ) {
+	for (index = PCI_BASE_ADDRESS_0; (index < PCI_BASE_ADDRESS_0 + (howmany << 2)); ) {
 		struct resource *resource;
 		resource = pci_get_resource(dev, index);
 		index += (resource->flags & IORESOURCE_PCI64)?8:4;
@@ -233,11 +233,63 @@
 	compact_resources(dev);
 }
 
+static void pci_read_rom_resource(struct device *dev, unsigned long index)
+{
+	struct resource *resource;
+	unsigned long value, attr;
+	resource_t  moving, limit;
+
+	/* Initialize the resources to nothing */
+	resource = new_resource(dev, index);
+
+	/* Get the initial value */
+	value = pci_read_config32(dev, index);
+
+	/* See which bits move */
+	moving = pci_moving_config32(dev, index);
+	/* clear the Enable bit */
+	moving = moving & 0xffffffffe;
+
+	/* Find the resource constraints. 
+	 *
+	 * Start by finding the bits that move. From there:
+	 * - Size is the least significant bit of the bits that move.
+	 * - Limit is all of the bits that move plus all of the lower bits.
+	 * See PCI Spec 6.2.5.1 ...
+	 */
+	limit = 0;
+
+	if (moving) {
+		resource->size = 1;
+		resource->align = resource->gran = 0;
+		while(!(moving & resource->size)) {
+			resource->size <<= 1;
+			resource->align += 1;
+			resource->gran  += 1;
+		}
+		resource->limit = limit = moving | (resource->size - 1);
+		printk_debug("%s, rom size: %x, limit: %x\n",
+			    dev_path(dev), resource->size, limit);
+	}
+
+	if (moving == 0) {
+		if (value != 0) {
+			printk_debug("%s register %02x(%08x), read-only ignoring it\n",
+				     dev_path(dev), index, value);
+		}
+		resource->flags = 0;
+	} else {
+		resource->flags |= IORESOURCE_MEM | IORESOURCE_READONLY;
+	}
+	compact_resources(dev);
+
+}
+
 static void pci_set_resource(struct device *dev, struct resource *resource);
 
-static void pci_record_bridge_resource(
-	struct device *dev, resource_t moving,
-	unsigned index, unsigned long mask, unsigned long type)
+static void pci_record_bridge_resource( struct device *dev, resource_t moving,
+					unsigned index, unsigned long mask,
+					unsigned long type)
 {
 	/* Initiliaze the constraints on the current bus */
 	struct resource *resource;
@@ -272,7 +324,6 @@
 	return;
 }
 
-
 static void pci_bridge_read_bases(struct device *dev)
 {
 	resource_t moving_base, moving_limit, moving;
@@ -329,8 +380,7 @@
 
 	pci_read_bases(dev, 6);
 
-	addr = pci_read_config32(dev, PCI_ROM_ADDRESS);
-	dev->rom_address = (addr == 0xffffffff)? 0 : addr;
+	pci_read_rom_resource(dev, PCI_ROM_ADDRESS);
 }
 
 void pci_bus_read_resources(struct device *dev)
@@ -339,9 +389,8 @@
 
 	pci_bridge_read_bases(dev);
 	pci_read_bases(dev, 2);
-	
-	addr = pci_read_config32(dev, PCI_ROM_ADDRESS1);
-	dev->rom_address = (addr == 0xffffffff)? 0 : addr;
+
+	pci_read_rom_resource(dev, PCI_ROM_ADDRESS1);
 }
 
 static void pci_set_resource(struct device *dev, struct resource *resource)
@@ -450,10 +499,10 @@
 
 	last = &dev->resource[dev->resources];
 
-	for(resource = &dev->resource[0]; resource < last; resource++) {
+	for (resource = &dev->resource[0]; resource < last; resource++) {
 		pci_set_resource(dev, resource);
 	}
-	for(link = 0; link < dev->links; link++) {
+	for (link = 0; link < dev->links; link++) {
 		struct bus *bus;
 		bus = &dev->link[link];
 		if (bus->children) {
diff --git a/src/devices/smbus_ops.c b/src/devices/smbus_ops.c
index e721bfb..8d32a66 100644
--- a/src/devices/smbus_ops.c
+++ b/src/devices/smbus_ops.c
@@ -7,7 +7,7 @@
 struct bus *get_pbus_smbus(device_t dev)
 {
 	struct bus *pbus = dev->bus;
-	while(pbus && pbus->dev && !ops_smbus_bus(pbus)) {
+	while (pbus && pbus->dev && !ops_smbus_bus(pbus)) {
 		pbus = pbus->dev->bus;
 	}
 	if (!pbus || !pbus->dev || !pbus->dev->ops || !pbus->dev->ops->ops_smbus_bus) {
@@ -18,9 +18,10 @@
 	return pbus;
 }
 
-	/*multi level i2c MUX??? may need to find the first i2c device and then set link down to current dev
-                 1 store get_pbus_smbus list link
-                 2 reverse the link and call set link */
+/*multi level i2c MUX??? may need to find the first i2c device and then set link
+ * down to current dev
+  1 store get_pbus_smbus list link
+  2 reverse the link and call set link */
 
 int smbus_set_link(device_t dev)
 {
@@ -33,10 +34,10 @@
                 pbus = pbus->dev->bus;
         }
 //	printk_info("smbus_set_link: ");
-	for(i=pbus_num-1; i>=0; i--) {
+	for (i=pbus_num-1; i>=0; i--) {
 //		printk_info(" %s[%d] -> ", dev_path(pbus_a[i]->dev), pbus_a[i]->link);
-        	if(ops_smbus_bus(get_pbus_smbus(pbus_a[i]->dev))) {
-                	if(pbus_a[i]->dev->ops && pbus_a[i]->dev->ops->set_link)
+        	if (ops_smbus_bus(get_pbus_smbus(pbus_a[i]->dev))) {
+                	if (pbus_a[i]->dev->ops && pbus_a[i]->dev->ops->set_link)
                         	pbus_a[i]->dev->ops->set_link(pbus_a[i]->dev, pbus_a[i]->link);
 		}
 	}
diff --git a/src/northbridge/amd/amdk8/northbridge.c b/src/northbridge/amd/amdk8/northbridge.c
index 788d698..7612d39 100644
--- a/src/northbridge/amd/amdk8/northbridge.c
+++ b/src/northbridge/amd/amdk8/northbridge.c
@@ -424,6 +424,8 @@
 {
 	struct resource *resource;
 	unsigned link;
+	uint32_t base, limit;
+	unsigned reg;
 	for (link = 0; link < dev->links; link++) {
 		if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
 			printk_info("%s: bridge on link %d has VGA device\n",
@@ -433,12 +435,29 @@
 			resource =  amdk8_find_mempair(dev, nodeid, link);
 			printk_info("MEM pair register %x\n", resource->index - 0x100);
 			resource->base = 0xa0000;
-			resource->size = 0x00000;
+			resource->size = 0x20000;
 			resource->gran = 16;
 			resource->align = 16;
-			resource->flags = IORESOURCE_PREFETCH | IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_ASSIGNED;
+			resource->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_ASSIGNED;
 		}
 	}
+#if 1
+	reg  = resource->index & 0xfc;
+	base  = f1_read_config32(reg);
+	limit = f1_read_config32(reg + 0x4);
+	base  &= 0x000000f0;
+	base  |= (resource->base >> 8) & 0xffffff00;
+	base  |= 3;
+	limit &= 0x00000048;
+	limit |= ((resource->base + resource->size) >> 8) & 0xffffff00;
+	limit |= (resource->index & 3) << 4;
+	limit |= (nodeid & 7);
+	f1_write_config32(reg + 0x4, limit);
+	f1_write_config32(reg, base);
+
+	/* release the resource */
+	resource->flags = 0;
+#endif
 }
 static void amdk8_set_resources(device_t dev)
 {