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

Signed-off-by: Roy Spliet <nouv...@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

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

Reply via email to