RS780 PCIE GEN2 Software Compliance support

Signed-off-by: Kerry She <Kerry.she@amd.com>

Index: src/southbridge/amd/rs780/rs780.h
===================================================================
--- src/southbridge/amd/rs780/rs780.h	(revision 6481)
+++ src/southbridge/amd/rs780/rs780.h	(working copy)
@@ -208,6 +208,7 @@
 void config_gpp_core(device_t nb_dev, device_t sb_dev);
 void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port);
 u8 PcieTrainPort(device_t nb_dev, device_t dev, u32 port);
+void init_gen2(device_t nb_dev, device_t dev, u8 port);
 u32 extractbit(u32 data, int bit_number);
 u32 extractbits(u32 source, int lsb, int msb);
 int cpuidFamily(void);
Index: src/southbridge/amd/rs780/pcie.c
===================================================================
--- src/southbridge/amd/rs780/pcie.c	(revision 6481)
+++ src/southbridge/amd/rs780/pcie.c	(working copy)
@@ -225,6 +225,64 @@
 	ProgK8TempMmioBase(0, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS);
 }
 
+/*
+ * GEN2 Software Compliance
+ */
+void init_gen2(device_t nb_dev, device_t dev, u8 port)
+{
+	u32 reg, val;
+
+	/* for A11 (0x89 == 0) */
+	reg = 0x34;
+	if (port <= 3) {
+		val = 1<<5;
+	} else {
+		val = 1<<31;
+		if (port >= 9)
+			reg = 0x39;
+	}
+
+	/* TODO: check for rev > a11 */
+	switch (port) {
+		case 2:
+			reg = 0x34;
+			val = 1<<5;
+			break;
+		case 3:
+			reg = 0x22;
+			val = 1<<6;
+			break;
+		case 4:
+			reg = 0x34;
+			val = 1<<31;
+			break;
+		case 5:
+		case 6:
+			reg = 0x39;
+			val = 1<<31;
+			break;
+		case 7:
+		case 8:
+		case 9:
+			reg = 0x37;
+			val = 1<<port;
+			break;
+		case 10:
+			reg = 0x22;
+			val = 1<<5;
+			break;
+		default:
+			reg = 0;
+			break;
+	}
+
+	/* Enables GEN2 capability of the device */
+	set_pcie_enable_bits(dev, 0xA4, 0x1, 0x1);
+	/* Advertise the link speed to be Gen2 */
+	pci_ext_write_config32(nb_dev, dev, 0x88, 0xF0, 1<<2); /* LINK_CRTL2 */
+	set_nbmisc_enable_bits(nb_dev, reg, val, val);
+}
+
 /*****************************************
 * Compliant with CIM_33's PCIEGPPInit
 * nb_dev:
@@ -334,6 +392,12 @@
 	/* step 5: dynamic slave CPL buffer allocation. Disable it, otherwise linux hangs. Why? */
 	/* set_pcie_enable_bits(nb_dev, 0x20 | gfx_gpp_sb_sel, 1 << 11, 1 << 11); */
 
+	/* set automatic Gen2 support, needs mainboard config option as Gen2 can cause issues on some platforms. */
+	init_gen2(nb_dev, dev, port);
+	set_pcie_enable_bits(dev, 0xA4, 1 << 29, 1 << 29);
+	set_pcie_enable_bits(dev, 0xC0, 1 << 15, 0);
+	set_pcie_enable_bits(dev, 0xA2, 1 << 13, 0);
+
 	/* step 5a: Training for GPP devices */
 	/* init GPP */
 	switch (port) {
Index: src/southbridge/amd/rs780/cmn.c
===================================================================
--- src/southbridge/amd/rs780/cmn.c	(revision 6481)
+++ src/southbridge/amd/rs780/cmn.c	(working copy)
@@ -259,6 +259,7 @@
 {
 	u16 count = 5000;
 	u32 lc_state, reg, current_link_width, lane_mask;
+	u32 lc_speed;
 	int8_t current, res = 0;
 	u32 gfx_gpp_sb_sel;
 	void set_pcie_dereset(void);
@@ -347,6 +348,25 @@
 			break;
 		}
 	}
+
+	lc_speed = nbpcie_p_read_index(dev, 0xA4); /* lc_speed_cntl */
+	printk(BIOS_DEBUG, "port=%x: lc_speed_cntl=%x\n", port, lc_speed);
+	if (lc_speed & (1 << 27)) {
+		printk(BIOS_DEBUG, "Gen2 support advertised, ");
+	} else {
+		printk(BIOS_DEBUG, "Only Gen1 support advertised, ");
+	}
+	if (lc_speed & (1 << 24)) {
+		printk(BIOS_DEBUG, "Device currently support Gen2\n");
+	} else {
+		printk(BIOS_DEBUG, "Device currently not support Gen2\n");
+	}
+	if (lc_speed & (1 << 11)) {
+		printk(BIOS_DEBUG, "Current Data Rate is Gen2\n");
+	} else {
+		printk(BIOS_DEBUG, "Current Data Rate is Gen1\n");
+	}
+
 	return res;
 }
 
