These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / nvkm / subdev / clk / gf100.c
index 3d7330d..a52b7e7 100644 (file)
  *
  * Authors: Ben Skeggs
  */
-#include <subdev/clk.h>
+#define gf100_clk(p) container_of((p), struct gf100_clk, base)
+#include "priv.h"
 #include "pll.h"
 
-#include <core/device.h>
 #include <subdev/bios.h>
 #include <subdev/bios/pll.h>
 #include <subdev/timer.h>
@@ -38,29 +38,29 @@ struct gf100_clk_info {
        u32 coef;
 };
 
-struct gf100_clk_priv {
+struct gf100_clk {
        struct nvkm_clk base;
        struct gf100_clk_info eng[16];
 };
 
-static u32 read_div(struct gf100_clk_priv *, int, u32, u32);
+static u32 read_div(struct gf100_clk *, int, u32, u32);
 
 static u32
-read_vco(struct gf100_clk_priv *priv, u32 dsrc)
+read_vco(struct gf100_clk *clk, u32 dsrc)
 {
-       struct nvkm_clk *clk = &priv->base;
-       u32 ssrc = nv_rd32(priv, dsrc);
+       struct nvkm_device *device = clk->base.subdev.device;
+       u32 ssrc = nvkm_rd32(device, dsrc);
        if (!(ssrc & 0x00000100))
-               return clk->read(clk, nv_clk_src_sppll0);
-       return clk->read(clk, nv_clk_src_sppll1);
+               return nvkm_clk_read(&clk->base, nv_clk_src_sppll0);
+       return nvkm_clk_read(&clk->base, nv_clk_src_sppll1);
 }
 
 static u32
-read_pll(struct gf100_clk_priv *priv, u32 pll)
+read_pll(struct gf100_clk *clk, u32 pll)
 {
-       struct nvkm_clk *clk = &priv->base;
-       u32 ctrl = nv_rd32(priv, pll + 0x00);
-       u32 coef = nv_rd32(priv, pll + 0x04);
+       struct nvkm_device *device = clk->base.subdev.device;
+       u32 ctrl = nvkm_rd32(device, pll + 0x00);
+       u32 coef = nvkm_rd32(device, pll + 0x04);
        u32 P = (coef & 0x003f0000) >> 16;
        u32 N = (coef & 0x0000ff00) >> 8;
        u32 M = (coef & 0x000000ff) >> 0;
@@ -72,20 +72,20 @@ read_pll(struct gf100_clk_priv *priv, u32 pll)
        switch (pll) {
        case 0x00e800:
        case 0x00e820:
-               sclk = nv_device(priv)->crystal;
+               sclk = device->crystal;
                P = 1;
                break;
        case 0x132000:
-               sclk = clk->read(clk, nv_clk_src_mpllsrc);
+               sclk = nvkm_clk_read(&clk->base, nv_clk_src_mpllsrc);
                break;
        case 0x132020:
-               sclk = clk->read(clk, nv_clk_src_mpllsrcref);
+               sclk = nvkm_clk_read(&clk->base, nv_clk_src_mpllsrcref);
                break;
        case 0x137000:
        case 0x137020:
        case 0x137040:
        case 0x1370e0:
-               sclk = read_div(priv, (pll & 0xff) / 0x20, 0x137120, 0x137140);
+               sclk = read_div(clk, (pll & 0xff) / 0x20, 0x137120, 0x137140);
                break;
        default:
                return 0;
@@ -95,46 +95,48 @@ read_pll(struct gf100_clk_priv *priv, u32 pll)
 }
 
 static u32
-read_div(struct gf100_clk_priv *priv, int doff, u32 dsrc, u32 dctl)
+read_div(struct gf100_clk *clk, int doff, u32 dsrc, u32 dctl)
 {
-       u32 ssrc = nv_rd32(priv, dsrc + (doff * 4));
-       u32 sctl = nv_rd32(priv, dctl + (doff * 4));
+       struct nvkm_device *device = clk->base.subdev.device;
+       u32 ssrc = nvkm_rd32(device, dsrc + (doff * 4));
+       u32 sctl = nvkm_rd32(device, dctl + (doff * 4));
 
        switch (ssrc & 0x00000003) {
        case 0:
                if ((ssrc & 0x00030000) != 0x00030000)
-                       return nv_device(priv)->crystal;
+                       return device->crystal;
                return 108000;
        case 2:
                return 100000;
        case 3:
                if (sctl & 0x80000000) {
-                       u32 sclk = read_vco(priv, dsrc + (doff * 4));
+                       u32 sclk = read_vco(clk, dsrc + (doff * 4));
                        u32 sdiv = (sctl & 0x0000003f) + 2;
                        return (sclk * 2) / sdiv;
                }
 
-               return read_vco(priv, dsrc + (doff * 4));
+               return read_vco(clk, dsrc + (doff * 4));
        default:
                return 0;
        }
 }
 
 static u32
-read_clk(struct gf100_clk_priv *priv, int clk)
+read_clk(struct gf100_clk *clk, int idx)
 {
-       u32 sctl = nv_rd32(priv, 0x137250 + (clk * 4));
-       u32 ssel = nv_rd32(priv, 0x137100);
+       struct nvkm_device *device = clk->base.subdev.device;
+       u32 sctl = nvkm_rd32(device, 0x137250 + (idx * 4));
+       u32 ssel = nvkm_rd32(device, 0x137100);
        u32 sclk, sdiv;
 
-       if (ssel & (1 << clk)) {
-               if (clk < 7)
-                       sclk = read_pll(priv, 0x137000 + (clk * 0x20));
+       if (ssel & (1 << idx)) {
+               if (idx < 7)
+                       sclk = read_pll(clk, 0x137000 + (idx * 0x20));
                else
-                       sclk = read_pll(priv, 0x1370e0);
+                       sclk = read_pll(clk, 0x1370e0);
                sdiv = ((sctl & 0x00003f00) >> 8) + 2;
        } else {
-               sclk = read_div(priv, clk, 0x137160, 0x1371d0);
+               sclk = read_div(clk, idx, 0x137160, 0x1371d0);
                sdiv = ((sctl & 0x0000003f) >> 0) + 2;
        }
 
@@ -145,10 +147,11 @@ read_clk(struct gf100_clk_priv *priv, int clk)
 }
 
 static int
-gf100_clk_read(struct nvkm_clk *clk, enum nv_clk_src src)
+gf100_clk_read(struct nvkm_clk *base, enum nv_clk_src src)
 {
-       struct nvkm_device *device = nv_device(clk);
-       struct gf100_clk_priv *priv = (void *)clk;
+       struct gf100_clk *clk = gf100_clk(base);
+       struct nvkm_subdev *subdev = &clk->base.subdev;
+       struct nvkm_device *device = subdev->device;
 
        switch (src) {
        case nv_clk_src_crystal:
@@ -156,47 +159,47 @@ gf100_clk_read(struct nvkm_clk *clk, enum nv_clk_src src)
        case nv_clk_src_href:
                return 100000;
        case nv_clk_src_sppll0:
-               return read_pll(priv, 0x00e800);
+               return read_pll(clk, 0x00e800);
        case nv_clk_src_sppll1:
-               return read_pll(priv, 0x00e820);
+               return read_pll(clk, 0x00e820);
 
        case nv_clk_src_mpllsrcref:
-               return read_div(priv, 0, 0x137320, 0x137330);
+               return read_div(clk, 0, 0x137320, 0x137330);
        case nv_clk_src_mpllsrc:
-               return read_pll(priv, 0x132020);
+               return read_pll(clk, 0x132020);
        case nv_clk_src_mpll:
-               return read_pll(priv, 0x132000);
+               return read_pll(clk, 0x132000);
        case nv_clk_src_mdiv:
-               return read_div(priv, 0, 0x137300, 0x137310);
+               return read_div(clk, 0, 0x137300, 0x137310);
        case nv_clk_src_mem:
-               if (nv_rd32(priv, 0x1373f0) & 0x00000002)
-                       return clk->read(clk, nv_clk_src_mpll);
-               return clk->read(clk, nv_clk_src_mdiv);
+               if (nvkm_rd32(device, 0x1373f0) & 0x00000002)
+                       return nvkm_clk_read(&clk->base, nv_clk_src_mpll);
+               return nvkm_clk_read(&clk->base, nv_clk_src_mdiv);
 
        case nv_clk_src_gpc:
-               return read_clk(priv, 0x00);
+               return read_clk(clk, 0x00);
        case nv_clk_src_rop:
-               return read_clk(priv, 0x01);
+               return read_clk(clk, 0x01);
        case nv_clk_src_hubk07:
-               return read_clk(priv, 0x02);
+               return read_clk(clk, 0x02);
        case nv_clk_src_hubk06:
-               return read_clk(priv, 0x07);
+               return read_clk(clk, 0x07);
        case nv_clk_src_hubk01:
-               return read_clk(priv, 0x08);
+               return read_clk(clk, 0x08);
        case nv_clk_src_copy:
-               return read_clk(priv, 0x09);
+               return read_clk(clk, 0x09);
        case nv_clk_src_daemon:
-               return read_clk(priv, 0x0c);
+               return read_clk(clk, 0x0c);
        case nv_clk_src_vdec:
-               return read_clk(priv, 0x0e);
+               return read_clk(clk, 0x0e);
        default:
-               nv_error(clk, "invalid clock source %d\n", src);
+               nvkm_error(subdev, "invalid clock source %d\n", src);
                return -EINVAL;
        }
 }
 
 static u32
-calc_div(struct gf100_clk_priv *priv, int clk, u32 ref, u32 freq, u32 *ddiv)
+calc_div(struct gf100_clk *clk, int idx, u32 ref, u32 freq, u32 *ddiv)
 {
        u32 div = min((ref * 2) / freq, (u32)65);
        if (div < 2)
@@ -207,7 +210,7 @@ calc_div(struct gf100_clk_priv *priv, int clk, u32 ref, u32 freq, u32 *ddiv)
 }
 
 static u32
-calc_src(struct gf100_clk_priv *priv, int clk, u32 freq, u32 *dsrc, u32 *ddiv)
+calc_src(struct gf100_clk *clk, int idx, u32 freq, u32 *dsrc, u32 *ddiv)
 {
        u32 sclk;
 
@@ -229,28 +232,29 @@ calc_src(struct gf100_clk_priv *priv, int clk, u32 freq, u32 *dsrc, u32 *ddiv)
        }
 
        /* otherwise, calculate the closest divider */
-       sclk = read_vco(priv, 0x137160 + (clk * 4));
-       if (clk < 7)
-               sclk = calc_div(priv, clk, sclk, freq, ddiv);
+       sclk = read_vco(clk, 0x137160 + (idx * 4));
+       if (idx < 7)
+               sclk = calc_div(clk, idx, sclk, freq, ddiv);
        return sclk;
 }
 
 static u32
-calc_pll(struct gf100_clk_priv *priv, int clk, u32 freq, u32 *coef)
+calc_pll(struct gf100_clk *clk, int idx, u32 freq, u32 *coef)
 {
-       struct nvkm_bios *bios = nvkm_bios(priv);
+       struct nvkm_subdev *subdev = &clk->base.subdev;
+       struct nvkm_bios *bios = subdev->device->bios;
        struct nvbios_pll limits;
        int N, M, P, ret;
 
-       ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits);
+       ret = nvbios_pll_parse(bios, 0x137000 + (idx * 0x20), &limits);
        if (ret)
                return 0;
 
-       limits.refclk = read_div(priv, clk, 0x137120, 0x137140);
+       limits.refclk = read_div(clk, idx, 0x137120, 0x137140);
        if (!limits.refclk)
                return 0;
 
-       ret = gt215_pll_calc(nv_subdev(priv), &limits, freq, &N, NULL, &M, &P);
+       ret = gt215_pll_calc(subdev, &limits, freq, &N, NULL, &M, &P);
        if (ret <= 0)
                return 0;
 
@@ -259,10 +263,9 @@ calc_pll(struct gf100_clk_priv *priv, int clk, u32 freq, u32 *coef)
 }
 
 static int
-calc_clk(struct gf100_clk_priv *priv,
-        struct nvkm_cstate *cstate, int clk, int dom)
+calc_clk(struct gf100_clk *clk, struct nvkm_cstate *cstate, int idx, int dom)
 {
-       struct gf100_clk_info *info = &priv->eng[clk];
+       struct gf100_clk_info *info = &clk->eng[idx];
        u32 freq = cstate->domain[dom];
        u32 src0, div0, div1D, div1P = 0;
        u32 clk0, clk1 = 0;
@@ -272,16 +275,16 @@ calc_clk(struct gf100_clk_priv *priv,
                return 0;
 
        /* first possible path, using only dividers */
-       clk0 = calc_src(priv, clk, freq, &src0, &div0);
-       clk0 = calc_div(priv, clk, clk0, freq, &div1D);
+       clk0 = calc_src(clk, idx, freq, &src0, &div0);
+       clk0 = calc_div(clk, idx, clk0, freq, &div1D);
 
        /* see if we can get any closer using PLLs */
-       if (clk0 != freq && (0x00004387 & (1 << clk))) {
-               if (clk <= 7)
-                       clk1 = calc_pll(priv, clk, freq, &info->coef);
+       if (clk0 != freq && (0x00004387 & (1 << idx))) {
+               if (idx <= 7)
+                       clk1 = calc_pll(clk, idx, freq, &info->coef);
                else
                        clk1 = cstate->domain[nv_clk_src_hubk06];
-               clk1 = calc_div(priv, clk, clk1, freq, &div1P);
+               clk1 = calc_div(clk, idx, clk1, freq, &div1P);
        }
 
        /* select the method which gets closest to target freq */
@@ -303,7 +306,7 @@ calc_clk(struct gf100_clk_priv *priv,
                        info->mdiv |= 0x80000000;
                        info->mdiv |= div1P << 8;
                }
-               info->ssel = (1 << clk);
+               info->ssel = (1 << idx);
                info->freq = clk1;
        }
 
@@ -311,81 +314,96 @@ calc_clk(struct gf100_clk_priv *priv,
 }
 
 static int
-gf100_clk_calc(struct nvkm_clk *clk, struct nvkm_cstate *cstate)
+gf100_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate)
 {
-       struct gf100_clk_priv *priv = (void *)clk;
+       struct gf100_clk *clk = gf100_clk(base);
        int ret;
 
-       if ((ret = calc_clk(priv, cstate, 0x00, nv_clk_src_gpc)) ||
-           (ret = calc_clk(priv, cstate, 0x01, nv_clk_src_rop)) ||
-           (ret = calc_clk(priv, cstate, 0x02, nv_clk_src_hubk07)) ||
-           (ret = calc_clk(priv, cstate, 0x07, nv_clk_src_hubk06)) ||
-           (ret = calc_clk(priv, cstate, 0x08, nv_clk_src_hubk01)) ||
-           (ret = calc_clk(priv, cstate, 0x09, nv_clk_src_copy)) ||
-           (ret = calc_clk(priv, cstate, 0x0c, nv_clk_src_daemon)) ||
-           (ret = calc_clk(priv, cstate, 0x0e, nv_clk_src_vdec)))
+       if ((ret = calc_clk(clk, cstate, 0x00, nv_clk_src_gpc)) ||
+           (ret = calc_clk(clk, cstate, 0x01, nv_clk_src_rop)) ||
+           (ret = calc_clk(clk, cstate, 0x02, nv_clk_src_hubk07)) ||
+           (ret = calc_clk(clk, cstate, 0x07, nv_clk_src_hubk06)) ||
+           (ret = calc_clk(clk, cstate, 0x08, nv_clk_src_hubk01)) ||
+           (ret = calc_clk(clk, cstate, 0x09, nv_clk_src_copy)) ||
+           (ret = calc_clk(clk, cstate, 0x0c, nv_clk_src_daemon)) ||
+           (ret = calc_clk(clk, cstate, 0x0e, nv_clk_src_vdec)))
                return ret;
 
        return 0;
 }
 
 static void
-gf100_clk_prog_0(struct gf100_clk_priv *priv, int clk)
+gf100_clk_prog_0(struct gf100_clk *clk, int idx)
 {
-       struct gf100_clk_info *info = &priv->eng[clk];
-       if (clk < 7 && !info->ssel) {
-               nv_mask(priv, 0x1371d0 + (clk * 0x04), 0x80003f3f, info->ddiv);
-               nv_wr32(priv, 0x137160 + (clk * 0x04), info->dsrc);
+       struct gf100_clk_info *info = &clk->eng[idx];
+       struct nvkm_device *device = clk->base.subdev.device;
+       if (idx < 7 && !info->ssel) {
+               nvkm_mask(device, 0x1371d0 + (idx * 0x04), 0x80003f3f, info->ddiv);
+               nvkm_wr32(device, 0x137160 + (idx * 0x04), info->dsrc);
        }
 }
 
 static void
-gf100_clk_prog_1(struct gf100_clk_priv *priv, int clk)
+gf100_clk_prog_1(struct gf100_clk *clk, int idx)
 {
-       nv_mask(priv, 0x137100, (1 << clk), 0x00000000);
-       nv_wait(priv, 0x137100, (1 << clk), 0x00000000);
+       struct nvkm_device *device = clk->base.subdev.device;
+       nvkm_mask(device, 0x137100, (1 << idx), 0x00000000);
+       nvkm_msec(device, 2000,
+               if (!(nvkm_rd32(device, 0x137100) & (1 << idx)))
+                       break;
+       );
 }
 
 static void
-gf100_clk_prog_2(struct gf100_clk_priv *priv, int clk)
+gf100_clk_prog_2(struct gf100_clk *clk, int idx)
 {
-       struct gf100_clk_info *info = &priv->eng[clk];
-       const u32 addr = 0x137000 + (clk * 0x20);
-       if (clk <= 7) {
-               nv_mask(priv, addr + 0x00, 0x00000004, 0x00000000);
-               nv_mask(priv, addr + 0x00, 0x00000001, 0x00000000);
+       struct gf100_clk_info *info = &clk->eng[idx];
+       struct nvkm_device *device = clk->base.subdev.device;
+       const u32 addr = 0x137000 + (idx * 0x20);
+       if (idx <= 7) {
+               nvkm_mask(device, addr + 0x00, 0x00000004, 0x00000000);
+               nvkm_mask(device, addr + 0x00, 0x00000001, 0x00000000);
                if (info->coef) {
-                       nv_wr32(priv, addr + 0x04, info->coef);
-                       nv_mask(priv, addr + 0x00, 0x00000001, 0x00000001);
-                       nv_wait(priv, addr + 0x00, 0x00020000, 0x00020000);
-                       nv_mask(priv, addr + 0x00, 0x00020004, 0x00000004);
+                       nvkm_wr32(device, addr + 0x04, info->coef);
+                       nvkm_mask(device, addr + 0x00, 0x00000001, 0x00000001);
+                       nvkm_msec(device, 2000,
+                               if (nvkm_rd32(device, addr + 0x00) & 0x00020000)
+                                       break;
+                       );
+                       nvkm_mask(device, addr + 0x00, 0x00020004, 0x00000004);
                }
        }
 }
 
 static void
-gf100_clk_prog_3(struct gf100_clk_priv *priv, int clk)
+gf100_clk_prog_3(struct gf100_clk *clk, int idx)
 {
-       struct gf100_clk_info *info = &priv->eng[clk];
+       struct gf100_clk_info *info = &clk->eng[idx];
+       struct nvkm_device *device = clk->base.subdev.device;
        if (info->ssel) {
-               nv_mask(priv, 0x137100, (1 << clk), info->ssel);
-               nv_wait(priv, 0x137100, (1 << clk), info->ssel);
+               nvkm_mask(device, 0x137100, (1 << idx), info->ssel);
+               nvkm_msec(device, 2000,
+                       u32 tmp = nvkm_rd32(device, 0x137100) & (1 << idx);
+                       if (tmp == info->ssel)
+                               break;
+               );
        }
 }
 
 static void
-gf100_clk_prog_4(struct gf100_clk_priv *priv, int clk)
+gf100_clk_prog_4(struct gf100_clk *clk, int idx)
 {
-       struct gf100_clk_info *info = &priv->eng[clk];
-       nv_mask(priv, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv);
+       struct gf100_clk_info *info = &clk->eng[idx];
+       struct nvkm_device *device = clk->base.subdev.device;
+       nvkm_mask(device, 0x137250 + (idx * 0x04), 0x00003f3f, info->mdiv);
 }
 
 static int
-gf100_clk_prog(struct nvkm_clk *clk)
+gf100_clk_prog(struct nvkm_clk *base)
 {
-       struct gf100_clk_priv *priv = (void *)clk;
+       struct gf100_clk *clk = gf100_clk(base);
        struct {
-               void (*exec)(struct gf100_clk_priv *, int);
+               void (*exec)(struct gf100_clk *, int);
        } stage[] = {
                { gf100_clk_prog_0 }, /* div programming */
                { gf100_clk_prog_1 }, /* select div mode */
@@ -396,10 +414,10 @@ gf100_clk_prog(struct nvkm_clk *clk)
        int i, j;
 
        for (i = 0; i < ARRAY_SIZE(stage); i++) {
-               for (j = 0; j < ARRAY_SIZE(priv->eng); j++) {
-                       if (!priv->eng[j].freq)
+               for (j = 0; j < ARRAY_SIZE(clk->eng); j++) {
+                       if (!clk->eng[j].freq)
                                continue;
-                       stage[i].exec(priv, j);
+                       stage[i].exec(clk, j);
                }
        }
 
@@ -407,56 +425,42 @@ gf100_clk_prog(struct nvkm_clk *clk)
 }
 
 static void
-gf100_clk_tidy(struct nvkm_clk *clk)
+gf100_clk_tidy(struct nvkm_clk *base)
 {
-       struct gf100_clk_priv *priv = (void *)clk;
-       memset(priv->eng, 0x00, sizeof(priv->eng));
+       struct gf100_clk *clk = gf100_clk(base);
+       memset(clk->eng, 0x00, sizeof(clk->eng));
 }
 
-static struct nvkm_domain
-gf100_domain[] = {
-       { nv_clk_src_crystal, 0xff },
-       { nv_clk_src_href   , 0xff },
-       { nv_clk_src_hubk06 , 0x00 },
-       { nv_clk_src_hubk01 , 0x01 },
-       { nv_clk_src_copy   , 0x02 },
-       { nv_clk_src_gpc    , 0x03, 0, "core", 2000 },
-       { nv_clk_src_rop    , 0x04 },
-       { nv_clk_src_mem    , 0x05, 0, "memory", 1000 },
-       { nv_clk_src_vdec   , 0x06 },
-       { nv_clk_src_daemon , 0x0a },
-       { nv_clk_src_hubk07 , 0x0b },
-       { nv_clk_src_max }
+static const struct nvkm_clk_func
+gf100_clk = {
+       .read = gf100_clk_read,
+       .calc = gf100_clk_calc,
+       .prog = gf100_clk_prog,
+       .tidy = gf100_clk_tidy,
+       .domains = {
+               { nv_clk_src_crystal, 0xff },
+               { nv_clk_src_href   , 0xff },
+               { nv_clk_src_hubk06 , 0x00 },
+               { nv_clk_src_hubk01 , 0x01 },
+               { nv_clk_src_copy   , 0x02 },
+               { nv_clk_src_gpc    , 0x03, 0, "core", 2000 },
+               { nv_clk_src_rop    , 0x04 },
+               { nv_clk_src_mem    , 0x05, 0, "memory", 1000 },
+               { nv_clk_src_vdec   , 0x06 },
+               { nv_clk_src_daemon , 0x0a },
+               { nv_clk_src_hubk07 , 0x0b },
+               { nv_clk_src_max }
+       }
 };
 
-static int
-gf100_clk_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
-              struct nvkm_oclass *oclass, void *data, u32 size,
-              struct nvkm_object **pobject)
+int
+gf100_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk)
 {
-       struct gf100_clk_priv *priv;
-       int ret;
+       struct gf100_clk *clk;
 
-       ret = nvkm_clk_create(parent, engine, oclass, gf100_domain,
-                             NULL, 0, false, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
+       if (!(clk = kzalloc(sizeof(*clk), GFP_KERNEL)))
+               return -ENOMEM;
+       *pclk = &clk->base;
 
-       priv->base.read = gf100_clk_read;
-       priv->base.calc = gf100_clk_calc;
-       priv->base.prog = gf100_clk_prog;
-       priv->base.tidy = gf100_clk_tidy;
-       return 0;
+       return nvkm_clk_ctor(&gf100_clk, device, index, false, &clk->base);
 }
-
-struct nvkm_oclass
-gf100_clk_oclass = {
-       .handle = NV_SUBDEV(CLK, 0xc0),
-       .ofuncs = &(struct nvkm_ofuncs) {
-               .ctor = gf100_clk_ctor,
-               .dtor = _nvkm_clk_dtor,
-               .init = _nvkm_clk_init,
-               .fini = _nvkm_clk_fini,
-       },
-};