Add an option to enable PCIe root port coalescing

Background: The PCI spec (3.0-3.2.2.3.4) requires that PCI devices
implement function 0.  The Linux Kernel therefore will not enumerate
a PCI device if it does not present a valid config space at function 0.

If a board does not have anything connected to root port 0 and it is
desired to disable the unused ports in order to save power then this
will cause the other downstream PCIe devices to go missing as they
will not be enumerated.

Intel chipsets provide a way to map root port numbers to different PCI
function numbers, thereby avoiding this issue and allowing root port 0
to be turned off.

This change adds a new chip config option 'pcie_port_coalesce' that
will collapse the enabled root ports into a linear map starting at
zero.  This option defaults to disabled as it can have a confusing
effect on the system as the declared static devicetree may not match
what is seen at runtime.  This option is also forced on if the static
devicetree disables port 0.

When each root port is processed in the early enable stage it looks
for a lower numbered root port that has been disabled and then swaps
the two assigned function numbers.

However the mapping register is write-once so it has to keep track of
the proposed mapping changes until all ports have been processed
before writing out the final map value.  At this point it also updates
the function numbers in the static device tree so they are consistent
with the new layout.

There are a few other closely related fixes in this change:

1) There is a power savings opportunity if an entire bank of ports
(0-3 or 4-7) are disabled.  This was checking the chipset revision to
look for CougarPoint B1+ stepping and that was not passing on
PantherPoint where this should always be applied.  To fix this I added
a function to determine the chipset type based on comparing the upper
byte of the device ID.

2) Apply the same chipset type check fix to the IOBP programming.

3) There is another power savings opportunity to enable dynamic clock
gating on shared PCIe resources which only applies to ports 0 and 4.
However if 0 or 4 is disabled then the later check to enable this
would fail as that device is already hidden.

LUMPY current:

  00:1c.0 PCI bridge: Intel Corporation Device 1c10 (rev b5)
  00:1c.3 PCI bridge: Intel Corporation Device 1c16 (rev b5)
  01:00.0 Network controller: Atheros Communications Inc. Device 0030 (rev 01)
  02:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B

LUMPY with PCIe port coalesce enabled:

  00:1c.0 PCI bridge: Intel Corporation Device 1c10 (rev b5)
  00:1c.1 PCI bridge: Intel Corporation Device 1c16 (rev b5)
  01:00.0 Network controller: Atheros Communications Inc. Device 0030 (rev 01)
  02:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B

Change-Id: I828aa407fdc9c156c1c42eda8e2d893c0aa66eef
Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: http://review.coreboot.org/979
Tested-by: build bot (Jenkins)
diff --git a/src/southbridge/intel/bd82x6x/pch.h b/src/southbridge/intel/bd82x6x/pch.h
index 80b09e2..7b646f3 100644
--- a/src/southbridge/intel/bd82x6x/pch.h
+++ b/src/southbridge/intel/bd82x6x/pch.h
@@ -2,7 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2008-2009 coresystems GmbH
- * Copyright (C) 2011 Google Inc.
+ * Copyright (C) 2012 The Chromium OS Authors.  All rights reserved.
  *
  * 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
@@ -21,6 +21,10 @@
 #ifndef SOUTHBRIDGE_INTEL_BD82X6X_PCH_H
 #define SOUTHBRIDGE_INTEL_BD82X6X_PCH_H
 
+/* PCH types */
+#define PCH_TYPE_CPT	0x1c /* CougarPoint */
+#define PCH_TYPE_PPT	0x1e /* IvyBridge */
+
 /* PCH stepping values for LPC device */
 #define PCH_STEP_A0	0
 #define PCH_STEP_A1	1
@@ -57,6 +61,8 @@
 #if !defined(__PRE_RAM__) && !defined(__SMM__)
 #include "chip.h"
 int pch_silicon_revision(void);
+int pch_silicon_type(void);
+int pch_silicon_supported(int type, int rev);
 void pch_enable(device_t dev);
 void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue);
 #else
@@ -270,8 +276,17 @@
 #define RP6D		0x0180	/* 32bit */
 #define RP6BA		0x0188	/* 64bit */
 
-#define RPC		0x0224	/* 32bit */
-#define RPFN		0x0238	/* 32bit */
+#define RPC		0x0400	/* 32bit */
+#define RPFN		0x0404	/* 32bit */
+
+/* Root Port configuratinon space hide */
+#define RPFN_HIDE(port)         (1 << (((port) * 4) + 3))
+/* Get the function number assigned to a Root Port */
+#define RPFN_FNGET(reg,port)    (((reg) >> ((port) * 4)) & 7)
+/* Set the function number for a Root Port */
+#define RPFN_FNSET(port,func)   (((func) & 7) << ((port) * 4))
+/* Root Port function number mask */
+#define RPFN_FNMASK(port)       (7 << ((port) * 4))
 
 #define TRSR		0x1e00	/*  8bit */
 #define TRCR		0x1e10	/* 64bit */