[Nouveau] [PATCH 06/13] nvkm/ramgt215: Move ram training up the chain

Roy Spliet nouveau at spliet.org
Mon Apr 10 19:50:43 UTC 2017


Parts are re-used even on NVA3, others from GF100 on

Signed-off-by: Roy Spliet <nouveau at spliet.org>
---
 drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h      |  17 +++
 drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c |  92 +++++++++-----
 drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c | 140 +---------------------
 drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c |  61 ++++++++++
 4 files changed, 140 insertions(+), 170 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
index b60068b..ce8a98e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
@@ -1,6 +1,7 @@
 #ifndef __NVKM_FB_RAM_PRIV_H__
 #define __NVKM_FB_RAM_PRIV_H__
 #include "priv.h"
+#include <subdev/bios/M0209.h>
 
 int  nvkm_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *,
 		   enum nvkm_ram_type, u64 size, u32 tags,
@@ -24,6 +25,22 @@ int  gf100_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *,
 int  gf100_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **);
 void gf100_ram_put(struct nvkm_ram *, struct nvkm_mem **);
 
+/* Training */
+struct gt215_ram_train {
+	u16 mask;
+	struct nvbios_M0209S remap;
+	struct nvbios_M0209S type00;
+	struct nvbios_M0209S type01;
+	struct nvbios_M0209S type04;
+	struct nvbios_M0209S type06;
+	struct nvbios_M0209S type07;
+	struct nvbios_M0209S type08;
+	struct nvbios_M0209S type09;
+};
+int gt215_ram_train_type(struct nvkm_ram *ram, int i, u8 ramcfg,
+		     struct gt215_ram_train *train);
+int  gf100_ram_train_init(struct nvkm_ram *ram);
+
 int  gk104_ram_ctor(struct nvkm_fb *, struct nvkm_ram **, u32);
 int  gk104_ram_init(struct nvkm_ram *ram);
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
index b4fe3bb..38a7e2b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
@@ -28,6 +28,7 @@
 #include <core/option.h>
 #include <subdev/bios.h>
 #include <subdev/bios/pll.h>
+#include <subdev/bios/M0205.h>
 #include <subdev/bios/rammap.h>
 #include <subdev/bios/timing.h>
 #include <subdev/clk.h>
@@ -549,45 +550,74 @@ gf100_ram_get(struct nvkm_ram *ram, u64 size, u32 align, u32 ncmin,
 }
 
 static int
-gf100_ram_init(struct nvkm_ram *base)
+gf100_ram_train_init_0(struct nvkm_ram *ram, struct gt215_ram_train *train)
 {
-	static const u8  train0[] = {
-		0x00, 0xff, 0x55, 0xaa, 0x33, 0xcc,
-		0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
-	};
-	static const u32 train1[] = {
-		0x00000000, 0xffffffff,
-		0x55555555, 0xaaaaaaaa,
-		0x33333333, 0xcccccccc,
-		0xf0f0f0f0, 0x0f0f0f0f,
-		0x00ff00ff, 0xff00ff00,
-		0x0000ffff, 0xffff0000,
-	};
-	struct gf100_ram *ram = gf100_ram(base);
-	struct nvkm_device *device = ram->base.fb->subdev.device;
-	int i;
+	struct nvkm_subdev *subdev = &ram->fb->subdev;
+	struct nvkm_device *device = subdev->device;
+	int i, j;
 
-	switch (ram->base.type) {
+	if ((train->mask & 0x03d3) != 0x03d3) {
+		nvkm_warn(subdev, "missing link training data\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < 0x30; i++) {
+		for (j = 0; j < 8; j += 4) {
+			nvkm_wr32(device, 0x10f968 + j, 0x00000000 | (i << 8));
+			nvkm_wr32(device, 0x10f920 + j, 0x00000000 |
+						   train->type08.data[i] << 4 |
+						   train->type06.data[i]);
+			nvkm_wr32(device, 0x10f918 + j, train->type00.data[i]);
+			nvkm_wr32(device, 0x10f920 + j, 0x00000100 |
+						   train->type09.data[i] << 4 |
+						   train->type07.data[i]);
+			nvkm_wr32(device, 0x10f918 + j, train->type01.data[i]);
+		}
+	}
+
+	for (j = 0; j < 8; j += 4) {
+		for (i = 0; i < 0x100; i++) {
+			nvkm_wr32(device, 0x10f968 + j, i);
+			nvkm_wr32(device, 0x10f900 + j, train->type04.data[i]);
+		}
+	}
+
+	return 0;
+}
+
+int
+gf100_ram_train_init(struct nvkm_ram *ram)
+{
+	u8 ramcfg = nvbios_ramcfg_index(&ram->fb->subdev);
+	struct gt215_ram_train *train;
+	int ret, i;
+
+	if (!(train = kzalloc(sizeof(*train), GFP_KERNEL)))
+		return -ENOMEM;
+
+	for (i = 0; i < 0x100; i++) {
+		ret = gt215_ram_train_type(ram, i, ramcfg, train);
+		if (ret && ret != -ENOENT)
+			break;
+	}
+
+	switch (ram->type) {
 	case NVKM_RAM_TYPE_GDDR5:
+		ret = gf100_ram_train_init_0(ram, train);
 		break;
 	default:
-		return 0;
+		ret = 0;
+		break;
 	}
 
-	/* prepare for ddr link training, and load training patterns */
-	for (i = 0; i < 0x30; i++) {
-		nvkm_wr32(device, 0x10f968, 0x00000000 | (i << 8));
-		nvkm_wr32(device, 0x10f96c, 0x00000000 | (i << 8));
-		nvkm_wr32(device, 0x10f920, 0x00000100 | train0[i % 12]);
-		nvkm_wr32(device, 0x10f924, 0x00000100 | train0[i % 12]);
-		nvkm_wr32(device, 0x10f918,              train1[i % 12]);
-		nvkm_wr32(device, 0x10f91c,              train1[i % 12]);
-		nvkm_wr32(device, 0x10f920, 0x00000000 | train0[i % 12]);
-		nvkm_wr32(device, 0x10f924, 0x00000000 | train0[i % 12]);
-		nvkm_wr32(device, 0x10f918,              train1[i % 12]);
-		nvkm_wr32(device, 0x10f91c,              train1[i % 12]);
-	}
+	kfree(train);
+	return ret;
+}
 
+static int
+gf100_ram_init(struct nvkm_ram *base)
+{
+	/* XXX: Don't hook up yet for bisectability */
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
index 7904fa4..8bf4638 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
@@ -1257,144 +1257,6 @@ gk104_ram_tidy(struct nvkm_ram *base)
 	ram_exec(&ram->fuc, false);
 }
 
-struct gk104_ram_train {
-	u16 mask;
-	struct nvbios_M0209S remap;
-	struct nvbios_M0209S type00;
-	struct nvbios_M0209S type01;
-	struct nvbios_M0209S type04;
-	struct nvbios_M0209S type06;
-	struct nvbios_M0209S type07;
-	struct nvbios_M0209S type08;
-	struct nvbios_M0209S type09;
-};
-
-static int
-gk104_ram_train_type(struct nvkm_ram *ram, int i, u8 ramcfg,
-		     struct gk104_ram_train *train)
-{
-	struct nvkm_bios *bios = ram->fb->subdev.device->bios;
-	struct nvbios_M0205E M0205E;
-	struct nvbios_M0205S M0205S;
-	struct nvbios_M0209E M0209E;
-	struct nvbios_M0209S *remap = &train->remap;
-	struct nvbios_M0209S *value;
-	u8  ver, hdr, cnt, len;
-	u32 data;
-
-	/* determine type of data for this index */
-	if (!(data = nvbios_M0205Ep(bios, i, &ver, &hdr, &cnt, &len, &M0205E)))
-		return -ENOENT;
-
-	switch (M0205E.type) {
-	case 0x00: value = &train->type00; break;
-	case 0x01: value = &train->type01; break;
-	case 0x04: value = &train->type04; break;
-	case 0x06: value = &train->type06; break;
-	case 0x07: value = &train->type07; break;
-	case 0x08: value = &train->type08; break;
-	case 0x09: value = &train->type09; break;
-	default:
-		return 0;
-	}
-
-	/* training data index determined by ramcfg strap */
-	if (!(data = nvbios_M0205Sp(bios, i, ramcfg, &ver, &hdr, &M0205S)))
-		return -EINVAL;
-	i = M0205S.data;
-
-	/* training data format information */
-	if (!(data = nvbios_M0209Ep(bios, i, &ver, &hdr, &cnt, &len, &M0209E)))
-		return -EINVAL;
-
-	/* ... and the raw data */
-	if (!(data = nvbios_M0209Sp(bios, i, 0, &ver, &hdr, value)))
-		return -EINVAL;
-
-	if (M0209E.v02_07 == 2) {
-		/* of course! why wouldn't we have a pointer to another entry
-		 * in the same table, and use the first one as an array of
-		 * remap indices...
-		 */
-		if (!(data = nvbios_M0209Sp(bios, M0209E.v03, 0, &ver, &hdr,
-					    remap)))
-			return -EINVAL;
-
-		for (i = 0; i < ARRAY_SIZE(value->data); i++)
-			value->data[i] = remap->data[value->data[i]];
-	} else
-	if (M0209E.v02_07 != 1)
-		return -EINVAL;
-
-	train->mask |= 1 << M0205E.type;
-	return 0;
-}
-
-static int
-gk104_ram_train_init_0(struct nvkm_ram *ram, struct gk104_ram_train *train)
-{
-	struct nvkm_subdev *subdev = &ram->fb->subdev;
-	struct nvkm_device *device = subdev->device;
-	int i, j;
-
-	if ((train->mask & 0x03d3) != 0x03d3) {
-		nvkm_warn(subdev, "missing link training data\n");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < 0x30; i++) {
-		for (j = 0; j < 8; j += 4) {
-			nvkm_wr32(device, 0x10f968 + j, 0x00000000 | (i << 8));
-			nvkm_wr32(device, 0x10f920 + j, 0x00000000 |
-						   train->type08.data[i] << 4 |
-						   train->type06.data[i]);
-			nvkm_wr32(device, 0x10f918 + j, train->type00.data[i]);
-			nvkm_wr32(device, 0x10f920 + j, 0x00000100 |
-						   train->type09.data[i] << 4 |
-						   train->type07.data[i]);
-			nvkm_wr32(device, 0x10f918 + j, train->type01.data[i]);
-		}
-	}
-
-	for (j = 0; j < 8; j += 4) {
-		for (i = 0; i < 0x100; i++) {
-			nvkm_wr32(device, 0x10f968 + j, i);
-			nvkm_wr32(device, 0x10f900 + j, train->type04.data[i]);
-		}
-	}
-
-	return 0;
-}
-
-static int
-gk104_ram_train_init(struct nvkm_ram *ram)
-{
-	u8 ramcfg = nvbios_ramcfg_index(&ram->fb->subdev);
-	struct gk104_ram_train *train;
-	int ret, i;
-
-	if (!(train = kzalloc(sizeof(*train), GFP_KERNEL)))
-		return -ENOMEM;
-
-	for (i = 0; i < 0x100; i++) {
-		ret = gk104_ram_train_type(ram, i, ramcfg, train);
-		if (ret && ret != -ENOENT)
-			break;
-	}
-
-	switch (ram->type) {
-	case NVKM_RAM_TYPE_GDDR5:
-		ret = gk104_ram_train_init_0(ram, train);
-		break;
-	default:
-		ret = 0;
-		break;
-	}
-
-	kfree(train);
-	return ret;
-}
-
 int
 gk104_ram_init(struct nvkm_ram *ram)
 {
@@ -1439,7 +1301,7 @@ gk104_ram_init(struct nvkm_ram *ram)
 	nvkm_wr32(device, 0x10ecc0, 0xffffffff);
 	nvkm_mask(device, 0x10f160, 0x00000010, 0x00000010);
 
-	return gk104_ram_train_init(ram);
+	return gf100_ram_train_init(ram);
 }
 
 static int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
index 8454899..6abd0e3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
@@ -267,6 +267,67 @@ gt215_link_train(struct gt215_ram *ram)
 	return ret;
 }
 
+int
+gt215_ram_train_type(struct nvkm_ram *ram, int i, u8 ramcfg,
+		     struct gt215_ram_train *train)
+{
+	struct nvkm_bios *bios = ram->fb->subdev.device->bios;
+	struct nvbios_M0205E M0205E;
+	struct nvbios_M0205S M0205S;
+	struct nvbios_M0209E M0209E;
+	struct nvbios_M0209S *remap = &train->remap;
+	struct nvbios_M0209S *value;
+	u8  ver, hdr, cnt, len;
+	u32 data;
+
+	/* determine type of data for this index */
+	if (!(data = nvbios_M0205Ep(bios, i, &ver, &hdr, &cnt, &len, &M0205E)))
+		return -ENOENT;
+
+	switch (M0205E.type) {
+	case 0x00: value = &train->type00; break;
+	case 0x01: value = &train->type01; break;
+	case 0x04: value = &train->type04; break;
+	case 0x06: value = &train->type06; break;
+	case 0x07: value = &train->type07; break;
+	case 0x08: value = &train->type08; break;
+	case 0x09: value = &train->type09; break;
+	default:
+		return 0;
+	}
+
+	/* training data index determined by ramcfg strap */
+	if (!(data = nvbios_M0205Sp(bios, i, ramcfg, &ver, &hdr, &M0205S)))
+		return -EINVAL;
+	i = M0205S.data;
+
+	/* training data format information */
+	if (!(data = nvbios_M0209Ep(bios, i, &ver, &hdr, &cnt, &len, &M0209E)))
+		return -EINVAL;
+
+	/* ... and the raw data */
+	if (!(data = nvbios_M0209Sp(bios, i, 0, &ver, &hdr, value)))
+		return -EINVAL;
+
+	if (M0209E.v02_07 == 2) {
+		/* of course! why wouldn't we have a pointer to another entry
+		 * in the same table, and use the first one as an array of
+		 * remap indices...
+		 */
+		if (!(data = nvbios_M0209Sp(bios, M0209E.v03, 0, &ver, &hdr,
+					    remap)))
+			return -EINVAL;
+
+		for (i = 0; i < ARRAY_SIZE(value->data); i++)
+			value->data[i] = remap->data[value->data[i]];
+	} else
+	if (M0209E.v02_07 != 1)
+		return -EINVAL;
+
+	train->mask |= 1 << M0205E.type;
+	return 0;
+}
+
 static int
 gt215_link_train_init(struct gt215_ram *ram)
 {
-- 
2.9.3



More information about the Nouveau mailing list