Following a series of three patches, two of which have been sitting in my tree for a while, the third is the result of some inspection of an NV134 BIOS that seems to use the 0xaf upcode to upload training patterns. Please test! Roy Ps. Sorry they come from yet another e-mail address. My previous provider, eclipso, actively blocks users of git send-email. Inquiries fall on deaf ears, hence I consider them hostile towards OSS developers.
Roy Spliet
2016-Jun-04 23:49 UTC
[Nouveau] [PATCH 1/3] nvkm/clk/gf100+: Clean up PLL locking test
Corresponds with GT215. Don't rely on the lock test logic being unconditionally enabled, and disable test logic when done (presumably to save power). Warn when locking fails. Signed-off-by: Roy Spliet <nouveau at spliet.org> --- drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c | 15 ++++++++++++--- drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c index 78c449b..f9a4918 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c @@ -366,11 +366,20 @@ gf100_clk_prog_2(struct gf100_clk *clk, int idx) if (info->coef) { nvkm_wr32(device, addr + 0x04, info->coef); nvkm_mask(device, addr + 0x00, 0x00000001, 0x00000001); - nvkm_msec(device, 2000, + + /* Test PLL lock */ + nvkm_mask(device, addr + 0x00, 0x00000010, 0x00000000); + if (nvkm_msec(device, 2000, if (nvkm_rd32(device, addr + 0x00) & 0x00020000) break; - ); - nvkm_mask(device, addr + 0x00, 0x00020004, 0x00000004); + ) < 0) { + nvkm_warn(&clk->base.subdev, + "Could not lock PLL %d", idx); + } + nvkm_mask(device, addr + 0x00, 0x00000010, 0x00000010); + + /* Enable sync mode */ + nvkm_mask(device, addr + 0x00, 0x00000004, 0x00000004); } } } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c index 975c401..b650f0c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c @@ -393,11 +393,20 @@ gk104_clk_prog_2(struct gk104_clk *clk, int idx) if (info->coef) { nvkm_wr32(device, addr + 0x04, info->coef); nvkm_mask(device, addr + 0x00, 0x00000001, 0x00000001); - nvkm_msec(device, 2000, + + /* Test PLL lock */ + nvkm_mask(device, addr + 0x00, 0x00000010, 0x00000000); + if (nvkm_msec(device, 2000, if (nvkm_rd32(device, addr + 0x00) & 0x00020000) break; - ); - nvkm_mask(device, addr + 0x00, 0x00020004, 0x00000004); + ) < 0) { + nvkm_warn(&clk->base.subdev, "Could not lock PLL %d", + idx); + } + nvkm_mask(device, addr + 0x00, 0x00000010, 0x00000010); + + /* Enable sync mode */ + nvkm_mask(device, addr + 0x00, 0x00000004, 0x00000004); } } -- 2.5.5
Roy Spliet
2016-Jun-04 23:49 UTC
[Nouveau] [PATCH 2/3] nvkm/clk/gf100: Read secondary bypass postdiv when required
Signed-off-by: Roy Spliet <nouveau at spliet.org> --- drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c index f9a4918..80c6dd6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c @@ -99,7 +99,7 @@ read_div(struct gf100_clk *clk, int doff, u32 dsrc, u32 dctl) { struct nvkm_device *device = clk->base.subdev.device; u32 ssrc = nvkm_rd32(device, dsrc + (doff * 4)); - u32 sctl = nvkm_rd32(device, dctl + (doff * 4)); + u32 sclk, sctl, sdiv = 2; switch (ssrc & 0x00000003) { case 0: @@ -109,13 +109,21 @@ read_div(struct gf100_clk *clk, int doff, u32 dsrc, u32 dctl) case 2: return 100000; case 3: - if (sctl & 0x80000000) { - u32 sclk = read_vco(clk, dsrc + (doff * 4)); - u32 sdiv = (sctl & 0x0000003f) + 2; - return (sclk * 2) / sdiv; + sclk = read_vco(clk, dsrc + (doff * 4)); + + /* Memclk has doff of 0 despite it's alt. location */ + if (doff <= 2) { + sctl = nvkm_rd32(device, dctl + (doff * 4)); + + if (sctl & 0x80000000) { + if (ssrc & 0x100) + sctl >>= 8; + + sdiv = (sctl & 0x3f) + 2; + } } - return read_vco(clk, dsrc + (doff * 4)); + return (sclk * 2) / sdiv; default: return 0; } -- 2.5.5
Roy Spliet
2016-Jun-04 23:49 UTC
[Nouveau] [PATCH 3/3] nvkm/init: Add support for opcode 0xaf
As seen in at least one NV134 VBIOS (... that I obviously don't own myself). Signed-off-by: Roy Spliet <nouveau at spliet.org> --- drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c index 38ed09f..a18f8b4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c @@ -2196,6 +2196,32 @@ init_gpio_ne(struct nvbios_init *init) init->offset += count; } +/** + * INIT_ZM_REG_SET_LOOP - opcode 0xaf + * + */ +static void +init_zm_reg_set_loop(struct nvbios_init *init) +{ + struct nvkm_bios *bios = init->bios; + u8 sets = nvbios_rd08(bios, init->offset + 1); + u8 regs = nvbios_rd08(bios, init->offset + 2); + u32 reg_off = init->offset + 3; + u32 addr, data, i, j; + + trace("ZM_REG_SET_LOOP 0x%02hhx 0x%02hhx\n", sets, regs); + init->offset += 3 + (regs * 4); + + for (i = 0; i < sets; i++) { + for (j = 0; j < regs; j++, init->offset += 4) { + addr = nvbios_rd32(bios, reg_off + (j * 4)); + data = nvbios_rd32(bios, init->offset); + init_wr32(init, addr, data); + trace("\tR[0x%06x] = 0x%08x\n", addr, data); + } + } +} + static struct nvbios_init_opcode { void (*exec)(struct nvbios_init *); } init_opcode[] = { @@ -2268,6 +2294,7 @@ static struct nvbios_init_opcode { [0x9a] = { init_i2c_long_if }, [0xa9] = { init_gpio_ne }, [0xaa] = { init_reserved }, + [0xaf] = { init_zm_reg_set_loop }, }; #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) -- 2.5.5