Adds reclocking for NVA0, and a whole lot of work for other cards. Had these patches collecting dust for a little, but tested them with both my NVA0, and Martin's a while back. Success not guaranteed, but should be quite a leap forward. Happy reviewing and testing. Cheers, Roy
Roy Spliet
2015-May-22 22:33 UTC
[Nouveau] [PATCH 1/9] nvkm/clk/gt215: u32->s32 for difference in req. and set clock
This difference can of course be negative too... Signed-off-by: Roy Spliet <rspliet at eclipso.eu> --- drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c index 822d32a..065e9f5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c @@ -180,7 +180,8 @@ gt215_clk_info(struct nvkm_clk *clock, int clk, u32 khz, struct gt215_clk_info *info) { struct gt215_clk_priv *priv = (void *)clock; - u32 oclk, sclk, sdiv, diff; + u32 oclk, sclk, sdiv; + s32 diff; info->clk = 0; -- 2.1.0
Roy Spliet
2015-May-22 22:33 UTC
[Nouveau] [PATCH 2/9] nvkm/bios/rammap: Pull DLLoff bit out of version 0x10 struct
In preparation of NV50 reclocking, where there is no version Signed-off-by: Roy Spliet <rspliet at eclipso.eu> --- drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c | 6 +++--- drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c | 2 +- 6 files changed, 8 insertions(+), 8 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 4204267..c6fb6aa 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h @@ -32,6 +32,7 @@ struct nvbios_ramcfg { unsigned ramcfg_ver; unsigned ramcfg_hdr; unsigned ramcfg_timing; + unsigned ramcfg_DLLoff; union { struct { unsigned ramcfg_10_02_01:1; @@ -40,7 +41,6 @@ struct nvbios_ramcfg { unsigned ramcfg_10_02_08:1; unsigned ramcfg_10_02_10:1; unsigned ramcfg_10_02_20:1; - unsigned ramcfg_10_DLLoff:1; unsigned ramcfg_10_03_0f:4; unsigned ramcfg_10_04_01:1; unsigned ramcfg_10_05:8; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c index 8b17bb4..a688d3b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c @@ -157,7 +157,7 @@ nvbios_rammapSp(struct nvkm_bios *bios, u32 data, p->ramcfg_10_02_08 = (nv_ro08(bios, data + 0x02) & 0x08) >> 3; p->ramcfg_10_02_10 = (nv_ro08(bios, data + 0x02) & 0x10) >> 4; p->ramcfg_10_02_20 = (nv_ro08(bios, data + 0x02) & 0x20) >> 5; - p->ramcfg_10_DLLoff = (nv_ro08(bios, data + 0x02) & 0x40) >> 6; + p->ramcfg_DLLoff = (nv_ro08(bios, data + 0x02) & 0x40) >> 6; p->ramcfg_10_03_0f = (nv_ro08(bios, data + 0x03) & 0x0f) >> 0; p->ramcfg_10_04_01 = (nv_ro08(bios, data + 0x04) & 0x01) >> 0; p->ramcfg_10_05 = (nv_ro08(bios, data + 0x05) & 0xff) >> 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c index 15b462a..e1d11f7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c @@ -77,7 +77,7 @@ nvkm_gddr3_calc(struct nvkm_ram *ram) CWL = ram->next->bios.timing_10_CWL; CL = ram->next->bios.timing_10_CL; WR = ram->next->bios.timing_10_WR; - DLL = !ram->next->bios.ramcfg_10_DLLoff; + DLL = !ram->next->bios.ramcfg_DLLoff; ODT = ram->next->bios.timing_10_ODT; break; case 0x20: diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c index 2417640..47d53ed 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c @@ -590,7 +590,7 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) r100da0 = 0x00000000; } - if (!next->bios.ramcfg_10_DLLoff) + if (!next->bios.ramcfg_DLLoff) r004018 |= 0x00004000; /* pll2pll requires to switch to a safe clock first */ @@ -630,7 +630,7 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) } /* If we're disabling the DLL, do it now */ - switch (next->bios.ramcfg_10_DLLoff * ram->base.type) { + switch (next->bios.ramcfg_DLLoff * ram->base.type) { case NV_MEM_TYPE_DDR3: nvkm_sddr3_dll_disable(fuc, ram->base.mr); break; @@ -810,7 +810,7 @@ gt215_ram_calc(struct nvkm_fb *pfb, u32 freq) gt215_ram_fbvref(fuc, 1); /* Reset DLL */ - if (!next->bios.ramcfg_10_DLLoff) + if (!next->bios.ramcfg_DLLoff) nvkm_sddr2_dll_reset(fuc); if (ram->base.type == NV_MEM_TYPE_GDDR3) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c index afab42d..86bf674 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c @@ -65,7 +65,7 @@ nvkm_sddr2_calc(struct nvkm_ram *ram) case 0x10: CL = ram->next->bios.timing_10_CL; WR = ram->next->bios.timing_10_WR; - DLL = !ram->next->bios.ramcfg_10_DLLoff; + DLL = !ram->next->bios.ramcfg_DLLoff; ODT = ram->next->bios.timing_10_ODT & 3; break; case 0x20: diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c index 1084435..77c53f9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c @@ -79,7 +79,7 @@ nvkm_sddr3_calc(struct nvkm_ram *ram) CWL = ram->next->bios.timing_10_CWL; CL = ram->next->bios.timing_10_CL; WR = ram->next->bios.timing_10_WR; - DLL = !ram->next->bios.ramcfg_10_DLLoff; + DLL = !ram->next->bios.ramcfg_DLLoff; ODT = ram->next->bios.timing_10_ODT; break; case 0x20: -- 2.1.0
Roy Spliet
2015-May-22 22:33 UTC
[Nouveau] [PATCH 3/9] nvkm/fb/ramnv50: Make 0x100da0 per-partition
Like on GT215 Signed-off-by: Roy Spliet <rspliet at eclipso.eu> --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c index d2c81dd..a96e512 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c @@ -42,7 +42,7 @@ struct nv50_ramseq { struct hwsq_reg r_0x1002d0; struct hwsq_reg r_0x1002d4; struct hwsq_reg r_0x1002dc; - struct hwsq_reg r_0x100da0[8]; + struct hwsq_reg r_0x100da0; struct hwsq_reg r_0x100e20; struct hwsq_reg r_0x100e24; struct hwsq_reg r_0x611200; @@ -70,6 +70,7 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) u8 size; } ramcfg, timing; u8 ver, hdr, cnt, len, strap; + u32 r100da0; int N1, M1, N2, M2, P; int ret, i; @@ -109,6 +110,13 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) timing.data = 0; } + /* XXX: where the fuck does 750MHz come from? */ + if (freq <= 750000) { + r100da0 = 0x00000010; + } else { + r100da0 = 0x00000000; + } + ret = ram_init(hwsq, nv_subdev(pfb)); if (ret) return ret; @@ -144,10 +152,9 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) ram_mask(hwsq, 0x00400c, 0x0000ffff, (N1 << 8) | M1); ram_mask(hwsq, 0x004008, 0x81ff0000, 0x80000000 | (mpll.bias_p << 19) | (P << 22) | (P << 16)); -#if QFX5800NVA0 - for (i = 0; i < 8; i++) - ram_mask(hwsq, 0x100da0[i], 0x00000000, 0x00000000); /*XXX*/ -#endif + + if (nv_device(pfb)->chipset == 0xa0) + ram_wr32(hwsq, 0x100da0, r100da0); /*XXX: here?*/ ram_nsec(hwsq, 96000); /*XXX*/ ram_mask(hwsq, 0x004008, 0x00002200, 0x00002000); @@ -430,8 +437,7 @@ nv50_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ram->hwsq.r_0x1002d0 = hwsq_reg(0x1002d0); ram->hwsq.r_0x1002d4 = hwsq_reg(0x1002d4); ram->hwsq.r_0x1002dc = hwsq_reg(0x1002dc); - for (i = 0; i < 8; i++) - ram->hwsq.r_0x100da0[i] = hwsq_reg(0x100da0 + (i * 0x04)); + ram->hwsq.r_0x100da0 = hwsq_stride(0x100da0, 4, ram->base.part_mask); ram->hwsq.r_0x100e20 = hwsq_reg(0x100e20); ram->hwsq.r_0x100e24 = hwsq_reg(0x100e24); ram->hwsq.r_0x611200 = hwsq_reg(0x611200); -- 2.1.0
Roy Spliet
2015-May-22 22:33 UTC
[Nouveau] [PATCH 4/9] nvkm/fb/ramnv50: Ressurect timing code, use proper timing/rammap handlers
Might need some generalisation to < GT200. For those: use at your own risk! Signed-off-by: Roy Spliet <rspliet at eclipso.eu> --- .../drm/nouveau/include/nvkm/subdev/bios/ramcfg.h | 16 ++ .../drm/nouveau/include/nvkm/subdev/bios/rammap.h | 2 + drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c | 29 ++++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | 167 +++++++++++++++++---- 4 files changed, 181 insertions(+), 33 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 c6fb6aa..f09b6bf 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h @@ -35,6 +35,22 @@ struct nvbios_ramcfg { unsigned ramcfg_DLLoff; union { struct { + unsigned ramcfg_00_03_01:1; + unsigned ramcfg_00_03_02:1; + unsigned ramcfg_00_03_08:1; + unsigned ramcfg_00_03_10:1; + unsigned ramcfg_00_04_02:1; + unsigned ramcfg_00_04_04:1; + unsigned ramcfg_00_04_20:1; + unsigned ramcfg_00_05:8; + unsigned ramcfg_00_06:8; + unsigned ramcfg_00_07:8; + unsigned ramcfg_00_08:8; + unsigned ramcfg_00_09:8; + unsigned ramcfg_00_0a_0f:4; + unsigned ramcfg_00_0a_f0:4; + }; + struct { unsigned ramcfg_10_02_01:1; unsigned ramcfg_10_02_02:1; unsigned ramcfg_10_02_04:1; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h index 609a905..2044fc9 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h @@ -15,6 +15,8 @@ u32 nvbios_rammapEm(struct nvkm_bios *, u16 mhz, u32 nvbios_rammapSe(struct nvkm_bios *, u32 data, u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, u8 *ver, u8 *hdr); +u32 nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int idx, + struct nvbios_ramcfg *p); u32 nvbios_rammapSp(struct nvkm_bios *, u32 data, u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, u8 *ver, u8 *hdr, struct nvbios_ramcfg *); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c index a688d3b..4ec376a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c @@ -141,6 +141,35 @@ nvbios_rammapSe(struct nvkm_bios *bios, u32 data, } u32 +nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int idx, + struct nvbios_ramcfg *p) +{ + data += (idx * size); + + if (size < 11) + return NULL; + + p->ramcfg_timing = nv_ro08(bios, data + 0x01); + p->ramcfg_00_03_01 = (nv_ro08(bios, data + 0x03) & 0x01) >> 0; + p->ramcfg_00_03_02 = (nv_ro08(bios, data + 0x03) & 0x02) >> 1; + p->ramcfg_DLLoff = (nv_ro08(bios, data + 0x03) & 0x04) >> 2; + p->ramcfg_00_03_08 = (nv_ro08(bios, data + 0x03) & 0x08) >> 3; + p->ramcfg_00_03_10 = (nv_ro08(bios, data + 0x03) & 0x10) >> 4; + p->ramcfg_00_04_02 = (nv_ro08(bios, data + 0x04) & 0x02) >> 1; + p->ramcfg_00_04_04 = (nv_ro08(bios, data + 0x04) & 0x04) >> 2; + p->ramcfg_00_04_20 = (nv_ro08(bios, data + 0x04) & 0x20) >> 5; + p->ramcfg_00_05 = (nv_ro08(bios, data + 0x05) & 0xff) >> 0; + p->ramcfg_00_06 = (nv_ro08(bios, data + 0x06) & 0xff) >> 0; + p->ramcfg_00_07 = (nv_ro08(bios, data + 0x07) & 0xff) >> 0; + p->ramcfg_00_08 = (nv_ro08(bios, data + 0x08) & 0xff) >> 0; + p->ramcfg_00_09 = (nv_ro08(bios, data + 0x09) & 0xff) >> 0; + p->ramcfg_00_0a_0f = (nv_ro08(bios, data + 0x0a) & 0x0f) >> 0; + p->ramcfg_00_0a_f0 = (nv_ro08(bios, data + 0x0a) & 0xf0) >> 4; + + return data; +} + +u32 nvbios_rammapSp(struct nvkm_bios *bios, u32 data, u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, u8 *ver, u8 *hdr, struct nvbios_ramcfg *p) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c index a96e512..51f93a0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c @@ -29,6 +29,7 @@ #include <subdev/bios.h> #include <subdev/bios/perf.h> #include <subdev/bios/pll.h> +#include <subdev/bios/rammap.h> #include <subdev/bios/timing.h> #include <subdev/clk/pll.h> @@ -55,6 +56,84 @@ struct nv50_ram { struct nv50_ramseq hwsq; }; +#define T(t) cfg->timing_10_##t +static int +nv50_ram_timing_calc(struct nvkm_fb *pfb, u32 *timing) +{ + struct nv50_ram *ram = (void *)pfb->ram; + struct nvbios_ramcfg *cfg = &ram->base.target.bios; + u32 cur2, cur3, cur4, cur7, cur8; + u8 unkt3b; + + cur2 = nv_rd32(pfb, 0x100228); + cur3 = nv_rd32(pfb, 0x10022c); + cur4 = nv_rd32(pfb, 0x100230); + cur7 = nv_rd32(pfb, 0x10023c); + cur8 = nv_rd32(pfb, 0x100240); + + switch ((!T(CWL)) * ram->base.type) { + case NV_MEM_TYPE_DDR2: + T(CWL) = T(CL) - 1; + break; + case NV_MEM_TYPE_GDDR3: + T(CWL) = ((cur2 & 0xff000000) >> 24) + 1; + break; + } + + /* XXX: N=1 is not proper statistics */ + if (nv_device(pfb)->chipset == 0xa0) { + unkt3b = 0x19 + ram->base.next->bios.rammap_00_16_40; + timing[6] = (0x2d + T(CL) - T(CWL) + ram->base.next->bios.rammap_00_16_40) << 16 | + T(CWL) << 8 | + (0x2f + T(CL) - T(CWL)); + } else { + unkt3b = 0x16; + timing[6] = (0x2b + T(CL) - T(CWL)) << 16 | + max_t(s8, T(CWL) - 2, 1) << 8 | + (0x2e + T(CL) - T(CWL)); + } + + timing[0] = (T(RP) << 24 | T(RAS) << 16 | T(RFC) << 8 | T(RC)); + timing[1] = (T(WR) + 1 + T(CWL)) << 24 | + max_t(u8, T(18), 1) << 16 | + (T(WTR) + 1 + T(CWL)) << 8 | + (3 + T(CL) - T(CWL)); + timing[2] = (T(CWL) - 1) << 24 | + (T(RRD) << 16) | + (T(RCDWR) << 8) | + T(RCDRD); + timing[3] = (unkt3b - 2 + T(CL)) << 24 | + unkt3b << 16 | + (T(CL) - 1) << 8 | + (T(CL) - 1); + timing[4] = (cur4 & 0xffff0000) | + T(13) << 8 | + T(13); + timing[5] = T(RFC) << 24 | + max_t(u8, T(RCDRD), T(RCDWR)) << 16 | + T(RP); + /* Timing 6 is already done above */ + timing[7] = (cur7 & 0xff00ffff) | (T(CL) - 1) << 16; + timing[8] = (cur8 & 0xffffff00); + + /* XXX: P.version == 1 only has DDR2 and GDDR3? */ + if (pfb->ram->type == NV_MEM_TYPE_DDR2) { + timing[5] |= (T(CL) + 3) << 8; + timing[8] |= (T(CL) - 4); + } else { + timing[5] |= (T(CL) + 2) << 8; + timing[8] |= (T(CL) - 2); + } + + nv_debug(pfb, " 220: %08x %08x %08x %08x\n", + timing[0], timing[1], timing[2], timing[3]); + nv_debug(pfb, " 230: %08x %08x %08x %08x\n", + timing[4], timing[5], timing[6], timing[7]); + nv_debug(pfb, " 240: %08x\n", timing[8]); + return 0; +} +#undef T + #define QFX5800NVA0 1 static int @@ -65,22 +144,25 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) struct nv50_ramseq *hwsq = &ram->hwsq; struct nvbios_perfE perfE; struct nvbios_pll mpll; - struct { - u32 data; - u8 size; - } ramcfg, timing; - u8 ver, hdr, cnt, len, strap; + struct nvkm_ram_data *next; + u8 ver, hdr, cnt, len, strap, size; + u32 data; u32 r100da0; int N1, M1, N2, M2, P; int ret, i; + u32 timing[9]; + + next = &ram->base.target; + next->freq = freq; + ram->base.next = next; /* lookup closest matching performance table entry for frequency */ i = 0; do { - ramcfg.data = nvbios_perfEp(bios, i++, &ver, &hdr, &cnt, - &ramcfg.size, &perfE); - if (!ramcfg.data || (ver < 0x25 || ver >= 0x40) || - (ramcfg.size < 2)) { + data = nvbios_perfEp(bios, i++, &ver, &hdr, &cnt, + &size, &perfE); + if (!data || (ver < 0x25 || ver >= 0x40) || + (size < 2)) { nv_error(pfb, "invalid/missing perftab entry\n"); return -EINVAL; } @@ -93,23 +175,48 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) return -EINVAL; } - ramcfg.data += hdr + (strap * ramcfg.size); + data = nvbios_rammapSp_from_perf(bios, data + hdr, size, strap, + &next->bios); + if (!data) { + nv_error(pfb, "invalid/missing rammap entry "); + return -EINVAL; + } /* lookup memory timings, if bios says they're present */ - strap = nv_ro08(bios, ramcfg.data + 0x01); - if (strap != 0xff) { - timing.data = nvbios_timingEe(bios, strap, &ver, &hdr, - &cnt, &len); - if (!timing.data || ver != 0x10 || hdr < 0x12) { + if (next->bios.ramcfg_timing != 0xff) { + data = nvbios_timingEp(bios, next->bios.ramcfg_timing, + &ver, &hdr, &cnt, &len, &next->bios); + if (!data || ver != 0x10 || hdr < 0x12) { nv_error(pfb, "invalid/missing timing entry " "%02x %04x %02x %02x\n", - strap, timing.data, ver, hdr); + strap, data, ver, hdr); return -EINVAL; } - } else { - timing.data = 0; } + nv50_ram_timing_calc(pfb, timing); + + ret = ram_init(hwsq, nv_subdev(pfb)); + if (ret) + return ret; + + /* Determine ram-specific MR values */ + ram->base.mr[0] = ram_rd32(hwsq, mr[0]); + ram->base.mr[1] = ram_rd32(hwsq, mr[1]); + ram->base.mr[2] = ram_rd32(hwsq, mr[2]); + + switch (ram->base.type) { + case NV_MEM_TYPE_GDDR3: + ret = nvkm_gddr3_calc(&ram->base); + break; + default: + ret = -ENOSYS; + break; + } + + if (ret) + return ret; + /* XXX: where the fuck does 750MHz come from? */ if (freq <= 750000) { r100da0 = 0x00000010; @@ -117,10 +224,6 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) r100da0 = 0x00000000; } - ret = ram_init(hwsq, nv_subdev(pfb)); - if (ret) - return ret; - ram_wait(hwsq, 0x01, 0x00); /* wait for !vblank */ ram_wait(hwsq, 0x01, 0x01); /* wait for vblank */ ram_wr32(hwsq, 0x611200, 0x00003300); @@ -177,17 +280,15 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) break; } - ram_mask(hwsq, timing[3], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[1], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[6], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[7], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[8], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[0], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[2], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[4], 0x00000000, 0x00000000); /*XXX*/ - ram_mask(hwsq, timing[5], 0x00000000, 0x00000000); /*XXX*/ - - ram_mask(hwsq, timing[0], 0x00000000, 0x00000000); /*XXX*/ + ram_mask(hwsq, timing[3], 0xffffffff, timing[3]); + ram_mask(hwsq, timing[1], 0xffffffff, timing[1]); + ram_mask(hwsq, timing[6], 0xffffffff, timing[6]); + ram_mask(hwsq, timing[7], 0xffffffff, timing[7]); + ram_mask(hwsq, timing[8], 0xffffffff, timing[8]); + ram_mask(hwsq, timing[0], 0xffffffff, timing[0]); + ram_mask(hwsq, timing[2], 0xffffffff, timing[2]); + ram_mask(hwsq, timing[4], 0xffffffff, timing[4]); + ram_mask(hwsq, timing[5], 0xffffffff, timing[5]); #if QFX5800NVA0 ram_nuke(hwsq, 0x100e24); -- 2.1.0
Roy Spliet
2015-May-22 22:33 UTC
[Nouveau] [PATCH 5/9] nvkm/bios/rammap: Parse perf mode as if it's a rammap entry
Some of the bits in there are similar to the bits in the gt215 rammap. Signed-off-by: Roy Spliet <rspliet at eclipso.eu> --- drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h | 5 +++++ drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h | 2 ++ drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c | 15 +++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | 2 ++ 4 files changed, 24 insertions(+) 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 f09b6bf..26e233a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h @@ -7,6 +7,11 @@ struct nvbios_ramcfg { unsigned rammap_max; union { struct { + unsigned rammap_00_16_20:1; + unsigned rammap_00_16_40:1; + unsigned rammap_00_17_02:1; + }; + struct { unsigned rammap_10_04_02:1; unsigned rammap_10_04_08:1; }; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h index 2044fc9..8d8ee13 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h @@ -7,6 +7,8 @@ u32 nvbios_rammapTe(struct nvkm_bios *, u8 *ver, u8 *hdr, u32 nvbios_rammapEe(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u32 nvbios_rammapEp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, + struct nvbios_ramcfg *p); u32 nvbios_rammapEp(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ramcfg *); u32 nvbios_rammapEm(struct nvkm_bios *, u16 mhz, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c index 4ec376a..8da8b26 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c @@ -72,6 +72,21 @@ nvbios_rammapEe(struct nvkm_bios *bios, int idx, return 0x0000; } +/* Pretend a performance mode is also a rammap entry, helps coalesce entries + * later on */ +u32 +nvbios_rammapEp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, + struct nvbios_ramcfg *p) +{ + memset(p, 0x00, sizeof(*p)); + + p->rammap_00_16_20 = (nv_ro08(bios, data + 0x16) & 0x20) >> 5; + p->rammap_00_16_40 = (nv_ro08(bios, data + 0x16) & 0x40) >> 6; + p->rammap_00_17_02 = (nv_ro08(bios, data + 0x17) & 0x02) >> 1; + + return data; +} + u32 nvbios_rammapEp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ramcfg *p) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c index 51f93a0..e720842 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c @@ -168,6 +168,8 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) } } while (perfE.memory < freq); + nvbios_rammapEp_from_perf(bios, data, hdr, &next->bios); + /* locate specific data set for the attached memory */ strap = nvbios_ramcfg_index(nv_subdev(pfb)); if (strap >= cnt) { -- 2.1.0
Roy Spliet
2015-May-22 22:33 UTC
[Nouveau] [PATCH 6/9] nvkm/bios/ramcfg: Separate out RON pull value
Signed-off-by: Roy Spliet <rspliet at eclipso.eu> --- drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h | 1 + drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c | 2 ++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c | 6 ++++-- 4 files changed, 9 insertions(+), 3 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 26e233a..3a9abd3 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h @@ -38,6 +38,7 @@ struct nvbios_ramcfg { unsigned ramcfg_hdr; unsigned ramcfg_timing; unsigned ramcfg_DLLoff; + unsigned ramcfg_RON; union { struct { unsigned ramcfg_00_03_01:1; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c index 8da8b26..5815f42 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c @@ -164,12 +164,13 @@ nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int idx, if (size < 11) return NULL; + p->ramcfg_ver = 0; p->ramcfg_timing = nv_ro08(bios, data + 0x01); p->ramcfg_00_03_01 = (nv_ro08(bios, data + 0x03) & 0x01) >> 0; p->ramcfg_00_03_02 = (nv_ro08(bios, data + 0x03) & 0x02) >> 1; p->ramcfg_DLLoff = (nv_ro08(bios, data + 0x03) & 0x04) >> 2; p->ramcfg_00_03_08 = (nv_ro08(bios, data + 0x03) & 0x08) >> 3; - p->ramcfg_00_03_10 = (nv_ro08(bios, data + 0x03) & 0x10) >> 4; + p->ramcfg_RON = (nv_ro08(bios, data + 0x03) & 0x10) >> 3; p->ramcfg_00_04_02 = (nv_ro08(bios, data + 0x04) & 0x02) >> 1; p->ramcfg_00_04_04 = (nv_ro08(bios, data + 0x04) & 0x04) >> 2; p->ramcfg_00_04_20 = (nv_ro08(bios, data + 0x04) & 0x20) >> 5; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c index 763fd29..bacd433 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c @@ -102,6 +102,8 @@ nvbios_timingEp(struct nvkm_bios *bios, int idx, p->timing_10_RRD = nv_ro08(bios, data + 0x0c); p->timing_10_13 = nv_ro08(bios, data + 0x0d); p->timing_10_ODT = nv_ro08(bios, data + 0x0e) & 0x07; + if (p->ramcfg_ver >= 0x10) + p->ramcfg_RON = nv_ro08(bios, data + 0x0e) & 0x07; p->timing_10_24 = 0xff; p->timing_10_21 = 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c index e1d11f7..8d759f8a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c @@ -70,7 +70,7 @@ ramgddr3_wr_lo[] = { int nvkm_gddr3_calc(struct nvkm_ram *ram) { - int CL, WR, CWL, DLL = 0, ODT = 0, hi; + int CL, WR, CWL, DLL = 0, ODT = 0, RON, hi; switch (ram->next->bios.timing_ver) { case 0x10: @@ -79,6 +79,7 @@ nvkm_gddr3_calc(struct nvkm_ram *ram) WR = ram->next->bios.timing_10_WR; DLL = !ram->next->bios.ramcfg_DLLoff; ODT = ram->next->bios.timing_10_ODT; + RON = ram->next->bios.ramcfg_RON; break; case 0x20: CWL = (ram->next->bios.timing[1] & 0x00000f80) >> 7; @@ -89,6 +90,7 @@ nvkm_gddr3_calc(struct nvkm_ram *ram) ODT = (ram->mr[1] & 0x004) >> 2 | (ram->mr[1] & 0x040) >> 5 | (ram->mr[1] & 0x200) >> 7; + RON = !(ram->mr[1] & 0x300) >> 8; break; default: return -ENOSYS; @@ -107,7 +109,7 @@ nvkm_gddr3_calc(struct nvkm_ram *ram) ram->mr[1] &= ~0x3fc; ram->mr[1] |= (ODT & 0x03) << 2; - ram->mr[1] |= (ODT & 0x03) << 8; + ram->mr[1] |= (RON & 0x03) << 8; ram->mr[1] |= (WR & 0x03) << 4; ram->mr[1] |= (WR & 0x04) << 5; ram->mr[1] |= !DLL << 6; -- 2.1.0
Roy Spliet
2015-May-22 22:33 UTC
[Nouveau] [PATCH 7/9] nvkm/fb/ramnv50: GDDR3 script for NVA0
This looks surprisingly similar to scripts on earlier cards as well but they don't seem to work just yet. That... and I don't have any, which makes it a tough job to reverse engineer. Signed-off-by: Roy Spliet <rspliet at eclipso.eu> --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | 129 ++++++++++++++++++----- 1 file changed, 104 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c index e720842..03ee6b6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c @@ -39,10 +39,19 @@ struct nv50_ramseq { struct hwsq_reg r_0x004008; struct hwsq_reg r_0x00400c; struct hwsq_reg r_0x00c040; + struct hwsq_reg r_0x100200; struct hwsq_reg r_0x100210; + struct hwsq_reg r_0x10021c; struct hwsq_reg r_0x1002d0; struct hwsq_reg r_0x1002d4; struct hwsq_reg r_0x1002dc; + struct hwsq_reg r_0x10053c; + struct hwsq_reg r_0x1005a0; + struct hwsq_reg r_0x1005a4; + struct hwsq_reg r_0x100710; + struct hwsq_reg r_0x100714; + struct hwsq_reg r_0x100718; + struct hwsq_reg r_0x10071c; struct hwsq_reg r_0x100da0; struct hwsq_reg r_0x100e20; struct hwsq_reg r_0x100e24; @@ -134,7 +143,13 @@ nv50_ram_timing_calc(struct nvkm_fb *pfb, u32 *timing) } #undef T -#define QFX5800NVA0 1 +static void +nvkm_sddr2_dll_reset(struct nv50_ramseq *hwsq) +{ + ram_mask(hwsq, mr[0], 0x100, 0x100); + ram_mask(hwsq, mr[0], 0x100, 0x000); + ram_nsec(hwsq, 24000); +} static int nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) @@ -147,7 +162,7 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) struct nvkm_ram_data *next; u8 ver, hdr, cnt, len, strap, size; u32 data; - u32 r100da0; + u32 r100da0, r004008, unk710, unk714, unk718, unk71c; int N1, M1, N2, M2, P; int ret, i; u32 timing[9]; @@ -219,12 +234,8 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) if (ret) return ret; - /* XXX: where the fuck does 750MHz come from? */ - if (freq <= 750000) { - r100da0 = 0x00000010; - } else { - r100da0 = 0x00000000; - } + /* Always disable this bit during reclock */ + ram_mask(hwsq, 0x100200, 0x00000800, 0x00000000); ram_wait(hwsq, 0x01, 0x00); /* wait for !vblank */ ram_wait(hwsq, 0x01, 0x01); /* wait for vblank */ @@ -233,6 +244,7 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) ram_nsec(hwsq, 8000); ram_setf(hwsq, 0x10, 0x00); /* disable fb */ ram_wait(hwsq, 0x00, 0x01); /* wait for fb disabled */ + ram_nsec(hwsq, 2000); ram_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge */ ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */ @@ -252,18 +264,33 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) if (ret < 0) return ret; + /* XXX: where the fuck does 750MHz come from? */ + if (freq <= 750000) { + r100da0 = 0x00000010; + r004008 = 0x90000000; + } else { + r100da0 = 0x00000000; + r004008 = 0x80000000; + } + + r004008 |= (mpll.bias_p << 19) | (P << 22) | (P << 16); + ram_mask(hwsq, 0x00c040, 0xc000c000, 0x0000c000); - ram_mask(hwsq, 0x004008, 0x00000200, 0x00000200); + /* XXX: Is rammap_00_16_40 the DLL bit we've seen in GT215? Why does + * it have a different rammap bit from DLLoff? */ + ram_mask(hwsq, 0x004008, 0x00004200, 0x00000200 | + next->bios.rammap_00_16_40 << 14); ram_mask(hwsq, 0x00400c, 0x0000ffff, (N1 << 8) | M1); - ram_mask(hwsq, 0x004008, 0x81ff0000, 0x80000000 | (mpll.bias_p << 19) | - (P << 22) | (P << 16)); + ram_mask(hwsq, 0x004008, 0x91ff0000, r004008); + if (nv_device(pfb)->chipset >= 0x96) + ram_wr32(hwsq, 0x100da0, r100da0); + ram_nsec(hwsq, 64000); /*XXX*/ + ram_nsec(hwsq, 32000); /*XXX*/ - if (nv_device(pfb)->chipset == 0xa0) - ram_wr32(hwsq, 0x100da0, r100da0); /*XXX: here?*/ - ram_nsec(hwsq, 96000); /*XXX*/ ram_mask(hwsq, 0x004008, 0x00002200, 0x00002000); ram_wr32(hwsq, 0x1002dc, 0x00000000); /* disable self-refresh */ + ram_wr32(hwsq, 0x1002d4, 0x00000001); /* disable self-refresh */ ram_wr32(hwsq, 0x100210, 0x80000000); /* enable auto-refresh */ ram_nsec(hwsq, 12000); @@ -274,9 +301,10 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) ram_mask(hwsq, mr[0], 0x000, 0x000); break; case NV_MEM_TYPE_GDDR3: - ram_mask(hwsq, mr[2], 0x000, 0x000); + ram_nuke(hwsq, mr[1]); /* force update */ + ram_wr32(hwsq, mr[1], ram->base.mr[1]); ram_nuke(hwsq, mr[0]); /* force update */ - ram_mask(hwsq, mr[0], 0x000, 0x000); + ram_wr32(hwsq, mr[0], ram->base.mr[0]); break; default: break; @@ -292,20 +320,62 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) ram_mask(hwsq, timing[4], 0xffffffff, timing[4]); ram_mask(hwsq, timing[5], 0xffffffff, timing[5]); -#if QFX5800NVA0 - ram_nuke(hwsq, 0x100e24); - ram_mask(hwsq, 0x100e24, 0x00000000, 0x00000000); - ram_nuke(hwsq, 0x100e20); - ram_mask(hwsq, 0x100e20, 0x00000000, 0x00000000); -#endif + if (!next->bios.ramcfg_00_03_02) + ram_mask(hwsq, 0x10021c, 0x00010000, 0x00000000); + ram_mask(hwsq, 0x100200, 0x00001000, !next->bios.ramcfg_00_04_02 << 12); + + /* XXX: A lot of this could be "chipset"/"ram type" specific stuff */ + unk710 = ram_rd32(hwsq, 0x100710) & ~0x00000101; + unk714 = ram_rd32(hwsq, 0x100714) & ~0xf0000020; + unk718 = ram_rd32(hwsq, 0x100718) & ~0x00000100; + unk71c = ram_rd32(hwsq, 0x10071c) & ~0x00000100; + + if ( next->bios.ramcfg_00_03_01) + unk71c |= 0x00000100; + if ( next->bios.ramcfg_00_03_02) + unk710 |= 0x00000100; + if (!next->bios.ramcfg_00_03_08) { + unk710 |= 0x1; + unk714 |= 0x20; + } + if ( next->bios.ramcfg_00_04_04) + unk714 |= 0x70000000; + if ( next->bios.ramcfg_00_04_20) + unk718 |= 0x00000100; + + ram_mask(hwsq, 0x100714, 0xffffffff, unk714); + ram_mask(hwsq, 0x10071c, 0xffffffff, unk71c); + ram_mask(hwsq, 0x100718, 0xffffffff, unk718); + ram_mask(hwsq, 0x100710, 0xffffffff, unk710); + + if (next->bios.rammap_00_16_20) { + ram_wr32(hwsq, 0x1005a0, next->bios.ramcfg_00_07 << 16 | + next->bios.ramcfg_00_06 << 8 | + next->bios.ramcfg_00_05); + ram_wr32(hwsq, 0x1005a4, next->bios.ramcfg_00_09 << 8 | + next->bios.ramcfg_00_08); + ram_mask(hwsq, 0x10053c, 0x00001000, 0x00000000); + } else { + ram_mask(hwsq, 0x10053c, 0x00001000, 0x00001000); + } + ram_mask(hwsq, mr[1], 0xffffffff, ram->base.mr[1]); - ram_mask(hwsq, mr[0], 0x100, 0x100); - ram_mask(hwsq, mr[0], 0x100, 0x000); + /* Reset DLL */ + if (!next->bios.ramcfg_DLLoff) + nvkm_sddr2_dll_reset(hwsq); ram_setf(hwsq, 0x10, 0x01); /* enable fb */ ram_wait(hwsq, 0x00, 0x00); /* wait for fb enabled */ ram_wr32(hwsq, 0x611200, 0x00003330); ram_wr32(hwsq, 0x002504, 0x00000000); /* un-block fifo */ + + if (next->bios.rammap_00_17_02) + ram_mask(hwsq, 0x100200, 0x00000800, 0x00000800); + if (!next->bios.rammap_00_16_40) + ram_mask(hwsq, 0x004008, 0x00004000, 0x00000000); + if (next->bios.ramcfg_00_03_02) + ram_mask(hwsq, 0x10021c, 0x00010000, 0x00010000); + return 0; } @@ -521,12 +591,12 @@ nv50_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, return ret; switch (ram->base.type) { - case NV_MEM_TYPE_DDR2: case NV_MEM_TYPE_GDDR3: ram->base.calc = nv50_ram_calc; ram->base.prog = nv50_ram_prog; ram->base.tidy = nv50_ram_tidy; break; + case NV_MEM_TYPE_DDR2: default: nv_warn(ram, "reclocking of this ram type unsupported\n"); return 0; @@ -536,10 +606,19 @@ nv50_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, ram->hwsq.r_0x00c040 = hwsq_reg(0x00c040); ram->hwsq.r_0x004008 = hwsq_reg(0x004008); ram->hwsq.r_0x00400c = hwsq_reg(0x00400c); + ram->hwsq.r_0x100200 = hwsq_reg(0x100200); ram->hwsq.r_0x100210 = hwsq_reg(0x100210); + ram->hwsq.r_0x10021c = hwsq_reg(0x10021c); ram->hwsq.r_0x1002d0 = hwsq_reg(0x1002d0); ram->hwsq.r_0x1002d4 = hwsq_reg(0x1002d4); ram->hwsq.r_0x1002dc = hwsq_reg(0x1002dc); + ram->hwsq.r_0x10053c = hwsq_reg(0x10053c); + ram->hwsq.r_0x1005a0 = hwsq_reg(0x1005a0); + ram->hwsq.r_0x1005a4 = hwsq_reg(0x1005a4); + ram->hwsq.r_0x100710 = hwsq_reg(0x100710); + ram->hwsq.r_0x100714 = hwsq_reg(0x100714); + ram->hwsq.r_0x100718 = hwsq_reg(0x100718); + ram->hwsq.r_0x10071c = hwsq_reg(0x10071c); ram->hwsq.r_0x100da0 = hwsq_stride(0x100da0, 4, ram->base.part_mask); ram->hwsq.r_0x100e20 = hwsq_reg(0x100e20); ram->hwsq.r_0x100e24 = hwsq_reg(0x100e24); -- 2.1.0
Roy Spliet
2015-May-22 22:33 UTC
[Nouveau] [PATCH 8/9] nvkm/fb/gddr3: Add a few CL and WR entries observed on GTX260
Signed-off-by: Roy Spliet <rspliet at eclipso.eu> --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c index 8d759f8a..4465446 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c @@ -42,9 +42,9 @@ ramxlat(const struct ramxlat *xlat, int id) static const struct ramxlat ramgddr3_cl_lo[] = { - { 7, 7 }, { 8, 0 }, { 9, 1 }, { 10, 2 }, { 11, 3 }, + { 5, 5 }, { 7, 7 }, { 8, 0 }, { 9, 1 }, { 10, 2 }, { 11, 3 }, { 12, 8 }, /* the below are mentioned in some, but not all, gddr3 docs */ - { 12, 4 }, { 13, 5 }, { 14, 6 }, + { 13, 9 }, { 14, 6 }, /* XXX: Per Samsung docs, are these used? They overlap with Qimonda */ /* { 4, 4 }, { 5, 5 }, { 6, 6 }, { 12, 8 }, { 13, 9 }, { 14, 10 }, * { 15, 11 }, */ @@ -61,9 +61,9 @@ ramgddr3_cl_hi[] = { static const struct ramxlat ramgddr3_wr_lo[] = { { 5, 2 }, { 7, 4 }, { 8, 5 }, { 9, 6 }, { 10, 7 }, - { 11, 0 }, + { 11, 0 }, { 13 , 1 }, /* the below are mentioned in some, but not all, gddr3 docs */ - { 4, 1 }, { 6, 3 }, { 12, 1 }, { 13 , 2 }, + { 4, 1 }, { 6, 3 }, { 12, 1 }, { -1 } }; -- 2.1.0
Roy Spliet
2015-May-22 22:33 UTC
[Nouveau] [PATCH 9/9] nvkm/clk/nv50: Enable user reclocking for NVA0
Tested on a few cards. Probably works quite well for most, given they should all be GDDR3. Signed-off-by: Roy Spliet <rspliet at eclipso.eu> --- drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c index 9b4ffd6..89c5d88 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/nv50.c @@ -509,7 +509,8 @@ nv50_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine, int ret; ret = nvkm_clk_create(parent, engine, oclass, pclass->domains, - NULL, 0, false, &priv); + NULL, 0, nv_device(parent)->chipset == 0xa0, + &priv); *pobject = nv_object(priv); if (ret) return ret; -- 2.1.0
Ilia Mirkin
2015-May-22 22:44 UTC
[Nouveau] [PATCH 3/9] nvkm/fb/ramnv50: Make 0x100da0 per-partition
On Fri, May 22, 2015 at 6:33 PM, Roy Spliet <rspliet at eclipso.eu> wrote:> Like on GT215 > > Signed-off-by: Roy Spliet <rspliet at eclipso.eu> > --- > drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | 20 +++++++++++++------- > 1 file changed, 13 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c > index d2c81dd..a96e512 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c > @@ -42,7 +42,7 @@ struct nv50_ramseq { > struct hwsq_reg r_0x1002d0; > struct hwsq_reg r_0x1002d4; > struct hwsq_reg r_0x1002dc; > - struct hwsq_reg r_0x100da0[8]; > + struct hwsq_reg r_0x100da0; > struct hwsq_reg r_0x100e20; > struct hwsq_reg r_0x100e24; > struct hwsq_reg r_0x611200; > @@ -70,6 +70,7 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) > u8 size; > } ramcfg, timing; > u8 ver, hdr, cnt, len, strap; > + u32 r100da0; > int N1, M1, N2, M2, P; > int ret, i; > > @@ -109,6 +110,13 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) > timing.data = 0; > } > > + /* XXX: where the fuck does 750MHz come from? */s/the fuck//> + if (freq <= 750000) { > + r100da0 = 0x00000010; > + } else { > + r100da0 = 0x00000000; > + } > + > ret = ram_init(hwsq, nv_subdev(pfb)); > if (ret) > return ret; > @@ -144,10 +152,9 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) > ram_mask(hwsq, 0x00400c, 0x0000ffff, (N1 << 8) | M1); > ram_mask(hwsq, 0x004008, 0x81ff0000, 0x80000000 | (mpll.bias_p << 19) | > (P << 22) | (P << 16)); > -#if QFX5800NVA0 > - for (i = 0; i < 8; i++) > - ram_mask(hwsq, 0x100da0[i], 0x00000000, 0x00000000); /*XXX*/ > -#endif > + > + if (nv_device(pfb)->chipset == 0xa0)Don't think this is quite right... probably more like vram == GDDR3. I definitely remember seeing non-nva0 cards writing 100da0 in the scripts.> + ram_wr32(hwsq, 0x100da0, r100da0); /*XXX: here?*/ > ram_nsec(hwsq, 96000); /*XXX*/ > ram_mask(hwsq, 0x004008, 0x00002200, 0x00002000); > > @@ -430,8 +437,7 @@ nv50_ram_ctor(struct nvkm_object *parent, struct nvkm_object *engine, > ram->hwsq.r_0x1002d0 = hwsq_reg(0x1002d0); > ram->hwsq.r_0x1002d4 = hwsq_reg(0x1002d4); > ram->hwsq.r_0x1002dc = hwsq_reg(0x1002dc); > - for (i = 0; i < 8; i++) > - ram->hwsq.r_0x100da0[i] = hwsq_reg(0x100da0 + (i * 0x04)); > + ram->hwsq.r_0x100da0 = hwsq_stride(0x100da0, 4, ram->base.part_mask); > ram->hwsq.r_0x100e20 = hwsq_reg(0x100e20); > ram->hwsq.r_0x100e24 = hwsq_reg(0x100e24); > ram->hwsq.r_0x611200 = hwsq_reg(0x611200); > -- > 2.1.0 > > > > _______________________________________________ > Nouveau mailing list > Nouveau at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/nouveau
Tobias Klausmann
2015-May-22 23:00 UTC
[Nouveau] [PATCH 4/9] nvkm/fb/ramnv50: Ressurect timing code, use proper timing/rammap handlers
On 23.05.2015 00:33, Roy Spliet wrote:> Might need some generalisation to < GT200. For those: use at your own risk! > > Signed-off-by: Roy Spliet <rspliet at eclipso.eu> > --- > .../drm/nouveau/include/nvkm/subdev/bios/ramcfg.h | 16 ++ > .../drm/nouveau/include/nvkm/subdev/bios/rammap.h | 2 + > drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c | 29 ++++ > drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | 167 +++++++++++++++++---- > 4 files changed, 181 insertions(+), 33 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 c6fb6aa..f09b6bf 100644 > --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h > +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h > @@ -35,6 +35,22 @@ struct nvbios_ramcfg { > unsigned ramcfg_DLLoff; > union { > struct { > + unsigned ramcfg_00_03_01:1; > + unsigned ramcfg_00_03_02:1; > + unsigned ramcfg_00_03_08:1; > + unsigned ramcfg_00_03_10:1; > + unsigned ramcfg_00_04_02:1; > + unsigned ramcfg_00_04_04:1; > + unsigned ramcfg_00_04_20:1; > + unsigned ramcfg_00_05:8; > + unsigned ramcfg_00_06:8; > + unsigned ramcfg_00_07:8; > + unsigned ramcfg_00_08:8; > + unsigned ramcfg_00_09:8; > + unsigned ramcfg_00_0a_0f:4; > + unsigned ramcfg_00_0a_f0:4; > + }; > + struct { > unsigned ramcfg_10_02_01:1; > unsigned ramcfg_10_02_02:1; > unsigned ramcfg_10_02_04:1; > diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h > index 609a905..2044fc9 100644 > --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h > +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/rammap.h > @@ -15,6 +15,8 @@ u32 nvbios_rammapEm(struct nvkm_bios *, u16 mhz, > u32 nvbios_rammapSe(struct nvkm_bios *, u32 data, > u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, > u8 *ver, u8 *hdr); > +u32 nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int idx, > + struct nvbios_ramcfg *p); > u32 nvbios_rammapSp(struct nvkm_bios *, u32 data, > u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, > u8 *ver, u8 *hdr, struct nvbios_ramcfg *); > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c > index a688d3b..4ec376a 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c > @@ -141,6 +141,35 @@ nvbios_rammapSe(struct nvkm_bios *bios, u32 data, > } > > u32 > +nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int idx, > + struct nvbios_ramcfg *p) > +{ > + data += (idx * size); > + > + if (size < 11) > + return NULL; > + > + p->ramcfg_timing = nv_ro08(bios, data + 0x01); > + p->ramcfg_00_03_01 = (nv_ro08(bios, data + 0x03) & 0x01) >> 0; > + p->ramcfg_00_03_02 = (nv_ro08(bios, data + 0x03) & 0x02) >> 1; > + p->ramcfg_DLLoff = (nv_ro08(bios, data + 0x03) & 0x04) >> 2; > + p->ramcfg_00_03_08 = (nv_ro08(bios, data + 0x03) & 0x08) >> 3; > + p->ramcfg_00_03_10 = (nv_ro08(bios, data + 0x03) & 0x10) >> 4; > + p->ramcfg_00_04_02 = (nv_ro08(bios, data + 0x04) & 0x02) >> 1; > + p->ramcfg_00_04_04 = (nv_ro08(bios, data + 0x04) & 0x04) >> 2; > + p->ramcfg_00_04_20 = (nv_ro08(bios, data + 0x04) & 0x20) >> 5; > + p->ramcfg_00_05 = (nv_ro08(bios, data + 0x05) & 0xff) >> 0; > + p->ramcfg_00_06 = (nv_ro08(bios, data + 0x06) & 0xff) >> 0; > + p->ramcfg_00_07 = (nv_ro08(bios, data + 0x07) & 0xff) >> 0; > + p->ramcfg_00_08 = (nv_ro08(bios, data + 0x08) & 0xff) >> 0; > + p->ramcfg_00_09 = (nv_ro08(bios, data + 0x09) & 0xff) >> 0; > + p->ramcfg_00_0a_0f = (nv_ro08(bios, data + 0x0a) & 0x0f) >> 0; > + p->ramcfg_00_0a_f0 = (nv_ro08(bios, data + 0x0a) & 0xf0) >> 4; > + > + return data; > +} > + > +u32 > nvbios_rammapSp(struct nvkm_bios *bios, u32 data, > u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, > u8 *ver, u8 *hdr, struct nvbios_ramcfg *p) > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c > index a96e512..51f93a0 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c > @@ -29,6 +29,7 @@ > #include <subdev/bios.h> > #include <subdev/bios/perf.h> > #include <subdev/bios/pll.h> > +#include <subdev/bios/rammap.h> > #include <subdev/bios/timing.h> > #include <subdev/clk/pll.h> > > @@ -55,6 +56,84 @@ struct nv50_ram { > struct nv50_ramseq hwsq; > }; > > +#define T(t) cfg->timing_10_##t > +static int > +nv50_ram_timing_calc(struct nvkm_fb *pfb, u32 *timing) > +{ > + struct nv50_ram *ram = (void *)pfb->ram; > + struct nvbios_ramcfg *cfg = &ram->base.target.bios; > + u32 cur2, cur3, cur4, cur7, cur8; > + u8 unkt3b; > + > + cur2 = nv_rd32(pfb, 0x100228); > + cur3 = nv_rd32(pfb, 0x10022c); > + cur4 = nv_rd32(pfb, 0x100230); > + cur7 = nv_rd32(pfb, 0x10023c); > + cur8 = nv_rd32(pfb, 0x100240); > + > + switch ((!T(CWL)) * ram->base.type) { > + case NV_MEM_TYPE_DDR2: > + T(CWL) = T(CL) - 1; > + break; > + case NV_MEM_TYPE_GDDR3: > + T(CWL) = ((cur2 & 0xff000000) >> 24) + 1; > + break; > + } > + > + /* XXX: N=1 is not proper statistics */ > + if (nv_device(pfb)->chipset == 0xa0) { > + unkt3b = 0x19 + ram->base.next->bios.rammap_00_16_40; > + timing[6] = (0x2d + T(CL) - T(CWL) + ram->base.next->bios.rammap_00_16_40) << 16 | > + T(CWL) << 8 | > + (0x2f + T(CL) - T(CWL)); > + } else { > + unkt3b = 0x16; > + timing[6] = (0x2b + T(CL) - T(CWL)) << 16 | > + max_t(s8, T(CWL) - 2, 1) << 8 | > + (0x2e + T(CL) - T(CWL)); > + } > + > + timing[0] = (T(RP) << 24 | T(RAS) << 16 | T(RFC) << 8 | T(RC)); > + timing[1] = (T(WR) + 1 + T(CWL)) << 24 | > + max_t(u8, T(18), 1) << 16 | > + (T(WTR) + 1 + T(CWL)) << 8 | > + (3 + T(CL) - T(CWL)); > + timing[2] = (T(CWL) - 1) << 24 | > + (T(RRD) << 16) | > + (T(RCDWR) << 8) | > + T(RCDRD); > + timing[3] = (unkt3b - 2 + T(CL)) << 24 | > + unkt3b << 16 | > + (T(CL) - 1) << 8 | > + (T(CL) - 1); > + timing[4] = (cur4 & 0xffff0000) | > + T(13) << 8 | > + T(13); > + timing[5] = T(RFC) << 24 | > + max_t(u8, T(RCDRD), T(RCDWR)) << 16 | > + T(RP); > + /* Timing 6 is already done above */ > + timing[7] = (cur7 & 0xff00ffff) | (T(CL) - 1) << 16; > + timing[8] = (cur8 & 0xffffff00); > + > + /* XXX: P.version == 1 only has DDR2 and GDDR3? */mh can you state both (DDR2/GDDR3) here and bail out on default as well?> + if (pfb->ram->type == NV_MEM_TYPE_DDR2) { > + timing[5] |= (T(CL) + 3) << 8; > + timing[8] |= (T(CL) - 4); > + } else { > + timing[5] |= (T(CL) + 2) << 8; > + timing[8] |= (T(CL) - 2); > + } > + > + nv_debug(pfb, " 220: %08x %08x %08x %08x\n", > + timing[0], timing[1], timing[2], timing[3]); > + nv_debug(pfb, " 230: %08x %08x %08x %08x\n", > + timing[4], timing[5], timing[6], timing[7]); > + nv_debug(pfb, " 240: %08x\n", timing[8]); > + return 0; > +} > +#undef T > + > #define QFX5800NVA0 1 > > static int > @@ -65,22 +144,25 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) > struct nv50_ramseq *hwsq = &ram->hwsq; > struct nvbios_perfE perfE; > struct nvbios_pll mpll; > - struct { > - u32 data; > - u8 size; > - } ramcfg, timing; > - u8 ver, hdr, cnt, len, strap; > + struct nvkm_ram_data *next; > + u8 ver, hdr, cnt, len, strap, size; > + u32 data; > u32 r100da0; > int N1, M1, N2, M2, P; > int ret, i; > + u32 timing[9]; > + > + next = &ram->base.target; > + next->freq = freq; > + ram->base.next = next; > > /* lookup closest matching performance table entry for frequency */ > i = 0; > do { > - ramcfg.data = nvbios_perfEp(bios, i++, &ver, &hdr, &cnt, > - &ramcfg.size, &perfE); > - if (!ramcfg.data || (ver < 0x25 || ver >= 0x40) || > - (ramcfg.size < 2)) { > + data = nvbios_perfEp(bios, i++, &ver, &hdr, &cnt, > + &size, &perfE); > + if (!data || (ver < 0x25 || ver >= 0x40) || > + (size < 2)) { > nv_error(pfb, "invalid/missing perftab entry\n"); > return -EINVAL; > } > @@ -93,23 +175,48 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) > return -EINVAL; > } > > - ramcfg.data += hdr + (strap * ramcfg.size); > + data = nvbios_rammapSp_from_perf(bios, data + hdr, size, strap, > + &next->bios); > + if (!data) { > + nv_error(pfb, "invalid/missing rammap entry "); > + return -EINVAL; > + } > > /* lookup memory timings, if bios says they're present */ > - strap = nv_ro08(bios, ramcfg.data + 0x01); > - if (strap != 0xff) { > - timing.data = nvbios_timingEe(bios, strap, &ver, &hdr, > - &cnt, &len); > - if (!timing.data || ver != 0x10 || hdr < 0x12) { > + if (next->bios.ramcfg_timing != 0xff) { > + data = nvbios_timingEp(bios, next->bios.ramcfg_timing, > + &ver, &hdr, &cnt, &len, &next->bios); > + if (!data || ver != 0x10 || hdr < 0x12) { > nv_error(pfb, "invalid/missing timing entry " > "%02x %04x %02x %02x\n", > - strap, timing.data, ver, hdr); > + strap, data, ver, hdr); > return -EINVAL; > } > - } else { > - timing.data = 0; > } > > + nv50_ram_timing_calc(pfb, timing); > + > + ret = ram_init(hwsq, nv_subdev(pfb)); > + if (ret) > + return ret; > + > + /* Determine ram-specific MR values */ > + ram->base.mr[0] = ram_rd32(hwsq, mr[0]); > + ram->base.mr[1] = ram_rd32(hwsq, mr[1]); > + ram->base.mr[2] = ram_rd32(hwsq, mr[2]); > + > + switch (ram->base.type) { > + case NV_MEM_TYPE_GDDR3: > + ret = nvkm_gddr3_calc(&ram->base); > + break; > + default: > + ret = -ENOSYS; > + break; > + } > + > + if (ret) > + return ret; > + > /* XXX: where the fuck does 750MHz come from? */get rid of that swearing...> if (freq <= 750000) { > r100da0 = 0x00000010; > @@ -117,10 +224,6 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) > r100da0 = 0x00000000; > } > > - ret = ram_init(hwsq, nv_subdev(pfb)); > - if (ret) > - return ret; > - > ram_wait(hwsq, 0x01, 0x00); /* wait for !vblank */ > ram_wait(hwsq, 0x01, 0x01); /* wait for vblank */ > ram_wr32(hwsq, 0x611200, 0x00003300); > @@ -177,17 +280,15 @@ nv50_ram_calc(struct nvkm_fb *pfb, u32 freq) > break; > } > > - ram_mask(hwsq, timing[3], 0x00000000, 0x00000000); /*XXX*/ > - ram_mask(hwsq, timing[1], 0x00000000, 0x00000000); /*XXX*/ > - ram_mask(hwsq, timing[6], 0x00000000, 0x00000000); /*XXX*/ > - ram_mask(hwsq, timing[7], 0x00000000, 0x00000000); /*XXX*/ > - ram_mask(hwsq, timing[8], 0x00000000, 0x00000000); /*XXX*/ > - ram_mask(hwsq, timing[0], 0x00000000, 0x00000000); /*XXX*/ > - ram_mask(hwsq, timing[2], 0x00000000, 0x00000000); /*XXX*/ > - ram_mask(hwsq, timing[4], 0x00000000, 0x00000000); /*XXX*/ > - ram_mask(hwsq, timing[5], 0x00000000, 0x00000000); /*XXX*/ > - > - ram_mask(hwsq, timing[0], 0x00000000, 0x00000000); /*XXX*/ > + ram_mask(hwsq, timing[3], 0xffffffff, timing[3]); > + ram_mask(hwsq, timing[1], 0xffffffff, timing[1]); > + ram_mask(hwsq, timing[6], 0xffffffff, timing[6]); > + ram_mask(hwsq, timing[7], 0xffffffff, timing[7]); > + ram_mask(hwsq, timing[8], 0xffffffff, timing[8]); > + ram_mask(hwsq, timing[0], 0xffffffff, timing[0]); > + ram_mask(hwsq, timing[2], 0xffffffff, timing[2]); > + ram_mask(hwsq, timing[4], 0xffffffff, timing[4]); > + ram_mask(hwsq, timing[5], 0xffffffff, timing[5]); > > #if QFX5800NVA0 > ram_nuke(hwsq, 0x100e24);