[coreboot-gerrit] Patch set updated for coreboot: 4deb1ef amd/agesa/hudson: Implement PNP resource setup in LPC bridge

Rudolf Marek (r.marek@assembler.cz) gerrit at coreboot.org
Sat Feb 1 21:43:36 CET 2014


Rudolf Marek (r.marek at assembler.cz) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4497

-gerrit

commit 4deb1ef15c47bb30ad995cf232dd356bf67fc7f7
Author: Rudolf Marek <r.marek at assembler.cz>
Date:   Sat Dec 7 22:29:36 2013 +0100

    amd/agesa/hudson: Implement PNP resource setup in LPC bridge
    
    The previous SBxxx generations were setting up LPC bridge based
    on the PNP resources. Implement it also for AGESA Hudson.
    The AGESA itself opens one big region DFLT_SIO_PME_BASE_ADDRESS
    (512 bytes). Make the code smart enough to detect already used
    region and if any resource fits into AGESA defined region, do nothing.
    
    Change-Id: I718d034bc4c778697a7bd0506d4550c8f5a43159
    Signed-off-by: Rudolf Marek <r.marek at assembler.cz>
---
 src/southbridge/amd/agesa/hudson/lpc.c | 174 ++++++++++++++++++++++++++++++++-
 1 file changed, 173 insertions(+), 1 deletion(-)

diff --git a/src/southbridge/amd/agesa/hudson/lpc.c b/src/southbridge/amd/agesa/hudson/lpc.c
index 3af3eb8..a0dc072 100644
--- a/src/southbridge/amd/agesa/hudson/lpc.c
+++ b/src/southbridge/amd/agesa/hudson/lpc.c
@@ -129,8 +129,180 @@ static void hudson_lpc_set_resources(struct device *dev)
  */
 static void hudson_lpc_enable_childrens_resources(device_t dev)
 {
-	printk(BIOS_DEBUG, "hudson_lpc_enable_childrens_resources\n");
+	struct bus *link;
+	u32 reg, reg_x;
+	int var_num = 0;
+	u16 reg_var[3];
+	u16 reg_size[1] =  {512};
+	u8 wiosize = pci_read_config8(dev, 0x74);
 
+	/* Be bit relaxed, tolerate that LPC region might be bigger than resource we try to fit,
+	 * do it like this for all regions < 16 bytes. If there is a resource > 16 bytes
+	 * it must be 512 bytes to be able to allocate the fresh LPC window.
+	 *
+	 * AGESA likes to enable already one LPC region in wide port base 0x64-0x65,
+	 * using DFLT_SIO_PME_BASE_ADDRESS, 512 bytes size
+	 * The code tries to check if resource can fit into this region
+	 */
+
+	reg = pci_read_config32(dev, 0x44);
+	reg_x = pci_read_config32(dev, 0x48);
+
+	/* check if ranges are free and not use them if entry is just already taken */
+	if (reg_x & (1 << 2))
+		var_num = 1;
+	/* just in case check if someone did not manually set other ranges too */
+	if (reg_x & (1 << 24))
+		var_num = 2;
+
+	if (reg_x & (1 << 25))
+		var_num = 3;
+
+	/* check AGESA region size */
+	if (wiosize & (1 << 0))
+		reg_size[0] = 16;
+
+	reg_var[2] = pci_read_config16(dev, 0x90);
+	reg_var[1] = pci_read_config16(dev, 0x66);
+	reg_var[0] = pci_read_config16(dev, 0x64);
+
+	for (link = dev->link_list; link; link = link->next) {
+		device_t child;
+		for (child = link->children; child;
+		     child = child->sibling) {
+			if (child->enabled
+			    && (child->path.type == DEVICE_PATH_PNP)) {
+				struct resource *res;
+				for (res = child->resource_list; res; res = res->next) {
+					u32 base, end;	/*  don't need long long */
+					u32 rsize, set = 0, set_x = 0;
+					if (!(res->flags & IORESOURCE_IO))
+						continue;
+					base = res->base;
+					end = resource_end(res);
+					/* find a resource size */
+					printk(BIOS_DEBUG, "hudson lpc decode:%s, base=0x%08x, end=0x%08x\n",
+					     dev_path(child), base, end);
+					switch (base) {
+					case 0x60:	/*  KB */
+					case 0x64:	/*  MS */
+						set |= (1 << 29);
+						rsize = 1;
+						break;
+					case 0x3f8:	/*  COM1 */
+						set |= (1 << 6);
+						rsize = 8;
+						break;
+					case 0x2f8:	/*  COM2 */
+						set |= (1 << 7);
+						rsize = 8;
+						break;
+					case 0x378:	/*  Parallel 1 */
+						set |= (1 << 0);
+						set |= (1 << 1); /* + 0x778 for ECP */
+						rsize = 8;
+						break;
+					case 0x3f0:	/*  FD0 */
+						set |= (1 << 26);
+						rsize = 8;
+						break;
+					case 0x220:	/*  0x220 - 0x227 */
+						set |= (1 << 8);
+						rsize = 8;
+						break;
+					case 0x228:	/*  0x228 - 0x22f */
+						set |= (1 << 9);
+						rsize = 8;
+						break;
+					case 0x238:	/*  0x238 - 0x23f */
+						set |= (1 << 10);
+						rsize = 8;
+						break;
+					case 0x300:	/*  0x300 -0x301 */
+						set |= (1 << 18);
+						rsize = 2;
+						break;
+					case 0x400:
+						set_x |= (1 << 16);
+						rsize = 0x40;
+						break;
+					case 0x480:
+						set_x |= (1 << 17);
+						rsize = 0x40;
+					case 0x500:
+						set_x |= (1 << 18);
+						rsize = 0x40;
+						break;
+					case 0x580:
+						set_x |= (1 << 19);
+						rsize = 0x40;
+						break;
+					case 0x4700:
+						set_x |= (1 << 22);
+						rsize = 0xc;
+						break;
+					case 0xfd60:
+						set_x |= (1 << 23);
+						rsize = 16;
+						break;
+					default:
+						rsize = 0;
+						/* try AGESA allocated region in region 0 */
+						if ((var_num > 0) && ((base >=reg_var[0]) &&
+								((base + res->size) <= (reg_var[0] + reg_size[0]))))
+							rsize = reg_size[0];
+					}
+					/* check if region found and matches the enable */
+					if (res->size <= rsize) {
+						reg |= set;
+						reg_x |= set_x;
+					/* check if we can fit resource in variable range */
+					} else if ((var_num < 3) &&
+						    ((res->size <= 16) || (res->size == 512))) {
+						/* use variable ranges if pre-defined do not match */
+						switch (var_num) {
+						case 0:
+							reg_x |= (1 << 2);
+							if (res->size <= 16) {
+								wiosize |= (1 << 0);
+							}
+							break;
+						case 1:
+							reg_x |= (1 << 24);
+							if (res->size <= 16)
+								wiosize |= (1 << 2);
+							break;
+						case 2:
+							reg_x |= (1 << 25);
+							if (res->size <= 16)
+								wiosize |= (1 << 3);
+							break;
+						}
+						reg_var[var_num++] =
+						    base & 0xffff;
+					} else {
+						printk(BIOS_ERR, "cannot fit LPC decode region:%s, base=0x%08x, end=0x%08x\n",
+							dev_path(child), base, end);
+					}
+				}
+			}
+		}
+	}
+	pci_write_config32(dev, 0x44, reg);
+	pci_write_config32(dev, 0x48, reg_x);
+	/* Set WideIO for as many IOs found (fall through is on purpose) */
+	switch (var_num) {
+	case 3:
+		pci_write_config16(dev, 0x90, reg_var[2]);
+		/* fall through */
+	case 2:
+		pci_write_config16(dev, 0x66, reg_var[1]);
+		/* fall through */
+	case 1:
+		pci_write_config16(dev, 0x64, reg_var[0]);
+		break;
+	}
+	pci_write_config8(dev, 0x74, wiosize);
 }
 
 static void hudson_lpc_enable_resources(device_t dev)



More information about the coreboot-gerrit mailing list