[Nouveau] [PATCH 03/11] nvkm/gddr5: MR calculation for timing table v1.0

Roy Spliet nouveau at spliet.org
Mon Apr 10 19:37:20 UTC 2017


Merges in skeggsb's:
"fb/ram/gf10x: timing_10_0e_30"

Todo:
- find l3, rq
- triple-check

Signed-off-by: Roy Spliet <nouveau at spliet.org>
---
 .../drm/nouveau/include/nvkm/subdev/bios/ramcfg.h  | 12 +++---
 drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c  | 22 ++++++++--
 drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c  |  2 +
 drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c     | 21 ++++++++--
 drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c  | 49 ++++++++++++----------
 5 files changed, 71 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
index 4560a52..44e4ca2 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h
@@ -40,6 +40,10 @@ struct nvbios_ramcfg {
 	unsigned ramcfg_DLLoff;
 	unsigned ramcfg_RON;
 	unsigned ramcfg_FBVDDQ;
+	unsigned ramcfg_LowFreq;
+	unsigned ramcfg_WCKPin;
+	unsigned ramcfg_Hf_VREF;
+	unsigned ramcfg_VREFD_off;
 	union {
 		struct {
 			unsigned ramcfg_00_03_01:1;
@@ -82,12 +86,9 @@ struct nvbios_ramcfg {
 			unsigned ramcfg_11_01_04:1;
 			unsigned ramcfg_11_01_08:1;
 			unsigned ramcfg_11_01_10:1;
-			unsigned ramcfg_11_01_40:1;
-			unsigned ramcfg_11_01_80:1;
 			unsigned ramcfg_11_02_03:2;
 			unsigned ramcfg_11_02_04:1;
 			unsigned ramcfg_11_02_08:1;
-			unsigned ramcfg_11_02_10:1;
 			unsigned ramcfg_11_02_40:1;
 			unsigned ramcfg_11_02_80:1;
 			unsigned ramcfg_11_03_0f:4;
@@ -95,7 +96,6 @@ struct nvbios_ramcfg {
 			unsigned ramcfg_11_03_c0:2;
 			unsigned ramcfg_11_03_f0:4;
 			unsigned ramcfg_11_04:8;
-			unsigned ramcfg_11_06:8;
 			unsigned ramcfg_11_07_02:1;
 			unsigned ramcfg_11_07_04:1;
 			unsigned ramcfg_11_07_08:1;
@@ -132,6 +132,7 @@ struct nvbios_ramcfg {
 			unsigned timing_10_RRD:8;
 			unsigned timing_10_XPDLL:8;
 			unsigned timing_10_ODT:3;
+			unsigned timing_10_DS:2;
 			/* empty: 15 */
 			unsigned timing_10_10:8;
 			/* empty: 17 */
@@ -139,7 +140,8 @@ struct nvbios_ramcfg {
 			unsigned timing_10_CWL:8;
 			unsigned timing_10_FAW:8;
 			unsigned timing_10_CKE:8;
-			/* empty: 22, 23 */
+			unsigned timing_10_ADRCMD_T:8;  /* XXX: [3:2]? */
+			/* empty: 23 */
 			unsigned timing_10_18:8;
 		};
 		struct {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
index 131d967..0d517a0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
@@ -205,8 +205,11 @@ nvbios_rammapSp(struct nvkm_bios *bios, u32 data,
 		p->ramcfg_10_02_20 = (nvbios_rd08(bios, data + 0x02) & 0x20) >> 5;
 		p->ramcfg_DLLoff   = (nvbios_rd08(bios, data + 0x02) & 0x40) >> 6;
 		p->ramcfg_10_03_0f = (nvbios_rd08(bios, data + 0x03) & 0x0f) >> 0;
+		p->ramcfg_LowFreq  = (nvbios_rd08(bios, data + 0x03) & 0x20) >> 5;
+		p->ramcfg_WCKPin   = (nvbios_rd08(bios, data + 0x03) & 0x40) >> 6;
 		p->ramcfg_10_04_01 = (nvbios_rd08(bios, data + 0x04) & 0x01) >> 0;
 		p->ramcfg_FBVDDQ   = (nvbios_rd08(bios, data + 0x04) & 0x08) >> 3;
+		p->ramcfg_Hf_VREF  = (nvbios_rd08(bios, data + 0x04) & 0x20) >> 5;
 		p->ramcfg_10_05_0f = (nvbios_rd08(bios, data + 0x05) & 0x0f) >> 0;
 		p->ramcfg_10_05_f0 = (nvbios_rd08(bios, data + 0x05) & 0xf0) >> 4;
 		p->ramcfg_10_06_0f = (nvbios_rd08(bios, data + 0x06) & 0x0f) >> 0;
@@ -216,6 +219,17 @@ nvbios_rammapSp(struct nvkm_bios *bios, u32 data,
 		p->ramcfg_10_08    = (nvbios_rd08(bios, data + 0x08) & 0xff) >> 0;
 		p->ramcfg_10_09_0f = (nvbios_rd08(bios, data + 0x09) & 0x0f) >> 0;
 		p->ramcfg_10_09_f0 = (nvbios_rd08(bios, data + 0x09) & 0xf0) >> 4;
+
+		switch (elen) {
+		case 0xe:
+		case 0xd:
+			p->ramcfg_VREFD_off = nvbios_rd08(bios, data + 0x0c);
+		case 0xc:
+		case 0xb:
+		default:
+			break;
+		}
+
 		break;
 	case 0x11:
 		p->ramcfg_timing   =  nvbios_rd08(bios, data + 0x00);
@@ -225,12 +239,12 @@ nvbios_rammapSp(struct nvkm_bios *bios, u32 data,
 		p->ramcfg_11_01_08 = (nvbios_rd08(bios, data + 0x01) & 0x08) >> 3;
 		p->ramcfg_11_01_10 = (nvbios_rd08(bios, data + 0x01) & 0x10) >> 4;
 		p->ramcfg_DLLoff =   (nvbios_rd08(bios, data + 0x01) & 0x20) >> 5;
-		p->ramcfg_11_01_40 = (nvbios_rd08(bios, data + 0x01) & 0x40) >> 6;
-		p->ramcfg_11_01_80 = (nvbios_rd08(bios, data + 0x01) & 0x80) >> 7;
+		p->ramcfg_LowFreq  = (nvbios_rd08(bios, data + 0x01) & 0x40) >> 6;
+		p->ramcfg_WCKPin   = (nvbios_rd08(bios, data + 0x01) & 0x80) >> 7;
 		p->ramcfg_11_02_03 = (nvbios_rd08(bios, data + 0x02) & 0x03) >> 0;
 		p->ramcfg_11_02_04 = (nvbios_rd08(bios, data + 0x02) & 0x04) >> 2;
 		p->ramcfg_11_02_08 = (nvbios_rd08(bios, data + 0x02) & 0x08) >> 3;
-		p->ramcfg_11_02_10 = (nvbios_rd08(bios, data + 0x02) & 0x10) >> 4;
+		p->ramcfg_Hf_VREF  = (nvbios_rd08(bios, data + 0x02) & 0x10) >> 4;
 		p->ramcfg_11_02_40 = (nvbios_rd08(bios, data + 0x02) & 0x40) >> 6;
 		p->ramcfg_11_02_80 = (nvbios_rd08(bios, data + 0x02) & 0x80) >> 7;
 		p->ramcfg_11_03_0f = (nvbios_rd08(bios, data + 0x03) & 0x0f) >> 0;
@@ -238,7 +252,7 @@ nvbios_rammapSp(struct nvkm_bios *bios, u32 data,
 		p->ramcfg_11_03_c0 = (nvbios_rd08(bios, data + 0x03) & 0xc0) >> 6;
 		p->ramcfg_11_03_f0 = (nvbios_rd08(bios, data + 0x03) & 0xf0) >> 4;
 		p->ramcfg_11_04    = (nvbios_rd08(bios, data + 0x04) & 0xff) >> 0;
-		p->ramcfg_11_06    = (nvbios_rd08(bios, data + 0x06) & 0xff) >> 0;
+		p->ramcfg_VREFD_off = (nvbios_rd08(bios, data + 0x06) & 0xff) >> 0;
 		p->ramcfg_11_07_02 = (nvbios_rd08(bios, data + 0x07) & 0x02) >> 1;
 		p->ramcfg_11_07_04 = (nvbios_rd08(bios, data + 0x07) & 0x04) >> 2;
 		p->ramcfg_11_07_08 = (nvbios_rd08(bios, data + 0x07) & 0x08) >> 3;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c
index c36be13..f1999e3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c
@@ -104,6 +104,7 @@ nvbios_timingEp(struct nvkm_bios *bios, int idx,
 		p->timing_10_ODT   = nvbios_rd08(bios, data + 0x0e) & 0x07;
 		if (p->ramcfg_ver >= 0x10)
 			p->ramcfg_RON = nvbios_rd08(bios, data + 0x0e) & 0x07;
+		p->timing_10_DS    = nvbios_rd08(bios, data + 0xe) & 0x30 >> 4;
 
 		p->timing_10_18  = 0xff;
 		p->timing_10_CKE = 0;
@@ -117,6 +118,7 @@ nvbios_timingEp(struct nvkm_bios *bios, int idx,
 			p->timing_10_18  = nvbios_rd08(bios, data + 0x18);
 		case 0x18:
 		case 0x17:
+			p->timing_10_ADRCMD_T = nvbios_rd08(bios, data + 0x16);
 		case 0x16:
 			p->timing_10_CKE = nvbios_rd08(bios, data + 0x15);
 		case 0x15:
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c
index 2cc074d..22e1e0b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c
@@ -39,14 +39,18 @@ nvkm_gddr5_calc(struct nvkm_ram *ram, bool nuts)
 	int rq = ram->freq < 1000000; /* XXX */
 
 	xd = !ram->next->bios.ramcfg_DLLoff;
+	lf =  ram->next->bios.ramcfg_LowFreq;
+	pd =  ram->next->bios.ramcfg_WCKPin;
+	vh =  ram->next->bios.ramcfg_Hf_VREF;
+	vo =  ram->next->bios.ramcfg_VREFD_off;
 
 	switch (ram->next->bios.ramcfg_ver) {
+	case 0x10:
+		vr = 0;
+		l3 = (ram->mr[5] & 0x4) >> 2;
+		break;
 	case 0x11:
-		pd =  ram->next->bios.ramcfg_11_01_80;
-		lf =  ram->next->bios.ramcfg_11_01_40;
-		vh =  ram->next->bios.ramcfg_11_02_10;
 		vr =  ram->next->bios.ramcfg_11_02_04;
-		vo =  ram->next->bios.ramcfg_11_06;
 		l3 = !ram->next->bios.ramcfg_11_07_02;
 		break;
 	default:
@@ -54,6 +58,15 @@ nvkm_gddr5_calc(struct nvkm_ram *ram, bool nuts)
 	}
 
 	switch (ram->next->bios.timing_ver) {
+	case 0x10:
+		WL = ram->next->bios.timing_10_CWL;
+		CL = ram->next->bios.timing_10_CL;
+		WR = ram->next->bios.timing_10_WR;
+		at[0] = ram->next->bios.timing_10_ADRCMD_T & 0x3;
+		at[1] = 0;
+		dt = ram->next->bios.timing_10_ODT;
+		ds = ram->next->bios.timing_10_DS;
+		break;
 	case 0x20:
 		WL = (ram->next->bios.timing[1] & 0x00000f80) >> 7;
 		CL = (ram->next->bios.timing[1] & 0x0000001f);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
index 6ebdc4c..b4fe3bb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
@@ -50,11 +50,7 @@ struct gf100_ramfuc {
 
 	struct ramfuc_reg r_0x10f290[5];
 
-	struct ramfuc_reg r_0x10f300;
-	struct ramfuc_reg r_0x10f338;
-	struct ramfuc_reg r_0x10f340;
-	struct ramfuc_reg r_0x10f344;
-	struct ramfuc_reg r_0x10f348;
+	struct ramfuc_reg r_mr[9];
 
 	struct ramfuc_reg r_0x10f910;
 	struct ramfuc_reg r_0x10f914;
@@ -226,6 +222,19 @@ gf100_ram_calc(struct nvkm_ram *base, u32 freq)
 	if (ret)
 		return ret;
 
+	/* Determine ram-specific MR values */
+	for (i = 0; i < 9; i++)
+		ram->base.mr[i] = ram_rd32(fuc, mr[i]);
+
+	switch (ram->base.type) {
+	case NVKM_RAM_TYPE_GDDR5:
+		ret = nvkm_gddr5_calc(&ram->base, false);
+		break;
+	default:
+		ret = -ENOSYS;
+		break;
+	}
+
 	/* determine current mclk configuration */
 	from = !!(ram_rd32(fuc, 0x1373f0) & 0x00000002); /*XXX: ok? */
 
@@ -354,9 +363,6 @@ gf100_ram_calc(struct nvkm_ram *base, u32 freq)
 		ram_nsec(fuc, 2000);
 		ram_wr32(fuc, 0x10f314, 0x00000001);
 		ram_wr32(fuc, 0x10f210, 0x80000000);
-		ram_wr32(fuc, 0x10f338, 0x00300220);
-		ram_wr32(fuc, 0x10f300, 0x0000011d);
-		ram_nsec(fuc, 1000);
 	} else {
 		ram_wr32(fuc, 0x10f800, 0x00001800);
 		ram_wr32(fuc, 0x13d8f4, 0x00000000);
@@ -382,25 +388,26 @@ gf100_ram_calc(struct nvkm_ram *base, u32 freq)
 		ram_nsec(fuc, 2000);
 		ram_wr32(fuc, 0x10f314, 0x00000001);
 		ram_wr32(fuc, 0x10f210, 0x80000000);
-		ram_wr32(fuc, 0x10f338, 0x00300200);
-		ram_wr32(fuc, 0x10f300, 0x0000084d);
-		ram_nsec(fuc, 1000);
 	}
 
+	ram_wr32(fuc, mr[3], ram->base.mr[3]);
+	ram_wr32(fuc, mr[0], ram->base.mr[0]);
+	ram_nsec(fuc, 1000);
+
 	for (i = 0; i < 5; i++)
 		ram_wr32(fuc, 0x10f290[i], timing[i]);
 
 	if (mode == 0) {
 		ram_wr32(fuc, 0x10f614, 0x40044f77);
 		ram_wr32(fuc, 0x10f610, 0x40044f77);
-		ram_wr32(fuc, 0x10f344, 0x00600009);
+		ram_wr32(fuc, mr[6], 0x00600009);
 		ram_nsec(fuc, 1000);
-		ram_wr32(fuc, 0x10f348, 0x00700008);
+		ram_wr32(fuc, mr[7], 0x00700008);
 		ram_wr32(fuc, 0x61c140, 0x19240000);
 		ram_wr32(fuc, 0x10f830, 0x00300017);
 		gf100_ram_train(fuc, 0x80021001);
 		gf100_ram_train(fuc, 0x80081001);
-		ram_wr32(fuc, 0x10f340, 0x00500004);
+		ram_wr32(fuc, mr[5], 0x00500004);
 		ram_nsec(fuc, 1000);
 		ram_wr32(fuc, 0x10f830, 0x01300017);
 		ram_wr32(fuc, 0x10f830, 0x00300017);
@@ -412,11 +419,11 @@ gf100_ram_calc(struct nvkm_ram *base, u32 freq)
 		ram_wr32(fuc, 0x10f200, 0x00ce0000);
 		ram_wr32(fuc, 0x10f614, 0x60044e77);
 		ram_wr32(fuc, 0x10f610, 0x60044e77);
-		ram_wr32(fuc, 0x10f340, 0x00500000);
+		ram_wr32(fuc, mr[5], 0x00500000);
 		ram_nsec(fuc, 1000);
-		ram_wr32(fuc, 0x10f344, 0x00600228);
+		ram_wr32(fuc, mr[6], 0x00600228);
 		ram_nsec(fuc, 1000);
-		ram_wr32(fuc, 0x10f348, 0x00700000);
+		ram_wr32(fuc, mr[7], 0x00700000);
 		ram_wr32(fuc, 0x13d8f4, 0x00000000);
 		ram_wr32(fuc, 0x61c140, 0x09a40000);
 
@@ -706,11 +713,9 @@ gf100_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
 	for (i = 0; i < 5; i++)
 		ram->fuc.r_0x10f290[i] = ramfuc_reg(0x10f290 + (i * 4));
 
-	ram->fuc.r_0x10f300 = ramfuc_reg(0x10f300);
-	ram->fuc.r_0x10f338 = ramfuc_reg(0x10f338);
-	ram->fuc.r_0x10f340 = ramfuc_reg(0x10f340);
-	ram->fuc.r_0x10f344 = ramfuc_reg(0x10f344);
-	ram->fuc.r_0x10f348 = ramfuc_reg(0x10f348);
+	ram->fuc.r_mr[0] = ramfuc_reg(0x10f300);
+	for (i = 1; i < 9; i++)
+		ram->fuc.r_mr[i] = ramfuc_reg(0x10f330 + ((i - 1) * 4));
 
 	ram->fuc.r_0x10f910 = ramfuc_reg(0x10f910);
 	ram->fuc.r_0x10f914 = ramfuc_reg(0x10f914);
-- 
2.9.3



More information about the Nouveau mailing list