[coreboot-gerrit] Patch set updated for coreboot: WIP, UNTESTED soc/intel/broadwell: Rework IGD's CDClk selection

Nico Huber (nico.h@gmx.de) gerrit at coreboot.org
Thu Dec 8 01:29:29 CET 2016


Nico Huber (nico.h at gmx.de) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17768

-gerrit

commit 3aad3707c3c10b00caa303ee50a1eddbce7743d6
Author: Nico Huber <nico.h at gmx.de>
Date:   Wed Dec 7 19:29:08 2016 +0100

    WIP, UNTESTED soc/intel/broadwell: Rework IGD's CDClk selection
    
    CDClk selection was wrong in some corner cases (e.g. ULX SKUs) and,
    for Broadwell, never took the devicetree config into account.
    
    Rewrite the selection with the following in mind:
    
      o cpu_is_ult() might return `true` for ULX SKUs, too,
    
      o ULX and Broadwell-ULT SKUs can be `overclocked` with additional
        cooling, so leave that as devicetree option.
    
    For Haswell, the following frequency selections are valid:
    
      o ULX: 337.5MHz by default, 450MHz optional
      o ULT: 450MHz only (maybe 337.5MHz too, documentation varies,
                          it wasn't selectable before either)
      o others: 540Mhz by default, 450MHz optional
    
    For Broadwell:
    
      o ULX: 450MHz by default, 337.5MHz / 540MHz optional
      o ULT: 540MHz by default, 337.5MHz / 450MHz / 675MHz optional
      o others: 667MHz by default, 337.5MHz / 450MHz / 540MHz optional
    
    Side effects: A too high setting in the devicetree results in the
    highest possible frequency now, Haswell non-ULT/ULX defaults to 540MHz
    instead of 450MHz.
    
    Change-Id: Iec12752f2a47bf4a5ae6077c75790eae9378c1b2
    Signed-off-by: Nico Huber <nico.h at gmx.de>
---
 src/soc/intel/broadwell/igd.c                     | 183 ++++++++++------------
 src/soc/intel/broadwell/include/soc/systemagent.h |   2 +
 2 files changed, 87 insertions(+), 98 deletions(-)

diff --git a/src/soc/intel/broadwell/igd.c b/src/soc/intel/broadwell/igd.c
index c1cfdd8..6459f90 100644
--- a/src/soc/intel/broadwell/igd.c
+++ b/src/soc/intel/broadwell/igd.c
@@ -33,11 +33,14 @@
 #include <vboot/vbnv.h>
 #include <soc/igd.h>
 
-#define GT_RETRY 		1000
-#define GT_CDCLK_337		0
-#define GT_CDCLK_450		1
-#define GT_CDCLK_540		2
-#define GT_CDCLK_675		3
+#define GT_RETRY		1000
+enum {
+	GT_CDCLK_DEFAULT = 0,
+	GT_CDCLK_337,
+	GT_CDCLK_450,
+	GT_CDCLK_540,
+	GT_CDCLK_675,
+};
 
 static u32 reg_em4;
 static u32 reg_em5;
@@ -338,81 +341,49 @@ static void igd_setup_panel(struct device *dev)
 	}
 }
 
-static void igd_cdclk_init_haswell(struct device *dev)
+static int igd_get_cdclk_haswell(u32 *const cdsel, int *const inform_pc,
+				 struct device *const dev)
 {
-	config_t *conf = dev->chip_info;
+	const config_t *const conf = dev->chip_info;
 	int cdclk = conf->cdclk;
-	int devid = pci_read_config16(dev, PCI_DEVICE_ID);
-	int gpu_is_ulx = 0;
-	u32 dpdiv, lpcll;
 
 	/* Check for ULX GT1 or GT2 */
-	if (devid == 0x0a0e || devid == 0x0a1e)
-		gpu_is_ulx = 1;
-
-	/* 675MHz is not supported on haswell */
-	if (cdclk == GT_CDCLK_675)
-		cdclk = GT_CDCLK_337;
+	const int devid = pci_read_config16(dev, PCI_DEVICE_ID);
+	const int gpu_is_ulx = devid == IGD_HASWELL_ULX_GT1 ||
+				devid == IGD_HASWELL_ULX_GT2;
 
-	/* If CD clock is fixed or ULT then set to 450MHz */
-	if ((gtt_read(0x42014) & 0x1000000) || cpu_is_ult())
+	/* Check for fixed fused clock */
+	if (gtt_read(0x42014) & 1 << 24)
 		cdclk = GT_CDCLK_450;
 
-	/* 540MHz is not supported on ULX */
-	if (gpu_is_ulx && cdclk == GT_CDCLK_540)
+	/*
+	 *    ULX defaults to 337MHz with possible override for 450MHz
+	 *    ULT is fixed at 450MHz
+	 * others default  to 540MHz with possible override for 450MHz
+	 */
+	if (gpu_is_ulx && cdclk <= GT_CDCLK_337)
 		cdclk = GT_CDCLK_337;
-
-	/* 337.5MHz is not supported on non-ULT/ULX */
-	if (!gpu_is_ulx && !cpu_is_ult() && cdclk == GT_CDCLK_337)
+	else if (gpu_is_ulx || cpu_is_ult() ||
+			cdclk == GT_CDCLK_337 || cdclk == GT_CDCLK_450)
 		cdclk = GT_CDCLK_450;
+	else
+		cdclk = GT_CDCLK_540;
 
-	/* Set variables based on CD Clock setting */
-	switch (cdclk) {
-	case GT_CDCLK_337:
-		dpdiv = 169;
-		lpcll = (1 << 26);
-		reg_em4 = 16;
-		reg_em5 = 225;
-		break;
-	case GT_CDCLK_450:
-		dpdiv = 225;
-		lpcll = 0;
-		reg_em4 = 4;
-		reg_em5 = 75;
-		break;
-	case GT_CDCLK_540:
-		dpdiv = 270;
-		lpcll = (1 << 26);
-		reg_em4 = 4;
-		reg_em5 = 90;
-		break;
-	default:
-		return;
-	}
-
-	/* Set LPCLL_CTL CD Clock Frequency Select */
-	gtt_rmw(0x130040, 0xf3ffffff, lpcll);
-
-	/* ULX: Inform power controller of selected frequency */
-	if (gpu_is_ulx) {
-		if (cdclk == GT_CDCLK_450)
-			gtt_write(0x138128, 0x00000000); /* 450MHz */
-		else
-			gtt_write(0x138128, 0x00000001); /* 337.5MHz */
-		gtt_write(0x13812c, 0x00000000);
-		gtt_write(0x138124, 0x80000017);
-	}
-
-	/* Set CPU DP AUX 2X bit clock dividers */
-	gtt_rmw(0x64010, 0xfffff800, dpdiv);
-	gtt_rmw(0x64810, 0xfffff800, dpdiv);
+	*cdsel = cdclk != GT_CDCLK_450;
+	*inform_pc = gpu_is_ulx;
+	return cdclk;
 }
 
-static void igd_cdclk_init_broadwell(struct device *dev)
+static int igd_get_cdclk_broadwell(u32 *const cdsel, int *const inform_pc,
+				   struct device *const dev)
 {
-	config_t *conf = dev->chip_info;
+	static const u32 cdsel_by_cdclk[] = { 0, 2, 0, 1, 3 };
+	const config_t *const conf = dev->chip_info;
 	int cdclk = conf->cdclk;
-	u32 dpdiv, lpcll, pwctl, cdset;
+
+	/* Check for ULX */
+	const int devid = pci_read_config16(dev, PCI_DEVICE_ID);
+	const int gpu_is_ulx = devid == IGD_BROADWELL_Y_GT2;
 
 	/* Inform power controller of upcoming frequency change */
 	gtt_write(0x138128, 0);
@@ -420,54 +391,69 @@ static void igd_cdclk_init_broadwell(struct device *dev)
 	gtt_write(0x138124, 0x80000018);
 
 	/* Poll GT driver mailbox for run/busy clear */
-	if (!gtt_poll(0x138124, (1 << 31), (0 << 31)))
+	if (gtt_poll(0x138124, (1 << 31), (0 << 31))) {
+		*inform_pc = 1;
+	} else {
 		cdclk = GT_CDCLK_450;
+		*inform_pc = 0;
+	}
 
-	if (gtt_read(0x42014) & 0x1000000) {
-		/* If CD clock is fixed then set to 450MHz */
+	/* Check for fixed fused clock */
+	if (gtt_read(0x42014) & 1 << 24)
 		cdclk = GT_CDCLK_450;
-	} else {
-		/* Program CD clock to highest supported freq */
-		if (cpu_is_ult())
-			cdclk = GT_CDCLK_540;
-		else
-			cdclk = GT_CDCLK_675;
-	}
 
-	/* CD clock frequency 675MHz not supported on ULT */
-	if (cpu_is_ult() && cdclk == GT_CDCLK_675)
+	/*
+	 *    ULX defaults to 450MHz with possible override up to 540MHz
+	 *    ULT defaults to 540MHz with possible override up to 675MHz
+	 * others default  to 675MHz with possible override for lower freqs
+	 */
+	if (cdclk == GT_CDCLK_337)
+		cdclk = GT_CDCLK_337;
+	else if (cdclk == GT_CDCLK_450 ||
+			(gpu_is_ulx && cdclk == GT_CDCLK_DEFAULT))
+		cdclk = GT_CDCLK_450;
+	else if (cdclk == GT_CDCLK_540 || gpu_is_ulx ||
+			(cpu_is_ult() && cdclk == GT_CDCLK_DEFAULT))
 		cdclk = GT_CDCLK_540;
+	else
+		cdclk = GT_CDCLK_675;
+
+	*cdsel = cdsel_by_cdclk[cdclk];
+	return cdclk;
+}
+
+static void igd_cdclk_init(struct device *dev, const int is_broadwell)
+{
+	u32 dpdiv, cdsel, cdval;
+	int cdclk, inform_pc;
+
+	if (is_broadwell)
+		cdclk = igd_get_cdclk_broadwell(&cdsel, &inform_pc, dev);
+	else
+		cdclk = igd_get_cdclk_haswell(&cdsel, &inform_pc, dev);
 
 	/* Set variables based on CD Clock setting */
 	switch (cdclk) {
 	case GT_CDCLK_337:
-		cdset = 337;
-		lpcll = (1 << 27);
-		pwctl = 2;
+		cdval = 337;
 		dpdiv = 169;
 		reg_em4 = 16;
 		reg_em5 = 225;
 		break;
 	case GT_CDCLK_450:
-		cdset = 449;
-		lpcll = 0;
-		pwctl = 0;
+		cdval = 449;
 		dpdiv = 225;
 		reg_em4 = 4;
 		reg_em5 = 75;
 		break;
 	case GT_CDCLK_540:
-		cdset = 539;
-		lpcll = (1 << 26);
-		pwctl = 1;
+		cdval = 539;
 		dpdiv = 270;
 		reg_em4 = 4;
 		reg_em5 = 90;
 		break;
 	case GT_CDCLK_675:
-		cdset = 674;
-		lpcll = (1 << 26) | (1 << 27);
-		pwctl = 3;
+		cdval = 674;
 		dpdiv = 338;
 		reg_em4 = 8;
 		reg_em5 = 225;
@@ -476,15 +462,17 @@ static void igd_cdclk_init_broadwell(struct device *dev)
 	}
 
 	/* Set LPCLL_CTL CD Clock Frequency Select */
-	gtt_rmw(0x130040, 0xf3ffffff, lpcll);
+	gtt_rmw(0x130040, 0xf3ffffff, cdsel << 26);
 
-	/* Inform power controller of selected frequency */
-	gtt_write(0x138128, pwctl);
-	gtt_write(0x13812c, 0);
-	gtt_write(0x138124, 0x80000017);
+	if (inform_pc) {
+		/* Inform power controller of selected frequency */
+		gtt_write(0x138128, cdsel);
+		gtt_write(0x13812c, 0);
+		gtt_write(0x138124, 0x80000017);
+	}
 
 	/* Program CD Clock Frequency */
-	gtt_rmw(0x46200, 0xfffffc00, cdset);
+	gtt_rmw(0x46200, 0xfffffc00, cdval);
 
 	/* Set CPU DP AUX 2X bit clock dividers */
 	gtt_rmw(0x64010, 0xfffff800, dpdiv);
@@ -541,11 +529,10 @@ static void igd_init(struct device *dev)
 	pci_dev_init(dev);
 
 	/* Late init steps */
+	igd_cdclk_init(dev, is_broadwell);
 	if (is_broadwell) {
-		igd_cdclk_init_broadwell(dev);
 		reg_script_run_on_dev(dev, broadwell_late_init_script);
 	} else {
-		igd_cdclk_init_haswell(dev);
 		reg_script_run_on_dev(dev, haswell_late_init_script);
 	}
 
diff --git a/src/soc/intel/broadwell/include/soc/systemagent.h b/src/soc/intel/broadwell/include/soc/systemagent.h
index d990841..125ba47 100644
--- a/src/soc/intel/broadwell/include/soc/systemagent.h
+++ b/src/soc/intel/broadwell/include/soc/systemagent.h
@@ -24,6 +24,8 @@
 #define IGD_HASWELL_ULT_GT1	0x0a06
 #define IGD_HASWELL_ULT_GT2	0x0a16
 #define IGD_HASWELL_ULT_GT3	0x0a26
+#define IGD_HASWELL_ULX_GT1	0x0a0e
+#define IGD_HASWELL_ULX_GT2	0x0a1e
 #define IGD_BROADWELL_U_GT1	0x1606
 #define IGD_BROADWELL_U_GT2	0x1616
 #define IGD_BROADWELL_U_GT3_15W	0x1626



More information about the coreboot-gerrit mailing list